Skip to content

Commit

Permalink
Merge branch 'master' into analysis-player-dialog
Browse files Browse the repository at this point in the history
johndoknjas committed Jan 21, 2025

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
2 parents 49612ba + 2ab6257 commit 5372271
Showing 200 changed files with 1,547 additions and 1,536 deletions.
2 changes: 1 addition & 1 deletion .scalafmt.conf
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version = "3.8.4"
version = "3.8.5"
runner.dialect = scala3

align.preset = more
36 changes: 20 additions & 16 deletions app/Env.scala
Original file line number Diff line number Diff line change
@@ -11,33 +11,36 @@ final class Env(
val config: Configuration,
val controllerComponents: ControllerComponents,
environment: Environment,
shutdown: akka.actor.CoordinatedShutdown
shutdown: akka.actor.CoordinatedShutdown,
cookieBaker: SessionCookieBaker
)(using val system: akka.actor.ActorSystem, val executor: Executor)(using
StandaloneWSClient,
akka.stream.Materializer,
SessionCookieBaker
akka.stream.Materializer
):
val net: NetConfig = config.get[NetConfig]("net")

export net.{ domain, baseUrl, assetBaseUrlInternal }
export net.{ baseUrl, assetBaseUrlInternal }

given mode: Mode = environment.mode
given translator: lila.core.i18n.Translator = lila.i18n.Translator
given scheduler: Scheduler = system.scheduler
given lila.core.config.RateLimit = net.rateLimit
given RateLimit = net.rateLimit
given NetDomain = net.domain

