From 354d1500c1adfbcfdcd7cd6aaa1d165e22c2aaea Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Thu, 28 Dec 2017 21:10:15 -0500 Subject: [PATCH] streamer pager WIP --- app/controllers/Streamer.scala | 2 +- app/views/streamer/index.scala.html | 0 conf/routes | 2 +- modules/streamer/src/main/BsonHandlers.scala | 3 +- modules/streamer/src/main/Env.scala | 2 +- modules/streamer/src/main/Importer.scala | 1 + modules/streamer/src/main/Streamer.scala | 10 +++-- modules/streamer/src/main/StreamerPager.scala | 45 ++++++++++--------- modules/user/src/main/UserRepo.scala | 2 + 9 files changed, 39 insertions(+), 28 deletions(-) create mode 100644 app/views/streamer/index.scala.html diff --git a/app/controllers/Streamer.scala b/app/controllers/Streamer.scala index 085bb70c2b..3abf651e99 100644 --- a/app/controllers/Streamer.scala +++ b/app/controllers/Streamer.scala @@ -9,7 +9,7 @@ object Streamer extends LilaController { private def api = Env.streamer.api - def all(page: Int) = Open { implicit ctx => + def index(page: Int) = Open { implicit ctx => Env.streamer.pager(page) map { pager => ??? // Ok(html.streamer.index(pager)) diff --git a/app/views/streamer/index.scala.html b/app/views/streamer/index.scala.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/conf/routes b/conf/routes index 807dab0c9f..80927d977e 100644 --- a/conf/routes +++ b/conf/routes @@ -32,7 +32,7 @@ GET /games controllers.Tv.games GET /games/:chanKey controllers.Tv.gamesChannel(chanKey: String) # Streamer -GET /streamers controllers.Streamer.index +GET /streamers controllers.Streamer.index(page: Int ?= 1) # Relation POST /rel/follow/:userId controllers.Relation.follow(userId: String) diff --git a/modules/streamer/src/main/BsonHandlers.scala b/modules/streamer/src/main/BsonHandlers.scala index ebeb005226..95fa1e0360 100644 --- a/modules/streamer/src/main/BsonHandlers.scala +++ b/modules/streamer/src/main/BsonHandlers.scala @@ -13,9 +13,10 @@ private object BsonHandlers { implicit val StreamerNameBSONHandler = stringAnyValHandler[Streamer.Name](_.value, Streamer.Name.apply) implicit val StreamerDescriptionBSONHandler = stringAnyValHandler[Streamer.Description](_.value, Streamer.Description.apply) - import Streamer.{ Live, Twitch, YouTube } + import Streamer.{ Live, Twitch, YouTube, Sorting } implicit val StreamerLiveBSONHandler = Macros.handler[Live] implicit val StreamerTwitchBSONHandler = Macros.handler[Twitch] implicit val StreamerYouTubeBSONHandler = Macros.handler[YouTube] + implicit val StreamerSortingBSONHandler = Macros.handler[Sorting] implicit val StreamerBSONHandler = Macros.handler[Streamer] } diff --git a/modules/streamer/src/main/Env.scala b/modules/streamer/src/main/Env.scala index 2e75160d0b..af37e82f4a 100644 --- a/modules/streamer/src/main/Env.scala +++ b/modules/streamer/src/main/Env.scala @@ -11,7 +11,7 @@ final class Env( private val CollectionStreamer = config getString "collection.streamer" private val CollectionImage = config getString "collection.image" - private val MaxPerPage = config getString "paginator.max_per_page" + private val MaxPerPage = config getInt "paginator.max_per_page" private lazy val streamerColl = db(CollectionStreamer) private lazy val imageColl = db(CollectionImage) diff --git a/modules/streamer/src/main/Importer.scala b/modules/streamer/src/main/Importer.scala index 823906956f..42ba510e12 100644 --- a/modules/streamer/src/main/Importer.scala +++ b/modules/streamer/src/main/Importer.scala @@ -23,6 +23,7 @@ private final class Importer(api: StreamerApi, flagColl: Coll) { description = none, twitch = s.twitch option Twitch(s.streamerName, Live.empty), youTube = s.youtube option YouTube(s.streamerName, Live.empty), + sorting = Sorting.empty, createdAt = now, updatedAt = now )) diff --git a/modules/streamer/src/main/Streamer.scala b/modules/streamer/src/main/Streamer.scala index 7103d634a7..af3f667f74 100644 --- a/modules/streamer/src/main/Streamer.scala +++ b/modules/streamer/src/main/Streamer.scala @@ -14,6 +14,7 @@ case class Streamer( description: Option[Streamer.Description], twitch: Option[Streamer.Twitch], youTube: Option[Streamer.YouTube], + sorting: Streamer.Sorting, createdAt: DateTime, updatedAt: DateTime ) { @@ -37,6 +38,7 @@ object Streamer { description = none, twitch = none, youTube = none, + sorting = Sorting.empty, createdAt = DateTime.now, updatedAt = DateTime.now ) @@ -48,14 +50,14 @@ object Streamer { case class PicturePath(value: String) extends AnyVal with StringValue case class Name(value: String) extends AnyVal with StringValue case class Description(value: String) extends AnyVal with StringValue + case class Sorting(streaming: Boolean, onlineAt: Option[DateTime]) + object Sorting { val empty = Sorting(false, none) } case class Live(liveAt: Option[DateTime], checkedAt: Option[DateTime]) { def now = liveAt ?? { l => checkedAt ?? { l == } } } - object Live { - val empty = Live(none, none) - } + object Live { val empty = Live(none, none) } case class Twitch(userId: String, live: Live) object Twitch { private val UserIdRegex = """^(\w{2,24})$""".r @@ -77,4 +79,6 @@ object Streamer { case _ => none } } + + case class WithUser(streamer: Streamer, user: User) } diff --git a/modules/streamer/src/main/StreamerPager.scala b/modules/streamer/src/main/StreamerPager.scala index 257e750593..dfeb1d5410 100644 --- a/modules/streamer/src/main/StreamerPager.scala +++ b/modules/streamer/src/main/StreamerPager.scala @@ -1,39 +1,42 @@ package lila.streamer +import reactivemongo.api._ + import lila.common.paginator.Paginator import lila.db.dsl._ -import lila.db.paginator.{ Adapter, CachedAdapter } -import lila.user.User +import lila.db.paginator.{ Adapter } +import lila.user.{ User, UserRepo } final class StreamerPager( coll: Coll, maxPerPage: lila.common.MaxPerPage ) { - import BSONHandlers._ + import BsonHandlers._ - def finished(me: Option[User], page: Int) = paginator( - repo.selectors finished true, me, page, fuccess(9999).some - ) - - private def paginator( - selector: Bdoc, - me: Option[User], - page: Int, - nbResults: Option[Fu[Int]] = none - ): Fu[Paginator[Relay.WithStudyAndLiked]] = { - val adapter = new Adapter[Relay]( - collection = repo.coll, - selector = selector, + def apply(page: Int): Fu[Paginator[Streamer.WithUser]] = { + val adapter = new Adapter[Streamer]( + collection = coll, + selector = $doc("listed" -> Streamer.Listed(true)), projection = $empty, - sort = $sort desc "startedAt" - ) mapFutureList withStudy.andLiked(me) + sort = $doc( + "sorting.streaming" -> -1, + "sorting.onlineAt" -> -1 + ) + ) mapFutureList withUsers Paginator( - adapter = nbResults.fold(adapter) { nb => - new CachedAdapter(adapter, nb) - }, + adapter = adapter, currentPage = page, maxPerPage = maxPerPage.value ) } + + private def withUsers(streamers: Seq[Streamer]): Fu[Seq[Streamer.WithUser]] = + UserRepo.withColl { + _.optionsByOrderedIds[User, User.ID](streamers.map(_.id.value), ReadPreference.secondaryPreferred)(_.id) + } map { users => + streamers zip users collect { + case (streamer, Some(user)) => Streamer.WithUser(streamer, user) + } + } } diff --git a/modules/user/src/main/UserRepo.scala b/modules/user/src/main/UserRepo.scala index f6856e60c4..ba3d6e9717 100644 --- a/modules/user/src/main/UserRepo.scala +++ b/modules/user/src/main/UserRepo.scala @@ -22,6 +22,8 @@ object UserRepo { private[user] val coll = Env.current.userColl import reactivemongo.api.collections.bson.BSONBatchCommands.AggregationFramework.{ Match, Group, SumField } + def withColl[A](f: Coll => A): A = f(coll) + val normalize = User normalize _ def topNbGame(nb: Int): Fu[List[User]] =