Skip to content

Commit

Permalink
more playban tweaks & fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
ornicar committed Apr 8, 2024
1 parent 262ecfa commit 84834f8
Show file tree
Hide file tree
Showing 8 changed files with 40 additions and 37 deletions.
2 changes: 1 addition & 1 deletion modules/api/src/main/AccountClosure.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ final class AccountClosure(
"garbageCollect" -> { case lila.core.actorApi.security.GarbageCollect(userId) =>
(modApi.garbageCollect(userId) >> lichessClose(userId))
},
"rageSitClose" -> { case lila.core.actorApi.playban.RageSitClose(userId) => lichessClose(userId) }
"rageSitClose" -> { case lila.core.playban.RageSitClose(userId) => lichessClose(userId) }
)

def close(u: User)(using me: Me): Funit = for
Expand Down
4 changes: 0 additions & 4 deletions modules/core/src/main/actorApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,6 @@ package puzzle:
case class RacerRun(userId: UserId, score: Int)
case class StreakRun(userId: UserId, score: Int)

package playban:
case class Playban(userId: UserId, mins: Int, inTournament: Boolean)
case class RageSitClose(userId: UserId)

package lpv:
enum LpvEmbed:
case PublicPgn(pgn: PgnStr)
Expand Down
4 changes: 3 additions & 1 deletion modules/core/src/main/playban.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ type BansOf = List[UserId] => Fu[Map[UserId, Int]]
type RageSitOf = UserId => Fu[RageSit]
type HasCurrentPlayban = UserId => Fu[Boolean]