// wire all the lila modules in the right order
val i18n: lila.i18n.Env.type = lila.i18n.Env
val mongo: lila.db.Env = wire[lila.db.Env]
val memo: lila.memo.Env = wire[lila.memo.Env]
val socket: lila.socket.Env = wire[lila.socket.Env]
val user: lila.user.Env = wire[lila.user.Env]
val mailer: lila.mailer.Env = wire[lila.mailer.Env]
val oAuth: lila.oauth.Env = wire[lila.oauth.Env]
val security: lila.security.Env = wire[lila.security.Env]
val pref: lila.pref.Env = wire[lila.pref.Env]
val relation: lila.relation.Env = wire[lila.relation.Env]
val game: lila.game.Env = wire[lila.game.Env]
val i18n: lila.i18n.Env.type = lila.i18n.Env
val mongo: lila.db.Env = wire[lila.db.Env]
val memo: lila.memo.Env = wire[lila.memo.Env]
val socket: lila.socket.Env = wire[lila.socket.Env]
val user: lila.user.Env = wire[lila.user.Env]
import user.flairApi.given
val mailer: lila.mailer.Env = wire[lila.mailer.Env]
val oAuth: lila.oauth.Env = wire[lila.oauth.Env]
val security: lila.security.Env = wire[lila.security.Env]
val pref: lila.pref.Env = wire[lila.pref.Env]
val relation: lila.relation.Env = wire[lila.relation.Env]
val game: lila.game.Env = wire[lila.game.Env]
import game.given
val notifyM: lila.notify.Env = wire[lila.notify.Env]
val irc: lila.irc.Env = wire[lila.irc.Env]
val report: lila.report.Env = wire[lila.report.Env]
@@ -62,6 +65,7 @@ final class Env(
val forum: lila.forum.Env = wire[lila.forum.Env]
val forumSearch: lila.forumSearch.Env = wire[lila.forumSearch.Env]
val pool: lila.pool.Env = wire[lila.pool.Env]
import pool.isClockCompatible
val lobby: lila.lobby.Env = wire[lila.lobby.Env]
val setup: lila.setup.Env = wire[lila.setup.Env]
val simul: lila.simul.Env = wire[lila.simul.Env]
6 changes: 6 additions & 0 deletions app/controllers/Api.scala
Original file line number Diff line number Diff line change
@@ -384,6 +384,12 @@ final class Api(
ttl = 1.hour,
maxConcurrency = 4
)
val eventsForVerifiedUser = lila.web.ConcurrencyLimit[IpAddress](
name = "API verified events concurrency per IP",
key = "api.ip.events.verified",
ttl = 1.hour,
maxConcurrency = 12
)
val download = lila.web.ConcurrencyLimit[IpAddress](
name = "API download concurrency per IP",
key = "api.ip.download",
2 changes: 1 addition & 1 deletion app/controllers/Auth.scala
Original file line number Diff line number Diff line change
@@ -278,7 +278,7 @@ final class Auth(
lila.mon.user.register.confirmEmailResult(true).increment()
env.user.repo.email(user.id).flatMap {
_.so: email =>
authLog(user.username, email.some, s"Confirmed email ${email.value}")
authLog(user.username, email.some, s"Confirmed email")
welcome(user, email, sendWelcomeEmail = false)
} >> redirectNewUser(user)
}
9 changes: 6 additions & 3 deletions app/controllers/RelayRound.scala
Original file line number Diff line number Diff line change
@@ -190,10 +190,13 @@ final class RelayRound(

def stream(id: RelayRoundId) = AnonOrScoped(): ctx ?=>
Found(env.relay.api.byIdWithStudy(id)): rs =>
val limiter =
if ctx.me.exists(_.isVerified)
then apiC.GlobalConcurrencyLimitPerIP.eventsForVerifiedUser
else apiC.GlobalConcurrencyLimitPerIP.events
studyC.CanView(rs.study) {
apiC.GlobalConcurrencyLimitPerIP
.events(req.ipAddress)(env.relay.pgnStream.streamRoundGames(rs)): source =>
noProxyBuffer(Ok.chunked[PgnStr](source.keepAlive(60.seconds, () => PgnStr(" "))))
limiter(req.ipAddress)(env.relay.pgnStream.streamRoundGames(rs)): source =>
noProxyBuffer(Ok.chunked[PgnStr](source.keepAlive(60.seconds, () => PgnStr(" "))))
}(Unauthorized, Forbidden)

def chapter(ts: String, rs: String, id: RelayRoundId, chapterId: StudyChapterId) =
69 changes: 34 additions & 35 deletions app/controllers/Round.scala
Original file line number Diff line number Diff line change
@@ -200,7 +200,7 @@ final class Round(
private[controllers] def getWatcherChat(
game: GameModel
)(using ctx: Context): Fu[Option[lila.chat.UserChat.Mine]] = {
ctx.kid.no && (ctx.noBot || ctx.userId.exists(game.userIds.has)) && ctx.me.fold(
(ctx.noBot || ctx.userId.exists(game.userIds.has)) && ctx.me.fold(
HTTPRequest.isHuman(ctx.req)
)(env.chat.panic.allowed(_)) && {
game.finishedOrAborted || !ctx.userId.exists(game.userIds.has)
@@ -211,41 +211,40 @@ final class Round(
private[controllers] def getPlayerChat(game: GameModel, tour: Option[Tour])(using
ctx: Context
): Fu[Option[Chat.GameOrEvent]] =
ctx.kid.no.so:
def toEventChat(resource: String)(c: lila.chat.UserChat.Mine) =
Chat
.GameOrEvent:
Right:
(c.truncate(100), lila.chat.Chat.ResourceId(resource))
.some
(game.tournamentId, game.simulId, game.swissId) match
case (Some(tid), _, _) =>
val hasChat = ctx.isAuth && tour.forall(tournamentC.canHaveChat(_, none))
hasChat.so(
def toEventChat(resource: String)(c: lila.chat.UserChat.Mine) =
Chat
.GameOrEvent:
Right:
(c.truncate(100), lila.chat.Chat.ResourceId(resource))
.some
(game.tournamentId, game.simulId, game.swissId) match
case (Some(tid), _, _) =>
val hasChat = ctx.isAuth && tour.forall(tournamentC.canHaveChat(_, none))
hasChat.so(
env.chat.api.userChat.cached
.findMine(tid.into(ChatId))
.dmap(toEventChat(s"tournament/$tid"))
)
case (_, Some(sid), _) =>
env.chat.api.userChat.cached.findMine(sid.into(ChatId)).dmap(toEventChat(s"simul/$sid"))
case (_, _, Some(sid)) =>
env.swiss.api
.roundInfo(sid)
.flatMapz(swissC.canHaveChat)
.flatMapz:
env.chat.api.userChat.cached
.findMine(tid.into(ChatId))
.dmap(toEventChat(s"tournament/$tid"))
)
case (_, Some(sid), _) =>
env.chat.api.userChat.cached.findMine(sid.into(ChatId)).dmap(toEventChat(s"simul/$sid"))
case (_, _, Some(sid)) =>
env.swiss.api
.roundInfo(sid)
.flatMapz(swissC.canHaveChat)
.flatMapz:
env.chat.api.userChat.cached
.findMine(sid.into(ChatId))
.dmap(toEventChat(s"swiss/$sid"))
case _ =>
game.hasChat.so:
for
chat <- env.chat.api.playerChat.findIf(game.id.into(ChatId), !game.justCreated)
lines <- lila.chat.JsonView.asyncLines(chat)
yield Chat
.GameOrEvent:
Left:
Chat.Restricted(chat, lines, restricted = game.sourceIs(_.Lobby) && ctx.isAnon)
.some
.findMine(sid.into(ChatId))
.dmap(toEventChat(s"swiss/$sid"))
case _ =>
game.hasChat.so:
for
chat <- env.chat.api.playerChat.findIf(game.id.into(ChatId), !game.justCreated)
lines <- lila.chat.JsonView.asyncLines(chat)
yield Chat
.GameOrEvent:
Left:
Chat.Restricted(chat, lines, restricted = game.sourceIs(_.Lobby) && ctx.isAnon)
.some

def sides(gameId: GameId, color: Color) = Open:
FoundSnip(env.round.proxyRepo.pov(gameId, color)): pov =>
3 changes: 2 additions & 1 deletion app/controllers/Setup.scala
Original file line number Diff line number Diff line change
@@ -210,7 +210,8 @@ final class Setup(
doubleJsonFormError,
config =>
processor.apiAi(config).map { pov =>
Created(env.game.jsonView.baseWithChessDenorm(pov.game, config.fen)).as(JSON)
val json = env.game.jsonView.apiAiNewGame(pov, config.fen)
Created(json).as(JSON)
}
)
}
31 changes: 16 additions & 15 deletions app/controllers/Study.scala
Original file line number Diff line number Diff line change
@@ -32,23 +32,24 @@ final class Study(

def search(text: String, page: Int) = OpenOrScopedBody(parse.anyContent)(_.Study.Read, _.Web.Mobile):
Reasonable(page):
if text.trim.isEmpty then
for
pag <- env.study.pager.all(Orders.default, page)
_ <- preloadMembers(pag)
res <- negotiate(
Ok.page(views.study.list.all(pag, Orders.default)),
apiStudies(pag)
)
yield res
else
env
.studySearch(ctx.me)(text.take(100), page)
.flatMap: pag =>
negotiate(
Ok.page(views.study.list.search(pag, text)),
text.trim.some.filter(_.nonEmpty).filter(_.sizeIs > 2).filter(_.sizeIs < 200) match
case None =>
for
pag <- env.study.pager.all(Orders.default, page)
_ <- preloadMembers(pag)
res <- negotiate(
Ok.page(views.study.list.all(pag, Orders.default)),
apiStudies(pag)
)
yield res
case Some(clean) =>
env
.studySearch(ctx.me)(clean.take(100), page)
.flatMap: pag =>
negotiate(
Ok.page(views.study.list.search(pag, text)),
apiStudies(pag)
)

def homeLang = LangPage(routes.Study.allDefault())(allResults(Order.hot, 1))

1 change: 1 addition & 0 deletions app/views/analyse/replay.scala
Original file line number Diff line number Diff line change
@@ -79,6 +79,7 @@ def replay(
.css(ctx.blind.option("round.nvui"))
.css(ctx.pref.hasKeyboardMove.option("keyboardMove"))
.i18n(_.puzzle, _.study)
.i18nOpt(ctx.blind, _.keyboardMove)
.js(analyseNvuiTag)
.js(
bits.analyseModule(
6 changes: 4 additions & 2 deletions app/views/base/embed.scala
Original file line number Diff line number Diff line change
@@ -20,7 +20,8 @@ object embed:
st.headTitle(title),
(ctx.bg == "system").option(page.ui.systemThemeScript(ctx.nonce.some)),
page.ui.pieceSprite(ctx.pieceSet.name),
cssTag("common.theme.embed"), // includes both light & dark colors
cssTag("common.theme.embed"),
link(rel := "stylesheet", href := assetUrl("css/theme/font-face.css")),
cssKeys.map(cssTag),
page.ui.scriptsPreload(modules.flatMap(_.map(_.key)))
),
@@ -65,7 +66,8 @@ object embed:
st.headTitle(title),
(ctx.bg == "system").option(page.ui.systemThemeScript(ctx.nonce.some)),
page.ui.pieceSprite(ctx.pieceSet.name),
cssTag("common.theme.embed"), // includes both light & dark colors
cssTag("common.theme.embed"),
link(rel := "stylesheet", href := assetUrl("css/theme/font-face.css")),
cssKeys.map(cssTag),
page.ui.sitePreload(
List[I18nModule.Selector](_.site, _.timeago) ++ i18nModules,
1 change: 1 addition & 0 deletions app/views/base/page.scala
Original file line number Diff line number Diff line change
@@ -59,6 +59,7 @@ object page:
else s"${ctx.me.so(_.username.value + " ")} $prodTitle"
,
cssTag("common.theme.all"),
link(rel := "stylesheet", href := assetUrl("css/theme/font-face.css")),
cssTag("site"),
pref.is3d.option(cssTag("common.board-3d")),
ctx.data.inquiry.isDefined.option(cssTag("mod.inquiry")),
2 changes: 1 addition & 1 deletion app/views/mod/inquiry.scala
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@ object inquiry:
)

def apply(in: lila.mod.Inquiry)(using ctx: Context) =
div(id := "inquiry")(
div(id := "inquiry", data("username") := in.user.user.username)(
i(title := "Costello the Inquiry Octopus", cls := "costello"),
div(cls := "meat")(
userLink(in.user.user, withPerfRating = in.user.perfs.some, params = "?mod"),
1 change: 1 addition & 0 deletions app/views/study.scala
Original file line number Diff line number Diff line change
@@ -51,6 +51,7 @@ def show(
.css("analyse.study")
.css(ctx.pref.hasKeyboardMove.option("keyboardMove"))
.i18n(_.puzzle, _.study)
.i18nOpt(ctx.blind, _.keyboardMove)
.js(analyseNvuiTag)
.js(
PageModule(
4 changes: 2 additions & 2 deletions app/views/user/show/header.scala
Original file line number Diff line number Diff line change
@@ -33,7 +33,7 @@ object header:
a(
href := routes.Plan.index(),
cls := "trophy award patron icon3d",
ariaTitle(s"Patron since ${showDate(u.plan.sinceDate)}")
ariaTitle(trans.patron.patronSince.txt(showDate(u.plan.sinceDate)))
)(patronIconChar)
)
),
@@ -82,7 +82,7 @@ object header:
cls := "nm-item",
href := routes.Ublog.index(u.username)
)(
splitNumber(s"${info.ublog.so(_.nbPosts)} blog posts")
splitNumber(trans.ublog.blogPosts.pluralSame(info.ublog.so(_.nbPosts)))
)
),
(ctx.isAuth && ctx.isnt(u))
13 changes: 2 additions & 11 deletions bin/gen/generate_css_for_a_board_with_backgroundimages.py
Original file line number Diff line number Diff line change
@@ -2,22 +2,13 @@

#config
schemeName = "canvas"
bgImgWhite = "../images/canvasboard_white.jpg"
bgImgBlack = "../images/canvasboard_black.jpg"

# adv. config
squareSize = 64 # width of a square in pixel
squareSize = 64 # width of a square in pixels

#code
print("body." + schemeName + " #GameBoard td.whiteSquare, body." + schemeName + " #GameBoard td.highlightWhiteSquare, body." + schemeName + " div.lcs.white, #top div.lcs.white." + schemeName + ", body." + schemeName + " div.lichess_board { background: url(../images/woodenboard_white.jpg) no-repeat; }")
print("body." + schemeName + " #GameBoard td.blackSquare, body." + schemeName + " #GameBoard td.highlightBlackSquare, body." + schemeName + " div.lcs.black, #top div.lcs.black." + schemeName + " { background: url(../images/woodenboard_black.jpg) no-repeat; }")
white = True
for y in range(0,8):
for x in range (0, 8):
if white:
img = bgImgWhite
else:
img = bgImgBlack
for x in range (0,8):
print("body." + schemeName + " #tcol"+str(x)+"trow"+str(y)+", body." + schemeName + " #"+str(chr(ord('a') + x))+str(8-y) + " { background-position: "+str((-x)*squareSize)+"px " +str((-y)*squareSize) +"px; }")
white = not white
white = not white
3 changes: 1 addition & 2 deletions bin/gen/licon.py
Original file line number Diff line number Diff line change
@@ -90,7 +90,7 @@ def main():

gen_sources(codes)

print('Generated:\n public/font/lichess.woff\n public/font/lichess.woff2\n public/font/lichess.ttf')
print('Generated:\n public/font/lichess.woff2\n public/font/lichess.ttf\n public/oops/font.html')
print(' modules/ui/src/main/Icon.scala\n ui/common/src/licon.ts')
print(' ui/common/css/abstract/_licon.scss\n')
print("Don't forget to install lichess.ttf in your code editor\n")
@@ -158,7 +158,6 @@ def gen_fonts():
[f, name] = tempfile.mkstemp(suffix='.pe', dir='.')
os.write(f, textwrap.dedent(f"""
Open('lichess.sfd')
Generate('lichess.woff')
Generate('lichess.woff2')
Generate('lichess.ttf')
Quit()
Loading

0 comments on commit 5372271

Please sign in to comment.