further optimize chat
parent
6bda5fa715
commit
e4578072a1
|
@ -46,7 +46,7 @@ final class BotPlayer(
|
|||
val source = d.room == "spectator" option {
|
||||
lila.hub.actorApi.shutup.PublicSource.Watcher(gameId)
|
||||
}
|
||||
chatApi.userChat.write(chatId, me.id, d.text, publicSource = source)
|
||||
chatApi.userChat.write(chatId, me.id, d.text, publicSource = source, _.Round)
|
||||
}
|
||||
|
||||
def rematchAccept(id: Game.ID, me: User): Fu[Boolean] = rematch(id, me, true)
|
||||
|
|
|
@ -80,7 +80,7 @@ final class ChatApi(
|
|||
userId: User.ID,
|
||||
text: String,
|
||||
publicSource: Option[PublicSource],
|
||||
busChan: Option[String] = None
|
||||
busChan: BusChan.Select
|
||||
): Funit =
|
||||
makeLine(chatId, userId, text) flatMap {
|
||||
_ ?? { line =>
|
||||
|
@ -100,14 +100,14 @@ final class ChatApi(
|
|||
|
||||
def clear(chatId: Chat.Id) = coll.delete.one($id(chatId)).void
|
||||
|
||||
def system(chatId: Chat.Id, text: String, busChan: Option[String] = None): Funit = {
|
||||
def system(chatId: Chat.Id, text: String, busChan: BusChan.Select): Funit = {
|
||||
val line = UserLine(systemUserId, None, text, troll = false, deleted = false)
|
||||
pushLine(chatId, line) >>-
|
||||
publish(chatId, actorApi.ChatLine(chatId, line), busChan)
|
||||
}
|
||||
|
||||
// like system, but not persisted.
|
||||
def volatile(chatId: Chat.Id, text: String, busChan: Option[String]): Unit = {
|
||||
def volatile(chatId: Chat.Id, text: String, busChan: BusChan.Select): Unit = {
|
||||
val line = UserLine(systemUserId, None, text, troll = false, deleted = false)
|
||||
publish(chatId, actorApi.ChatLine(chatId, line), busChan)
|
||||
}
|
||||
|
@ -118,11 +118,12 @@ final class ChatApi(
|
|||
userId: User.ID,
|
||||
reason: ChatTimeout.Reason,
|
||||
scope: ChatTimeout.Scope,
|
||||
text: String
|
||||
text: String,
|
||||
busChan: BusChan.Select
|
||||
): 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) || scope == ChatTimeout.Scope.Local =>
|
||||
doTimeout(chat, mod, user, reason, scope, text)
|
||||
doTimeout(chat, mod, user, reason, scope, text, busChan)
|
||||
case _ => fuccess(none)
|
||||
}
|
||||
|
||||
|
@ -139,7 +140,8 @@ final class ChatApi(
|
|||
user: User,
|
||||
reason: ChatTimeout.Reason,
|
||||
scope: ChatTimeout.Scope,
|
||||
text: String
|
||||
text: String,
|
||||
busChan: BusChan.Select
|
||||
): Funit = {
|
||||
val line = c.hasRecentLine(user) option UserLine(
|
||||
username = systemUserId,
|
||||
|
@ -153,9 +155,9 @@ final class ChatApi(
|
|||
coll.update.one($id(chat.id), chat).void >>
|
||||
chatTimeout.add(c, mod, user, reason, scope) >>- {
|
||||
cached invalidate chat.id
|
||||
publish(chat.id, actorApi.OnTimeout(chat.id, user.id))
|
||||
publish(chat.id, actorApi.OnTimeout(chat.id, user.id), busChan)
|
||||
line foreach { l =>
|
||||
publish(chat.id, actorApi.ChatLine(chat.id, l))
|
||||
publish(chat.id, actorApi.ChatLine(chat.id, l), busChan)
|
||||
}
|
||||
if (isMod(mod))
|
||||
modActor ! lila.hub.actorApi.mod.ChatTimeout(
|
||||
|
@ -168,19 +170,18 @@ final class ChatApi(
|
|||
}
|
||||
}
|
||||
|
||||
def delete(c: UserChat, user: User): Funit = {
|
||||
def delete(c: UserChat, user: User, busChan: BusChan.Select): Funit = {
|
||||
val chat = c.markDeleted(user)
|
||||
coll.update.one($id(chat.id), chat).void >>- {
|
||||
cached invalidate chat.id
|
||||
publish(chat.id, actorApi.OnTimeout(chat.id, user.id))
|
||||
publish(chat.id, actorApi.OnTimeout(chat.id, user.id), busChan)
|
||||
}
|
||||
}
|
||||
|
||||
private def isMod(user: User) = lila.security.Granter(_.ChatTimeout)(user)
|
||||
|
||||
def reinstate(list: List[ChatTimeout.Reinstate]) = list.foreach { r =>
|
||||
val chatId = Chat.Id(r.chat)
|
||||
publish(chatId, actorApi.OnReinstate(chatId, r.user))
|
||||
Bus.publish(actorApi.OnReinstate(Chat.Id(r.chat), r.user), BusChan.Global.chan)
|
||||
}
|
||||
|
||||
private[ChatApi] def makeLine(chatId: Chat.Id, userId: String, t1: String): Fu[Option[UserLine]] =
|
||||
|
@ -219,10 +220,10 @@ final class ChatApi(
|
|||
def optionsByOrderedIds(chatIds: List[Chat.Id]): Fu[List[Option[MixedChat]]] =
|
||||
coll.optionsByOrderedIds[MixedChat, Chat.Id](chatIds, none, ReadPreference.secondaryPreferred)(_.id)
|
||||
|
||||
def write(chatId: Chat.Id, color: Color, text: String, busChan: String): Funit =
|
||||
def write(chatId: Chat.Id, color: Color, text: String, busChan: BusChan.Select): Funit =
|
||||
makeLine(chatId, color, text) ?? { line =>
|
||||
pushLine(chatId, line) >>- {
|
||||
publish(chatId, actorApi.ChatLine(chatId, line), busChan.some)
|
||||
publish(chatId, actorApi.ChatLine(chatId, line), busChan)
|
||||
lila.mon.chat.message("anonPlayer", false).increment()
|
||||
}
|
||||
}
|
||||
|
@ -234,8 +235,8 @@ final class ChatApi(
|
|||
}
|
||||
}
|
||||
|
||||
private def publish(chatId: Chat.Id, msg: Any, busChan: Option[String] = None): Unit = {
|
||||
Bus.publish(msg, busChan | "chat")
|
||||
private def publish(chatId: Chat.Id, msg: Any, busChan: BusChan.Select): Unit = {
|
||||
Bus.publish(msg, busChan(BusChan).chan)
|
||||
Bus.publish(msg, Chat chanOf chatId)
|
||||
}
|
||||
|
||||
|
|
|
@ -6,3 +6,16 @@ case class UserModInfo(
|
|||
user: User,
|
||||
history: List[ChatTimeout.UserEntry]
|
||||
)
|
||||
|
||||
sealed trait BusChan {
|
||||
lazy val chan = s"chat:${toString.toLowerCase}"
|
||||
}
|
||||
object BusChan {
|
||||
case object Round extends BusChan
|
||||
case object Tournament extends BusChan
|
||||
case object Simul extends BusChan
|
||||
case object Study extends BusChan
|
||||
case object Global extends BusChan
|
||||
|
||||
type Select = BusChan.type => BusChan
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ final class PublicChat(
|
|||
case (tours, simuls) =>
|
||||
(tours.map(_._2) ::: simuls.map(_._2))
|
||||
.filter(_ hasLinesOf suspect.user)
|
||||
.map(chatApi.userChat.delete(_, suspect.user))
|
||||
.map(chatApi.userChat.delete(_, suspect.user, _.Global))
|
||||
.sequenceFu
|
||||
.void
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ final private class PlaybanFeedback(
|
|||
pov.player.userId foreach { userId =>
|
||||
lightUser(userId) foreach { light =>
|
||||
val message = template.replace("{user}", light.fold(userId)(_.name))
|
||||
chatApi.userChat.volatile(Chat.Id(pov.gameId), message, "chat:round".some)
|
||||
chatApi.userChat.volatile(Chat.Id(pov.gameId), message, _.Round)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package lila.room
|
||||
|
||||
import lila.chat.{ Chat, ChatApi, ChatTimeout, UserLine }
|
||||
import lila.chat.{ BusChan, Chat, ChatApi, ChatTimeout, UserLine }
|
||||
import lila.hub.actorApi.shutup.PublicSource
|
||||
import lila.hub.{ Trouper, TrouperMap }
|
||||
import lila.log.Logger
|
||||
|
@ -61,16 +61,31 @@ object RoomSocket {
|
|||
chat: ChatApi,
|
||||
logger: Logger,
|
||||
publicSource: RoomId => PublicSource.type => Option[PublicSource],
|
||||
localTimeout: Option[(RoomId, User.ID, User.ID) => Fu[Boolean]] = None
|
||||
localTimeout: Option[(RoomId, User.ID, User.ID) => Fu[Boolean]] = None,
|
||||
chatBusChan: BusChan.Select
|
||||
)(implicit ec: ExecutionContext): Handler =
|
||||
({
|
||||
case Protocol.In.ChatSay(roomId, userId, msg) =>
|
||||
chat.userChat.write(Chat.Id(roomId.value), userId, msg, publicSource(roomId)(PublicSource))
|
||||
chat.userChat.write(
|
||||
Chat.Id(roomId.value),
|
||||
userId,
|
||||
msg,
|
||||
publicSource(roomId)(PublicSource),
|
||||
chatBusChan
|
||||
)
|
||||
case Protocol.In.ChatTimeout(roomId, modId, suspect, reason, text) =>
|
||||
lila.chat.ChatTimeout.Reason(reason) foreach { r =>
|
||||
localTimeout.?? { _(roomId, modId, suspect) } foreach { local =>
|
||||
val scope = if (local) ChatTimeout.Scope.Local else ChatTimeout.Scope.Global
|
||||
chat.userChat.timeout(Chat.Id(roomId.value), modId, suspect, r, text = text, scope = scope)
|
||||
chat.userChat.timeout(
|
||||
Chat.Id(roomId.value),
|
||||
modId,
|
||||
suspect,
|
||||
r,
|
||||
text = text,
|
||||
scope = scope,
|
||||
busChan = chatBusChan
|
||||
)
|
||||
}
|
||||
}
|
||||
}: Handler) orElse minRoomHandler(rooms, logger)
|
||||
|
@ -91,9 +106,9 @@ object RoomSocket {
|
|||
|
||||
private val chatMsgs = Set("message", "chat_timeout", "chat_reinstate")
|
||||
|
||||
def subscribeChat(rooms: TrouperMap[RoomState]) = {
|
||||
def subscribeChat(rooms: TrouperMap[RoomState], busChan: BusChan.Select) = {
|
||||
import lila.chat.actorApi._
|
||||
lila.common.Bus.subscribeFun("chat") {
|
||||
lila.common.Bus.subscribeFun(busChan(BusChan).chan, BusChan.Global.chan) {
|
||||
case ChatLine(id, line: UserLine) =>
|
||||
rooms.tellIfPresent(id.value, NotifyVersion("message", lila.chat.JsonView(line), line.troll))
|
||||
case OnTimeout(id, userId) =>
|
||||
|
|
|
@ -7,8 +7,6 @@ import lila.user.User
|
|||
|
||||
final class Messenger(api: ChatApi) {
|
||||
|
||||
private[round] val busChan = "chat:round"
|
||||
|
||||
def system(game: Game, message: String): Unit =
|
||||
system(true)(game, message)
|
||||
|
||||
|
@ -19,16 +17,16 @@ final class Messenger(api: ChatApi) {
|
|||
val apiCall =
|
||||
if (persistent) api.userChat.system _
|
||||
else api.userChat.volatile _
|
||||
apiCall(watcherId(Chat.Id(game.id)), message, busChan.some)
|
||||
if (game.nonAi) apiCall(Chat.Id(game.id), message, busChan.some)
|
||||
apiCall(watcherId(Chat.Id(game.id)), message, _.Round)
|
||||
if (game.nonAi) apiCall(Chat.Id(game.id), message, _.Round)
|
||||
}
|
||||
|
||||
def systemForOwners(chatId: Chat.Id, message: String): Unit = {
|
||||
api.userChat.system(chatId, message, busChan.some)
|
||||
api.userChat.system(chatId, message, _.Round)
|
||||
}
|
||||
|
||||
def watcher(gameId: Game.Id, userId: User.ID, text: String) =
|
||||
api.userChat.write(watcherId(gameId), userId, text, PublicSource.Watcher(gameId.value).some, busChan.some)
|
||||
api.userChat.write(watcherId(gameId), userId, text, PublicSource.Watcher(gameId.value).some, _.Round)
|
||||
|
||||
private val whisperCommands = List("/whisper ", "/w ")
|
||||
|
||||
|
@ -36,18 +34,18 @@ final class Messenger(api: ChatApi) {
|
|||
whisperCommands.collectFirst {
|
||||
case command if text startsWith command =>
|
||||
val source = PublicSource.Watcher(gameId.value)
|
||||
api.userChat.write(watcherId(gameId), userId, text drop command.size, source.some, busChan.some)
|
||||
api.userChat.write(watcherId(gameId), userId, text drop command.size, source.some, _.Round)
|
||||
} getOrElse {
|
||||
if (!text.startsWith("/")) // mistyped command?
|
||||
api.userChat.write(Chat.Id(gameId.value), userId, text, publicSource = none, busChan.some).some
|
||||
api.userChat.write(Chat.Id(gameId.value), userId, text, publicSource = none, _.Round).some
|
||||
}
|
||||
|
||||
def owner(gameId: Game.Id, anonColor: chess.Color, text: String): Unit =
|
||||
api.playerChat.write(Chat.Id(gameId.value), anonColor, text, busChan)
|
||||
api.playerChat.write(Chat.Id(gameId.value), anonColor, text, _.Round)
|
||||
|
||||
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, ChatTimeout.Scope.Global, text)
|
||||
api.userChat.timeout(chatId, modId, suspect, r, ChatTimeout.Scope.Global, text, _.Round)
|
||||
}
|
||||
|
||||
private def watcherId(chatId: Chat.Id) = Chat.Id(s"$chatId/w")
|
||||
|
|
|
@ -9,7 +9,7 @@ import actorApi._
|
|||
import actorApi.round._
|
||||
import chess.format.Uci
|
||||
import chess.{ Black, Centis, Color, MoveMetrics, Speed, White }
|
||||
import lila.chat.Chat
|
||||
import lila.chat.{ BusChan, Chat }
|
||||
import lila.common.{ Bus, IpAddress, Lilakka }
|
||||
import lila.game.Game.{ FullId, PlayerId }
|
||||
import lila.game.{ Event, Game, Pov }
|
||||
|
@ -173,7 +173,7 @@ final class RoundSocket(
|
|||
|
||||
{
|
||||
import lila.chat.actorApi._
|
||||
Bus.subscribeFun(messenger.busChan) {
|
||||
Bus.subscribeFun(BusChan.Round.chan, BusChan.Global.chan) {
|
||||
case ChatLine(Chat.Id(id), l) =>
|
||||
val line = RoundLine(l, id endsWith "/w")
|
||||
rounds.tellIfPresent(if (line.watcher) id take Game.gameIdSize else id, line)
|
||||
|
|
|
@ -46,9 +46,10 @@ final private class SimulSocket(
|
|||
|
||||
lazy val rooms = makeRoomMap(send)
|
||||
|
||||
subscribeChat(rooms)
|
||||
subscribeChat(rooms, _.Simul)
|
||||
|
||||
private lazy val handler: Handler = roomHandler(rooms, chat, logger, roomId => _.Simul(roomId.value).some)
|
||||
private lazy val handler: Handler =
|
||||
roomHandler(rooms, chat, logger, roomId => _.Simul(roomId.value).some, chatBusChan = _.Simul)
|
||||
|
||||
private lazy val send: String => Unit = remoteSocketApi.makeSender("simul-out").apply _
|
||||
|
||||
|
|
|
@ -153,7 +153,8 @@ final private class ChapterMaker(
|
|||
chatId = Chat.Id(chatId),
|
||||
userId = userId,
|
||||
text = s"I'm studying this game on ${net.domain}/study/${study.id}",
|
||||
publicSource = none
|
||||
publicSource = none,
|
||||
_.Study
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -129,7 +129,8 @@ final class StudyApi(
|
|||
newChapters.map(chapterRepo.insert).sequenceFu >>- {
|
||||
chatApi.userChat.system(
|
||||
Chat.Id(study.id.value),
|
||||
s"Cloned from lichess.org/study/${prev.id}"
|
||||
s"Cloned from lichess.org/study/${prev.id}",
|
||||
_.Study
|
||||
)
|
||||
} inject study.some
|
||||
}
|
||||
|
@ -161,7 +162,8 @@ final class StudyApi(
|
|||
Chat.Id(studyId.value),
|
||||
userId = userId,
|
||||
text = text,
|
||||
publicSource = lila.hub.actorApi.shutup.PublicSource.Study(studyId.value).some
|
||||
publicSource = lila.hub.actorApi.shutup.PublicSource.Study(studyId.value).some,
|
||||
busChan = _.Study
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ final private class StudySocket(
|
|||
|
||||
lazy val rooms = makeRoomMap(send)
|
||||
|
||||
subscribeChat(rooms)
|
||||
subscribeChat(rooms, _.Study)
|
||||
|
||||
def isPresent(studyId: Study.Id, userId: User.ID): Fu[Boolean] =
|
||||
remoteSocketApi.request[Boolean](
|
||||
|
@ -221,7 +221,8 @@ final private class StudySocket(
|
|||
_ => _ => none, // the "talk" event is handled by the study API
|
||||
localTimeout = Some { (roomId, modId, suspectId) =>
|
||||
api.isContributor(roomId, modId) >>& !api.isMember(roomId, suspectId)
|
||||
}
|
||||
},
|
||||
chatBusChan = _.Study
|
||||
)
|
||||
|
||||
private def moveOrDrop(studyId: Study.Id, m: AnaAny, opts: MoveOpts)(who: Who) = m.branch match {
|
||||
|
|
|
@ -67,10 +67,10 @@ final private class TournamentSocket(
|
|||
|
||||
lazy val rooms = makeRoomMap(send)
|
||||
|
||||
subscribeChat(rooms)
|
||||
subscribeChat(rooms, _.Tournament)
|
||||
|
||||
private lazy val handler: Handler =
|
||||
roomHandler(rooms, chat, logger, roomId => _.Tournament(roomId.value).some)
|
||||
roomHandler(rooms, chat, logger, roomId => _.Tournament(roomId.value).some, chatBusChan = _.Tournament)
|
||||
|
||||
private lazy val tourHandler: Handler = {
|
||||
case Protocol.In.WaitingUsers(roomId, users) =>
|
||||
|
|
Loading…
Reference in New Issue