Last active
February 14, 2021 10:41
-
-
Save tjarvstrand/529ac4f9f93d87621aa99988469642b3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example | |
import akka.http.scaladsl.model.Uri | |
import enumeratum.{Circe => Enumeratum} | |
import enumeratum.Enum | |
import enumeratum.EnumEntry | |
import io.circe._ | |
import io.circe.generic.extras.auto._ | |
import io.circe.generic.extras.Configuration | |
import io.circe.generic.extras.semiauto.deriveConfiguredCodec | |
import io.circe.generic.semiauto.deriveCodec | |
import io.circe.syntax.EncoderOps | |
import java.time.ZonedDateTime | |
object Json { | |
def enumeratumCodec[T <: EnumEntry](e: Enum[T]): Codec[T] = Codec.from(Enumeratum.decoder(e), Enumeratum.encoder(e)) | |
implicit val UriCodec: Codec[Uri] = Codec.from(_.as[String].map(Uri(_)), _.toString.asJson) | |
implicit val ZonedDateTimeCodec: Codec[ZonedDateTime] = | |
Codec.from(_.as[String].map(ZonedDateTime.parse(_)), _.toString.asJson) | |
implicit val config: Configuration = Configuration.default | |
.withDiscriminator("type") | |
.withSnakeCaseConstructorNames | |
implicit val ActivityCodec: Codec[Activity] = deriveConfiguredCodec | |
implicit val ContentCodec: Codec[Activity.Content] = deriveCodec | |
implicit val ParentCodec: Codec[Activity.Parent] = deriveCodec | |
implicit val TargetCodec: Codec[Activity.Target] = deriveCodec | |
implicit val TargetTypeCodec: Codec[Activity.Target.Type] = enumeratumCodec(Activity.Target.Type) | |
implicit val UserCodec: Codec[User] = deriveConfiguredCodec | |
implicit val AttachmentCodec: Codec[Activity.Content.Attachment] = Codec.from( | |
cursor => cursor.get[Uri]("image") | |
.map(Activity.Content.Attachment.Image) | |
.orElse(cursor.get[Uri]("video").map(Activity.Content.Attachment.Video)), | |
{ | |
case image: Activity.Content.Attachment.Image => Map("image" -> image.image).asJson | |
case video: Activity.Content.Attachment.Video => Map("video" -> video.video).asJson | |
} | |
) | |
val ImplementedEvents = Set("activity_created", "activity_updated") | |
implicit val EventCodec: Codec[Event] = { | |
implicit val config: Configuration = Json.config | |
.withDiscriminator("event") | |
.copy(transformConstructorNames = Configuration.snakeCaseTransformation(_) match { | |
case n if ImplementedEvents.contains(n) => n | |
case _ => "unimplemented_event" | |
}) | |
deriveConfiguredCodec[Event] | |
} | |
} | |
sealed trait Event { | |
def unique_id: String | |
def timestamp: ZonedDateTime | |
def version: Int | |
} | |
object Event { | |
case class ActivityCreated(unique_id: String, | |
activity: Activity, | |
timestamp: ZonedDateTime, | |
version: Int = 2 | |
) extends Event | |
case class ActivityUpdated(unique_id: String, | |
activity: Activity, | |
timestamp: ZonedDateTime, | |
version: Int = 2) extends Event | |
case class UnimplementedEvent(unique_id: String, | |
timestamp: ZonedDateTime, | |
version: Int = 2) extends Event | |
} | |
object Activity { | |
case class Parent(id: String, author: User) | |
object Target { | |
sealed abstract class Type extends EnumEntry.Lowercase | |
object Type extends Enum[Type] { | |
case object Topic extends Type | |
case object Group extends Type | |
case object User extends Type | |
override def values: IndexedSeq[Type] = findValues | |
} | |
} | |
case class Target(id: String, `type`: Target.Type) | |
object Content { | |
sealed abstract class Attachment | |
object Attachment { | |
case class Video(video: Uri) extends Attachment | |
case class Image(image: Uri) extends Attachment | |
} | |
} | |
case class Content(language: String, | |
text: String, | |
enriched_text: String, | |
attachments: Seq[Content.Attachment]) | |
} | |
sealed trait Activity { | |
def id: String | |
def author: User | |
def content: Activity.Content | |
def target: Activity.Target | |
def created_at: ZonedDateTime | |
def version: String | |
} | |
case class Post(id: String, | |
author: User, | |
content: Activity.Content, | |
target: Activity.Target, | |
created_at: ZonedDateTime, | |
version: String = "2") extends Activity | |
case class Comment(id: String, | |
author: User, | |
content: Activity.Content, | |
target: Activity.Target, | |
parent: Activity.Parent, | |
created_at: ZonedDateTime, | |
version: String = "2") extends Activity | |
case class User(id: String, | |
display_name: String, | |
avatar: String, | |
identities: Map[String, String], | |
public_properties: Map[String, String], | |
private_properties: Map[String, String]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment