improve sandbag auto-reporting - for lichess-org/tavern#27

pull/8342/head
Thibault Duplessis 2021-03-09 13:45:36 +01:00
parent 3e8e043670
commit 26e235ff34
3 changed files with 36 additions and 20 deletions

View File

@ -239,16 +239,18 @@ object inquiry {
.withFilter(_.byLichess)
.flatMap(_.text.linesIterator)
.collect {
case farmWithRegex(userId) => userId
case sandbagWithRegex(userId) => userId
case farmWithRegex(userId) => List(userId)
case sandbagWithRegex(userIds) => userIds.split(' ').toList.map(_.trim.replace("@", ""))
}
.flatten
.distinct
.toNel
}
private val farmWithRegex =
("^Boosting: farms rating points from @(" + User.historicalUsernameRegex.pattern + ")").r.unanchored
private val sandbagWithRegex =
("^Sandbagging: throws games to @(" + User.historicalUsernameRegex.pattern + ")").r.unanchored
"^Sandbagging: throws games to (.+)".r.unanchored
private def thenForms(url: String, button: Tag) =
div(

View File

@ -36,16 +36,15 @@ final private class SandbagWatch(
}
else {
records.put(userId, record)
if (record.latest has Sandbag) {
if (record.count(Sandbag) == 3) sendMessage(userId, MsgPreset.sandbagAuto)
else if (record.count(Sandbag) == 4) withWinnerAndLoser(game)(reportApi.autoSandbagReport)
else funit
} else {
val boostCount = record.samePlayerBoostCount
if (boostCount == 3) sendMessage(userId, MsgPreset.boostAuto)
else if (boostCount == 4) withWinnerAndLoser(game)(reportApi.autoBoostReport)
else funit
val sandbagCount = record.countSandbagWithLatest
val boostCount = record.samePlayerBoostCount
if (sandbagCount == 3) sendMessage(userId, MsgPreset.sandbagAuto)
else if (sandbagCount == 4) game.loserUserId ?? { loser =>
reportApi.autoSandbagReport(record.sandbagOpponents, loser)
}
else if (boostCount == 3) sendMessage(userId, MsgPreset.boostAuto)
else if (boostCount == 4) withWinnerAndLoser(game)(reportApi.autoBoostReport)
else funit
}
private def sendMessage(userId: User.ID, preset: MsgPreset): Funit =
@ -70,7 +69,8 @@ final private class SandbagWatch(
.playerByUserId(userId)
.ifTrue(isSandbag(game))
.fold[Outcome](Good) { player =>
if (player.color == loser) Sandbag else game.loserUserId.fold[Outcome](Good)(Boost.apply)
if (player.color == loser) game.winnerUserId.fold[Outcome](Good)(Sandbag.apply)
else game.loserUserId.fold[Outcome](Good)(Boost.apply)
}
private def isSandbag(game: Game): Boolean =
@ -83,9 +83,9 @@ final private class SandbagWatch(
private object SandbagWatch {
sealed trait Outcome
case object Good extends Outcome
case object Sandbag extends Outcome
case class Boost(opponent: User.ID) extends Outcome
case object Good extends Outcome
case class Sandbag(opponent: User.ID) extends Outcome
case class Boost(opponent: User.ID) extends Outcome
val maxOutcomes = 7
@ -99,6 +99,20 @@ private object SandbagWatch {
def immaculate = outcomes.sizeIs == maxOutcomes && outcomes.forall(Good ==)
def latestIsSandbag = latest exists {
case Sandbag(_) => true
case _ => false
}
def countSandbagWithLatest: Int = latestIsSandbag ?? outcomes.count {
case Sandbag(_) => true
case _ => false
}
def sandbagOpponents = outcomes.collect { case Sandbag(opponent) =>
opponent
}.distinct
def samePlayerBoostCount = latest ?? {
case Boost(opponent) =>
outcomes.count {

View File

@ -251,15 +251,15 @@ final class ReportApi(
case _ => funit
}
def autoSandbagReport(winnerId: User.ID, loserId: User.ID): Funit =
userRepo.pair(winnerId, loserId) zip getLichessReporter flatMap {
case Some((winner, loser)) ~ reporter if !winner.lame && !loser.lame =>
def autoSandbagReport(winnerIds: List[User.ID], loserId: User.ID): Funit =
userRepo.byId(loserId) zip getLichessReporter flatMap {
case Some(loser) ~ reporter if !loser.lame =>
create(
Candidate(
reporter = reporter,
suspect = Suspect(loser),
reason = Reason.Boost,
text = s"Sandbagging: throws games to @${winner.username}"
text = s"Sandbagging: throws games to ${winnerIds.map("@" + _) mkString " "}"
)
)
case _ => funit