lila/app/controllers/Setup.scala

215 lines
6.8 KiB
Scala
Raw Normal View History

2013-05-08 20:00:13 -06:00
package controllers
import play.api.data.Form
2014-11-10 15:00:34 -07:00
import play.api.libs.json.Json
2015-01-18 10:59:20 -07:00
import play.api.mvc.{ Result, Results, Call, RequestHeader, Accepting }
import lila.api.{ Context, BodyContext }
2013-05-08 20:00:13 -06:00
import lila.app._
import lila.common.{ HTTPRequest, LilaCookie }
import lila.game.{ GameRepo, Pov, AnonCookie }
2013-06-05 02:08:22 -06:00
import lila.user.UserRepo
2013-05-08 20:00:13 -06:00
import views._
2014-05-09 12:01:33 -06:00
object Setup extends LilaController with TheftPrevention with play.api.http.ContentTypes {
2013-05-08 20:00:13 -06:00
private def env = Env.setup
2014-02-17 02:12:19 -07:00
def aiForm = Open { implicit ctx =>
if (HTTPRequest isXhr ctx.req)
2014-04-18 02:46:31 -06:00
env.forms aiFilled get("fen") map { form =>
2014-05-09 12:01:33 -06:00
html.setup.ai(form, Env.ai.aiPerfApi.intRatings)
2014-02-27 17:18:22 -07:00
}
else fuccess {
Redirect(routes.Lobby.home + "#ai")
}
2013-05-08 20:00:13 -06:00
}
2014-02-17 02:12:19 -07:00
def ai = process(env.forms.ai) { config =>
implicit ctx =>
env.processor ai config map { pov =>
pov -> routes.Round.player(pov.fullId)
2013-05-08 20:00:13 -06:00
}
}
2014-05-24 10:43:09 -06:00
def friendForm(userId: Option[String]) = Open { implicit ctx =>
if (HTTPRequest isXhr ctx.req) userId ?? UserRepo.named flatMap {
2014-05-14 02:44:17 -06:00
case None => env.forms friendFilled get("fen") map {
html.setup.friend(_, none, none)
}
case Some(user) => challenge(user) flatMap { error =>
env.forms friendFilled get("fen") map {
2014-05-25 06:37:25 -06:00
html.setup.friend(_, user.some, error)
2013-06-05 06:10:01 -06:00
}
}
}
else fuccess {
Redirect(routes.Lobby.home + "#friend")
2013-06-05 05:55:16 -06:00
}
2013-05-08 20:00:13 -06:00
}
private def challenge(user: lila.user.User)(implicit ctx: Context): Fu[Option[String]] = ctx.me match {
2014-05-14 02:44:17 -06:00
case None => fuccess("Only registered players can send challenges.".some)
2014-02-17 02:12:19 -07:00
case Some(me) => Env.relation.api.blocks(user.id, me.id) flatMap {
2014-05-14 02:44:17 -06:00
case true => fuccess(s"{{user}} doesn't accept challenges from you.".some)
case false => Env.pref.api getPref user zip Env.relation.api.follows(user.id, me.id) map {
case (pref, follow) => lila.pref.Pref.Challenge.block(me, user, pref.challenge, follow)
}
}
}
2014-05-24 10:43:09 -06:00
def friend(userId: Option[String]) = process(env.forms.friend) { config =>
2014-02-17 02:12:19 -07:00
implicit ctx =>
env.processor friend config map { pov =>
2014-05-24 10:43:09 -06:00
pov -> routes.Setup.await(pov.fullId, userId)
2013-05-08 20:00:13 -06:00
}
}
2014-02-17 02:12:19 -07:00
def decline(gameId: String) = Auth { implicit ctx =>
me =>
OptionResult(GameRepo game gameId) { game =>
if (game.started) BadRequest("Cannot decline started challenge")
else {
GameRepo remove game.id
Env.hub.actor.challenger ! lila.hub.actorApi.setup.DeclineChallenge(gameId)
Ok("ok")
}
2013-06-05 06:54:33 -06:00
}
}
2014-02-17 02:12:19 -07:00
def hookForm = Open { implicit ctx =>
if (HTTPRequest isXhr ctx.req)
env.forms.hookFilled map { html.setup.hook(_) }
else fuccess {
Redirect(routes.Lobby.home + "#hook")
}
2013-05-08 20:00:13 -06:00
}
2014-02-17 02:12:19 -07:00
def hook(uid: String) = OpenBody { implicit ctx =>
2013-05-18 21:31:06 -06:00
implicit val req = ctx.body
env.forms.hook(ctx).bindFromRequest.fold(
err => negotiate(
2014-11-30 04:30:39 -07:00
html = BadRequest(err.errorsAsJson.toString).fuccess,
api = _ => BadRequest(err.errorsAsJson).fuccess),
2014-11-10 15:00:34 -07:00
config => (ctx.userId ?? Env.relation.api.blocking) flatMap { blocking =>
JsonOk {
env.processor.hook(config, uid, lila.common.HTTPRequest sid req, blocking) map { hookId =>
Json.obj(
"ok" -> true,
"hook" -> Json.obj(
"id" -> hookId))
}
2014-11-10 15:00:34 -07:00
}
}
)
2013-05-08 20:00:13 -06:00
}
2014-02-17 02:12:19 -07:00
def filterForm = Open { implicit ctx =>
2013-07-26 06:53:04 -06:00
env.forms.filterFilled map {
2014-02-17 02:12:19 -07:00
case (form, filter) => html.setup.filter(form, filter)
2013-07-26 06:53:04 -06:00
}
2013-05-08 20:00:13 -06:00
}
2014-02-17 02:12:19 -07:00
def filter = OpenBody { implicit ctx =>
2013-05-08 20:00:13 -06:00
implicit val req = ctx.body
env.forms.filter(ctx).bindFromRequest.fold[Fu[Result]](
f => fulogwarn(f.errors.toString) inject BadRequest(()),
2014-02-17 02:12:19 -07:00
config => JsonOk(env.processor filter config inject config.render)
2013-05-08 20:00:13 -06:00
)
}
2014-02-17 02:12:19 -07:00
def join(id: String) = Open { implicit ctx =>
OptionFuResult(GameRepo game id) { game =>
2013-05-08 20:00:13 -06:00
env.friendJoiner(game, ctx.me).fold(
2015-01-18 10:59:20 -07:00
err => negotiate(
html = fuccess {
Redirect(routes.Round.watcher(id, "white"))
},
api = _ => fuccess {
BadRequest(Json.obj("error" -> err.toString)) as JSON
}
),
_ flatMap {
2014-02-17 02:12:19 -07:00
case (p, events) => {
2014-06-03 02:26:54 -06:00
Env.hub.socket.round ! lila.hub.actorApi.map.Tell(p.gameId, lila.round.actorApi.EventList(events))
2015-01-18 10:59:20 -07:00
negotiate(
html = fuccess {
implicit val req = ctx.req
redirectPov(p, routes.Round.player(p.fullId))
},
api = apiVersion => Env.api.roundApi.player(p, apiVersion, otherPovs = Nil) map { data =>
Created(data) as JSON
})
2013-05-08 20:00:13 -06:00
}
})
}
}
2014-05-24 10:43:09 -06:00
def await(fullId: String, userId: Option[String]) = Open { implicit ctx =>
2014-02-17 02:12:19 -07:00
OptionFuResult(GameRepo pov fullId) { pov =>
2013-05-08 20:00:13 -06:00
pov.game.started.fold(
Redirect(routes.Round.player(pov.fullId)).fuccess,
Env.api.roundApi.player(pov, lila.api.Mobile.Api.currentVersion, otherPovs = Nil) zip
2014-05-24 10:43:09 -06:00
(userId ?? UserRepo.named) flatMap {
case (data, user) => PreventTheft(pov) {
2013-06-05 05:55:16 -06:00
Ok(html.setup.await(
pov,
data,
2013-06-05 05:55:16 -06:00
env.friendConfigMemo get pov.game.id,
user)).fuccess
}
2013-05-08 20:00:13 -06:00
}
)
}
}
2014-02-17 02:12:19 -07:00
def cancel(fullId: String) = Open { implicit ctx =>
OptionResult(GameRepo pov fullId) { pov =>
if (pov.game.started) Redirect(routes.Round.player(pov.fullId))
else {
GameRepo remove pov.game.id
Redirect(routes.Lobby.home)
}
2013-05-08 20:00:13 -06:00
}
}
2014-02-17 02:12:19 -07:00
def validateFen = Open { implicit ctx =>
2013-05-08 20:00:13 -06:00
{
for {
fen get("fen")
parsed chess.format.Forsyth <<< fen
strict = get("strict").isDefined
if (parsed.situation playable strict)
validated = chess.format.Forsyth >> parsed
} yield html.game.miniBoard(validated, parsed.situation.color.name)
}.fold[Result](BadRequest)(Ok(_)).fuccess
2013-05-08 20:00:13 -06:00
}
2014-02-17 02:12:19 -07:00
private def process[A](form: Context => Form[A])(op: A => BodyContext => Fu[(Pov, Call)]) =
OpenBody { implicit ctx =>
2013-05-08 20:00:13 -06:00
implicit val req = ctx.body
form(ctx).bindFromRequest.fold(
2014-05-09 12:01:33 -06:00
f => negotiate(
2014-12-01 17:10:23 -07:00
html = Lobby.renderHome(Results.BadRequest),
2014-05-11 15:26:11 -06:00
api = _ => fuccess(BadRequest(f.errorsAsJson))
2014-05-09 12:01:33 -06:00
),
config => op(config)(ctx) flatMap {
case (pov, call) => negotiate(
html = fuccess(redirectPov(pov, call)),
api = apiVersion => Env.api.roundApi.player(pov, apiVersion, otherPovs = Nil) map { data =>
2014-10-01 16:19:49 -06:00
Created(data) as JSON
}
2014-05-09 12:01:33 -06:00
)
}
)
2013-05-08 20:00:13 -06:00
}
private def redirectPov(pov: Pov, call: Call)(implicit ctx: Context, req: RequestHeader) =
if (ctx.isAuth) Redirect(call)
else Redirect(call) withCookies LilaCookie.cookie(
AnonCookie.name,
pov.playerId,
maxAge = AnonCookie.maxAge.some,
httpOnly = false.some)
2013-05-08 20:00:13 -06:00
}