2016-05-30 06:51:36 -06:00
|
|
|
package lila.notify
|
|
|
|
|
2017-01-26 14:46:26 -07:00
|
|
|
import scala.concurrent.duration._
|
|
|
|
|
2019-11-26 14:44:08 -07:00
|
|
|
import lila.common.Bus
|
2019-11-30 16:34:58 -07:00
|
|
|
import lila.common.config.MaxPerPage
|
2016-05-30 06:51:36 -06:00
|
|
|
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
|
2021-04-07 03:11:36 -06:00
|
|
|
import lila.i18n.I18nLangPicker
|
2016-05-30 06:51:36 -06:00
|
|
|
|
2016-05-31 14:54:05 -06:00
|
|
|
final class NotifyApi(
|
|
|
|
jsonHandlers: JSONHandlers,
|
2017-01-26 14:46:26 -07:00
|
|
|
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
|
2019-12-13 18:17:43 -07:00
|
|
|
)(implicit ec: scala.concurrent.ExecutionContext) {
|
2016-05-30 06:51:36 -06:00
|
|
|
|
2020-02-19 11:52:13 -07:00
|
|
|
import BSONHandlers.{ NotificationBSONHandler, NotifiesHandler }
|
2016-05-31 14:54:05 -06:00
|
|
|
import jsonHandlers._
|
2016-05-30 06:51:36 -06:00
|
|
|
|
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
|
|
|
|
)
|
2016-06-02 12:42:53 -06:00
|
|
|
|
|
|
|
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-30 06:51:36 -06:00
|
|
|
|
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))
|
2016-05-30 06:51:36 -06:00
|
|
|
|
2019-09-04 13:10:32 -06:00
|
|
|
def markAllRead(userIds: Iterable[Notification.Notifies]) =
|
|
|
|
repo.markAllRead(userIds) >>- userIds.foreach {
|
|
|
|
unreadCountCache.put(_, fuccess(0))
|
|
|
|
}
|
|
|
|
|
2019-12-24 07:31:19 -07:00
|
|
|
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
|
|
|
|
2016-06-02 12:42:53 -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
|
2016-05-30 06:51:36 -06:00
|
|
|
|
2016-06-02 12:42:53 -06:00
|
|
|
def addNotification(notification: Notification): Funit =
|
2016-05-30 06:51:36 -06:00
|
|
|
// Add to database and then notify any connected clients of the new notification
|
2016-05-30 18:14:06 -06:00
|
|
|
insertOrDiscardNotification(notification) map {
|
2016-06-02 12:42:53 -06:00
|
|
|
_ foreach { notif =>
|
|
|
|
notifyUser(notif.notifies)
|
2016-05-30 18:14:06 -06:00
|
|
|
}
|
|
|
|
}
|
2016-05-30 06:51:36 -06:00
|
|
|
|
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
|
2016-05-30 06:51:36 -06:00
|
|
|
|
2021-09-26 09:10:22 -06:00
|
|
|
def remove(notifies: Notification.Notifies, selector: Bdoc = $empty): Funit =
|
2017-01-26 14:46:26 -07:00
|
|
|
repo.remove(notifies, selector) >>- unreadCountCache.invalidate(notifies)
|
2016-06-08 06:52:28 -06:00
|
|
|
|
2020-02-19 11:52:13 -07:00
|
|
|
def markRead(notifies: Notification.Notifies, selector: Bdoc): Funit =
|
|
|
|
repo.markManyRead(selector ++ $doc("notifies" -> notifies, "read" -> false)) >>-
|
|
|
|
unreadCountCache.invalidate(notifies)
|
|
|
|
|
2016-06-19 15:54:42 -06:00
|
|
|
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
|
2016-05-30 18:14:06 -06:00
|
|
|
}
|
|
|
|
|
2016-06-02 12:42:53 -06:00
|
|
|
private def notifyUser(notifies: Notification.Notifies): Funit =
|
|
|
|
getNotificationsAndCount(notifies, 1) map { msg =>
|
2021-04-07 03:11:36 -06:00
|
|
|
Bus.publish(
|
|
|
|
SendTo.async(
|
|
|
|
notifies.value,
|
|
|
|
"notifications",
|
|
|
|
() => {
|
|
|
|
userRepo langOf notifies.value map I18nLangPicker.byStrOrDefault map { implicit lang =>
|
|
|
|
jsonHandlers(msg)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
),
|
|
|
|
"socketUsers"
|
|
|
|
)
|
2016-06-02 12:42:53 -06:00
|
|
|
}
|
2016-05-31 06:28:21 -06:00
|
|
|
}
|