lila/modules/notify/src/main/NotifyApi.scala

117 lines
4.2 KiB
Scala
Raw Permalink Normal View History

package lila.notify
import scala.concurrent.duration._
import lila.common.Bus
2019-11-30 16:34:58 -07:00
import lila.common.config.MaxPerPage
import lila.common.paginator.Paginator
import lila.db.dsl._
import lila.db.paginator.Adapter
2018-12-08 04:45:19 -07:00
import lila.hub.actorApi.socket.SendTo
2019-12-23 18:01:45 -07:00
import lila.memo.CacheApi._
2016-06-02 13:41:49 -06:00
import lila.user.UserRepo
import lila.i18n.I18nLangPicker
final class NotifyApi(
jsonHandlers: JSONHandlers,
repo: NotificationRepo,
2019-11-30 16:34:58 -07:00
userRepo: UserRepo,
2019-12-23 18:01:45 -07:00
cacheApi: lila.memo.CacheApi,
2019-11-30 16:34:58 -07:00
maxPerPage: MaxPerPage
)(implicit ec: scala.concurrent.ExecutionContext) {
import BSONHandlers.{ NotificationBSONHandler, NotifiesHandler }
import jsonHandlers._
2020-05-05 22:11:15 -06:00
def getNotifications(userId: Notification.Notifies, page: Int): Fu[Paginator[Notification]] =
Paginator(
adapter = new Adapter(
collection = repo.coll,
selector = repo.userNotificationsQuery(userId),
projection = none,
sort = repo.recentSort
),
currentPage = page,
maxPerPage = maxPerPage
)
def getNotificationsAndCount(userId: Notification.Notifies, page: Int): Fu[Notification.AndUnread] =
2019-12-23 18:01:45 -07:00
getNotifications(userId, page) zip unreadCount(userId) dmap (Notification.AndUnread.apply _).tupled
2016-05-31 16:18:42 -06:00
def markAllRead(userId: Notification.Notifies) =
2019-09-04 11:42:54 -06:00
repo.markAllRead(userId) >>- unreadCountCache.put(userId, fuccess(0))
2019-09-04 13:10:32 -06:00
def markAllRead(userIds: Iterable[Notification.Notifies]) =
repo.markAllRead(userIds) >>- userIds.foreach {
unreadCountCache.put(_, fuccess(0))
}
private val unreadCountCache = cacheApi[Notification.Notifies, Int](32768, "notify.unreadCountCache") {
_.expireAfterAccess(20 minutes)
2019-12-23 18:01:45 -07:00
.buildAsyncFuture(repo.unreadNotificationsCount)
}
2016-05-31 16:18:42 -06:00
def unreadCount(userId: Notification.Notifies): Fu[Notification.UnreadCount] =
2019-12-23 18:01:45 -07:00
unreadCountCache get userId dmap Notification.UnreadCount.apply
def addNotification(notification: Notification): Funit =
// Add to database and then notify any connected clients of the new notification
insertOrDiscardNotification(notification) map {
_ foreach { notif =>
notifyUser(notif.notifies)
}
}
2016-06-03 06:15:48 -06:00
def addNotificationWithoutSkipOrEvent(notification: Notification): Funit =
2019-09-04 11:46:04 -06:00
repo.insert(notification) >>- unreadCountCache.update(notification.notifies, _ + 1)
2016-06-03 06:15:48 -06:00
def addNotifications(notifications: List[Notification]): Funit =
2019-11-30 19:29:40 -07:00
notifications.map(addNotification).sequenceFu.void
2021-09-26 09:10:22 -06:00
def remove(notifies: Notification.Notifies, selector: Bdoc = $empty): Funit =
repo.remove(notifies, selector) >>- unreadCountCache.invalidate(notifies)
def markRead(notifies: Notification.Notifies, selector: Bdoc): Funit =
repo.markManyRead(selector ++ $doc("notifies" -> notifies, "read" -> false)) >>-
unreadCountCache.invalidate(notifies)
def exists = repo.exists _
2016-05-31 16:50:56 -06:00
private def shouldSkip(notification: Notification) =
2020-02-02 21:05:37 -07:00
(!notification.isMsg ?? userRepo.isKid(notification.notifies.value)) >>| {
2017-09-04 11:52:08 -06:00
notification.content match {
2019-12-13 07:30:20 -07:00
case MentionedInThread(_, _, topicId, _, _) =>
repo.hasRecentNotificationsInThread(notification.notifies, topicId)
2019-12-08 07:12:47 -07:00
case InvitedToStudy(_, _, studyId) => repo.hasRecentStudyInvitation(notification.notifies, studyId)
2020-01-25 17:18:21 -07:00
case PrivateMessage(sender, _) => repo.hasRecentPrivateMessageFrom(notification.notifies, sender)
2019-12-13 07:30:20 -07:00
case _ => fuFalse
2016-06-02 13:41:49 -06:00
}
2016-05-31 16:50:56 -06:00
}
2020-10-10 03:08:23 -06:00
/** Inserts notification into the repository.
2019-12-13 07:30:20 -07:00
* If the user already has an unread notification on the topic, discard it.
* If the user does not already have an unread notification on the topic, returns it unmodified.
*/
2016-05-31 16:50:56 -06:00
private def insertOrDiscardNotification(notification: Notification): Fu[Option[Notification]] =
shouldSkip(notification) flatMap {
2019-12-13 07:30:20 -07:00
case true => fuccess(none)
2016-06-03 06:15:48 -06:00
case false => addNotificationWithoutSkipOrEvent(notification) inject notification.some
}
private def notifyUser(notifies: Notification.Notifies): Funit =
getNotificationsAndCount(notifies, 1) map { msg =>
Bus.publish(
SendTo.async(
notifies.value,
"notifications",
() => {
userRepo langOf notifies.value map I18nLangPicker.byStrOrDefault map { implicit lang =>
jsonHandlers(msg)
}
}
),
"socketUsers"
)
}
2016-05-31 06:28:21 -06:00
}