trigger auto-analysis on report
parent
db71005bef
commit
a7a67974b1
|
@ -571,6 +571,7 @@ fishnet {
|
||||||
client = fishnet_client
|
client = fishnet_client
|
||||||
}
|
}
|
||||||
offline_mode = true # any client can provide moves and analysis
|
offline_mode = true # any client can provide moves and analysis
|
||||||
|
actor.name = fishnet
|
||||||
analysis.nodes = 4000000
|
analysis.nodes = 4000000
|
||||||
move.plies = 300
|
move.plies = 300
|
||||||
client_min_version = "1.13.0"
|
client_min_version = "1.13.0"
|
||||||
|
|
|
@ -152,6 +152,16 @@
|
||||||
</rollingPolicy>
|
</rollingPolicy>
|
||||||
</appender>
|
</appender>
|
||||||
</logger>
|
</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 -->
|
<!-- Set a specific actor to DEBUG -->
|
||||||
<!-- <logger name="actors.MyActor" level="DEBUG" /> -->
|
<!-- <logger name="actors.MyActor" level="DEBUG" /> -->
|
||||||
|
|
|
@ -17,6 +17,7 @@ final class Env(
|
||||||
sink: lila.analyse.Analyser
|
sink: lila.analyse.Analyser
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
private val ActorName = config getString "actor.name"
|
||||||
private val OfflineMode = config getBoolean "offline_mode"
|
private val OfflineMode = config getBoolean "offline_mode"
|
||||||
private val AnalysisNodes = config getInt "analysis.nodes"
|
private val AnalysisNodes = config getInt "analysis.nodes"
|
||||||
private val MovePlies = config getInt "move.plies"
|
private val MovePlies = config getInt "move.plies"
|
||||||
|
@ -105,7 +106,7 @@ final class Env(
|
||||||
case lila.hub.actorApi.fishnet.AutoAnalyse(gameId) =>
|
case lila.hub.actorApi.fishnet.AutoAnalyse(gameId) =>
|
||||||
analyser(gameId, Work.Sender(userId = none, ip = none, mod = false, system = true))
|
analyser(gameId, Work.Sender(userId = none, ip = none, mod = false, system = true))
|
||||||
}
|
}
|
||||||
}))
|
}), name = ActorName)
|
||||||
|
|
||||||
def cli = new lila.common.Cli {
|
def cli = new lila.common.Cli {
|
||||||
def process = {
|
def process = {
|
||||||
|
|
|
@ -600,11 +600,6 @@ object Game {
|
||||||
chess.variant.Antichess
|
chess.variant.Antichess
|
||||||
)
|
)
|
||||||
|
|
||||||
val visualisableVariants: Set[Variant] = Set(
|
|
||||||
chess.variant.Standard,
|
|
||||||
chess.variant.Chess960
|
|
||||||
)
|
|
||||||
|
|
||||||
val hordeWhitePawnsSince = new DateTime(2015, 4, 11, 10, 0)
|
val hordeWhitePawnsSince = new DateTime(2015, 4, 11, 10, 0)
|
||||||
|
|
||||||
def isOldHorde(game: Game) =
|
def isOldHorde(game: Game) =
|
||||||
|
|
|
@ -427,12 +427,11 @@ object GameRepo {
|
||||||
getOptionPgn(id) map (_ filter (_.nonEmpty))
|
getOptionPgn(id) map (_ filter (_.nonEmpty))
|
||||||
|
|
||||||
def getOptionPgn(id: ID): Fu[Option[PgnMoves]] =
|
def getOptionPgn(id: ID): Fu[Option[PgnMoves]] =
|
||||||
coll.find(
|
coll.primitiveOne[BSONBinary]($id(id), F.binaryPgn) map {
|
||||||
$id(id), $doc(
|
_ map { bin =>
|
||||||
F.id -> false,
|
BinaryFormat.pgn read { ByteArray.ByteArrayBSONHandler read bin }
|
||||||
F.binaryPgn -> true
|
}
|
||||||
)
|
}
|
||||||
).uno[Bdoc] map { _ flatMap extractPgnMoves }
|
|
||||||
|
|
||||||
def lastGameBetween(u1: String, u2: String, since: DateTime): Fu[Option[Game]] =
|
def lastGameBetween(u1: String, u2: String, since: DateTime): Fu[Option[Game]] =
|
||||||
coll.uno[Game]($doc(
|
coll.uno[Game]($doc(
|
||||||
|
@ -440,16 +439,22 @@ object GameRepo {
|
||||||
F.createdAt $gt since
|
F.createdAt $gt since
|
||||||
))
|
))
|
||||||
|
|
||||||
def getUserIds(id: ID): Fu[List[String]] =
|
def lastGamesBetween(u1: String, u2: String, since: DateTime, nb: Int): Fu[List[Game]] =
|
||||||
coll.find(
|
coll.find($doc(
|
||||||
$id(id), $doc(
|
F.playerUids $all List(u1, u2),
|
||||||
F.id -> false,
|
F.createdAt $gt since
|
||||||
F.playerUids -> true
|
)).list[Game](nb, ReadPreference.secondaryPreferred)
|
||||||
)
|
|
||||||
).uno[Bdoc] map { ~_.flatMap(_.getAs[List[String]](F.playerUids)) }
|
|
||||||
|
|
||||||
private def extractPgnMoves(doc: Bdoc) =
|
def getUserIds(id: ID): Fu[List[User.ID]] =
|
||||||
doc.getAs[BSONBinary](F.binaryPgn) map { bin =>
|
coll.primitiveOne[List[User.ID]]($id(id), F.playerUids) map (~_)
|
||||||
BinaryFormat.pgn read { ByteArray.ByteArrayBSONHandler read bin }
|
|
||||||
}
|
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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,8 +19,13 @@ final class Env(
|
||||||
|
|
||||||
lazy val forms = new DataForm(hub.actor.captcher)
|
lazy val forms = new DataForm(hub.actor.captcher)
|
||||||
|
|
||||||
|
private lazy val autoAnalysis = new AutoAnalysis(
|
||||||
|
fishnet = hub.actor.fishnet
|
||||||
|
)
|
||||||
|
|
||||||
lazy val api = new ReportApi(
|
lazy val api = new ReportApi(
|
||||||
reportColl,
|
reportColl,
|
||||||
|
autoAnalysis,
|
||||||
noteApi,
|
noteApi,
|
||||||
isOnline,
|
isOnline,
|
||||||
asyncCache,
|
asyncCache,
|
||||||
|
|
|
@ -11,6 +11,7 @@ import lila.user.{ User, UserRepo, NoteApi }
|
||||||
|
|
||||||
final class ReportApi(
|
final class ReportApi(
|
||||||
val coll: Coll,
|
val coll: Coll,
|
||||||
|
autoAnalysis: AutoAnalysis,
|
||||||
noteApi: NoteApi,
|
noteApi: NoteApi,
|
||||||
isOnline: User.ID => Boolean,
|
isOnline: User.ID => Boolean,
|
||||||
asyncCache: lila.memo.AsyncCache.Builder,
|
asyncCache: lila.memo.AsyncCache.Builder,
|
||||||
|
@ -36,7 +37,8 @@ final class ReportApi(
|
||||||
|
|
||||||
lila.mon.mod.report.create(report.reason.key)()
|
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)
|
bus.publish(lila.hub.actorApi.report.Created(reported.id, report.reason.key, by.id), 'report)
|
||||||
|
|
||||||
if (by.id == UserRepo.lichessId) coll.update(
|
if (by.id == UserRepo.lichessId) coll.update(
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
package lila
|
package lila
|
||||||
|
|
||||||
package object report extends PackageObject with WithPlay
|
package object report extends PackageObject with WithPlay {
|
||||||
|
|
||||||
|
private[report] def logger = lila.log("report")
|
||||||
|
}
|
||||||
|
|
|
@ -341,7 +341,7 @@ object ApplicationBuild extends Build {
|
||||||
play.api, play.test, reactivemongo.driver)
|
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(
|
libraryDependencies ++= provided(
|
||||||
play.api, reactivemongo.driver)
|
play.api, reactivemongo.driver)
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue