handle ghost users WIP

scrub-username
Thibault Duplessis 2021-04-13 12:19:45 +02:00
parent d6b13e38a2
commit 1d515dedaf
6 changed files with 37 additions and 16 deletions

View File

@ -150,6 +150,13 @@ trait GameHelper { self: I18nHelper with UserHelper with AiHelper with StringHel
player.rating.ifTrue(withRating) map { rating => s" ($rating)" },
statusIcon
)
case Some(user) if user.id == "ghost" =>
span(cls := "user-link")(
"Ghost",
(player.ratingDiff ifTrue withDiff) map { d =>
frag(" ", showRatingDiff(d))
}
)
case Some(user) =>
frag(
(if (link) a else span)(

View File

@ -227,8 +227,8 @@ trait UserHelper { self: I18nHelper with StringHelper with NumberHelper =>
case _ => ""
}
private def userUrl(username: String, params: String = "") =
s"""${routes.User.show(username)}$params"""
private def userUrl(username: String, params: String = ""): Option[String] =
(username != "Ghost" && username != "ghost") option s"""${routes.User.show(username)}$params"""
protected def userClass(
userId: String,
@ -236,11 +236,13 @@ trait UserHelper { self: I18nHelper with StringHelper with NumberHelper =>
withOnline: Boolean,
withPowerTip: Boolean = true
): List[(String, Boolean)] =
(withOnline ?? List((if (isOnline(userId)) "online" else "offline") -> true)) ::: List(
"user-link" -> true,
~cssClass -> cssClass.isDefined,
"ulpt" -> withPowerTip
)
if (userId == "ghost") List("user-link" -> true, ~cssClass -> cssClass.isDefined)
else
(withOnline ?? List((if (isOnline(userId)) "online" else "offline") -> true)) ::: List(
"user-link" -> true,
~cssClass -> cssClass.isDefined,
"ulpt" -> withPowerTip
)
def userGameFilterTitle(u: User, nbs: UserInfo.NbGames, filter: GameFilter)(implicit
lang: Lang

View File

@ -18,6 +18,8 @@ object LightUser {
private type UserID = String
val ghost = LightUser("ghost", "Ghost", none, false)
implicit val lightUserWrites = OWrites[LightUser] { u =>
writeNoId(u) + ("id" -> JsString(u.id))
}

View File

@ -1,5 +1,6 @@
package lila.user
import reactivemongo.api.bson._
import scala.concurrent.duration._
import scala.util.Success
@ -16,8 +17,10 @@ final class LightUserApi(
import LightUserApi._
val async = new LightUser.Getter(cache.async)
val sync = new LightUser.GetterSync(cache.sync)
val async = new LightUser.Getter(id =>
if (User isGhost id) fuccess(LightUser.ghost.some) else cache.async(id)
)
val sync = new LightUser.GetterSync(id => if (User isGhost id) LightUser.ghost.some else cache.sync(id))
def syncFallback(id: User.ID) = sync(id) | LightUser.fallback(id)
def asyncFallback(id: User.ID) = async(id) dmap (_ | LightUser.fallback(id))
@ -34,7 +37,9 @@ final class LightUserApi(
private val cache = cacheApi.sync[User.ID, Option[LightUser]](
name = "user.light",
initialCapacity = 1024 * 1024,
compute = id => repo.coll.find($id(id), projection).one[LightUser],
compute = id =>
if (User isGhost id) fuccess(LightUser.ghost.some)
else repo.coll.find($id(id), projection).one[LightUser],
default = id => LightUser(id, id, None, isPatron = false).some,
strategy = Syncache.WaitAfterUptime(8 millis),
expireAfter = Syncache.ExpireAfterWrite(20 minutes)

View File

@ -233,6 +233,10 @@ object User {
def validateId(name: String): Option[User.ID] = couldBeUsername(name) option normalize(name)
def isGhost(name: String) = name.headOption has '!'
def noGhost(name: String) = !isGhost(name)
object BSONFields {
val id = "_id"
val username = "username"

View File

@ -24,7 +24,7 @@ final class UserRepo(val coll: Coll)(implicit ec: scala.concurrent.ExecutionCont
def topNbGame(nb: Int): Fu[List[User]] =
coll.find(enabledSelect).sort($sort desc "count.game").cursor[User]().list(nb)
def byId(id: ID): Fu[Option[User]] = coll.byId[User](id)
def byId(id: ID): Fu[Option[User]] = User.noGhost(id) ?? coll.byId[User](id)
def byIds(ids: Iterable[ID]): Fu[List[User]] = coll.byIds[User](ids)
@ -89,14 +89,15 @@ final class UserRepo(val coll: Coll)(implicit ec: scala.concurrent.ExecutionCont
coll.list[User](enabledSelect ++ $inIds(ids), ReadPreference.secondaryPreferred)
def enabledById(id: ID): Fu[Option[User]] =
coll.one[User](enabledSelect ++ $id(id))
User.noGhost(id) ?? coll.one[User](enabledSelect ++ $id(id))
def disabledById(id: ID): Fu[Option[User]] =
coll.one[User](disabledSelect ++ $id(id))
User.noGhost(id) ?? coll.one[User](disabledSelect ++ $id(id))
def named(username: String): Fu[Option[User]] = coll.byId[User](normalize(username)) recover {
case _: reactivemongo.api.bson.exceptions.BSONValueNotFoundException => none // probably GDPRed user
}
def named(username: String): Fu[Option[User]] =
User.noGhost(username) ?? coll.byId[User](normalize(username)) recover {
case _: reactivemongo.api.bson.exceptions.BSONValueNotFoundException => none // probably GDPRed user
}
def enabledNameds(usernames: List[String]): Fu[List[User]] =
coll