Compare commits

..

No commits in common. "main" and "main" have entirely different histories.
main ... main

279 changed files with 3520 additions and 7284 deletions

View file

@ -1,5 +1,5 @@
# db settings # db settings
POSTGRES_PASSWORD=example-forkey-pass POSTGRES_PASSWORD=example-misskey-pass
POSTGRES_USER=example-forkey-user POSTGRES_USER=example-misskey-user
POSTGRES_DB=forkey POSTGRES_DB=misskey
DATABASE_URL="postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}" DATABASE_URL="postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}"

View file

@ -1,5 +1,5 @@
#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ #━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# Forkey configuration # Misskey configuration
#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ #━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# ┌─────┐ # ┌─────┐
@ -15,11 +15,11 @@ url: https://example.tld/
#───┘ Port and TLS settings └─────────────────────────────────── #───┘ Port and TLS settings └───────────────────────────────────
# #
# Forkey requires a reverse proxy to support HTTPS connections. # Misskey requires a reverse proxy to support HTTPS connections.
# #
# +----- https://example.tld/ ------------+ # +----- https://example.tld/ ------------+
# +------+ |+-------------+ +----------------+| # +------+ |+-------------+ +----------------+|
# | User | ---> || Proxy (443) | ---> | Forkey (3000) || # | User | ---> || Proxy (443) | ---> | Misskey (3000) ||
# +------+ |+-------------+ +----------------+| # +------+ |+-------------+ +----------------+|
# +---------------------------------------+ # +---------------------------------------+
# #
@ -27,7 +27,7 @@ url: https://example.tld/
# An encrypted connection with HTTPS is highly recommended # An encrypted connection with HTTPS is highly recommended
# because tokens may be transferred in GET requests. # because tokens may be transferred in GET requests.
# The port that your Forkey server should listen on. # The port that your Misskey server should listen on.
port: 3000 port: 3000
# ┌──────────────────────────┐ # ┌──────────────────────────┐
@ -38,11 +38,11 @@ db:
port: 5432 port: 5432
# Database name # Database name
db: forkey db: misskey
# Auth # Auth
user: example-forkey-user user: example-misskey-user
pass: example-forkey-pass pass: example-misskey-pass
# Whether disable Caching queries # Whether disable Caching queries
#disableCache: true #disableCache: true

View file

@ -1,5 +1,5 @@
#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ #━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# Forkey configuration # Misskey configuration
#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ #━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# ┌─────┐ # ┌─────┐
@ -15,11 +15,11 @@ url: https://example.tld/
#───┘ Port and TLS settings └─────────────────────────────────── #───┘ Port and TLS settings └───────────────────────────────────
# #
# Forkey requires a reverse proxy to support HTTPS connections. # Misskey requires a reverse proxy to support HTTPS connections.
# #
# +----- https://example.tld/ ------------+ # +----- https://example.tld/ ------------+
# +------+ |+-------------+ +----------------+| # +------+ |+-------------+ +----------------+|
# | User | ---> || Proxy (443) | ---> | Forkey (3000) || # | User | ---> || Proxy (443) | ---> | Misskey (3000) ||
# +------+ |+-------------+ +----------------+| # +------+ |+-------------+ +----------------+|
# +---------------------------------------+ # +---------------------------------------+
# #
@ -27,7 +27,7 @@ url: https://example.tld/
# An encrypted connection with HTTPS is highly recommended # An encrypted connection with HTTPS is highly recommended
# because tokens may be transferred in GET requests. # because tokens may be transferred in GET requests.
# The port that your Forkey server should listen on. # The port that your Misskey server should listen on.
port: 3000 port: 3000
# You can also use UNIX domain socket. # You can also use UNIX domain socket.
@ -42,11 +42,11 @@ db:
port: 5432 port: 5432
# Database name # Database name
db: forkey db: misskey
# Auth # Auth
user: example-forkey-user user: example-misskey-user
pass: example-forkey-pass pass: example-misskey-pass
# Whether disable Caching queries # Whether disable Caching queries
#disableCache: true #disableCache: true
@ -206,7 +206,7 @@ proxyRemoteFiles: true
# Movie Thumbnail Generation URL # Movie Thumbnail Generation URL
# There is no reference implementation. # There is no reference implementation.
# For example, Forkey will point to the following URL: # For example, Misskey will point to the following URL:
# https://example.com/thumbnail.webp?thumbnail=1&url=https%3A%2F%2Fstorage.example.com%2Fpath%2Fto%2Fvideo.mp4 # https://example.com/thumbnail.webp?thumbnail=1&url=https%3A%2F%2Fstorage.example.com%2Fpath%2Fto%2Fvideo.mp4
#videoThumbnailGenerator: https://example.com #videoThumbnailGenerator: https://example.com

View file

@ -1,7 +1,7 @@
**/.git **/.git
.autogen .autogen
.forgejo .github
.travis .travis
.vscode .vscode
.config .config

View file

@ -1,16 +0,0 @@
# Workaround for Forgejo not supporting port redirection
url: 'http://misskey.local'
port: 61812
db:
host: postgres
port: 5432
db: test-misskey
user: postgres
pass: ''
redis:
host: dragonfly
port: 6379
id: aidx

View file

@ -17,10 +17,11 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
fetch-depth: 0
submodules: true submodules: true
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v4.0.0 uses: pnpm/action-setup@v4
with: with:
run_install: false run_install: false

View file

@ -3,7 +3,9 @@ name: Check Misskey JS version
on: on:
push: push:
branches: branches:
- main - beta
- io
- host
paths: paths:
- packages/misskey-js/package.json - packages/misskey-js/package.json
- package.json - package.json
@ -21,6 +23,7 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
fetch-depth: 0
submodules: true submodules: true
- name: Check version - name: Check version
run: | run: |

52
.github/workflows/docker-beta.yml vendored Normal file
View file

@ -0,0 +1,52 @@
name: Publish Docker image (beta)
on:
push:
branches:
- beta
workflow_dispatch:
jobs:
push_to_registry:
name: Push Docker image to GitHub Container Registry
runs-on: ubuntu-22.04
if: github.repository == 'MisskeyIO/misskey'
steps:
- name: Check out the repo
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3
with:
platforms: linux/amd64
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/misskeyio/misskey
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Prepare image tags
run: |
echo "FORMATTED_BRANCH_NAME=$(echo ${{ github.ref_name }} | sed -e 's/\//-/g' )" >> $GITHUB_ENV
- name: Build and Push to GitHub Container Registry
uses: docker/build-push-action@v6
with:
builder: ${{ steps.buildx.outputs.name }}
context: .
push: true
platforms: ${{ steps.buildx.outputs.platforms }}
provenance: false
labels: ${{ env.FORMATTED_BRANCH_NAME }}
cache-from: type=registry,ref=ghcr.io/misskeyio/misskey:io-buildcache
cache-to: type=registry,ref=ghcr.io/misskeyio/misskey:io-buildcache,mode=max
tags: |
ghcr.io/misskeyio/misskey:beta
ghcr.io/misskeyio/misskey:${{ env.FORMATTED_BRANCH_NAME }}

54
.github/workflows/docker-host.yml vendored Normal file
View file

@ -0,0 +1,54 @@
name: Publish Docker image (host)
on:
push:
branches:
- host
tags:
- '**-host.*'
workflow_dispatch:
jobs:
push_to_registry:
name: Push Docker image to GitHub Container Registry
runs-on: ubuntu-22.04
if: github.repository == 'MisskeyIO/misskey'
steps:
- name: Check out the repo
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3
with:
platforms: linux/amd64
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/misskeyio/misskey
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Prepare image tags
run: |
echo "FORMATTED_BRANCH_NAME=$(echo ${{ github.ref_name }} | sed -e 's/\//-/g' )" >> $GITHUB_ENV
- name: Build and Push to GitHub Container Registry
uses: docker/build-push-action@v6
with:
builder: ${{ steps.buildx.outputs.name }}
context: .
push: true
platforms: ${{ steps.buildx.outputs.platforms }}
provenance: false
labels: ${{ env.FORMATTED_BRANCH_NAME }}
cache-from: type=registry,ref=ghcr.io/misskeyio/misskey:host-buildcache
cache-to: type=registry,ref=ghcr.io/misskeyio/misskey:host-buildcache,mode=max
tags: |
ghcr.io/misskeyio/misskey:host
ghcr.io/misskeyio/misskey:${{ env.FORMATTED_BRANCH_NAME }}

54
.github/workflows/docker-io.yml vendored Normal file
View file

@ -0,0 +1,54 @@
name: Publish Docker image (io)
on:
push:
branches:
- io
tags:
- '**-io.*'
workflow_dispatch:
jobs:
push_to_registry:
name: Push Docker image to GitHub Container Registry
runs-on: ubuntu-22.04
if: github.repository == 'MisskeyIO/misskey'
steps:
- name: Check out the repo
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3
with:
platforms: linux/amd64
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/misskeyio/misskey
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Prepare image tags
run: |
echo "FORMATTED_BRANCH_NAME=$(echo ${{ github.ref_name }} | sed -e 's/\//-/g' )" >> $GITHUB_ENV
- name: Build and Push to GitHub Container Registry
uses: docker/build-push-action@v6
with:
builder: ${{ steps.buildx.outputs.name }}
context: .
push: true
platforms: ${{ steps.buildx.outputs.platforms }}
provenance: false
labels: ${{ env.FORMATTED_BRANCH_NAME }}
cache-from: type=registry,ref=ghcr.io/misskeyio/misskey:io-buildcache
cache-to: type=registry,ref=ghcr.io/misskeyio/misskey:io-buildcache,mode=max
tags: |
ghcr.io/misskeyio/misskey:latest
ghcr.io/misskeyio/misskey:${{ env.FORMATTED_BRANCH_NAME }}

38
.github/workflows/dockle.yml vendored Normal file
View file

@ -0,0 +1,38 @@
name: Dockle
on:
push:
branches:
- beta
- io
- host
pull_request:
jobs:
dockle:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- name: Build an image from Dockerfile
uses: docker/build-push-action@v6
with:
context: .
push: false
provenance: false
cache-from: type=registry,ref=ghcr.io/misskeyio/misskey:io-buildcache
tags: |
misskey:scan
- name: Run dockle
uses: docker://goodwithtech/dockle:v0.4.14
env:
DOCKLE_OUTPUT_FORMAT: list
DOCKLE_EXIT_CODE: 1
DOCKLE_EXIT_LEVEL: WARN
DOCKLE_IGNORES: CIS-DI-0005,CIS-DI-0010
DOCKLE_DEBUG: true
with:
args: 'misskey:scan'

16
.github/workflows/labeler.yml vendored Normal file
View file

@ -0,0 +1,16 @@
name: "Pull Request Labeler"
on:
pull_request_target:
branches-ignore:
- 'l10n_develop'
jobs:
triage:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v5
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"

View file

