Merge pull request #9098 from niklasf/mention-pref
opt-out of forum mentions (closes #9069)pull/9111/head
commit
a940235095
|
@ -169,6 +169,10 @@ object pref {
|
||||||
trans.letOtherPlayersInviteYouToStudy(),
|
trans.letOtherPlayersInviteYouToStudy(),
|
||||||
radios(form("studyInvite"), translatedStudyInviteChoices)
|
radios(form("studyInvite"), translatedStudyInviteChoices)
|
||||||
),
|
),
|
||||||
|
setting(
|
||||||
|
trans.receiveForumNotifications(),
|
||||||
|
radios(form("mention"), booleanChoices)
|
||||||
|
),
|
||||||
setting(
|
setting(
|
||||||
trans.shareYourInsightsData(),
|
trans.shareYourInsightsData(),
|
||||||
radios(form("insightShare"), translatedInsightShareChoices)
|
radios(form("insightShare"), translatedInsightShareChoices)
|
||||||
|
|
|
@ -9,6 +9,7 @@ import lila.hub.actorApi.team.CreateTeam
|
||||||
import lila.mod.ModlogApi
|
import lila.mod.ModlogApi
|
||||||
import lila.notify.NotifyApi
|
import lila.notify.NotifyApi
|
||||||
import lila.relation.RelationApi
|
import lila.relation.RelationApi
|
||||||
|
import lila.pref.PrefApi
|
||||||
import play.api.libs.ws.StandaloneWSClient
|
import play.api.libs.ws.StandaloneWSClient
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
|
@ -30,6 +31,7 @@ final class Env(
|
||||||
forumSearch: lila.hub.actors.ForumSearch,
|
forumSearch: lila.hub.actors.ForumSearch,
|
||||||
notifyApi: NotifyApi,
|
notifyApi: NotifyApi,
|
||||||
relationApi: RelationApi,
|
relationApi: RelationApi,
|
||||||
|
prefApi: PrefApi,
|
||||||
userRepo: lila.user.UserRepo,
|
userRepo: lila.user.UserRepo,
|
||||||
cacheApi: lila.memo.CacheApi,
|
cacheApi: lila.memo.CacheApi,
|
||||||
ws: StandaloneWSClient
|
ws: StandaloneWSClient
|
||||||
|
|
|
@ -4,6 +4,7 @@ import lila.common.Future
|
||||||
import lila.notify.NotifyApi
|
import lila.notify.NotifyApi
|
||||||
import lila.notify.{ MentionedInThread, Notification }
|
import lila.notify.{ MentionedInThread, Notification }
|
||||||
import lila.relation.RelationApi
|
import lila.relation.RelationApi
|
||||||
|
import lila.pref.PrefApi
|
||||||
import lila.user.{ User, UserRepo }
|
import lila.user.{ User, UserRepo }
|
||||||
|
|
||||||
/** Notifier to inform users if they have been mentioned in a post
|
/** Notifier to inform users if they have been mentioned in a post
|
||||||
|
@ -13,11 +14,10 @@ import lila.user.{ User, UserRepo }
|
||||||
final class MentionNotifier(
|
final class MentionNotifier(
|
||||||
userRepo: UserRepo,
|
userRepo: UserRepo,
|
||||||
notifyApi: NotifyApi,
|
notifyApi: NotifyApi,
|
||||||
relationApi: RelationApi
|
relationApi: RelationApi,
|
||||||
|
prefApi: PrefApi
|
||||||
)(implicit ec: scala.concurrent.ExecutionContext) {
|
)(implicit ec: scala.concurrent.ExecutionContext) {
|
||||||
|
|
||||||
private val forbidden = Set("lichess", "thibault")
|
|
||||||
|
|
||||||
def notifyMentionedUsers(post: Post, topic: Topic): Funit =
|
def notifyMentionedUsers(post: Post, topic: Topic): Funit =
|
||||||
post.userId.ifFalse(post.troll) ?? { author =>
|
post.userId.ifFalse(post.troll) ?? { author =>
|
||||||
filterValidUsers(extractMentionedUsers(post), author) flatMap { validUsers =>
|
filterValidUsers(extractMentionedUsers(post), author) flatMap { validUsers =>
|
||||||
|
@ -30,15 +30,18 @@ final class MentionNotifier(
|
||||||
/** Checks the database to make sure that the users mentioned exist, and removes any users that do not exist
|
/** Checks the database to make sure that the users mentioned exist, and removes any users that do not exist
|
||||||
* or block the mentioner from the returned list.
|
* or block the mentioner from the returned list.
|
||||||
*/
|
*/
|
||||||
private def filterValidUsers(users: Set[User.ID], mentionedBy: User.ID): Fu[List[Notification.Notifies]] = {
|
private def filterValidUsers(
|
||||||
|
candidates: Set[User.ID],
|
||||||
|
mentionedBy: User.ID
|
||||||
|
): Fu[List[Notification.Notifies]] = {
|
||||||
for {
|
for {
|
||||||
validUsers <-
|
existingUsers <-
|
||||||
userRepo
|
userRepo
|
||||||
.existingUsernameIds(users take 10 diff forbidden)
|
.existingUsernameIds(candidates take 10)
|
||||||
.map(_ take 5)
|
.map(_.take(5).toSet)
|
||||||
validUnblockedUsers <- filterNotBlockedByUsers(validUsers, mentionedBy)
|
mentionableUsers <- prefApi.mentionableIds(existingUsers)
|
||||||
validNotifies = validUnblockedUsers.map(Notification.Notifies.apply)
|
users <- filterNotBlockedByUsers(mentionableUsers.toList, mentionedBy)
|
||||||
} yield validNotifies
|
} yield users.map(Notification.Notifies.apply)
|
||||||
}
|
}
|
||||||
|
|
||||||
private def filterNotBlockedByUsers(
|
private def filterNotBlockedByUsers(
|
||||||
|
|
|
@ -540,6 +540,7 @@ val `youCanAlsoScrollOverTheBoardToMoveInTheGame` = new I18nKey("youCanAlsoScrol
|
||||||
val `scrollOverComputerVariationsToPreviewThem` = new I18nKey("scrollOverComputerVariationsToPreviewThem")
|
val `scrollOverComputerVariationsToPreviewThem` = new I18nKey("scrollOverComputerVariationsToPreviewThem")
|
||||||
val `analysisShapesHowTo` = new I18nKey("analysisShapesHowTo")
|
val `analysisShapesHowTo` = new I18nKey("analysisShapesHowTo")
|
||||||
val `letOtherPlayersMessageYou` = new I18nKey("letOtherPlayersMessageYou")
|
val `letOtherPlayersMessageYou` = new I18nKey("letOtherPlayersMessageYou")
|
||||||
|
val `receiveForumNotifications` = new I18nKey("receiveForumNotifications")
|
||||||
val `shareYourInsightsData` = new I18nKey("shareYourInsightsData")
|
val `shareYourInsightsData` = new I18nKey("shareYourInsightsData")
|
||||||
val `withNobody` = new I18nKey("withNobody")
|
val `withNobody` = new I18nKey("withNobody")
|
||||||
val `withFriends` = new I18nKey("withFriends")
|
val `withFriends` = new I18nKey("withFriends")
|
||||||
|
|
|
@ -36,6 +36,7 @@ object JsonView {
|
||||||
"coordColor" -> p.coordColor,
|
"coordColor" -> p.coordColor,
|
||||||
"submitMove" -> p.submitMove,
|
"submitMove" -> p.submitMove,
|
||||||
"confirmResign" -> p.confirmResign,
|
"confirmResign" -> p.confirmResign,
|
||||||
|
"mention" -> p.mention,
|
||||||
"insightShare" -> p.insightShare,
|
"insightShare" -> p.insightShare,
|
||||||
"keyboardMove" -> p.keyboardMove,
|
"keyboardMove" -> p.keyboardMove,
|
||||||
"zen" -> p.zen,
|
"zen" -> p.zen,
|
||||||
|
|
|
@ -32,6 +32,7 @@ case class Pref(
|
||||||
coordColor: Int,
|
coordColor: Int,
|
||||||
submitMove: Int,
|
submitMove: Int,
|
||||||
confirmResign: Int,
|
confirmResign: Int,
|
||||||
|
mention: Boolean,
|
||||||
insightShare: Int,
|
insightShare: Int,
|
||||||
keyboardMove: Int,
|
keyboardMove: Int,
|
||||||
zen: Int,
|
zen: Int,
|
||||||
|
@ -211,6 +212,8 @@ object Pref {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object Mention extends BooleanPref
|
||||||
|
|
||||||
object KeyboardMove extends BooleanPref
|
object KeyboardMove extends BooleanPref
|
||||||
|
|
||||||
object RookCastle {
|
object RookCastle {
|
||||||
|
@ -433,6 +436,7 @@ object Pref {
|
||||||
coordColor = Color.RANDOM,
|
coordColor = Color.RANDOM,
|
||||||
submitMove = SubmitMove.CORRESPONDENCE_ONLY,
|
submitMove = SubmitMove.CORRESPONDENCE_ONLY,
|
||||||
confirmResign = ConfirmResign.YES,
|
confirmResign = ConfirmResign.YES,
|
||||||
|
mention = true,
|
||||||
insightShare = InsightShare.FRIENDS,
|
insightShare = InsightShare.FRIENDS,
|
||||||
keyboardMove = KeyboardMove.NO,
|
keyboardMove = KeyboardMove.NO,
|
||||||
zen = Zen.NO,
|
zen = Zen.NO,
|
||||||
|
|
|
@ -51,7 +51,7 @@ final class PrefApi(
|
||||||
def followable(userId: User.ID): Fu[Boolean] =
|
def followable(userId: User.ID): Fu[Boolean] =
|
||||||
coll.primitiveOne[Boolean]($id(userId), "follow") map (_ | Pref.default.follow)
|
coll.primitiveOne[Boolean]($id(userId), "follow") map (_ | Pref.default.follow)
|
||||||
|
|
||||||
def unfollowableIds(userIds: List[User.ID]): Fu[Set[User.ID]] =
|
private def unfollowableIds(userIds: List[User.ID]): Fu[Set[User.ID]] =
|
||||||
coll.secondaryPreferred.distinctEasy[User.ID, Set](
|
coll.secondaryPreferred.distinctEasy[User.ID, Set](
|
||||||
"_id",
|
"_id",
|
||||||
$inIds(userIds) ++ $doc("follow" -> false)
|
$inIds(userIds) ++ $doc("follow" -> false)
|
||||||
|
@ -65,6 +65,15 @@ final class PrefApi(
|
||||||
userIds map followables.contains
|
userIds map followables.contains
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private def unmentionableIds(userIds: Set[User.ID]): Fu[Set[User.ID]] =
|
||||||
|
coll.secondaryPreferred.distinctEasy[User.ID, Set](
|
||||||
|
"_id",
|
||||||
|
$inIds(userIds) ++ $doc("mention" -> false)
|
||||||
|
)
|
||||||
|
|
||||||
|
def mentionableIds(userIds: Set[User.ID]): Fu[Set[User.ID]] =
|
||||||
|
unmentionableIds(userIds) map userIds.diff
|
||||||
|
|
||||||
def setPref(pref: Pref): Funit =
|
def setPref(pref: Pref): Funit =
|
||||||
coll.update.one($id(pref.id), pref, upsert = true).void >>-
|
coll.update.one($id(pref.id), pref, upsert = true).void >>-
|
||||||
cache.put(pref.id, fuccess(pref.some))
|
cache.put(pref.id, fuccess(pref.some))
|
||||||
|
|
|
@ -51,6 +51,7 @@ object PrefForm {
|
||||||
"challenge" -> checkedNumber(Pref.Challenge.choices),
|
"challenge" -> checkedNumber(Pref.Challenge.choices),
|
||||||
"message" -> checkedNumber(Pref.Message.choices),
|
"message" -> checkedNumber(Pref.Message.choices),
|
||||||
"studyInvite" -> optional(checkedNumber(Pref.StudyInvite.choices)),
|
"studyInvite" -> optional(checkedNumber(Pref.StudyInvite.choices)),
|
||||||
|
"mention" -> booleanNumber,
|
||||||
"insightShare" -> numberIn(Set(0, 1, 2))
|
"insightShare" -> numberIn(Set(0, 1, 2))
|
||||||
)(PrefData.apply)(PrefData.unapply)
|
)(PrefData.apply)(PrefData.unapply)
|
||||||
)
|
)
|
||||||
|
@ -95,6 +96,7 @@ object PrefForm {
|
||||||
challenge: Int,
|
challenge: Int,
|
||||||
message: Int,
|
message: Int,
|
||||||
studyInvite: Option[Int],
|
studyInvite: Option[Int],
|
||||||
|
mention: Int,
|
||||||
insightShare: Int
|
insightShare: Int
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
@ -119,6 +121,7 @@ object PrefForm {
|
||||||
premove = behavior.premove == 1,
|
premove = behavior.premove == 1,
|
||||||
animation = display.animation,
|
animation = display.animation,
|
||||||
submitMove = behavior.submitMove,
|
submitMove = behavior.submitMove,
|
||||||
|
mention = mention == 1,
|
||||||
insightShare = insightShare,
|
insightShare = insightShare,
|
||||||
confirmResign = behavior.confirmResign,
|
confirmResign = behavior.confirmResign,
|
||||||
captured = display.captured == 1,
|
captured = display.captured == 1,
|
||||||
|
@ -167,6 +170,7 @@ object PrefForm {
|
||||||
challenge = pref.challenge,
|
challenge = pref.challenge,
|
||||||
message = pref.message,
|
message = pref.message,
|
||||||
studyInvite = pref.studyInvite.some,
|
studyInvite = pref.studyInvite.some,
|
||||||
|
mention = if (pref.mention) 1 else 0,
|
||||||
insightShare = pref.insightShare
|
insightShare = pref.insightShare
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ private object PrefHandlers {
|
||||||
coordColor = r.getD("coordColor", Pref.default.coordColor),
|
coordColor = r.getD("coordColor", Pref.default.coordColor),
|
||||||
submitMove = r.getD("submitMove", Pref.default.submitMove),
|
submitMove = r.getD("submitMove", Pref.default.submitMove),
|
||||||
confirmResign = r.getD("confirmResign", Pref.default.confirmResign),
|
confirmResign = r.getD("confirmResign", Pref.default.confirmResign),
|
||||||
|
mention = r.getD("mention", Pref.default.mention),
|
||||||
insightShare = r.getD("insightShare", Pref.default.insightShare),
|
insightShare = r.getD("insightShare", Pref.default.insightShare),
|
||||||
keyboardMove = r.getD("keyboardMove", Pref.default.keyboardMove),
|
keyboardMove = r.getD("keyboardMove", Pref.default.keyboardMove),
|
||||||
zen = r.getD("zen", Pref.default.zen),
|
zen = r.getD("zen", Pref.default.zen),
|
||||||
|
@ -85,6 +86,7 @@ private object PrefHandlers {
|
||||||
"coordColor" -> o.coordColor,
|
"coordColor" -> o.coordColor,
|
||||||
"submitMove" -> o.submitMove,
|
"submitMove" -> o.submitMove,
|
||||||
"confirmResign" -> o.confirmResign,
|
"confirmResign" -> o.confirmResign,
|
||||||
|
"mention" -> o.mention,
|
||||||
"insightShare" -> o.insightShare,
|
"insightShare" -> o.insightShare,
|
||||||
"keyboardMove" -> o.keyboardMove,
|
"keyboardMove" -> o.keyboardMove,
|
||||||
"zen" -> o.zen,
|
"zen" -> o.zen,
|
||||||
|
|
|
@ -681,6 +681,7 @@ computer analysis, game chat and shareable URL.</string>
|
||||||
<string name="scrollOverComputerVariationsToPreviewThem">Scroll over computer variations to preview them.</string>
|
<string name="scrollOverComputerVariationsToPreviewThem">Scroll over computer variations to preview them.</string>
|
||||||
<string name="analysisShapesHowTo">Press shift+click or right-click to draw circles and arrows on the board.</string>
|
<string name="analysisShapesHowTo">Press shift+click or right-click to draw circles and arrows on the board.</string>
|
||||||
<string name="letOtherPlayersMessageYou">Let other players message you</string>
|
<string name="letOtherPlayersMessageYou">Let other players message you</string>
|
||||||
|
<string name="receiveForumNotifications">Receive notifications when mentioned in the forum</string>
|
||||||
<string name="shareYourInsightsData">Share your chess insights data</string>
|
<string name="shareYourInsightsData">Share your chess insights data</string>
|
||||||
<string name="withNobody">With nobody</string>
|
<string name="withNobody">With nobody</string>
|
||||||
<string name="withFriends">With friends</string>
|
<string name="withFriends">With friends</string>
|
||||||
|
|
Loading…
Reference in New Issue