From f7a8a58cb2fe1abf198b1acacfabf7f0ddcfdadf Mon Sep 17 00:00:00 2001 From: naskya Date: Mon, 18 Mar 2024 03:29:19 +0900 Subject: [PATCH] Revert "refactor: remove note.mentionedRemoteUsers column" This reverts commit 65797a934ac02bd7ad31ec6060f070196d19e2c4. --- ...688552234-remove-mentioned-users-column.ts | 20 ------------ packages/backend/src/models/entities/note.ts | 13 ++++++++ .../src/remote/activitypub/renderer/note.ts | 31 +++++++++---------- .../backend/src/services/messages/create.ts | 7 +++++ packages/backend/src/services/note/create.ts | 16 ++++++++++ packages/backend/src/services/note/delete.ts | 15 +++++---- 6 files changed, 58 insertions(+), 44 deletions(-) delete mode 100644 packages/backend/src/migration/1710688552234-remove-mentioned-users-column.ts diff --git a/packages/backend/src/migration/1710688552234-remove-mentioned-users-column.ts b/packages/backend/src/migration/1710688552234-remove-mentioned-users-column.ts deleted file mode 100644 index f2730f3cde..0000000000 --- a/packages/backend/src/migration/1710688552234-remove-mentioned-users-column.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { MigrationInterface, QueryRunner } from "typeorm"; - -export class RemoveMentionedUsersColumn1710688552234 - implements MigrationInterface -{ - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query( - `ALTER TABLE "note" DROP COLUMN "mentionedRemoteUsers"`, - ); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query( - `ALTER TABLE "note" ADD "mentionedRemoteUsers" TEXT NOT NULL DEFAULT '[]'::text`, - ); - await queryRunner.query( - `UPDATE "note" SET "mentionedRemoteUsers" = (SELECT COALESCE(json_agg(row_to_json("data"))::text, '[]') FROM (SELECT "url", "uri", "username", "host" FROM "user" JOIN "user_profile" ON "user"."id" = "user_profile". "userId" WHERE "user"."host" IS NOT NULL AND "user"."id" = ANY("note"."mentions")) AS "data")`, - ); - } -} diff --git a/packages/backend/src/models/entities/note.ts b/packages/backend/src/models/entities/note.ts index e6fd892af3..a31dd7dd46 100644 --- a/packages/backend/src/models/entities/note.ts +++ b/packages/backend/src/models/entities/note.ts @@ -172,6 +172,12 @@ export class Note { }) public mentions: User["id"][]; + // FIXME: WHAT IS THIS + @Column("text", { + default: "[]", + }) + public mentionedRemoteUsers: string; + @Column("varchar", { length: 128, array: true, @@ -301,3 +307,10 @@ export class Note { } } } + +export type IMentionedRemoteUsers = { + uri: string; + url?: string; + username: string; + host: string; +}[]; diff --git a/packages/backend/src/remote/activitypub/renderer/note.ts b/packages/backend/src/remote/activitypub/renderer/note.ts index bfa424242a..f3bce41aa7 100644 --- a/packages/backend/src/remote/activitypub/renderer/note.ts +++ b/packages/backend/src/remote/activitypub/renderer/note.ts @@ -1,6 +1,6 @@ import { In, IsNull } from "typeorm"; import config from "@/config/index.js"; -import type { Note } from "@/models/entities/note.js"; +import type { Note, IMentionedRemoteUsers } from "@/models/entities/note.js"; import type { DriveFile } from "@/models/entities/drive-file.js"; import { DriveFiles, Notes, Users, Emojis, Polls } from "@/models/index.js"; import type { Emoji } from "@/models/entities/emoji.js"; @@ -61,34 +61,33 @@ export default async function renderNote( const attributedTo = `${config.url}/users/${note.userId}`; - const mentionedUsers = - note.mentions.length > 0 - ? await Users.findBy({ - id: In(note.mentions), - }) - : []; - - const mentionUris = mentionedUsers - // only remote users - .filter((user) => Users.isRemoteUser(user)) - .map((user) => user.uri); + const mentions = ( + JSON.parse(note.mentionedRemoteUsers) as IMentionedRemoteUsers + ).map((x) => x.uri); let to: string[] = []; let cc: string[] = []; if (note.visibility === "public") { to = ["https://www.w3.org/ns/activitystreams#Public"]; - cc = [`${attributedTo}/followers`].concat(mentionUris); + cc = [`${attributedTo}/followers`].concat(mentions); } else if (note.visibility === "home") { to = [`${attributedTo}/followers`]; - cc = ["https://www.w3.org/ns/activitystreams#Public"].concat(mentionUris); + cc = ["https://www.w3.org/ns/activitystreams#Public"].concat(mentions); } else if (note.visibility === "followers") { to = [`${attributedTo}/followers`]; - cc = mentionUris; + cc = mentions; } else { - to = mentionUris; + to = mentions; } + const mentionedUsers = + note.mentions.length > 0 + ? await Users.findBy({ + id: In(note.mentions), + }) + : []; + const hashtagTags = (note.tags || []).map((tag) => renderHashtag(tag)); const mentionTags = mentionedUsers.map((u) => renderMention(u)); diff --git a/packages/backend/src/services/messages/create.ts b/packages/backend/src/services/messages/create.ts index 81d1614cb0..0b3f8eded9 100644 --- a/packages/backend/src/services/messages/create.ts +++ b/packages/backend/src/services/messages/create.ts @@ -134,6 +134,13 @@ export async function createMessage( userId: message.userId, visibility: "specified", mentions: [recipientUser].map((u) => u.id), + mentionedRemoteUsers: JSON.stringify( + [recipientUser].map((u) => ({ + uri: u.uri, + username: u.username, + host: u.host, + })), + ), } as Note; let renderedNote: Record = await renderNote( diff --git a/packages/backend/src/services/note/create.ts b/packages/backend/src/services/note/create.ts index 16b2c1deed..fc9913e985 100644 --- a/packages/backend/src/services/note/create.ts +++ b/packages/backend/src/services/note/create.ts @@ -18,6 +18,7 @@ import { registerOrFetchInstanceDoc } from "@/services/register-or-fetch-instanc import { extractMentions } from "@/misc/extract-mentions.js"; import { extractCustomEmojisFromMfm } from "@/misc/extract-custom-emojis-from-mfm.js"; import { extractHashtags } from "@/misc/extract-hashtags.js"; +import type { IMentionedRemoteUsers } from "@/models/entities/note.js"; import { Note } from "@/models/entities/note.js"; import { Mutings, @@ -750,6 +751,21 @@ async function insertNote( // Append mentions data if (mentionedUsers.length > 0) { insert.mentions = mentionedUsers.map((u) => u.id); + const profiles = await UserProfiles.findBy({ userId: In(insert.mentions) }); + insert.mentionedRemoteUsers = JSON.stringify( + mentionedUsers + .filter((u) => Users.isRemoteUser(u)) + .map((u) => { + const profile = profiles.find((p) => p.userId === u.id); + const url = profile != null ? profile.url : null; + return { + uri: u.uri, + url: url == null ? undefined : url, + username: u.username, + host: u.host, + } as IMentionedRemoteUsers[0]; + }), + ); } // 投稿を作成 diff --git a/packages/backend/src/services/note/delete.ts b/packages/backend/src/services/note/delete.ts index 8a42ddf2ae..988e1c8c48 100644 --- a/packages/backend/src/services/note/delete.ts +++ b/packages/backend/src/services/note/delete.ts @@ -1,4 +1,4 @@ -import { Brackets, In, IsNull, Not } from "typeorm"; +import { Brackets, In } from "typeorm"; import { publishNoteStream } from "@/services/stream.js"; import renderDelete from "@/remote/activitypub/renderer/delete.js"; import renderAnnounce from "@/remote/activitypub/renderer/announce.js"; @@ -7,7 +7,7 @@ import { renderActivity } from "@/remote/activitypub/renderer/index.js"; import renderTombstone from "@/remote/activitypub/renderer/tombstone.js"; import config from "@/config/index.js"; import type { User, ILocalUser, IRemoteUser } from "@/models/entities/user.js"; -import type { Note } from "@/models/entities/note.js"; +import type { Note, IMentionedRemoteUsers } from "@/models/entities/note.js"; import { Notes, Users, Instances } from "@/models/index.js"; import { deliverToFollowers, @@ -147,12 +147,11 @@ async function getMentionedRemoteUsers(note: Note) { const where = [] as any[]; // mention / reply / dm - if (note.mentions.length > 0) { - where.push({ - id: In(note.mentions), - // only remote users, local users are on the server and do not need to be notified - host: Not(IsNull()), - }); + const uris = ( + JSON.parse(note.mentionedRemoteUsers) as IMentionedRemoteUsers + ).map((x) => x.uri); + if (uris.length > 0) { + where.push({ uri: In(uris) }); } // renote / quote