Implement #2736
This commit is contained in:
@@ -25,6 +25,7 @@ import { TextElementMention } from '../../mfm/parse/elements/mention';
|
||||
import { TextElementHashtag } from '../../mfm/parse/elements/hashtag';
|
||||
import { updateNoteStats } from '../update-chart';
|
||||
import { erase, unique } from '../../prelude/array';
|
||||
import insertNoteUnread from './unread';
|
||||
|
||||
type NotificationType = 'reply' | 'renote' | 'quote' | 'mention';
|
||||
|
||||
@@ -170,6 +171,17 @@ export default async (user: IUser, data: Option, silent = false) => new Promise<
|
||||
// Increment notes count (user)
|
||||
incNotesCountOfUser(user);
|
||||
|
||||
// 未読通知を作成
|
||||
if (data.visibility == 'specified') {
|
||||
data.visibleUsers.forEach(u => {
|
||||
insertNoteUnread(u, note, true);
|
||||
});
|
||||
} else {
|
||||
mentionedUsers.forEach(u => {
|
||||
insertNoteUnread(u, note, false);
|
||||
});
|
||||
}
|
||||
|
||||
if (data.reply) {
|
||||
saveReply(data.reply, note);
|
||||
}
|
||||
@@ -314,16 +326,6 @@ async function publish(user: IUser, note: INote, noteObj: any, reply: INote, ren
|
||||
publishGlobalTimelineStream(noteObj);
|
||||
}
|
||||
|
||||
if (note.visibility == 'specified') {
|
||||
visibleUsers.forEach(async (u) => {
|
||||
const n = await pack(note, u, {
|
||||
detail: true
|
||||
});
|
||||
publishUserStream(u._id, 'note', n);
|
||||
publishHybridTimelineStream(u._id, n);
|
||||
});
|
||||
}
|
||||
|
||||
if (['public', 'home', 'followers'].includes(note.visibility)) {
|
||||
// フォロワーに配信
|
||||
publishToFollowers(note, user, noteActivity);
|
||||
|
62
src/services/note/read.ts
Normal file
62
src/services/note/read.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import * as mongo from 'mongodb';
|
||||
import { publishUserStream } from '../../stream';
|
||||
import User from '../../models/user';
|
||||
import NoteUnread from '../../models/note-unread';
|
||||
|
||||
/**
|
||||
* Mark a note as read
|
||||
*/
|
||||
export default (
|
||||
user: string | mongo.ObjectID,
|
||||
note: string | mongo.ObjectID
|
||||
) => new Promise<any>(async (resolve, reject) => {
|
||||
|
||||
const userId: mongo.ObjectID = mongo.ObjectID.prototype.isPrototypeOf(user)
|
||||
? user as mongo.ObjectID
|
||||
: new mongo.ObjectID(user);
|
||||
|
||||
const noteId: mongo.ObjectID = mongo.ObjectID.prototype.isPrototypeOf(note)
|
||||
? note as mongo.ObjectID
|
||||
: new mongo.ObjectID(note);
|
||||
|
||||
// Remove document
|
||||
await NoteUnread.remove({
|
||||
userId: userId,
|
||||
noteId: noteId
|
||||
});
|
||||
|
||||
const count1 = await NoteUnread
|
||||
.count({
|
||||
userId: userId,
|
||||
isSpecified: false
|
||||
}, {
|
||||
limit: 1
|
||||
});
|
||||
|
||||
const count2 = await NoteUnread
|
||||
.count({
|
||||
userId: userId,
|
||||
isSpecified: true
|
||||
}, {
|
||||
limit: 1
|
||||
});
|
||||
|
||||
if (count1 == 0 || count2 == 0) {
|
||||
User.update({ _id: userId }, {
|
||||
$set: {
|
||||
hasUnreadMentions: count1 != 0 || count2 != 0,
|
||||
hasUnreadSpecifiedNotes: count2 != 0
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (count1 == 0) {
|
||||
// 全て既読になったイベントを発行
|
||||
publishUserStream(userId, 'readAllUnreadMentions');
|
||||
}
|
||||
|
||||
if (count2 == 0) {
|
||||
// 全て既読になったイベントを発行
|
||||
publishUserStream(userId, 'readAllUnreadSpecifiedNotes');
|
||||
}
|
||||
});
|
47
src/services/note/unread.ts
Normal file
47
src/services/note/unread.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import NoteUnread from '../../models/note-unread';
|
||||
import User, { IUser } from '../../models/user';
|
||||
import { INote } from '../../models/note';
|
||||
import Mute from '../../models/mute';
|
||||
import { publishUserStream } from '../../stream';
|
||||
|
||||
export default async function(user: IUser, note: INote, isSpecified = false) {
|
||||
const unread = await NoteUnread.insert({
|
||||
noteId: note._id,
|
||||
userId: user._id,
|
||||
isSpecified,
|
||||
_note: {
|
||||
userId: note.userId
|
||||
}
|
||||
});
|
||||
|
||||
// 3秒経っても既読にならなかったら「未読の投稿がありますよ」イベントを発行する
|
||||
setTimeout(async () => {
|
||||
const exist = await NoteUnread.findOne({ _id: unread._id });
|
||||
if (exist == null) return;
|
||||
|
||||
//#region ただしミュートされているなら発行しない
|
||||
const mute = await Mute.find({
|
||||
muterId: user._id
|
||||
});
|
||||
const mutedUserIds = mute.map(m => m.muteeId.toString());
|
||||
if (mutedUserIds.includes(note.userId.toString())) return;
|
||||
//#endregion
|
||||
|
||||
User.update({
|
||||
_id: user._id
|
||||
}, {
|
||||
$set: isSpecified ? {
|
||||
hasUnreadSpecifiedNotes: true,
|
||||
hasUnreadMentions: true
|
||||
} : {
|
||||
hasUnreadMentions: true
|
||||
}
|
||||
});
|
||||
|
||||
publishUserStream(user._id, 'unreadMention', note._id);
|
||||
|
||||
if (isSpecified) {
|
||||
publishUserStream(user._id, 'unreadSpecifiedNote', note._id);
|
||||
}
|
||||
}, 3000);
|
||||
}
|
Reference in New Issue
Block a user