rudeshark.net/packages/backend/src/services/note/read.ts

174 lines
4.1 KiB
TypeScript
Raw Normal View History

2023-01-13 05:40:33 +01:00
import { publishMainStream } from "@/services/stream.js";
import type { Note } from "@/models/entities/note.js";
import type { User } from "@/models/entities/user.js";
import {
NoteUnreads,
AntennaNotes,
Users,
Followings,
ChannelFollowings,
} from "@/models/index.js";
import { Not, IsNull, In } from "typeorm";
import type { Channel } from "@/models/entities/channel.js";
import { checkHitAntenna } from "@/misc/check-hit-antenna.js";
import { getAntennas } from "@/misc/antenna-cache.js";
import { readNotificationByQuery } from "@/server/api/common/read-notification.js";
import type { Packed } from "@/misc/schema.js";
/**
2021-03-21 09:38:09 +01:00
* Mark notes as read
*/
2023-01-13 05:40:33 +01:00
export default async function (
userId: User["id"],
notes: (Note | Packed<"Note">)[],
2021-03-23 07:12:47 +01:00
info?: {
2023-01-13 05:40:33 +01:00
following: Set<User["id"]>;
followingChannels: Set<Channel["id"]>;
},
) {
2023-01-13 05:40:33 +01: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 07:12:47 +01:00
2023-01-13 05:40:33 +01:00
const myAntennas = (await getAntennas()).filter((a) => a.userId === userId);
const readMentions: (Note | Packed<"Note">)[] = [];
const readSpecifiedNotes: (Note | Packed<"Note">)[] = [];
const readChannelNotes: (Note | Packed<"Note">)[] = [];
const readAntennaNotes: (Note | Packed<"Note">)[] = [];
2021-03-23 07:06:56 +01:00
for (const note of notes) {
2023-01-13 05:40:33 +01:00
if (note.mentions?.includes(userId)) {
2021-03-23 07:06:56 +01:00
readMentions.push(note);
2023-01-13 05:40:33 +01:00
} else if (note.visibleUserIds?.includes(userId)) {
2021-03-23 07:06:56 +01:00
readSpecifiedNotes.push(note);
}
2021-03-23 07:12:47 +01:00
if (note.channelId && followingChannels.has(note.channelId)) {
2021-03-23 07:06:56 +01:00
readChannelNotes.push(note);
}
2023-01-13 05:40:33 +01:00
if (note.user != null) {
// たぶんnullになることは無いはずだけど一応
2021-03-23 07:06:56 +01:00
for (const antenna of myAntennas) {
2023-01-13 05:40:33 +01:00
if (
await checkHitAntenna(
antenna,
note,
note.user,
undefined,
Array.from(following),
)
) {
2021-03-23 07:06:56 +01:00
readAntennaNotes.push(note);
}
}
}
}
2023-01-13 05:40:33 +01:00
if (
readMentions.length > 0 ||
readSpecifiedNotes.length > 0 ||
readChannelNotes.length > 0
) {
// Remove the record
await NoteUnreads.delete({
userId: userId,
2023-01-13 05:40:33 +01:00
noteId: In([
...readMentions.map((n) => n.id),
...readSpecifiedNotes.map((n) => n.id),
...readChannelNotes.map((n) => n.id),
]),
});
2021-03-23 07:06:56 +01:00
// TODO: ↓まとめてクエリしたい
NoteUnreads.countBy({
2021-03-21 09:38:09 +01:00
userId: userId,
2021-12-09 15:58:30 +01:00
isMentioned: true,
2023-01-13 05:40:33 +01:00
}).then((mentionsCount) => {
2021-03-21 09:38:09 +01:00
if (mentionsCount === 0) {
// 全て既読になったイベントを発行
2023-01-13 05:40:33 +01:00
publishMainStream(userId, "readAllUnreadMentions");
2021-03-21 09:38:09 +01:00
}
});
NoteUnreads.countBy({
2021-03-21 09:38:09 +01:00
userId: userId,
2021-12-09 15:58:30 +01:00
isSpecified: true,
2023-01-13 05:40:33 +01:00
}).then((specifiedCount) => {
2021-03-21 09:38:09 +01:00
if (specifiedCount === 0) {
// 全て既読になったイベントを発行
2023-01-13 05:40:33 +01:00
publishMainStream(userId, "readAllUnreadSpecifiedNotes");
2021-03-21 09:38:09 +01:00
}
});
NoteUnreads.countBy({
2021-03-21 09:38:09 +01:00
userId: userId,
2021-12-09 15:58:30 +01:00
noteChannelId: Not(IsNull()),
2023-01-13 05:40:33 +01:00
}).then((channelNoteCount) => {
2021-03-21 09:38:09 +01:00
if (channelNoteCount === 0) {
// 全て既読になったイベントを発行
2023-01-13 05:40:33 +01:00
publishMainStream(userId, "readAllChannels");
2021-03-21 09:38:09 +01:00
}
});
2021-07-08 18:07:55 +02:00
readNotificationByQuery(userId, {
2023-01-13 05:40:33 +01:00
noteId: In([
...readMentions.map((n) => n.id),
...readSpecifiedNotes.map((n) => n.id),
]),
2021-07-08 18:07:55 +02:00
});
}
2021-03-23 07:06:56 +01:00
if (readAntennaNotes.length > 0) {
2023-01-13 05:40:33 +01:00
await AntennaNotes.update(
{
antennaId: In(myAntennas.map((a) => a.id)),
noteId: In(readAntennaNotes.map((n) => n.id)),
},
{
read: true,
},
);
2021-03-23 07:06:56 +01:00
// TODO: まとめてクエリしたい
for (const antenna of myAntennas) {
const count = await AntennaNotes.countBy({
antennaId: antenna.id,
2021-12-09 15:58:30 +01:00
read: false,
});
2021-03-23 07:06:56 +01:00
if (count === 0) {
2023-01-13 05:40:33 +01:00
publishMainStream(userId, "readAntenna", antenna);
}
2021-03-23 07:06:56 +01:00
}
2023-01-13 05:40:33 +01:00
Users.getHasUnreadAntenna(userId).then((unread) => {
if (!unread) {
2023-01-13 05:40:33 +01:00
publishMainStream(userId, "readAllAntennas");
}
});
}
}