create blog module
This commit is contained in:
parent
724e29e1a9
commit
cd7e29d865
|
@ -48,7 +48,7 @@ final class Env(
|
||||||
|
|
||||||
if (!Env.ai.ServerOnly) {
|
if (!Env.ai.ServerOnly) {
|
||||||
loginfo("[boot] Preloading modules")
|
loginfo("[boot] Preloading modules")
|
||||||
(Env.socket,
|
List(Env.socket,
|
||||||
Env.site,
|
Env.site,
|
||||||
Env.tournament,
|
Env.tournament,
|
||||||
Env.lobby,
|
Env.lobby,
|
||||||
|
@ -69,7 +69,8 @@ final class Env(
|
||||||
Env.evaluation,
|
Env.evaluation,
|
||||||
Env.chat,
|
Env.chat,
|
||||||
Env.puzzle,
|
Env.puzzle,
|
||||||
Env.tv)
|
Env.tv,
|
||||||
|
Env.blog)
|
||||||
loginfo("[boot] Preloading complete")
|
loginfo("[boot] Preloading complete")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,4 +125,5 @@ object Env {
|
||||||
def puzzle = lila.puzzle.Env.current
|
def puzzle = lila.puzzle.Env.current
|
||||||
def coordinate = lila.coordinate.Env.current
|
def coordinate = lila.coordinate.Env.current
|
||||||
def tv = lila.tv.Env.current
|
def tv = lila.tv.Env.current
|
||||||
|
def blog = lila.blog.Env.current
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,32 +2,40 @@ package controllers
|
||||||
|
|
||||||
import play.api.mvc._, Results._
|
import play.api.mvc._, Results._
|
||||||
|
|
||||||
import io.prismic.Document
|
import io.prismic.{ Document, DocumentLinkResolver, Fragment }
|
||||||
|
|
||||||
import lila.app._
|
import lila.app._
|
||||||
import views._
|
import views._
|
||||||
|
|
||||||
object Blog extends LilaController {
|
object Blog extends LilaController {
|
||||||
|
|
||||||
|
private def blogApi = Env.blog.api
|
||||||
|
|
||||||
def index(ref: Option[String]) = Open { implicit ctx =>
|
def index(ref: Option[String]) = Open { implicit ctx =>
|
||||||
Prismic.WithPrismic(ref) { implicit prismic =>
|
blogApi context ref flatMap { implicit prismic =>
|
||||||
prismic.api.forms("blog").ref(prismic.ref).pageSize(20).page(1).submit() map { response =>
|
blogApi recent 20 map { response =>
|
||||||
Ok(views.html.blog.index(response))
|
Ok(views.html.blog.index(response))
|
||||||
}
|
}
|
||||||
}(ctx.req)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def show(id: String, slug: String, ref: Option[String]) = Open { implicit ctx =>
|
def show(id: String, slug: String, ref: Option[String]) = Open { implicit ctx =>
|
||||||
Prismic.WithPrismic(ref) { implicit prismic =>
|
blogApi context ref flatMap { implicit prismic =>
|
||||||
Prismic getDocument id flatMap { maybeDocument =>
|
blogApi one id flatMap { maybeDocument =>
|
||||||
checkSlug(maybeDocument, slug) {
|
checkSlug(maybeDocument, slug) {
|
||||||
case Left(newSlug) => MovedPermanently(routes.Blog.show(id, newSlug, ref).url)
|
case Left(newSlug) => MovedPermanently(routes.Blog.show(id, newSlug, ref).url)
|
||||||
case Right(doc) => Ok(views.html.blog.show(doc))
|
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
|
// -- 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) =
|
private def checkSlug(document: Option[Document], slug: String)(callback: Either[String, Document] => SimpleResult)(implicit ctx: lila.api.Context) =
|
||||||
document.collect {
|
document.collect {
|
||||||
|
|
|
@ -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")
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
|
|
@ -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(
|
@layout(
|
||||||
title = "Blog") {
|
title = "Blog") {
|
||||||
|
|
|
@ -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">
|
<div class="meta">
|
||||||
@doc.getText("blog.date").map { date =>
|
@doc.getText("blog.date").map { date =>
|
||||||
<span data-icon="p"> @date</span>
|
<span data-icon="p"> @date</span>
|
||||||
|
|
|
@ -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 = {
|
@goodies = {
|
||||||
<br />
|
<br />
|
||||||
|
@ -30,5 +30,5 @@ goodies = goodies.some) {
|
||||||
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
|
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
|
||||||
})();
|
})();
|
||||||
</script>
|
</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>
|
||||||
}
|
}
|
||||||
|
|
40
modules/blog/src/main/BlogApi.scala
Normal file
40
modules/blog/src/main/BlogApi.scala
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
22
modules/blog/src/main/Env.scala
Normal file
22
modules/blog/src/main/Env.scala
Normal 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")
|
||||||
|
}
|
3
modules/blog/src/main/package.scala
Normal file
3
modules/blog/src/main/package.scala
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
package lila
|
||||||
|
|
||||||
|
package object blog extends PackageObject with WithPlay
|
|
@ -32,7 +32,7 @@ object ApplicationBuild extends Build {
|
||||||
gameSearch, timeline, forum, forumSearch, team, teamSearch,
|
gameSearch, timeline, forum, forumSearch, team, teamSearch,
|
||||||
ai, analyse, mod, monitor, site, round, lobby, setup,
|
ai, analyse, mod, monitor, site, round, lobby, setup,
|
||||||
importer, tournament, relation, report, pref, simulation,
|
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 moduleRefs = modules map projectToRef
|
||||||
lazy val moduleCPDeps = moduleRefs map { new sbt.ClasspathDependency(_, None) }
|
lazy val moduleCPDeps = moduleRefs map { new sbt.ClasspathDependency(_, None) }
|
||||||
|
@ -53,6 +53,10 @@ object ApplicationBuild extends Build {
|
||||||
libraryDependencies ++= provided(play.api, RM, PRM)
|
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(
|
lazy val evaluation = project("evaluation", Seq(
|
||||||
common, hub, db, user, game)).settings(
|
common, hub, db, user, game)).settings(
|
||||||
libraryDependencies ++= provided(play.api, RM, PRM)
|
libraryDependencies ++= provided(play.api, RM, PRM)
|
||||||
|
|
Loading…
Reference in a new issue