publish official broadcast API

pull/6962/head
Thibault Duplessis 2020-07-09 00:10:29 +02:00
parent c3c9fb8d9b
commit 579abeba57
8 changed files with 59 additions and 46 deletions

View File

@ -1,19 +1,20 @@
package controllers
import play.api.mvc._
import play.api.data.Form
import play.api.libs.json._
import play.api.mvc._
import scala.annotation.nowarn
import lila.api.Context
import lila.app._
import lila.common.config.MaxPerSecond
import lila.relay.{ Relay => RelayModel, RelayForm }
import lila.user.{ User => UserModel }
import views._
final class Relay(
env: Env,
studyC: => Study
studyC: => Study,
apiC: => Api
) extends LilaController(env) {
def index(page: Int) =
@ -54,7 +55,7 @@ final class Relay(
err => BadRequest(apiFormError(err)).fuccess,
setup =>
env.relay.api.create(setup, me) map { relay =>
Ok(asJson(relay)) as JSON
Ok(env.relay.jsonView.admin(relay)) as JSON
}
)
)
@ -87,7 +88,7 @@ final class Relay(
case Some(res) =>
res.fold(
{ case (_, err) => BadRequest(apiFormError(err)) },
relay => Ok(asJson(relay)) as JSON
relay => Ok(env.relay.jsonView.admin(relay)) as JSON
)
}
)
@ -136,7 +137,7 @@ final class Relay(
me =>
env.relay.api.byIdAndContributor(id, me) map {
case None => NotFound(jsonError("No such broadcast"))
case Some(relay) => Ok(asJson(relay)) as JSON
case Some(relay) => Ok(env.relay.jsonView.admin(relay)) as JSON
}
)
@ -166,11 +167,12 @@ final class Relay(
}
}
private def asJson(relay: RelayModel) =
Json.obj(
"broadcast" -> env.relay.jsonView.apiShow(relay),
"url" -> s"${env.net.baseUrl}${showRoute(relay)}"
)
def apiIndex =
Action.async { implicit req =>
apiC.jsonStream {
env.relay.api.officialStream(MaxPerSecond(20), getInt("nb", req) | 20)
}.fuccess
}
private def WithRelay(slug: String, id: String)(
f: RelayModel => Fu[Result]

View File

@ -576,6 +576,7 @@ POST /api/challenge/:user controllers.Challenge.apiCreate(user: Str
POST /api/challenge/$id<\w{8}>/accept controllers.Challenge.apiAccept(id: String)
POST /api/challenge/$id<\w{8}>/decline controllers.Challenge.apiDecline(id: String)
GET /api/cloud-eval controllers.Api.cloudEval
GET /api/broadcast controllers.Relay.apiIndex
GET /api/games/user/:username controllers.Game.apiExportByUser(username: String)

View File

@ -13,7 +13,8 @@ final class Env(
studyApi: lila.study.StudyApi,
chapterRepo: lila.study.ChapterRepo,
cacheApi: lila.memo.CacheApi,
slackApi: lila.slack.SlackApi
slackApi: lila.slack.SlackApi,
baseUrl: BaseUrl
)(implicit
ec: scala.concurrent.ExecutionContext,
system: ActorSystem
@ -27,7 +28,7 @@ final class Env(
private lazy val withStudy = wire[RelayWithStudy]
lazy val jsonView = new JsonView(new RelayMarkup)
lazy val jsonView = new JsonView(new RelayMarkup, baseUrl)
lazy val api: RelayApi = wire[RelayApi]

View File

@ -3,23 +3,26 @@ package lila.relay
import play.api.libs.json._
import lila.common.Json.jodaWrites
import lila.common.config.BaseUrl
final class JsonView(markup: RelayMarkup) {
final class JsonView(markup: RelayMarkup, baseUrl: BaseUrl) {
import JsonView._
implicit val relayWrites = OWrites[Relay] { r =>
implicit private val relayWrites = OWrites[Relay] { r =>
Json
.obj(
"id" -> r.id,
"slug" -> r.slug,
"url" -> s"$baseUrl/broadcast/${r.slug}/${r.id}",
"name" -> r.name,
"description" -> r.description,
"ownerId" -> r.ownerId,
"sync" -> r.sync
"description" -> r.description
)
.add("credit", r.credit)
.add("markup" -> r.markup.map(markup.apply))
.add("startsAt" -> r.startsAt)
.add("startedAt" -> r.startedAt)
.add("official" -> r.official.option(true))
.add("finished" -> r.finished.option(true))
}
def makeData(relay: Relay, studyData: lila.study.JsonView.JsData) =
@ -29,14 +32,13 @@ final class JsonView(markup: RelayMarkup) {
analysis = studyData.analysis
)
def apiShow(r: Relay) =
relayWrites
.writes(r)
def public(r: Relay) = relayWrites writes r
def admin(r: Relay) =
public(r)
.add("markdown" -> r.markup)
.add("startsAt" -> r.startsAt)
.add("startedAt" -> r.startedAt)
.add("official" -> r.official.option(true))
.add("throttle" -> r.sync.delay)
.add("sync" -> r.sync.some)
}
object JsonView {

View File

@ -1,11 +1,14 @@
package lila.relay
import akka.stream.scaladsl.Source
import org.joda.time.DateTime
import ornicar.scalalib.Zero
import play.api.libs.json._
import reactivemongo.api.bson._
import scala.concurrent.duration._
import scala.util.chaining._
import lila.common.config.MaxPerSecond
import lila.db.dsl._
import lila.study.{ Settings, Study, StudyApi, StudyMaker }
import lila.user.User
@ -16,7 +19,7 @@ final class RelayApi(
withStudy: RelayWithStudy,
jsonView: JsonView,
formatApi: RelayFormatApi
)(implicit ec: scala.concurrent.ExecutionContext) {
)(implicit ec: scala.concurrent.ExecutionContext, mat: akka.stream.Materializer) {
import BSONHandlers._
import lila.study.BSONHandlers.LikesBSONHandler
@ -114,6 +117,13 @@ final class RelayApi(
def getOngoing(id: Relay.Id): Fu[Option[Relay]] =
repo.coll.one[Relay]($doc("_id" -> id, "finished" -> false))
def officialStream(perSecond: MaxPerSecond, nb: Int): Source[JsObject, _] =
repo
.officialCursor(perSecond.value)
.documentSource(nb)
.throttle(perSecond.value, 1.second)
.map(jsonView.public)
private[relay] def autoStart: Funit =
repo.coll.ext
.find(
@ -158,7 +168,7 @@ final class RelayApi(
repo.coll.delete.one($id(Relay.Id(studyId))).void
private[relay] def publishRelay(relay: Relay): Funit =
sendToContributors(relay.id, "relayData", jsonView.relayWrites writes relay)
sendToContributors(relay.id, "relayData", jsonView admin relay)
private def sendToContributors(id: Relay.Id, t: String, msg: JsObject): Funit =
studyApi members Study.Id(id.value) map {

View File

@ -2,6 +2,8 @@ package lila.relay
import org.joda.time.DateTime
import reactivemongo.api.bson._
import reactivemongo.akkastream.{ cursorProducer, AkkaStreamCursor }
import reactivemongo.api.ReadPreference
import lila.db.dsl._
@ -29,34 +31,29 @@ final private class RelayRepo(val coll: Coll)(implicit ec: scala.concurrent.Exec
.sort($sort asc "startedAt")
.list[Relay]()
def finished =
private[relay] def officialCursor(batchSize: Int): AkkaStreamCursor[Relay] =
coll.ext
.find(
$doc(
selectors finished true
)
)
.sort($sort desc "startedAt")
.list[Relay]()
.find(selectors officialOption true)
.sort($sort desc "startsAt")
.batchSize(batchSize)
.cursor[Relay](ReadPreference.secondaryPreferred)
private[relay] object selectors {
def officialOption(v: Boolean) = $doc("official" -> v.option(true))
def scheduled(official: Boolean) =
$doc(
officialOption(official) ++ $doc(
"startsAt" $gt DateTime.now.minusHours(1),
"startedAt" $exists false,
"official" -> official.option(true)
"startedAt" $exists false
)
def ongoing(official: Boolean) =
$doc(
officialOption(official) ++ $doc(
"startedAt" $exists true,
"finished" -> false,
"official" -> official.option(true)
"finished" -> false
)
def finished(official: Boolean) =
$doc(
officialOption(official) ++ $doc(
"startedAt" $exists true,
"finished" -> true,
"official" -> official.option(true)
"finished" -> true
)
}
}

View File

@ -1,6 +1,6 @@
export interface RelayData {
id: string;
slug: string;
url: string;
description: string;
markup?: string;
credit?: string;

View File

@ -12,7 +12,7 @@ export default function(ctrl: RelayCtrl): VNode | undefined {
h('span.text', { attrs: dataIcon('') }, 'Broadcast manager'),
h('a', {
attrs: {
href: `/broadcast/${ctrl.data.slug}/${ctrl.data.id}/edit`,
href: `${ctrl.data.url}/edit`,
'data-icon': '%'
}
})