From dbbd5c5e02ca8c49276fa716bdfcae2e5026e2dc Mon Sep 17 00:00:00 2001 From: Dominic Lupo Date: Fri, 16 Oct 2020 12:03:33 -0400 Subject: [PATCH 01/11] uianalyse --- ui/@types/lichess/index.d.ts | 4 ++++ ui/analyse/src/evalCache.ts | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/ui/@types/lichess/index.d.ts b/ui/@types/lichess/index.d.ts index 1e1f400349..faad5c0635 100644 --- a/ui/@types/lichess/index.d.ts +++ b/ui/@types/lichess/index.d.ts @@ -272,6 +272,10 @@ declare namespace Tree { cp?: number; mate?: number; best?: Uci; + fen: Fen; + knodes: number; + depth: number; + pvs: PvData[]; } export interface PvData { diff --git a/ui/analyse/src/evalCache.ts b/ui/analyse/src/evalCache.ts index b475b00c15..27509c6de1 100644 --- a/ui/analyse/src/evalCache.ts +++ b/ui/analyse/src/evalCache.ts @@ -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, From 82121021c3ab5c1fda614ee44af92f103a8bc6f0 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Fri, 16 Oct 2020 09:54:20 +0200 Subject: [PATCH 02/11] {master} improve captcha help url --- app/views/base/captcha.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/base/captcha.scala b/app/views/base/captcha.scala index 93afe4b119..660397b8ff 100644 --- a/app/views/base/captcha.scala +++ b/app/views/base/captcha.scala @@ -53,7 +53,7 @@ object captcha { br, trans.help(), " ", - a(title := trans.viewTheSolution.txt(), targetBlank, href := url)(url), + a(title := trans.viewTheSolution.txt(), targetBlank, href := s"${url}#last")(url), div(cls := "result success text", dataIcon := "E")(trans.checkmate()), div(cls := "result failure text", dataIcon := "k")(trans.notACheckmate()), form3.hidden(form("move")) From cb5d0cf8a3c67b154aef209ce894570ffcd3c2e8 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Fri, 16 Oct 2020 09:57:34 +0200 Subject: [PATCH 03/11] {master} tweak scalatags --- app/ui/scalatags.scala | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/app/ui/scalatags.scala b/app/ui/scalatags.scala index 514f2eb0c7..c086dcb1c9 100644 --- a/app/ui/scalatags.scala +++ b/app/ui/scalatags.scala @@ -136,8 +136,6 @@ trait ScalatagsExtensions { val emptyFrag: Frag = new RawFrag("") implicit val LilaFragZero: Zero[Frag] = Zero.instance(emptyFrag) - val emptyModifier: Modifier = (t: Builder) => {} - val targetBlank: Modifier = (t: Builder) => { // Prevent tab nabbing when opening untrusted links. Apply also to trusted // links, because there can be a small peformance advantage and lila does @@ -147,20 +145,15 @@ trait ScalatagsExtensions { t.setAttr("target", Builder.GenericAttrValueSource("_blank")) } - def ariaTitle(v: String) = - new Modifier { - def applyTo(t: Builder) = { - val value = Builder.GenericAttrValueSource(v) - t.setAttr("title", value) - t.setAttr("aria-label", value) - } - } + def ariaTitle(v: String): Modifier = (t: Builder) => { + val value = Builder.GenericAttrValueSource(v) + t.setAttr("title", value) + t.setAttr("aria-label", value) + } - def titleOrText(blind: Boolean, v: String): Modifier = - (t: Builder) => { - if (blind) t.addChild(v) - else t.setAttr("title", Builder.GenericAttrValueSource(v)) - } + def titleOrText(blind: Boolean, v: String): Modifier = (t: Builder) => + if (blind) t.addChild(v) + else t.setAttr("title", Builder.GenericAttrValueSource(v)) def titleOrText(v: String)(implicit ctx: Context): Modifier = titleOrText(ctx.blind, v) } From 37f1a735270c76b3b5100470022e288779fd91b5 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Fri, 16 Oct 2020 10:47:15 +0200 Subject: [PATCH 04/11] {master} help timeago with layout reflow --- app/templating/DateHelper.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templating/DateHelper.scala b/app/templating/DateHelper.scala index 7ab6baf01d..1cfffc8f91 100644 --- a/app/templating/DateHelper.scala +++ b/app/templating/DateHelper.scala @@ -78,7 +78,7 @@ trait DateHelper { self: I18nHelper with StringHelper => def momentFromNow(date: DateTime, alwaysRelative: Boolean = false, once: Boolean = false): Tag = { if (!alwaysRelative && (date.getMillis - nowMillis) > oneDayMillis) absClientDateTime(date) - else timeTag(cls := s"timeago${once ?? " once"}", datetimeAttr := isoDate(date)) + else timeTag(cls := s"timeago${once ?? " once"}", datetimeAttr := isoDate(date))(nbsp) } def momentFromNowWithPreload(date: DateTime, alwaysRelative: Boolean = false, once: Boolean = false): Frag = From 072ff3d00194df934cf1e956f0247bac52bf4772 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Fri, 16 Oct 2020 15:01:30 +0200 Subject: [PATCH 05/11] {master} ignore more streamer image upload exceptions such as invalid GIF headers --- app/controllers/Streamer.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/Streamer.scala b/app/controllers/Streamer.scala index 06606d4fb4..00ad050b79 100644 --- a/app/controllers/Streamer.scala +++ b/app/controllers/Streamer.scala @@ -136,7 +136,7 @@ final class Streamer( AsStreamer { s => ctx.body.body.file("picture") match { case Some(pic) => - api.uploadPicture(s.streamer, pic) recover { case e: lila.base.LilaException => + api.uploadPicture(s.streamer, pic) recover { case e: Exception => BadRequest(html.streamer.picture(s, e.message.some)) } inject Redirect(routes.Streamer.edit()) case None => fuccess(Redirect(routes.Streamer.edit())) From 8eed73d4082b4f984ca22a7dfebc9dea75f0cf57 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Sat, 17 Oct 2020 10:40:13 +0200 Subject: [PATCH 06/11] fix compile error --- app/controllers/Streamer.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/Streamer.scala b/app/controllers/Streamer.scala index 00ad050b79..9a4b226546 100644 --- a/app/controllers/Streamer.scala +++ b/app/controllers/Streamer.scala @@ -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())) } From 57829b2d1805882b544a2aa2c92b0dd6dd033f30 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Sat, 17 Oct 2020 10:40:20 +0200 Subject: [PATCH 07/11] fix swiss faq style --- ui/swiss/css/_home.scss | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/ui/swiss/css/_home.scss b/ui/swiss/css/_home.scss index 356af50266..29a11d493e 100644 --- a/ui/swiss/css/_home.scss +++ b/ui/swiss/css/_home.scss @@ -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; + } } } } From d4c3d2aaf779ff575bbeae539819f041a0fb607d Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Sat, 17 Oct 2020 11:02:01 +0200 Subject: [PATCH 08/11] refactor event name form, allow single quotes --- modules/common/src/main/Form.scala | 12 +++++++++++- modules/simul/src/main/SimulForm.scala | 8 +------- modules/swiss/src/main/SwissForm.scala | 12 +----------- modules/tournament/src/main/TournamentForm.scala | 8 +------- 4 files changed, 14 insertions(+), 26 deletions(-) diff --git a/modules/common/src/main/Form.scala b/modules/common/src/main/Form.scala index f779c038d1..0a3d2d4161 100644 --- a/modules/common/src/main/Form.scala +++ b/modules/common/src/main/Form.scala @@ -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, _)) diff --git a/modules/simul/src/main/SimulForm.scala b/modules/simul/src/main/SimulForm.scala index bd29838053..a1c4f305be 100644 --- a/modules/simul/src/main/SimulForm.scala +++ b/modules/simul/src/main/SimulForm.scala @@ -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\"")) diff --git a/modules/swiss/src/main/SwissForm.scala b/modules/swiss/src/main/SwissForm.scala index 90c8a181c9..d117e05070 100644 --- a/modules/swiss/src/main/SwissForm.scala +++ b/modules/swiss/src/main/SwissForm.scala @@ -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) diff --git a/modules/tournament/src/main/TournamentForm.scala b/modules/tournament/src/main/TournamentForm.scala index e2bae3ecff..70f273f16d 100644 --- a/modules/tournament/src/main/TournamentForm.scala +++ b/modules/tournament/src/main/TournamentForm.scala @@ -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\"")) From c22f7a04e91eef7f059994addcc1df05868ebc71 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Sat, 17 Oct 2020 13:07:08 +0200 Subject: [PATCH 09/11] dark board 3d --- ui/common/css/vendor/chessground/_dark-board.scss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/common/css/vendor/chessground/_dark-board.scss b/ui/common/css/vendor/chessground/_dark-board.scss index 25a22b6784..3e50067e56 100644 --- a/ui/common/css/vendor/chessground/_dark-board.scss +++ b/ui/common/css/vendor/chessground/_dark-board.scss @@ -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; } From 9d5b13ea4108c678c87508d3be4b20f54ce37a3a Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Sat, 17 Oct 2020 19:24:56 +0200 Subject: [PATCH 10/11] fix impersonation of the lichess user --- app/controllers/Mod.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/Mod.scala b/app/controllers/Mod.scala index 7a4d70dc92..8065b1ec90 100644 --- a/app/controllers/Mod.scala +++ b/app/controllers/Mod.scala @@ -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)) From 2ff2dccf1a3fafd6b7eef3a939d88b6ba13a38e3 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Sat, 17 Oct 2020 19:34:48 +0200 Subject: [PATCH 11/11] add ModNote permission to Shusher package --- modules/security/src/main/Permission.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/security/src/main/Permission.scala b/modules/security/src/main/Permission.scala index 08c8f138f1..fa05695cc1 100644 --- a/modules/security/src/main/Permission.scala +++ b/modules/security/src/main/Permission.scala @@ -104,7 +104,8 @@ object Permission { ReportBan, ModMessage, SeeReport, - ModLog + ModLog, + ModNote ), "Shusher" )