send ublog images to zulip, improve etiquette mention
parent
b8b122b86a
commit
79a3364b8a
|
@ -130,7 +130,7 @@ final class Ublog(env: Env) extends LilaController(env) {
|
|||
ctx.body.body.file("image") match {
|
||||
case Some(image) =>
|
||||
ImageRateLimitPerIp(HTTPRequest ipAddress ctx.req) {
|
||||
env.ublog.api.uploadImage(post, image) map { newPost =>
|
||||
env.ublog.api.uploadImage(me, post, image) map { newPost =>
|
||||
Ok(html.ublog.form.formImage(newPost))
|
||||
} recover { case e: Exception =>
|
||||
BadRequest(e.getMessage)
|
||||
|
|
|
@ -16,6 +16,8 @@ trait AssetHelper { self: I18nHelper with SecurityHelper =>
|
|||
private lazy val minifiedAssets = env.net.minifiedAssets
|
||||
lazy val vapidPublicKey = env.push.vapidPublicKey
|
||||
|
||||
lazy val picfitUrl = env.memo.picfitUrl
|
||||
|
||||
lazy val sameAssetDomain = netDomain.value == assetDomain.value
|
||||
|
||||
def assetVersion = AssetVersion.current
|
||||
|
@ -26,8 +28,6 @@ trait AssetHelper { self: I18nHelper with SecurityHelper =>
|
|||
|
||||
def dbImageUrl(path: String) = s"$assetBaseUrl/image/$path"
|
||||
|
||||
lazy val picfitUrl = new lila.memo.PicfitUrl(env.net.picfitEndpoint, env.net.picfitSecretKey)
|
||||
|
||||
def cssTag(name: String)(implicit ctx: Context): Frag =
|
||||
cssTagWithTheme(name, ctx.currentBg)
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ object form {
|
|||
) {
|
||||
main(cls := "box box-pad page page-small ublog-post-form")(
|
||||
h1(trans.ublog.newPost()),
|
||||
etiquette,
|
||||
inner(user, f, none)
|
||||
)
|
||||
}
|
||||
|
@ -90,18 +91,18 @@ object form {
|
|||
)(form3.textarea(_)(rows := 30)),
|
||||
form3.actions(
|
||||
a(href := post.fold(routes.Ublog.index(user.username))(views.html.ublog.post.urlOf))(trans.cancel()),
|
||||
span(
|
||||
etiquette,
|
||||
form3.submit(trans.apply())
|
||||
)
|
||||
form3.submit(trans.apply())
|
||||
)
|
||||
)
|
||||
|
||||
private def etiquette(implicit ctx: Context) =
|
||||
private def etiquette(implicit ctx: Context) = div(cls := "ublog-post-form__etiquette")(
|
||||
p("Please only post safe and respectful content."),
|
||||
p("Anything even slightly inappropriate could get your account closed."),
|
||||
a(
|
||||
dataIcon := "",
|
||||
href := routes.Page.loneBookmark("blog-etiquette"),
|
||||
cls := "text ublog-post-form__etiquette",
|
||||
cls := "text",
|
||||
targetBlank
|
||||
)("Blog Etiquette")
|
||||
)
|
||||
}
|
||||
|
|
|
@ -89,21 +89,13 @@ object post {
|
|||
def editUrlOf(post: UblogPost.BasePost) = routes.Ublog.edit(usernameOrId(post.user), post.id.value)
|
||||
|
||||
object thumbnail {
|
||||
sealed abstract class Size(val width: Int) {
|
||||
def height = width * 10 / 16
|
||||
}
|
||||
case object Large extends Size(880)
|
||||
case object Small extends Size(400)
|
||||
|
||||
def apply(post: UblogPost.BasePost, size: thumbnail.type => Size) =
|
||||
def apply(post: UblogPost.BasePost, size: UblogPost.thumbnail.SizeSelector) =
|
||||
img(cls := "ublog-post-image")(src := url(post, size))
|
||||
|
||||
def url(post: UblogPost.BasePost, size: thumbnail.type => Size) = {
|
||||
val s = size(thumbnail)
|
||||
def url(post: UblogPost.BasePost, size: UblogPost.thumbnail.SizeSelector) =
|
||||
post.image match {
|
||||
case Some(image) => picfitUrl.thumbnail(image, s.width, s.height)
|
||||
case Some(image) => UblogPost.thumbnail(picfitUrl, image, size)
|
||||
case _ => assetUrl("images/user-blog-default.png")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -113,7 +113,7 @@ lazy val blog = module("blog",
|
|||
)
|
||||
|
||||
lazy val ublog = module("ublog",
|
||||
Seq(common, memo, timeline),
|
||||
Seq(common, memo, timeline, irc),
|
||||
Seq(specs2) ++ reactivemongo.bundle
|
||||
)
|
||||
|
||||
|
|
|
@ -17,8 +17,6 @@ net {
|
|||
prodDomain = "lichess.org"
|
||||
http.log = true
|
||||
stage.banner = false
|
||||
picfitEndpoint = ${memo.picfit.endpointGet}
|
||||
picfitSecretKey = ${memo.picfit.secretKey}
|
||||
}
|
||||
play {
|
||||
application.loader = "lila.app.AppLoader"
|
||||
|
|
|
@ -42,9 +42,7 @@ object config {
|
|||
@ConfigName("socket.domains") socketDomains: List[String],
|
||||
crawlable: Boolean,
|
||||
@ConfigName("ratelimit") rateLimit: RateLimit,
|
||||
email: EmailAddress,
|
||||
picfitEndpoint: String,
|
||||
picfitSecretKey: Secret
|
||||
email: EmailAddress
|
||||
) {
|
||||
def isProd = domain == prodDomain
|
||||
}
|
||||
|
|
|
@ -96,6 +96,18 @@ final class IrcApi(
|
|||
def broadcastError(id: String, name: String, error: String): Funit =
|
||||
zulip(_.broadcast, "lila error log")(s"${markdown.broadcastLink(id, name)} $error")
|
||||
|
||||
def ublogImage(
|
||||
user: User,
|
||||
id: String,
|
||||
slug: String,
|
||||
title: String,
|
||||
filename: String,
|
||||
imageUrl: String
|
||||
): Funit =
|
||||
zulip(_.image, "blog")(
|
||||
s"![$filename]($imageUrl) [$title](/@/${user.username}/blog/$slug/$id) by ${markdown.userLink(user)}"
|
||||
)
|
||||
|
||||
def userAppeal(user: User, mod: Holder): Funit =
|
||||
zulip
|
||||
.sendAndGetLink(_.mod.adminAppeal, "/" + user.username)(
|
||||
|
|
|
@ -91,6 +91,7 @@ private object ZulipClient {
|
|||
}
|
||||
val general = "general"
|
||||
val broadcast = "content-broadcast"
|
||||
val image = "mod-comms-image"
|
||||
type Selector = ZulipClient.stream.type => String
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,4 +41,6 @@ final class Env(
|
|||
lazy val mongoRateLimitApi = wire[MongoRateLimitApi]
|
||||
|
||||
lazy val picfitApi = new PicfitApi(db(config.picfit.collection), ws, config.picfit)
|
||||
|
||||
lazy val picfitUrl = new lila.memo.PicfitUrl(config.picfit)
|
||||
}
|
||||
|
|
|
@ -128,7 +128,7 @@ object PicfitApi {
|
|||
}
|
||||
}
|
||||
|
||||
final class PicfitUrl(endpoint: String, secretKey: config.Secret) {
|
||||
final class PicfitUrl(config: PicfitConfig) {
|
||||
|
||||
// This operation will able you to resize the image to the specified width and height.
|
||||
// Preserves the aspect ratio
|
||||
|
@ -155,11 +155,11 @@ final class PicfitUrl(endpoint: String, secretKey: config.Secret) {
|
|||
) = {
|
||||
// parameters must be given in alphabetical order for the signature to work (!)
|
||||
val queryString = s"h=$height&op=$operation&path=$id&w=$width"
|
||||
s"$endpoint/display?${signQueryString(queryString)}"
|
||||
s"${config.endpointGet}/display?${signQueryString(queryString)}"
|
||||
}
|
||||
|
||||
private object signQueryString {
|
||||
private val signer = com.roundeights.hasher.Algo hmac secretKey.value
|
||||
private val signer = com.roundeights.hasher.Algo hmac config.secretKey.value
|
||||
private val cache: LoadingCache[String, String] =
|
||||
CacheApi.scaffeineNoScheduler
|
||||
.expireAfterWrite(10 minutes)
|
||||
|
|
|
@ -9,7 +9,9 @@ final class Env(
|
|||
db: lila.db.Db,
|
||||
userRepo: lila.user.UserRepo,
|
||||
timeline: lila.hub.actors.Timeline,
|
||||
picfit: lila.memo.PicfitApi
|
||||
picfitApi: lila.memo.PicfitApi,
|
||||
picfitUrl: lila.memo.PicfitUrl,
|
||||
ircApi: lila.irc.IrcApi
|
||||
)(implicit
|
||||
ec: scala.concurrent.ExecutionContext
|
||||
) {
|
||||
|
|
|
@ -9,11 +9,17 @@ import lila.common.config.MaxPerPage
|
|||
import lila.common.paginator.Paginator
|
||||
import lila.db.dsl._
|
||||
import lila.db.paginator.Adapter
|
||||
import lila.memo.PicfitApi
|
||||
import lila.memo.{ PicfitApi, PicfitUrl }
|
||||
import lila.user.User
|
||||
import lila.hub.actorApi.timeline.Propagate
|
||||
|
||||
final class UblogApi(coll: Coll, picfitApi: PicfitApi, timeline: lila.hub.actors.Timeline)(implicit
|
||||
final class UblogApi(
|
||||
coll: Coll,
|
||||
picfitApi: PicfitApi,
|
||||
picfitUrl: PicfitUrl,
|
||||
timeline: lila.hub.actors.Timeline,
|
||||
irc: lila.irc.IrcApi
|
||||
)(implicit
|
||||
ec: ExecutionContext
|
||||
) {
|
||||
|
||||
|
@ -61,13 +67,21 @@ final class UblogApi(coll: Coll, picfitApi: PicfitApi, timeline: lila.hub.actors
|
|||
|
||||
private def imageRel(post: UblogPost) = s"ublog:${post.id}"
|
||||
|
||||
def uploadImage(post: UblogPost, picture: PicfitApi.Uploaded): Fu[UblogPost] =
|
||||
picfitApi
|
||||
.upload(imageRel(post), picture, userId = post.user)
|
||||
.flatMap { image =>
|
||||
coll.update.one($id(post.id), $set("image" -> image.id)) inject post.copy(image = image.id.some)
|
||||
}
|
||||
.logFailure(logger branch "upload")
|
||||
def uploadImage(user: User, post: UblogPost, picture: PicfitApi.Uploaded): Fu[UblogPost] = {
|
||||
for {
|
||||
image <- picfitApi
|
||||
.upload(imageRel(post), picture, userId = post.user)
|
||||
_ <- coll.update.one($id(post.id), $set("image" -> image.id))
|
||||
_ <- post.live ?? irc.ublogImage(
|
||||
user,
|
||||
id = post.id.value,
|
||||
slug = post.slug,
|
||||
title = post.title,
|
||||
filename = image.name,
|
||||
imageUrl = UblogPost.thumbnail(picfitUrl, image.id, _.Small)
|
||||
)
|
||||
} yield post.copy(image = image.id.some)
|
||||
}.logFailure(logger branch "upload")
|
||||
|
||||
def lightsByIds(ids: List[UblogPost.Id]): Fu[List[UblogPost.LightPost]] =
|
||||
coll
|
||||
|
|
|
@ -2,7 +2,7 @@ package lila.ublog
|
|||
|
||||
import org.joda.time.DateTime
|
||||
|
||||
import lila.memo.PicfitImage
|
||||
import lila.memo.{ PicfitImage, PicfitUrl }
|
||||
import lila.user.User
|
||||
|
||||
case class UblogPost(
|
||||
|
@ -56,4 +56,16 @@ object UblogPost {
|
|||
val s = lila.common.String slugify title
|
||||
if (s.isEmpty) "-" else s
|
||||
}
|
||||
|
||||
object thumbnail {
|
||||
sealed abstract class Size(val width: Int) {
|
||||
def height = width * 10 / 16
|
||||
}
|
||||
case object Large extends Size(880)
|
||||
case object Small extends Size(400)
|
||||
type SizeSelector = thumbnail.type => Size
|
||||
|
||||
def apply(picfitUrl: PicfitUrl, image: PicfitImage.Id, size: SizeSelector) =
|
||||
picfitUrl.thumbnail(image, size(thumbnail).width, size(thumbnail).height)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,4 +16,11 @@
|
|||
align-items: center;
|
||||
}
|
||||
}
|
||||
&__etiquette {
|
||||
@extend %box-neat;
|
||||
background: $c-bg-zebra;
|
||||
padding: 2em 3em;
|
||||
margin: 3em auto;
|
||||
max-width: 80ch;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue