lila/modules/report/src/main/ReportApi.scala

130 lines
4.0 KiB
Scala

package lila.report
import akka.actor.ActorSelection
import org.joda.time.DateTime
import play.api.libs.json._
import play.modules.reactivemongo.json.ImplicitBSONHandlers._
import lila.db.api._
import lila.db.Implicits._
import lila.user.{ User, UserRepo }
import tube.reportTube
private[report] final class ReportApi {
def create(setup: ReportSetup, by: User): Funit =
Reason(setup.reason).fold[Funit](fufail(s"Invalid report reason ${setup.reason}")) { reason =>
val user = setup.user
val report = Report.make(
user = setup.user,
reason = reason,
text = setup.text,
createdBy = by)
!isAlreadySlain(report, user) ?? {
if (by.id == UserRepo.lichessId) reportTube.coll.update(
selectRecent(user, reason),
Json.obj("$set" -> (reportTube.toMongo(report).get - "processedBy" - "_id"))
) flatMap { res =>
(res.n == 0) ?? $insert(report)
}
else $insert(report)
}
}
private def isAlreadySlain(report: Report, user: User) =
(report.isCheat && user.engine) ||
(report.isAutomatic && report.isOther && user.troll) ||
(report.isTroll && user.troll)
def autoCheatReport(userId: String, text: String): Funit = {
UserRepo byId userId zip UserRepo.lichess flatMap {
case (Some(user), Some(lichess)) => create(ReportSetup(
user = user,
reason = "cheat",
text = text,
gameId = "",
move = ""), lichess)
case _ => funit
}
}
def clean(userId: String): Funit = $update(
Json.obj(
"user" -> userId,
"reason" -> "cheat"
) ++ unprocessedSelect,
$set("processedBy" -> "lichess"),
multi = true)
def process(id: String, by: User): Funit = $find byId id flatMap {
_ ?? { report =>
$update(
Json.obj(
"user" -> report.user,
"reason" -> report.reason
) ++ unprocessedSelect,
$set("processedBy" -> by.id),
multi = true)
}
}
def processEngine(userId: String, byModId: String): Funit = $update(
Json.obj(
"user" -> userId,
"reason" -> Reason.Cheat.name
) ++ unprocessedSelect,
$set("processedBy" -> byModId),
multi = true)
def processTroll(userId: String, byModId: String): Funit = $update(
Json.obj(
"user" -> userId,
"reason" -> $in(List(Reason.Insult.name, Reason.Troll.name, Reason.Other.name))
) ++ unprocessedSelect,
$set("processedBy" -> byModId),
multi = true)
def autoInsultReport(userId: String, text: String): Funit = {
UserRepo byId userId zip UserRepo.lichess flatMap {
case (Some(user), Some(lichess)) => create(ReportSetup(
user = user,
reason = "insult",
text = text,
gameId = "",
move = ""), lichess)
case _ => funit
}
}
def autoProcess(userId: String): Funit =
$update(Json.obj("user" -> userId.toLowerCase), Json.obj("processedBy" -> "lichess"))
private val unprocessedSelect = Json.obj("processedBy" -> $exists(false))
private val processedSelect = Json.obj("processedBy" -> $exists(true))
def nbUnprocessed = $count(unprocessedSelect)
def recent(nb: Int) = $find($query.all sort $sort.createdDesc, nb)
def unprocessedAndRecent(nb: Int): Fu[List[Report.WithUser]] =
recentUnprocessed |+| recentProcessed(nb) flatMap { reports =>
UserRepo byIds reports.map(_.user).distinct map { users =>
reports.flatMap { r =>
users.find(_.id == r.user) map { Report.WithUser(r, _) }
}
}
}
def recentUnprocessed = $find($query(unprocessedSelect) sort $sort.createdDesc)
def recentProcessed(nb: Int) = $find($query(processedSelect) sort $sort.createdDesc, nb)
private def selectRecent(user: User, reason: Reason) = Json.obj(
"createdAt" -> $gt($date(DateTime.now minusDays 7)),
"user" -> user.id,
"reason" -> reason.name)
private def findRecent(user: User, reason: Reason): Fu[Option[Report]] =
$find.one(selectRecent(user, reason))
}