create blog module

This commit is contained in:
Thibault Duplessis 2014-05-31 21:03:04 +02:00
parent 724e29e1a9
commit cd7e29d865
10 changed files with 93 additions and 139 deletions

View file

@ -48,7 +48,7 @@ final class Env(
if (!Env.ai.ServerOnly) {
loginfo("[boot] Preloading modules")
(Env.socket,
List(Env.socket,
Env.site,
Env.tournament,
Env.lobby,
@ -69,7 +69,8 @@ final class Env(
Env.evaluation,
Env.chat,
Env.puzzle,
Env.tv)
Env.tv,
Env.blog)
loginfo("[boot] Preloading complete")
}
@ -124,4 +125,5 @@ object Env {
def puzzle = lila.puzzle.Env.current
def coordinate = lila.coordinate.Env.current
def tv = lila.tv.Env.current
def blog = lila.blog.Env.current
}

View file

@ -2,32 +2,40 @@ package controllers
import play.api.mvc._, Results._
import io.prismic.Document
import io.prismic.{ Document, DocumentLinkResolver, Fragment }
import lila.app._
import views._
object Blog extends LilaController {
private def blogApi = Env.blog.api
def index(ref: Option[String]) = Open { implicit ctx =>
Prismic.WithPrismic(ref) { implicit prismic =>
prismic.api.forms("blog").ref(prismic.ref).pageSize(20).page(1).submit() map { response =>
blogApi context ref flatMap { implicit prismic =>
blogApi recent 20 map { response =>
Ok(views.html.blog.index(response))
}
}(ctx.req)
}
}
def show(id: String, slug: String, ref: Option[String]) = Open { implicit ctx =>
Prismic.WithPrismic(ref) { implicit prismic =>
Prismic getDocument id flatMap { maybeDocument =>
blogApi context ref flatMap { implicit prismic =>
blogApi one id flatMap { maybeDocument =>
checkSlug(maybeDocument, slug) {
case Left(newSlug) => MovedPermanently(routes.Blog.show(id, newSlug, ref).url)
case Right(doc) => Ok(views.html.blog.show(doc))
}
}
}(ctx.req)
}
}
implicit def makeLinkResolver(prismicApi: io.prismic.Api, ref: Option[String]): DocumentLinkResolver =
DocumentLinkResolver(prismicApi) {
case (Fragment.DocumentLink(id, _, _, slug, false), _) => routes.Blog.show(id, slug, ref).url
case (Fragment.DocumentLink(_, _, _, _, true), _) => routes.Lobby.home.url
}
// -- Helper: Check if the slug is valid and redirect to the most recent version id needed
private def checkSlug(document: Option[Document], slug: String)(callback: Either[String, Document] => SimpleResult)(implicit ctx: lila.api.Context) =
document.collect {

View file

@ -1,125 +0,0 @@
package controllers
import play.api._
import play.api.mvc._
import play.api.libs.json._
import play.api.libs.ws._
import play.api.libs.concurrent.Execution.Implicits._
import scala.concurrent._
import io.prismic.{ Api => PrismicApi, _ }
object Prismic {
private val ACCESS_TOKEN = "PRISMIC_TK"
private val Cache = BuiltInCache(200)
private val Logger = (level: Symbol, message: String) => level match {
case 'DEBUG => play.api.Logger("prismic").debug(message)
case 'ERROR => play.api.Logger("prismic").error(message)
case _ => play.api.Logger("prismic").info(message)
}
private lazy val config = lila.common.PlayApp loadConfig "prismic"
private lazy val prismicToken = scala.util.Try(config getString "token").toOption
private lazy val apiUrl = config getString "api"
def linkResolver(api: PrismicApi, ref: Option[String])(implicit request: RequestHeader) = DocumentLinkResolver(api) {
case (Fragment.DocumentLink(id, docType, tags, slug, false), maybeBookmarked) =>
routes.Blog.show(id, slug, ref).absoluteURL()
case (link@Fragment.DocumentLink(_, _, _, _, true), _) =>
routes.Lobby.home.absoluteURL()
}
// Compute the callback URL to use for the OAuth worklow
// private def callbackUrl(implicit rh: RequestHeader) =
// routes.Prismic.callback(code = None, redirect_uri = rh.headers.get("referer")).absoluteURL()
// -- A Prismic context that help to keep the reference to useful primisc.io contextual data
case class Context(api: PrismicApi, ref: String, accessToken: Option[String], linkResolver: DocumentLinkResolver) {
def maybeRef = Option(ref).filterNot(_ == api.master.ref)
def hasPrivilegedAccess = accessToken.isDefined
}
// -- Build a Prismic context
def buildContext(ref: Option[String])(implicit request: RequestHeader) =
apiHome(request.session.get(ACCESS_TOKEN).orElse(prismicToken)) map { api =>
Context(api,
ref.map(_.trim).filterNot(_.isEmpty).getOrElse(api.master.ref),
request.session.get(ACCESS_TOKEN),
linkResolver(api, ref.filterNot(_ == api.master.ref))(request))
}
def WithPrismic(ref: Option[String] = None)(block: Context => Future[SimpleResult])(implicit req: RequestHeader): Future[SimpleResult] =
buildContext(ref) flatMap block
// -- Fetch the API entry document
def apiHome(accessToken: Option[String] = None) =
PrismicApi.get(apiUrl, accessToken = accessToken, cache = Cache, logger = Logger)
// -- Helper: Retrieve a single document by Id
def getDocument(id: String)(implicit ctx: Prismic.Context): Future[Option[Document]] =
ctx.api.forms("everything")
.query(s"""[[:d = at(document.id, "$id")]]""")
.ref(ctx.ref).submit() map (_.results.headOption)
// -- Helper: Retrieve several documents by Id
def getDocuments(ids: String*)(implicit ctx: Prismic.Context): Future[Seq[Document]] =
ids match {
case Nil => Future.successful(Nil)
case ids => ctx.api.forms("everything")
.query(s"""[[:d = any(document.id, ${ids.mkString("[\"", "\",\"", "\"]")})]]""")
.ref(ctx.ref).submit() map (_.results)
}
// -- Helper: Retrieve a single document from its bookmark
def getBookmark(bookmark: String)(implicit ctx: Prismic.Context): Future[Option[Document]] =
ctx.api.bookmarks.get(bookmark).map(id => getDocument(id)).getOrElse(Future.successful(None))
// --
// -- OAuth actions
// --
// def signin = Action.async { implicit req =>
// apiHome().map(_.oauthInitiateEndpoint).recover {
// case InvalidToken(_, url) => url
// case AuthorizationNeeded(_, url) => url
// } map { url =>
// Redirect(url, Map(
// "client_id" -> Seq(config("prismic.clientId")),
// "redirect_uri" -> Seq(callbackUrl),
// "scope" -> Seq("master+releases")
// ))
// }
// }
// def signout = Action {
// Redirect(routes.Application.index(ref = None)).withNewSession
// }
// def callback(code: Option[String], redirect_uri: Option[String]) =
// Action.async { implicit req =>
// (
// for {
// api <- apiHome()
// tokenResponse <- WS.url(api.oauthTokenEndpoint).post(Map(
// "grant_type" -> Seq("authorization_code"),
// "code" -> Seq(code.get),
// "redirect_uri" -> Seq(callbackUrl),
// "client_id" -> Seq(config("prismic.clientId")),
// "client_secret" -> Seq(config("prismic.clientSecret"))
// )).filter(_.status == 200).map(_.json)
// } yield {
// Redirect(redirect_uri.getOrElse(routes.Application.index(ref = None).url)).withSession(
// ACCESS_TOKEN -> (tokenResponse \ "access_token").as[String]
// )
// }
// ).recover {
// case x: Throwable =>
// Logger('ERROR, s"""Can't retrieve the OAuth token for code $code: ${x.getMessage}""".stripMargin)
// Unauthorized("Can't sign you in")
// }
// }
}

View file

@ -1,4 +1,4 @@
@(pager: io.prismic.Response)(implicit ctx: Context, prismic: Prismic.Context)
@(pager: io.prismic.Response)(implicit ctx: Context, prismic: lila.blog.BlogApi.Context)
@layout(
title = "Blog") {

View file

@ -1,4 +1,4 @@
@(doc: io.prismic.Document)(implicit ctx: Context, prismic: Prismic.Context)
@(doc: io.prismic.Document)(implicit ctx: Context, prismic: lila.blog.BlogApi.Context)
<div class="meta">
@doc.getText("blog.date").map { date =>
<span data-icon="p"> @date</span>

View file

@ -1,4 +1,4 @@
@(doc: io.prismic.Document)(implicit ctx: Context, prismic: Prismic.Context)
@(doc: io.prismic.Document)(implicit ctx: Context, prismic: lila.blog.BlogApi.Context)
@goodies = {
<br />
@ -30,5 +30,5 @@ goodies = goodies.some) {
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
})();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments.</a></noscript>
<noscript>Please enable JavaScript to view the comments.</noscript>
}

View file

@ -0,0 +1,40 @@
package lila.blog
import io.prismic._
import play.api.mvc.RequestHeader
final class BlogApi(prismicUrl: String, collection: String) {
def recent(nb: Int)(implicit ctx: BlogApi.Context) =
ctx.api.forms(collection).ref(ctx.ref).pageSize(nb).page(1).submit()
def one(id: String)(implicit ctx: BlogApi.Context) =
ctx.api.forms(collection)
.query(s"""[[:d = at(document.id, "$id")]]""")
.ref(ctx.ref).submit() map (_.results.headOption)
// -- Build a Prismic context
def context(ref: Option[String])(implicit linkResolver: (Api, Option[String]) => DocumentLinkResolver) =
prismicApi map { api =>
BlogApi.Context(
api,
ref.map(_.trim).filterNot(_.isEmpty).getOrElse(api.master.ref),
linkResolver(api, ref))
}
private val cache = BuiltInCache(200)
private val logger = (level: Symbol, message: String) => level match {
case 'DEBUG => play.api.Logger("prismic") debug message
case 'ERROR => play.api.Logger("prismic") error message
case _ => play.api.Logger("prismic") info message
}
private def prismicApi = Api.get(prismicUrl, cache = cache, logger = logger)
}
object BlogApi {
case class Context(api: Api, ref: String, linkResolver: DocumentLinkResolver) {
def maybeRef = Option(ref).filterNot(_ == api.master.ref)
}
}

View file

@ -0,0 +1,22 @@
package lila.blog
import com.typesafe.config.Config
import lila.common.PimpedConfig._
final class Env(
config: Config) {
private val PrismicApiUrl = config getString "prismic.api_url"
private val PrismicCollection = config getString "prismic.collection"
lazy val api = new BlogApi(
prismicUrl = PrismicApiUrl,
collection = PrismicCollection)
}
object Env {
lazy val current: Env = "[boot] blog" describes new Env(
config = lila.common.PlayApp loadConfig "blog")
}

View file

@ -0,0 +1,3 @@
package lila
package object blog extends PackageObject with WithPlay

View file

@ -32,7 +32,7 @@ object ApplicationBuild extends Build {
gameSearch, timeline, forum, forumSearch, team, teamSearch,
ai, analyse, mod, monitor, site, round, lobby, setup,
importer, tournament, relation, report, pref, simulation,
evaluation, chat, puzzle, tv, coordinate)
evaluation, chat, puzzle, tv, coordinate, blog)
lazy val moduleRefs = modules map projectToRef
lazy val moduleCPDeps = moduleRefs map { new sbt.ClasspathDependency(_, None) }
@ -53,6 +53,10 @@ object ApplicationBuild extends Build {
libraryDependencies ++= provided(play.api, RM, PRM)
)
lazy val blog = project("blog", Seq(common, message)).settings(
libraryDependencies ++= provided(play.api, prismic)
)
lazy val evaluation = project("evaluation", Seq(
common, hub, db, user, game)).settings(
libraryDependencies ++= provided(play.api, RM, PRM)