anonymous challenge join

This commit is contained in:
Thibault Duplessis 2016-02-04 07:29:30 +07:00
parent f486211a2c
commit 01630eb87b
5 changed files with 73 additions and 62 deletions

View file

@ -3,7 +3,7 @@ package controllers
import play.api.data.Form
import play.api.i18n.Messages.Implicits._
import play.api.libs.json._
import play.api.mvc.{ Result, Results, Call, RequestHeader, Accepting }
import play.api.mvc.Result
import scala.concurrent.duration._
import lila.api.{ Context, BodyContext }
@ -53,10 +53,15 @@ object Challenge extends LilaController {
def accept(id: String) = Open { implicit ctx =>
OptionFuResult(env.api byId id) { c =>
if (isForMe(c)) env.api.accept(c, ctx.me) map { game =>
Redirect(routes.Round.watcher(game.id, "white"))
isForMe(c) ?? env.api.accept(c, ctx.me).flatMap {
case Some(pov) => negotiate(
html = Setup.redirectPov(pov).fuccess,
api = apiVersion =>
Env.api.roundApi.player(pov, apiVersion) map { Ok(_) })
case None => negotiate(
html = Redirect(routes.Round.watcher(c.id, "white")).fuccess,
api = _ => notFoundJson("Someone else accepted the challenge"))
}
else notFound
}
}

View file

@ -37,9 +37,7 @@ object Setup extends LilaController with TheftPrevention {
def ai = process(env.forms.ai) { config =>
implicit ctx =>
env.processor ai config map { pov =>
pov -> routes.Round.player(pov.fullId)
}
env.processor ai config
}
def friendForm(userId: Option[String]) = Open { implicit ctx =>
@ -196,7 +194,7 @@ object Setup extends LilaController with TheftPrevention {
}
}
private def process[A](form: Context => Form[A])(op: A => BodyContext[_] => Fu[(Pov, Call)]) =
private def process[A](form: Context => Form[A])(op: A => BodyContext[_] => Fu[Pov]) =
OpenBody { implicit ctx =>
implicit val req = ctx.body
form(ctx).bindFromRequest.fold(
@ -204,9 +202,9 @@ object Setup extends LilaController with TheftPrevention {
html = Lobby.renderHome(Results.BadRequest),
api = _ => fuccess(BadRequest(errorsAsJson(f)))
),
config => op(config)(ctx) flatMap {
case (pov, call) => negotiate(
html = fuccess(redirectPov(pov, call)),
config => op(config)(ctx) flatMap { pov =>
negotiate(
html = fuccess(redirectPov(pov)),
api = apiVersion => Env.api.roundApi.player(pov, apiVersion) map { data =>
Created(data) as JSON
}
@ -215,11 +213,14 @@ object Setup extends LilaController with TheftPrevention {
)
}
private def redirectPov(pov: Pov, call: Call)(implicit ctx: Context, req: RequestHeader) =
if (ctx.isAuth) Redirect(call)
else Redirect(call) withCookies LilaCookie.cookie(
private[controllers] def redirectPov(pov: Pov)(implicit ctx: Context) = {
implicit val req = ctx.req
val redir = Redirect(routes.Round.player(pov.fullId))
if (ctx.isAuth) redir
else redir withCookies LilaCookie.cookie(
AnonCookie.name,
pov.playerId,
maxAge = AnonCookie.maxAge.some,
httpOnly = false.some)
}
}

View file

@ -4,7 +4,7 @@ import akka.actor._
import org.joda.time.DateTime
import scala.concurrent.duration._
import lila.game.Game
import lila.game.{ Game, Pov }
import lila.hub.actorApi.map.Tell
import lila.hub.actorApi.SendTo
import lila.memo.{ MixedCache, AsyncCache }
@ -46,9 +46,10 @@ final class ChallengeApi(
def decline(c: Challenge) = (repo decline c) >> uncacheAndNotify(c)
def accept(c: Challenge, user: Option[User]): Fu[Game] =
joiner(c, user).flatMap { game =>
(repo accept c) >> uncacheAndNotify(c) inject game
def accept(c: Challenge, user: Option[User]): Fu[Option[Pov]] =
joiner(c, user).flatMap {
case None => fuccess(None)
case Some(pov) => (repo accept c) >> uncacheAndNotify(c) inject pov.some
}
private[challenge] def sweep: Funit =

View file

@ -6,58 +6,60 @@ import akka.pattern.ask
import chess.format.Forsyth
import chess.format.Forsyth.SituationPlus
import chess.{ Situation, Mode }
import lila.game.{ GameRepo, Game, Source, Player, AnonCookie, PerfPicker }
import lila.game.{ GameRepo, Game, Pov, Source, Player, AnonCookie, PerfPicker }
import lila.user.{ User, UserRepo }
private[challenge] final class Joiner(onStart: String => Unit) {
def apply(c: Challenge, destUser: Option[User]): Fu[Game] = GameRepo game c.id getOrElse {
def apply(c: Challenge, destUser: Option[User]): Fu[Option[Pov]] =
GameRepo exists c.id flatMap {
case true => fuccess(None)
case false =>
c.challengerUserId.??(UserRepo.byId) flatMap { challengerUser =>
c.challengerUserId.??(UserRepo.byId) flatMap { challengerUser =>
def makeChess(variant: chess.variant.Variant): chess.Game =
chess.Game(board = chess.Board init variant, clock = c.clock.map(_.chessClock))
def makeChess(variant: chess.variant.Variant): chess.Game =
chess.Game(board = chess.Board init variant, clock = c.clock.map(_.chessClock))
val baseState = c.initialFen.ifTrue(c.variant == chess.variant.FromPosition) flatMap Forsyth.<<<
val (chessGame, state) = baseState.fold(makeChess(c.variant) -> none[SituationPlus]) {
case sit@SituationPlus(Situation(board, color), _) =>
val game = chess.Game(
board = board,
player = color,
turns = sit.turns,
startedAtTurn = sit.turns,
clock = c.clock.map(_.chessClock))
if (Forsyth.>>(game) == Forsyth.initial) makeChess(chess.variant.Standard) -> none
else game -> baseState
}
val realVariant = chessGame.board.variant
def makePlayer(color: chess.Color, userOption: Option[User]) = Player.make(color, None) |> { p =>
userOption.fold(p) { user =>
p.withUser(user.id, user.perfs(c.perfType))
}
}
val game = Game.make(
game = chessGame,
whitePlayer = makePlayer(chess.White, c.chessColor.fold(challengerUser, destUser)),
blackPlayer = makePlayer(chess.Black, c.chessColor.fold(destUser, challengerUser)),
mode = (realVariant == chess.variant.FromPosition).fold(Mode.Casual, c.mode),
variant = realVariant,
source = (realVariant == chess.variant.FromPosition).fold(Source.Position, Source.Friend),
daysPerTurn = c.daysPerTurn,
pgnImport = None).copy(id = c.id).|> { g =>
state.fold(g) {
case sit@SituationPlus(Situation(board, _), _) => g.copy(
variant = chess.variant.FromPosition,
castleLastMoveTime = g.castleLastMoveTime.copy(
lastMove = board.history.lastMove.map(_.origDest),
castles = board.history.castles
),
turns = sit.turns)
val baseState = c.initialFen.ifTrue(c.variant == chess.variant.FromPosition) flatMap Forsyth.<<<
val (chessGame, state) = baseState.fold(makeChess(c.variant) -> none[SituationPlus]) {
case sit@SituationPlus(Situation(board, color), _) =>
val game = chess.Game(
board = board,
player = color,
turns = sit.turns,
startedAtTurn = sit.turns,
clock = c.clock.map(_.chessClock))
if (Forsyth.>>(game) == Forsyth.initial) makeChess(chess.variant.Standard) -> none
else game -> baseState
}
}.start
(GameRepo insertDenormalized game) >>- onStart(game.id) inject game
val realVariant = chessGame.board.variant
def makePlayer(color: chess.Color, userOption: Option[User]) = Player.make(color, None) |> { p =>
userOption.fold(p) { user =>
p.withUser(user.id, user.perfs(c.perfType))
}
}
val game = Game.make(
game = chessGame,
whitePlayer = makePlayer(chess.White, c.chessColor.fold(challengerUser, destUser)),
blackPlayer = makePlayer(chess.Black, c.chessColor.fold(destUser, challengerUser)),
mode = (realVariant == chess.variant.FromPosition).fold(Mode.Casual, c.mode),
variant = realVariant,
source = (realVariant == chess.variant.FromPosition).fold(Source.Position, Source.Friend),
daysPerTurn = c.daysPerTurn,
pgnImport = None).copy(id = c.id).|> { g =>
state.fold(g) {
case sit@SituationPlus(Situation(board, _), _) => g.copy(
variant = chess.variant.FromPosition,
castleLastMoveTime = g.castleLastMoveTime.copy(
lastMove = board.history.lastMove.map(_.origDest),
castles = board.history.castles
),
turns = sit.turns)
}
}.start
(GameRepo insertDenormalized game) >>- onStart(game.id) inject Pov(game, !c.chessColor).some
}
}
}
// def apply(game: Game, user: Option[User]): Valid[Fu[(Pov, List[Event])]] =
// game.notStarted option {

View file

@ -174,6 +174,8 @@ object GameRepo {
def isAnalysed(id: ID): Fu[Boolean] =
$count.exists($select(id) ++ Query.analysed(true))
def exists(id: ID) = $count.exists($select(id))
def filterAnalysed(ids: Seq[String]): Fu[Set[String]] =
gameTube.coll.distinct("_id", BSONDocument(
"_id" -> BSONDocument("$in" -> ids),