1
0
mirror of https://github.com/MisskeyIO/misskey synced 2024-12-26 12:38:16 +09:00
MisskeyIO/src/services/note/read.ts

128 lines
3.6 KiB
TypeScript
Raw Normal View History

import { publishMainStream } from '../stream';
import { Note } from '../../models/entities/note';
import { User } from '../../models/entities/user';
2021-03-23 15:12:47 +09:00
import { NoteUnreads, AntennaNotes, Users, Followings, ChannelFollowings } from '../../models';
2021-03-21 17:38:09 +09:00
import { Not, IsNull, In } from 'typeorm';
2021-03-23 15:06:56 +09:00
import { Channel } from '../../models/entities/channel';
import { checkHitAntenna } from '../../misc/check-hit-antenna';
import { getAntennas } from '../../misc/antenna-cache';
import { PackedNote } from '../../models/repositories/note';
/**
2021-03-21 17:38:09 +09:00
* Mark notes as read
*/
export default async function(
userId: User['id'],
2021-03-23 15:06:56 +09:00
notes: (Note | PackedNote)[],
2021-03-23 15:12:47 +09:00
info?: {
following: Set<User['id']>;
2021-03-23 15:06:56 +09:00
followingChannels: Set<Channel['id']>;
}
) {
2021-03-23 15:12:47 +09:00
const following = info?.following ? info.following : new Set<string>((await Followings.find({
where: {
followerId: userId
},
select: ['followeeId']
})).map(x => x.followeeId));
const followingChannels = info?.followingChannels ? info.followingChannels : new Set<string>((await ChannelFollowings.find({
where: {
followerId: userId
},
select: ['followeeId']
})).map(x => x.followeeId));
2021-03-23 15:06:56 +09:00
const myAntennas = (await getAntennas()).filter(a => a.userId === userId);
const readMentions: (Note | PackedNote)[] = [];
const readSpecifiedNotes: (Note | PackedNote)[] = [];
const readChannelNotes: (Note | PackedNote)[] = [];
const readAntennaNotes: (Note | PackedNote)[] = [];
for (const note of notes) {
if (note.mentions && note.mentions.includes(userId)) {
readMentions.push(note);
} else if (note.visibleUserIds && note.visibleUserIds.includes(userId)) {
readSpecifiedNotes.push(note);
}
2021-03-23 15:12:47 +09:00
if (note.channelId && followingChannels.has(note.channelId)) {
2021-03-23 15:06:56 +09:00
readChannelNotes.push(note);
}
if (note.user != null) { // たぶんnullになることは無いはずだけど一応
for (const antenna of myAntennas) {
2021-03-23 15:12:47 +09:00
if (checkHitAntenna(antenna, note, note.user as any, undefined, Array.from(following))) {
2021-03-23 15:06:56 +09:00
readAntennaNotes.push(note);
}
}
}
}
if ((readMentions.length > 0) || (readSpecifiedNotes.length > 0) || (readChannelNotes.length > 0)) {
// Remove the record
await NoteUnreads.delete({
userId: userId,
2021-03-23 15:06:56 +09:00
noteId: In([...readMentions.map(n => n.id), ...readSpecifiedNotes.map(n => n.id), ...readChannelNotes.map(n => n.id)]),
});
2021-03-23 15:06:56 +09:00
// TODO: ↓まとめてクエリしたい
2021-03-21 17:38:09 +09:00
NoteUnreads.count({
userId: userId,
isMentioned: true
}).then(mentionsCount => {
if (mentionsCount === 0) {
// 全て既読になったイベントを発行
publishMainStream(userId, 'readAllUnreadMentions');
}
});
2021-03-21 17:38:09 +09:00
NoteUnreads.count({
userId: userId,
isSpecified: true
}).then(specifiedCount => {
if (specifiedCount === 0) {
// 全て既読になったイベントを発行
publishMainStream(userId, 'readAllUnreadSpecifiedNotes');
}
});
2021-03-21 17:38:09 +09:00
NoteUnreads.count({
userId: userId,
noteChannelId: Not(IsNull())
}).then(channelNoteCount => {
if (channelNoteCount === 0) {
// 全て既読になったイベントを発行
publishMainStream(userId, 'readAllChannels');
}
});
}
2021-03-23 15:06:56 +09:00
if (readAntennaNotes.length > 0) {
await AntennaNotes.update({
antennaId: In(myAntennas.map(a => a.id)),
noteId: In(readAntennaNotes.map(n => n.id))
}, {
read: true
});
2021-03-23 15:06:56 +09:00
// TODO: まとめてクエリしたい
for (const antenna of myAntennas) {
const count = await AntennaNotes.count({
antennaId: antenna.id,
read: false
});
2021-03-23 15:06:56 +09:00
if (count === 0) {
publishMainStream(userId, 'readAntenna', antenna);
}
2021-03-23 15:06:56 +09:00
}
Users.getHasUnreadAntenna(userId).then(unread => {
if (!unread) {
publishMainStream(userId, 'readAllAntennas');
}
});
}
}