2013-05-08 20:00:13 -06:00
|
|
|
package controllers
|
|
|
|
|
2013-09-26 10:18:07 -06:00
|
|
|
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 }
|
2013-09-26 10:18:07 -06:00
|
|
|
|
2014-02-12 16:23:18 -07:00
|
|
|
import lila.api.{ Context, BodyContext }
|
2013-05-08 20:00:13 -06:00
|
|
|
import lila.app._
|
2014-02-12 16:23:18 -07:00
|
|
|
import lila.common.{ HTTPRequest, LilaCookie }
|
|
|
|
import lila.game.{ GameRepo, Pov, AnonCookie }
|
2015-06-20 09:00:40 -06:00
|
|
|
import lila.setup.{ HookConfig, ValidFen }
|
2015-03-17 10:23:04 -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 =>
|
2015-06-20 09:00:40 -06:00
|
|
|
if (HTTPRequest isXhr ctx.req) {
|
2014-04-18 02:46:31 -06:00
|
|
|
env.forms aiFilled get("fen") map { form =>
|
2015-06-20 09:00:40 -06:00
|
|
|
html.setup.ai(
|
|
|
|
form,
|
|
|
|
Env.ai.aiPerfApi.intRatings,
|
|
|
|
form("fen").value flatMap ValidFen(getBool("strict")))
|
2014-02-27 17:18:22 -07:00
|
|
|
}
|
2015-06-20 09:00:40 -06:00
|
|
|
}
|
2013-12-13 16:52:40 -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 =>
|
2014-02-12 16:23:18 -07:00
|
|
|
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 =>
|
2015-06-20 09:00:40 -06:00
|
|
|
if (HTTPRequest isXhr ctx.req) {
|
|
|
|
env.forms friendFilled get("fen") flatMap { form =>
|
|
|
|
val validFen = form("fen").value flatMap ValidFen(false)
|
|
|
|
userId ?? UserRepo.named flatMap {
|
|
|
|
case None => fuccess(html.setup.friend(form, none, none, validFen))
|
|
|
|
case Some(user) => challenge(user) map { error =>
|
|
|
|
html.setup.friend(form, user.some, error, validFen)
|
|
|
|
}
|
2013-06-05 06:10:01 -06:00
|
|
|
}
|
|
|
|
}
|
2013-12-21 14:13:00 -07:00
|
|
|
}
|
2013-12-13 16:52:40 -07:00
|
|
|
else fuccess {
|
|
|
|
Redirect(routes.Lobby.home + "#friend")
|
2013-06-05 05:55:16 -06:00
|
|
|
}
|
2013-05-08 20:00:13 -06:00
|
|
|
}
|
|
|
|
|
2013-12-21 14:13:00 -07: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)
|
2013-12-21 14:13:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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 =>
|
2013-09-26 10:18:07 -06:00
|
|
|
if (game.started) BadRequest("Cannot decline started challenge")
|
|
|
|
else {
|
2014-11-30 07:53:39 -07:00
|
|
|
GameRepo remove game.id
|
2013-09-26 10:18:07 -06:00
|
|
|
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 =>
|
2015-04-26 04:08:13 -06:00
|
|
|
if (HTTPRequest isXhr ctx.req) NoPlayban {
|
2015-03-26 15:22:14 -06:00
|
|
|
env.forms.hookFilled(timeModeString = get("time")) map { html.setup.hook(_) }
|
2015-04-26 04:08:13 -06:00
|
|
|
}
|
2013-12-13 16:52:40 -07:00
|
|
|
else fuccess {
|
|
|
|
Redirect(routes.Lobby.home + "#hook")
|
|
|
|
}
|
2013-05-08 20:00:13 -06:00
|
|
|
}
|
|
|
|
|
2015-03-16 01:49:02 -06:00
|
|
|
// if request comes from mobile
|
|
|
|
// and the hook is casual,
|
|
|
|
// reuse the saved "membersOnly" value
|
|
|
|
// from the site preferred hook setup
|
|
|
|
private def mobileHookAllowAnon(config: HookConfig)(implicit ctx: Context): Fu[HookConfig] =
|
|
|
|
if (lila.api.Mobile.Api requested ctx.req)
|
|
|
|
env.forms.hookConfig map { saved =>
|
|
|
|
config.copy(allowAnon = saved.allowAnon)
|
|
|
|
}
|
|
|
|
else fuccess(config)
|
|
|
|
|
2015-04-22 03:47:55 -06:00
|
|
|
private def hookResponse(hookId: String) =
|
|
|
|
Ok(Json.obj(
|
|
|
|
"ok" -> true,
|
|
|
|
"hook" -> Json.obj("id" -> hookId))) as JSON
|
|
|
|
|
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
|
2015-04-26 04:08:13 -06:00
|
|
|
NoPlayban {
|
|
|
|
env.forms.hook(ctx).bindFromRequest.fold(
|
|
|
|
err => negotiate(
|
|
|
|
html = BadRequest(err.errorsAsJson.toString).fuccess,
|
|
|
|
api = _ => BadRequest(err.errorsAsJson).fuccess),
|
|
|
|
preConfig => (ctx.userId ?? Env.relation.api.blocking) zip
|
|
|
|
mobileHookAllowAnon(preConfig) flatMap {
|
|
|
|
case (blocking, config) =>
|
|
|
|
env.processor.hook(config, uid, HTTPRequest sid req, blocking) map hookResponse recover {
|
|
|
|
case e: IllegalArgumentException => BadRequest(Json.obj("error" -> e.getMessage)) as JSON
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
2013-05-08 20:00:13 -06:00
|
|
|
}
|
|
|
|
|
2015-04-22 03:47:55 -06:00
|
|
|
def like(uid: String, gameId: String) = Open { implicit ctx =>
|
2015-04-26 04:08:13 -06:00
|
|
|
NoPlayban {
|
|
|
|
env.forms.hookConfig flatMap { config =>
|
|
|
|
GameRepo game gameId map {
|
|
|
|
_.fold(config)(config.updateFrom)
|
|
|
|
} flatMap { config =>
|
|
|
|
(ctx.userId ?? Env.relation.api.blocking) flatMap { blocking =>
|
|
|
|
env.processor.hook(config, uid, HTTPRequest sid ctx.req, blocking) map hookResponse recover {
|
|
|
|
case e: IllegalArgumentException => BadRequest(Json.obj("error" -> e.getMessage)) as JSON
|
|
|
|
}
|
2015-04-21 15:09:10 -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
|
2014-06-01 17:01:39 -06:00
|
|
|
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))
|
|
|
|
},
|
2015-04-04 04:42:14 -06:00
|
|
|
api = apiVersion => Env.api.roundApi.player(p, apiVersion) map { data =>
|
2015-01-18 10:59:20 -07:00
|
|
|
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,
|
2015-04-04 04:42:14 -06:00
|
|
|
Env.api.roundApi.player(pov, lila.api.Mobile.Api.currentVersion) zip
|
2014-05-24 10:43:09 -06:00
|
|
|
(userId ?? UserRepo.named) flatMap {
|
2014-10-12 16:17:24 -06:00
|
|
|
case (data, user) => PreventTheft(pov) {
|
2013-06-05 05:55:16 -06:00
|
|
|
Ok(html.setup.await(
|
|
|
|
pov,
|
2014-10-12 16:17:24 -06:00
|
|
|
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 =>
|
2013-09-26 10:18:07 -06:00
|
|
|
if (pov.game.started) Redirect(routes.Round.player(pov.fullId))
|
|
|
|
else {
|
2014-11-30 07:53:39 -07:00
|
|
|
GameRepo remove pov.game.id
|
2013-09-26 10:18:07 -06:00
|
|
|
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 =>
|
2015-06-20 09:00:40 -06:00
|
|
|
get("fen") flatMap ValidFen(getBool("strict")) match {
|
|
|
|
case None => BadRequest.fuccess
|
|
|
|
case Some(v) => Ok(html.game.miniBoard(v.fen, v.color.name)).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
|
2014-02-12 16:23:18 -07:00
|
|
|
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)),
|
2015-04-04 04:42:14 -06:00
|
|
|
api = apiVersion => Env.api.roundApi.player(pov, apiVersion) map { data =>
|
2014-10-01 16:19:49 -06:00
|
|
|
Created(data) as JSON
|
2014-05-10 03:17:00 -06:00
|
|
|
}
|
2014-05-09 12:01:33 -06:00
|
|
|
)
|
2014-02-12 16:23:18 -07:00
|
|
|
}
|
|
|
|
)
|
2013-05-08 20:00:13 -06:00
|
|
|
}
|
2014-02-12 16:23:18 -07: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
|
|
|
}
|