lila/modules/irwin/src/main/IrwinApi.scala

118 lines
3.8 KiB
Scala

package lila.irwin
import org.joda.time.DateTime
import reactivemongo.bson._
import lila.db.dsl._
import lila.game.{ Pov, GameRepo }
import lila.report.{ Report, Mod, Suspect, Reporter, SuspectId, ModId }
import lila.tournament.{ Tournament, TournamentTop }
import lila.user.{ User, UserRepo }
final class IrwinApi(
reportColl: Coll,
modApi: lila.mod.ModApi,
reportApi: lila.report.ReportApi,
notifyApi: lila.notify.NotifyApi,
bus: lila.common.Bus,
mode: () => String
) {
import BSONHandlers._
def dashboard: Fu[IrwinDashboard] =
reportColl.find($empty).sort($sort desc "date").list[IrwinReport](20) map IrwinDashboard.apply
object reports {
def insert(report: IrwinReport) = (mode() != "none") ?? {
for {
_ <- reportColl.update($id(report._id), report, upsert = true)
_ <- markOrReport(report)
_ <- notification(report)
} yield ()
}
def get(user: User): Fu[Option[IrwinReport]] =
reportColl.find($id(user.id)).uno[IrwinReport]
def withPovs(user: User): Fu[Option[IrwinReport.WithPovs]] = get(user) flatMap {
_ ?? { report =>
GameRepo.gamesFromSecondary(report.games.map(_.gameId)) map { games =>
val povs = games.flatMap { g =>
Pov(g, user) map { g.id -> _ }
}.toMap
IrwinReport.WithPovs(report, povs).some
}
}
}
private def getSuspect(suspectId: User.ID) =
UserRepo byId suspectId flatten s"suspect $suspectId not found" map Suspect.apply
private def markOrReport(report: IrwinReport): Funit =
if (report.activation > 90 && mode() == "mark")
modApi.autoMark(report.suspectId, ModId.irwin) >>-
lila.mon.mod.irwin.mark()
else if (report.activation >= 60 && mode() != "none") for {
suspect <- getSuspect(report.suspectId.value)
irwin <- UserRepo byId "irwin" flatten s"Irwin user not found" map Mod.apply
_ <- reportApi.create(Report.Candidate(
reporter = Reporter(irwin.user),
suspect = suspect,
reason = lila.report.Reason.Cheat,
text = s"${report.activation}% over ${report.games.size} games"
))
} yield lila.mon.mod.irwin.report()
else funit
}
object requests {
import IrwinRequest.Origin
def fromMod(suspectId: SuspectId, mod: User) = {
notification.add(suspectId, ModId(mod.id))
insert(suspectId, _.Moderator)
}
private[irwin] def insert(suspectId: SuspectId, origin: Origin.type => Origin): Funit = fuccess {
bus.publish(IrwinRequest(
suspect = suspectId,
origin = origin(Origin),
date = DateTime.now
), 'irwin)
}
private[irwin] def fromTournamentLeaders(leaders: Map[Tournament, TournamentTop]): Funit =
lila.common.Future.applySequentially(leaders.toList) {
case (tour, top) =>
val userIds = top.value.zipWithIndex.filter(_._2 <= tour.nbPlayers * 2 / 100).map(_._1.userId)
lila.common.Future.applySequentially(userIds) { userId =>
insert(SuspectId(userId), _.Tournament)
}
}
private[irwin] def fromLeaderboard(leaders: List[User]): Funit =
lila.common.Future.applySequentially(leaders) { user =>
insert(SuspectId(user.id), _.Leaderboard)
}
}
object notification {
private var subs = Map.empty[SuspectId, ModId]
def add(suspectId: SuspectId, modId: ModId): Unit = subs += (suspectId -> modId)
private[IrwinApi] def apply(report: IrwinReport): Funit =
subs.get(report.suspectId) ?? { modId =>
subs = subs - report.suspectId
import lila.notify.{ Notification, IrwinDone }
notifyApi.addNotification(
Notification.make(Notification.Notifies(modId.value), IrwinDone(report.suspectId.value))
)
}
}
}