lila/app/controllers/Game.scala

149 lines
5.7 KiB
Scala
Raw Normal View History

2013-05-06 19:57:42 -06:00
package controllers
2018-03-07 17:20:00 -07:00
import org.joda.time.DateTime
import org.joda.time.format.DateTimeFormat
import play.api.mvc._
2018-03-07 16:55:02 -07:00
2018-05-06 16:40:17 -06:00
import lila.api.GameApiV2
2013-05-06 19:57:42 -06:00
import lila.app._
2019-12-04 16:39:16 -07:00
import lila.common.config.MaxPerSecond
import lila.common.HTTPRequest
import lila.game.{ Game => GameModel }
2013-05-06 19:57:42 -06:00
2019-12-04 16:39:16 -07:00
final class Game(
env: Env,
apiC: Api
) extends LilaController(env) {
2013-05-06 19:57:42 -06:00
2017-01-25 09:45:00 -07:00
def delete(gameId: String) = Auth { implicit ctx => me =>
2019-12-04 16:39:16 -07:00
OptionFuResult(env.game.gameRepo game gameId) { game =>
2017-01-25 09:45:00 -07:00
if (game.pgnImport.flatMap(_.user) ?? (me.id==)) {
2019-12-04 16:39:16 -07:00
env.hub.bookmark ! lila.hub.actorApi.bookmark.Remove(game.id)
(env.game.gameRepo remove game.id) >>
(env.analyse.analysisRepo remove game.id) >>
env.game.cached.clearNbImportedByCache(me.id) inject
2017-01-25 09:45:00 -07:00
Redirect(routes.User.show(me.username))
} else fuccess {
2017-01-25 09:45:00 -07:00
Redirect(routes.Round.watcher(game.id, game.firstColor.name))
}
}
}
2018-05-06 18:10:47 -06:00
def exportOne(id: String) = Open { implicit ctx =>
2019-12-04 16:39:16 -07:00
OptionFuResult(env.game.gameRepo game id) { game =>
if (game.playable) BadRequest("Only bots can access their games in progress. See https://lichess.org/api#tag/Chess-Bot").fuccess
2018-05-06 18:10:47 -06:00
else {
val config = GameApiV2.OneConfig(
format = if (HTTPRequest acceptsJson ctx.req) GameApiV2.Format.JSON else GameApiV2.Format.PGN,
imported = getBool("imported"),
2018-05-06 18:17:23 -06:00
flags = requestPgnFlags(ctx.req, extended = true)
2018-05-06 18:10:47 -06:00
)
lila.mon.export.pgn.game()
2019-12-04 16:39:16 -07:00
env.api.gameApiV2.exportOne(game, config) flatMap { content =>
env.api.gameApiV2.filename(game, config.format) map { filename =>
2018-05-06 18:10:47 -06:00
Ok(content).withHeaders(
CONTENT_TYPE -> gameContentType(config),
CONTENT_DISPOSITION -> s"attachment; filename=$filename"
)
}
}
}
}
}
def exportByUser(username: String) = OpenOrScoped()(
open = ctx => handleExport(username, ctx.me, ctx.req, oauth = false),
scoped = req => me => handleExport(username, me.some, req, oauth = true)
)
2018-03-07 16:50:59 -07:00
def apiExportByUser(username: String) = AnonOrScoped()(
anon = req => handleExport(username, none, req, oauth = false),
scoped = req => me => handleExport(username, me.some, req, oauth = true)
)
private def handleExport(username: String, me: Option[lila.user.User], req: RequestHeader, oauth: Boolean) =
2019-12-04 18:47:46 -07:00
env.user.repo named username flatMap {
_ ?? { user =>
2019-12-04 16:39:16 -07:00
apiC.GlobalLinearLimitPerIP(HTTPRequest lastRemoteAddress req) {
apiC.GlobalLinearLimitPerUserOption(me) {
2018-05-08 20:38:45 -06:00
val format = GameApiV2.Format byRequest req
WithVs(req) { vs =>
val config = GameApiV2.ByUserConfig(
user = user,
format = format,
vs = vs,
since = getLong("since", req) map { new DateTime(_) },
until = getLong("until", req) map { new DateTime(_) },
2018-05-08 20:38:45 -06:00
max = getInt("max", req) map (_ atLeast 1),
rated = getBoolOpt("rated", req),
perfType = ~get("perfType", req) split "," flatMap { lila.rating.PerfType(_) } toSet,
color = get("color", req) flatMap chess.Color.apply,
analysed = getBoolOpt("analysed", req),
ongoing = getBool("ongoing", req),
2018-05-09 11:16:47 -06:00
flags = requestPgnFlags(req, extended = false).copy(
literate = false
),
2018-05-08 20:38:45 -06:00
perSecond = MaxPerSecond(me match {
case Some(m) if m is user.id => 50
case Some(_) if oauth => 20 // bonus for oauth logged in only (not for XSRF)
case _ => 10
})
)
2018-05-09 11:16:47 -06:00
val date = DateTimeFormat forPattern "yyyy-MM-dd" print new DateTime
2019-12-04 16:39:16 -07:00
Ok.chunked(env.api.gameApiV2.exportByUser(config)).withHeaders(
noProxyBufferHeader,
2018-05-08 20:38:45 -06:00
CONTENT_TYPE -> gameContentType(config),
CONTENT_DISPOSITION -> s"attachment; filename=lichess_${user.username}_$date.${format.toString.toLowerCase}"
).fuccess
2018-04-09 18:06:35 -06:00
}
}
}
}
}
2018-03-07 16:50:59 -07:00
def exportByIds = Action.async(parse.tolerantText) { req =>
2019-12-04 16:39:16 -07:00
apiC.GlobalLinearLimitPerIP(HTTPRequest lastRemoteAddress req) {
2018-05-08 20:38:45 -06:00
val config = GameApiV2.ByIdsConfig(
2019-12-05 08:46:00 -07:00
ids = req.body.split(',').view.take(300).toSeq,
2018-05-08 20:38:45 -06:00
format = GameApiV2.Format byRequest req,
flags = requestPgnFlags(req, extended = false),
perSecond = MaxPerSecond(20)
)
2019-12-04 16:39:16 -07:00
Ok.chunked(env.api.gameApiV2.exportByIds(config)).withHeaders(
noProxyBufferHeader,
2018-05-08 20:38:45 -06:00
CONTENT_TYPE -> gameContentType(config)
).fuccess
}
}
private def WithVs(req: RequestHeader)(f: Option[lila.user.User] => Fu[Result]): Fu[Result] =
get("vs", req) match {
case None => f(none)
2019-12-04 18:47:46 -07:00
case Some(name) => env.user.repo named name flatMap {
case None => notFoundJson(s"No such opponent: $name")
case Some(user) => f(user.some)
}
}
private[controllers] def requestPgnFlags(req: RequestHeader, extended: Boolean) =
2018-05-06 18:10:47 -06:00
lila.game.PgnDump.WithFlags(
moves = getBoolOpt("moves", req) | true,
tags = getBoolOpt("tags", req) | true,
2018-05-06 18:17:23 -06:00
clocks = getBoolOpt("clocks", req) | extended,
evals = getBoolOpt("evals", req) | extended,
2018-05-09 11:16:47 -06:00
opening = getBoolOpt("opening", req) | extended,
literate = getBoolOpt("literate", req) | false
2018-05-06 18:10:47 -06:00
)
private[controllers] def gameContentType(config: GameApiV2.Config) = config.format match {
2018-05-06 18:10:47 -06:00
case GameApiV2.Format.PGN => pgnContentType
case GameApiV2.Format.JSON => config match {
case _: GameApiV2.OneConfig => JSON
case _ => ndJsonContentType
2018-05-06 18:10:47 -06:00
}
}
2017-01-25 09:45:00 -07:00
private[controllers] def preloadUsers(game: GameModel): Funit =
2019-12-04 16:39:16 -07:00
env.user.lightUserApi preloadMany game.userIds
2013-05-06 19:57:42 -06:00
}