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 07:35:02 +01:00
|
|
|
|
|
|
|
/**
|
2021-03-21 09:38:09 +01:00
|
|
|
* Mark notes as read
|
2021-03-21 07:35:02 +01:00
|
|
|
*/
|
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"]>;
|
|
|
|
},
|
2021-03-21 07:35:02 +01:00
|
|
|
) {
|
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
|
|
|
|
) {
|
2021-03-21 07:35:02 +01:00
|
|
|
// 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-21 07:35:02 +01:00
|
|
|
});
|
|
|
|
|
2021-03-23 07:06:56 +01:00
|
|
|
// TODO: ↓まとめてクエリしたい
|
|
|
|
|
2022-03-26 07:34:00 +01:00
|
|
|
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
|
|
|
}
|
|
|
|
});
|
2021-03-21 07:35:02 +01:00
|
|
|
|
2022-03-26 07:34:00 +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
|
|
|
}
|
|
|
|
});
|
2021-03-21 07:35:02 +01:00
|
|
|
|
2022-03-26 07:34:00 +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-21 07:35:02 +01: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-21 07:35:02 +01:00
|
|
|
|
2021-03-23 07:06:56 +01:00
|
|
|
// TODO: まとめてクエリしたい
|
|
|
|
for (const antenna of myAntennas) {
|
2022-03-26 07:34:00 +01:00
|
|
|
const count = await AntennaNotes.countBy({
|
2021-03-21 07:35:02 +01:00
|
|
|
antennaId: antenna.id,
|
2021-12-09 15:58:30 +01:00
|
|
|
read: false,
|
2021-03-21 07:35:02 +01:00
|
|
|
});
|
|
|
|
|
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-21 07:35:02 +01:00
|
|
|
}
|
2021-03-23 07:06:56 +01:00
|
|
|
}
|
2021-03-21 07:35:02 +01:00
|
|
|
|
2023-01-13 05:40:33 +01:00
|
|
|
Users.getHasUnreadAntenna(userId).then((unread) => {
|
2021-03-21 07:35:02 +01:00
|
|
|
if (!unread) {
|
2023-01-13 05:40:33 +01:00
|
|
|
publishMainStream(userId, "readAllAntennas");
|
2021-03-21 07:35:02 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|