From 65797a934ac02bd7ad31ec6060f070196d19e2c4 Mon Sep 17 00:00:00 2001 From: Johann150 Date: Wed, 24 Aug 2022 23:57:34 +0200 Subject: [PATCH] refactor: remove note.mentionedRemoteUsers column The column mentionedRemoteUsers on the note table in the database is firstly in the wrong type since it contains JSON data but is typed as text. Secondly it seems redundant, since that data can be acquired by using the note.mentions column to fetch the respective data instead. Co-authored-by: Francis Dinh --- ...688552234-remove-mentioned-users-column.ts | 20 +++++++++ packages/backend/src/models/entities/note.ts | 13 ------ .../src/remote/activitypub/renderer/note.ts | 43 ++++++++++--------- .../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, 50 insertions(+), 64 deletions(-) create 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 new file mode 100644 index 0000000000..f2730f3cde --- /dev/null +++ b/packages/backend/src/migration/1710688552234-remove-mentioned-users-column.ts @@ -0,0 +1,20 @@ +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 a31dd7dd46..e6fd892af3 100644 --- a/packages/backend/src/models/entities/note.ts +++ b/packages/backend/src/models/entities/note.ts @@ -172,12 +172,6 @@ export class Note { }) public mentions: User["id"][]; - // FIXME: WHAT IS THIS - @Column("text", { - default: "[]", - }) - public mentionedRemoteUsers: string; - @Column("varchar", { length: 128, array: true, @@ -307,10 +301,3 @@ 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 f3bce41aa7..bfa424242a 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, IMentionedRemoteUsers } from "@/models/entities/note.js"; +import type { Note } 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,26 +61,6 @@ export default async function renderNote( const attributedTo = `${config.url}/users/${note.userId}`; - 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(mentions); - } else if (note.visibility === "home") { - to = [`${attributedTo}/followers`]; - cc = ["https://www.w3.org/ns/activitystreams#Public"].concat(mentions); - } else if (note.visibility === "followers") { - to = [`${attributedTo}/followers`]; - cc = mentions; - } else { - to = mentions; - } - const mentionedUsers = note.mentions.length > 0 ? await Users.findBy({ @@ -88,6 +68,27 @@ export default async function renderNote( }) : []; + const mentionUris = mentionedUsers + // only remote users + .filter((user) => Users.isRemoteUser(user)) + .map((user) => user.uri); + + let to: string[] = []; + let cc: string[] = []; + + if (note.visibility === "public") { + to = ["https://www.w3.org/ns/activitystreams#Public"]; + cc = [`${attributedTo}/followers`].concat(mentionUris); + } else if (note.visibility === "home") { + to = [`${attributedTo}/followers`]; + cc = ["https://www.w3.org/ns/activitystreams#Public"].concat(mentionUris); + } else if (note.visibility === "followers") { + to = [`${attributedTo}/followers`]; + cc = mentionUris; + } else { + to = mentionUris; + } + 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 0b3f8eded9..81d1614cb0 100644 --- a/packages/backend/src/services/messages/create.ts +++ b/packages/backend/src/services/messages/create.ts @@ -134,13 +134,6 @@ 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 fc9913e985..16b2c1deed 100644 --- a/packages/backend/src/services/note/create.ts +++ b/packages/backend/src/services/note/create.ts @@ -18,7 +18,6 @@ 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, @@ -751,21 +750,6 @@ 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 988e1c8c48..8a42ddf2ae 100644 --- a/packages/backend/src/services/note/delete.ts +++ b/packages/backend/src/services/note/delete.ts @@ -1,4 +1,4 @@ -import { Brackets, In } from "typeorm"; +import { Brackets, In, IsNull, Not } 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, IMentionedRemoteUsers } from "@/models/entities/note.js"; +import type { Note } from "@/models/entities/note.js"; import { Notes, Users, Instances } from "@/models/index.js"; import { deliverToFollowers, @@ -147,11 +147,12 @@ async function getMentionedRemoteUsers(note: Note) { const where = [] as any[]; // mention / reply / dm - const uris = ( - JSON.parse(note.mentionedRemoteUsers) as IMentionedRemoteUsers - ).map((x) => x.uri); - if (uris.length > 0) { - where.push({ uri: In(uris) }); + 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()), + }); } // renote / quote