Merge branch 'develop' into 'main'
release: v20240728 Co-authored-by: 老周部落 <laozhoubuluo@gmail.com> Co-authored-by: GitLab CI <project_7_bot_1bfaee5701aed20091a86249a967a6c1@noreply.firefish.dev> See merge request firefish/firefish!11211
This commit is contained in:
commit
22b89fe3bd
185 changed files with 2004 additions and 1823 deletions
|
@ -40,6 +40,7 @@ packages/backend/assets/instance.css
|
|||
.gitattributes
|
||||
.weblate
|
||||
animated.svg
|
||||
compose.yml
|
||||
docker-compose.yml
|
||||
docker-compose.example.yml
|
||||
title.svg
|
||||
|
@ -48,6 +49,7 @@ title.svg
|
|||
/dev
|
||||
/docs
|
||||
/scripts
|
||||
!/scripts/copy-index.mjs
|
||||
!/scripts/copy-assets.mjs
|
||||
biome.json
|
||||
CODE_OF_CONDUCT.md
|
||||
|
|
2
.vscode/extensions.json
vendored
2
.vscode/extensions.json
vendored
|
@ -15,7 +15,7 @@
|
|||
"biomejs.biome",
|
||||
"rust-lang.rust-analyzer",
|
||||
"vadimcn.vscode-lldb",
|
||||
"serayuzgur.crates",
|
||||
"fill-labs.dependi",
|
||||
"tamasfe.even-better-toml",
|
||||
"aaron-bond.better-comments"
|
||||
]
|
||||
|
|
63
Cargo.lock
generated
63
Cargo.lock
generated
|
@ -84,6 +84,12 @@ version = "1.3.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110"
|
||||
|
||||
[[package]]
|
||||
name = "arc-swap"
|
||||
version = "1.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
|
||||
|
||||
[[package]]
|
||||
name = "arg_enum_proc_macro"
|
||||
version = "0.3.4"
|
||||
|
@ -871,9 +877,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "emojis"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f619a926616ae7149a0d82610b051134a0d6c4ae2962d990c06c847a445c5d9"
|
||||
checksum = "e72f23d65b46527e461b161ab9a126c378aa2249d8a8d15718d23ab1fb4d8786"
|
||||
dependencies = [
|
||||
"phf",
|
||||
]
|
||||
|
@ -1576,9 +1582,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
|||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.31"
|
||||
version = "0.1.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e"
|
||||
checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
@ -1768,6 +1774,8 @@ dependencies = [
|
|||
"quote",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"syn 2.0.72",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1919,14 +1927,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "nom-exif"
|
||||
version = "1.2.6"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3dac386e49252f313c88764101ca16681caa4a5b0260d494d58b6af7f04edd3a"
|
||||
checksum = "ab35c38930e837f191de96c6f23e8dee7547916fbae0ce25e4d5fad405bbc2d2"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"nom",
|
||||
"regex",
|
||||
"thiserror",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2073,9 +2082,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.36.1"
|
||||
version = "0.36.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce"
|
||||
checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
@ -2621,15 +2630,17 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "redis"
|
||||
version = "0.25.4"
|
||||
version = "0.26.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0d7a6955c7511f60f3ba9e86c6d02b3c3f144f8c24b288d1f4e18074ab8bbec"
|
||||
checksum = "8cc5b667390cb038bc65fc4b18c06e2550469f7e06a02d886f1a018a11f63563"
|
||||
dependencies = [
|
||||
"arc-swap",
|
||||
"async-trait",
|
||||
"bytes",
|
||||
"combine",
|
||||
"futures-util",
|
||||
"itoa",
|
||||
"num-bigint",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"ryu",
|
||||
|
@ -3021,9 +3032,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "0.6.6"
|
||||
version = "0.6.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0"
|
||||
checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
@ -3676,9 +3687,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
|||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.39.1"
|
||||
version = "1.39.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d040ac2b29ab03b09d4129c2f5bbd012a3ac2f79d38ff506a4bf8dd34b0eac8a"
|
||||
checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
|
@ -3741,9 +3752,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.8.15"
|
||||
version = "0.8.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac2caab0bf757388c6c0ae23b3293fdb463fee59434529014f85e3263b995c28"
|
||||
checksum = "81967dd0dd2c1ab0bc3468bd7caecc32b8a4aa47d0c8c695d8c2b2108168d62c"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
|
@ -3753,18 +3764,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.6.6"
|
||||
version = "0.6.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf"
|
||||
checksum = "f8fb9f64314842840f1d940ac544da178732128f1c78c21772e876579e0da1db"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.22.16"
|
||||
version = "0.22.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "278f3d518e152219c994ce877758516bca5e118eaed6996192a774fb9fbf0788"
|
||||
checksum = "8d9f8729f5aea9562aac1cc0441f5d6de3cff1ee0c5d67293eeca5eb36ee7c16"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde",
|
||||
|
@ -3975,9 +3986,9 @@ checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b"
|
|||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "waker-fn"
|
||||
|
@ -4285,9 +4296,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
|||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.6.14"
|
||||
version = "0.6.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "374ec40a2d767a3c1b4972d9475ecd557356637be906f2cb3f7fe17a6eb5e22f"
|
||||
checksum = "b480ae9340fc261e6be3e95a1ba86d54ae3f9171132a73ce8d4bbaf68339507c"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
@ -4461,9 +4472,9 @@ checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a"
|
|||
|
||||
[[package]]
|
||||
name = "zune-jpeg"
|
||||
version = "0.4.11"
|
||||
version = "0.4.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec866b44a2a1fd6133d363f073ca1b179f438f99e7e5bfb1e33f7181facfe448"
|
||||
checksum = "16099418600b4d8f028622f73ff6e3deaabdff330fb9a2a131dea781ee8b0768"
|
||||
dependencies = [
|
||||
"zune-core",
|
||||
]
|
||||
|
|
|
@ -22,17 +22,17 @@ bcrypt = { version = "0.15.1", default-features = false }
|
|||
chrono = { version = "0.4.38", default-features = false }
|
||||
convert_case = { version = "0.6.0", default-features = false }
|
||||
cuid2 = { version = "0.1.2", default-features = false }
|
||||
emojis = { version = "0.6.2", default-features = false }
|
||||
emojis = { version = "0.6.3", default-features = false }
|
||||
idna = { version = "1.0.2", default-features = false }
|
||||
image = { version = "0.25.2", default-features = false }
|
||||
isahc = { version = "1.7.2", default-features = false }
|
||||
nom-exif = { version = "1.2.6", default-features = false }
|
||||
nom-exif = { version = "1.3.0", default-features = false }
|
||||
once_cell = { version = "1.19.0", default-features = false }
|
||||
pretty_assertions = { version = "1.4.0", default-features = false }
|
||||
proc-macro2 = { version = "1.0.86", default-features = false }
|
||||
quote = { version = "1.0.36", default-features = false }
|
||||
rand = { version = "0.8.5", default-features = false }
|
||||
redis = { version = "0.25.4", default-features = false }
|
||||
redis = { version = "0.26.0", default-features = false }
|
||||
regex = { version = "1.10.5", default-features = false }
|
||||
rmp-serde = { version = "1.3.0", default-features = false }
|
||||
sea-orm = { version = "0.12.15", default-features = false }
|
||||
|
@ -42,7 +42,7 @@ serde_yaml = { version = "0.9.34", default-features = false }
|
|||
syn = { version = "2.0.72", default-features = false }
|
||||
sysinfo = { version = "0.30.13", default-features = false }
|
||||
thiserror = { version = "1.0.63", default-features = false }
|
||||
tokio = { version = "1.39.1", default-features = false }
|
||||
tokio = { version = "1.39.2", default-features = false }
|
||||
tokio-test = { version = "0.4.4", default-features = false }
|
||||
tracing = { version = "0.1.40", default-features = false }
|
||||
tracing-subscriber = { version = "0.3.18", default-features = false }
|
||||
|
|
56
Dockerfile
56
Dockerfile
|
@ -1,56 +1,28 @@
|
|||
## Install dev and compilation dependencies, build files
|
||||
FROM docker.io/node:20-alpine as build
|
||||
# Install dev and compilation dependencies, build files
|
||||
FROM docker.io/node:20-alpine AS build
|
||||
WORKDIR /firefish
|
||||
|
||||
# Copy only backend-rs pnpm-related files first, to cache efficiently
|
||||
COPY package.json pnpm-workspace.yaml ./
|
||||
COPY packages/backend-rs/package.json packages/backend-rs/package.json
|
||||
|
||||
# Install compilation dependencies
|
||||
# Install build tools and work around the linker name issue
|
||||
RUN apk update && apk add --no-cache build-base linux-headers curl ca-certificates python3 perl
|
||||
RUN ln -s $(which gcc) /usr/bin/aarch64-linux-musl-gcc
|
||||
|
||||
# Install Rust toolchain
|
||||
RUN curl --proto '=https' --tlsv1.2 --silent --show-error --fail https://sh.rustup.rs | sh -s -- -y
|
||||
ENV PATH="/root/.cargo/bin:${PATH}"
|
||||
|
||||
# Copy only backend-rs dependency-related files first, to cache efficiently
|
||||
COPY packages/macro-rs packages/macro-rs/
|
||||
COPY packages/backend-rs/src/lib.rs packages/backend-rs/src/
|
||||
COPY packages/backend-rs/Cargo.toml packages/backend-rs/Cargo.toml
|
||||
COPY Cargo.toml Cargo.lock ./
|
||||
# Configure pnpm
|
||||
RUN corepack enable && corepack prepare pnpm@latest --activate
|
||||
|
||||
# Configure pnpm, and install backend-rs dependencies
|
||||
RUN corepack enable && corepack prepare pnpm@latest --activate && pnpm --filter backend-rs install
|
||||
RUN cargo fetch --locked --manifest-path Cargo.toml
|
||||
|
||||
# Copy in the rest of the rust files
|
||||
COPY packages/backend-rs packages/backend-rs/
|
||||
|
||||
# Compile backend-rs
|
||||
RUN ln -s $(which gcc) /usr/bin/aarch64-linux-musl-gcc
|
||||
RUN NODE_ENV='production' NODE_OPTIONS='--max_old_space_size=3072' pnpm run --filter backend-rs build
|
||||
|
||||
# Copy/Overwrite index.js to mitigate the bug in napi-rs codegen
|
||||
COPY packages/backend-rs/index.js packages/backend-rs/built/index.js
|
||||
|
||||
# Copy only the dependency-related files first, to cache efficiently
|
||||
COPY packages/backend/package.json packages/backend/package.json
|
||||
COPY packages/client/package.json packages/client/package.json
|
||||
COPY packages/sw/package.json packages/sw/package.json
|
||||
COPY packages/firefish-js/package.json packages/firefish-js/package.json
|
||||
COPY pnpm-lock.yaml ./
|
||||
|
||||
# Install dev mode dependencies for compilation
|
||||
RUN pnpm install --frozen-lockfile
|
||||
|
||||
# Copy in the rest of the files to build
|
||||
# Build
|
||||
COPY . ./
|
||||
|
||||
# Build other workspaces
|
||||
RUN NODE_ENV='production' NODE_OPTIONS='--max_old_space_size=3072' pnpm run --recursive --filter '!backend-rs' build && pnpm run build:assets
|
||||
RUN pnpm install --frozen-lockfile
|
||||
RUN cargo fetch --locked --manifest-path Cargo.toml
|
||||
RUN NODE_ENV='production' NODE_OPTIONS='--max_old_space_size=3072' pnpm run build
|
||||
|
||||
# Trim down the dependencies to only those for production
|
||||
RUN find . -path '*/node_modules/*' -delete && pnpm install --prod --frozen-lockfile
|
||||
|
||||
## Runtime container
|
||||
# Runtime container
|
||||
FROM docker.io/node:20-alpine
|
||||
WORKDIR /firefish
|
||||
|
||||
|
@ -66,7 +38,7 @@ COPY --from=build /firefish/packages/backend/node_modules /firefish/packages/bac
|
|||
# COPY --from=build /firefish/packages/client/node_modules /firefish/packages/client/node_modules
|
||||
COPY --from=build /firefish/packages/firefish-js/node_modules /firefish/packages/firefish-js/node_modules
|
||||
|
||||
# Copy the finished compiled files
|
||||
# Copy the build artifacts
|
||||
COPY --from=build /firefish/built /firefish/built
|
||||
COPY --from=build /firefish/packages/backend/built /firefish/packages/backend/built
|
||||
COPY --from=build /firefish/packages/backend/assets/instance.css /firefish/packages/backend/assets/instance.css
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
Breaking changes are indicated by the :warning: icon.
|
||||
|
||||
## v20240728
|
||||
|
||||
- Added `name`, `category`, `aliases`, `license` optional parameters to `admin/emoji/add` endpoint.
|
||||
- Added `name` optional parameter to `drive/files/upload-from-url` endpoint.
|
||||
|
||||
## v20240725
|
||||
|
||||
- Added `i/export-followers` endpoint.
|
||||
|
|
|
@ -2,9 +2,16 @@
|
|||
|
||||
Critical security updates are indicated by the :warning: icon.
|
||||
|
||||
This changelog is not an exhaustive list. Code refactorings, minor bug fixes, documentation/dependency updates, etc. are usually not listed here. If you want to see all changes, click on the version number and check the commit history.
|
||||
|
||||
- Server administrators must check [notice-for-admins.md](https://firefish.dev/firefish/firefish/-/blob/main/docs/notice-for-admins.md) as well.
|
||||
- Third-party client/bot developers may want to check [api-change.md](https://firefish.dev/firefish/firefish/-/blob/main/docs/api-change.md) as well.
|
||||
|
||||
## [v20240728](https://firefish.dev/firefish/firefish/-/merge_requests/11211/commits)
|
||||
|
||||
- Improve `admin/emoji/add` API
|
||||
- Fix bugs
|
||||
|
||||
## [v20240725](https://firefish.dev/firefish/firefish/-/merge_requests/11196/commits)
|
||||
|
||||
- Add followers list export feature
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
# Install Firefish
|
||||
|
||||
Please check the [v20240206 release note](https://firefish.dev/firefish/firefish/-/releases/v20240206) first. This project is barely maintained for those who really want to keep using Firefish. Please understand this before proceeding.
|
||||
|
||||
## Dependencies
|
||||
|
||||
Firefish depends on the following software.
|
||||
|
||||
## Runtime dependencies
|
||||
### Runtime dependencies
|
||||
|
||||
- At least [NodeJS](https://nodejs.org/en/) v18.19.0 (v20/v22 recommended)
|
||||
- At least [PostgreSQL](https://www.postgresql.org/) v12 (v16 recommended) with [PGroonga](https://pgroonga.github.io/) extension
|
||||
|
@ -17,7 +21,7 @@ Firefish depends on the following software.
|
|||
- [KeyDB](https://keydb.dev/)
|
||||
- Another [Redis](https://redis.io/) / [Valkey](https://valkey.io/) server
|
||||
|
||||
## Build dependencies
|
||||
### Build dependencies
|
||||
|
||||
- At least [Rust](https://www.rust-lang.org/) v1.74
|
||||
- C/C++ compiler & build tools (like [GNU Make](https://www.gnu.org/software/make/))
|
||||
|
@ -35,7 +39,7 @@ We don't test Firefish on non-Linux systems, so please install Firefish on such
|
|||
|
||||
<details>
|
||||
|
||||
<summary>Possible setup on FreeBSD (as of version <code>20240630</code>)</summary>
|
||||
<summary>Possible setup on FreeBSD (as of version <code>20240725</code>)</summary>
|
||||
|
||||
You can install Firefish on FreeBSD by adding these extra steps to the standard instructions:
|
||||
|
||||
|
@ -44,7 +48,7 @@ You can install Firefish on FreeBSD by adding these extra steps to the standard
|
|||
```json
|
||||
"pnpm": {
|
||||
"overrides": {
|
||||
"rollup": "npm:@rollup/wasm-node@4.17.2"
|
||||
"rollup": "npm:@rollup/wasm-node
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "firefish",
|
||||
"version": "20240725",
|
||||
"version": "20240728",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://firefish.dev/firefish/firefish.git"
|
||||
|
|
97
packages/backend-rs/index.d.ts
vendored
97
packages/backend-rs/index.d.ts
vendored
|
@ -48,6 +48,8 @@ export interface Acct {
|
|||
|
||||
export declare function acctToString(acct: Acct): string
|
||||
|
||||
export type Activity = 'Follow';
|
||||
|
||||
export interface Ad {
|
||||
id: string
|
||||
createdAt: DateTimeWithTimeZone
|
||||
|
@ -217,7 +219,7 @@ export interface Config {
|
|||
proxySmtp?: string
|
||||
proxyBypassHosts?: Array<string>
|
||||
allowedPrivateNetworks?: Array<string>
|
||||
maxFileSize?: number
|
||||
maxFileSize: number
|
||||
accessLog?: string
|
||||
clusterLimits: WorkerConfig
|
||||
cuid?: IdConfig
|
||||
|
@ -369,6 +371,40 @@ export interface Emoji {
|
|||
height: number | null
|
||||
}
|
||||
|
||||
export declare enum Event {
|
||||
Notification = 0,
|
||||
NewNotification = 1,
|
||||
Mention = 2,
|
||||
NewMention = 3,
|
||||
Chat = 4,
|
||||
NewChat = 5,
|
||||
NewDm = 6,
|
||||
Reply = 7,
|
||||
Renote = 8,
|
||||
Follow = 9,
|
||||
Followed = 10,
|
||||
Unfollow = 11,
|
||||
NewFollowRequest = 12,
|
||||
Page = 13,
|
||||
ReadAllNotifications = 14,
|
||||
ReadAllMentions = 15,
|
||||
ReadNotifications = 16,
|
||||
ReadAllDms = 17,
|
||||
ReadAllChats = 18,
|
||||
ReadAntenna = 19,
|
||||
ReadAllAntennaPosts = 20,
|
||||
NewAntennaPost = 21,
|
||||
ReadAllAnnouncements = 22,
|
||||
ReadAllChannelPosts = 23,
|
||||
NewChannelPost = 24,
|
||||
DriveFile = 25,
|
||||
UrlUploadFinished = 26,
|
||||
Me = 27,
|
||||
RegenerateMyToken = 28,
|
||||
Signin = 29,
|
||||
Registry = 30
|
||||
}
|
||||
|
||||
export declare function extractHost(uri: string): string
|
||||
|
||||
export declare function fetchMeta(): Promise<Meta>
|
||||
|
@ -389,6 +425,13 @@ export interface Following {
|
|||
followeeSharedInbox: string | null
|
||||
}
|
||||
|
||||
export interface FollowRelay {
|
||||
id: string
|
||||
type: Activity
|
||||
actor: string
|
||||
object: string
|
||||
}
|
||||
|
||||
export interface FollowRequest {
|
||||
id: string
|
||||
createdAt: DateTimeWithTimeZone
|
||||
|
@ -448,10 +491,12 @@ export declare function getFullApAccount(username: string, host?: string | undef
|
|||
|
||||
export declare function getImageSizeFromUrl(url: string): Promise<ImageSize>
|
||||
|
||||
export declare function getInternalActor(actor: InternalActor): Promise<User>
|
||||
export declare function getInstanceActor(): Promise<User>
|
||||
|
||||
export declare function getNoteSummary(fileIds: Array<string>, text: string | undefined | null, cw: string | undefined | null, hasPoll: boolean): string
|
||||
|
||||
export declare function getRelayActorId(): Promise<string>
|
||||
|
||||
export declare function getTimestamp(id: string): number
|
||||
|
||||
/** Prints the greeting message and the Firefish version to stdout. */
|
||||
|
@ -529,8 +574,20 @@ export interface Instance {
|
|||
faviconUrl: string | null
|
||||
}
|
||||
|
||||
export type InternalActor = 'instance'|
|
||||
'relay';
|
||||
export declare enum InternalEvent {
|
||||
Suspend = 0,
|
||||
Silence = 1,
|
||||
Moderator = 2,
|
||||
Token = 3,
|
||||
LocalUser = 4,
|
||||
RemoteUser = 5,
|
||||
WebhookCreated = 6,
|
||||
WebhookUpdated = 7,
|
||||
WebhookDeleted = 8,
|
||||
AntennaCreated = 9,
|
||||
AntennaUpdated = 10,
|
||||
AntennaDeleted = 11
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a server is allowlisted.
|
||||
|
@ -832,6 +889,15 @@ export interface NoteEdit {
|
|||
emojis: Array<string>
|
||||
}
|
||||
|
||||
export declare enum NoteEvent {
|
||||
Delete = 0,
|
||||
React = 1,
|
||||
Unreact = 2,
|
||||
Reply = 3,
|
||||
Update = 4,
|
||||
Vote = 5
|
||||
}
|
||||
|
||||
export interface NoteFavorite {
|
||||
id: string
|
||||
createdAt: DateTimeWithTimeZone
|
||||
|
@ -1113,10 +1179,20 @@ export declare function publishToDriveFolderStream(userId: string, kind: DriveFo
|
|||
|
||||
export declare function publishToGroupChatStream(groupId: string, kind: ChatEvent, object: any): Promise<void>
|
||||
|
||||
export declare function publishToInternalStream(kind: InternalEvent, object: any): Promise<void>
|
||||
|
||||
export declare function publishToMainStream(userId: string, kind: Event, object: any): Promise<void>
|
||||
|
||||
export declare function publishToModerationStream(moderatorId: string, report: AbuseUserReportLike): Promise<void>
|
||||
|
||||
export declare function publishToNotesStream(note: Note): Promise<void>
|
||||
|
||||
export declare function publishToNoteStream(noteId: string, kind: NoteEvent, object: any): Promise<void>
|
||||
|
||||
export declare function publishToNoteUpdatesStream(note: Note): Promise<void>
|
||||
|
||||
export declare function publishToUserStream(userId: string, kind: UserEvent, object: any): Promise<void>
|
||||
|
||||
export interface PugArgs {
|
||||
img: string | null
|
||||
title: string
|
||||
|
@ -1189,6 +1265,8 @@ export type RelayStatus = 'accepted'|
|
|||
/** Delete all entries in the [attestation_challenge] table created at more than 5 minutes ago */
|
||||
export declare function removeOldAttestationChallenges(): Promise<void>
|
||||
|
||||
export declare function renderFollowRelay(relayId: string): Promise<FollowRelay>
|
||||
|
||||
export interface RenoteMuting {
|
||||
id: string
|
||||
createdAt: DateTimeWithTimeZone
|
||||
|
@ -1406,6 +1484,17 @@ export type UserEmojiModPerm = 'add'|
|
|||
'mod'|
|
||||
'unauthorized';
|
||||
|
||||
export declare enum UserEvent {
|
||||
Disconnect = 0,
|
||||
FollowChannel = 1,
|
||||
UnfollowChannel = 2,
|
||||
UpdateProfile = 3,
|
||||
Mute = 4,
|
||||
Unmute = 5,
|
||||
Follow = 6,
|
||||
Unfollow = 7
|
||||
}
|
||||
|
||||
export interface UserGroup {
|
||||
id: string
|
||||
createdAt: DateTimeWithTimeZone
|
||||
|
|
|
@ -362,6 +362,7 @@ if (!nativeBinding) {
|
|||
}
|
||||
|
||||
module.exports.acctToString = nativeBinding.acctToString
|
||||
module.exports.Activity = nativeBinding.Activity
|
||||
module.exports.AntennaSrc = nativeBinding.AntennaSrc
|
||||
module.exports.ChatEvent = nativeBinding.ChatEvent
|
||||
module.exports.ChatIndexEvent = nativeBinding.ChatIndexEvent
|
||||
|
@ -374,6 +375,7 @@ module.exports.decodeReaction = nativeBinding.decodeReaction
|
|||
module.exports.DriveFileEvent = nativeBinding.DriveFileEvent
|
||||
module.exports.DriveFileUsageHint = nativeBinding.DriveFileUsageHint
|
||||
module.exports.DriveFolderEvent = nativeBinding.DriveFolderEvent
|
||||
module.exports.Event = nativeBinding.Event
|
||||
module.exports.extractHost = nativeBinding.extractHost
|
||||
module.exports.fetchMeta = nativeBinding.fetchMeta
|
||||
module.exports.fetchNodeinfo = nativeBinding.fetchNodeinfo
|
||||
|
@ -384,14 +386,15 @@ module.exports.genId = nativeBinding.genId
|
|||
module.exports.genIdAt = nativeBinding.genIdAt
|
||||
module.exports.getFullApAccount = nativeBinding.getFullApAccount
|
||||
module.exports.getImageSizeFromUrl = nativeBinding.getImageSizeFromUrl
|
||||
module.exports.getInternalActor = nativeBinding.getInternalActor
|
||||
module.exports.getInstanceActor = nativeBinding.getInstanceActor
|
||||
module.exports.getNoteSummary = nativeBinding.getNoteSummary
|
||||
module.exports.getRelayActorId = nativeBinding.getRelayActorId
|
||||
module.exports.getTimestamp = nativeBinding.getTimestamp
|
||||
module.exports.greet = nativeBinding.greet
|
||||
module.exports.hashPassword = nativeBinding.hashPassword
|
||||
module.exports.Inbound = nativeBinding.Inbound
|
||||
module.exports.initializeRustLogger = nativeBinding.initializeRustLogger
|
||||
module.exports.InternalActor = nativeBinding.InternalActor
|
||||
module.exports.InternalEvent = nativeBinding.InternalEvent
|
||||
module.exports.isAllowedServer = nativeBinding.isAllowedServer
|
||||
module.exports.isBlockedServer = nativeBinding.isBlockedServer
|
||||
module.exports.isOldPasswordAlgorithm = nativeBinding.isOldPasswordAlgorithm
|
||||
|
@ -408,6 +411,7 @@ module.exports.metaToPugArgs = nativeBinding.metaToPugArgs
|
|||
module.exports.MutedNoteReason = nativeBinding.MutedNoteReason
|
||||
module.exports.nodeinfo_2_0 = nativeBinding.nodeinfo_2_0
|
||||
module.exports.nodeinfo_2_1 = nativeBinding.nodeinfo_2_1
|
||||
module.exports.NoteEvent = nativeBinding.NoteEvent
|
||||
module.exports.NoteVisibility = nativeBinding.NoteVisibility
|
||||
module.exports.NotificationType = nativeBinding.NotificationType
|
||||
module.exports.nyaify = nativeBinding.nyaify
|
||||
|
@ -422,12 +426,18 @@ module.exports.publishToChatStream = nativeBinding.publishToChatStream
|
|||
module.exports.publishToDriveFileStream = nativeBinding.publishToDriveFileStream
|
||||
module.exports.publishToDriveFolderStream = nativeBinding.publishToDriveFolderStream
|
||||
module.exports.publishToGroupChatStream = nativeBinding.publishToGroupChatStream
|
||||
module.exports.publishToInternalStream = nativeBinding.publishToInternalStream
|
||||
module.exports.publishToMainStream = nativeBinding.publishToMainStream
|
||||
module.exports.publishToModerationStream = nativeBinding.publishToModerationStream
|
||||
module.exports.publishToNotesStream = nativeBinding.publishToNotesStream
|
||||
module.exports.publishToNoteStream = nativeBinding.publishToNoteStream
|
||||
module.exports.publishToNoteUpdatesStream = nativeBinding.publishToNoteUpdatesStream
|
||||
module.exports.publishToUserStream = nativeBinding.publishToUserStream
|
||||
module.exports.PushNotificationKind = nativeBinding.PushNotificationKind
|
||||
module.exports.PushSubscriptionType = nativeBinding.PushSubscriptionType
|
||||
module.exports.RelayStatus = nativeBinding.RelayStatus
|
||||
module.exports.removeOldAttestationChallenges = nativeBinding.removeOldAttestationChallenges
|
||||
module.exports.renderFollowRelay = nativeBinding.renderFollowRelay
|
||||
module.exports.safeForSql = nativeBinding.safeForSql
|
||||
module.exports.sendPushNotification = nativeBinding.sendPushNotification
|
||||
module.exports.shouldNyaify = nativeBinding.shouldNyaify
|
||||
|
@ -445,6 +455,7 @@ module.exports.updateAntennasOnNewNote = nativeBinding.updateAntennasOnNewNote
|
|||
module.exports.updateMetaCache = nativeBinding.updateMetaCache
|
||||
module.exports.updateNodeinfoCache = nativeBinding.updateNodeinfoCache
|
||||
module.exports.UserEmojiModPerm = nativeBinding.UserEmojiModPerm
|
||||
module.exports.UserEvent = nativeBinding.UserEvent
|
||||
module.exports.UserProfileFfvisibility = nativeBinding.UserProfileFfvisibility
|
||||
module.exports.UserProfileMutingNotificationTypes = nativeBinding.UserProfileMutingNotificationTypes
|
||||
module.exports.verifyPassword = nativeBinding.verifyPassword
|
||||
|
|
|
@ -200,7 +200,7 @@ pub struct Config {
|
|||
pub proxy_smtp: Option<String>,
|
||||
pub proxy_bypass_hosts: Option<Vec<String>>,
|
||||
pub allowed_private_networks: Option<Vec<String>>,
|
||||
pub max_file_size: Option<i64>,
|
||||
pub max_file_size: i64,
|
||||
pub access_log: Option<String>,
|
||||
pub cluster_limits: WorkerConfig,
|
||||
pub cuid: Option<IdConfig>,
|
||||
|
@ -309,7 +309,7 @@ pub fn load_config() -> Config {
|
|||
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,
|
||||
max_file_size: server_config.max_file_size.unwrap_or(262144000),
|
||||
access_log: server_config.access_log,
|
||||
cluster_limits,
|
||||
cuid: server_config.cuid,
|
||||
|
|
1
packages/backend-rs/src/federation/activitypub/mod.rs
Normal file
1
packages/backend-rs/src/federation/activitypub/mod.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub mod object;
|
|
@ -0,0 +1,9 @@
|
|||
pub mod relay;
|
||||
|
||||
pub trait ActivityPubObject {}
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
#[macros::export(string_enum)]
|
||||
pub enum Activity {
|
||||
Follow,
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
use super::*;
|
||||
use crate::{config::CONFIG, federation::internal_actor};
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[macros::export(object)]
|
||||
pub struct FollowRelay {
|
||||
pub id: String,
|
||||
pub r#type: Activity,
|
||||
pub actor: String,
|
||||
pub object: String,
|
||||
}
|
||||
|
||||
impl ActivityPubObject for FollowRelay {}
|
||||
|
||||
#[macros::export(js_name = "renderFollowRelay")]
|
||||
pub async fn follow(relay_id: &str) -> Result<FollowRelay, internal_actor::relay::Error> {
|
||||
Ok(FollowRelay {
|
||||
id: format!("{}/activities/follow-relay/{}", CONFIG.url, relay_id),
|
||||
r#type: Activity::Follow,
|
||||
actor: format!(
|
||||
"{}/users/{}",
|
||||
CONFIG.url,
|
||||
internal_actor::relay::get_id().await?
|
||||
),
|
||||
object: "https://www.w3.org/ns/activitystreams#Public".to_owned(),
|
||||
})
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
//! In-memory internal actor cache handler
|
||||
|
||||
// TODO: refactoring
|
||||
|
||||
use super::*;
|
||||
use crate::{database::db_conn, model::entity::user};
|
||||
use sea_orm::prelude::*;
|
||||
use std::sync::Mutex;
|
||||
|
||||
#[macros::errors]
|
||||
pub enum Error {
|
||||
#[error(transparent)]
|
||||
#[doc = "database error"]
|
||||
Db(#[from] DbErr),
|
||||
#[error("{} does not exist", Acct::from(.0.to_owned()))]
|
||||
#[doc = "internal actor does not exist"]
|
||||
InternalActorNotFound(InternalActor),
|
||||
}
|
||||
|
||||
static INSTANCE_ACTOR: Mutex<Option<user::Model>> = Mutex::new(None);
|
||||
static RELAY_ACTOR: Mutex<Option<user::Model>> = Mutex::new(None);
|
||||
|
||||
fn set_instance_actor(value: &user::Model) {
|
||||
let _ = INSTANCE_ACTOR
|
||||
.lock()
|
||||
.map(|mut cache| *cache = Some(value.to_owned()));
|
||||
}
|
||||
fn set_relay_actor(value: &user::Model) {
|
||||
let _ = RELAY_ACTOR
|
||||
.lock()
|
||||
.map(|mut cache| *cache = Some(value.to_owned()));
|
||||
}
|
||||
|
||||
async fn cache_instance_actor() -> Result<user::Model, Error> {
|
||||
let actor = user::Entity::find()
|
||||
.filter(user::Column::Username.eq(INSTANCE_ACTOR_USERNAME))
|
||||
.filter(user::Column::Host.is_null())
|
||||
.one(db_conn().await?)
|
||||
.await?;
|
||||
|
||||
if let Some(actor) = actor {
|
||||
set_instance_actor(&actor);
|
||||
Ok(actor)
|
||||
} else {
|
||||
Err(Error::InternalActorNotFound(InternalActor::Instance))
|
||||
}
|
||||
}
|
||||
async fn cache_relay_actor() -> Result<user::Model, Error> {
|
||||
let actor = user::Entity::find()
|
||||
.filter(user::Column::Username.eq(RELAY_ACTOR_USERNAME))
|
||||
.filter(user::Column::Host.is_null())
|
||||
.one(db_conn().await?)
|
||||
.await?;
|
||||
|
||||
if let Some(actor) = actor {
|
||||
set_relay_actor(&actor);
|
||||
Ok(actor)
|
||||
} else {
|
||||
Err(Error::InternalActorNotFound(InternalActor::Relay))
|
||||
}
|
||||
}
|
||||
|
||||
// for napi export
|
||||
// https://github.com/napi-rs/napi-rs/issues/2060
|
||||
type User = user::Model;
|
||||
|
||||
#[macros::export(js_name = "getInternalActor")]
|
||||
pub async fn get(actor: InternalActor) -> Result<User, Error> {
|
||||
match actor {
|
||||
InternalActor::Instance => {
|
||||
if let Some(cache) = INSTANCE_ACTOR.lock().ok().and_then(|cache| cache.clone()) {
|
||||
tracing::debug!("Using cached instance.actor");
|
||||
return Ok(cache);
|
||||
}
|
||||
tracing::debug!("Caching instance.actor");
|
||||
cache_instance_actor().await
|
||||
}
|
||||
InternalActor::Relay => {
|
||||
if let Some(cache) = RELAY_ACTOR.lock().ok().and_then(|cache| cache.clone()) {
|
||||
tracing::debug!("Using cached relay.actor");
|
||||
return Ok(cache);
|
||||
}
|
||||
tracing::debug!("Caching relay.actor");
|
||||
cache_relay_actor().await
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
//! In-memory instance actor cache
|
||||
|
||||
use crate::{database::db_conn, model::entity::user};
|
||||
use sea_orm::prelude::*;
|
||||
use tokio::sync::OnceCell;
|
||||
|
||||
// for napi export
|
||||
// https://github.com/napi-rs/napi-rs/issues/2060
|
||||
type User = user::Model;
|
||||
|
||||
pub const USERNAME: &str = "instance.actor";
|
||||
static INSTANCE_ACTOR: OnceCell<User> = OnceCell::const_new();
|
||||
|
||||
#[macros::errors]
|
||||
pub enum Error {
|
||||
#[error("@instance.actor not found")]
|
||||
InstanceActorNotFound,
|
||||
#[error(transparent)]
|
||||
#[doc = "database error"]
|
||||
Db(#[from] DbErr),
|
||||
}
|
||||
|
||||
async fn set_cache() -> Result<&'static User, Error> {
|
||||
let instance_actor = INSTANCE_ACTOR
|
||||
.get_or_try_init(|| async {
|
||||
tracing::debug!("caching @instance.actor");
|
||||
let found_model = user::Entity::find()
|
||||
.filter(user::Column::Username.eq(USERNAME))
|
||||
.filter(user::Column::Host.is_null())
|
||||
.one(db_conn().await?)
|
||||
.await?;
|
||||
|
||||
found_model.ok_or(Error::InstanceActorNotFound)
|
||||
})
|
||||
.await?;
|
||||
|
||||
Ok(instance_actor)
|
||||
}
|
||||
|
||||
pub async fn get() -> Result<&'static User, Error> {
|
||||
match INSTANCE_ACTOR.get() {
|
||||
Some(model) => Ok(model),
|
||||
None => set_cache().await,
|
||||
}
|
||||
}
|
||||
|
||||
#[macros::ts_export(js_name = "getInstanceActor")]
|
||||
pub async fn get_js() -> Result<User, Error> {
|
||||
Ok(get().await?.to_owned())
|
||||
}
|
|
@ -1,34 +1,4 @@
|
|||
mod cache;
|
||||
pub mod instance;
|
||||
pub mod relay;
|
||||
|
||||
pub use cache::get;
|
||||
|
||||
use super::acct::Acct;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[macros::derive_clone_and_export(string_enum = "lowercase")]
|
||||
pub enum InternalActor {
|
||||
Instance,
|
||||
Relay,
|
||||
}
|
||||
|
||||
const INSTANCE_ACTOR_USERNAME: &str = "instance.actor";
|
||||
const RELAY_ACTOR_USERNAME: &str = "relay.actor";
|
||||
|
||||
// TODO: When `std::mem::variant_count` is stabilized, use
|
||||
// it to count system actors instead of hard coding the magic number
|
||||
pub const INTERNAL_ACTORS: u64 = 2;
|
||||
|
||||
impl From<InternalActor> for Acct {
|
||||
fn from(actor: InternalActor) -> Self {
|
||||
match actor {
|
||||
InternalActor::Instance => Acct {
|
||||
username: INSTANCE_ACTOR_USERNAME.to_owned(),
|
||||
host: None,
|
||||
},
|
||||
InternalActor::Relay => Acct {
|
||||
username: RELAY_ACTOR_USERNAME.to_owned(),
|
||||
host: None,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
45
packages/backend-rs/src/federation/internal_actor/relay.rs
Normal file
45
packages/backend-rs/src/federation/internal_actor/relay.rs
Normal file
|
@ -0,0 +1,45 @@
|
|||
//! In-memory relay actor id cache
|
||||
|
||||
use crate::{database::db_conn, model::entity::user};
|
||||
use sea_orm::{prelude::*, QuerySelect, SelectColumns};
|
||||
use tokio::sync::OnceCell;
|
||||
|
||||
pub const USERNAME: &str = "relay.actor";
|
||||
static RELAY_ACTOR_ID: OnceCell<String> = OnceCell::const_new();
|
||||
|
||||
#[macros::errors]
|
||||
pub enum Error {
|
||||
#[error("@relay.actor not found")]
|
||||
RelayActorNotFound,
|
||||
#[error(transparent)]
|
||||
#[doc = "database error"]
|
||||
Db(#[from] DbErr),
|
||||
}
|
||||
|
||||
async fn set_id_cache() -> Result<&'static str, Error> {
|
||||
let id = RELAY_ACTOR_ID
|
||||
.get_or_try_init(|| async {
|
||||
tracing::debug!("caching @relay.actor");
|
||||
let found_id = user::Entity::find()
|
||||
.select_only()
|
||||
.select_column(user::Column::Id)
|
||||
.filter(user::Column::Username.eq(USERNAME))
|
||||
.filter(user::Column::Host.is_null())
|
||||
.into_tuple::<String>()
|
||||
.one(db_conn().await?)
|
||||
.await?;
|
||||
|
||||
found_id.ok_or(Error::RelayActorNotFound)
|
||||
})
|
||||
.await?;
|
||||
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
#[macros::export(js_name = "getRelayActorId")]
|
||||
pub async fn get_id() -> Result<&'static str, Error> {
|
||||
match RELAY_ACTOR_ID.get() {
|
||||
Some(id) => Ok(id),
|
||||
None => set_id_cache().await,
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
//! Services used to federate with other servers
|
||||
|
||||
pub mod acct;
|
||||
pub mod activitypub;
|
||||
pub mod internal_actor;
|
||||
pub mod nodeinfo;
|
||||
|
|
|
@ -5,8 +5,13 @@ pub mod chat_index;
|
|||
pub mod custom_emoji;
|
||||
pub mod drive;
|
||||
pub mod group_chat;
|
||||
pub mod internal;
|
||||
pub mod main;
|
||||
pub mod moderation;
|
||||
pub mod note;
|
||||
pub mod note_edit;
|
||||
pub mod notes;
|
||||
pub mod user;
|
||||
|
||||
use crate::{
|
||||
config::CONFIG,
|
||||
|
@ -30,9 +35,7 @@ pub enum Stream {
|
|||
note_id: String,
|
||||
},
|
||||
Notes,
|
||||
UserList {
|
||||
list_id: String,
|
||||
},
|
||||
NoteEdit,
|
||||
Main {
|
||||
user_id: String,
|
||||
},
|
||||
|
@ -86,8 +89,8 @@ pub async fn publish_to_stream(
|
|||
Stream::User { user_id } => format!("user:{user_id}"),
|
||||
Stream::Channel { channel_id } => format!("channelStream:{channel_id}"),
|
||||
Stream::Note { note_id } => format!("noteStream:{note_id}"),
|
||||
Stream::NoteEdit => "noteUpdatesStream".to_owned(),
|
||||
Stream::Notes => "notesStream".to_owned(),
|
||||
Stream::UserList { list_id } => format!("userListStream:{list_id}"),
|
||||
Stream::Main { user_id } => format!("mainStream:{user_id}"),
|
||||
Stream::Drive { user_id } => format!("driveStream:{user_id}"),
|
||||
Stream::Antenna { antenna_id } => format!("antennaStream:{antenna_id}"),
|
||||
|
|
45
packages/backend-rs/src/service/stream/internal.rs
Normal file
45
packages/backend-rs/src/service/stream/internal.rs
Normal file
|
@ -0,0 +1,45 @@
|
|||
use crate::service::stream::{publish_to_stream, Error, Stream};
|
||||
|
||||
#[macros::export]
|
||||
pub enum InternalEvent {
|
||||
Suspend,
|
||||
Silence,
|
||||
Moderator,
|
||||
Token,
|
||||
LocalUser,
|
||||
RemoteUser,
|
||||
WebhookCreated,
|
||||
WebhookUpdated,
|
||||
WebhookDeleted,
|
||||
AntennaCreated,
|
||||
AntennaUpdated,
|
||||
AntennaDeleted,
|
||||
}
|
||||
|
||||
// We want to merge `kind` and `object` into a single enum
|
||||
// https://github.com/napi-rs/napi-rs/issues/2036
|
||||
|
||||
#[macros::export(js_name = "publishToInternalStream")]
|
||||
pub async fn publish(kind: InternalEvent, object: &serde_json::Value) -> Result<(), Error> {
|
||||
let kind = match kind {
|
||||
InternalEvent::Suspend => "userChangeSuspendedState",
|
||||
InternalEvent::Silence => "userChangeSilencedState",
|
||||
InternalEvent::Moderator => "userChangeModeratorState",
|
||||
InternalEvent::Token => "userTokenRegenerated",
|
||||
InternalEvent::LocalUser => "localUserUpdated",
|
||||
InternalEvent::RemoteUser => "remoteUserUpdated",
|
||||
InternalEvent::WebhookCreated => "webhookCreated",
|
||||
InternalEvent::WebhookUpdated => "webhookUpdated",
|
||||
InternalEvent::WebhookDeleted => "webhookDeleted",
|
||||
InternalEvent::AntennaCreated => "antennaCreated",
|
||||
InternalEvent::AntennaUpdated => "antennaUpdated",
|
||||
InternalEvent::AntennaDeleted => "antennaDeleted",
|
||||
};
|
||||
|
||||
publish_to_stream(
|
||||
&Stream::Internal,
|
||||
Some(kind),
|
||||
Some(serde_json::to_string(&object)?),
|
||||
)
|
||||
.await
|
||||
}
|
87
packages/backend-rs/src/service/stream/main.rs
Normal file
87
packages/backend-rs/src/service/stream/main.rs
Normal file
|
@ -0,0 +1,87 @@
|
|||
use crate::service::stream::{publish_to_stream, Error, Stream};
|
||||
|
||||
#[macros::export]
|
||||
pub enum Event {
|
||||
Notification,
|
||||
NewNotification,
|
||||
Mention,
|
||||
NewMention,
|
||||
Chat,
|
||||
NewChat,
|
||||
NewDm,
|
||||
Reply,
|
||||
Renote,
|
||||
Follow,
|
||||
Followed,
|
||||
Unfollow,
|
||||
NewFollowRequest,
|
||||
Page,
|
||||
ReadAllNotifications,
|
||||
ReadAllMentions,
|
||||
ReadNotifications,
|
||||
ReadAllDms,
|
||||
ReadAllChats,
|
||||
ReadAntenna,
|
||||
ReadAllAntennaPosts,
|
||||
NewAntennaPost,
|
||||
ReadAllAnnouncements,
|
||||
ReadAllChannelPosts,
|
||||
NewChannelPost,
|
||||
DriveFile,
|
||||
UrlUploadFinished,
|
||||
Me,
|
||||
RegenerateMyToken,
|
||||
Signin,
|
||||
Registry,
|
||||
}
|
||||
|
||||
// We want to merge `kind` and `object` into a single enum
|
||||
// https://github.com/napi-rs/napi-rs/issues/2036
|
||||
|
||||
#[macros::export(js_name = "publishToMainStream")]
|
||||
pub async fn publish(
|
||||
user_id: String,
|
||||
kind: Event,
|
||||
object: &serde_json::Value,
|
||||
) -> Result<(), Error> {
|
||||
let kind = match kind {
|
||||
Event::Notification => "notification",
|
||||
Event::Mention => "mention",
|
||||
Event::Reply => "reply",
|
||||
Event::Renote => "renote",
|
||||
Event::Follow => "follow",
|
||||
Event::Followed => "followed",
|
||||
Event::Unfollow => "unfollow",
|
||||
Event::Me => "meUpdated",
|
||||
Event::Page => "pageEvent",
|
||||
Event::UrlUploadFinished => "urlUploadFinished",
|
||||
Event::ReadAllNotifications => "readAllNotifications",
|
||||
Event::ReadNotifications => "readNotifications",
|
||||
Event::NewNotification => "unreadNotification",
|
||||
Event::NewMention => "unreadMention",
|
||||
Event::ReadAllMentions => "readAllUnreadMentions",
|
||||
Event::ReadAllDms => "readAllUnreadSpecifiedNotes",
|
||||
Event::NewDm => "unreadSpecifiedNote",
|
||||
Event::ReadAllChats => "readAllMessagingMessages",
|
||||
Event::Chat => "messagingMessage",
|
||||
Event::NewChat => "unreadMessagingMessage",
|
||||
Event::ReadAllAntennaPosts => "readAllAntennas",
|
||||
Event::NewAntennaPost => "unreadAntenna",
|
||||
Event::ReadAllAnnouncements => "readAllAnnouncements",
|
||||
Event::ReadAllChannelPosts => "readAllChannels",
|
||||
Event::NewChannelPost => "unreadChannel",
|
||||
Event::RegenerateMyToken => "myTokenRegenerated",
|
||||
Event::Signin => "signin",
|
||||
Event::Registry => "registryUpdated",
|
||||
Event::DriveFile => "driveFileCreated",
|
||||
Event::ReadAntenna => "readAntenna",
|
||||
Event::NewFollowRequest => "receiveFollowRequest",
|
||||
};
|
||||
|
||||
publish_to_stream(
|
||||
&Stream::Main { user_id },
|
||||
Some(kind),
|
||||
Some(serde_json::to_string(&object)?),
|
||||
)
|
||||
.await
|
||||
}
|
43
packages/backend-rs/src/service/stream/note.rs
Normal file
43
packages/backend-rs/src/service/stream/note.rs
Normal file
|
@ -0,0 +1,43 @@
|
|||
use crate::service::stream::{publish_to_stream, Error, Stream};
|
||||
use serde_json::json;
|
||||
|
||||
#[macros::export]
|
||||
pub enum NoteEvent {
|
||||
Delete,
|
||||
React,
|
||||
Unreact,
|
||||
Reply,
|
||||
Update,
|
||||
Vote,
|
||||
}
|
||||
|
||||
// We want to merge `kind` and `object` into a single enum
|
||||
// https://github.com/napi-rs/napi-rs/issues/2036
|
||||
|
||||
#[macros::export(js_name = "publishToNoteStream")]
|
||||
pub async fn publish(
|
||||
note_id: String,
|
||||
kind: NoteEvent,
|
||||
object: &serde_json::Value,
|
||||
) -> Result<(), Error> {
|
||||
let kind = match kind {
|
||||
NoteEvent::Delete => "deleted",
|
||||
NoteEvent::React => "reacted",
|
||||
NoteEvent::Unreact => "unreacted",
|
||||
NoteEvent::Reply => "replied",
|
||||
NoteEvent::Update => "updated",
|
||||
NoteEvent::Vote => "pollVoted",
|
||||
};
|
||||
|
||||
let value = json!({
|
||||
"id": note_id.clone(),
|
||||
"body": object,
|
||||
});
|
||||
|
||||
publish_to_stream(
|
||||
&Stream::Note { note_id },
|
||||
Some(kind),
|
||||
Some(serde_json::to_string(&value)?),
|
||||
)
|
||||
.await
|
||||
}
|
18
packages/backend-rs/src/service/stream/note_edit.rs
Normal file
18
packages/backend-rs/src/service/stream/note_edit.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
use crate::{
|
||||
model::entity::note,
|
||||
service::stream::{publish_to_stream, Error, Stream},
|
||||
};
|
||||
|
||||
// for napi export
|
||||
// https://github.com/napi-rs/napi-rs/issues/2060
|
||||
type Note = note::Model;
|
||||
|
||||
#[macros::export(js_name = "publishToNoteUpdatesStream")]
|
||||
pub async fn publish(note: &Note) -> Result<(), Error> {
|
||||
publish_to_stream(
|
||||
&Stream::NoteEdit,
|
||||
Some("updated"),
|
||||
Some(serde_json::to_string(note)?),
|
||||
)
|
||||
.await
|
||||
}
|
41
packages/backend-rs/src/service/stream/user.rs
Normal file
41
packages/backend-rs/src/service/stream/user.rs
Normal file
|
@ -0,0 +1,41 @@
|
|||
use crate::service::stream::{publish_to_stream, Error, Stream};
|
||||
|
||||
#[macros::export]
|
||||
pub enum UserEvent {
|
||||
Disconnect,
|
||||
FollowChannel,
|
||||
UnfollowChannel,
|
||||
UpdateProfile,
|
||||
Mute,
|
||||
Unmute,
|
||||
Follow,
|
||||
Unfollow,
|
||||
}
|
||||
|
||||
// We want to merge `kind` and `object` into a single enum
|
||||
// https://github.com/napi-rs/napi-rs/issues/2036
|
||||
|
||||
#[macros::export(js_name = "publishToUserStream")]
|
||||
pub async fn publish(
|
||||
user_id: String,
|
||||
kind: UserEvent,
|
||||
object: &serde_json::Value,
|
||||
) -> Result<(), Error> {
|
||||
let kind = match kind {
|
||||
UserEvent::Disconnect => "terminate",
|
||||
UserEvent::FollowChannel => "followChannel",
|
||||
UserEvent::UnfollowChannel => "unfollowChannel",
|
||||
UserEvent::UpdateProfile => "updateUserProfile",
|
||||
UserEvent::Mute => "mute",
|
||||
UserEvent::Unmute => "unmute",
|
||||
UserEvent::Follow => "follow",
|
||||
UserEvent::Unfollow => "unfollow",
|
||||
};
|
||||
|
||||
publish_to_stream(
|
||||
&Stream::User { user_id },
|
||||
Some(kind),
|
||||
Some(serde_json::to_string(&object)?),
|
||||
)
|
||||
.await
|
||||
}
|
|
@ -33,7 +33,7 @@
|
|||
"archiver": "7.0.1",
|
||||
"async-lock": "1.4.1",
|
||||
"async-mutex": "0.5.0",
|
||||
"aws-sdk": "2.1662.0",
|
||||
"aws-sdk": "2.1664.0",
|
||||
"axios": "1.7.2",
|
||||
"backend-rs": "workspace:*",
|
||||
"blurhash": "2.0.5",
|
||||
|
|
|
@ -18,7 +18,6 @@ export const DB_MAX_NOTE_TEXT_LENGTH = 100000;
|
|||
*/
|
||||
export const DB_MAX_IMAGE_COMMENT_LENGTH = 8192;
|
||||
|
||||
|
||||
export const MAX_NOTE_TEXT_LENGTH = Math.min(
|
||||
config.maxNoteLength ?? 3000,
|
||||
DB_MAX_NOTE_TEXT_LENGTH,
|
||||
|
|
|
@ -13,8 +13,8 @@ export default async function () {
|
|||
ev.emit(`serverStatsLog:${x.id}`, log.slice(0, x.length || 50));
|
||||
});
|
||||
|
||||
const meta = await fetchMeta();
|
||||
if (!meta.enableServerMachineStats) return;
|
||||
const instanceMeta = await fetchMeta();
|
||||
if (!instanceMeta.enableServerMachineStats) return;
|
||||
|
||||
async function tick() {
|
||||
const stats = {
|
||||
|
|
|
@ -1,9 +1,29 @@
|
|||
import type { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
import { v4 as uuid } from "uuid";
|
||||
import { genRsaKeyPair } from "@/misc/gen-key-pair.js";
|
||||
import { generateUserToken, genIdAt, hashPassword } from "backend-rs";
|
||||
|
||||
import * as crypto from "node:crypto";
|
||||
import * as util from "node:util";
|
||||
|
||||
const generateKeyPair = util.promisify(crypto.generateKeyPair);
|
||||
|
||||
async function genRsaKeyPair(modulusLength = 2048) {
|
||||
return await generateKeyPair("rsa", {
|
||||
modulusLength,
|
||||
publicKeyEncoding: {
|
||||
type: "spki",
|
||||
format: "pem",
|
||||
},
|
||||
privateKeyEncoding: {
|
||||
type: "pkcs8",
|
||||
format: "pem",
|
||||
cipher: undefined,
|
||||
passphrase: undefined,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async function createSystemUser(username: string, queryRunner: QueryRunner) {
|
||||
const password = uuid();
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ export async function downloadUrl(url: string, path: string): Promise<void> {
|
|||
|
||||
const timeout = 30 * 1000;
|
||||
const operationTimeout = 60 * 1000;
|
||||
const maxSize = config.maxFileSize || 262144000;
|
||||
const maxSize = config.maxFileSize;
|
||||
|
||||
const req = got
|
||||
.stream(url, {
|
||||
|
|
|
@ -3,9 +3,9 @@ import type { ILocalUser } from "@/models/entities/user.js";
|
|||
import { Users } from "@/models/index.js";
|
||||
|
||||
export async function fetchProxyAccount(): Promise<ILocalUser | null> {
|
||||
const meta = await fetchMeta();
|
||||
if (meta.proxyAccountId == null) return null;
|
||||
const instanceMeta = await fetchMeta();
|
||||
if (instanceMeta.proxyAccountId == null) return null;
|
||||
return (await Users.findOneByOrFail({
|
||||
id: meta.proxyAccountId,
|
||||
id: instanceMeta.proxyAccountId,
|
||||
})) as ILocalUser;
|
||||
}
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
import * as crypto from "node:crypto";
|
||||
import * as util from "node:util";
|
||||
|
||||
const generateKeyPair = util.promisify(crypto.generateKeyPair);
|
||||
|
||||
export async function genRsaKeyPair(modulusLength = 2048) {
|
||||
return await generateKeyPair("rsa", {
|
||||
modulusLength,
|
||||
publicKeyEncoding: {
|
||||
type: "spki",
|
||||
format: "pem",
|
||||
},
|
||||
privateKeyEncoding: {
|
||||
type: "pkcs8",
|
||||
format: "pem",
|
||||
cipher: undefined,
|
||||
passphrase: undefined,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function genEcKeyPair(
|
||||
namedCurve:
|
||||
| "prime256v1"
|
||||
| "secp384r1"
|
||||
| "secp521r1"
|
||||
| "curve25519" = "prime256v1",
|
||||
) {
|
||||
return await generateKeyPair("ec", {
|
||||
namedCurve,
|
||||
publicKeyEncoding: {
|
||||
type: "spki",
|
||||
format: "pem",
|
||||
},
|
||||
privateKeyEncoding: {
|
||||
type: "pkcs8",
|
||||
format: "pem",
|
||||
cipher: undefined,
|
||||
passphrase: undefined,
|
||||
},
|
||||
});
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
import { noteVisibilities } from "@/types.js";
|
||||
|
||||
export type Post = {
|
||||
text: string | undefined;
|
||||
cw: string | null;
|
||||
localOnly: boolean;
|
||||
createdAt: Date;
|
||||
visibility: string;
|
||||
};
|
||||
|
||||
export function parse(acct: any): Post {
|
||||
return {
|
||||
text: acct.text || undefined,
|
||||
cw: acct.cw,
|
||||
localOnly: acct.localOnly,
|
||||
createdAt: new Date(acct.createdAt),
|
||||
visibility: noteVisibilities.includes(acct.visibility)
|
||||
? acct.visibility
|
||||
: "specified",
|
||||
};
|
||||
}
|
||||
|
||||
export function toJson(acct: Post): string {
|
||||
return { text: acct.text, cw: acct.cw, localOnly: acct.localOnly }.toString();
|
||||
}
|
|
@ -231,13 +231,13 @@ export const DriveFileRepository = db.getRepository(DriveFile).extend({
|
|||
if (url.startsWith(`${config.url}/identicon`)) return url;
|
||||
if (url.startsWith(`${config.url}/avatar`)) return url;
|
||||
|
||||
const meta = await fetchMeta();
|
||||
const baseUrl = meta
|
||||
? meta.objectStorageBaseUrl ??
|
||||
`${meta.objectStorageUseSsl ? "https" : "http"}://${
|
||||
meta.objectStorageEndpoint
|
||||
}${meta.objectStoragePort ? `:${meta.objectStoragePort}` : ""}/${
|
||||
meta.objectStorageBucket
|
||||
const instanceMeta = await fetchMeta();
|
||||
const baseUrl = instanceMeta
|
||||
? instanceMeta.objectStorageBaseUrl ??
|
||||
`${instanceMeta.objectStorageUseSsl ? "https" : "http"}://${
|
||||
instanceMeta.objectStorageEndpoint
|
||||
}${instanceMeta.objectStoragePort ? `:${instanceMeta.objectStoragePort}` : ""}/${
|
||||
instanceMeta.objectStorageBucket
|
||||
}`
|
||||
: null;
|
||||
if (baseUrl !== null && url.startsWith(baseUrl)) return url;
|
||||
|
|
|
@ -155,13 +155,13 @@ webhookDeliverQueue
|
|||
webhookLogger.warn(`stalled ${getJobInfo(job)} to=${job.data.to}`),
|
||||
);
|
||||
|
||||
export function deliver(user: ThinUser, content: unknown, to: string | null) {
|
||||
export function deliver(userId: string, content: unknown, to: string | null) {
|
||||
if (content == null) return null;
|
||||
if (to == null) return null;
|
||||
|
||||
const data = {
|
||||
user: {
|
||||
id: user.id,
|
||||
id: userId,
|
||||
},
|
||||
content,
|
||||
to,
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import * as Post from "@/misc/post.js";
|
||||
import create from "@/services/note/create.js";
|
||||
import { NoteFiles, Users } from "@/models/index.js";
|
||||
import type { DbUserImportMastoPostJobData } from "@/queue/types.js";
|
||||
|
@ -10,6 +9,7 @@ import { createImportCkPostJob } from "@/queue/index.js";
|
|||
import { Notes, NoteEdits } from "@/models/index.js";
|
||||
import type { Note } from "@/models/entities/note.js";
|
||||
import { genId } from "backend-rs";
|
||||
import { noteVisibilities } from "@/types.js";
|
||||
|
||||
const logger = queueLogger.createSubLogger("import-firefish-post");
|
||||
|
||||
|
@ -52,10 +52,15 @@ export async function importCkPost(
|
|||
logger.info(`Skipped adding file to drive: ${url}`);
|
||||
}
|
||||
}
|
||||
const { text, cw, localOnly, createdAt, visibility } = Post.parse(post);
|
||||
|
||||
const createdAt = new Date(post.createdAt);
|
||||
const visibility = noteVisibilities.includes(post.visibility)
|
||||
? post.visibility
|
||||
: "specified";
|
||||
|
||||
let note = await Notes.findOneBy({
|
||||
createdAt: createdAt,
|
||||
text: text,
|
||||
createdAt,
|
||||
text: post.text || undefined,
|
||||
userId: user.id,
|
||||
});
|
||||
|
||||
|
@ -95,16 +100,16 @@ export async function importCkPost(
|
|||
note = await create(
|
||||
user,
|
||||
{
|
||||
createdAt: createdAt,
|
||||
createdAt,
|
||||
scheduledAt: undefined,
|
||||
files: files.length === 0 ? undefined : files,
|
||||
poll: undefined,
|
||||
text: text || undefined,
|
||||
text: post.text || undefined,
|
||||
reply: post.replyId ? job.data.parent : null,
|
||||
renote: post.renoteId ? job.data.parent : null,
|
||||
cw: cw,
|
||||
localOnly,
|
||||
visibility: visibility,
|
||||
cw: post.cw,
|
||||
localOnly: post.localOnly,
|
||||
visibility,
|
||||
visibleUsers: [],
|
||||
channel: null,
|
||||
apMentions: new Array(0),
|
||||
|
|
|
@ -2,7 +2,7 @@ import type Bull from "bull";
|
|||
import { In } from "typeorm";
|
||||
import { Mutings } from "@/models/index.js";
|
||||
import { queueLogger } from "../../logger.js";
|
||||
import { publishUserEvent } from "@/services/stream.js";
|
||||
import { publishToUserStream, UserEvent } from "backend-rs";
|
||||
|
||||
const logger = queueLogger.createSubLogger("check-expired-mutings");
|
||||
|
||||
|
@ -23,9 +23,11 @@ export async function checkExpiredMutings(
|
|||
id: In(expired.map((m) => m.id)),
|
||||
});
|
||||
|
||||
for (const m of expired) {
|
||||
publishUserEvent(m.muterId, "unmute", m.mutee!);
|
||||
}
|
||||
await Promise.all(
|
||||
expired.map((m) =>
|
||||
publishToUserStream(m.muterId, UserEvent.Unmute, m.mutee),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
logger.info("All expired mutings checked.");
|
||||
|
|
|
@ -15,8 +15,8 @@ import type { UserPublickey } from "@/models/entities/user-publickey.js";
|
|||
import { verify } from "node:crypto";
|
||||
|
||||
export async function hasSignature(req: IncomingMessage): Promise<string> {
|
||||
const meta = await fetchMeta();
|
||||
const required = meta.secureMode || meta.privateMode;
|
||||
const instanceMeta = await fetchMeta();
|
||||
const required = instanceMeta.secureMode || instanceMeta.privateMode;
|
||||
|
||||
try {
|
||||
httpSignature.parseRequest(req, { headers: [] });
|
||||
|
@ -30,8 +30,8 @@ export async function hasSignature(req: IncomingMessage): Promise<string> {
|
|||
}
|
||||
|
||||
export async function checkFetch(req: IncomingMessage): Promise<number> {
|
||||
const meta = await fetchMeta();
|
||||
if (meta.secureMode || meta.privateMode) {
|
||||
const instanceMeta = await fetchMeta();
|
||||
if (instanceMeta.secureMode || instanceMeta.privateMode) {
|
||||
if (req.headers.host !== config.host) return 400;
|
||||
|
||||
let signature;
|
||||
|
|
|
@ -148,7 +148,7 @@ export default class DeliverManager {
|
|||
// skip instances as indicated
|
||||
if (instancesToSkip.includes(valid.host)) continue;
|
||||
|
||||
deliver(this.actor, this.activity, valid.inbox);
|
||||
deliver(this.actor.id, this.activity, valid.inbox);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,14 +36,14 @@ export async function createImage(
|
|||
|
||||
apLogger.info(`Creating an image: ${image.url}`);
|
||||
|
||||
const instance = await fetchMeta();
|
||||
const instanceMeta = await fetchMeta();
|
||||
|
||||
let file = await uploadFromUrl({
|
||||
url: image.url,
|
||||
user: actor,
|
||||
uri: image.url,
|
||||
sensitive: image.sensitive,
|
||||
isLink: !instance.cacheRemoteFiles,
|
||||
isLink: !instanceMeta.cacheRemoteFiles,
|
||||
comment: truncate(image.name, config.maxCaptionLength),
|
||||
usageHint: usage,
|
||||
});
|
||||
|
|
|
@ -15,11 +15,13 @@ import { apLogger } from "../logger.js";
|
|||
import type { DriveFile } from "@/models/entities/drive-file.js";
|
||||
import {
|
||||
type ImageSize,
|
||||
NoteEvent,
|
||||
extractHost,
|
||||
genId,
|
||||
getImageSizeFromUrl,
|
||||
isBlockedServer,
|
||||
isSameOrigin,
|
||||
publishToNoteStream,
|
||||
toPuny,
|
||||
} from "backend-rs";
|
||||
import {
|
||||
|
@ -47,7 +49,6 @@ import { parseAudience } from "../audience.js";
|
|||
import { extractApMentions } from "./mention.js";
|
||||
import DbResolver from "../db-resolver.js";
|
||||
import { StatusError } from "@/misc/fetch.js";
|
||||
import { publishNoteStream } from "@/services/stream.js";
|
||||
import { extractHashtags } from "@/misc/extract-hashtags.js";
|
||||
import { UserProfiles } from "@/models/index.js";
|
||||
import { In } from "typeorm";
|
||||
|
@ -795,7 +796,7 @@ export async function updateNote(value: string | IObject, resolver?: Resolver) {
|
|||
|
||||
if (publishing) {
|
||||
// Publish update event for the updated note details
|
||||
publishNoteStream(note.id, "updated", {
|
||||
publishToNoteStream(note.id, NoteEvent.Update, {
|
||||
updatedAt: update.updatedAt,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -16,7 +16,14 @@ import type { IRemoteUser, CacheableUser } from "@/models/entities/user.js";
|
|||
import { User } from "@/models/entities/user.js";
|
||||
import type { Emoji } from "@/models/entities/emoji.js";
|
||||
import { UserNotePining } from "@/models/entities/user-note-pining.js";
|
||||
import { genId, genIdAt, isSameOrigin, toPuny } from "backend-rs";
|
||||
import {
|
||||
genId,
|
||||
genIdAt,
|
||||
InternalEvent,
|
||||
isSameOrigin,
|
||||
publishToInternalStream,
|
||||
toPuny,
|
||||
} from "backend-rs";
|
||||
import { UserPublickey } from "@/models/entities/user-publickey.js";
|
||||
import { isDuplicateKeyValueError } from "@/misc/is-duplicate-key-value-error.js";
|
||||
import { UserProfile } from "@/models/entities/user-profile.js";
|
||||
|
@ -26,7 +33,6 @@ import { normalizeForSearch } from "@/misc/normalize-for-search.js";
|
|||
import { truncate } from "@/misc/truncate.js";
|
||||
import { StatusError } from "@/misc/fetch.js";
|
||||
import { uriPersonCache } from "@/services/user-cache.js";
|
||||
import { publishInternalEvent } from "@/services/stream.js";
|
||||
import { db } from "@/db/postgre.js";
|
||||
import { apLogger } from "../logger.js";
|
||||
import { htmlToMfm } from "../misc/html-to-mfm.js";
|
||||
|
@ -611,7 +617,7 @@ export async function updatePerson(
|
|||
},
|
||||
);
|
||||
|
||||
publishInternalEvent("remoteUserUpdated", { id: user.id });
|
||||
publishToInternalStream(InternalEvent.RemoteUser, { id: user.id });
|
||||
|
||||
// Hashtag Update
|
||||
updateUsertags(user, tags);
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
import { config } from "@/config.js";
|
||||
import type { Relay } from "@/models/entities/relay.js";
|
||||
import type { ILocalUser } from "@/models/entities/user.js";
|
||||
|
||||
export function renderFollowRelay(relay: Relay, relayActor: ILocalUser) {
|
||||
const follow = {
|
||||
id: `${config.url}/activities/follow-relay/${relay.id}`,
|
||||
type: "Follow",
|
||||
actor: `${config.url}/users/${relayActor.id}`,
|
||||
object: "https://www.w3.org/ns/activitystreams#Public",
|
||||
};
|
||||
|
||||
return follow;
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
import { config } from "@/config.js";
|
||||
import type { User } from "@/models/entities/user.js";
|
||||
|
||||
export default (object: any, user: { id: User["id"] }) => {
|
||||
export const renderUndo = (object: any, userId: string) => {
|
||||
if (object == null) return null;
|
||||
const id =
|
||||
typeof object.id === "string" && object.id.startsWith(config.url)
|
||||
|
@ -11,7 +10,7 @@ export default (object: any, user: { id: User["id"] }) => {
|
|||
return {
|
||||
type: "Undo",
|
||||
...(id ? { id } : {}),
|
||||
actor: `${config.url}/users/${user.id}`,
|
||||
actor: `${config.url}/users/${userId}`,
|
||||
object,
|
||||
published: new Date().toISOString(),
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@ import { config } from "@/config.js";
|
|||
import type { ILocalUser } from "@/models/entities/user.js";
|
||||
import {
|
||||
extractHost,
|
||||
getInternalActor,
|
||||
getInstanceActor,
|
||||
isAllowedServer,
|
||||
isBlockedServer,
|
||||
isSelfHost,
|
||||
|
@ -112,7 +112,7 @@ export default class Resolver {
|
|||
}
|
||||
|
||||
if (!this.user) {
|
||||
this.user = await getInternalActor("instance");
|
||||
this.user = (await getInstanceActor()) as ILocalUser;
|
||||
}
|
||||
|
||||
apLogger.info(
|
||||
|
|
|
@ -9,7 +9,7 @@ import renderKey from "@/remote/activitypub/renderer/key.js";
|
|||
import { renderPerson } from "@/remote/activitypub/renderer/person.js";
|
||||
import renderEmoji from "@/remote/activitypub/renderer/emoji.js";
|
||||
import { inbox as processInbox } from "@/queue/index.js";
|
||||
import { fetchMeta, getInternalActor, isSelfHost } from "backend-rs";
|
||||
import { fetchMeta, getInstanceActor, isSelfHost } from "backend-rs";
|
||||
import {
|
||||
Notes,
|
||||
Users,
|
||||
|
@ -242,8 +242,8 @@ router.get("/notes/:note", async (ctx, next) => {
|
|||
|
||||
ctx.body = renderActivity(await renderNote(note, false));
|
||||
|
||||
const meta = await fetchMeta();
|
||||
if (meta.secureMode || meta.privateMode) {
|
||||
const instanceMeta = await fetchMeta();
|
||||
if (instanceMeta.secureMode || instanceMeta.privateMode) {
|
||||
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
||||
} else {
|
||||
ctx.set("Cache-Control", "public, max-age=180");
|
||||
|
@ -272,8 +272,8 @@ router.get("/notes/:note/activity", async (ctx) => {
|
|||
}
|
||||
|
||||
ctx.body = renderActivity(await packActivity(note));
|
||||
const meta = await fetchMeta();
|
||||
if (meta.secureMode || meta.privateMode) {
|
||||
const instanceMeta = await fetchMeta();
|
||||
if (instanceMeta.secureMode || instanceMeta.privateMode) {
|
||||
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
||||
} else {
|
||||
ctx.set("Cache-Control", "public, max-age=180");
|
||||
|
@ -295,7 +295,7 @@ router.get("/users/:user/collections/featured", Featured);
|
|||
|
||||
// publickey
|
||||
router.get("/users/:user/publickey", async (ctx) => {
|
||||
const instanceActor = await getInternalActor("instance");
|
||||
const instanceActor = (await getInstanceActor()) as ILocalUser;
|
||||
if (ctx.params.user === instanceActor.id) {
|
||||
ctx.body = renderActivity(
|
||||
renderKey(instanceActor, await getUserKeypair(instanceActor.id)),
|
||||
|
@ -327,8 +327,8 @@ router.get("/users/:user/publickey", async (ctx) => {
|
|||
|
||||
if (Users.isLocalUser(user)) {
|
||||
ctx.body = renderActivity(renderKey(user, keypair));
|
||||
const meta = await fetchMeta();
|
||||
if (meta.secureMode || meta.privateMode) {
|
||||
const instanceMeta = await fetchMeta();
|
||||
if (instanceMeta.secureMode || instanceMeta.privateMode) {
|
||||
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
||||
} else {
|
||||
ctx.set("Cache-Control", "public, max-age=180");
|
||||
|
@ -347,8 +347,8 @@ async function userInfo(ctx: Router.RouterContext, user: User | null) {
|
|||
}
|
||||
|
||||
ctx.body = renderActivity(await renderPerson(user as ILocalUser));
|
||||
const meta = await fetchMeta();
|
||||
if (meta.secureMode || meta.privateMode) {
|
||||
const instanceMeta = await fetchMeta();
|
||||
if (instanceMeta.secureMode || instanceMeta.privateMode) {
|
||||
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
||||
} else {
|
||||
ctx.set("Cache-Control", "public, max-age=180");
|
||||
|
@ -359,7 +359,7 @@ async function userInfo(ctx: Router.RouterContext, user: User | null) {
|
|||
router.get("/users/:user", async (ctx, next) => {
|
||||
if (!isActivityPubReq(ctx)) return await next();
|
||||
|
||||
const instanceActor = await getInternalActor("instance");
|
||||
const instanceActor = (await getInstanceActor()) as ILocalUser;
|
||||
if (ctx.params.user === instanceActor.id) {
|
||||
await userInfo(ctx, instanceActor);
|
||||
return;
|
||||
|
@ -386,7 +386,7 @@ router.get("/@:user", async (ctx, next) => {
|
|||
if (!isActivityPubReq(ctx)) return await next();
|
||||
|
||||
if (ctx.params.user === "instance.actor") {
|
||||
const instanceActor = await getInternalActor("instance");
|
||||
const instanceActor = (await getInstanceActor()) as ILocalUser;
|
||||
await userInfo(ctx, instanceActor);
|
||||
return;
|
||||
}
|
||||
|
@ -407,7 +407,7 @@ router.get("/@:user", async (ctx, next) => {
|
|||
});
|
||||
|
||||
router.get("/actor", async (ctx, _next) => {
|
||||
const instanceActor = await getInternalActor("instance");
|
||||
const instanceActor = (await getInstanceActor()) as ILocalUser;
|
||||
await userInfo(ctx, instanceActor);
|
||||
});
|
||||
//#endregion
|
||||
|
@ -431,8 +431,8 @@ router.get("/emojis/:emoji", async (ctx) => {
|
|||
}
|
||||
|
||||
ctx.body = renderActivity(renderEmoji(emoji));
|
||||
const meta = await fetchMeta();
|
||||
if (meta.secureMode || meta.privateMode) {
|
||||
const instanceMeta = await fetchMeta();
|
||||
if (instanceMeta.secureMode || instanceMeta.privateMode) {
|
||||
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
||||
} else {
|
||||
ctx.set("Cache-Control", "public, max-age=180");
|
||||
|
@ -463,8 +463,8 @@ router.get("/likes/:like", async (ctx) => {
|
|||
}
|
||||
|
||||
ctx.body = renderActivity(await renderLike(reaction, note));
|
||||
const meta = await fetchMeta();
|
||||
if (meta.secureMode || meta.privateMode) {
|
||||
const instanceMeta = await fetchMeta();
|
||||
if (instanceMeta.secureMode || instanceMeta.privateMode) {
|
||||
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
||||
} else {
|
||||
ctx.set("Cache-Control", "public, max-age=180");
|
||||
|
@ -501,8 +501,8 @@ router.get(
|
|||
}
|
||||
|
||||
ctx.body = renderActivity(renderFollow(follower, followee));
|
||||
const meta = await fetchMeta();
|
||||
if (meta.secureMode || meta.privateMode) {
|
||||
const instanceMeta = await fetchMeta();
|
||||
if (instanceMeta.secureMode || instanceMeta.privateMode) {
|
||||
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
||||
} else {
|
||||
ctx.set("Cache-Control", "public, max-age=180");
|
||||
|
@ -544,8 +544,8 @@ router.get("/follows/:followRequestId", async (ctx: Router.RouterContext) => {
|
|||
return;
|
||||
}
|
||||
|
||||
const meta = await fetchMeta();
|
||||
if (meta.secureMode || meta.privateMode) {
|
||||
const instanceMeta = await fetchMeta();
|
||||
if (instanceMeta.secureMode || instanceMeta.privateMode) {
|
||||
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
||||
} else {
|
||||
ctx.set("Cache-Control", "public, max-age=180");
|
||||
|
|
|
@ -57,8 +57,8 @@ export default async (ctx: Router.RouterContext) => {
|
|||
|
||||
ctx.body = renderActivity(rendered);
|
||||
|
||||
const meta = await fetchMeta();
|
||||
if (meta.secureMode || meta.privateMode) {
|
||||
const instanceMeta = await fetchMeta();
|
||||
if (instanceMeta.secureMode || instanceMeta.privateMode) {
|
||||
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
||||
} else {
|
||||
ctx.set("Cache-Control", "public, max-age=180");
|
||||
|
|
|
@ -110,8 +110,8 @@ export default async (ctx: Router.RouterContext) => {
|
|||
ctx.body = renderActivity(rendered);
|
||||
setResponseType(ctx);
|
||||
}
|
||||
const meta = await fetchMeta();
|
||||
if (meta.secureMode || meta.privateMode) {
|
||||
const instanceMeta = await fetchMeta();
|
||||
if (instanceMeta.secureMode || instanceMeta.privateMode) {
|
||||
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
||||
} else {
|
||||
ctx.set("Cache-Control", "public, max-age=180");
|
||||
|
|
|
@ -110,8 +110,8 @@ export default async (ctx: Router.RouterContext) => {
|
|||
ctx.body = renderActivity(rendered);
|
||||
setResponseType(ctx);
|
||||
}
|
||||
const meta = await fetchMeta();
|
||||
if (meta.secureMode || meta.privateMode) {
|
||||
const instanceMeta = await fetchMeta();
|
||||
if (instanceMeta.secureMode || instanceMeta.privateMode) {
|
||||
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
||||
} else {
|
||||
ctx.set("Cache-Control", "public, max-age=180");
|
||||
|
|
|
@ -117,8 +117,8 @@ export default async (ctx: Router.RouterContext) => {
|
|||
|
||||
setResponseType(ctx);
|
||||
}
|
||||
const meta = await fetchMeta();
|
||||
if (meta.secureMode || meta.privateMode) {
|
||||
const instanceMeta = await fetchMeta();
|
||||
if (instanceMeta.secureMode || instanceMeta.privateMode) {
|
||||
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
||||
} else {
|
||||
ctx.set("Cache-Control", "public, max-age=180");
|
||||
|
|
|
@ -117,9 +117,9 @@ export default async (
|
|||
}
|
||||
|
||||
// private mode
|
||||
const meta = await fetchMeta();
|
||||
const instanceMeta = await fetchMeta();
|
||||
if (
|
||||
meta.privateMode &&
|
||||
instanceMeta.privateMode &&
|
||||
ep.meta.requireCredentialPrivateMode &&
|
||||
user == null
|
||||
) {
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import { publishMainStream } from "@/services/stream.js";
|
||||
import {
|
||||
publishToChatStream,
|
||||
publishToGroupChatStream,
|
||||
publishToChatIndexStream,
|
||||
sendPushNotification,
|
||||
publishToMainStream,
|
||||
Event,
|
||||
} from "backend-rs";
|
||||
import type { User, IRemoteUser } from "@/models/entities/user.js";
|
||||
import type { MessagingMessage } from "@/models/entities/messaging-message.js";
|
||||
|
@ -61,7 +62,7 @@ export async function readUserMessagingMessage(
|
|||
|
||||
if (!(await Users.getHasUnreadMessagingMessage(userId))) {
|
||||
// 全ての(いままで未読だった)自分宛てのメッセージを(これで)読みましたよというイベントを発行
|
||||
publishMainStream(userId, "readAllMessagingMessages");
|
||||
await publishToMainStream(userId, Event.ReadAllChats, {});
|
||||
await sendPushNotification(userId, "readAllChats", {});
|
||||
} else {
|
||||
// そのユーザーとのメッセージで未読がなければイベント発行
|
||||
|
@ -135,7 +136,7 @@ export async function readGroupMessagingMessage(
|
|||
|
||||
if (!(await Users.getHasUnreadMessagingMessage(userId))) {
|
||||
// 全ての(いままで未読だった)自分宛てのメッセージを(これで)読みましたよというイベントを発行
|
||||
publishMainStream(userId, "readAllMessagingMessages");
|
||||
await publishToMainStream(userId, Event.ReadAllChats, {});
|
||||
await sendPushNotification(userId, "readAllChats", {});
|
||||
} else {
|
||||
// そのグループにおいて未読がなければイベント発行
|
||||
|
@ -173,10 +174,10 @@ export async function deliverReadActivity(
|
|||
undefined,
|
||||
contents,
|
||||
);
|
||||
deliver(user, renderActivity(collection), recipient.inbox);
|
||||
deliver(user.id, renderActivity(collection), recipient.inbox);
|
||||
} else {
|
||||
for (const content of contents) {
|
||||
deliver(user, renderActivity(content), recipient.inbox);
|
||||
deliver(user.id, renderActivity(content), recipient.inbox);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { In } from "typeorm";
|
||||
import { publishMainStream } from "@/services/stream.js";
|
||||
import { sendPushNotification } from "backend-rs";
|
||||
import { Event, publishToMainStream, sendPushNotification } from "backend-rs";
|
||||
import type { User } from "@/models/entities/user.js";
|
||||
import type { Notification } from "@/models/entities/notification.js";
|
||||
import { Notifications, Users } from "@/models/index.js";
|
||||
|
@ -46,7 +45,7 @@ export async function readNotificationByQuery(
|
|||
}
|
||||
|
||||
function postReadAllNotifications(userId: User["id"]) {
|
||||
publishMainStream(userId, "readAllNotifications");
|
||||
publishToMainStream(userId, Event.ReadAllNotifications, {});
|
||||
return sendPushNotification(userId, "readAllNotifications", {});
|
||||
}
|
||||
|
||||
|
@ -54,7 +53,7 @@ function postReadNotifications(
|
|||
userId: User["id"],
|
||||
notificationIds: Notification["id"][],
|
||||
) {
|
||||
publishMainStream(userId, "readNotifications", notificationIds);
|
||||
publishToMainStream(userId, Event.ReadNotifications, notificationIds);
|
||||
return sendPushNotification(userId, "readNotifications", {
|
||||
notificationIds,
|
||||
});
|
||||
|
|
|
@ -3,8 +3,7 @@ import type Koa from "koa";
|
|||
import { config } from "@/config.js";
|
||||
import type { ILocalUser } from "@/models/entities/user.js";
|
||||
import { Signins } from "@/models/index.js";
|
||||
import { genIdAt } from "backend-rs";
|
||||
import { publishMainStream } from "@/services/stream.js";
|
||||
import { Event, genIdAt, publishToMainStream } from "backend-rs";
|
||||
|
||||
export default function (ctx: Koa.Context, user: ILocalUser, redirect = false) {
|
||||
if (redirect) {
|
||||
|
@ -40,6 +39,6 @@ export default function (ctx: Koa.Context, user: ILocalUser, redirect = false) {
|
|||
}).then((x) => Signins.findOneByOrFail(x.identifiers[0]));
|
||||
|
||||
// Publish signin event
|
||||
publishMainStream(user.id, "signin", await Signins.pack(record));
|
||||
publishToMainStream(user.id, Event.Signin, await Signins.pack(record));
|
||||
})();
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import define from "@/server/api/define.js";
|
||||
import { Users } from "@/models/index.js";
|
||||
import { doPostSuspend } from "@/services/suspend-user.js";
|
||||
import { publishUserEvent } from "@/services/stream.js";
|
||||
import { publishToUserStream, UserEvent } from "backend-rs";
|
||||
import { createDeleteAccountJob } from "@/queue/index.js";
|
||||
|
||||
export const meta = {
|
||||
|
@ -53,6 +53,6 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
|
||||
if (Users.isLocalUser(user)) {
|
||||
// Terminate streaming
|
||||
publishUserEvent(user.id, "terminate", {});
|
||||
await publishToUserStream(user.id, UserEvent.Disconnect, {});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Users, UserProfiles } from "@/models/index.js";
|
||||
import { publishMainStream } from "@/services/stream.js";
|
||||
import { Event, publishToMainStream } from "backend-rs";
|
||||
import define from "@/server/api/define.js";
|
||||
|
||||
export const meta = {
|
||||
|
@ -36,5 +36,5 @@ export default define(meta, paramDef, async (ps) => {
|
|||
includeSecrets: true,
|
||||
});
|
||||
|
||||
publishMainStream(user.id, "meUpdated", iObj);
|
||||
publishToMainStream(user.id, Event.Me, iObj);
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Users, UserProfiles, UserSecurityKeys } from "@/models/index.js";
|
||||
import { publishMainStream } from "@/services/stream.js";
|
||||
import { Event, publishToMainStream } from "backend-rs";
|
||||
import define from "@/server/api/define.js";
|
||||
|
||||
export const meta = {
|
||||
|
@ -38,5 +38,5 @@ export default define(meta, paramDef, async (ps) => {
|
|||
includeSecrets: true,
|
||||
});
|
||||
|
||||
publishMainStream(user.id, "meUpdated", iObj);
|
||||
publishToMainStream(user.id, Event.Me, iObj);
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import define from "@/server/api/define.js";
|
||||
import { Users } from "@/models/index.js";
|
||||
import { insertModerationLog } from "@/services/insert-moderation-log.js";
|
||||
import { publishInternalEvent } from "@/services/stream.js";
|
||||
import { InternalEvent, publishToInternalStream } from "backend-rs";
|
||||
export const meta = {
|
||||
tags: ["admin"],
|
||||
|
||||
|
@ -33,7 +33,7 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
driveCapacityOverrideMb: ps.overrideMb,
|
||||
});
|
||||
|
||||
publishInternalEvent("localUserUpdated", {
|
||||
publishToInternalStream(InternalEvent.LocalUser, {
|
||||
id: user.id,
|
||||
});
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import define from "@/server/api/define.js";
|
|||
import { Emojis, DriveFiles } from "@/models/index.js";
|
||||
import {
|
||||
type ImageSize,
|
||||
genId,
|
||||
genIdAt,
|
||||
getImageSizeFromUrl,
|
||||
publishToBroadcastStream,
|
||||
} from "backend-rs";
|
||||
|
@ -36,7 +36,31 @@ export const meta = {
|
|||
export const paramDef = {
|
||||
type: "object",
|
||||
properties: {
|
||||
fileId: { type: "string", format: "misskey:id" },
|
||||
fileId: {
|
||||
type: "string",
|
||||
format: "misskey:id",
|
||||
nullable: false,
|
||||
},
|
||||
name: {
|
||||
type: "string",
|
||||
nullable: false,
|
||||
},
|
||||
category: {
|
||||
type: "string",
|
||||
nullable: false,
|
||||
},
|
||||
aliases: {
|
||||
type: "array",
|
||||
nullable: false,
|
||||
items: {
|
||||
type: "string",
|
||||
nullable: false,
|
||||
},
|
||||
},
|
||||
license: {
|
||||
type: "string",
|
||||
nullable: false,
|
||||
},
|
||||
},
|
||||
required: ["fileId"],
|
||||
} as const;
|
||||
|
@ -50,7 +74,10 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
|
||||
if (file == null) throw new ApiError(meta.errors.noSuchFile);
|
||||
|
||||
const name = file.name.split(".")[0].match(/^[a-z0-9_]+$/)
|
||||
const name =
|
||||
ps.name != null
|
||||
? ps.name
|
||||
: file.name.split(".")[0].match(/^[a-z0-9_]+$/)
|
||||
? file.name.split(".")[0]
|
||||
: `_${rndstr("a-z0-9", 8)}_`;
|
||||
|
||||
|
@ -62,17 +89,19 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
apiLogger.debug(inspect(err));
|
||||
}
|
||||
|
||||
const now = new Date();
|
||||
|
||||
const emoji = await Emojis.insert({
|
||||
id: genId(),
|
||||
updatedAt: new Date(),
|
||||
id: genIdAt(now),
|
||||
updatedAt: now,
|
||||
name: name,
|
||||
category: null,
|
||||
category: ps.category ?? null,
|
||||
host: null,
|
||||
aliases: [],
|
||||
aliases: ps.aliases ?? [],
|
||||
originalUrl: file.url,
|
||||
publicUrl: file.webpublicUrl ?? file.url,
|
||||
type: file.webpublicType ?? file.type,
|
||||
license: null,
|
||||
license: ps.license ?? null,
|
||||
width: size?.width || null,
|
||||
height: size?.height || null,
|
||||
}).then((x) => Emojis.findOneByOrFail(x.identifiers[0]));
|
||||
|
|
|
@ -470,97 +470,98 @@ export const paramDef = {
|
|||
} as const;
|
||||
|
||||
export default define(meta, paramDef, async () => {
|
||||
const instance = await fetchMeta();
|
||||
const instanceMeta = await fetchMeta();
|
||||
|
||||
return {
|
||||
maintainerName: instance.maintainerName,
|
||||
maintainerEmail: instance.maintainerEmail,
|
||||
maintainerName: instanceMeta.maintainerName,
|
||||
maintainerEmail: instanceMeta.maintainerEmail,
|
||||
version: config.version,
|
||||
name: instance.name,
|
||||
name: instanceMeta.name,
|
||||
uri: config.url,
|
||||
description: instance.description,
|
||||
langs: instance.langs,
|
||||
tosUrl: instance.tosUrl,
|
||||
moreUrls: instance.moreUrls,
|
||||
repositoryUrl: instance.repositoryUrl,
|
||||
feedbackUrl: instance.feedbackUrl,
|
||||
disableRegistration: instance.disableRegistration,
|
||||
disableLocalTimeline: instance.disableLocalTimeline,
|
||||
disableRecommendedTimeline: instance.disableRecommendedTimeline,
|
||||
disableGlobalTimeline: instance.disableGlobalTimeline,
|
||||
enableGuestTimeline: instance.enableGuestTimeline,
|
||||
driveCapacityPerLocalUserMb: instance.localDriveCapacityMb,
|
||||
driveCapacityPerRemoteUserMb: instance.remoteDriveCapacityMb,
|
||||
antennaLimit: instance.antennaLimit,
|
||||
emailRequiredForSignup: instance.emailRequiredForSignup,
|
||||
enableHcaptcha: instance.enableHcaptcha,
|
||||
hcaptchaSiteKey: instance.hcaptchaSiteKey,
|
||||
enableRecaptcha: instance.enableRecaptcha,
|
||||
recaptchaSiteKey: instance.recaptchaSiteKey,
|
||||
swPublickey: instance.swPublicKey,
|
||||
themeColor: instance.themeColor,
|
||||
mascotImageUrl: instance.mascotImageUrl,
|
||||
bannerUrl: instance.bannerUrl,
|
||||
errorImageUrl: instance.errorImageUrl,
|
||||
iconUrl: instance.iconUrl,
|
||||
backgroundImageUrl: instance.backgroundImageUrl,
|
||||
logoImageUrl: instance.logoImageUrl,
|
||||
description: instanceMeta.description,
|
||||
langs: instanceMeta.langs,
|
||||
tosUrl: instanceMeta.tosUrl,
|
||||
moreUrls: instanceMeta.moreUrls,
|
||||
repositoryUrl: instanceMeta.repositoryUrl,
|
||||
feedbackUrl: instanceMeta.feedbackUrl,
|
||||
disableRegistration: instanceMeta.disableRegistration,
|
||||
disableLocalTimeline: instanceMeta.disableLocalTimeline,
|
||||
disableRecommendedTimeline: instanceMeta.disableRecommendedTimeline,
|
||||
disableGlobalTimeline: instanceMeta.disableGlobalTimeline,
|
||||
enableGuestTimeline: instanceMeta.enableGuestTimeline,
|
||||
driveCapacityPerLocalUserMb: instanceMeta.localDriveCapacityMb,
|
||||
driveCapacityPerRemoteUserMb: instanceMeta.remoteDriveCapacityMb,
|
||||
antennaLimit: instanceMeta.antennaLimit,
|
||||
emailRequiredForSignup: instanceMeta.emailRequiredForSignup,
|
||||
enableHcaptcha: instanceMeta.enableHcaptcha,
|
||||
hcaptchaSiteKey: instanceMeta.hcaptchaSiteKey,
|
||||
enableRecaptcha: instanceMeta.enableRecaptcha,
|
||||
recaptchaSiteKey: instanceMeta.recaptchaSiteKey,
|
||||
swPublickey: instanceMeta.swPublicKey,
|
||||
themeColor: instanceMeta.themeColor,
|
||||
mascotImageUrl: instanceMeta.mascotImageUrl,
|
||||
bannerUrl: instanceMeta.bannerUrl,
|
||||
errorImageUrl: instanceMeta.errorImageUrl,
|
||||
iconUrl: instanceMeta.iconUrl,
|
||||
backgroundImageUrl: instanceMeta.backgroundImageUrl,
|
||||
logoImageUrl: instanceMeta.logoImageUrl,
|
||||
maxNoteTextLength: config.maxNoteLength, // for backward compatibility
|
||||
maxCaptionTextLength: config.maxCaptionLength,
|
||||
defaultLightTheme: instance.defaultLightTheme,
|
||||
defaultDarkTheme: instance.defaultDarkTheme,
|
||||
enableEmail: instance.enableEmail,
|
||||
enableServiceWorker: instance.enableServiceWorker,
|
||||
defaultLightTheme: instanceMeta.defaultLightTheme,
|
||||
defaultDarkTheme: instanceMeta.defaultDarkTheme,
|
||||
enableEmail: instanceMeta.enableEmail,
|
||||
enableServiceWorker: instanceMeta.enableServiceWorker,
|
||||
translatorAvailable:
|
||||
instance.deeplAuthKey != null || instance.libreTranslateApiUrl != null,
|
||||
pinnedPages: instance.pinnedPages,
|
||||
pinnedClipId: instance.pinnedClipId,
|
||||
cacheRemoteFiles: instance.cacheRemoteFiles,
|
||||
markLocalFilesNsfwByDefault: instance.markLocalFilesNsfwByDefault,
|
||||
defaultReaction: instance.defaultReaction,
|
||||
recommendedInstances: instance.recommendedInstances,
|
||||
pinnedUsers: instance.pinnedUsers,
|
||||
customMOTD: instance.customMotd,
|
||||
customSplashIcons: instance.customSplashIcons,
|
||||
hiddenTags: instance.hiddenTags,
|
||||
blockedHosts: instance.blockedHosts,
|
||||
silencedHosts: instance.silencedHosts,
|
||||
allowedHosts: instance.allowedHosts,
|
||||
privateMode: instance.privateMode,
|
||||
secureMode: instance.secureMode,
|
||||
hcaptchaSecretKey: instance.hcaptchaSecretKey,
|
||||
recaptchaSecretKey: instance.recaptchaSecretKey,
|
||||
proxyAccountId: instance.proxyAccountId,
|
||||
summalyProxy: instance.summalyProxy,
|
||||
email: instance.email,
|
||||
smtpSecure: instance.smtpSecure,
|
||||
smtpHost: instance.smtpHost,
|
||||
smtpPort: instance.smtpPort,
|
||||
smtpUser: instance.smtpUser,
|
||||
smtpPass: instance.smtpPass,
|
||||
swPrivateKey: instance.swPrivateKey,
|
||||
useObjectStorage: instance.useObjectStorage,
|
||||
objectStorageBaseUrl: instance.objectStorageBaseUrl,
|
||||
objectStorageBucket: instance.objectStorageBucket,
|
||||
objectStoragePrefix: instance.objectStoragePrefix,
|
||||
objectStorageEndpoint: instance.objectStorageEndpoint,
|
||||
objectStorageRegion: instance.objectStorageRegion,
|
||||
objectStoragePort: instance.objectStoragePort,
|
||||
objectStorageAccessKey: instance.objectStorageAccessKey,
|
||||
objectStorageSecretKey: instance.objectStorageSecretKey,
|
||||
objectStorageUseSSL: instance.objectStorageUseSsl,
|
||||
objectStorageUseProxy: instance.objectStorageUseProxy,
|
||||
objectStorageSetPublicRead: instance.objectStorageSetPublicRead,
|
||||
objectStorageS3ForcePathStyle: instance.objectStorageS3ForcePathStyle,
|
||||
deeplAuthKey: instance.deeplAuthKey,
|
||||
deeplIsPro: instance.deeplIsPro,
|
||||
libreTranslateApiUrl: instance.libreTranslateApiUrl,
|
||||
libreTranslateApiKey: instance.libreTranslateApiKey,
|
||||
enableIpLogging: instance.enableIpLogging,
|
||||
enableActiveEmailValidation: instance.enableActiveEmailValidation,
|
||||
experimentalFeatures: instance.experimentalFeatures,
|
||||
enableServerMachineStats: instance.enableServerMachineStats,
|
||||
enableIdenticonGeneration: instance.enableIdenticonGeneration,
|
||||
donationLink: instance.donationLink,
|
||||
instanceMeta.deeplAuthKey != null ||
|
||||
instanceMeta.libreTranslateApiUrl != null,
|
||||
pinnedPages: instanceMeta.pinnedPages,
|
||||
pinnedClipId: instanceMeta.pinnedClipId,
|
||||
cacheRemoteFiles: instanceMeta.cacheRemoteFiles,
|
||||
markLocalFilesNsfwByDefault: instanceMeta.markLocalFilesNsfwByDefault,
|
||||
defaultReaction: instanceMeta.defaultReaction,
|
||||
recommendedInstances: instanceMeta.recommendedInstances,
|
||||
pinnedUsers: instanceMeta.pinnedUsers,
|
||||
customMOTD: instanceMeta.customMotd,
|
||||
customSplashIcons: instanceMeta.customSplashIcons,
|
||||
hiddenTags: instanceMeta.hiddenTags,
|
||||
blockedHosts: instanceMeta.blockedHosts,
|
||||
silencedHosts: instanceMeta.silencedHosts,
|
||||
allowedHosts: instanceMeta.allowedHosts,
|
||||
privateMode: instanceMeta.privateMode,
|
||||
secureMode: instanceMeta.secureMode,
|
||||
hcaptchaSecretKey: instanceMeta.hcaptchaSecretKey,
|
||||
recaptchaSecretKey: instanceMeta.recaptchaSecretKey,
|
||||
proxyAccountId: instanceMeta.proxyAccountId,
|
||||
summalyProxy: instanceMeta.summalyProxy,
|
||||
email: instanceMeta.email,
|
||||
smtpSecure: instanceMeta.smtpSecure,
|
||||
smtpHost: instanceMeta.smtpHost,
|
||||
smtpPort: instanceMeta.smtpPort,
|
||||
smtpUser: instanceMeta.smtpUser,
|
||||
smtpPass: instanceMeta.smtpPass,
|
||||
swPrivateKey: instanceMeta.swPrivateKey,
|
||||
useObjectStorage: instanceMeta.useObjectStorage,
|
||||
objectStorageBaseUrl: instanceMeta.objectStorageBaseUrl,
|
||||
objectStorageBucket: instanceMeta.objectStorageBucket,
|
||||
objectStoragePrefix: instanceMeta.objectStoragePrefix,
|
||||
objectStorageEndpoint: instanceMeta.objectStorageEndpoint,
|
||||
objectStorageRegion: instanceMeta.objectStorageRegion,
|
||||
objectStoragePort: instanceMeta.objectStoragePort,
|
||||
objectStorageAccessKey: instanceMeta.objectStorageAccessKey,
|
||||
objectStorageSecretKey: instanceMeta.objectStorageSecretKey,
|
||||
objectStorageUseSSL: instanceMeta.objectStorageUseSsl,
|
||||
objectStorageUseProxy: instanceMeta.objectStorageUseProxy,
|
||||
objectStorageSetPublicRead: instanceMeta.objectStorageSetPublicRead,
|
||||
objectStorageS3ForcePathStyle: instanceMeta.objectStorageS3ForcePathStyle,
|
||||
deeplAuthKey: instanceMeta.deeplAuthKey,
|
||||
deeplIsPro: instanceMeta.deeplIsPro,
|
||||
libreTranslateApiUrl: instanceMeta.libreTranslateApiUrl,
|
||||
libreTranslateApiKey: instanceMeta.libreTranslateApiKey,
|
||||
enableIpLogging: instanceMeta.enableIpLogging,
|
||||
enableActiveEmailValidation: instanceMeta.enableActiveEmailValidation,
|
||||
experimentalFeatures: instanceMeta.experimentalFeatures,
|
||||
enableServerMachineStats: instanceMeta.enableServerMachineStats,
|
||||
enableIdenticonGeneration: instanceMeta.enableIdenticonGeneration,
|
||||
donationLink: instanceMeta.donationLink,
|
||||
};
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import define from "@/server/api/define.js";
|
||||
import { Users } from "@/models/index.js";
|
||||
import { publishInternalEvent } from "@/services/stream.js";
|
||||
import { InternalEvent, publishToInternalStream } from "backend-rs";
|
||||
|
||||
export const meta = {
|
||||
tags: ["admin"],
|
||||
|
@ -32,7 +32,7 @@ export default define(meta, paramDef, async (ps) => {
|
|||
isModerator: true,
|
||||
});
|
||||
|
||||
publishInternalEvent("userChangeModeratorState", {
|
||||
publishToInternalStream(InternalEvent.Moderator, {
|
||||
id: user.id,
|
||||
isModerator: true,
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import define from "@/server/api/define.js";
|
||||
import { Users } from "@/models/index.js";
|
||||
import { publishInternalEvent } from "@/services/stream.js";
|
||||
import { InternalEvent, publishToInternalStream } from "backend-rs";
|
||||
|
||||
export const meta = {
|
||||
tags: ["admin"],
|
||||
|
@ -28,7 +28,7 @@ export default define(meta, paramDef, async (ps) => {
|
|||
isModerator: false,
|
||||
});
|
||||
|
||||
publishInternalEvent("userChangeModeratorState", {
|
||||
publishToInternalStream(InternalEvent.Moderator, {
|
||||
id: user.id,
|
||||
isModerator: false,
|
||||
});
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import define from "@/server/api/define.js";
|
||||
import { AbuseUserReports, Users } from "@/models/index.js";
|
||||
import { getInternalActor } from "backend-rs";
|
||||
import { getInstanceActor } from "backend-rs";
|
||||
import { deliver } from "@/queue/index.js";
|
||||
import { renderActivity } from "@/remote/activitypub/renderer/index.js";
|
||||
import { renderFlag } from "@/remote/activitypub/renderer/flag.js";
|
||||
import { ILocalUser } from "@/models/entities/user";
|
||||
|
||||
export const meta = {
|
||||
tags: ["admin"],
|
||||
|
@ -29,11 +30,11 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
}
|
||||
|
||||
if (ps.forward && report.targetUserHost != null) {
|
||||
const actor = await getInternalActor("instance");
|
||||
const actor = (await getInstanceActor()) as ILocalUser;
|
||||
const targetUser = await Users.findOneByOrFail({ id: report.targetUserId });
|
||||
|
||||
deliver(
|
||||
actor,
|
||||
actor.id,
|
||||
renderActivity(renderFlag(actor, [targetUser.uri!], report.comment)),
|
||||
targetUser.inbox,
|
||||
);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import define from "@/server/api/define.js";
|
||||
import { Users } from "@/models/index.js";
|
||||
import { publishInternalEvent } from "@/services/stream.js";
|
||||
import type { EmojiModPerm } from "@/models/entities/user.js";
|
||||
import { unsafeCast } from "@/prelude/unsafe-cast.js";
|
||||
|
||||
|
@ -36,9 +35,4 @@ export default define(meta, paramDef, async (ps) => {
|
|||
await Users.update(user.id, {
|
||||
emojiModPerm: unsafeCast<EmojiModPerm>(ps.emojiModPerm),
|
||||
});
|
||||
|
||||
publishInternalEvent("userChangeModeratorState", {
|
||||
id: user.id,
|
||||
isModerator: true,
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import define from "@/server/api/define.js";
|
||||
import { Users } from "@/models/index.js";
|
||||
import { insertModerationLog } from "@/services/insert-moderation-log.js";
|
||||
import { publishInternalEvent } from "@/services/stream.js";
|
||||
import { InternalEvent, publishToInternalStream } from "backend-rs";
|
||||
|
||||
export const meta = {
|
||||
tags: ["admin"],
|
||||
|
@ -33,7 +33,7 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
isSilenced: true,
|
||||
});
|
||||
|
||||
publishInternalEvent("userChangeSilencedState", {
|
||||
publishToInternalStream(InternalEvent.Silence, {
|
||||
id: user.id,
|
||||
isSilenced: true,
|
||||
});
|
||||
|
|
|
@ -4,7 +4,7 @@ import { Users, Followings, Notifications } from "@/models/index.js";
|
|||
import type { User } from "@/models/entities/user.js";
|
||||
import { insertModerationLog } from "@/services/insert-moderation-log.js";
|
||||
import { doPostSuspend } from "@/services/suspend-user.js";
|
||||
import { publishUserEvent } from "@/services/stream.js";
|
||||
import { publishToUserStream, UserEvent } from "backend-rs";
|
||||
|
||||
export const meta = {
|
||||
tags: ["admin"],
|
||||
|
@ -46,7 +46,7 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
|
||||
// Terminate streaming
|
||||
if (Users.isLocalUser(user)) {
|
||||
publishUserEvent(user.id, "terminate", {});
|
||||
await publishToUserStream(user.id, UserEvent.Disconnect, {});
|
||||
}
|
||||
|
||||
(async () => {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import define from "@/server/api/define.js";
|
||||
import { Users } from "@/models/index.js";
|
||||
import { insertModerationLog } from "@/services/insert-moderation-log.js";
|
||||
import { publishInternalEvent } from "@/services/stream.js";
|
||||
import { InternalEvent, publishToInternalStream } from "backend-rs";
|
||||
|
||||
export const meta = {
|
||||
tags: ["admin"],
|
||||
|
@ -29,7 +29,7 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
isSilenced: false,
|
||||
});
|
||||
|
||||
publishInternalEvent("userChangeSilencedState", {
|
||||
publishToInternalStream(InternalEvent.Silence, {
|
||||
id: user.id,
|
||||
isSilenced: false,
|
||||
});
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
import define from "@/server/api/define.js";
|
||||
import { fetchMeta, genIdAt, updateAntennaCache } from "backend-rs";
|
||||
import {
|
||||
fetchMeta,
|
||||
genIdAt,
|
||||
InternalEvent,
|
||||
publishToInternalStream,
|
||||
updateAntennaCache,
|
||||
} from "backend-rs";
|
||||
import { Antennas, UserLists, UserGroupJoinings } from "@/models/index.js";
|
||||
import { ApiError } from "@/server/api/error.js";
|
||||
import { publishInternalEvent } from "@/services/stream.js";
|
||||
|
||||
export const meta = {
|
||||
tags: ["antennas"],
|
||||
|
@ -123,12 +128,12 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
let userList;
|
||||
let userGroupJoining;
|
||||
|
||||
const instance = await fetchMeta();
|
||||
const instanceMeta = await fetchMeta();
|
||||
|
||||
const antennas = await Antennas.findBy({
|
||||
userId: user.id,
|
||||
});
|
||||
if (antennas.length >= instance.antennaLimit) {
|
||||
if (antennas.length >= instanceMeta.antennaLimit) {
|
||||
throw new ApiError(meta.errors.tooManyAntennas);
|
||||
}
|
||||
|
||||
|
@ -172,7 +177,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
notify: ps.notify,
|
||||
}).then((x) => Antennas.findOneByOrFail(x.identifiers[0]));
|
||||
|
||||
publishInternalEvent("antennaCreated", antenna);
|
||||
await publishToInternalStream(InternalEvent.AntennaCreated, antenna);
|
||||
await updateAntennaCache();
|
||||
|
||||
return await Antennas.pack(antenna);
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
import define from "@/server/api/define.js";
|
||||
import { ApiError } from "@/server/api/error.js";
|
||||
import { Antennas } from "@/models/index.js";
|
||||
import { publishInternalEvent } from "@/services/stream.js";
|
||||
import { updateAntennaCache } from "backend-rs";
|
||||
import {
|
||||
InternalEvent,
|
||||
publishToInternalStream,
|
||||
updateAntennaCache,
|
||||
} from "backend-rs";
|
||||
|
||||
export const meta = {
|
||||
tags: ["antennas"],
|
||||
|
@ -40,6 +43,6 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
|
||||
await Antennas.delete(antenna.id);
|
||||
|
||||
publishInternalEvent("antennaDeleted", antenna);
|
||||
await publishToInternalStream(InternalEvent.AntennaDeleted, antenna);
|
||||
await updateAntennaCache();
|
||||
});
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
import define from "@/server/api/define.js";
|
||||
import { ApiError } from "@/server/api/error.js";
|
||||
import { Antennas, UserLists, UserGroupJoinings } from "@/models/index.js";
|
||||
import { publishInternalEvent } from "@/services/stream.js";
|
||||
import { updateAntennaCache } from "backend-rs";
|
||||
import {
|
||||
InternalEvent,
|
||||
publishToInternalStream,
|
||||
updateAntennaCache,
|
||||
} from "backend-rs";
|
||||
|
||||
export const meta = {
|
||||
tags: ["antennas"],
|
||||
|
@ -163,8 +166,8 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
notify: ps.notify,
|
||||
});
|
||||
|
||||
publishInternalEvent(
|
||||
"antennaUpdated",
|
||||
await publishToInternalStream(
|
||||
InternalEvent.AntennaUpdated,
|
||||
await Antennas.findOneByOrFail({ id: antenna.id }),
|
||||
);
|
||||
await updateAntennaCache();
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import define from "@/server/api/define.js";
|
||||
import { ApiError } from "@/server/api/error.js";
|
||||
import { Channels, ChannelFollowings } from "@/models/index.js";
|
||||
import { genIdAt } from "backend-rs";
|
||||
import { publishUserEvent } from "@/services/stream.js";
|
||||
import { genIdAt, publishToUserStream, UserEvent } from "backend-rs";
|
||||
|
||||
export const meta = {
|
||||
tags: ["channels"],
|
||||
|
@ -46,5 +45,5 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
followeeId: channel.id,
|
||||
});
|
||||
|
||||
publishUserEvent(user.id, "followChannel", channel);
|
||||
await publishToUserStream(user.id, UserEvent.FollowChannel, channel);
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import define from "@/server/api/define.js";
|
||||
import { ApiError } from "@/server/api/error.js";
|
||||
import { Channels, ChannelFollowings } from "@/models/index.js";
|
||||
import { publishUserEvent } from "@/services/stream.js";
|
||||
import { publishToUserStream, UserEvent } from "backend-rs";
|
||||
|
||||
export const meta = {
|
||||
tags: ["channels"],
|
||||
|
@ -41,5 +41,5 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
followeeId: channel.id,
|
||||
});
|
||||
|
||||
publishUserEvent(user.id, "unfollowChannel", channel);
|
||||
await publishToUserStream(user.id, UserEvent.UnfollowChannel, channel);
|
||||
});
|
||||
|
|
|
@ -27,7 +27,7 @@ export const paramDef = {
|
|||
} as const;
|
||||
|
||||
export default define(meta, paramDef, async () => {
|
||||
const meta = await fetchMeta();
|
||||
const motd = await Promise.all(meta.customMotd.map((x) => x));
|
||||
const instanceMeta = await fetchMeta();
|
||||
const motd = await Promise.all(instanceMeta.customMotd.map((x) => x));
|
||||
return motd;
|
||||
});
|
||||
|
|
|
@ -27,7 +27,7 @@ export const paramDef = {
|
|||
} as const;
|
||||
|
||||
export default define(meta, paramDef, async () => {
|
||||
const meta = await fetchMeta();
|
||||
const icons = await Promise.all(meta.customSplashIcons.map((x) => x));
|
||||
const instanceMeta = await fetchMeta();
|
||||
const icons = await Promise.all(instanceMeta.customSplashIcons.map((x) => x));
|
||||
return icons;
|
||||
});
|
||||
|
|
|
@ -35,7 +35,7 @@ export const paramDef = {
|
|||
} as const;
|
||||
|
||||
export default define(meta, paramDef, async (ps, user) => {
|
||||
const instance = await fetchMeta();
|
||||
const instanceMeta = await fetchMeta();
|
||||
|
||||
// Calculate drive usage
|
||||
const usage = await DriveFiles.calcDriveUsageOf(user.id);
|
||||
|
@ -44,7 +44,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
capacity:
|
||||
1024 *
|
||||
1024 *
|
||||
(user.driveCapacityOverrideMb || instance.localDriveCapacityMb),
|
||||
(user.driveCapacityOverrideMb || instanceMeta.localDriveCapacityMb),
|
||||
usage: usage,
|
||||
};
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { uploadFromUrl } from "@/services/drive/upload-from-url.js";
|
||||
import define from "@/server/api/define.js";
|
||||
import { DriveFiles } from "@/models/index.js";
|
||||
import { publishMainStream } from "@/services/stream.js";
|
||||
import { Event, publishToMainStream } from "backend-rs";
|
||||
import { HOUR } from "@/const.js";
|
||||
|
||||
export const meta = {
|
||||
|
@ -24,6 +24,7 @@ export const paramDef = {
|
|||
type: "object",
|
||||
properties: {
|
||||
url: { type: "string" },
|
||||
name: { type: "string" },
|
||||
folderId: {
|
||||
type: "string",
|
||||
format: "misskey:id",
|
||||
|
@ -41,6 +42,7 @@ export const paramDef = {
|
|||
export default define(meta, paramDef, async (ps, user) => {
|
||||
uploadFromUrl({
|
||||
url: ps.url,
|
||||
name: ps.name,
|
||||
user,
|
||||
folderId: ps.folderId,
|
||||
sensitive: ps.isSensitive,
|
||||
|
@ -48,7 +50,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
comment: ps.comment,
|
||||
}).then((file) => {
|
||||
DriveFiles.pack(file, { self: true }).then((packedFile) => {
|
||||
publishMainStream(user.id, "urlUploadFinished", {
|
||||
publishToMainStream(user.id, Event.UrlUploadFinished, {
|
||||
marker: ps.marker,
|
||||
file: packedFile,
|
||||
});
|
||||
|
|
|
@ -37,15 +37,13 @@ export const paramDef = {
|
|||
required: ["name"],
|
||||
} as const;
|
||||
|
||||
export default define(meta, paramDef, async (ps, me) => {
|
||||
const emoji = await Emojis.findOne({
|
||||
where: {
|
||||
export default define(meta, paramDef, async (ps) => {
|
||||
const emoji = await Emojis.findOneBy({
|
||||
name: ps.name,
|
||||
host: IsNull(),
|
||||
},
|
||||
});
|
||||
|
||||
if (!emoji) {
|
||||
if (emoji == null) {
|
||||
throw new ApiError(meta.errors.noSuchEmoji);
|
||||
}
|
||||
|
||||
|
|
|
@ -100,33 +100,33 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
}
|
||||
|
||||
if (typeof ps.blocked === "boolean") {
|
||||
const meta = await fetchMeta();
|
||||
const instanceMeta = await fetchMeta();
|
||||
if (ps.blocked) {
|
||||
if (meta.blockedHosts.length === 0) {
|
||||
if (instanceMeta.blockedHosts.length === 0) {
|
||||
return [];
|
||||
}
|
||||
query.andWhere("instance.host IN (:...blocks)", {
|
||||
blocks: meta.blockedHosts,
|
||||
blocks: instanceMeta.blockedHosts,
|
||||
});
|
||||
} else if (meta.blockedHosts.length > 0) {
|
||||
} else if (instanceMeta.blockedHosts.length > 0) {
|
||||
query.andWhere("instance.host NOT IN (:...blocks)", {
|
||||
blocks: meta.blockedHosts,
|
||||
blocks: instanceMeta.blockedHosts,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof ps.silenced === "boolean") {
|
||||
const meta = await fetchMeta();
|
||||
const instanceMeta = await fetchMeta();
|
||||
if (ps.silenced) {
|
||||
if (meta.silencedHosts.length === 0) {
|
||||
if (instanceMeta.silencedHosts.length === 0) {
|
||||
return [];
|
||||
}
|
||||
query.andWhere("instance.host IN (:...silences)", {
|
||||
silences: meta.silencedHosts,
|
||||
silences: instanceMeta.silencedHosts,
|
||||
});
|
||||
} else if (meta.silencedHosts.length > 0) {
|
||||
} else if (instanceMeta.silencedHosts.length > 0) {
|
||||
query.andWhere("instance.host NOT IN (:...silences)", {
|
||||
silences: meta.silencedHosts,
|
||||
silences: instanceMeta.silencedHosts,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,8 +66,8 @@ export const paramDef = {
|
|||
} as const;
|
||||
|
||||
export default define(meta, paramDef, async () => {
|
||||
const instance = await fetchMeta();
|
||||
const hiddenTags = instance.hiddenTags.map((t) => normalizeForSearch(t));
|
||||
const instanceMeta = await fetchMeta();
|
||||
const hiddenTags = instanceMeta.hiddenTags.map((t) => normalizeForSearch(t));
|
||||
|
||||
const now = new Date(); // 5分単位で丸めた現在日時
|
||||
now.setMinutes(Math.round(now.getMinutes() / 5) * 5, 0, 0);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { publishMainStream } from "@/services/stream.js";
|
||||
import { Event, publishToMainStream } from "backend-rs";
|
||||
import * as OTPAuth from "otpauth";
|
||||
import define from "@/server/api/define.js";
|
||||
import { Users, UserProfiles } from "@/models/index.js";
|
||||
|
@ -47,5 +47,5 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
includeSecrets: true,
|
||||
});
|
||||
|
||||
publishMainStream(user.id, "meUpdated", iObj);
|
||||
publishToMainStream(user.id, Event.Me, iObj);
|
||||
});
|
||||
|
|
|
@ -8,8 +8,7 @@ import {
|
|||
} from "@/models/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";
|
||||
import { Event, publishToMainStream, verifyPassword } from "backend-rs";
|
||||
|
||||
const rpIdHashReal = hash(Buffer.from(config.hostname, "utf-8"));
|
||||
|
||||
|
@ -132,9 +131,9 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
});
|
||||
|
||||
// Publish meUpdated event
|
||||
publishMainStream(
|
||||
publishToMainStream(
|
||||
user.id,
|
||||
"meUpdated",
|
||||
Event.Me,
|
||||
await Users.pack(user.id, user, {
|
||||
detail: true,
|
||||
includeSecrets: true,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import define from "@/server/api/define.js";
|
||||
import { Users, UserProfiles, UserSecurityKeys } from "@/models/index.js";
|
||||
import { publishMainStream } from "@/services/stream.js";
|
||||
import { Event, publishToMainStream } from "backend-rs";
|
||||
import { ApiError } from "@/server/api/error.js";
|
||||
|
||||
export const meta = {
|
||||
|
@ -57,5 +57,5 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
includeSecrets: true,
|
||||
});
|
||||
|
||||
publishMainStream(user.id, "meUpdated", iObj);
|
||||
publishToMainStream(user.id, Event.Me, iObj);
|
||||
});
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { verifyPassword } from "backend-rs";
|
||||
import { Event, publishToMainStream, verifyPassword } from "backend-rs";
|
||||
import define from "@/server/api/define.js";
|
||||
import { UserProfiles, UserSecurityKeys, Users } from "@/models/index.js";
|
||||
import { publishMainStream } from "@/services/stream.js";
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true,
|
||||
|
@ -54,9 +53,9 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
}
|
||||
|
||||
// Publish meUpdated event
|
||||
publishMainStream(
|
||||
publishToMainStream(
|
||||
user.id,
|
||||
"meUpdated",
|
||||
Event.Me,
|
||||
await Users.pack(user.id, user, {
|
||||
detail: true,
|
||||
includeSecrets: true,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { publishMainStream } from "@/services/stream.js";
|
||||
import define from "@/server/api/define.js";
|
||||
import { Users, UserProfiles } from "@/models/index.js";
|
||||
import { verifyPassword } from "backend-rs";
|
||||
import { Event, publishToMainStream, verifyPassword } from "backend-rs";
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true,
|
||||
|
@ -38,5 +37,5 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
includeSecrets: true,
|
||||
});
|
||||
|
||||
publishMainStream(user.id, "meUpdated", iObj);
|
||||
publishToMainStream(user.id, Event.Me, iObj);
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { publishMainStream } from "@/services/stream.js";
|
||||
import define from "@/server/api/define.js";
|
||||
import { Users, UserSecurityKeys } from "@/models/index.js";
|
||||
import { ApiError } from "@/server/api/error.js";
|
||||
import { Event, publishToMainStream } from "backend-rs";
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true,
|
||||
|
@ -54,5 +54,5 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
includeSecrets: true,
|
||||
});
|
||||
|
||||
publishMainStream(user.id, "meUpdated", iObj);
|
||||
publishToMainStream(user.id, Event.Me, iObj);
|
||||
});
|
||||
|
|
|
@ -3,8 +3,7 @@ import { Users } from "@/models/index.js";
|
|||
import { resolveUser } from "@/remote/resolve-user.js";
|
||||
import acceptAllFollowRequests from "@/services/following/requests/accept-all.js";
|
||||
import { publishToFollowers } from "@/services/i/update.js";
|
||||
import { publishMainStream } from "@/services/stream.js";
|
||||
import { stringToAcct } from "backend-rs";
|
||||
import { Event, publishToMainStream, stringToAcct } from "backend-rs";
|
||||
import { DAY } from "@/const.js";
|
||||
import { apiLogger } from "@/server/api/logger.js";
|
||||
import define from "@/server/api/define.js";
|
||||
|
@ -97,7 +96,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
});
|
||||
|
||||
// Publish meUpdated event
|
||||
publishMainStream(user.id, "meUpdated", iObj);
|
||||
publishToMainStream(user.id, Event.Me, iObj);
|
||||
|
||||
if (user.isLocked === false) {
|
||||
acceptAllFollowRequests(user);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import type { User } from "@/models/entities/user.js";
|
||||
import { resolveUser } from "@/remote/resolve-user.js";
|
||||
import { stringToAcct } from "backend-rs";
|
||||
import { Event, publishToMainStream, stringToAcct } from "backend-rs";
|
||||
import { DAY } from "@/const.js";
|
||||
import DeliverManager from "@/remote/activitypub/deliver-manager.js";
|
||||
import { renderActivity } from "@/remote/activitypub/renderer/index.js";
|
||||
|
@ -12,7 +12,6 @@ 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.js";
|
||||
import { publishMainStream } from "@/services/stream.js";
|
||||
import { inspect } from "node:util";
|
||||
|
||||
export const meta = {
|
||||
|
@ -134,7 +133,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
dm.execute();
|
||||
|
||||
// Publish meUpdated event
|
||||
publishMainStream(user.id, "meUpdated", iObj);
|
||||
publishToMainStream(user.id, Event.Me, iObj);
|
||||
|
||||
const followings = await Followings.findBy({
|
||||
followeeId: user.id,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { publishMainStream } from "@/services/stream.js";
|
||||
import { Event, publishToMainStream } from "backend-rs";
|
||||
import define from "@/server/api/define.js";
|
||||
import { MessagingMessages, UserGroupJoinings } from "@/models/index.js";
|
||||
|
||||
|
@ -16,7 +16,7 @@ export const paramDef = {
|
|||
required: [],
|
||||
} as const;
|
||||
|
||||
export default define(meta, paramDef, async (ps, user) => {
|
||||
export default define(meta, paramDef, async (_ps, user) => {
|
||||
// Update documents
|
||||
await MessagingMessages.update(
|
||||
{
|
||||
|
@ -44,5 +44,5 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
),
|
||||
);
|
||||
|
||||
publishMainStream(user.id, "readAllMessagingMessages");
|
||||
publishToMainStream(user.id, Event.ReadAllChats, {});
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { publishMainStream } from "@/services/stream.js";
|
||||
import { Event, publishToMainStream } from "backend-rs";
|
||||
import define from "@/server/api/define.js";
|
||||
import { NoteUnreads } from "@/models/index.js";
|
||||
|
||||
|
@ -23,6 +23,6 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
});
|
||||
|
||||
// 全て既読になったイベントを発行
|
||||
publishMainStream(user.id, "readAllUnreadMentions");
|
||||
publishMainStream(user.id, "readAllUnreadSpecifiedNotes");
|
||||
publishToMainStream(user.id, Event.ReadAllMentions, {});
|
||||
publishToMainStream(user.id, Event.ReadAllDms, {});
|
||||
});
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import define from "@/server/api/define.js";
|
||||
import { ApiError } from "@/server/api/error.js";
|
||||
import { genIdAt } from "backend-rs";
|
||||
import { Event, genIdAt, publishToMainStream } from "backend-rs";
|
||||
import { AnnouncementReads, Announcements, Users } from "@/models/index.js";
|
||||
import { publishMainStream } from "@/services/stream.js";
|
||||
|
||||
export const meta = {
|
||||
tags: ["account"],
|
||||
|
@ -59,6 +58,6 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
});
|
||||
|
||||
if (!(await Users.getHasUnreadAnnouncement(user.id))) {
|
||||
publishMainStream(user.id, "readAllAnnouncements");
|
||||
publishToMainStream(user.id, Event.ReadAllAnnouncements, {});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
import {
|
||||
publishInternalEvent,
|
||||
publishMainStream,
|
||||
publishUserEvent,
|
||||
} from "@/services/stream.js";
|
||||
import define from "@/server/api/define.js";
|
||||
import { Users, UserProfiles } from "@/models/index.js";
|
||||
import { generateUserToken, verifyPassword } from "backend-rs";
|
||||
import {
|
||||
Event,
|
||||
generateUserToken,
|
||||
InternalEvent,
|
||||
publishToInternalStream,
|
||||
publishToMainStream,
|
||||
publishToUserStream,
|
||||
UserEvent,
|
||||
verifyPassword,
|
||||
} from "backend-rs";
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true,
|
||||
|
@ -41,15 +45,15 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
});
|
||||
|
||||
// Publish event
|
||||
publishInternalEvent("userTokenRegenerated", {
|
||||
publishToInternalStream(InternalEvent.Token, {
|
||||
id: user.id,
|
||||
oldToken,
|
||||
newToken,
|
||||
});
|
||||
publishMainStream(user.id, "myTokenRegenerated");
|
||||
publishToMainStream(user.id, Event.RegenerateMyToken, {});
|
||||
|
||||
// Terminate streaming
|
||||
setTimeout(() => {
|
||||
publishUserEvent(user.id, "terminate", {});
|
||||
publishToUserStream(user.id, UserEvent.Disconnect, {});
|
||||
}, 5000);
|
||||
});
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { publishMainStream } from "@/services/stream.js";
|
||||
import define from "@/server/api/define.js";
|
||||
import { RegistryItems } from "@/models/index.js";
|
||||
import { genIdAt } from "backend-rs";
|
||||
import { Event, genIdAt, publishToMainStream } from "backend-rs";
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true,
|
||||
|
@ -55,7 +54,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
}
|
||||
|
||||
// TODO: サードパーティアプリが傍受出来てしまうのでどうにかする
|
||||
publishMainStream(user.id, "registryUpdated", {
|
||||
publishToMainStream(user.id, Event.Registry, {
|
||||
scope: ps.scope,
|
||||
key: ps.key,
|
||||
value: ps.value,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import define from "@/server/api/define.js";
|
||||
import { AccessTokens } from "@/models/index.js";
|
||||
import { publishUserEvent } from "@/services/stream.js";
|
||||
import { publishToUserStream, UserEvent } from "backend-rs";
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true,
|
||||
|
@ -26,6 +26,6 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
});
|
||||
|
||||
// Terminate streaming
|
||||
publishUserEvent(user.id, "terminate");
|
||||
await publishToUserStream(user.id, UserEvent.Disconnect, {});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { publishMainStream } from "@/services/stream.js";
|
||||
import define from "@/server/api/define.js";
|
||||
import rndstr from "rndstr";
|
||||
import { config } from "@/config.js";
|
||||
|
@ -6,7 +5,7 @@ import { Users, UserProfiles } from "@/models/index.js";
|
|||
import { sendEmail } from "@/services/send-email.js";
|
||||
import { ApiError } from "@/server/api/error.js";
|
||||
import { validateEmailForAccount } from "@/services/validate-email-for-account.js";
|
||||
import { verifyPassword } from "backend-rs";
|
||||
import { Event, publishToMainStream, verifyPassword } from "backend-rs";
|
||||
import { HOUR } from "@/const.js";
|
||||
|
||||
export const meta = {
|
||||
|
@ -72,7 +71,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
});
|
||||
|
||||
// Publish meUpdated event
|
||||
publishMainStream(user.id, "meUpdated", iObj);
|
||||
publishToMainStream(user.id, Event.Me, iObj);
|
||||
|
||||
if (ps.email != null) {
|
||||
const code = rndstr("a-z0-9", 16);
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
import * as mfm from "mfm-js";
|
||||
import { publishMainStream, publishUserEvent } from "@/services/stream.js";
|
||||
import {
|
||||
Event,
|
||||
publishToMainStream,
|
||||
publishToUserStream,
|
||||
UserEvent,
|
||||
} from "backend-rs";
|
||||
import acceptAllFollowRequests from "@/services/following/requests/accept-all.js";
|
||||
import { publishToFollowers } from "@/services/i/update.js";
|
||||
import { extractCustomEmojisFromMfm } from "@/misc/extract-custom-emojis-from-mfm.js";
|
||||
|
@ -345,10 +350,10 @@ export default define(meta, paramDef, async (ps, _user, token) => {
|
|||
});
|
||||
|
||||
// Publish meUpdated event
|
||||
publishMainStream(user.id, "meUpdated", iObj);
|
||||
publishUserEvent(
|
||||
await publishToMainStream(user.id, Event.Me, iObj);
|
||||
await publishToUserStream(
|
||||
user.id,
|
||||
"updateUserProfile",
|
||||
UserEvent.UpdateProfile,
|
||||
await UserProfiles.findOneBy({ userId: user.id }),
|
||||
);
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import define from "@/server/api/define.js";
|
||||
import { genIdAt } from "backend-rs";
|
||||
import { genIdAt, InternalEvent, publishToInternalStream } from "backend-rs";
|
||||
import { Webhooks } from "@/models/index.js";
|
||||
import { publishInternalEvent } from "@/services/stream.js";
|
||||
import { webhookEventTypes } from "@/models/entities/webhook.js";
|
||||
|
||||
export const meta = {
|
||||
|
@ -41,7 +40,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
on: ps.on,
|
||||
}).then((x) => Webhooks.findOneByOrFail(x.identifiers[0]));
|
||||
|
||||
publishInternalEvent("webhookCreated", webhook);
|
||||
publishToInternalStream(InternalEvent.WebhookCreated, webhook);
|
||||
|
||||
return webhook;
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import define from "@/server/api/define.js";
|
||||
import { ApiError } from "@/server/api/error.js";
|
||||
import { Webhooks } from "@/models/index.js";
|
||||
import { publishInternalEvent } from "@/services/stream.js";
|
||||
import { InternalEvent, publishToInternalStream } from "backend-rs";
|
||||
|
||||
export const meta = {
|
||||
tags: ["webhooks"],
|
||||
|
@ -39,5 +39,5 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
|
||||
await Webhooks.delete(webhook.id);
|
||||
|
||||
publishInternalEvent("webhookDeleted", webhook);
|
||||
publishToInternalStream(InternalEvent.WebhookDeleted, webhook);
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import define from "@/server/api/define.js";
|
||||
import { ApiError } from "@/server/api/error.js";
|
||||
import { Webhooks } from "@/models/index.js";
|
||||
import { publishInternalEvent } from "@/services/stream.js";
|
||||
import { InternalEvent, publishToInternalStream } from "backend-rs";
|
||||
import { webhookEventTypes } from "@/models/entities/webhook.js";
|
||||
|
||||
export const meta = {
|
||||
|
@ -57,5 +57,5 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
active: ps.active,
|
||||
});
|
||||
|
||||
publishInternalEvent("webhookUpdated", webhook);
|
||||
publishToInternalStream(InternalEvent.WebhookUpdated, webhook);
|
||||
});
|
||||
|
|
|
@ -402,7 +402,7 @@ export const paramDef = {
|
|||
} as const;
|
||||
|
||||
export default define(meta, paramDef, async (ps, me) => {
|
||||
const instance = await fetchMeta();
|
||||
const instanceMeta = await fetchMeta();
|
||||
|
||||
const emojis = await Emojis.find({
|
||||
where: {
|
||||
|
@ -425,56 +425,57 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
});
|
||||
|
||||
const response: any = {
|
||||
maintainerName: instance.maintainerName,
|
||||
maintainerEmail: instance.maintainerEmail,
|
||||
maintainerName: instanceMeta.maintainerName,
|
||||
maintainerEmail: instanceMeta.maintainerEmail,
|
||||
|
||||
version: config.version,
|
||||
|
||||
name: instance.name,
|
||||
name: instanceMeta.name,
|
||||
uri: config.url,
|
||||
description: instance.description,
|
||||
langs: instance.langs,
|
||||
tosUrl: instance.tosUrl,
|
||||
moreUrls: instance.moreUrls,
|
||||
repositoryUrl: instance.repositoryUrl,
|
||||
feedbackUrl: instance.feedbackUrl,
|
||||
description: instanceMeta.description,
|
||||
langs: instanceMeta.langs,
|
||||
tosUrl: instanceMeta.tosUrl,
|
||||
moreUrls: instanceMeta.moreUrls,
|
||||
repositoryUrl: instanceMeta.repositoryUrl,
|
||||
feedbackUrl: instanceMeta.feedbackUrl,
|
||||
|
||||
secureMode: instance.secureMode,
|
||||
privateMode: instance.privateMode,
|
||||
secureMode: instanceMeta.secureMode,
|
||||
privateMode: instanceMeta.privateMode,
|
||||
|
||||
disableRegistration: instance.disableRegistration,
|
||||
disableLocalTimeline: instance.disableLocalTimeline,
|
||||
disableRecommendedTimeline: instance.disableRecommendedTimeline,
|
||||
disableGlobalTimeline: instance.disableGlobalTimeline,
|
||||
enableGuestTimeline: instance.enableGuestTimeline,
|
||||
driveCapacityPerLocalUserMb: instance.localDriveCapacityMb,
|
||||
driveCapacityPerRemoteUserMb: instance.remoteDriveCapacityMb,
|
||||
antennaLimit: instance.antennaLimit,
|
||||
emailRequiredForSignup: instance.emailRequiredForSignup,
|
||||
enableHcaptcha: instance.enableHcaptcha,
|
||||
hcaptchaSiteKey: instance.hcaptchaSiteKey,
|
||||
enableRecaptcha: instance.enableRecaptcha,
|
||||
recaptchaSiteKey: instance.recaptchaSiteKey,
|
||||
swPublickey: instance.swPublicKey,
|
||||
themeColor: instance.themeColor,
|
||||
mascotImageUrl: instance.mascotImageUrl,
|
||||
bannerUrl: instance.bannerUrl,
|
||||
errorImageUrl: instance.errorImageUrl,
|
||||
iconUrl: instance.iconUrl,
|
||||
backgroundImageUrl: instance.backgroundImageUrl,
|
||||
logoImageUrl: instance.logoImageUrl,
|
||||
disableRegistration: instanceMeta.disableRegistration,
|
||||
disableLocalTimeline: instanceMeta.disableLocalTimeline,
|
||||
disableRecommendedTimeline: instanceMeta.disableRecommendedTimeline,
|
||||
disableGlobalTimeline: instanceMeta.disableGlobalTimeline,
|
||||
enableGuestTimeline: instanceMeta.enableGuestTimeline,
|
||||
driveCapacityPerLocalUserMb: instanceMeta.localDriveCapacityMb,
|
||||
driveCapacityPerRemoteUserMb: instanceMeta.remoteDriveCapacityMb,
|
||||
antennaLimit: instanceMeta.antennaLimit,
|
||||
emailRequiredForSignup: instanceMeta.emailRequiredForSignup,
|
||||
enableHcaptcha: instanceMeta.enableHcaptcha,
|
||||
hcaptchaSiteKey: instanceMeta.hcaptchaSiteKey,
|
||||
enableRecaptcha: instanceMeta.enableRecaptcha,
|
||||
recaptchaSiteKey: instanceMeta.recaptchaSiteKey,
|
||||
swPublickey: instanceMeta.swPublicKey,
|
||||
themeColor: instanceMeta.themeColor,
|
||||
mascotImageUrl: instanceMeta.mascotImageUrl,
|
||||
bannerUrl: instanceMeta.bannerUrl,
|
||||
errorImageUrl: instanceMeta.errorImageUrl,
|
||||
iconUrl: instanceMeta.iconUrl,
|
||||
backgroundImageUrl: instanceMeta.backgroundImageUrl,
|
||||
logoImageUrl: instanceMeta.logoImageUrl,
|
||||
maxNoteTextLength: config.maxNoteLength, // for backward compatibility
|
||||
maxCaptionTextLength: config.maxCaptionLength,
|
||||
emojis: instance.privateMode && !me ? [] : await Emojis.packMany(emojis),
|
||||
emojis:
|
||||
instanceMeta.privateMode && !me ? [] : await Emojis.packMany(emojis),
|
||||
// クライアントの手間を減らすためあらかじめJSONに変換しておく
|
||||
defaultLightTheme: instance.defaultLightTheme
|
||||
? JSON.stringify(JSON5.parse(instance.defaultLightTheme))
|
||||
defaultLightTheme: instanceMeta.defaultLightTheme
|
||||
? JSON.stringify(JSON5.parse(instanceMeta.defaultLightTheme))
|
||||
: null,
|
||||
defaultDarkTheme: instance.defaultDarkTheme
|
||||
? JSON.stringify(JSON5.parse(instance.defaultDarkTheme))
|
||||
defaultDarkTheme: instanceMeta.defaultDarkTheme
|
||||
? JSON.stringify(JSON5.parse(instanceMeta.defaultDarkTheme))
|
||||
: null,
|
||||
ads:
|
||||
instance.privateMode && !me
|
||||
instanceMeta.privateMode && !me
|
||||
? []
|
||||
: ads.map((ad) => ({
|
||||
id: ad.id,
|
||||
|
@ -483,50 +484,52 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
ratio: ad.ratio,
|
||||
imageUrl: ad.imageUrl,
|
||||
})),
|
||||
enableEmail: instance.enableEmail,
|
||||
enableEmail: instanceMeta.enableEmail,
|
||||
|
||||
enableServiceWorker: instance.enableServiceWorker,
|
||||
enableServiceWorker: instanceMeta.enableServiceWorker,
|
||||
|
||||
translatorAvailable:
|
||||
instance.deeplAuthKey != null || instance.libreTranslateApiUrl != null,
|
||||
defaultReaction: instance.defaultReaction,
|
||||
donationLink: instance.donationLink,
|
||||
enableServerMachineStats: instance.enableServerMachineStats,
|
||||
enableIdenticonGeneration: instance.enableIdenticonGeneration,
|
||||
instanceMeta.deeplAuthKey != null ||
|
||||
instanceMeta.libreTranslateApiUrl != null,
|
||||
defaultReaction: instanceMeta.defaultReaction,
|
||||
donationLink: instanceMeta.donationLink,
|
||||
enableServerMachineStats: instanceMeta.enableServerMachineStats,
|
||||
enableIdenticonGeneration: instanceMeta.enableIdenticonGeneration,
|
||||
|
||||
...(ps.detail
|
||||
? {
|
||||
pinnedPages: instance.privateMode && !me ? [] : instance.pinnedPages,
|
||||
pinnedPages:
|
||||
instanceMeta.privateMode && !me ? [] : instanceMeta.pinnedPages,
|
||||
pinnedClipId:
|
||||
instance.privateMode && !me ? [] : instance.pinnedClipId,
|
||||
cacheRemoteFiles: instance.cacheRemoteFiles,
|
||||
markLocalFilesNsfwByDefault: instance.markLocalFilesNsfwByDefault,
|
||||
instanceMeta.privateMode && !me ? [] : instanceMeta.pinnedClipId,
|
||||
cacheRemoteFiles: instanceMeta.cacheRemoteFiles,
|
||||
markLocalFilesNsfwByDefault: instanceMeta.markLocalFilesNsfwByDefault,
|
||||
requireSetup: (await countLocalUsers()) === 0,
|
||||
}
|
||||
: {}),
|
||||
};
|
||||
|
||||
if (ps.detail) {
|
||||
if (!instance.privateMode || me) {
|
||||
const proxyAccount = instance.proxyAccountId
|
||||
? await Users.pack(instance.proxyAccountId).catch(() => null)
|
||||
if (!instanceMeta.privateMode || me) {
|
||||
const proxyAccount = instanceMeta.proxyAccountId
|
||||
? await Users.pack(instanceMeta.proxyAccountId).catch(() => null)
|
||||
: null;
|
||||
response.proxyAccountName = proxyAccount ? proxyAccount.username : null;
|
||||
}
|
||||
|
||||
response.features = {
|
||||
registration: !instance.disableRegistration,
|
||||
localTimeLine: !instance.disableLocalTimeline,
|
||||
recommendedTimeline: !instance.disableRecommendedTimeline,
|
||||
globalTimeLine: !instance.disableGlobalTimeline,
|
||||
guestTimeline: instance.enableGuestTimeline,
|
||||
emailRequiredForSignup: instance.emailRequiredForSignup,
|
||||
hcaptcha: instance.enableHcaptcha,
|
||||
recaptcha: instance.enableRecaptcha,
|
||||
objectStorage: instance.useObjectStorage,
|
||||
serviceWorker: instance.enableServiceWorker,
|
||||
registration: !instanceMeta.disableRegistration,
|
||||
localTimeLine: !instanceMeta.disableLocalTimeline,
|
||||
recommendedTimeline: !instanceMeta.disableRecommendedTimeline,
|
||||
globalTimeLine: !instanceMeta.disableGlobalTimeline,
|
||||
guestTimeline: instanceMeta.enableGuestTimeline,
|
||||
emailRequiredForSignup: instanceMeta.emailRequiredForSignup,
|
||||
hcaptcha: instanceMeta.enableHcaptcha,
|
||||
recaptcha: instanceMeta.enableRecaptcha,
|
||||
objectStorage: instanceMeta.useObjectStorage,
|
||||
serviceWorker: instanceMeta.enableServiceWorker,
|
||||
postEditing: true,
|
||||
postImports: instance.experimentalFeatures?.postImports || false,
|
||||
postImports: instanceMeta.experimentalFeatures?.postImports || false,
|
||||
miauth: true,
|
||||
};
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue