import { Notes, Notifications } from "../../../../models/index.js"; import { PaginationHelpers } from "./pagination.js"; import { MastoApiError } from "../middleware/catch-errors.js"; export class NotificationHelpers { static async getNotifications(maxId, sinceId, minId, limit = 40, types, excludeTypes, accountId, ctx) { if (limit > 80) limit = 80; const user = ctx.user; let requestedTypes = types ? this.decodeTypes(types) : [ 'follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollEnded', 'receiveFollowRequest' ]; if (excludeTypes) { const excludedTypes = this.decodeTypes(excludeTypes); requestedTypes = requestedTypes.filter((p)=>!excludedTypes.includes(p)); } const query = PaginationHelpers.makePaginationQuery(Notifications.createQueryBuilder("notification"), sinceId, maxId, minId).andWhere("notification.notifieeId = :userId", { userId: user.id }).andWhere("notification.type IN (:...types)", { types: requestedTypes }); if (accountId !== undefined) query.andWhere("notification.notifierId = :notifierId", { notifierId: accountId }); query.leftJoinAndSelect("notification.note", "note").leftJoinAndSelect("notification.notifier", "notifier").leftJoinAndSelect("notification.notifiee", "notifiee"); return PaginationHelpers.execQueryLinkPagination(query, limit, minId !== undefined, ctx); } static async getNotification(id, ctx) { const user = ctx.user; return Notifications.findOneBy({ id: id, notifieeId: user.id }); } static async getNotificationOr404(id, ctx) { return this.getNotification(id, ctx).then((p)=>{ if (p) return p; throw new MastoApiError(404); }); } static async dismissNotification(id, ctx) { const user = ctx.user; await Notifications.update({ id: id, notifieeId: user.id }, { isRead: true }); } static async clearAllNotifications(ctx) { const user = ctx.user; await Notifications.update({ notifieeId: user.id }, { isRead: true }); } static async markConversationAsRead(id, ctx) { const user = ctx.user; const notesQuery = Notes.createQueryBuilder("note").select("note.id").andWhere("COALESCE(note.threadId, note.id) = :conversationId"); await Notifications.createQueryBuilder("notification").where(`notification."noteId" IN (${notesQuery.getQuery()})`).andWhere(`notification."notifieeId" = :userId`).andWhere(`notification."isRead" = FALSE`).andWhere("notification.type IN (:...types)").setParameter("userId", user.id).setParameter("conversationId", id).setParameter("types", [ 'reply', 'mention' ]).update().set({ isRead: true }).execute(); } static decodeTypes(types) { const result = []; if (types.includes('follow')) result.push('follow'); if (types.includes('mention')) result.push('mention', 'reply'); if (types.includes('reblog')) result.push('renote', 'quote'); if (types.includes('favourite')) result.push('reaction'); if (types.includes('poll')) result.push('pollEnded'); if (types.includes('follow_request')) result.push('receiveFollowRequest'); return result; } }