make controllers more async and readable

pull/2571/head
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
import play.api.data.Form
import play.twirl.api.Html
import play.api.libs.json._
import play.twirl.api.Html
import lila.api.Context
import lila.app._
@ -17,78 +17,76 @@ object Message extends LilaController {
private def forms = Env.message.forms
private def relationApi = Env.relation.api
def inbox(page: Int) = Auth { implicit ctx =>
me =>
NotForKids {
negotiate (
html = api.inbox(me, page) map { html.message.inbox(me, _) },
api = _ => api.inbox(me, page) map { Env.message.jsonView.inbox(me, _) }
)
}
def inbox(page: Int) = Auth { implicit ctx => me =>
NotForKids {
for {
pag <- api.inbox(me, page)
_ <- Env.user.lightUserApi preloadMany pag.currentPageResults.flatMap(_.userIds)
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 =>
implicit me =>
NotForKids {
negotiate (
html = OptionFuOk(api.thread(id, me)) { thread =>
relationApi.fetchBlocks(thread otherUserId me, me.id) map { 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))
)
def thread(id: String) = Auth { implicit ctx => implicit me =>
NotForKids {
negotiate(
html = OptionFuOk(api.thread(id, me)) { thread =>
relationApi.fetchBlocks(thread otherUserId me, me.id) map { blocked =>
html.message.thread(thread, forms.post, blocked)
}
} map NoCache,
api = _ => JsonOptionFuOk(api.thread(id, me)) { thread => Env.message.jsonView.thread(thread) }
)
}
}
def form = Auth { implicit ctx =>
implicit me =>
NotForKids {
renderForm(me, get("title"), identity) map { Ok(_) }
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))
)
}
)
}
def create = AuthBody { implicit ctx =>
implicit me =>
NotForKids {
def form = Auth { implicit ctx => implicit me =>
NotForKids {
renderForm(me, get("title"), identity) map { Ok(_) }
}
}
def create = AuthBody { implicit ctx => implicit me =>
NotForKids {
import play.api.Play.current
import play.api.i18n.Messages.Implicits._
implicit val req = ctx.body
negotiate (
html = forms.thread(me).bindFromRequest.fold(
err => renderForm(me, none, _ => err) map { BadRequest(_) },
data => api.makeThread(data, me) map { thread =>
Redirect(routes.Message.thread(thread.id))
}),
api = _ => forms.thread(me).bindFromRequest.fold(
err => fuccess(BadRequest(errorsAsJson(err))),
data => api.makeThread(data, me) map { thread =>
Ok(Json.obj("ok" -> true, "id" -> thread.id))
})
)
}
implicit val req = ctx.body
negotiate(
html = forms.thread(me).bindFromRequest.fold(
err => renderForm(me, none, _ => err) map { BadRequest(_) },
data => api.makeThread(data, me) map { thread =>
Redirect(routes.Message.thread(thread.id))
}),
api = _ => forms.thread(me).bindFromRequest.fold(
err => fuccess(BadRequest(errorsAsJson(err))),
data => api.makeThread(data, me) map { thread =>
Ok(Json.obj("ok" -> true, "id" -> thread.id))
})
)
}
}
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 =>
implicit me =>
val ids = get("ids").??(_.split(",").toList).distinct take 200
Env.message.batch(me, ~get("action"), ids) inject Redirect(routes.Message.inbox(1))
def batch = AuthBody { implicit ctx => implicit me =>
val ids = get("ids").??(_.split(",").toList).distinct take 200
Env.message.batch(me, ~get("action"), ids) inject Redirect(routes.Message.inbox(1))
}
def delete(id: String) = AuthBody { implicit ctx =>
implicit me =>
negotiate (
html = api.deleteThread(id, me) inject Redirect(routes.Message.inbox(1)),
api = _ => api.deleteThread(id, me) inject Ok(Json.obj("ok" -> true))
)
def delete(id: String) = AuthBody { implicit ctx => implicit me =>
negotiate(
html = api.deleteThread(id, me) inject Redirect(routes.Message.inbox(1)),
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) =
OptionFuResult(query) {
case WithChapter(study, chapter) => CanViewResult(study) {
env.chapterRepo.orderedMetadataByStudy(study.id) flatMap { chapters =>
env.api.resetIfOld(study, chapters) flatMap { study =>
if (HTTPRequest isSynchronousHttp ctx.req) env.studyRepo.incViews(study)
val pov = UserAnalysis.makePov(chapter.root.fen.value.some, chapter.setup.variant)
Env.round.jsonView.userAnalysisJson(pov, ctx.pref, chapter.setup.orientation, owner = false) zip
chatOf(study) zip
env.jsonView(study, chapters, chapter, ctx.me) zip
env.version(study.id) flatMap {
case (((baseData, chat), studyJson), sVersion) =>
import lila.tree.Node.partitionTreeJsonWriter
val analysis = baseData ++ Json.obj(
"treeParts" -> partitionTreeJsonWriter.writes {
lila.study.TreeBuilder(chapter.root, chapter.setup.variant)
})
val data = lila.study.JsonView.JsData(
study = studyJson,
analysis = analysis)
negotiate(
html = Ok(html.study.show(study, data, chat, sVersion)).fuccess,
api = _ => Ok(Json.obj(
"study" -> data.study,
"analysis" -> data.analysis)).fuccess
)
}
}
}
case WithChapter(s, chapter) => CanViewResult(s) {
import lila.tree.Node.partitionTreeJsonWriter
for {
chapters <- env.chapterRepo.orderedMetadataByStudy(s.id)
study <- env.api.resetIfOld(s, chapters)
_ <- Env.user.lightUserApi preloadMany study.members.ids.toList
_ = if (HTTPRequest isSynchronousHttp ctx.req) env.studyRepo.incViews(study)
pov = UserAnalysis.makePov(chapter.root.fen.value.some, chapter.setup.variant)
baseData <- Env.round.jsonView.userAnalysisJson(pov, ctx.pref, chapter.setup.orientation, owner = false)
studyJson <- env.jsonView(study, chapters, chapter, ctx.me)
data = lila.study.JsonView.JsData(
study = studyJson,
analysis = baseData ++ Json.obj(
"treeParts" -> partitionTreeJsonWriter.writes {
lila.study.TreeBuilder(chapter.root, chapter.setup.variant)
}))
res <- negotiate(
html = for {
chat <- chatOf(study)
sVersion <- env.version(study.id)
} yield Ok(html.study.show(study, data, chat, sVersion)),
api = _ => Ok(Json.obj(
"study" -> data.study,
"analysis" -> data.analysis)).fuccess
)
} yield res
}
} map NoCache

View File

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