trigger auto-analysis on report

pull/3445/head
Thibault Duplessis 2017-08-08 18:35:16 -05:00
parent db71005bef
commit a7a67974b1
10 changed files with 77 additions and 26 deletions

View File

@ -571,6 +571,7 @@ fishnet {
client = fishnet_client
}
offline_mode = true # any client can provide moves and analysis
actor.name = fishnet
analysis.nodes = 4000000
move.plies = 300
client_min_version = "1.13.0"

View File

@ -152,6 +152,16 @@
</rollingPolicy>
</appender>
</logger>
<logger name="report" level="DEBUG">
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/var/log/lichess/report.log</file>
<encoder><pattern>%date %-5level %logger{30} %message%n%xException</pattern></encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>/var/log/lichess/report-log-%d{yyyy-MM-dd}.gz</fileNamePattern>
<maxHistory>7</maxHistory>
</rollingPolicy>
</appender>
</logger>
<!-- Set a specific actor to DEBUG -->
<!-- <logger name="actors.MyActor" level="DEBUG" /> -->

View File

@ -17,6 +17,7 @@ final class Env(
sink: lila.analyse.Analyser
) {
private val ActorName = config getString "actor.name"
private val OfflineMode = config getBoolean "offline_mode"
private val AnalysisNodes = config getInt "analysis.nodes"
private val MovePlies = config getInt "move.plies"
@ -105,7 +106,7 @@ final class Env(
case lila.hub.actorApi.fishnet.AutoAnalyse(gameId) =>
analyser(gameId, Work.Sender(userId = none, ip = none, mod = false, system = true))
}
}))
}), name = ActorName)
def cli = new lila.common.Cli {
def process = {

View File

@ -600,11 +600,6 @@ object Game {
chess.variant.Antichess
)
val visualisableVariants: Set[Variant] = Set(
chess.variant.Standard,
chess.variant.Chess960
)
val hordeWhitePawnsSince = new DateTime(2015, 4, 11, 10, 0)
def isOldHorde(game: Game) =

View File

@ -427,12 +427,11 @@ object GameRepo {
getOptionPgn(id) map (_ filter (_.nonEmpty))
def getOptionPgn(id: ID): Fu[Option[PgnMoves]] =
coll.find(
$id(id), $doc(
F.id -> false,
F.binaryPgn -> true
)
).uno[Bdoc] map { _ flatMap extractPgnMoves }
coll.primitiveOne[BSONBinary]($id(id), F.binaryPgn) map {
_ map { bin =>
BinaryFormat.pgn read { ByteArray.ByteArrayBSONHandler read bin }
}
}
def lastGameBetween(u1: String, u2: String, since: DateTime): Fu[Option[Game]] =
coll.uno[Game]($doc(
@ -440,16 +439,22 @@ object GameRepo {
F.createdAt $gt since
))
def getUserIds(id: ID): Fu[List[String]] =
coll.find(
$id(id), $doc(
F.id -> false,
F.playerUids -> true
)
).uno[Bdoc] map { ~_.flatMap(_.getAs[List[String]](F.playerUids)) }
def lastGamesBetween(u1: String, u2: String, since: DateTime, nb: Int): Fu[List[Game]] =
coll.find($doc(
F.playerUids $all List(u1, u2),
F.createdAt $gt since
)).list[Game](nb, ReadPreference.secondaryPreferred)
private def extractPgnMoves(doc: Bdoc) =
doc.getAs[BSONBinary](F.binaryPgn) map { bin =>
BinaryFormat.pgn read { ByteArray.ByteArrayBSONHandler read bin }
}
def getUserIds(id: ID): Fu[List[User.ID]] =
coll.primitiveOne[List[User.ID]]($id(id), F.playerUids) map (~_)
def recentAnalysableGamesByUserId(userId: User.ID, nb: Int) =
coll.find(
Query.finished
++ Query.rated
++ Query.user(userId)
++ Query.turnsMoreThan(20)
).sort(Query.sortCreated)
.cursor[Game](ReadPreference.secondaryPreferred)
.list(nb)
}

View File

@ -0,0 +1,29 @@
package lila.report
import org.joda.time.DateTime
import lila.game.{ Game, GameRepo }
final class AutoAnalysis(fishnet: akka.actor.ActorSelection) {
def apply(r: Report): Funit = r.isCheat ?? {
gamesToAnalyse(r) map { games =>
if (games.nonEmpty)
logger.info(s"Auto-analyse ${games.size} games after report ${r.createdBy} -> ${r.user}")
games foreach { game =>
lila.mon.cheat.autoAnalysis.reason("Report")()
fishnet ! lila.hub.actorApi.fishnet.AutoAnalyse(game.id)
}
}
}
private def gamesToAnalyse(r: Report): Fu[List[Game]] = {
GameRepo.recentAnalysableGamesByUserId(r.user, 10) |+|
GameRepo.lastGamesBetween(r.user, r.createdBy, DateTime.now.minusHours(2), 10)
}.map {
_.filter { g => g.analysable && !g.metadata.analysed }
.distinct
.sortBy(-_.createdAt.getSeconds)
.take(5)
}
}

View File

@ -19,8 +19,13 @@ final class Env(
lazy val forms = new DataForm(hub.actor.captcher)
private lazy val autoAnalysis = new AutoAnalysis(
fishnet = hub.actor.fishnet
)
lazy val api = new ReportApi(
reportColl,
autoAnalysis,
noteApi,
isOnline,
asyncCache,

View File

@ -11,6 +11,7 @@ import lila.user.{ User, UserRepo, NoteApi }
final class ReportApi(
val coll: Coll,
autoAnalysis: AutoAnalysis,
noteApi: NoteApi,
isOnline: User.ID => Boolean,
asyncCache: lila.memo.AsyncCache.Builder,
@ -36,7 +37,8 @@ final class ReportApi(
lila.mon.mod.report.create(report.reason.key)()
def insert = coll.insert(report).void >>-
def insert = coll.insert(report).void >>
autoAnalysis(report) >>-
bus.publish(lila.hub.actorApi.report.Created(reported.id, report.reason.key, by.id), 'report)
if (by.id == UserRepo.lichessId) coll.update(

View File

@ -1,3 +1,6 @@
package lila
package object report extends PackageObject with WithPlay
package object report extends PackageObject with WithPlay {
private[report] def logger = lila.log("report")
}

View File

@ -341,7 +341,7 @@ object ApplicationBuild extends Build {
play.api, play.test, reactivemongo.driver)
)
lazy val report = project("report", Seq(common, db, user)).settings(
lazy val report = project("report", Seq(common, db, user, game)).settings(
libraryDependencies ++= provided(
play.api, reactivemongo.driver)
)