export study chapter as gif (closes #6180)
parent
b56401de36
commit
9a7170f6b2
|
@ -406,7 +406,7 @@ final class Study(
|
|||
lila.mon.export.pgn.study.increment()
|
||||
env.study.pgnDump(study) map { pgns =>
|
||||
Ok(pgns.mkString("\n\n\n")).withHeaders(
|
||||
CONTENT_DISPOSITION -> ("attachment; filename=" + (env.study.pgnDump filename study))
|
||||
CONTENT_DISPOSITION -> s"attachment; filename=${env.study.pgnDump filename study}.pgn"
|
||||
) as pgnContentType
|
||||
}
|
||||
}
|
||||
|
@ -422,8 +422,7 @@ final class Study(
|
|||
lila.mon.export.pgn.studyChapter.increment()
|
||||
Ok(env.study.pgnDump.ofChapter(study, chapter).toString)
|
||||
.withHeaders(
|
||||
CONTENT_DISPOSITION -> ("attachment; filename=" + (env.study.pgnDump
|
||||
.filename(study, chapter)))
|
||||
CONTENT_DISPOSITION -> s"attachment; filename=${env.study.pgnDump.filename(study, chapter)}.pgn"
|
||||
)
|
||||
.as(pgnContentType)
|
||||
.fuccess
|
||||
|
@ -432,6 +431,23 @@ final class Study(
|
|||
}
|
||||
}
|
||||
|
||||
def chapterGif(id: String, chapterId: String) = Open { implicit ctx =>
|
||||
env.study.api.byIdWithChapter(id, chapterId) flatMap {
|
||||
_.fold(notFound) {
|
||||
case WithChapter(study, chapter) =>
|
||||
CanViewResult(study) {
|
||||
env.study.gifExport.ofChapter(chapter) map { stream =>
|
||||
Ok.chunked(stream)
|
||||
.withHeaders(
|
||||
noProxyBufferHeader,
|
||||
CONTENT_DISPOSITION -> s"attachment; filename=${env.study.pgnDump.filename(study, chapter)}.gif"
|
||||
) as "image/gif"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def multiBoard(id: String, page: Int) = Open { implicit ctx =>
|
||||
OptionFuResult(env.study.api byId id) { study =>
|
||||
CanViewResult(study) {
|
||||
|
|
|
@ -119,6 +119,7 @@ POST /study controllers.Study.create
|
|||
POST /study/as controllers.Study.createAs
|
||||
GET /study/$id<\w{8}>.pgn controllers.Study.pgn(id: String)
|
||||
GET /study/$id<\w{8}>/$chapterId<\w{8}>.pgn controllers.Study.chapterPgn(id: String, chapterId: String)
|
||||
GET /study/$id<\w{8}>/$chapterId<\w{8}>.gif controllers.Study.chapterGif(id: String, chapterId: String)
|
||||
POST /study/$id<\w{8}>/delete controllers.Study.delete(id: String)
|
||||
GET /study/$id<\w{8}>/clone controllers.Study.cloneStudy(id: String)
|
||||
POST /study/$id<\w{8}>/cloneAplly controllers.Study.cloneApply(id: String)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package lila.study
|
||||
|
||||
import com.softwaremill.macwire._
|
||||
import play.api.Configuration
|
||||
import play.api.libs.ws.WSClient
|
||||
|
||||
import lila.common.config._
|
||||
|
@ -9,6 +10,7 @@ import lila.user.User
|
|||
|
||||
@Module
|
||||
final class Env(
|
||||
appConfig: Configuration,
|
||||
ws: WSClient,
|
||||
lightUserApi: lila.user.LightUserApi,
|
||||
gamePgnDump: lila.game.PgnDump,
|
||||
|
@ -78,6 +80,8 @@ final class Env(
|
|||
|
||||
lazy val pgnDump = wire[PgnDump]
|
||||
|
||||
lazy val gifExport = new GifExport(ws, appConfig.get[String]("game.gifUrl"))
|
||||
|
||||
def cli = new lila.common.Cli {
|
||||
def process = {
|
||||
case "study" :: "rank" :: "reset" :: Nil =>
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
package lila.study
|
||||
|
||||
import akka.stream.scaladsl._
|
||||
import akka.util.ByteString
|
||||
import play.api.libs.json._
|
||||
import play.api.libs.ws.WSClient
|
||||
import org.joda.time.format.DateTimeFormat
|
||||
|
||||
final class GifExport(
|
||||
ws: WSClient,
|
||||
url: String
|
||||
)(implicit ec: scala.concurrent.ExecutionContext) {
|
||||
def ofChapter(chapter: Chapter): Fu[Source[ByteString, _]] =
|
||||
ws.url(s"$url/game.gif")
|
||||
.withMethod("POST")
|
||||
.addHttpHeaders("Content-Type" -> "application/json")
|
||||
.withBody(
|
||||
Json.obj(
|
||||
"delay" -> 80,
|
||||
"orientation" -> chapter.setup.orientation.name,
|
||||
"white" -> List(
|
||||
chapter.tags(_.WhiteTitle),
|
||||
chapter.tags(_.White),
|
||||
chapter.tags(_.WhiteElo).map(elo => s"($elo)")
|
||||
).flatten.mkString(" "),
|
||||
"black" -> List(
|
||||
chapter.tags(_.BlackTitle),
|
||||
chapter.tags(_.Black),
|
||||
chapter.tags(_.BlackElo).map(elo => s"($elo)")
|
||||
).flatten.mkString(" "),
|
||||
"frames" -> (chapter.root :: chapter.root.mainline).map { node =>
|
||||
Json
|
||||
.obj(
|
||||
"fen" -> node.fen.value
|
||||
)
|
||||
.add("check", node.check option true)
|
||||
.add("lastMove", node.moveOption.map(_.uci.uci))
|
||||
}
|
||||
)
|
||||
)
|
||||
.stream() flatMap {
|
||||
case res if res.status != 200 =>
|
||||
logger.warn(s"GifExport study ${chapter.studyId}/${chapter._id} ${res.status}")
|
||||
fufail(res.statusText)
|
||||
case res => fuccess(res.bodyAsSource)
|
||||
}
|
||||
}
|
|
@ -36,7 +36,7 @@ final class PgnDump(
|
|||
def filename(study: Study): String = {
|
||||
val date = dateFormat.print(study.createdAt)
|
||||
fileR.replaceAllIn(
|
||||
s"lichess_study_${slugify(study.name.value)}_by_${ownerName(study)}_${date}.pgn",
|
||||
s"lichess_study_${slugify(study.name.value)}_by_${ownerName(study)}_${date}",
|
||||
""
|
||||
)
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ final class PgnDump(
|
|||
def filename(study: Study, chapter: Chapter): String = {
|
||||
val date = dateFormat.print(chapter.createdAt)
|
||||
fileR.replaceAllIn(
|
||||
s"lichess_study_${slugify(study.name.value)}_${slugify(chapter.name.value)}_by_${ownerName(study)}_${date}.pgn",
|
||||
s"lichess_study_${slugify(study.name.value)}_${slugify(chapter.name.value)}_by_${ownerName(study)}_${date}",
|
||||
""
|
||||
)
|
||||
}
|
||||
|
|
|
@ -70,7 +70,13 @@ export function view(ctrl): VNode {
|
|||
'data-icon': 'x',
|
||||
href: `/study/${studyId}/${chapter.id}.pgn`
|
||||
}
|
||||
}, ctrl.trans.noarg('chapterPgn'))
|
||||
}, ctrl.trans.noarg('chapterPgn')),
|
||||
h('a.button.text', {
|
||||
attrs: {
|
||||
'data-icon': 'x',
|
||||
href: `/study/${studyId}/${chapter.id}.gif`
|
||||
}
|
||||
}, 'GIF')
|
||||
]),
|
||||
h('form.form3', [
|
||||
h('div.form-group', [
|
||||
|
|
Loading…
Reference in New Issue