diff --git a/app/controllers/Mod.scala b/app/controllers/Mod.scala index 4076a86f1f..3f4b471586 100644 --- a/app/controllers/Mod.scala +++ b/app/controllers/Mod.scala @@ -96,9 +96,11 @@ object Mod extends LilaController { def assessment(username: String) = Open { implicit ctx => ModExternalBot { OptionFuResult(UserRepo named username) { user => - Env.mod.jsonView(user) map { - case None => NotFound - case Some(data) => Ok(data) + Env.mod.jsonView(user) flatMap { + case None => NotFound.fuccess + case Some(data) => Env.mod.userHistory(user) map { history => + Ok(data + ("history" -> history)) + } } map (_ as JSON) } } diff --git a/modules/mod/src/main/Env.scala b/modules/mod/src/main/Env.scala index 578f2ef62b..e14258e997 100644 --- a/modules/mod/src/main/Env.scala +++ b/modules/mod/src/main/Env.scala @@ -13,7 +13,7 @@ final class Env( system: ActorSystem, scheduler: lila.common.Scheduler, firewall: Firewall, - reportColl: Coll, + reportApi: lila.report.ReportApi, lightUserApi: lila.user.LightUserApi, userSpy: String => Fu[UserSpy], securityApi: lila.security.Api, @@ -42,7 +42,7 @@ final class Env( lazy val logApi = new ModlogApi(logColl) - private lazy val notifier = new ModNotifier(notifyApi, reportColl) + private lazy val notifier = new ModNotifier(notifyApi, reportApi) private lazy val ratingRefund = new RatingRefund( scheduler = scheduler, @@ -77,7 +77,7 @@ final class Env( lazy val gamify = new Gamify( logColl = logColl, - reportColl = reportColl, + reportApi = reportApi, historyColl = db(CollectionGamingHistory)) lazy val publicChat = new PublicChat(chatApi, tournamentApi, simulEnv) @@ -89,6 +89,10 @@ final class Env( lazy val jsonView = new JsonView( assessApi = assessApi) + lazy val userHistory = new UserHistory( + logApi = logApi, + reportApi = reportApi) + // api actor system.lilaBus.subscribe(system.actorOf(Props(new Actor { def receive = { @@ -114,7 +118,7 @@ object Env { system = lila.common.PlayApp.system, scheduler = lila.common.PlayApp.scheduler, firewall = lila.security.Env.current.firewall, - reportColl = lila.report.Env.current.reportColl, + reportApi = lila.report.Env.current.api, userSpy = lila.security.Env.current.userSpy, lightUserApi = lila.user.Env.current.lightUserApi, securityApi = lila.security.Env.current.api, diff --git a/modules/mod/src/main/Gamify.scala b/modules/mod/src/main/Gamify.scala index 143a9baf1c..c002a75731 100644 --- a/modules/mod/src/main/Gamify.scala +++ b/modules/mod/src/main/Gamify.scala @@ -11,7 +11,7 @@ import lila.memo.AsyncCache final class Gamify( logColl: Coll, - reportColl: Coll, + reportApi: lila.report.ReportApi, historyColl: Coll) { import Gamify._ @@ -90,7 +90,7 @@ final class Gamify( } private def reportLeaderboard(after: DateTime, before: Option[DateTime]): Fu[List[ModCount]] = - reportColl.aggregate( + reportApi.coll.aggregate( Match($doc( "createdAt" -> dateRange(after, before), "processedBy" -> notLichess diff --git a/modules/mod/src/main/JsonView.scala b/modules/mod/src/main/JsonView.scala index a95f33f3d5..5a0951cab0 100644 --- a/modules/mod/src/main/JsonView.scala +++ b/modules/mod/src/main/JsonView.scala @@ -53,3 +53,8 @@ final class JsonView(assessApi: AssessApi) { ).noNull } } + +object JsonView { + + private[mod] implicit val modlogWrites: Writes[Modlog] = Json.writes[Modlog] +} diff --git a/modules/mod/src/main/ModNotifier.scala b/modules/mod/src/main/ModNotifier.scala index 02f3dd2158..d448580001 100644 --- a/modules/mod/src/main/ModNotifier.scala +++ b/modules/mod/src/main/ModNotifier.scala @@ -1,21 +1,14 @@ package lila.mod -import org.joda.time.DateTime - -import lila.db.dsl._ import lila.notify.{ Notification, NotifyApi } import lila.user.User private final class ModNotifier( notifyApi: NotifyApi, - reportColl: Coll) { + reportApi: lila.report.ReportApi) { def reporters(user: User): Funit = - reportColl.distinct[String, List]("createdBy", $doc( - "user" -> user.id, - "createdAt" -> $gt(DateTime.now minusDays 3), - "createdBy" -> $ne("lichess") - ).some) flatMap { + reportApi.recentReportersOf(user) flatMap { _.map { reporterId => notifyApi.addNotification(Notification.make( notifies = Notification.Notifies(reporterId), diff --git a/modules/mod/src/main/ModlogApi.scala b/modules/mod/src/main/ModlogApi.scala index fbeae27fe9..7bc03aa048 100644 --- a/modules/mod/src/main/ModlogApi.scala +++ b/modules/mod/src/main/ModlogApi.scala @@ -103,7 +103,7 @@ final class ModlogApi(coll: Coll) { )) def userHistory(userId: String): Fu[List[Modlog]] = - coll.find($doc("user" -> userId)).sort($sort desc "date").cursor[Modlog]().gather[List](100) + coll.find($doc("user" -> userId)).sort($sort desc "date").cursor[Modlog]().gather[List](30) private def add(m: Modlog): Funit = { lila.mon.mod.log.create() diff --git a/modules/mod/src/main/UserHistory.scala b/modules/mod/src/main/UserHistory.scala new file mode 100644 index 0000000000..e607fe6ec8 --- /dev/null +++ b/modules/mod/src/main/UserHistory.scala @@ -0,0 +1,35 @@ +package lila.mod + +import play.api.libs.json._ + +import lila.report.Report +import lila.user.User + +final class UserHistory( + logApi: ModlogApi, + reportApi: lila.report.ReportApi) { + + import JsonView.modlogWrites + import lila.report.JsonView.reportWrites + + def apply(user: User): Fu[JsArray] = for { + logs <- logApi.userHistory(user.id) + reports <- reportApi.recent(user, 15) + } yield { + val all: List[Either[Modlog, Report]] = logs.map(Left.apply) ::: reports.map(Right.apply) + val sorted = all.sortBy { + case Left(log) => -log.date.getMillis + case Right(rep) => -rep.createdAt.getMillis + } + JsArray { + sorted map { + case Left(log) => Json.obj( + "type" -> "modAction", + "data" -> (modlogWrites writes log)) + case Right(rep) => Json.obj( + "type" -> "report", + "data" -> (reportWrites writes rep)) + } + } + } +} diff --git a/modules/report/src/main/JsonView.scala b/modules/report/src/main/JsonView.scala new file mode 100644 index 0000000000..3148d37a3e --- /dev/null +++ b/modules/report/src/main/JsonView.scala @@ -0,0 +1,8 @@ +package lila.report + +import play.api.libs.json._ + +object JsonView { + + implicit val reportWrites: Writes[Report] = Json.writes[Report] +} diff --git a/modules/report/src/main/ReportApi.scala b/modules/report/src/main/ReportApi.scala index ffd0df6ce3..a1dc67430f 100644 --- a/modules/report/src/main/ReportApi.scala +++ b/modules/report/src/main/ReportApi.scala @@ -6,8 +6,8 @@ import org.joda.time.DateTime import lila.db.dsl._ import lila.user.{ User, UserRepo, NoteApi } -private[report] final class ReportApi( - coll: Coll, +final class ReportApi( + val coll: Coll, noteApi: NoteApi, isOnline: User.ID => Boolean) { @@ -153,8 +153,18 @@ private[report] final class ReportApi( def nbUnprocessed = coll.countSel(unprocessedSelect) - def recent(nb: Int) = - coll.find($empty).sort($sort.createdDesc).cursor[Report]().gather[List](nb) + def recent(nb: Int): Fu[List[Report]] = + coll.find($empty).sort($sort.createdDesc).list[Report](nb) + + def recent(user: User, nb: Int): Fu[List[Report]] = + coll.find($doc("user" -> user.id)).sort($sort.createdDesc).list[Report](nb) + + def recentReportersOf(user: User): Fu[List[User.ID]] = + coll.distinct[String, List]("createdBy", $doc( + "user" -> user.id, + "createdAt" -> $gt(DateTime.now minusDays 3), + "createdBy" -> $ne("lichess") + ).some) def unprocessedAndRecent(nb: Int): Fu[List[Report.WithUserAndNotes]] = recentUnprocessed(nb * 2) |+| recentProcessed(nb) flatMap { all =>