From a9682e8a87eb3b16d0388fa281039461896e82c6 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Mon, 13 Jan 2014 22:51:16 +0100 Subject: [PATCH] auto evaluation of reported users --- app/templating/UserHelper.scala | 20 +++++++++----- app/views/report/list.scala.html | 36 ++++++++++++------------- modules/report/src/main/Env.scala | 4 ++- modules/report/src/main/Report.scala | 6 ++++- modules/report/src/main/ReportApi.scala | 12 +++++---- modules/user/src/main/Evaluator.scala | 24 +++++++---------- 6 files changed, 57 insertions(+), 45 deletions(-) diff --git a/app/templating/UserHelper.scala b/app/templating/UserHelper.scala index b8a315fe4b..a3525e42ea 100644 --- a/app/templating/UserHelper.scala +++ b/app/templating/UserHelper.scala @@ -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 = """%s""".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, diff --git a/app/views/report/list.scala.html b/app/views/report/list.scala.html index 6a9c576340..333ac5707d 100644 --- a/app/views/report/list.scala.html +++ b/app/views/report/list.scala.html @@ -7,7 +7,7 @@ } @base.layout( -title = title, +title = title, moreCss = cssTag("report.css"), goodies = goodies.some) { @@ -23,23 +23,23 @@ goodies = goodies.some) { - @reports.map { r => - - @userIdLink(r.createdBy.some)@timeago(r.createdAt) - @userIdLink(r.user.some) - - @r.reason.capitalize - - @autoLink(r.text) - - @r.processedBy.map { u => - }.getOrElse { -
- -
- } - - - } + @reports.map { r => + + @userIdLink(r.createdBy.some)@timeago(r.createdAt) + @userIdLink(r.user.some, params = "?mod") + + @r.reason.capitalize + - @autoLink(r.text) + + @r.processedBy.map { u => + }.getOrElse { +
+ +
+ } + + + } diff --git a/modules/report/src/main/Env.scala b/modules/report/src/main/Env.scala index b23f056418..4abda963e0 100644 --- a/modules/report/src/main/Env.scala +++ b/modules/report/src/main/Env.scala @@ -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) } diff --git a/modules/report/src/main/Report.scala b/modules/report/src/main/Report.scala index 22be396fb4..627fb657fa 100644 --- a/modules/report/src/main/Report.scala +++ b/modules/report/src/main/Report.scala @@ -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 { diff --git a/modules/report/src/main/ReportApi.scala b/modules/report/src/main/ReportApi.scala index ad8fe810e3..24cb483ec2 100644 --- a/modules/report/src/main/ReportApi.scala +++ b/modules/report/src/main/ReportApi.scala @@ -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) diff --git a/modules/user/src/main/Evaluator.scala b/modules/user/src/main/Evaluator.scala index 9186212062..a6cb21eea7 100644 --- a/modules/user/src/main/Evaluator.scala +++ b/modules/user/src/main/Evaluator.scala @@ -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 {