2015-04-25 12:48:13 -06:00
|
|
|
package lila.playban
|
|
|
|
|
|
|
|
import org.joda.time.DateTime
|
|
|
|
import reactivemongo.bson._
|
|
|
|
import reactivemongo.bson.Macros
|
|
|
|
import reactivemongo.core.commands._
|
|
|
|
import scala.concurrent.duration._
|
|
|
|
|
2015-04-25 15:06:44 -06:00
|
|
|
import chess.Color
|
2015-04-25 12:48:13 -06:00
|
|
|
import lila.db.BSON._
|
|
|
|
import lila.db.Types.Coll
|
2015-04-25 15:06:44 -06:00
|
|
|
import lila.game.{ Pov, Game, Player, Source }
|
2015-04-25 12:48:13 -06:00
|
|
|
|
|
|
|
final class PlaybanApi(coll: Coll) {
|
|
|
|
|
|
|
|
import lila.db.BSON.BSONJodaDateTimeHandler
|
|
|
|
import reactivemongo.bson.Macros
|
|
|
|
private implicit val OutcomeBSONHandler = new BSONHandler[BSONInteger, Outcome] {
|
|
|
|
def read(bsonInt: BSONInteger): Outcome = Outcome(bsonInt.value) err s"No such playban outcome: ${bsonInt.value}"
|
|
|
|
def write(x: Outcome) = BSONInteger(x.id)
|
|
|
|
}
|
2015-04-25 15:06:44 -06:00
|
|
|
private implicit val banBSONHandler = Macros.handler[TempBan]
|
2015-04-25 12:48:13 -06:00
|
|
|
private implicit val UserRecordBSONHandler = Macros.handler[UserRecord]
|
|
|
|
|
2015-04-25 15:06:44 -06:00
|
|
|
private case class Blame(player: Player, outcome: Outcome)
|
|
|
|
|
2015-04-25 16:08:07 -06:00
|
|
|
private def blameable(game: Game) = game.source == Some(Source.Lobby) && game.hasClock
|
2015-04-25 15:06:44 -06:00
|
|
|
|
|
|
|
def abort(pov: Pov): Funit = blameable(pov.game) ?? {
|
|
|
|
|
|
|
|
val blame =
|
|
|
|
if (pov.game olderThan 45) pov.game.playerWhoDidNotMove map { Blame(_, Outcome.NoPlay) }
|
|
|
|
else if (pov.game olderThan 15) none
|
|
|
|
else pov.player.some map { Blame(_, Outcome.Abort) }
|
|
|
|
|
|
|
|
blame match {
|
2015-04-25 16:08:07 -06:00
|
|
|
case None => pov.game.userIds.map(save(Outcome.Good)).sequenceFu.void
|
|
|
|
case Some(Blame(player, outcome)) => player.userId.??(save(outcome))
|
2015-04-25 15:06:44 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-25 16:11:06 -06:00
|
|
|
def currentBan(userId: String): Fu[Option[TempBan]] = fuccess(none)
|
|
|
|
// coll.find(
|
|
|
|
// BSONDocument("_id" -> userId, "b.0" -> BSONDocument("$exists" -> true)),
|
|
|
|
// BSONDocument("_id" -> false, "b" -> BSONDocument("$slice" -> -1))
|
|
|
|
// ).one[BSONDocument].map {
|
|
|
|
// _.flatMap(_.getAs[List[TempBan]]("b")).??(_.find(_.inEffect))
|
|
|
|
// }
|
2015-04-25 15:06:44 -06:00
|
|
|
|
|
|
|
def bans(userId: String): Fu[List[TempBan]] = coll.find(
|
|
|
|
BSONDocument("_id" -> userId, "b.0" -> BSONDocument("$exists" -> true)),
|
|
|
|
BSONDocument("_id" -> false, "b" -> true)
|
|
|
|
).one[BSONDocument].map {
|
|
|
|
~_.flatMap(_.getAs[List[TempBan]]("b"))
|
|
|
|
}
|
|
|
|
|
|
|
|
private def save(outcome: Outcome): String => Funit = userId => coll.db.command {
|
2015-04-25 12:48:13 -06:00
|
|
|
FindAndModify(
|
|
|
|
collection = coll.name,
|
|
|
|
query = BSONDocument("_id" -> userId),
|
|
|
|
modify = Update(
|
|
|
|
update = BSONDocument("$push" -> BSONDocument(
|
2015-04-25 15:06:44 -06:00
|
|
|
"o" -> BSONDocument(
|
2015-04-25 12:48:13 -06:00
|
|
|
"$each" -> List(outcome),
|
2015-04-25 15:06:44 -06:00
|
|
|
"$slice" -> -20)
|
2015-04-25 12:48:13 -06:00
|
|
|
)),
|
|
|
|
fetchNewObject = true),
|
|
|
|
upsert = true
|
|
|
|
)
|
|
|
|
} map2 UserRecordBSONHandler.read flatMap {
|
2015-04-25 15:06:44 -06:00
|
|
|
case None => fufail(s"can't find record for user $userId")
|
|
|
|
case Some(record) => legiferate(record)
|
2015-04-25 12:48:13 -06:00
|
|
|
} logFailure "PlaybanApi"
|
2015-04-25 15:06:44 -06:00
|
|
|
|
|
|
|
private def legiferate(record: UserRecord): Funit = record.newBan ?? { ban =>
|
|
|
|
loginfo(s"[playban] ban ${record.userId} for {$ban.mins} minutes")
|
|
|
|
coll.update(
|
|
|
|
BSONDocument("_id" -> record.userId),
|
|
|
|
BSONDocument(
|
|
|
|
"$unset" -> BSONDocument("o" -> true),
|
|
|
|
"$push" -> BSONDocument(
|
|
|
|
"b" -> BSONDocument(
|
|
|
|
"$each" -> List(ban),
|
|
|
|
"$slice" -> -30)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
).void
|
|
|
|
}
|
2015-04-25 12:48:13 -06:00
|
|
|
}
|