Files
2026-07-26 18:25:37 +09:00

129 lines
5.5 KiB
JavaScript

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);
}
});