import { In } from "typeorm"; import { Notification } from "../entities/notification.js"; import { awaitAll } from "../../prelude/await-all.js"; import { aggregateNoteEmojis, prefetchEmojis } from "../../misc/populate-emojis.js"; import { db } from "../../db/postgre.js"; import { Users, Notes, UserGroupInvitations, AccessTokens, NoteReactions, Bites } from "../index.js"; export const NotificationRepository = db.getRepository(Notification).extend({ async pack (src, options) { const notification = typeof src === "object" ? src : await this.findOneByOrFail({ id: src }); const token = notification.appAccessTokenId ? await AccessTokens.findOneByOrFail({ id: notification.appAccessTokenId }) : null; return await awaitAll({ id: notification.id, createdAt: notification.createdAt.toISOString(), type: notification.type, isRead: notification.isRead, userId: notification.notifierId, user: notification.notifierId ? Users.pack(notification.notifier || notification.notifierId) : null, ...notification.type === "mention" ? { note: Notes.pack(notification.note || notification.noteId, { id: notification.notifieeId }, { detail: true, _hint_: options._hintForEachNotes_ }) } : {}, ...notification.type === "reply" ? { note: Notes.pack(notification.note || notification.noteId, { id: notification.notifieeId }, { detail: true, _hint_: options._hintForEachNotes_ }) } : {}, ...notification.type === "renote" ? { note: Notes.pack(notification.note || notification.noteId, { id: notification.notifieeId }, { detail: true, _hint_: options._hintForEachNotes_ }) } : {}, ...notification.type === "quote" ? { note: Notes.pack(notification.note || notification.noteId, { id: notification.notifieeId }, { detail: true, _hint_: options._hintForEachNotes_ }) } : {}, ...notification.type === "reaction" ? { note: Notes.pack(notification.note || notification.noteId, { id: notification.notifieeId }, { detail: true, _hint_: options._hintForEachNotes_ }), reaction: notification.reaction } : {}, ...notification.type === "pollVote" ? { note: Notes.pack(notification.note || notification.noteId, { id: notification.notifieeId }, { detail: true, _hint_: options._hintForEachNotes_ }), choice: notification.choice } : {}, ...notification.type === "pollEnded" ? { note: Notes.pack(notification.note || notification.noteId, { id: notification.notifieeId }, { detail: true, _hint_: options._hintForEachNotes_ }) } : {}, ...notification.type === "groupInvited" ? { invitation: UserGroupInvitations.pack(notification.userGroupInvitationId) } : {}, ...notification.type === "app" ? { body: notification.customBody, header: notification.customHeader || token?.name, icon: notification.customIcon || token?.iconUrl } : {}, ...notification.type === "bite" ? { bite: Bites.pack(notification.bite || notification.biteId, { id: notification.notifieeId }) } : {} }); }, async packMany (notifications, meId) { if (notifications.length === 0) return []; const notes = notifications.filter((x)=>x.note != null).map((x)=>x.note); const noteIds = notes.map((n)=>n.id); const myReactionsMap = new Map(); const myRenotesMap = new Map(); const renoteIds = notes.filter((n)=>n.renoteId != null).map((n)=>n.renoteId); const targets = [ ...noteIds, ...renoteIds ]; const myReactions = await NoteReactions.findBy({ userId: meId, noteId: In(targets) }); const myRenotes = targets.length > 0 ? await Notes.createQueryBuilder('note').select('note.renoteId').where('note.userId = :meId', { meId }).andWhere('note.renoteId IN (:...targets)', { targets }).getMany() : []; for (const target of targets){ myReactionsMap.set(target, myReactions.find((reaction)=>reaction.noteId === target) || null); myRenotesMap.set(target, !!myRenotes.find((p)=>p.renoteId == target)); } await prefetchEmojis(aggregateNoteEmojis(notes)); const results = await Promise.all(notifications.map((x)=>this.pack(x, { _hintForEachNotes_: { myReactions: myReactionsMap, myRenotes: myRenotesMap } }).catch((e)=>null))); return results.filter((x)=>x != null); } });