auto evaluation of reported users

This commit is contained in:
Thibault Duplessis 2014-01-13 22:51:16 +01:00
parent 0ddbb9988a
commit a9682e8a87
6 changed files with 57 additions and 45 deletions

View file

@ -31,11 +31,18 @@ trait UserHelper { self: I18nHelper with StringHelper ⇒
userIdOption: Option[String],
cssClass: Option[String] = None,
withOnline: Boolean = true,
truncate: Option[Int] = None): Html = Html {
truncate: Option[Int] = None,
params: String = ""): Html = Html {
userIdOption.fold(User.anonymous) { userId
Env.user usernameOption userId map {
_.fold(User.anonymous) { username
userIdNameLink(userId, username, cssClass, withOnline, truncate)
userIdNameLink(
userId = userId,
username = username,
cssClass = cssClass,
withOnline = withOnline,
truncate = truncate,
params = params)
}
} await
}
@ -70,10 +77,11 @@ trait UserHelper { self: I18nHelper with StringHelper ⇒
username: String,
cssClass: Option[String] = None,
withOnline: Boolean = true,
truncate: Option[Int] = None): String =
truncate: Option[Int] = None,
params: String = ""): String =
"""<a %s %s>%s</a>""".format(
userClass(userId, cssClass, withOnline),
userHref(username),
userHref(username, params = params),
truncate.fold(username)(username.take)
)
@ -107,8 +115,8 @@ trait UserHelper { self: I18nHelper with StringHelper ⇒
def perfTitle(perf: String): String = lila.user.Perf.titles get perf getOrElse perf
private def userHref(username: String) =
"href=\"" + routes.User.show(username) + "\""
private def userHref(username: String, params: String = "") =
s"""href="${routes.User.show(username)}$params""""
protected def userClass(
userId: String,

View file

@ -7,7 +7,7 @@
}
@base.layout(
title = title,
title = title,
moreCss = cssTag("report.css"),
goodies = goodies.some) {
@ -23,23 +23,23 @@ goodies = goodies.some) {
</tr>
</thead>
<tbody>
@reports.map { r =>
<tr class="@r.unprocessed.fold("new", "")">
<td>@userIdLink(r.createdBy.some)@timeago(r.createdAt)</td>
<td>@userIdLink(r.user.some)</td>
<td>
<strong>@r.reason.capitalize</strong>
- @autoLink(r.text)
</td>
<td>@r.processedBy.map { u =>
}.getOrElse {
<form action="@routes.Report.process(r.id)" method="post">
<button type="submit" class="button">Check</button>
</form>
}
</td>
</tr>
}
@reports.map { r =>
<tr class="@r.unprocessed.fold("new", "")">
<td>@userIdLink(r.createdBy.some)@timeago(r.createdAt)</td>
<td>@userIdLink(r.user.some, params = "?mod")</td>
<td>
<strong>@r.reason.capitalize</strong>
- @autoLink(r.text)
</td>
<td>@r.processedBy.map { u =>
}.getOrElse {
<form action="@routes.Report.process(r.id)" method="post">
<button type="submit" class="button">Check</button>
</form>
}
</td>
</tr>
}
</tbody>
</table>
</div>

View file

@ -9,13 +9,14 @@ import lila.common.PimpedConfig._
final class Env(
config: Config,
db: lila.db.Env,
evaluator: lila.user.Evaluator,
hub: lila.hub.Env) {
private val CollectionReport = config getString "collection.report"
lazy val forms = new DataForm(hub.actor.captcher)
lazy val api = new ReportApi
lazy val api = new ReportApi(evaluator)
private[report] lazy val reportColl = db(CollectionReport)
}
@ -25,5 +26,6 @@ object Env {
lazy val current = "[boot] report" describes new Env(
config = lila.common.PlayApp loadConfig "report",
db = lila.db.Env.current,
evaluator = lila.user.Env.current.evaluator,
hub = lila.hub.Env.current)
}

View file

@ -18,11 +18,15 @@ case class Report(
def isCreator(user: String) = user == createdBy
def isCheat = realReason == Reason.Cheat
def isManual = createdBy != "lichess"
def process(by: User) = copy(processedBy = by.id.some)
def unprocessed = processedBy.isEmpty
def realReason = Reason byName reason
def realReason: Reason = Reason byName reason
}
object Report {

View file

@ -4,10 +4,10 @@ import play.api.libs.json._
import lila.db.api._
import lila.db.Implicits._
import lila.user.User
import lila.user.{ User, Evaluator }
import tube.reportTube
final class ReportApi {
final class ReportApi(evaluator: Evaluator) {
def create(setup: ReportSetup, by: User): Funit =
Reason(setup.reason).fold[Funit](fufail("Invalid report reason " + setup.reason)) { reason
@ -16,12 +16,14 @@ final class ReportApi {
reason = reason,
text = setup.text,
createdBy = by)
$insert(report)
$insert(report) >> {
(report.isCheat && report.isManual) ?? evaluator.generate(report.user, true).void
}
}
def process(id: String, by: User): Funit =
def process(id: String, by: User): Funit =
$update.field(id, "processedBy", by.id)
def nbUnprocessed = $count(Json.obj("processedBy" -> $exists(false)))
def recent = $find($query.all sort $sort.createdDesc, 50)

View file

@ -11,29 +11,25 @@ import lila.db.api._
import lila.db.JsTube.Helpers.{ rename, writeDate, readDate }
import lila.db.Types._
private[user] final class Evaluator(coll: Coll, script: String) {
final class Evaluator(coll: Coll, script: String) {
def findOrGenerate(user: User, deep: Boolean): Fu[Option[Evaluation]] = find(user) flatMap {
case x@Some(eval) if (!deep || eval.isDeep) fuccess(x)
case _ generate(user, deep)
case _ generate(user.id, deep)
}
def find(user: User): Fu[Option[Evaluation]] =
coll.find(Json.obj("_id" -> user.id)).one[JsObject] map { _ map readEvaluation }
def generate(user: User, deep: Boolean): Fu[Option[Evaluation]] = UserRepo byId user.id flatMap {
_ ?? { user
for {
output run(user.id, deep).future
evalJs (Json parse output).transform(evaluationTransformer) match {
case JsSuccess(v, _) fuccess(v)
case JsError(e) fufail(lila.common.LilaException(s"Can't parse evaluator output: $e on $output"))
}
eval scala.concurrent.Future(readEvaluation(evalJs))
_ coll.update(Json.obj("_id" -> user.id), evalJs, upsert = true)
} yield eval.some
def generate(userId: String, deep: Boolean): Fu[Option[Evaluation]] = for {
output run(userId, deep).future
evalJs (Json parse output).transform(evaluationTransformer) match {
case JsSuccess(v, _) fuccess(v)
case JsError(e) fufail(lila.common.LilaException(s"Can't parse evaluator output: $e on $output"))
}
}
eval scala.concurrent.Future(readEvaluation(evalJs))
_ coll.update(Json.obj("_id" -> userId), evalJs, upsert = true)
} yield eval.some
private def readEvaluation(js: JsValue): Evaluation =
(readDate('date) andThen Evaluation.reader) reads js match {