Skip to content

Instantly share code, notes, and snippets.

@nicocavallo
Created September 8, 2017 21:37
Show Gist options
  • Save nicocavallo/65f44d146760509f4f5b3b43abb003a0 to your computer and use it in GitHub Desktop.
Save nicocavallo/65f44d146760509f4f5b3b43abb003a0 to your computer and use it in GitHub Desktop.
Contentful Scala Library
package nicocavallo.contentful
import java.time.ZonedDateTime
import com.contentful.java.cda._
import com.typesafe.config.Config
import org.reactivestreams.{Subscriber, Subscription}
import scala.concurrent.{Future, Promise}
import scala.language.postfixOps
import scala.util.Try
import scala.collection.JavaConverters._
object Contentful {
val CDATokenKey = "contentful.cda.token"
val SpaceIdKey = "contentful.space.id"
val PreviewKey= "contentful.preview"
private def preview(cdaToken: String, spaceId: String):CDAClient =
CDAClient
.builder()
.preview()
.setToken(cdaToken)
.setSpace(spaceId)
.build()
def apply(config:Config): CDAClient = {
val token = config.getString(CDATokenKey)
val space = config.getString(SpaceIdKey)
val isPreview = Option(config.getBoolean(PreviewKey)).getOrElse(false)
apply(token, space, isPreview)
}
private def apply(cdaToken: String, spaceId: String, isPreview: Boolean = false):CDAClient =
if (isPreview)
preview(cdaToken, spaceId)
else
CDAClient.builder()
.setToken(cdaToken)
.setSpace(spaceId)
.build()
def createdAt(entry:CDAEntry):ZonedDateTime =
ZonedDateTime.parse(entry.getAttribute("createdAt"))
def url(entry: CDAEntry, field: String): Option[String] = {
Try {
val a: CDAAsset = entry.getField(field)
a.url()
} toOption
}
}
trait Contentful {
implicit class CDAClientOps(client: CDAClient) {
def fetchEntries:ObserveQuery[CDAEntry] =
client.observe(classOf[CDAEntry])
}
implicit class FetchQueryOps[T <: CDAResource](query: ObserveQuery[T]) {
def async(): Future[Seq[T]] = {
val observable = query.all()
val p = Promise[Seq[T]]()
observable.subscribe(new Subscriber[CDAArray] {
var r:CDAArray = _
override def onSubscribe(s: Subscription): Unit = {
s.request(Long.MaxValue)
}
override def onError(t: Throwable): Unit = {
p.failure(t)
}
override def onComplete(): Unit = {
p.complete(Try(r.toSeq map {_.asInstanceOf[T]}))
}
override def onNext(t: CDAArray): Unit = {
r = t
}
})
p.future
}
}
implicit class CDAArrayOps(array:CDAArray) {
def toSeq: Seq[CDAResource] =
array.items().asScala
}
implicit class CDAEntryOps(entry: CDAEntry) {
def apply[T](key:String): T =
entry.getField(key)
def opt[T](key:String): Option[T] = Option(apply(key))
def string(key:String): String =
apply(key).toString
def strings(key:String): Set[String] =
opt[String](key)
.map[String](_.toString)
.map(_.split(",").toSet)
.getOrElse(Set.empty[String])
def orElse[T](key:String, default: => T): T =
opt(key).getOrElse(default)
def createdAt: ZonedDateTime =
Contentful.createdAt(entry)
def url(field: String, prefix: String = "https:"): Option[String] =
Contentful.url(entry, field).map(prefix + _)
}
}
package nicocavallo.contentful
import com.typesafe.config.{ConfigFactory, ConfigValueFactory}
import scala.concurrent.Await
import scala.concurrent.duration._
import scala.language.postfixOps
import scala.concurrent.ExecutionContext.Implicits.global
object MainApp extends App with Contentful {
val config = ConfigFactory
.empty()
.withValue(Contentful.CDATokenKey,
ConfigValueFactory.fromAnyRef("<my_cda_token>"))
.withValue(Contentful.SpaceIdKey,
ConfigValueFactory.fromAnyRef("<my_space_id>"))
.withValue(Contentful.PreviewKey,
ConfigValueFactory.fromAnyRef(false))
val client = Contentful(config)
val futureEntries = client
.fetchEntries
.async() map { _.toSeq}
val futureCreationDates = futureEntries map { _ map { _ createdAt } }
val futureTitles = futureEntries map { _ map { _.string("title") } }
val futureTitlesAndDates = for {
title <- futureTitles
date <- futureCreationDates
} yield (title, date)
futureTitlesAndDates map { case (titles, dates) =>
titles.zip(dates)
} foreach println
Await.result(futureTitlesAndDates, 5 seconds)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment