Skip to content

Commit

Permalink
Merge branch 'lichess-org:master' into broadcast-chat-game-navigate-1…
Browse files Browse the repository at this point in the history
…5029
  • Loading branch information
Carbrex authored Jun 20, 2024
2 parents 221cda1 + b58a6da commit 3547b56
Show file tree
Hide file tree
Showing 368 changed files with 3,915 additions and 6,909 deletions.
3 changes: 3 additions & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,6 @@ cd9708a0d772fe445635ae05306f1cb9365902de

# Scala Steward: Reformat with scalafmt 3.8.1
1aae0c7b022f9e505e1ca7fec3b32efeef9f9981

# Scala Steward: Reformat with scalafmt 3.8.2
2b774ffaf8926dc9986954f3c427cbe479e05f6a
8 changes: 6 additions & 2 deletions .github/workflows/assets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ jobs:
- uses: actions/checkout@v4
with:
submodules: recursive
- uses: pnpm/action-setup@v3
- uses: actions/setup-node@v4
with:
node-version: 22
- uses: pnpm/action-setup@v4
with:
run_install: true
- uses: actions/checkout@v4
Expand All @@ -39,7 +42,8 @@ jobs:
- run: pnpm link "$GITHUB_WORKSPACE/ab"
if: steps.ab.outcome == 'success'
- run: ./ui/build --no-install -p
- run: cd ui && pnpm run test && cd -
- run: pnpm test
working-directory: ui
- run: mkdir assets && mv public assets/ && cp -p bin/download-lifat LICENSE COPYING.md README.md assets/ && git log -n 1 --pretty=oneline > assets/commit.txt
- run: cd assets && tar --zstd -cvpf ../assets.tar.zst . && cd -
- uses: actions/upload-artifact@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
security-events: write
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v3
- uses: pnpm/action-setup@v4
with:
run_install: true
- uses: github/codeql-action/init@v3
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ data/
dist/
node_modules/
local/
gen/
ui/common/css/theme/gen/*.scss
ui/common/**/*.js
ui/common/**/*.d.ts
ui/chess/**/*.js
Expand Down
3 changes: 3 additions & 0 deletions .ignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ public/sound
public/piece
public/piece-css
public/flair
public/images
public/cursors
*.png
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.1"
version = "3.8.2"
runner.dialect = scala3

