diff --git a/packages/backend/migration/1680491187535-cleanup.js b/packages/backend/migration/1680491187535-cleanup.js new file mode 100644 index 000000000..021a368c0 --- /dev/null +++ b/packages/backend/migration/1680491187535-cleanup.js @@ -0,0 +1,9 @@ +export class cleanup1680491187535 { + name = "cleanup1680491187535"; + + async up(queryRunner) { + await queryRunner.query(`DROP TABLE "antenna_note" `); + } + + async down(queryRunner) {} +} diff --git a/packages/backend/src/models/index.ts b/packages/backend/src/models/index.ts index cfc3b01c5..ca35b7708 100644 --- a/packages/backend/src/models/index.ts +++ b/packages/backend/src/models/index.ts @@ -123,7 +123,6 @@ export const ModerationLogs = ModerationLogRepository; export const Clips = ClipRepository; export const ClipNotes = db.getRepository(ClipNote); export const Antennas = AntennaRepository; -export const AntennaNotes = db.getRepository(AntennaNote); export const PromoNotes = db.getRepository(PromoNote); export const PromoReads = db.getRepository(PromoRead); export const Relays = RelayRepository; diff --git a/packages/backend/src/models/repositories/user.ts b/packages/backend/src/models/repositories/user.ts index 5ca36e3d3..1f9cd80fb 100644 --- a/packages/backend/src/models/repositories/user.ts +++ b/packages/backend/src/models/repositories/user.ts @@ -18,7 +18,6 @@ import { createPerson } from "@/remote/activitypub/models/person.js"; import { AnnouncementReads, Announcements, - AntennaNotes, Blockings, ChannelFollowings, DriveFiles, @@ -258,23 +257,24 @@ export const UserRepository = db.getRepository(User).extend({ }, async getHasUnreadAntenna(userId: User["id"]): Promise { - try { - const myAntennas = (await getAntennas()).filter( - (a) => a.userId === userId, - ); + // try { + // const myAntennas = (await getAntennas()).filter( + // (a) => a.userId === userId, + // ); - const unread = - myAntennas.length > 0 - ? await AntennaNotes.findOneBy({ - antennaId: In(myAntennas.map((x) => x.id)), - read: false, - }) - : null; + // const unread = + // myAntennas.length > 0 + // ? await AntennaNotes.findOneBy({ + // antennaId: In(myAntennas.map((x) => x.id)), + // read: false, + // }) + // : null; - return unread != null; - } catch (e) { - return false; - } + // return unread != null; + // } catch (e) { + // return false; + // } + return false; // TODO }, async getHasUnreadChannel(userId: User["id"]): Promise { diff --git a/packages/backend/src/server/api/endpoints/antennas/markread.ts b/packages/backend/src/server/api/endpoints/antennas/markread.ts index e29e13bbb..fedb48c91 100644 --- a/packages/backend/src/server/api/endpoints/antennas/markread.ts +++ b/packages/backend/src/server/api/endpoints/antennas/markread.ts @@ -1,5 +1,5 @@ import define from "../../define.js"; -import { Antennas, AntennaNotes } from "@/models/index.js"; +import { Antennas } from "@/models/index.js"; import { FindOptionsWhere } from "typeorm"; import { AntennaNote } from "@/models/entities/antenna-note.js"; @@ -29,15 +29,15 @@ export default define(meta, paramDef, async (ps, me) => { return null; } - await AntennaNotes.update( - { - antennaId: antenna.id, - read: false, - }, - { - read: true, - }, - ); + // await AntennaNotes.update( + // { + // antennaId: antenna.id, + // read: false, + // }, + // { + // read: true, + // }, + // ); return true; }); diff --git a/packages/backend/src/server/api/endpoints/antennas/notes.ts b/packages/backend/src/server/api/endpoints/antennas/notes.ts index 29e2e085a..6ca71c08e 100644 --- a/packages/backend/src/server/api/endpoints/antennas/notes.ts +++ b/packages/backend/src/server/api/endpoints/antennas/notes.ts @@ -1,6 +1,8 @@ import define from "../../define.js"; import readNote from "@/services/note/read.js"; -import { Antennas, Notes, AntennaNotes } from "@/models/index.js"; +import { Antennas, Notes } from "@/models/index.js"; +import { redisClient } from "@/db/redis.js"; +import { genId } from "@/misc/gen-id.js"; import { makePaginationQuery } from "../../common/make-pagination-query.js"; import { generateVisibilityQuery } from "../../common/generate-visibility-query.js"; import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js"; @@ -58,6 +60,26 @@ export default define(meta, paramDef, async (ps, user) => { throw new ApiError(meta.errors.noSuchAntenna); } + const noteIdsRes = await redisClient.xrevrange( + `antennaTimeline:${antenna.id}`, + ps.untilDate || "+", + "-", + "COUNT", + ps.limit + 1, + ); // untilIdに指定したものも含まれるため+1 + + if (noteIdsRes.length === 0) { + return []; + } + + const noteIds = noteIdsRes + .map((x) => x[1][1]) + .filter((x) => x !== ps.untilId); + + if (noteIds.length === 0) { + return []; + } + const query = makePaginationQuery( Notes.createQueryBuilder("note"), ps.sinceId, @@ -65,11 +87,7 @@ export default define(meta, paramDef, async (ps, user) => { ps.sinceDate, ps.untilDate, ) - .innerJoin( - AntennaNotes.metadata.targetName, - "antennaNote", - "antennaNote.noteId = note.id", - ) + .where("note.id IN (:...noteIds)", { noteIds: noteIds }) .innerJoinAndSelect("note.user", "user") .leftJoinAndSelect("user.avatar", "avatar") .leftJoinAndSelect("user.banner", "banner") @@ -81,7 +99,6 @@ export default define(meta, paramDef, async (ps, user) => { .leftJoinAndSelect("renote.user", "renoteUser") .leftJoinAndSelect("renoteUser.avatar", "renoteUserAvatar") .leftJoinAndSelect("renoteUser.banner", "renoteUserBanner") - .andWhere("antennaNote.antennaId = :antennaId", { antennaId: antenna.id }) .andWhere("note.visibility != 'home'"); generateVisibilityQuery(query, user); diff --git a/packages/backend/src/services/add-note-to-antenna.ts b/packages/backend/src/services/add-note-to-antenna.ts index 38979acb4..131c0348c 100644 --- a/packages/backend/src/services/add-note-to-antenna.ts +++ b/packages/backend/src/services/add-note-to-antenna.ts @@ -1,9 +1,8 @@ import type { Antenna } from "@/models/entities/antenna.js"; import type { Note } from "@/models/entities/note.js"; -import { AntennaNotes, Mutings, Notes } from "@/models/index.js"; import { genId } from "@/misc/gen-id.js"; -import { isUserRelated } from "@/misc/is-user-related.js"; -import { publishAntennaStream, publishMainStream } from "@/services/stream.js"; +import { redisClient } from "@/db/redis.js"; +import { publishAntennaStream } from "@/services/stream.js"; import type { User } from "@/models/entities/user.js"; export async function addNoteToAntenna( @@ -14,48 +13,15 @@ export async function addNoteToAntenna( // 通知しない設定になっているか、自分自身の投稿なら既読にする const read = !antenna.notify || antenna.userId === noteUser.id; - AntennaNotes.insert({ - id: genId(), - antennaId: antenna.id, - noteId: note.id, - read: read, - }); + redisClient.xadd( + `antennaTimeline:${antenna.id}`, + "MAXLEN", + "~", + "200", + `${genId(note.createdAt)}-*`, + "note", + note.id, + ); publishAntennaStream(antenna.id, "note", note); - - if (!read) { - const mutings = await Mutings.find({ - where: { - muterId: antenna.userId, - }, - select: ["muteeId"], - }); - - // Copy - const _note: Note = { - ...note, - }; - - if (note.replyId != null) { - _note.reply = await Notes.findOneByOrFail({ id: note.replyId }); - } - if (note.renoteId != null) { - _note.renote = await Notes.findOneByOrFail({ id: note.renoteId }); - } - - if (isUserRelated(_note, new Set(mutings.map((x) => x.muteeId)))) { - return; - } - - // 2秒経っても既読にならなかったら通知 - setTimeout(async () => { - const unread = await AntennaNotes.findOneBy({ - antennaId: antenna.id, - read: false, - }); - if (unread) { - publishMainStream(antenna.userId, "unreadAntenna", antenna); - } - }, 2000); - } } diff --git a/packages/backend/src/services/note/read.ts b/packages/backend/src/services/note/read.ts index 53188f15f..2dcf49235 100644 --- a/packages/backend/src/services/note/read.ts +++ b/packages/backend/src/services/note/read.ts @@ -3,7 +3,6 @@ import type { Note } from "@/models/entities/note.js"; import type { User } from "@/models/entities/user.js"; import { NoteUnreads, - AntennaNotes, Users, Followings, ChannelFollowings, @@ -55,7 +54,7 @@ export default async function ( const readMentions: (Note | Packed<"Note">)[] = []; const readSpecifiedNotes: (Note | Packed<"Note">)[] = []; const readChannelNotes: (Note | Packed<"Note">)[] = []; - const readAntennaNotes: (Note | Packed<"Note">)[] = []; + // const readAntennaNotes: (Note | Packed<"Note">)[] = []; for (const note of notes) { if (note.mentions?.includes(userId)) { @@ -68,22 +67,22 @@ export default async function ( readChannelNotes.push(note); } - if (note.user != null) { - // たぶんnullになることは無いはずだけど一応 - for (const antenna of myAntennas) { - if ( - await checkHitAntenna( - antenna, - note, - note.user, - undefined, - Array.from(following), - ) - ) { - readAntennaNotes.push(note); - } - } - } + // if (note.user != null) { + // // たぶんnullになることは無いはずだけど一応 + // for (const antenna of myAntennas) { + // if ( + // await checkHitAntenna( + // antenna, + // note, + // note.user, + // undefined, + // Array.from(following), + // ) + // ) { + // readAntennaNotes.push(note); + // } + // } + // } } if ( @@ -141,33 +140,33 @@ export default async function ( }); } - if (readAntennaNotes.length > 0) { - await AntennaNotes.update( - { - antennaId: In(myAntennas.map((a) => a.id)), - noteId: In(readAntennaNotes.map((n) => n.id)), - }, - { - read: true, - }, - ); + // if (readAntennaNotes.length > 0) { + // await AntennaNotes.update( + // { + // antennaId: In(myAntennas.map((a) => a.id)), + // noteId: In(readAntennaNotes.map((n) => n.id)), + // }, + // { + // read: true, + // }, + // ); - // TODO: まとめてクエリしたい - for (const antenna of myAntennas) { - const count = await AntennaNotes.countBy({ - antennaId: antenna.id, - read: false, - }); + // // TODO: まとめてクエリしたい + // for (const antenna of myAntennas) { + // const count = await AntennaNotes.countBy({ + // antennaId: antenna.id, + // read: false, + // }); - if (count === 0) { - publishMainStream(userId, "readAntenna", antenna); - } - } + // if (count === 0) { + // publishMainStream(userId, "readAntenna", antenna); + // } + // } - Users.getHasUnreadAntenna(userId).then((unread) => { - if (!unread) { - publishMainStream(userId, "readAllAntennas"); - } - }); - } + // Users.getHasUnreadAntenna(userId).then((unread) => { + // if (!unread) { + // publishMainStream(userId, "readAllAntennas"); + // } + // }); + // } }