configurable appeal and PM mod presets
parent
c1c47944ec
commit
ac422a9b72
|
@ -42,7 +42,7 @@ final class Appeal(env: Env, reportC: => Report) extends LilaController(env) {
|
|||
Secure(_.Appeals) { implicit ctx => me =>
|
||||
asMod(username) { (appeal, suspect) =>
|
||||
env.report.api.inquiries.ofSuspectId(suspect.user.id) map { inquiry =>
|
||||
Ok(html.appeal.show(appeal, suspect, inquiry, env.appeal.forms.text))
|
||||
Ok(html.appeal.show(appeal, suspect, inquiry, env.appeal.forms.text, getPresets))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ final class Appeal(env: Env, reportC: => Report) extends LilaController(env) {
|
|||
.fold(
|
||||
err =>
|
||||
env.report.api.inquiries.ofSuspectId(suspect.user.id) map { inquiry =>
|
||||
BadRequest(html.appeal.show(appeal, suspect, inquiry, err))
|
||||
BadRequest(html.appeal.show(appeal, suspect, inquiry, err, getPresets))
|
||||
},
|
||||
text =>
|
||||
for {
|
||||
|
@ -93,6 +93,8 @@ final class Appeal(env: Env, reportC: => Report) extends LilaController(env) {
|
|||
}
|
||||
}
|
||||
|
||||
private def getPresets = env.mod.presets.appealPresets.get()
|
||||
|
||||
private def asMod(
|
||||
username: String
|
||||
)(f: (lila.appeal.Appeal, Suspect) => Fu[Result])(implicit ctx: Context): Fu[Result] =
|
||||
|
|
|
@ -93,12 +93,12 @@ final class Mod(
|
|||
|
||||
def warn(username: String, subject: String) =
|
||||
OAuthModBody(_.ModMessage) { me =>
|
||||
lila.msg.MsgPreset.byName(subject) ?? { preset =>
|
||||
env.mod.presets.pmPresets.get().named(subject) ?? { preset =>
|
||||
withSuspect(username) { prev =>
|
||||
for {
|
||||
inquiry <- env.report.api.inquiries ofModId me.id
|
||||
suspect <- modApi.setTroll(AsMod(me), prev, prev.user.marks.troll)
|
||||
_ <- env.msg.api.postPreset(suspect.user, preset)
|
||||
_ <- env.msg.api.systemPost(suspect.user.id, preset.text)
|
||||
_ <- env.mod.logApi.modMessage(me.id, suspect.user.id, preset.name)
|
||||
} yield (inquiry, suspect).some
|
||||
}
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
package views.html
|
||||
|
||||
import controllers.routes
|
||||
import play.api.data.Form
|
||||
import play.api.i18n.Lang
|
||||
|
||||
import lila.api.Context
|
||||
import lila.app.templating.Environment._
|
||||
import lila.app.ui.ScalatagsTemplate._
|
||||
import lila.appeal.Appeal
|
||||
import lila.common.String.html.richText
|
||||
import lila.mod.{ ModPreset, ModPresets }
|
||||
import lila.report.Report.Inquiry
|
||||
import lila.report.Suspect
|
||||
import lila.user.User
|
||||
import play.api.data.Form
|
||||
import play.api.i18n.Lang
|
||||
|
||||
object appeal {
|
||||
|
||||
|
@ -18,7 +20,7 @@ object appeal {
|
|||
layout("Appeal") {
|
||||
main(cls := "page-small box box-pad page appeal")(
|
||||
appeal match {
|
||||
case Some(a) => renderAppeal(a, textForm, asMod = false)
|
||||
case Some(a) => renderAppeal(a, textForm, asMod = false, presets = none)
|
||||
case None => newAppeal(textForm)
|
||||
}
|
||||
)
|
||||
|
@ -29,16 +31,28 @@ object appeal {
|
|||
h1("Appeal a moderation decision"),
|
||||
renderHelp,
|
||||
div(cls := "body")(
|
||||
renderForm(textForm, action = routes.Appeal.post().url, isNew = true)
|
||||
renderForm(textForm, action = routes.Appeal.post().url, isNew = true, presets = none)
|
||||
)
|
||||
)
|
||||
|
||||
def show(appeal: Appeal, suspect: Suspect, inquiry: Option[Inquiry], textForm: Form[_])(implicit
|
||||
def show(
|
||||
appeal: Appeal,
|
||||
suspect: Suspect,
|
||||
inquiry: Option[Inquiry],
|
||||
textForm: Form[_],
|
||||
presets: ModPresets
|
||||
)(implicit
|
||||
ctx: Context
|
||||
) =
|
||||
layout(s"Appeal by ${suspect.user.username}") {
|
||||
main(cls := "page-small box box-pad page appeal")(
|
||||
renderAppeal(appeal, textForm, asMod = true, inquiry = inquiry.map(_.mod).exists(ctx.userId.has)),
|
||||
renderAppeal(
|
||||
appeal,
|
||||
textForm,
|
||||
asMod = true,
|
||||
inquiry = inquiry.map(_.mod).exists(ctx.userId.has),
|
||||
presets.some
|
||||
),
|
||||
div(cls := "appeal__actions")(
|
||||
inquiry match {
|
||||
case None =>
|
||||
|
@ -88,7 +102,7 @@ object appeal {
|
|||
tr(
|
||||
th("By"),
|
||||
th("Last message"),
|
||||
th
|
||||
th(isGranted(_.Presets) option a(href := routes.Mod.presets("appeal"))("Presets"))
|
||||
)
|
||||
),
|
||||
tbody(
|
||||
|
@ -119,15 +133,24 @@ object appeal {
|
|||
|
||||
private def layout(title: String)(body: Frag)(implicit ctx: Context) =
|
||||
views.html.base.layout(
|
||||
title = title,
|
||||
moreCss = frag(
|
||||
cssTag("form3"),
|
||||
cssTag("appeal")
|
||||
),
|
||||
title = title
|
||||
moreJs = embedJsUnsafe(
|
||||
"""$('select.appeal-presets').on('change', e => $('#form3-text').val(e.target.value))"""
|
||||
)
|
||||
)(body)
|
||||
|
||||
private def renderAppeal(appeal: Appeal, textForm: Form[_], asMod: Boolean, inquiry: Boolean = false)(
|
||||
implicit ctx: Context
|
||||
private def renderAppeal(
|
||||
appeal: Appeal,
|
||||
textForm: Form[_],
|
||||
asMod: Boolean,
|
||||
inquiry: Boolean = false,
|
||||
presets: Option[ModPresets]
|
||||
)(implicit
|
||||
ctx: Context
|
||||
) =
|
||||
frag(
|
||||
h1(
|
||||
|
@ -152,7 +175,8 @@ object appeal {
|
|||
action =
|
||||
if (asMod) routes.Appeal.reply(appeal.id).url
|
||||
else routes.Appeal.post().url,
|
||||
isNew = false
|
||||
isNew = false,
|
||||
presets = presets ifTrue asMod
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -198,12 +222,28 @@ object appeal {
|
|||
")"
|
||||
)
|
||||
|
||||
private def renderForm(form: Form[_], action: String, isNew: Boolean)(implicit ctx: Context) =
|
||||
private def renderForm(form: Form[_], action: String, isNew: Boolean, presets: Option[ModPresets])(implicit
|
||||
ctx: Context
|
||||
) =
|
||||
postForm(st.action := action)(
|
||||
form3.globalError(form),
|
||||
form3.group(form("text"), if (isNew) "Create an appeal" else "Add something to the appeal")(
|
||||
form3.textarea(_)(rows := 6)
|
||||
),
|
||||
form3.submit(trans.send())
|
||||
presets.map { ps =>
|
||||
form3.actions(
|
||||
select(cls := "appeal-presets")(
|
||||
option(st.value := "")("Presets"),
|
||||
ps.value.map {
|
||||
case ModPreset(name, text) =>
|
||||
option(
|
||||
st.value := text,
|
||||
st.title := text
|
||||
)(name)
|
||||
}
|
||||
),
|
||||
form3.submit(trans.send())
|
||||
)
|
||||
} getOrElse form3.submit(trans.send())
|
||||
)
|
||||
}
|
||||
|
|
|
@ -144,7 +144,7 @@ object inquiry {
|
|||
isGranted(_.ModMessage) option div(cls := "dropper warn buttons")(
|
||||
iconTag("e"),
|
||||
div(
|
||||
lila.msg.MsgPreset.all.map { preset =>
|
||||
env.mod.presets.pmPresets.get().value.map { preset =>
|
||||
postForm(action := routes.Mod.warn(in.user.username, preset.name))(
|
||||
submitButton(cls := "fbt")(preset.name),
|
||||
autoNextInput
|
||||
|
|
|
@ -7,10 +7,11 @@ import lila.app.templating.Environment._
|
|||
import lila.app.ui.ScalatagsTemplate._
|
||||
import lila.memo.SettingStore
|
||||
import play.api.data.Form
|
||||
import lila.mod.ModPresets
|
||||
|
||||
object presets {
|
||||
|
||||
def apply(group: String, setting: SettingStore[lila.mod.ModPresets], form: Form[_])(implicit ctx: Context) =
|
||||
def apply(group: String, setting: SettingStore[ModPresets], form: Form[_])(implicit ctx: Context) =
|
||||
views.html.base.layout(
|
||||
title = s"$group presets",
|
||||
moreCss = frag(cssTag("mod.misc"), cssTag("form3"))
|
||||
|
@ -18,10 +19,15 @@ object presets {
|
|||
main(cls := "page-menu")(
|
||||
views.html.mod.menu("presets"),
|
||||
div(cls := "page-menu__content box box-pad mod-presets")(
|
||||
h1(s"$group presets"),
|
||||
div(ModPresets.groups.filter(group !=).map { group =>
|
||||
a(href := routes.Mod.presets(group))(group)
|
||||
}),
|
||||
h1(
|
||||
s"${setting.get().value.size} $group presets",
|
||||
small(
|
||||
" / ",
|
||||
ModPresets.groups.filter(group !=).map { group =>
|
||||
a(href := routes.Mod.presets(group))(s"$group presets")
|
||||
}
|
||||
)
|
||||
),
|
||||
standardFlash(),
|
||||
postForm(action := routes.Mod.presetsUpdate(group))(
|
||||
form3.group(
|
||||
|
|
|
@ -13,8 +13,6 @@ final class ModPresetsApi(
|
|||
|
||||
import ModPresets.setting._
|
||||
|
||||
val groups = List("PM", "appeal")
|
||||
|
||||
def get(group: String) =
|
||||
group match {
|
||||
case "PM" => pmPresets.some
|
||||
|
@ -35,27 +33,31 @@ final class ModPresetsApi(
|
|||
)
|
||||
}
|
||||
|
||||
case class ModPresets(value: List[ModPreset])
|
||||
case class ModPresets(value: List[ModPreset]) {
|
||||
def named(name: String) = value.find(_.name == name)
|
||||
}
|
||||
case class ModPreset(name: String, text: String)
|
||||
|
||||
private object ModPresets {
|
||||
object ModPresets {
|
||||
|
||||
object setting {
|
||||
val groups = List("PM", "appeal")
|
||||
|
||||
private[mod] object setting {
|
||||
|
||||
private def write(presets: ModPresets): String =
|
||||
presets.value.map {
|
||||
case ModPreset(name, text) => s"$name\n$text"
|
||||
} mkString "\n----------\n"
|
||||
case ModPreset(name, text) => s"$name\n\n$text"
|
||||
} mkString "\n\n----------\n\n"
|
||||
|
||||
private def read(s: String): ModPresets =
|
||||
ModPresets {
|
||||
"\n-{3,}\n"
|
||||
.split(s)
|
||||
"\n-{3,}\\s*\n".r
|
||||
.split(s.linesIterator.map(_.trim).dropWhile(_.isEmpty) mkString "\n")
|
||||
.toList
|
||||
.map(_.linesIterator.map(_.trim).filter(_.nonEmpty).toList)
|
||||
.map(_.linesIterator.toList)
|
||||
.filter(_.nonEmpty)
|
||||
.flatMap {
|
||||
case name :: text => ModPreset(name, text mkString "\n").some
|
||||
case name :: text => ModPreset(name, text.dropWhile(_.isEmpty) mkString "\n").some
|
||||
case _ => none
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,106 +4,6 @@ case class MsgPreset(name: String, text: String)
|
|||
|
||||
object MsgPreset {
|
||||
|
||||
/* First line is the preset name;
|
||||
* Other lines are the message.
|
||||
* The message can contain several lines.
|
||||
*/
|
||||
// format: off
|
||||
val all = List("""
|
||||
|
||||
Warning: Offensive language
|
||||
|
||||
On Lichess, you *must* be nice when communicating with other players. At all times.
|
||||
|
||||
Lichess is intended to be a fun and friendly environment for everyone. Please note that repeated violation of chat policy will result in loss of chat privileges.
|
||||
|
||||
""", /* ---------------------------------------------------------------*/ """
|
||||
|
||||
Warning: Sandbagging
|
||||
|
||||
In your game history, you have several games where you clearly have intentionally lost the game. Attempts to artificially manipulate your own or someone else's rating are unacceptable. If this behavior continues to happen, your account will be terminated.
|
||||
|
||||
""", /* ---------------------------------------------------------------*/ """
|
||||
|
||||
Warning: Boosting
|
||||
|
||||
In your game history, you have several games where the opponent clearly has intentionally lost against you. Attempts to artificially manipulate your own or someone else's rating are unacceptable. If this behavior continues to happen, your account will be terminated.
|
||||
|
||||
""", /* ---------------------------------------------------------------*/ """
|
||||
|
||||
Warning: Excessive draw offers
|
||||
|
||||
Offering an excessive amount of draws in order to distract or annoy an opponent is not acceptable on Lichess. If this behavior continues to happen, your account will be terminated.
|
||||
|
||||
""", /* ---------------------------------------------------------------*/ """
|
||||
|
||||
En passant
|
||||
|
||||
This is called "en passant" and is one of the rules of chess. Check https://lichess.org/learn#/15 to learn more about it.
|
||||
|
||||
""", /* ---------------------------------------------------------------*/ """
|
||||
|
||||
Use /report
|
||||
|
||||
In order to report players for bad behavior, please visit https://lichess.org/report
|
||||
|
||||
""", /* ---------------------------------------------------------------*/ """
|
||||
|
||||
Warning: Accusations
|
||||
|
||||
Accusing other players of using computer assistance or otherwise cheating is not acceptable on Lichess. If you are confident that a player is cheating, use the report button on their profile page to report them to the moderators.
|
||||
|
||||
""", /* ---------------------------------------------------------------*/ """
|
||||
|
||||
Warning: spam is not permitted
|
||||
|
||||
Spamming is not permitted on Lichess.
|
||||
Do not post anything more than once, in public chats, private chats, forums, or any other communication channel.
|
||||
Please note that repeated violation of this policy will result in loss of communication privileges.
|
||||
|
||||
""", /* ---------------------------------------------------------------*/ """
|
||||
|
||||
Regarding rating refunds
|
||||
|
||||
To receive rating refunds certain conditions must be met, in order to mitigate rating inflation. These conditions were not met in this case.
|
||||
Please also remember that, over the long run, ratings tend to gravitate towards the player's real skill level.
|
||||
|
||||
""", /* ---------------------------------------------------------------*/ """
|
||||
|
||||
Warning: Username or profile that implies you are a titled player
|
||||
|
||||
The username policy (https://github.com/ornicar/lila/wiki/Username-policy) for Lichess states that you can't have a username that implies that you have a FIDE title or the Lichess Master title, or impersonating a specific titled player. Actual titled players can verify using the form here (https://lichess.org/verify-title) with evidence that documents their identity, e.g. a scanned ID card, driving license, passport or similar. We will then verify your identity and title, and your title will be shown in front of your username and on your Lichess user profile. Since your username or profile implies that you have a title, we reserve the right to close your account within two weeks, if you have not verified your title within that time.
|
||||
|
||||
""", /* ---------------------------------------------------------------*/ """
|
||||
|
||||
Account marked for computer assistance
|
||||
|
||||
Our cheating detection algorithms have marked your account for using computer assistance. If you want to contest the mark, please send an email to Lichess Contact contact@lichess.org. If you are a titled player, we will need a proof of your identity. It can be a picture of a document, like an ID card or a driving license. You can verify your title using the form at lichess.org/help/master .
|
||||
|
||||
""", /* ---------------------------------------------------------------*/ """
|
||||
|
||||
Warning: leaving games / stalling on time
|
||||
|
||||
In your game history, you have several games where you have left the game or just let the time run out instead of playing or resigning.
|
||||
This can be very annoying for your opponents. If this behavior continues to happen, we may be forced to terminate your account.
|
||||
|
||||
""", /* ---------------------------------------------------------------*/ """
|
||||
|
||||
Title Verification
|
||||
|
||||
Unfortunately we had to reject your title verification. You are free to make another application with the appropriate documentation.
|
||||
|
||||
""") flatMap toPreset
|
||||
// format: on
|
||||
|
||||
private def toPreset(txt: String) =
|
||||
txt.linesIterator.toList.map(_.trim).filter(_.nonEmpty) match {
|
||||
case name :: body => MsgPreset(name, body mkString "\n").some
|
||||
case _ =>
|
||||
logger.warn(s"Invalid message preset $txt")
|
||||
none
|
||||
}
|
||||
|
||||
lazy val sandbagAuto = MsgPreset(
|
||||
name = "Warning: possible sandbagging",
|
||||
text =
|
||||
|
@ -128,12 +28,4 @@ To follow new players, you must first unfollow some on https://lichess.org/@/$us
|
|||
|
||||
Thank you for your understanding."""
|
||||
)
|
||||
|
||||
lazy val asJson = play.api.libs.json.Json.toJson {
|
||||
all.map { p =>
|
||||
List(p.name, p.text)
|
||||
}
|
||||
}
|
||||
|
||||
def byName(s: String) = all.find(_.name == s)
|
||||
}
|
||||
|
|
|
@ -65,6 +65,9 @@
|
|||
}
|
||||
|
||||
.mod-presets {
|
||||
h1 small {
|
||||
font-size: 70%;
|
||||
}
|
||||
textarea {
|
||||
width: 100%;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue