make controllers more async and readable

This commit is contained in:
Thibault Duplessis 2017-01-26 15:28:16 +01:00
parent 5eedd1d3dc
commit 880cf89f0c
3 changed files with 112 additions and 118 deletions

View file

@ -1,8 +1,8 @@
package controllers package controllers
import play.api.data.Form import play.api.data.Form
import play.twirl.api.Html
import play.api.libs.json._ import play.api.libs.json._
import play.twirl.api.Html
import lila.api.Context import lila.api.Context
import lila.app._ import lila.app._
@ -17,78 +17,76 @@ object Message extends LilaController {
private def forms = Env.message.forms private def forms = Env.message.forms
private def relationApi = Env.relation.api private def relationApi = Env.relation.api
def inbox(page: Int) = Auth { implicit ctx => def inbox(page: Int) = Auth { implicit ctx => me =>
me => NotForKids {
NotForKids { for {
negotiate ( pag <- api.inbox(me, page)
html = api.inbox(me, page) map { html.message.inbox(me, _) }, _ <- Env.user.lightUserApi preloadMany pag.currentPageResults.flatMap(_.userIds)
api = _ => api.inbox(me, page) map { Env.message.jsonView.inbox(me, _) } res <- negotiate(
) html = fuccess(html.message.inbox(me, pag)),
} api = _ => fuccess(Env.message.jsonView.inbox(me, pag)))
} yield res
}
} }
def thread(id: String) = Auth { implicit ctx => def thread(id: String) = Auth { implicit ctx => implicit me =>
implicit me => NotForKids {
NotForKids { negotiate(
negotiate ( html = OptionFuOk(api.thread(id, me)) { thread =>
html = OptionFuOk(api.thread(id, me)) { thread => relationApi.fetchBlocks(thread otherUserId me, me.id) map { blocked =>
relationApi.fetchBlocks(thread otherUserId me, me.id) map { blocked => html.message.thread(thread, forms.post, blocked)
html.message.thread(thread, forms.post, blocked)
}
} map NoCache,
api = _ => JsonOptionFuOk(api.thread(id, me)) { thread => Env.message.jsonView.thread(thread) }
)
}
}
def answer(id: String) = AuthBody { implicit ctx =>
implicit me =>
negotiate (
html = OptionFuResult(api.thread(id, me)) { thread =>
implicit val req = ctx.body
forms.post.bindFromRequest.fold(
err => relationApi.fetchBlocks(thread otherUserId me, me.id) map { blocked =>
BadRequest(html.message.thread(thread, err, blocked))
},
text => api.makePost(thread, text, me) inject Redirect(routes.Message.thread(thread.id) + "#bottom")
)
},
api = _ => OptionFuResult(api.thread(id, me)) { thread =>
implicit val req = ctx.body
forms.post.bindFromRequest.fold(
err => fuccess(BadRequest(Json.obj("err" -> "Malformed request"))),
text => api.makePost(thread, text, me) inject Ok(Json.obj("ok" -> true, "id" -> thread.id))
)
} }
} map NoCache,
api = _ => JsonOptionFuOk(api.thread(id, me)) { thread => Env.message.jsonView.thread(thread) }
) )
}
} }
def form = Auth { implicit ctx => def answer(id: String) = AuthBody { implicit ctx => implicit me =>
implicit me => negotiate(
NotForKids { html = OptionFuResult(api.thread(id, me)) { thread =>
renderForm(me, get("title"), identity) map { Ok(_) } implicit val req = ctx.body
forms.post.bindFromRequest.fold(
err => relationApi.fetchBlocks(thread otherUserId me, me.id) map { blocked =>
BadRequest(html.message.thread(thread, err, blocked))
},
text => api.makePost(thread, text, me) inject Redirect(routes.Message.thread(thread.id) + "#bottom")
)
},
api = _ => OptionFuResult(api.thread(id, me)) { thread =>
implicit val req = ctx.body
forms.post.bindFromRequest.fold(
err => fuccess(BadRequest(Json.obj("err" -> "Malformed request"))),
text => api.makePost(thread, text, me) inject Ok(Json.obj("ok" -> true, "id" -> thread.id))
)
} }
)
} }
def create = AuthBody { implicit ctx => def form = Auth { implicit ctx => implicit me =>
implicit me => NotForKids {
NotForKids { renderForm(me, get("title"), identity) map { Ok(_) }
}
}
def create = AuthBody { implicit ctx => implicit me =>
NotForKids {
import play.api.Play.current import play.api.Play.current
import play.api.i18n.Messages.Implicits._ import play.api.i18n.Messages.Implicits._
implicit val req = ctx.body implicit val req = ctx.body
negotiate ( negotiate(
html = forms.thread(me).bindFromRequest.fold( html = forms.thread(me).bindFromRequest.fold(
err => renderForm(me, none, _ => err) map { BadRequest(_) }, err => renderForm(me, none, _ => err) map { BadRequest(_) },
data => api.makeThread(data, me) map { thread => data => api.makeThread(data, me) map { thread =>
Redirect(routes.Message.thread(thread.id)) Redirect(routes.Message.thread(thread.id))
}), }),
api = _ => forms.thread(me).bindFromRequest.fold( api = _ => forms.thread(me).bindFromRequest.fold(
err => fuccess(BadRequest(errorsAsJson(err))), err => fuccess(BadRequest(errorsAsJson(err))),
data => api.makeThread(data, me) map { thread => data => api.makeThread(data, me) map { thread =>
Ok(Json.obj("ok" -> true, "id" -> thread.id)) Ok(Json.obj("ok" -> true, "id" -> thread.id))
}) })
) )
} }
} }
private def renderForm(me: UserModel, title: Option[String], f: Form[_] => Form[_])(implicit ctx: Context): Fu[Html] = private def renderForm(me: UserModel, title: Option[String], f: Form[_] => Form[_])(implicit ctx: Context): Fu[Html] =
@ -99,17 +97,15 @@ object Message extends LilaController {
} }
} }
def batch = AuthBody { implicit ctx => def batch = AuthBody { implicit ctx => implicit me =>
implicit me => val ids = get("ids").??(_.split(",").toList).distinct take 200
val ids = get("ids").??(_.split(",").toList).distinct take 200 Env.message.batch(me, ~get("action"), ids) inject Redirect(routes.Message.inbox(1))
Env.message.batch(me, ~get("action"), ids) inject Redirect(routes.Message.inbox(1))
} }
def delete(id: String) = AuthBody { implicit ctx => def delete(id: String) = AuthBody { implicit ctx => implicit me =>
implicit me => negotiate(
negotiate ( html = api.deleteThread(id, me) inject Redirect(routes.Message.inbox(1)),
html = api.deleteThread(id, me) inject Redirect(routes.Message.inbox(1)), api = _ => api.deleteThread(id, me) inject Ok(Json.obj("ok" -> true))
api = _ => api.deleteThread(id, me) inject Ok(Json.obj("ok" -> true)) )
)
} }
} }

