msg integration WIP
parent
b1b230a1cb
commit
5a40eb8483
|
@ -93,13 +93,13 @@ final class Mod(
|
|||
|
||||
def warn(username: String, subject: String) =
|
||||
OAuthModBody(_.ModMessage) { me =>
|
||||
lila.message.ModPreset.bySubject(subject) ?? { preset =>
|
||||
lila.msg.MsgPreset.byName(subject) ?? { preset =>
|
||||
withSuspect(username) { prev =>
|
||||
for {
|
||||
inquiry <- env.report.api.inquiries ofModId me.id
|
||||
suspect <- modApi.setTroll(AsMod(me), prev, prev.user.marks.troll)
|
||||
thread <- env.message.api.sendPreset(me, suspect.user, preset)
|
||||
_ <- env.mod.logApi.modMessage(thread.creatorId, thread.invitedId, thread.name)
|
||||
_ <- env.msg.api.postPreset(suspect.user, preset)
|
||||
_ <- env.mod.logApi.modMessage(me.id, suspect.user.id, preset.name)
|
||||
} yield (inquiry, suspect).some
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,10 +46,10 @@ final class Relation(
|
|||
def follow(userId: String) = Auth { implicit ctx => me =>
|
||||
api.reachedMaxFollowing(me.id) flatMap {
|
||||
case true =>
|
||||
env.message.api
|
||||
.sendPresetFromLichess(
|
||||
env.msg.api
|
||||
.postPreset(
|
||||
me,
|
||||
lila.message.ModPreset.maxFollow(me.username, env.relation.maxFollow.value)
|
||||
lila.msg.MsgPreset.maxFollow(me.username, env.relation.maxFollow.value)
|
||||
)
|
||||
.void
|
||||
case _ =>
|
||||
|
|
|
@ -66,7 +66,7 @@ object form {
|
|||
isGranted(_.ModMessage) option frag(
|
||||
form3.checkbox(form("mod"), frag("Send as mod")),
|
||||
form3.group(form("preset"), frag("Preset")) { form3.select(_, Nil) },
|
||||
embedJsUnsafe(s"""lichess_mod_presets=${safeJsonValue(lila.message.ModPreset.asJson)}""")
|
||||
embedJsUnsafe(s"""lichess_mod_presets=${safeJsonValue(lila.msg.MsgPreset.asJson)}""")
|
||||
),
|
||||
form3.group(form("subject"), trans.subject()) { f =>
|
||||
input(
|
||||
|
|
|
@ -136,17 +136,12 @@ object inquiry {
|
|||
div(cls := "dropper warn buttons")(
|
||||
iconTag("e"),
|
||||
div(
|
||||
lila.message.ModPreset.all.map { preset =>
|
||||
postForm(action := routes.Mod.warn(in.user.username, preset.subject))(
|
||||
submitButton(cls := "fbt")(preset.subject),
|
||||
lila.msg.MsgPreset.all.map { preset =>
|
||||
postForm(action := routes.Mod.warn(in.user.username, preset.name))(
|
||||
submitButton(cls := "fbt")(preset.name),
|
||||
autoNextInput
|
||||
)
|
||||
},
|
||||
form(method := "get", action := routes.Message.form)(
|
||||
input(tpe := "hidden", name := "mod", value := "1"),
|
||||
input(tpe := "hidden", name := "user", value := "@in.user.id"),
|
||||
submitButton(cls := "fbt")("Custom message")
|
||||
)
|
||||
}
|
||||
)
|
||||
),
|
||||
isGranted(_.MarkEngine) option {
|
||||
|
|
|
@ -319,7 +319,7 @@ lazy val practice = module("practice",
|
|||
)
|
||||
|
||||
lazy val playban = module("playban",
|
||||
Seq(common, db, game, message, chat),
|
||||
Seq(common, db, game, msg, chat),
|
||||
reactivemongo.bundle
|
||||
)
|
||||
|
||||
|
|
|
@ -46,20 +46,6 @@ final class MessageApi(
|
|||
_ <- threadOption.filter(_ isUnReadBy me).??(threadRepo.setReadFor(me))
|
||||
} yield threadOption
|
||||
|
||||
def sendPreset(mod: User, user: User, preset: ModPreset): Fu[Thread] =
|
||||
makeThread(
|
||||
DataForm.ThreadData(
|
||||
user = user.light,
|
||||
subject = preset.subject,
|
||||
text = preset.text,
|
||||
asMod = true
|
||||
),
|
||||
mod
|
||||
)
|
||||
|
||||
def sendPresetFromLichess(user: User, preset: ModPreset) =
|
||||
userRepo.lichess orFail "Missing lichess user" flatMap { sendPreset(_, user, preset) }
|
||||
|
||||
def makeThread(data: DataForm.ThreadData, me: User): Fu[Thread] = {
|
||||
val fromMod = Granter(_.MessageAnyone)(me)
|
||||
userRepo named data.user.id flatMap {
|
||||
|
|
|
@ -29,12 +29,12 @@ object Msg {
|
|||
read: Boolean
|
||||
)
|
||||
|
||||
def make(
|
||||
text: String,
|
||||
user: User.ID
|
||||
): Msg = Msg(
|
||||
text = text,
|
||||
user = user,
|
||||
date = DateTime.now
|
||||
)
|
||||
def make(text: String, user: User.ID): Option[Msg] = {
|
||||
val cleanText = text.trim
|
||||
cleanText.nonEmpty option Msg(
|
||||
text = cleanText take 10_000,
|
||||
user = user,
|
||||
date = DateTime.now
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package lila.msg
|
||||
|
||||
import play.api.data._
|
||||
import play.api.data.Forms._
|
||||
import reactivemongo.api._
|
||||
import scala.concurrent.duration._
|
||||
|
||||
|
@ -48,10 +46,7 @@ final class MsgApi(
|
|||
.void
|
||||
}
|
||||
|
||||
val postForm = Form(single("text" -> nonEmptyText(maxLength = 10_000)))
|
||||
|
||||
private[msg] def post(orig: User.ID, dest: User.ID, text: String): Funit = {
|
||||
val msg = Msg.make(text, orig)
|
||||
private[msg] def post(orig: User.ID, dest: User.ID, text: String): Funit = Msg.make(text, orig) ?? { msg =>
|
||||
val threadId = MsgThread.id(orig, dest)
|
||||
!colls.thread.exists($id(threadId)) flatMap { isNew =>
|
||||
security.can.post(dest, msg, isNew) flatMap {
|
||||
|
@ -96,9 +91,19 @@ final class MsgApi(
|
|||
"lastMsg.read",
|
||||
true
|
||||
)
|
||||
.void >>- notifier.onRead(threadId)
|
||||
.map { res =>
|
||||
if (res.nModified > 0) notifier.onRead(threadId)
|
||||
}
|
||||
}
|
||||
|
||||
def postPreset(dest: User, preset: MsgPreset): Funit =
|
||||
postAsLichess(dest, preset.text)
|
||||
|
||||
def postAsLichess(dest: User, text: String): Funit =
|
||||
post(User.lichessId, dest.id, text)
|
||||
|
||||
def unreadCount(me: User): Fu[Int] = unreadCountCache.get(me.id)
|
||||
|
||||
private val unreadCountCache = cacheApi[User.ID, Int](256, "message.unreadCount") {
|
||||
_.expireAfterWrite(10 seconds)
|
||||
.buildAsyncFuture[User.ID, Int] { userId =>
|
||||
|
@ -106,8 +111,6 @@ final class MsgApi(
|
|||
}
|
||||
}
|
||||
|
||||
def unreadCount(me: User): Fu[Int] = unreadCountCache.get(me.id)
|
||||
|
||||
private val msgProjection = $doc("_id" -> false, "tid" -> false)
|
||||
|
||||
private def threadMsgsFor(threadId: MsgThread.Id, me: User): Fu[List[Msg]] =
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
package lila.message
|
||||
package lila.msg
|
||||
|
||||
case class ModPreset(subject: String, text: String)
|
||||
case class MsgPreset(name: String, text: String)
|
||||
|
||||
/* From https://github.com/ornicar/lila/wiki/Canned-responses-for-moderators */
|
||||
object ModPreset {
|
||||
object MsgPreset {
|
||||
|
||||
/* First line is the message subject;
|
||||
* Other lines are the message body.
|
||||
* The message body can contain several lines.
|
||||
/* First line is the preset name;
|
||||
* Other lines are the message.
|
||||
* The message can contain several lines.
|
||||
*/
|
||||
// format: off
|
||||
val all = List("""
|
||||
|
@ -97,14 +96,14 @@ Unfortunately we had to reject your title verification. You are free to make ano
|
|||
|
||||
private def toPreset(txt: String) =
|
||||
txt.linesIterator.toList.map(_.trim).filter(_.nonEmpty) match {
|
||||
case subject :: body => ModPreset(subject, body mkString "\n").some
|
||||
case name :: body => MsgPreset(name, body mkString "\n").some
|
||||
case _ =>
|
||||
logger.warn(s"Invalid mod message preset $txt")
|
||||
logger.warn(s"Invalid message preset $txt")
|
||||
none
|
||||
}
|
||||
|
||||
lazy val sandbagAuto = ModPreset(
|
||||
subject = "Warning: possible sandbagging",
|
||||
lazy val sandbagAuto = MsgPreset(
|
||||
name = "Warning: possible sandbagging",
|
||||
text =
|
||||
"""You have lost a couple games after a few moves. Please note that you MUST try to win every rated game.
|
||||
Losing rated games on purpose is called "sandbagging", and is not allowed on Lichess.
|
||||
|
@ -112,15 +111,15 @@ Losing rated games on purpose is called "sandbagging", and is not allowed on Lic
|
|||
Thank you for your understanding."""
|
||||
)
|
||||
|
||||
lazy val sittingAuto = ModPreset(
|
||||
subject = "Warning: leaving games / stalling on time",
|
||||
lazy val sittingAuto = MsgPreset(
|
||||
name = "Warning: leaving games / stalling on time",
|
||||
text =
|
||||
"""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."""
|
||||
)
|
||||
|
||||
def maxFollow(username: String, max: Int) = ModPreset(
|
||||
subject = "Follow limit reached!",
|
||||
def maxFollow(username: String, max: Int) = MsgPreset(
|
||||
name = "Follow limit reached!",
|
||||
text = s"""Sorry, you can't follow more than $max players on Lichess.
|
||||
To follow new players, you must first unfollow some on https://lichess.org/@/$username/following.
|
||||
|
||||
|
@ -129,9 +128,9 @@ Thank you for your understanding."""
|
|||
|
||||
lazy val asJson = play.api.libs.json.Json.toJson {
|
||||
all.map { p =>
|
||||
List(p.subject, p.text)
|
||||
List(p.name, p.text)
|
||||
}
|
||||
}
|
||||
|
||||
def bySubject(s: String) = all.find(_.subject == s)
|
||||
def byName(s: String) = all.find(_.name == s)
|
||||
}
|
|
@ -78,10 +78,11 @@ final private class MsgSecurity(
|
|||
|
||||
object may {
|
||||
|
||||
def post(orig: User.ID, dest: User.ID): Fu[Boolean] =
|
||||
def post(orig: User.ID, dest: User.ID): Fu[Boolean] = (dest != User.lichessId) ?? {
|
||||
!relationApi.fetchBlocks(dest, orig) >>& {
|
||||
create(orig, dest) >>| reply(orig, dest)
|
||||
}
|
||||
}
|
||||
|
||||
private def create(orig: User.ID, dest: User.ID): Fu[Boolean] =
|
||||
prefApi.getPref(dest, _.message) flatMap {
|
||||
|
|
|
@ -8,7 +8,7 @@ import lila.common.config.CollName
|
|||
@Module
|
||||
final class Env(
|
||||
appConfig: Configuration,
|
||||
messenger: lila.message.MessageApi,
|
||||
messenger: lila.msg.MsgApi,
|
||||
chatApi: lila.chat.ChatApi,
|
||||
userRepo: lila.user.UserRepo,
|
||||
lightUser: lila.common.LightUser.Getter,
|
||||
|
|
|
@ -7,7 +7,7 @@ import chess.{ Centis, Color, Status }
|
|||
import lila.common.{ Bus, Iso, Uptime }
|
||||
import lila.db.dsl._
|
||||
import lila.game.{ Game, Player, Pov, Source }
|
||||
import lila.message.{ MessageApi, ModPreset }
|
||||
import lila.msg.{ MsgApi, MsgPreset }
|
||||
import lila.user.{ User, UserRepo }
|
||||
|
||||
import org.joda.time.DateTime
|
||||
|
@ -18,7 +18,7 @@ final class PlaybanApi(
|
|||
feedback: PlaybanFeedback,
|
||||
userRepo: UserRepo,
|
||||
cacheApi: lila.memo.CacheApi,
|
||||
messenger: MessageApi
|
||||
messenger: MsgApi
|
||||
)(implicit ec: scala.concurrent.ExecutionContext) {
|
||||
|
||||
import lila.db.BSON.BSONJodaDateTimeHandler
|
||||
|
@ -239,16 +239,14 @@ final class PlaybanApi(
|
|||
rageSitCache.put(record.userId, fuccess(record.rageSit))
|
||||
(delta < 0) ?? {
|
||||
if (record.rageSit.isTerrible) funit
|
||||
else if (record.rageSit.isVeryBad) for {
|
||||
mod <- userRepo.lichess
|
||||
user <- userRepo byId record.userId
|
||||
} yield (mod zip user).headOption foreach {
|
||||
case (m, u) =>
|
||||
lila.log("ragesit").info(s"https://lichess.org/@/${u.username} ${record.rageSit.counterView}")
|
||||
Bus.publish(lila.hub.actorApi.mod.AutoWarning(u.id, ModPreset.sittingAuto.subject), "autoWarning")
|
||||
messenger.sendPreset(m, u, ModPreset.sittingAuto).void
|
||||
}
|
||||
else funit
|
||||
else if (record.rageSit.isVeryBad)
|
||||
userRepo byId record.userId map {
|
||||
_ ?? { u =>
|
||||
lila.log("ragesit").info(s"https://lichess.org/@/${u.username} ${record.rageSit.counterView}")
|
||||
Bus.publish(lila.hub.actorApi.mod.AutoWarning(u.id, MsgPreset.sittingAuto.name), "autoWarning")
|
||||
messenger.postPreset(u, MsgPreset.sittingAuto).void
|
||||
}
|
||||
} else funit
|
||||
}
|
||||
case _ => funit
|
||||
}
|
||||
|
|
|
@ -5,12 +5,12 @@ import scala.concurrent.duration._
|
|||
|
||||
import chess.Color
|
||||
import lila.game.Game
|
||||
import lila.message.{ MessageApi, ModPreset }
|
||||
import lila.msg.{ MsgApi, MsgPreset }
|
||||
import lila.user.{ User, UserRepo }
|
||||
|
||||
final private class SandbagWatch(
|
||||
userRepo: UserRepo,
|
||||
messenger: MessageApi
|
||||
messenger: MsgApi
|
||||
)(implicit ec: scala.concurrent.ExecutionContext) {
|
||||
|
||||
import SandbagWatch._
|
||||
|
@ -29,15 +29,13 @@ final private class SandbagWatch(
|
|||
}
|
||||
|
||||
private def sendMessage(userId: User.ID): Funit =
|
||||
for {
|
||||
mod <- userRepo.lichess
|
||||
user <- userRepo byId userId
|
||||
} yield (mod zip user).headOption.?? {
|
||||
case (m, u) =>
|
||||
userRepo byId userId map {
|
||||
_ ?? { u =>
|
||||
lila.log("sandbag").info(s"https://lichess.org/@/${u.username}")
|
||||
lila.common.Bus
|
||||
.publish(lila.hub.actorApi.mod.AutoWarning(u.id, ModPreset.sandbagAuto.subject), "autoWarning")
|
||||
messenger.sendPreset(m, u, ModPreset.sandbagAuto).void
|
||||
.publish(lila.hub.actorApi.mod.AutoWarning(u.id, MsgPreset.sandbagAuto.name), "autoWarning")
|
||||
messenger.postPreset(u, MsgPreset.sandbagAuto).void
|
||||
}
|
||||
}
|
||||
|
||||
private def updateRecord(userId: User.ID, record: Record) =
|
||||
|
|
|
@ -176,7 +176,7 @@ final class RelationApi(
|
|||
(config.maxBlock < nb) ?? repo.drop(u, false, nb - config.maxBlock.value)
|
||||
}
|
||||
|
||||
def block(u1: ID, u2: ID): Funit = (u1 != u2) ?? {
|
||||
def block(u1: ID, u2: ID): Funit = (u1 != u2 && u2 != User.lichessId) ?? {
|
||||
fetchBlocks(u1, u2) flatMap {
|
||||
case true => funit
|
||||
case _ =>
|
||||
|
|
|
@ -5,6 +5,7 @@ import { bind } from './util';
|
|||
import MsgCtrl from '../ctrl';
|
||||
|
||||
export default function renderActions(ctrl: MsgCtrl, convo: Convo): VNode[] {
|
||||
if (convo.user.id == 'lichess') return [];
|
||||
const nodes = [];
|
||||
const cls = 'msg-app__convo__action.button.button-empty';
|
||||
nodes.push(
|
||||
|
|
Loading…
Reference in New Issue