lila/modules/timeline/src/main/Entry.scala

144 lines
5.6 KiB
Scala

package lila.timeline
import org.joda.time.DateTime
import play.api.libs.json._
import reactivemongo.api.bson._
import scala.util.{ Failure, Success, Try }
import lila.common.Json.jodaWrites
import lila.db.dsl._
import lila.hub.actorApi.timeline._
case class Entry(
_id: BSONObjectID,
typ: String,
chan: Option[String],
data: Bdoc,
date: DateTime
) {
import Entry._
import atomBsonHandlers._
def similarTo(other: Entry) = typ == other.typ && data == other.data
case object Deprecated extends lila.base.LilaException {
val message = "Deprecated timeline entry"
}
lazy val decode: Option[Atom] = Try(typ match {
case "follow" => followHandler.readTry(data).get
case "team-join" => teamJoinHandler.readTry(data).get
case "team-create" => teamCreateHandler.readTry(data).get
case "forum-post" => forumPostHandler.readTry(data).get
case "tour-join" => tourJoinHandler.readTry(data).get
case "game-end" => gameEndHandler.readTry(data).get
case "simul-create" => simulCreateHandler.readTry(data).get
case "simul-join" => simulJoinHandler.readTry(data).get
case "study-create" => studyCreateHandler.readTry(data).get
case "study-like" => studyLikeHandler.readTry(data).get
case "plan-start" => planStartHandler.readTry(data).get
case "blog-post" => blogPostHandler.readTry(data).get
case "stream-start" => streamStartHandler.readTry(data).get
case "note-create" => throw Deprecated
case _ => sys error s"Unhandled atom type: $typ"
}) match {
case Success(atom) => Some(atom)
case Failure(Deprecated) => none
case Failure(err) =>
lila.log("timeline").warn(err.getMessage)
none
}
def userIds = decode.??(_.userIds)
def okForKid = decode ?? (_.okForKid)
}
object Entry {
case class ForUsers(entry: Entry, userIds: List[String])
private def toBson[A](data: A)(implicit writer: BSONDocumentWriter[A]) = writer.writeTry(data).get
private[timeline] def make(data: Atom): Entry = {
import atomBsonHandlers._
data match {
case d: Follow => "follow" -> toBson(d)
case d: TeamJoin => "team-join" -> toBson(d)
case d: TeamCreate => "team-create" -> toBson(d)
case d: ForumPost => "forum-post" -> toBson(d)
case d: TourJoin => "tour-join" -> toBson(d)
case d: GameEnd => "game-end" -> toBson(d)
case d: SimulCreate => "simul-create" -> toBson(d)
case d: SimulJoin => "simul-join" -> toBson(d)
case d: StudyCreate => "study-create" -> toBson(d)(studyCreateHandler)
case d: StudyLike => "study-like" -> toBson(d)(studyLikeHandler)
case d: PlanStart => "plan-start" -> toBson(d)(planStartHandler)
case d: BlogPost => "blog-post" -> toBson(d)(blogPostHandler)
case d: StreamStart => "stream-start" -> toBson(d)(streamStartHandler)
}
} match {
case (typ, bson) =>
new Entry(BSONObjectID.generate(), typ, data.channel.some, bson, DateTime.now)
}
object atomBsonHandlers {
implicit val followHandler = Macros.handler[Follow]
implicit val teamJoinHandler = Macros.handler[TeamJoin]
implicit val teamCreateHandler = Macros.handler[TeamCreate]
implicit val forumPostHandler = Macros.handler[ForumPost]
implicit val tourJoinHandler = Macros.handler[TourJoin]
implicit val gameEndHandler = Macros.handler[GameEnd]
implicit val simulCreateHandler = Macros.handler[SimulCreate]
implicit val simulJoinHandler = Macros.handler[SimulJoin]
implicit val studyCreateHandler = Macros.handler[StudyCreate]
implicit val studyLikeHandler = Macros.handler[StudyLike]
implicit val planStartHandler = Macros.handler[PlanStart]
implicit val blogPostHandler = Macros.handler[BlogPost]
implicit val streamStartHandler = Macros.handler[StreamStart]
}
object atomJsonWrite {
implicit val followWrite = Json.writes[Follow]
implicit val teamJoinWrite = Json.writes[TeamJoin]
implicit val teamCreateWrite = Json.writes[TeamCreate]
implicit val forumPostWrite = Json.writes[ForumPost]
implicit val tourJoinWrite = Json.writes[TourJoin]
implicit val gameEndWrite = Json.writes[GameEnd]
implicit val simulCreateWrite = Json.writes[SimulCreate]
implicit val simulJoinWrite = Json.writes[SimulJoin]
implicit val studyCreateWrite = Json.writes[StudyCreate]
implicit val studyLikeWrite = Json.writes[StudyLike]
implicit val planStartWrite = Json.writes[PlanStart]
implicit val blogPostWrite = Json.writes[BlogPost]
implicit val streamStartWrite = Json.writes[StreamStart]
implicit val atomWrite = Writes[Atom] {
case d: Follow => followWrite writes d
case d: TeamJoin => teamJoinWrite writes d
case d: TeamCreate => teamCreateWrite writes d
case d: ForumPost => forumPostWrite writes d
case d: TourJoin => tourJoinWrite writes d
case d: GameEnd => gameEndWrite writes d
case d: SimulCreate => simulCreateWrite writes d
case d: SimulJoin => simulJoinWrite writes d
case d: StudyCreate => studyCreateWrite writes d
case d: StudyLike => studyLikeWrite writes d
case d: PlanStart => planStartWrite writes d
case d: BlogPost => blogPostWrite writes d
case d: StreamStart => streamStartWrite writes d
}
}
implicit val EntryBSONHandler = Macros.handler[Entry]
implicit val entryWrites = OWrites[Entry] { e =>
import atomJsonWrite._
Json.obj(
"type" -> e.typ,
"data" -> e.decode,
"date" -> e.date
)
}
}