Skip to content

Commit

Permalink
/api/user?challenge=true
Browse files Browse the repository at this point in the history
  • Loading branch information
ornicar committed Jun 26, 2024
1 parent c2579e5 commit 73008f9
Show file tree
Hide file tree
Showing 8 changed files with 51 additions and 37 deletions.
1 change: 1 addition & 0 deletions app/controllers/Account.scala
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ final class Account(
me.value,
withFollows = apiC.userWithFollows,
withTrophies = false,
withCanChallenge = false,
forWiki = wikiGranted
)
.dmap { JsonOk(_) }
Expand Down
3 changes: 2 additions & 1 deletion app/controllers/Api.scala
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ final class Api(
.extended(
name,
withFollows = userWithFollows,
withTrophies = getBool("trophies")
withTrophies = getBool("trophies"),
withCanChallenge = getBool("challenge")
)
.map(toApiResult)
.map(toHttp)
Expand Down
6 changes: 3 additions & 3 deletions app/controllers/Challenge.scala
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ final class Challenge(
case None => redir
case Some(dest) if ctx.is(dest) => redir
case Some(dest) =>
env.challenge.granter.isDenied(dest, c.perfType).flatMap {
env.challenge.granter.isDenied(dest, c.perfType.key.some).flatMap {
case Some(denied) =>
showChallenge(c, lila.challenge.ChallengeDenied.translated(denied).some)
case None => api.setDestUser(c, dest).inject(redir)
Expand Down Expand Up @@ -303,7 +303,7 @@ final class Challenge(
limit.challengeUser(me, rateLimited, cost = cost):
for
challenge <- makeOauthChallenge(config, me, destUser)
grant <- env.challenge.granter.isDenied(destUser, config.perfType)
grant <- env.challenge.granter.isDenied(destUser, config.perfKey.some)
res <- grant match
case Some(denied) =>
fuccess:
Expand Down Expand Up @@ -376,7 +376,7 @@ final class Challenge(
NoBot:
Found(env.game.gameRepo.game(gameId)): g =>
g.opponentOf(me).flatMap(_.userId).so(env.user.repo.byId).orNotFound { opponent =>
env.challenge.granter.isDenied(opponent, g.perfKey).flatMap {
env.challenge.granter.isDenied(opponent, g.perfKey.some).flatMap {
case Some(d) => BadRequest(jsonError(lila.challenge.ChallengeDenied.translated(d)))
case _ =>
api.offerRematchForGame(g, me).map {
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/Setup.scala
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ final class Setup(
for
origUser <- ctx.user.soFu(env.user.perfsRepo.withPerf(_, config.perfType))
destUser <- userId.so(env.user.api.enabledWithPerf(_, config.perfType))
denied <- destUser.so(u => env.challenge.granter.isDenied(u.user, config.perfType))
denied <- destUser.so(u => env.challenge.granter.isDenied(u.user, config.perfKey.some))
result <- denied match
case Some(denied) =>
val message = lila.challenge.ChallengeDenied.translated(denied)
Expand Down
10 changes: 8 additions & 2 deletions modules/api/src/main/UserApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ final class UserApi(
trophyApi: lila.user.TrophyApi,
shieldApi: lila.tournament.TournamentShieldApi,
revolutionApi: lila.tournament.RevolutionApi,
challengeGranter: lila.challenge.ChallengeGranter,
net: NetConfig
)(using Executor, lila.core.i18n.Translator):

Expand All @@ -38,16 +39,18 @@ final class UserApi(
def extended(
username: UserStr,
withFollows: Boolean,
withTrophies: Boolean
withTrophies: Boolean,
withCanChallenge: Boolean
)(using Option[Me], Lang): Fu[Option[JsObject]] =
userApi.withPerfs(username).flatMapz {
extended(_, withFollows, withTrophies).dmap(some)
extended(_, withFollows, withTrophies, withCanChallenge).dmap(some)
}

def extended(
u: User | UserWithPerfs,
withFollows: Boolean,
withTrophies: Boolean,
withCanChallenge: Boolean,
forWiki: Boolean = false
)(using as: Option[Me], lang: Lang): Fu[JsObject] =
u.match
Expand All @@ -69,6 +72,7 @@ final class UserApi(
gameCache.nbImportedBy(u.id),
(withTrophies && !u.lame).soFu(getTrophiesAndAwards(u.user)),
streamerApi.listed(u.user),
withCanChallenge.so(challengeGranter.mayChallenge(u.user).dmap(some)),
forWiki.soFu(userRepo.email(u.id))
).mapN:
(
Expand All @@ -83,6 +87,7 @@ final class UserApi(
nbImported,
trophiesAndAwards,
streamer,
canChallenge,
email
) =>
jsonView.full(u.user, u.perfs.some, withProfile = true) ++ {
Expand Down Expand Up @@ -112,6 +117,7 @@ final class UserApi(
.add("nbFollowing", following)
.add("nbFollowers", withFollows.option(0))
.add("trophies", trophiesAndAwards.map(trophiesJson))
.add("canChallenge", canChallenge)
.add(
"streamer",
streamer.map: s =>
Expand Down
64 changes: 34 additions & 30 deletions modules/challenge/src/main/ChallengeGranter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -42,38 +42,42 @@ final class ChallengeGranter(

val ratingThreshold = 300

def isDenied(dest: User, perfKey: PerfKey)(using
def mayChallenge(dest: User)(using Executor)(using me: Option[Me]): Fu[Boolean] =
isDenied(dest, None).map(_.isEmpty)

// perfkey is None when we're not yet trying to challenge
def isDenied(dest: User, perfKey: Option[PerfKey])(using
Executor
)(using me: Option[Me]): Fu[Option[ChallengeDenied]] = me
.fold[Fu[Option[ChallengeDenied.Reason]]] {
prefApi.getChallenge(dest.id).map {
case lila.core.pref.Challenge.ALWAYS => none
case _ => YouAreAnon.some
}
} { from =>
type Res = Option[ChallengeDenied.Reason]
given Conversion[Res, Fu[Res]] = fuccess
relationApi.fetchRelation(dest.id, from.userId).zip(prefApi.getChallenge(dest.id)).flatMap {
case (Some(Block), _) => YouAreBlocked.some
case (_, lila.core.pref.Challenge.NEVER) => TheyDontAcceptChallenges.some
case (Some(Follow), _) => none // always accept from followed
case (_, _) if from.marks.engine && !dest.marks.engine => YouAreBlocked.some
case (_, lila.core.pref.Challenge.FRIEND) => FriendsOnly.some
case (_, lila.core.pref.Challenge.RATING) =>
userApi
.perfsOf(from.value -> dest, primary = false)
.map: (fromPerfs, destPerfs) =>
if fromPerfs(perfKey).provisional || destPerfs(perfKey).provisional
then RatingIsProvisional(perfKey).some
else
val diff =
math.abs(fromPerfs(perfKey).intRating.value - destPerfs(perfKey).intRating.value)
(diff > ratingThreshold).option(RatingOutsideRange(perfKey))
case (_, lila.core.pref.Challenge.REGISTERED) => none
case _ if from == dest => SelfChallenge.some
case _ => none
}
}
.match
case None =>
prefApi.getChallenge(dest.id).map {
case lila.core.pref.Challenge.ALWAYS => none
case _ => YouAreAnon.some
}
case Some(from) =>
type Res = Option[ChallengeDenied.Reason]
given Conversion[Res, Fu[Res]] = fuccess
relationApi.fetchRelation(dest.id, from.userId).zip(prefApi.getChallenge(dest.id)).flatMap {
case (Some(Block), _) => YouAreBlocked.some
case (_, lila.core.pref.Challenge.NEVER) => TheyDontAcceptChallenges.some
case (Some(Follow), _) => none // always accept from followed
case (_, _) if from.marks.engine && !dest.marks.engine => YouAreBlocked.some
case (_, lila.core.pref.Challenge.FRIEND) => FriendsOnly.some
case (_, lila.core.pref.Challenge.RATING) =>
perfKey.so: pk =>
userApi
.perfsOf(from.value -> dest, primary = false)
.map: (fromPerfs, destPerfs) =>
if fromPerfs(pk).provisional || destPerfs(pk).provisional
then RatingIsProvisional(pk).some
else
val diff = math.abs(fromPerfs(pk).intRating.value - destPerfs(pk).intRating.value)
(diff > ratingThreshold).option(RatingOutsideRange(pk))
case (_, lila.core.pref.Challenge.REGISTERED) => none
case _ if from == dest => SelfChallenge.some
case _ => none
}
.map:
case None if dest.isBot && perfKey == PerfKey.ultraBullet => BotUltraBullet.some
case res => res
Expand Down
1 change: 1 addition & 0 deletions modules/setup/src/main/ApiConfig.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ final case class ApiConfig(
):

def perfType: PerfType = lila.rating.PerfType(variant, chess.Speed(days.isEmpty.so(clock)))
def perfKey = perfType.key

def validFen = Variant.isValidInitialFen(variant, position)

Expand Down
1 change: 1 addition & 0 deletions modules/setup/src/main/Config.scala
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ private[setup] trait Config:
def makeSpeed: Speed = chess.Speed(makeClock)

def perfType: PerfType = lila.rating.PerfType(variant, makeSpeed)
def perfKey = perfType.key

trait Positional:
self: Config =>
Expand Down

0 comments on commit 73008f9

Please sign in to comment.