Merge branch 'master' into stripe-api-version

* master:
  add ModNote permission to Shusher package
  fix impersonation of the lichess user
  dark board 3d
  refactor event name form, allow single quotes
  fix swiss faq style
  fix compile error
  {master} ignore more streamer image upload exceptions
  {master} help timeago with layout reflow
  {master} tweak scalatags
  {master} improve captcha help url
  uianalyse
stripe-api-version
Thibault Duplessis 2020-10-18 10:04:14 +02:00
commit 8af5dd1152
11 changed files with 40 additions and 36 deletions

View File

@ -156,7 +156,7 @@ final class Mod(
env.mod.impersonate.stop(me)
Redirect(routes.User.show(me.username))
}
else if (isGranted(_.Impersonate) || (isGranted(_.Admin) && username == "lichess"))
else if (isGranted(_.Impersonate) || (isGranted(_.Admin) && username.toLowerCase == "lichess"))
OptionFuRedirect(env.user.repo named username) { user =>
env.mod.impersonate.start(me, user)
fuccess(routes.User.show(user.username))

View File

@ -137,7 +137,7 @@ final class Streamer(
ctx.body.body.file("picture") match {
case Some(pic) =>
api.uploadPicture(s.streamer, pic) recover { case e: Exception =>
BadRequest(html.streamer.picture(s, e.message.some))
BadRequest(html.streamer.picture(s, e.getMessage.some))
} inject Redirect(routes.Streamer.edit())
case None => fuccess(Redirect(routes.Streamer.edit()))
}

View File

@ -5,7 +5,7 @@ import play.api.data.format.Formats._
import play.api.data.format.{ Formatter, JodaFormats }
import play.api.data.Forms._
import play.api.data.JodaForms._
import play.api.data.validation.Constraint
import play.api.data.validation.{ Constraint, Constraints }
import play.api.data.{ Field, FormError, Mapping }
import scala.util.Try
@ -60,6 +60,16 @@ object Form {
trim(m)
.verifying("This text contains invalid chars", s => !String.hasZeroWidthChars(s))
def eventName(minLength: Int, maxLength: Int) =
clean(text).verifying(
Constraints minLength minLength,
Constraints maxLength maxLength,
Constraints.pattern(
regex = """[\p{L}\p{N}-\s:,;'\+]+""".r,
error = "Invalid characters"
)
)
def stringIn(choices: Options[String]) =
text.verifying(hasKey(choices, _))

View File

@ -104,7 +104,8 @@ object Permission {
ReportBan,
ModMessage,
SeeReport,
ModLog
ModLog,
ModNote
),
"Shusher"
)

View File

@ -32,13 +32,7 @@ object SimulForm {
val colorDefault = "white"
private def nameType(host: User) =
clean(text).verifying(
Constraints minLength 2,
Constraints maxLength 40,
Constraints.pattern(
regex = """[\p{L}\p{N}-\s:,;]+""".r,
error = "error.unknown"
),
eventName(2, 40).verifying(
Constraint[String] { (t: String) =>
if (t.toLowerCase contains "lichess")
validation.Invalid(validation.ValidationError("Must not contain \"lichess\""))

View File

@ -5,7 +5,6 @@ import chess.variant.Variant
import org.joda.time.DateTime
import play.api.data._
import play.api.data.Forms._
import play.api.data.validation.Constraints
import play.api.Mode
import scala.concurrent.duration._
@ -18,16 +17,7 @@ final class SwissForm(implicit mode: Mode) {
def form(minRounds: Int = 3) =
Form(
mapping(
"name" -> optional(
clean(text).verifying(
Constraints minLength 2,
Constraints maxLength 30,
Constraints.pattern(
regex = """[\p{L}\p{N}-\s:,;\+]+""".r,
error = "Invalid characters"
)
)
),
"name" -> optional(eventName(2, 3)),
"clock" -> mapping(
"limit" -> number.verifying(clockLimits.contains _),
"increment" -> number(min = 0, max = 600)

View File

@ -59,13 +59,7 @@ final class TournamentForm {
hasChat = tour.hasChat.some
)
private def nameType(user: User) = clean(text).verifying(
Constraints minLength 2,
Constraints maxLength 30,
Constraints.pattern(
regex = """[\p{L}\p{N}-\s:,;]+""".r,
error = "error.unknown"
),
private def nameType(user: User) = eventName(2, 30).verifying(
Constraint[String] { (t: String) =>
if (t.toLowerCase.contains("lichess") && !user.isVerified && !user.isAdmin)
validation.Invalid(validation.ValidationError("Must not contain \"lichess\""))

View File

@ -272,6 +272,10 @@ declare namespace Tree {
cp?: number;
mate?: number;
best?: Uci;
fen: Fen;
knodes: number;
depth: number;
pvs: PvData[];
}
export interface PvData {

View File

@ -20,7 +20,7 @@ const evalPutMinDepth = 20;
const evalPutMinNodes = 3e6;
const evalPutMaxMoves = 10;
function qualityCheck(ev): boolean {
function qualityCheck(ev: Tree.ClientEval): boolean {
// below 500k nodes, the eval might come from an imminent threefold repetition
// and should therefore be ignored
return ev.nodes > 500000 && (
@ -29,7 +29,7 @@ function qualityCheck(ev): boolean {
}
// from client eval to server eval
function toPutData(variant: VariantKey, ev) {
function toPutData(variant: VariantKey, ev: Tree.ClientEval) {
const data: any = {
fen: ev.fen,
knodes: Math.round(ev.nodes / 1000),
@ -47,7 +47,7 @@ function toPutData(variant: VariantKey, ev) {
}
// from server eval to client eval
function toCeval(e) {
function toCeval(e: Tree.ServerEval) {
const res: any = {
fen: e.fen,
nodes: e.knodes * 1000,

View File

@ -2,7 +2,8 @@
body.dark-board {
--dark-factor: 0.4;
cg-board {
cg-board,
.is3d cg-board::before {
background-color: rgba(0, 0, 0, var(--dark-factor));
background-blend-mode: darken;
}

View File

@ -18,10 +18,20 @@
color: $c-brag;
font-weight: bold;
}
}
&.faq strong {
display: block;
margin-bottom: .4em;
#faq {
display: block;
.faq {
@extend %flex-center-nowrap;
margin-bottom: 4em;
strong {
display: block;
margin-bottom: .4em;
}
}
}
}