@ -3,7 +3,9 @@ name: Lint
on: on:
push: push:
branches: branches:
- main - beta
- io
- host
paths: paths:
- packages/backend/** - packages/backend/**
- packages/frontend/** - packages/frontend/**
@ -24,8 +26,9 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
fetch-depth: 0
submodules: true submodules: true
- uses: pnpm/action-setup@v4.0.0 - uses: pnpm/action-setup@v4
with: with:
run_install: false run_install: false
- uses: actions/setup-node@v4.1.0 - uses: actions/setup-node@v4.1.0
@ -48,8 +51,9 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
fetch-depth: 0
submodules: true submodules: true
- uses: pnpm/action-setup@v4.0.0 - uses: pnpm/action-setup@v4
with: with:
run_install: false run_install: false
- uses: actions/setup-node@v4.1.0 - uses: actions/setup-node@v4.1.0
@ -71,8 +75,9 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
fetch-depth: 0
submodules: true submodules: true
- uses: pnpm/action-setup@v4.0.0 - uses: pnpm/action-setup@v4
with: with:
run_install: false run_install: false
- uses: actions/setup-node@v4.1.0 - uses: actions/setup-node@v4.1.0

View file

@ -3,7 +3,9 @@ name: Test (backend)
on: on:
push: push:
branches: branches:
- main - beta
- io
- host
paths: paths:
- packages/backend/** - packages/backend/**
# for permissions # for permissions
@ -25,6 +27,8 @@ jobs:
services: services:
postgres: postgres:
image: postgres:15 image: postgres:15
ports:
- 54312:5432
env: env:
POSTGRES_DB: test-misskey POSTGRES_DB: test-misskey
POSTGRES_HOST_AUTH_METHOD: trust POSTGRES_HOST_AUTH_METHOD: trust
@ -40,17 +44,20 @@ jobs:
DFLY_conn_io_threads: 4 DFLY_conn_io_threads: 4
DFLY_epoll_file_threads: 4 DFLY_epoll_file_threads: 4
DFLY_proactor_threads: 4 DFLY_proactor_threads: 4
ports:
- 56312:6379
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
fetch-depth: 0
submodules: true submodules: true
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v4.0.0 uses: pnpm/action-setup@v4
with: with:
run_install: false run_install: false
- name: Install FFmpeg - name: Install FFmpeg
uses: https://github.com/FedericoCarboni/setup-ffmpeg@v3 uses: FedericoCarboni/setup-ffmpeg@v3
- name: Use Node.js ${{ matrix.node-version }} - name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.1.0 uses: actions/setup-node@v4.1.0
with: with:
@ -60,11 +67,16 @@ jobs:
- name: Check pnpm-lock.yaml - name: Check pnpm-lock.yaml
run: git diff --exit-code pnpm-lock.yaml run: git diff --exit-code pnpm-lock.yaml
- name: Copy Configure - name: Copy Configure
run: cp .forgejo/misskey/test-forgejo.yml .config/test.yml run: cp .github/misskey/test.yml .config
- name: Build - name: Build
run: pnpm build run: pnpm build
- name: Test - name: Test
run: pnpm --filter backend test run: pnpm --filter backend test-and-coverage
- name: Upload to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./packages/backend/coverage/coverage-final.json
e2e: e2e:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -76,6 +88,8 @@ jobs:
services: services:
postgres: postgres:
image: postgres:15 image: postgres:15
ports:
- 54312:5432
env: env:
POSTGRES_DB: test-misskey POSTGRES_DB: test-misskey
POSTGRES_HOST_AUTH_METHOD: trust POSTGRES_HOST_AUTH_METHOD: trust
@ -91,13 +105,16 @@ jobs:
DFLY_conn_io_threads: 4 DFLY_conn_io_threads: 4
DFLY_epoll_file_threads: 4 DFLY_epoll_file_threads: 4
DFLY_proactor_threads: 4 DFLY_proactor_threads: 4
ports:
- 56312:6379
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
fetch-depth: 0
submodules: true submodules: true
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v4.0.0 uses: pnpm/action-setup@v4
with: with:
run_install: false run_install: false
- name: Use Node.js ${{ matrix.node-version }} - name: Use Node.js ${{ matrix.node-version }}
@ -109,8 +126,13 @@ jobs:
- name: Check pnpm-lock.yaml - name: Check pnpm-lock.yaml
run: git diff --exit-code pnpm-lock.yaml run: git diff --exit-code pnpm-lock.yaml
- name: Copy Configure - name: Copy Configure
run: cp .forgejo/misskey/test-forgejo.yml .config/test.yml run: cp .github/misskey/test.yml .config
- name: Build - name: Build
run: pnpm build run: pnpm build
- name: Test - name: Test
run: pnpm --filter backend test:e2e run: pnpm --filter backend test-and-coverage:e2e
- name: Upload to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./packages/backend/coverage/coverage-final.json

View file

@ -32,9 +32,10 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
fetch-depth: 0
submodules: true submodules: true
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v4.0.0 uses: pnpm/action-setup@v4
with: with:
run_install: false run_install: false
- name: Use Node.js ${{ matrix.node-version }} - name: Use Node.js ${{ matrix.node-version }}
@ -46,8 +47,13 @@ jobs:
- name: Check pnpm-lock.yaml - name: Check pnpm-lock.yaml
run: git diff --exit-code pnpm-lock.yaml run: git diff --exit-code pnpm-lock.yaml
- name: Copy Configure - name: Copy Configure
run: cp .forgejo/misskey/test-forgejo.yml .config/test.yml run: cp .github/misskey/test.yml .config
- name: Build - name: Build
run: pnpm build run: pnpm build
- name: Test - name: Test
run: pnpm --filter frontend test run: pnpm --filter frontend test-and-coverage
- name: Upload Coverage
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./packages/frontend/coverage/coverage-final.json

View file

@ -6,7 +6,9 @@ name: Test (misskey.js)
on: on:
push: push:
branches: branches:
- main - beta
- io
- host
paths: paths:
- packages/misskey-js/** - packages/misskey-js/**
pull_request: pull_request:
@ -27,10 +29,11 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
fetch-depth: 0
submodules: true submodules: true
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v4.0.0 uses: pnpm/action-setup@v4
with: with:
run_install: false run_install: false
@ -53,3 +56,9 @@ jobs:
run: pnpm --filter misskey-js test run: pnpm --filter misskey-js test
env: env:
CI: true CI: true
- name: Upload Coverage
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./packages/misskey-js/coverage/coverage-final.json

View file

@ -3,7 +3,9 @@ name: Test (production install and build)
on: on:
push: push:
branches: branches:
- main - beta
- io
- host
pull_request: pull_request:
env: env:
@ -20,9 +22,10 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
fetch-depth: 0
submodules: true submodules: true
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v4.0.0 uses: pnpm/action-setup@v4
with: with:
run_install: false run_install: false
- name: Use Node.js ${{ matrix.node-version }} - name: Use Node.js ${{ matrix.node-version }}
@ -34,6 +37,6 @@ jobs:
- name: Check pnpm-lock.yaml - name: Check pnpm-lock.yaml
run: git diff --exit-code pnpm-lock.yaml run: git diff --exit-code pnpm-lock.yaml
- name: Copy Configure - name: Copy Configure
run: cp .forgejo/misskey/test-forgejo.yml .config/default.yml run: cp .github/misskey/test.yml .config/default.yml
- name: Build - name: Build
run: pnpm build run: pnpm build

View file

@ -3,7 +3,9 @@ name: Test (backend)
on: on:
push: push:
branches: branches:
- main - beta
- io
- host
paths: paths:
- packages/backend/** - packages/backend/**
pull_request: pull_request:
@ -21,9 +23,10 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
fetch-depth: 0
submodules: true submodules: true
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v4.0.0 uses: pnpm/action-setup@v4
with: with:
run_install: false run_install: false
- name: Use Node.js ${{ matrix.node-version }} - name: Use Node.js ${{ matrix.node-version }}

View file

@ -1,5 +1,5 @@
# Contribution guide # Contribution guide
We're glad you're interested in contributing Forkey! In this document you will find the information you need to contribute to the project. We're glad you're interested in contributing Misskey! In this document you will find the information you need to contribute to the project.
> **Note** > **Note**
> This project uses Japanese as its major language, **but you do not need to translate and write the Issues/PRs in Japanese.** > This project uses Japanese as its major language, **but you do not need to translate and write the Issues/PRs in Japanese.**
@ -161,7 +161,7 @@ pnpm dev
### Run test ### Run test
Create a config file. Create a config file.
``` ```
cp .forgejo/misskey/test.yml .config/ cp .github/misskey/test.yml .config/
``` ```
Prepare DB/Redis for testing. Prepare DB/Redis for testing.
``` ```
@ -188,8 +188,8 @@ TODO
- `MISSKEY_WEBFINGER_USE_HTTP`: If it's set true, WebFinger requests will be http instead of https, useful for testing federation between servers in localhost. NEVER USE IN PRODUCTION. - `MISSKEY_WEBFINGER_USE_HTTP`: If it's set true, WebFinger requests will be http instead of https, useful for testing federation between servers in localhost. NEVER USE IN PRODUCTION.
## Continuous integration ## Continuous integration
Misskey uses Forgejo Actions for executing automated tests. Misskey uses GitHub Actions for executing automated tests.
Configuration files are located in [`/.forgejo/workflows`](/.forgejo/workflows). Configuration files are located in [`/.github/workflows`](/.github/workflows).
## Vue ## Vue
Misskey uses Vue(v3) as its front-end framework. Misskey uses Vue(v3) as its front-end framework.

View file

@ -14,7 +14,7 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
&& apt-get install -yqq --no-install-recommends \ && apt-get install -yqq --no-install-recommends \
build-essential build-essential
WORKDIR /forkey WORKDIR /misskey
COPY --link pnpm-lock.yaml ./ COPY --link pnpm-lock.yaml ./
RUN npm install -g pnpm RUN npm install -g pnpm
@ -45,7 +45,7 @@ RUN apt-get update \
&& apt-get install -yqq --no-install-recommends \ && apt-get install -yqq --no-install-recommends \
build-essential build-essential
WORKDIR /forkey WORKDIR /misskey
COPY --link pnpm-lock.yaml ./ COPY --link pnpm-lock.yaml ./
RUN npm install -g pnpm RUN npm install -g pnpm
@ -71,8 +71,8 @@ RUN apt-get update \
&& apt-get install -y --no-install-recommends \ && apt-get install -y --no-install-recommends \
curl ffmpeg libjemalloc-dev libjemalloc2 tini \ curl ffmpeg libjemalloc-dev libjemalloc2 tini \
&& ln -s /usr/lib/$(uname -m)-linux-gnu/libjemalloc.so.2 /usr/local/lib/libjemalloc.so \ && ln -s /usr/lib/$(uname -m)-linux-gnu/libjemalloc.so.2 /usr/local/lib/libjemalloc.so \
&& groupadd -g "${GID}" forkey \ && groupadd -g "${GID}" misskey \
&& useradd -l -u "${UID}" -g "${GID}" -m -d /forkey forkey \ && useradd -l -u "${UID}" -g "${GID}" -m -d /misskey misskey \
&& find / -type d -path /sys -prune -o -type d -path /proc -prune -o -type f -perm /u+s -ignore_readdir_race -exec chmod u-s {} \; \ && find / -type d -path /sys -prune -o -type d -path /proc -prune -o -type f -perm /u+s -ignore_readdir_race -exec chmod u-s {} \; \
&& find / -type d -path /sys -prune -o -type d -path /proc -prune -o -type f -perm /g+s -ignore_readdir_race -exec chmod g-s {} \; \ && find / -type d -path /sys -prune -o -type d -path /proc -prune -o -type f -perm /g+s -ignore_readdir_race -exec chmod g-s {} \; \
&& apt-get clean \ && apt-get clean \
@ -80,27 +80,27 @@ RUN apt-get update \
WORKDIR /misskey WORKDIR /misskey
COPY --chown=forkey:forkey pnpm-lock.yaml ./ COPY --chown=misskey:misskey pnpm-lock.yaml ./
RUN npm install -g pnpm RUN npm install -g pnpm
COPY --chown=forkey:forkey --from=target-builder /forkey/node_modules ./node_modules COPY --chown=misskey:misskey --from=target-builder /misskey/node_modules ./node_modules
COPY --chown=forkey:forkey --from=target-builder /forkey/packages/backend/node_modules ./packages/backend/node_modules COPY --chown=misskey:misskey --from=target-builder /misskey/packages/backend/node_modules ./packages/backend/node_modules
COPY --chown=forkey:forkey --from=target-builder /forkey/packages/misskey-js/node_modules ./packages/misskey-js/node_modules COPY --chown=misskey:misskey --from=target-builder /misskey/packages/misskey-js/node_modules ./packages/misskey-js/node_modules
COPY --chown=forkey:forkey --from=target-builder /forkey/packages/misskey-reversi/node_modules ./packages/misskey-reversi/node_modules COPY --chown=misskey:misskey --from=target-builder /misskey/packages/misskey-reversi/node_modules ./packages/misskey-reversi/node_modules
COPY --chown=forkey:forkey --from=target-builder /forkey/packages/misskey-bubble-game/node_modules ./packages/misskey-bubble-game/node_modules COPY --chown=misskey:misskey --from=target-builder /misskey/packages/misskey-bubble-game/node_modules ./packages/misskey-bubble-game/node_modules
COPY --chown=forkey:forkey --from=native-builder /forkey/built ./built COPY --chown=misskey:misskey --from=native-builder /misskey/built ./built
COPY --chown=forkey:forkey --from=native-builder /forkey/packages/misskey-js/built ./packages/misskey-js/built COPY --chown=misskey:misskey --from=native-builder /misskey/packages/misskey-js/built ./packages/misskey-js/built
COPY --chown=forkey:forkey --from=native-builder /forkey/packages/misskey-reversi/built ./packages/misskey-reversi/built COPY --chown=misskey:misskey --from=native-builder /misskey/packages/misskey-reversi/built ./packages/misskey-reversi/built
COPY --chown=forkey:forkey --from=native-builder /forkey/packages/misskey-bubble-game/built ./packages/misskey-bubble-game/built COPY --chown=misskey:misskey --from=native-builder /misskey/packages/misskey-bubble-game/built ./packages/misskey-bubble-game/built
COPY --chown=forkey:forkey --from=native-builder /forkey/packages/backend/built ./packages/backend/built COPY --chown=misskey:misskey --from=native-builder /misskey/packages/backend/built ./packages/backend/built
COPY --chown=forkey:forkey --from=native-builder /forkey/fluent-emojis /forkey/fluent-emojis COPY --chown=misskey:misskey --from=native-builder /misskey/fluent-emojis /misskey/fluent-emojis
COPY --chown=forkey:forkey . ./ COPY --chown=misskey:misskey . ./
USER forkey USER misskey
ENV LD_PRELOAD=/usr/local/lib/libjemalloc.so ENV LD_PRELOAD=/usr/local/lib/libjemalloc.so
ENV MALLOC_CONF=background_thread:true,metadata_thp:auto,dirty_decay_ms:30000,muzzy_decay_ms:30000 ENV MALLOC_CONF=background_thread:true,metadata_thp:auto,dirty_decay_ms:30000,muzzy_decay_ms:30000
ENV TF_CPP_MIN_LOG_LEVEL=2 ENV TF_CPP_MIN_LOG_LEVEL=2
ENV NODE_ENV=production ENV NODE_ENV=production
HEALTHCHECK --interval=5s --retries=20 CMD ["/bin/bash", "/forkey/healthcheck.sh"] HEALTHCHECK --interval=5s --retries=20 CMD ["/bin/bash", "/misskey/healthcheck.sh"]
ENTRYPOINT ["/usr/bin/tini", "--"] ENTRYPOINT ["/usr/bin/tini", "--"]
CMD ["pnpm", "run", "migrateandstart:docker"] CMD ["pnpm", "run", "migrateandstart:docker"]

View file

@ -1,9 +1,9 @@
<div align="center"> <div align="center">
<a href="https://misskey-hub.net"> <a href="https://misskey-hub.net">
<img src="./assets/title_float.svg" alt="Forkey logo" style="border-radius:50%" width="300"/> <img src="./assets/title_float.svg" alt="Misskey logo" style="border-radius:50%" width="300"/>
</a> </a>
**🌎 **Forkey** is an open source, federated social media platform that's free forever! 🚀** **🌎 **Misskey** is an open source, federated social media platform that's free forever! 🚀**
[Learn more](https://misskey-hub.net/) [Learn more](https://misskey-hub.net/)

View file

@ -30,11 +30,11 @@ spec:
image: postgres:15-alpine image: postgres:15-alpine
env: env:
- name: POSTGRES_USER - name: POSTGRES_USER
value: "example-forkey-user" value: "example-misskey-user"
- name: POSTGRES_PASSWORD - name: POSTGRES_PASSWORD
value: "example-forkey-pass" value: "example-misskey-pass"
- name: POSTGRES_DB - name: POSTGRES_DB
value: "forkey" value: "misskey"
ports: ports:
- containerPort: 5432 - containerPort: 5432
- name: dragonfly - name: dragonfly

View file

@ -20,8 +20,8 @@ services:
- internal_network - internal_network
- external_network - external_network
volumes: volumes:
- ./files:/forkey/files - ./files:/misskey/files
- ./.config:/forkey/.config:ro - ./.config:/misskey/.config:ro
dragonfly: dragonfly:
restart: always restart: always

View file

@ -3,5 +3,5 @@
# SPDX-FileCopyrightText: syuilo and misskey-project # SPDX-FileCopyrightText: syuilo and misskey-project
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
PORT=$(grep '^port:' /forkey/.config/default.yml | awk 'NR==1{print $2; exit}') PORT=$(grep '^port:' /misskey/.config/default.yml | awk 'NR==1{print $2; exit}')
curl -s -S -o /dev/null "http://localhost:${PORT}" curl -s -S -o /dev/null "http://localhost:${PORT}"

View file

@ -1458,7 +1458,7 @@ _achievements:
_login1000: _login1000:
title: "Mestre de les Notes III" title: "Mestre de les Notes III"
description: "Vas iniciar sessió fa mil dies" description: "Vas iniciar sessió fa mil dies"
flavor: "Gràcies per fer servir Forkey!" flavor: "Gràcies per fer servir MissKey!"
_noteClipped1: _noteClipped1:
title: "He de retallar-te!" title: "He de retallar-te!"
description: "Retalla la teva primera nota" description: "Retalla la teva primera nota"
@ -1518,9 +1518,9 @@ _achievements:
title: "M'agraden els èxits " title: "M'agraden els èxits "
description: "Mira la teva llista d'assoliments durant més de 3 minuts" description: "Mira la teva llista d'assoliments durant més de 3 minuts"
_iLoveMisskey: _iLoveMisskey:
title: "Estimo Forkey" title: "Estimo Misskey"
description: "Publica \"I ❤ #Forkey\"" description: "Publica \"I ❤ #Misskey\""
flavor: "L'equip de desenvolupament de Forkey agraeix el vostre suport!" flavor: "L'equip de desenvolupament de Misskey agraeix el vostre suport!"
_foundTreasure: _foundTreasure:
title: "A la Recerca del Tresor" title: "A la Recerca del Tresor"
description: "Has trobat el tresor amagat" description: "Has trobat el tresor amagat"
@ -1599,7 +1599,7 @@ _achievements:
title: "Sobrecàrrega de proves" title: "Sobrecàrrega de proves"
description: "Envia moltes notificacions de prova en un període de temps molt curt" description: "Envia moltes notificacions de prova en un període de temps molt curt"
_tutorialCompleted: _tutorialCompleted:
title: "Diploma del Curs Elemental de Forkey" title: "Diploma del Curs Elemental de Misskey"
description: "Has completat el tutorial" description: "Has completat el tutorial"
_bubbleGameExplodingHead: _bubbleGameExplodingHead:
title: "🤯" title: "🤯"

View file

@ -1235,7 +1235,7 @@ _achievements:
_login1000: _login1000:
title: "Mistr poznámek III" title: "Mistr poznámek III"
description: "Přihlaste se celkově za 1000 dní" description: "Přihlaste se celkově za 1000 dní"
flavor: "Děkujeme, že používáte Forkey!" flavor: "Děkujeme, že používáte Misskey!"
_noteClipped1: _noteClipped1:
title: "Musím... připnout..." title: "Musím... připnout..."
description: "Připněte si první poznámku" description: "Připněte si první poznámku"
@ -1295,9 +1295,9 @@ _achievements:
title: "Máš rád úspěchy" title: "Máš rád úspěchy"
description: "Koukejte na váš seznam úspěchů alespoň po dobu 3 minut" description: "Koukejte na váš seznam úspěchů alespoň po dobu 3 minut"
_iLoveMisskey: _iLoveMisskey:
title: "Miluju Forkey" title: "Miluju Misskey"
description: "Zveřejněte \" I ❤ #Forkey\"" description: "Zveřejněte \" I ❤ #Misskey\""
flavor: "Vývojový tým Forkey si velmi váží vaší podpory!" flavor: "Vývojový tým Misskey si velmi váží vaší podpory!"
_foundTreasure: _foundTreasure:
title: "Hon za pokladem" title: "Hon za pokladem"
description: "Našli jste schovaný poklad!" description: "Našli jste schovaný poklad!"

View file

@ -166,7 +166,7 @@ youCanCleanRemoteFilesCache: "Klicke auf den 🗑️-Knopf der Dateiverwaltungsa
cacheRemoteSensitiveFiles: "Sensitive Dateien von fremden Instanzen im Cache speichern" cacheRemoteSensitiveFiles: "Sensitive Dateien von fremden Instanzen im Cache speichern"
cacheRemoteSensitiveFilesDescription: "Ist diese Einstellung deaktiviert, so werden sensitive Dateien fremder Instanzen direkt von dort ohne Zwischenspeicherung geladen." cacheRemoteSensitiveFilesDescription: "Ist diese Einstellung deaktiviert, so werden sensitive Dateien fremder Instanzen direkt von dort ohne Zwischenspeicherung geladen."
flagAsBot: "Als Bot markieren" flagAsBot: "Als Bot markieren"
flagAsBotDescription: "Aktiviere diese Option, falls dieses Benutzerkonto durch ein Programm gesteuert wird. Falls aktiviert, agiert es als Flag für andere Entwickler zur Verhinderung von endlosen Kettenreaktionen mit anderen Bots und lässt forkeys interne Systeme dieses Benutzerkonto als Bot behandeln." flagAsBotDescription: "Aktiviere diese Option, falls dieses Benutzerkonto durch ein Programm gesteuert wird. Falls aktiviert, agiert es als Flag für andere Entwickler zur Verhinderung von endlosen Kettenreaktionen mit anderen Bots und lässt Misskeys interne Systeme dieses Benutzerkonto als Bot behandeln."
flagAsCat: "Als Katze markieren" flagAsCat: "Als Katze markieren"
flagAsCatDescription: "Aktiviere diese Option, um dieses Benutzerkonto als Katze zu markieren." flagAsCatDescription: "Aktiviere diese Option, um dieses Benutzerkonto als Katze zu markieren."
flagShowTimelineReplies: "Antworten in der Chronik anzeigen" flagShowTimelineReplies: "Antworten in der Chronik anzeigen"
@ -1374,7 +1374,7 @@ _achievements:
_login1000: _login1000:
title: "Meister der Notizen Ⅲ" title: "Meister der Notizen Ⅲ"
description: "An 1000 Tagen eingeloggt" description: "An 1000 Tagen eingeloggt"
flavor: "Danke, dass du Forkey nutzt!" flavor: "Danke, dass du Misskey nutzt!"
_noteClipped1: _noteClipped1:
title: "Muss... clippen..." title: "Muss... clippen..."
description: "Die erste Notiz geclippt" description: "Die erste Notiz geclippt"
@ -1434,9 +1434,9 @@ _achievements:
title: "Fan von Errungenschaften" title: "Fan von Errungenschaften"
description: "Schau dir die Liste deiner Errungenschaften für mindestens 3 Minuten an" description: "Schau dir die Liste deiner Errungenschaften für mindestens 3 Minuten an"
_iLoveMisskey: _iLoveMisskey:
title: "I Love Forkey" title: "I Love Misskey"
description: "Sende \"I ❤ #Forkey\"" description: "Sende \"I ❤ #Misskey\""
flavor: "Danke, dass du Forkey verwendest! - vom Entwicklerteam" flavor: "Danke, dass du Misskey verwendest! - vom Entwicklerteam"
_foundTreasure: _foundTreasure:
title: "Schatzsuche" title: "Schatzsuche"
description: "Du hast einen verborgenen Schatz gefunden" description: "Du hast einen verborgenen Schatz gefunden"

View file

@ -43,7 +43,6 @@ alreadyFavorited: "Already added to favorites."
cantFavorite: "Couldn't add to favorites." cantFavorite: "Couldn't add to favorites."
pin: "Pin to profile" pin: "Pin to profile"
unpin: "Unpin from profile" unpin: "Unpin from profile"
approvals: "Approvals"
copyContent: "Copy contents" copyContent: "Copy contents"
copyLink: "Copy link" copyLink: "Copy link"
copyLinkRenote: "Copy renote link" copyLinkRenote: "Copy renote link"
@ -149,7 +148,6 @@ unsuspend: "Unsuspend"
blockConfirm: "Are you sure that you want to block this account?" blockConfirm: "Are you sure that you want to block this account?"
unblockConfirm: "Are you sure that you want to unblock this account?" unblockConfirm: "Are you sure that you want to unblock this account?"
suspendConfirm: "Are you sure that you want to suspend this account?" suspendConfirm: "Are you sure that you want to suspend this account?"
approveConfirm: "Are you sure that you want to approve this account?"
unsuspendConfirm: "Are you sure that you want to unsuspend this account?" unsuspendConfirm: "Are you sure that you want to unsuspend this account?"
selectList: "Select a list" selectList: "Select a list"
editList: "Edit list" editList: "Edit list"
@ -175,8 +173,6 @@ flagAsBot: "Mark this account as a bot"
flagAsBotDescription: "Enable this option if this account is controlled by a program. If enabled, it will act as a flag for other developers to prevent endless interaction chains with other bots and adjust Misskey's internal systems to treat this account as a bot." flagAsBotDescription: "Enable this option if this account is controlled by a program. If enabled, it will act as a flag for other developers to prevent endless interaction chains with other bots and adjust Misskey's internal systems to treat this account as a bot."
flagAsCat: "Mark this account as a cat" flagAsCat: "Mark this account as a cat"
flagAsCatDescription: "Enable this option to mark this account as a cat." flagAsCatDescription: "Enable this option to mark this account as a cat."
flagSpeakAsCat: "Speak as a cat"
flagSpeakAsCatDescription: "Your posts will get nyanified when in cat mode. If this isn't working, then please check that you dont have 'Disable cat speak' on under General/Note Display"
flagShowTimelineReplies: "Show replies in timeline" flagShowTimelineReplies: "Show replies in timeline"
flagShowTimelineRepliesDescription: "Shows replies of users to notes of other users in the timeline if turned on." flagShowTimelineRepliesDescription: "Shows replies of users to notes of other users in the timeline if turned on."
autoAcceptFollowed: "Automatically approve follow requests from users you're following" autoAcceptFollowed: "Automatically approve follow requests from users you're following"
@ -439,7 +435,6 @@ popularTags: "Popular tags"
userList: "Lists" userList: "Lists"
about: "About" about: "About"
aboutMisskey: "About Misskey" aboutMisskey: "About Misskey"
aboutForkey: "About Forkey"
administrator: "Administrator" administrator: "Administrator"
token: "Token" token: "Token"
2fa: "Two-factor authentication" 2fa: "Two-factor authentication"
@ -764,7 +759,6 @@ noCrawleDescription: "Ask search engines to not index your profile page, notes,
lockedAccountInfo: "Unless you set your note visiblity to \"Followers only\", your notes will be visible to anyone, even if you require followers to be manually approved." lockedAccountInfo: "Unless you set your note visiblity to \"Followers only\", your notes will be visible to anyone, even if you require followers to be manually approved."
alwaysMarkSensitive: "Mark as sensitive by default" alwaysMarkSensitive: "Mark as sensitive by default"
loadRawImages: "Load original images instead of showing thumbnails" loadRawImages: "Load original images instead of showing thumbnails"
disableCatSpeak: "Disable cat speak"
disableShowingAnimatedImages: "Don't play animated images" disableShowingAnimatedImages: "Don't play animated images"
highlightSensitiveMedia: "Highlight sensitive media" highlightSensitiveMedia: "Highlight sensitive media"
verificationEmailSent: "A verification email has been sent. Please follow the included link to complete verification." verificationEmailSent: "A verification email has been sent. Please follow the included link to complete verification."
@ -912,7 +906,6 @@ itsOff: "Disabled"
on: "On" on: "On"
off: "Off" off: "Off"
emailRequiredForSignup: "Require email address for sign-up" emailRequiredForSignup: "Require email address for sign-up"
approvalRequiredForSignup: "Require approval for new users"
unread: "Unread" unread: "Unread"
filter: "Filter" filter: "Filter"
controlPanel: "Control Panel" controlPanel: "Control Panel"
@ -973,12 +966,6 @@ requireAdminForView: "You must log in with an administrator account to view this
isSystemAccount: "An account created and automatically operated by the system." isSystemAccount: "An account created and automatically operated by the system."
typeToConfirm: "Please enter {x} to confirm" typeToConfirm: "Please enter {x} to confirm"
deleteAccount: "Delete account" deleteAccount: "Delete account"
pendingUserApprovals: "There are users awaiting approval."
approveAccount: "Approve"
denyAccount: "Deny & Delete"
approved: "Approved"
notApproved: "Not Approved"
approvalStatus: "Approval Status"
document: "Documentation" document: "Documentation"
numberOfPageCache: "Number of cached pages" numberOfPageCache: "Number of cached pages"
numberOfPageCacheDescription: "Increasing this number will improve convenience for but cause more load as more memory usage on the user's device." numberOfPageCacheDescription: "Increasing this number will improve convenience for but cause more load as more memory usage on the user's device."
@ -1074,7 +1061,6 @@ disableFederationConfirm: "Really disable federation?"
disableFederationConfirmWarn: "Even if defederated, posts will continue to be public unless set otherwise. You usually do not need to do this." disableFederationConfirmWarn: "Even if defederated, posts will continue to be public unless set otherwise. You usually do not need to do this."
disableFederationOk: "Disable" disableFederationOk: "Disable"
invitationRequiredToRegister: "This instance is invite-only. You must enter a valid invite code sign up." invitationRequiredToRegister: "This instance is invite-only. You must enter a valid invite code sign up."
approvalRequiredToRegister: "This instance is only accepting users who specify a reason for registration."
emailNotSupported: "This instance does not support sending emails" emailNotSupported: "This instance does not support sending emails"
postToTheChannel: "Post to channel" postToTheChannel: "Post to channel"
cannotBeChangedLater: "This cannot be changed later." cannotBeChangedLater: "This cannot be changed later."
@ -1336,14 +1322,6 @@ consentAll: "Allow All Items"
consentSelected: "Allow Selected Items" consentSelected: "Allow Selected Items"
emailAddressLogin: "Login with email address" emailAddressLogin: "Login with email address"
usernameLogin: "Login with username" usernameLogin: "Login with username"
autoloadDrafts: "Automatically load drafts when opening the posting form"
drafts: "Drafts"
unsent: "Unsent"
schedule: "Schedule"
scheduled: "Scheduled"
unschedule: "Unschedule"
setScheduledTime: "Set scheduled time"
willBePostedAt: "Note will be posted at {x}"
_bubbleGame: _bubbleGame:
howToPlay: "How to play" howToPlay: "How to play"
@ -1384,8 +1362,8 @@ _abuseReportCategory:
otherBreach_description: "Other actions that violate the terms but do not fall under specific categories" otherBreach_description: "Other actions that violate the terms but do not fall under specific categories"
violationRights: "Rights Infringement or Impersonation (Reported by Rights Holder)" violationRights: "Rights Infringement or Impersonation (Reported by Rights Holder)"
violationRights_description: "Posts infringing the rights (such as copyright or trademark) of the rights holder or impersonation" violationRights_description: "Posts infringing the rights (such as copyright or trademark) of the rights holder or impersonation"
violationRightsOther: "Rights Infringement (Reported by Third Party)" violationRightsOther: "Rights Infringement or Impersonation (Reported by Third Party)"
violationRightsOther_description: "Posts infringing the rights (such as copyright or trademark) of others\nIf reported by a third party, cases outside the scope of non-complaint offenses as defined by law may not be addressed" violationRightsOther_description: "Posts infringing the rights (such as copyright or trademark) of others or impersonation\nIf reported by a third party, cases outside the scope of non-complaint offenses as defined by law may not be addressed"
notLike: "Dislike This Person" notLike: "Dislike This Person"
notLike_description: "Users or posts that you find unpleasant for personal reasons" notLike_description: "Users or posts that you find unpleasant for personal reasons"
other: "Other" other: "Other"
@ -1522,9 +1500,9 @@ _achievements:
earnedAt: "Unlocked at" earnedAt: "Unlocked at"
_types: _types:
_notes1: _notes1:
title: "just setting up my forkey" title: "just setting up my msky"
description: "Post your first note" description: "Post your first note"
flavor: "Have a good time with Forkey!" flavor: "Have a good time with Misskey!"
_notes10: _notes10:
title: "Some notes" title: "Some notes"
description: "Post 10 notes" description: "Post 10 notes"
@ -1620,7 +1598,7 @@ _achievements:
_login1000: _login1000:
title: "Master of Notes III" title: "Master of Notes III"
description: "Log in for a total of 1,000 days" description: "Log in for a total of 1,000 days"
flavor: "Thank you for using Forkey!" flavor: "Thank you for using Misskey!"
_noteClipped1: _noteClipped1:
title: "Must... clip..." title: "Must... clip..."
description: "Clip your first note" description: "Clip your first note"
@ -1680,9 +1658,9 @@ _achievements:
title: "Likes Achievements" title: "Likes Achievements"
description: "Look at your list of achievements for at least 3 minutes" description: "Look at your list of achievements for at least 3 minutes"
_iLoveMisskey: _iLoveMisskey:
title: "I Love Forkey" title: "I Love Misskey"
description: "Post \"I ❤ #Forkey\"" description: "Post \"I ❤ #Misskey\""
flavor: "Forkey's development team greatly appreciates your support!" flavor: "Misskey's development team greatly appreciates your support!"
_foundTreasure: _foundTreasure:
title: "Treasure Hunt" title: "Treasure Hunt"
description: "You've found the hidden treasure" description: "You've found the hidden treasure"
@ -1761,7 +1739,7 @@ _achievements:
title: "Test overflow" title: "Test overflow"
description: "Trigger the notification test repeatedly within an extremely short time" description: "Trigger the notification test repeatedly within an extremely short time"
_tutorialCompleted: _tutorialCompleted:
title: "Forkey Elementary Course Diploma" title: "Misskey Elementary Course Diploma"
description: "Tutorial completed" description: "Tutorial completed"
_bubbleGameExplodingHead: _bubbleGameExplodingHead:
title: "🤯" title: "🤯"
@ -1812,9 +1790,6 @@ _role:
gtlAvailable: "Can view the global timeline" gtlAvailable: "Can view the global timeline"
ltlAvailable: "Can view the local timeline" ltlAvailable: "Can view the local timeline"
canPublicNote: "Can send public notes" canPublicNote: "Can send public notes"
canScheduleNote: "Can schedule notes"
scheduleNoteLimit: "Maximum number of scheduled notes"
scheduleNoteMaxDays: "Maximum number of days that note can be scheduled"
canInitiateConversation: "Can mention, reply or quote" canInitiateConversation: "Can mention, reply or quote"
canCreateContent: "Can create contents" canCreateContent: "Can create contents"
canUpdateContent: "Can edit contents" canUpdateContent: "Can edit contents"
@ -1894,8 +1869,6 @@ _signup:
almostThere: "Almost there" almostThere: "Almost there"
emailAddressInfo: "Please enter your email address. It will not be made public." emailAddressInfo: "Please enter your email address. It will not be made public."
emailSent: "A confirmation email has been sent to your email address ({email}). Please click the included link to complete account creation." emailSent: "A confirmation email has been sent to your email address ({email}). Please click the included link to complete account creation."
approvalPending: "Your account has been created and is awaiting approval."
reasonInfo: "Please enter a reason as to why you want to join the instance."
_accountDelete: _accountDelete:
accountDelete: "Delete account" accountDelete: "Delete account"
mayTakeTime: "As account deletion is a resource-heavy process, it may take some time to complete depending on how much content you have created and how many files you have uploaded." mayTakeTime: "As account deletion is a resource-heavy process, it may take some time to complete depending on how much content you have created and how many files you have uploaded."
@ -1962,17 +1935,13 @@ _aboutMisskey:
contributors: "Main contributors" contributors: "Main contributors"
allContributors: "All contributors" allContributors: "All contributors"
source: "Source code" source: "Source code"
original: "Misskey Original" original: "Original"
thisIsModifiedVersion: "{name} uses a modified version of the original Misskey." thisIsModifiedVersion: "{name} uses a modified version of the original Misskey."
translation: "Translate Misskey" translation: "Translate Misskey"
donate: "Donate to Misskey" donate: "Donate to Misskey"
morePatrons: "We also appreciate the support of many other helpers not listed here. Thank you! 🥰" morePatrons: "We also appreciate the support of many other helpers not listed here. Thank you! 🥰"
patrons: "Patrons" patrons: "Patrons"
projectMembers: "Misskey Project members" projectMembers: "Project members"
_aboutForkey:
about: "Forkey is open-source software based on Misskey which has been in development by syuilo since 2014."
original: "Forkey Original"
projectMembers: "Forkey Project Members"
_displayOfSensitiveMedia: _displayOfSensitiveMedia:
respect: "Hide media marked as sensitive" respect: "Hide media marked as sensitive"
ignore: "Display media marked as sensitive" ignore: "Display media marked as sensitive"
@ -2243,7 +2212,6 @@ _permissions:
"read:clip-favorite": "View favorited clips" "read:clip-favorite": "View favorited clips"
"read:federation": "Get federation data" "read:federation": "Get federation data"
"write:report-abuse": "Report violation" "write:report-abuse": "Report violation"
"write:push-notification": "Receive push notifications"
_auth: _auth:
shareAccessTitle: "Granting application permissions" shareAccessTitle: "Granting application permissions"
shareAccess: "Would you like to authorize \"{name}\" to access this account?" shareAccess: "Would you like to authorize \"{name}\" to access this account?"
@ -2352,8 +2320,6 @@ _postForm:
d: "What do you want to say?" d: "What do you want to say?"
e: "Start writing..." e: "Start writing..."
f: "Waiting for you to write..." f: "Waiting for you to write..."
policyScheduleNoteMaxDaysExceeded: "The maximum number of days you can schedule notes for with your current support plan is {max}.\nYou can upgrade your plan [here](https://go.misskey.io/donate)."
tosAndGuidelinesInfo: "Before posting, please read the [Terms of Service]({tosUrl}) and [NSFW Guidelines](https://go.misskey.io/media-guideline)."
_profile: _profile:
name: "Name" name: "Name"
username: "Username" username: "Username"
@ -2378,7 +2344,7 @@ _profile:
sectionName: "Section name" sectionName: "Section name"
sectionNameNoneDescription: "Do not display the section name" sectionNameNoneDescription: "Do not display the section name"
sectionNameNone: "Section without name" sectionNameNone: "Section without name"
policyDisplayLimitExceeded: "The number of items displayed exceeds the current support plan's limit ({max}). This item will not be displayed.\nYou can upgrade your plan [here](https://go.misskey.io/donate)." policyDisplayLimitExceeded: "The number of items displayed exceeds the current support plan's limit ({max}). This item will not be displayed. You can upgrade your plan [here](https://go.misskey.io/donate)."
_exportOrImport: _exportOrImport:
allNotes: "All notes" allNotes: "All notes"
favoritedNotes: "Favorite notes" favoritedNotes: "Favorite notes"
@ -2511,9 +2477,6 @@ _notification:
roleAssigned: "Role given" roleAssigned: "Role given"
emptyPushNotificationMessage: "Push notifications have been updated" emptyPushNotificationMessage: "Push notifications have been updated"
achievementEarned: "Achievement unlocked" achievementEarned: "Achievement unlocked"
noteScheduled: "Note has been scheduled"
scheduledNotePosted: "Scheduled note has been posted"
scheduledNoteError: "Scheduled note has problem with posting"
testNotification: "Test notification" testNotification: "Test notification"
checkNotificationBehavior: "Check notification appearance" checkNotificationBehavior: "Check notification appearance"
sendTestNotification: "Send test notification" sendTestNotification: "Send test notification"
@ -2537,9 +2500,6 @@ _notification:
followRequestAccepted: "Accepted follow requests" followRequestAccepted: "Accepted follow requests"
roleAssigned: "Role given" roleAssigned: "Role given"
achievementEarned: "Achievement unlocked" achievementEarned: "Achievement unlocked"
noteScheduled: "Note scheduled"
scheduledNotePosted: "Scheduled note posted"
scheduledNoteError: "Problem with scheduled note"
app: "Notifications from linked apps" app: "Notifications from linked apps"
_actions: _actions:
followBack: "followed you back" followBack: "followed you back"

View file

@ -1476,7 +1476,7 @@ _achievements:
_login1000: _login1000:
title: "Maestro III" title: "Maestro III"
description: "Días desde el inicio de sesión: 1000" description: "Días desde el inicio de sesión: 1000"
flavor: "¡Gracias por usar Forkey!" flavor: "¡Gracias por usar Misskey!"
_noteClipped1: _noteClipped1:
title: "No puedo evitar clipearte..." title: "No puedo evitar clipearte..."
description: "Hacer un clip por primera vez" description: "Hacer un clip por primera vez"
@ -1536,9 +1536,9 @@ _achievements:
title: "¡Te gustan los logros!" title: "¡Te gustan los logros!"
description: "Mirando tus logros por 3 minutos" description: "Mirando tus logros por 3 minutos"
_iLoveMisskey: _iLoveMisskey:
title: "¡AMO Forkey!" title: "¡AMO Misskey!"
description: "\"I ❤ #Forkey\" Publicado" description: "\"I ❤ #Misskey\" Publicado"
flavor: "El equipo de desarrollo de Forkey, en verdad, ¡aprecia tu apoyo!" flavor: "El equipo de desarrollo de Misskey, en verdad, ¡aprecia tu apoyo!"
_foundTreasure: _foundTreasure:
title: "Búsqueda del tesoro" title: "Búsqueda del tesoro"
description: "Encontraste un tesoro" description: "Encontraste un tesoro"
@ -1617,7 +1617,7 @@ _achievements:
title: "Sobrecarga de pruebas" title: "Sobrecarga de pruebas"
description: "Envía muchas notificaciones de prueba en un corto espacio de tiempo" description: "Envía muchas notificaciones de prueba en un corto espacio de tiempo"
_tutorialCompleted: _tutorialCompleted:
title: "Diploma del Curso Básico de Forkey" title: "Diploma del Curso Básico de Misskey"
description: "Tutorial completado" description: "Tutorial completado"
_bubbleGameExplodingHead: _bubbleGameExplodingHead:
title: "🤯" title: "🤯"

View file

@ -1393,7 +1393,7 @@ _achievements:
_login900: _login900:
description: "Se connecter pour un total de 900 jours" description: "Se connecter pour un total de 900 jours"
_login1000: _login1000:
flavor: "Merci d'utiliser Forkey !" flavor: "Merci d'utiliser Misskey !"
_profileFilled: _profileFilled:
title: "Bien préparé" title: "Bien préparé"
description: "Configuration de votre profil" description: "Configuration de votre profil"
@ -1429,9 +1429,9 @@ _achievements:
title: "Influenceur·euse" title: "Influenceur·euse"
description: "Obtenir plus de 1000 abonné·e·s" description: "Obtenir plus de 1000 abonné·e·s"
_iLoveMisskey: _iLoveMisskey:
title: "Jadore Forkey" title: "Jadore Misskey"
description: "Publication « J❤ #Forkey »" description: "Publication « J❤ #Misskey »"
flavor: "L'équipe de développement de Forkey apprécie vraiment votre aide !" flavor: "L'équipe de développement de Misskey apprécie vraiment votre aide !"
_foundTreasure: _foundTreasure:
title: "Chasse au trésor" title: "Chasse au trésor"
description: "Vous avez trouvé le trésor caché" description: "Vous avez trouvé le trésor caché"
@ -1472,7 +1472,7 @@ _achievements:
title: "Débordement de tests" title: "Débordement de tests"
description: "Détruire le bouton de test de notifications dans un intervalle extrêmement court" description: "Détruire le bouton de test de notifications dans un intervalle extrêmement court"
_tutorialCompleted: _tutorialCompleted:
title: "Diplôme de la course élémentaire de Forkey" title: "Diplôme de la course élémentaire de Misskey"
description: "Terminer le tutoriel" description: "Terminer le tutoriel"
_role: _role:
new: "Nouveau rôle" new: "Nouveau rôle"

View file

@ -1478,7 +1478,7 @@ _achievements:
_login1000: _login1000:
title: "Sepuh Catatan III" title: "Sepuh Catatan III"
description: "Login selama 1000 hari" description: "Login selama 1000 hari"
flavor: "Terima kasih telah menggunakan Forkey!" flavor: "Terima kasih telah menggunakan Misskey!"
_noteClipped1: _noteClipped1:
title: "Harus... Ngeklip..." title: "Harus... Ngeklip..."
description: "Klip catatan pertamamu" description: "Klip catatan pertamamu"
@ -1538,9 +1538,9 @@ _achievements:
title: "Suka Pencapaian" title: "Suka Pencapaian"
description: "Lugat daftar pencapaianmu setidaknya 3 menit" description: "Lugat daftar pencapaianmu setidaknya 3 menit"
_iLoveMisskey: _iLoveMisskey:
title: "I Love Forkey" title: "I Love Misskey"
description: "Catat \"I ❤ #Forkey\"" description: "Catat \"I ❤ #Misskey\""
flavor: "Tim pengembang forkey sangat mengapresiasi dukungan kamu!" flavor: "Tim pengembang misskey sangat mengapresiasi dukungan kamu!"
_foundTreasure: _foundTreasure:
title: "Berburu Harta Karun" title: "Berburu Harta Karun"
description: "Kamu telah menemukan harta karun tersembunyi" description: "Kamu telah menemukan harta karun tersembunyi"
@ -1619,7 +1619,7 @@ _achievements:
title: "Tes overflow" title: "Tes overflow"
description: "Picu tes notifikasi secara berulang dalam waktu yang sangat pendek" description: "Picu tes notifikasi secara berulang dalam waktu yang sangat pendek"
_tutorialCompleted: _tutorialCompleted:
title: "Ijazah Sekolah Dasar Forkey" title: "Ijazah Sekolah Dasar Misskey"
description: "Tutorial selesai" description: "Tutorial selesai"
_bubbleGameExplodingHead: _bubbleGameExplodingHead:
title: "🤯" title: "🤯"

176
locales/index.d.ts vendored
View file

@ -620,10 +620,6 @@ export interface Locale extends ILocale {
* *
*/ */
"suspendConfirm": string; "suspendConfirm": string;
/**
*
*/
"approveConfirm": string;
/** /**
* *
*/ */
@ -724,14 +720,6 @@ export interface Locale extends ILocale {
* *
*/ */
"flagAsCatDescription": string; "flagAsCatDescription": string;
/**
*
*/
"flagSpeakAsCat": string;
/**
* 稿
*/
"flagSpeakAsCatDescription": string;
/** /**
* *
*/ */
@ -1780,10 +1768,6 @@ export interface Locale extends ILocale {
* Misskeyについて * Misskeyについて
*/ */
"aboutMisskey": string; "aboutMisskey": string;
/**
* Forkeyについて
*/
"aboutForkey": string;
/** /**
* *
*/ */
@ -3072,10 +3056,6 @@ export interface Locale extends ILocale {
* *
*/ */
"loadRawImages": string; "loadRawImages": string;
/**
*
*/
"disableCatSpeak": string;
/** /**
* *
*/ */
@ -3664,10 +3644,6 @@ export interface Locale extends ILocale {
* *
*/ */
"emailRequiredForSignup": string; "emailRequiredForSignup": string;
/**
*
*/
"approvalRequiredForSignup": string;
/** /**
* *
*/ */
@ -3911,30 +3887,6 @@ export interface Locale extends ILocale {
* *
*/ */
"deleteAccount": string; "deleteAccount": string;
/**
*
*/
"pendingUserApprovals": string;
/**
*
*/
"approveAccount": string;
/**
*
*/
"denyAccount": string;
/**
*
*/
"approved": string;
/**
*
*/
"notApproved": string;
/**
*
*/
"approvalStatus": string;
/** /**
* *
*/ */
@ -4315,10 +4267,6 @@ export interface Locale extends ILocale {
* *
*/ */
"invitationRequiredToRegister": string; "invitationRequiredToRegister": string;
/**
*
*/
"approvalRequiredToRegister": string;
/** /**
* *
*/ */
@ -5398,38 +5346,6 @@ export interface Locale extends ILocale {
* *
*/ */
"usernameLogin": string; "usernameLogin": string;
/**
* 稿
*/
"autoloadDrafts": string;
/**
*
*/
"drafts": string;
/**
*
*/
"unsent": string;
/**
*
*/
"schedule": string;
/**
*
*/
"scheduled": string;
/**
*
*/
"unschedule": string;
/**
*
*/
"setScheduledTime": string;
/**
* {x}稿
*/
"willBePostedAt": ParameterizedString<"x">;
"_bubbleGame": { "_bubbleGame": {
/** /**
* *
@ -5558,11 +5474,11 @@ export interface Locale extends ILocale {
*/ */
"violationRights_description": string; "violationRights_description": string;
/** /**
* *
*/ */
"violationRightsOther": string; "violationRightsOther": string;
/** /**
* * 稿
* *
*/ */
"violationRightsOther_description": string; "violationRightsOther_description": string;
@ -6081,7 +5997,7 @@ export interface Locale extends ILocale {
"_types": { "_types": {
"_notes1": { "_notes1": {
/** /**
* just setting up my forkey * just setting up my msky
*/ */
"title": string; "title": string;
/** /**
@ -6089,7 +6005,7 @@ export interface Locale extends ILocale {
*/ */
"description": string; "description": string;
/** /**
* Forkeyライフを * Misskeyライフを
*/ */
"flavor": string; "flavor": string;
}; };
@ -6413,7 +6329,7 @@ export interface Locale extends ILocale {
*/ */
"description": string; "description": string;
/** /**
* Forkeyを使ってくれてありがとう * Misskeyを使ってくれてありがとう
*/ */
"flavor": string; "flavor": string;
}; };
@ -6613,15 +6529,15 @@ export interface Locale extends ILocale {
}; };
"_iLoveMisskey": { "_iLoveMisskey": {
/** /**
* I Love Forkey * I Love Misskey
*/ */
"title": string; "title": string;
/** /**
* "I ❤ #Forkey"稿 * "I ❤ #Misskey"稿
*/ */
"description": string; "description": string;
/** /**
* Forkeyを使ってくださりありがとうございます by * Misskeyを使ってくださりありがとうございます by
*/ */
"flavor": string; "flavor": string;
}; };
@ -6887,7 +6803,7 @@ export interface Locale extends ILocale {
}; };
"_tutorialCompleted": { "_tutorialCompleted": {
/** /**
* Forkey初心者講座 * Misskey初心者講座
*/ */
"title": string; "title": string;
/** /**
@ -7083,18 +6999,6 @@ export interface Locale extends ILocale {
* 稿 * 稿
*/ */
"canPublicNote": string; "canPublicNote": string;
/**
* 稿
*/
"canScheduleNote": string;
/**
* 稿
*/
"scheduleNoteLimit": string;
/**
* 稿
*/
"scheduleNoteMaxDays": string;
/** /**
* *
*/ */
@ -7402,14 +7306,6 @@ export interface Locale extends ILocale {
* ({email})30 * ({email})30
*/ */
"emailSent": ParameterizedString<"email">; "emailSent": ParameterizedString<"email">;
/**
*
*/
"approvalPending": string;
/**
*
*/
"reasonInfo": string;
}; };
"_accountDelete": { "_accountDelete": {
/** /**
@ -7653,7 +7549,7 @@ export interface Locale extends ILocale {
*/ */
"source": string; "source": string;
/** /**
* Misskeyオリジナ *
*/ */
"original": string; "original": string;
/** /**
@ -7677,21 +7573,7 @@ export interface Locale extends ILocale {
*/ */
"patrons": string; "patrons": string;
/** /**
* Misskeyプロジェクトメンバー *
*/
"projectMembers": string;
};
"_aboutForkey": {
/**
* Forkey 2014 syuilo Misskey
*/
"about": string;
/**
* Forkeyに寄付
*/
"original": string;
/**
* Forkeyプロジェクトメンバー
*/ */
"projectMembers": string; "projectMembers": string;
}; };
@ -9166,14 +9048,9 @@ export interface Locale extends ILocale {
"f": string; "f": string;
}; };
/** /**
* {max} * [NSFWガイドライン]({nsfwGuideUrl})
* [](https://go.misskey.io/donate)からプランをアップグレードできます。
*/ */
"policyScheduleNoteMaxDaysExceeded": ParameterizedString<"max">; "guidelineInfo": ParameterizedString<"nsfwGuideUrl">;
/**
* 稿[]({tosUrl})[NSFWガイドライン](https://go.misskey.io/media-guideline)を必ずお読みください。
*/
"tosAndGuidelinesInfo": ParameterizedString<"tosUrl">;
}; };
"_profile": { "_profile": {
/** /**
@ -9269,8 +9146,7 @@ export interface Locale extends ILocale {
*/ */
"sectionNameNone": string; "sectionNameNone": string;
/** /**
* ({max}) * ({max})[](https://go.misskey.io/donate)からプランをアップグレードできます。
* [](https://go.misskey.io/donate)からプランをアップグレードできます。
*/ */
"policyDisplayLimitExceeded": ParameterizedString<"max">; "policyDisplayLimitExceeded": ParameterizedString<"max">;
}; };
@ -9781,18 +9657,6 @@ export interface Locale extends ILocale {
* *
*/ */
"achievementEarned": string; "achievementEarned": string;
/**
*
*/
"noteScheduled": string;
/**
* 稿
*/
"scheduledNotePosted": string;
/**
* 稿
*/
"scheduledNoteError": string;
/** /**
* *
*/ */
@ -9882,18 +9746,6 @@ export interface Locale extends ILocale {
* *
*/ */
"achievementEarned": string; "achievementEarned": string;
/**
*
*/
"noteScheduled": string;
/**
* 稿
*/
"scheduledNotePosted": string;
/**
* 稿
*/
"scheduledNoteError": string;
/** /**
* *
*/ */

View file

@ -72,7 +72,7 @@ export function build() {
.reduce((a, [k, v]) => (a[k] = (() => { .reduce((a, [k, v]) => (a[k] = (() => {
const [lang] = k.split('-'); const [lang] = k.split('-');
switch (k) { switch (k) {
case 'ja-JP': return merge(locales['en-US'], v); case 'ja-JP': return v;
case 'ja-KS': case 'ja-KS':
case 'en-US': return merge(locales['ja-JP'], v); case 'en-US': return merge(locales['ja-JP'], v);
default: return merge( default: return merge(

View file

@ -1476,7 +1476,7 @@ _achievements:
_login1000: _login1000:
title: "Maestro di Note III livello" title: "Maestro di Note III livello"
description: "Hai totalizzato 1000 accessi!" description: "Hai totalizzato 1000 accessi!"
flavor: "Grazie per aver usato Forkey!" flavor: "Grazie per aver usato Misskey!"
_noteClipped1: _noteClipped1:
title: "Devo clippare!" title: "Devo clippare!"
description: "Hai raccolto la tua prima Nota in una Clip" description: "Hai raccolto la tua prima Nota in una Clip"
@ -1536,9 +1536,9 @@ _achievements:
title: "Mi piacciono i risultati" title: "Mi piacciono i risultati"
description: "Guarda la tua collezione di obiettivi per almeno 3 minuti" description: "Guarda la tua collezione di obiettivi per almeno 3 minuti"
_iLoveMisskey: _iLoveMisskey:
title: "I LOVE Forkey" title: "I LOVE Misskey"
description: "Pubblica «I ♥ #Forkey»" description: "Pubblica «I ♥ #Misskey»"
flavor: "Grazie per aver utilizzato Forkey! Dal team di sviluppo" flavor: "Grazie per aver utilizzato Misskey! Dal team di sviluppo"
_foundTreasure: _foundTreasure:
title: "Caccia al tesoro" title: "Caccia al tesoro"
description: "Hai trovato un tesoro nascosto" description: "Hai trovato un tesoro nascosto"
@ -1617,7 +1617,7 @@ _achievements:
title: "Prove eccessive" title: "Prove eccessive"
description: "Hai provato le notifiche consecutivamente in un periodo di tempo molto breve" description: "Hai provato le notifiche consecutivamente in un periodo di tempo molto breve"
_tutorialCompleted: _tutorialCompleted:
title: "Attestato di partecipazione al corso per principianti di Forkey" title: "Attestato di partecipazione al corso per principianti di Misskey"
description: "Ha completato il tutorial" description: "Ha completato il tutorial"
_bubbleGameExplodingHead: _bubbleGameExplodingHead:
title: "🤯" title: "🤯"

View file

@ -151,7 +151,6 @@ unsuspend: "解凍"
blockConfirm: "ブロックしますか?" blockConfirm: "ブロックしますか?"
unblockConfirm: "ブロック解除しますか?" unblockConfirm: "ブロック解除しますか?"
suspendConfirm: "凍結しますか?" suspendConfirm: "凍結しますか?"
approveConfirm: "このアカウントを承認してもよろしいですか?"
unsuspendConfirm: "解凍しますか?" unsuspendConfirm: "解凍しますか?"
selectList: "リストを選択" selectList: "リストを選択"
editList: "リストを編集" editList: "リストを編集"
@ -177,8 +176,6 @@ flagAsBot: "Botとして設定"
flagAsBotDescription: "このアカウントがプログラムによって運用される場合は、このフラグをオンにします。オンにすると、反応の連鎖を防ぐためのフラグとして他の開発者に役立ったり、Misskeyのシステム上での扱いがBotに合ったものになります。" flagAsBotDescription: "このアカウントがプログラムによって運用される場合は、このフラグをオンにします。オンにすると、反応の連鎖を防ぐためのフラグとして他の開発者に役立ったり、Misskeyのシステム上での扱いがBotに合ったものになります。"
flagAsCat: "にゃああああああああああああああ!!!!!!!!!!!!" flagAsCat: "にゃああああああああああああああ!!!!!!!!!!!!"
flagAsCatDescription: "にゃにゃにゃ??" flagAsCatDescription: "にゃにゃにゃ??"
flagSpeakAsCat: "猫語で話す"
flagSpeakAsCatDescription: "有効にすると、あなたの投稿の 「な」を「にゃ」にします。"
flagShowTimelineReplies: "タイムラインにノートへの返信を表示する" flagShowTimelineReplies: "タイムラインにノートへの返信を表示する"
flagShowTimelineRepliesDescription: "オンにすると、タイムラインにユーザーのノート以外にもそのユーザーの他のノートへの返信を表示します。" flagShowTimelineRepliesDescription: "オンにすると、タイムラインにユーザーのノート以外にもそのユーザーの他のノートへの返信を表示します。"
autoAcceptFollowed: "フォロー中ユーザーからのフォロリクを自動承認" autoAcceptFollowed: "フォロー中ユーザーからのフォロリクを自動承認"
@ -441,7 +438,6 @@ popularTags: "人気のタグ"
userList: "リスト" userList: "リスト"
about: "情報" about: "情報"
aboutMisskey: "Misskeyについて" aboutMisskey: "Misskeyについて"
aboutForkey: "Forkeyについて"
administrator: "管理者" administrator: "管理者"
token: "確認コード" token: "確認コード"
2fa: "二要素認証" 2fa: "二要素認証"
@ -764,7 +760,6 @@ noCrawleDescription: "外部の検索エンジンにあなたのユーザーペ
lockedAccountInfo: "フォローを承認制にしても、ノートの公開範囲を「フォロワー」にしない限り、誰でもあなたのノートを見ることができます。" lockedAccountInfo: "フォローを承認制にしても、ノートの公開範囲を「フォロワー」にしない限り、誰でもあなたのノートを見ることができます。"
alwaysMarkSensitive: "デフォルトでメディアをセンシティブ設定にする" alwaysMarkSensitive: "デフォルトでメディアをセンシティブ設定にする"
loadRawImages: "添付画像のサムネイルをオリジナル画質にする" loadRawImages: "添付画像のサムネイルをオリジナル画質にする"
disableCatSpeak: "猫の話し方を無効にする"
disableShowingAnimatedImages: "アニメーション画像を再生しない" disableShowingAnimatedImages: "アニメーション画像を再生しない"
highlightSensitiveMedia: "メディアがセンシティブであることを分かりやすく表示" highlightSensitiveMedia: "メディアがセンシティブであることを分かりやすく表示"
verificationEmailSent: "確認のメールを送信しました。メールに記載されたリンクにアクセスして、設定を完了してください。" verificationEmailSent: "確認のメールを送信しました。メールに記載されたリンクにアクセスして、設定を完了してください。"
@ -912,7 +907,6 @@ itsOff: "オフになっています"
on: "オン" on: "オン"
off: "オフ" off: "オフ"
emailRequiredForSignup: "アカウント登録にメールアドレスを必須にする" emailRequiredForSignup: "アカウント登録にメールアドレスを必須にする"
approvalRequiredForSignup: "新規ユーザーの承認が必要"
unread: "未読" unread: "未読"
filter: "フィルタ" filter: "フィルタ"
controlPanel: "コントロールパネル" controlPanel: "コントロールパネル"
@ -973,12 +967,6 @@ requireAdminForView: "閲覧するには管理者アカウントでログイン
isSystemAccount: "システムにより自動で作成・管理されているアカウントです。" isSystemAccount: "システムにより自動で作成・管理されているアカウントです。"
typeToConfirm: "この操作を行うには {x} と入力してください" typeToConfirm: "この操作を行うには {x} と入力してください"
deleteAccount: "アカウント削除" deleteAccount: "アカウント削除"
pendingUserApprovals: "承認待ちのユーザーがいます。"
approveAccount: "承認する"
denyAccount: "拒否と削除"
approved: "承認済み"
notApproved: "承認されていない"
approvalStatus: "承認状況"
document: "ドキュメント" document: "ドキュメント"
numberOfPageCache: "ページキャッシュ数" numberOfPageCache: "ページキャッシュ数"
numberOfPageCacheDescription: "多くすると利便性が向上しますが、負荷とメモリ使用量が増えます。" numberOfPageCacheDescription: "多くすると利便性が向上しますが、負荷とメモリ使用量が増えます。"
@ -1074,7 +1062,6 @@ disableFederationConfirm: "連合なしにしますか?"
disableFederationConfirmWarn: "連合なしにしても投稿は非公開になりません。ほとんどの場合、連合なしにする必要はありません。" disableFederationConfirmWarn: "連合なしにしても投稿は非公開になりません。ほとんどの場合、連合なしにする必要はありません。"
disableFederationOk: "連合なしにする" disableFederationOk: "連合なしにする"
invitationRequiredToRegister: "現在このサーバーは招待制です。招待コードをお持ちの方のみ登録できます。" invitationRequiredToRegister: "現在このサーバーは招待制です。招待コードをお持ちの方のみ登録できます。"
approvalRequiredToRegister: "このインスタンスは、登録理由を指定したユーザーのみを受け入れています。"
emailNotSupported: "このサーバーではメール配信はサポートされていません" emailNotSupported: "このサーバーではメール配信はサポートされていません"
postToTheChannel: "チャンネルに投稿" postToTheChannel: "チャンネルに投稿"
cannotBeChangedLater: "後から変更できません。" cannotBeChangedLater: "後から変更できません。"
@ -1343,14 +1330,6 @@ consentAll: "全て許可"
consentSelected: "選択した項目のみ許可" consentSelected: "選択した項目のみ許可"
emailAddressLogin: "メールアドレスでログイン" emailAddressLogin: "メールアドレスでログイン"
usernameLogin: "ユーザー名でログイン" usernameLogin: "ユーザー名でログイン"
autoloadDrafts: "投稿フォームを開いたときに下書きを自動で読み込む"
drafts: "下書き"
unsent: "未送信"
schedule: "予約"
scheduled: "予約済み"
unschedule: "予約を解除"
setScheduledTime: "予約日時を設定"
willBePostedAt: "{x}に投稿されます"
_bubbleGame: _bubbleGame:
howToPlay: "遊び方" howToPlay: "遊び方"
@ -1387,8 +1366,8 @@ _abuseReportCategory:
otherBreach_description: "明確に分類されないその他の規約違反行為" otherBreach_description: "明確に分類されないその他の規約違反行為"
violationRights: "権利侵害やなりすまし(侵害を受けた権利者本人によるご申告)" violationRights: "権利侵害やなりすまし(侵害を受けた権利者本人によるご申告)"
violationRights_description: "権利者本人の著作権、商標権、またはその他の権利を侵害する投稿及びなりすまし行為" violationRights_description: "権利者本人の著作権、商標権、またはその他の権利を侵害する投稿及びなりすまし行為"
violationRightsOther: "権利侵害(第三者による通報)" violationRightsOther: "権利侵害やなりすまし(第三者による通報)"
violationRightsOther_description: "他人の著作権、商標権、またはその他の権利を侵害する行為\n第三者による通報の場合、法律で定められた非親告罪の範囲外のケースには対応できないことがあります" violationRightsOther_description: "他人の著作権、商標権、またはその他の権利を侵害する投稿及びなりすまし行為\n第三者による通報の場合、法律で定められた非親告罪の範囲外のケースには対応できないことがあります"
notLike: "この人が気に入らない" notLike: "この人が気に入らない"
notLike_description: "個人的な理由で不快と感じるユーザーや投稿" notLike_description: "個人的な理由で不快と感じるユーザーや投稿"
other: "その他" other: "その他"
@ -1533,9 +1512,9 @@ _achievements:
earnedAt: "獲得日時" earnedAt: "獲得日時"
_types: _types:
_notes1: _notes1:
title: "just setting up my forkey" title: "just setting up my msky"
description: "初めてノートを投稿した" description: "初めてノートを投稿した"
flavor: "良いForkeyライフを" flavor: "良いMisskeyライフを"
_notes10: _notes10:
title: "いくつかのノート" title: "いくつかのノート"
description: "ートを10回投稿した" description: "ートを10回投稿した"
@ -1631,7 +1610,7 @@ _achievements:
_login1000: _login1000:
title: "ノートマスターⅢ" title: "ノートマスターⅢ"
description: "通算ログイン日数が1,000日" description: "通算ログイン日数が1,000日"
flavor: "Forkeyを使ってくれてありがとう" flavor: "Misskeyを使ってくれてありがとう"
_noteClipped1: _noteClipped1:
title: "クリップせずにはいられないな" title: "クリップせずにはいられないな"
description: "初めてノートをクリップした" description: "初めてノートをクリップした"
@ -1691,9 +1670,9 @@ _achievements:
title: "実績好き" title: "実績好き"
description: "実績一覧を3分以上眺め続けた" description: "実績一覧を3分以上眺め続けた"
_iLoveMisskey: _iLoveMisskey:
title: "I Love Forkey" title: "I Love Misskey"
description: "\"I ❤ #Forkey\"を投稿した" description: "\"I ❤ #Misskey\"を投稿した"
flavor: "Forkeyを使ってくださりありがとうございます by 開発チーム" flavor: "Misskeyを使ってくださりありがとうございます by 開発チーム"
_foundTreasure: _foundTreasure:
title: "宝探し" title: "宝探し"
description: "隠されたお宝を発見した" description: "隠されたお宝を発見した"
@ -1772,7 +1751,7 @@ _achievements:
title: "テスト過剰" title: "テスト過剰"
description: "通知のテストをごく短時間のうちに連続して行った" description: "通知のテストをごく短時間のうちに連続して行った"
_tutorialCompleted: _tutorialCompleted:
title: "Forkey初心者講座 修了証" title: "Misskey初心者講座 修了証"
description: "チュートリアルを完了した" description: "チュートリアルを完了した"
_bubbleGameExplodingHead: _bubbleGameExplodingHead:
title: "🤯" title: "🤯"
@ -1824,9 +1803,6 @@ _role:
gtlAvailable: "グローバルタイムラインの閲覧" gtlAvailable: "グローバルタイムラインの閲覧"
ltlAvailable: "ローカルタイムラインの閲覧" ltlAvailable: "ローカルタイムラインの閲覧"
canPublicNote: "パブリック投稿の許可" canPublicNote: "パブリック投稿の許可"
canScheduleNote: "予約投稿の許可"
scheduleNoteLimit: "予約投稿の最大数"
scheduleNoteMaxDays: "予約投稿の最大日数"
canInitiateConversation: "メンション、リプライ、引用の許可" canInitiateConversation: "メンション、リプライ、引用の許可"
canCreateContent: "コンテンツの作成" canCreateContent: "コンテンツの作成"
canUpdateContent: "コンテンツの編集" canUpdateContent: "コンテンツの編集"
@ -1910,8 +1886,6 @@ _signup:
almostThere: "ほとんど完了です" almostThere: "ほとんど完了です"
emailAddressInfo: "あなたが使っているメールアドレスを入力してください。メールアドレスが公開されることはありません。" emailAddressInfo: "あなたが使っているメールアドレスを入力してください。メールアドレスが公開されることはありません。"
emailSent: "入力されたメールアドレス({email})宛に確認のメールが送信されました。メールに記載されたリンクにアクセスすると、アカウントの作成が完了します。メールに記載されているリンクの有効期限は30分です。" emailSent: "入力されたメールアドレス({email})宛に確認のメールが送信されました。メールに記載されたリンクにアクセスすると、アカウントの作成が完了します。メールに記載されているリンクの有効期限は30分です。"
approvalPending: "アカウントが作成され、承認待ちの状態です。"
reasonInfo: "インスタンスに参加したい理由を入力してください。"
_accountDelete: _accountDelete:
accountDelete: "アカウントの削除" accountDelete: "アカウントの削除"
@ -1987,19 +1961,13 @@ _aboutMisskey:
contributors: "コントリビューター" contributors: "コントリビューター"
allContributors: "全てのコントリビューター" allContributors: "全てのコントリビューター"
source: "ソースコード" source: "ソースコード"
original: "Misskeyオリジナル" original: "オリジナル"
thisIsModifiedVersion: "{name}はオリジナルのMisskeyを改変したバージョンを使用しています。" thisIsModifiedVersion: "{name}はオリジナルのMisskeyを改変したバージョンを使用しています。"
translation: "Misskeyを翻訳" translation: "Misskeyを翻訳"
donate: "Misskeyに寄付" donate: "Misskeyに寄付"
morePatrons: "他にも多くの方が支援してくれています。ありがとうございます🥰" morePatrons: "他にも多くの方が支援してくれています。ありがとうございます🥰"
patrons: "支援者" patrons: "支援者"
projectMembers: "Misskeyプロジェクトメンバー" projectMembers: "プロジェクトメンバー"
_aboutForkey:
about: "Forkey は、2014 年から syuilo によって開発されている Misskey をベースにしたオープンソース ソフトウェアです。"
original: "Forkeyに寄付"
projectMembers: "Forkeyプロジェクトメンバー"
_displayOfSensitiveMedia: _displayOfSensitiveMedia:
respect: "センシティブ設定されたメディアを隠す" respect: "センシティブ設定されたメディアを隠す"
@ -2404,8 +2372,7 @@ _postForm:
d: "言いたいことは?" d: "言いたいことは?"
e: "ここに書いてください" e: "ここに書いてください"
f: "あなたが書くのを待っています..." f: "あなたが書くのを待っています..."
policyScheduleNoteMaxDaysExceeded: "現在の支援プランで予約できる日数の上限は{max}日です。\n[ここ](https://go.misskey.io/donate)からプランをアップグレードできます。" guidelineInfo: "[NSFWガイドライン]({nsfwGuideUrl})を必ずお読みになってからご利用ください。"
tosAndGuidelinesInfo: "投稿する前に、[利用規約]({tosUrl})と[NSFWガイドライン](https://go.misskey.io/media-guideline)を必ずお読みください。"
_profile: _profile:
name: "名前" name: "名前"
@ -2431,7 +2398,7 @@ _profile:
sectionName: "セクション名" sectionName: "セクション名"
sectionNameNoneDescription: "セクション名を表示しないようにする" sectionNameNoneDescription: "セクション名を表示しないようにする"
sectionNameNone: "名前が表示されないセクション" sectionNameNone: "名前が表示されないセクション"
policyDisplayLimitExceeded: "現在の支援プランの表示上限({max}個)を超えているため、この項目は表示されません。\n[ここ](https://go.misskey.io/donate)からプランをアップグレードできます。" policyDisplayLimitExceeded: "現在の支援プランの表示上限({max}個)を超えているため、この項目は表示されません。[ここ](https://go.misskey.io/donate)からプランをアップグレードできます。"
_exportOrImport: _exportOrImport:
allNotes: "全てのノート" allNotes: "全てのノート"
@ -2573,9 +2540,6 @@ _notification:
roleAssigned: "ロールが付与されました" roleAssigned: "ロールが付与されました"
emptyPushNotificationMessage: "プッシュ通知の更新をしました" emptyPushNotificationMessage: "プッシュ通知の更新をしました"
achievementEarned: "実績を獲得" achievementEarned: "実績を獲得"
noteScheduled: "ノートが予約されました"
scheduledNotePosted: "予約済みのノートが投稿されました"
scheduledNoteError: "予約済みのノートを投稿できませんでした"
testNotification: "通知テスト" testNotification: "通知テスト"
checkNotificationBehavior: "通知の表示を確かめる" checkNotificationBehavior: "通知の表示を確かめる"
sendTestNotification: "テスト通知を送信する" sendTestNotification: "テスト通知を送信する"
@ -2600,9 +2564,6 @@ _notification:
followRequestAccepted: "フォローが受理された" followRequestAccepted: "フォローが受理された"
roleAssigned: "ロールが付与された" roleAssigned: "ロールが付与された"
achievementEarned: "実績の獲得" achievementEarned: "実績の獲得"
noteScheduled: "ノートが予約された"
scheduledNotePosted: "予約済みのノートが投稿された"
scheduledNoteError: "予約済みのノートが投稿できなかった"
app: "連携アプリからの通知" app: "連携アプリからの通知"
_actions: _actions:

View file

@ -1478,7 +1478,7 @@ _achievements:
_login1000: _login1000:
title: "ノートマイスターⅢ" title: "ノートマイスターⅢ"
description: "通算1,000日ログインした" description: "通算1,000日ログインした"
flavor: "Forkeyようさん使てもろておおきにな" flavor: "Misskeyようさん使てもろておおきにな"
_noteClipped1: _noteClipped1:
title: "アカンどれもクリップしたいわ" title: "アカンどれもクリップしたいわ"
description: "初めてノートをクリップした" description: "初めてノートをクリップした"
@ -1538,9 +1538,9 @@ _achievements:
title: "実績好き" title: "実績好き"
description: "実績一覧を3分以上眺め続けた" description: "実績一覧を3分以上眺め続けた"
_iLoveMisskey: _iLoveMisskey:
title: "Forkey好きやねん" title: "Misskey好きやねん"
description: "\"I ❤ #Forkey\"を投稿した" description: "\"I ❤ #Misskey\"を投稿した"
flavor: "Forkeyを使ってくれておおきにな by 開発チーム" flavor: "Misskeyを使ってくれておおきにな by 開発チーム"
_foundTreasure: _foundTreasure:
title: "なんでも鑑定団" title: "なんでも鑑定団"
description: "隠されたお宝を発見した" description: "隠されたお宝を発見した"
@ -1619,7 +1619,7 @@ _achievements:
title: "心配性" title: "心配性"
description: "通知のテストしすぎやって" description: "通知のテストしすぎやって"
_tutorialCompleted: _tutorialCompleted:
title: "Forkeyひよっこ講座 修了証" title: "Misskeyひよっこ講座 修了証"
description: "チュートリアル全部やった" description: "チュートリアル全部やった"
_bubbleGameExplodingHead: _bubbleGameExplodingHead:
title: "🤯" title: "🤯"

View file

@ -700,7 +700,7 @@ _achievements:
_myNoteFavorited1: _myNoteFavorited1:
description: "다런 사람이 내 노트럴 질겨찾기에 담앗십니다" description: "다런 사람이 내 노트럴 질겨찾기에 담앗십니다"
_iLoveMisskey: _iLoveMisskey:
description: "“I ❤ #Forkey”럴 섰어예" description: "“I ❤ #Misskey”럴 섰어예"
_postedAt0min0sec: _postedAt0min0sec:
description: "0분 0초에 노트를 섰어예" description: "0분 0초에 노트를 섰어예"
_tutorialCompleted: _tutorialCompleted:

View file

@ -1314,14 +1314,6 @@ consentAll: "모두 허용"
consentSelected: "선택한 항목만 허용" consentSelected: "선택한 항목만 허용"
emailAddressLogin: "이메일 주소로 로그인" emailAddressLogin: "이메일 주소로 로그인"
usernameLogin: "사용자명으로 로그인" usernameLogin: "사용자명으로 로그인"
autoloadDrafts: "글 작성 시 자동으로 임시 저장된 글 불러오기"
drafts: "임시 저장"
unsent: "미전송"
schedule: "예약"
scheduled: "예약됨"
unschedule: "예약 취소"
setScheduledTime: "예약 시간 설정"
willBePostedAt: "{x}에 게시됩니다"
_bubbleGame: _bubbleGame:
howToPlay: "설명" howToPlay: "설명"
@ -1362,8 +1354,8 @@ _abuseReportCategory:
otherBreach_description: "명확하게 분류되지 않는 기타 규약 위반 행위" otherBreach_description: "명확하게 분류되지 않는 기타 규약 위반 행위"
violationRights: "권리 침해 또는 사칭 (권리자 본인에 의한 신고)" violationRights: "권리 침해 또는 사칭 (권리자 본인에 의한 신고)"
violationRights_description: "권리자 본인의 저작권, 상표권 또는 기타 권리를 침해하는 게시물 및 사칭 행위" violationRights_description: "권리자 본인의 저작권, 상표권 또는 기타 권리를 침해하는 게시물 및 사칭 행위"
violationRightsOther: "권리 침해 (제3자에 의한 신고)" violationRightsOther: "권리 침해 또는 사칭 (제3자에 의한 신고)"
violationRightsOther_description: "타인의 저작권, 상표권 또는 기타 권리를 침해하는 행위\n제3자에 의한 신고의 경우, 법으로 정해진 비친고죄 범위 외의 사례에는 대응할 수 없습니다" violationRightsOther_description: "타인의 저작권, 상표권 또는 기타 권리를 침해하는 게시물 및 사칭 행위\n제3자에 의한 신고의 경우, 법으로 정해진 비친고죄 범위 외의 사례에는 대응할 수 없습니다"
notLike: "이 사람이 마음에 들지 않음" notLike: "이 사람이 마음에 들지 않음"
notLike_description: "개인적인 이유로 불쾌감을 느끼는 사용자나 게시물" notLike_description: "개인적인 이유로 불쾌감을 느끼는 사용자나 게시물"
other: "기타" other: "기타"
@ -1598,7 +1590,7 @@ _achievements:
_login1000: _login1000:
title: "노트 마스터 III" title: "노트 마스터 III"
description: "총 1,000일간 로그인했습니다" description: "총 1,000일간 로그인했습니다"
flavor: "Forkey를 사용해 주셔서 감사합니다!" flavor: "Misskey를 사용해 주셔서 감사합니다!"
_noteClipped1: _noteClipped1:
title: "클립할 수밖에 없었어" title: "클립할 수밖에 없었어"
description: "처음으로 노트를 클립했습니다" description: "처음으로 노트를 클립했습니다"
@ -1658,9 +1650,9 @@ _achievements:
title: "저 도전과제 좋아해요" title: "저 도전과제 좋아해요"
description: "도전 과제 목록을 3분 이상 쳐다봤습니다" description: "도전 과제 목록을 3분 이상 쳐다봤습니다"
_iLoveMisskey: _iLoveMisskey:
title: "I Love Forkey" title: "I Love Misskey"
description: "\"I ❤ #Forkey\"를 포스트했습니다" description: "\"I ❤ #Misskey\"를 포스트했습니다"
flavor: "Forkey를 이용해 주셔서 감사합니다! ― 개발 팀" flavor: "Misskey를 이용해 주셔서 감사합니다! ― 개발 팀"
_foundTreasure: _foundTreasure:
title: "보물찾기" title: "보물찾기"
description: "숨겨진 보물을 발견했습니다" description: "숨겨진 보물을 발견했습니다"
@ -1739,7 +1731,7 @@ _achievements:
title: "테스트 과잉" title: "테스트 과잉"
description: "매우 짧은 시간 안에 알림 테스트를 여러 번 수행했습니다" description: "매우 짧은 시간 안에 알림 테스트를 여러 번 수행했습니다"
_tutorialCompleted: _tutorialCompleted:
title: "Forkey 입문자 과정 수료증" title: "Misskey 입문자 과정 수료증"
description: "튜토리얼을 완료했습니다" description: "튜토리얼을 완료했습니다"
_bubbleGameExplodingHead: _bubbleGameExplodingHead:
title: "🤯" title: "🤯"
@ -1790,9 +1782,6 @@ _role:
gtlAvailable: "글로벌 타임라인 보이기" gtlAvailable: "글로벌 타임라인 보이기"
ltlAvailable: "로컬 타임라인 보이기" ltlAvailable: "로컬 타임라인 보이기"
canPublicNote: "공개 노트 허용" canPublicNote: "공개 노트 허용"
canScheduleNote: "노트 예약 허용"
scheduleNoteLimit: "노트 예약 한도"
scheduleNoteMaxDays: "노트 예약 최대 일수"
mentionMax: "노트에 넣을 수 있는 멘션 수" mentionMax: "노트에 넣을 수 있는 멘션 수"
canCreateContent: "컨텐츠 생성 허용" canCreateContent: "컨텐츠 생성 허용"
canUpdateContent: "컨텐츠 수정 허용" canUpdateContent: "컨텐츠 수정 허용"
@ -2312,8 +2301,6 @@ _postForm:
d: "말하고 싶은 게 있나요?" d: "말하고 싶은 게 있나요?"
e: "여기에 적어 주세요" e: "여기에 적어 주세요"
f: "글 쓰기를 기다려요…" f: "글 쓰기를 기다려요…"
policyScheduleNoteMaxDaysExceeded: "현재 지원 플랜의 예약 가능한 최대 일수는 {max}일입니다.\n[여기](https://go.misskey.io/donate)에서 플랜을 업그레이드할 수 있습니다."
tosAndGuidelinesInfo: "노트를 게시하기 전에 [이용약관]({tosUrl})과 [NSFW 가이드라인](https://go.misskey.io/media-guideline)을 반드시 읽어 주세요."
_profile: _profile:
name: "이름" name: "이름"
username: "사용자 이름" username: "사용자 이름"
@ -2338,7 +2325,7 @@ _profile:
sectionName: "섹션 이름" sectionName: "섹션 이름"
sectionNameNoneDescription: "섹션 이름이 표시되지 않도록 합니다" sectionNameNoneDescription: "섹션 이름이 표시되지 않도록 합니다"
sectionNameNone: "이름이 표시되지 않는 섹션" sectionNameNone: "이름이 표시되지 않는 섹션"
policyDisplayLimitExceeded: "현재 지원 플랜의 표시 제한({max}개)을 초과하였기 때문에 이 항목은 표시되지 않습니다.\n[여기](https://go.misskey.io/donate)에서 플랜을 업그레이드할 수 있습니다." policyDisplayLimitExceeded: "현재 지원 플랜의 표시 제한({max}개)을 초과하였기 때문에 이 항목은 표시되지 않습니다. [여기](https://go.misskey.io/donate)에서 플랜을 업그레이드할 수 있습니다."
_exportOrImport: _exportOrImport:
allNotes: "모든 노트" allNotes: "모든 노트"
favoritedNotes: "즐겨찾기한 노트" favoritedNotes: "즐겨찾기한 노트"
@ -2467,12 +2454,9 @@ _notification:
pollEnded: "투표 결과가 발표되었습니다" pollEnded: "투표 결과가 발표되었습니다"
newNote: "새 게시물" newNote: "새 게시물"
unreadAntennaNote: "안테나 {name}" unreadAntennaNote: "안테나 {name}"
roleAssigned: "역할이 부여 되었습니다" roleAssigned: "역할이 부여 되었습니다."
emptyPushNotificationMessage: "푸시 알림이 갱신되었습니다" emptyPushNotificationMessage: "푸시 알림이 갱신되었습니다"
achievementEarned: "도전 과제를 달성했습니다" achievementEarned: "도전 과제를 달성했습니다"
noteScheduled: "노트가 예약되었습니다"
scheduledNotePosted: "예약된 노트가 게시되었습니다"
scheduledNoteError: "예약된 노트를 게시하지 못했습니다"
testNotification: "알림 테스트" testNotification: "알림 테스트"
checkNotificationBehavior: "알림 표시를 체크하기" checkNotificationBehavior: "알림 표시를 체크하기"
sendTestNotification: "테스트 알림 보내기" sendTestNotification: "테스트 알림 보내기"
@ -2496,9 +2480,6 @@ _notification:
followRequestAccepted: "팔로우 요청이 승인되었을 때" followRequestAccepted: "팔로우 요청이 승인되었을 때"
roleAssigned: "역할이 부여 됨" roleAssigned: "역할이 부여 됨"
achievementEarned: "도전 과제 획득" achievementEarned: "도전 과제 획득"
noteScheduled: "노트가 예약됨"
scheduledNotePosted: "예약된 노트가 게시됨"
scheduledNoteError: "예약된 노트를 게시하지 못함"
app: "연동된 앱을 통한 알림" app: "연동된 앱을 통한 알림"
_actions: _actions:
followBack: "팔로우" followBack: "팔로우"

View file

@ -127,7 +127,7 @@ emojis: "Emojier"
addEmoji: "Legg til emoji" addEmoji: "Legg til emoji"
settingGuide: "Anbefalte innstillinger" settingGuide: "Anbefalte innstillinger"
flagAsBot: "Merk denne kontoen som en bot" flagAsBot: "Merk denne kontoen som en bot"
flagAsBotDescription: "Aktiver dette alternativet hvis denne kontoen styres av et program. Hvis det er aktivert, vil det fungere som et flagg for andre utviklere for å forhindre endeløse interaksjonskjeder med andre roboter og justere forkeys interne systemer til å behandle denne kontoen som en bot." flagAsBotDescription: "Aktiver dette alternativet hvis denne kontoen styres av et program. Hvis det er aktivert, vil det fungere som et flagg for andre utviklere for å forhindre endeløse interaksjonskjeder med andre roboter og justere Misskeys interne systemer til å behandle denne kontoen som en bot."
flagAsCat: "Merk denne kontoen som en katt" flagAsCat: "Merk denne kontoen som en katt"
flagAsCatDescription: "Aktiver dette alternativet for å merke denne kontoen som en katt." flagAsCatDescription: "Aktiver dette alternativet for å merke denne kontoen som en katt."
flagShowTimelineReplies: "Vis svar i tidslinje" flagShowTimelineReplies: "Vis svar i tidslinje"

View file

@ -1125,7 +1125,7 @@ _achievements:
_login1000: _login1000:
title: "Mestre das notas III" title: "Mestre das notas III"
description: "Fez login por um total de 1000 dias" description: "Fez login por um total de 1000 dias"
flavor: "Obrigado por utilizar o Forkey!" flavor: "Obrigado por utilizar o Misskey!"
_noteClipped1: _noteClipped1:
title: "Não posso deixar de adicionar ao clipe" title: "Não posso deixar de adicionar ao clipe"
description: "Adicionou a um clipe a sua primeira nota" description: "Adicionou a um clipe a sua primeira nota"

View file

@ -1219,7 +1219,7 @@ _achievements:
_login1000: _login1000:
title: "Повелитель заметок Ⅲ" title: "Повелитель заметок Ⅲ"
description: "1000 дней на сайте" description: "1000 дней на сайте"
flavor: "Спасибо, что пользуетесь Forkey!" flavor: "Спасибо, что пользуетесь Misskey!"
_noteClipped1: _noteClipped1:
title: "Нельзя не сохранить" title: "Нельзя не сохранить"
description: "Первая заметка в подборке" description: "Первая заметка в подборке"
@ -1279,9 +1279,9 @@ _achievements:
title: "Любовь к успехам" title: "Любовь к успехам"
description: "Более 3 минут любования достижениями" description: "Более 3 минут любования достижениями"
_iLoveMisskey: _iLoveMisskey:
title: "Я люблю Forkey" title: "Я люблю Misskey"
description: "Написана заметка «I ❤ #Forkey»" description: "Написана заметка «I ❤ #Misskey»"
flavor: "Спасибо за поддержку Forkey! Ваша команда разработчиков" flavor: "Спасибо за поддержку Misskey! Ваша команда разработчиков"
_foundTreasure: _foundTreasure:
title: "Охота за сокровищами" title: "Охота за сокровищами"
description: "Найдено спрятанное сокровище" description: "Найдено спрятанное сокровище"

View file

@ -152,7 +152,7 @@ settingGuide: "Rekommenderade inställningar"
cacheRemoteFiles: "Spara externa filer till cachen" cacheRemoteFiles: "Spara externa filer till cachen"
cacheRemoteFilesDescription: "När denna inställning är avstängd kommer externa filer laddas direkt från den externa instansen. Genom att stänga av detta kommer lagringsutrymme minska i användning men kommer öka datatrafiken eftersom miniatyrer inte kommer genereras." cacheRemoteFilesDescription: "När denna inställning är avstängd kommer externa filer laddas direkt från den externa instansen. Genom att stänga av detta kommer lagringsutrymme minska i användning men kommer öka datatrafiken eftersom miniatyrer inte kommer genereras."
flagAsBot: "Markera konto som bot" flagAsBot: "Markera konto som bot"
flagAsBotDescription: "Aktivera det här alternativet om kontot är kontrollerat av ett program. Om aktiverat kommer den fungera som en flagga för andra utvecklare för att hindra ändlösa kedjor med andra bottar. Det kommer också få forkeys interna system att hantera kontot som en bot." flagAsBotDescription: "Aktivera det här alternativet om kontot är kontrollerat av ett program. Om aktiverat kommer den fungera som en flagga för andra utvecklare för att hindra ändlösa kedjor med andra bottar. Det kommer också få Misskeys interna system att hantera kontot som en bot."
flagAsCat: "Markera konto som katt" flagAsCat: "Markera konto som katt"
flagAsCatDescription: "Aktivera denna inställning för att markera kontot som en katt." flagAsCatDescription: "Aktivera denna inställning för att markera kontot som en katt."
flagShowTimelineReplies: "Visa svar i tidslinje" flagShowTimelineReplies: "Visa svar i tidslinje"

View file

@ -1380,9 +1380,9 @@ _achievements:
earnedAt: "ได้รับเมื่อ" earnedAt: "ได้รับเมื่อ"
_types: _types:
_notes1: _notes1:
title: "just setting up my forkey" title: "just setting up my msky"
description: "โพสต์โน้ตแรกของคุณ" description: "โพสต์โน้ตแรกของคุณ"
flavor: "ขอให้มีช่วงเวลาที่ดีกับ Forkey นะคะ!" flavor: "ขอให้มีช่วงเวลาที่ดีกับ Misskey นะคะ!"
_notes10: _notes10:
title: "โน้ตไม่กี่ชิ้น" title: "โน้ตไม่กี่ชิ้น"
description: "โพสต์ 10 โน้ต" description: "โพสต์ 10 โน้ต"
@ -1478,7 +1478,7 @@ _achievements:
_login1000: _login1000:
title: "ปรมาจารย์ด้านโน้ต III" title: "ปรมาจารย์ด้านโน้ต III"
description: "เข้าสู่ระบบเป็นเวลารวม 1,000 วัน" description: "เข้าสู่ระบบเป็นเวลารวม 1,000 วัน"
flavor: "ขอบคุณที่ใช้ Forkey นะ !" flavor: "ขอบคุณที่ใช้ Misskey นะ !"
_noteClipped1: _noteClipped1:
title: "อดไม่ได้ที่จะต้องคลิปมันเอาไว้" title: "อดไม่ได้ที่จะต้องคลิปมันเอาไว้"
description: "คลิปโน้ตตัวแรกของคุณ" description: "คลิปโน้ตตัวแรกของคุณ"
@ -1538,9 +1538,9 @@ _achievements:
title: "ชอบบรรลุความสําเร็จ" title: "ชอบบรรลุความสําเร็จ"
description: "มองดูรายการความสำเร็จของคุณเป็นเวลาอย่างน้อย 3 นาที" description: "มองดูรายการความสำเร็จของคุณเป็นเวลาอย่างน้อย 3 นาที"
_iLoveMisskey: _iLoveMisskey:
title: "ฉันรัก Forkey" title: "ฉันรัก Misskey"
description: "โพสต์ “I ❤ #Forkey”" description: "โพสต์ “I ❤ #Misskey”"
flavor: "ขอบคุณพระคุณเป็นอย่างสูงที่ท่านใช้ Forkey นะคะ ! by ทีมผู้พัฒนา" flavor: "ขอบคุณพระคุณเป็นอย่างสูงที่ท่านใช้ Misskey นะคะ ! by ทีมผู้พัฒนา"
_foundTreasure: _foundTreasure:
title: "ล่าสมบัติ" title: "ล่าสมบัติ"
description: "คุณพบสมบัติที่ซ่อนอยู่" description: "คุณพบสมบัติที่ซ่อนอยู่"
@ -1619,7 +1619,7 @@ _achievements:
title: "ทดสอบโอเวอร์โฟลว์" title: "ทดสอบโอเวอร์โฟลว์"
description: "ทดสอบการแจ้งเตือนทริกเกอร์ซ้ำๆ ภายในระยะเวลาอันสั้นๆ" description: "ทดสอบการแจ้งเตือนทริกเกอร์ซ้ำๆ ภายในระยะเวลาอันสั้นๆ"
_tutorialCompleted: _tutorialCompleted:
title: "ใบรับรองการสำเร็จหลักสูตร Forkey มือใหม่" title: "ใบรับรองการสำเร็จหลักสูตร Misskey มือใหม่"
description: "เสร็จสิ้นการสอนแล้ว" description: "เสร็จสิ้นการสอนแล้ว"
_bubbleGameExplodingHead: _bubbleGameExplodingHead:
title: "🤯" title: "🤯"

View file

@ -1017,7 +1017,7 @@ _achievements:
_login1000: _login1000:
title: "Майстер нотаток III" title: "Майстер нотаток III"
description: "1000 днів користування загально" description: "1000 днів користування загально"
flavor: "Дякуємо, що користуєтеся Forkey!" flavor: "Дякуємо, що користуєтеся Misskey!"
_noteClipped1: _noteClipped1:
title: "Не можна не зберегти" title: "Не можна не зберегти"
description: "Перша нотатка у добірці" description: "Перша нотатка у добірці"
@ -1072,9 +1072,9 @@ _achievements:
title: "Шанувальник досягнень" title: "Шанувальник досягнень"
description: "Переглядати список досягнень принаймні 3 хвилини" description: "Переглядати список досягнень принаймні 3 хвилини"
_iLoveMisskey: _iLoveMisskey:
title: "I Love Forkey" title: "I Love Misskey"
description: "Відправлено \"I ❤ #Forkey\"" description: "Відправлено \"I ❤ #Misskey\""
flavor: "Дякуємо вам, що користуєтесь Forkey! команда розробників" flavor: "Дякуємо вам, що користуєтесь Misskey! команда розробників"
_foundTreasure: _foundTreasure:
title: "Пошуки скарбів" title: "Пошуки скарбів"
description: "Ви знайшли прихований скарб" description: "Ви знайшли прихований скарб"

View file

@ -1157,9 +1157,9 @@ _achievements:
earnedAt: "Ngày thu nhận" earnedAt: "Ngày thu nhận"
_types: _types:
_notes1: _notes1:
title: "just setting up my forkey" title: "just setting up my msky"
description: "Lần đầu tiên đăng bài" description: "Lần đầu tiên đăng bài"
flavor: "Chúc bạn trên Forkey vui vẻ nha!!" flavor: "Chúc bạn trên Miskey vui vẻ nha!!"
_notes10: _notes10:
title: "Một số bài viết" title: "Một số bài viết"
description: "Đăng bài 10 lần" description: "Đăng bài 10 lần"
@ -1225,7 +1225,7 @@ _achievements:
title: "Khách hàng thường xuyên cấp III" title: "Khách hàng thường xuyên cấp III"
description: "Tổng số ngày đăng nhập đạt 400 ngày" description: "Tổng số ngày đăng nhập đạt 400 ngày"
_login1000: _login1000:
flavor: "Cảm ơn bạn đã sử dụng Forkey!" flavor: "Cảm ơn bạn đã sử dụng Misskey!"
_noteFavorited1: _noteFavorited1:
title: "Nhà thiên văn học" title: "Nhà thiên văn học"
_myNoteFavorited1: _myNoteFavorited1:
@ -1280,9 +1280,9 @@ _achievements:
title: "Yêu Thành tích" title: "Yêu Thành tích"
description: "Ngắm danh sách thành tích đến tận hơn 3 phút" description: "Ngắm danh sách thành tích đến tận hơn 3 phút"
_iLoveMisskey: _iLoveMisskey:
title: "Tôi Yêu Forkey" title: "Tôi Yêu Misskey"
description: "Đăng lời nói \"I ❤ #Forkey\"" description: "Đăng lời nói \"I ❤ #Misskey\""
flavor: "Xin chân thành cảm ơn bạn đã sử dụng Forkey!! by Đội ngũ phát triển" flavor: "Xin chân thành cảm ơn bạn đã sử dụng Misskey!! by Đội ngũ phát triển"
_foundTreasure: _foundTreasure:
title: "Tìm kiếm kho báu" title: "Tìm kiếm kho báu"
description: "Tìm thấy được những kho báu cất giấu" description: "Tìm thấy được những kho báu cất giấu"

View file

@ -1499,7 +1499,7 @@ _achievements:
_login1000: _login1000:
title: "帖子大师 Ⅲ" title: "帖子大师 Ⅲ"
description: "累计登录 1000 天" description: "累计登录 1000 天"
flavor: "感谢您使用 Forkey" flavor: "感谢您使用 Misskey"
_noteClipped1: _noteClipped1:
title: "忍不住要收藏到便签" title: "忍不住要收藏到便签"
description: "第一次将贴文贴进便签" description: "第一次将贴文贴进便签"
@ -1559,9 +1559,9 @@ _achievements:
title: "成就爱好者" title: "成就爱好者"
description: "盯着成就看三分钟" description: "盯着成就看三分钟"
_iLoveMisskey: _iLoveMisskey:
title: "I Love Forkey" title: "I Love Misskey"
description: "发布 \"I ❤ #Forkey\" 帖子" description: "发布 \"I ❤ #Misskey\" 帖子"
flavor: "感谢您使用 Forkey by 开发团队" flavor: "感谢您使用 Misskey by 开发团队"
_foundTreasure: _foundTreasure:
title: "寻宝" title: "寻宝"
description: "发现了隐藏的宝藏" description: "发现了隐藏的宝藏"
@ -1640,7 +1640,7 @@ _achievements:
title: "过度测试" title: "过度测试"
description: "短时间内连续测试通知" description: "短时间内连续测试通知"
_tutorialCompleted: _tutorialCompleted:
title: "Forkey 初学者课程 结业证书" title: "Misskey 初学者课程 结业证书"
description: "完成了教学" description: "完成了教学"
_bubbleGameExplodingHead: _bubbleGameExplodingHead:
title: "🤯" title: "🤯"

View file

@ -1478,7 +1478,7 @@ _achievements:
_login1000: _login1000:
title: "貼文大師ⅠⅠⅠ" title: "貼文大師ⅠⅠⅠ"
description: "總登入天數為一千天" description: "總登入天數為一千天"
flavor: "感謝您使用 Forkey" flavor: "感謝您使用 Misskey"
_noteClipped1: _noteClipped1:
title: "忍不住要收進摘錄裡" title: "忍不住要收進摘錄裡"
description: "第一次將貼文收進摘錄" description: "第一次將貼文收進摘錄"
@ -1540,7 +1540,7 @@ _achievements:
_iLoveMisskey: _iLoveMisskey:
title: "I Love Misskey" title: "I Love Misskey"
description: "發佈「I ❤ #Misskey」" description: "發佈「I ❤ #Misskey」"
flavor: "感謝您使用 Forkeyby 開發團隊" flavor: "感謝您使用 Misskeyby 開發團隊"
_foundTreasure: _foundTreasure:
title: "尋寶" title: "尋寶"
description: "發現了隱藏的寶藏" description: "發現了隱藏的寶藏"
@ -1619,7 +1619,7 @@ _achievements:
title: "過度測試" title: "過度測試"
description: "極短時間內連續測試通知" description: "極短時間內連續測試通知"
_tutorialCompleted: _tutorialCompleted:
title: "Forkey新手講座 結業證書" title: "Misskey新手講座 結業證書"
description: "已完成教學課程" description: "已完成教學課程"
_bubbleGameExplodingHead: _bubbleGameExplodingHead:
title: "🤯" title: "🤯"

View file

@ -1,12 +1,12 @@
{ {
"name": "forkey", "name": "misskey",
"version": "2024.5.0-io.7c", "version": "2024.5.0-io.5e",
"codename": "nasubi", "codename": "nasubi",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://git.woem.men/woem.men/forkey.git" "url": "https://github.com/MisskeyIO/misskey.git"
}, },
"packageManager": "pnpm@9.15.4", "packageManager": "pnpm@9.15.0",
"workspaces": [ "workspaces": [
"packages/frontend", "packages/frontend",
"packages/backend", "packages/backend",
@ -56,26 +56,26 @@
"jpeg-js": "0.4.4", "jpeg-js": "0.4.4",
"lodash": "4.17.21", "lodash": "4.17.21",
"sharp": "0.33.5", "sharp": "0.33.5",
"tough-cookie": "5.1.0", "tough-cookie": "5.0.0",
"web-streams-polyfill": "4.1.0" "web-streams-polyfill": "4.0.0"
}, },
"dependencies": { "dependencies": {
"cssnano": "7.0.6", "cssnano": "7.0.6",
"execa": "9.5.2", "execa": "9.5.2",
"js-yaml": "4.1.0", "js-yaml": "4.1.0",
"postcss": "8.5.1", "postcss": "8.4.49",
"terser": "5.37.0", "terser": "5.37.0",
"typescript": "5.7.3" "typescript": "5.7.2"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "22.10.7", "@types/node": "22.10.2",
"@typescript-eslint/eslint-plugin": "7.10.0", "@typescript-eslint/eslint-plugin": "7.10.0",
"@typescript-eslint/parser": "7.10.0", "@typescript-eslint/parser": "7.10.0",
"cross-env": "7.0.3", "cross-env": "7.0.3",
"cypress": "13.17.0", "cypress": "13.17.0",
"eslint": "8.57.1", "eslint": "8.57.1",
"ncp": "2.0.0", "ncp": "2.0.0",
"start-server-and-test": "2.0.10" "start-server-and-test": "2.0.9"
}, },
"optionalDependencies": { "optionalDependencies": {
"@tensorflow/tfjs-core": "4.22.0" "@tensorflow/tfjs-core": "4.22.0"

View file

@ -1,7 +1,7 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>Forkey API</title> <title>Misskey API</title>
<!-- needed for adaptive design --> <!-- needed for adaptive design -->
<meta charset="utf-8"/> <meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 B

View file

@ -1,12 +0,0 @@
export class SpeakAsCat1696386694000 {
name = "SpeakAsCat1696386694000";
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "user" ADD "speakAsCat" boolean NOT NULL DEFAULT true`);
await queryRunner.query(`COMMENT ON COLUMN "user"."speakAsCat" IS 'Whether to speak as a cat if chosen.'`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "speakAsCat"`);
}
}

View file

@ -1,20 +0,0 @@
/*
* SPDX-FileCopyrightText: marie and other Sharkey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class friendlyCaptcha1730505338000 {
name = 'friendlyCaptcha1730505338000';
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" ADD "enableFC" boolean NOT NULL DEFAULT false`, undefined);
await queryRunner.query(`ALTER TABLE "meta" ADD "fcSiteKey" character varying(1024)`, undefined);
await queryRunner.query(`ALTER TABLE "meta" ADD "fcSecretKey" character varying(1024)`, undefined);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "fcSecretKey"`, undefined);
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "fcSiteKey"`, undefined);
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "enableFC"`, undefined);
}
}

View file

@ -1,22 +0,0 @@
/*
* SPDX-FileCopyrightText: syuilo and other misskey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class ApprovalSignup1697580470000 {
name = 'ApprovalSignup1697580470000'
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" ADD "approvalRequiredForSignup" boolean DEFAULT false NOT NULL`);
await queryRunner.query(`ALTER TABLE "user" ADD "approved" boolean DEFAULT true NOT NULL`);
await queryRunner.query(`ALTER TABLE "user" ADD "signupReason" character varying(1000) NULL`);
await queryRunner.query(`ALTER TABLE "user_pending" ADD "reason" character varying(1000) NULL`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "approvalRequiredForSignup"`);
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "approved"`);
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "signupReason"`);
await queryRunner.query(`ALTER TABLE "user_pending" DROP COLUMN "reason"`);
}
}

View file

@ -1,18 +0,0 @@
export class MastodonOauth1736599563231 {
name = 'MastodonOauth1736599563231'
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "app" ADD "website" character varying(128)`);
await queryRunner.query(`COMMENT ON COLUMN "app"."website" IS 'Application website.'`);
await queryRunner.query(`ALTER TABLE "app" ADD "mastodonScopes" character varying(64) array`);
await queryRunner.query(`COMMENT ON COLUMN "app"."mastodonScopes" IS 'Mastodon app scopes, only set for apps created with Mastodon API.'`);
await queryRunner.query(`ALTER TABLE "app" ADD "redirectUris" character varying(512) array DEFAULT '{}' NOT NULL`);
await queryRunner.query(`COMMENT ON COLUMN "app"."redirectUris" IS 'Redirect URIs.'`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "app" DROP COLUMN "website"`);
await queryRunner.query(`ALTER TABLE "app" DROP COLUMN "mastodonScopes"`);
await queryRunner.query(`ALTER TABLE "app" DROP COLUMN "redirectUris"`);
}
}

View file

@ -1,11 +0,0 @@
export class NoteUserIdIdIndex1736888704471 {
name = 'NoteUserIdIdIndex1736888704471'
async up(queryRunner) {
await queryRunner.query(`CREATE INDEX "IDX_note_userId_id" ON "note" ("userId", "id") `);
}
async down(queryRunner) {
await queryRunner.query(`DROP INDEX "public"."IDX_note_userId_id"`);
}
}

View file

@ -1,21 +0,0 @@
export class ScheduledNote1736923279563 {
name = 'ScheduledNote1736923279563'
async up(queryRunner) {
await queryRunner.query(`CREATE TABLE "note_scheduled" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "scheduledAt" TIMESTAMP WITH TIME ZONE, "reason" character varying(256), "userId" character varying(32) NOT NULL, "draft" jsonb NOT NULL, CONSTRAINT "PK_14ca8fa67f70dc68ebab8900f4b" PRIMARY KEY ("id")); COMMENT ON COLUMN "note_scheduled"."createdAt" IS 'The created date of the Note.'; COMMENT ON COLUMN "note_scheduled"."scheduledAt" IS 'The scheduled date of the Note.'; COMMENT ON COLUMN "note_scheduled"."userId" IS 'The ID of author.'`);
await queryRunner.query(`CREATE INDEX "IDX_7ddf8710a9faee81081592ec35" ON "note_scheduled" ("createdAt") `);
await queryRunner.query(`CREATE INDEX "IDX_bbe52891059217fc31e73e84e2" ON "note_scheduled" ("scheduledAt") `);
await queryRunner.query(`CREATE INDEX "IDX_b148b24837cc7a2707ae1f0975" ON "note_scheduled" ("userId") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_dfeab22d6bbc4799193997553a" ON "note_scheduled" ("userId", "scheduledAt") `);
await queryRunner.query(`ALTER TABLE "note_scheduled" ADD CONSTRAINT "FK_b148b24837cc7a2707ae1f0975a" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "note_scheduled" DROP CONSTRAINT "FK_b148b24837cc7a2707ae1f0975a"`);
await queryRunner.query(`DROP INDEX "public"."IDX_dfeab22d6bbc4799193997553a"`);
await queryRunner.query(`DROP INDEX "public"."IDX_b148b24837cc7a2707ae1f0975"`);
await queryRunner.query(`DROP INDEX "public"."IDX_bbe52891059217fc31e73e84e2"`);
await queryRunner.query(`DROP INDEX "public"."IDX_7ddf8710a9faee81081592ec35"`);
await queryRunner.query(`DROP TABLE "note_scheduled"`);
}
}

View file

@ -33,16 +33,16 @@
"generate-api-json": "pnpm build && node ./scripts/generate_api_json.js" "generate-api-json": "pnpm build && node ./scripts/generate_api_json.js"
}, },
"optionalDependencies": { "optionalDependencies": {
"@swc/core-darwin-arm64": "1.10.7", "@swc/core-darwin-arm64": "1.10.3",
"@swc/core-darwin-x64": "1.10.7", "@swc/core-darwin-x64": "1.10.3",
"@swc/core-linux-arm-gnueabihf": "1.10.7", "@swc/core-linux-arm-gnueabihf": "1.10.3",
"@swc/core-linux-arm64-gnu": "1.10.7", "@swc/core-linux-arm64-gnu": "1.10.3",
"@swc/core-linux-arm64-musl": "1.10.7", "@swc/core-linux-arm64-musl": "1.10.3",
"@swc/core-linux-x64-gnu": "1.10.7", "@swc/core-linux-x64-gnu": "1.10.3",
"@swc/core-linux-x64-musl": "1.10.7", "@swc/core-linux-x64-musl": "1.10.3",
"@swc/core-win32-arm64-msvc": "1.10.7", "@swc/core-win32-arm64-msvc": "1.10.3",
"@swc/core-win32-ia32-msvc": "1.10.7", "@swc/core-win32-ia32-msvc": "1.10.3",
"@swc/core-win32-x64-msvc": "1.10.7", "@swc/core-win32-x64-msvc": "1.10.3",
"@tensorflow/tfjs": "4.22.0", "@tensorflow/tfjs": "4.22.0",
"@tensorflow/tfjs-node": "4.22.0", "@tensorflow/tfjs-node": "4.22.0",
"bufferutil": "4.0.9", "bufferutil": "4.0.9",
@ -63,22 +63,22 @@
}, },
"dependencies": { "dependencies": {
"@authenio/samlify-node-xmllint": "2.0.0", "@authenio/samlify-node-xmllint": "2.0.0",
"@aws-sdk/client-s3": "3.729.0", "@aws-sdk/client-s3": "3.717.0",
"@aws-sdk/lib-storage": "3.729.0", "@aws-sdk/lib-storage": "3.717.0",
"@bull-board/api": "6.6.2", "@bull-board/api": "6.5.4",
"@bull-board/fastify": "6.6.2", "@bull-board/fastify": "6.5.4",
"@bull-board/ui": "6.6.2", "@bull-board/ui": "6.5.4",
"@discordapp/twemoji": "15.1.0", "@discordapp/twemoji": "15.1.0",
"@elastic/elasticsearch": "8.17.0", "@elastic/elasticsearch": "8.17.0",
"@fastify/accepts": "5.0.2", "@fastify/accepts": "5.0.2",
"@fastify/cookie": "11.0.2", "@fastify/cookie": "11.0.1",
"@fastify/cors": "10.0.2", "@fastify/cors": "10.0.1",
"@fastify/express": "4.0.2", "@fastify/express": "4.0.1",
"@fastify/formbody": "8.0.2", "@fastify/formbody": "8.0.1",
"@fastify/http-proxy": "11.0.1", "@fastify/http-proxy": "11.0.0",
"@fastify/multipart": "9.0.2", "@fastify/multipart": "9.0.1",
"@fastify/static": "8.0.4", "@fastify/static": "8.0.3",
"@fastify/view": "10.0.2", "@fastify/view": "10.0.1",
"@misskey-dev/sharp-read-bmp": "1.2.0", "@misskey-dev/sharp-read-bmp": "1.2.0",
"@misskey-dev/summaly": "github:MisskeyIO/summaly#5.1.3", "@misskey-dev/summaly": "github:MisskeyIO/summaly#5.1.3",
"@napi-rs/canvas": "0.1.65", "@napi-rs/canvas": "0.1.65",
@ -86,11 +86,11 @@
"@nestjs/core": "10.4.15", "@nestjs/core": "10.4.15",
"@nestjs/testing": "10.4.15", "@nestjs/testing": "10.4.15",
"@peertube/http-signature": "1.7.0", "@peertube/http-signature": "1.7.0",
"@simplewebauthn/server": "13.1.0", "@simplewebauthn/server": "13.0.0",
"@sinonjs/fake-timers": "11.3.1", "@sinonjs/fake-timers": "11.3.1",
"@smithy/node-http-handler": "4.0.2", "@smithy/node-http-handler": "3.3.3",
"@swc/cli": "0.6.0", "@swc/cli": "0.5.2",
"@swc/core": "1.10.7", "@swc/core": "1.10.3",
"@twemoji/parser": "15.1.1", "@twemoji/parser": "15.1.1",
"accepts": "1.3.8", "accepts": "1.3.8",
"ajv": "8.17.1", "ajv": "8.17.1",
@ -99,7 +99,7 @@
"bcryptjs": "2.4.3", "bcryptjs": "2.4.3",
"blurhash": "2.0.5", "blurhash": "2.0.5",
"body-parser": "1.20.3", "body-parser": "1.20.3",
"bullmq": "5.34.10", "bullmq": "5.34.5",
"cacheable-lookup": "7.0.0", "cacheable-lookup": "7.0.0",
"cbor": "10.0.3", "cbor": "10.0.3",
"chalk": "5.4.1", "chalk": "5.4.1",
@ -110,11 +110,11 @@
"content-disposition": "0.5.4", "content-disposition": "0.5.4",
"date-fns": "4.1.0", "date-fns": "4.1.0",
"deep-email-validator": "0.1.21", "deep-email-validator": "0.1.21",
"fastify": "5.2.1", "fastify": "5.2.0",
"fastify-http-errors-enhanced": "6.0.1", "fastify-http-errors-enhanced": "6.0.0",
"fastify-raw-body": "5.0.0", "fastify-raw-body": "5.0.0",
"feed": "4.2.2", "feed": "4.2.2",
"file-type": "20.0.0", "file-type": "19.6.0",
"fluent-ffmpeg": "2.1.3", "fluent-ffmpeg": "2.1.3",
"form-data": "4.0.1", "form-data": "4.0.1",
"got": "14.4.5", "got": "14.4.5",
@ -127,11 +127,11 @@
"is-svg": "5.1.0", "is-svg": "5.1.0",
"jose": "5.9.6", "jose": "5.9.6",
"js-yaml": "4.1.0", "js-yaml": "4.1.0",
"jsdom": "26.0.0", "jsdom": "25.0.1",
"json5": "2.2.3", "json5": "2.2.3",
"jsonld": "8.3.3", "jsonld": "8.3.3",
"jsrsasign": "11.1.0", "jsrsasign": "11.1.0",
"meilisearch": "0.48.0", "meilisearch": "0.47.0",
"mfm-js": "0.24.0", "mfm-js": "0.24.0",
"microformats-parser": "2.0.2", "microformats-parser": "2.0.2",
"mime-types": "2.1.35", "mime-types": "2.1.35",
@ -163,24 +163,25 @@
"random-seed": "0.3.0", "random-seed": "0.3.0",
"ratelimiter": "3.4.1", "ratelimiter": "3.4.1",
"re2": "1.21.4", "re2": "1.21.4",
"redis-lock": "0.1.4",
"reflect-metadata": "0.2.2", "reflect-metadata": "0.2.2",
"rename": "1.0.4", "rename": "1.0.4",
"rss-parser": "3.13.0", "rss-parser": "3.13.0",
"rxjs": "7.8.1", "rxjs": "7.8.1",
"samlify": "2.8.11", "samlify": "2.8.11",
"sanitize-html": "2.14.0", "sanitize-html": "2.14.0",
"secure-json-parse": "3.0.2", "secure-json-parse": "3.0.1",
"sharp": "0.33.5", "sharp": "0.33.5",
"slacc": "0.0.10", "slacc": "0.0.10",
"strict-event-emitter-types": "2.0.0", "strict-event-emitter-types": "2.0.0",
"stringz": "2.1.0", "stringz": "2.1.0",
"systeminformation": "5.25.11", "systeminformation": "5.23.23",
"tinycolor2": "1.6.0", "tinycolor2": "1.6.0",
"tmp": "0.2.3", "tmp": "0.2.3",
"tsc-alias": "1.8.10", "tsc-alias": "1.8.10",
"tsconfig-paths": "4.2.0", "tsconfig-paths": "4.2.0",
"typeorm": "0.3.20", "typeorm": "0.3.20",
"typescript": "5.7.3", "typescript": "5.7.2",
"ulid": "2.3.0", "ulid": "2.3.0",
"vary": "1.1.2", "vary": "1.1.2",
"web-push": "3.6.7", "web-push": "3.6.7",
@ -209,7 +210,7 @@
"@types/jsrsasign": "10.5.15", "@types/jsrsasign": "10.5.15",
"@types/mime-types": "2.1.4", "@types/mime-types": "2.1.4",
"@types/ms": "0.7.34", "@types/ms": "0.7.34",
"@types/node": "22.10.7", "@types/node": "22.10.2",
"@types/node-forge": "1.3.11", "@types/node-forge": "1.3.11",
"@types/nodemailer": "6.4.17", "@types/nodemailer": "6.4.17",
"@types/oauth": "0.9.6", "@types/oauth": "0.9.6",

View file

@ -0,0 +1,13 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare module 'redis-lock' {
import type Redis from 'ioredis';
type Lock = (lockName: string, timeout?: number, taskToPerform?: () => Promise<void>) => void;
function redisLock(client: Redis.Redis, retryDelay: number): Lock;
export = redisLock;
}

View file

@ -19,7 +19,7 @@ import { workerMain } from './worker.js';
import 'reflect-metadata'; import 'reflect-metadata';
process.title = `Forkey (${cluster.isPrimary ? 'master' : 'worker'})`; process.title = `Misskey (${cluster.isPrimary ? 'master' : 'worker'})`;
Error.stackTraceLimit = Infinity; Error.stackTraceLimit = Infinity;
EventEmitter.defaultMaxListeners = 128; EventEmitter.defaultMaxListeners = 128;

View file

@ -28,25 +28,24 @@ const themeColor = chalk.hex('#86b300');
function greet() { function greet() {
if (!envOption.quiet && !envOption.logJson) { if (!envOption.quiet && !envOption.logJson) {
//#region Forkey logo //#region Misskey logo
const v = `v${meta.version}`; const v = `v${meta.version}`;
console.log(themeColor('███████╗░█████╗░██████╗░██╗░░██╗███████╗██╗░░░██╗')); console.log(themeColor(' _____ _ _ '));
console.log(themeColor('██╔════╝██╔══██╗██╔══██╗██║░██╔╝██╔════╝╚██╗░██╔╝')); console.log(themeColor(' | |_|___ ___| |_ ___ _ _ '));
console.log(themeColor('█████╗░░██║░░██║██████╔╝█████═╝░█████╗░░░╚████╔╝░')); console.log(themeColor(' | | | | |_ -|_ -| \'_| -_| | |'));
console.log(themeColor('██╔══╝░░██║░░██║██╔══██╗██╔═██╗░██╔══╝░░░░╚██╔╝░░')); console.log(themeColor(' |_|_|_|_|___|___|_,_|___|_ |'));
console.log(themeColor('██║░░░░░╚█████╔╝██║░░██║██║░╚██╗███████╗░░░██║░░░')); console.log(' ' + chalk.gray(v) + themeColor(' |___|\n'.substring(v.length)));
console.log(' ' + chalk.gray(v) + themeColor('╚═╝░░░░░░╚════╝░╚═╝░░╚═╝╚═╝░░╚═╝╚══════╝░░░╚═╝░░░\n'.substring(v.length)));
//#endregion //#endregion
console.log(' Forkey is an open-source decentralized microblogging platform.'); console.log(' Misskey is an open-source decentralized microblogging platform.');
// console.log(chalk.rgb(255, 136, 0)(' If you like Forkey, please donate to support development. https://www.patreon.com/syuilo')); console.log(chalk.rgb(255, 136, 0)(' If you like Misskey, please donate to support development. https://www.patreon.com/syuilo'));
console.log(''); console.log('');
console.log(chalkTemplate`--- ${os.hostname()} {gray (PID: ${process.pid.toString()})} ---`); console.log(chalkTemplate`--- ${os.hostname()} {gray (PID: ${process.pid.toString()})} ---`);
} }
bootLogger.info('Welcome to Forkey!'); bootLogger.info('Welcome to Misskey!');
bootLogger.info(`Forkey v${meta.version}`, { version: meta.version, hostname: os.hostname(), pid: process.pid }, true); bootLogger.info(`Misskey v${meta.version}`, { version: meta.version, hostname: os.hostname(), pid: process.pid }, true);
} }
/** /**
@ -69,7 +68,7 @@ export async function masterMain() {
process.exit(1); process.exit(1);
} }
bootLogger.succ('Forkey initialized'); bootLogger.succ('Misskey initialized');
if (envOption.disableClustering) { if (envOption.disableClustering) {
if (envOption.onlyServer) { if (envOption.onlyServer) {

View file

@ -0,0 +1,44 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { promisify } from 'node:util';
import { Inject, Injectable } from '@nestjs/common';
import redisLock from 'redis-lock';
import * as Redis from 'ioredis';
import { DI } from '@/di-symbols.js';
import { bindThis } from '@/decorators.js';
/**
* Retry delay (ms) for lock acquisition
*/
const retryDelay = 100;
@Injectable()
export class AppLockService {
private lock: (key: string, timeout?: number, _?: (() => Promise<void>) | undefined) => Promise<() => void>;
constructor(
@Inject(DI.redis)
private redisClient: Redis.Redis,
) {
this.lock = promisify(redisLock(this.redisClient, retryDelay));
}
/**
* Get AP Object lock
* @param uri AP object ID
* @param timeout Lock timeout (ms), The timeout releases previous lock.
* @returns Unlock function
*/
@bindThis
public getApLock(uri: string, timeout = 30 * 1000): Promise<() => void> {
return this.lock(`ap-object:${uri}`, timeout);
}
@bindThis
public getChartInsertLock(lockKey: string, timeout = 30 * 1000): Promise<() => void> {
return this.lock(`chart-insert:${lockKey}`, timeout);
}
}

View file

@ -10,7 +10,6 @@ import { bindThis } from '@/decorators.js';
type CaptchaResponse = { type CaptchaResponse = {
success: boolean; success: boolean;
'error-codes'?: string[]; 'error-codes'?: string[];
'errors'?: string[];
}; };
@Injectable() @Injectable()
@ -74,35 +73,6 @@ export class CaptchaService {
} }
} }
@bindThis
public async verifyFriendlyCaptcha(secret: string, response: string | null | undefined): Promise<void> {
if (response == null) {
throw new Error('frc-failed: no response provided');
}
const result = await this.httpRequestService.send('https://api.friendlycaptcha.com/api/v1/siteverify', {
method: 'POST',
body: JSON.stringify({
secret: secret,
solution: response,
}),
headers: {
'Content-Type': 'application/json',
},
});
if (result.status !== 200) {
throw new Error('frc-failed: frc didn\'t return 200 OK');
}
const resp = await result.json() as CaptchaResponse;
if (resp.success !== true) {
const errorCodes = resp['error-codes'] ? resp['errors']?.join(', ') : '';
throw new Error(`frc-failed: ${errorCodes}`);
}
}
// https://codeberg.org/Gusted/mCaptcha/src/branch/main/mcaptcha.go // https://codeberg.org/Gusted/mCaptcha/src/branch/main/mcaptcha.go
@bindThis @bindThis
public async verifyMcaptcha(secret: string, siteKey: string, instanceHost: string, response: string | null | undefined): Promise<void> { public async verifyMcaptcha(secret: string, siteKey: string, instanceHost: string, response: string | null | undefined): Promise<void> {

View file

@ -10,6 +10,7 @@ import { AccountUpdateService } from './AccountUpdateService.js';
import { AiService } from './AiService.js'; import { AiService } from './AiService.js';
import { AnnouncementService } from './AnnouncementService.js'; import { AnnouncementService } from './AnnouncementService.js';
import { AntennaService } from './AntennaService.js'; import { AntennaService } from './AntennaService.js';
import { AppLockService } from './AppLockService.js';
import { AchievementService } from './AchievementService.js'; import { AchievementService } from './AchievementService.js';
import { AvatarDecorationService } from './AvatarDecorationService.js'; import { AvatarDecorationService } from './AvatarDecorationService.js';
import { CaptchaService } from './CaptchaService.js'; import { CaptchaService } from './CaptchaService.js';
@ -104,7 +105,6 @@ import { UserAccountMoveLogEntityService } from './entities/UserAccountMoveLogEn
import { MutingEntityService } from './entities/MutingEntityService.js'; import { MutingEntityService } from './entities/MutingEntityService.js';
import { RenoteMutingEntityService } from './entities/RenoteMutingEntityService.js'; import { RenoteMutingEntityService } from './entities/RenoteMutingEntityService.js';
import { NoteEntityService } from './entities/NoteEntityService.js'; import { NoteEntityService } from './entities/NoteEntityService.js';
import { ScheduledNoteEntityService } from './entities/ScheduledNoteEntityService.js';
import { NoteFavoriteEntityService } from './entities/NoteFavoriteEntityService.js'; import { NoteFavoriteEntityService } from './entities/NoteFavoriteEntityService.js';
import { NoteReactionEntityService } from './entities/NoteReactionEntityService.js'; import { NoteReactionEntityService } from './entities/NoteReactionEntityService.js';
import { NotificationEntityService } from './entities/NotificationEntityService.js'; import { NotificationEntityService } from './entities/NotificationEntityService.js';
@ -140,7 +140,6 @@ import { ApQuestionService } from './activitypub/models/ApQuestionService.js';
import { QueueModule } from './QueueModule.js'; import { QueueModule } from './QueueModule.js';
import { QueueService } from './QueueService.js'; import { QueueService } from './QueueService.js';
import { LoggerService } from './LoggerService.js'; import { LoggerService } from './LoggerService.js';
import { MastodonUserConverterService } from './mastodon/MastodonUserConverterService.js';
import type { Provider } from '@nestjs/common'; import type { Provider } from '@nestjs/common';
//#region 文字列ベースでのinjection用(循環参照対応のため) //#region 文字列ベースでのinjection用(循環参照対応のため)
@ -150,6 +149,7 @@ const $AccountUpdateService: Provider = { provide: 'AccountUpdateService', useEx
const $AiService: Provider = { provide: 'AiService', useExisting: AiService }; const $AiService: Provider = { provide: 'AiService', useExisting: AiService };
const $AnnouncementService: Provider = { provide: 'AnnouncementService', useExisting: AnnouncementService }; const $AnnouncementService: Provider = { provide: 'AnnouncementService', useExisting: AnnouncementService };
const $AntennaService: Provider = { provide: 'AntennaService', useExisting: AntennaService }; const $AntennaService: Provider = { provide: 'AntennaService', useExisting: AntennaService };
const $AppLockService: Provider = { provide: 'AppLockService', useExisting: AppLockService };
const $AchievementService: Provider = { provide: 'AchievementService', useExisting: AchievementService }; const $AchievementService: Provider = { provide: 'AchievementService', useExisting: AchievementService };
const $AvatarDecorationService: Provider = { provide: 'AvatarDecorationService', useExisting: AvatarDecorationService }; const $AvatarDecorationService: Provider = { provide: 'AvatarDecorationService', useExisting: AvatarDecorationService };
const $CaptchaService: Provider = { provide: 'CaptchaService', useExisting: CaptchaService }; const $CaptchaService: Provider = { provide: 'CaptchaService', useExisting: CaptchaService };
@ -247,7 +247,6 @@ const $UserAccountMoveLogEntityService: Provider = { provide: 'UserAccountMoveLo
const $MutingEntityService: Provider = { provide: 'MutingEntityService', useExisting: MutingEntityService }; const $MutingEntityService: Provider = { provide: 'MutingEntityService', useExisting: MutingEntityService };
const $RenoteMutingEntityService: Provider = { provide: 'RenoteMutingEntityService', useExisting: RenoteMutingEntityService }; const $RenoteMutingEntityService: Provider = { provide: 'RenoteMutingEntityService', useExisting: RenoteMutingEntityService };
const $NoteEntityService: Provider = { provide: 'NoteEntityService', useExisting: NoteEntityService }; const $NoteEntityService: Provider = { provide: 'NoteEntityService', useExisting: NoteEntityService };
const $ScheduledNoteEntityService: Provider = { provide: 'ScheduledNoteEntityService', useExisting: ScheduledNoteEntityService };
const $NoteFavoriteEntityService: Provider = { provide: 'NoteFavoriteEntityService', useExisting: NoteFavoriteEntityService }; const $NoteFavoriteEntityService: Provider = { provide: 'NoteFavoriteEntityService', useExisting: NoteFavoriteEntityService };
const $NoteReactionEntityService: Provider = { provide: 'NoteReactionEntityService', useExisting: NoteReactionEntityService }; const $NoteReactionEntityService: Provider = { provide: 'NoteReactionEntityService', useExisting: NoteReactionEntityService };
const $NotificationEntityService: Provider = { provide: 'NotificationEntityService', useExisting: NotificationEntityService }; const $NotificationEntityService: Provider = { provide: 'NotificationEntityService', useExisting: NotificationEntityService };
@ -293,6 +292,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
AiService, AiService,
AnnouncementService, AnnouncementService,
AntennaService, AntennaService,
AppLockService,
AchievementService, AchievementService,
AvatarDecorationService, AvatarDecorationService,
CaptchaService, CaptchaService,
@ -388,7 +388,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
MutingEntityService, MutingEntityService,
RenoteMutingEntityService, RenoteMutingEntityService,
NoteEntityService, NoteEntityService,
ScheduledNoteEntityService,
NoteFavoriteEntityService, NoteFavoriteEntityService,
NoteReactionEntityService, NoteReactionEntityService,
NotificationEntityService, NotificationEntityService,
@ -423,9 +422,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
ApQuestionService, ApQuestionService,
QueueService, QueueService,
// Mastodon
MastodonUserConverterService,
//#region 文字列ベースでのinjection用(循環参照対応のため) //#region 文字列ベースでのinjection用(循環参照対応のため)
$LoggerService, $LoggerService,
$AccountMoveService, $AccountMoveService,
@ -433,6 +429,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$AiService, $AiService,
$AnnouncementService, $AnnouncementService,
$AntennaService, $AntennaService,
$AppLockService,
$AchievementService, $AchievementService,
$AvatarDecorationService, $AvatarDecorationService,
$CaptchaService, $CaptchaService,
@ -528,7 +525,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$MutingEntityService, $MutingEntityService,
$RenoteMutingEntityService, $RenoteMutingEntityService,
$NoteEntityService, $NoteEntityService,
$ScheduledNoteEntityService,
$NoteFavoriteEntityService, $NoteFavoriteEntityService,
$NoteReactionEntityService, $NoteReactionEntityService,
$NotificationEntityService, $NotificationEntityService,
@ -571,6 +567,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
AiService, AiService,
AnnouncementService, AnnouncementService,
AntennaService, AntennaService,
AppLockService,
AchievementService, AchievementService,
AvatarDecorationService, AvatarDecorationService,
CaptchaService, CaptchaService,
@ -665,7 +662,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
MutingEntityService, MutingEntityService,
RenoteMutingEntityService, RenoteMutingEntityService,
NoteEntityService, NoteEntityService,
ScheduledNoteEntityService,
NoteFavoriteEntityService, NoteFavoriteEntityService,
NoteReactionEntityService, NoteReactionEntityService,
NotificationEntityService, NotificationEntityService,
@ -700,9 +696,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
ApQuestionService, ApQuestionService,
QueueService, QueueService,
// Mastodon
MastodonUserConverterService,
//#region 文字列ベースでのinjection用(循環参照対応のため) //#region 文字列ベースでのinjection用(循環参照対応のため)
$LoggerService, $LoggerService,
$AccountMoveService, $AccountMoveService,
@ -710,6 +703,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$AiService, $AiService,
$AnnouncementService, $AnnouncementService,
$AntennaService, $AntennaService,
$AppLockService,
$AchievementService, $AchievementService,
$AvatarDecorationService, $AvatarDecorationService,
$CaptchaService, $CaptchaService,
@ -804,7 +798,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$MutingEntityService, $MutingEntityService,
$RenoteMutingEntityService, $RenoteMutingEntityService,
$NoteEntityService, $NoteEntityService,
$ScheduledNoteEntityService,
$NoteFavoriteEntityService, $NoteFavoriteEntityService,
$NoteReactionEntityService, $NoteReactionEntityService,
$NotificationEntityService, $NotificationEntityService,

View file

@ -61,7 +61,6 @@ export class CreateSystemUserService {
isLocked: true, isLocked: true,
isExplorable: false, isExplorable: false,
isBot: true, isBot: true,
approved: true,
}).then(x => transactionalEntityManager.findOneByOrFail(MiUser, x.identifiers[0])); }).then(x => transactionalEntityManager.findOneByOrFail(MiUser, x.identifiers[0]));
await transactionalEntityManager.insert(MiUserKeypair, { await transactionalEntityManager.insert(MiUserKeypair, {

View file

@ -9,7 +9,7 @@ import { join } from 'node:path';
import * as stream from 'node:stream/promises'; import * as stream from 'node:stream/promises';
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { FSWatcher } from 'chokidar'; import { FSWatcher } from 'chokidar';
import { fileTypeFromFile } from 'file-type'; import * as fileType from 'file-type';
import FFmpeg from 'fluent-ffmpeg'; import FFmpeg from 'fluent-ffmpeg';
import isSvg from 'is-svg'; import isSvg from 'is-svg';
import probeImageSize from 'probe-image-size'; import probeImageSize from 'probe-image-size';
@ -309,7 +309,7 @@ export class FileInfoService {
} }
@bindThis @bindThis
public fixMime(mime: string): string { public fixMime(mime: string | fileType.MimeType): string {
// see https://github.com/misskey-dev/misskey/pull/10686 // see https://github.com/misskey-dev/misskey/pull/10686
if (mime === 'audio/x-flac') { if (mime === 'audio/x-flac') {
return 'audio/flac'; return 'audio/flac';
@ -363,7 +363,7 @@ export class FileInfoService {
return TYPE_OCTET_STREAM; return TYPE_OCTET_STREAM;
} }
const type = await fileTypeFromFile(path); const type = await fileType.fileTypeFromFile(path);
if (type) { if (type) {
// XMLはSVGかもしれない // XMLはSVGかもしれない

View file

@ -13,28 +13,16 @@ import { extractCustomEmojisFromMfm } from '@/misc/extract-custom-emojis-from-mf
import { extractHashtags } from '@/misc/extract-hashtags.js'; import { extractHashtags } from '@/misc/extract-hashtags.js';
import type { IMentionedRemoteUsers } from '@/models/Note.js'; import type { IMentionedRemoteUsers } from '@/models/Note.js';
import { MiNote } from '@/models/Note.js'; import { MiNote } from '@/models/Note.js';
import { MiScheduledNote } from '@/models/ScheduledNote.js'; import type { ChannelFollowingsRepository, ChannelsRepository, FollowingsRepository, InstancesRepository, MiFollowing, NotesRepository, NoteThreadMutingsRepository, UserListMembershipsRepository, UserProfilesRepository, UsersRepository } from '@/models/_.js';
import type {
ChannelFollowingsRepository,
ChannelsRepository,
FollowingsRepository,
InstancesRepository,
MiFollowing,
NotesRepository,
NoteThreadMutingsRepository,
ScheduledNotesRepository,
UserListMembershipsRepository,
UserProfilesRepository,
UsersRepository
} from '@/models/_.js';
import type { MiDriveFile } from '@/models/DriveFile.js'; import type { MiDriveFile } from '@/models/DriveFile.js';
import type { MiApp } from '@/models/App.js';
import { concat } from '@/misc/prelude/array.js'; import { concat } from '@/misc/prelude/array.js';
import { IdService } from '@/core/IdService.js'; import { IdService } from '@/core/IdService.js';
import type { MiUser, MiLocalUser, MiRemoteUser } from '@/models/User.js'; import type { MiUser, MiLocalUser, MiRemoteUser } from '@/models/User.js';
import type { IPoll } from '@/models/Poll.js'; import type { IPoll } from '@/models/Poll.js';
import { MiPoll } from '@/models/Poll.js'; import { MiPoll } from '@/models/Poll.js';
import type { NoteCreateOption, MinimumUser } from '@/types.js';
import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js'; import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js';
import type { MiChannel } from '@/models/Channel.js';
import { normalizeForSearch } from '@/misc/normalize-for-search.js'; import { normalizeForSearch } from '@/misc/normalize-for-search.js';
import { RelayService } from '@/core/RelayService.js'; import { RelayService } from '@/core/RelayService.js';
import { FederatedInstanceService } from '@/core/FederatedInstanceService.js'; import { FederatedInstanceService } from '@/core/FederatedInstanceService.js';
@ -130,6 +118,35 @@ class NotificationManager {
} }
} }
type MinimumUser = {
id: MiUser['id'];
host: MiUser['host'];
username: MiUser['username'];
uri: MiUser['uri'];
};
type Option = {
createdAt?: Date | null;
name?: string | null;
text?: string | null;
reply?: MiNote | null;
renote?: MiNote | null;
files?: MiDriveFile[] | null;
poll?: IPoll | null;
localOnly?: boolean | null;
reactionAcceptance?: MiNote['reactionAcceptance'];
cw?: string | null;
visibility?: string;
visibleUsers?: MinimumUser[] | null;
channel?: MiChannel | null;
apMentions?: MinimumUser[] | null;
apHashtags?: string[] | null;
apEmojis?: string[] | null;
uri?: string | null;
url?: string | null;
app?: MiApp | null;
};
@Injectable() @Injectable()
export class NoteCreateService implements OnApplicationShutdown { export class NoteCreateService implements OnApplicationShutdown {
private logger: Logger; private logger: Logger;
@ -152,9 +169,6 @@ export class NoteCreateService implements OnApplicationShutdown {
@Inject(DI.notesRepository) @Inject(DI.notesRepository)
private notesRepository: NotesRepository, private notesRepository: NotesRepository,
@Inject(DI.scheduledNotesRepository)
private scheduledNotesRepository: ScheduledNotesRepository,
@Inject(DI.instancesRepository) @Inject(DI.instancesRepository)
private instancesRepository: InstancesRepository, private instancesRepository: InstancesRepository,
@ -215,7 +229,7 @@ export class NoteCreateService implements OnApplicationShutdown {
host: MiUser['host']; host: MiUser['host'];
isBot: MiUser['isBot']; isBot: MiUser['isBot'];
isCat: MiUser['isCat']; isCat: MiUser['isCat'];
}, data: NoteCreateOption, silent = false): Promise<MiNote | MiScheduledNote> { }, data: Option, silent = false): Promise<MiNote> {
// チャンネル外にリプライしたら対象のスコープに合わせる // チャンネル外にリプライしたら対象のスコープに合わせる
// (クライアントサイドでやっても良い処理だと思うけどとりあえずサーバーサイドで) // (クライアントサイドでやっても良い処理だと思うけどとりあえずサーバーサイドで)
if (data.reply && data.channel && data.reply.channelId !== data.channel.id) { if (data.reply && data.channel && data.reply.channelId !== data.channel.id) {
@ -411,39 +425,18 @@ export class NoteCreateService implements OnApplicationShutdown {
throw new IdentifiableError('9f466dab-c856-48cd-9e65-ff90ff750580', `Notes including mentions are limited to ${policies.mentionLimit} users.`); throw new IdentifiableError('9f466dab-c856-48cd-9e65-ff90ff750580', `Notes including mentions are limited to ${policies.mentionLimit} users.`);
} }
if (!data.scheduledAt) { const note = await this.insertNote(user, data, tags, emojis, mentionedUsers);
const note = await this.insertNote(user, data, tags, emojis, mentionedUsers);
setImmediate('post created', { signal: this.#shutdownController.signal }).then( setImmediate('post created', { signal: this.#shutdownController.signal }).then(
() => this.postNoteCreated(note, user, data, silent, tags!, mentionedUsers!), () => this.postNoteCreated(note, user, data, silent, tags!, mentionedUsers!),
() => { /* aborted, ignore this */ }, () => { /* aborted, ignore this */ },
); );
return note; return note;
} else {
if (!policies.canScheduleNote) {
throw new IdentifiableError('7cc42034-f7ab-4f7c-87b4-e00854479080', 'User has no permission to schedule notes.');
}
if ((data.scheduledAt.getTime() - Date.now()) / 86_400_000 > policies.scheduleNoteMaxDays) {
throw new IdentifiableError('506006cf-3092-4ae1-8145-b025001c591f', `User can schedule notes up to ${policies.scheduleNoteMaxDays} days in the future.`);
}
const scheduledCount = await this.scheduledNotesRepository.countBy({ userId: user.id });
if (scheduledCount >= policies.scheduleNoteLimit) {
throw new IdentifiableError('7fc78d25-d947-45c1-9547-02257b98cab3', `User can schedule up to ${policies.scheduleNoteLimit} notes.`);
}
const draft = await this.insertScheduledNote(user, data);
await this.queueService.createScheduledNoteJob(draft.id, draft.scheduledAt!);
return draft;
}
} }
@bindThis @bindThis
private async insertNote(user: { id: MiUser['id']; host: MiUser['host']; }, data: NoteCreateOption, tags: string[], emojis: string[], mentionedUsers: MinimumUser[]) { private async insertNote(user: { id: MiUser['id']; host: MiUser['host']; }, data: Option, tags: string[], emojis: string[], mentionedUsers: MinimumUser[]) {
const insert = new MiNote({ const insert = new MiNote({
id: this.idService.gen(data.createdAt?.getTime()), id: this.idService.gen(data.createdAt?.getTime()),
createdAt: data.createdAt!, createdAt: data.createdAt!,
@ -541,40 +534,13 @@ export class NoteCreateService implements OnApplicationShutdown {
} }
} }
@bindThis
private async insertScheduledNote(user: { id: MiUser['id']; host: MiUser['host']; }, data: NoteCreateOption) {
const insert = new MiScheduledNote({
id: this.idService.gen(data.createdAt?.getTime()),
createdAt: data.createdAt!,
scheduledAt: data.scheduledAt!,
userId: user.id,
draft: data,
});
// 予約投稿を作成
try {
await this.scheduledNotesRepository.insert(insert);
return insert;
} catch (e) {
// duplicate key error
if (isDuplicateKeyValueError(e)) {
throw new IdentifiableError('5ea8e4f5-9d64-4e6c-92b8-9e2b5a4756bc', 'There is already a scheduled note with the same time.');
}
this.logger.error(`Failed to create scheduled note: ${e}`, { error: e });
throw e;
}
}
@bindThis @bindThis
private async postNoteCreated(note: MiNote, user: { private async postNoteCreated(note: MiNote, user: {
id: MiUser['id']; id: MiUser['id'];
username: MiUser['username']; username: MiUser['username'];
host: MiUser['host']; host: MiUser['host'];
isBot: MiUser['isBot']; isBot: MiUser['isBot'];
}, data: NoteCreateOption, silent: boolean, tags: string[], mentionedUsers: MinimumUser[]) { }, data: Option, silent: boolean, tags: string[], mentionedUsers: MinimumUser[]) {
const meta = await this.metaService.fetch(); const meta = await this.metaService.fetch();
this.notesChart.update(note, true); this.notesChart.update(note, true);
@ -826,12 +792,12 @@ export class NoteCreateService implements OnApplicationShutdown {
} }
@bindThis @bindThis
private isRenote(note: NoteCreateOption): note is NoteCreateOption & { renote: MiNote } { private isRenote(note: Option): note is Option & { renote: MiNote } {
return note.renote != null; return note.renote != null;
} }
@bindThis @bindThis
private isQuote(note: NoteCreateOption): note is NoteCreateOption & { renote: MiNote } & ( private isQuote(note: Option): note is Option & { renote: MiNote } & (
{ text: string } | { cw: string } | { reply: MiNote } | { poll: IPoll } | { files: MiDriveFile[] } { text: string } | { cw: string } | { reply: MiNote } | { poll: IPoll } | { files: MiDriveFile[] }
) { ) {
// NOTE: SYNC WITH misc/is-renote.ts // NOTE: SYNC WITH misc/is-renote.ts
@ -907,7 +873,7 @@ export class NoteCreateService implements OnApplicationShutdown {
} }
@bindThis @bindThis
private async renderNoteOrRenoteActivity(data: NoteCreateOption, note: MiNote) { private async renderNoteOrRenoteActivity(data: Option, note: MiNote) {
if (data.localOnly) return null; if (data.localOnly) return null;
const content = this.isRenote(data) && !this.isQuote(data) const content = this.isRenote(data) && !this.isQuote(data)

View file

@ -7,7 +7,6 @@ import { randomUUID } from 'node:crypto';
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import type { IActivity } from '@/core/activitypub/type.js'; import type { IActivity } from '@/core/activitypub/type.js';
import type { MiDriveFile } from '@/models/DriveFile.js'; import type { MiDriveFile } from '@/models/DriveFile.js';
import type { MiScheduledNote } from '@/models/ScheduledNote.js';
import type { MiAbuseUserReport } from '@/models/AbuseUserReport.js'; import type { MiAbuseUserReport } from '@/models/AbuseUserReport.js';
import type { MiWebhook, webhookEventTypes } from '@/models/Webhook.js'; import type { MiWebhook, webhookEventTypes } from '@/models/Webhook.js';
import type { Config } from '@/config.js'; import type { Config } from '@/config.js';
@ -35,11 +34,6 @@ export class QueueService {
@Inject('queue:objectStorage') public objectStorageQueue: ObjectStorageQueue, @Inject('queue:objectStorage') public objectStorageQueue: ObjectStorageQueue,
@Inject('queue:webhookDeliver') public webhookDeliverQueue: WebhookDeliverQueue, @Inject('queue:webhookDeliver') public webhookDeliverQueue: WebhookDeliverQueue,
) { ) {
this.ensureRepeatJobs();
}
@bindThis
private ensureRepeatJobs() {
this.systemQueue.add('tickCharts', { this.systemQueue.add('tickCharts', {
}, { }, {
repeat: { pattern: '55 * * * *' }, repeat: { pattern: '55 * * * *' },
@ -75,12 +69,6 @@ export class QueueService {
repeat: { pattern: '*/5 * * * *' }, repeat: { pattern: '*/5 * * * *' },
removeOnComplete: true, removeOnComplete: true,
}); });
this.systemQueue.add('checkMissingScheduledNote', {
}, {
repeat: { pattern: '*/5 * * * *' },
removeOnComplete: true,
});
} }
@bindThis @bindThis
@ -388,22 +376,7 @@ export class QueueService {
@bindThis @bindThis
public createReportAbuseJob(report: MiAbuseUserReport) { public createReportAbuseJob(report: MiAbuseUserReport) {
return this.dbQueue.add('reportAbuse', report, { return this.dbQueue.add('reportAbuse', report);
removeOnComplete: true,
removeOnFail: true,
});
}
@bindThis
public createScheduledNoteJob(draftId: MiScheduledNote['id'], scheduledAt: Date) {
return this.systemQueue.add('scheduledNote', {
draftId,
}, {
jobId: `scheduledNote:${draftId}`,
delay: Math.max(scheduledAt.getTime() - Date.now(), 0) + Math.floor(Math.random() * 500 + 250),
removeOnComplete: true,
removeOnFail: true,
});
} }
@bindThis @bindThis

View file

@ -36,9 +36,6 @@ export type RolePolicies = {
gtlAvailable: boolean; gtlAvailable: boolean;
ltlAvailable: boolean; ltlAvailable: boolean;
canPublicNote: boolean; canPublicNote: boolean;
canScheduleNote: boolean;
scheduleNoteLimit: number;
scheduleNoteMaxDays: number;
canInitiateConversation: boolean; canInitiateConversation: boolean;
canCreateContent: boolean; canCreateContent: boolean;
canUpdateContent: boolean; canUpdateContent: boolean;
@ -80,9 +77,6 @@ export const DEFAULT_POLICIES: RolePolicies = {
gtlAvailable: true, gtlAvailable: true,
ltlAvailable: true, ltlAvailable: true,
canPublicNote: true, canPublicNote: true,
canScheduleNote: true,
scheduleNoteLimit: 10,
scheduleNoteMaxDays: 365,
canInitiateConversation: true, canInitiateConversation: true,
canCreateContent: true, canCreateContent: true,
canUpdateContent: true, canUpdateContent: true,
@ -395,9 +389,6 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit {
gtlAvailable: calc('gtlAvailable', vs => vs.some(v => v === true)), gtlAvailable: calc('gtlAvailable', vs => vs.some(v => v === true)),
ltlAvailable: calc('ltlAvailable', vs => vs.some(v => v === true)), ltlAvailable: calc('ltlAvailable', vs => vs.some(v => v === true)),
canPublicNote: calc('canPublicNote', vs => vs.some(v => v === true)), canPublicNote: calc('canPublicNote', vs => vs.some(v => v === true)),
canScheduleNote: calc('canScheduleNote', vs => vs.some(v => v === true)),
scheduleNoteLimit: calc('scheduleNoteLimit', vs => Math.max(...vs)),
scheduleNoteMaxDays: calc('scheduleNoteMaxDays', vs => Math.max(...vs)),
canInitiateConversation: calc('canInitiateConversation', vs => vs.some(v => v === true)), canInitiateConversation: calc('canInitiateConversation', vs => vs.some(v => v === true)),
canCreateContent: calc('canCreateContent', vs => vs.some(v => v === true)), canCreateContent: calc('canCreateContent', vs => vs.some(v => v === true)),
canUpdateContent: calc('canUpdateContent', vs => vs.some(v => v === true)), canUpdateContent: calc('canUpdateContent', vs => vs.some(v => v === true)),

View file

@ -46,8 +46,6 @@ export class S3Service {
tls: meta.objectStorageUseSSL, tls: meta.objectStorageUseSSL,
forcePathStyle: meta.objectStorageEndpoint ? meta.objectStorageS3ForcePathStyle : false, // AWS with endPoint omitted forcePathStyle: meta.objectStorageEndpoint ? meta.objectStorageS3ForcePathStyle : false, // AWS with endPoint omitted
requestHandler: new NodeHttpHandler(handlerOption), requestHandler: new NodeHttpHandler(handlerOption),
requestChecksumCalculation: 'WHEN_REQUIRED',
responseChecksumValidation: 'WHEN_REQUIRED',
}); });
} }

View file

@ -58,10 +58,9 @@ export class SignupService {
password?: string | null; password?: string | null;
passwordHash?: MiUserProfile['password'] | null; passwordHash?: MiUserProfile['password'] | null;
host?: string | null; host?: string | null;
reason?: string | null;
ignorePreservedUsernames?: boolean; ignorePreservedUsernames?: boolean;
}) { }) {
const { username, password, passwordHash, host, reason } = opts; const { username, password, passwordHash, host } = opts;
let hash = passwordHash; let hash = passwordHash;
// Validate username // Validate username
@ -94,9 +93,9 @@ export class SignupService {
} }
const isTheFirstUser = !await this.instanceActorService.realLocalUsersPresent(); const isTheFirstUser = !await this.instanceActorService.realLocalUsersPresent();
const instance = await this.metaService.fetch(true);
if (!opts.ignorePreservedUsernames && !isTheFirstUser) { if (!opts.ignorePreservedUsernames && !isTheFirstUser) {
const instance = await this.metaService.fetch(true);
const isPreserved = instance.preservedUsernames.map(x => x.toLowerCase()).includes(username.toLowerCase()); const isPreserved = instance.preservedUsernames.map(x => x.toLowerCase()).includes(username.toLowerCase());
if (isPreserved) { if (isPreserved) {
throw new Error('USED_USERNAME'); throw new Error('USED_USERNAME');
@ -129,10 +128,6 @@ export class SignupService {
try { try {
let account!: MiUser; let account!: MiUser;
let defaultApproval = false;
if (!instance.approvalRequiredForSignup) defaultApproval = true;
// Start transaction // Start transaction
await this.db.transaction(async transactionalEntityManager => { await this.db.transaction(async transactionalEntityManager => {
const exist = await transactionalEntityManager.findOneBy(MiUser, { const exist = await transactionalEntityManager.findOneBy(MiUser, {
@ -149,8 +144,6 @@ export class SignupService {
host: host ? this.utilityService.normalizeHost(host) : null, host: host ? this.utilityService.normalizeHost(host) : null,
token: secret, token: secret,
isRoot: isTheFirstUser, isRoot: isTheFirstUser,
approved: defaultApproval,
signupReason: reason,
})); }));
await transactionalEntityManager.save(new MiUserKeypair({ await transactionalEntityManager.save(new MiUserKeypair({

View file

@ -5,7 +5,6 @@
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import { In } from 'typeorm'; import { In } from 'typeorm';
import * as Redis from 'ioredis';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js'; import type { Config } from '@/config.js';
import { UserFollowingService } from '@/core/UserFollowingService.js'; import { UserFollowingService } from '@/core/UserFollowingService.js';
@ -15,8 +14,8 @@ import { NotePiningService } from '@/core/NotePiningService.js';
import { UserBlockingService } from '@/core/UserBlockingService.js'; import { UserBlockingService } from '@/core/UserBlockingService.js';
import { NoteDeleteService } from '@/core/NoteDeleteService.js'; import { NoteDeleteService } from '@/core/NoteDeleteService.js';
import { NoteCreateService } from '@/core/NoteCreateService.js'; import { NoteCreateService } from '@/core/NoteCreateService.js';
import { acquireApObjectLock } from '@/misc/distributed-lock.js';
import { concat, toArray, toSingle, unique } from '@/misc/prelude/array.js'; import { concat, toArray, toSingle, unique } from '@/misc/prelude/array.js';
import { AppLockService } from '@/core/AppLockService.js';
import type Logger from '@/logger.js'; import type Logger from '@/logger.js';
import { MetaService } from '@/core/MetaService.js'; import { MetaService } from '@/core/MetaService.js';
import { IdService } from '@/core/IdService.js'; import { IdService } from '@/core/IdService.js';
@ -50,9 +49,6 @@ export class ApInboxService {
@Inject(DI.config) @Inject(DI.config)
private config: Config, private config: Config,
@Inject(DI.redisForTimelines)
private redisForTimelines: Redis.Redis,
@Inject(DI.usersRepository) @Inject(DI.usersRepository)
private usersRepository: UsersRepository, private usersRepository: UsersRepository,
@ -81,6 +77,7 @@ export class ApInboxService {
private userBlockingService: UserBlockingService, private userBlockingService: UserBlockingService,
private noteCreateService: NoteCreateService, private noteCreateService: NoteCreateService,
private noteDeleteService: NoteDeleteService, private noteDeleteService: NoteDeleteService,
private appLockService: AppLockService,
private apResolverService: ApResolverService, private apResolverService: ApResolverService,
private apDbResolverService: ApDbResolverService, private apDbResolverService: ApDbResolverService,
private apLoggerService: ApLoggerService, private apLoggerService: ApLoggerService,
@ -315,7 +312,7 @@ export class ApInboxService {
const meta = await this.metaService.fetch(); const meta = await this.metaService.fetch();
if (this.utilityService.isItemListedIn(this.utilityService.extractHost(uri), meta.blockedHosts)) return 'skip: blocked host'; if (this.utilityService.isItemListedIn(this.utilityService.extractHost(uri), meta.blockedHosts)) return 'skip: blocked host';
const unlock = await acquireApObjectLock(this.redisForTimelines, uri); const unlock = await this.appLockService.getApLock(uri);
try { try {
// 既に同じURIを持つものが登録されていないかチェック // 既に同じURIを持つものが登録されていないかチェック
@ -443,7 +440,7 @@ export class ApInboxService {
} }
} }
const unlock = await acquireApObjectLock(this.redisForTimelines, uri); const unlock = await this.appLockService.getApLock(uri);
try { try {
const exist = await this.apNoteService.fetchNote(note); const exist = await this.apNoteService.fetchNote(note);
@ -546,7 +543,7 @@ export class ApInboxService {
private async deleteNote(actor: MiRemoteUser, uri: string): Promise<string> { private async deleteNote(actor: MiRemoteUser, uri: string): Promise<string> {
this.logger.info(`Deleting the Note: ${uri}`); this.logger.info(`Deleting the Note: ${uri}`);
const unlock = await acquireApObjectLock(this.redisForTimelines, uri); const unlock = await this.appLockService.getApLock(uri);
try { try {
const note = await this.apDbResolverService.getNoteFromApId(uri); const note = await this.apDbResolverService.getNoteFromApId(uri);
@ -816,7 +813,7 @@ export class ApInboxService {
return 'ok: Question updated'; return 'ok: Question updated';
} else if (additionalCc && isPost(object)) { } else if (additionalCc && isPost(object)) {
const uri = getApId(object); const uri = getApId(object);
const unlock = await acquireApObjectLock(this.redisForTimelines, uri); const unlock = await this.appLockService.getApLock(uri);
try { try {
const exist = await this.apNoteService.fetchNote(object); const exist = await this.apNoteService.fetchNote(object);

View file

@ -518,7 +518,6 @@ export class ApRendererService {
discoverable: user.isExplorable, discoverable: user.isExplorable,
publicKey: this.renderKey(user, keypair, '#main-key'), publicKey: this.renderKey(user, keypair, '#main-key'),
isCat: user.isCat, isCat: user.isCat,
speakAsCat: user.speakAsCat,
attachment: attachment.length ? attachment : undefined, attachment: attachment.length ? attachment : undefined,
}; };

View file

@ -553,9 +553,6 @@ export const CONTEXTS: (string | Context)[] = [
'_misskey_votes': 'misskey:_misskey_votes', '_misskey_votes': 'misskey:_misskey_votes',
'_misskey_summary': 'misskey:_misskey_summary', '_misskey_summary': 'misskey:_misskey_summary',
'isCat': 'misskey:isCat', 'isCat': 'misskey:isCat',
// Firefish
firefish: "https://joinfirefish.org/ns#",
speakAsCat: "firefish:speakAsCat",
// vcard // vcard
vcard: 'http://www.w3.org/2006/vcard/ns#', vcard: 'http://www.w3.org/2006/vcard/ns#',
} satisfies Context, } satisfies Context,

View file

@ -5,16 +5,15 @@
import { forwardRef, Inject, Injectable } from '@nestjs/common'; import { forwardRef, Inject, Injectable } from '@nestjs/common';
import { In } from 'typeorm'; import { In } from 'typeorm';
import * as Redis from 'ioredis';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import type { UsersRepository, PollsRepository, EmojisRepository } from '@/models/_.js'; import type { UsersRepository, PollsRepository, EmojisRepository } from '@/models/_.js';
import type { Config } from '@/config.js'; import type { Config } from '@/config.js';
import type { MiRemoteUser } from '@/models/User.js'; import type { MiRemoteUser } from '@/models/User.js';
import type { MiNote } from '@/models/Note.js'; import type { MiNote } from '@/models/Note.js';
import { acquireApObjectLock } from '@/misc/distributed-lock.js';
import { toArray, toSingle, unique } from '@/misc/prelude/array.js'; import { toArray, toSingle, unique } from '@/misc/prelude/array.js';
import type { MiEmoji } from '@/models/Emoji.js'; import type { MiEmoji } from '@/models/Emoji.js';
import { MetaService } from '@/core/MetaService.js'; import { MetaService } from '@/core/MetaService.js';
import { AppLockService } from '@/core/AppLockService.js';
import type { MiDriveFile } from '@/models/DriveFile.js'; import type { MiDriveFile } from '@/models/DriveFile.js';
import { NoteCreateService } from '@/core/NoteCreateService.js'; import { NoteCreateService } from '@/core/NoteCreateService.js';
import type Logger from '@/logger.js'; import type Logger from '@/logger.js';
@ -48,9 +47,6 @@ export class ApNoteService {
@Inject(DI.config) @Inject(DI.config)
private config: Config, private config: Config,
@Inject(DI.redisForTimelines)
private redisForTimelines: Redis.Redis,
@Inject(DI.usersRepository) @Inject(DI.usersRepository)
private usersRepository: UsersRepository, private usersRepository: UsersRepository,
@ -74,6 +70,7 @@ export class ApNoteService {
private apImageService: ApImageService, private apImageService: ApImageService,
private apQuestionService: ApQuestionService, private apQuestionService: ApQuestionService,
private metaService: MetaService, private metaService: MetaService,
private appLockService: AppLockService,
private pollService: PollService, private pollService: PollService,
private noteCreateService: NoteCreateService, private noteCreateService: NoteCreateService,
private apDbResolverService: ApDbResolverService, private apDbResolverService: ApDbResolverService,
@ -352,7 +349,7 @@ export class ApNoteService {
poll, poll,
uri: note.id, uri: note.id,
url: url, url: url,
}, silent) as MiNote; }, silent);
} catch (err: any) { } catch (err: any) {
if (err.name !== 'duplicated') { if (err.name !== 'duplicated') {
throw err; throw err;
@ -382,7 +379,7 @@ export class ApNoteService {
throw new StatusError('blocked host', 451); throw new StatusError('blocked host', 451);
} }
const unlock = await acquireApObjectLock(this.redisForTimelines, uri); const unlock = await this.appLockService.getApLock(uri);
try { try {
//#region このサーバーに既に登録されていたらそれを返す //#region このサーバーに既に登録されていたらそれを返す

View file

@ -328,8 +328,8 @@ export class ApPersonService implements OnModuleInit {
this.logger.error('error occurred while fetching following/followers collection', { error: err }); this.logger.error('error occurred while fetching following/followers collection', { error: err });
} }
return 'private'; return 'private';
}), })
), )
); );
const bday = person['vcard:bday']?.match(/^\d{4}-\d{2}-\d{2}/); const bday = person['vcard:bday']?.match(/^\d{4}-\d{2}-\d{2}/);
@ -378,7 +378,6 @@ export class ApPersonService implements OnModuleInit {
alsoKnownAs: person.alsoKnownAs, alsoKnownAs: person.alsoKnownAs,
isExplorable: person.discoverable, isExplorable: person.discoverable,
username: person.preferredUsername, username: person.preferredUsername,
approved: true,
usernameLower: person.preferredUsername?.toLowerCase(), usernameLower: person.preferredUsername?.toLowerCase(),
host, host,
inbox: person.inbox, inbox: person.inbox,
@ -389,7 +388,6 @@ export class ApPersonService implements OnModuleInit {
tags, tags,
isBot, isBot,
isCat: (person as any).isCat === true, isCat: (person as any).isCat === true,
speakAsCat: (person as any).speakAsCat != null ? (person as any).speakAsCat === true : (person as any).isCat === true,
emojis, emojis,
})) as MiRemoteUser; })) as MiRemoteUser;
@ -528,8 +526,8 @@ export class ApPersonService implements OnModuleInit {
return undefined; return undefined;
} }
return 'private'; return 'private';
}), })
), )
); );
const bday = person['vcard:bday']?.match(/^\d{4}-\d{2}-\d{2}/); const bday = person['vcard:bday']?.match(/^\d{4}-\d{2}-\d{2}/);
@ -563,13 +561,12 @@ export class ApPersonService implements OnModuleInit {
tags, tags,
isBot: getApType(object) === 'Service' || getApType(object) === 'Application', isBot: getApType(object) === 'Service' || getApType(object) === 'Application',
isCat: (person as any).isCat === true, isCat: (person as any).isCat === true,
speakAsCat: (person as any).speakAsCat != null ? (person as any).speakAsCat === true : (person as any).isCat === true,
isLocked: person.manuallyApprovesFollowers, isLocked: person.manuallyApprovesFollowers,
movedToUri: person.movedTo ?? null, movedToUri: person.movedTo ?? null,
alsoKnownAs: person.alsoKnownAs ?? null, alsoKnownAs: person.alsoKnownAs ?? null,
isExplorable: person.discoverable, isExplorable: person.discoverable,
...((policy.canUpdateAvatar || policy.canUpdateBanner) ? await this.resolveAvatarAndBanner(exist, policy.canUpdateAvatar ? person.icon : exist.avatarUrl, policy.canUpdateBanner ? person.image : exist.bannerUrl).catch(() => ({})) : {}), ...((policy.canUpdateAvatar || policy.canUpdateBanner) ? await this.resolveAvatarAndBanner(exist, policy.canUpdateAvatar ? person.icon : exist.avatarUrl, policy.canUpdateBanner ? person.image : exist.bannerUrl).catch(() => ({})) : {}),
} as Partial<MiRemoteUser> & Pick<MiRemoteUser, 'isBot' | 'isCat' | 'speakAsCat' | 'isLocked' | 'movedToUri' | 'alsoKnownAs' | 'isExplorable'>; } as Partial<MiRemoteUser> & Pick<MiRemoteUser, 'isBot' | 'isCat' | 'isLocked' | 'movedToUri' | 'alsoKnownAs' | 'isExplorable'>;
const moving = ((): boolean => { const moving = ((): boolean => {
// 移行先がない→ある // 移行先がない→ある

View file

@ -58,9 +58,9 @@ export class ChartManagementService implements OnApplicationShutdown {
@bindThis @bindThis
public async start() { public async start() {
// 20分おきにメモリ情報をDBに書き込み // 20分おきにメモリ情報をDBに書き込み
this.saveIntervalId = setInterval(async () => { this.saveIntervalId = setInterval(() => {
for (const chart of this.charts) { for (const chart of this.charts) {
await chart.save(); chart.save();
} }
}, 1000 * 60 * 20); }, 1000 * 60 * 20);
} }
@ -69,9 +69,9 @@ export class ChartManagementService implements OnApplicationShutdown {
public async dispose(): Promise<void> { public async dispose(): Promise<void> {
clearInterval(this.saveIntervalId); clearInterval(this.saveIntervalId);
if (process.env.NODE_ENV !== 'test') { if (process.env.NODE_ENV !== 'test') {
for (const chart of this.charts) { await Promise.all(
await chart.save(); this.charts.map(chart => chart.save()),
} );
} }
} }

View file

@ -5,12 +5,11 @@
import { Injectable, Inject } from '@nestjs/common'; import { Injectable, Inject } from '@nestjs/common';
import { DataSource } from 'typeorm'; import { DataSource } from 'typeorm';
import * as Redis from 'ioredis'; import { AppLockService } from '@/core/AppLockService.js';
import type { MiUser } from '@/models/User.js'; import type { MiUser } from '@/models/User.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { IdService } from '@/core/IdService.js'; import { IdService } from '@/core/IdService.js';
import { acquireChartInsertLock } from '@/misc/distributed-lock.js';
import Chart from '../core.js'; import Chart from '../core.js';
import { ChartLoggerService } from '../ChartLoggerService.js'; import { ChartLoggerService } from '../ChartLoggerService.js';
import { name, schema } from './entities/active-users.js'; import { name, schema } from './entities/active-users.js';
@ -29,13 +28,11 @@ export default class ActiveUsersChart extends Chart<typeof schema> { // eslint-d
@Inject(DI.db) @Inject(DI.db)
private db: DataSource, private db: DataSource,
@Inject(DI.redisForTimelines) private appLockService: AppLockService,
private redisForTimelines: Redis.Redis,
private chartLoggerService: ChartLoggerService, private chartLoggerService: ChartLoggerService,
private idService: IdService, private idService: IdService,
) { ) {
super(db, (k) => acquireChartInsertLock(redisForTimelines, k), chartLoggerService.logger, name, schema); super(db, (k) => appLockService.getChartInsertLock(k), chartLoggerService.logger, name, schema);
} }
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> { protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {

View file

@ -5,10 +5,9 @@
import { Injectable, Inject } from '@nestjs/common'; import { Injectable, Inject } from '@nestjs/common';
import { DataSource } from 'typeorm'; import { DataSource } from 'typeorm';
import * as Redis from 'ioredis'; import { AppLockService } from '@/core/AppLockService.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { acquireChartInsertLock } from '@/misc/distributed-lock.js';
import Chart from '../core.js'; import Chart from '../core.js';
import { ChartLoggerService } from '../ChartLoggerService.js'; import { ChartLoggerService } from '../ChartLoggerService.js';
import { name, schema } from './entities/ap-request.js'; import { name, schema } from './entities/ap-request.js';
@ -23,12 +22,10 @@ export default class ApRequestChart extends Chart<typeof schema> { // eslint-dis
@Inject(DI.db) @Inject(DI.db)
private db: DataSource, private db: DataSource,
@Inject(DI.redisForTimelines) private appLockService: AppLockService,
private redisForTimelines: Redis.Redis,
private chartLoggerService: ChartLoggerService, private chartLoggerService: ChartLoggerService,
) { ) {
super(db, (k) => acquireChartInsertLock(redisForTimelines, k), chartLoggerService.logger, name, schema); super(db, (k) => appLockService.getChartInsertLock(k), chartLoggerService.logger, name, schema);
} }
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> { protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {

View file

@ -5,11 +5,10 @@
import { Injectable, Inject } from '@nestjs/common'; import { Injectable, Inject } from '@nestjs/common';
import { DataSource } from 'typeorm'; import { DataSource } from 'typeorm';
import * as Redis from 'ioredis';
import type { MiDriveFile } from '@/models/DriveFile.js'; import type { MiDriveFile } from '@/models/DriveFile.js';
import { AppLockService } from '@/core/AppLockService.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { acquireChartInsertLock } from '@/misc/distributed-lock.js';
import Chart from '../core.js'; import Chart from '../core.js';
import { ChartLoggerService } from '../ChartLoggerService.js'; import { ChartLoggerService } from '../ChartLoggerService.js';
import { name, schema } from './entities/drive.js'; import { name, schema } from './entities/drive.js';
@ -24,12 +23,10 @@ export default class DriveChart extends Chart<typeof schema> { // eslint-disable
@Inject(DI.db) @Inject(DI.db)
private db: DataSource, private db: DataSource,
@Inject(DI.redisForTimelines) private appLockService: AppLockService,
private redisForTimelines: Redis.Redis,
private chartLoggerService: ChartLoggerService, private chartLoggerService: ChartLoggerService,
) { ) {
super(db, (k) => acquireChartInsertLock(redisForTimelines, k), chartLoggerService.logger, name, schema); super(db, (k) => appLockService.getChartInsertLock(k), chartLoggerService.logger, name, schema);
} }
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> { protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {

View file

@ -5,12 +5,11 @@
import { Injectable, Inject } from '@nestjs/common'; import { Injectable, Inject } from '@nestjs/common';
import { DataSource } from 'typeorm'; import { DataSource } from 'typeorm';
import * as Redis from 'ioredis';
import type { FollowingsRepository, InstancesRepository } from '@/models/_.js'; import type { FollowingsRepository, InstancesRepository } from '@/models/_.js';
import { AppLockService } from '@/core/AppLockService.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { MetaService } from '@/core/MetaService.js'; import { MetaService } from '@/core/MetaService.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { acquireChartInsertLock } from '@/misc/distributed-lock.js';
import Chart from '../core.js'; import Chart from '../core.js';
import { ChartLoggerService } from '../ChartLoggerService.js'; import { ChartLoggerService } from '../ChartLoggerService.js';
import { name, schema } from './entities/federation.js'; import { name, schema } from './entities/federation.js';
@ -25,9 +24,6 @@ export default class FederationChart extends Chart<typeof schema> { // eslint-di
@Inject(DI.db) @Inject(DI.db)
private db: DataSource, private db: DataSource,
@Inject(DI.redisForTimelines)
private redisForTimelines: Redis.Redis,
@Inject(DI.followingsRepository) @Inject(DI.followingsRepository)
private followingsRepository: FollowingsRepository, private followingsRepository: FollowingsRepository,
@ -35,9 +31,10 @@ export default class FederationChart extends Chart<typeof schema> { // eslint-di
private instancesRepository: InstancesRepository, private instancesRepository: InstancesRepository,
private metaService: MetaService, private metaService: MetaService,
private appLockService: AppLockService,
private chartLoggerService: ChartLoggerService, private chartLoggerService: ChartLoggerService,
) { ) {
super(db, (k) => acquireChartInsertLock(redisForTimelines, k), chartLoggerService.logger, name, schema); super(db, (k) => appLockService.getChartInsertLock(k), chartLoggerService.logger, name, schema);
} }
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> { protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {

View file

@ -5,14 +5,13 @@
import { Injectable, Inject } from '@nestjs/common'; import { Injectable, Inject } from '@nestjs/common';
import { DataSource } from 'typeorm'; import { DataSource } from 'typeorm';
import * as Redis from 'ioredis';
import type { DriveFilesRepository, FollowingsRepository, UsersRepository, NotesRepository } from '@/models/_.js'; import type { DriveFilesRepository, FollowingsRepository, UsersRepository, NotesRepository } from '@/models/_.js';
import type { MiDriveFile } from '@/models/DriveFile.js'; import type { MiDriveFile } from '@/models/DriveFile.js';
import type { MiNote } from '@/models/Note.js'; import type { MiNote } from '@/models/Note.js';
import { AppLockService } from '@/core/AppLockService.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { UtilityService } from '@/core/UtilityService.js'; import { UtilityService } from '@/core/UtilityService.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { acquireChartInsertLock } from '@/misc/distributed-lock.js';
import Chart from '../core.js'; import Chart from '../core.js';
import { ChartLoggerService } from '../ChartLoggerService.js'; import { ChartLoggerService } from '../ChartLoggerService.js';
import { name, schema } from './entities/instance.js'; import { name, schema } from './entities/instance.js';
@ -27,9 +26,6 @@ export default class InstanceChart extends Chart<typeof schema> { // eslint-disa
@Inject(DI.db) @Inject(DI.db)
private db: DataSource, private db: DataSource,
@Inject(DI.redisForTimelines)
private redisForTimelines: Redis.Redis,
@Inject(DI.usersRepository) @Inject(DI.usersRepository)
private usersRepository: UsersRepository, private usersRepository: UsersRepository,
@ -43,9 +39,10 @@ export default class InstanceChart extends Chart<typeof schema> { // eslint-disa
private followingsRepository: FollowingsRepository, private followingsRepository: FollowingsRepository,
private utilityService: UtilityService, private utilityService: UtilityService,
private appLockService: AppLockService,
private chartLoggerService: ChartLoggerService, private chartLoggerService: ChartLoggerService,
) { ) {
super(db, (k) => acquireChartInsertLock(redisForTimelines, k), chartLoggerService.logger, name, schema, true); super(db, (k) => appLockService.getChartInsertLock(k), chartLoggerService.logger, name, schema, true);
} }
protected async tickMajor(group: string): Promise<Partial<KVs<typeof schema>>> { protected async tickMajor(group: string): Promise<Partial<KVs<typeof schema>>> {

View file

@ -5,12 +5,11 @@
import { Injectable, Inject } from '@nestjs/common'; import { Injectable, Inject } from '@nestjs/common';
import { Not, IsNull, DataSource } from 'typeorm'; import { Not, IsNull, DataSource } from 'typeorm';
import * as Redis from 'ioredis';
import type { NotesRepository } from '@/models/_.js'; import type { NotesRepository } from '@/models/_.js';
import type { MiNote } from '@/models/Note.js'; import type { MiNote } from '@/models/Note.js';
import { AppLockService } from '@/core/AppLockService.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { acquireChartInsertLock } from '@/misc/distributed-lock.js';
import Chart from '../core.js'; import Chart from '../core.js';
import { ChartLoggerService } from '../ChartLoggerService.js'; import { ChartLoggerService } from '../ChartLoggerService.js';
import { name, schema } from './entities/notes.js'; import { name, schema } from './entities/notes.js';
@ -25,15 +24,13 @@ export default class NotesChart extends Chart<typeof schema> { // eslint-disable
@Inject(DI.db) @Inject(DI.db)
private db: DataSource, private db: DataSource,
@Inject(DI.redisForTimelines)
private redisForTimelines: Redis.Redis,
@Inject(DI.notesRepository) @Inject(DI.notesRepository)
private notesRepository: NotesRepository, private notesRepository: NotesRepository,
private appLockService: AppLockService,
private chartLoggerService: ChartLoggerService, private chartLoggerService: ChartLoggerService,
) { ) {
super(db, (k) => acquireChartInsertLock(redisForTimelines, k), chartLoggerService.logger, name, schema); super(db, (k) => appLockService.getChartInsertLock(k), chartLoggerService.logger, name, schema);
} }
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> { protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {

View file

@ -5,13 +5,12 @@
import { Injectable, Inject } from '@nestjs/common'; import { Injectable, Inject } from '@nestjs/common';
import { DataSource } from 'typeorm'; import { DataSource } from 'typeorm';
import * as Redis from 'ioredis';
import type { DriveFilesRepository } from '@/models/_.js'; import type { DriveFilesRepository } from '@/models/_.js';
import type { MiDriveFile } from '@/models/DriveFile.js'; import type { MiDriveFile } from '@/models/DriveFile.js';
import { AppLockService } from '@/core/AppLockService.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js'; import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { acquireChartInsertLock } from '@/misc/distributed-lock.js';
import Chart from '../core.js'; import Chart from '../core.js';
import { ChartLoggerService } from '../ChartLoggerService.js'; import { ChartLoggerService } from '../ChartLoggerService.js';
import { name, schema } from './entities/per-user-drive.js'; import { name, schema } from './entities/per-user-drive.js';
@ -26,16 +25,14 @@ export default class PerUserDriveChart extends Chart<typeof schema> { // eslint-
@Inject(DI.db) @Inject(DI.db)
private db: DataSource, private db: DataSource,
@Inject(DI.redisForTimelines)
private redisForTimelines: Redis.Redis,
@Inject(DI.driveFilesRepository) @Inject(DI.driveFilesRepository)
private driveFilesRepository: DriveFilesRepository, private driveFilesRepository: DriveFilesRepository,
private appLockService: AppLockService,
private driveFileEntityService: DriveFileEntityService, private driveFileEntityService: DriveFileEntityService,
private chartLoggerService: ChartLoggerService, private chartLoggerService: ChartLoggerService,
) { ) {
super(db, (k) => acquireChartInsertLock(redisForTimelines, k), chartLoggerService.logger, name, schema, true); super(db, (k) => appLockService.getChartInsertLock(k), chartLoggerService.logger, name, schema, true);
} }
protected async tickMajor(group: string): Promise<Partial<KVs<typeof schema>>> { protected async tickMajor(group: string): Promise<Partial<KVs<typeof schema>>> {

View file

@ -5,13 +5,12 @@
import { Injectable, Inject } from '@nestjs/common'; import { Injectable, Inject } from '@nestjs/common';
import { Not, IsNull, DataSource } from 'typeorm'; import { Not, IsNull, DataSource } from 'typeorm';
import * as Redis from 'ioredis';
import type { MiUser } from '@/models/User.js'; import type { MiUser } from '@/models/User.js';
import { AppLockService } from '@/core/AppLockService.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js';
import type { FollowingsRepository } from '@/models/_.js'; import type { FollowingsRepository } from '@/models/_.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { acquireChartInsertLock } from '@/misc/distributed-lock.js';
import Chart from '../core.js'; import Chart from '../core.js';
import { ChartLoggerService } from '../ChartLoggerService.js'; import { ChartLoggerService } from '../ChartLoggerService.js';
import { name, schema } from './entities/per-user-following.js'; import { name, schema } from './entities/per-user-following.js';
@ -26,16 +25,14 @@ export default class PerUserFollowingChart extends Chart<typeof schema> { // esl
@Inject(DI.db) @Inject(DI.db)
private db: DataSource, private db: DataSource,
@Inject(DI.redisForTimelines)
private redisForTimelines: Redis.Redis,
@Inject(DI.followingsRepository) @Inject(DI.followingsRepository)
private followingsRepository: FollowingsRepository, private followingsRepository: FollowingsRepository,
private appLockService: AppLockService,
private userEntityService: UserEntityService, private userEntityService: UserEntityService,
private chartLoggerService: ChartLoggerService, private chartLoggerService: ChartLoggerService,
) { ) {
super(db, (k) => acquireChartInsertLock(redisForTimelines, k), chartLoggerService.logger, name, schema, true); super(db, (k) => appLockService.getChartInsertLock(k), chartLoggerService.logger, name, schema, true);
} }
protected async tickMajor(group: string): Promise<Partial<KVs<typeof schema>>> { protected async tickMajor(group: string): Promise<Partial<KVs<typeof schema>>> {

View file

@ -5,13 +5,12 @@
import { Injectable, Inject } from '@nestjs/common'; import { Injectable, Inject } from '@nestjs/common';
import { DataSource } from 'typeorm'; import { DataSource } from 'typeorm';
import * as Redis from 'ioredis';
import type { MiUser } from '@/models/User.js'; import type { MiUser } from '@/models/User.js';
import type { MiNote } from '@/models/Note.js'; import type { MiNote } from '@/models/Note.js';
import { AppLockService } from '@/core/AppLockService.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import type { NotesRepository } from '@/models/_.js'; import type { NotesRepository } from '@/models/_.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { acquireChartInsertLock } from '@/misc/distributed-lock.js';
import Chart from '../core.js'; import Chart from '../core.js';
import { ChartLoggerService } from '../ChartLoggerService.js'; import { ChartLoggerService } from '../ChartLoggerService.js';
import { name, schema } from './entities/per-user-notes.js'; import { name, schema } from './entities/per-user-notes.js';
@ -26,15 +25,13 @@ export default class PerUserNotesChart extends Chart<typeof schema> { // eslint-
@Inject(DI.db) @Inject(DI.db)
private db: DataSource, private db: DataSource,
@Inject(DI.redisForTimelines)
private redisForTimelines: Redis.Redis,
@Inject(DI.notesRepository) @Inject(DI.notesRepository)
private notesRepository: NotesRepository, private notesRepository: NotesRepository,
private appLockService: AppLockService,
private chartLoggerService: ChartLoggerService, private chartLoggerService: ChartLoggerService,
) { ) {
super(db, (k) => acquireChartInsertLock(redisForTimelines, k), chartLoggerService.logger, name, schema, true); super(db, (k) => appLockService.getChartInsertLock(k), chartLoggerService.logger, name, schema, true);
} }
protected async tickMajor(group: string): Promise<Partial<KVs<typeof schema>>> { protected async tickMajor(group: string): Promise<Partial<KVs<typeof schema>>> {

Some files were not shown because too many files have changed in this diff Show more