From de4da3c1fd491376e4b59585e28d339e26722989 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=81=E5=91=A8=E9=83=A8=E8=90=BD?= Date: Tue, 19 Mar 2024 22:37:46 +0800 Subject: [PATCH 01/99] docs: add minimum dependencies --- dev/docs/local-installation.md | 2 ++ docs/install.md | 30 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/dev/docs/local-installation.md b/dev/docs/local-installation.md index a13aa6437f..132d86bd56 100644 --- a/dev/docs/local-installation.md +++ b/dev/docs/local-installation.md @@ -42,6 +42,8 @@ cargo --version ### PostgreSQL and PGroonga +Firefish requires PostgreSQL v12 or later. While you can choose any versions between v12 and the latest version (v16.2 as of writing), we recommend that you install v12.x so as not to use new features inadvertently and introduce incompatibility issues. + PostgreSQL install instructions can be found at [this page](https://www.postgresql.org/download/). ```sh diff --git a/docs/install.md b/docs/install.md index 061000fa32..f030e87125 100644 --- a/docs/install.md +++ b/docs/install.md @@ -4,6 +4,8 @@ This document shows an example procedure for installing Firefish on Debian 12. N If you want to use the pre-built container image, please refer to [`install-container.md`](./install-container.md). +If you do not prepare your environment as document, be sure to meet the minimum dependencies given at the bottom of the page. + Make sure that you can use the `sudo` command before proceeding. ## 1. Install dependencies @@ -315,3 +317,31 @@ cd ~/firefish - Run `psql -d firefish` (or whatever the database name is) - Run `UPDATE "user" SET "isAdmin" = true WHERE id='999999';` (replace `999999` with the copied ID) - Restart your Firefish server + +## Dependencies + +**We only recommend that you use components that are still within the upstream support cycle for better performance and security, and it is recommended that new sites meet the recommended dependency version requirements.** + +- At least [NodeJS](https://nodejs.org/en/) v18.17.0 (v20/v21 recommended) +- At least [PostgreSQL](https://www.postgresql.org/) v12 (v16 recommended) with [PGroonga](https://pgroonga.github.io/) extension +- At least [Redis](https://redis.io/) v7 +- Web Proxy (one of the following) + - Caddy (recommended for new users) + - Nginx (recommended) + - Apache + +### Optional dependencies + +- [FFmpeg](https://ffmpeg.org/) for video transcoding +- Caching server (one of the following) + - [DragonflyDB](https://www.dragonflydb.io/) (recommended) + - [KeyDB](https://keydb.dev/) + - Another [Redis](https://redis.io/) server + +### Build dependencies + +- At least [Rust](https://www.rust-lang.org/) v1.74 +- C/C++ compiler & build tools + - `build-essential` on Debian/Ubuntu Linux + - `base-devel` on Arch Linux +- [Python 3](https://www.python.org/) From db0bd21edcc4681dac033b7ec4184cb555940607 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=81=E5=91=A8=E9=83=A8=E8=90=BD?= Date: Mon, 11 Mar 2024 08:33:47 +0800 Subject: [PATCH 02/99] feat(client): attachment without description opened when choose add alt --- packages/client/src/components/MkPostForm.vue | 81 ++++++++++++++++++- 1 file changed, 79 insertions(+), 2 deletions(-) diff --git a/packages/client/src/components/MkPostForm.vue b/packages/client/src/components/MkPostForm.vue index 3890908026..ad8c4c5ba3 100644 --- a/packages/client/src/components/MkPostForm.vue +++ b/packages/client/src/components/MkPostForm.vue @@ -500,6 +500,8 @@ const withHashtags = computed( ); const hashtags = computed(defaultStore.makeGetterSetter("postFormHashtags")); +let firstTryPost = true; + watch(text, () => { checkMissingMention(); }); @@ -1048,16 +1050,91 @@ async function post() { defaultStore.state.showNoAltTextWarning && files.value.some((f) => f.comment == null || f.comment.length === 0) ) { + if (firstTryPost) { + for (const file of files.value) { + if (file.comment == null || file.comment.length === 0) { + os.popup( + defineAsyncComponent( + () => import("@/components/MkMediaCaption.vue"), + ), + { + title: i18n.ts.describeFile, + input: { + placeholder: i18n.ts.inputNewDescription, + default: + file.comment !== null ? file.comment : "", + }, + image: file, + }, + { + done: (result) => { + if (!result || result.canceled) return; + const comment = + result.result.length === 0 + ? null + : result.result; + os.api("drive/files/update", { + fileId: file.id, + comment, + }).then(() => { + file.comment = comment; + }); + }, + }, + "closed", + ); + } + } + firstTryPost = false; + return; + } + // "canceled" means "post anyway" const { canceled } = await os.confirm({ type: "warning", text: i18n.ts.noAltTextWarning, - okText: i18n.ts.goBack, + okText: i18n.ts.describeFile, cancelText: i18n.ts.toPost, isPlaintext: true, }); - if (!canceled) return; + if (!canceled) { + for (const file of files.value) { + if (file.comment == null || file.comment.length === 0) { + os.popup( + defineAsyncComponent( + () => import("@/components/MkMediaCaption.vue"), + ), + { + title: i18n.ts.describeFile, + input: { + placeholder: i18n.ts.inputNewDescription, + default: + file.comment !== null ? file.comment : "", + }, + image: file, + }, + { + done: (result) => { + if (!result || result.canceled) return; + const comment = + result.result.length === 0 + ? null + : result.result; + os.api("drive/files/update", { + fileId: file.id, + comment, + }).then(() => { + file.comment = comment; + }); + }, + }, + "closed", + ); + } + } + return; + } } const processedText = preprocess(text.value); From 2267e90d3bfb9ac51ed6dcdaee051c39c594bd19 Mon Sep 17 00:00:00 2001 From: naskya Date: Mon, 25 Mar 2024 03:12:59 +0900 Subject: [PATCH 03/99] refactor (client): await asynchronous processes, remove duplicate code --- packages/client/src/components/MkPostForm.vue | 99 +++++++------------ 1 file changed, 35 insertions(+), 64 deletions(-) diff --git a/packages/client/src/components/MkPostForm.vue b/packages/client/src/components/MkPostForm.vue index ad8c4c5ba3..6478838f4e 100644 --- a/packages/client/src/components/MkPostForm.vue +++ b/packages/client/src/components/MkPostForm.vue @@ -309,6 +309,8 @@ import XNoteSimple from "@/components/MkNoteSimple.vue"; import XNotePreview from "@/components/MkNotePreview.vue"; import XPostFormAttaches from "@/components/MkPostFormAttaches.vue"; import XPollEditor from "@/components/MkPollEditor.vue"; +import XCheatSheet from "@/components/MkCheatSheetDialog.vue"; +import XMediaCaption from "@/components/MkMediaCaption.vue"; import { host, url } from "@/config"; import { erase, unique } from "@/scripts/array"; import { extractMentions } from "@/scripts/extract-mentions"; @@ -325,7 +327,6 @@ import { getAccounts, openAccountMenu as openAccountMenu_ } from "@/account"; import { me } from "@/me"; import { uploadFile } from "@/scripts/upload"; import { deepClone } from "@/scripts/clone"; -import XCheatSheet from "@/components/MkCheatSheetDialog.vue"; import preprocess from "@/scripts/preprocess"; import { vibrate } from "@/scripts/vibrate"; import { langmap } from "@/scripts/langmap"; @@ -500,7 +501,7 @@ const withHashtags = computed( ); const hashtags = computed(defaultStore.makeGetterSetter("postFormHashtags")); -let firstTryPost = true; +let isFirstPostAttempt = true; watch(text, () => { checkMissingMention(); @@ -1012,6 +1013,34 @@ function deleteDraft() { localStorage.setItem("drafts", JSON.stringify(draftData)); } +async function openFileDescriptionWindow(file: DriveFile) { + await os.popup( + XMediaCaption, + { + title: i18n.ts.describeFile, + input: { + placeholder: i18n.ts.inputNewDescription, + default: file.comment !== null ? file.comment : "", + }, + image: file, + }, + { + done: (result) => { + if (!result || result.canceled) return; + const comment = + result.result.length === 0 ? null : result.result; + os.api("drive/files/update", { + fileId: file.id, + comment, + }).then(() => { + file.comment = comment; + }); + }, + }, + "closed", + ); +} + async function post() { // For text that is too short, the false positive rate may be too high, so we don't show alarm. if (defaultStore.state.autocorrectNoteLanguage && text.value.length > 10) { @@ -1050,42 +1079,13 @@ async function post() { defaultStore.state.showNoAltTextWarning && files.value.some((f) => f.comment == null || f.comment.length === 0) ) { - if (firstTryPost) { + if (isFirstPostAttempt) { for (const file of files.value) { if (file.comment == null || file.comment.length === 0) { - os.popup( - defineAsyncComponent( - () => import("@/components/MkMediaCaption.vue"), - ), - { - title: i18n.ts.describeFile, - input: { - placeholder: i18n.ts.inputNewDescription, - default: - file.comment !== null ? file.comment : "", - }, - image: file, - }, - { - done: (result) => { - if (!result || result.canceled) return; - const comment = - result.result.length === 0 - ? null - : result.result; - os.api("drive/files/update", { - fileId: file.id, - comment, - }).then(() => { - file.comment = comment; - }); - }, - }, - "closed", - ); + await openFileDescriptionWindow(file); } } - firstTryPost = false; + isFirstPostAttempt = false; return; } @@ -1101,36 +1101,7 @@ async function post() { if (!canceled) { for (const file of files.value) { if (file.comment == null || file.comment.length === 0) { - os.popup( - defineAsyncComponent( - () => import("@/components/MkMediaCaption.vue"), - ), - { - title: i18n.ts.describeFile, - input: { - placeholder: i18n.ts.inputNewDescription, - default: - file.comment !== null ? file.comment : "", - }, - image: file, - }, - { - done: (result) => { - if (!result || result.canceled) return; - const comment = - result.result.length === 0 - ? null - : result.result; - os.api("drive/files/update", { - fileId: file.id, - comment, - }).then(() => { - file.comment = comment; - }); - }, - }, - "closed", - ); + await openFileDescriptionWindow(file); } } return; From f346d2e2f6b4674c9af03e761bf991b1c98f7d17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=81=E5=91=A8=E9=83=A8=E8=90=BD?= Date: Mon, 25 Mar 2024 22:52:37 +0800 Subject: [PATCH 04/99] feat: add showAddFileDescriptionAtFirstPost and allow cancel adding alt-text midway --- locales/en-US.yml | 2 + locales/zh-CN.yml | 1 + packages/client/src/components/MkPostForm.vue | 86 ++++++++++++------- .../client/src/pages/settings/general.vue | 6 ++ .../pages/settings/preferences-backups.vue | 1 + packages/client/src/store.ts | 4 + 6 files changed, 71 insertions(+), 29 deletions(-) diff --git a/locales/en-US.yml b/locales/en-US.yml index d736a7d881..116b8eabd0 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -1226,6 +1226,8 @@ publishTimelinesDescription: "If enabled, the Local and Global timelines will be on {url} even when signed out." noAltTextWarning: "Some attached file(s) have no description. Did you forget to write?" showNoAltTextWarning: "Show a warning if you attempt to post files without a description" +showAddFileDescriptionAtFirstPost: "Show add description page automatically when + first try to post a post attachment without a description" _emojiModPerm: unauthorized: "None" diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index f67bf4a600..8f5d009acc 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -2058,5 +2058,6 @@ searchRangeDescription: "如果您要过滤时间段,请按以下格式输入 messagingUnencryptedInfo: "Firefish 上的聊天没有经过端到端加密,请不要在聊天中分享您的敏感信息。" noAltTextWarning: 有些附件没有描述。您是否忘记写描述了? showNoAltTextWarning: 当您尝试发布没有描述的帖子附件时显示警告 +showAddFileDescriptionAtFirstPost: 当您首次尝试发布没有描述的帖子附件时自动弹出添加描述页面 autocorrectNoteLanguage: 当帖子语言不符合自动检测的结果的时候显示警告 incorrectLanguageWarning: "看上去您帖子使用的语言是{detected},但您选择的语言是{current}。\n要改为以{detected}发帖吗?" diff --git a/packages/client/src/components/MkPostForm.vue b/packages/client/src/components/MkPostForm.vue index 6478838f4e..fee812317e 100644 --- a/packages/client/src/components/MkPostForm.vue +++ b/packages/client/src/components/MkPostForm.vue @@ -1013,32 +1013,43 @@ function deleteDraft() { localStorage.setItem("drafts", JSON.stringify(draftData)); } -async function openFileDescriptionWindow(file: DriveFile) { - await os.popup( - XMediaCaption, - { - title: i18n.ts.describeFile, - input: { - placeholder: i18n.ts.inputNewDescription, - default: file.comment !== null ? file.comment : "", +/** + * @returns whether the file is described + */ + function openFileDescriptionWindow(file: entities.DriveFile) { + return new Promise((resolve, reject) => { + os.popup( + XMediaCaption, + { + title: i18n.ts.describeFile, + input: { + placeholder: i18n.ts.inputNewDescription, + default: file.comment !== null ? file.comment : "", + }, + image: file, }, - image: file, - }, - { - done: (result) => { - if (!result || result.canceled) return; - const comment = - result.result.length === 0 ? null : result.result; - os.api("drive/files/update", { - fileId: file.id, - comment, - }).then(() => { - file.comment = comment; - }); + { + done: (result) => { + if (!result || result.canceled) { + resolve(false); + return; + } + const comment = + result.result.length === 0 ? null : result.result; + os.api("drive/files/update", { + fileId: file.id, + comment, + }).then(() => { + resolve(true); + file.comment = comment; + }).catch((err: unknown) => { + reject(err); + }); + }, }, - }, - "closed", - ); + "closed", + ); + }) } async function post() { @@ -1076,19 +1087,30 @@ async function post() { } if ( - defaultStore.state.showNoAltTextWarning && + defaultStore.state.showAddFileDescriptionAtFirstPost && files.value.some((f) => f.comment == null || f.comment.length === 0) ) { if (isFirstPostAttempt) { for (const file of files.value) { if (file.comment == null || file.comment.length === 0) { - await openFileDescriptionWindow(file); + const described = await openFileDescriptionWindow(file); + if (!described) { + return; + } } } isFirstPostAttempt = false; - return; + // Continue if all files have alt-text added. + if (files.value.some((f) => f.comment == null || f.comment.length === 0)) { + return; + } } + } + if ( + defaultStore.state.showNoAltTextWarning && + files.value.some((f) => f.comment == null || f.comment.length === 0) + ) { // "canceled" means "post anyway" const { canceled } = await os.confirm({ type: "warning", @@ -1101,10 +1123,16 @@ async function post() { if (!canceled) { for (const file of files.value) { if (file.comment == null || file.comment.length === 0) { - await openFileDescriptionWindow(file); + const described = await openFileDescriptionWindow(file); + if (!described) { + return; + } } } - return; + // Continue if all files have alt-text added. + if (files.value.some((f) => f.comment == null || f.comment.length === 0)) { + return; + } } } diff --git a/packages/client/src/pages/settings/general.vue b/packages/client/src/pages/settings/general.vue index 15e1172169..bc21efc132 100644 --- a/packages/client/src/pages/settings/general.vue +++ b/packages/client/src/pages/settings/general.vue @@ -124,6 +124,9 @@ {{ i18n.ts.showNoAltTextWarning }} + {{ + i18n.ts.showAddFileDescriptionAtFirstPost + }} {{ i18n.ts.autocorrectNoteLanguage }} @@ -533,6 +536,9 @@ const pullToRefreshThreshold = computed( const showNoAltTextWarning = computed( defaultStore.makeGetterSetter("showNoAltTextWarning"), ); +const showAddFileDescriptionAtFirstPost = computed( + defaultStore.makeGetterSetter("showAddFileDescriptionAtFirstPost"), +); const autocorrectNoteLanguage = computed( defaultStore.makeGetterSetter("autocorrectNoteLanguage"), ); diff --git a/packages/client/src/pages/settings/preferences-backups.vue b/packages/client/src/pages/settings/preferences-backups.vue index 202de0a082..885fec70c1 100644 --- a/packages/client/src/pages/settings/preferences-backups.vue +++ b/packages/client/src/pages/settings/preferences-backups.vue @@ -125,6 +125,7 @@ const defaultStoreSaveKeys: (keyof (typeof defaultStore)["state"])[] = [ "enablePullToRefresh", "pullToRefreshThreshold", "showNoAltTextWarning", + "showAddFileDescriptionAtFirstPost", "autocorrectNoteLanguage", ]; const coldDeviceStorageSaveKeys: (keyof typeof ColdDeviceStorage.default)[] = [ diff --git a/packages/client/src/store.ts b/packages/client/src/store.ts index cf17917477..11abb2e30f 100644 --- a/packages/client/src/store.ts +++ b/packages/client/src/store.ts @@ -432,6 +432,10 @@ export const defaultStore = markRaw( where: "account", default: true, }, + showAddFileDescriptionAtFirstPost: { + where: "account", + default: false, + }, autocorrectNoteLanguage: { where: "account", default: true, From 46bf02cdd591df1bed64677ccb15e358aa6b921d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=81=E5=91=A8=E9=83=A8=E8=90=BD?= Date: Sun, 31 Mar 2024 06:44:00 +0800 Subject: [PATCH 05/99] chore: format --- packages/client/src/components/MkPostForm.vue | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/packages/client/src/components/MkPostForm.vue b/packages/client/src/components/MkPostForm.vue index fee812317e..ffeb1a1cc5 100644 --- a/packages/client/src/components/MkPostForm.vue +++ b/packages/client/src/components/MkPostForm.vue @@ -1016,7 +1016,7 @@ function deleteDraft() { /** * @returns whether the file is described */ - function openFileDescriptionWindow(file: entities.DriveFile) { +function openFileDescriptionWindow(file: entities.DriveFile) { return new Promise((resolve, reject) => { os.popup( XMediaCaption, @@ -1034,22 +1034,23 @@ function deleteDraft() { resolve(false); return; } - const comment = - result.result.length === 0 ? null : result.result; - os.api("drive/files/update", { + const comment = result.result.length === 0 ? null : result.result; + os.api("drive/files/update", { fileId: file.id, comment, - }).then(() => { - resolve(true); - file.comment = comment; - }).catch((err: unknown) => { - reject(err); - }); + }) + .then(() => { + resolve(true); + file.comment = comment; + }) + .catch((err: unknown) => { + reject(err); + }); }, }, "closed", ); - }) + }); } async function post() { @@ -1101,7 +1102,9 @@ async function post() { } isFirstPostAttempt = false; // Continue if all files have alt-text added. - if (files.value.some((f) => f.comment == null || f.comment.length === 0)) { + if ( + files.value.some((f) => f.comment == null || f.comment.length === 0) + ) { return; } } @@ -1130,7 +1133,9 @@ async function post() { } } // Continue if all files have alt-text added. - if (files.value.some((f) => f.comment == null || f.comment.length === 0)) { + if ( + files.value.some((f) => f.comment == null || f.comment.length === 0) + ) { return; } } From f44a2937d4a7ab3c8b15f00b74623a158909e35b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=81=E5=91=A8=E9=83=A8=E8=90=BD?= Date: Sat, 13 Apr 2024 07:41:11 +0800 Subject: [PATCH 06/99] fix: download-url should use proxy bypass hosts --- packages/backend/src/misc/download-url.ts | 7 ++----- packages/backend/src/misc/fetch.ts | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/packages/backend/src/misc/download-url.ts b/packages/backend/src/misc/download-url.ts index ab04e8aa9c..663d354ead 100644 --- a/packages/backend/src/misc/download-url.ts +++ b/packages/backend/src/misc/download-url.ts @@ -2,7 +2,7 @@ import * as fs from "node:fs"; import * as stream from "node:stream"; import * as util from "node:util"; import got, * as Got from "got"; -import { httpAgent, httpsAgent, StatusError } from "./fetch.js"; +import { getAgentByHostname, StatusError } from "./fetch.js"; import config from "@/config/index.js"; import chalk from "chalk"; import Logger from "@/services/logger.js"; @@ -40,10 +40,7 @@ export async function downloadUrl(url: string, path: string): Promise { send: timeout, request: operationTimeout, // whole operation timeout }, - agent: { - http: httpAgent, - https: httpsAgent, - }, + agent: getAgentByHostname(new URL(url).hostname), http2: false, // default retry: { limit: 0, diff --git a/packages/backend/src/misc/fetch.ts b/packages/backend/src/misc/fetch.ts index 4b8fc048e2..2cfd6b95f7 100644 --- a/packages/backend/src/misc/fetch.ts +++ b/packages/backend/src/misc/fetch.ts @@ -171,6 +171,25 @@ export function getAgentByUrl(url: URL, bypassProxy = false) { } } +/** + * Get agent by Hostname + * @param hostname Hostname + * @param bypassProxy Allways bypass proxy + */ +export function getAgentByHostname(hostname: string, bypassProxy = false) { + if (bypassProxy || (config.proxyBypassHosts || []).includes(hostname)) { + return { + http: _http, + https: _https, + }; + } else { + return { + http: httpAgent, + https: httpsAgent, + }; + } +} + export class StatusError extends Error { public statusCode: number; public statusMessage?: string; From 5eff4da27b382226bcd0be0772dac6105ade4216 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=81=E5=91=A8=E9=83=A8=E8=90=BD?= Date: Sat, 13 Apr 2024 08:59:11 +0800 Subject: [PATCH 07/99] feat: antenna limit --- locales/en-US.yml | 1 + locales/zh-CN.yml | 1 + packages/backend-rs/index.d.ts | 1 + packages/backend-rs/src/model/entity/meta.rs | 2 ++ .../migration/1712937600000-antennaLimit.ts | 19 +++++++++++++++++++ packages/backend/src/models/entities/meta.ts | 6 ++++++ .../src/server/api/endpoints/admin/meta.ts | 6 ++++++ .../server/api/endpoints/admin/update-meta.ts | 5 +++++ .../server/api/endpoints/antennas/create.ts | 5 ++++- .../backend/src/server/api/endpoints/meta.ts | 6 ++++++ packages/client/src/pages/admin/settings.vue | 16 ++++++++++++++++ packages/firefish-js/src/entities.ts | 1 + 12 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 packages/backend/src/migration/1712937600000-antennaLimit.ts diff --git a/locales/en-US.yml b/locales/en-US.yml index f8da18450c..a8663375a8 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -394,6 +394,7 @@ enableRegistration: "Enable new user registration" invite: "Invite" driveCapacityPerLocalAccount: "Drive capacity per local user" driveCapacityPerRemoteAccount: "Drive capacity per remote user" +antennaLimit: "The maximum number of antennas that each user can create" inMb: "In megabytes" iconUrl: "Icon URL" bannerUrl: "Banner image URL" diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index a8510612dc..9e7a0ed19e 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -340,6 +340,7 @@ invite: "邀请" driveCapacityPerLocalAccount: "每个本地用户的网盘容量" driveCapacityPerRemoteAccount: "每个远程用户的网盘容量" inMb: "以兆字节 (MegaByte) 为单位" +antennaLimit: "每个用户最多可以创建的天线数量" iconUrl: "图标 URL" bannerUrl: "横幅图 URL" backgroundImageUrl: "背景图 URL" diff --git a/packages/backend-rs/index.d.ts b/packages/backend-rs/index.d.ts index 617bedf5b9..509c3d912d 100644 --- a/packages/backend-rs/index.d.ts +++ b/packages/backend-rs/index.d.ts @@ -443,6 +443,7 @@ export interface Meta { recaptchaSecretKey: string | null localDriveCapacityMb: number remoteDriveCapacityMb: number + antennaLimit: number summalyProxy: string | null enableEmail: boolean email: string | null diff --git a/packages/backend-rs/src/model/entity/meta.rs b/packages/backend-rs/src/model/entity/meta.rs index b9a89914bd..7d0972b844 100644 --- a/packages/backend-rs/src/model/entity/meta.rs +++ b/packages/backend-rs/src/model/entity/meta.rs @@ -50,6 +50,8 @@ pub struct Model { pub local_drive_capacity_mb: i32, #[sea_orm(column_name = "remoteDriveCapacityMb")] pub remote_drive_capacity_mb: i32, + #[sea_orm(column_name = "antennaLimit")] + pub antenna_limit: i32, #[sea_orm(column_name = "summalyProxy")] pub summaly_proxy: Option, #[sea_orm(column_name = "enableEmail")] diff --git a/packages/backend/src/migration/1712937600000-antennaLimit.ts b/packages/backend/src/migration/1712937600000-antennaLimit.ts new file mode 100644 index 0000000000..cd8f9ff658 --- /dev/null +++ b/packages/backend/src/migration/1712937600000-antennaLimit.ts @@ -0,0 +1,19 @@ +import type { MigrationInterface, QueryRunner } from "typeorm"; + +export class antennaLimit1712937600000 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" ADD "antennaLimit" integer NOT NULL DEFAULT 5`, + undefined, + ); + await queryRunner.query( + `COMMENT ON COLUMN "meta"."antennaLimit" IS 'Antenna Limit'`, + ); + } + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "meta" DROP COLUMN "antennaLimit"`, + undefined, + ); + } +} diff --git a/packages/backend/src/models/entities/meta.ts b/packages/backend/src/models/entities/meta.ts index cdb8e14c3f..5e267a8e24 100644 --- a/packages/backend/src/models/entities/meta.ts +++ b/packages/backend/src/models/entities/meta.ts @@ -276,6 +276,12 @@ export class Meta { }) public remoteDriveCapacityMb: number; + @Column("integer", { + default: 5, + comment: "Antenna Limit", + }) + public antennaLimit: number; + @Column("varchar", { length: 128, nullable: true, diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts index a22fbab8f1..1f382f1254 100644 --- a/packages/backend/src/server/api/endpoints/admin/meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/meta.ts @@ -24,6 +24,11 @@ export const meta = { optional: false, nullable: false, }, + antennaLimit: { + type: "number", + optional: false, + nullable: false, + }, cacheRemoteFiles: { type: "boolean", optional: false, @@ -487,6 +492,7 @@ export default define(meta, paramDef, async () => { enableGuestTimeline: instance.enableGuestTimeline, driveCapacityPerLocalUserMb: instance.localDriveCapacityMb, driveCapacityPerRemoteUserMb: instance.remoteDriveCapacityMb, + antennaLimit: instance.antennaLimit, emailRequiredForSignup: instance.emailRequiredForSignup, enableHcaptcha: instance.enableHcaptcha, hcaptchaSiteKey: instance.hcaptchaSiteKey, diff --git a/packages/backend/src/server/api/endpoints/admin/update-meta.ts b/packages/backend/src/server/api/endpoints/admin/update-meta.ts index 604ef3a0fc..e5234ea720 100644 --- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts @@ -94,6 +94,7 @@ export const paramDef = { defaultDarkTheme: { type: "string", nullable: true }, localDriveCapacityMb: { type: "integer" }, remoteDriveCapacityMb: { type: "integer" }, + antennaLimit: { type: "integer" }, cacheRemoteFiles: { type: "boolean" }, markLocalFilesNsfwByDefault: { type: "boolean" }, emailRequiredForSignup: { type: "boolean" }, @@ -327,6 +328,10 @@ export default define(meta, paramDef, async (ps, me) => { set.remoteDriveCapacityMb = ps.remoteDriveCapacityMb; } + if (ps.antennaLimit !== undefined) { + set.antennaLimit = ps.antennaLimit; + } + if (ps.cacheRemoteFiles !== undefined) { set.cacheRemoteFiles = ps.cacheRemoteFiles; } diff --git a/packages/backend/src/server/api/endpoints/antennas/create.ts b/packages/backend/src/server/api/endpoints/antennas/create.ts index 792301d4de..792c5e30b4 100644 --- a/packages/backend/src/server/api/endpoints/antennas/create.ts +++ b/packages/backend/src/server/api/endpoints/antennas/create.ts @@ -3,6 +3,7 @@ import { genId } from "backend-rs"; import { Antennas, UserLists, UserGroupJoinings } from "@/models/index.js"; import { ApiError } from "@/server/api/error.js"; import { publishInternalEvent } from "@/services/stream.js"; +import { fetchMeta } from "@/misc/fetch-meta.js"; export const meta = { tags: ["antennas"], @@ -109,10 +110,12 @@ export default define(meta, paramDef, async (ps, user) => { let userList; let userGroupJoining; + const instance = await fetchMeta(true); + const antennas = await Antennas.findBy({ userId: user.id, }); - if (antennas.length > 5 && !user.isAdmin) { + if (antennas.length >= instance.antennaLimit) { throw new ApiError(meta.errors.tooManyAntennas); } diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts index 2a674b52c3..cb494bf27e 100644 --- a/packages/backend/src/server/api/endpoints/meta.ts +++ b/packages/backend/src/server/api/endpoints/meta.ts @@ -126,6 +126,11 @@ export const meta = { optional: false, nullable: false, }, + antennaLimit: { + type: "number", + optional: false, + nullable: false, + }, cacheRemoteFiles: { type: "boolean", optional: false, @@ -445,6 +450,7 @@ export default define(meta, paramDef, async (ps, me) => { enableGuestTimeline: instance.enableGuestTimeline, driveCapacityPerLocalUserMb: instance.localDriveCapacityMb, driveCapacityPerRemoteUserMb: instance.remoteDriveCapacityMb, + antennaLimit: instance.antennaLimit, emailRequiredForSignup: instance.emailRequiredForSignup, enableHcaptcha: instance.enableHcaptcha, hcaptchaSiteKey: instance.hcaptchaSiteKey, diff --git a/packages/client/src/pages/admin/settings.vue b/packages/client/src/pages/admin/settings.vue index f69c4fb23b..1c2188daac 100644 --- a/packages/client/src/pages/admin/settings.vue +++ b/packages/client/src/pages/admin/settings.vue @@ -350,6 +350,19 @@ + + + + + + + @@ -502,6 +515,7 @@ const cacheRemoteFiles = ref(false); const markLocalFilesNsfwByDefault = ref(false); const localDriveCapacityMb = ref(0); const remoteDriveCapacityMb = ref(0); +const antennaLimit = ref(0); const enableRegistration = ref(false); const emailRequiredForSignup = ref(false); const enableServiceWorker = ref(false); @@ -579,6 +593,7 @@ async function init() { markLocalFilesNsfwByDefault.value = meta.markLocalFilesNsfwByDefault; localDriveCapacityMb.value = meta.driveCapacityPerLocalUserMb; remoteDriveCapacityMb.value = meta.driveCapacityPerRemoteUserMb; + antennaLimit.value = meta.antennaLimit; enableRegistration.value = !meta.disableRegistration; emailRequiredForSignup.value = meta.emailRequiredForSignup; enableServiceWorker.value = meta.enableServiceWorker; @@ -631,6 +646,7 @@ function save() { markLocalFilesNsfwByDefault: markLocalFilesNsfwByDefault.value, localDriveCapacityMb: localDriveCapacityMb.value, remoteDriveCapacityMb: remoteDriveCapacityMb.value, + antennaLimit: antennaLimit.value, disableRegistration: !enableRegistration.value, emailRequiredForSignup: emailRequiredForSignup.value, enableServiceWorker: enableServiceWorker.value, diff --git a/packages/firefish-js/src/entities.ts b/packages/firefish-js/src/entities.ts index ce940a1481..6f9d6b400b 100644 --- a/packages/firefish-js/src/entities.ts +++ b/packages/firefish-js/src/entities.ts @@ -341,6 +341,7 @@ export type LiteInstanceMetadata = { disableGlobalTimeline: boolean; driveCapacityPerLocalUserMb: number; driveCapacityPerRemoteUserMb: number; + antennaLimit: number; enableHcaptcha: boolean; hcaptchaSiteKey: string | null; enableRecaptcha: boolean; From f0a50bc2889416c8fb741147523b077719621130 Mon Sep 17 00:00:00 2001 From: Lhcfl Date: Sun, 14 Apr 2024 13:59:27 +0800 Subject: [PATCH 08/99] feat: show MkRemoteCaution in note history page --- packages/client/src/pages/note-history.vue | 74 ++++++++++++---------- 1 file changed, 39 insertions(+), 35 deletions(-) diff --git a/packages/client/src/pages/note-history.vue b/packages/client/src/pages/note-history.vue index f6fbf517a3..33cae5860a 100644 --- a/packages/client/src/pages/note-history.vue +++ b/packages/client/src/pages/note-history.vue @@ -4,30 +4,35 @@ > - - -
- - - -
-
+ +
+ + +
+ + + +
+
+
@@ -42,6 +47,7 @@ import XNote from "@/components/MkNote.vue"; import { i18n } from "@/i18n"; import { definePageMetadata } from "@/scripts/page-metadata"; import icon from "@/scripts/icon"; +import MkRemoteCaution from "@/components/MkRemoteCaution.vue"; const pagingComponent = ref>(); @@ -65,8 +71,7 @@ definePageMetadata( })), ); -const note = ref({} as entities.Note); -const loaded = ref(false); +const note = ref(null); onMounted(() => { api("notes/show", { @@ -79,20 +84,19 @@ onMounted(() => { res.replyId = null; note.value = res; - loaded.value = true; }); }); function convertNoteEditsToNotes(noteEdits: entities.NoteEdit[]) { const now: entities.NoteEdit = { id: "EditionNow", - noteId: note.value.id, - updatedAt: note.value.createdAt, - text: note.value.text, - cw: note.value.cw, - files: note.value.files, - fileIds: note.value.fileIds, - emojis: note.value.emojis, + noteId: note.value!.id, + updatedAt: note.value!.createdAt, + text: note.value!.text, + cw: note.value!.cw, + files: note.value!.files, + fileIds: note.value!.fileIds, + emojis: note.value!.emojis, }; return [now] @@ -108,7 +112,7 @@ function convertNoteEditsToNotes(noteEdits: entities.NoteEdit[]) { _shouldInsertAd_: false, files: noteEdit.files, fileIds: noteEdit.fileIds, - emojis: note.value.emojis.concat(noteEdit.emojis), + emojis: note.value!.emojis.concat(noteEdit.emojis), }); }); } From 54d9916fecaab64a8b61ea59fe52e6a51ebcc97e Mon Sep 17 00:00:00 2001 From: Lhcfl Date: Sun, 14 Apr 2024 16:34:33 +0800 Subject: [PATCH 09/99] fix: rss feed no HTML --- packages/backend/src/server/web/feed.ts | 47 ++++++++++++++++++------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/packages/backend/src/server/web/feed.ts b/packages/backend/src/server/web/feed.ts index e6b09b4f4f..3b1b9d6fa5 100644 --- a/packages/backend/src/server/web/feed.ts +++ b/packages/backend/src/server/web/feed.ts @@ -2,7 +2,19 @@ import { Feed } from "feed"; import { In, IsNull } from "typeorm"; import config from "@/config/index.js"; import type { User } from "@/models/entities/user.js"; +import type { Note } from "@/models/entities/note.js"; import { Notes, DriveFiles, UserProfiles, Users } from "@/models/index.js"; +import getNoteHtml from "@/remote/activitypub/misc/get-note-html.js"; + +/** + * If there is this part in the note, it will cause CDATA to be terminated early. + * So I inserted two zero-width spaces in the middle, which doesn't make a visual difference + * Although this is not a good solution, there seems no other way. + * Anyway, it is not common to encounter such extreme situations. + */ +function escapeCDATA(str: string) { + return str.replaceAll("]]>", "]​]​>"); +} export default async function ( user: User, @@ -15,7 +27,7 @@ export default async function ( const author = { link: `${config.url}/@${user.username}`, email: `${user.username}@${config.host}`, - name: user.name || user.username, + name: escapeCDATA(user.name || user.username), }; const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); @@ -44,11 +56,13 @@ export default async function ( title: `${author.name} (@${user.username}@${config.host})`, updated: notes[0].createdAt, generator: "Firefish", - description: `${user.notesCount} Notes, ${ - profile.ffVisibility === "public" ? user.followingCount : "?" - } Following, ${ - profile.ffVisibility === "public" ? user.followersCount : "?" - } Followers${profile.description ? ` · ${profile.description}` : ""}`, + description: escapeCDATA( + `${user.notesCount} Notes, ${ + profile.ffVisibility === "public" ? user.followingCount : "?" + } Following, ${ + profile.ffVisibility === "public" ? user.followersCount : "?" + } Followers${profile.description ? ` · ${profile.description}` : ""}`, + ), link: author.link, image: await Users.getAvatarUrl(user), feedLinks: { @@ -88,19 +102,23 @@ export default async function ( } feed.addItem({ - title: title - .replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, "") - .substring(0, 100), + title: escapeCDATA( + title + .replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, "") + .substring(0, 100), + ), link: `${config.url}/notes/${note.id}`, date: note.createdAt, description: note.cw - ? note.cw.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, "") + ? escapeCDATA(note.cw.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, "")) : undefined, - content: contentStr.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, ""), + content: escapeCDATA( + contentStr.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, ""), + ), }); } - async function noteToString(note, isTheNote = false) { + async function noteToString(note: Note, isTheNote = false) { const author = isTheNote ? null : await Users.findOneBy({ id: note.userId }); @@ -135,7 +153,10 @@ export default async function ( }">${file.name}`; } } - outstr += `${note.cw ? note.cw + "
" : ""}${note.text || ""}${fileEle}`; + + outstr += `${note.cw ? note.cw + "
" : ""}${ + getNoteHtml(note) || "" + }${fileEle}`; if (isTheNote) { outstr += ` Date: Sun, 14 Apr 2024 16:44:12 +0800 Subject: [PATCH 10/99] fix: use better `]]>` replacer --- packages/backend/src/server/web/feed.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/backend/src/server/web/feed.ts b/packages/backend/src/server/web/feed.ts index 3b1b9d6fa5..f3b3c97c32 100644 --- a/packages/backend/src/server/web/feed.ts +++ b/packages/backend/src/server/web/feed.ts @@ -8,12 +8,9 @@ import getNoteHtml from "@/remote/activitypub/misc/get-note-html.js"; /** * If there is this part in the note, it will cause CDATA to be terminated early. - * So I inserted two zero-width spaces in the middle, which doesn't make a visual difference - * Although this is not a good solution, there seems no other way. - * Anyway, it is not common to encounter such extreme situations. */ function escapeCDATA(str: string) { - return str.replaceAll("]]>", "]​]​>"); + return str.replaceAll("]]>", "]]]]>"); } export default async function ( From 4823abd3a9415cea56f703854e8ea344a65f644b Mon Sep 17 00:00:00 2001 From: yumeko Date: Fri, 19 Apr 2024 03:34:25 +0300 Subject: [PATCH 11/99] Add usageHint field to DriveFile, and fill accordingly when operating on Persons --- .../migration/1713451569342-AddDriveFileUsage.ts | 15 +++++++++++++++ .../backend/src/models/entities/drive-file.ts | 7 +++++++ .../src/remote/activitypub/models/image.ts | 5 ++++- .../backend/src/remote/activitypub/models/note.ts | 4 ++-- .../src/remote/activitypub/models/person.ts | 8 ++++---- packages/backend/src/services/drive/add-file.ts | 10 ++++++++++ .../backend/src/services/drive/upload-from-url.ts | 11 +++++++++-- 7 files changed, 51 insertions(+), 9 deletions(-) create mode 100644 packages/backend/src/migration/1713451569342-AddDriveFileUsage.ts diff --git a/packages/backend/src/migration/1713451569342-AddDriveFileUsage.ts b/packages/backend/src/migration/1713451569342-AddDriveFileUsage.ts new file mode 100644 index 0000000000..c0c96fe74c --- /dev/null +++ b/packages/backend/src/migration/1713451569342-AddDriveFileUsage.ts @@ -0,0 +1,15 @@ +import type { MigrationInterface, QueryRunner } from "typeorm"; + +export class AddDriveFileUsage1713451569342 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "drive_file" ADD "usageHint" character varying(16) DEFAULT NULL`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "drive_file" DROP COLUMN "usageHint"` + ); + } +} diff --git a/packages/backend/src/models/entities/drive-file.ts b/packages/backend/src/models/entities/drive-file.ts index 3c49e89fd5..b5717d62cd 100644 --- a/packages/backend/src/models/entities/drive-file.ts +++ b/packages/backend/src/models/entities/drive-file.ts @@ -177,6 +177,13 @@ export class DriveFile { }) public isSensitive: boolean; + @Column("varchar", { + length: 16, + nullable: true, + comment: "Hint for what the file is used for.", + }) + public usageHint: string | null; + /** * 外部の(信頼されていない)URLへの直リンクか否か */ diff --git a/packages/backend/src/remote/activitypub/models/image.ts b/packages/backend/src/remote/activitypub/models/image.ts index e2072a963a..23fb720362 100644 --- a/packages/backend/src/remote/activitypub/models/image.ts +++ b/packages/backend/src/remote/activitypub/models/image.ts @@ -16,6 +16,7 @@ const logger = apLogger; export async function createImage( actor: CacheableRemoteUser, value: any, + usage: 'avatar' | 'banner' | null ): Promise { // Skip if author is frozen. if (actor.isSuspended) { @@ -43,6 +44,7 @@ export async function createImage( sensitive: image.sensitive, isLink: !instance.cacheRemoteFiles, comment: truncate(image.name, DB_MAX_IMAGE_COMMENT_LENGTH), + usageHint: usage }); if (file.isLink) { @@ -73,9 +75,10 @@ export async function createImage( export async function resolveImage( actor: CacheableRemoteUser, value: any, + usage: 'avatar' | 'banner' | null, ): Promise { // TODO // Fetch from remote server and register - return await createImage(actor, value); + return await createImage(actor, value, usage); } diff --git a/packages/backend/src/remote/activitypub/models/note.ts b/packages/backend/src/remote/activitypub/models/note.ts index ad59930457..5e1c3829a7 100644 --- a/packages/backend/src/remote/activitypub/models/note.ts +++ b/packages/backend/src/remote/activitypub/models/note.ts @@ -213,7 +213,7 @@ export async function createNote( ? ( await Promise.all( note.attachment.map( - (x) => limit(() => resolveImage(actor, x)) as Promise, + (x) => limit(() => resolveImage(actor, x, null)) as Promise, ), ) ).filter((image) => image != null) @@ -616,7 +616,7 @@ export async function updateNote(value: string | IObject, resolver?: Resolver) { fileList.map( (x) => limit(async () => { - const file = await resolveImage(actor, x); + const file = await resolveImage(actor, x, null); const update: Partial = {}; const altText = truncate(x.name, DB_MAX_IMAGE_COMMENT_LENGTH); diff --git a/packages/backend/src/remote/activitypub/models/person.ts b/packages/backend/src/remote/activitypub/models/person.ts index e91280125f..47a1152c36 100644 --- a/packages/backend/src/remote/activitypub/models/person.ts +++ b/packages/backend/src/remote/activitypub/models/person.ts @@ -362,10 +362,10 @@ export async function createPerson( //#region Fetch avatar and header image const [avatar, banner] = await Promise.all( - [person.icon, person.image].map((img) => + [person.icon, person.image].map((img, index) => img == null ? Promise.resolve(null) - : resolveImage(user!, img).catch(() => null), + : resolveImage(user!, img, index === 0 ? "avatar" : index === 1 ? "banner" : null).catch(() => null), ), ); @@ -438,10 +438,10 @@ export async function updatePerson( // Fetch avatar and header image const [avatar, banner] = await Promise.all( - [person.icon, person.image].map((img) => + [person.icon, person.image].map((img, index) => img == null ? Promise.resolve(null) - : resolveImage(user, img).catch(() => null), + : resolveImage(user, img, index === 0 ? "avatar" : index === 1 ? "banner" : null).catch(() => null), ), ); diff --git a/packages/backend/src/services/drive/add-file.ts b/packages/backend/src/services/drive/add-file.ts index 24ad9f8f02..cfb871dd93 100644 --- a/packages/backend/src/services/drive/add-file.ts +++ b/packages/backend/src/services/drive/add-file.ts @@ -65,6 +65,7 @@ function urlPathJoin( * @param type Content-Type for original * @param hash Hash for original * @param size Size for original + * @param usage Optional usage hint for file (f.e. "avatar") */ async function save( file: DriveFile, @@ -73,6 +74,7 @@ async function save( type: string, hash: string, size: number, + usage: string | null = null ): Promise { // thunbnail, webpublic を必要なら生成 const alts = await generateAlts(path, type, !file.uri); @@ -161,6 +163,7 @@ async function save( file.md5 = hash; file.size = size; file.storedInternal = false; + file.usageHint = usage ?? null; return await DriveFiles.insert(file).then((x) => DriveFiles.findOneByOrFail(x.identifiers[0]), @@ -204,6 +207,7 @@ async function save( file.type = type; file.md5 = hash; file.size = size; + file.usageHint = usage ?? null; return await DriveFiles.insert(file).then((x) => DriveFiles.findOneByOrFail(x.identifiers[0]), @@ -450,6 +454,9 @@ type AddFileArgs = { requestIp?: string | null; requestHeaders?: Record | null; + + /** Whether this file has a known use case, like user avatar or instance icon */ + usageHint?: string | null; }; /** @@ -469,6 +476,7 @@ export async function addFile({ sensitive = null, requestIp = null, requestHeaders = null, + usageHint = null, }: AddFileArgs): Promise { const info = await getFileInfo(path); logger.info(`${JSON.stringify(info)}`); @@ -581,6 +589,7 @@ export async function addFile({ file.isLink = isLink; file.requestIp = requestIp; file.requestHeaders = requestHeaders; + file.usageHint = usageHint; file.isSensitive = user ? Users.isLocalUser(user) && (instance!.markLocalFilesNsfwByDefault || profile!.alwaysMarkNsfw) @@ -639,6 +648,7 @@ export async function addFile({ info.type.mime, info.md5, info.size, + usageHint ); } diff --git a/packages/backend/src/services/drive/upload-from-url.ts b/packages/backend/src/services/drive/upload-from-url.ts index 551d3757ca..238f8714fa 100644 --- a/packages/backend/src/services/drive/upload-from-url.ts +++ b/packages/backend/src/services/drive/upload-from-url.ts @@ -13,7 +13,11 @@ const logger = driveLogger.createSubLogger("downloader"); type Args = { url: string; - user: { id: User["id"]; host: User["host"] } | null; + user: { + id: User["id"]; + host: User["host"]; + driveCapacityOverrideMb: User["driveCapacityOverrideMb"]; + } | null; folderId?: DriveFolder["id"] | null; uri?: string | null; sensitive?: boolean; @@ -22,6 +26,7 @@ type Args = { comment?: string | null; requestIp?: string | null; requestHeaders?: Record | null; + usageHint?: string | null; }; export async function uploadFromUrl({ @@ -35,6 +40,7 @@ export async function uploadFromUrl({ comment = null, requestIp = null, requestHeaders = null, + usageHint = null }: Args): Promise { const parsedUrl = new URL(url); if ( @@ -75,9 +81,10 @@ export async function uploadFromUrl({ sensitive, requestIp, requestHeaders, + usageHint }); logger.succ(`Got: ${driveFile.id}`); - return driveFile!; + return driveFile; } catch (e) { logger.error(`Failed to create drive file:\n${inspect(e)}`); throw e; From c0f93de94b2183c53ce041b58d028474c0f7ed73 Mon Sep 17 00:00:00 2001 From: yumeko Date: Fri, 19 Apr 2024 06:26:40 +0300 Subject: [PATCH 12/99] Set file usage hints on local avatar/banner uploads as well + export "valid" values as type --- .../backend/src/models/entities/drive-file.ts | 4 +++- .../src/remote/activitypub/models/image.ts | 6 ++--- .../src/remote/activitypub/models/person.ts | 4 ++-- .../src/server/api/endpoints/i/update.ts | 23 +++++++++++++++++-- .../backend/src/services/drive/add-file.ts | 7 +++--- 5 files changed, 33 insertions(+), 11 deletions(-) diff --git a/packages/backend/src/models/entities/drive-file.ts b/packages/backend/src/models/entities/drive-file.ts index b5717d62cd..f257280d60 100644 --- a/packages/backend/src/models/entities/drive-file.ts +++ b/packages/backend/src/models/entities/drive-file.ts @@ -16,6 +16,8 @@ import { DriveFolder } from "./drive-folder.js"; import { DB_MAX_IMAGE_COMMENT_LENGTH } from "@/misc/hard-limits.js"; import { NoteFile } from "./note-file.js"; +export type DriveFileUsageHint = "user_avatar" | "user_banner" | null; + @Entity() @Index(["userId", "folderId", "id"]) export class DriveFile { @@ -182,7 +184,7 @@ export class DriveFile { nullable: true, comment: "Hint for what the file is used for.", }) - public usageHint: string | null; + public usageHint: DriveFileUsageHint; /** * 外部の(信頼されていない)URLへの直リンクか否か diff --git a/packages/backend/src/remote/activitypub/models/image.ts b/packages/backend/src/remote/activitypub/models/image.ts index 23fb720362..9183b82ebe 100644 --- a/packages/backend/src/remote/activitypub/models/image.ts +++ b/packages/backend/src/remote/activitypub/models/image.ts @@ -3,7 +3,7 @@ import type { CacheableRemoteUser } from "@/models/entities/user.js"; import Resolver from "../resolver.js"; import { fetchMeta } from "backend-rs"; import { apLogger } from "../logger.js"; -import type { DriveFile } from "@/models/entities/drive-file.js"; +import type { DriveFile, DriveFileUsageHint } from "@/models/entities/drive-file.js"; import { DriveFiles } from "@/models/index.js"; import { truncate } from "@/misc/truncate.js"; import { DB_MAX_IMAGE_COMMENT_LENGTH } from "@/misc/hard-limits.js"; @@ -16,7 +16,7 @@ const logger = apLogger; export async function createImage( actor: CacheableRemoteUser, value: any, - usage: 'avatar' | 'banner' | null + usage: DriveFileUsageHint ): Promise { // Skip if author is frozen. if (actor.isSuspended) { @@ -75,7 +75,7 @@ export async function createImage( export async function resolveImage( actor: CacheableRemoteUser, value: any, - usage: 'avatar' | 'banner' | null, + usage: DriveFileUsageHint, ): Promise { // TODO diff --git a/packages/backend/src/remote/activitypub/models/person.ts b/packages/backend/src/remote/activitypub/models/person.ts index 47a1152c36..64a4c7f5c5 100644 --- a/packages/backend/src/remote/activitypub/models/person.ts +++ b/packages/backend/src/remote/activitypub/models/person.ts @@ -365,7 +365,7 @@ export async function createPerson( [person.icon, person.image].map((img, index) => img == null ? Promise.resolve(null) - : resolveImage(user!, img, index === 0 ? "avatar" : index === 1 ? "banner" : null).catch(() => null), + : resolveImage(user, img, index === 0 ? "user_avatar" : index === 1 ? "user_banner" : null).catch(() => null) ), ); @@ -441,7 +441,7 @@ export async function updatePerson( [person.icon, person.image].map((img, index) => img == null ? Promise.resolve(null) - : resolveImage(user, img, index === 0 ? "avatar" : index === 1 ? "banner" : null).catch(() => null), + : resolveImage(user, img, index === 0 ? "user_avatar" : index === 1 ? "user_banner" : null).catch(() => null), ), ); diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts index 4389688a12..9d39903eac 100644 --- a/packages/backend/src/server/api/endpoints/i/update.ts +++ b/packages/backend/src/server/api/endpoints/i/update.ts @@ -13,6 +13,7 @@ import { normalizeForSearch } from "@/misc/normalize-for-search.js"; import { verifyLink } from "@/services/fetch-rel-me.js"; import { ApiError } from "@/server/api/error.js"; import define from "@/server/api/define.js"; +import { DriveFile } from "@/models/entities/drive-file"; export const meta = { tags: ["account"], @@ -241,8 +242,9 @@ export default define(meta, paramDef, async (ps, _user, token) => { if (ps.emailNotificationTypes !== undefined) profileUpdates.emailNotificationTypes = ps.emailNotificationTypes; + let avatar: DriveFile | null = null if (ps.avatarId) { - const avatar = await DriveFiles.findOneBy({ id: ps.avatarId }); + avatar = await DriveFiles.findOneBy({ id: ps.avatarId }); if (avatar == null || avatar.userId !== user.id) throw new ApiError(meta.errors.noSuchAvatar); @@ -250,8 +252,9 @@ export default define(meta, paramDef, async (ps, _user, token) => { throw new ApiError(meta.errors.avatarNotAnImage); } + let banner: DriveFile | null = null if (ps.bannerId) { - const banner = await DriveFiles.findOneBy({ id: ps.bannerId }); + banner = await DriveFiles.findOneBy({ id: ps.bannerId }); if (banner == null || banner.userId !== user.id) throw new ApiError(meta.errors.noSuchBanner); @@ -328,6 +331,22 @@ export default define(meta, paramDef, async (ps, _user, token) => { updateUsertags(user, tags); //#endregion + // Update old/new avatar usage hints + if (avatar) + { + if (user.avatarId) + await DriveFiles.update(user.avatarId, {usageHint: null}); + await DriveFiles.update(avatar.id, {usageHint: "user_avatar"}); + } + + // Update old/new banner usage hints + if (banner) + { + if (user.bannerId) + await DriveFiles.update(user.bannerId, {usageHint: null}); + await DriveFiles.update(banner.id, {usageHint: "user_banner"}); + } + if (Object.keys(updates).length > 0) await Users.update(user.id, updates); if (Object.keys(profileUpdates).length > 0) await UserProfiles.update(user.id, profileUpdates); diff --git a/packages/backend/src/services/drive/add-file.ts b/packages/backend/src/services/drive/add-file.ts index cfb871dd93..79f30a651b 100644 --- a/packages/backend/src/services/drive/add-file.ts +++ b/packages/backend/src/services/drive/add-file.ts @@ -16,6 +16,7 @@ import { UserProfiles, } from "@/models/index.js"; import { DriveFile } from "@/models/entities/drive-file.js"; +import type { DriveFileUsageHint } from "@/models/entities/drive-file.js"; import type { IRemoteUser, User } from "@/models/entities/user.js"; import { genId } from "backend-rs"; import { isDuplicateKeyValueError } from "@/misc/is-duplicate-key-value-error.js"; @@ -65,7 +66,7 @@ function urlPathJoin( * @param type Content-Type for original * @param hash Hash for original * @param size Size for original - * @param usage Optional usage hint for file (f.e. "avatar") + * @param usage Optional usage hint for file (f.e. "user_avatar") */ async function save( file: DriveFile, @@ -74,7 +75,7 @@ async function save( type: string, hash: string, size: number, - usage: string | null = null + usage: DriveFileUsageHint = null ): Promise { // thunbnail, webpublic を必要なら生成 const alts = await generateAlts(path, type, !file.uri); @@ -456,7 +457,7 @@ type AddFileArgs = { requestHeaders?: Record | null; /** Whether this file has a known use case, like user avatar or instance icon */ - usageHint?: string | null; + usageHint?: DriveFileUsageHint; }; /** From 4aeb0d95ccf7e4427c60ecd915a48922f465e451 Mon Sep 17 00:00:00 2001 From: yumeko Date: Fri, 19 Apr 2024 07:03:09 +0300 Subject: [PATCH 13/99] Add DriveFile usageHint field to rust model as well --- packages/backend-rs/src/model/entity/drive_file.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/backend-rs/src/model/entity/drive_file.rs b/packages/backend-rs/src/model/entity/drive_file.rs index e3e4622a62..e5c3995573 100644 --- a/packages/backend-rs/src/model/entity/drive_file.rs +++ b/packages/backend-rs/src/model/entity/drive_file.rs @@ -52,6 +52,8 @@ pub struct Model { pub request_headers: Option, #[sea_orm(column_name = "requestIp")] pub request_ip: Option, + #[sea_orm(column_name = "usageHint")] + pub usage_hint: Option, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] From 913de651dbb4413728599a1c7df3a646098c750c Mon Sep 17 00:00:00 2001 From: yumeko Date: Fri, 19 Apr 2024 07:25:42 +0300 Subject: [PATCH 14/99] When updating (remote) user avatar/banner, clear usageHint for the previous drivefile, if any --- packages/backend/src/remote/activitypub/models/person.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/backend/src/remote/activitypub/models/person.ts b/packages/backend/src/remote/activitypub/models/person.ts index 64a4c7f5c5..5460a0234b 100644 --- a/packages/backend/src/remote/activitypub/models/person.ts +++ b/packages/backend/src/remote/activitypub/models/person.ts @@ -10,6 +10,7 @@ import { Followings, UserProfiles, UserPublickeys, + DriveFiles, } from "@/models/index.js"; import type { IRemoteUser, CacheableUser } from "@/models/entities/user.js"; import { User } from "@/models/entities/user.js"; @@ -561,10 +562,14 @@ export async function updatePerson( } as Partial; if (avatar) { + if (user?.avatarId) + await DriveFiles.update(user.avatarId, {usageHint: null}); updates.avatarId = avatar.id; } if (banner) { + if (user?.bannerId) + await DriveFiles.update(user.bannerId, {usageHint: null}); updates.bannerId = banner.id; } From 968657d26eff412fd18e8b8cab47718f40a0f5e1 Mon Sep 17 00:00:00 2001 From: yumeko Date: Fri, 19 Apr 2024 07:54:11 +0300 Subject: [PATCH 15/99] Run format --- .../1713451569342-AddDriveFileUsage.ts | 4 +--- .../src/remote/activitypub/models/image.ts | 9 ++++++--- .../src/remote/activitypub/models/note.ts | 3 ++- .../src/remote/activitypub/models/person.ts | 16 ++++++++++++---- .../src/server/api/endpoints/i/update.ts | 18 ++++++++---------- .../backend/src/services/drive/add-file.ts | 4 ++-- .../src/services/drive/upload-from-url.ts | 8 ++++---- 7 files changed, 35 insertions(+), 27 deletions(-) diff --git a/packages/backend/src/migration/1713451569342-AddDriveFileUsage.ts b/packages/backend/src/migration/1713451569342-AddDriveFileUsage.ts index c0c96fe74c..57c6a73890 100644 --- a/packages/backend/src/migration/1713451569342-AddDriveFileUsage.ts +++ b/packages/backend/src/migration/1713451569342-AddDriveFileUsage.ts @@ -8,8 +8,6 @@ export class AddDriveFileUsage1713451569342 implements MigrationInterface { } public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query( - `ALTER TABLE "drive_file" DROP COLUMN "usageHint"` - ); + await queryRunner.query(`ALTER TABLE "drive_file" DROP COLUMN "usageHint"`); } } diff --git a/packages/backend/src/remote/activitypub/models/image.ts b/packages/backend/src/remote/activitypub/models/image.ts index 9183b82ebe..a6ac698feb 100644 --- a/packages/backend/src/remote/activitypub/models/image.ts +++ b/packages/backend/src/remote/activitypub/models/image.ts @@ -3,7 +3,10 @@ import type { CacheableRemoteUser } from "@/models/entities/user.js"; import Resolver from "../resolver.js"; import { fetchMeta } from "backend-rs"; import { apLogger } from "../logger.js"; -import type { DriveFile, DriveFileUsageHint } from "@/models/entities/drive-file.js"; +import type { + DriveFile, + DriveFileUsageHint, +} from "@/models/entities/drive-file.js"; import { DriveFiles } from "@/models/index.js"; import { truncate } from "@/misc/truncate.js"; import { DB_MAX_IMAGE_COMMENT_LENGTH } from "@/misc/hard-limits.js"; @@ -16,7 +19,7 @@ const logger = apLogger; export async function createImage( actor: CacheableRemoteUser, value: any, - usage: DriveFileUsageHint + usage: DriveFileUsageHint, ): Promise { // Skip if author is frozen. if (actor.isSuspended) { @@ -44,7 +47,7 @@ export async function createImage( sensitive: image.sensitive, isLink: !instance.cacheRemoteFiles, comment: truncate(image.name, DB_MAX_IMAGE_COMMENT_LENGTH), - usageHint: usage + usageHint: usage, }); if (file.isLink) { diff --git a/packages/backend/src/remote/activitypub/models/note.ts b/packages/backend/src/remote/activitypub/models/note.ts index 5e1c3829a7..b2fd67288c 100644 --- a/packages/backend/src/remote/activitypub/models/note.ts +++ b/packages/backend/src/remote/activitypub/models/note.ts @@ -213,7 +213,8 @@ export async function createNote( ? ( await Promise.all( note.attachment.map( - (x) => limit(() => resolveImage(actor, x, null)) as Promise, + (x) => + limit(() => resolveImage(actor, x, null)) as Promise, ), ) ).filter((image) => image != null) diff --git a/packages/backend/src/remote/activitypub/models/person.ts b/packages/backend/src/remote/activitypub/models/person.ts index 5460a0234b..657ac7d553 100644 --- a/packages/backend/src/remote/activitypub/models/person.ts +++ b/packages/backend/src/remote/activitypub/models/person.ts @@ -366,7 +366,11 @@ export async function createPerson( [person.icon, person.image].map((img, index) => img == null ? Promise.resolve(null) - : resolveImage(user, img, index === 0 ? "user_avatar" : index === 1 ? "user_banner" : null).catch(() => null) + : resolveImage( + user, + img, + index === 0 ? "user_avatar" : index === 1 ? "user_banner" : null, + ).catch(() => null), ), ); @@ -442,7 +446,11 @@ export async function updatePerson( [person.icon, person.image].map((img, index) => img == null ? Promise.resolve(null) - : resolveImage(user, img, index === 0 ? "user_avatar" : index === 1 ? "user_banner" : null).catch(() => null), + : resolveImage( + user, + img, + index === 0 ? "user_avatar" : index === 1 ? "user_banner" : null, + ).catch(() => null), ), ); @@ -563,13 +571,13 @@ export async function updatePerson( if (avatar) { if (user?.avatarId) - await DriveFiles.update(user.avatarId, {usageHint: null}); + await DriveFiles.update(user.avatarId, { usageHint: null }); updates.avatarId = avatar.id; } if (banner) { if (user?.bannerId) - await DriveFiles.update(user.bannerId, {usageHint: null}); + await DriveFiles.update(user.bannerId, { usageHint: null }); updates.bannerId = banner.id; } diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts index 9d39903eac..29d03cc465 100644 --- a/packages/backend/src/server/api/endpoints/i/update.ts +++ b/packages/backend/src/server/api/endpoints/i/update.ts @@ -242,7 +242,7 @@ export default define(meta, paramDef, async (ps, _user, token) => { if (ps.emailNotificationTypes !== undefined) profileUpdates.emailNotificationTypes = ps.emailNotificationTypes; - let avatar: DriveFile | null = null + let avatar: DriveFile | null = null; if (ps.avatarId) { avatar = await DriveFiles.findOneBy({ id: ps.avatarId }); @@ -252,7 +252,7 @@ export default define(meta, paramDef, async (ps, _user, token) => { throw new ApiError(meta.errors.avatarNotAnImage); } - let banner: DriveFile | null = null + let banner: DriveFile | null = null; if (ps.bannerId) { banner = await DriveFiles.findOneBy({ id: ps.bannerId }); @@ -332,19 +332,17 @@ export default define(meta, paramDef, async (ps, _user, token) => { //#endregion // Update old/new avatar usage hints - if (avatar) - { + if (avatar) { if (user.avatarId) - await DriveFiles.update(user.avatarId, {usageHint: null}); - await DriveFiles.update(avatar.id, {usageHint: "user_avatar"}); + await DriveFiles.update(user.avatarId, { usageHint: null }); + await DriveFiles.update(avatar.id, { usageHint: "user_avatar" }); } // Update old/new banner usage hints - if (banner) - { + if (banner) { if (user.bannerId) - await DriveFiles.update(user.bannerId, {usageHint: null}); - await DriveFiles.update(banner.id, {usageHint: "user_banner"}); + await DriveFiles.update(user.bannerId, { usageHint: null }); + await DriveFiles.update(banner.id, { usageHint: "user_banner" }); } if (Object.keys(updates).length > 0) await Users.update(user.id, updates); diff --git a/packages/backend/src/services/drive/add-file.ts b/packages/backend/src/services/drive/add-file.ts index 79f30a651b..2f975e1984 100644 --- a/packages/backend/src/services/drive/add-file.ts +++ b/packages/backend/src/services/drive/add-file.ts @@ -75,7 +75,7 @@ async function save( type: string, hash: string, size: number, - usage: DriveFileUsageHint = null + usage: DriveFileUsageHint = null, ): Promise { // thunbnail, webpublic を必要なら生成 const alts = await generateAlts(path, type, !file.uri); @@ -649,7 +649,7 @@ export async function addFile({ info.type.mime, info.md5, info.size, - usageHint + usageHint, ); } diff --git a/packages/backend/src/services/drive/upload-from-url.ts b/packages/backend/src/services/drive/upload-from-url.ts index 238f8714fa..a96e8e3262 100644 --- a/packages/backend/src/services/drive/upload-from-url.ts +++ b/packages/backend/src/services/drive/upload-from-url.ts @@ -3,7 +3,7 @@ import type { User } from "@/models/entities/user.js"; import { createTemp } from "@/misc/create-temp.js"; import { downloadUrl, isPrivateIp } from "@/misc/download-url.js"; import type { DriveFolder } from "@/models/entities/drive-folder.js"; -import type { DriveFile } from "@/models/entities/drive-file.js"; +import type { DriveFile, DriveFileUsageHint } from "@/models/entities/drive-file.js"; import { DriveFiles } from "@/models/index.js"; import { driveLogger } from "./logger.js"; import { addFile } from "./add-file.js"; @@ -26,7 +26,7 @@ type Args = { comment?: string | null; requestIp?: string | null; requestHeaders?: Record | null; - usageHint?: string | null; + usageHint?: DriveFileUsageHint; }; export async function uploadFromUrl({ @@ -40,7 +40,7 @@ export async function uploadFromUrl({ comment = null, requestIp = null, requestHeaders = null, - usageHint = null + usageHint = null, }: Args): Promise { const parsedUrl = new URL(url); if ( @@ -81,7 +81,7 @@ export async function uploadFromUrl({ sensitive, requestIp, requestHeaders, - usageHint + usageHint, }); logger.succ(`Got: ${driveFile.id}`); return driveFile; From 6c46bb56fd2c13672ac6338b970f090f1f3c0672 Mon Sep 17 00:00:00 2001 From: yumeko Date: Fri, 19 Apr 2024 18:22:02 +0300 Subject: [PATCH 16/99] Switch DriveFile's usageHint field to an enum type --- .../src/migration/1713451569342-AddDriveFileUsage.ts | 6 +++++- packages/backend/src/models/entities/drive-file.ts | 7 ++++--- packages/backend/src/remote/activitypub/models/person.ts | 4 ++-- packages/backend/src/server/api/endpoints/i/update.ts | 4 ++-- packages/backend/src/services/drive/add-file.ts | 2 +- 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/packages/backend/src/migration/1713451569342-AddDriveFileUsage.ts b/packages/backend/src/migration/1713451569342-AddDriveFileUsage.ts index 57c6a73890..3bdb1aafc8 100644 --- a/packages/backend/src/migration/1713451569342-AddDriveFileUsage.ts +++ b/packages/backend/src/migration/1713451569342-AddDriveFileUsage.ts @@ -3,11 +3,15 @@ import type { MigrationInterface, QueryRunner } from "typeorm"; export class AddDriveFileUsage1713451569342 implements MigrationInterface { public async up(queryRunner: QueryRunner): Promise { await queryRunner.query( - `ALTER TABLE "drive_file" ADD "usageHint" character varying(16) DEFAULT NULL`, + `CREATE TYPE drive_file_usage_hint_enum AS ENUM ('userAvatar', 'userBanner')`, + ); + await queryRunner.query( + `ALTER TABLE "drive_file" ADD "usageHint" drive_file_usage_hint_enum DEFAULT NULL`, ); } public async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`ALTER TABLE "drive_file" DROP COLUMN "usageHint"`); + await queryRunner.query(`DROP TYPE drive_file_usage_hint_enum`); } } diff --git a/packages/backend/src/models/entities/drive-file.ts b/packages/backend/src/models/entities/drive-file.ts index f257280d60..2c6c1bf598 100644 --- a/packages/backend/src/models/entities/drive-file.ts +++ b/packages/backend/src/models/entities/drive-file.ts @@ -16,7 +16,7 @@ import { DriveFolder } from "./drive-folder.js"; import { DB_MAX_IMAGE_COMMENT_LENGTH } from "@/misc/hard-limits.js"; import { NoteFile } from "./note-file.js"; -export type DriveFileUsageHint = "user_avatar" | "user_banner" | null; +export type DriveFileUsageHint = "userAvatar" | "userBanner" | null; @Entity() @Index(["userId", "folderId", "id"]) @@ -179,8 +179,9 @@ export class DriveFile { }) public isSensitive: boolean; - @Column("varchar", { - length: 16, + @Column({ + type: "enum", + enum: ["userAvatar", "userBanner"], nullable: true, comment: "Hint for what the file is used for.", }) diff --git a/packages/backend/src/remote/activitypub/models/person.ts b/packages/backend/src/remote/activitypub/models/person.ts index 657ac7d553..4baa2c021b 100644 --- a/packages/backend/src/remote/activitypub/models/person.ts +++ b/packages/backend/src/remote/activitypub/models/person.ts @@ -369,7 +369,7 @@ export async function createPerson( : resolveImage( user, img, - index === 0 ? "user_avatar" : index === 1 ? "user_banner" : null, + index === 0 ? "userAvatar" : index === 1 ? "userBanner" : null, ).catch(() => null), ), ); @@ -449,7 +449,7 @@ export async function updatePerson( : resolveImage( user, img, - index === 0 ? "user_avatar" : index === 1 ? "user_banner" : null, + index === 0 ? "userAvatar" : index === 1 ? "userBanner" : null, ).catch(() => null), ), ); diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts index 29d03cc465..4f65c59a9e 100644 --- a/packages/backend/src/server/api/endpoints/i/update.ts +++ b/packages/backend/src/server/api/endpoints/i/update.ts @@ -335,14 +335,14 @@ export default define(meta, paramDef, async (ps, _user, token) => { if (avatar) { if (user.avatarId) await DriveFiles.update(user.avatarId, { usageHint: null }); - await DriveFiles.update(avatar.id, { usageHint: "user_avatar" }); + await DriveFiles.update(avatar.id, { usageHint: "userAvatar" }); } // Update old/new banner usage hints if (banner) { if (user.bannerId) await DriveFiles.update(user.bannerId, { usageHint: null }); - await DriveFiles.update(banner.id, { usageHint: "user_banner" }); + await DriveFiles.update(banner.id, { usageHint: "userBanner" }); } if (Object.keys(updates).length > 0) await Users.update(user.id, updates); diff --git a/packages/backend/src/services/drive/add-file.ts b/packages/backend/src/services/drive/add-file.ts index 2f975e1984..d180bbabf3 100644 --- a/packages/backend/src/services/drive/add-file.ts +++ b/packages/backend/src/services/drive/add-file.ts @@ -66,7 +66,7 @@ function urlPathJoin( * @param type Content-Type for original * @param hash Hash for original * @param size Size for original - * @param usage Optional usage hint for file (f.e. "user_avatar") + * @param usage Optional usage hint for file (f.e. "userAvatar") */ async function save( file: DriveFile, From 3b89a8bfa692cfeb9b71e7489bf493c40ab6a701 Mon Sep 17 00:00:00 2001 From: naskya Date: Sat, 20 Apr 2024 02:07:08 +0900 Subject: [PATCH 17/99] refactor (backend): port config loader to backend-rs completely --- packages/backend-rs/index.d.ts | 70 +++++- packages/backend-rs/index.js | 6 +- packages/backend-rs/src/config/environment.rs | 2 +- packages/backend-rs/src/config/server.rs | 201 +++++++++++++++++- packages/backend-rs/src/database/mod.rs | 12 +- packages/backend-rs/src/misc/convert_host.rs | 8 +- packages/backend/src/boot/index.ts | 2 +- packages/backend/src/boot/master.ts | 30 +-- packages/backend/src/boot/worker.ts | 2 +- packages/backend/src/config.ts | 4 + packages/backend/src/config/index.ts | 5 - packages/backend/src/config/load.ts | 89 -------- packages/backend/src/config/types.ts | 20 -- packages/backend/src/const.ts | 2 +- packages/backend/src/db/postgre.ts | 2 +- packages/backend/src/db/redis.ts | 2 +- packages/backend/src/mfm/to-html.ts | 2 +- packages/backend/src/misc/captcha.ts | 2 +- packages/backend/src/misc/download-url.ts | 2 +- packages/backend/src/misc/fetch.ts | 2 +- packages/backend/src/misc/populate-emojis.ts | 2 +- .../src/models/repositories/drive-file.ts | 2 +- .../backend/src/models/repositories/user.ts | 2 +- .../src/models/schema/federation-instance.ts | 2 +- packages/backend/src/queue/index.ts | 6 +- packages/backend/src/queue/initialize.ts | 2 +- .../processors/db/export-custom-emojis.ts | 2 +- .../src/queue/processors/webhook-deliver.ts | 2 +- packages/backend/src/queue/queues.ts | 2 +- .../src/remote/activitypub/check-fetch.ts | 2 +- .../src/remote/activitypub/db-resolver.ts | 2 +- .../remote/activitypub/kernel/flag/index.ts | 2 +- .../src/remote/activitypub/renderer/accept.ts | 2 +- .../src/remote/activitypub/renderer/add.ts | 2 +- .../remote/activitypub/renderer/announce.ts | 2 +- .../src/remote/activitypub/renderer/block.ts | 2 +- .../src/remote/activitypub/renderer/create.ts | 2 +- .../src/remote/activitypub/renderer/delete.ts | 2 +- .../src/remote/activitypub/renderer/emoji.ts | 2 +- .../src/remote/activitypub/renderer/flag.ts | 2 +- .../activitypub/renderer/follow-relay.ts | 2 +- .../activitypub/renderer/follow-user.ts | 2 +- .../src/remote/activitypub/renderer/follow.ts | 2 +- .../remote/activitypub/renderer/hashtag.ts | 2 +- .../src/remote/activitypub/renderer/index.ts | 2 +- .../src/remote/activitypub/renderer/key.ts | 2 +- .../src/remote/activitypub/renderer/like.ts | 2 +- .../remote/activitypub/renderer/mention.ts | 2 +- .../src/remote/activitypub/renderer/note.ts | 2 +- .../src/remote/activitypub/renderer/person.ts | 2 +- .../remote/activitypub/renderer/question.ts | 2 +- .../src/remote/activitypub/renderer/read.ts | 2 +- .../src/remote/activitypub/renderer/reject.ts | 2 +- .../src/remote/activitypub/renderer/remove.ts | 2 +- .../src/remote/activitypub/renderer/undo.ts | 2 +- .../src/remote/activitypub/renderer/update.ts | 2 +- .../src/remote/activitypub/renderer/vote.ts | 2 +- .../backend/src/remote/activitypub/request.ts | 2 +- .../src/remote/activitypub/resolver.ts | 2 +- packages/backend/src/remote/resolve-user.ts | 2 +- packages/backend/src/server/activitypub.ts | 2 +- .../src/server/activitypub/featured.ts | 2 +- .../src/server/activitypub/followers.ts | 2 +- .../src/server/activitypub/following.ts | 2 +- .../backend/src/server/activitypub/outbox.ts | 2 +- packages/backend/src/server/api/2fa.ts | 2 +- .../backend/src/server/api/common/signin.ts | 2 +- .../backend/src/server/api/common/signup.ts | 2 +- .../api/endpoints/admin/accounts/hosted.ts | 2 +- .../src/server/api/endpoints/admin/meta.ts | 2 +- .../api/endpoints/auth/session/generate.ts | 2 +- .../src/server/api/endpoints/fetch-rss.ts | 2 +- .../server/api/endpoints/i/2fa/key-done.ts | 2 +- .../server/api/endpoints/i/2fa/register.ts | 2 +- .../src/server/api/endpoints/i/move.ts | 2 +- .../server/api/endpoints/i/update-email.ts | 2 +- .../backend/src/server/api/endpoints/meta.ts | 2 +- .../api/endpoints/request-reset-password.ts | 2 +- .../api/endpoints/username/available.ts | 2 +- packages/backend/src/server/api/index.ts | 2 +- .../src/server/api/mastodon/endpoints/meta.ts | 2 +- .../src/server/api/openapi/gen-spec.ts | 2 +- .../backend/src/server/api/private/signin.ts | 2 +- .../backend/src/server/api/private/signup.ts | 2 +- packages/backend/src/server/index.ts | 2 +- packages/backend/src/server/nodeinfo.ts | 2 +- packages/backend/src/server/web/feed.ts | 2 +- packages/backend/src/server/web/index.ts | 2 +- packages/backend/src/server/web/manifest.ts | 2 +- .../backend/src/server/web/url-preview.ts | 2 +- packages/backend/src/server/well-known.ts | 2 +- .../src/services/drive/internal-storage.ts | 2 +- packages/backend/src/services/fetch-rel-me.ts | 2 +- .../src/services/following/requests/create.ts | 2 +- packages/backend/src/services/i/pin.ts | 2 +- packages/backend/src/services/logger.ts | 2 +- .../backend/src/services/messages/delete.ts | 2 +- packages/backend/src/services/note/create.ts | 2 +- packages/backend/src/services/note/delete.ts | 2 +- .../backend/src/services/push-notification.ts | 2 +- packages/backend/src/services/send-email.ts | 2 +- packages/backend/src/services/stream.ts | 2 +- packages/backend/src/services/suspend-user.ts | 2 +- .../backend/src/services/unsuspend-user.ts | 2 +- 104 files changed, 375 insertions(+), 262 deletions(-) create mode 100644 packages/backend/src/config.ts delete mode 100644 packages/backend/src/config/index.ts delete mode 100644 packages/backend/src/config/load.ts delete mode 100644 packages/backend/src/config/types.ts diff --git a/packages/backend-rs/index.d.ts b/packages/backend-rs/index.d.ts index 1cf961bd30..d985eb368d 100644 --- a/packages/backend-rs/index.d.ts +++ b/packages/backend-rs/index.d.ts @@ -12,7 +12,7 @@ export interface EnvConfig { withLogTime: boolean slow: boolean } -export function readEnvironmentConfig(): EnvConfig +export function loadEnv(): EnvConfig export interface ServerConfig { url: string port: number @@ -29,7 +29,7 @@ export interface ServerConfig { /** `NapiValue` is not implemented for `u64` */ maxFileSize?: number accessLog?: string - clusterLimits?: WorkerConfig + clusterLimits?: _WorkerConfig cuid?: IdConfig outgoingAddress?: string deliverJobConcurrency?: number @@ -76,6 +76,10 @@ export interface TlsConfig { host: string rejectUnauthorized: boolean } +export interface WorkerConfig { + web: number + queue: number +} export interface WorkerConfig { web?: number queue?: number @@ -121,7 +125,67 @@ export interface ObjectStorageConfig { setPublicReadOnUpload?: boolean s3ForcePathStyle?: boolean } -export function readServerConfig(): ServerConfig +export interface Config { + url: string + port: number + bind?: string + disableHsts?: boolean + db: DbConfig + redis: RedisConfig + cacheServer?: RedisConfig + proxy?: string + proxySmtp?: string + proxyBypassHosts?: Array + allowedPrivateNetworks?: Array + maxFileSize?: number + accessLog?: string + clusterLimits: WorkerConfig + cuid?: IdConfig + outgoingAddress?: string + deliverJobConcurrency?: number + inboxJobConcurrency?: number + deliverJobPerSec?: number + inboxJobPerSec?: number + deliverJobMaxAttempts?: number + inboxJobMaxAttempts?: number + logLevel?: Array + syslog?: SysLogConfig + proxyRemoteFiles?: boolean + mediaProxy?: string + summalyProxyUrl?: string + reservedUsernames?: Array + maxUserSignups?: number + isManagedHosting?: boolean + maxNoteLength?: number + maxCaptionLength?: number + deepl?: DeepLConfig + libreTranslate?: LibreTranslateConfig + email?: EmailConfig + objectStorage?: ObjectStorageConfig + version: string + host: string + hostname: string + scheme: string + wsScheme: string + apiUrl: string + wsUrl: string + authUrl: string + driveUrl: string + userAgent: string + clientEntry: Manifest +} +export interface Manifest { + file: string + name: string + src: string + isEntry: boolean + isDynamicEntry: boolean + imports: Array + dynamicImports: Array + css: Array + assets: Array +} +export function loadConfig(): Config export interface Acct { username: string host: string | null diff --git a/packages/backend-rs/index.js b/packages/backend-rs/index.js index 1ea7bb5bed..5fd1e9d784 100644 --- a/packages/backend-rs/index.js +++ b/packages/backend-rs/index.js @@ -310,10 +310,10 @@ if (!nativeBinding) { throw new Error(`Failed to load native binding`) } -const { readEnvironmentConfig, readServerConfig, stringToAcct, acctToString, checkWordMute, getFullApAccount, isSelfHost, isSameOrigin, extractHost, toPuny, isUnicodeEmoji, sqlLikeEscape, safeForSql, formatMilliseconds, getNoteSummary, toMastodonId, fromMastodonId, fetchMeta, metaToPugArgs, nyaify, hashPassword, verifyPassword, isOldPasswordAlgorithm, decodeReaction, countReactions, toDbReaction, AntennaSrcEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, initIdGenerator, getTimestamp, genId, secureRndstr } = nativeBinding +const { loadEnv, loadConfig, stringToAcct, acctToString, checkWordMute, getFullApAccount, isSelfHost, isSameOrigin, extractHost, toPuny, isUnicodeEmoji, sqlLikeEscape, safeForSql, formatMilliseconds, getNoteSummary, toMastodonId, fromMastodonId, fetchMeta, metaToPugArgs, nyaify, hashPassword, verifyPassword, isOldPasswordAlgorithm, decodeReaction, countReactions, toDbReaction, AntennaSrcEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, initIdGenerator, getTimestamp, genId, secureRndstr } = nativeBinding -module.exports.readEnvironmentConfig = readEnvironmentConfig -module.exports.readServerConfig = readServerConfig +module.exports.loadEnv = loadEnv +module.exports.loadConfig = loadConfig module.exports.stringToAcct = stringToAcct module.exports.acctToString = acctToString module.exports.checkWordMute = checkWordMute diff --git a/packages/backend-rs/src/config/environment.rs b/packages/backend-rs/src/config/environment.rs index 7d66aec7ba..1825af326a 100644 --- a/packages/backend-rs/src/config/environment.rs +++ b/packages/backend-rs/src/config/environment.rs @@ -11,7 +11,7 @@ pub struct EnvConfig { } #[crate::export] -pub fn read_environment_config() -> EnvConfig { +pub fn load_env() -> EnvConfig { let node_env = std::env::var("NODE_ENV").unwrap_or_default().to_lowercase(); let is_testing = node_env == "test"; diff --git a/packages/backend-rs/src/config/server.rs b/packages/backend-rs/src/config/server.rs index 125bae90b9..4b9fbc7131 100644 --- a/packages/backend-rs/src/config/server.rs +++ b/packages/backend-rs/src/config/server.rs @@ -6,7 +6,7 @@ use std::fs; #[derive(Clone, Debug, PartialEq, Deserialize)] #[serde(rename_all = "camelCase")] #[crate::export(object, use_nullable = false)] -pub struct ServerConfig { +struct ServerConfig { pub url: String, pub port: u16, /// host to listen on @@ -25,7 +25,7 @@ pub struct ServerConfig { /// `NapiValue` is not implemented for `u64` pub max_file_size: Option, pub access_log: Option, - pub cluster_limits: Option, + pub cluster_limits: Option<_WorkerConfig>, pub cuid: Option, pub outgoing_address: Option, @@ -94,10 +94,16 @@ pub struct TlsConfig { pub reject_unauthorized: bool, } +#[crate::export(object, use_nullable = false)] +pub struct WorkerConfig { + pub web: u32, + pub queue: u32, +} + #[derive(Clone, Debug, PartialEq, Deserialize)] #[serde(rename_all = "camelCase")] #[crate::export(object, use_nullable = false)] -pub struct WorkerConfig { +pub struct _WorkerConfig { pub web: Option, pub queue: Option, } @@ -167,17 +173,198 @@ pub struct ObjectStorageConfig { pub s3_force_path_style: Option, } -#[crate::export] -pub fn read_server_config() -> ServerConfig { +#[crate::export(object, use_nullable = false)] +pub struct Config { + // ServerConfig (from default.yml) + pub url: String, + pub port: u16, + pub bind: Option, + pub disable_hsts: Option, + pub db: DbConfig, + pub redis: RedisConfig, + pub cache_server: Option, + pub proxy: Option, + pub proxy_smtp: Option, + pub proxy_bypass_hosts: Option>, + pub allowed_private_networks: Option>, + pub max_file_size: Option, + pub access_log: Option, + pub cluster_limits: WorkerConfig, + pub cuid: Option, + pub outgoing_address: Option, + pub deliver_job_concurrency: Option, + pub inbox_job_concurrency: Option, + pub deliver_job_per_sec: Option, + pub inbox_job_per_sec: Option, + pub deliver_job_max_attempts: Option, + pub inbox_job_max_attempts: Option, + pub log_level: Option>, + pub syslog: Option, + pub proxy_remote_files: Option, + pub media_proxy: Option, + pub summaly_proxy_url: Option, + pub reserved_usernames: Option>, + pub max_user_signups: Option, + pub is_managed_hosting: Option, + pub max_note_length: Option, + pub max_caption_length: Option, + pub deepl: Option, + pub libre_translate: Option, + pub email: Option, + pub object_storage: Option, + + // Mixin + pub version: String, + pub host: String, + pub hostname: String, + pub scheme: String, + pub ws_scheme: String, + pub api_url: String, + pub ws_url: String, + pub auth_url: String, + pub drive_url: String, + pub user_agent: String, + pub client_entry: Manifest, +} + +#[derive(Clone, Debug, PartialEq, Deserialize)] +#[serde(rename_all = "camelCase")] +struct Meta { + pub version: String, +} + +#[derive(Clone, Debug, PartialEq, Deserialize)] +struct ManifestJson { + #[serde(rename = "src/init.ts")] + pub init_ts: Manifest, +} + +#[derive(Clone, Debug, PartialEq, Deserialize)] +#[serde(rename_all = "camelCase")] +#[crate::export(object, use_nullable = false)] +pub struct Manifest { + pub file: String, + pub name: String, + pub src: String, + pub is_entry: bool, + pub is_dynamic_entry: bool, + pub imports: Vec, + pub dynamic_imports: Vec, + pub css: Vec, + pub assets: Vec, +} + +fn read_config_file() -> ServerConfig { let cwd = env::current_dir().unwrap(); let yml = fs::File::open(cwd.join("../../.config/default.yml")) .expect("Failed to open '.config/default.yml'"); - let mut data: ServerConfig = serde_yaml::from_reader(yml).expect("Failed to parse yaml"); + let mut data: ServerConfig = + serde_yaml::from_reader(yml).expect("Failed to parse .config/default.yml"); + data.url = url::Url::parse(&data.url) .expect("Config url is invalid") .origin() .ascii_serialization(); + + if data.bind.is_none() { + data.bind = std::env::var("BIND").ok() + } + data } -pub static SERVER_CONFIG: Lazy = Lazy::new(read_server_config); +fn read_meta() -> Meta { + let cwd = env::current_dir().unwrap(); + let meta_json = fs::File::open(cwd.join("../../built/meta.json")) + .expect("Failed to open 'built/meta.json'"); + serde_json::from_reader(meta_json).expect("Failed to parse built/meta.json") +} + +fn read_manifest() -> Manifest { + let cwd = env::current_dir().unwrap(); + let manifest_json = fs::File::open(cwd.join("../../built/_client_dist_/manifest.json")) + .expect("Failed to open 'built/_client_dist_/manifest.json'"); + let manifest: ManifestJson = serde_json::from_reader(manifest_json) + .expect("Failed to parse built/_client_dist_/manifest.json"); + + manifest.init_ts +} + +#[crate::export] +fn load_config() -> Config { + let server_config = read_config_file(); + let version = read_meta().version; + let manifest = read_manifest(); + let url = url::Url::parse(&server_config.url).expect("Config url is invalid"); + let host = url + .host_str() + .expect("Hostname is missing in the config url") + .to_owned(); + let hostname = url + .domain() + .expect("Domain is missing in the config url") + .to_owned(); + let scheme = url.scheme().to_owned(); + let ws_scheme = scheme.replace("http", "ws"); + + let cluster_limits = match server_config.cluster_limits { + Some(cl) => WorkerConfig { + web: cl.web.unwrap_or(1), + queue: cl.queue.unwrap_or(1), + }, + None => WorkerConfig { web: 1, queue: 1 }, + }; + + Config { + url: server_config.url, + port: server_config.port, + bind: server_config.bind, + disable_hsts: server_config.disable_hsts, + db: server_config.db, + redis: server_config.redis, + cache_server: server_config.cache_server, + proxy: server_config.proxy, + proxy_smtp: server_config.proxy_smtp, + proxy_bypass_hosts: server_config.proxy_bypass_hosts, + allowed_private_networks: server_config.allowed_private_networks, + max_file_size: server_config.max_file_size, + access_log: server_config.access_log, + cluster_limits, + cuid: server_config.cuid, + outgoing_address: server_config.outgoing_address, + deliver_job_concurrency: server_config.deliver_job_concurrency, + inbox_job_concurrency: server_config.inbox_job_concurrency, + deliver_job_per_sec: server_config.deliver_job_per_sec, + inbox_job_per_sec: server_config.inbox_job_per_sec, + deliver_job_max_attempts: server_config.deliver_job_max_attempts, + inbox_job_max_attempts: server_config.inbox_job_max_attempts, + log_level: server_config.log_level, + syslog: server_config.syslog, + proxy_remote_files: server_config.proxy_remote_files, + media_proxy: server_config.media_proxy, + summaly_proxy_url: server_config.summaly_proxy_url, + reserved_usernames: server_config.reserved_usernames, + max_user_signups: server_config.max_user_signups, + is_managed_hosting: server_config.is_managed_hosting, + max_note_length: server_config.max_note_length, + max_caption_length: server_config.max_caption_length, + deepl: server_config.deepl, + libre_translate: server_config.libre_translate, + email: server_config.email, + object_storage: server_config.object_storage, + + ws_url: format!("{}://{}", ws_scheme, host), + api_url: format!("{}://{}/api", scheme, host), + auth_url: format!("{}://{}/auth", scheme, host), + drive_url: format!("{}://{}/files", scheme, host), + user_agent: format!("Firefish/{} ({})", version, url), + version, + host, + hostname, + scheme, + ws_scheme, + client_entry: manifest, + } +} + +pub static CONFIG: Lazy = Lazy::new(load_config); diff --git a/packages/backend-rs/src/database/mod.rs b/packages/backend-rs/src/database/mod.rs index f598e35cc7..a60d20af9c 100644 --- a/packages/backend-rs/src/database/mod.rs +++ b/packages/backend-rs/src/database/mod.rs @@ -1,4 +1,4 @@ -use crate::config::server::SERVER_CONFIG; +use crate::config::server::CONFIG; use sea_orm::{Database, DbConn, DbErr}; static DB_CONN: once_cell::sync::OnceCell = once_cell::sync::OnceCell::new(); @@ -6,11 +6,11 @@ static DB_CONN: once_cell::sync::OnceCell = once_cell::sync::OnceCell::n async fn init_database() -> Result<&'static DbConn, DbErr> { let database_uri = format!( "postgres://{}:{}@{}:{}/{}", - SERVER_CONFIG.db.user, - urlencoding::encode(&SERVER_CONFIG.db.pass), - SERVER_CONFIG.db.host, - SERVER_CONFIG.db.port, - SERVER_CONFIG.db.db, + CONFIG.db.user, + urlencoding::encode(&CONFIG.db.pass), + CONFIG.db.host, + CONFIG.db.port, + CONFIG.db.db, ); let conn = Database::connect(database_uri).await?; Ok(DB_CONN.get_or_init(move || conn)) diff --git a/packages/backend-rs/src/misc/convert_host.rs b/packages/backend-rs/src/misc/convert_host.rs index 34a0792c62..cff52aeb07 100644 --- a/packages/backend-rs/src/misc/convert_host.rs +++ b/packages/backend-rs/src/misc/convert_host.rs @@ -1,4 +1,4 @@ -use crate::config::server::SERVER_CONFIG; +use crate::config::server::CONFIG; #[derive(thiserror::Error, Debug)] pub enum Error { @@ -14,21 +14,21 @@ pub enum Error { pub fn get_full_ap_account(username: &str, host: Option<&str>) -> Result { Ok(match host { Some(host) => format!("{}@{}", username, to_puny(host)?), - None => format!("{}@{}", username, extract_host(&SERVER_CONFIG.url)?), + None => format!("{}@{}", username, extract_host(&CONFIG.url)?), }) } #[crate::export] pub fn is_self_host(host: Option<&str>) -> Result { Ok(match host { - Some(host) => extract_host(&SERVER_CONFIG.url)? == to_puny(host)?, + Some(host) => extract_host(&CONFIG.url)? == to_puny(host)?, None => true, }) } #[crate::export] pub fn is_same_origin(uri: &str) -> Result { - Ok(url::Url::parse(uri)?.origin().ascii_serialization() == SERVER_CONFIG.url) + Ok(url::Url::parse(uri)?.origin().ascii_serialization() == CONFIG.url) } #[crate::export] diff --git a/packages/backend/src/boot/index.ts b/packages/backend/src/boot/index.ts index 9854d2dce4..3e542a6e36 100644 --- a/packages/backend/src/boot/index.ts +++ b/packages/backend/src/boot/index.ts @@ -3,7 +3,7 @@ import chalk from "chalk"; import Xev from "xev"; import Logger from "@/services/logger.js"; -import { envOption } from "@/config/index.js"; +import { envOption } from "@/config.js"; import { inspect } from "node:util"; // for typeorm diff --git a/packages/backend/src/boot/master.ts b/packages/backend/src/boot/master.ts index 3ba2d0cf50..44c4a8a2f1 100644 --- a/packages/backend/src/boot/master.ts +++ b/packages/backend/src/boot/master.ts @@ -8,9 +8,8 @@ import chalkTemplate from "chalk-template"; import semver from "semver"; import Logger from "@/services/logger.js"; -import loadConfig from "@/config/load.js"; -import type { Config } from "@/config/types.js"; -import { envOption } from "@/config/index.js"; +import type { Config } from "backend-rs"; +import { config, envOption } from "@/config.js"; import { showMachineInfo } from "@/misc/show-machine-info.js"; import { db, initDb } from "@/db/postgre.js"; import { inspect } from "node:util"; @@ -87,15 +86,12 @@ function greet() { * Init master process */ export async function masterMain() { - let config!: Config; - // initialize app try { greet(); showEnvironment(); await showMachineInfo(bootLogger); showNodejsVersion(); - config = loadConfigBoot(); await connectDb(); } catch (e) { bootLogger.error( @@ -154,28 +150,6 @@ function showNodejsVersion(): void { } } -function loadConfigBoot(): Config { - const configLogger = bootLogger.createSubLogger("config"); - let config; - - try { - config = loadConfig(); - } catch (exception) { - if (exception.code === "ENOENT") { - configLogger.error("Configuration file not found", null, true); - process.exit(1); - } else if (e instanceof Error) { - configLogger.error(e.message); - process.exit(1); - } - throw exception; - } - - configLogger.succ("Loaded"); - - return config; -} - async function connectDb(): Promise { const dbLogger = bootLogger.createSubLogger("db"); diff --git a/packages/backend/src/boot/worker.ts b/packages/backend/src/boot/worker.ts index 647ea40fbd..cae861230f 100644 --- a/packages/backend/src/boot/worker.ts +++ b/packages/backend/src/boot/worker.ts @@ -1,5 +1,5 @@ import cluster from "node:cluster"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { initDb } from "@/db/postgre.js"; import { initIdGenerator } from "backend-rs"; import os from "node:os"; diff --git a/packages/backend/src/config.ts b/packages/backend/src/config.ts new file mode 100644 index 0000000000..c91294b611 --- /dev/null +++ b/packages/backend/src/config.ts @@ -0,0 +1,4 @@ +import { loadConfig, loadEnv } from "backend-rs"; + +export const config = loadConfig(); +export const envOption = loadEnv(); diff --git a/packages/backend/src/config/index.ts b/packages/backend/src/config/index.ts deleted file mode 100644 index fe87e5026a..0000000000 --- a/packages/backend/src/config/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import load from "./load.js"; -import { readEnvironmentConfig } from "backend-rs"; - -export default load(); -export const envOption = readEnvironmentConfig(); diff --git a/packages/backend/src/config/load.ts b/packages/backend/src/config/load.ts deleted file mode 100644 index 682bf309d2..0000000000 --- a/packages/backend/src/config/load.ts +++ /dev/null @@ -1,89 +0,0 @@ -/** - * Config loader - */ - -import * as fs from "node:fs"; -import { fileURLToPath } from "node:url"; -import { dirname } from "node:path"; -import type { Mixin } from "./types.js"; -import { readServerConfig } from "backend-rs"; - -const _filename = fileURLToPath(import.meta.url); -const _dirname = dirname(_filename); - -/** - * Path of configuration directory - */ -const dir = `${_dirname}/../../../../.config`; - -/** - * Path of configuration file - */ -const path = - process.env.NODE_ENV === "test" ? `${dir}/test.yml` : `${dir}/default.yml`; - -export default function load() { - const meta = JSON.parse( - fs.readFileSync(`${_dirname}/../../../../built/meta.json`, "utf-8"), - ); - const clientManifest = JSON.parse( - fs.readFileSync( - `${_dirname}/../../../../built/_client_dist_/manifest.json`, - "utf-8", - ), - ); - const config = readServerConfig(); - - const mixin = {} as Mixin; - - const url = tryCreateUrl(config.url); - - config.url = url.origin; - - config.port = config.port || parseInt(process.env.PORT || "", 10); - config.bind = config.bind || process.env.BIND; - - mixin.version = meta.version; - mixin.host = url.host; - mixin.hostname = url.hostname; - mixin.scheme = url.protocol.replace(/:$/, ""); - mixin.wsScheme = mixin.scheme.replace("http", "ws"); - mixin.wsUrl = `${mixin.wsScheme}://${mixin.host}`; - mixin.apiUrl = `${mixin.scheme}://${mixin.host}/api`; - mixin.authUrl = `${mixin.scheme}://${mixin.host}/auth`; - mixin.driveUrl = `${mixin.scheme}://${mixin.host}/files`; - mixin.userAgent = `Firefish/${meta.version} (${config.url})`; - mixin.clientEntry = clientManifest["src/init.ts"]; - - if (config.proxyRemoteFiles == null) config.proxyRemoteFiles = true; - if (!config.redis.prefix) config.redis.prefix = mixin.hostname; - if (config.cacheServer && !config.cacheServer.prefix) - config.cacheServer.prefix = mixin.hostname; - - if (!config.clusterLimits) { - config.clusterLimits = { - web: 1, - queue: 1, - }; - } else { - config.clusterLimits = { - web: 1, - queue: 1, - ...config.clusterLimits, - }; - - if (config.clusterLimits.web! < 1 || config.clusterLimits.queue! < 1) { - throw new Error("Invalid cluster limits"); - } - } - - return Object.assign(config, mixin); -} - -function tryCreateUrl(url: string) { - try { - return new URL(url); - } catch (e) { - throw new Error(`url="${url}" is not a valid URL.`); - } -} diff --git a/packages/backend/src/config/types.ts b/packages/backend/src/config/types.ts deleted file mode 100644 index 6b593d3b2d..0000000000 --- a/packages/backend/src/config/types.ts +++ /dev/null @@ -1,20 +0,0 @@ -import type { ServerConfig } from "backend-rs"; - -/** - * Firefish が自動的に(ユーザーが設定した情報から推論して)設定する情報 - */ -export type Mixin = { - version: string; - host: string; - hostname: string; - scheme: string; - wsScheme: string; - apiUrl: string; - wsUrl: string; - authUrl: string; - driveUrl: string; - userAgent: string; - clientEntry: string; -}; - -export type Config = ServerConfig & Mixin; diff --git a/packages/backend/src/const.ts b/packages/backend/src/const.ts index 39ff99fda7..2c52e2b009 100644 --- a/packages/backend/src/const.ts +++ b/packages/backend/src/const.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { DB_MAX_IMAGE_COMMENT_LENGTH, DB_MAX_NOTE_TEXT_LENGTH, diff --git a/packages/backend/src/db/postgre.ts b/packages/backend/src/db/postgre.ts index 6baccaa271..e0ab9d6d37 100644 --- a/packages/backend/src/db/postgre.ts +++ b/packages/backend/src/db/postgre.ts @@ -5,7 +5,7 @@ pg.types.setTypeParser(20, Number); import type { Logger } from "typeorm"; import { DataSource } from "typeorm"; import * as highlight from "cli-highlight"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { User } from "@/models/entities/user.js"; import { DriveFile } from "@/models/entities/drive-file.js"; diff --git a/packages/backend/src/db/redis.ts b/packages/backend/src/db/redis.ts index 215effd8ea..dc703e9d47 100644 --- a/packages/backend/src/db/redis.ts +++ b/packages/backend/src/db/redis.ts @@ -1,5 +1,5 @@ import Redis from "ioredis"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; export function createConnection() { let source = config.redis; diff --git a/packages/backend/src/mfm/to-html.ts b/packages/backend/src/mfm/to-html.ts index 7b7c0967a1..64aa9d7164 100644 --- a/packages/backend/src/mfm/to-html.ts +++ b/packages/backend/src/mfm/to-html.ts @@ -1,7 +1,7 @@ import { type HTMLElement, Window } from "happy-dom"; import type * as mfm from "mfm-js"; import katex from "katex"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { intersperse } from "@/prelude/array.js"; import type { IMentionedRemoteUsers } from "@/models/entities/note.js"; diff --git a/packages/backend/src/misc/captcha.ts b/packages/backend/src/misc/captcha.ts index c163d4d82d..d0969b0205 100644 --- a/packages/backend/src/misc/captcha.ts +++ b/packages/backend/src/misc/captcha.ts @@ -1,7 +1,7 @@ import fetch from "node-fetch"; import { URLSearchParams } from "node:url"; import { getAgentByUrl } from "@/misc/fetch.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { inspect } from "node:util"; export async function verifyRecaptcha(secret: string, response: string) { diff --git a/packages/backend/src/misc/download-url.ts b/packages/backend/src/misc/download-url.ts index ab04e8aa9c..1bfd0a9f80 100644 --- a/packages/backend/src/misc/download-url.ts +++ b/packages/backend/src/misc/download-url.ts @@ -3,7 +3,7 @@ import * as stream from "node:stream"; import * as util from "node:util"; import got, * as Got from "got"; import { httpAgent, httpsAgent, StatusError } from "./fetch.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import chalk from "chalk"; import Logger from "@/services/logger.js"; import IPCIDR from "ip-cidr"; diff --git a/packages/backend/src/misc/fetch.ts b/packages/backend/src/misc/fetch.ts index 4b8fc048e2..b26fa83052 100644 --- a/packages/backend/src/misc/fetch.ts +++ b/packages/backend/src/misc/fetch.ts @@ -4,7 +4,7 @@ import type { URL } from "node:url"; import CacheableLookup from "cacheable-lookup"; import fetch, { type RequestRedirect } from "node-fetch"; import { HttpProxyAgent, HttpsProxyAgent } from "hpagent"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { isValidUrl } from "./is-valid-url.js"; export async function getJson( diff --git a/packages/backend/src/misc/populate-emojis.ts b/packages/backend/src/misc/populate-emojis.ts index 4ca60b222f..f2656ea28a 100644 --- a/packages/backend/src/misc/populate-emojis.ts +++ b/packages/backend/src/misc/populate-emojis.ts @@ -4,7 +4,7 @@ import type { Emoji } from "@/models/entities/emoji.js"; import type { Note } from "@/models/entities/note.js"; import { Cache } from "./cache.js"; import { decodeReaction, isSelfHost, toPuny } from "backend-rs"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { query } from "@/prelude/url.js"; import { redisClient } from "@/db/redis.js"; import type { NoteEdit } from "@/models/entities/note-edit.js"; diff --git a/packages/backend/src/models/repositories/drive-file.ts b/packages/backend/src/models/repositories/drive-file.ts index 2321f20d4c..757bd77ad6 100644 --- a/packages/backend/src/models/repositories/drive-file.ts +++ b/packages/backend/src/models/repositories/drive-file.ts @@ -4,7 +4,7 @@ import type { User } from "@/models/entities/user.js"; import { toPuny } from "backend-rs"; import { awaitAll } from "@/prelude/await-all.js"; import type { Packed } from "@/misc/schema.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { query, appendQuery } from "@/prelude/url.js"; import { Users, DriveFolders } from "../index.js"; import { deepClone } from "@/misc/clone.js"; diff --git a/packages/backend/src/models/repositories/user.ts b/packages/backend/src/models/repositories/user.ts index 3bc943965b..040106b410 100644 --- a/packages/backend/src/models/repositories/user.ts +++ b/packages/backend/src/models/repositories/user.ts @@ -2,7 +2,7 @@ import { In, Not } from "typeorm"; import Ajv from "ajv"; import type { ILocalUser, IRemoteUser } from "@/models/entities/user.js"; import { User } from "@/models/entities/user.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { Packed } from "@/misc/schema.js"; import type { Promiseable } from "@/prelude/await-all.js"; import { awaitAll } from "@/prelude/await-all.js"; diff --git a/packages/backend/src/models/schema/federation-instance.ts b/packages/backend/src/models/schema/federation-instance.ts index 7a8af7f51d..338e079e28 100644 --- a/packages/backend/src/models/schema/federation-instance.ts +++ b/packages/backend/src/models/schema/federation-instance.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; export const packedFederationInstanceSchema = { type: "object", diff --git a/packages/backend/src/queue/index.ts b/packages/backend/src/queue/index.ts index e4e413be52..6272a5e668 100644 --- a/packages/backend/src/queue/index.ts +++ b/packages/backend/src/queue/index.ts @@ -1,11 +1,10 @@ import type httpSignature from "@peertube/http-signature"; import { v4 as uuid } from "uuid"; -import config from "@/config/index.js"; +import { config, envOption } from "@/config.js"; import type { DriveFile } from "@/models/entities/drive-file.js"; import type { IActivity } from "@/remote/activitypub/type.js"; import type { Webhook, webhookEventTypes } from "@/models/entities/webhook.js"; -import { envOption } from "@/config/index.js"; import processDeliver from "./processors/deliver.js"; import processInbox from "./processors/inbox.js"; @@ -24,10 +23,9 @@ import { objectStorageQueue, endedPollNotificationQueue, webhookDeliverQueue, - backgroundQueue, } from "./queues.js"; import type { ThinUser } from "./types.js"; -import { Note } from "@/models/entities/note.js"; +import type { Note } from "@/models/entities/note.js"; function renderError(e: Error): any { return { diff --git a/packages/backend/src/queue/initialize.ts b/packages/backend/src/queue/initialize.ts index 0f9c83132f..3291d47675 100644 --- a/packages/backend/src/queue/initialize.ts +++ b/packages/backend/src/queue/initialize.ts @@ -1,5 +1,5 @@ import Bull from "bull"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; export function initialize(name: string, limitPerSec = -1) { return new Bull(name, { diff --git a/packages/backend/src/queue/processors/db/export-custom-emojis.ts b/packages/backend/src/queue/processors/db/export-custom-emojis.ts index a1ca3a91c5..157751c1aa 100644 --- a/packages/backend/src/queue/processors/db/export-custom-emojis.ts +++ b/packages/backend/src/queue/processors/db/export-custom-emojis.ts @@ -9,7 +9,7 @@ import { format as dateFormat } from "date-fns"; import { Users, Emojis } from "@/models/index.js"; import { createTemp, createTempDir } from "@/misc/create-temp.js"; import { downloadUrl } from "@/misc/download-url.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { IsNull } from "typeorm"; import { inspect } from "node:util"; diff --git a/packages/backend/src/queue/processors/webhook-deliver.ts b/packages/backend/src/queue/processors/webhook-deliver.ts index 12c9a05498..63a16c373b 100644 --- a/packages/backend/src/queue/processors/webhook-deliver.ts +++ b/packages/backend/src/queue/processors/webhook-deliver.ts @@ -3,7 +3,7 @@ import Logger from "@/services/logger.js"; import type { WebhookDeliverJobData } from "../types.js"; import { getResponse, StatusError } from "@/misc/fetch.js"; import { Webhooks } from "@/models/index.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; const logger = new Logger("webhook"); diff --git a/packages/backend/src/queue/queues.ts b/packages/backend/src/queue/queues.ts index 6b0eb2de42..06b9567e74 100644 --- a/packages/backend/src/queue/queues.ts +++ b/packages/backend/src/queue/queues.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { initialize as initializeQueue } from "./initialize.js"; import type { DeliverJobData, diff --git a/packages/backend/src/remote/activitypub/check-fetch.ts b/packages/backend/src/remote/activitypub/check-fetch.ts index 12ea63a931..04d989064f 100644 --- a/packages/backend/src/remote/activitypub/check-fetch.ts +++ b/packages/backend/src/remote/activitypub/check-fetch.ts @@ -1,6 +1,6 @@ import { URL } from "url"; import httpSignature, { IParsedSignature } from "@peertube/http-signature"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { fetchMeta } from "backend-rs"; import { toPuny } from "backend-rs"; import DbResolver from "@/remote/activitypub/db-resolver.js"; diff --git a/packages/backend/src/remote/activitypub/db-resolver.ts b/packages/backend/src/remote/activitypub/db-resolver.ts index a753606a14..088a2db9da 100644 --- a/packages/backend/src/remote/activitypub/db-resolver.ts +++ b/packages/backend/src/remote/activitypub/db-resolver.ts @@ -1,5 +1,5 @@ import escapeRegexp from "escape-regexp"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { Note } from "@/models/entities/note.js"; import type { CacheableRemoteUser, diff --git a/packages/backend/src/remote/activitypub/kernel/flag/index.ts b/packages/backend/src/remote/activitypub/kernel/flag/index.ts index 0f83f6b449..c556605865 100644 --- a/packages/backend/src/remote/activitypub/kernel/flag/index.ts +++ b/packages/backend/src/remote/activitypub/kernel/flag/index.ts @@ -1,5 +1,5 @@ import type { CacheableRemoteUser } from "@/models/entities/user.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { IFlag } from "../../type.js"; import { getApIds } from "../../type.js"; import { AbuseUserReports, Users } from "@/models/index.js"; diff --git a/packages/backend/src/remote/activitypub/renderer/accept.ts b/packages/backend/src/remote/activitypub/renderer/accept.ts index fd145dcf97..2d27a1b29d 100644 --- a/packages/backend/src/remote/activitypub/renderer/accept.ts +++ b/packages/backend/src/remote/activitypub/renderer/accept.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { User } from "@/models/entities/user.js"; export default (object: any, user: { id: User["id"]; host: null }) => ({ diff --git a/packages/backend/src/remote/activitypub/renderer/add.ts b/packages/backend/src/remote/activitypub/renderer/add.ts index d8203ac1ea..14c71694e1 100644 --- a/packages/backend/src/remote/activitypub/renderer/add.ts +++ b/packages/backend/src/remote/activitypub/renderer/add.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { ILocalUser } from "@/models/entities/user.js"; export default (user: ILocalUser, target: any, object: any) => ({ diff --git a/packages/backend/src/remote/activitypub/renderer/announce.ts b/packages/backend/src/remote/activitypub/renderer/announce.ts index 1fd1842acf..0cc9bec6f4 100644 --- a/packages/backend/src/remote/activitypub/renderer/announce.ts +++ b/packages/backend/src/remote/activitypub/renderer/announce.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { Note } from "@/models/entities/note.js"; export default (object: any, note: Note) => { diff --git a/packages/backend/src/remote/activitypub/renderer/block.ts b/packages/backend/src/remote/activitypub/renderer/block.ts index c2ea267f38..5169e0d550 100644 --- a/packages/backend/src/remote/activitypub/renderer/block.ts +++ b/packages/backend/src/remote/activitypub/renderer/block.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { Blocking } from "@/models/entities/blocking.js"; /** diff --git a/packages/backend/src/remote/activitypub/renderer/create.ts b/packages/backend/src/remote/activitypub/renderer/create.ts index 857f5722cc..89b14b88b2 100644 --- a/packages/backend/src/remote/activitypub/renderer/create.ts +++ b/packages/backend/src/remote/activitypub/renderer/create.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { Note } from "@/models/entities/note.js"; export default (object: any, note: Note) => { diff --git a/packages/backend/src/remote/activitypub/renderer/delete.ts b/packages/backend/src/remote/activitypub/renderer/delete.ts index 70bdc34922..0d2105941e 100644 --- a/packages/backend/src/remote/activitypub/renderer/delete.ts +++ b/packages/backend/src/remote/activitypub/renderer/delete.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { User } from "@/models/entities/user.js"; export default (object: any, user: { id: User["id"]; host: null }) => ({ diff --git a/packages/backend/src/remote/activitypub/renderer/emoji.ts b/packages/backend/src/remote/activitypub/renderer/emoji.ts index 3d9b8cd55b..dab0e8cac7 100644 --- a/packages/backend/src/remote/activitypub/renderer/emoji.ts +++ b/packages/backend/src/remote/activitypub/renderer/emoji.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { Emoji } from "@/models/entities/emoji.js"; export default (emoji: Emoji) => ({ diff --git a/packages/backend/src/remote/activitypub/renderer/flag.ts b/packages/backend/src/remote/activitypub/renderer/flag.ts index 44da33f5c2..1fa260be5e 100644 --- a/packages/backend/src/remote/activitypub/renderer/flag.ts +++ b/packages/backend/src/remote/activitypub/renderer/flag.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { ILocalUser } from "@/models/entities/user.js"; // to anonymise reporters, the reporting actor must be a system user diff --git a/packages/backend/src/remote/activitypub/renderer/follow-relay.ts b/packages/backend/src/remote/activitypub/renderer/follow-relay.ts index ad7f05bf84..b62d9c4011 100644 --- a/packages/backend/src/remote/activitypub/renderer/follow-relay.ts +++ b/packages/backend/src/remote/activitypub/renderer/follow-relay.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { Relay } from "@/models/entities/relay.js"; import type { ILocalUser } from "@/models/entities/user.js"; diff --git a/packages/backend/src/remote/activitypub/renderer/follow-user.ts b/packages/backend/src/remote/activitypub/renderer/follow-user.ts index 22ee429ff6..93228a6327 100644 --- a/packages/backend/src/remote/activitypub/renderer/follow-user.ts +++ b/packages/backend/src/remote/activitypub/renderer/follow-user.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { Users } from "@/models/index.js"; import type { User } from "@/models/entities/user.js"; diff --git a/packages/backend/src/remote/activitypub/renderer/follow.ts b/packages/backend/src/remote/activitypub/renderer/follow.ts index 3ff89c12aa..30ad799507 100644 --- a/packages/backend/src/remote/activitypub/renderer/follow.ts +++ b/packages/backend/src/remote/activitypub/renderer/follow.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { User } from "@/models/entities/user.js"; import { Users } from "@/models/index.js"; diff --git a/packages/backend/src/remote/activitypub/renderer/hashtag.ts b/packages/backend/src/remote/activitypub/renderer/hashtag.ts index a00cd1ff5e..ab6651f55d 100644 --- a/packages/backend/src/remote/activitypub/renderer/hashtag.ts +++ b/packages/backend/src/remote/activitypub/renderer/hashtag.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; export default (tag: string) => ({ type: "Hashtag", diff --git a/packages/backend/src/remote/activitypub/renderer/index.ts b/packages/backend/src/remote/activitypub/renderer/index.ts index 2b6229b3e4..a085443d23 100644 --- a/packages/backend/src/remote/activitypub/renderer/index.ts +++ b/packages/backend/src/remote/activitypub/renderer/index.ts @@ -1,5 +1,5 @@ import { v4 as uuid } from "uuid"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { getUserKeypair } from "@/misc/keypair-store.js"; import type { User } from "@/models/entities/user.js"; import { LdSignature } from "../misc/ld-signature.js"; diff --git a/packages/backend/src/remote/activitypub/renderer/key.ts b/packages/backend/src/remote/activitypub/renderer/key.ts index 084bb5361a..1e01640e59 100644 --- a/packages/backend/src/remote/activitypub/renderer/key.ts +++ b/packages/backend/src/remote/activitypub/renderer/key.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { ILocalUser } from "@/models/entities/user.js"; import type { UserKeypair } from "@/models/entities/user-keypair.js"; import { createPublicKey } from "node:crypto"; diff --git a/packages/backend/src/remote/activitypub/renderer/like.ts b/packages/backend/src/remote/activitypub/renderer/like.ts index 6f810cd201..ea0df3e359 100644 --- a/packages/backend/src/remote/activitypub/renderer/like.ts +++ b/packages/backend/src/remote/activitypub/renderer/like.ts @@ -1,5 +1,5 @@ import { IsNull } from "typeorm"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { NoteReaction } from "@/models/entities/note-reaction.js"; import type { Note } from "@/models/entities/note.js"; import { Emojis } from "@/models/index.js"; diff --git a/packages/backend/src/remote/activitypub/renderer/mention.ts b/packages/backend/src/remote/activitypub/renderer/mention.ts index e7f0435c16..c935c7d325 100644 --- a/packages/backend/src/remote/activitypub/renderer/mention.ts +++ b/packages/backend/src/remote/activitypub/renderer/mention.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { User, ILocalUser } from "@/models/entities/user.js"; import { Users } from "@/models/index.js"; diff --git a/packages/backend/src/remote/activitypub/renderer/note.ts b/packages/backend/src/remote/activitypub/renderer/note.ts index f1344c1b03..dc978f1e0e 100644 --- a/packages/backend/src/remote/activitypub/renderer/note.ts +++ b/packages/backend/src/remote/activitypub/renderer/note.ts @@ -1,5 +1,5 @@ import { In, IsNull } from "typeorm"; -import config from "@/config/index.js"; +import { config } from "@/config.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"; diff --git a/packages/backend/src/remote/activitypub/renderer/person.ts b/packages/backend/src/remote/activitypub/renderer/person.ts index bba963d72e..c6371440b4 100644 --- a/packages/backend/src/remote/activitypub/renderer/person.ts +++ b/packages/backend/src/remote/activitypub/renderer/person.ts @@ -1,6 +1,6 @@ import { URL } from "node:url"; import * as mfm from "mfm-js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { ILocalUser } from "@/models/entities/user.js"; import { DriveFiles, UserProfiles } from "@/models/index.js"; import { getUserKeypair } from "@/misc/keypair-store.js"; diff --git a/packages/backend/src/remote/activitypub/renderer/question.ts b/packages/backend/src/remote/activitypub/renderer/question.ts index cb89aa7583..ac62734395 100644 --- a/packages/backend/src/remote/activitypub/renderer/question.ts +++ b/packages/backend/src/remote/activitypub/renderer/question.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { User } from "@/models/entities/user.js"; import type { Note } from "@/models/entities/note.js"; import type { Poll } from "@/models/entities/poll.js"; diff --git a/packages/backend/src/remote/activitypub/renderer/read.ts b/packages/backend/src/remote/activitypub/renderer/read.ts index 212e7e8ddf..9ea15b10f7 100644 --- a/packages/backend/src/remote/activitypub/renderer/read.ts +++ b/packages/backend/src/remote/activitypub/renderer/read.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { User } from "@/models/entities/user.js"; import type { MessagingMessage } from "@/models/entities/messaging-message.js"; diff --git a/packages/backend/src/remote/activitypub/renderer/reject.ts b/packages/backend/src/remote/activitypub/renderer/reject.ts index 7ac4452411..75c3b9d065 100644 --- a/packages/backend/src/remote/activitypub/renderer/reject.ts +++ b/packages/backend/src/remote/activitypub/renderer/reject.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { User } from "@/models/entities/user.js"; export default (object: any, user: { id: User["id"] }) => ({ diff --git a/packages/backend/src/remote/activitypub/renderer/remove.ts b/packages/backend/src/remote/activitypub/renderer/remove.ts index e3b3fef856..270744dd30 100644 --- a/packages/backend/src/remote/activitypub/renderer/remove.ts +++ b/packages/backend/src/remote/activitypub/renderer/remove.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { User } from "@/models/entities/user.js"; export default (user: { id: User["id"] }, target: any, object: any) => ({ diff --git a/packages/backend/src/remote/activitypub/renderer/undo.ts b/packages/backend/src/remote/activitypub/renderer/undo.ts index 4394c4bf2f..a0285ea9c7 100644 --- a/packages/backend/src/remote/activitypub/renderer/undo.ts +++ b/packages/backend/src/remote/activitypub/renderer/undo.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { User } from "@/models/entities/user.js"; export default (object: any, user: { id: User["id"] }) => { diff --git a/packages/backend/src/remote/activitypub/renderer/update.ts b/packages/backend/src/remote/activitypub/renderer/update.ts index ecb0ed2192..b47f7c5cda 100644 --- a/packages/backend/src/remote/activitypub/renderer/update.ts +++ b/packages/backend/src/remote/activitypub/renderer/update.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { User } from "@/models/entities/user.js"; export default (object: any, user: { id: User["id"] }) => { diff --git a/packages/backend/src/remote/activitypub/renderer/vote.ts b/packages/backend/src/remote/activitypub/renderer/vote.ts index 21234a112d..118e6761ab 100644 --- a/packages/backend/src/remote/activitypub/renderer/vote.ts +++ b/packages/backend/src/remote/activitypub/renderer/vote.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { Note } from "@/models/entities/note.js"; import type { IRemoteUser, User } from "@/models/entities/user.js"; import type { PollVote } from "@/models/entities/poll-vote.js"; diff --git a/packages/backend/src/remote/activitypub/request.ts b/packages/backend/src/remote/activitypub/request.ts index f6d33b8549..8e3bc764d3 100644 --- a/packages/backend/src/remote/activitypub/request.ts +++ b/packages/backend/src/remote/activitypub/request.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { getUserKeypair } from "@/misc/keypair-store.js"; import type { User, ILocalUser } from "@/models/entities/user.js"; import { StatusError, getResponse } from "@/misc/fetch.js"; diff --git a/packages/backend/src/remote/activitypub/resolver.ts b/packages/backend/src/remote/activitypub/resolver.ts index 79b7962b72..65e6f1d635 100644 --- a/packages/backend/src/remote/activitypub/resolver.ts +++ b/packages/backend/src/remote/activitypub/resolver.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { ILocalUser } from "@/models/entities/user.js"; import { getInstanceActor } from "@/services/instance-actor.js"; import { fetchMeta } from "backend-rs"; diff --git a/packages/backend/src/remote/resolve-user.ts b/packages/backend/src/remote/resolve-user.ts index 0883386371..69a99c767a 100644 --- a/packages/backend/src/remote/resolve-user.ts +++ b/packages/backend/src/remote/resolve-user.ts @@ -1,7 +1,7 @@ import { URL } from "node:url"; import chalk from "chalk"; import { IsNull } from "typeorm"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { User, IRemoteUser } from "@/models/entities/user.js"; import { Users } from "@/models/index.js"; import { toPuny } from "backend-rs"; diff --git a/packages/backend/src/server/activitypub.ts b/packages/backend/src/server/activitypub.ts index 00c8a6babe..2de7ab1827 100644 --- a/packages/backend/src/server/activitypub.ts +++ b/packages/backend/src/server/activitypub.ts @@ -31,7 +31,7 @@ import Following from "./activitypub/following.js"; import Followers from "./activitypub/followers.js"; import Outbox, { packActivity } from "./activitypub/outbox.js"; import { serverLogger } from "./index.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import Koa from "koa"; import * as crypto from "node:crypto"; import { inspect } from "node:util"; diff --git a/packages/backend/src/server/activitypub/featured.ts b/packages/backend/src/server/activitypub/featured.ts index e7ea6f238e..671c7ac67e 100644 --- a/packages/backend/src/server/activitypub/featured.ts +++ b/packages/backend/src/server/activitypub/featured.ts @@ -1,5 +1,5 @@ import { IsNull } from "typeorm"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { renderActivity } from "@/remote/activitypub/renderer/index.js"; import renderOrderedCollection from "@/remote/activitypub/renderer/ordered-collection.js"; import renderNote from "@/remote/activitypub/renderer/note.js"; diff --git a/packages/backend/src/server/activitypub/followers.ts b/packages/backend/src/server/activitypub/followers.ts index 576a672d6d..603e93ebe8 100644 --- a/packages/backend/src/server/activitypub/followers.ts +++ b/packages/backend/src/server/activitypub/followers.ts @@ -1,5 +1,5 @@ import { IsNull, LessThan } from "typeorm"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import * as url from "@/prelude/url.js"; import { renderActivity } from "@/remote/activitypub/renderer/index.js"; import renderOrderedCollection from "@/remote/activitypub/renderer/ordered-collection.js"; diff --git a/packages/backend/src/server/activitypub/following.ts b/packages/backend/src/server/activitypub/following.ts index 76b4e79716..be5a4e9643 100644 --- a/packages/backend/src/server/activitypub/following.ts +++ b/packages/backend/src/server/activitypub/following.ts @@ -1,5 +1,5 @@ import { LessThan, IsNull } from "typeorm"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import * as url from "@/prelude/url.js"; import { renderActivity } from "@/remote/activitypub/renderer/index.js"; import renderOrderedCollection from "@/remote/activitypub/renderer/ordered-collection.js"; diff --git a/packages/backend/src/server/activitypub/outbox.ts b/packages/backend/src/server/activitypub/outbox.ts index 305102cf12..06319565e5 100644 --- a/packages/backend/src/server/activitypub/outbox.ts +++ b/packages/backend/src/server/activitypub/outbox.ts @@ -1,5 +1,5 @@ import { Brackets, IsNull } from "typeorm"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { renderActivity } from "@/remote/activitypub/renderer/index.js"; import renderOrderedCollection from "@/remote/activitypub/renderer/ordered-collection.js"; import renderOrderedCollectionPage from "@/remote/activitypub/renderer/ordered-collection-page.js"; diff --git a/packages/backend/src/server/api/2fa.ts b/packages/backend/src/server/api/2fa.ts index 7318f0f433..5a6479939d 100644 --- a/packages/backend/src/server/api/2fa.ts +++ b/packages/backend/src/server/api/2fa.ts @@ -1,6 +1,6 @@ import * as crypto from "node:crypto"; import * as jsrsasign from "jsrsasign"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; const ECC_PRELUDE = Buffer.from([0x04]); const NULL_BYTE = Buffer.from([0]); diff --git a/packages/backend/src/server/api/common/signin.ts b/packages/backend/src/server/api/common/signin.ts index e59a39ac41..e5ca09df95 100644 --- a/packages/backend/src/server/api/common/signin.ts +++ b/packages/backend/src/server/api/common/signin.ts @@ -1,6 +1,6 @@ import type Koa from "koa"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { ILocalUser } from "@/models/entities/user.js"; import { Signins } from "@/models/index.js"; import { genId } from "backend-rs"; diff --git a/packages/backend/src/server/api/common/signup.ts b/packages/backend/src/server/api/common/signup.ts index 58b88b7d02..40b59c8ed5 100644 --- a/packages/backend/src/server/api/common/signup.ts +++ b/packages/backend/src/server/api/common/signup.ts @@ -8,7 +8,7 @@ import { genId, hashPassword, toPuny } from "backend-rs"; import { UserKeypair } from "@/models/entities/user-keypair.js"; import { UsedUsername } from "@/models/entities/used-username.js"; import { db } from "@/db/postgre.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; export async function signup(opts: { username: User["username"]; diff --git a/packages/backend/src/server/api/endpoints/admin/accounts/hosted.ts b/packages/backend/src/server/api/endpoints/admin/accounts/hosted.ts index fd4ad9401a..01d08f7a3d 100644 --- a/packages/backend/src/server/api/endpoints/admin/accounts/hosted.ts +++ b/packages/backend/src/server/api/endpoints/admin/accounts/hosted.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { Meta } from "@/models/entities/meta.js"; import { insertModerationLog } from "@/services/insert-moderation-log.js"; import { db } from "@/db/postgre.js"; diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts index c7731c6c81..d0e639fcf1 100644 --- a/packages/backend/src/server/api/endpoints/admin/meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/meta.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { fetchMeta } from "backend-rs"; import { MAX_NOTE_TEXT_LENGTH, MAX_CAPTION_TEXT_LENGTH } from "@/const.js"; import define from "@/server/api/define.js"; diff --git a/packages/backend/src/server/api/endpoints/auth/session/generate.ts b/packages/backend/src/server/api/endpoints/auth/session/generate.ts index 26a1fddfcb..f20219aa82 100644 --- a/packages/backend/src/server/api/endpoints/auth/session/generate.ts +++ b/packages/backend/src/server/api/endpoints/auth/session/generate.ts @@ -1,5 +1,5 @@ import { v4 as uuid } from "uuid"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import define from "@/server/api/define.js"; import { ApiError } from "@/server/api/error.js"; import { Apps, AuthSessions } from "@/models/index.js"; diff --git a/packages/backend/src/server/api/endpoints/fetch-rss.ts b/packages/backend/src/server/api/endpoints/fetch-rss.ts index bda3c455d1..489aaab0f5 100644 --- a/packages/backend/src/server/api/endpoints/fetch-rss.ts +++ b/packages/backend/src/server/api/endpoints/fetch-rss.ts @@ -1,6 +1,6 @@ import Parser from "rss-parser"; import { getResponse } from "@/misc/fetch.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import define from "@/server/api/define.js"; const rssParser = new Parser(); diff --git a/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts b/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts index 6c99217e7d..0951369dd8 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts @@ -6,7 +6,7 @@ import { AttestationChallenges, Users, } from "@/models/index.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { procedures, hash } from "@/server/api/2fa.js"; import { publishMainStream } from "@/services/stream.js"; import { verifyPassword } from "backend-rs"; diff --git a/packages/backend/src/server/api/endpoints/i/2fa/register.ts b/packages/backend/src/server/api/endpoints/i/2fa/register.ts index c0e6137d5d..eb926a6098 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/register.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/register.ts @@ -1,6 +1,6 @@ import * as OTPAuth from "otpauth"; import * as QRCode from "qrcode"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { UserProfiles } from "@/models/index.js"; import define from "@/server/api/define.js"; import { verifyPassword } from "backend-rs"; diff --git a/packages/backend/src/server/api/endpoints/i/move.ts b/packages/backend/src/server/api/endpoints/i/move.ts index 4784d3ee20..381bb1dea9 100644 --- a/packages/backend/src/server/api/endpoints/i/move.ts +++ b/packages/backend/src/server/api/endpoints/i/move.ts @@ -10,7 +10,7 @@ import deleteFollowing from "@/services/following/delete.js"; import create from "@/services/following/create.js"; import { getUser } from "@/server/api/common/getters.js"; import { Followings, Users } from "@/models/index.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { publishMainStream } from "@/services/stream.js"; import { stringToAcct } from "backend-rs"; import { inspect } from "node:util"; diff --git a/packages/backend/src/server/api/endpoints/i/update-email.ts b/packages/backend/src/server/api/endpoints/i/update-email.ts index 234127f584..185d1c8dc9 100644 --- a/packages/backend/src/server/api/endpoints/i/update-email.ts +++ b/packages/backend/src/server/api/endpoints/i/update-email.ts @@ -1,7 +1,7 @@ import { publishMainStream } from "@/services/stream.js"; import define from "@/server/api/define.js"; import rndstr from "rndstr"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { Users, UserProfiles } from "@/models/index.js"; import { sendEmail } from "@/services/send-email.js"; import { ApiError } from "@/server/api/error.js"; diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts index 31677ee2ef..0167377944 100644 --- a/packages/backend/src/server/api/endpoints/meta.ts +++ b/packages/backend/src/server/api/endpoints/meta.ts @@ -1,6 +1,6 @@ import JSON5 from "json5"; import { IsNull, MoreThan } from "typeorm"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { fetchMeta } from "backend-rs"; import { Ads, Emojis, Users } from "@/models/index.js"; import { MAX_NOTE_TEXT_LENGTH, MAX_CAPTION_TEXT_LENGTH } from "@/const.js"; diff --git a/packages/backend/src/server/api/endpoints/request-reset-password.ts b/packages/backend/src/server/api/endpoints/request-reset-password.ts index 9855b06513..00936c9d22 100644 --- a/packages/backend/src/server/api/endpoints/request-reset-password.ts +++ b/packages/backend/src/server/api/endpoints/request-reset-password.ts @@ -1,6 +1,6 @@ import rndstr from "rndstr"; import { IsNull } from "typeorm"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { Users, UserProfiles, PasswordResetRequests } from "@/models/index.js"; import { sendEmail } from "@/services/send-email.js"; import { genId } from "backend-rs"; diff --git a/packages/backend/src/server/api/endpoints/username/available.ts b/packages/backend/src/server/api/endpoints/username/available.ts index cd634a798a..3818a3c28f 100644 --- a/packages/backend/src/server/api/endpoints/username/available.ts +++ b/packages/backend/src/server/api/endpoints/username/available.ts @@ -1,6 +1,6 @@ import { IsNull } from "typeorm"; import { Users, UsedUsernames } from "@/models/index.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import define from "@/server/api/define.js"; export const meta = { diff --git a/packages/backend/src/server/api/index.ts b/packages/backend/src/server/api/index.ts index 493661b2a2..7e5cd892bc 100644 --- a/packages/backend/src/server/api/index.ts +++ b/packages/backend/src/server/api/index.ts @@ -12,7 +12,7 @@ import { getClient, } from "./mastodon/ApiMastodonCompatibleService.js"; import { AccessTokens, Users } from "@/models/index.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import endpoints from "./endpoints.js"; import compatibility from "./compatibility.js"; import handler from "./api-handler.js"; diff --git a/packages/backend/src/server/api/mastodon/endpoints/meta.ts b/packages/backend/src/server/api/mastodon/endpoints/meta.ts index 5c304929a1..862310fb3e 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/meta.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/meta.ts @@ -1,5 +1,5 @@ import { Entity } from "megalodon"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { fetchMeta } from "backend-rs"; import { Users, Notes } from "@/models/index.js"; import { IsNull } from "typeorm"; diff --git a/packages/backend/src/server/api/openapi/gen-spec.ts b/packages/backend/src/server/api/openapi/gen-spec.ts index 8b2f92b745..79dc48a8bb 100644 --- a/packages/backend/src/server/api/openapi/gen-spec.ts +++ b/packages/backend/src/server/api/openapi/gen-spec.ts @@ -1,5 +1,5 @@ import endpoints from "@/server/api/endpoints.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { errors as basicErrors } from "./errors.js"; import { schemas, convertSchemaToOpenApiSchema } from "./schemas.js"; diff --git a/packages/backend/src/server/api/private/signin.ts b/packages/backend/src/server/api/private/signin.ts index a7eb623062..d8bbbf74ad 100644 --- a/packages/backend/src/server/api/private/signin.ts +++ b/packages/backend/src/server/api/private/signin.ts @@ -1,7 +1,7 @@ import type Koa from "koa"; import * as OTPAuth from "otpauth"; import signin from "@/server/api/common/signin.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { Users, Signins, diff --git a/packages/backend/src/server/api/private/signup.ts b/packages/backend/src/server/api/private/signup.ts index 5af5d65b50..4dd4ffb231 100644 --- a/packages/backend/src/server/api/private/signup.ts +++ b/packages/backend/src/server/api/private/signup.ts @@ -3,7 +3,7 @@ import rndstr from "rndstr"; import { verifyHcaptcha, verifyRecaptcha } from "@/misc/captcha.js"; import { Users, RegistrationTickets, UserPendings } from "@/models/index.js"; import { signup } from "@/server/api/common/signup.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { sendEmail } from "@/services/send-email.js"; import { fetchMeta, genId, hashPassword } from "backend-rs"; import { validateEmailForAccount } from "@/services/validate-email-for-account.js"; diff --git a/packages/backend/src/server/index.ts b/packages/backend/src/server/index.ts index 17358a4758..54d6e8bf5f 100644 --- a/packages/backend/src/server/index.ts +++ b/packages/backend/src/server/index.ts @@ -13,7 +13,7 @@ import koaLogger from "koa-logger"; import * as slow from "koa-slow"; import { IsNull } from "typeorm"; -import config, { envOption } from "@/config/index.js"; +import { config, envOption } from "@/config.js"; import Logger from "@/services/logger.js"; import { Users } from "@/models/index.js"; import { fetchMeta } from "backend-rs"; diff --git a/packages/backend/src/server/nodeinfo.ts b/packages/backend/src/server/nodeinfo.ts index 7359878b19..91e5fd8034 100644 --- a/packages/backend/src/server/nodeinfo.ts +++ b/packages/backend/src/server/nodeinfo.ts @@ -1,5 +1,5 @@ import Router from "@koa/router"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { fetchMeta } from "backend-rs"; import { Users, Notes } from "@/models/index.js"; import { IsNull, MoreThan } from "typeorm"; diff --git a/packages/backend/src/server/web/feed.ts b/packages/backend/src/server/web/feed.ts index e6b09b4f4f..5208ee70e4 100644 --- a/packages/backend/src/server/web/feed.ts +++ b/packages/backend/src/server/web/feed.ts @@ -1,6 +1,6 @@ import { Feed } from "feed"; import { In, IsNull } from "typeorm"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { User } from "@/models/entities/user.js"; import { Notes, DriveFiles, UserProfiles, Users } from "@/models/index.js"; diff --git a/packages/backend/src/server/web/index.ts b/packages/backend/src/server/web/index.ts index 939fcfab14..dfc1cdc475 100644 --- a/packages/backend/src/server/web/index.ts +++ b/packages/backend/src/server/web/index.ts @@ -16,7 +16,7 @@ import { KoaAdapter } from "@bull-board/koa"; import { In, IsNull } from "typeorm"; import { fetchMeta, metaToPugArgs } from "backend-rs"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { Users, Notes, diff --git a/packages/backend/src/server/web/manifest.ts b/packages/backend/src/server/web/manifest.ts index a4c615c7ab..77c8a57cf4 100644 --- a/packages/backend/src/server/web/manifest.ts +++ b/packages/backend/src/server/web/manifest.ts @@ -1,6 +1,6 @@ import type Koa from "koa"; import { fetchMeta } from "backend-rs"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import manifest from "./manifest.json" assert { type: "json" }; export const manifestHandler = async (ctx: Koa.Context) => { diff --git a/packages/backend/src/server/web/url-preview.ts b/packages/backend/src/server/web/url-preview.ts index f59f3f357a..8fd757ef14 100644 --- a/packages/backend/src/server/web/url-preview.ts +++ b/packages/backend/src/server/web/url-preview.ts @@ -2,7 +2,7 @@ import type Koa from "koa"; import summaly from "summaly"; import { fetchMeta } from "backend-rs"; import Logger from "@/services/logger.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { query } from "@/prelude/url.js"; import { getJson } from "@/misc/fetch.js"; import { inspect } from "node:util"; diff --git a/packages/backend/src/server/well-known.ts b/packages/backend/src/server/well-known.ts index fc339eaad6..4a244db57f 100644 --- a/packages/backend/src/server/well-known.ts +++ b/packages/backend/src/server/well-known.ts @@ -1,6 +1,6 @@ import Router from "@koa/router"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { type Acct, stringToAcct } from "backend-rs"; import { links } from "./nodeinfo.js"; import { escapeAttribute, escapeValue } from "@/prelude/xml.js"; diff --git a/packages/backend/src/services/drive/internal-storage.ts b/packages/backend/src/services/drive/internal-storage.ts index b2a663b3ea..6413f7920e 100644 --- a/packages/backend/src/services/drive/internal-storage.ts +++ b/packages/backend/src/services/drive/internal-storage.ts @@ -3,7 +3,7 @@ import * as fsPromises from "node:fs/promises"; import * as Path from "node:path"; import { fileURLToPath } from "node:url"; import { dirname } from "node:path"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; const _filename = fileURLToPath(import.meta.url); const _dirname = dirname(_filename); diff --git a/packages/backend/src/services/fetch-rel-me.ts b/packages/backend/src/services/fetch-rel-me.ts index c9a37d1c88..e9736f8c33 100644 --- a/packages/backend/src/services/fetch-rel-me.ts +++ b/packages/backend/src/services/fetch-rel-me.ts @@ -1,5 +1,5 @@ import { Window } from "happy-dom"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; async function getRelMeLinks(url: string): Promise { try { diff --git a/packages/backend/src/services/following/requests/create.ts b/packages/backend/src/services/following/requests/create.ts index d2f2c1ca41..146e20efd9 100644 --- a/packages/backend/src/services/following/requests/create.ts +++ b/packages/backend/src/services/following/requests/create.ts @@ -6,7 +6,7 @@ import type { User } from "@/models/entities/user.js"; import { Blockings, FollowRequests, Users } from "@/models/index.js"; import { genId } from "backend-rs"; import { createNotification } from "@/services/create-notification.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; export default async function ( follower: { diff --git a/packages/backend/src/services/i/pin.ts b/packages/backend/src/services/i/pin.ts index 2d2675a535..b44ba5f9fa 100644 --- a/packages/backend/src/services/i/pin.ts +++ b/packages/backend/src/services/i/pin.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import renderAdd from "@/remote/activitypub/renderer/add.js"; import renderRemove from "@/remote/activitypub/renderer/remove.js"; import { renderActivity } from "@/remote/activitypub/renderer/index.js"; diff --git a/packages/backend/src/services/logger.ts b/packages/backend/src/services/logger.ts index e53279e31c..bd2ca74793 100644 --- a/packages/backend/src/services/logger.ts +++ b/packages/backend/src/services/logger.ts @@ -2,7 +2,7 @@ import cluster from "node:cluster"; import chalk from "chalk"; import { default as convertColor } from "color-convert"; import { format as dateFormat } from "date-fns"; -import config, { envOption } from "@/config/index.js"; +import { config, envOption } from "@/config.js"; import * as SyslogPro from "syslog-pro"; diff --git a/packages/backend/src/services/messages/delete.ts b/packages/backend/src/services/messages/delete.ts index 77caba80ce..2d8f6b9baf 100644 --- a/packages/backend/src/services/messages/delete.ts +++ b/packages/backend/src/services/messages/delete.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { MessagingMessages, Users } from "@/models/index.js"; import type { MessagingMessage } from "@/models/entities/messaging-message.js"; import { diff --git a/packages/backend/src/services/note/create.ts b/packages/backend/src/services/note/create.ts index 0a4ddc517f..662064da57 100644 --- a/packages/backend/src/services/note/create.ts +++ b/packages/backend/src/services/note/create.ts @@ -10,7 +10,7 @@ import renderCreate from "@/remote/activitypub/renderer/create.js"; import renderAnnounce from "@/remote/activitypub/renderer/announce.js"; import { renderActivity } from "@/remote/activitypub/renderer/index.js"; import { resolveUser } from "@/remote/resolve-user.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { updateHashtags } from "@/services/update-hashtag.js"; import { concat } from "@/prelude/array.js"; import { insertNoteUnread } from "@/services/note/unread.js"; diff --git a/packages/backend/src/services/note/delete.ts b/packages/backend/src/services/note/delete.ts index be3bf1e8b2..c709792fef 100644 --- a/packages/backend/src/services/note/delete.ts +++ b/packages/backend/src/services/note/delete.ts @@ -5,7 +5,7 @@ import renderAnnounce from "@/remote/activitypub/renderer/announce.js"; import renderUndo from "@/remote/activitypub/renderer/undo.js"; import { renderActivity } from "@/remote/activitypub/renderer/index.js"; import renderTombstone from "@/remote/activitypub/renderer/tombstone.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { User, ILocalUser, IRemoteUser } from "@/models/entities/user.js"; import type { Note, IMentionedRemoteUsers } from "@/models/entities/note.js"; import { Notes, Users, Instances } from "@/models/index.js"; diff --git a/packages/backend/src/services/push-notification.ts b/packages/backend/src/services/push-notification.ts index 3f1f2cfb1a..86dd2a32e2 100644 --- a/packages/backend/src/services/push-notification.ts +++ b/packages/backend/src/services/push-notification.ts @@ -1,5 +1,5 @@ import push from "web-push"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { SwSubscriptions } from "@/models/index.js"; import { fetchMeta, getNoteSummary } from "backend-rs"; import type { Packed } from "@/misc/schema.js"; diff --git a/packages/backend/src/services/send-email.ts b/packages/backend/src/services/send-email.ts index 11a899d267..bcbecce356 100644 --- a/packages/backend/src/services/send-email.ts +++ b/packages/backend/src/services/send-email.ts @@ -1,7 +1,7 @@ import * as nodemailer from "nodemailer"; import { fetchMeta } from "backend-rs"; import Logger from "@/services/logger.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { inspect } from "node:util"; export const logger = new Logger("email"); diff --git a/packages/backend/src/services/stream.ts b/packages/backend/src/services/stream.ts index bd09bc3f2c..0e2395e87e 100644 --- a/packages/backend/src/services/stream.ts +++ b/packages/backend/src/services/stream.ts @@ -3,7 +3,7 @@ import type { User } from "@/models/entities/user.js"; import type { Note } from "@/models/entities/note.js"; import type { UserList } from "@/models/entities/user-list.js"; import type { UserGroup } from "@/models/entities/user-group.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { Antenna } from "@/models/entities/antenna.js"; import type { Channel } from "@/models/entities/channel.js"; import type { diff --git a/packages/backend/src/services/suspend-user.ts b/packages/backend/src/services/suspend-user.ts index f72b8ffcb1..0babd31bc5 100644 --- a/packages/backend/src/services/suspend-user.ts +++ b/packages/backend/src/services/suspend-user.ts @@ -1,7 +1,7 @@ import renderDelete from "@/remote/activitypub/renderer/delete.js"; import { renderActivity } from "@/remote/activitypub/renderer/index.js"; import { deliver } from "@/queue/index.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { User } from "@/models/entities/user.js"; import { Users, Followings } from "@/models/index.js"; import { Not, IsNull } from "typeorm"; diff --git a/packages/backend/src/services/unsuspend-user.ts b/packages/backend/src/services/unsuspend-user.ts index 69447a4a26..72d7e30d66 100644 --- a/packages/backend/src/services/unsuspend-user.ts +++ b/packages/backend/src/services/unsuspend-user.ts @@ -2,7 +2,7 @@ import renderDelete from "@/remote/activitypub/renderer/delete.js"; import renderUndo from "@/remote/activitypub/renderer/undo.js"; import { renderActivity } from "@/remote/activitypub/renderer/index.js"; import { deliver } from "@/queue/index.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { User } from "@/models/entities/user.js"; import { Users, Followings } from "@/models/index.js"; import { Not, IsNull } from "typeorm"; From e60898b4b056726aff09d120b055d3205bbcb3b6 Mon Sep 17 00:00:00 2001 From: naskya Date: Sat, 20 Apr 2024 02:11:41 +0900 Subject: [PATCH 18/99] refactor (backend-rs): separate postgresql connector from database/mod.rs --- packages/backend-rs/src/database/mod.rs | 36 ++----------------- .../backend-rs/src/database/postgresql.rs | 34 ++++++++++++++++++ 2 files changed, 36 insertions(+), 34 deletions(-) create mode 100644 packages/backend-rs/src/database/postgresql.rs diff --git a/packages/backend-rs/src/database/mod.rs b/packages/backend-rs/src/database/mod.rs index a60d20af9c..26db81c644 100644 --- a/packages/backend-rs/src/database/mod.rs +++ b/packages/backend-rs/src/database/mod.rs @@ -1,34 +1,2 @@ -use crate::config::server::CONFIG; -use sea_orm::{Database, DbConn, DbErr}; - -static DB_CONN: once_cell::sync::OnceCell = once_cell::sync::OnceCell::new(); - -async fn init_database() -> Result<&'static DbConn, DbErr> { - let database_uri = format!( - "postgres://{}:{}@{}:{}/{}", - CONFIG.db.user, - urlencoding::encode(&CONFIG.db.pass), - CONFIG.db.host, - CONFIG.db.port, - CONFIG.db.db, - ); - let conn = Database::connect(database_uri).await?; - Ok(DB_CONN.get_or_init(move || conn)) -} - -pub async fn db_conn() -> Result<&'static DbConn, DbErr> { - match DB_CONN.get() { - Some(conn) => Ok(conn), - None => init_database().await, - } -} - -#[cfg(test)] -mod unit_test { - use super::db_conn; - - #[tokio::test] - async fn connect_test() { - assert!(db_conn().await.is_ok()); - } -} +pub use postgresql::db_conn; +pub mod postgresql; diff --git a/packages/backend-rs/src/database/postgresql.rs b/packages/backend-rs/src/database/postgresql.rs new file mode 100644 index 0000000000..a60d20af9c --- /dev/null +++ b/packages/backend-rs/src/database/postgresql.rs @@ -0,0 +1,34 @@ +use crate::config::server::CONFIG; +use sea_orm::{Database, DbConn, DbErr}; + +static DB_CONN: once_cell::sync::OnceCell = once_cell::sync::OnceCell::new(); + +async fn init_database() -> Result<&'static DbConn, DbErr> { + let database_uri = format!( + "postgres://{}:{}@{}:{}/{}", + CONFIG.db.user, + urlencoding::encode(&CONFIG.db.pass), + CONFIG.db.host, + CONFIG.db.port, + CONFIG.db.db, + ); + let conn = Database::connect(database_uri).await?; + Ok(DB_CONN.get_or_init(move || conn)) +} + +pub async fn db_conn() -> Result<&'static DbConn, DbErr> { + match DB_CONN.get() { + Some(conn) => Ok(conn), + None => init_database().await, + } +} + +#[cfg(test)] +mod unit_test { + use super::db_conn; + + #[tokio::test] + async fn connect_test() { + assert!(db_conn().await.is_ok()); + } +} From e82a07c03d9c1f35ae96a51d4e3a3a2e0e16ca43 Mon Sep 17 00:00:00 2001 From: naskya Date: Sat, 20 Apr 2024 02:17:03 +0900 Subject: [PATCH 19/99] dev (backend-rs): make backend-rs accessible to Redis --- Cargo.lock | 32 +++++++++++++++ Cargo.toml | 1 + packages/backend-rs/Cargo.toml | 1 + packages/backend-rs/index.d.ts | 4 +- packages/backend-rs/src/config/server.rs | 4 +- packages/backend-rs/src/database/mod.rs | 4 ++ packages/backend-rs/src/database/redis.rs | 47 +++++++++++++++++++++++ 7 files changed, 89 insertions(+), 4 deletions(-) create mode 100644 packages/backend-rs/src/database/redis.rs diff --git a/Cargo.lock b/Cargo.lock index c6ba96e683..52ef14933f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -220,6 +220,7 @@ dependencies = [ "parse-display", "pretty_assertions", "rand", + "redis", "regex", "schemars", "sea-orm", @@ -524,6 +525,16 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "const-oid" version = "0.9.6" @@ -1858,6 +1869,21 @@ dependencies = [ "getrandom", ] +[[package]] +name = "redis" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6472825949c09872e8f2c50bde59fcefc17748b6be5c90fd67cd8b4daca73bfd" +dependencies = [ + "combine", + "itoa", + "percent-encoding", + "ryu", + "sha1_smol", + "socket2", + "url", +] + [[package]] name = "redox_syscall" version = "0.4.1" @@ -2295,6 +2321,12 @@ dependencies = [ "digest", ] +[[package]] +name = "sha1_smol" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" + [[package]] name = "sha2" version = "0.10.8" diff --git a/Cargo.toml b/Cargo.toml index 7ca43c960b..b82635d8b4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ pretty_assertions = "1.4.0" proc-macro2 = "1.0.79" quote = "1.0.36" rand = "0.8.5" +redis = "0.25.3" regex = "1.10.4" schemars = "0.8.16" sea-orm = "0.12.15" diff --git a/packages/backend-rs/Cargo.toml b/packages/backend-rs/Cargo.toml index af9e10cdc1..d077028e13 100644 --- a/packages/backend-rs/Cargo.toml +++ b/packages/backend-rs/Cargo.toml @@ -30,6 +30,7 @@ jsonschema = { workspace = true } once_cell = { workspace = true } parse-display = { workspace = true } rand = { workspace = true } +redis = { workspace = true } regex = { workspace = true } schemars = { workspace = true, features = ["chrono"] } sea-orm = { workspace = true, features = ["sqlx-postgres", "runtime-tokio-rustls"] } diff --git a/packages/backend-rs/index.d.ts b/packages/backend-rs/index.d.ts index d985eb368d..433e80999c 100644 --- a/packages/backend-rs/index.d.ts +++ b/packages/backend-rs/index.d.ts @@ -29,7 +29,7 @@ export interface ServerConfig { /** `NapiValue` is not implemented for `u64` */ maxFileSize?: number accessLog?: string - clusterLimits?: _WorkerConfig + clusterLimits?: WorkerConfigInternal cuid?: IdConfig outgoingAddress?: string deliverJobConcurrency?: number @@ -80,7 +80,7 @@ export interface WorkerConfig { web: number queue: number } -export interface WorkerConfig { +export interface WorkerConfigInternal { web?: number queue?: number } diff --git a/packages/backend-rs/src/config/server.rs b/packages/backend-rs/src/config/server.rs index 4b9fbc7131..edfdf6109c 100644 --- a/packages/backend-rs/src/config/server.rs +++ b/packages/backend-rs/src/config/server.rs @@ -25,7 +25,7 @@ struct ServerConfig { /// `NapiValue` is not implemented for `u64` pub max_file_size: Option, pub access_log: Option, - pub cluster_limits: Option<_WorkerConfig>, + pub cluster_limits: Option, pub cuid: Option, pub outgoing_address: Option, @@ -103,7 +103,7 @@ pub struct WorkerConfig { #[derive(Clone, Debug, PartialEq, Deserialize)] #[serde(rename_all = "camelCase")] #[crate::export(object, use_nullable = false)] -pub struct _WorkerConfig { +pub struct WorkerConfigInternal { pub web: Option, pub queue: Option, } diff --git a/packages/backend-rs/src/database/mod.rs b/packages/backend-rs/src/database/mod.rs index 26db81c644..7a6277068b 100644 --- a/packages/backend-rs/src/database/mod.rs +++ b/packages/backend-rs/src/database/mod.rs @@ -1,2 +1,6 @@ pub use postgresql::db_conn; +pub use redis::key as redis_key; +pub use redis::redis_conn; + pub mod postgresql; +pub mod redis; diff --git a/packages/backend-rs/src/database/redis.rs b/packages/backend-rs/src/database/redis.rs new file mode 100644 index 0000000000..863f57b35d --- /dev/null +++ b/packages/backend-rs/src/database/redis.rs @@ -0,0 +1,47 @@ +use crate::config::server::CONFIG; +use redis::{Client, Connection, RedisError}; + +static REDIS_CLIENT: once_cell::sync::OnceCell = once_cell::sync::OnceCell::new(); + +fn init_redis() -> Result { + let redis_url = { + let mut params = vec!["redis://".to_owned()]; + + if let Some(user) = &CONFIG.redis.user { + params.push(user.to_string()) + } + if let Some(pass) = &CONFIG.redis.pass { + params.push(format!(":{}@", pass)) + } + params.push(CONFIG.redis.host.to_string()); + params.push(format!(":{}", CONFIG.redis.port)); + params.push(format!("/{}", CONFIG.redis.db)); + + params.concat() + }; + + Client::open(redis_url) +} + +pub fn redis_conn() -> Result { + match REDIS_CLIENT.get() { + Some(client) => Ok(client.get_connection()?), + None => init_redis()?.get_connection(), + } +} + +#[inline] +/// prefix redis key with the hostname +pub fn key(key: &str) -> String { + format!("{}:{}", CONFIG.hostname, key) +} + +#[cfg(test)] +mod unit_test { + use super::init_redis; + + #[test] + fn connect_test() { + assert!(init_redis().is_ok()); + } +} From 037b7950a264123396982dd9dfeaa0f31d1c336b Mon Sep 17 00:00:00 2001 From: naskya Date: Sat, 20 Apr 2024 02:58:39 +0900 Subject: [PATCH 20/99] refactor (backend): clean the booting process a bit --- packages/backend/src/boot/master.ts | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/packages/backend/src/boot/master.ts b/packages/backend/src/boot/master.ts index 44c4a8a2f1..090a84f6ea 100644 --- a/packages/backend/src/boot/master.ts +++ b/packages/backend/src/boot/master.ts @@ -169,23 +169,31 @@ async function connectDb(): Promise { } async function spawnWorkers( - clusterLimits: Required, + clusterLimits: Config["clusterLimits"], ): Promise { - const modes = ["web", "queue"]; const cpus = os.cpus().length; - for (const mode of modes.filter((mode) => clusterLimits[mode] > cpus)) { + + if (clusterLimits.queue > cpus) { bootLogger.warn( - `configuration warning: cluster limit for ${mode} exceeds number of cores (${cpus})`, + "config: queue cluster limit exceeds the number of cpu cores", ); } - const total = modes.reduce((acc, mode) => acc + clusterLimits[mode], 0); + if (clusterLimits.web > cpus) { + bootLogger.warn( + "config: web cluster limit exceeds the number of cpu cores", + ); + } + + const total = clusterLimits.queue + clusterLimits.web; + + // workers = ["web", "web", ..., "web", "queue", "queue", ..., "queue"] const workers = new Array(total); - workers.fill("web", 0, clusterLimits?.web); - workers.fill("queue", clusterLimits?.web); + workers.fill("web", 0, clusterLimits.web); + workers.fill("queue", clusterLimits.web); bootLogger.info( - `Starting ${clusterLimits?.web} web workers and ${clusterLimits?.queue} queue workers (total ${total})...`, + `Starting ${clusterLimits.web} web workers and ${clusterLimits.queue} queue workers (total ${total})...`, ); await Promise.all(workers.map((mode) => spawnWorker(mode))); bootLogger.succ("All workers started"); From 56038b174d146330a6f8d367020455d5d26b67ca Mon Sep 17 00:00:00 2001 From: naskya Date: Sat, 20 Apr 2024 03:01:13 +0900 Subject: [PATCH 21/99] fix (backend): correct import path --- packages/backend/src/ormconfig.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/ormconfig.ts b/packages/backend/src/ormconfig.ts index a1891e00df..293be57cae 100644 --- a/packages/backend/src/ormconfig.ts +++ b/packages/backend/src/ormconfig.ts @@ -1,6 +1,6 @@ import { DataSource } from "typeorm"; -import config from "./config/index.js"; -import { entities } from "./db/postgre.js"; +import { config } from "@/config.js"; +import { entities } from "@/db/postgre.js"; export default new DataSource({ type: "postgres", From def62ff1cecfd36e24e48aabc3d45bc89a362d6b Mon Sep 17 00:00:00 2001 From: naskya Date: Sat, 20 Apr 2024 03:04:34 +0900 Subject: [PATCH 22/99] chore (minor, backend): remove unused import --- packages/backend/src/db/postgre.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/backend/src/db/postgre.ts b/packages/backend/src/db/postgre.ts index e0ab9d6d37..1295136054 100644 --- a/packages/backend/src/db/postgre.ts +++ b/packages/backend/src/db/postgre.ts @@ -77,7 +77,6 @@ import { NoteFile } from "@/models/entities/note-file.js"; import { entities as charts } from "@/services/chart/entities.js"; import { dbLogger } from "./logger.js"; -import { redisClient } from "./redis.js"; const sqlLogger = dbLogger.createSubLogger("sql", "gray", false); From ccb17977c36eec325517e7f5090053c07292a0db Mon Sep 17 00:00:00 2001 From: naskya Date: Sat, 20 Apr 2024 03:08:35 +0900 Subject: [PATCH 23/99] chore (minor, backend): use type import --- packages/backend/src/misc/cache.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/misc/cache.ts b/packages/backend/src/misc/cache.ts index 30a50e5714..e99b17a5f7 100644 --- a/packages/backend/src/misc/cache.ts +++ b/packages/backend/src/misc/cache.ts @@ -1,6 +1,6 @@ import { redisClient } from "@/db/redis.js"; import { encode, decode } from "msgpackr"; -import { ChainableCommander } from "ioredis"; +import type { ChainableCommander } from "ioredis"; export class Cache { private ttl: number; From b157cbe79a30d2fa10b53008c4447dc878ccc9aa Mon Sep 17 00:00:00 2001 From: naskya Date: Sat, 20 Apr 2024 04:41:47 +0900 Subject: [PATCH 24/99] chore (backend-rs): make entities serializable --- packages/backend-rs/Makefile | 4 +- .../src/model/entity/abuse_user_report.rs | 2 +- .../src/model/entity/access_token.rs | 2 +- packages/backend-rs/src/model/entity/ad.rs | 2 +- .../src/model/entity/announcement.rs | 2 +- .../src/model/entity/announcement_read.rs | 2 +- .../backend-rs/src/model/entity/antenna.rs | 2 +- .../src/model/entity/antenna_note.rs | 49 ------------------- packages/backend-rs/src/model/entity/app.rs | 2 +- .../src/model/entity/attestation_challenge.rs | 2 +- .../src/model/entity/auth_session.rs | 2 +- .../backend-rs/src/model/entity/blocking.rs | 2 +- .../backend-rs/src/model/entity/channel.rs | 2 +- .../src/model/entity/channel_following.rs | 2 +- .../src/model/entity/channel_note_pining.rs | 2 +- packages/backend-rs/src/model/entity/clip.rs | 2 +- .../backend-rs/src/model/entity/clip_note.rs | 2 +- .../backend-rs/src/model/entity/drive_file.rs | 2 +- .../src/model/entity/drive_folder.rs | 2 +- packages/backend-rs/src/model/entity/emoji.rs | 2 +- .../src/model/entity/follow_request.rs | 2 +- .../backend-rs/src/model/entity/following.rs | 2 +- .../src/model/entity/gallery_like.rs | 2 +- .../src/model/entity/gallery_post.rs | 2 +- .../backend-rs/src/model/entity/hashtag.rs | 2 +- .../backend-rs/src/model/entity/instance.rs | 2 +- .../src/model/entity/messaging_message.rs | 2 +- packages/backend-rs/src/model/entity/meta.rs | 2 +- .../backend-rs/src/model/entity/migrations.rs | 2 +- .../src/model/entity/moderation_log.rs | 2 +- .../backend-rs/src/model/entity/muted_note.rs | 2 +- .../backend-rs/src/model/entity/muting.rs | 2 +- packages/backend-rs/src/model/entity/note.rs | 2 +- .../backend-rs/src/model/entity/note_edit.rs | 2 +- .../src/model/entity/note_favorite.rs | 2 +- .../backend-rs/src/model/entity/note_file.rs | 2 +- .../src/model/entity/note_reaction.rs | 2 +- .../src/model/entity/note_thread_muting.rs | 2 +- .../src/model/entity/note_unread.rs | 2 +- .../src/model/entity/note_watching.rs | 2 +- .../src/model/entity/notification.rs | 2 +- packages/backend-rs/src/model/entity/page.rs | 2 +- .../backend-rs/src/model/entity/page_like.rs | 2 +- .../model/entity/password_reset_request.rs | 2 +- packages/backend-rs/src/model/entity/poll.rs | 2 +- .../backend-rs/src/model/entity/poll_vote.rs | 2 +- .../backend-rs/src/model/entity/promo_note.rs | 2 +- .../backend-rs/src/model/entity/promo_read.rs | 2 +- .../src/model/entity/registration_ticket.rs | 2 +- .../src/model/entity/registry_item.rs | 2 +- packages/backend-rs/src/model/entity/relay.rs | 2 +- .../src/model/entity/renote_muting.rs | 2 +- .../src/model/entity/reply_muting.rs | 2 +- .../src/model/entity/sea_orm_active_enums.rs | 20 ++++---- .../backend-rs/src/model/entity/signin.rs | 2 +- .../src/model/entity/sw_subscription.rs | 2 +- .../src/model/entity/used_username.rs | 2 +- packages/backend-rs/src/model/entity/user.rs | 2 +- .../backend-rs/src/model/entity/user_group.rs | 2 +- .../src/model/entity/user_group_invitation.rs | 2 +- .../src/model/entity/user_group_invite.rs | 2 +- .../src/model/entity/user_group_joining.rs | 2 +- .../backend-rs/src/model/entity/user_ip.rs | 2 +- .../src/model/entity/user_keypair.rs | 2 +- .../backend-rs/src/model/entity/user_list.rs | 2 +- .../src/model/entity/user_list_joining.rs | 2 +- .../src/model/entity/user_note_pining.rs | 2 +- .../src/model/entity/user_pending.rs | 2 +- .../src/model/entity/user_profile.rs | 2 +- .../src/model/entity/user_publickey.rs | 2 +- .../src/model/entity/user_security_key.rs | 2 +- .../backend-rs/src/model/entity/webhook.rs | 2 +- 72 files changed, 82 insertions(+), 129 deletions(-) delete mode 100644 packages/backend-rs/src/model/entity/antenna_note.rs diff --git a/packages/backend-rs/Makefile b/packages/backend-rs/Makefile index 11b614c82a..29a00e847d 100644 --- a/packages/backend-rs/Makefile +++ b/packages/backend-rs/Makefile @@ -6,6 +6,7 @@ SRC += $(call recursive_wildcard, src, *) .PHONY: regenerate-entities regenerate-entities: + rm --recursive --force src/model/entity sea-orm-cli generate entity \ --output-dir='src/model/entity' \ --database-url='postgres://$(POSTGRES_USER):$(POSTGRES_PASSWORD)@localhost:25432/$(POSTGRES_DB)' \ @@ -16,8 +17,9 @@ regenerate-entities: jsname=$$(printf '%s\n' "$${base%.*}" | perl -pe 's/(^|_)./uc($$&)/ge;s/_//g'); \ attribute=$$(printf 'cfg_attr(feature = "napi", napi_derive::napi(object, js_name = "%s", use_nullable = true))' "$${jsname}"); \ sed -i "s/NAPI_EXTRA_ATTR_PLACEHOLDER/$${attribute}/" "$${file}"; \ + sed -i 's/#\[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)\]/#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)]/' "$${file}"; \ done - sed -i 's/#\[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum)\]/#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)]\n#[cfg_attr(not(feature = "napi"), derive(Clone))]\n#[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))]/' \ + sed -i 's/#\[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum)\]/#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize)]\n#[cfg_attr(not(feature = "napi"), derive(Clone))]\n#[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))]/' \ src/model/entity/sea_orm_active_enums.rs cargo fmt --all -- diff --git a/packages/backend-rs/src/model/entity/abuse_user_report.rs b/packages/backend-rs/src/model/entity/abuse_user_report.rs index 4d781f06dd..4d46581a89 100644 --- a/packages/backend-rs/src/model/entity/abuse_user_report.rs +++ b/packages/backend-rs/src/model/entity/abuse_user_report.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "abuse_user_report")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/access_token.rs b/packages/backend-rs/src/model/entity/access_token.rs index 3083bb8c90..ffe4fd9914 100644 --- a/packages/backend-rs/src/model/entity/access_token.rs +++ b/packages/backend-rs/src/model/entity/access_token.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "access_token")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/ad.rs b/packages/backend-rs/src/model/entity/ad.rs index 98ec50ea91..f8de656383 100644 --- a/packages/backend-rs/src/model/entity/ad.rs +++ b/packages/backend-rs/src/model/entity/ad.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "ad")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/announcement.rs b/packages/backend-rs/src/model/entity/announcement.rs index 311571c113..73b9c84080 100644 --- a/packages/backend-rs/src/model/entity/announcement.rs +++ b/packages/backend-rs/src/model/entity/announcement.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "announcement")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/announcement_read.rs b/packages/backend-rs/src/model/entity/announcement_read.rs index 157e402aa6..5f0c27599d 100644 --- a/packages/backend-rs/src/model/entity/announcement_read.rs +++ b/packages/backend-rs/src/model/entity/announcement_read.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "announcement_read")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/antenna.rs b/packages/backend-rs/src/model/entity/antenna.rs index 1edd6e8761..2abe216cda 100644 --- a/packages/backend-rs/src/model/entity/antenna.rs +++ b/packages/backend-rs/src/model/entity/antenna.rs @@ -3,7 +3,7 @@ use super::sea_orm_active_enums::AntennaSrcEnum; use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "antenna")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/antenna_note.rs b/packages/backend-rs/src/model/entity/antenna_note.rs deleted file mode 100644 index c86fb349d4..0000000000 --- a/packages/backend-rs/src/model/entity/antenna_note.rs +++ /dev/null @@ -1,49 +0,0 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 - -use sea_orm::entity::prelude::*; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] -#[sea_orm(table_name = "antenna_note")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = false)] - pub id: String, - #[sea_orm(column_name = "noteId")] - pub note_id: String, - #[sea_orm(column_name = "antennaId")] - pub antenna_id: String, - pub read: bool, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm( - belongs_to = "super::antenna::Entity", - from = "Column::AntennaId", - to = "super::antenna::Column::Id", - on_update = "NoAction", - on_delete = "Cascade" - )] - Antenna, - #[sea_orm( - belongs_to = "super::note::Entity", - from = "Column::NoteId", - to = "super::note::Column::Id", - on_update = "NoAction", - on_delete = "Cascade" - )] - Note, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Antenna.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Note.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend-rs/src/model/entity/app.rs b/packages/backend-rs/src/model/entity/app.rs index d9517ed211..72c908e87a 100644 --- a/packages/backend-rs/src/model/entity/app.rs +++ b/packages/backend-rs/src/model/entity/app.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "app")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/attestation_challenge.rs b/packages/backend-rs/src/model/entity/attestation_challenge.rs index 0c131066dd..9513a584e7 100644 --- a/packages/backend-rs/src/model/entity/attestation_challenge.rs +++ b/packages/backend-rs/src/model/entity/attestation_challenge.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "attestation_challenge")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/auth_session.rs b/packages/backend-rs/src/model/entity/auth_session.rs index f022a5e632..873a15ec3d 100644 --- a/packages/backend-rs/src/model/entity/auth_session.rs +++ b/packages/backend-rs/src/model/entity/auth_session.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "auth_session")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/blocking.rs b/packages/backend-rs/src/model/entity/blocking.rs index 2f5a3e0482..5ffc685f80 100644 --- a/packages/backend-rs/src/model/entity/blocking.rs +++ b/packages/backend-rs/src/model/entity/blocking.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "blocking")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/channel.rs b/packages/backend-rs/src/model/entity/channel.rs index 52f8059030..e309a7ead6 100644 --- a/packages/backend-rs/src/model/entity/channel.rs +++ b/packages/backend-rs/src/model/entity/channel.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "channel")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/channel_following.rs b/packages/backend-rs/src/model/entity/channel_following.rs index 01a25ccb83..ee5a5a9bbc 100644 --- a/packages/backend-rs/src/model/entity/channel_following.rs +++ b/packages/backend-rs/src/model/entity/channel_following.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "channel_following")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/channel_note_pining.rs b/packages/backend-rs/src/model/entity/channel_note_pining.rs index 0a41efd3e8..28431d2999 100644 --- a/packages/backend-rs/src/model/entity/channel_note_pining.rs +++ b/packages/backend-rs/src/model/entity/channel_note_pining.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "channel_note_pining")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/clip.rs b/packages/backend-rs/src/model/entity/clip.rs index 6cbbcf4756..7316831088 100644 --- a/packages/backend-rs/src/model/entity/clip.rs +++ b/packages/backend-rs/src/model/entity/clip.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "clip")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/clip_note.rs b/packages/backend-rs/src/model/entity/clip_note.rs index 262f4a9b50..c7b089d35b 100644 --- a/packages/backend-rs/src/model/entity/clip_note.rs +++ b/packages/backend-rs/src/model/entity/clip_note.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "clip_note")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/drive_file.rs b/packages/backend-rs/src/model/entity/drive_file.rs index e3e4622a62..5527d79530 100644 --- a/packages/backend-rs/src/model/entity/drive_file.rs +++ b/packages/backend-rs/src/model/entity/drive_file.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "drive_file")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/drive_folder.rs b/packages/backend-rs/src/model/entity/drive_folder.rs index 727a698ce3..717a28b8b0 100644 --- a/packages/backend-rs/src/model/entity/drive_folder.rs +++ b/packages/backend-rs/src/model/entity/drive_folder.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "drive_folder")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/emoji.rs b/packages/backend-rs/src/model/entity/emoji.rs index 530dfe12f5..19c080bc4d 100644 --- a/packages/backend-rs/src/model/entity/emoji.rs +++ b/packages/backend-rs/src/model/entity/emoji.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "emoji")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/follow_request.rs b/packages/backend-rs/src/model/entity/follow_request.rs index 4a6b572433..0ee2f954f6 100644 --- a/packages/backend-rs/src/model/entity/follow_request.rs +++ b/packages/backend-rs/src/model/entity/follow_request.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "follow_request")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/following.rs b/packages/backend-rs/src/model/entity/following.rs index f19e46140e..25a9caf226 100644 --- a/packages/backend-rs/src/model/entity/following.rs +++ b/packages/backend-rs/src/model/entity/following.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "following")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/gallery_like.rs b/packages/backend-rs/src/model/entity/gallery_like.rs index f4ede4169a..b07ad74266 100644 --- a/packages/backend-rs/src/model/entity/gallery_like.rs +++ b/packages/backend-rs/src/model/entity/gallery_like.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "gallery_like")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/gallery_post.rs b/packages/backend-rs/src/model/entity/gallery_post.rs index 797bf38242..396075c252 100644 --- a/packages/backend-rs/src/model/entity/gallery_post.rs +++ b/packages/backend-rs/src/model/entity/gallery_post.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "gallery_post")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/hashtag.rs b/packages/backend-rs/src/model/entity/hashtag.rs index e2bb816b26..a689e110b7 100644 --- a/packages/backend-rs/src/model/entity/hashtag.rs +++ b/packages/backend-rs/src/model/entity/hashtag.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "hashtag")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/instance.rs b/packages/backend-rs/src/model/entity/instance.rs index 8b598f72b1..8b534eae6e 100644 --- a/packages/backend-rs/src/model/entity/instance.rs +++ b/packages/backend-rs/src/model/entity/instance.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "instance")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/messaging_message.rs b/packages/backend-rs/src/model/entity/messaging_message.rs index 304f876d1a..0997d18013 100644 --- a/packages/backend-rs/src/model/entity/messaging_message.rs +++ b/packages/backend-rs/src/model/entity/messaging_message.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "messaging_message")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/meta.rs b/packages/backend-rs/src/model/entity/meta.rs index b9a89914bd..67cf3d96e7 100644 --- a/packages/backend-rs/src/model/entity/meta.rs +++ b/packages/backend-rs/src/model/entity/meta.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "meta")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/migrations.rs b/packages/backend-rs/src/model/entity/migrations.rs index 235156ba4e..9487b29f0f 100644 --- a/packages/backend-rs/src/model/entity/migrations.rs +++ b/packages/backend-rs/src/model/entity/migrations.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "migrations")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/moderation_log.rs b/packages/backend-rs/src/model/entity/moderation_log.rs index b76f2c33df..097f620318 100644 --- a/packages/backend-rs/src/model/entity/moderation_log.rs +++ b/packages/backend-rs/src/model/entity/moderation_log.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "moderation_log")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/muted_note.rs b/packages/backend-rs/src/model/entity/muted_note.rs index 7c2880a03d..580f13b1aa 100644 --- a/packages/backend-rs/src/model/entity/muted_note.rs +++ b/packages/backend-rs/src/model/entity/muted_note.rs @@ -3,7 +3,7 @@ use super::sea_orm_active_enums::MutedNoteReasonEnum; use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "muted_note")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/muting.rs b/packages/backend-rs/src/model/entity/muting.rs index 917e6a2e20..5ae9bf3dfa 100644 --- a/packages/backend-rs/src/model/entity/muting.rs +++ b/packages/backend-rs/src/model/entity/muting.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "muting")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/note.rs b/packages/backend-rs/src/model/entity/note.rs index 5903216c1a..1344fe8fad 100644 --- a/packages/backend-rs/src/model/entity/note.rs +++ b/packages/backend-rs/src/model/entity/note.rs @@ -3,7 +3,7 @@ use super::sea_orm_active_enums::NoteVisibilityEnum; use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "note")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/note_edit.rs b/packages/backend-rs/src/model/entity/note_edit.rs index edfb35029a..e594704fe8 100644 --- a/packages/backend-rs/src/model/entity/note_edit.rs +++ b/packages/backend-rs/src/model/entity/note_edit.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "note_edit")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/note_favorite.rs b/packages/backend-rs/src/model/entity/note_favorite.rs index 76d45e9e98..c201b82092 100644 --- a/packages/backend-rs/src/model/entity/note_favorite.rs +++ b/packages/backend-rs/src/model/entity/note_favorite.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "note_favorite")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/note_file.rs b/packages/backend-rs/src/model/entity/note_file.rs index 2c52a4e5e8..fad63db8bd 100644 --- a/packages/backend-rs/src/model/entity/note_file.rs +++ b/packages/backend-rs/src/model/entity/note_file.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "note_file")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/note_reaction.rs b/packages/backend-rs/src/model/entity/note_reaction.rs index dd870a3e7f..ab4c87d76d 100644 --- a/packages/backend-rs/src/model/entity/note_reaction.rs +++ b/packages/backend-rs/src/model/entity/note_reaction.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "note_reaction")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/note_thread_muting.rs b/packages/backend-rs/src/model/entity/note_thread_muting.rs index 965001189e..fa7a4365a0 100644 --- a/packages/backend-rs/src/model/entity/note_thread_muting.rs +++ b/packages/backend-rs/src/model/entity/note_thread_muting.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "note_thread_muting")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/note_unread.rs b/packages/backend-rs/src/model/entity/note_unread.rs index ba96aed69f..9e15f631ec 100644 --- a/packages/backend-rs/src/model/entity/note_unread.rs +++ b/packages/backend-rs/src/model/entity/note_unread.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "note_unread")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/note_watching.rs b/packages/backend-rs/src/model/entity/note_watching.rs index 5b3b331e90..00433a08e0 100644 --- a/packages/backend-rs/src/model/entity/note_watching.rs +++ b/packages/backend-rs/src/model/entity/note_watching.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "note_watching")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/notification.rs b/packages/backend-rs/src/model/entity/notification.rs index 6ed5f718aa..b5d1dced95 100644 --- a/packages/backend-rs/src/model/entity/notification.rs +++ b/packages/backend-rs/src/model/entity/notification.rs @@ -3,7 +3,7 @@ use super::sea_orm_active_enums::NotificationTypeEnum; use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "notification")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/page.rs b/packages/backend-rs/src/model/entity/page.rs index e1652a372b..3256bfff1c 100644 --- a/packages/backend-rs/src/model/entity/page.rs +++ b/packages/backend-rs/src/model/entity/page.rs @@ -3,7 +3,7 @@ use super::sea_orm_active_enums::PageVisibilityEnum; use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "page")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/page_like.rs b/packages/backend-rs/src/model/entity/page_like.rs index c1e59ef0e1..e7a477e922 100644 --- a/packages/backend-rs/src/model/entity/page_like.rs +++ b/packages/backend-rs/src/model/entity/page_like.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "page_like")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/password_reset_request.rs b/packages/backend-rs/src/model/entity/password_reset_request.rs index 058eaedebe..76e89bd8d5 100644 --- a/packages/backend-rs/src/model/entity/password_reset_request.rs +++ b/packages/backend-rs/src/model/entity/password_reset_request.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "password_reset_request")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/poll.rs b/packages/backend-rs/src/model/entity/poll.rs index 6bcbcac08b..9572a3c728 100644 --- a/packages/backend-rs/src/model/entity/poll.rs +++ b/packages/backend-rs/src/model/entity/poll.rs @@ -3,7 +3,7 @@ use super::sea_orm_active_enums::PollNotevisibilityEnum; use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "poll")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/poll_vote.rs b/packages/backend-rs/src/model/entity/poll_vote.rs index 0f2df2f5db..8208c3a95a 100644 --- a/packages/backend-rs/src/model/entity/poll_vote.rs +++ b/packages/backend-rs/src/model/entity/poll_vote.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "poll_vote")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/promo_note.rs b/packages/backend-rs/src/model/entity/promo_note.rs index c4e012b1a9..5e38b3440f 100644 --- a/packages/backend-rs/src/model/entity/promo_note.rs +++ b/packages/backend-rs/src/model/entity/promo_note.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "promo_note")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/promo_read.rs b/packages/backend-rs/src/model/entity/promo_read.rs index 10fe176405..f4d8854e39 100644 --- a/packages/backend-rs/src/model/entity/promo_read.rs +++ b/packages/backend-rs/src/model/entity/promo_read.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "promo_read")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/registration_ticket.rs b/packages/backend-rs/src/model/entity/registration_ticket.rs index 55d60d78b0..e06f2b295e 100644 --- a/packages/backend-rs/src/model/entity/registration_ticket.rs +++ b/packages/backend-rs/src/model/entity/registration_ticket.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "registration_ticket")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/registry_item.rs b/packages/backend-rs/src/model/entity/registry_item.rs index 74ae18cef3..7c7fcbf4b5 100644 --- a/packages/backend-rs/src/model/entity/registry_item.rs +++ b/packages/backend-rs/src/model/entity/registry_item.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "registry_item")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/relay.rs b/packages/backend-rs/src/model/entity/relay.rs index c035a74bec..24e4fb81c0 100644 --- a/packages/backend-rs/src/model/entity/relay.rs +++ b/packages/backend-rs/src/model/entity/relay.rs @@ -3,7 +3,7 @@ use super::sea_orm_active_enums::RelayStatusEnum; use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "relay")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/renote_muting.rs b/packages/backend-rs/src/model/entity/renote_muting.rs index b6604cad88..80b0f57f59 100644 --- a/packages/backend-rs/src/model/entity/renote_muting.rs +++ b/packages/backend-rs/src/model/entity/renote_muting.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "renote_muting")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/reply_muting.rs b/packages/backend-rs/src/model/entity/reply_muting.rs index 84fe0cbbfa..8d2e00eb3f 100644 --- a/packages/backend-rs/src/model/entity/reply_muting.rs +++ b/packages/backend-rs/src/model/entity/reply_muting.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "reply_muting")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/sea_orm_active_enums.rs b/packages/backend-rs/src/model/entity/sea_orm_active_enums.rs index 38820e1bd8..2232800070 100644 --- a/packages/backend-rs/src/model/entity/sea_orm_active_enums.rs +++ b/packages/backend-rs/src/model/entity/sea_orm_active_enums.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize)] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "antenna_src_enum")] @@ -20,7 +20,7 @@ pub enum AntennaSrcEnum { #[sea_orm(string_value = "users")] Users, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize)] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm( @@ -38,7 +38,7 @@ pub enum MutedNoteReasonEnum { #[sea_orm(string_value = "word")] Word, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize)] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm( @@ -58,7 +58,7 @@ pub enum NoteVisibilityEnum { #[sea_orm(string_value = "specified")] Specified, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize)] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm( @@ -92,7 +92,7 @@ pub enum NotificationTypeEnum { #[sea_orm(string_value = "reply")] Reply, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize)] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm( @@ -108,7 +108,7 @@ pub enum PageVisibilityEnum { #[sea_orm(string_value = "specified")] Specified, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize)] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm( @@ -126,7 +126,7 @@ pub enum PollNotevisibilityEnum { #[sea_orm(string_value = "specified")] Specified, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize)] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "relay_status_enum")] @@ -138,7 +138,7 @@ pub enum RelayStatusEnum { #[sea_orm(string_value = "requesting")] Requesting, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize)] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm( @@ -156,7 +156,7 @@ pub enum UserEmojimodpermEnum { #[sea_orm(string_value = "unauthorized")] Unauthorized, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize)] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm( @@ -172,7 +172,7 @@ pub enum UserProfileFfvisibilityEnum { #[sea_orm(string_value = "public")] Public, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize)] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm( diff --git a/packages/backend-rs/src/model/entity/signin.rs b/packages/backend-rs/src/model/entity/signin.rs index 491f079a82..08c7ad59f1 100644 --- a/packages/backend-rs/src/model/entity/signin.rs +++ b/packages/backend-rs/src/model/entity/signin.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "signin")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/sw_subscription.rs b/packages/backend-rs/src/model/entity/sw_subscription.rs index 4aa275f77b..a1bf0a9b3d 100644 --- a/packages/backend-rs/src/model/entity/sw_subscription.rs +++ b/packages/backend-rs/src/model/entity/sw_subscription.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "sw_subscription")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/used_username.rs b/packages/backend-rs/src/model/entity/used_username.rs index 9e108a8a4f..af038530b4 100644 --- a/packages/backend-rs/src/model/entity/used_username.rs +++ b/packages/backend-rs/src/model/entity/used_username.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "used_username")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user.rs b/packages/backend-rs/src/model/entity/user.rs index 8af0b27e88..25c8854abe 100644 --- a/packages/backend-rs/src/model/entity/user.rs +++ b/packages/backend-rs/src/model/entity/user.rs @@ -3,7 +3,7 @@ use super::sea_orm_active_enums::UserEmojimodpermEnum; use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "user")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_group.rs b/packages/backend-rs/src/model/entity/user_group.rs index 7d9ae71b24..8c5b08514f 100644 --- a/packages/backend-rs/src/model/entity/user_group.rs +++ b/packages/backend-rs/src/model/entity/user_group.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "user_group")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_group_invitation.rs b/packages/backend-rs/src/model/entity/user_group_invitation.rs index c449a48078..c676248ce4 100644 --- a/packages/backend-rs/src/model/entity/user_group_invitation.rs +++ b/packages/backend-rs/src/model/entity/user_group_invitation.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "user_group_invitation")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_group_invite.rs b/packages/backend-rs/src/model/entity/user_group_invite.rs index 3df43af3f6..41d47eb1b5 100644 --- a/packages/backend-rs/src/model/entity/user_group_invite.rs +++ b/packages/backend-rs/src/model/entity/user_group_invite.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "user_group_invite")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_group_joining.rs b/packages/backend-rs/src/model/entity/user_group_joining.rs index 2ff31b3a5f..3289b7e1e4 100644 --- a/packages/backend-rs/src/model/entity/user_group_joining.rs +++ b/packages/backend-rs/src/model/entity/user_group_joining.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "user_group_joining")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_ip.rs b/packages/backend-rs/src/model/entity/user_ip.rs index d6eadc7f71..77caeec313 100644 --- a/packages/backend-rs/src/model/entity/user_ip.rs +++ b/packages/backend-rs/src/model/entity/user_ip.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "user_ip")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_keypair.rs b/packages/backend-rs/src/model/entity/user_keypair.rs index d59853158a..f5fc9cd6b5 100644 --- a/packages/backend-rs/src/model/entity/user_keypair.rs +++ b/packages/backend-rs/src/model/entity/user_keypair.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "user_keypair")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_list.rs b/packages/backend-rs/src/model/entity/user_list.rs index 356ec5318c..399767fb25 100644 --- a/packages/backend-rs/src/model/entity/user_list.rs +++ b/packages/backend-rs/src/model/entity/user_list.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "user_list")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_list_joining.rs b/packages/backend-rs/src/model/entity/user_list_joining.rs index 037d7af181..adfdda8560 100644 --- a/packages/backend-rs/src/model/entity/user_list_joining.rs +++ b/packages/backend-rs/src/model/entity/user_list_joining.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "user_list_joining")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_note_pining.rs b/packages/backend-rs/src/model/entity/user_note_pining.rs index f0a80a66c9..74f4e1c1cd 100644 --- a/packages/backend-rs/src/model/entity/user_note_pining.rs +++ b/packages/backend-rs/src/model/entity/user_note_pining.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "user_note_pining")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_pending.rs b/packages/backend-rs/src/model/entity/user_pending.rs index 1fa13c2829..ddab5f2aee 100644 --- a/packages/backend-rs/src/model/entity/user_pending.rs +++ b/packages/backend-rs/src/model/entity/user_pending.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "user_pending")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_profile.rs b/packages/backend-rs/src/model/entity/user_profile.rs index a121118926..076729669f 100644 --- a/packages/backend-rs/src/model/entity/user_profile.rs +++ b/packages/backend-rs/src/model/entity/user_profile.rs @@ -4,7 +4,7 @@ use super::sea_orm_active_enums::UserProfileFfvisibilityEnum; use super::sea_orm_active_enums::UserProfileMutingnotificationtypesEnum; use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "user_profile")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_publickey.rs b/packages/backend-rs/src/model/entity/user_publickey.rs index ad6a456ead..3683a25a7c 100644 --- a/packages/backend-rs/src/model/entity/user_publickey.rs +++ b/packages/backend-rs/src/model/entity/user_publickey.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "user_publickey")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_security_key.rs b/packages/backend-rs/src/model/entity/user_security_key.rs index aae6dfa8c6..bd0a7a493a 100644 --- a/packages/backend-rs/src/model/entity/user_security_key.rs +++ b/packages/backend-rs/src/model/entity/user_security_key.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "user_security_key")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/webhook.rs b/packages/backend-rs/src/model/entity/webhook.rs index e7656056b9..72c1c7e011 100644 --- a/packages/backend-rs/src/model/entity/webhook.rs +++ b/packages/backend-rs/src/model/entity/webhook.rs @@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] #[sea_orm(table_name = "webhook")] #[cfg_attr( feature = "napi", From b017f9ce94a4c4678468f570958458106cb5a088 Mon Sep 17 00:00:00 2001 From: naskya Date: Sat, 20 Apr 2024 06:53:34 +0900 Subject: [PATCH 25/99] fix (backend-rs): use cache server if present --- packages/backend-rs/src/database/redis.rs | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/packages/backend-rs/src/database/redis.rs b/packages/backend-rs/src/database/redis.rs index 863f57b35d..8652c6b53c 100644 --- a/packages/backend-rs/src/database/redis.rs +++ b/packages/backend-rs/src/database/redis.rs @@ -7,15 +7,21 @@ fn init_redis() -> Result { let redis_url = { let mut params = vec!["redis://".to_owned()]; - if let Some(user) = &CONFIG.redis.user { + let redis = if let Some(cache_server) = &CONFIG.cache_server { + cache_server + } else { + &CONFIG.redis + }; + + if let Some(user) = &redis.user { params.push(user.to_string()) } - if let Some(pass) = &CONFIG.redis.pass { + if let Some(pass) = &redis.pass { params.push(format!(":{}@", pass)) } - params.push(CONFIG.redis.host.to_string()); - params.push(format!(":{}", CONFIG.redis.port)); - params.push(format!("/{}", CONFIG.redis.db)); + params.push(redis.host.to_string()); + params.push(format!(":{}", redis.port)); + params.push(format!("/{}", redis.db)); params.concat() }; @@ -31,9 +37,9 @@ pub fn redis_conn() -> Result { } #[inline] -/// prefix redis key with the hostname -pub fn key(key: &str) -> String { - format!("{}:{}", CONFIG.hostname, key) +/// prefix redis key +pub fn key(key: impl ToString) -> String { + format!("{}:{}", CONFIG.redis.prefix, key.to_string()) } #[cfg(test)] From f486caf24477d8bbaf6097a5beb53fd520d7ddc1 Mon Sep 17 00:00:00 2001 From: naskya Date: Sat, 20 Apr 2024 06:52:27 +0900 Subject: [PATCH 26/99] fix (backend-rs): use correct Redis key prefix --- packages/backend-rs/index.d.ts | 3 ++- packages/backend-rs/src/config/server.rs | 12 ++++++++++-- packages/backend-rs/src/database/redis.rs | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/packages/backend-rs/index.d.ts b/packages/backend-rs/index.d.ts index 433e80999c..0c75def671 100644 --- a/packages/backend-rs/index.d.ts +++ b/packages/backend-rs/index.d.ts @@ -70,7 +70,7 @@ export interface RedisConfig { pass?: string tls?: TlsConfig db: number - prefix: string + prefix?: string } export interface TlsConfig { host: string @@ -165,6 +165,7 @@ export interface Config { version: string host: string hostname: string + redisKeyPrefix: string scheme: string wsScheme: string apiUrl: string diff --git a/packages/backend-rs/src/config/server.rs b/packages/backend-rs/src/config/server.rs index edfdf6109c..720e1a9c49 100644 --- a/packages/backend-rs/src/config/server.rs +++ b/packages/backend-rs/src/config/server.rs @@ -82,8 +82,7 @@ pub struct RedisConfig { pub tls: Option, #[serde(default)] pub db: u32, - #[serde(default)] - pub prefix: String, + pub prefix: Option, } #[derive(Clone, Debug, PartialEq, Deserialize)] @@ -217,6 +216,7 @@ pub struct Config { pub version: String, pub host: String, pub hostname: String, + pub redis_key_prefix: String, pub scheme: String, pub ws_scheme: String, pub api_url: String, @@ -315,6 +315,13 @@ fn load_config() -> Config { None => WorkerConfig { web: 1, queue: 1 }, }; + let redis_key_prefix = if let Some(cache_server) = &server_config.cache_server { + cache_server.prefix.clone() + } else { + server_config.redis.prefix.clone() + } + .unwrap_or(hostname.clone()); + Config { url: server_config.url, port: server_config.port, @@ -361,6 +368,7 @@ fn load_config() -> Config { version, host, hostname, + redis_key_prefix, scheme, ws_scheme, client_entry: manifest, diff --git a/packages/backend-rs/src/database/redis.rs b/packages/backend-rs/src/database/redis.rs index 8652c6b53c..e717201f95 100644 --- a/packages/backend-rs/src/database/redis.rs +++ b/packages/backend-rs/src/database/redis.rs @@ -39,7 +39,7 @@ pub fn redis_conn() -> Result { #[inline] /// prefix redis key pub fn key(key: impl ToString) -> String { - format!("{}:{}", CONFIG.redis.prefix, key.to_string()) + format!("{}:{}", CONFIG.redis_key_prefix, key.to_string()) } #[cfg(test)] From ccbd6178e4336f801adae8a5d49c3f3f9f93525a Mon Sep 17 00:00:00 2001 From: naskya Date: Sat, 20 Apr 2024 06:54:06 +0900 Subject: [PATCH 27/99] refactor (backend): port add-note-to-antenna to backend-rs I hit this bug: https://github.com/napi-rs/napi-rs/issues/2060 --- Cargo.lock | 31 ++++++- Cargo.toml | 1 + packages/backend-rs/Cargo.toml | 1 + packages/backend-rs/index.d.ts | 1 + packages/backend-rs/index.js | 3 +- packages/backend-rs/src/lib.rs | 1 + .../src/service/add_note_to_antenna.rs | 20 +++++ packages/backend-rs/src/service/mod.rs | 2 + packages/backend-rs/src/service/stream.rs | 86 +++++++++++++++++++ packages/backend/package.json | 1 + .../backend/src/prelude/undefined-to-null.ts | 76 ++++++++++++++++ .../src/services/add-note-to-antenna.ts | 24 ------ packages/backend/src/services/note/create.ts | 7 +- packages/backend/src/services/stream.ts | 28 +++--- pnpm-lock.yaml | 8 ++ 15 files changed, 247 insertions(+), 43 deletions(-) create mode 100644 packages/backend-rs/src/service/add_note_to_antenna.rs create mode 100644 packages/backend-rs/src/service/mod.rs create mode 100644 packages/backend-rs/src/service/stream.rs create mode 100644 packages/backend/src/prelude/undefined-to-null.ts delete mode 100644 packages/backend/src/services/add-note-to-antenna.ts diff --git a/Cargo.lock b/Cargo.lock index 52ef14933f..6cb32a21d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -227,6 +227,7 @@ dependencies = [ "serde", "serde_json", "serde_yaml", + "strum 0.26.2", "thiserror", "tokio", "url", @@ -2096,6 +2097,12 @@ dependencies = [ "untrusted", ] +[[package]] +name = "rustversion" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47" + [[package]] name = "ryu" version = "1.0.17" @@ -2176,7 +2183,7 @@ dependencies = [ "serde", "serde_json", "sqlx", - "strum", + "strum 0.25.0", "thiserror", "time", "tracing", @@ -2708,6 +2715,28 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +[[package]] +name = "strum" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.58", +] + [[package]] name = "subtle" version = "2.5.0" diff --git a/Cargo.toml b/Cargo.toml index b82635d8b4..0bde324447 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,7 @@ sea-orm = "0.12.15" serde = "1.0.197" serde_json = "1.0.115" serde_yaml = "0.9.34" +strum = "0.26.2" syn = "2.0.58" thiserror = "1.0.58" tokio = "1.37.0" diff --git a/packages/backend-rs/Cargo.toml b/packages/backend-rs/Cargo.toml index d077028e13..93c57dc321 100644 --- a/packages/backend-rs/Cargo.toml +++ b/packages/backend-rs/Cargo.toml @@ -37,6 +37,7 @@ sea-orm = { workspace = true, features = ["sqlx-postgres", "runtime-tokio-rustls serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } serde_yaml = { workspace = true } +strum = { workspace = true, features = ["derive"] } thiserror = { workspace = true } tokio = { workspace = true, features = ["full"] } url = { workspace = true } diff --git a/packages/backend-rs/index.d.ts b/packages/backend-rs/index.d.ts index 0c75def671..f13cb0bc45 100644 --- a/packages/backend-rs/index.d.ts +++ b/packages/backend-rs/index.d.ts @@ -1098,6 +1098,7 @@ export interface Webhook { latestSentAt: Date | null latestStatus: number | null } +export function addNoteToAntenna(antennaId: string, note: Note): void /** Initializes Cuid2 generator. Must be called before any [create_id]. */ export function initIdGenerator(length: number, fingerprint: string): void export function getTimestamp(id: string): number diff --git a/packages/backend-rs/index.js b/packages/backend-rs/index.js index 5fd1e9d784..fbaf1dc352 100644 --- a/packages/backend-rs/index.js +++ b/packages/backend-rs/index.js @@ -310,7 +310,7 @@ if (!nativeBinding) { throw new Error(`Failed to load native binding`) } -const { loadEnv, loadConfig, stringToAcct, acctToString, checkWordMute, getFullApAccount, isSelfHost, isSameOrigin, extractHost, toPuny, isUnicodeEmoji, sqlLikeEscape, safeForSql, formatMilliseconds, getNoteSummary, toMastodonId, fromMastodonId, fetchMeta, metaToPugArgs, nyaify, hashPassword, verifyPassword, isOldPasswordAlgorithm, decodeReaction, countReactions, toDbReaction, AntennaSrcEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, initIdGenerator, getTimestamp, genId, secureRndstr } = nativeBinding +const { loadEnv, loadConfig, stringToAcct, acctToString, checkWordMute, getFullApAccount, isSelfHost, isSameOrigin, extractHost, toPuny, isUnicodeEmoji, sqlLikeEscape, safeForSql, formatMilliseconds, getNoteSummary, toMastodonId, fromMastodonId, fetchMeta, metaToPugArgs, nyaify, hashPassword, verifyPassword, isOldPasswordAlgorithm, decodeReaction, countReactions, toDbReaction, AntennaSrcEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, addNoteToAntenna, initIdGenerator, getTimestamp, genId, secureRndstr } = nativeBinding module.exports.loadEnv = loadEnv module.exports.loadConfig = loadConfig @@ -348,6 +348,7 @@ module.exports.RelayStatusEnum = RelayStatusEnum module.exports.UserEmojimodpermEnum = UserEmojimodpermEnum module.exports.UserProfileFfvisibilityEnum = UserProfileFfvisibilityEnum module.exports.UserProfileMutingnotificationtypesEnum = UserProfileMutingnotificationtypesEnum +module.exports.addNoteToAntenna = addNoteToAntenna module.exports.initIdGenerator = initIdGenerator module.exports.getTimestamp = getTimestamp module.exports.genId = genId diff --git a/packages/backend-rs/src/lib.rs b/packages/backend-rs/src/lib.rs index bef7a41808..0dcc4e6251 100644 --- a/packages/backend-rs/src/lib.rs +++ b/packages/backend-rs/src/lib.rs @@ -4,4 +4,5 @@ pub mod config; pub mod database; pub mod misc; pub mod model; +pub mod service; pub mod util; diff --git a/packages/backend-rs/src/service/add_note_to_antenna.rs b/packages/backend-rs/src/service/add_note_to_antenna.rs new file mode 100644 index 0000000000..b919f4e1a0 --- /dev/null +++ b/packages/backend-rs/src/service/add_note_to_antenna.rs @@ -0,0 +1,20 @@ +use crate::database::{redis_conn, redis_key}; +use crate::model::entity::note; +use crate::service::stream::{publish, Error, Stream}; +use crate::util::id::get_timestamp; +use redis::{streams::StreamMaxlen, Commands}; + +#[crate::export] +pub fn add_note_to_antenna(antenna_id: &str, note: ¬e::Model) -> Result<(), Error> { + redis_conn()?.xadd_maxlen( + redis_key(format!("antennaTimeline:{}", antenna_id)), + StreamMaxlen::Approx(200), + format!("{}-*", get_timestamp(¬e.id)), + &[("note", ¬e.id)], + )?; + + let stream = Stream::Antenna { + id: antenna_id.to_string(), + }; + publish(&stream, Some("note"), Some(serde_json::to_value(note)?)) +} diff --git a/packages/backend-rs/src/service/mod.rs b/packages/backend-rs/src/service/mod.rs new file mode 100644 index 0000000000..cc239e3f9e --- /dev/null +++ b/packages/backend-rs/src/service/mod.rs @@ -0,0 +1,2 @@ +pub mod add_note_to_antenna; +pub mod stream; diff --git a/packages/backend-rs/src/service/stream.rs b/packages/backend-rs/src/service/stream.rs new file mode 100644 index 0000000000..fc545fa95c --- /dev/null +++ b/packages/backend-rs/src/service/stream.rs @@ -0,0 +1,86 @@ +use crate::database::redis_conn; +use redis::{Commands, RedisError}; + +#[derive(strum::Display, serde::Serialize)] +pub enum Stream { + #[strum(serialize = "internal")] + Internal, + #[strum(serialize = "broadcast")] + Broadcast, + #[strum(to_string = "adminStream:{id}")] + Admin { id: String }, + #[strum(to_string = "user:{id}")] + User { id: String }, + #[strum(to_string = "channelStream:{id}")] + Channel { id: String }, + #[strum(to_string = "noteStream:{id}")] + Note { id: String }, + #[strum(serialize = "notesStream")] + Notes, + #[strum(to_string = "userListStream:{id}")] + UserList { id: String }, + #[strum(to_string = "mainStream:{id}")] + Main { id: String }, + #[strum(to_string = "driveStream:{id}")] + Drive { id: String }, + #[strum(to_string = "antennaStream:{id}")] + Antenna { id: String }, + #[strum(to_string = "messagingStream:{id}")] + Messaging { id: String }, + #[strum(to_string = "messagingIndexStream:{id}")] + MessagingIndex { id: String }, +} + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("Redis error: {0}")] + RedisError(#[from] RedisError), + #[error("Json serialization error: {0}")] + JsonError(#[from] serde_json::Error), + #[error("Value error: {0}")] + ValueError(String), +} + +pub fn publish( + channel: &Stream, + kind: Option<&str>, + value: Option, +) -> Result<(), Error> { + #[derive(serde::Serialize)] + struct Message { + r#type: String, + body: Option, + } + + let message = if let Some(kind) = kind { + serde_json::to_value(Message { + r#type: kind.to_string(), + body: value, + })? + } else { + value.ok_or(Error::ValueError("Invalid streaming message".to_string()))? + }; + + redis_conn()?.publish(channel.to_string(), message.to_string())?; + + Ok(()) +} + +#[cfg(test)] +mod unit_test { + use super::Stream; + use pretty_assertions::assert_eq; + + #[test] + fn channel_to_string() { + assert_eq!(Stream::Internal.to_string(), "internal"); + assert_eq!(Stream::Broadcast.to_string(), "broadcast"); + assert_eq!( + Stream::Admin { + id: "9tb42br63g5apjcq".to_string() + } + .to_string(), + "adminStream:9tb42br63g5apjcq" + ); + } +} diff --git a/packages/backend/package.json b/packages/backend/package.json index 9289c2f7ea..0599a39d4b 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -178,6 +178,7 @@ "ts-loader": "9.5.1", "ts-node": "10.9.2", "tsconfig-paths": "4.2.0", + "type-fest": "4.15.0", "typescript": "5.4.5", "webpack": "^5.91.0", "ws": "8.16.0" diff --git a/packages/backend/src/prelude/undefined-to-null.ts b/packages/backend/src/prelude/undefined-to-null.ts new file mode 100644 index 0000000000..013be3cf9e --- /dev/null +++ b/packages/backend/src/prelude/undefined-to-null.ts @@ -0,0 +1,76 @@ +// https://gist.github.com/tkrotoff/a6baf96eb6b61b445a9142e5555511a0 +import type { Primitive } from "type-fest"; + +type NullToUndefined = T extends null + ? undefined + : T extends Primitive | Function | Date | RegExp + ? T + : T extends Array + ? Array> + : T extends Map + ? Map> + : T extends Set + ? Set> + : T extends object + ? { [K in keyof T]: NullToUndefined } + : unknown; + +type UndefinedToNull = T extends undefined + ? null + : T extends Primitive | Function | Date | RegExp + ? T + : T extends Array + ? Array> + : T extends Map + ? Map> + : T extends Set + ? Set> + : T extends object + ? { [K in keyof T]: UndefinedToNull } + : unknown; + +function _nullToUndefined(obj: T): NullToUndefined { + if (obj === null) { + return undefined as any; + } + + if (typeof obj === "object") { + if (obj instanceof Map) { + obj.forEach((value, key) => obj.set(key, _nullToUndefined(value))); + } else { + for (const key in obj) { + obj[key] = _nullToUndefined(obj[key]) as any; + } + } + } + + return obj as any; +} + +function _undefinedToNull(obj: T): UndefinedToNull { + if (obj === undefined) { + return null as any; + } + + if (typeof obj === "object") { + if (obj instanceof Map) { + obj.forEach((value, key) => obj.set(key, _undefinedToNull(value))); + } else { + for (const key in obj) { + obj[key] = _undefinedToNull(obj[key]) as any; + } + } + } + + return obj as any; +} + +/** + * Recursively converts all undefined values to null. + * + * @param obj object to convert + * @returns a copy of the object with all its undefined values converted to null + */ +export function undefinedToNull(obj: T) { + return _undefinedToNull(structuredClone(obj)); +} diff --git a/packages/backend/src/services/add-note-to-antenna.ts b/packages/backend/src/services/add-note-to-antenna.ts deleted file mode 100644 index 66bc898263..0000000000 --- a/packages/backend/src/services/add-note-to-antenna.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { Antenna } from "@/models/entities/antenna.js"; -import type { Note } from "@/models/entities/note.js"; -import { getTimestamp } from "backend-rs"; -import { redisClient } from "@/db/redis.js"; -import { publishAntennaStream } from "@/services/stream.js"; -import type { User } from "@/models/entities/user.js"; - -export async function addNoteToAntenna( - antenna: Antenna, - note: Note, - _noteUser: { id: User["id"] }, -) { - redisClient.xadd( - `antennaTimeline:${antenna.id}`, - "MAXLEN", - "~", - "200", - `${getTimestamp(note.id)}-*`, - "note", - note.id, - ); - - publishAntennaStream(antenna.id, "note", note); -} diff --git a/packages/backend/src/services/note/create.ts b/packages/backend/src/services/note/create.ts index 662064da57..206f6a50ad 100644 --- a/packages/backend/src/services/note/create.ts +++ b/packages/backend/src/services/note/create.ts @@ -44,8 +44,7 @@ import { Poll } from "@/models/entities/poll.js"; import { createNotification } from "@/services/create-notification.js"; import { isDuplicateKeyValueError } from "@/misc/is-duplicate-key-value-error.js"; import { checkHitAntenna } from "@/misc/check-hit-antenna.js"; -import { checkWordMute } from "backend-rs"; -import { addNoteToAntenna } from "@/services/add-note-to-antenna.js"; +import { addNoteToAntenna, checkWordMute } from "backend-rs"; import { countSameRenotes } from "@/misc/count-same-renotes.js"; import { deliverToRelays, getCachedRelays } from "../relay.js"; import type { Channel } from "@/models/entities/channel.js"; @@ -63,6 +62,7 @@ import { Mutex } from "redis-semaphore"; import { langmap } from "@/misc/langmap.js"; import Logger from "@/services/logger.js"; import { inspect } from "node:util"; +import { undefinedToNull } from "@/prelude/undefined-to-null.js"; const logger = new Logger("create-note"); @@ -399,7 +399,8 @@ export default async ( for (const antenna of await getAntennas()) { checkHitAntenna(antenna, note, user).then((hit) => { if (hit) { - addNoteToAntenna(antenna, note, user); + // TODO: do this more sanely + addNoteToAntenna(antenna.id, undefinedToNull(note) as Note); } }); } diff --git a/packages/backend/src/services/stream.ts b/packages/backend/src/services/stream.ts index 0e2395e87e..6dff9602cd 100644 --- a/packages/backend/src/services/stream.ts +++ b/packages/backend/src/services/stream.ts @@ -4,12 +4,12 @@ import type { Note } from "@/models/entities/note.js"; import type { UserList } from "@/models/entities/user-list.js"; import type { UserGroup } from "@/models/entities/user-group.js"; import { config } from "@/config.js"; -import type { Antenna } from "@/models/entities/antenna.js"; +// import type { Antenna } from "@/models/entities/antenna.js"; import type { Channel } from "@/models/entities/channel.js"; import type { StreamChannels, AdminStreamTypes, - AntennaStreamTypes, + // AntennaStreamTypes, BroadcastTypes, ChannelStreamTypes, DriveStreamTypes, @@ -134,17 +134,17 @@ class Publisher { ); }; - public publishAntennaStream = ( - antennaId: Antenna["id"], - type: K, - value?: AntennaStreamTypes[K], - ): void => { - this.publish( - `antennaStream:${antennaId}`, - type, - typeof value === "undefined" ? null : value, - ); - }; + // public publishAntennaStream = ( + // antennaId: Antenna["id"], + // type: K, + // value?: AntennaStreamTypes[K], + // ): void => { + // this.publish( + // `antennaStream:${antennaId}`, + // type, + // typeof value === "undefined" ? null : value, + // ); + // }; public publishMessagingStream = ( userId: User["id"], @@ -217,7 +217,7 @@ export const publishNoteStream = publisher.publishNoteStream; export const publishNotesStream = publisher.publishNotesStream; export const publishChannelStream = publisher.publishChannelStream; export const publishUserListStream = publisher.publishUserListStream; -export const publishAntennaStream = publisher.publishAntennaStream; +// export const publishAntennaStream = publisher.publishAntennaStream; export const publishMessagingStream = publisher.publishMessagingStream; export const publishGroupMessagingStream = publisher.publishGroupMessagingStream; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b591ffe9c1..16a4ad6ad4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -521,6 +521,9 @@ importers: tsconfig-paths: specifier: 4.2.0 version: 4.2.0 + type-fest: + specifier: 4.15.0 + version: 4.15.0 typescript: specifier: 5.4.5 version: 5.4.5 @@ -16632,6 +16635,11 @@ packages: engines: {node: '>=8'} dev: true + /type-fest@4.15.0: + resolution: {integrity: sha512-tB9lu0pQpX5KJq54g+oHOLumOx+pMep4RaM6liXh2PKmVRFF+/vAtUP0ZaJ0kOySfVNjF6doBWPHhBhISKdlIA==} + engines: {node: '>=16'} + dev: true + /type-is@1.6.18: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} engines: {node: '>= 0.6'} From d41b462a893ec57717ca3c2527485927f00ce6e1 Mon Sep 17 00:00:00 2001 From: naskya Date: Sat, 20 Apr 2024 07:43:09 +0900 Subject: [PATCH 28/99] fix (backend): fix redis key prefix --- packages/backend/src/db/redis.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/db/redis.ts b/packages/backend/src/db/redis.ts index dc703e9d47..72c23d84e2 100644 --- a/packages/backend/src/db/redis.ts +++ b/packages/backend/src/db/redis.ts @@ -12,7 +12,7 @@ export function createConnection() { family: source.family ?? 0, password: source.pass, username: source.user ?? "default", - keyPrefix: `${source.prefix}:`, + keyPrefix: `${config.redisKeyPrefix}:`, db: source.db || 0, tls: source.tls, }); From f33c7c6c94074acba664acde306803cd53bfa3b5 Mon Sep 17 00:00:00 2001 From: naskya Date: Sat, 20 Apr 2024 08:48:48 +0900 Subject: [PATCH 29/99] fix (backend): host and hostname was messed up --- packages/backend-rs/src/config/server.rs | 12 ++++++------ .../src/server/api/stream/channels/user-list.ts | 2 +- packages/backend/src/server/api/stream/index.ts | 2 +- packages/backend/src/server/api/stream/types.ts | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/backend-rs/src/config/server.rs b/packages/backend-rs/src/config/server.rs index 720e1a9c49..b822d0d300 100644 --- a/packages/backend-rs/src/config/server.rs +++ b/packages/backend-rs/src/config/server.rs @@ -296,14 +296,14 @@ fn load_config() -> Config { let version = read_meta().version; let manifest = read_manifest(); let url = url::Url::parse(&server_config.url).expect("Config url is invalid"); - let host = url + let hostname = url .host_str() .expect("Hostname is missing in the config url") .to_owned(); - let hostname = url - .domain() - .expect("Domain is missing in the config url") - .to_owned(); + let host = match url.port() { + Some(port) => format!("{}:{}", hostname, port), + None => hostname.clone(), + }; let scheme = url.scheme().to_owned(); let ws_scheme = scheme.replace("http", "ws"); @@ -320,7 +320,7 @@ fn load_config() -> Config { } else { server_config.redis.prefix.clone() } - .unwrap_or(hostname.clone()); + .unwrap_or(host.clone()); Config { url: server_config.url, diff --git a/packages/backend/src/server/api/stream/channels/user-list.ts b/packages/backend/src/server/api/stream/channels/user-list.ts index fcfb7ecda3..2722a6610a 100644 --- a/packages/backend/src/server/api/stream/channels/user-list.ts +++ b/packages/backend/src/server/api/stream/channels/user-list.ts @@ -22,7 +22,7 @@ export default class extends Channel { this.listId = params.listId as string; // Check existence and owner - const exist = await UserLists.exist({ + const exist = await UserLists.exists({ where: { id: this.listId, userId: this.user!.id, diff --git a/packages/backend/src/server/api/stream/index.ts b/packages/backend/src/server/api/stream/index.ts index 416a041b52..313719e207 100644 --- a/packages/backend/src/server/api/stream/index.ts +++ b/packages/backend/src/server/api/stream/index.ts @@ -1,4 +1,4 @@ -import type { EventEmitter } from "events"; +import type { EventEmitter } from "node:events"; import type * as websocket from "websocket"; import readNote from "@/services/note/read.js"; import type { User } from "@/models/entities/user.js"; diff --git a/packages/backend/src/server/api/stream/types.ts b/packages/backend/src/server/api/stream/types.ts index 91095a46d3..8b4ac9e502 100644 --- a/packages/backend/src/server/api/stream/types.ts +++ b/packages/backend/src/server/api/stream/types.ts @@ -1,4 +1,4 @@ -import type { EventEmitter } from "events"; +import type { EventEmitter } from "node:events"; import type Emitter from "strict-event-emitter-types"; import type { Channel } from "@/models/entities/channel.js"; import type { User } from "@/models/entities/user.js"; From f13df7e2022992b53bea07f19a13ca956bac85f1 Mon Sep 17 00:00:00 2001 From: naskya Date: Sat, 20 Apr 2024 09:13:14 +0900 Subject: [PATCH 30/99] chore (backend-rs): make entities deserializable --- packages/backend-rs/Makefile | 4 +- .../src/model/entity/abuse_user_report.rs | 3 +- .../src/model/entity/access_token.rs | 3 +- packages/backend-rs/src/model/entity/ad.rs | 3 +- .../src/model/entity/announcement.rs | 3 +- .../src/model/entity/announcement_read.rs | 3 +- .../backend-rs/src/model/entity/antenna.rs | 3 +- packages/backend-rs/src/model/entity/app.rs | 3 +- .../src/model/entity/attestation_challenge.rs | 3 +- .../src/model/entity/auth_session.rs | 3 +- .../backend-rs/src/model/entity/blocking.rs | 3 +- .../backend-rs/src/model/entity/channel.rs | 3 +- .../src/model/entity/channel_following.rs | 3 +- .../src/model/entity/channel_note_pining.rs | 3 +- packages/backend-rs/src/model/entity/clip.rs | 3 +- .../backend-rs/src/model/entity/clip_note.rs | 3 +- .../backend-rs/src/model/entity/drive_file.rs | 3 +- .../src/model/entity/drive_folder.rs | 3 +- packages/backend-rs/src/model/entity/emoji.rs | 3 +- .../src/model/entity/follow_request.rs | 3 +- .../backend-rs/src/model/entity/following.rs | 3 +- .../src/model/entity/gallery_like.rs | 3 +- .../src/model/entity/gallery_post.rs | 3 +- .../backend-rs/src/model/entity/hashtag.rs | 3 +- .../backend-rs/src/model/entity/instance.rs | 3 +- .../src/model/entity/messaging_message.rs | 3 +- packages/backend-rs/src/model/entity/meta.rs | 3 +- .../backend-rs/src/model/entity/migrations.rs | 3 +- .../src/model/entity/moderation_log.rs | 3 +- .../backend-rs/src/model/entity/muted_note.rs | 3 +- .../backend-rs/src/model/entity/muting.rs | 3 +- packages/backend-rs/src/model/entity/note.rs | 3 +- .../backend-rs/src/model/entity/note_edit.rs | 3 +- .../src/model/entity/note_favorite.rs | 3 +- .../backend-rs/src/model/entity/note_file.rs | 3 +- .../src/model/entity/note_reaction.rs | 3 +- .../src/model/entity/note_thread_muting.rs | 3 +- .../src/model/entity/note_unread.rs | 3 +- .../src/model/entity/note_watching.rs | 3 +- .../src/model/entity/notification.rs | 3 +- packages/backend-rs/src/model/entity/page.rs | 3 +- .../backend-rs/src/model/entity/page_like.rs | 3 +- .../model/entity/password_reset_request.rs | 3 +- packages/backend-rs/src/model/entity/poll.rs | 3 +- .../backend-rs/src/model/entity/poll_vote.rs | 3 +- .../backend-rs/src/model/entity/promo_note.rs | 3 +- .../backend-rs/src/model/entity/promo_read.rs | 3 +- .../src/model/entity/registration_ticket.rs | 3 +- .../src/model/entity/registry_item.rs | 3 +- packages/backend-rs/src/model/entity/relay.rs | 3 +- .../src/model/entity/renote_muting.rs | 3 +- .../src/model/entity/reply_muting.rs | 3 +- .../src/model/entity/sea_orm_active_enums.rs | 50 +++++++++++++++---- .../backend-rs/src/model/entity/signin.rs | 3 +- .../src/model/entity/sw_subscription.rs | 3 +- .../src/model/entity/used_username.rs | 3 +- packages/backend-rs/src/model/entity/user.rs | 3 +- .../backend-rs/src/model/entity/user_group.rs | 3 +- .../src/model/entity/user_group_invitation.rs | 3 +- .../src/model/entity/user_group_invite.rs | 3 +- .../src/model/entity/user_group_joining.rs | 3 +- .../backend-rs/src/model/entity/user_ip.rs | 3 +- .../src/model/entity/user_keypair.rs | 3 +- .../backend-rs/src/model/entity/user_list.rs | 3 +- .../src/model/entity/user_list_joining.rs | 3 +- .../src/model/entity/user_note_pining.rs | 3 +- .../src/model/entity/user_pending.rs | 3 +- .../src/model/entity/user_profile.rs | 3 +- .../src/model/entity/user_publickey.rs | 3 +- .../src/model/entity/user_security_key.rs | 3 +- .../backend-rs/src/model/entity/webhook.rs | 3 +- 71 files changed, 180 insertions(+), 81 deletions(-) diff --git a/packages/backend-rs/Makefile b/packages/backend-rs/Makefile index 29a00e847d..abe6045801 100644 --- a/packages/backend-rs/Makefile +++ b/packages/backend-rs/Makefile @@ -17,9 +17,9 @@ regenerate-entities: jsname=$$(printf '%s\n' "$${base%.*}" | perl -pe 's/(^|_)./uc($$&)/ge;s/_//g'); \ attribute=$$(printf 'cfg_attr(feature = "napi", napi_derive::napi(object, js_name = "%s", use_nullable = true))' "$${jsname}"); \ sed -i "s/NAPI_EXTRA_ATTR_PLACEHOLDER/$${attribute}/" "$${file}"; \ - sed -i 's/#\[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)\]/#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)]/' "$${file}"; \ + sed -i 's/#\[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)\]/#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)]\n#[serde(rename_all = "camelCase")]/' "$${file}"; \ done - sed -i 's/#\[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum)\]/#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize)]\n#[cfg_attr(not(feature = "napi"), derive(Clone))]\n#[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))]/' \ + sed -i 's/#\[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum)\]/#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize, serde::Deserialize)]\n#[serde(rename_all = "camelCase")]\n#[cfg_attr(not(feature = "napi"), derive(Clone))]\n#[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))]/' \ src/model/entity/sea_orm_active_enums.rs cargo fmt --all -- diff --git a/packages/backend-rs/src/model/entity/abuse_user_report.rs b/packages/backend-rs/src/model/entity/abuse_user_report.rs index 4d46581a89..e12b2f4d31 100644 --- a/packages/backend-rs/src/model/entity/abuse_user_report.rs +++ b/packages/backend-rs/src/model/entity/abuse_user_report.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "abuse_user_report")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/access_token.rs b/packages/backend-rs/src/model/entity/access_token.rs index ffe4fd9914..8b79877b8b 100644 --- a/packages/backend-rs/src/model/entity/access_token.rs +++ b/packages/backend-rs/src/model/entity/access_token.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "access_token")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/ad.rs b/packages/backend-rs/src/model/entity/ad.rs index f8de656383..8a7b9abb86 100644 --- a/packages/backend-rs/src/model/entity/ad.rs +++ b/packages/backend-rs/src/model/entity/ad.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "ad")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/announcement.rs b/packages/backend-rs/src/model/entity/announcement.rs index 73b9c84080..4532614a24 100644 --- a/packages/backend-rs/src/model/entity/announcement.rs +++ b/packages/backend-rs/src/model/entity/announcement.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "announcement")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/announcement_read.rs b/packages/backend-rs/src/model/entity/announcement_read.rs index 5f0c27599d..de54dae082 100644 --- a/packages/backend-rs/src/model/entity/announcement_read.rs +++ b/packages/backend-rs/src/model/entity/announcement_read.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "announcement_read")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/antenna.rs b/packages/backend-rs/src/model/entity/antenna.rs index 2abe216cda..4074f5f106 100644 --- a/packages/backend-rs/src/model/entity/antenna.rs +++ b/packages/backend-rs/src/model/entity/antenna.rs @@ -3,7 +3,8 @@ use super::sea_orm_active_enums::AntennaSrcEnum; use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "antenna")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/app.rs b/packages/backend-rs/src/model/entity/app.rs index 72c908e87a..8d2aa5373a 100644 --- a/packages/backend-rs/src/model/entity/app.rs +++ b/packages/backend-rs/src/model/entity/app.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "app")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/attestation_challenge.rs b/packages/backend-rs/src/model/entity/attestation_challenge.rs index 9513a584e7..999952943d 100644 --- a/packages/backend-rs/src/model/entity/attestation_challenge.rs +++ b/packages/backend-rs/src/model/entity/attestation_challenge.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "attestation_challenge")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/auth_session.rs b/packages/backend-rs/src/model/entity/auth_session.rs index 873a15ec3d..fac397308d 100644 --- a/packages/backend-rs/src/model/entity/auth_session.rs +++ b/packages/backend-rs/src/model/entity/auth_session.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "auth_session")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/blocking.rs b/packages/backend-rs/src/model/entity/blocking.rs index 5ffc685f80..d7773108ab 100644 --- a/packages/backend-rs/src/model/entity/blocking.rs +++ b/packages/backend-rs/src/model/entity/blocking.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "blocking")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/channel.rs b/packages/backend-rs/src/model/entity/channel.rs index e309a7ead6..4f3ec777ee 100644 --- a/packages/backend-rs/src/model/entity/channel.rs +++ b/packages/backend-rs/src/model/entity/channel.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "channel")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/channel_following.rs b/packages/backend-rs/src/model/entity/channel_following.rs index ee5a5a9bbc..d45b2c9706 100644 --- a/packages/backend-rs/src/model/entity/channel_following.rs +++ b/packages/backend-rs/src/model/entity/channel_following.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "channel_following")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/channel_note_pining.rs b/packages/backend-rs/src/model/entity/channel_note_pining.rs index 28431d2999..9080c0181e 100644 --- a/packages/backend-rs/src/model/entity/channel_note_pining.rs +++ b/packages/backend-rs/src/model/entity/channel_note_pining.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "channel_note_pining")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/clip.rs b/packages/backend-rs/src/model/entity/clip.rs index 7316831088..05dc66fa48 100644 --- a/packages/backend-rs/src/model/entity/clip.rs +++ b/packages/backend-rs/src/model/entity/clip.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "clip")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/clip_note.rs b/packages/backend-rs/src/model/entity/clip_note.rs index c7b089d35b..a76b5d5d8a 100644 --- a/packages/backend-rs/src/model/entity/clip_note.rs +++ b/packages/backend-rs/src/model/entity/clip_note.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "clip_note")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/drive_file.rs b/packages/backend-rs/src/model/entity/drive_file.rs index 5527d79530..cff9aa5a92 100644 --- a/packages/backend-rs/src/model/entity/drive_file.rs +++ b/packages/backend-rs/src/model/entity/drive_file.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "drive_file")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/drive_folder.rs b/packages/backend-rs/src/model/entity/drive_folder.rs index 717a28b8b0..e4f6fccb6f 100644 --- a/packages/backend-rs/src/model/entity/drive_folder.rs +++ b/packages/backend-rs/src/model/entity/drive_folder.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "drive_folder")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/emoji.rs b/packages/backend-rs/src/model/entity/emoji.rs index 19c080bc4d..374781c4d2 100644 --- a/packages/backend-rs/src/model/entity/emoji.rs +++ b/packages/backend-rs/src/model/entity/emoji.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "emoji")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/follow_request.rs b/packages/backend-rs/src/model/entity/follow_request.rs index 0ee2f954f6..332eeed204 100644 --- a/packages/backend-rs/src/model/entity/follow_request.rs +++ b/packages/backend-rs/src/model/entity/follow_request.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "follow_request")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/following.rs b/packages/backend-rs/src/model/entity/following.rs index 25a9caf226..6f3255ecc9 100644 --- a/packages/backend-rs/src/model/entity/following.rs +++ b/packages/backend-rs/src/model/entity/following.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "following")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/gallery_like.rs b/packages/backend-rs/src/model/entity/gallery_like.rs index b07ad74266..db519bc91b 100644 --- a/packages/backend-rs/src/model/entity/gallery_like.rs +++ b/packages/backend-rs/src/model/entity/gallery_like.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "gallery_like")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/gallery_post.rs b/packages/backend-rs/src/model/entity/gallery_post.rs index 396075c252..5492417911 100644 --- a/packages/backend-rs/src/model/entity/gallery_post.rs +++ b/packages/backend-rs/src/model/entity/gallery_post.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "gallery_post")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/hashtag.rs b/packages/backend-rs/src/model/entity/hashtag.rs index a689e110b7..56b9314e08 100644 --- a/packages/backend-rs/src/model/entity/hashtag.rs +++ b/packages/backend-rs/src/model/entity/hashtag.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "hashtag")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/instance.rs b/packages/backend-rs/src/model/entity/instance.rs index 8b534eae6e..839c6206df 100644 --- a/packages/backend-rs/src/model/entity/instance.rs +++ b/packages/backend-rs/src/model/entity/instance.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "instance")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/messaging_message.rs b/packages/backend-rs/src/model/entity/messaging_message.rs index 0997d18013..b5f5d818a0 100644 --- a/packages/backend-rs/src/model/entity/messaging_message.rs +++ b/packages/backend-rs/src/model/entity/messaging_message.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "messaging_message")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/meta.rs b/packages/backend-rs/src/model/entity/meta.rs index 67cf3d96e7..a1e50228d5 100644 --- a/packages/backend-rs/src/model/entity/meta.rs +++ b/packages/backend-rs/src/model/entity/meta.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "meta")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/migrations.rs b/packages/backend-rs/src/model/entity/migrations.rs index 9487b29f0f..f0d55ba123 100644 --- a/packages/backend-rs/src/model/entity/migrations.rs +++ b/packages/backend-rs/src/model/entity/migrations.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "migrations")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/moderation_log.rs b/packages/backend-rs/src/model/entity/moderation_log.rs index 097f620318..e51ac4cc0d 100644 --- a/packages/backend-rs/src/model/entity/moderation_log.rs +++ b/packages/backend-rs/src/model/entity/moderation_log.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "moderation_log")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/muted_note.rs b/packages/backend-rs/src/model/entity/muted_note.rs index 580f13b1aa..b1345565b7 100644 --- a/packages/backend-rs/src/model/entity/muted_note.rs +++ b/packages/backend-rs/src/model/entity/muted_note.rs @@ -3,7 +3,8 @@ use super::sea_orm_active_enums::MutedNoteReasonEnum; use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "muted_note")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/muting.rs b/packages/backend-rs/src/model/entity/muting.rs index 5ae9bf3dfa..b9850b3a42 100644 --- a/packages/backend-rs/src/model/entity/muting.rs +++ b/packages/backend-rs/src/model/entity/muting.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "muting")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/note.rs b/packages/backend-rs/src/model/entity/note.rs index 1344fe8fad..85947ea35d 100644 --- a/packages/backend-rs/src/model/entity/note.rs +++ b/packages/backend-rs/src/model/entity/note.rs @@ -3,7 +3,8 @@ use super::sea_orm_active_enums::NoteVisibilityEnum; use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "note")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/note_edit.rs b/packages/backend-rs/src/model/entity/note_edit.rs index e594704fe8..0fb10b82a8 100644 --- a/packages/backend-rs/src/model/entity/note_edit.rs +++ b/packages/backend-rs/src/model/entity/note_edit.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "note_edit")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/note_favorite.rs b/packages/backend-rs/src/model/entity/note_favorite.rs index c201b82092..12e5c641b1 100644 --- a/packages/backend-rs/src/model/entity/note_favorite.rs +++ b/packages/backend-rs/src/model/entity/note_favorite.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "note_favorite")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/note_file.rs b/packages/backend-rs/src/model/entity/note_file.rs index fad63db8bd..9d13c7506d 100644 --- a/packages/backend-rs/src/model/entity/note_file.rs +++ b/packages/backend-rs/src/model/entity/note_file.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "note_file")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/note_reaction.rs b/packages/backend-rs/src/model/entity/note_reaction.rs index ab4c87d76d..9d5de3fab4 100644 --- a/packages/backend-rs/src/model/entity/note_reaction.rs +++ b/packages/backend-rs/src/model/entity/note_reaction.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "note_reaction")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/note_thread_muting.rs b/packages/backend-rs/src/model/entity/note_thread_muting.rs index fa7a4365a0..fbbb30e948 100644 --- a/packages/backend-rs/src/model/entity/note_thread_muting.rs +++ b/packages/backend-rs/src/model/entity/note_thread_muting.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "note_thread_muting")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/note_unread.rs b/packages/backend-rs/src/model/entity/note_unread.rs index 9e15f631ec..2b74e3a63c 100644 --- a/packages/backend-rs/src/model/entity/note_unread.rs +++ b/packages/backend-rs/src/model/entity/note_unread.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "note_unread")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/note_watching.rs b/packages/backend-rs/src/model/entity/note_watching.rs index 00433a08e0..817431daaa 100644 --- a/packages/backend-rs/src/model/entity/note_watching.rs +++ b/packages/backend-rs/src/model/entity/note_watching.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "note_watching")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/notification.rs b/packages/backend-rs/src/model/entity/notification.rs index b5d1dced95..e2273017e5 100644 --- a/packages/backend-rs/src/model/entity/notification.rs +++ b/packages/backend-rs/src/model/entity/notification.rs @@ -3,7 +3,8 @@ use super::sea_orm_active_enums::NotificationTypeEnum; use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "notification")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/page.rs b/packages/backend-rs/src/model/entity/page.rs index 3256bfff1c..a88b53459d 100644 --- a/packages/backend-rs/src/model/entity/page.rs +++ b/packages/backend-rs/src/model/entity/page.rs @@ -3,7 +3,8 @@ use super::sea_orm_active_enums::PageVisibilityEnum; use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "page")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/page_like.rs b/packages/backend-rs/src/model/entity/page_like.rs index e7a477e922..7f7caabde5 100644 --- a/packages/backend-rs/src/model/entity/page_like.rs +++ b/packages/backend-rs/src/model/entity/page_like.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "page_like")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/password_reset_request.rs b/packages/backend-rs/src/model/entity/password_reset_request.rs index 76e89bd8d5..de78019087 100644 --- a/packages/backend-rs/src/model/entity/password_reset_request.rs +++ b/packages/backend-rs/src/model/entity/password_reset_request.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "password_reset_request")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/poll.rs b/packages/backend-rs/src/model/entity/poll.rs index 9572a3c728..2e65674b15 100644 --- a/packages/backend-rs/src/model/entity/poll.rs +++ b/packages/backend-rs/src/model/entity/poll.rs @@ -3,7 +3,8 @@ use super::sea_orm_active_enums::PollNotevisibilityEnum; use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "poll")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/poll_vote.rs b/packages/backend-rs/src/model/entity/poll_vote.rs index 8208c3a95a..47e68084cc 100644 --- a/packages/backend-rs/src/model/entity/poll_vote.rs +++ b/packages/backend-rs/src/model/entity/poll_vote.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "poll_vote")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/promo_note.rs b/packages/backend-rs/src/model/entity/promo_note.rs index 5e38b3440f..8b13b8987b 100644 --- a/packages/backend-rs/src/model/entity/promo_note.rs +++ b/packages/backend-rs/src/model/entity/promo_note.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "promo_note")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/promo_read.rs b/packages/backend-rs/src/model/entity/promo_read.rs index f4d8854e39..3e6d822d29 100644 --- a/packages/backend-rs/src/model/entity/promo_read.rs +++ b/packages/backend-rs/src/model/entity/promo_read.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "promo_read")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/registration_ticket.rs b/packages/backend-rs/src/model/entity/registration_ticket.rs index e06f2b295e..ab735b2422 100644 --- a/packages/backend-rs/src/model/entity/registration_ticket.rs +++ b/packages/backend-rs/src/model/entity/registration_ticket.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "registration_ticket")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/registry_item.rs b/packages/backend-rs/src/model/entity/registry_item.rs index 7c7fcbf4b5..cb129128b7 100644 --- a/packages/backend-rs/src/model/entity/registry_item.rs +++ b/packages/backend-rs/src/model/entity/registry_item.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "registry_item")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/relay.rs b/packages/backend-rs/src/model/entity/relay.rs index 24e4fb81c0..f2eeb571f4 100644 --- a/packages/backend-rs/src/model/entity/relay.rs +++ b/packages/backend-rs/src/model/entity/relay.rs @@ -3,7 +3,8 @@ use super::sea_orm_active_enums::RelayStatusEnum; use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "relay")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/renote_muting.rs b/packages/backend-rs/src/model/entity/renote_muting.rs index 80b0f57f59..308e4c1563 100644 --- a/packages/backend-rs/src/model/entity/renote_muting.rs +++ b/packages/backend-rs/src/model/entity/renote_muting.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "renote_muting")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/reply_muting.rs b/packages/backend-rs/src/model/entity/reply_muting.rs index 8d2e00eb3f..77891d1ee2 100644 --- a/packages/backend-rs/src/model/entity/reply_muting.rs +++ b/packages/backend-rs/src/model/entity/reply_muting.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "reply_muting")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/sea_orm_active_enums.rs b/packages/backend-rs/src/model/entity/sea_orm_active_enums.rs index 2232800070..e8a53acdd3 100644 --- a/packages/backend-rs/src/model/entity/sea_orm_active_enums.rs +++ b/packages/backend-rs/src/model/entity/sea_orm_active_enums.rs @@ -2,7 +2,10 @@ use sea_orm::entity::prelude::*; -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize)] +#[derive( + Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize, serde::Deserialize, +)] +#[serde(rename_all = "camelCase")] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "antenna_src_enum")] @@ -20,7 +23,10 @@ pub enum AntennaSrcEnum { #[sea_orm(string_value = "users")] Users, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize)] +#[derive( + Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize, serde::Deserialize, +)] +#[serde(rename_all = "camelCase")] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm( @@ -38,7 +44,10 @@ pub enum MutedNoteReasonEnum { #[sea_orm(string_value = "word")] Word, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize)] +#[derive( + Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize, serde::Deserialize, +)] +#[serde(rename_all = "camelCase")] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm( @@ -58,7 +67,10 @@ pub enum NoteVisibilityEnum { #[sea_orm(string_value = "specified")] Specified, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize)] +#[derive( + Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize, serde::Deserialize, +)] +#[serde(rename_all = "camelCase")] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm( @@ -92,7 +104,10 @@ pub enum NotificationTypeEnum { #[sea_orm(string_value = "reply")] Reply, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize)] +#[derive( + Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize, serde::Deserialize, +)] +#[serde(rename_all = "camelCase")] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm( @@ -108,7 +123,10 @@ pub enum PageVisibilityEnum { #[sea_orm(string_value = "specified")] Specified, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize)] +#[derive( + Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize, serde::Deserialize, +)] +#[serde(rename_all = "camelCase")] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm( @@ -126,7 +144,10 @@ pub enum PollNotevisibilityEnum { #[sea_orm(string_value = "specified")] Specified, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize)] +#[derive( + Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize, serde::Deserialize, +)] +#[serde(rename_all = "camelCase")] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "relay_status_enum")] @@ -138,7 +159,10 @@ pub enum RelayStatusEnum { #[sea_orm(string_value = "requesting")] Requesting, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize)] +#[derive( + Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize, serde::Deserialize, +)] +#[serde(rename_all = "camelCase")] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm( @@ -156,7 +180,10 @@ pub enum UserEmojimodpermEnum { #[sea_orm(string_value = "unauthorized")] Unauthorized, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize)] +#[derive( + Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize, serde::Deserialize, +)] +#[serde(rename_all = "camelCase")] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm( @@ -172,7 +199,10 @@ pub enum UserProfileFfvisibilityEnum { #[sea_orm(string_value = "public")] Public, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize)] +#[derive( + Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize, serde::Deserialize, +)] +#[serde(rename_all = "camelCase")] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm( diff --git a/packages/backend-rs/src/model/entity/signin.rs b/packages/backend-rs/src/model/entity/signin.rs index 08c7ad59f1..d5584f9d84 100644 --- a/packages/backend-rs/src/model/entity/signin.rs +++ b/packages/backend-rs/src/model/entity/signin.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "signin")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/sw_subscription.rs b/packages/backend-rs/src/model/entity/sw_subscription.rs index a1bf0a9b3d..fe694177f3 100644 --- a/packages/backend-rs/src/model/entity/sw_subscription.rs +++ b/packages/backend-rs/src/model/entity/sw_subscription.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "sw_subscription")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/used_username.rs b/packages/backend-rs/src/model/entity/used_username.rs index af038530b4..8557955034 100644 --- a/packages/backend-rs/src/model/entity/used_username.rs +++ b/packages/backend-rs/src/model/entity/used_username.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "used_username")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user.rs b/packages/backend-rs/src/model/entity/user.rs index 25c8854abe..f8a2b09324 100644 --- a/packages/backend-rs/src/model/entity/user.rs +++ b/packages/backend-rs/src/model/entity/user.rs @@ -3,7 +3,8 @@ use super::sea_orm_active_enums::UserEmojimodpermEnum; use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "user")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_group.rs b/packages/backend-rs/src/model/entity/user_group.rs index 8c5b08514f..387c50d422 100644 --- a/packages/backend-rs/src/model/entity/user_group.rs +++ b/packages/backend-rs/src/model/entity/user_group.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "user_group")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_group_invitation.rs b/packages/backend-rs/src/model/entity/user_group_invitation.rs index c676248ce4..289acf89df 100644 --- a/packages/backend-rs/src/model/entity/user_group_invitation.rs +++ b/packages/backend-rs/src/model/entity/user_group_invitation.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "user_group_invitation")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_group_invite.rs b/packages/backend-rs/src/model/entity/user_group_invite.rs index 41d47eb1b5..62fcf0c524 100644 --- a/packages/backend-rs/src/model/entity/user_group_invite.rs +++ b/packages/backend-rs/src/model/entity/user_group_invite.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "user_group_invite")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_group_joining.rs b/packages/backend-rs/src/model/entity/user_group_joining.rs index 3289b7e1e4..b29bdd11eb 100644 --- a/packages/backend-rs/src/model/entity/user_group_joining.rs +++ b/packages/backend-rs/src/model/entity/user_group_joining.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "user_group_joining")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_ip.rs b/packages/backend-rs/src/model/entity/user_ip.rs index 77caeec313..9847fb8d65 100644 --- a/packages/backend-rs/src/model/entity/user_ip.rs +++ b/packages/backend-rs/src/model/entity/user_ip.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "user_ip")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_keypair.rs b/packages/backend-rs/src/model/entity/user_keypair.rs index f5fc9cd6b5..dad29ab3b3 100644 --- a/packages/backend-rs/src/model/entity/user_keypair.rs +++ b/packages/backend-rs/src/model/entity/user_keypair.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "user_keypair")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_list.rs b/packages/backend-rs/src/model/entity/user_list.rs index 399767fb25..30dc6db715 100644 --- a/packages/backend-rs/src/model/entity/user_list.rs +++ b/packages/backend-rs/src/model/entity/user_list.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "user_list")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_list_joining.rs b/packages/backend-rs/src/model/entity/user_list_joining.rs index adfdda8560..972cc34bb6 100644 --- a/packages/backend-rs/src/model/entity/user_list_joining.rs +++ b/packages/backend-rs/src/model/entity/user_list_joining.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "user_list_joining")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_note_pining.rs b/packages/backend-rs/src/model/entity/user_note_pining.rs index 74f4e1c1cd..26f05274fd 100644 --- a/packages/backend-rs/src/model/entity/user_note_pining.rs +++ b/packages/backend-rs/src/model/entity/user_note_pining.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "user_note_pining")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_pending.rs b/packages/backend-rs/src/model/entity/user_pending.rs index ddab5f2aee..43a5c2f1e2 100644 --- a/packages/backend-rs/src/model/entity/user_pending.rs +++ b/packages/backend-rs/src/model/entity/user_pending.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "user_pending")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_profile.rs b/packages/backend-rs/src/model/entity/user_profile.rs index 076729669f..644817aa8d 100644 --- a/packages/backend-rs/src/model/entity/user_profile.rs +++ b/packages/backend-rs/src/model/entity/user_profile.rs @@ -4,7 +4,8 @@ use super::sea_orm_active_enums::UserProfileFfvisibilityEnum; use super::sea_orm_active_enums::UserProfileMutingnotificationtypesEnum; use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "user_profile")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_publickey.rs b/packages/backend-rs/src/model/entity/user_publickey.rs index 3683a25a7c..f8bc8629eb 100644 --- a/packages/backend-rs/src/model/entity/user_publickey.rs +++ b/packages/backend-rs/src/model/entity/user_publickey.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "user_publickey")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_security_key.rs b/packages/backend-rs/src/model/entity/user_security_key.rs index bd0a7a493a..a4694cf177 100644 --- a/packages/backend-rs/src/model/entity/user_security_key.rs +++ b/packages/backend-rs/src/model/entity/user_security_key.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "user_security_key")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/webhook.rs b/packages/backend-rs/src/model/entity/webhook.rs index 72c1c7e011..430cf9fcc0 100644 --- a/packages/backend-rs/src/model/entity/webhook.rs +++ b/packages/backend-rs/src/model/entity/webhook.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "webhook")] #[cfg_attr( feature = "napi", From 2b0668dacd3f540b93c932e504d1e86a1337afc1 Mon Sep 17 00:00:00 2001 From: naskya Date: Sat, 20 Apr 2024 09:54:02 +0900 Subject: [PATCH 31/99] fix (backend-rs): Redis streaming --- .../src/service/add_note_to_antenna.rs | 2 +- packages/backend-rs/src/service/stream.rs | 35 ++++++++++--------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/packages/backend-rs/src/service/add_note_to_antenna.rs b/packages/backend-rs/src/service/add_note_to_antenna.rs index b919f4e1a0..6a06fb6993 100644 --- a/packages/backend-rs/src/service/add_note_to_antenna.rs +++ b/packages/backend-rs/src/service/add_note_to_antenna.rs @@ -16,5 +16,5 @@ pub fn add_note_to_antenna(antenna_id: &str, note: ¬e::Model) -> Result<(), E let stream = Stream::Antenna { id: antenna_id.to_string(), }; - publish(&stream, Some("note"), Some(serde_json::to_value(note)?)) + publish(&stream, Some("note"), Some(serde_json::to_string(note)?)) } diff --git a/packages/backend-rs/src/service/stream.rs b/packages/backend-rs/src/service/stream.rs index fc545fa95c..6fbe699f44 100644 --- a/packages/backend-rs/src/service/stream.rs +++ b/packages/backend-rs/src/service/stream.rs @@ -1,3 +1,4 @@ +use crate::config::server::CONFIG; use crate::database::redis_conn; use redis::{Commands, RedisError}; @@ -35,33 +36,33 @@ pub enum Stream { pub enum Error { #[error("Redis error: {0}")] RedisError(#[from] RedisError), - #[error("Json serialization error: {0}")] + #[error("Json (de)serialization error: {0}")] JsonError(#[from] serde_json::Error), #[error("Value error: {0}")] ValueError(String), } -pub fn publish( - channel: &Stream, - kind: Option<&str>, - value: Option, -) -> Result<(), Error> { - #[derive(serde::Serialize)] - struct Message { - r#type: String, - body: Option, - } - +pub fn publish(channel: &Stream, kind: Option<&str>, value: Option) -> Result<(), Error> { let message = if let Some(kind) = kind { - serde_json::to_value(Message { - r#type: kind.to_string(), - body: value, - })? + format!( + "{{ \"type\": \"{}\", \"body\": {} }}", + kind, + match value { + Some(v) => v, + None => "null".to_string(), + } + ) } else { value.ok_or(Error::ValueError("Invalid streaming message".to_string()))? }; - redis_conn()?.publish(channel.to_string(), message.to_string())?; + redis_conn()?.publish( + &CONFIG.host, + format!( + "{{ \"channel\": \"{}\", \"message\": {} }}", + channel, message, + ), + )?; Ok(()) } From 35c7dccb498ac8f068199f09f982e80997ed7bcb Mon Sep 17 00:00:00 2001 From: Lhcfl Date: Sat, 20 Apr 2024 15:56:13 +0800 Subject: [PATCH 32/99] fix: use MkPagination in notes for Quote, Boost, Reaction --- .../backend/src/models/repositories/note.ts | 22 ++++- packages/backend/src/models/schema/note.ts | 10 ++ .../server/api/endpoints/notes/reactions.ts | 2 - .../src/server/api/endpoints/notes/renotes.ts | 15 ++- .../client/src/components/MkNoteDetailed.vue | 93 ++++++++++--------- .../client/src/components/MkReactedUsers.vue | 31 +++++-- .../client/src/components/MkRenoteButton.vue | 16 +--- packages/firefish-js/src/api.types.ts | 8 +- packages/firefish-js/src/entities.ts | 2 + 9 files changed, 131 insertions(+), 68 deletions(-) diff --git a/packages/backend/src/models/repositories/note.ts b/packages/backend/src/models/repositories/note.ts index c877048709..5974fc24af 100644 --- a/packages/backend/src/models/repositories/note.ts +++ b/packages/backend/src/models/repositories/note.ts @@ -1,4 +1,4 @@ -import { In } from "typeorm"; +import { In, IsNull, Not } from "typeorm"; import * as mfm from "mfm-js"; import { Note } from "@/models/entities/note.js"; import type { User } from "@/models/entities/user.js"; @@ -10,6 +10,7 @@ import { Followings, Polls, Channels, + Notes, } from "../index.js"; import type { Packed } from "@/misc/schema.js"; import { countReactions, decodeReaction, nyaify } from "backend-rs"; @@ -101,7 +102,7 @@ export const NoteRepository = db.getRepository(Note).extend({ return true; } else { // 指定されているかどうか - return note.visibleUserIds.some((id: any) => meId === id); + return note.visibleUserIds.some((id) => meId === id); } } @@ -211,8 +212,25 @@ export const NoteRepository = db.getRepository(Note).extend({ localOnly: note.localOnly || undefined, visibleUserIds: note.visibility === "specified" ? note.visibleUserIds : undefined, + // FIXME: Deleting a post does not decrease these two numbers, causing the number to be wrong renoteCount: note.renoteCount, repliesCount: note.repliesCount, + // TODO: add it to database and use note.quoteCount + quoteCount: Notes.count({ + where: { + renoteId: note.id, + text: Not(IsNull()), + }, + }), + meRenoteCount: me + ? Notes.count({ + where: { + renoteId: note.id, + text: IsNull(), + userId: me.id, + }, + }) + : undefined, reactions: countReactions(note.reactions), reactionEmojis: reactionEmoji, emojis: noteEmoji, diff --git a/packages/backend/src/models/schema/note.ts b/packages/backend/src/models/schema/note.ts index fff872b69f..e0048f7d00 100644 --- a/packages/backend/src/models/schema/note.ts +++ b/packages/backend/src/models/schema/note.ts @@ -208,5 +208,15 @@ export const packedNoteSchema = { optional: true, nullable: true, }, + meRenoteCount: { + type: "number", + optional: true, + nullable: false, + }, + quoteCount: { + type: "number", + optional: false, + nullable: false, + }, }, } as const; diff --git a/packages/backend/src/server/api/endpoints/notes/reactions.ts b/packages/backend/src/server/api/endpoints/notes/reactions.ts index 386a3a08df..d6ff8888af 100644 --- a/packages/backend/src/server/api/endpoints/notes/reactions.ts +++ b/packages/backend/src/server/api/endpoints/notes/reactions.ts @@ -42,8 +42,6 @@ export const paramDef = { type: { type: "string", nullable: true }, limit: { type: "integer", minimum: 1, maximum: 100, default: 10 }, offset: { type: "integer", default: 0 }, - sinceId: { type: "string", format: "misskey:id" }, - untilId: { type: "string", format: "misskey:id" }, }, required: ["noteId"], } as const; diff --git a/packages/backend/src/server/api/endpoints/notes/renotes.ts b/packages/backend/src/server/api/endpoints/notes/renotes.ts index 683004ebe8..282777b2e4 100644 --- a/packages/backend/src/server/api/endpoints/notes/renotes.ts +++ b/packages/backend/src/server/api/endpoints/notes/renotes.ts @@ -42,6 +42,12 @@ export const paramDef = { limit: { type: "integer", minimum: 1, maximum: 100, default: 10 }, sinceId: { type: "string", format: "misskey:id" }, untilId: { type: "string", format: "misskey:id" }, + filter: { + type: "string", + enum: ["boost", "quote"], + nullable: true, + default: null, + }, }, required: ["noteId"], } as const; @@ -53,7 +59,7 @@ export default define(meta, paramDef, async (ps, user) => { throw err; }); - let query = makePaginationQuery( + const query = makePaginationQuery( Notes.createQueryBuilder("note"), ps.sinceId, ps.untilId, @@ -61,6 +67,13 @@ export default define(meta, paramDef, async (ps, user) => { .andWhere("note.renoteId = :renoteId", { renoteId: note.id }) .innerJoinAndSelect("note.user", "user"); + if (ps.filter === "boost") { + query.andWhere("note.text IS NULL"); + } + if (ps.filter === "quote") { + query.andWhere("note.text IS NOT NULL"); + } + if (ps.userId) { query.andWhere("user.id = :userId", { userId: ps.userId }); } diff --git a/packages/client/src/components/MkNoteDetailed.vue b/packages/client/src/components/MkNoteDetailed.vue index b6c0d784ba..71e4aeb783 100644 --- a/packages/client/src/components/MkNoteDetailed.vue +++ b/packages/client/src/components/MkNoteDetailed.vue @@ -64,11 +64,11 @@ ) }} -