align.preset = more
Expand Down
1 change: 1 addition & 0 deletions COPYING.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public/piece/disguised | danegraphics | [CC BY-NC-SA 4.0](https://creativecommon
public/piece/kiwen-suwi | [neverRare](https://github.com/neverRare) | [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/)
public/piece/mpchess | [Maxime Chupin](https://github.com/chupinmaxime) | [GPL3v3+](https://www.gnu.org/licenses/quick-guide-gplv3.en.html)
public/piece/cooke | [fejfar](https://github.com/fejfar) | [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/)
public/piece/monarchy | [slither77](https://github.com/slither77) | [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/)
public/sounds/futuristic | [Enigmahack](https://github.com/Enigmahack) | AGPLv3+
public/sounds/nes | [Enigmahack](https://github.com/Enigmahack) | AGPLv3+
public/sounds/piano | [Enigmahack](https://github.com/Enigmahack) | AGPLv3+
Expand Down
147 changes: 78 additions & 69 deletions app/controllers/Challenge.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ final class Challenge(
api.allFor(me).map(env.challenge.jsonView.apply).map(JsonOk)
}

def apiList = ScopedBody(_.Challenge.Read) { ctx ?=> me ?=>
def apiList = ScopedBody(_.Challenge.Read, _.Web.Mobile) { ctx ?=> me ?=>
api.allFor(me, 300).map { all =>
JsonOk:
Json.obj(
Expand All @@ -39,18 +39,18 @@ final class Challenge(
def show(id: ChallengeId, _color: Option[Color]) = Open:
showId(id)

def apiShow(id: ChallengeId) = Scoped(_.Challenge.Read) { ctx ?=> _ ?=>
def apiShow(id: ChallengeId) = Scoped(_.Challenge.Read, _.Web.Mobile) { ctx ?=> _ ?=>
Found(api.byId(id)): c =>
val direction: Option[Direction] =
if isMine(c) then Direction.Out.some
else if isForMe(c) then Direction.In.some
else none
direction.so: dir =>
val json = env.challenge.jsonView(dir.some)(c)
for
fullId <- c.accepted.so(env.round.proxyRepo.game(c.gameId).map2(c.fullIdOf(_, dir)))
socketVersion <- ctx.isMobileOauth.so(env.challenge.version(c.id).dmap(some))
yield JsonOk(json.add("fullId", fullId).add("socketVersion", socketVersion))
json = env.challenge.jsonView.apiAndMobile(c, socketVersion, dir.some, fullId)
yield JsonOk(json)
}

protected[controllers] def showId(id: ChallengeId)(using Context): Fu[Result] =
Expand All @@ -69,7 +69,7 @@ final class Challenge(
if mine then Direction.Out.some
else if isForMe(c) then Direction.In.some
else none
val json = env.challenge.jsonView.show(c, version, direction)
val json = env.challenge.jsonView.websiteAndLichobile(c, version, direction)
negotiate(
html =
val color = get("color").flatMap(Color.fromName)
Expand Down Expand Up @@ -125,7 +125,7 @@ final class Challenge(
)

def apiAccept(id: ChallengeId) =
Scoped(_.Challenge.Write, _.Bot.Play, _.Board.Play) { _ ?=> me ?=>
Scoped(_.Challenge.Write, _.Bot.Play, _.Board.Play, _.Web.Mobile) { _ ?=> me ?=>
def tryRematch =
env.bot.player.rematchAccept(id.into(GameId)).flatMap {
if _ then jsonOkResult
Expand Down Expand Up @@ -173,19 +173,20 @@ final class Challenge(
)
.inject(NoContent)
}
def apiDecline(id: ChallengeId) = ScopedBody(_.Challenge.Write, _.Bot.Play, _.Board.Play) { ctx ?=> me ?=>
api.activeByIdFor(id, me).flatMap {
case None =>
env.bot.player.rematchDecline(id.into(GameId)).flatMap {
if _ then jsonOkResult
else notFoundJson()
}
case Some(c) =>
bindForm(env.challenge.forms.decline)(
jsonFormError,
data => api.decline(c, data.realReason).inject(jsonOkResult)
)
}
def apiDecline(id: ChallengeId) = ScopedBody(_.Challenge.Write, _.Bot.Play, _.Board.Play, _.Web.Mobile) {
ctx ?=> me ?=>
api.activeByIdFor(id, me).flatMap {
case None =>
env.bot.player.rematchDecline(id.into(GameId)).flatMap {
if _ then jsonOkResult
else notFoundJson()
}
case Some(c) =>
bindForm(env.challenge.forms.decline)(
jsonFormError,
data => api.decline(c, data.realReason).inject(jsonOkResult)
)
}
}

def cancel(id: ChallengeId) =
Expand All @@ -195,49 +196,50 @@ final class Challenge(
then api.cancel(c).inject(NoContent)
else notFound

def apiCancel(id: ChallengeId) = Scoped(_.Challenge.Write, _.Bot.Play, _.Board.Play) { ctx ?=> me ?=>
api.activeByIdBy(id, me).flatMap {
case Some(c) => api.cancel(c).inject(jsonOkResult)
case None =>
api.activeByIdFor(id, me).flatMap {
case Some(c) => api.decline(c, ChallengeModel.DeclineReason.default).inject(jsonOkResult)
case None =>
import lila.core.misc.map.Tell
import lila.core.round.Abort
import lila.core.round.AbortForce
env.game.gameRepo
.game(id.into(GameId))
.dmap {
_.flatMap { Pov(_, me) }
}
.flatMapz { p =>
env.round.proxyRepo.upgradeIfPresent(p).dmap(some)
}
.flatMap {
case Some(pov) if pov.game.abortableByUser =>
lila.common.Bus.publish(Tell(id.value, Abort(pov.playerId)), "roundSocket")
jsonOkResult
case Some(pov) if pov.game.playable =>
Bearer.from(get("opponentToken")) match
case Some(bearer) =>
val required = OAuthScope.select(_.Challenge.Write).into(EndpointScopes)
env.oAuth.server.auth(bearer, required, ctx.req.some).map {
case Right(access) if pov.opponent.isUser(access.me) =>
def apiCancel(id: ChallengeId) = Scoped(_.Challenge.Write, _.Bot.Play, _.Board.Play, _.Web.Mobile) {
ctx ?=> me ?=>
api.activeByIdBy(id, me).flatMap {
case Some(c) => api.cancel(c).inject(jsonOkResult)
case None =>
api.activeByIdFor(id, me).flatMap {
case Some(c) => api.decline(c, ChallengeModel.DeclineReason.default).inject(jsonOkResult)
case None =>
import lila.core.misc.map.Tell
import lila.core.round.Abort
import lila.core.round.AbortForce
env.game.gameRepo
.game(id.into(GameId))
.dmap {
_.flatMap { Pov(_, me) }
}
.flatMapz { p =>
env.round.proxyRepo.upgradeIfPresent(p).dmap(some)
}
.flatMap {
case Some(pov) if pov.game.abortableByUser =>
lila.common.Bus.publish(Tell(id.value, Abort(pov.playerId)), "roundSocket")
jsonOkResult
case Some(pov) if pov.game.playable =>
Bearer.from(get("opponentToken")) match
case Some(bearer) =>
val required = OAuthScope.select(_.Challenge.Write).into(EndpointScopes)
env.oAuth.server.auth(bearer, required, ctx.req.some).map {
case Right(access) if pov.opponent.isUser(access.me) =>
lila.common.Bus.publish(Tell(id.value, AbortForce), "roundSocket")
jsonOkResult
case Right(_) => BadRequest(jsonError("Not the opponent token"))
case Left(err) => BadRequest(jsonError(err.message))
}
case None if api.isOpenBy(id, me) =>
if pov.game.abortable then
lila.common.Bus.publish(Tell(id.value, AbortForce), "roundSocket")
jsonOkResult
case Right(_) => BadRequest(jsonError("Not the opponent token"))
case Left(err) => BadRequest(jsonError(err.message))
}
case None if api.isOpenBy(id, me) =>
if pov.game.abortable then
lila.common.Bus.publish(Tell(id.value, AbortForce), "roundSocket")
jsonOkResult
else BadRequest(jsonError("The game can no longer be aborted"))
case None => BadRequest(jsonError("Missing opponentToken"))
case _ => notFoundJson()
}
}
}
else BadRequest(jsonError("The game can no longer be aborted"))
case None => BadRequest(jsonError("Missing opponentToken"))
case _ => notFoundJson()
}
}
}
}

def apiStartClocks(id: GameId) = Anon:
Expand Down Expand Up @@ -308,15 +310,22 @@ final class Challenge(
JsonBadRequest:
jsonError(lila.challenge.ChallengeDenied.translated(denied))
case _ =>
env.challenge.api.create(challenge).map {
env.challenge.api.create(challenge).flatMap {
if _ then
val json = env.challenge.jsonView
.show(challenge, SocketVersion(0), lila.challenge.Direction.Out.some)
if config.keepAliveStream then
jsOptToNdJson:
ndJson.addKeepAlive(env.challenge.keepAliveStream(challenge, json))
else JsonOk(json)
else JsonBadRequest(jsonError("Challenge not created"))
ctx.isMobileOauth
.so(env.challenge.version(challenge.id).dmap(some))
.map: socketVersion =>
val json = env.challenge.jsonView
.apiAndMobile(
challenge,
socketVersion,
lila.challenge.Direction.Out.some
)
if config.keepAliveStream then
jsOptToNdJson:
ndJson.addKeepAlive(env.challenge.keepAliveStream(challenge, json))
else JsonOk(json)
else JsonBadRequest(jsonError("Challenge not created")).toFuccess
}
yield res
}
Expand Down Expand Up @@ -356,7 +365,7 @@ final class Challenge(
.map: challenge =>
JsonOk:
val url = s"${env.net.baseUrl}/${challenge.id}"
env.challenge.jsonView.show(challenge, SocketVersion(0), none) ++ Json.obj(
env.challenge.jsonView.apiAndMobile(challenge, none, none) ++ Json.obj(
"urlWhite" -> s"$url?color=white",
"urlBlack" -> s"$url?color=black"
)
Expand Down
18 changes: 11 additions & 7 deletions app/controllers/Fide.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,17 @@ final class Fide(env: Env) extends LilaController(env):
yield Ok(renderedPage)

def show(id: chess.FideId, slug: String, page: Int) = Open:
Found(env.fide.repo.player.fetch(id)): player =>
if player.slug != slug then Redirect(routes.Fide.show(id, player.slug))
else
for
tours <- env.relay.playerTour.playerTours(player, page)
rendered <- renderPage(views.fide.player.show(player, tours))
yield Ok(rendered)
env.fide.repo.player
.fetch(id)
.flatMap:
case None => NotFound.page(views.fide.player.notFound(id))
case Some(player) =>
if player.slug != slug then Redirect(routes.Fide.show(id, player.slug))
else
for
tours <- env.relay.playerTour.playerTours(player, page)
rendered <- renderPage(views.fide.player.show(player, tours))
yield Ok(rendered)

def federations(page: Int) = Open:
for
Expand Down
Loading

0 comments on commit 3547b56

Please sign in to comment.