log the user text when a chat timeout occurs

pull/6119/head
Thibault Duplessis 2020-03-03 09:44:36 -06:00
parent 847a51266b
commit 488295f7ce
9 changed files with 29 additions and 38 deletions

View File

@ -110,10 +110,11 @@ final class ChatApi(
modId: User.ID,
userId: User.ID,
reason: ChatTimeout.Reason,
text: String,
local: Boolean
): Funit =
coll.byId[UserChat](chatId.value) zip userRepo.byId(modId) zip userRepo.byId(userId) flatMap {
case Some(chat) ~ Some(mod) ~ Some(user) if isMod(mod) || local => doTimeout(chat, mod, user, reason)
case Some(chat) ~ Some(mod) ~ Some(user) if isMod(mod) || local => doTimeout(chat, mod, user, reason, text)
case _ => fuccess(none)
}
@ -124,7 +125,7 @@ final class ChatApi(
}
}
private def doTimeout(c: UserChat, mod: User, user: User, reason: ChatTimeout.Reason): Funit = {
private def doTimeout(c: UserChat, mod: User, user: User, reason: ChatTimeout.Reason, text: String): Funit = {
val line = c.hasRecentLine(user) option UserLine(
username = systemUserId,
title = None,
@ -145,7 +146,8 @@ final class ChatApi(
modActor ! lila.hub.actorApi.mod.ChatTimeout(
mod = mod.id,
user = user.id,
reason = reason.key
reason = reason.key,
text = text
)
else logger.info(s"${mod.username} times out ${user.username} in #${c.id} for ${reason.key}")
}

View File

@ -79,7 +79,7 @@ package shutup {
package mod {
case class MarkCheater(userId: String, value: Boolean)
case class MarkBooster(userId: String)
case class ChatTimeout(mod: String, user: String, reason: String)
case class ChatTimeout(mod: String, user: String, reason: String, text: String)
case class Shadowban(user: String, value: Boolean)
case class KickFromRankings(userId: String)
case class SetPermissions(userId: String, permissions: List[String])

View File

@ -99,7 +99,7 @@ final class Env(
}
if (game.status == chess.Status.Cheat)
game.loserUserId foreach { logApi.cheatDetected(_, game.id) }
case lila.hub.actorApi.mod.ChatTimeout(mod, user, reason) => logApi.chatTimeout(mod, user, reason)
case lila.hub.actorApi.mod.ChatTimeout(mod, user, reason, text) => logApi.chatTimeout(mod, user, reason, text)
case lila.hub.actorApi.security.GCImmediateSb(userId) =>
reportApi getSuspect userId orFail s"No such suspect $userId" flatMap { sus =>
reportApi.getLichessMod map { mod =>

View File

@ -107,9 +107,7 @@ final class ModlogApi(repo: ModlogRepo, userRepo: UserRepo, slackApi: lila.slack
mod,
none,
if (closed) Modlog.closeTopic else Modlog.openTopic,
details = Some(
categ + " / " + topic
)
details = s"$categ/$topic".some
)
}
@ -118,9 +116,7 @@ final class ModlogApi(repo: ModlogRepo, userRepo: UserRepo, slackApi: lila.slack
mod,
none,
if (hidden) Modlog.hideTopic else Modlog.showTopic,
details = Some(
categ + " / " + topic
)
details = s"$categ/$topic".some
)
}
@ -129,9 +125,7 @@ final class ModlogApi(repo: ModlogRepo, userRepo: UserRepo, slackApi: lila.slack
mod,
none,
if (sticky) Modlog.stickyTopic else Modlog.unstickyTopic,
details = Some(
categ + " / " + topic
)
details = s"$categ/$topic".some
)
}
@ -143,8 +137,8 @@ final class ModlogApi(repo: ModlogRepo, userRepo: UserRepo, slackApi: lila.slack
Modlog(mod, none, Modlog.terminateTournament, details = name.some)
}
def chatTimeout(mod: User.ID, user: User.ID, reason: String) = add {
Modlog(mod, user.some, Modlog.chatTimeout, details = reason.some)
def chatTimeout(mod: User.ID, user: User.ID, reason: String, text: String) = add {
Modlog(mod, user.some, Modlog.chatTimeout, details = s"$reason: $text".some)
}
def setPermissions(mod: Mod, user: User.ID, permissions: List[Permission]) = add {

View File

@ -80,10 +80,10 @@ object RoomSocket {
({
case Protocol.In.ChatSay(roomId, userId, msg) =>
chat.userChat.write(Chat.Id(roomId.value), userId, msg, publicSource(roomId)(PublicSource))
case Protocol.In.ChatTimeout(roomId, modId, suspect, reason) =>
case Protocol.In.ChatTimeout(roomId, modId, suspect, reason, text) =>
lila.chat.ChatTimeout.Reason(reason) foreach { r =>
localTimeout.?? { _(roomId, modId, suspect) } foreach { local =>
chat.userChat.timeout(Chat.Id(roomId.value), modId, suspect, r, local = local)
chat.userChat.timeout(Chat.Id(roomId.value), modId, suspect, r, text = text, local = local)
}
}
}: Handler) orElse minRoomHandler(rooms, logger)
@ -107,7 +107,7 @@ object RoomSocket {
object In {
case class ChatSay(roomId: RoomId, userId: String, msg: String) extends P.In
case class ChatTimeout(roomId: RoomId, userId: String, suspect: String, reason: String) extends P.In
case class ChatTimeout(roomId: RoomId, userId: String, suspect: String, reason: String, text: String) extends P.In
case class KeepAlives(roomIds: Iterable[RoomId]) extends P.In
case class TellRoomSri(roomId: RoomId, tellSri: P.In.TellSri) extends P.In
case class SetVersions(versions: Iterable[(String, SocketVersion)]) extends P.In
@ -120,9 +120,9 @@ object RoomSocket {
case Array(roomId, userId, msg) => ChatSay(RoomId(roomId), userId, msg).some
}
case "chat/timeout" =>
raw.get(4) {
case Array(roomId, userId, suspect, reason) =>
ChatTimeout(RoomId(roomId), userId, suspect, reason).some
raw.get(5) {
case Array(roomId, userId, suspect, reason, text) =>
ChatTimeout(RoomId(roomId), userId, suspect, reason, text).some
}
case "tell/room/sri" =>
raw.get(4) {

View File

@ -3,8 +3,6 @@ package lila.round
import lila.chat.{ Chat, ChatApi, ChatTimeout }
import lila.game.Game
import lila.hub.actorApi.shutup.PublicSource
import lila.i18n.I18nKey.{ Select => SelectI18nKey }
import lila.i18n.{ enLang, I18nKeys }
import lila.user.User
final class Messenger(api: ChatApi) {
@ -49,9 +47,9 @@ final class Messenger(api: ChatApi) {
def external(setup: Chat.Setup, userId: User.ID, text: String): Unit =
api.userChat.write(setup.id, userId, text, setup.publicSource.some)
def timeout(chatId: Chat.Id, modId: User.ID, suspect: User.ID, reason: String): Unit =
def timeout(chatId: Chat.Id, modId: User.ID, suspect: User.ID, reason: String, text: String): Unit =
ChatTimeout.Reason(reason) foreach { r =>
api.userChat.timeout(chatId, modId, suspect, r, local = false)
api.userChat.timeout(chatId, modId, suspect, r, text, local = false)
}
private def watcherId(chatId: Chat.Id) = Chat.Id(s"$chatId/w")

View File

@ -109,8 +109,8 @@ final class RoundSocket(
case c: Protocol.In.PlayerChatSay => tellRound(c.gameId, c)
case Protocol.In.WatcherChatSay(gameId, userId, msg) =>
messenger.watcher(Chat.Id(gameId.value), userId, msg)
case RP.In.ChatTimeout(roomId, modId, suspect, reason) =>
messenger.timeout(Chat.Id(s"$roomId/w"), modId, suspect, reason)
case RP.In.ChatTimeout(roomId, modId, suspect, reason, text) =>
messenger.timeout(Chat.Id(s"$roomId/w"), modId, suspect, reason, text)
case Protocol.In.Berserk(gameId, userId) => tournamentActor ! Berserk(gameId.value, userId)
case Protocol.In.PlayerOnlines(onlines) =>
onlines foreach {

View File

@ -117,7 +117,7 @@ export interface ModerationCtrl {
permissions(): Permissions
open(line: HTMLElement): void
close(): void
timeout(reason: ModerationReason): void
timeout(reason: ModerationReason, text: string): void
}
export interface ModerationData {

View File

@ -43,10 +43,11 @@ export function moderationCtrl(opts: ModerationOpts): ModerationCtrl {
permissions: () => opts.permissions,
open,
close,
timeout(reason: ModerationReason) {
timeout(reason: ModerationReason, text: string) {
data && window.lichess.pubsub.emit('socket.send', 'timeout', {
userId: data.id,
reason: reason.key
reason: reason.key,
text
});
close();
opts.redraw();
@ -54,11 +55,7 @@ export function moderationCtrl(opts: ModerationOpts): ModerationCtrl {
};
}
export function lineAction() {
return h('i.mod', {
attrs: { 'data-icon': '' }
});
}
export const lineAction = () => h('i.mod', { attrs: { 'data-icon': '' } });
export function moderationView(ctrl?: ModerationCtrl): VNode[] | undefined {
if (!ctrl) return;
@ -92,14 +89,14 @@ export function moderationView(ctrl?: ModerationCtrl): VNode[] | undefined {
...ctrl.reasons.map(r => {
return h('a.text', {
attrs: { 'data-icon': 'p' },
hook: bind('click', () => ctrl.timeout(r))
hook: bind('click', () => ctrl.timeout(r, data.text))
}, r.name);
})
]) : h('div.timeout.block', [
h('strong', 'Moderation'),
h('a.text', {
attrs: { 'data-icon': 'p' },
hook: bind('click', () => ctrl.timeout(ctrl.reasons[0]))
hook: bind('click', () => ctrl.timeout(ctrl.reasons[0], data.text))
}, 'Timeout 10 minutes')
]);