diff --git a/app/controllers/Bot.scala b/app/controllers/Bot.scala index 51d609d1e9..9a8283e22d 100644 --- a/app/controllers/Bot.scala +++ b/app/controllers/Bot.scala @@ -39,14 +39,12 @@ object Bot extends LilaController { } private def WithMyBotGame(anyId: String, me: lila.user.User)(f: lila.game.Pov => Fu[Result]) = - lila.user.UserRepo.isBot(me) flatMap { - case false => BadRequest(jsonError("This endpoint only works for bot accounts. See https://lichess.org/api#operation/botAccountUpgrade")).fuccess - case _ => Env.round.roundProxyGame(lila.game.Game takeGameId anyId) flatMap { - case None => NotFound(jsonError("No such game")).fuccess - case Some(game) => lila.game.Pov(game, me) match { - case None => NotFound(jsonError("Not your game")).fuccess - case Some(pov) => f(pov) - } + if (!me.isBot) BadRequest(jsonError("This endpoint only works for bot accounts. See https://lichess.org/api#operation/botAccountUpgrade")).fuccess + else Env.round.roundProxyGame(lila.game.Game takeGameId anyId) flatMap { + case None => NotFound(jsonError("No such game")).fuccess + case Some(game) => lila.game.Pov(game, me) match { + case None => NotFound(jsonError("Not your game")).fuccess + case Some(pov) => f(pov) } } } diff --git a/app/templating/UserHelper.scala b/app/templating/UserHelper.scala index 50be0b9367..01c528f84b 100644 --- a/app/templating/UserHelper.scala +++ b/app/templating/UserHelper.scala @@ -139,9 +139,8 @@ trait UserHelper { self: I18nHelper with StringHelper with NumberHelper => ): Html = userIdLink(userId.some, cssClass) def titleTag(title: Option[String]) = Html { - title match { - case None => "" - case Some(t) => s"""$t """ + title.fold("") { t => + s"""$t """ } } diff --git a/modules/api/src/main/UserApi.scala b/modules/api/src/main/UserApi.scala index f97d2db3f1..48486dac62 100644 --- a/modules/api/src/main/UserApi.scala +++ b/modules/api/src/main/UserApi.scala @@ -51,10 +51,9 @@ private[api] final class UserApi( bookmarkApi.countByUser(u) zip gameCache.nbPlaying(u.id) zip gameCache.nbImportedBy(u.id) zip - lila.user.UserRepo.isBot(u) zip playBanApi.completionRate(u.id).map(_.map { cr => math.round(cr * 100) }) map { case gameOption ~ nbGamesWithMe ~ following ~ followers ~ followable ~ relation ~ - isFollowed ~ nbBookmarks ~ nbPlaying ~ nbImported ~ isBot ~ completionRate => + isFollowed ~ nbBookmarks ~ nbPlaying ~ nbImported ~ completionRate => jsonView(u) ++ { Json.obj( "url" -> makeUrl(s"@/${u.username}"), // for app BC @@ -77,8 +76,7 @@ private[api] final class UserApi( "import" -> nbImported, "me" -> nbGamesWithMe ) - ).add("streaming", isStreaming(u.id)) - .add("bot" -> isBot) ++ + ).add("streaming", isStreaming(u.id)) ++ as.isDefined.??(Json.obj( "followable" -> followable, "following" -> relation.has(true), diff --git a/modules/common/src/main/LightUser.scala b/modules/common/src/main/LightUser.scala index 4d6758e5ff..1f9fa8990e 100644 --- a/modules/common/src/main/LightUser.scala +++ b/modules/common/src/main/LightUser.scala @@ -11,10 +11,14 @@ case class LightUser( def titleName = title.fold(name)(_ + " " + name) def titleNameHtml = title.fold(name)(_ + " " + name) + + def isBot = title has LightUser.botTitle } object LightUser { + val botTitle = "BOT" + implicit val lightUserWrites = OWrites[LightUser] { u => Json.obj( "id" -> u.id, diff --git a/modules/game/src/main/Namer.scala b/modules/game/src/main/Namer.scala index 6e71ff1fcb..d4f842c5c0 100644 --- a/modules/game/src/main/Namer.scala +++ b/modules/game/src/main/Namer.scala @@ -13,7 +13,7 @@ object Namer { p.aiLevel.fold( p.userId.flatMap(lightUser).fold(lila.user.User.anonymous) { user => val title = (user.title ifTrue withTitle) ?? { t => - s"""$t """ + s"""$t """ } if (withRating) s"$title${user.name} (${ratingString(p)})" else s"$title${user.name}" diff --git a/modules/user/src/main/User.scala b/modules/user/src/main/User.scala index 44d67f3152..b7f408f06b 100644 --- a/modules/user/src/main/User.scala +++ b/modules/user/src/main/User.scala @@ -108,6 +108,8 @@ case class User( def createdSinceDays(days: Int) = createdAt isBefore DateTime.now.minusDays(days) def is(name: String) = id == User.normalize(name) + + def isBot = title has User.botTitle } object User { @@ -173,9 +175,12 @@ object User { "CM" -> "Candidate Master", "WCM" -> "Woman Candidate Master", "WNM" -> "Woman National Master", - "LM" -> "Lichess Master" + "LM" -> "Lichess Master", + "BOT" -> "Chess Robot" ) + val botTitle = LightUser.botTitle + val titlesMap = titles.toMap def titleName(title: String) = titlesMap get title getOrElse title @@ -197,7 +202,6 @@ object User { val createdAt = "createdAt" val seenAt = "seenAt" val kid = "kid" - val bot = "bot" val createdWithApiVersion = "createdWithApiVersion" val lang = "lang" val title = "title" diff --git a/modules/user/src/main/UserRepo.scala b/modules/user/src/main/UserRepo.scala index 0b57fdd26a..7b87c65e41 100644 --- a/modules/user/src/main/UserRepo.scala +++ b/modules/user/src/main/UserRepo.scala @@ -326,10 +326,9 @@ object UserRepo { def setBot(user: User): Funit = if (user.count.game > 0) fufail("You already have games played. Make a new account.") - else coll.updateField($id(user.id), F.bot, true).void + else coll.updateField($id(user.id), F.title, User.botTitle).void - def isBot(user: User): Fu[Boolean] = - coll.primitiveOne[Boolean]($id(user.id), F.bot) map (~_) + private def botSelector(v: Boolean) = $doc(F.title -> v) def getTitle(id: ID): Fu[Option[String]] = coll.primitiveOne[String]($id(id), F.title) diff --git a/public/stylesheets/common.css b/public/stylesheets/common.css index 499f4a31ed..a3afdb9c45 100644 --- a/public/stylesheets/common.css +++ b/public/stylesheets/common.css @@ -1036,6 +1036,9 @@ span.progress > .negative { color: #d59120; font-weight: bold; } +.user_link span.title[data-title=BOT] { + color: #c320d5!important; +} div.warning { padding: 5px; background: #f2dede; diff --git a/ui/round/src/view/user.ts b/ui/round/src/view/user.ts index 5c36bba81f..749a9b27c5 100644 --- a/ui/round/src/view/user.ts +++ b/ui/round/src/view/user.ts @@ -40,7 +40,9 @@ export function userHtml(ctrl: RoundController, player: Player) { href: '/@/' + user.username, target: ctrl.isPlaying() ? '_blank' : '_self' } - }, user.title ? [h('span.title', user.title), ' ', user.username] : [user.username]), + }, user.title ? [h('span.title', { + attrs: { 'data-title': user.title } + }, user.title), ' ', user.username] : [user.username]), rating ? h('rating', rating + (player.provisional ? '?' : '')) : null, ratingDiff(player), player.engine ? h('span', {