broadcast stream download endpoint
parent
861c8c9763
commit
a5a8ba23ba
|
@ -4,11 +4,13 @@ import play.api.data.Form
|
|||
import play.api.mvc._
|
||||
import scala.annotation.nowarn
|
||||
import scala.concurrent.duration._
|
||||
import scala.util.chaining._
|
||||
import views._
|
||||
|
||||
import lila.api.Context
|
||||
import lila.app._
|
||||
import lila.common.config.MaxPerSecond
|
||||
import lila.common.{ HTTPRequest, IpAddress }
|
||||
import lila.relay.{ RelayRound => RoundModel, RelayTour => TourModel }
|
||||
import lila.user.{ User => UserModel }
|
||||
|
||||
|
@ -124,6 +126,21 @@ final class RelayTour(env: Env, apiC: => Api) extends LilaController(env) {
|
|||
}
|
||||
}
|
||||
|
||||
def pgn(id: String) =
|
||||
Action.async { req =>
|
||||
env.relay.api tourById TourModel.Id(id) map {
|
||||
_ ?? { tour =>
|
||||
apiC.GlobalConcurrencyLimitPerIP(HTTPRequest ipAddress req)(
|
||||
env.relay.pgnStream(tour)
|
||||
) { source =>
|
||||
asAttachmentStream(s"${env.relay.pgnStream filename tour}.pgn")(
|
||||
Ok chunked source as pgnContentType
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def apiIndex =
|
||||
Action.async { implicit req =>
|
||||
apiC.jsonStream {
|
||||
|
@ -162,7 +179,7 @@ final class RelayTour(env: Env, apiC: => Api) extends LilaController(env) {
|
|||
key = "broadcast.tournament.user"
|
||||
)
|
||||
|
||||
private val CreateLimitPerIP = new lila.memo.RateLimit[lila.common.IpAddress](
|
||||
private val CreateLimitPerIP = new lila.memo.RateLimit[IpAddress](
|
||||
credits = 10 * 10,
|
||||
duration = 24.hour,
|
||||
key = "broadcast.tournament.ip"
|
||||
|
@ -180,7 +197,7 @@ final class RelayTour(env: Env, apiC: => Api) extends LilaController(env) {
|
|||
else if (me.hasTitle || me.isVerified) 5
|
||||
else 10
|
||||
CreateLimitPerUser(me.id, cost = cost) {
|
||||
CreateLimitPerIP(lila.common.HTTPRequest ipAddress req, cost = cost) {
|
||||
CreateLimitPerIP(HTTPRequest ipAddress req, cost = cost) {
|
||||
create
|
||||
}(fail.fuccess)
|
||||
}(fail.fuccess)
|
||||
|
|
|
@ -200,6 +200,7 @@ GET /broadcast controllers.RelayTour.index(page:
|
|||
GET /broadcast/new controllers.RelayTour.form
|
||||
POST /broadcast/new controllers.RelayTour.create
|
||||
GET /broadcast/:rs/$anyId<\w{8}> controllers.RelayTour.redirectOrApiTour(rs: String, anyId: String)
|
||||
GET /broadcast/$tourId<\w{8}>.pgn controllers.RelayTour.pgn(tourId: String)
|
||||
GET /broadcast/$tourId<\w{8}>/edit controllers.RelayTour.edit(tourId: String)
|
||||
POST /broadcast/$tourId<\w{8}>/edit controllers.RelayTour.update(tourId: String)
|
||||
GET /broadcast/$tourId<\w{8}>/new controllers.RelayRound.form(tourId: String)
|
||||
|
|
|
@ -14,6 +14,7 @@ final class Env(
|
|||
multiboard: lila.study.StudyMultiBoard,
|
||||
studyRepo: lila.study.StudyRepo,
|
||||
chapterRepo: lila.study.ChapterRepo,
|
||||
studyPgnDump: lila.study.PgnDump,
|
||||
gameRepo: lila.game.GameRepo,
|
||||
pgnDump: lila.game.PgnDump,
|
||||
gameProxy: lila.round.GameProxyRepo,
|
||||
|
@ -43,6 +44,8 @@ final class Env(
|
|||
|
||||
lazy val markup = wire[RelayMarkup]
|
||||
|
||||
lazy val pgnStream = wire[RelayPgnStream]
|
||||
|
||||
private lazy val sync = wire[RelaySync]
|
||||
|
||||
private lazy val formatApi = wire[RelayFormatApi]
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package lila.relay
|
||||
|
||||
import akka.stream.scaladsl._
|
||||
import org.joda.time.format.DateTimeFormat
|
||||
import scala.concurrent.duration._
|
||||
import scala.concurrent.ExecutionContext
|
||||
|
||||
import lila.study.{ PgnDump, Study, StudyRepo }
|
||||
|
||||
final class RelayPgnStream(
|
||||
roundRepo: RelayRoundRepo,
|
||||
studyRepo: StudyRepo,
|
||||
studyPgnDump: PgnDump
|
||||
)(implicit ec: ExecutionContext) {
|
||||
|
||||
def apply(tour: RelayTour): Source[String, _] =
|
||||
Source futureSource {
|
||||
roundRepo.idsByTourOrdered(tour) flatMap { ids =>
|
||||
studyRepo.byOrderedIds(ids.map(_.value).map(Study.Id)) map { studies =>
|
||||
Source(studies).flatMapConcat { studyPgnDump(_, flags) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val flags = PgnDump.WithFlags(comments = false, variations = false, clocks = true)
|
||||
private val fileR = """[\s,]""".r
|
||||
private val dateFormat = DateTimeFormat forPattern "yyyy.MM.dd"
|
||||
|
||||
def filename(tour: RelayTour): String = {
|
||||
val date = dateFormat.print(tour.syncedAt | tour.createdAt)
|
||||
fileR.replaceAllIn(s"lichess_broadcast_${tour.slug}_${tour.id}_$date", "")
|
||||
}
|
||||
}
|
|
@ -18,6 +18,14 @@ final private class RelayRoundRepo(val coll: Coll)(implicit ec: scala.concurrent
|
|||
.cursor[RelayRound]()
|
||||
.list(RelayTour.maxRelays)
|
||||
|
||||
def idsByTourOrdered(tour: RelayTour): Fu[List[RelayRound.Id]] =
|
||||
coll
|
||||
.find(selectors.tour(tour.id), $id(true).some)
|
||||
.sort(sort.chrono)
|
||||
.cursor[Bdoc]()
|
||||
.list(RelayTour.maxRelays)
|
||||
.map(_.flatMap(_.getAsOpt[RelayRound.Id]("_id")))
|
||||
|
||||
def lastByTour(tour: RelayTour): Fu[Option[RelayRound]] =
|
||||
coll
|
||||
.find(selectors tour tour.id)
|
||||
|
|
Loading…
Reference in New Issue