View file

@ -85,33 +85,32 @@ object Study extends LilaController {
private def showQuery(query: Fu[Option[WithChapter]])(implicit ctx: Context) = private def showQuery(query: Fu[Option[WithChapter]])(implicit ctx: Context) =
OptionFuResult(query) { OptionFuResult(query) {
case WithChapter(study, chapter) => CanViewResult(study) { case WithChapter(s, chapter) => CanViewResult(s) {
env.chapterRepo.orderedMetadataByStudy(study.id) flatMap { chapters => import lila.tree.Node.partitionTreeJsonWriter
env.api.resetIfOld(study, chapters) flatMap { study => for {
if (HTTPRequest isSynchronousHttp ctx.req) env.studyRepo.incViews(study) chapters <- env.chapterRepo.orderedMetadataByStudy(s.id)
val pov = UserAnalysis.makePov(chapter.root.fen.value.some, chapter.setup.variant) study <- env.api.resetIfOld(s, chapters)
Env.round.jsonView.userAnalysisJson(pov, ctx.pref, chapter.setup.orientation, owner = false) zip _ <- Env.user.lightUserApi preloadMany study.members.ids.toList
chatOf(study) zip _ = if (HTTPRequest isSynchronousHttp ctx.req) env.studyRepo.incViews(study)
env.jsonView(study, chapters, chapter, ctx.me) zip pov = UserAnalysis.makePov(chapter.root.fen.value.some, chapter.setup.variant)
env.version(study.id) flatMap { baseData <- Env.round.jsonView.userAnalysisJson(pov, ctx.pref, chapter.setup.orientation, owner = false)
case (((baseData, chat), studyJson), sVersion) => studyJson <- env.jsonView(study, chapters, chapter, ctx.me)
import lila.tree.Node.partitionTreeJsonWriter data = lila.study.JsonView.JsData(
val analysis = baseData ++ Json.obj( study = studyJson,
"treeParts" -> partitionTreeJsonWriter.writes { analysis = baseData ++ Json.obj(
lila.study.TreeBuilder(chapter.root, chapter.setup.variant) "treeParts" -> partitionTreeJsonWriter.writes {
}) lila.study.TreeBuilder(chapter.root, chapter.setup.variant)
val data = lila.study.JsonView.JsData( }))
study = studyJson, res <- negotiate(
analysis = analysis) html = for {
negotiate( chat <- chatOf(study)
html = Ok(html.study.show(study, data, chat, sVersion)).fuccess, sVersion <- env.version(study.id)
api = _ => Ok(Json.obj( } yield Ok(html.study.show(study, data, chat, sVersion)),
"study" -> data.study, api = _ => Ok(Json.obj(
"analysis" -> data.analysis)).fuccess "study" -> data.study,
) "analysis" -> data.analysis)).fuccess
} )
} } yield res
}
} }
} map NoCache } map NoCache

View file

@ -37,25 +37,24 @@ object User extends LilaController {
def showMini(username: String) = Open { implicit ctx => def showMini(username: String) = Open { implicit ctx =>
OptionFuResult(UserRepo named username) { user => OptionFuResult(UserRepo named username) { user =>
if (user.enabled) GameRepo lastPlayedPlaying user zip if (user.enabled) for {
(ctx.userId ?? { relationApi.fetchBlocks(user.id, _) }) zip blocked <- ctx.userId ?? { relationApi.fetchBlocks(user.id, _) }
(ctx.userId ?? { Env.game.crosstableApi(user.id, _) }) zip crosstable <- ctx.userId ?? { Env.game.crosstableApi(user.id, _) }
(ctx.isAuth ?? { Env.pref.api.followable(user.id) }) zip followable <- ctx.isAuth ?? { Env.pref.api.followable(user.id) }
(ctx.userId ?? { relationApi.fetchRelation(_, user.id) }) flatMap { relation <- ctx.userId ?? { relationApi.fetchRelation(_, user.id) }
case ((((pov, blocked), crosstable), followable), relation) => res <- negotiate(
negotiate( html = GameRepo lastPlayedPlaying user map { pov =>
html = fuccess { Ok(html.user.mini(user, pov, blocked, followable, relation, crosstable))
Ok(html.user.mini(user, pov, blocked, followable, relation, crosstable)) .withHeaders(CACHE_CONTROL -> "max-age=5")
.withHeaders(CACHE_CONTROL -> "max-age=5") },
}, api = _ => {
api = _ => { import lila.game.JsonView.crosstableWrites
import lila.game.JsonView.crosstableWrites fuccess(Ok(Json.obj(
fuccess(Ok(Json.obj( "crosstable" -> crosstable,
"crosstable" -> crosstable, "perfs" -> lila.user.JsonView.perfs(user, user.best8Perfs)
"perfs" -> lila.user.JsonView.perfs(user, user.best8Perfs) )))
))) })
}) } yield res
}
else fuccess(Ok(html.user.miniClosed(user))) else fuccess(Ok(html.user.miniClosed(user)))
} }
} }