show patron flair in chats - for lichess-org/strategy#90
parent
5709fb4312
commit
9d42eebcb0
|
@ -97,7 +97,7 @@ final class GameStateStream(
|
|||
|
||||
def receive = {
|
||||
case MoveGameEvent(g, _, _) if g.id == id && !g.finished => pushState(g).unit
|
||||
case lila.chat.actorApi.ChatLine(chatId, UserLine(username, _, text, false, false)) =>
|
||||
case lila.chat.actorApi.ChatLine(chatId, UserLine(username, _, _, text, false, false)) =>
|
||||
pushChatLine(username, text, chatId.value.lengthIs == Game.gameIdSize).unit
|
||||
case FinishGame(g, _, _) if g.id == id => onGameOver(g.some).unit
|
||||
case AbortedBy(pov) if pov.gameId == id => onGameOver(pov.game.some).unit
|
||||
|
|
|
@ -122,7 +122,7 @@ final class ChatApi(
|
|||
def clear(chatId: Chat.Id) = coll.delete.one($id(chatId)).void
|
||||
|
||||
def system(chatId: Chat.Id, text: String, busChan: BusChan.Select): Funit = {
|
||||
val line = UserLine(systemUserId, None, text, troll = false, deleted = false)
|
||||
val line = UserLine(systemUserId, None, false, text, troll = false, deleted = false)
|
||||
persistLine(chatId, line) >>- {
|
||||
cached.invalidate(chatId)
|
||||
publish(chatId, actorApi.ChatLine(chatId, line), busChan)
|
||||
|
@ -131,7 +131,7 @@ final class ChatApi(
|
|||
|
||||
// like system, but not persisted.
|
||||
def volatile(chatId: Chat.Id, text: String, busChan: BusChan.Select): Unit = {
|
||||
val line = UserLine(systemUserId, None, text, troll = false, deleted = false)
|
||||
val line = UserLine(systemUserId, None, false, text, troll = false, deleted = false)
|
||||
publish(chatId, actorApi.ChatLine(chatId, line), busChan)
|
||||
}
|
||||
|
||||
|
@ -191,6 +191,7 @@ final class ChatApi(
|
|||
val line = c.hasRecentLine(user) option UserLine(
|
||||
username = systemUserId,
|
||||
title = None,
|
||||
patron = user.isPatron,
|
||||
text = lineText,
|
||||
troll = false,
|
||||
deleted = false
|
||||
|
@ -249,6 +250,7 @@ final class ChatApi(
|
|||
UserLine(
|
||||
user.username,
|
||||
user.title,
|
||||
user.isPatron,
|
||||
Writer.removeSelfMention(Writer preprocessUserInput t2, user.username),
|
||||
troll = user.isTroll,
|
||||
deleted = false
|
||||
|
|
|
@ -70,6 +70,7 @@ object JsonView {
|
|||
)
|
||||
.add("r" -> l.troll)
|
||||
.add("d" -> l.deleted)
|
||||
.add("p" -> l.patron)
|
||||
.add("title" -> l.title)
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ sealed trait Line {
|
|||
case class UserLine(
|
||||
username: String,
|
||||
title: Option[Title],
|
||||
patron: Boolean,
|
||||
text: String,
|
||||
troll: Boolean,
|
||||
deleted: Boolean
|
||||
|
@ -52,7 +53,7 @@ object Line {
|
|||
|
||||
import reactivemongo.api.bson._
|
||||
|
||||
private val invalidLine = UserLine("", None, "[invalid character]", troll = false, deleted = true)
|
||||
private val invalidLine = UserLine("", None, false, "[invalid character]", troll = false, deleted = true)
|
||||
|
||||
implicit private[chat] val userLineBSONHandler = BSONStringHandler.as[UserLine](
|
||||
v => strToUserLine(v) getOrElse invalidLine,
|
||||
|
@ -64,23 +65,30 @@ object Line {
|
|||
lineToStr
|
||||
)
|
||||
|
||||
private val UserLineRegex = """(?s)([\w-~]{2,}+)([ !?])(.++)""".r
|
||||
private val trollChar = "!"
|
||||
private val deletedChar = "?"
|
||||
private val patronChar = "&"
|
||||
private val UserLineRegex = {
|
||||
"""(?s)([\w-~]{2,}+)([ """ + s"$trollChar$deletedChar$patronChar" + """])(.++)"""
|
||||
}.r
|
||||
private def strToUserLine(str: String): Option[UserLine] =
|
||||
str match {
|
||||
case UserLineRegex(username, sep, text) =>
|
||||
val troll = sep == "!"
|
||||
val deleted = sep == "?"
|
||||
val troll = sep == trollChar
|
||||
val deleted = sep == deletedChar
|
||||
val patron = sep == patronChar
|
||||
username split titleSep match {
|
||||
case Array(title, name) =>
|
||||
UserLine(name, Title get title, text, troll = troll, deleted = deleted).some
|
||||
case _ => UserLine(username, None, text, troll = troll, deleted = deleted).some
|
||||
UserLine(name, Title get title, patron, text, troll = troll, deleted = deleted).some
|
||||
case _ => UserLine(username, None, patron, text, troll = troll, deleted = deleted).some
|
||||
}
|
||||
case _ => none
|
||||
}
|
||||
def userLineToStr(x: UserLine): String = {
|
||||
val sep =
|
||||
if (x.troll) "!"
|
||||
else if (x.deleted) "?"
|
||||
if (x.troll) trollChar
|
||||
else if (x.deleted) deletedChar
|
||||
else if (x.patron) patronChar
|
||||
else " "
|
||||
val tit = x.title.??(_.value + titleSep)
|
||||
s"$tit${x.username}$sep${x.text}"
|
||||
|
|
|
@ -110,7 +110,7 @@ case class User(
|
|||
|
||||
def isPatron = plan.active
|
||||
|
||||
def activePlan: Option[Plan] = if (plan.active) Some(plan) else None
|
||||
def activePlan: Option[Plan] = plan.active option plan
|
||||
|
||||
def planMonths: Option[Int] = activePlan.map(_.months)
|
||||
|
||||
|
@ -188,9 +188,16 @@ object User {
|
|||
case class TotpToken(value: String) extends AnyVal
|
||||
case class PasswordAndToken(password: ClearPassword, token: Option[TotpToken])
|
||||
|
||||
case class Speaker(username: String, title: Option[Title], enabled: Boolean, marks: Option[UserMarks]) {
|
||||
def isBot = title has Title.BOT
|
||||
def isTroll = marks.exists(_.troll)
|
||||
case class Speaker(
|
||||
username: String,
|
||||
title: Option[Title],
|
||||
enabled: Boolean,
|
||||
plan: Option[Plan],
|
||||
marks: Option[UserMarks]
|
||||
) {
|
||||
def isBot = title has Title.BOT
|
||||
def isTroll = marks.exists(_.troll)
|
||||
def isPatron = plan.exists(_.active)
|
||||
}
|
||||
|
||||
case class Contact(
|
||||
|
@ -279,6 +286,8 @@ object User {
|
|||
import lila.db.BSON
|
||||
import lila.db.dsl._
|
||||
|
||||
implicit private def planHandler = Plan.planBSONHandler
|
||||
|
||||
implicit val userBSONHandler = new BSON[User] {
|
||||
|
||||
import BSONFields._
|
||||
|
@ -288,7 +297,6 @@ object User {
|
|||
implicit private def countHandler = Count.countBSONHandler
|
||||
implicit private def profileHandler = Profile.profileBSONHandler
|
||||
implicit private def perfsHandler = Perfs.perfsBSONHandler
|
||||
implicit private def planHandler = Plan.planBSONHandler
|
||||
implicit private def totpSecretHandler = TotpSecret.totpSecretBSONHandler
|
||||
|
||||
def reads(r: BSON.Reader): User = {
|
||||
|
|
|
@ -644,9 +644,17 @@ final class UserRepo(val coll: Coll)(implicit ec: scala.concurrent.ExecutionCont
|
|||
(res.nModified == 1) ?? email(id)
|
||||
}
|
||||
|
||||
private val speakerProjection = $doc(
|
||||
F.username -> true,
|
||||
F.title -> true,
|
||||
F.plan -> true,
|
||||
F.enabled -> true,
|
||||
F.marks -> true
|
||||
)
|
||||
|
||||
def speaker(id: User.ID): Fu[Option[User.Speaker]] = {
|
||||
import User.speakerHandler
|
||||
coll.one[User.Speaker]($id(id))
|
||||
coll.one[User.Speaker]($id(id), speakerProjection)
|
||||
}
|
||||
|
||||
def contacts(orig: User.ID, dest: User.ID): Fu[Option[User.Contacts]] = {
|
||||
|
|
|
@ -44,6 +44,13 @@
|
|||
margin-right: 0.4em;
|
||||
}
|
||||
|
||||
line.patron {
|
||||
font-size: 1.1em;
|
||||
width: 1.2em;
|
||||
text-align: left;
|
||||
color: $c-brag;
|
||||
}
|
||||
|
||||
.utitle {
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
|
|
@ -208,7 +208,7 @@ function renderLine(ctrl: Ctrl, line: Line): VNode {
|
|||
|
||||
if (line.c) return h('li', [h('span.color', '[' + line.c + ']'), textNode]);
|
||||
|
||||
const userNode = thunk('a', line.u, userLink, [line.u, line.title]);
|
||||
const userNode = thunk('a', line.u, userLink, [line.u, line.title, line.p]);
|
||||
|
||||
return h(
|
||||
'li',
|
||||
|
|
|
@ -47,6 +47,7 @@ export interface Line {
|
|||
d: boolean; // deleted
|
||||
c?: string; // color
|
||||
r?: boolean; // troll
|
||||
p?: boolean; // patron
|
||||
title?: string;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
import { h, VNode } from 'snabbdom';
|
||||
|
||||
export function userLink(u: string, title?: string): VNode {
|
||||
export function userLink(u: string, title?: string, patron?: boolean): VNode {
|
||||
const trunc = u.substring(0, 14);
|
||||
const line = patron
|
||||
? h('line.line.patron', {
|
||||
attrs: {
|
||||
title: 'Lichess Patron',
|
||||
},
|
||||
})
|
||||
: undefined;
|
||||
return h(
|
||||
'a',
|
||||
{
|
||||
|
@ -14,7 +21,7 @@ export function userLink(u: string, title?: string): VNode {
|
|||
href: '/@/' + u,
|
||||
},
|
||||
},
|
||||
title && title != 'BOT' ? [h('span.utitle', title), trunc] : [trunc]
|
||||
title && title != 'BOT' ? [line, h('span.utitle', title), trunc] : [line, trunc]
|
||||
);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue