lila/app/controllers/RelayRound.scala

221 lines
7.3 KiB
Scala

package controllers
import play.api.data.Form
import play.api.mvc._
import lila.api.Context
import lila.app._
// import lila.common.config.MaxPerSecond
import lila.relay.{ RelayRound => RoundModel, RelayTour => TourModel, RelayRoundForm }
import lila.user.{ User => UserModel }
import views._
final class RelayRound(
env: Env,
studyC: => Study
// apiC: => Api
) extends LilaController(env) {
def form(tourId: String) =
Auth { implicit ctx => me =>
NoLameOrBot {
WithTourAndRounds(tourId) { trs =>
(trs.tour.ownerId == me.id) ?? {
Ok(html.relay.roundForm.create(env.relay.roundForm.create(trs), trs.tour)).fuccess
}
}
}
}
def create(tourId: String) =
AuthOrScopedBody(_.Study.Write)(
auth = implicit ctx =>
me =>
NoLameOrBot {
WithTourAndRounds(tourId) { trs =>
(trs.tour.ownerId == me.id) ?? {
env.relay.roundForm
.create(trs)
.bindFromRequest()(ctx.body, formBinding)
.fold(
err => BadRequest(html.relay.roundForm.create(err, trs.tour)).fuccess,
setup =>
env.relay.api.create(setup, me, trs.tour) map { relay =>
Redirect(routes.RelayTour.show(trs.tour.slug, trs.tour.id.value))
}
)
}
}
},
scoped = req =>
me =>
env.relay.api tourById TourModel.Id(tourId) flatMap {
_ ?? { tour =>
env.relay.api.withRounds(tour) flatMap { trs =>
!(me.isBot || me.lame) ??
env.relay.roundForm
.create(trs)
.bindFromRequest()(req, formBinding)
.fold(
err => BadRequest(apiFormError(err)).fuccess,
setup => env.relay.api.create(setup, me, tour) map env.relay.jsonView.admin map JsonOk
)
}
}
}
)
def edit(id: String) =
Auth { implicit ctx => me =>
OptionFuResult(env.relay.api.byIdAndContributor(id, me)) { rt =>
Ok(html.relay.roundForm.edit(rt, env.relay.roundForm.edit(rt.relay))).fuccess
}
}
def update(id: String) =
AuthOrScopedBody(_.Study.Write)(
auth = implicit ctx =>
me =>
doUpdate(id, me)(ctx.body) flatMap {
case None => notFound
case Some(res) =>
res
.fold(
{ case (old, err) => BadRequest(html.relay.roundForm.edit(old, err)) },
rt => Redirect(rt.path)
)
.fuccess
},
scoped = req =>
me =>
doUpdate(id, me)(req) map {
case None => NotFound(jsonError("No such broadcast"))
case Some(res) =>
res.fold(
{ case (_, err) => BadRequest(apiFormError(err)) },
rt => JsonOk(env.relay.jsonView.admin(rt.relay))
)
}
)
private def doUpdate(id: String, me: UserModel)(implicit
req: Request[_]
): Fu[Option[Either[(RoundModel.WithTour, Form[RelayRoundForm.Data]), RoundModel.WithTour]]] =
env.relay.api.byIdAndContributor(id, me) flatMap {
_ ?? { rt =>
env.relay.roundForm
.edit(rt.relay)
.bindFromRequest()
.fold(
err => fuccess(Left(rt -> err)),
data =>
env.relay.api.update(rt.relay) { data.update(_, me) }.dmap(_ withTour rt.tour) dmap Right.apply
) dmap some
}
}
def reset(id: String) =
Auth { implicit ctx => me =>
OptionFuResult(env.relay.api.byIdAndContributor(id, me)) { rt =>
env.relay.api.reset(rt.relay, me) inject Redirect(rt.path)
}
}
def show(ts: String, rs: String, id: String) =
OpenOrScoped(_.Study.Read)(
open = implicit ctx => {
pageHit
WithRelay(ts, rs, id) { rt =>
val sc =
if (rt.relay.sync.ongoing)
env.study.chapterRepo relaysAndTagsByStudyId rt.relay.studyId flatMap { chapters =>
chapters.find(_.looksAlive) orElse chapters.headOption match {
case Some(chapter) => env.study.api.byIdWithChapter(rt.relay.studyId, chapter.id)
case None => env.study.api byIdWithChapter rt.relay.studyId
}
}
else env.study.api byIdWithChapter rt.relay.studyId
sc flatMap { _ ?? { doShow(rt, _) } }
}
},
scoped = _ =>
me =>
env.relay.api.byIdAndContributor(id, me) map {
case None => NotFound(jsonError("No such broadcast"))
case Some(rt) => JsonOk(env.relay.jsonView.admin(rt.relay))
}
)
def chapter(ts: String, rs: String, id: String, chapterId: String) =
Open { implicit ctx =>
WithRelay(ts, rs, id) { rt =>
env.study.api.byIdWithChapter(rt.relay.studyId, chapterId) flatMap {
_ ?? { doShow(rt, _) }
}
}
}
def cloneRelay(id: String) =
Auth { implicit ctx => me =>
OptionFuResult(env.relay.api.byIdAndContributor(id, me)) { rt =>
env.relay.api.cloneRelay(rt, me) map { newRelay =>
Redirect(routes.RelayRound.edit(newRelay.id.value))
}
}
}
def push(id: String) =
ScopedBody(parse.tolerantText)(Seq(_.Study.Write)) { req => me =>
env.relay.api.byIdAndContributor(id, me) flatMap {
case None => notFoundJson()
case Some(rt) => env.relay.push(rt, req.body) inject jsonOkResult
}
}
// def apiIndex =
// Action.async { implicit req =>
// apiC.jsonStream {
// env.relay.api.officialStream(MaxPerSecond(20), getInt("nb", req) | 20)
// }.fuccess
// }
private def WithRelay(ts: String, rs: String, id: String)(
f: RoundModel.WithTour => Fu[Result]
)(implicit ctx: Context): Fu[Result] =
OptionFuResult(env.relay.api byIdWithTour id) { rt =>
if (rt.tour.slug != ts) Redirect(rt.path).fuccess
if (rt.relay.slug != rs) Redirect(rt.path).fuccess
else f(rt)
}
private def WithTour(id: String)(
f: TourModel => Fu[Result]
)(implicit ctx: Context): Fu[Result] =
OptionFuResult(env.relay.api tourById TourModel.Id(id))(f)
private def WithTourAndRounds(id: String)(
f: TourModel.WithRounds => Fu[Result]
)(implicit ctx: Context): Fu[Result] =
WithTour(id) { tour =>
env.relay.api withRounds tour flatMap f
}
private def doShow(rt: RoundModel.WithTour, oldSc: lila.study.Study.WithChapter)(implicit
ctx: Context
): Fu[Result] =
studyC.CanViewResult(oldSc.study) {
for {
(sc, studyData) <- studyC.getJsonData(oldSc)
data = env.relay.jsonView.makeData(rt.relay, studyData, ctx.userId exists sc.study.canContribute)
chat <- studyC.chatOf(sc.study)
sVersion <- env.study.version(sc.study.id)
streams <- studyC.streamsOf(sc.study)
} yield EnableSharedArrayBuffer(
Ok(html.relay.show(rt withStudy sc.study, data, chat, sVersion, streams))
)
}
implicit private def makeRelayId(id: String): RoundModel.Id = RoundModel.Id(id)
implicit private def makeChapterId(id: String): lila.study.Chapter.Id = lila.study.Chapter.Id(id)
}