From 78986a4aaf29ecb2ee3d8140162e827aef6d834a Mon Sep 17 00:00:00 2001 From: YaFred Date: Mon, 13 Jan 2025 23:07:05 +0100 Subject: [PATCH 1/6] strip chat info for kids --- app/controllers/Round.scala | 69 +++++++++++++++--------------- modules/chat/src/main/ChatUi.scala | 69 +++++++++++++++++------------- ui/chat/src/ctrl.ts | 9 ++-- ui/chat/src/interfaces.ts | 1 + 4 files changed, 81 insertions(+), 67 deletions(-) diff --git a/app/controllers/Round.scala b/app/controllers/Round.scala index b98c8f803b9e2..8199666854bd4 100644 --- a/app/controllers/Round.scala +++ b/app/controllers/Round.scala @@ -201,7 +201,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) @@ -212,41 +212,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 => diff --git a/modules/chat/src/main/ChatUi.scala b/modules/chat/src/main/ChatUi.scala index f276263c7aea4..0cd3e1cb6357b 100644 --- a/modules/chat/src/main/ChatUi.scala +++ b/modules/chat/src/main/ChatUi.scala @@ -64,34 +64,45 @@ final class ChatUi(helpers: Helpers): palantir: Boolean = false, hostIds: List[UserId] = Nil )(using ctx: Context): JsObject = - Json - .obj( - "data" -> Json + ctx.kid.yes match + case true => + Json .obj( - "id" -> chat.id, - "name" -> name, - "lines" -> lines, - "resourceId" -> resourceId.value + "data" -> false + ) + .add("kidMode" -> ctx.kid.yes) + .add("noteId" -> (withNoteAge.isDefined && ctx.noBlind).option(chat.id.value.take(8))) + .add("noteAge" -> withNoteAge) + case false => + Json + .obj( + "data" -> Json + .obj( + "id" -> chat.id, + "name" -> name, + "lines" -> lines, + "resourceId" -> resourceId.value + ) + .add("hostIds" -> hostIds.some.filter(_.nonEmpty)) + .add("userId" -> ctx.userId) + .add("loginRequired" -> chat.loginRequired) + .add("restricted" -> restricted) + .add("palantir" -> (palantir && ctx.isAuth)), + "writeable" -> writeable, + "public" -> public, + "permissions" -> Json + .obj("local" -> (public && localMod)) + .add("broadcast" -> (public && broadcastMod)) + .add("timeout" -> (public && Granter.opt(_.ChatTimeout))) + .add("shadowban" -> (public && Granter.opt(_.Shadowban))) + ) + .add("kidMode" -> ctx.kid.yes) + .add("kobold" -> ctx.troll) + .add("blind" -> ctx.blind) + .add("timeout" -> timeout) + .add("noteId" -> (withNoteAge.isDefined && ctx.noBlind).option(chat.id.value.take(8))) + .add("noteAge" -> withNoteAge) + .add( + "timeoutReasons" -> (!localMod && (Granter.opt(_.ChatTimeout) || Granter.opt(_.BroadcastTimeout))) + .option(JsonView.timeoutReasons) ) - .add("hostIds" -> hostIds.some.filter(_.nonEmpty)) - .add("userId" -> ctx.userId) - .add("loginRequired" -> chat.loginRequired) - .add("restricted" -> restricted) - .add("palantir" -> (palantir && ctx.isAuth)), - "writeable" -> writeable, - "public" -> public, - "permissions" -> Json - .obj("local" -> (public && localMod)) - .add("broadcast" -> (public && broadcastMod)) - .add("timeout" -> (public && Granter.opt(_.ChatTimeout))) - .add("shadowban" -> (public && Granter.opt(_.Shadowban))) - ) - .add("kobold" -> ctx.troll) - .add("blind" -> ctx.blind) - .add("timeout" -> timeout) - .add("noteId" -> (withNoteAge.isDefined && ctx.noBlind).option(chat.id.value.take(8))) - .add("noteAge" -> withNoteAge) - .add( - "timeoutReasons" -> (!localMod && (Granter.opt(_.ChatTimeout) || Granter.opt(_.BroadcastTimeout))) - .option(JsonView.timeoutReasons) - ) diff --git a/ui/chat/src/ctrl.ts b/ui/chat/src/ctrl.ts index f6b5835a27d88..aae62225746d5 100644 --- a/ui/chat/src/ctrl.ts +++ b/ui/chat/src/ctrl.ts @@ -25,7 +25,7 @@ export default class ChatCtrl { private maxLinesDrop = 50; // how many lines to drop at once private subs: [PubsubEvent, PubsubCallback][]; - allTabs: Tab[] = ['discussion']; + allTabs: Tab[] = []; palantir: ChatPalantir; tabStorage: LichessStorage = storage.make('chat.tab'); storedTab: string | null = this.tabStorage.get(); @@ -39,12 +39,13 @@ export default class ChatCtrl { readonly redraw: Redraw, ) { this.data = opts.data; + if (!opts.kidMode) this.allTabs.push('discussion'); if (opts.noteId) this.allTabs.push('note'); - if (opts.plugin) this.allTabs.push(opts.plugin.tab.key); + if (!opts.kidMode && opts.plugin) this.allTabs.push(opts.plugin.tab.key); this.palantir = { instance: undefined, loaded: false, - enabled: prop(!!this.data.palantir), + enabled: prop(!!this.data.palantir && !opts.kidMode), }; const noChat = storage.get('nochat'); this.vm = { @@ -71,6 +72,8 @@ export default class ChatCtrl { redraw: this.redraw, }); + if (opts.kidMode) return; + /* If discussion is disabled, and we have another chat tab, * then select that tab over discussion */ if (this.allTabs.length > 1 && this.vm.tab === 'discussion' && noChat) this.vm.tab = this.allTabs[1]; diff --git a/ui/chat/src/interfaces.ts b/ui/chat/src/interfaces.ts index e9af0f7925f08..c5aad21ec5305 100644 --- a/ui/chat/src/interfaces.ts +++ b/ui/chat/src/interfaces.ts @@ -20,6 +20,7 @@ export interface ChatOpts { noteText?: string; plugin?: ChatPlugin; alwaysEnabled: boolean; + kidMode: boolean; } export interface ChatPlugin { From 7b5f24fb2fb228dc9b2910d0d4701f81c3fa2ff8 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Tue, 14 Jan 2025 11:05:03 +0100 Subject: [PATCH 2/6] use if/then/else --- modules/chat/src/main/ChatUi.scala | 81 ++++++++++++++---------------- 1 file changed, 39 insertions(+), 42 deletions(-) diff --git a/modules/chat/src/main/ChatUi.scala b/modules/chat/src/main/ChatUi.scala index 0cd3e1cb6357b..a007a5061b78e 100644 --- a/modules/chat/src/main/ChatUi.scala +++ b/modules/chat/src/main/ChatUi.scala @@ -64,45 +64,42 @@ final class ChatUi(helpers: Helpers): palantir: Boolean = false, hostIds: List[UserId] = Nil )(using ctx: Context): JsObject = - ctx.kid.yes match - case true => - Json - .obj( - "data" -> false - ) - .add("kidMode" -> ctx.kid.yes) - .add("noteId" -> (withNoteAge.isDefined && ctx.noBlind).option(chat.id.value.take(8))) - .add("noteAge" -> withNoteAge) - case false => - Json - .obj( - "data" -> Json - .obj( - "id" -> chat.id, - "name" -> name, - "lines" -> lines, - "resourceId" -> resourceId.value - ) - .add("hostIds" -> hostIds.some.filter(_.nonEmpty)) - .add("userId" -> ctx.userId) - .add("loginRequired" -> chat.loginRequired) - .add("restricted" -> restricted) - .add("palantir" -> (palantir && ctx.isAuth)), - "writeable" -> writeable, - "public" -> public, - "permissions" -> Json - .obj("local" -> (public && localMod)) - .add("broadcast" -> (public && broadcastMod)) - .add("timeout" -> (public && Granter.opt(_.ChatTimeout))) - .add("shadowban" -> (public && Granter.opt(_.Shadowban))) - ) - .add("kidMode" -> ctx.kid.yes) - .add("kobold" -> ctx.troll) - .add("blind" -> ctx.blind) - .add("timeout" -> timeout) - .add("noteId" -> (withNoteAge.isDefined && ctx.noBlind).option(chat.id.value.take(8))) - .add("noteAge" -> withNoteAge) - .add( - "timeoutReasons" -> (!localMod && (Granter.opt(_.ChatTimeout) || Granter.opt(_.BroadcastTimeout))) - .option(JsonView.timeoutReasons) - ) + if ctx.kid.yes then + Json + .obj("data" -> false) + .add("kidMode" -> true) + .add("noteId" -> (withNoteAge.isDefined && ctx.noBlind).option(chat.id.value.take(8))) + .add("noteAge" -> withNoteAge) + else + Json + .obj( + "data" -> Json + .obj( + "id" -> chat.id, + "name" -> name, + "lines" -> lines, + "resourceId" -> resourceId.value + ) + .add("hostIds" -> hostIds.some.filter(_.nonEmpty)) + .add("userId" -> ctx.userId) + .add("loginRequired" -> chat.loginRequired) + .add("restricted" -> restricted) + .add("palantir" -> (palantir && ctx.isAuth)), + "writeable" -> writeable, + "public" -> public, + "permissions" -> Json + .obj("local" -> (public && localMod)) + .add("broadcast" -> (public && broadcastMod)) + .add("timeout" -> (public && Granter.opt(_.ChatTimeout))) + .add("shadowban" -> (public && Granter.opt(_.Shadowban))) + ) + .add("kidMode" -> ctx.kid.yes) + .add("kobold" -> ctx.troll) + .add("blind" -> ctx.blind) + .add("timeout" -> timeout) + .add("noteId" -> (withNoteAge.isDefined && ctx.noBlind).option(chat.id.value.take(8))) + .add("noteAge" -> withNoteAge) + .add( + "timeoutReasons" -> (!localMod && (Granter.opt(_.ChatTimeout) || Granter.opt(_.BroadcastTimeout))) + .option(JsonView.timeoutReasons) + ) From f9d025387ef1ea3e5e90c5fd7fb3fb3d9e937e3f Mon Sep 17 00:00:00 2001 From: YaFred Date: Tue, 14 Jan 2025 17:03:23 +0100 Subject: [PATCH 3/6] strip chat data but stick to ChatData type --- modules/chat/src/main/ChatUi.scala | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/modules/chat/src/main/ChatUi.scala b/modules/chat/src/main/ChatUi.scala index a007a5061b78e..294802dac7939 100644 --- a/modules/chat/src/main/ChatUi.scala +++ b/modules/chat/src/main/ChatUi.scala @@ -66,7 +66,18 @@ final class ChatUi(helpers: Helpers): )(using ctx: Context): JsObject = if ctx.kid.yes then Json - .obj("data" -> false) + .obj( + "data" -> Json + .obj( + "id" -> "", + "name" -> "", + "lines" -> JsonChatLines.empty, + "resourceId" -> "" + ) + .add("loginRequired" -> true) + .add("restricted" -> true) + .add("palantir" -> false) + ) .add("kidMode" -> true) .add("noteId" -> (withNoteAge.isDefined && ctx.noBlind).option(chat.id.value.take(8))) .add("noteAge" -> withNoteAge) From ea8aec2902765ad098f075e0f3a4430910db4a98 Mon Sep 17 00:00:00 2001 From: YaFred Date: Tue, 14 Jan 2025 17:14:33 +0100 Subject: [PATCH 4/6] refactor (remove duplicates) --- modules/chat/src/main/ChatUi.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/chat/src/main/ChatUi.scala b/modules/chat/src/main/ChatUi.scala index 294802dac7939..97932df0df81f 100644 --- a/modules/chat/src/main/ChatUi.scala +++ b/modules/chat/src/main/ChatUi.scala @@ -64,6 +64,7 @@ final class ChatUi(helpers: Helpers): palantir: Boolean = false, hostIds: List[UserId] = Nil )(using ctx: Context): JsObject = + val noteId = (withNoteAge.isDefined && ctx.noBlind).option(chat.id.value.take(8)) if ctx.kid.yes then Json .obj( @@ -79,7 +80,7 @@ final class ChatUi(helpers: Helpers): .add("palantir" -> false) ) .add("kidMode" -> true) - .add("noteId" -> (withNoteAge.isDefined && ctx.noBlind).option(chat.id.value.take(8))) + .add("noteId" -> noteId) .add("noteAge" -> withNoteAge) else Json @@ -108,7 +109,7 @@ final class ChatUi(helpers: Helpers): .add("kobold" -> ctx.troll) .add("blind" -> ctx.blind) .add("timeout" -> timeout) - .add("noteId" -> (withNoteAge.isDefined && ctx.noBlind).option(chat.id.value.take(8))) + .add("noteId" -> noteId) .add("noteAge" -> withNoteAge) .add( "timeoutReasons" -> (!localMod && (Granter.opt(_.ChatTimeout) || Granter.opt(_.BroadcastTimeout))) From 8b300694a54492b9c21073938ca26af64abf363a Mon Sep 17 00:00:00 2001 From: YaFred Date: Tue, 14 Jan 2025 17:20:09 +0100 Subject: [PATCH 5/6] remove superfluous field kidMode --- modules/chat/src/main/ChatUi.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/chat/src/main/ChatUi.scala b/modules/chat/src/main/ChatUi.scala index 97932df0df81f..06eec147b5a40 100644 --- a/modules/chat/src/main/ChatUi.scala +++ b/modules/chat/src/main/ChatUi.scala @@ -105,7 +105,6 @@ final class ChatUi(helpers: Helpers): .add("timeout" -> (public && Granter.opt(_.ChatTimeout))) .add("shadowban" -> (public && Granter.opt(_.Shadowban))) ) - .add("kidMode" -> ctx.kid.yes) .add("kobold" -> ctx.troll) .add("blind" -> ctx.blind) .add("timeout" -> timeout) From 60698716219bb933409bc6bdadce7e139d45754d Mon Sep 17 00:00:00 2001 From: YaFred Date: Wed, 15 Jan 2025 18:43:18 +0100 Subject: [PATCH 6/6] fix json in kidMode --- modules/chat/src/main/ChatUi.scala | 14 +------------- ui/chat/src/ctrl.ts | 2 +- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/modules/chat/src/main/ChatUi.scala b/modules/chat/src/main/ChatUi.scala index 06eec147b5a40..6607ce3cdd717 100644 --- a/modules/chat/src/main/ChatUi.scala +++ b/modules/chat/src/main/ChatUi.scala @@ -67,19 +67,7 @@ final class ChatUi(helpers: Helpers): val noteId = (withNoteAge.isDefined && ctx.noBlind).option(chat.id.value.take(8)) if ctx.kid.yes then Json - .obj( - "data" -> Json - .obj( - "id" -> "", - "name" -> "", - "lines" -> JsonChatLines.empty, - "resourceId" -> "" - ) - .add("loginRequired" -> true) - .add("restricted" -> true) - .add("palantir" -> false) - ) - .add("kidMode" -> true) + .obj("kidMode" -> true) .add("noteId" -> noteId) .add("noteAge" -> withNoteAge) else diff --git a/ui/chat/src/ctrl.ts b/ui/chat/src/ctrl.ts index aae62225746d5..4c416808a02ed 100644 --- a/ui/chat/src/ctrl.ts +++ b/ui/chat/src/ctrl.ts @@ -45,7 +45,7 @@ export default class ChatCtrl { this.palantir = { instance: undefined, loaded: false, - enabled: prop(!!this.data.palantir && !opts.kidMode), + enabled: prop(!opts.kidMode && !!this.data.palantir), }; const noChat = storage.get('nochat'); this.vm = {