131 lines
3.8 KiB
Scala
131 lines
3.8 KiB
Scala
package lila.appeal
|
|
|
|
import org.joda.time.DateTime
|
|
|
|
import lila.db.dsl._
|
|
import lila.user.{ Holder, NoteApi, User, UserRepo }
|
|
import reactivemongo.api.ReadPreference
|
|
|
|
final class AppealApi(
|
|
coll: Coll,
|
|
userRepo: UserRepo,
|
|
noteApi: NoteApi,
|
|
snoozer: lila.memo.Snoozer[Appeal.SnoozeKey]
|
|
)(implicit ec: scala.concurrent.ExecutionContext) {
|
|
|
|
import BsonHandlers._
|
|
|
|
def mine(me: User): Fu[Option[Appeal]] = coll.byId[Appeal](me.id)
|
|
|
|
def get(user: User) = coll.byId[Appeal](user.id)
|
|
|
|
def byUserIds(userIds: List[User.ID]) = coll.byIds[Appeal](userIds)
|
|
|
|
def byId(appealId: User.ID) = coll.byId[Appeal](appealId)
|
|
|
|
def exists(user: User) = coll.exists($id(user.id))
|
|
|
|
def post(text: String, me: User) =
|
|
mine(me) flatMap {
|
|
case None =>
|
|
val appeal =
|
|
Appeal(
|
|
_id = me.id,
|
|
msgs = Vector(
|
|
AppealMsg(
|
|
by = me.id,
|
|
text = text,
|
|
at = DateTime.now
|
|
)
|
|
),
|
|
status = Appeal.Status.Unread,
|
|
createdAt = DateTime.now,
|
|
updatedAt = DateTime.now,
|
|
firstUnrepliedAt = DateTime.now
|
|
)
|
|
coll.insert.one(appeal) inject appeal
|
|
case Some(prev) =>
|
|
val appeal = prev.post(text, me)
|
|
coll.update.one($id(appeal.id), appeal) inject appeal
|
|
}
|
|
|
|
def reply(text: String, prev: Appeal, mod: Holder, preset: Option[String]) = {
|
|
val appeal = prev.post(text, mod.user)
|
|
coll.update.one($id(appeal.id), appeal) >> {
|
|
preset ?? { note =>
|
|
userRepo.byId(appeal.id) flatMap {
|
|
_ ?? { noteApi.write(_, s"Appeal reply: $note", mod.user, modOnly = true, dox = false) }
|
|
}
|
|
}
|
|
} inject appeal
|
|
}
|
|
|
|
def countUnread = coll.countSel($doc("status" -> Appeal.Status.Unread.key))
|
|
|
|
def queueOf(mod: User) = bothQueues(snoozer snoozedKeysOf mod.id map (_.appealId))
|
|
|
|
private def bothQueues(exceptIds: Iterable[User.ID]): Fu[List[Appeal.WithUser]] =
|
|
fetchQueue(
|
|
selector = $doc("status" -> Appeal.Status.Unread.key) ++ {
|
|
exceptIds.nonEmpty ?? $doc("_id" $nin exceptIds)
|
|
},
|
|
ascending = true,
|
|
nb = 30
|
|
) flatMap { unreads =>
|
|
fetchQueue(
|
|
selector = $doc("status" $ne Appeal.Status.Unread.key),
|
|
ascending = false,
|
|
nb = 40 - unreads.size
|
|
) map { unreads ::: _ }
|
|
}
|
|
|
|
private def fetchQueue(selector: Bdoc, ascending: Boolean, nb: Int): Fu[List[Appeal.WithUser]] =
|
|
coll
|
|
.aggregateList(
|
|
maxDocs = nb,
|
|
ReadPreference.secondaryPreferred
|
|
) { framework =>
|
|
import framework._
|
|
Match(selector) -> List(
|
|
Sort((if (ascending) Ascending.apply _ else Descending.apply _)("firstUnrepliedAt")),
|
|
Limit(nb),
|
|
PipelineOperator(
|
|
$lookup.simple(
|
|
from = userRepo.coll,
|
|
as = "user",
|
|
local = "_id",
|
|
foreign = "_id"
|
|
)
|
|
),
|
|
UnwindField("user")
|
|
)
|
|
}
|
|
.map { docs =>
|
|
for {
|
|
doc <- docs
|
|
appeal <- doc.asOpt[Appeal]
|
|
user <- doc.getAsOpt[User]("user")
|
|
} yield Appeal.WithUser(appeal, user)
|
|
}
|
|
|
|
def setRead(appeal: Appeal) =
|
|
coll.update.one($id(appeal.id), appeal.read).void
|
|
|
|
def setUnread(appeal: Appeal) =
|
|
coll.update.one($id(appeal.id), appeal.unread).void
|
|
|
|
def toggleMute(appeal: Appeal) =
|
|
coll.update.one($id(appeal.id), appeal.toggleMute).void
|
|
|
|
def setReadById(userId: User.ID) =
|
|
byId(userId) flatMap { _ ?? setRead }
|
|
|
|
def setUnreadById(userId: User.ID) =
|
|
byId(userId) flatMap { _ ?? setUnread }
|
|
|
|
def onAccountClose(user: User) = setReadById(user.id)
|
|
|
|
def snooze(mod: User, appealId: User.ID, duration: String): Unit =
|
|
snoozer.set(Appeal.SnoozeKey(mod.id, appealId), duration)
|
|
}
|