case class Playban(userId: UserId, mins: Int)
case class Playban(userId: UserId, mins: Int, inTournament: Boolean)
case class SittingDetected(tourId: TourId, userId: UserId)
case class RageSitClose(userId: UserId)
39 changes: 23 additions & 16 deletions modules/playban/src/main/PlaybanApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,20 @@ final class PlaybanApi(
pov.player.userId
.ifTrue(isOnGame(pov.opponent.color))
.so: userId =>
save(Outcome.Abort, userId, RageSit.Update.Reset).andDo(feedback.abort(pov))
save(Outcome.Abort, userId, RageSit.Update.Reset, pov.game.source).andDo(feedback.abort(pov))

def noStart(pov: Pov): Funit =
IfBlameable(pov.game):
pov.player.userId.so: userId =>
save(Outcome.NoPlay, userId, RageSit.Update.Reset).andDo(feedback.noStart(pov))
save(Outcome.NoPlay, userId, RageSit.Update.Reset, pov.game.source).andDo(feedback.noStart(pov))

def rageQuit(game: Game, quitterColor: Color): Funit =
IfBlameable(game):
game
.player(quitterColor)
.userId
.so: userId =>
save(Outcome.RageQuit, userId, RageSit.imbalanceInc(game, quitterColor))
save(Outcome.RageQuit, userId, RageSit.imbalanceInc(game, quitterColor), game.source)
.andDo(feedback.rageQuit(Pov(game, quitterColor)))

def flag(game: Game, flaggerColor: Color): Funit =
Expand All @@ -79,7 +79,7 @@ final class PlaybanApi(
userId <- game.player(flaggerColor).userId
seconds = nowSeconds - game.movedAt.toSeconds
if unreasonableTime.exists(seconds >= _)
yield (save(Outcome.Sitting, userId, RageSit.imbalanceInc(game, flaggerColor)) >>
yield (save(Outcome.Sitting, userId, RageSit.imbalanceInc(game, flaggerColor), game.source) >>
propagateSitting(game, userId)).andDo(feedback.sitting(Pov(game, flaggerColor)))

// flagged after waiting a short time;
Expand All @@ -97,7 +97,7 @@ final class PlaybanApi(
yield lastMovetime.toSeconds >= limit)
}
.map { userId =>
(save(Outcome.SitMoving, userId, RageSit.imbalanceInc(game, flaggerColor)) >>
(save(Outcome.SitMoving, userId, RageSit.imbalanceInc(game, flaggerColor), game.source) >>
propagateSitting(game, userId)).andDo(feedback.sitting(Pov(game, flaggerColor)))
}

Expand All @@ -106,9 +106,11 @@ final class PlaybanApi(
}

private def propagateSitting(game: Game, userId: UserId): Funit =
rageSitCache.get(userId).map { rageSit =>
if rageSit.isBad then Bus.publish(SittingDetected(game, userId), "playban")
}
game.tournamentId.so: tourId =>
rageSitCache.get(userId).map { rageSit =>
if rageSit.isBad
then Bus.publish(lila.core.playban.SittingDetected(tourId, userId), "playban")
}

def other(game: Game, status: Status.type => Status, winner: Option[Color]): Funit =
IfBlameable(game) {
Expand All @@ -118,7 +120,7 @@ final class PlaybanApi(
loserId <- loser.userId
yield
if Status.NoStart.is(status) then
save(Outcome.NoPlay, loserId, RageSit.Update.Reset)
save(Outcome.NoPlay, loserId, RageSit.Update.Reset, game.source)
.andDo(feedback.noStart(Pov(game, !w)))
else
game.clock
Expand All @@ -130,7 +132,7 @@ final class PlaybanApi(
(c.estimateTotalSeconds / 10).atLeast(30).atMost(3 * 60)
.exists(_ < nowSeconds - game.movedAt.toSeconds)
.option:
(save(Outcome.SitResign, loserId, RageSit.imbalanceInc(game, loser.color)) >>
(save(Outcome.SitResign, loserId, RageSit.imbalanceInc(game, loser.color), game.source) >>
propagateSitting(game, loserId)).andDo(feedback.sitting(Pov(game, loser.color)))
.getOrElse:
good(game, !w)
Expand All @@ -139,7 +141,7 @@ final class PlaybanApi(

private def good(game: Game, loserColor: Color): Funit =
game.player(loserColor).userId.so {
save(Outcome.Good, _, RageSit.redeem(game))
save(Outcome.Good, _, RageSit.redeem(game), game.source)
}

// memorize users without any ban to save DB reads
Expand Down Expand Up @@ -193,7 +195,12 @@ final class PlaybanApi(
}
}

private def save(outcome: Outcome, userId: UserId, rsUpdate: RageSit.Update): Funit = {
private def save(
outcome: Outcome,
userId: UserId,
rsUpdate: RageSit.Update,
source: Option[Source]
): Funit = {
lila.mon.playban.outcome(outcome.key).increment()
for
withOutcome <- coll
Expand All @@ -216,21 +223,21 @@ final class PlaybanApi(
else
for
createdAt <- userRepo.createdAtById(userId).orFail(s"Missing user creation date $userId")
withBan <- legiferate(withOutcome, createdAt)
withBan <- legiferate(withOutcome, createdAt, source)
yield withBan
_ <- registerRageSit(withBan, rsUpdate)
yield ()
}.void.logFailure(lila.log("playban"))

private def legiferate(record: UserRecord, accCreatedAt: Instant): Fu[UserRecord] =
private def legiferate(record: UserRecord, accCreatedAt: Instant, source: Option[Source]): Fu[UserRecord] =
record
.bannable(accCreatedAt)
.ifFalse(record.banInEffect)
.so: ban =>
lila.mon.playban.ban.count.increment()
lila.mon.playban.ban.mins.record(ban.mins)
Bus.publish(
lila.core.playban.Playban(record.userId, ban.mins),
lila.core.playban.Playban(record.userId, ban.mins, inTournament = source.has(Source.Arena)),
"playban"
)
coll
Expand Down Expand Up @@ -263,6 +270,6 @@ final class PlaybanApi(
.flatMapz: user =>
noteApi
.lichessWrite(user, "Closed for ragesit recidive")
.andDo(Bus.publish(lila.core.actorApi.playban.RageSitClose(user.id), "rageSitClose"))
.andDo(Bus.publish(lila.core.playban.RageSitClose(user.id), "rageSitClose"))
}
case _ => funit
2 changes: 0 additions & 2 deletions modules/playban/src/main/RageSit.scala
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,3 @@ object RageSit:
case Speed.Blitz => 1
case _ => 2
}

case class SittingDetected(game: Game, userId: UserId)
2 changes: 1 addition & 1 deletion modules/report/src/main/Env.scala
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,4 @@ final class Env(
api.inquiries.expire

lila.common.Bus.subscribeFun("playban"):
case lila.core.playban.Playban(userId, mins) => api.maybeAutoPlaybanReport(userId, mins)
case lila.core.playban.Playban(userId, mins, _) => api.maybeAutoPlaybanReport(userId, mins)
13 changes: 6 additions & 7 deletions modules/tournament/src/main/TournamentApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -345,13 +345,12 @@ final class TournamentApi(
def selfPause(tourId: TourId, userId: UserId): Funit =
withdraw(tourId, userId, isPause = true, isStalling = false)

private def stallPause(tourId: TourId, userId: UserId): Funit =
withdraw(tourId, userId, isPause = false, isStalling = true)

private[tournament] def sittingDetected(game: Game, player: UserId): Funit =
game.tournamentId.so { stallPause(_, player) }

private def withdraw(tourId: TourId, userId: UserId, isPause: Boolean, isStalling: Boolean): Funit =
private[tournament] def withdraw(
tourId: TourId,
userId: UserId,
isPause: Boolean,
isStalling: Boolean
): Funit =
Parallel(tourId, "withdraw")(cached.tourCache.enterable):
case tour if tour.isCreated =>
(playerRepo.remove(tour.id, userId) >> updateNbPlayers(tour.id)).andDo {
Expand Down
11 changes: 6 additions & 5 deletions modules/tournament/src/main/TournamentBusHandler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,12 @@ final private class TournamentBusHandler(
winnersApi.clearAfterMarking(userId)
()

case lila.core.mod.MarkBooster(userId) => ejectFromEnterable(userId)
case lila.core.round.Berserk(gameId, userId) => api.berserk(gameId, userId)
case lila.core.actorApi.playban.Playban(userId, _, true) => api.pausePlaybanned(userId)
case lila.core.team.KickFromTeam(teamId, _, userId) => api.kickFromTeam(teamId, userId)
case lila.playban.SittingDetected(game, player) => api.sittingDetected(game, player)
case lila.core.mod.MarkBooster(userId) => ejectFromEnterable(userId)
case lila.core.round.Berserk(gameId, userId) => api.berserk(gameId, userId)
case lila.core.playban.Playban(userId, _, true) => api.pausePlaybanned(userId)
case lila.core.team.KickFromTeam(teamId, _, userId) => api.kickFromTeam(teamId, userId)
case lila.core.playban.SittingDetected(tourId, userId) =>
api.withdraw(tourId, userId, isPause = false, isStalling = true)

private def ejectFromEnterable(userId: UserId) =
tournamentRepo.withdrawableIds(userId, reason = "ejectFromEnterable").flatMap {
Expand Down

0 comments on commit 84834f8

Please sign in to comment.