176 lines
6.1 KiB
Scala
176 lines
6.1 KiB
Scala
package lila.mod
|
|
|
|
import lila.common.{ Bus, EmailAddress }
|
|
import lila.report.{ Mod, ModId, Room, Suspect, SuspectId }
|
|
import lila.security.{ Granter, Permission }
|
|
import lila.user.{ Holder, LightUserApi, Title, User, UserRepo }
|
|
|
|
final class ModApi(
|
|
userRepo: UserRepo,
|
|
logApi: ModlogApi,
|
|
reportApi: lila.report.ReportApi,
|
|
noteApi: lila.user.NoteApi,
|
|
notifier: ModNotifier,
|
|
lightUserApi: LightUserApi,
|
|
refunder: RatingRefund
|
|
)(implicit ec: scala.concurrent.ExecutionContext) {
|
|
|
|
def setAlt(mod: Mod, prev: Suspect, v: Boolean): Funit =
|
|
for {
|
|
_ <- userRepo.setAlt(prev.user.id, v)
|
|
sus = prev.set(_.withMarks(_.set(_.Alt, v)))
|
|
_ <- reportApi.process(mod, sus, Set(Room.Cheat, Room.Print))
|
|
_ <- logApi.alt(mod, sus, v)
|
|
} yield {
|
|
if (v) notifier.reporters(mod, sus).unit
|
|
}
|
|
|
|
def setEngine(mod: Mod, prev: Suspect, v: Boolean): Funit =
|
|
(prev.user.marks.engine != v) ?? {
|
|
for {
|
|
_ <- userRepo.setEngine(prev.user.id, v)
|
|
sus = prev.set(_.withMarks(_.set(_.Engine, v)))
|
|
_ <- reportApi.process(mod, sus, Set(Room.Cheat, Room.Print))
|
|
_ <- logApi.engine(mod, sus, v)
|
|
} yield {
|
|
Bus.publish(lila.hub.actorApi.mod.MarkCheater(sus.user.id, v), "adjustCheater")
|
|
if (v) {
|
|
notifier.reporters(mod, sus)
|
|
refunder schedule sus
|
|
}
|
|
}
|
|
}
|
|
|
|
def autoMark(suspectId: SuspectId, modId: ModId, note: String): Funit =
|
|
for {
|
|
sus <- reportApi.getSuspect(suspectId.value) orFail s"No such suspect $suspectId"
|
|
unengined <- logApi.wasUnengined(sus)
|
|
_ <- (!sus.user.isBot && !sus.user.marks.engine && !unengined) ?? {
|
|
reportApi.getMod(modId.value) flatMap {
|
|
_ ?? { mod =>
|
|
lila.mon.cheat.autoMark.increment()
|
|
setEngine(mod, sus, v = true) >>
|
|
noteApi.lichessWrite(sus.user, note)
|
|
}
|
|
}
|
|
}
|
|
} yield ()
|
|
|
|
def setBoost(mod: Mod, prev: Suspect, v: Boolean): Fu[Suspect] =
|
|
if (prev.user.marks.boost == v) fuccess(prev)
|
|
else
|
|
for {
|
|
_ <- userRepo.setBoost(prev.user.id, v)
|
|
sus = prev.set(_.withMarks(_.set(_.Boost, v)))
|
|
_ <- reportApi.process(mod, sus, Set(Room.Other))
|
|
_ <- logApi.booster(mod, sus, v)
|
|
} yield {
|
|
if (v) {
|
|
Bus.publish(lila.hub.actorApi.mod.MarkBooster(sus.user.id), "adjustBooster")
|
|
notifier.reporters(mod, sus)
|
|
}
|
|
sus
|
|
}
|
|
|
|
def setTroll(mod: Mod, prev: Suspect, value: Boolean): Fu[Suspect] = {
|
|
val changed = value != prev.user.marks.troll
|
|
val sus = prev.set(_.withMarks(_.set(_.Troll, value)))
|
|
changed ?? {
|
|
userRepo.updateTroll(sus.user).void >>- {
|
|
logApi.troll(mod, sus)
|
|
Bus.publish(lila.hub.actorApi.mod.Shadowban(sus.user.id, value), "shadowban")
|
|
}
|
|
} >>
|
|
reportApi.process(mod, sus, Set(Room.Comm)) >>- {
|
|
if (value) notifier.reporters(mod, sus).unit
|
|
} inject sus
|
|
}
|
|
|
|
def autoTroll(sus: Suspect, note: String): Funit =
|
|
reportApi.getLichessMod flatMap { mod =>
|
|
setTroll(mod, sus, true) >>
|
|
noteApi.lichessWrite(sus.user, note)
|
|
}
|
|
|
|
def garbageCollect(sus: Suspect): Funit =
|
|
reportApi.getLichessMod flatMap { mod =>
|
|
setAlt(mod, sus, v = true) >>
|
|
setTroll(mod, sus, value = false) >>
|
|
logApi.garbageCollect(mod, sus)
|
|
}
|
|
|
|
def disableTwoFactor(mod: String, username: String): Funit =
|
|
withUser(username) { user =>
|
|
(userRepo disableTwoFactor user.id) >> logApi.disableTwoFactor(mod, user.id)
|
|
}
|
|
|
|
def reopenAccount(mod: String, username: String): Funit =
|
|
withUser(username) { user =>
|
|
!user.enabled ?? {
|
|
(userRepo reopen user.id) >> logApi.reopenAccount(mod, user.id)
|
|
}
|
|
}
|
|
|
|
def setKid(mod: String, username: String): Funit =
|
|
withUser(username) { user =>
|
|
userRepo.isKid(user.id) flatMap {
|
|
!_ ?? { (userRepo.setKid(user, true)) } >> logApi.setKidMode(mod, user.id)
|
|
}
|
|
}
|
|
|
|
def setTitle(mod: String, username: String, title: Option[Title]): Funit =
|
|
withUser(username) { user =>
|
|
title match {
|
|
case None =>
|
|
userRepo.removeTitle(user.id) >>
|
|
logApi.removeTitle(mod, user.id) >>-
|
|
lightUserApi.invalidate(user.id)
|
|
case Some(t) =>
|
|
Title.names.get(t) ?? { tFull =>
|
|
userRepo.addTitle(user.id, t) >>
|
|
logApi.addTitle(mod, user.id, s"$t ($tFull)") >>-
|
|
lightUserApi.invalidate(user.id)
|
|
}
|
|
}
|
|
}
|
|
|
|
def setEmail(mod: String, username: String, email: EmailAddress): Funit =
|
|
withUser(username) { user =>
|
|
userRepo.setEmail(user.id, email) >>
|
|
userRepo.setEmailConfirmed(user.id) >>
|
|
logApi.setEmail(mod, user.id)
|
|
}
|
|
|
|
def setPermissions(mod: Holder, username: String, permissions: Set[Permission]): Funit =
|
|
withUser(username) { user =>
|
|
val finalPermissions = Permission(user.roles).filter { p =>
|
|
// only remove permissions the mod can actually grant
|
|
permissions.contains(p) || !Granter.canGrant(mod, p)
|
|
} ++
|
|
// only add permissions the mod can actually grant
|
|
permissions.filter(Granter.canGrant(mod, _))
|
|
userRepo.setRoles(user.id, finalPermissions.map(_.dbKey).toList) >>
|
|
logApi.setPermissions(mod, user.id, Permission.diff(Permission(user.roles), permissions))
|
|
}
|
|
|
|
def setReportban(mod: Mod, sus: Suspect, v: Boolean): Funit =
|
|
(sus.user.marks.reportban != v) ?? {
|
|
userRepo.setReportban(sus.user.id, v) >> logApi.reportban(mod, sus, v)
|
|
}
|
|
|
|
def setRankban(mod: Mod, sus: Suspect, v: Boolean): Funit =
|
|
(sus.user.marks.rankban != v) ?? {
|
|
if (v) Bus.publish(lila.hub.actorApi.mod.KickFromRankings(sus.user.id), "kickFromRankings")
|
|
userRepo.setRankban(sus.user.id, v) >> logApi.rankban(mod, sus, v)
|
|
}
|
|
|
|
def allMods =
|
|
userRepo.userIdsWithRoles(Permission.modPermissions.view.map(_.dbKey).toList) flatMap
|
|
userRepo.enabledByIds dmap {
|
|
_.sortBy(_.timeNoSee)
|
|
}
|
|
|
|
private def withUser[A](username: String)(op: User => Fu[A]): Fu[A] =
|
|
userRepo named username orFail s"[mod] missing user $username" flatMap op
|
|
}
|