try to unify chat messages / round is OK
parent
59e1f64012
commit
c9484b7552
|
@ -36,17 +36,15 @@ trait StringHelper {
|
|||
|
||||
private val urlRegex = """(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))""".r
|
||||
|
||||
def addLinks(text: String) = urlRegex.replaceAllIn(text, m ⇒ "<a href='%s'>%s</a>".format(
|
||||
(prependHttp _ compose delocalize _ compose quoteReplacement _)(m group 1),
|
||||
(delocalize _ compose quoteReplacement _)(m group 1)
|
||||
))
|
||||
def addLinks(text: String) = urlRegex.replaceAllIn(text, m ⇒ {
|
||||
val url = delocalize(quoteReplacement(m group 1))
|
||||
"<a href='%s'>%s</a>".format(prependHttp(url), url)
|
||||
})
|
||||
|
||||
private def prependHttp(url: String): String =
|
||||
url startsWith "http" fold(url, "http://" + url)
|
||||
private def prependHttp(url: String): String =
|
||||
url startsWith "http" fold (url, "http://" + url)
|
||||
|
||||
private val delocalizeRegex = ("""\w+\.""" + quoteReplacement(netDomain)).r
|
||||
|
||||
private def delocalize(url: String) = delocalizeRegex.replaceAllIn(url, netDomain)
|
||||
private val delocalize = new lila.common.String.Delocalizer(netDomain)
|
||||
|
||||
def showNumber(n: Int): String = (n > 0).fold("+" + n, n.toString)
|
||||
|
||||
|
|
|
@ -18,20 +18,17 @@ trait UserHelper {
|
|||
def isOnline(userId: String) = Env.user isOnline userId
|
||||
|
||||
def userIdLink(
|
||||
userId: Option[String],
|
||||
userIdOption: Option[String],
|
||||
cssClass: Option[String] = None,
|
||||
withOnline: Boolean = true,
|
||||
truncate: Option[Int] = None): Html = Html {
|
||||
(userId zmap Env.user.usernameOption) map {
|
||||
_.fold(User.anonymous) { username ⇒
|
||||
"""<a class="user_link%s%s" href="%s">%s</a>""".format(
|
||||
withOnline ?? isOnline(username).fold(" online", " offline"),
|
||||
cssClass.zmap(" " + _),
|
||||
routes.User.show(username),
|
||||
truncate.fold(username)(username.take)
|
||||
)
|
||||
}
|
||||
} await
|
||||
userIdOption.fold(User.anonymous) { userId ⇒
|
||||
Env.user usernameOption userId map {
|
||||
_.fold(User.anonymous) { username ⇒
|
||||
userIdNameLink(userId, username, cssClass, withOnline, truncate)
|
||||
}
|
||||
} await
|
||||
}
|
||||
}
|
||||
|
||||
def userIdLink(
|
||||
|
@ -47,6 +44,29 @@ trait UserHelper {
|
|||
} await
|
||||
}
|
||||
|
||||
def usernameLink(
|
||||
usernameOption: Option[String],
|
||||
cssClass: Option[String] = None,
|
||||
withOnline: Boolean = true,
|
||||
truncate: Option[Int] = None): Html = Html {
|
||||
usernameOption.fold(User.anonymous) { username ⇒
|
||||
userIdNameLink(username.toLowerCase, username, cssClass, withOnline, truncate)
|
||||
}
|
||||
}
|
||||
|
||||
private def userIdNameLink(
|
||||
userId: String,
|
||||
username: String,
|
||||
cssClass: Option[String] = None,
|
||||
withOnline: Boolean = true,
|
||||
truncate: Option[Int] = None): String =
|
||||
"""<a class="user_link%s%s" href="%s">%s</a>""".format(
|
||||
withOnline ?? isOnline(userId).fold(" online", " offline"),
|
||||
cssClass.zmap(" " + _),
|
||||
routes.User.show(username),
|
||||
truncate.fold(username)(username.take)
|
||||
)
|
||||
|
||||
def userLink(
|
||||
user: User,
|
||||
cssClass: Option[String] = None,
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
|
||||
@base.layout(title = title) {
|
||||
|
||||
<style type="text/css">
|
||||
</style>
|
||||
<div class="content_box">
|
||||
<h1>@title</h1>
|
||||
<br /><br />
|
||||
|
@ -13,7 +11,7 @@
|
|||
@messages.map { message =>
|
||||
<tr>
|
||||
<td>@showDate(message.date)</td>
|
||||
<td>@userIdLink(message.userId.some)</td>
|
||||
<td>@userIdLink(message.user)</td>
|
||||
<td>@Html(message.text)</td>
|
||||
</tr>
|
||||
}
|
||||
|
|
|
@ -1,12 +1,7 @@
|
|||
@(messages: List[(Option[String], String)])(implicit ctx: Context)
|
||||
|
||||
@messages.map {
|
||||
case (author, text) => {
|
||||
<li>
|
||||
<span>
|
||||
@userIdLink(author, withOnline = false, truncate = 12.some)
|
||||
</span>
|
||||
@text
|
||||
</li>
|
||||
case (username, text) => {
|
||||
<li><span>@usernameLink(username, withOnline = false, truncate = 12.some)</span>@text</li>
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package lila.common
|
||||
|
||||
import java.text.Normalizer
|
||||
import java.util.regex.Matcher.quoteReplacement
|
||||
|
||||
object String {
|
||||
|
||||
|
@ -10,4 +11,11 @@ object String {
|
|||
val slug = """[^\w-]""".r.replaceAllIn(normalized, "")
|
||||
slug.toLowerCase
|
||||
}
|
||||
|
||||
final class Delocalizer(netDomain: String) {
|
||||
|
||||
private val regex = ("""\w+\.""" + quoteReplacement(netDomain)).r
|
||||
|
||||
def apply(url: String) = regex.replaceAllIn(url, netDomain)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,23 +114,18 @@ object Event {
|
|||
|
||||
case class Message(author: String, text: String) extends Event {
|
||||
def typ = "message"
|
||||
def data = JsString("""<li class="%s%s">%s</li>""".format(
|
||||
author, (author == "system") ?? " trans_me", escapeXml(text)))
|
||||
def data = Json.obj("u" -> author, "t" -> escapeXml(text))
|
||||
override def owner = true
|
||||
}
|
||||
|
||||
case class WatcherMessage(author: Option[String], text: String) extends Event {
|
||||
// it *IS* a username, and not a user ID
|
||||
// immediately used for rendering
|
||||
case class WatcherMessage(username: Option[String], text: String) extends Event {
|
||||
def typ = "message"
|
||||
def data = JsString(renderWatcherRoom(author, text))
|
||||
def data = Json.obj("u" -> username, "t" -> escapeXml(text))
|
||||
override def watcher = true
|
||||
}
|
||||
|
||||
// TODO FIXME the username is @userId and there is no link
|
||||
private def renderWatcherRoom(author: Option[String], text: String): String =
|
||||
"""<li><span>%s</span>%s</li>""".format(
|
||||
author.fold("Anonymous")("@" + _),
|
||||
escapeXml(text))
|
||||
|
||||
object End extends Empty {
|
||||
def typ = "end"
|
||||
}
|
||||
|
|
|
@ -4,28 +4,31 @@ import play.api.libs.json._
|
|||
import reactivemongo.bson._
|
||||
import org.joda.time.DateTime
|
||||
|
||||
// it is really a username, not a user ID
|
||||
case class Message(
|
||||
userId: String,
|
||||
user: Option[String],
|
||||
text: String,
|
||||
date: DateTime) {
|
||||
|
||||
def render = Json.obj("txt" -> text, "u" -> userId)
|
||||
def render = Json.obj("u" -> user, "t" -> text)
|
||||
|
||||
def isEmpty = text.isEmpty
|
||||
}
|
||||
|
||||
object Message {
|
||||
|
||||
def make(userId: String, text: String) = new Message(
|
||||
userId = userId,
|
||||
def make(user: Option[String], text: String) = new Message(
|
||||
user = user,
|
||||
text = text,
|
||||
date = DateTime.now)
|
||||
|
||||
import lila.db.Tube
|
||||
import Tube.Helpers._
|
||||
|
||||
private def defaults = Json.obj("user" -> none[String])
|
||||
|
||||
private[lobby] lazy val tube = Tube[Message](
|
||||
(__.json update readDate('date)) andThen Json.reads[Message],
|
||||
(__.json update (merge(defaults) andThen readDate('date))) andThen Json.reads[Message],
|
||||
Json.writes[Message] andThen (__.json update writeDate('date)),
|
||||
flags = Seq(_.NoId))
|
||||
}
|
||||
|
|
|
@ -1,24 +1,21 @@
|
|||
package lila.lobby
|
||||
|
||||
import lila.user.{ UserRepo, User, Room }
|
||||
import lila.user.tube.userTube
|
||||
import tube.messageTube
|
||||
import lila.db.api._
|
||||
|
||||
private[lobby] final class Messenger(val netDomain: String) extends Room {
|
||||
|
||||
def apply(userId: String, text: String): Fu[Message] = for {
|
||||
userOption ← $find.byId[User](userId)
|
||||
message ← (for {
|
||||
user ← userOption filter (_.canChat) toValid "This user cannot chat"
|
||||
msg ← createMessage(user, text)
|
||||
(u, t) = msg
|
||||
} yield Message.make(u, t)).future
|
||||
userOption ← UserRepo byId userId
|
||||
message ← (userMessage(userOption, text) map {
|
||||
case (u, t) ⇒ Message.make(u.some, t)
|
||||
}).future
|
||||
_ ← $insert(message)
|
||||
} yield message
|
||||
|
||||
def system(text: String): Fu[Message] =
|
||||
Message.make(userId = "", text = text) |> { message ⇒
|
||||
Message.make(user = none, text = text) |> { message ⇒
|
||||
$insert(message) inject message
|
||||
}
|
||||
|
||||
|
|
|
@ -39,13 +39,13 @@ private[lobby] final class Socket(
|
|||
case Talk(u, txt) ⇒ messenger(u, txt) effectFold (
|
||||
e ⇒ logwarn(e.toString),
|
||||
message ⇒ notifyVersion("talk", Json.obj(
|
||||
"u" -> message.userId,
|
||||
"txt" -> message.text
|
||||
"u" -> message.user,
|
||||
"t" -> message.text
|
||||
))
|
||||
)
|
||||
|
||||
case SysTalk(txt) ⇒ messenger system txt foreach { message ⇒
|
||||
notifyVersion("talk", Json.obj("txt" -> message.text))
|
||||
notifyVersion("talk", Json.obj("t" -> message.text))
|
||||
}
|
||||
|
||||
case UnTalk(regex) ⇒ (messenger remove regex) >>-
|
||||
|
|
|
@ -16,6 +16,7 @@ final class Env(
|
|||
db: lila.db.Env,
|
||||
hub: lila.hub.Env,
|
||||
ai: lila.ai.Ai,
|
||||
getUsername: String ⇒ Fu[Option[String]],
|
||||
i18nKeys: lila.i18n.I18nKeys,
|
||||
scheduler: lila.common.Scheduler) {
|
||||
|
||||
|
@ -31,6 +32,7 @@ final class Env(
|
|||
val SocketTimeout = config duration "socket.timeout"
|
||||
val FinisherLockTimeout = config duration "finisher.lock.timeout"
|
||||
val HijackTimeout = config duration "hijack.timeout"
|
||||
val NetDomain = config getString "net.domain"
|
||||
}
|
||||
import settings._
|
||||
|
||||
|
@ -72,7 +74,7 @@ final class Env(
|
|||
finisher = finisher,
|
||||
socketHub = socketHub)
|
||||
|
||||
lazy val messenger = new Messenger(i18nKeys)
|
||||
lazy val messenger = new Messenger(NetDomain, i18nKeys, getUsername)
|
||||
|
||||
lazy val eloCalculator = new chess.EloCalculator(false)
|
||||
|
||||
|
@ -122,6 +124,7 @@ object Env {
|
|||
db = lila.db.Env.current,
|
||||
hub = lila.hub.Env.current,
|
||||
ai = lila.ai.Env.current.ai,
|
||||
getUsername = lila.user.Env.current.usernameOption,
|
||||
i18nKeys = lila.i18n.Env.current.keys,
|
||||
scheduler = lila.common.PlayApp.scheduler)
|
||||
}
|
||||
|
|
|
@ -7,8 +7,14 @@ import chess.Color
|
|||
import lila.game.Event
|
||||
import tube.{ roomTube, watcherRoomTube }
|
||||
import lila.db.api._
|
||||
import lila.user.UserRepo
|
||||
|
||||
final class Messenger(i18nKeys: I18nKeys) {
|
||||
import org.apache.commons.lang3.StringEscapeUtils.escapeXml
|
||||
|
||||
final class Messenger(
|
||||
val netDomain: String,
|
||||
i18nKeys: I18nKeys,
|
||||
getUsername: String ⇒ Fu[Option[String]]) extends lila.user.Room {
|
||||
|
||||
private val nbMessagesCopiedToRematch = 20
|
||||
|
||||
|
@ -31,7 +37,7 @@ final class Messenger(i18nKeys: I18nKeys) {
|
|||
} yield ()
|
||||
|
||||
def playerMessage(ref: PovRef, text: String): Fu[List[Event.Message]] =
|
||||
cleanupText(text) zmap { t ⇒
|
||||
cleanupText(text).future flatMap { t ⇒
|
||||
RoomRepo.addMessage(ref.gameId, ref.color.name, t) inject {
|
||||
Event.Message(ref.color.name, t) :: Nil
|
||||
}
|
||||
|
@ -40,12 +46,12 @@ final class Messenger(i18nKeys: I18nKeys) {
|
|||
def watcherMessage(
|
||||
gameId: String,
|
||||
userId: Option[String],
|
||||
text: String): Fu[List[Event.WatcherMessage]] =
|
||||
cleanupText(text) zmap { t ⇒
|
||||
WatcherRoomRepo.addMessage(gameId, userId, t) inject {
|
||||
Event.WatcherMessage(userId, text) :: Nil
|
||||
}
|
||||
}
|
||||
text: String): Fu[List[Event.WatcherMessage]] = for {
|
||||
userOption ← userId.zmap(UserRepo.byId)
|
||||
message ← userOrAnonMessage(userOption, text).future
|
||||
(u, t) = message
|
||||
_ ← WatcherRoomRepo.addMessage(gameId, u, t)
|
||||
} yield Event.WatcherMessage(u, t) :: Nil
|
||||
|
||||
def systemMessages(game: Game, messages: List[SelectI18nKey]): Fu[List[Event]] =
|
||||
game.hasChat ?? {
|
||||
|
@ -65,11 +71,6 @@ final class Messenger(i18nKeys: I18nKeys) {
|
|||
}
|
||||
}
|
||||
|
||||
private def cleanupText(text: String) = {
|
||||
val cleanedUp = text.trim.replace(""""""", "'")
|
||||
(cleanedUp.size <= 140 && cleanedUp.nonEmpty) option cleanedUp
|
||||
}
|
||||
|
||||
private def messageToEn(message: SelectI18nKey): String =
|
||||
message(i18nKeys).en()
|
||||
}
|
||||
|
|
|
@ -20,11 +20,11 @@ object WatcherRoom {
|
|||
Json.reads[WatcherRoom],
|
||||
Json.writes[WatcherRoom])
|
||||
|
||||
def encode(userId: Option[String], text: String): String =
|
||||
~userId + "|" + text
|
||||
def encode(username: Option[String], text: String): String =
|
||||
~username + "|" + text
|
||||
|
||||
def decode(encoded: String): (Option[String], String) =
|
||||
encoded.span('|' !=) match {
|
||||
case (userId, rest) ⇒ Some(userId).filter(_.nonEmpty) -> rest
|
||||
case (username, rest) ⇒ Some(username).filter(_.nonEmpty) -> rest.drop(1)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,9 @@ object WatcherRoomRepo {
|
|||
|
||||
def addMessage(
|
||||
id: String,
|
||||
userId: Option[String],
|
||||
username: Option[String],
|
||||
text: String): Funit = $update(
|
||||
$select(id),
|
||||
$push("messages", WatcherRoom.encode(userId, text)),
|
||||
$push("messages", WatcherRoom.encode(username, text)),
|
||||
upsert = true)
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ final class Env(
|
|||
}
|
||||
}
|
||||
|
||||
lazy val messenger = new Messenger(NetDomain)
|
||||
lazy val messenger = new Messenger(getUsername, NetDomain)
|
||||
|
||||
private[tournament] lazy val tournamentColl = db(CollectionTournament)
|
||||
private[tournament] lazy val roomColl = db(CollectionRoom)
|
||||
|
|
|
@ -1,29 +1,31 @@
|
|||
package lila.tournament
|
||||
|
||||
import lila.db.api.$find
|
||||
import lila.db.api._
|
||||
import tube.tournamentTube
|
||||
import lila.user.{ User, UserRepo, Room ⇒ UserRoom }
|
||||
|
||||
private[tournament] final class Messenger(val netDomain: String) extends UserRoom {
|
||||
private[tournament] final class Messenger(
|
||||
getUsername: String ⇒ Fu[Option[String]],
|
||||
val netDomain: String) extends UserRoom {
|
||||
|
||||
import Room._
|
||||
|
||||
def init(tour: Created): Fu[List[Message]] = for {
|
||||
userOption ← UserRepo named tour.data.createdBy
|
||||
username = userOption.fold(tour.data.createdBy)(_.username)
|
||||
username ← getUsername(tour.data.createdBy) flatMap {
|
||||
_.fold[Fu[String]](fufail("No username found"))(fuccess(_))
|
||||
}
|
||||
message ← systemMessage(tour, "%s creates the tournament" format username)
|
||||
} yield List(message)
|
||||
|
||||
def userMessage(tournamentId: String, userId: String, text: String): Fu[Message] = for {
|
||||
userOption ← UserRepo named userId
|
||||
tourOption ← $find byId tournamentId
|
||||
userOption ← UserRepo byId userId
|
||||
tourExists ← $count.exists($select(tournamentId))
|
||||
message ← (for {
|
||||
user ← userOption filter (_.canChat) toValid "This user cannot chat"
|
||||
_ ← tourOption toValid "No such tournament"
|
||||
msg ← createMessage(user, text)
|
||||
_ ← Unit.validIf(tourExists, "No such tournament")
|
||||
msg ← userMessage(userOption, text)
|
||||
(u, t) = msg
|
||||
} yield Message(u.some, t)).future
|
||||
_ ← RoomRepo.addMessage(tournamentId, message)
|
||||
_ ← RoomRepo.addMessage(tournamentId, message)
|
||||
} yield message
|
||||
|
||||
def systemMessage(tour: Tournament, text: String): Fu[Message] =
|
||||
|
@ -31,6 +33,6 @@ private[tournament] final class Messenger(val netDomain: String) extends UserRoo
|
|||
RoomRepo.addMessage(tour.id, message) inject message
|
||||
}
|
||||
|
||||
def getMessages(tournamentId: String): Fu[List[Room.Message]] =
|
||||
def getMessages(tournamentId: String): Fu[List[Room.Message]] =
|
||||
RoomRepo room tournamentId map (_.decodedMessages)
|
||||
}
|
||||
|
|
|
@ -1,30 +1,31 @@
|
|||
package lila.user
|
||||
|
||||
import org.apache.commons.lang3.StringEscapeUtils.escapeXml
|
||||
import java.util.regex.Matcher.quoteReplacement
|
||||
|
||||
trait Room {
|
||||
|
||||
def netDomain: String
|
||||
|
||||
def createMessage(user: User, text: String): Valid[(String, String)] =
|
||||
if (user.isChatBan) !!("Chat banned " + user)
|
||||
else if (user.disabled) !!("User disabled " + user)
|
||||
else escapeXml(text.replace(""""""", "'").trim take 140) |> { escaped ⇒
|
||||
(escaped.nonEmpty).fold(
|
||||
success((
|
||||
user.username,
|
||||
urlRegex.replaceAllIn(escaped, m ⇒ quoteReplacement(netDomain + "/" + (m group 1)))
|
||||
)),
|
||||
!!("Empty message")
|
||||
)
|
||||
def userMessage(userOption: Option[User], text: String): Valid[(String, String)] =
|
||||
userOption toValid "Anonymous cannot talk in this room" flatMap { user ⇒
|
||||
if (user.isChatBan) !!("Chat banned " + user)
|
||||
else if (user.disabled) !!("User disabled " + user)
|
||||
else cleanupText(text) map { user.username -> _ }
|
||||
}
|
||||
|
||||
def userOrAnonMessage(userOption: Option[User], text: String): Valid[(Option[String], String)] =
|
||||
cleanupText(text) map { userOption.map(_.username) -> _ }
|
||||
|
||||
def cleanupText(text: String): Valid[String] =
|
||||
(text.replace(""""""", "'").trim take 140) |> { t ⇒
|
||||
if (t.isEmpty) !!("Empty message")
|
||||
else success(delocalize(noPrivateUrl(t)))
|
||||
}
|
||||
|
||||
private def noPrivateUrl(str: String): String =
|
||||
urlRegex.replaceAllIn(str, m ⇒ quoteReplacement(netDomain + "/" + (m group 1)))
|
||||
|
||||
private val delocalize = new lila.common.String.Delocalizer(netDomain)
|
||||
private val domainRegex = netDomain.replace(".", """\.""")
|
||||
private val urlRegex = (domainRegex + """/([\w-]{8})[\w-]{4}""").r
|
||||
|
||||
private def cleanupText(text: String) = {
|
||||
val cleanedUp = text.trim.replace(""""""", "'")
|
||||
(cleanedUp.size <= 140 && cleanedUp.nonEmpty) option cleanedUp
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ object UserRepo {
|
|||
|
||||
val normalize = User normalize _
|
||||
|
||||
def byId(id: ID): Fu[Option[User]] = $find byId id
|
||||
|
||||
def named(username: String): Fu[Option[User]] = $find byId normalize(username)
|
||||
|
||||
def nameds(usernames: List[String]): Fu[List[User]] = $find byIds usernames.map(normalize)
|
||||
|
|
|
@ -203,6 +203,10 @@ var lichess_translations = [];
|
|||
domain: document.domain.replace(/^\w+\.(.+)$/, '$1')
|
||||
};
|
||||
|
||||
$.userLink = function(u, limit) {
|
||||
return (u || false) ? '<a class="user_link" href="/@/' + u + '">' + u + '</a>' : 'Anonymous';
|
||||
}
|
||||
|
||||
var lichess = {
|
||||
socket: null,
|
||||
socketDefaults: {
|
||||
|
@ -587,7 +591,14 @@ var lichess_translations = [];
|
|||
self.initTable();
|
||||
self.initClocks();
|
||||
if (self.$chat) self.$chat.chat({
|
||||
resize: true
|
||||
resize: true,
|
||||
render: function(u, t) {
|
||||
if (self.options.player.spectator) {
|
||||
return '<li><span>' + $.userLink(u, 12) + '</span>' + urlToLink(t) + '</li>';
|
||||
} else {
|
||||
return '<li class="' + u + (u == 'system' ? ' trans_me' : '') + '">' + urlToLink(t) + '</li>';
|
||||
}
|
||||
}
|
||||
});
|
||||
self.$watchers.watchers();
|
||||
if (self.isMyTurn() && self.options.game.turns == 0) {
|
||||
|
@ -638,9 +649,9 @@ var lichess_translations = [];
|
|||
ack: function() {
|
||||
clearTimeout(self.socketAckTimeout);
|
||||
},
|
||||
message: function(event) {
|
||||
message: function(e) {
|
||||
self.element.queue(function() {
|
||||
if (self.$chat) self.$chat.chat("append", event);
|
||||
if (self.$chat) self.$chat.chat("append", e.u, e.t);
|
||||
self.element.dequeue();
|
||||
});
|
||||
},
|
||||
|
@ -1182,18 +1193,7 @@ var lichess_translations = [];
|
|||
set: function(users) {
|
||||
var self = this;
|
||||
if (users.length > 0) {
|
||||
var html = [],
|
||||
user, i, w;
|
||||
for (i in users) {
|
||||
w = users[i];
|
||||
if (w.indexOf("Anonymous") == 0) {
|
||||
user = w;
|
||||
} else {
|
||||
user = '<a href="/@/' + w + '">' + w + '</a>';
|
||||
}
|
||||
html.push(user);
|
||||
}
|
||||
self.list.html(html.join(", "));
|
||||
self.list.html(_.map(users, $.userLink).join(", "));
|
||||
self.element.show();
|
||||
} else {
|
||||
self.element.hide();
|
||||
|
@ -1204,8 +1204,8 @@ var lichess_translations = [];
|
|||
$.widget("lichess.chat", {
|
||||
_create: function() {
|
||||
this.options = $.extend({
|
||||
render: function(t) {
|
||||
return urlToLink(t);
|
||||
render: function(u, t) {
|
||||
console.debug("How to render " + u + " " + t + " in chat?");
|
||||
},
|
||||
resize: false
|
||||
}, this.options);
|
||||
|
@ -1252,15 +1252,14 @@ var lichess_translations = [];
|
|||
}
|
||||
$toggle[0].checked = $toggle.data("enabled");
|
||||
},
|
||||
append: function(msg, u) {
|
||||
this._appendHtml(this.options.render(msg, u));
|
||||
append: function(u, t) {
|
||||
this._appendHtml(this.options.render(u, t));
|
||||
},
|
||||
appendMany: function(objs) {
|
||||
var self = this,
|
||||
html = "";
|
||||
$.each(objs, function() {
|
||||
if (this.txt) html += self.options.render(this.txt, this.u);
|
||||
else if (this.msg) html += self.options.render(this.msg, this.u);
|
||||
html += self.options.render(this.u, this.t);
|
||||
});
|
||||
this._appendHtml(html);
|
||||
},
|
||||
|
@ -1728,10 +1727,8 @@ var lichess_translations = [];
|
|||
});
|
||||
|
||||
var $chat = $("div.lichess_chat").chat({
|
||||
render: function(txt, u) {
|
||||
return (u || false)
|
||||
? '<li><span><a class="user_link" href="/@/' + u + '">' + u.substr(0, 12) + '</a></span>' + urlToLink(txt) + '</li>'
|
||||
: '<li>' + urlToLink(txt) + '</li>';
|
||||
render: function(u, t) {
|
||||
return (u || false) ? '<li><span><a class="user_link" href="/@/' + u + '">' + u.substr(0, 12) + '</a></span>' + urlToLink(t) + '</li>' : '<li>' + urlToLink(t) + '</li>';
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1757,7 +1754,7 @@ var lichess_translations = [];
|
|||
},
|
||||
events: {
|
||||
talk: function(e) {
|
||||
$chat.chat('append', e.txt, e.u);
|
||||
$chat.chat('append', e.u, e.t);
|
||||
},
|
||||
untalk: function(e) {
|
||||
$chat.chat('remove', e.regex);
|
||||
|
@ -1927,8 +1924,8 @@ var lichess_translations = [];
|
|||
var $watchers = $("div.watchers").watchers();
|
||||
|
||||
var $chat = $("div.lichess_chat").chat({
|
||||
render: function(txt, u) {
|
||||
return '<li><span><a class="user_link" href="/@/' + u + '">' + u.substr(0, 12) + '</a></span>' + urlToLink(txt) + '</li>';
|
||||
render: function(u, t) {
|
||||
return '<li><span>' + userLink(u, 12) + '</span>' + urlToLink(t) + '</li>';
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1956,7 +1953,7 @@ var lichess_translations = [];
|
|||
lichess.socket = new strongSocket(lichess.socketUrl + socketUrl, _ld_.version, $.extend(true, lichess.socketDefaults, {
|
||||
events: {
|
||||
talk: function(e) {
|
||||
$chat.chat('append', e.txt, e.u);
|
||||
$chat.chat('append', e.u, e.t);
|
||||
},
|
||||
start: start,
|
||||
reload: reload,
|
||||
|
@ -2004,8 +2001,8 @@ var lichess_translations = [];
|
|||
ignoreUnknownMessages: true
|
||||
},
|
||||
events: {
|
||||
message: function(event) {
|
||||
$chat.chat("append", event);
|
||||
message: function(e) {
|
||||
$chat.chat("append", e.u, e.t);
|
||||
},
|
||||
crowd: function(event) {
|
||||
$watchers.watchers("set", event.watchers);
|
||||
|
|
1
todo
1
todo
|
@ -82,6 +82,7 @@ stream game export
|
|||
show fen only after game is finished http://en.lichess.org/forum/lichess-feedback/please-disable-live-fen-notation?page=1
|
||||
I owe the admins decent tools
|
||||
move db game.if (initialFen) to another collection to prevent systematic loading, and doc moving
|
||||
tell opponent chat is disabled
|
||||
|
||||
DEPLOY p21
|
||||
----------
|
||||
|
|
Loading…
Reference in New Issue