lila/modules/challenge/src/main/ChallengeGranter.scala

86 lines
3.6 KiB
Scala

package lila.challenge
import play.api.i18n.Lang
import lila.i18n.I18nKeys.{ challenge => trans }
import lila.pref.Pref
import lila.rating.PerfType
import lila.relation.{ Block, Follow }
import lila.user.User
case class ChallengeDenied(dest: User, reason: ChallengeDenied.Reason)
object ChallengeDenied {
sealed trait Reason
object Reason {
case object YouAreAnon extends Reason
case object YouAreBlocked extends Reason
case object TheyDontAcceptChallenges extends Reason
case class RatingOutsideRange(perf: PerfType) extends Reason
case class RatingIsProvisional(perf: PerfType) extends Reason
case object FriendsOnly extends Reason
case object BotUltraBullet extends Reason
case object SelfChallenge extends Reason
}
def translated(d: ChallengeDenied)(implicit lang: Lang): String =
d.reason match {
case Reason.YouAreAnon => trans.registerToSendChallenges.txt()
case Reason.YouAreBlocked => trans.youCannotChallengeX.txt(d.dest.titleUsername)
case Reason.TheyDontAcceptChallenges => trans.xDoesNotAcceptChallenges.txt(d.dest.titleUsername)
case Reason.RatingOutsideRange(perf) =>
trans.yourXRatingIsTooFarFromY.txt(perf.trans, d.dest.titleUsername)
case Reason.RatingIsProvisional(perf) => trans.cannotChallengeDueToProvisionalXRating.txt(perf.trans)
case Reason.FriendsOnly => trans.xOnlyAcceptsChallengesFromFriends.txt(d.dest.titleUsername)
case Reason.BotUltraBullet => "Bots cannot play UltraBullet. Choose a slower time control."
case Reason.SelfChallenge => "You cannot challenge yourself."
}
}
final class ChallengeGranter(
prefApi: lila.pref.PrefApi,
relationApi: lila.relation.RelationApi
) {
import ChallengeDenied.Reason._
val ratingThreshold = 300
def apply(fromOption: Option[User], dest: User, perfType: Option[PerfType])(implicit
ec: scala.concurrent.ExecutionContext
): Fu[Option[ChallengeDenied]] =
fromOption
.fold[Fu[Option[ChallengeDenied.Reason]]](fuccess(YouAreAnon.some)) { from =>
relationApi.fetchRelation(dest, from) zip
prefApi.getPref(dest).map(_.challenge) map {
case (Some(Block), _) => YouAreBlocked.some
case (_, Pref.Challenge.NEVER) => TheyDontAcceptChallenges.some
case (Some(Follow), _) => none // always accept from followed
case (_, _) if from.marks.engine && !dest.marks.engine => YouAreBlocked.some
case (_, Pref.Challenge.FRIEND) => FriendsOnly.some
case (_, Pref.Challenge.RATING) =>
perfType ?? { pt =>
if (from.perfs(pt).provisional || dest.perfs(pt).provisional)
RatingIsProvisional(pt).some
else {
val diff = math.abs(from.perfs(pt).intRating - dest.perfs(pt).intRating)
(diff > ratingThreshold) option RatingOutsideRange(pt)
}
}
case (_, Pref.Challenge.ALWAYS) => none
case _ if from == dest => SelfChallenge.some
case _ => none
}
}
.map {
case None if dest.isBot && perfType.has(PerfType.UltraBullet) => BotUltraBullet.some
case res => res
}
.map {
_.map { ChallengeDenied(dest, _) }
}
}