diff --git a/Cargo.lock b/Cargo.lock index c6ba96e683..f34ed4aea4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -220,12 +220,15 @@ dependencies = [ "parse-display", "pretty_assertions", "rand", + "redis", "regex", + "rmp-serde", "schemars", "sea-orm", "serde", "serde_json", "serde_yaml", + "strum 0.26.2", "thiserror", "tokio", "url", @@ -524,6 +527,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 +1871,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" @@ -1985,6 +2013,28 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "rmp" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4" +dependencies = [ + "byteorder", + "num-traits", + "paste", +] + +[[package]] +name = "rmp-serde" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "938a142ab806f18b88a97b0dea523d39e0fd730a064b035726adcfc58a8a5188" +dependencies = [ + "byteorder", + "rmp", + "serde", +] + [[package]] name = "rsa" version = "0.9.6" @@ -2070,6 +2120,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" @@ -2150,7 +2206,7 @@ dependencies = [ "serde", "serde_json", "sqlx", - "strum", + "strum 0.25.0", "thiserror", "time", "tracing", @@ -2295,6 +2351,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" @@ -2676,6 +2738,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 7ca43c960b..2beb8e3fe5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,12 +26,15 @@ 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" +rmp-serde = "1.2.0" schemars = "0.8.16" 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/dev/docs/local-installation.md b/dev/docs/local-installation.md index 154f768037..15c7dad7d4 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. We recommend that you install v12.x for the same reason as Node.js. + 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 324923c6a7..0e850e2545 100644 --- a/docs/install.md +++ b/docs/install.md @@ -1,9 +1,36 @@ # Install Firefish -This document shows an example procedure for installing Firefish on Debian 12. Note that there is much room for customizing the server setup; this document merely demonstrates a simple installation. +Firefish depends on the following software. + +## Runtime dependencies + +- 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) + - Nginx (recommended) + - Apache +- [FFmpeg](https://ffmpeg.org/) for video transcoding (**optional**) +- Caching server (**optional**, one of the following) + - [DragonflyDB](https://www.dragonflydb.io/) + - [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/) + +This document shows an example procedure for installing these dependencies and Firefish on Debian 12. Note that there is much room for customizing the server setup; this document merely demonstrates a simple installation. 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 diff --git a/locales/bg-BG.yml b/locales/bg-BG.yml index 1142a1eb57..45bd1eb465 100644 --- a/locales/bg-BG.yml +++ b/locales/bg-BG.yml @@ -69,7 +69,7 @@ renameFile: Преименуване на файла _widgets: activity: Дейност notifications: Известия - timeline: Инфопоток + timeline: Хронология clock: Часовник trends: Актуални photos: Снимки @@ -187,7 +187,7 @@ notesAndReplies: Публикации и отговори noSuchUser: Потребителят не е намерен pinnedPages: Закачени страници pinLimitExceeded: Не може да закачаш повече публикации -flagShowTimelineReplies: Показване на отговори в инфопотока +flagShowTimelineReplies: Показване на отговори в хронологията followersCount: Брой последователи receivedReactionsCount: Брой получени реакции federation: Федерация @@ -340,7 +340,7 @@ _deck: _columns: notifications: Известия mentions: Споменавания - tl: Инфопоток + tl: Хронология direct: Директни съобщения list: Списък antenna: Антена @@ -375,7 +375,7 @@ basicSettings: Основни настройки otherSettings: Други настройки openInWindow: Отваряне в прозорец profile: Профил -timeline: Инфопоток +timeline: Хронология noAccountDescription: Този потребител все още не е написал своята биография. login: Вход loggingIn: Вписване @@ -558,12 +558,12 @@ _visibility: specified: Директна localOnly: Само местни public: Общодостъпна - publicDescription: Публикацията ще бъде видима във всички публични инфопотоци + publicDescription: Публикацията ще бъде видима във всички публични хронологии home: Скрита localOnlyDescription: Не е видима за отдалечени потребители specifiedDescription: Видима само за определени потребители followersDescription: Видима само за последователите ти и споменатите потребители - homeDescription: Публикуване само в началния инфопоток + homeDescription: Публикуване само в началната хронология explore: Разглеждане theme: Теми wallpaper: Тапет @@ -594,21 +594,21 @@ _tutorial: да разберат дали искат да видят вашите публикации или да ви следват. title: Как се използва Firefish step1_1: Добре дошли! - step5_1: Инфопотоци, инфопотоци навсякъде! + step5_1: Хронологии, хронологии навсякъде! step3_1: Сега е време да последвате няколко хора! step1_2: Нека да ви настроим. Ще бъдете готови за нула време! - step5_3: Началният {icon} инфопоток е мястото, където можете да видите публикации + step5_3: Началната {icon} хронология е мястото, където можете да видите публикации от акаунтите, които следвате. step6_1: И така, какво е това място? - step5_7: Глобалният {icon} инфопоток е мястото, където можете да видите публикации + step5_7: Глобалната {icon} хронология е мястото, където можете да видите публикации от всеки друг свързан сървър. step4_2: За първата си публикация някои хора обичат да правят публикация {introduction} или просто „Здравей свят!“ - step5_2: Вашият сървър има активирани {timelines} различни инфопотоци. - step5_4: Местният {icon} инфопоток е мястото, където можете да видите публикации + step5_2: Вашият сървър има активирани {timelines} различни хронологии. + step5_4: Местната {icon} хронология е мястото, където можете да видите публикации от всички останали на този сървър. - step5_5: Социалният {icon} инфопоток е комбинация от Началния и Местния инфопоток. - step5_6: Препоръчаният {icon} инфопоток е мястото, където можете да видите публикации + step5_5: Социалната {icon} хронология е комбинация от Началната и Местната хронология. + step5_6: Препоръчаната {icon} хронология е мястото, където можете да видите публикации от сървъри, препоръчани от администраторите. step6_4: Сега отидете, изследвайте и се забавлявайте! step6_3: Всеки сървър работи по различни начини и не всички сървъри работят с Firefish. @@ -754,7 +754,7 @@ _feeds: general: Общи metadata: Метаданни disk: Диск -featured: Представени +featured: Препоръчани yearsOld: на {age} години reload: Опресняване invites: Покани @@ -778,8 +778,8 @@ uploadFromUrl: Качване от URL адрес instanceName: Име на сървъра instanceDescription: Описание на сървъра accept: Приемане -enableLocalTimeline: Включване на местния инфопоток -enableGlobalTimeline: Включване на глобалния инфопоток +enableLocalTimeline: Включване на местната хронология +enableGlobalTimeline: Включване на глобалната хронология removeMember: Премахване на член isAdmin: Администратор isModerator: Модератор @@ -862,8 +862,8 @@ apply: Прилагане selectAccount: Избор на акаунт muteThread: Заглушаване на нишката ffVisibility: Видимост на Последвани/Последователи -renoteMute: Заглушаване на подсилванията в инфопотоците -replyMute: Заглушаване на отговорите в инфопотоците +renoteMute: Заглуш. на подсилванията в хронолог. +replyMute: Заглуш. на отговорите в хронолог. blockConfirm: Сигурни ли сте, че искате да блокирате този акаунт? appearance: Облик fontSize: Размер на шрифта @@ -893,7 +893,7 @@ charts: Диаграми disablePagesScript: Изключване на AiScript в Страниците updatedAt: Обновено на privateDescription: Видима само за теб -enableTimelineStreaming: Автоматично обновяване на инфопотоците +enableTimelineStreaming: Автоматично обновяване на хронологиите toEdit: Редактиране showEmojisInReactionNotifications: Показване на емоджита в известията за реакции rememberNoteVisibility: Запомняне на настройките за видимост на публикациите @@ -932,3 +932,11 @@ clientSettings: Настройки за устройството behavior: Поведение detectPostLanguage: Автоматично откриване на езика и показване на бутон за превеждане за публикации на чужди езици +replyUnmute: Отмяна на заглушаването на отговорите +searchWords: Думи за търсене / ID или URL за поглеждане +reloadConfirm: Искате ли да опресните хронологията? +enableRecommendedTimeline: Включване на препоръчаната хронология +showGapBetweenNotesInTimeline: Показване на празнина между публикациите в хронологията +lookup: Поглеждане +media: Мултимедия +welcomeBackWithName: Добре дошли отново, {name} diff --git a/locales/en-US.yml b/locales/en-US.yml index f44c3d1842..a70eb2406f 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -1227,6 +1227,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: "Automatically open a form to write a description when you + attempt to post files without a description" _emojiModPerm: unauthorized: "None" diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index c8579a4c1a..1be460f7f0 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -2054,6 +2054,7 @@ searchRangeDescription: "如果您要过滤时间段,请按以下格式输入 messagingUnencryptedInfo: "Firefish 上的聊天没有经过端到端加密,请不要在聊天中分享您的敏感信息。" noAltTextWarning: 有些附件没有描述。您是否忘记写描述了? showNoAltTextWarning: 当您尝试发布没有描述的帖子附件时显示警告 +showAddFileDescriptionAtFirstPost: 当您首次尝试发布没有描述的帖子附件时自动弹出添加描述页面 autocorrectNoteLanguage: 当帖子语言不符合自动检测的结果的时候显示警告 incorrectLanguageWarning: "看上去您帖子使用的语言是{detected},但您选择的语言是{current}。\n要改为以{detected}发帖吗?" noteEditHistory: "帖子编辑历史" diff --git a/packages/backend-rs/Cargo.toml b/packages/backend-rs/Cargo.toml index af9e10cdc1..5a18dc92cf 100644 --- a/packages/backend-rs/Cargo.toml +++ b/packages/backend-rs/Cargo.toml @@ -30,12 +30,15 @@ jsonschema = { workspace = true } once_cell = { workspace = true } parse-display = { workspace = true } rand = { workspace = true } +redis = { workspace = true } regex = { workspace = true } +rmp-serde = { workspace = true } schemars = { workspace = true, features = ["chrono"] } 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/Makefile b/packages/backend-rs/Makefile index 11b614c82a..abe6045801 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, 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)]\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/index.d.ts b/packages/backend-rs/index.d.ts index 04b26c3e5a..69de833dcc 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?: WorkerConfigInternal cuid?: IdConfig outgoingAddress?: string deliverJobConcurrency?: number @@ -70,13 +70,17 @@ export interface RedisConfig { pass?: string tls?: TlsConfig db: number - prefix: string + prefix?: string } export interface TlsConfig { host: string rejectUnauthorized: boolean } export interface WorkerConfig { + web: number + queue: number +} +export interface WorkerConfigInternal { web?: number queue?: number } @@ -121,13 +125,89 @@ 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 + redisKeyPrefix: 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 } export function stringToAcct(acct: string): Acct export function acctToString(acct: Acct): string +/** + * @param host punycoded instance host + * @returns whether the given host should be blocked +*/ +export function isBlockedServer(host: string): Promise +/** + * @param host punycoded instance host + * @returns whether the given host should be limited +*/ +export function isSilencedServer(host: string): Promise +/** + * @param host punycoded instance host + * @returns whether the given host is allowlisted (this is always true if private mode is disabled) +*/ +export function isAllowedServer(host: string): Promise /** TODO: handle name collisions better */ export interface NoteLikeForCheckWordMute { fileIds: Array @@ -492,7 +572,6 @@ export interface Meta { recaptchaSecretKey: string | null localDriveCapacityMb: number remoteDriveCapacityMb: number - antennaLimit: number summalyProxy: string | null enableEmail: boolean email: string | null @@ -555,6 +634,7 @@ export interface Meta { donationLink: string | null moreUrls: Json markLocalFilesNsfwByDefault: boolean + antennaLimit: number } export interface Migrations { id: number @@ -1039,6 +1119,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 6d64f6ec75..b4d86dccdf 100644 --- a/packages/backend-rs/index.js +++ b/packages/backend-rs/index.js @@ -310,12 +310,15 @@ 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, DriveFileUsageHintEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, initIdGenerator, getTimestamp, genId, secureRndstr } = nativeBinding +const { loadEnv, loadConfig, stringToAcct, acctToString, isBlockedServer, isSilencedServer, isAllowedServer, checkWordMute, getFullApAccount, isSelfHost, isSameOrigin, extractHost, toPuny, isUnicodeEmoji, sqlLikeEscape, safeForSql, formatMilliseconds, getNoteSummary, toMastodonId, fromMastodonId, fetchMeta, metaToPugArgs, nyaify, hashPassword, verifyPassword, isOldPasswordAlgorithm, decodeReaction, countReactions, toDbReaction, AntennaSrcEnum, DriveFileUsageHintEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, addNoteToAntenna, 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.isBlockedServer = isBlockedServer +module.exports.isSilencedServer = isSilencedServer +module.exports.isAllowedServer = isAllowedServer module.exports.checkWordMute = checkWordMute module.exports.getFullApAccount = getFullApAccount module.exports.isSelfHost = isSelfHost @@ -349,6 +352,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/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/mod.rs b/packages/backend-rs/src/config/mod.rs index b708f2b265..6155f15e54 100644 --- a/packages/backend-rs/src/config/mod.rs +++ b/packages/backend-rs/src/config/mod.rs @@ -1,2 +1,4 @@ +pub use server::CONFIG; + pub mod environment; pub mod server; diff --git a/packages/backend-rs/src/config/server.rs b/packages/backend-rs/src/config/server.rs index 125bae90b9..5a4ee481cd 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, pub cuid: Option, pub outgoing_address: Option, @@ -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)] @@ -94,10 +93,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 WorkerConfigInternal { pub web: Option, pub queue: Option, } @@ -167,17 +172,207 @@ 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 redis_key_prefix: 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 hostname = url + .host_str() + .expect("Hostname 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"); + + 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 }, + }; + + 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, + 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, + redis_key_prefix, + 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..7a6277068b 100644 --- a/packages/backend-rs/src/database/mod.rs +++ b/packages/backend-rs/src/database/mod.rs @@ -1,34 +1,6 @@ -use crate::config::server::SERVER_CONFIG; -use sea_orm::{Database, DbConn, DbErr}; +pub use postgresql::db_conn; +pub use redis::key as redis_key; +pub use redis::redis_conn; -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://{}:{}@{}:{}/{}", - SERVER_CONFIG.db.user, - urlencoding::encode(&SERVER_CONFIG.db.pass), - SERVER_CONFIG.db.host, - SERVER_CONFIG.db.port, - SERVER_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 mod postgresql; +pub mod redis; diff --git a/packages/backend-rs/src/database/postgresql.rs b/packages/backend-rs/src/database/postgresql.rs new file mode 100644 index 0000000000..ec0945fbe3 --- /dev/null +++ b/packages/backend-rs/src/database/postgresql.rs @@ -0,0 +1,35 @@ +use crate::config::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() { + assert!(db_conn().await.is_ok()); + assert!(db_conn().await.is_ok()); + } +} diff --git a/packages/backend-rs/src/database/redis.rs b/packages/backend-rs/src/database/redis.rs new file mode 100644 index 0000000000..f8f6c712de --- /dev/null +++ b/packages/backend-rs/src/database/redis.rs @@ -0,0 +1,68 @@ +use crate::config::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()]; + + 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) = &redis.pass { + params.push(format!(":{}@", pass)) + } + params.push(redis.host.to_string()); + params.push(format!(":{}", redis.port)); + params.push(format!("/{}", 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 +pub fn key(key: impl ToString) -> String { + format!("{}:{}", CONFIG.redis_key_prefix, key.to_string()) +} + +#[cfg(test)] +mod unit_test { + use super::redis_conn; + use pretty_assertions::assert_eq; + use redis::Commands; + + #[test] + fn connect() { + assert!(redis_conn().is_ok()); + assert!(redis_conn().is_ok()); + } + + #[test] + fn access() { + let mut redis = redis_conn().unwrap(); + + let key = "CARGO_UNIT_TEST_KEY"; + let value = "CARGO_UNIT_TEST_VALUE"; + + assert_eq!(redis.set::<&str, &str, String>(key, value).unwrap(), "OK"); + assert_eq!(redis.get::<&str, String>(key).unwrap(), value); + assert_eq!(redis.del::<&str, u32>(key).unwrap(), 1); + } +} 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/misc/check_server_block.rs b/packages/backend-rs/src/misc/check_server_block.rs new file mode 100644 index 0000000000..b5e262aa87 --- /dev/null +++ b/packages/backend-rs/src/misc/check_server_block.rs @@ -0,0 +1,49 @@ +use crate::misc::meta::fetch_meta; +use sea_orm::DbErr; + +/** + * @param host punycoded instance host + * @returns whether the given host should be blocked + */ +#[crate::export] +pub async fn is_blocked_server(host: &str) -> Result { + Ok(fetch_meta(true) + .await? + .blocked_hosts + .iter() + .any(|blocked_host| { + host == blocked_host || host.ends_with(format!(".{}", blocked_host).as_str()) + })) +} + +/** + * @param host punycoded instance host + * @returns whether the given host should be limited + */ +#[crate::export] +pub async fn is_silenced_server(host: &str) -> Result { + Ok(fetch_meta(true) + .await? + .silenced_hosts + .iter() + .any(|silenced_host| { + host == silenced_host || host.ends_with(format!(".{}", silenced_host).as_str()) + })) +} + +/** + * @param host punycoded instance host + * @returns whether the given host is allowlisted (this is always true if private mode is disabled) + */ +#[crate::export] +pub async fn is_allowed_server(host: &str) -> Result { + let meta = fetch_meta(true).await?; + + if !meta.private_mode.unwrap_or(false) { + return Ok(true); + } + if let Some(allowed_hosts) = meta.allowed_hosts { + return Ok(allowed_hosts.contains(&host.to_string())); + } + Ok(false) +} diff --git a/packages/backend-rs/src/misc/convert_host.rs b/packages/backend-rs/src/misc/convert_host.rs index 34a0792c62..8f054488de 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::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-rs/src/misc/mod.rs b/packages/backend-rs/src/misc/mod.rs index a9d7074dbf..24cec14969 100644 --- a/packages/backend-rs/src/misc/mod.rs +++ b/packages/backend-rs/src/misc/mod.rs @@ -1,4 +1,5 @@ pub mod acct; +pub mod check_server_block; pub mod check_word_mute; pub mod convert_host; pub mod emoji; @@ -10,3 +11,4 @@ pub mod meta; pub mod nyaify; pub mod password; pub mod reaction; +pub mod redis_cache; diff --git a/packages/backend-rs/src/misc/redis_cache.rs b/packages/backend-rs/src/misc/redis_cache.rs new file mode 100644 index 0000000000..d4924bb646 --- /dev/null +++ b/packages/backend-rs/src/misc/redis_cache.rs @@ -0,0 +1,84 @@ +use crate::database::{redis_conn, redis_key}; +use redis::{Commands, RedisError}; +use serde::{Deserialize, Serialize}; + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("Redis error: {0}")] + RedisError(#[from] RedisError), + #[error("Data serialization error: {0}")] + SerializeError(#[from] rmp_serde::encode::Error), + #[error("Data deserialization error: {0}")] + DeserializeError(#[from] rmp_serde::decode::Error), +} + +pub fn set_cache Deserialize<'a> + Serialize>( + key: &str, + value: &V, + expire_seconds: u64, +) -> Result<(), Error> { + redis_conn()?.set_ex( + redis_key(key), + rmp_serde::encode::to_vec(&value)?, + expire_seconds, + )?; + Ok(()) +} + +pub fn get_cache Deserialize<'a> + Serialize>(key: &str) -> Result, Error> { + let serialized_value: Option> = redis_conn()?.get(redis_key(key))?; + Ok(match serialized_value { + Some(v) => Some(rmp_serde::from_slice::(v.as_ref())?), + None => None, + }) +} + +#[cfg(test)] +mod unit_test { + use super::{get_cache, set_cache}; + use pretty_assertions::assert_eq; + + #[test] + fn set_get_expire() { + #[derive(serde::Deserialize, serde::Serialize, PartialEq, Debug)] + struct Data { + id: u32, + kind: String, + } + + let key_1 = "CARGO_TEST_CACHE_KEY_1"; + let value_1: Vec = vec![1, 2, 3, 4, 5]; + + let key_2 = "CARGO_TEST_CACHE_KEY_2"; + let value_2 = "Hello fedizens".to_string(); + + let key_3 = "CARGO_TEST_CACHE_KEY_3"; + let value_3 = Data { + id: 1000000007, + kind: "prime number".to_string(), + }; + + set_cache(key_1, &value_1, 1).unwrap(); + set_cache(key_2, &value_2, 1).unwrap(); + set_cache(key_3, &value_3, 1).unwrap(); + + let cached_value_1: Vec = get_cache(key_1).unwrap().unwrap(); + let cached_value_2: String = get_cache(key_2).unwrap().unwrap(); + let cached_value_3: Data = get_cache(key_3).unwrap().unwrap(); + + assert_eq!(value_1, cached_value_1); + assert_eq!(value_2, cached_value_2); + assert_eq!(value_3, cached_value_3); + + // wait for the cache to expire + std::thread::sleep(std::time::Duration::from_millis(1100)); + + let expired_value_1: Option> = get_cache(key_1).unwrap(); + let expired_value_2: Option> = get_cache(key_2).unwrap(); + let expired_value_3: Option> = get_cache(key_3).unwrap(); + + assert!(expired_value_1.is_none()); + assert!(expired_value_2.is_none()); + assert!(expired_value_3.is_none()); + } +} 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..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)] +#[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 3083bb8c90..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)] +#[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 98ec50ea91..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)] +#[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 311571c113..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)] +#[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 157e402aa6..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)] +#[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 1edd6e8761..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)] +#[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/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..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)] +#[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 0c131066dd..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)] +#[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 f022a5e632..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)] +#[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 2f5a3e0482..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)] +#[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 52f8059030..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)] +#[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 01a25ccb83..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)] +#[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 0a41efd3e8..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)] +#[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 6cbbcf4756..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)] +#[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 262f4a9b50..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)] +#[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 a6926e7af2..699fa182a5 100644 --- a/packages/backend-rs/src/model/entity/drive_file.rs +++ b/packages/backend-rs/src/model/entity/drive_file.rs @@ -3,7 +3,8 @@ use super::sea_orm_active_enums::DriveFileUsageHintEnum; use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[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 727a698ce3..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)] +#[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 530dfe12f5..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)] +#[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 4a6b572433..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)] +#[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 f19e46140e..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)] +#[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 f4ede4169a..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)] +#[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 797bf38242..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)] +#[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 e2bb816b26..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)] +#[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 8b598f72b1..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)] +#[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 304f876d1a..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)] +#[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 fcba9e0be9..3bf205d040 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)] +#[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 235156ba4e..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)] +#[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 b76f2c33df..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)] +#[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 7c2880a03d..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)] +#[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 917e6a2e20..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)] +#[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 5903216c1a..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)] +#[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 edfb35029a..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)] +#[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 76d45e9e98..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)] +#[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 2c52a4e5e8..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)] +#[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 dd870a3e7f..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)] +#[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 965001189e..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)] +#[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 ba96aed69f..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)] +#[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 5b3b331e90..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)] +#[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 6ed5f718aa..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)] +#[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 e1652a372b..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)] +#[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 c1e59ef0e1..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)] +#[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 058eaedebe..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)] +#[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 6bcbcac08b..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)] +#[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 0f2df2f5db..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)] +#[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 c4e012b1a9..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)] +#[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 10fe176405..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)] +#[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 55d60d78b0..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)] +#[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 74ae18cef3..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)] +#[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 c035a74bec..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)] +#[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 b6604cad88..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)] +#[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 84fe0cbbfa..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)] +#[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 36281f4dc5..a9c974b9c4 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)] +#[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)] +#[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( @@ -34,7 +40,10 @@ pub enum DriveFileUsageHintEnum { #[sea_orm(string_value = "userBanner")] UserBanner, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[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( @@ -52,7 +61,10 @@ pub enum MutedNoteReasonEnum { #[sea_orm(string_value = "word")] Word, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[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( @@ -72,7 +84,10 @@ pub enum NoteVisibilityEnum { #[sea_orm(string_value = "specified")] Specified, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[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( @@ -106,7 +121,10 @@ pub enum NotificationTypeEnum { #[sea_orm(string_value = "reply")] Reply, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[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( @@ -122,7 +140,10 @@ pub enum PageVisibilityEnum { #[sea_orm(string_value = "specified")] Specified, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[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( @@ -140,7 +161,10 @@ pub enum PollNotevisibilityEnum { #[sea_orm(string_value = "specified")] Specified, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[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")] @@ -152,7 +176,10 @@ pub enum RelayStatusEnum { #[sea_orm(string_value = "requesting")] Requesting, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[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( @@ -170,7 +197,10 @@ pub enum UserEmojimodpermEnum { #[sea_orm(string_value = "unauthorized")] Unauthorized, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[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( @@ -186,7 +216,10 @@ pub enum UserProfileFfvisibilityEnum { #[sea_orm(string_value = "public")] Public, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[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 491f079a82..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)] +#[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 4aa275f77b..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)] +#[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 9e108a8a4f..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)] +#[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 8af0b27e88..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)] +#[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 7d9ae71b24..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)] +#[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 c449a48078..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)] +#[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 3df43af3f6..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)] +#[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 2ff31b3a5f..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)] +#[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 d6eadc7f71..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)] +#[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 d59853158a..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)] +#[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 356ec5318c..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)] +#[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 037d7af181..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)] +#[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 f0a80a66c9..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)] +#[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 1fa13c2829..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)] +#[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 a121118926..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)] +#[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 ad6a456ead..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)] +#[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 aae6dfa8c6..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)] +#[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 e7656056b9..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)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "webhook")] #[cfg_attr( feature = "napi", 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..4f294cc881 --- /dev/null +++ b/packages/backend-rs/src/service/add_note_to_antenna.rs @@ -0,0 +1,23 @@ +use crate::database::{redis_conn, redis_key}; +use crate::model::entity::note; +use crate::service::stream::{publish_to_stream, Error, Stream}; +use crate::util::id::get_timestamp; +use redis::{streams::StreamMaxlen, Commands}; + +type Note = note::Model; + +#[crate::export] +pub fn add_note_to_antenna(antenna_id: String, note: &Note) -> Result<(), Error> { + redis_conn()?.xadd_maxlen( + redis_key(format!("antennaTimeline:{}", antenna_id)), + StreamMaxlen::Approx(200), + format!("{}-*", get_timestamp(¬e.id)), + &[("note", ¬e.id)], + )?; + + publish_to_stream( + &Stream::Antenna { antenna_id }, + Some("note"), + Some(serde_json::to_string(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..6c5e6be4dd --- /dev/null +++ b/packages/backend-rs/src/service/stream.rs @@ -0,0 +1,93 @@ +use crate::config::CONFIG; +use crate::database::redis_conn; +use redis::{Commands, RedisError}; + +#[derive(strum::Display)] +pub enum Stream { + #[strum(serialize = "internal")] + Internal, + #[strum(serialize = "broadcast")] + Broadcast, + #[strum(to_string = "adminStream:{user_id}")] + Admin { user_id: String }, + #[strum(to_string = "user:{user_id}")] + User { user_id: String }, + #[strum(to_string = "channelStream:{channel_id}")] + Channel { channel_id: String }, + #[strum(to_string = "noteStream:{note_id}")] + Note { note_id: String }, + #[strum(serialize = "notesStream")] + Notes, + #[strum(to_string = "userListStream:{list_id}")] + UserList { list_id: String }, + #[strum(to_string = "mainStream:{user_id}")] + Main { user_id: String }, + #[strum(to_string = "driveStream:{user_id}")] + Drive { user_id: String }, + #[strum(to_string = "antennaStream:{antenna_id}")] + Antenna { antenna_id: String }, + #[strum(to_string = "messagingStream:{sender_user_id}-{receiver_user_id}")] + Chat { + sender_user_id: String, + receiver_user_id: String, + }, + #[strum(to_string = "messagingStream:{group_id}")] + GroupChat { group_id: String }, + #[strum(to_string = "messagingIndexStream:{user_id}")] + MessagingIndex { user_id: String }, +} + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("Redis error: {0}")] + RedisError(#[from] RedisError), + #[error("Json (de)serialization error: {0}")] + JsonError(#[from] serde_json::Error), + #[error("Value error: {0}")] + ValueError(String), +} + +pub fn publish_to_stream( + stream: &Stream, + kind: Option<&str>, + value: Option, +) -> Result<(), Error> { + let message = if let Some(kind) = kind { + format!( + "{{ \"type\": \"{}\", \"body\": {} }}", + kind, + value.unwrap_or("null".to_string()), + ) + } else { + value.ok_or(Error::ValueError("Invalid streaming message".to_string()))? + }; + + redis_conn()?.publish( + &CONFIG.host, + format!( + "{{ \"channel\": \"{}\", \"message\": {} }}", + stream, message, + ), + )?; + + 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 { + user_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/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..f254aaea17 100644 --- a/packages/backend/src/boot/master.ts +++ b/packages/backend/src/boot/master.ts @@ -8,9 +8,9 @@ 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 { fetchMeta } 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 +87,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( @@ -127,6 +124,9 @@ export async function masterMain() { import("../daemons/queue-stats.js").then((x) => x.default()); import("../daemons/janitor.js").then((x) => x.default()); } + + // Update meta cache every 5 minitues + setInterval(() => fetchMeta(false), 1000 * 60 * 5); } function showEnvironment(): void { @@ -154,28 +154,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"); @@ -195,23 +173,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"); 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..1295136054 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"; @@ -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); diff --git a/packages/backend/src/db/redis.ts b/packages/backend/src/db/redis.ts index 215effd8ea..72c23d84e2 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; @@ -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, }); 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..f516265106 100644 --- a/packages/backend/src/misc/download-url.ts +++ b/packages/backend/src/misc/download-url.ts @@ -2,8 +2,8 @@ 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 config from "@/config/index.js"; +import { config } from "@/config.js"; +import { getAgentByHostname, StatusError } from "./fetch.js"; import chalk from "chalk"; import Logger from "@/services/logger.js"; import IPCIDR from "ip-cidr"; @@ -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..1f8c70a196 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( @@ -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; 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/misc/should-block-instance.ts b/packages/backend/src/misc/should-block-instance.ts deleted file mode 100644 index 465be41f2a..0000000000 --- a/packages/backend/src/misc/should-block-instance.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { fetchMeta } from "backend-rs"; -import type { Instance } from "@/models/entities/instance.js"; -import type { Meta } from "@/models/entities/meta.js"; - -/** - * Returns whether a specific host (punycoded) should be blocked. - * - * @param host punycoded instance host - * @param meta a resolved Meta table - * @returns whether the given host should be blocked - */ -export async function shouldBlockInstance( - host: Instance["host"], - meta?: Meta, -): Promise { - const { blockedHosts } = meta ?? (await fetchMeta(true)); - return blockedHosts.some( - (blockedHost) => host === blockedHost || host.endsWith(`.${blockedHost}`), - ); -} - -/** - * Returns whether a specific host (punycoded) should be limited. - * - * @param host punycoded instance host - * @param meta a resolved Meta table - * @returns whether the given host should be limited - */ -export async function shouldSilenceInstance( - host: Instance["host"], - meta?: Meta, -): Promise { - const { silencedHosts } = meta ?? (await fetchMeta(true)); - return silencedHosts.some( - (silencedHost) => - host === silencedHost || host.endsWith(`.${silencedHost}`), - ); -} diff --git a/packages/backend/src/misc/skipped-instances.ts b/packages/backend/src/misc/skipped-instances.ts index 14b26a3032..0c87a524f6 100644 --- a/packages/backend/src/misc/skipped-instances.ts +++ b/packages/backend/src/misc/skipped-instances.ts @@ -1,9 +1,8 @@ import { Brackets } from "typeorm"; -import { fetchMeta } from "backend-rs"; +import { isBlockedServer } from "backend-rs"; import { Instances } from "@/models/index.js"; import type { Instance } from "@/models/entities/instance.js"; import { DAY } from "@/const.js"; -import { shouldBlockInstance } from "./should-block-instance.js"; // Threshold from last contact after which an instance will be considered // "dead" and should no longer get activities delivered to it. @@ -19,16 +18,16 @@ export async function skippedInstances( hosts: Instance["host"][], ): Promise { // first check for blocked instances since that info may already be in memory - const meta = await fetchMeta(true); const shouldSkip = await Promise.all( - hosts.map((host) => shouldBlockInstance(host, meta)), + hosts.map((host) => isBlockedServer(host)), ); const skipped = hosts.filter((_, i) => shouldSkip[i]); // if possible return early and skip accessing the database if (skipped.length === hosts.length) return hosts; - const deadTime = new Date(Date.now() - deadThreshold); + // FIXME: Use or remove this + // const deadTime = new Date(Date.now() - deadThreshold); return skipped.concat( await Instances.createQueryBuilder("instance") diff --git a/packages/backend/src/models/repositories/drive-file.ts b/packages/backend/src/models/repositories/drive-file.ts index 18b139caff..ac0b1e5f17 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/instance.ts b/packages/backend/src/models/repositories/instance.ts index 667ec948de..8f479e8ea4 100644 --- a/packages/backend/src/models/repositories/instance.ts +++ b/packages/backend/src/models/repositories/instance.ts @@ -1,10 +1,7 @@ import { db } from "@/db/postgre.js"; import { Instance } from "@/models/entities/instance.js"; import type { Packed } from "@/misc/schema.js"; -import { - shouldBlockInstance, - shouldSilenceInstance, -} from "@/misc/should-block-instance.js"; +import { isBlockedServer, isSilencedServer } from "backend-rs"; export const InstanceRepository = db.getRepository(Instance).extend({ async pack(instance: Instance): Promise> { @@ -22,8 +19,8 @@ export const InstanceRepository = db.getRepository(Instance).extend({ lastCommunicatedAt: instance.lastCommunicatedAt.toISOString(), isNotResponding: instance.isNotResponding, isSuspended: instance.isSuspended, - isBlocked: await shouldBlockInstance(instance.host), - isSilenced: await shouldSilenceInstance(instance.host), + isBlocked: await isBlockedServer(instance.host), + isSilenced: await isSilencedServer(instance.host), softwareName: instance.softwareName, softwareVersion: instance.softwareVersion, openRegistrations: instance.openRegistrations, 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/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", 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/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 a874005fbd..32cc0005e9 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/inbox.ts b/packages/backend/src/queue/processors/inbox.ts index 0ea72306b6..898c68cff3 100644 --- a/packages/backend/src/queue/processors/inbox.ts +++ b/packages/backend/src/queue/processors/inbox.ts @@ -5,7 +5,7 @@ import perform from "@/remote/activitypub/perform.js"; import Logger from "@/services/logger.js"; import { registerOrFetchInstanceDoc } from "@/services/register-or-fetch-instance-doc.js"; import { Instances } from "@/models/index.js"; -import { fetchMeta } from "backend-rs"; +import { isAllowedServer, isBlockedServer } from "backend-rs"; import { toPuny, extractHost } from "backend-rs"; import { getApId } from "@/remote/activitypub/type.js"; import { fetchInstanceMetadata } from "@/services/fetch-instance-metadata.js"; @@ -16,7 +16,6 @@ import { LdSignature } from "@/remote/activitypub/misc/ld-signature.js"; import { StatusError } from "@/misc/fetch.js"; import type { CacheableRemoteUser } from "@/models/entities/user.js"; import type { UserPublickey } from "@/models/entities/user-publickey.js"; -import { shouldBlockInstance } from "@/misc/should-block-instance.js"; import { verifySignature } from "@/remote/activitypub/check-fetch.js"; import { inspect } from "node:util"; @@ -41,13 +40,12 @@ export default async (job: Bull.Job): Promise => { const host = toPuny(new URL(signature.keyId).hostname); // interrupt if blocked - const meta = await fetchMeta(true); - if (await shouldBlockInstance(host, meta)) { + if (await isBlockedServer(host)) { return `Blocked request: ${host}`; } // only whitelisted instances in private mode - if (meta.privateMode && !meta.allowedHosts.includes(host)) { + if (!isAllowedServer(host)) { return `Blocked request: ${host}`; } @@ -158,7 +156,7 @@ export default async (job: Bull.Job): Promise => { // ブロックしてたら中断 const ldHost = extractHost(authUser.user.uri); - if (await shouldBlockInstance(ldHost, meta)) { + if (await isBlockedServer(ldHost)) { return `Blocked request: ${ldHost}`; } } else { 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..726d996ad8 100644 --- a/packages/backend/src/remote/activitypub/check-fetch.ts +++ b/packages/backend/src/remote/activitypub/check-fetch.ts @@ -1,11 +1,10 @@ import { URL } from "url"; -import httpSignature, { IParsedSignature } from "@peertube/http-signature"; -import config from "@/config/index.js"; -import { fetchMeta } from "backend-rs"; +import httpSignature, { type IParsedSignature } from "@peertube/http-signature"; +import { config } from "@/config.js"; +import { fetchMeta, isAllowedServer, isBlockedServer } from "backend-rs"; import { toPuny } from "backend-rs"; import DbResolver from "@/remote/activitypub/db-resolver.js"; import { getApId } from "@/remote/activitypub/type.js"; -import { shouldBlockInstance } from "@/misc/should-block-instance.js"; import type { IncomingMessage } from "http"; import type { CacheableRemoteUser } from "@/models/entities/user.js"; import type { UserPublickey } from "@/models/entities/user-publickey.js"; @@ -44,15 +43,11 @@ export async function checkFetch(req: IncomingMessage): Promise { const keyId = new URL(signature.keyId); const host = toPuny(keyId.hostname); - if (await shouldBlockInstance(host, meta)) { + if (await isBlockedServer(host)) { return 403; } - if ( - meta.privateMode && - host !== config.host && - !meta.allowedHosts.includes(host) - ) { + if (host !== config.host && !isAllowedServer(host)) { return 403; } 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/announce/note.ts b/packages/backend/src/remote/activitypub/kernel/announce/note.ts index ae16c77dbd..41d1319dbd 100644 --- a/packages/backend/src/remote/activitypub/kernel/announce/note.ts +++ b/packages/backend/src/remote/activitypub/kernel/announce/note.ts @@ -10,7 +10,7 @@ import { getApLock } from "@/misc/app-lock.js"; import { parseAudience } from "../../audience.js"; import { StatusError } from "@/misc/fetch.js"; import { Notes } from "@/models/index.js"; -import { shouldBlockInstance } from "@/misc/should-block-instance.js"; +import { isBlockedServer } from "backend-rs"; import { inspect } from "node:util"; const logger = apLogger; @@ -31,7 +31,7 @@ export default async function ( } // Interrupt if you block the announcement destination - if (await shouldBlockInstance(extractHost(uri))) return; + if (await isBlockedServer(extractHost(uri))) return; const lock = await getApLock(uri); 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/kernel/index.ts b/packages/backend/src/remote/activitypub/kernel/index.ts index f64a0e2ee8..b556550c5f 100644 --- a/packages/backend/src/remote/activitypub/kernel/index.ts +++ b/packages/backend/src/remote/activitypub/kernel/index.ts @@ -38,8 +38,7 @@ import block from "./block/index.js"; import flag from "./flag/index.js"; import move from "./move/index.js"; import type { IObject, IActivity } from "../type.js"; -import { extractHost } from "backend-rs"; -import { shouldBlockInstance } from "@/misc/should-block-instance.js"; +import { extractHost, isBlockedServer } from "backend-rs"; import { inspect } from "node:util"; export async function performActivity( @@ -71,7 +70,7 @@ async function performOneActivity( if (typeof activity.id !== "undefined") { const host = extractHost(getApId(activity)); - if (await shouldBlockInstance(host)) return; + if (await isBlockedServer(host)) return; } if (isCreate(activity)) { diff --git a/packages/backend/src/remote/activitypub/models/note.ts b/packages/backend/src/remote/activitypub/models/note.ts index b2fd67288c..4b685747ba 100644 --- a/packages/backend/src/remote/activitypub/models/note.ts +++ b/packages/backend/src/remote/activitypub/models/note.ts @@ -12,7 +12,7 @@ import { unique, toArray, toSingle } from "@/prelude/array.js"; import { extractPollFromQuestion } from "./question.js"; import vote from "@/services/note/polls/vote.js"; import { apLogger } from "../logger.js"; -import { DriveFile } from "@/models/entities/drive-file.js"; +import type { DriveFile } from "@/models/entities/drive-file.js"; import { extractHost, isSameOrigin, toPuny } from "backend-rs"; import { Emojis, @@ -33,14 +33,13 @@ import { getApType, } from "../type.js"; import type { Emoji } from "@/models/entities/emoji.js"; -import { genId } from "backend-rs"; +import { genId, isBlockedServer } from "backend-rs"; import { getApLock } from "@/misc/app-lock.js"; import { createMessage } from "@/services/messages/create.js"; import { parseAudience } from "../audience.js"; import { extractApMentions } from "./mention.js"; import DbResolver from "../db-resolver.js"; import { StatusError } from "@/misc/fetch.js"; -import { shouldBlockInstance } from "@/misc/should-block-instance.js"; import { publishNoteStream } from "@/services/stream.js"; import { extractHashtags } from "@/misc/extract-hashtags.js"; import { UserProfiles } from "@/models/index.js"; @@ -421,7 +420,7 @@ export async function resolveNote( if (uri == null) throw new Error("missing uri"); // Abort if origin host is blocked - if (await shouldBlockInstance(extractHost(uri))) + if (await isBlockedServer(extractHost(uri))) throw new StatusError( "host blocked", 451, 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..51419deecf 100644 --- a/packages/backend/src/remote/activitypub/resolver.ts +++ b/packages/backend/src/remote/activitypub/resolver.ts @@ -1,8 +1,12 @@ -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"; -import { extractHost, isSelfHost } from "backend-rs"; +import { + extractHost, + isAllowedServer, + isBlockedServer, + isSelfHost, +} from "backend-rs"; import { apGet } from "./request.js"; import type { IObject, ICollection, IOrderedCollection } from "./type.js"; import { isCollectionOrOrderedCollection, getApId } from "./type.js"; @@ -21,7 +25,6 @@ import renderQuestion from "@/remote/activitypub/renderer/question.js"; import renderCreate from "@/remote/activitypub/renderer/create.js"; import { renderActivity } from "@/remote/activitypub/renderer/index.js"; import renderFollow from "@/remote/activitypub/renderer/follow.js"; -import { shouldBlockInstance } from "@/misc/should-block-instance.js"; import { apLogger } from "@/remote/activitypub/logger.js"; import { IsNull, Not } from "typeorm"; @@ -69,7 +72,7 @@ export default class Resolver { apLogger.debug("Object to resolve is not a string"); if (typeof value.id !== "undefined") { const host = extractHost(getApId(value)); - if (await shouldBlockInstance(host)) { + if (await isBlockedServer(host)) { throw new Error("instance is blocked"); } } @@ -100,17 +103,12 @@ export default class Resolver { return await this.resolveLocal(value); } - const meta = await fetchMeta(true); - if (await shouldBlockInstance(host, meta)) { - throw new Error("Instance is blocked"); + if (await isBlockedServer(host)) { + throw new Error("This instance is blocked"); } - if ( - meta.privateMode && - config.host !== host && - !meta.allowedHosts.includes(host) - ) { - throw new Error("Instance is not allowed"); + if (config.host !== host && !isAllowedServer(host)) { + throw new Error("This instance is not allowed"); } if (!this.user) { 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 71d95709b7..1e070f91f9 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 type 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 ab04800944..ecfed950d3 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/ap/show.ts b/packages/backend/src/server/api/endpoints/ap/show.ts index f1d42d8d93..56307311b2 100644 --- a/packages/backend/src/server/api/endpoints/ap/show.ts +++ b/packages/backend/src/server/api/endpoints/ap/show.ts @@ -4,14 +4,13 @@ import { createNote } from "@/remote/activitypub/models/note.js"; import DbResolver from "@/remote/activitypub/db-resolver.js"; import Resolver from "@/remote/activitypub/resolver.js"; import { ApiError } from "@/server/api/error.js"; -import { extractHost } from "backend-rs"; +import { extractHost, isBlockedServer } from "backend-rs"; import { Users, Notes } from "@/models/index.js"; import type { Note } from "@/models/entities/note.js"; import type { CacheableLocalUser, User } from "@/models/entities/user.js"; import { isActor, isPost, getApId } from "@/remote/activitypub/type.js"; import type { SchemaType } from "@/misc/schema.js"; import { MINUTE } from "@/const.js"; -import { shouldBlockInstance } from "@/misc/should-block-instance.js"; import { updateQuestion } from "@/remote/activitypub/models/question.js"; import { populatePoll } from "@/models/repositories/note.js"; import { redisClient } from "@/db/redis.js"; @@ -101,7 +100,7 @@ async function fetchAny( me: CacheableLocalUser | null | undefined, ): Promise | null> { // Wait if blocked. - if (await shouldBlockInstance(extractHost(uri))) return null; + if (await isBlockedServer(extractHost(uri))) return null; const dbResolver = new DbResolver(); 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 ec8f701976..f35ae9cc6b 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/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"; 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..3beffc82f0 100644 --- a/packages/backend/src/server/web/feed.ts +++ b/packages/backend/src/server/web/feed.ts @@ -1,8 +1,17 @@ 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 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. + */ +function escapeCDATA(str: string) { + return str.replaceAll("]]>", "]]]]>"); +} export default async function ( user: User, @@ -15,7 +24,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 +53,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 +99,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 +150,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 += ` { 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/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/create-notification.ts b/packages/backend/src/services/create-notification.ts index a108d4f5de..93fec126d3 100644 --- a/packages/backend/src/services/create-notification.ts +++ b/packages/backend/src/services/create-notification.ts @@ -8,11 +8,10 @@ import { Users, Followings, } from "@/models/index.js"; -import { genId } from "backend-rs"; +import { genId, isSilencedServer } from "backend-rs"; import type { User } from "@/models/entities/user.js"; import type { Notification } from "@/models/entities/notification.js"; import { sendEmailNotification } from "./send-email-notification.js"; -import { shouldSilenceInstance } from "@/misc/should-block-instance.js"; export async function createNotification( notifieeId: User["id"], @@ -35,8 +34,8 @@ export async function createNotification( if ( (notifier.isSilenced || (Users.isRemoteUser(notifier) && - (await shouldSilenceInstance(notifier.host)))) && - !(await Followings.exist({ + (await isSilencedServer(notifier.host)))) && + !(await Followings.exists({ where: { followerId: notifieeId, followeeId: data.notifierId }, })) ) 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 70faa01aa7..88f9c2ab1e 100644 --- a/packages/backend/src/services/fetch-rel-me.ts +++ b/packages/backend/src/services/fetch-rel-me.ts @@ -1,6 +1,6 @@ import { Window } from "happy-dom"; import type { HTMLAnchorElement, HTMLLinkElement } 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/create.ts b/packages/backend/src/services/following/create.ts index 7387346d1a..49852ee9ef 100644 --- a/packages/backend/src/services/following/create.ts +++ b/packages/backend/src/services/following/create.ts @@ -17,13 +17,12 @@ import { Instances, UserProfiles, } from "@/models/index.js"; -import { genId } from "backend-rs"; +import { genId, isSilencedServer } from "backend-rs"; import { createNotification } from "@/services/create-notification.js"; import { isDuplicateKeyValueError } from "@/misc/is-duplicate-key-value-error.js"; import type { Packed } from "@/misc/schema.js"; import { getActiveWebhooks } from "@/misc/webhook-cache.js"; import { webhookDeliver } from "@/queue/index.js"; -import { shouldSilenceInstance } from "@/misc/should-block-instance.js"; const logger = new Logger("following/create"); @@ -231,7 +230,7 @@ export default async function ( (Users.isLocalUser(follower) && Users.isRemoteUser(followee)) || (Users.isRemoteUser(follower) && Users.isLocalUser(followee) && - (await shouldSilenceInstance(follower.host))) + (await isSilencedServer(follower.host))) ) { let autoAccept = false; 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 f4b4454ef8..aec4542b82 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..2135847a17 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"; @@ -37,15 +37,18 @@ import type { DriveFile } from "@/models/entities/drive-file.js"; import type { App } from "@/models/entities/app.js"; import { Not, In } from "typeorm"; import type { User, ILocalUser, IRemoteUser } from "@/models/entities/user.js"; -import { genId } from "backend-rs"; import { activeUsersChart } from "@/services/chart/index.js"; import type { IPoll } from "@/models/entities/poll.js"; 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, + genId, + isSilencedServer, +} 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"; @@ -57,12 +60,12 @@ import { Cache } from "@/misc/cache.js"; import type { UserProfile } from "@/models/entities/user-profile.js"; import { db } from "@/db/postgre.js"; import { getActiveWebhooks } from "@/misc/webhook-cache.js"; -import { shouldSilenceInstance } from "@/misc/should-block-instance.js"; import { redisClient } from "@/db/redis.js"; 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"); @@ -225,7 +228,7 @@ export default async ( if ( data.visibility === "public" && Users.isRemoteUser(user) && - (await shouldSilenceInstance(user.host)) + (await isSilencedServer(user.host)) ) { data.visibility = "home"; } @@ -399,7 +402,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/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..7f1862b74d 100644 --- a/packages/backend/src/services/stream.ts +++ b/packages/backend/src/services/stream.ts @@ -3,13 +3,13 @@ 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 type { Antenna } from "@/models/entities/antenna.js"; +import { config } from "@/config.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,18 @@ class Publisher { ); }; - public publishAntennaStream = ( - antennaId: Antenna["id"], - type: K, - value?: AntennaStreamTypes[K], - ): void => { - this.publish( - `antennaStream:${antennaId}`, - type, - typeof value === "undefined" ? null : value, - ); - }; + /* ported to backend-rs */ + // 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 +218,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/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"; diff --git a/packages/client/src/components/MkFollowButton.vue b/packages/client/src/components/MkFollowButton.vue index 0920001c7b..4e2d884749 100644 --- a/packages/client/src/components/MkFollowButton.vue +++ b/packages/client/src/components/MkFollowButton.vue @@ -8,7 +8,7 @@