This commit is contained in:
syuilo 2018-07-21 08:47:48 +09:00
parent 91ad9e4c41
commit 7671c37f2a
1 changed files with 41 additions and 14 deletions

View File

@ -33,29 +33,52 @@ type Type = 'reply' | 'renote' | 'quote' | 'mention';
class NotificationManager { class NotificationManager {
private notifier: IUser; private notifier: IUser;
private note: INote; private note: INote;
private queue: Array<{
target: ILocalUser['_id'];
reason: Type;
}>;
constructor(notifier: IUser, note: INote) { constructor(notifier: IUser, note: INote) {
this.notifier = notifier; this.notifier = notifier;
this.note = note; this.note = note;
this.queue = [];
} }
public async push(notifiee: ILocalUser['_id'], type: Type) { public push(notifiee: ILocalUser['_id'], reason: Type) {
// 自分自身へは通知しない // 自分自身へは通知しない
if (this.notifier._id.equals(notifiee)) return; if (this.notifier._id.equals(notifiee)) return;
const exist = this.queue.find(x => x.target.equals(notifiee));
if (exist) {
// 「メンションされているかつ返信されている」場合は、メンションとしての通知ではなく返信としての通知にする
if (reason != 'mention') {
exist.reason = reason;
}
} else {
this.queue.push({
reason: reason,
target: notifiee
});
}
}
public deliver() {
this.queue.forEach(async x => {
// ミュート情報を取得 // ミュート情報を取得
const mentioneeMutes = await Mute.find({ const mentioneeMutes = await Mute.find({
muterId: notifiee muterId: x.target
}); });
const mentioneesMutedUserIds = mentioneeMutes.map(m => m.muteeId.toString()); const mentioneesMutedUserIds = mentioneeMutes.map(m => m.muteeId.toString());
// 通知される側のユーザーが通知する側のユーザーをミュートしていない限りは通知する // 通知される側のユーザーが通知する側のユーザーをミュートしていない限りは通知する
if (!mentioneesMutedUserIds.includes(this.notifier._id.toString())) { if (!mentioneesMutedUserIds.includes(this.notifier._id.toString())) {
notify(notifiee, this.notifier._id, type, { notify(x.target, this.notifier._id, x.reason, {
noteId: this.note._id noteId: this.note._id
}); });
} }
});
} }
} }
@ -124,6 +147,7 @@ export default async (user: IUser, data: Option, silent = false) => new Promise<
const noteObj = await pack(note); const noteObj = await pack(note);
const nm = new NotificationManager(user, note); const nm = new NotificationManager(user, note);
const nmRelatedPromises = [];
createMentionedEvents(mentionedUsers, noteObj, nm); createMentionedEvents(mentionedUsers, noteObj, nm);
@ -136,7 +160,7 @@ export default async (user: IUser, data: Option, silent = false) => new Promise<
// If has in reply to note // If has in reply to note
if (data.reply) { if (data.reply) {
// Fetch watchers // Fetch watchers
notifyToWatchersOfReplyee(data.reply, user, nm); nmRelatedPromises.push(notifyToWatchersOfReplyee(data.reply, user, nm));
// この投稿をWatchする // この投稿をWatchする
if (isLocalUser(user) && user.settings.autoWatch !== false) { if (isLocalUser(user) && user.settings.autoWatch !== false) {
@ -154,7 +178,7 @@ export default async (user: IUser, data: Option, silent = false) => new Promise<
nm.push(data.renote.userId, type); nm.push(data.renote.userId, type);
// Fetch watchers // Fetch watchers
notifyToWatchersOfRenotee(data.renote, user, nm, type); nmRelatedPromises.push(notifyToWatchersOfRenotee(data.renote, user, nm, type));
// この投稿をWatchする // この投稿をWatchする
if (isLocalUser(user) && user.settings.autoWatch !== false) { if (isLocalUser(user) && user.settings.autoWatch !== false) {
@ -177,6 +201,10 @@ export default async (user: IUser, data: Option, silent = false) => new Promise<
publish(user, note, noteObj, data.reply, data.renote, data.visibleUsers, noteActivity); publish(user, note, noteObj, data.reply, data.renote, data.visibleUsers, noteActivity);
} }
Promise.all(nmRelatedPromises).then(() => {
nm.deliver();
});
// Register to search database // Register to search database
index(note); index(note);
}); });
@ -413,7 +441,6 @@ function deliverNoteToMentionedRemoteUsers(mentionedUsers: IUser[], user: ILocal
function createMentionedEvents(mentionedUsers: IUser[], noteObj: any, nm: NotificationManager) { function createMentionedEvents(mentionedUsers: IUser[], noteObj: any, nm: NotificationManager) {
mentionedUsers.filter(u => isLocalUser(u)).forEach(async (u) => { mentionedUsers.filter(u => isLocalUser(u)).forEach(async (u) => {
event(u, 'mention', noteObj); event(u, 'mention', noteObj);
// TODO: 既に言及されたユーザーに対する返信や引用renoteの場合はスキップ
// Create notification // Create notification
nm.push(u._id, 'mention'); nm.push(u._id, 'mention');