add endpoints to list and delete bulk pairings
parent
f31cfc849c
commit
411b0752da
|
@ -154,6 +154,7 @@ final class LilaComponents(ctx: ApplicationLoader.Context) extends BuiltInCompon
|
|||
lazy val swiss: Swiss = wire[Swiss]
|
||||
lazy val dgt: DgtCtrl = wire[DgtCtrl]
|
||||
lazy val storm: Storm = wire[Storm]
|
||||
lazy val bulkPairing: BulkPairing = wire[BulkPairing]
|
||||
|
||||
// eagerly wire up all controllers
|
||||
val router: Router = {
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
package controllers
|
||||
|
||||
import play.api.libs.json.Json
|
||||
|
||||
import lila.app._
|
||||
import lila.setup.SetupBulk
|
||||
|
||||
final class BulkPairing(env: Env) extends LilaController(env) {
|
||||
|
||||
def list =
|
||||
ScopedBody(_.Challenge.Bulk) { implicit req => me =>
|
||||
env.challenge.bulk.scheduledBy(me) map { list =>
|
||||
Ok(Json.obj("bulks" -> list.map(SetupBulk.toJson))) as JSON
|
||||
}
|
||||
}
|
||||
|
||||
def delete(id: String) =
|
||||
ScopedBody(_.Challenge.Bulk) { implicit req => me =>
|
||||
env.challenge.bulk.deleteBy(id, me) flatMap {
|
||||
case true => jsonOkResult.fuccess
|
||||
case _ => notFoundJson()
|
||||
}
|
||||
}
|
||||
|
||||
def create =
|
||||
ScopedBody(_.Challenge.Bulk) { implicit req => me =>
|
||||
implicit val lang = reqLang
|
||||
import lila.setup.SetupBulk
|
||||
lila.setup.SetupBulk.form
|
||||
.bindFromRequest()
|
||||
.fold(
|
||||
newJsonFormError,
|
||||
data =>
|
||||
env.setup.bulk(data, me) flatMap {
|
||||
case Left(SetupBulk.RateLimited) =>
|
||||
TooManyRequests(
|
||||
jsonError(s"Ratelimited! Max games per 10 minutes: ${SetupBulk.maxGames}")
|
||||
).fuccess
|
||||
case Left(SetupBulk.BadTokens(tokens)) =>
|
||||
import lila.setup.SetupBulk.BadToken
|
||||
import play.api.libs.json._
|
||||
BadRequest(
|
||||
Json.obj(
|
||||
"tokens" -> JsObject {
|
||||
tokens.map { case BadToken(token, error) =>
|
||||
token.value -> JsString(error.message)
|
||||
}
|
||||
}
|
||||
)
|
||||
).fuccess
|
||||
case Right(bulk) =>
|
||||
env.challenge.bulk.schedule(bulk) map {
|
||||
case Left(error) => BadRequest(jsonError(error))
|
||||
case Right(bulk) => Ok(SetupBulk toJson bulk) as JSON
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
|
@ -309,47 +309,6 @@ final class Challenge(
|
|||
)
|
||||
}
|
||||
|
||||
def bulk =
|
||||
ScopedBody(_.Challenge.Bulk) { implicit req => me =>
|
||||
implicit val lang = reqLang
|
||||
import lila.setup.SetupBulk
|
||||
lila.setup.SetupBulk.form
|
||||
.bindFromRequest()
|
||||
.fold(
|
||||
newJsonFormError,
|
||||
data =>
|
||||
env.setup.bulk(data, me) flatMap {
|
||||
case Left(SetupBulk.RateLimited) =>
|
||||
TooManyRequests(
|
||||
jsonError(s"Ratelimited! Max games per 10 minutes: ${SetupBulk.maxGames}")
|
||||
).fuccess
|
||||
case Left(SetupBulk.BadTokens(tokens)) =>
|
||||
import lila.setup.SetupBulk.BadToken
|
||||
import play.api.libs.json._
|
||||
BadRequest(
|
||||
Json.obj(
|
||||
"tokens" -> JsObject {
|
||||
tokens.map { case BadToken(token, error) =>
|
||||
token.value -> JsString(error.message)
|
||||
}
|
||||
}
|
||||
)
|
||||
).fuccess
|
||||
case Right(bulk) =>
|
||||
env.challenge.bulk.schedule(bulk) map {
|
||||
case Some(error) => BadRequest(jsonError(error))
|
||||
case _ =>
|
||||
Ok(Json.obj("games" -> bulk.games.map { g =>
|
||||
Json.obj(
|
||||
"gameId" -> g.id,
|
||||
"userIds" -> Json.arr(g.white, g.black)
|
||||
)
|
||||
})) as JSON
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
def apiCreateAdmin(origName: String, destName: String) =
|
||||
ScopedBody(_.Challenge.Write) { implicit req => admin =>
|
||||
IfGranted(_.ApiChallengeAdmin, req, admin) {
|
||||
|
|
|
@ -612,7 +612,6 @@ GET /api/account/preferences controllers.Pref.apiGet
|
|||
POST /api/challenge/ai controllers.Setup.apiAi
|
||||
POST /api/challenge/open controllers.Challenge.openCreate
|
||||
POST /api/challenge/admin/:orig/:dest controllers.Challenge.apiCreateAdmin(orig: String, dest: String)
|
||||
POST /api/challenge/bulk controllers.Challenge.bulk
|
||||
POST /api/challenge/:user controllers.Challenge.apiCreate(user: String)
|
||||
POST /api/challenge/$id<\w{8}>/accept controllers.Challenge.apiAccept(id: String)
|
||||
POST /api/challenge/$id<\w{8}>/decline controllers.Challenge.apiDecline(id: String)
|
||||
|
@ -622,6 +621,9 @@ POST /api/round/$id<\w{8}>/add-time/:seconds controllers.Round.apiAddTime(id: S
|
|||
GET /api/cloud-eval controllers.Api.cloudEval
|
||||
GET /api/broadcast controllers.Relay.apiIndex
|
||||
POST /api/import controllers.Importer.apiSendGame
|
||||
GET /api/bulk-pairing controllers.BulkPairing.list
|
||||
POST /api/bulk-pairing controllers.BulkPairing.create
|
||||
DELETE /api/bulk-pairing/:id controllers.BulkPairing.delete(id: String)
|
||||
|
||||
GET /api/games/user/:username controllers.Game.apiExportByUser(username: String)
|
||||
|
||||
|
|
|
@ -40,16 +40,22 @@ final class ChallengeBulkApi(
|
|||
private val workQueue =
|
||||
new DuctSequencers(maxSize = 16, expiration = 10 minutes, timeout = 10 seconds, name = "challenge.bulk")
|
||||
|
||||
def schedule(bulk: ScheduledBulk): Fu[Option[String]] = workQueue(bulk.by) {
|
||||
if (bulk.pairAt.isBeforeNow) makePairings(bulk) inject none
|
||||
def scheduledBy(me: User): Fu[List[ScheduledBulk]] =
|
||||
coll.list[ScheduledBulk]($doc("by" -> me.id))
|
||||
|
||||
def deleteBy(id: String, me: User): Fu[Boolean] =
|
||||
coll.delete.one($doc("_id" -> id, "by" -> me.id)).map(_.n == 1)
|
||||
|
||||
def schedule(bulk: ScheduledBulk): Fu[Either[String, ScheduledBulk]] = workQueue(bulk.by) {
|
||||
if (bulk.pairAt.isBeforeNow) makePairings(bulk) inject Right(bulk.copy(pairedAt = DateTime.now.some))
|
||||
else
|
||||
coll.list[ScheduledBulk]($doc("by" -> bulk.by, "pairedAt" $exists false)) flatMap { bulks =>
|
||||
val nbGames = bulks.map(_.games.size).sum
|
||||
if (bulks.sizeIs >= 10) fuccess("Already too many bulks queued".some)
|
||||
else if (bulks.map(_.games.size).sum >= 1000) fuccess("Already too many games queued".some)
|
||||
if (bulks.sizeIs >= 10) fuccess(Left("Already too many bulks queued"))
|
||||
else if (bulks.map(_.games.size).sum >= 1000) fuccess(Left("Already too many games queued"))
|
||||
else if (bulks.exists(_ collidesWith bulk))
|
||||
fuccess("A bulk containing the same players is scheduled at the same time".some)
|
||||
else coll.insert.one(bulk) inject none
|
||||
fuccess(Left("A bulk containing the same players is scheduled at the same time"))
|
||||
else coll.insert.one(bulk) inject Right(bulk)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import chess.{ Clock, Mode, Speed }
|
|||
import org.joda.time.DateTime
|
||||
import play.api.data._
|
||||
import play.api.data.Forms._
|
||||
import play.api.libs.json.Json
|
||||
import scala.concurrent.duration._
|
||||
|
||||
import lila.game.Game
|
||||
|
@ -106,6 +107,32 @@ object SetupBulk {
|
|||
sealed trait ScheduleError
|
||||
case class BadTokens(tokens: List[BadToken]) extends ScheduleError
|
||||
case object RateLimited extends ScheduleError
|
||||
|
||||
def toJson(bulk: ScheduledBulk) = {
|
||||
import bulk._
|
||||
import lila.common.Json.jodaWrites
|
||||
Json.obj(
|
||||
"id" -> _id,
|
||||
"games" -> games.map { g =>
|
||||
Json.obj(
|
||||
"id" -> g.id,
|
||||
"white" -> g.white,
|
||||
"black" -> g.black
|
||||
)
|
||||
},
|
||||
"variant" -> variant.key,
|
||||
"clock" -> Json.obj(
|
||||
"limit" -> clock.limitSeconds,
|
||||
"increment" -> clock.incrementSeconds
|
||||
),
|
||||
"rated" -> mode.rated,
|
||||
"pairAt" -> pairAt,
|
||||
"startClocksAt" -> startClocksAt,
|
||||
"scheduledAt" -> scheduledAt,
|
||||
"pairedAt" -> pairedAt
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
final class BulkChallengeApi(oauthServer: OAuthServer, idGenerator: IdGenerator)(implicit
|
||||
|
|
Loading…
Reference in New Issue