Merge branch 'develop' into fix-10650
This commit is contained in:
commit
7db0971aa9
2
.github/workflows/api-misskey-js.yml
vendored
2
.github/workflows/api-misskey-js.yml
vendored
|
@ -20,7 +20,7 @@ jobs:
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v4.0.1
|
uses: actions/setup-node@v4.0.2
|
||||||
with:
|
with:
|
||||||
node-version-file: '.node-version'
|
node-version-file: '.node-version'
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
2
.github/workflows/changelog-check.yml
vendored
2
.github/workflows/changelog-check.yml
vendored
|
@ -14,7 +14,7 @@ jobs:
|
||||||
- name: Checkout head
|
- name: Checkout head
|
||||||
uses: actions/checkout@v4.1.1
|
uses: actions/checkout@v4.1.1
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v4.0.1
|
uses: actions/setup-node@v4.0.2
|
||||||
with:
|
with:
|
||||||
node-version-file: '.node-version'
|
node-version-file: '.node-version'
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4.1.1
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
|
@ -31,7 +31,7 @@ jobs:
|
||||||
|
|
||||||
- name: setup node
|
- name: setup node
|
||||||
id: setup-node
|
id: setup-node
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4.0.2
|
||||||
with:
|
with:
|
||||||
node-version-file: '.node-version'
|
node-version-file: '.node-version'
|
||||||
cache: pnpm
|
cache: pnpm
|
||||||
|
@ -48,7 +48,7 @@ jobs:
|
||||||
wait-interval: 30
|
wait-interval: 30
|
||||||
|
|
||||||
- name: Download artifact
|
- name: Download artifact
|
||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v7.0.1
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|
|
@ -28,7 +28,7 @@ jobs:
|
||||||
wait_time: ${{ steps.get-wait-time.outputs.wait_time }}
|
wait_time: ${{ steps.get-wait-time.outputs.wait_time }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4.1.1
|
||||||
|
|
||||||
- name: Check allowed users
|
- name: Check allowed users
|
||||||
id: check-allowed-users
|
id: check-allowed-users
|
||||||
|
|
75
.github/workflows/docker-develop.yml
vendored
75
.github/workflows/docker-develop.yml
vendored
|
@ -6,38 +6,83 @@ on:
|
||||||
- develop
|
- develop
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY_IMAGE: misskey/misskey
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
push_to_registry:
|
# see https://docs.docker.com/build/ci/github-actions/multi-platform/#distribute-build-across-multiple-runners
|
||||||
name: Push Docker image to Docker Hub
|
build:
|
||||||
|
name: Build
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
platform:
|
||||||
|
- linux/amd64
|
||||||
|
- linux/arm64
|
||||||
if: github.repository == 'misskey-dev/misskey'
|
if: github.repository == 'misskey-dev/misskey'
|
||||||
steps:
|
steps:
|
||||||
|
- name: Prepare
|
||||||
|
run: |
|
||||||
|
platform=${{ matrix.platform }}
|
||||||
|
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||||
- name: Check out the repo
|
- name: Check out the repo
|
||||||
uses: actions/checkout@v4.1.1
|
uses: actions/checkout@v4.1.1
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
id: buildx
|
uses: docker/setup-buildx-action@v3
|
||||||
uses: docker/setup-buildx-action@v3.0.0
|
|
||||||
with:
|
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
- name: Docker meta
|
|
||||||
id: meta
|
|
||||||
uses: docker/metadata-action@v5
|
|
||||||
with:
|
|
||||||
images: misskey/misskey
|
|
||||||
- name: Log in to Docker Hub
|
- name: Log in to Docker Hub
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
- name: Build and Push to Docker Hub
|
- name: Build and push by digest
|
||||||
|
id: build
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
builder: ${{ steps.buildx.outputs.name }}
|
|
||||||
context: .
|
context: .
|
||||||
push: true
|
push: true
|
||||||
platforms: ${{ steps.buildx.outputs.platforms }}
|
platforms: ${{ matrix.platform }}
|
||||||
provenance: false
|
provenance: false
|
||||||
tags: misskey/misskey:develop
|
|
||||||
labels: develop
|
labels: develop
|
||||||
cache-from: type=gha
|
cache-from: type=gha
|
||||||
cache-to: type=gha,mode=max
|
cache-to: type=gha,mode=max
|
||||||
|
outputs: type=image,name=${{ env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true
|
||||||
|
- name: Export digest
|
||||||
|
run: |
|
||||||
|
mkdir -p /tmp/digests
|
||||||
|
digest="${{ steps.build.outputs.digest }}"
|
||||||
|
touch "/tmp/digests/${digest#sha256:}"
|
||||||
|
- name: Upload digest
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: digests-${{ env.PLATFORM_PAIR }}
|
||||||
|
path: /tmp/digests/*
|
||||||
|
if-no-files-found: error
|
||||||
|
retention-days: 1
|
||||||
|
|
||||||
|
merge:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- build
|
||||||
|
steps:
|
||||||
|
- name: Download digests
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
path: /tmp/digests
|
||||||
|
pattern: digests-*
|
||||||
|
merge-multiple: true
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
- name: Create manifest list and push
|
||||||
|
working-directory: /tmp/digests
|
||||||
|
run: |
|
||||||
|
docker buildx imagetools create --tag ${{ env.REGISTRY_IMAGE }}:develop \
|
||||||
|
$(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *)
|
||||||
|
- name: Inspect image
|
||||||
|
run: |
|
||||||
|
docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:develop
|
||||||
|
|
100
.github/workflows/docker.yml
vendored
100
.github/workflows/docker.yml
vendored
|
@ -5,45 +5,101 @@ on:
|
||||||
types: [published]
|
types: [published]
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
env:
|
||||||
push_to_registry:
|
REGISTRY_IMAGE: misskey/misskey
|
||||||
name: Push Docker image to Docker Hub
|
TAGS: |
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Check out the repo
|
|
||||||
uses: actions/checkout@v4.1.1
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
id: buildx
|
|
||||||
uses: docker/setup-buildx-action@v3.0.0
|
|
||||||
with:
|
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
- name: Docker meta
|
|
||||||
id: meta
|
|
||||||
uses: docker/metadata-action@v5
|
|
||||||
with:
|
|
||||||
images: misskey/misskey
|
|
||||||
tags: |
|
|
||||||
type=edge
|
type=edge
|
||||||
type=ref,event=pr
|
type=ref,event=pr
|
||||||
type=ref,event=branch
|
type=ref,event=branch
|
||||||
type=semver,pattern={{version}}
|
type=semver,pattern={{version}}
|
||||||
type=semver,pattern={{major}}.{{minor}}
|
type=semver,pattern={{major}}.{{minor}}
|
||||||
type=semver,pattern={{major}}
|
type=semver,pattern={{major}}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# see https://docs.docker.com/build/ci/github-actions/multi-platform/#distribute-build-across-multiple-runners
|
||||||
|
build:
|
||||||
|
name: Build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
platform:
|
||||||
|
- linux/amd64
|
||||||
|
- linux/arm64
|
||||||
|
steps:
|
||||||
|
- name: Prepare
|
||||||
|
run: |
|
||||||
|
platform=${{ matrix.platform }}
|
||||||
|
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||||
|
- name: Check out the repo
|
||||||
|
uses: actions/checkout@v4.1.1
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
- name: Docker meta
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: ${{ env.REGISTRY_IMAGE }}
|
||||||
|
tags: ${{ env.TAGS }}
|
||||||
- name: Log in to Docker Hub
|
- name: Log in to Docker Hub
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
- name: Build and Push to Docker Hub
|
- name: Build and Push to Docker Hub
|
||||||
|
id: build
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
builder: ${{ steps.buildx.outputs.name }}
|
|
||||||
context: .
|
context: .
|
||||||
push: true
|
push: true
|
||||||
platforms: ${{ steps.buildx.outputs.platforms }}
|
platforms: ${{ matrix.platform }}
|
||||||
provenance: false
|
provenance: false
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
cache-from: type=gha
|
cache-from: type=gha
|
||||||
cache-to: type=gha,mode=max
|
cache-to: type=gha,mode=max
|
||||||
|
outputs: type=image,name=${{ env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true
|
||||||
|
- name: Export digest
|
||||||
|
run: |
|
||||||
|
mkdir -p /tmp/digests
|
||||||
|
digest="${{ steps.build.outputs.digest }}"
|
||||||
|
touch "/tmp/digests/${digest#sha256:}"
|
||||||
|
- name: Upload digest
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: digests-${{ env.PLATFORM_PAIR }}
|
||||||
|
path: /tmp/digests/*
|
||||||
|
if-no-files-found: error
|
||||||
|
retention-days: 1
|
||||||
|
|
||||||
|
merge:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- build
|
||||||
|
steps:
|
||||||
|
- name: Download digests
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
path: /tmp/digests
|
||||||
|
pattern: digests-*
|
||||||
|
merge-multiple: true
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
- name: Docker meta
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: ${{ env.REGISTRY_IMAGE }}
|
||||||
|
tags: ${{ env.TAGS }}
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
- name: Create manifest list and push
|
||||||
|
working-directory: /tmp/digests
|
||||||
|
run: |
|
||||||
|
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
|
||||||
|
$(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *)
|
||||||
|
- name: Inspect image
|
||||||
|
run: |
|
||||||
|
docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.version }}
|
||||||
|
|
2
.github/workflows/get-api-diff.yml
vendored
2
.github/workflows/get-api-diff.yml
vendored
|
@ -37,7 +37,7 @@ jobs:
|
||||||
version: 8
|
version: 8
|
||||||
run_install: false
|
run_install: false
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v4.0.1
|
uses: actions/setup-node@v4.0.2
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
6
.github/workflows/lint.yml
vendored
6
.github/workflows/lint.yml
vendored
|
@ -31,7 +31,7 @@ jobs:
|
||||||
with:
|
with:
|
||||||
version: 8
|
version: 8
|
||||||
run_install: false
|
run_install: false
|
||||||
- uses: actions/setup-node@v4.0.1
|
- uses: actions/setup-node@v4.0.2
|
||||||
with:
|
with:
|
||||||
node-version-file: '.node-version'
|
node-version-file: '.node-version'
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
@ -58,7 +58,7 @@ jobs:
|
||||||
with:
|
with:
|
||||||
version: 7
|
version: 7
|
||||||
run_install: false
|
run_install: false
|
||||||
- uses: actions/setup-node@v4.0.1
|
- uses: actions/setup-node@v4.0.2
|
||||||
with:
|
with:
|
||||||
node-version-file: '.node-version'
|
node-version-file: '.node-version'
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
@ -84,7 +84,7 @@ jobs:
|
||||||
with:
|
with:
|
||||||
version: 7
|
version: 7
|
||||||
run_install: false
|
run_install: false
|
||||||
- uses: actions/setup-node@v4.0.1
|
- uses: actions/setup-node@v4.0.2
|
||||||
with:
|
with:
|
||||||
node-version-file: '.node-version'
|
node-version-file: '.node-version'
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
4
.github/workflows/on-release-created.yml
vendored
4
.github/workflows/on-release-created.yml
vendored
|
@ -20,7 +20,7 @@ jobs:
|
||||||
node-version: [20.10.0]
|
node-version: [20.10.0]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4.1.1
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Install pnpm
|
- name: Install pnpm
|
||||||
|
@ -29,7 +29,7 @@ jobs:
|
||||||
version: 8
|
version: 8
|
||||||
run_install: false
|
run_install: false
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4.0.2
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
6
.github/workflows/pr-preview-deploy.yml
vendored
6
.github/workflows/pr-preview-deploy.yml
vendored
|
@ -13,7 +13,7 @@ jobs:
|
||||||
github.event.client_payload.slash_command.sha != '' &&
|
github.event.client_payload.slash_command.sha != '' &&
|
||||||
contains(github.event.client_payload.pull_request.head.sha, github.event.client_payload.slash_command.sha)
|
contains(github.event.client_payload.pull_request.head.sha, github.event.client_payload.slash_command.sha)
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/github-script@v7
|
- uses: actions/github-script@v7.0.1
|
||||||
id: check-id
|
id: check-id
|
||||||
env:
|
env:
|
||||||
number: ${{ github.event.client_payload.pull_request.number }}
|
number: ${{ github.event.client_payload.pull_request.number }}
|
||||||
|
@ -37,7 +37,7 @@ jobs:
|
||||||
|
|
||||||
return check[0].id;
|
return check[0].id;
|
||||||
|
|
||||||
- uses: actions/github-script@v7
|
- uses: actions/github-script@v7.0.1
|
||||||
env:
|
env:
|
||||||
check_id: ${{ steps.check-id.outputs.result }}
|
check_id: ${{ steps.check-id.outputs.result }}
|
||||||
details_url: ${{ github.server_url }}/${{ github.repository }}/runs/${{ github.run_id }}
|
details_url: ${{ github.server_url }}/${{ github.repository }}/runs/${{ github.run_id }}
|
||||||
|
@ -72,7 +72,7 @@ jobs:
|
||||||
timeout: 15m
|
timeout: 15m
|
||||||
|
|
||||||
# Update check run called "integration-fork"
|
# Update check run called "integration-fork"
|
||||||
- uses: actions/github-script@v7
|
- uses: actions/github-script@v7.0.1
|
||||||
id: update-check-run
|
id: update-check-run
|
||||||
if: ${{ always() }}
|
if: ${{ always() }}
|
||||||
env:
|
env:
|
||||||
|
|
2
.github/workflows/pr-preview-destroy.yml
vendored
2
.github/workflows/pr-preview-destroy.yml
vendored
|
@ -10,7 +10,7 @@ jobs:
|
||||||
destroy-preview-environment:
|
destroy-preview-environment:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/github-script@v7
|
- uses: actions/github-script@v7.0.1
|
||||||
id: check-conclusion
|
id: check-conclusion
|
||||||
env:
|
env:
|
||||||
number: ${{ github.event.number }}
|
number: ${{ github.event.number }}
|
||||||
|
|
2
.github/workflows/report-api-diff.yml
vendored
2
.github/workflows/report-api-diff.yml
vendored
|
@ -16,7 +16,7 @@ jobs:
|
||||||
# api-artifact
|
# api-artifact
|
||||||
steps:
|
steps:
|
||||||
- name: Download artifact
|
- name: Download artifact
|
||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v7.0.1
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|
12
.github/workflows/storybook.yml
vendored
12
.github/workflows/storybook.yml
vendored
|
@ -16,12 +16,12 @@ jobs:
|
||||||
NODE_OPTIONS: "--max_old_space_size=7168"
|
NODE_OPTIONS: "--max_old_space_size=7168"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3.6.0
|
- uses: actions/checkout@v4.1.1
|
||||||
if: github.event_name != 'pull_request_target'
|
if: github.event_name != 'pull_request_target'
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
submodules: true
|
submodules: true
|
||||||
- uses: actions/checkout@v3.6.0
|
- uses: actions/checkout@v4.1.1
|
||||||
if: github.event_name == 'pull_request_target'
|
if: github.event_name == 'pull_request_target'
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
@ -34,12 +34,12 @@ jobs:
|
||||||
echo "base=$(git rev-list --parents -n1 HEAD | cut -d" " -f2)" >> $GITHUB_OUTPUT
|
echo "base=$(git rev-list --parents -n1 HEAD | cut -d" " -f2)" >> $GITHUB_OUTPUT
|
||||||
git checkout $(git rev-list --parents -n1 HEAD | cut -d" " -f3)
|
git checkout $(git rev-list --parents -n1 HEAD | cut -d" " -f3)
|
||||||
- name: Install pnpm
|
- name: Install pnpm
|
||||||
uses: pnpm/action-setup@v2
|
uses: pnpm/action-setup@v3
|
||||||
with:
|
with:
|
||||||
version: 8
|
version: 8
|
||||||
run_install: false
|
run_install: false
|
||||||
- name: Use Node.js 20.x
|
- name: Use Node.js 20.x
|
||||||
uses: actions/setup-node@v3.8.1
|
uses: actions/setup-node@v4.0.2
|
||||||
with:
|
with:
|
||||||
node-version-file: '.node-version'
|
node-version-file: '.node-version'
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
@ -95,7 +95,7 @@ jobs:
|
||||||
env:
|
env:
|
||||||
CHROMATIC_PROJECT_TOKEN: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
|
CHROMATIC_PROJECT_TOKEN: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
|
||||||
- name: Notify that Chromatic detects changes
|
- name: Notify that Chromatic detects changes
|
||||||
uses: actions/github-script@v6.4.0
|
uses: actions/github-script@v7.0.1
|
||||||
if: github.event_name != 'pull_request_target' && steps.chromatic_push.outputs.success == 'false'
|
if: github.event_name != 'pull_request_target' && steps.chromatic_push.outputs.success == 'false'
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
@ -107,7 +107,7 @@ jobs:
|
||||||
body: 'Chromatic detects changes. Please [review the changes on Chromatic](https://www.chromatic.com/builds?appId=6428f7d7b962f0b79f97d6e4).'
|
body: 'Chromatic detects changes. Please [review the changes on Chromatic](https://www.chromatic.com/builds?appId=6428f7d7b962f0b79f97d6e4).'
|
||||||
})
|
})
|
||||||
- name: Upload Artifacts
|
- name: Upload Artifacts
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: storybook
|
name: storybook
|
||||||
path: packages/frontend/storybook-static
|
path: packages/frontend/storybook-static
|
||||||
|
|
4
.github/workflows/test-backend.yml
vendored
4
.github/workflows/test-backend.yml
vendored
|
@ -46,7 +46,7 @@ jobs:
|
||||||
version: 8
|
version: 8
|
||||||
run_install: false
|
run_install: false
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v4.0.1
|
uses: actions/setup-node@v4.0.2
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
@ -96,7 +96,7 @@ jobs:
|
||||||
version: 8
|
version: 8
|
||||||
run_install: false
|
run_install: false
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v4.0.1
|
uses: actions/setup-node@v4.0.2
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
4
.github/workflows/test-frontend.yml
vendored
4
.github/workflows/test-frontend.yml
vendored
|
@ -38,7 +38,7 @@ jobs:
|
||||||
version: 8
|
version: 8
|
||||||
run_install: false
|
run_install: false
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v4.0.1
|
uses: actions/setup-node@v4.0.2
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
@ -96,7 +96,7 @@ jobs:
|
||||||
version: 7
|
version: 7
|
||||||
run_install: false
|
run_install: false
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v4.0.1
|
uses: actions/setup-node@v4.0.2
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
2
.github/workflows/test-misskey-js.yml
vendored
2
.github/workflows/test-misskey-js.yml
vendored
|
@ -30,7 +30,7 @@ jobs:
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
|
|
||||||
- name: Setup Node.js ${{ matrix.node-version }}
|
- name: Setup Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v4.0.1
|
uses: actions/setup-node@v4.0.2
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
2
.github/workflows/test-production.yml
vendored
2
.github/workflows/test-production.yml
vendored
|
@ -28,7 +28,7 @@ jobs:
|
||||||
version: 8
|
version: 8
|
||||||
run_install: false
|
run_install: false
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v4.0.1
|
uses: actions/setup-node@v4.0.2
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
2
.github/workflows/validate-api-json.yml
vendored
2
.github/workflows/validate-api-json.yml
vendored
|
@ -29,7 +29,7 @@ jobs:
|
||||||
version: 8
|
version: 8
|
||||||
run_install: false
|
run_install: false
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v4.0.1
|
uses: actions/setup-node@v4.0.2
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -19,11 +19,11 @@
|
||||||
|
|
||||||
### General
|
### General
|
||||||
- Feat: [mCaptcha](https://github.com/mCaptcha/mCaptcha)のサポートを追加
|
- Feat: [mCaptcha](https://github.com/mCaptcha/mCaptcha)のサポートを追加
|
||||||
- Fix: リストライムラインの「リノートを表示」が正しく機能しない問題を修正
|
|
||||||
- Feat: Add support for TrueMail
|
- Feat: Add support for TrueMail
|
||||||
|
- Enhance: モデレーターはすべてのユーザーのリアクション一覧を見られるように
|
||||||
|
- Fix: リストライムラインの「リノートを表示」が正しく機能しない問題を修正
|
||||||
- Fix: リモートユーザーのリアクション一覧がすべて見えてしまうのを修正
|
- Fix: リモートユーザーのリアクション一覧がすべて見えてしまうのを修正
|
||||||
* すべてのリモートユーザーのリアクション一覧を見えないようにします
|
* すべてのリモートユーザーのリアクション一覧を見えないようにします
|
||||||
- Enhance: モデレーターはすべてのユーザーのリアクション一覧を見られるように
|
|
||||||
- Fix: 特定のキーワード及び正規表現にマッチする文字列を含むノートが投稿された際、エラーに出来るような設定項目を追加 #13207
|
- Fix: 特定のキーワード及び正規表現にマッチする文字列を含むノートが投稿された際、エラーに出来るような設定項目を追加 #13207
|
||||||
* デフォルトは空欄なので適用前と同等の動作になります
|
* デフォルトは空欄なので適用前と同等の動作になります
|
||||||
- Fix: 破損した通知をクライアントに送信しないように
|
- Fix: 破損した通知をクライアントに送信しないように
|
||||||
|
@ -59,6 +59,7 @@
|
||||||
- リモートのユーザーにローカルのみのカスタム絵文字をリアクションしようとした場合
|
- リモートのユーザーにローカルのみのカスタム絵文字をリアクションしようとした場合
|
||||||
- センシティブなリアクションを認めていないユーザーにセンシティブなカスタム絵文字をリアクションしようとした場合
|
- センシティブなリアクションを認めていないユーザーにセンシティブなカスタム絵文字をリアクションしようとした場合
|
||||||
- ロールが必要な絵文字をリアクションしようとした場合
|
- ロールが必要な絵文字をリアクションしようとした場合
|
||||||
|
- Enhance: ページ遷移時にPlayerを閉じるように
|
||||||
- Fix: ネイティブモードの絵文字がモノクロにならないように
|
- Fix: ネイティブモードの絵文字がモノクロにならないように
|
||||||
- Fix: v2023.12.0で追加された「モデレーターがユーザーのアイコンもしくはバナー画像を未設定状態にできる機能」が管理画面上で正しく表示されていない問題を修正
|
- Fix: v2023.12.0で追加された「モデレーターがユーザーのアイコンもしくはバナー画像を未設定状態にできる機能」が管理画面上で正しく表示されていない問題を修正
|
||||||
- Fix: AiScriptの`readline`関数が不正な値を返すことがある問題のv2023.12.0時点での修正がPlay以外に適用されていないのを修正
|
- Fix: AiScriptの`readline`関数が不正な値を返すことがある問題のv2023.12.0時点での修正がPlay以外に適用されていないのを修正
|
||||||
|
@ -69,7 +70,6 @@
|
||||||
- Fix: デッキのプロファイル作成時に名前を空にできる問題を修正
|
- Fix: デッキのプロファイル作成時に名前を空にできる問題を修正
|
||||||
- Fix: テーマ作成時に名称が空欄でも作成できてしまう問題を修正
|
- Fix: テーマ作成時に名称が空欄でも作成できてしまう問題を修正
|
||||||
- Fix: プラグインで`Plugin:register_note_post_interruptor`を使用すると、ノートが投稿できなくなる問題を修正
|
- Fix: プラグインで`Plugin:register_note_post_interruptor`を使用すると、ノートが投稿できなくなる問題を修正
|
||||||
- Enhance: ページ遷移時にPlayerを閉じるように
|
|
||||||
- Fix: iOSで大きな画像を変換してアップロードできない問題を修正
|
- Fix: iOSで大きな画像を変換してアップロードできない問題を修正
|
||||||
- Fix: 「アニメーション画像を再生しない」もしくは「データセーバー(アイコン)」を有効にしていても、アイコンデコレーションのアニメーションが停止されない問題を修正
|
- Fix: 「アニメーション画像を再生しない」もしくは「データセーバー(アイコン)」を有効にしていても、アイコンデコレーションのアニメーションが停止されない問題を修正
|
||||||
- Fix: 画像をクロップするとクロップ後の解像度が異様に低くなる問題の修正
|
- Fix: 画像をクロップするとクロップ後の解像度が異様に低くなる問題の修正
|
||||||
|
@ -81,11 +81,12 @@
|
||||||
- Fix: Summaly proxy利用時にプレイヤーが動作しないことがあるのを修正 #13196
|
- Fix: Summaly proxy利用時にプレイヤーが動作しないことがあるのを修正 #13196
|
||||||
|
|
||||||
### Server
|
### Server
|
||||||
- Enhance: 連合先のレートリミットに引っかかった際にリトライするようになりました
|
- Enhance: 連合先のレートリミットを超過した際にリトライするようになりました
|
||||||
- Enhance: ActivityPub Deliver queueでBodyを事前処理するように (#12916)
|
- Enhance: ActivityPub Deliver queueでBodyを事前処理するように (#12916)
|
||||||
- Enhance: クリップをエクスポートできるように
|
- Enhance: クリップをエクスポートできるように
|
||||||
- Enhance: `/files`のファイルに対してHTTP Rangeリクエストを行えるように
|
- Enhance: `/files`のファイルに対してHTTP Rangeリクエストを行えるように
|
||||||
- Enhance: `api.json`のOpenAPI Specificationを3.1.0に更新
|
- Enhance: `api.json`のOpenAPI Specificationを3.1.0に更新
|
||||||
|
- Enhance: 連合向けのノート配信を軽量化 #13192
|
||||||
- Fix: `drive/files/update`でファイル名のバリデーションが機能していない問題を修正
|
- Fix: `drive/files/update`でファイル名のバリデーションが機能していない問題を修正
|
||||||
- Fix: `notes/create`で、`text`が空白文字のみで構成されているか`null`であって、かつ`text`だけであるリクエストに対するレスポンスが400になるように変更
|
- Fix: `notes/create`で、`text`が空白文字のみで構成されているか`null`であって、かつ`text`だけであるリクエストに対するレスポンスが400になるように変更
|
||||||
- Fix: `notes/create`で、`text`が空白文字のみで構成されていてかつリノート、ファイルまたは投票を含んでいるリクエストに対するレスポンスの`text`が`""`から`null`になるように変更
|
- Fix: `notes/create`で、`text`が空白文字のみで構成されていてかつリノート、ファイルまたは投票を含んでいるリクエストに対するレスポンスの`text`が`""`から`null`になるように変更
|
||||||
|
@ -93,7 +94,7 @@
|
||||||
- Fix: properly handle cc followers
|
- Fix: properly handle cc followers
|
||||||
- Fix: ジョブに関する設定の名前を修正 relashionshipJobPerSec -> relationshipJobPerSec
|
- Fix: ジョブに関する設定の名前を修正 relashionshipJobPerSec -> relationshipJobPerSec
|
||||||
- Fix: コントロールパネル->モデレーション->「誰でも新規登録できるようにする」の初期値をONからOFFに変更 #13122
|
- Fix: コントロールパネル->モデレーション->「誰でも新規登録できるようにする」の初期値をONからOFFに変更 #13122
|
||||||
- Enhance: 連合向けのノート配信を軽量化 #13192
|
- Fix: リモートユーザーが復活してもキャッシュにより該当ユーザーのActivityが受け入れられないのを修正 #13273
|
||||||
|
|
||||||
### Service Worker
|
### Service Worker
|
||||||
- Enhance: オフライン表示のデザインを改善・多言語対応
|
- Enhance: オフライン表示のデザインを改善・多言語対応
|
||||||
|
|
|
@ -27,13 +27,13 @@ COPY --link ["packages/misskey-js/package.json", "./packages/misskey-js/"]
|
||||||
COPY --link ["packages/misskey-reversi/package.json", "./packages/misskey-reversi/"]
|
COPY --link ["packages/misskey-reversi/package.json", "./packages/misskey-reversi/"]
|
||||||
COPY --link ["packages/misskey-bubble-game/package.json", "./packages/misskey-bubble-game/"]
|
COPY --link ["packages/misskey-bubble-game/package.json", "./packages/misskey-bubble-game/"]
|
||||||
|
|
||||||
|
ARG NODE_ENV=production
|
||||||
|
|
||||||
RUN --mount=type=cache,target=/root/.local/share/pnpm/store,sharing=locked \
|
RUN --mount=type=cache,target=/root/.local/share/pnpm/store,sharing=locked \
|
||||||
pnpm i --frozen-lockfile --aggregate-output
|
pnpm i --frozen-lockfile --aggregate-output
|
||||||
|
|
||||||
COPY --link . ./
|
COPY --link . ./
|
||||||
|
|
||||||
ARG NODE_ENV=production
|
|
||||||
|
|
||||||
RUN git submodule update --init
|
RUN git submodule update --init
|
||||||
RUN pnpm build
|
RUN pnpm build
|
||||||
RUN rm -rf .git/
|
RUN rm -rf .git/
|
||||||
|
@ -57,6 +57,8 @@ COPY --link ["packages/misskey-js/package.json", "./packages/misskey-js/"]
|
||||||
COPY --link ["packages/misskey-reversi/package.json", "./packages/misskey-reversi/"]
|
COPY --link ["packages/misskey-reversi/package.json", "./packages/misskey-reversi/"]
|
||||||
COPY --link ["packages/misskey-bubble-game/package.json", "./packages/misskey-bubble-game/"]
|
COPY --link ["packages/misskey-bubble-game/package.json", "./packages/misskey-bubble-game/"]
|
||||||
|
|
||||||
|
ARG NODE_ENV=production
|
||||||
|
|
||||||
RUN --mount=type=cache,target=/root/.local/share/pnpm/store,sharing=locked \
|
RUN --mount=type=cache,target=/root/.local/share/pnpm/store,sharing=locked \
|
||||||
pnpm i --frozen-lockfile --aggregate-output
|
pnpm i --frozen-lockfile --aggregate-output
|
||||||
|
|
||||||
|
|
|
@ -1975,8 +1975,12 @@ _permissions:
|
||||||
"read:admin:abuse-user-reports": "View user reports"
|
"read:admin:abuse-user-reports": "View user reports"
|
||||||
"write:admin:delete-account": "Delete user account"
|
"write:admin:delete-account": "Delete user account"
|
||||||
"write:admin:delete-all-files-of-a-user": "Delete all files of a user"
|
"write:admin:delete-all-files-of-a-user": "Delete all files of a user"
|
||||||
|
"read:admin:index-stats": "View database index stats"
|
||||||
|
"read:admin:table-stats": "View database table stats"
|
||||||
|
"read:admin:user-ips": "View user IP addresses"
|
||||||
"read:admin:meta": "View instance metadata"
|
"read:admin:meta": "View instance metadata"
|
||||||
"write:admin:reset-password": "Reset user password"
|
"write:admin:reset-password": "Reset user password"
|
||||||
|
"write:admin:resolve-abuse-user-report": "Resolve user report"
|
||||||
"write:admin:send-email": "Send email"
|
"write:admin:send-email": "Send email"
|
||||||
"read:admin:server-info": "View server info"
|
"read:admin:server-info": "View server info"
|
||||||
"read:admin:show-moderation-log": "View moderation log"
|
"read:admin:show-moderation-log": "View moderation log"
|
||||||
|
@ -1997,6 +2001,26 @@ _permissions:
|
||||||
"write:admin:announcements": "Manage announcements"
|
"write:admin:announcements": "Manage announcements"
|
||||||
"read:admin:announcements": "View announcements"
|
"read:admin:announcements": "View announcements"
|
||||||
"write:admin:avatar-decorations": "Manage avatar decorations"
|
"write:admin:avatar-decorations": "Manage avatar decorations"
|
||||||
|
"read:admin:avatar-decorations": "View avatar decorations"
|
||||||
|
"write:admin:federation": "Manage federation data"
|
||||||
|
"write:admin:account": "Manage user account"
|
||||||
|
"read:admin:account": "View user account"
|
||||||
|
"write:admin:emoji": "Manage emoji"
|
||||||
|
"read:admin:emoji": "View emoji"
|
||||||
|
"write:admin:queue": "Manage job queue"
|
||||||
|
"read:admin:queue": "View job queue info"
|
||||||
|
"write:admin:promo": "Manage promotion notes"
|
||||||
|
"write:admin:drive": "Manage user drive"
|
||||||
|
"read:admin:drive": "View user drive info"
|
||||||
|
"read:admin:stream": "Use WebSocket API for Admin"
|
||||||
|
"write:admin:ad": "Manage ads"
|
||||||
|
"read:admin:ad": "View ads"
|
||||||
|
"write:invite-codes": "Create invite codes"
|
||||||
|
"read:invite-codes": "Get invite codes"
|
||||||
|
"write:clip-favorite": "Manage favorited clips"
|
||||||
|
"read:clip-favorite": "View favorited clips"
|
||||||
|
"read:federation": "Get federation data"
|
||||||
|
"write:report-abuse": "Report violation"
|
||||||
_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?"
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
_lang_: "Français"
|
_lang_: "Français"
|
||||||
headlineMisskey: "Réseau relié par des notes"
|
headlineMisskey: "Réseau relié par des notes"
|
||||||
introMisskey: "Bienvenue ! Misskey est un service de microblogage décentralisé, libre et ouvert.\nÉcrivez des « notes » et partagez ce qui se passe à l’instant présent, autour de vous avec les autres 📡\nLa fonction « réactions », vous permet également d’ajouter une réaction rapide aux notes des autres utilisateur·rice·s 👍\nExplorons un nouveau monde 🚀"
|
introMisskey: "Bienvenue ! Misskey est un service de microblogage décentralisé, libre et ouvert.\nÉcrivez des « notes » et partagez ce qui se passe à l’instant présent, autour de vous avec les autres 📡\nLa fonction « réactions », vous permet également d’ajouter une réaction rapide aux notes des autres utilisateur·rice·s 👍\nExplorons un nouveau monde 🚀"
|
||||||
poweredByMisskeyDescription: "{nom} est l'un des services propulsés par la plateforme ouverte <b>Misskey</b> (appelée \"instance Misskey\")."
|
poweredByMisskeyDescription: "{name} est l'un des services propulsés par la plateforme ouverte <b>Misskey</b> (appelée \"instance Misskey\")."
|
||||||
monthAndDay: "{day}/{month}"
|
monthAndDay: "{day}/{month}"
|
||||||
search: "Rechercher"
|
search: "Rechercher"
|
||||||
notifications: "Notifications"
|
notifications: "Notifications"
|
||||||
|
@ -1175,7 +1175,7 @@ _initialAccountSetting:
|
||||||
profileSetting: "Paramètres du profil"
|
profileSetting: "Paramètres du profil"
|
||||||
privacySetting: "Paramètres de confidentialité"
|
privacySetting: "Paramètres de confidentialité"
|
||||||
initialAccountSettingCompleted: "Configuration du profil terminée avec succès !"
|
initialAccountSettingCompleted: "Configuration du profil terminée avec succès !"
|
||||||
youCanContinueTutorial: "Vous pouvez procéder au tutoriel sur l'utilisation de {nom}(Misskey) ou vous arrêter ici et commencer à l'utiliser immédiatement."
|
youCanContinueTutorial: "Vous pouvez procéder au tutoriel sur l'utilisation de {name}(Misskey) ou vous arrêter ici et commencer à l'utiliser immédiatement."
|
||||||
startTutorial: "Démarrer le tutoriel"
|
startTutorial: "Démarrer le tutoriel"
|
||||||
skipAreYouSure: "Désirez-vous ignorer la configuration du profil ?"
|
skipAreYouSure: "Désirez-vous ignorer la configuration du profil ?"
|
||||||
_initialTutorial:
|
_initialTutorial:
|
||||||
|
|
|
@ -1041,6 +1041,8 @@ resetPasswordConfirm: "비밀번호를 재설정하시겠습니까?"
|
||||||
sensitiveWords: "민감한 단어"
|
sensitiveWords: "민감한 단어"
|
||||||
sensitiveWordsDescription: "설정한 단어가 포함된 노트의 공개 범위를 '홈'으로 강제합니다. 개행으로 구분하여 여러 개를 지정할 수 있습니다."
|
sensitiveWordsDescription: "설정한 단어가 포함된 노트의 공개 범위를 '홈'으로 강제합니다. 개행으로 구분하여 여러 개를 지정할 수 있습니다."
|
||||||
sensitiveWordsDescription2: "공백으로 구분하면 AND 지정이 되며, 키워드를 슬래시로 둘러싸면 정규 표현식이 됩니다."
|
sensitiveWordsDescription2: "공백으로 구분하면 AND 지정이 되며, 키워드를 슬래시로 둘러싸면 정규 표현식이 됩니다."
|
||||||
|
prohibitedWords: "금지 워드"
|
||||||
|
prohibitedWordsDescription: "설정된 워드가 포함되는 노트를 작성하려고 하면, 에러가 발생하도록 합니다. 줄바꿈으로 구분지어 복수 설정할 수 있습니다."
|
||||||
prohibitedWordsDescription2: "공백으로 구분하면 AND 지정이 되며, 키워드를 슬래시로 둘러싸면 정규 표현식이 됩니다."
|
prohibitedWordsDescription2: "공백으로 구분하면 AND 지정이 되며, 키워드를 슬래시로 둘러싸면 정규 표현식이 됩니다."
|
||||||
hiddenTags: "숨긴 해시태그"
|
hiddenTags: "숨긴 해시태그"
|
||||||
hiddenTagsDescription: "설정한 태그를 트렌드에 표시하지 않도록 합니다. 줄 바꿈으로 하나씩 나눠서 설정할 수 있습니다."
|
hiddenTagsDescription: "설정한 태그를 트렌드에 표시하지 않도록 합니다. 줄 바꿈으로 하나씩 나눠서 설정할 수 있습니다."
|
||||||
|
|
|
@ -1041,6 +1041,8 @@ resetPasswordConfirm: "รีเซ็ตรหัสผ่านของคุ
|
||||||
sensitiveWords: "คำที่มีเนื้อหาละเอียดอ่อน"
|
sensitiveWords: "คำที่มีเนื้อหาละเอียดอ่อน"
|
||||||
sensitiveWordsDescription: "การเปิดเผยโน้ตทั้งหมดที่มีคำที่กำหนดค่าไว้จะถูกตั้งค่าเป็น \"หน้าแรก\" โดยอัตโนมัติ คุณยังสามารถแสดงหลายรายการได้โดยแยกรายการโดยใช้ตัวแบ่งบรรทัดได้นะ"
|
sensitiveWordsDescription: "การเปิดเผยโน้ตทั้งหมดที่มีคำที่กำหนดค่าไว้จะถูกตั้งค่าเป็น \"หน้าแรก\" โดยอัตโนมัติ คุณยังสามารถแสดงหลายรายการได้โดยแยกรายการโดยใช้ตัวแบ่งบรรทัดได้นะ"
|
||||||
sensitiveWordsDescription2: "การใช้ช่องว่างนั้นอาจจะสร้างนิพจน์ AND และคำหลักที่มีเครื่องหมายทับล้อมรอบจะเปลี่ยนเป็นนิพจน์ทั่วไปนะ"
|
sensitiveWordsDescription2: "การใช้ช่องว่างนั้นอาจจะสร้างนิพจน์ AND และคำหลักที่มีเครื่องหมายทับล้อมรอบจะเปลี่ยนเป็นนิพจน์ทั่วไปนะ"
|
||||||
|
prohibitedWords: "คำต้องห้าม"
|
||||||
|
prohibitedWordsDescription: "จะแจ้งเตือนว่าเกิดข้อผิดพลาดเมื่อพยายามโพสต์โน้ตที่มีคำที่กำหนดไว้ สามารถตั้งได้หลายคำด้วยการขึ้นบรรทัดใหม่"
|
||||||
prohibitedWordsDescription2: "การใช้ช่องว่างนั้นอาจจะสร้างนิพจน์ AND และคำหลักที่มีเครื่องหมายทับล้อมรอบจะเปลี่ยนเป็นนิพจน์ทั่วไปนะ"
|
prohibitedWordsDescription2: "การใช้ช่องว่างนั้นอาจจะสร้างนิพจน์ AND และคำหลักที่มีเครื่องหมายทับล้อมรอบจะเปลี่ยนเป็นนิพจน์ทั่วไปนะ"
|
||||||
hiddenTags: "แฮชแท็กที่ซ่อนอยู่"
|
hiddenTags: "แฮชแท็กที่ซ่อนอยู่"
|
||||||
hiddenTagsDescription: "เลือกแท็กที่จะไม่แสดงในรายการเทรนด์ สามารถลงทะเบียนหลายแท็กได้โดยขึ้นบรรทัดใหม่"
|
hiddenTagsDescription: "เลือกแท็กที่จะไม่แสดงในรายการเทรนด์ สามารถลงทะเบียนหลายแท็กได้โดยขึ้นบรรทัดใหม่"
|
||||||
|
@ -1203,6 +1205,9 @@ replaying: "กำลังรีเพลย์"
|
||||||
ranking: "อันดับ"
|
ranking: "อันดับ"
|
||||||
lastNDays: "ล่าสุด {n} วันที่แล้ว"
|
lastNDays: "ล่าสุด {n} วันที่แล้ว"
|
||||||
backToTitle: "กลับไปหน้าไตเติ้ล"
|
backToTitle: "กลับไปหน้าไตเติ้ล"
|
||||||
|
hemisphere: "พื้นที่ที่อาศัยอยู่"
|
||||||
|
withSensitive: "แสดงโน้ตที่มีไฟล์ที่ระบุว่ามีเนื้อหาละเอียดอ่อน"
|
||||||
|
userSaysSomethingSensitive: "โพสต์ที่มีไฟล์เนื้อหาละเอียดอ่อนของ {name}"
|
||||||
enableHorizontalSwipe: "ปัดเพื่อสลับแท็บ"
|
enableHorizontalSwipe: "ปัดเพื่อสลับแท็บ"
|
||||||
_bubbleGame:
|
_bubbleGame:
|
||||||
howToPlay: "วิธีเล่น"
|
howToPlay: "วิธีเล่น"
|
||||||
|
@ -2439,6 +2444,53 @@ _dataSaver:
|
||||||
_code:
|
_code:
|
||||||
title: "ไฮไลต์โค้ด"
|
title: "ไฮไลต์โค้ด"
|
||||||
description: "หากใช้สัญลักษณ์ไฮไลต์โค้ดใน MFM ฯลฯ สัญลักษณ์เหล่านั้นจะไม่โหลดจนกว่าจะแตะ การไฮไลต์ไวยากรณ์(syntax)จำเป็นต้องดาวน์โหลดไฟล์คำจำกัดความของไฮไลต์สำหรับแต่ละภาษา ดังนั้นการปิดใช้งานการโหลดไฟล์เหล่านี้โดยอัตโนมัติจึงคาดว่าจะช่วยลดปริมาณข้อมูลการสื่อสารได้"
|
description: "หากใช้สัญลักษณ์ไฮไลต์โค้ดใน MFM ฯลฯ สัญลักษณ์เหล่านั้นจะไม่โหลดจนกว่าจะแตะ การไฮไลต์ไวยากรณ์(syntax)จำเป็นต้องดาวน์โหลดไฟล์คำจำกัดความของไฮไลต์สำหรับแต่ละภาษา ดังนั้นการปิดใช้งานการโหลดไฟล์เหล่านี้โดยอัตโนมัติจึงคาดว่าจะช่วยลดปริมาณข้อมูลการสื่อสารได้"
|
||||||
|
_hemisphere:
|
||||||
|
N: "ซีกโลกเหนือ"
|
||||||
|
S: "ซีกโลกใต้"
|
||||||
|
caption: "ใช้เพื่อกำหนดฤดูกาลของไคลเอ็นต์"
|
||||||
_reversi:
|
_reversi:
|
||||||
|
reversi: "รีเวอร์ซี"
|
||||||
|
gameSettings: "ตั้งค่าการเล่น"
|
||||||
|
chooseBoard: "เลือกกระดาน"
|
||||||
|
blackOrWhite: "ดำ/ขาว"
|
||||||
|
blackIs: "{name}เป็นสีดำ"
|
||||||
|
rules: "กฎ"
|
||||||
|
thisGameIsStartedSoon: "การเล่นจะเริ่มแล้ว"
|
||||||
|
waitingForOther: "กำลังรออีกฝ่ายเตรียมตัวให้เสร็จ"
|
||||||
|
waitingForMe: "กำลังรอฝ่ายคุณเตรียมตัวให้เสร็จ"
|
||||||
|
waitingBoth: "กรุณาเตรียมตัว"
|
||||||
|
ready: "เตรียมตัวพร้อมแล้ว"
|
||||||
|
cancelReady: "ยกเลิกการเตรียมตัวพร้อม"
|
||||||
|
opponentTurn: "ตาอีกฝ่าย"
|
||||||
|
myTurn: "ตาของคุณ"
|
||||||
|
turnOf: "ตาของ{name}"
|
||||||
|
pastTurnOf: "ตาของ{name}"
|
||||||
|
surrender: "ยอมแพ้"
|
||||||
|
surrendered: "ยอมแพ้แล้ว"
|
||||||
|
timeout: "หมดเวลาแล้ว"
|
||||||
|
drawn: "เสมอ"
|
||||||
|
won: "{name}ชนะ"
|
||||||
|
black: "ดำ"
|
||||||
|
white: "ขาว"
|
||||||
total: "รวมทั้งหมด"
|
total: "รวมทั้งหมด"
|
||||||
|
turnCount: "ตาที่{count}"
|
||||||
|
myGames: "การเล่นของตัวเอง"
|
||||||
|
allGames: "การเล่นของทุกคน"
|
||||||
|
ended: "จบ"
|
||||||
|
playing: "กำลังเล่น"
|
||||||
|
isLlotheo: "คนที่มีตัวหมากน้อยกว่าชนะ (Roseo)"
|
||||||
|
loopedMap: "ลูปแมป"
|
||||||
|
canPutEverywhere: "โหมดที่สามารถวางได้ทุกที่"
|
||||||
|
timeLimitForEachTurn: "จำกัดเวลาต่อแต่ละตา"
|
||||||
|
freeMatch: "ฟรีแมตช์"
|
||||||
|
lookingForPlayer: "กำลังมองหาคู่ต่อสู้อยู่"
|
||||||
|
gameCanceled: "ยกเลิกการเล่นแล้ว"
|
||||||
|
shareToTlTheGameWhenStart: "โพสต์ลงไทม์ไลน์เมื่อเริ่มการเล่น"
|
||||||
|
iStartedAGame: "เริ่มเล่นหมากรีเวอร์ซีแล้ว! #MisskeyReversi"
|
||||||
|
opponentHasSettingsChanged: "อีกฝ่ายเปลี่ยนการตั้งค่า"
|
||||||
|
allowIrregularRules: "อนุญาตกฎที่ไม่ปรกติ (โหมดฟรีทุกอย่าง)"
|
||||||
|
disallowIrregularRules: "ไม่อนุญาตกฎที่ไม่ปรกติ"
|
||||||
|
_offlineScreen:
|
||||||
|
title: "ออฟไลน์ - ไม่สามารถเชื่อมต่อกับเซิร์ฟเวอร์ได้"
|
||||||
|
header: "ไม่สามารถเชื่อมต่อกับเซิร์ฟเวอร์ได้"
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ password: "密码"
|
||||||
forgotPassword: "忘记密码"
|
forgotPassword: "忘记密码"
|
||||||
fetchingAsApObject: "在联邦宇宙查询中..."
|
fetchingAsApObject: "在联邦宇宙查询中..."
|
||||||
ok: "OK"
|
ok: "OK"
|
||||||
gotIt: "我明白了"
|
gotIt: "好"
|
||||||
cancel: "取消"
|
cancel: "取消"
|
||||||
noThankYou: "不用,谢谢"
|
noThankYou: "不用,谢谢"
|
||||||
enterUsername: "输入用户名"
|
enterUsername: "输入用户名"
|
||||||
|
@ -1041,6 +1041,7 @@ resetPasswordConfirm: "确定重置密码?"
|
||||||
sensitiveWords: "敏感词"
|
sensitiveWords: "敏感词"
|
||||||
sensitiveWordsDescription: "将包含设置词的帖子的可见范围设置为首页。可以通过用换行符分隔来设置多个。"
|
sensitiveWordsDescription: "将包含设置词的帖子的可见范围设置为首页。可以通过用换行符分隔来设置多个。"
|
||||||
sensitiveWordsDescription2: "AND 条件用空格分隔,正则表达式用斜线包裹。"
|
sensitiveWordsDescription2: "AND 条件用空格分隔,正则表达式用斜线包裹。"
|
||||||
|
prohibitedWords: "禁用词"
|
||||||
prohibitedWordsDescription2: "AND 条件用空格分隔,正则表达式用斜线包裹。"
|
prohibitedWordsDescription2: "AND 条件用空格分隔,正则表达式用斜线包裹。"
|
||||||
hiddenTags: "隐藏标签"
|
hiddenTags: "隐藏标签"
|
||||||
hiddenTagsDescription: "设定的标签将不会在时间线上显示。可使用换行来设置多个标签。"
|
hiddenTagsDescription: "设定的标签将不会在时间线上显示。可使用换行来设置多个标签。"
|
||||||
|
|
|
@ -66,7 +66,7 @@ showMore: "載入更多"
|
||||||
showLess: "關閉"
|
showLess: "關閉"
|
||||||
youGotNewFollower: "您有新的追隨者"
|
youGotNewFollower: "您有新的追隨者"
|
||||||
receiveFollowRequest: "您有新的追隨請求"
|
receiveFollowRequest: "您有新的追隨請求"
|
||||||
followRequestAccepted: "追隨請求已接受"
|
followRequestAccepted: "追隨請求已被接受"
|
||||||
mention: "提及"
|
mention: "提及"
|
||||||
mentions: "提及"
|
mentions: "提及"
|
||||||
directNotes: "私訊"
|
directNotes: "私訊"
|
||||||
|
@ -604,7 +604,7 @@ inboxUrl: "收件夾URL"
|
||||||
addedRelays: "已加入的中繼器"
|
addedRelays: "已加入的中繼器"
|
||||||
serviceworkerInfo: "如要使用推播通知,需要啟用此選項並設定金鑰。"
|
serviceworkerInfo: "如要使用推播通知,需要啟用此選項並設定金鑰。"
|
||||||
deletedNote: "已刪除的貼文"
|
deletedNote: "已刪除的貼文"
|
||||||
invisibleNote: "私密的貼文"
|
invisibleNote: "私人貼文"
|
||||||
enableInfiniteScroll: "啟用自動滾動頁面模式"
|
enableInfiniteScroll: "啟用自動滾動頁面模式"
|
||||||
visibility: "可見性"
|
visibility: "可見性"
|
||||||
poll: "票選活動"
|
poll: "票選活動"
|
||||||
|
@ -2096,7 +2096,7 @@ _poll:
|
||||||
deadlineTime: "小時"
|
deadlineTime: "小時"
|
||||||
duration: "時長"
|
duration: "時長"
|
||||||
votesCount: "{n} 票"
|
votesCount: "{n} 票"
|
||||||
totalVotes: "一共{n}票"
|
totalVotes: "合計 {n} 票"
|
||||||
vote: "投票"
|
vote: "投票"
|
||||||
showResult: "顯示結果"
|
showResult: "顯示結果"
|
||||||
voted: "已投票"
|
voted: "已投票"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "misskey",
|
"name": "misskey",
|
||||||
"version": "2024.2.0-beta.11",
|
"version": "2024.2.0-beta.12",
|
||||||
"codename": "nasubi",
|
"codename": "nasubi",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
@ -16,10 +16,10 @@ import type { OnApplicationShutdown } from '@nestjs/common';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CacheService implements OnApplicationShutdown {
|
export class CacheService implements OnApplicationShutdown {
|
||||||
public userByIdCache: MemoryKVCache<MiUser, MiUser | string>;
|
public userByIdCache: MemoryKVCache<MiUser>;
|
||||||
public localUserByNativeTokenCache: MemoryKVCache<MiLocalUser | null, string | null>;
|
public localUserByNativeTokenCache: MemoryKVCache<MiLocalUser | null>;
|
||||||
public localUserByIdCache: MemoryKVCache<MiLocalUser>;
|
public localUserByIdCache: MemoryKVCache<MiLocalUser>;
|
||||||
public uriPersonCache: MemoryKVCache<MiUser | null, string | null>;
|
public uriPersonCache: MemoryKVCache<MiUser | null>;
|
||||||
public userProfileCache: RedisKVCache<MiUserProfile>;
|
public userProfileCache: RedisKVCache<MiUserProfile>;
|
||||||
public userMutingsCache: RedisKVCache<Set<string>>;
|
public userMutingsCache: RedisKVCache<Set<string>>;
|
||||||
public userBlockingCache: RedisKVCache<Set<string>>;
|
public userBlockingCache: RedisKVCache<Set<string>>;
|
||||||
|
@ -56,41 +56,10 @@ export class CacheService implements OnApplicationShutdown {
|
||||||
) {
|
) {
|
||||||
//this.onMessage = this.onMessage.bind(this);
|
//this.onMessage = this.onMessage.bind(this);
|
||||||
|
|
||||||
const localUserByIdCache = new MemoryKVCache<MiLocalUser>(1000 * 60 * 60 * 6 /* 6h */);
|
this.userByIdCache = new MemoryKVCache<MiUser>(Infinity);
|
||||||
this.localUserByIdCache = localUserByIdCache;
|
this.localUserByNativeTokenCache = new MemoryKVCache<MiLocalUser | null>(Infinity);
|
||||||
|
this.localUserByIdCache = new MemoryKVCache<MiLocalUser>(Infinity);
|
||||||
// ローカルユーザーならlocalUserByIdCacheにデータを追加し、こちらにはid(文字列)だけを追加する
|
this.uriPersonCache = new MemoryKVCache<MiUser | null>(Infinity);
|
||||||
const userByIdCache = new MemoryKVCache<MiUser, MiUser | string>(1000 * 60 * 60 * 6 /* 6h */, {
|
|
||||||
toMapConverter: user => {
|
|
||||||
if (user.host === null) {
|
|
||||||
localUserByIdCache.set(user.id, user as MiLocalUser);
|
|
||||||
return user.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
return user;
|
|
||||||
},
|
|
||||||
fromMapConverter: userOrId => typeof userOrId === 'string' ? localUserByIdCache.get(userOrId) : userOrId,
|
|
||||||
});
|
|
||||||
this.userByIdCache = userByIdCache;
|
|
||||||
|
|
||||||
this.localUserByNativeTokenCache = new MemoryKVCache<MiLocalUser | null, string | null>(Infinity, {
|
|
||||||
toMapConverter: user => {
|
|
||||||
if (user === null) return null;
|
|
||||||
|
|
||||||
localUserByIdCache.set(user.id, user);
|
|
||||||
return user.id;
|
|
||||||
},
|
|
||||||
fromMapConverter: id => id === null ? null : localUserByIdCache.get(id),
|
|
||||||
});
|
|
||||||
this.uriPersonCache = new MemoryKVCache<MiUser | null, string | null>(Infinity, {
|
|
||||||
toMapConverter: user => {
|
|
||||||
if (user === null) return null;
|
|
||||||
|
|
||||||
userByIdCache.set(user.id, user);
|
|
||||||
return user.id;
|
|
||||||
},
|
|
||||||
fromMapConverter: id => id === null ? null : userByIdCache.get(id),
|
|
||||||
});
|
|
||||||
|
|
||||||
this.userProfileCache = new RedisKVCache<MiUserProfile>(this.redisClient, 'userProfile', {
|
this.userProfileCache = new RedisKVCache<MiUserProfile>(this.redisClient, 'userProfile', {
|
||||||
lifetime: 1000 * 60 * 30, // 30m
|
lifetime: 1000 * 60 * 30, // 30m
|
||||||
|
@ -160,10 +129,18 @@ export class CacheService implements OnApplicationShutdown {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'userChangeSuspendedState':
|
case 'userChangeSuspendedState':
|
||||||
case 'remoteUserUpdated': {
|
case 'remoteUserUpdated': {
|
||||||
const user = await this.usersRepository.findOneByOrFail({ id: body.id });
|
const user = await this.usersRepository.findOneBy({ id: body.id });
|
||||||
|
if (user == null) {
|
||||||
|
this.userByIdCache.delete(body.id);
|
||||||
|
for (const [k, v] of this.uriPersonCache.cache.entries()) {
|
||||||
|
if (v.value?.id === body.id) {
|
||||||
|
this.uriPersonCache.delete(k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
this.userByIdCache.set(user.id, user);
|
this.userByIdCache.set(user.id, user);
|
||||||
for (const [k, v] of this.uriPersonCache.cache.entries()) {
|
for (const [k, v] of this.uriPersonCache.cache.entries()) {
|
||||||
if (v.value === user.id) {
|
if (v.value?.id === user.id) {
|
||||||
this.uriPersonCache.set(k, user);
|
this.uriPersonCache.set(k, user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -171,6 +148,7 @@ export class CacheService implements OnApplicationShutdown {
|
||||||
this.localUserByNativeTokenCache.set(user.token!, user);
|
this.localUserByNativeTokenCache.set(user.token!, user);
|
||||||
this.localUserByIdCache.set(user.id, user);
|
this.localUserByIdCache.set(user.id, user);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'userTokenRegenerated': {
|
case 'userTokenRegenerated': {
|
||||||
|
|
|
@ -30,12 +30,12 @@ import { RoleService } from '@/core/RoleService.js';
|
||||||
import { FeaturedService } from '@/core/FeaturedService.js';
|
import { FeaturedService } from '@/core/FeaturedService.js';
|
||||||
import { trackPromise } from '@/misc/promise-tracker.js';
|
import { trackPromise } from '@/misc/promise-tracker.js';
|
||||||
|
|
||||||
const FALLBACK = '❤';
|
const FALLBACK = '\u2764';
|
||||||
const PER_NOTE_REACTION_USER_PAIR_CACHE_MAX = 16;
|
const PER_NOTE_REACTION_USER_PAIR_CACHE_MAX = 16;
|
||||||
|
|
||||||
const legacies: Record<string, string> = {
|
const legacies: Record<string, string> = {
|
||||||
'like': '👍',
|
'like': '👍',
|
||||||
'love': '❤', // ここに記述する場合は異体字セレクタを入れない
|
'love': '\u2764', // ハート、異体字セレクタを入れない
|
||||||
'laugh': '😆',
|
'laugh': '😆',
|
||||||
'hmm': '🤔',
|
'hmm': '🤔',
|
||||||
'surprise': '😮',
|
'surprise': '😮',
|
||||||
|
@ -120,7 +120,7 @@ export class ReactionService {
|
||||||
let reaction = _reaction ?? FALLBACK;
|
let reaction = _reaction ?? FALLBACK;
|
||||||
|
|
||||||
if (note.reactionAcceptance === 'likeOnly' || ((note.reactionAcceptance === 'likeOnlyForRemote' || note.reactionAcceptance === 'nonSensitiveOnlyForLocalLikeOnlyForRemote') && (user.host != null))) {
|
if (note.reactionAcceptance === 'likeOnly' || ((note.reactionAcceptance === 'likeOnlyForRemote' || note.reactionAcceptance === 'nonSensitiveOnlyForLocalLikeOnlyForRemote') && (user.host != null))) {
|
||||||
reaction = '❤️';
|
reaction = '\u2764';
|
||||||
} else if (_reaction) {
|
} else if (_reaction) {
|
||||||
const custom = reaction.match(isCustomEmojiRegexp);
|
const custom = reaction.match(isCustomEmojiRegexp);
|
||||||
if (custom) {
|
if (custom) {
|
||||||
|
|
|
@ -106,12 +106,12 @@ export class ApDbResolverService implements OnApplicationShutdown {
|
||||||
|
|
||||||
return await this.cacheService.userByIdCache.fetchMaybe(
|
return await this.cacheService.userByIdCache.fetchMaybe(
|
||||||
parsed.id,
|
parsed.id,
|
||||||
() => this.usersRepository.findOneBy({ id: parsed.id }).then(x => x ?? undefined),
|
() => this.usersRepository.findOneBy({ id: parsed.id, isDeleted: false }).then(x => x ?? undefined),
|
||||||
) as MiLocalUser | undefined ?? null;
|
) as MiLocalUser | undefined ?? null;
|
||||||
} else {
|
} else {
|
||||||
return await this.cacheService.uriPersonCache.fetch(
|
return await this.cacheService.uriPersonCache.fetch(
|
||||||
parsed.uri,
|
parsed.uri,
|
||||||
() => this.usersRepository.findOneBy({ uri: parsed.uri }),
|
() => this.usersRepository.findOneBy({ uri: parsed.uri, isDeleted: false }),
|
||||||
) as MiRemoteUser | null;
|
) as MiRemoteUser | null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,8 +136,12 @@ export class ApDbResolverService implements OnApplicationShutdown {
|
||||||
|
|
||||||
if (key == null) return null;
|
if (key == null) return null;
|
||||||
|
|
||||||
|
const user = await this.cacheService.findUserById(key.userId).catch(() => null) as MiRemoteUser | null;
|
||||||
|
if (user == null) return null;
|
||||||
|
if (user.isDeleted) return null;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
user: await this.cacheService.findUserById(key.userId) as MiRemoteUser,
|
user,
|
||||||
key,
|
key,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -151,6 +155,7 @@ export class ApDbResolverService implements OnApplicationShutdown {
|
||||||
key: MiUserPublickey | null;
|
key: MiUserPublickey | null;
|
||||||
} | null> {
|
} | null> {
|
||||||
const user = await this.apPersonService.resolvePerson(uri) as MiRemoteUser;
|
const user = await this.apPersonService.resolvePerson(uri) as MiRemoteUser;
|
||||||
|
if (user.isDeleted) return null;
|
||||||
|
|
||||||
const key = await this.publicKeyByUserIdCache.fetch(
|
const key = await this.publicKeyByUserIdCache.fetch(
|
||||||
user.id,
|
user.id,
|
||||||
|
|
|
@ -35,6 +35,8 @@ import { ApResolverService } from './ApResolverService.js';
|
||||||
import { ApAudienceService } from './ApAudienceService.js';
|
import { ApAudienceService } from './ApAudienceService.js';
|
||||||
import { ApPersonService } from './models/ApPersonService.js';
|
import { ApPersonService } from './models/ApPersonService.js';
|
||||||
import { ApQuestionService } from './models/ApQuestionService.js';
|
import { ApQuestionService } from './models/ApQuestionService.js';
|
||||||
|
import { CacheService } from '@/core/CacheService.js';
|
||||||
|
import { GlobalEventService } from '@/core/GlobalEventService.js';
|
||||||
import type { Resolver } from './ApResolverService.js';
|
import type { Resolver } from './ApResolverService.js';
|
||||||
import type { IAccept, IAdd, IAnnounce, IBlock, ICreate, IDelete, IFlag, IFollow, ILike, IObject, IReject, IRemove, IUndo, IUpdate, IMove } from './type.js';
|
import type { IAccept, IAdd, IAnnounce, IBlock, ICreate, IDelete, IFlag, IFollow, ILike, IObject, IReject, IRemove, IUndo, IUpdate, IMove } from './type.js';
|
||||||
|
|
||||||
|
@ -82,6 +84,8 @@ export class ApInboxService {
|
||||||
private apPersonService: ApPersonService,
|
private apPersonService: ApPersonService,
|
||||||
private apQuestionService: ApQuestionService,
|
private apQuestionService: ApQuestionService,
|
||||||
private queueService: QueueService,
|
private queueService: QueueService,
|
||||||
|
private cacheService: CacheService,
|
||||||
|
private globalEventService: GlobalEventService,
|
||||||
) {
|
) {
|
||||||
this.logger = this.apLoggerService.logger;
|
this.logger = this.apLoggerService.logger;
|
||||||
}
|
}
|
||||||
|
@ -479,6 +483,8 @@ export class ApInboxService {
|
||||||
isDeleted: true,
|
isDeleted: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.globalEventService.publishInternalEvent('remoteUserUpdated', { id: actor.id });
|
||||||
|
|
||||||
return `ok: queued ${job.name} ${job.id}`;
|
return `ok: queued ${job.name} ${job.id}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -186,28 +186,14 @@ export class RedisSingleCache<T> {
|
||||||
|
|
||||||
// TODO: メモリ節約のためあまり参照されないキーを定期的に削除できるようにする?
|
// TODO: メモリ節約のためあまり参照されないキーを定期的に削除できるようにする?
|
||||||
|
|
||||||
function nothingToDo<T, V = T>(value: T): V {
|
export class MemoryKVCache<T> {
|
||||||
return value as unknown as V;
|
public cache: Map<string, { date: number; value: T; }>;
|
||||||
}
|
|
||||||
|
|
||||||
export class MemoryKVCache<T, V = T> {
|
|
||||||
public cache: Map<string, { date: number; value: V; }>;
|
|
||||||
private lifetime: number;
|
private lifetime: number;
|
||||||
private gcIntervalHandle: NodeJS.Timeout;
|
private gcIntervalHandle: NodeJS.Timeout;
|
||||||
private toMapConverter: (value: T) => V;
|
|
||||||
private fromMapConverter: (cached: V) => T | undefined;
|
|
||||||
|
|
||||||
constructor(lifetime: MemoryKVCache<never>['lifetime'], options: {
|
constructor(lifetime: MemoryKVCache<never>['lifetime']) {
|
||||||
toMapConverter: (value: T) => V;
|
|
||||||
fromMapConverter: (cached: V) => T | undefined;
|
|
||||||
} = {
|
|
||||||
toMapConverter: nothingToDo,
|
|
||||||
fromMapConverter: nothingToDo,
|
|
||||||
}) {
|
|
||||||
this.cache = new Map();
|
this.cache = new Map();
|
||||||
this.lifetime = lifetime;
|
this.lifetime = lifetime;
|
||||||
this.toMapConverter = options.toMapConverter;
|
|
||||||
this.fromMapConverter = options.fromMapConverter;
|
|
||||||
|
|
||||||
this.gcIntervalHandle = setInterval(() => {
|
this.gcIntervalHandle = setInterval(() => {
|
||||||
this.gc();
|
this.gc();
|
||||||
|
@ -218,7 +204,7 @@ export class MemoryKVCache<T, V = T> {
|
||||||
public set(key: string, value: T): void {
|
public set(key: string, value: T): void {
|
||||||
this.cache.set(key, {
|
this.cache.set(key, {
|
||||||
date: Date.now(),
|
date: Date.now(),
|
||||||
value: this.toMapConverter(value),
|
value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,7 +216,7 @@ export class MemoryKVCache<T, V = T> {
|
||||||
this.cache.delete(key);
|
this.cache.delete(key);
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
return this.fromMapConverter(cached.value);
|
return cached.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
|
@ -241,10 +227,9 @@ export class MemoryKVCache<T, V = T> {
|
||||||
/**
|
/**
|
||||||
* キャッシュがあればそれを返し、無ければfetcherを呼び出して結果をキャッシュ&返します
|
* キャッシュがあればそれを返し、無ければfetcherを呼び出して結果をキャッシュ&返します
|
||||||
* optional: キャッシュが存在してもvalidatorでfalseを返すとキャッシュ無効扱いにします
|
* optional: キャッシュが存在してもvalidatorでfalseを返すとキャッシュ無効扱いにします
|
||||||
* fetcherの引数はcacheに保存されている値があれば渡されます
|
|
||||||
*/
|
*/
|
||||||
@bindThis
|
@bindThis
|
||||||
public async fetch(key: string, fetcher: (value: V | undefined) => Promise<T>, validator?: (cachedValue: T) => boolean): Promise<T> {
|
public async fetch(key: string, fetcher: () => Promise<T>, validator?: (cachedValue: T) => boolean): Promise<T> {
|
||||||
const cachedValue = this.get(key);
|
const cachedValue = this.get(key);
|
||||||
if (cachedValue !== undefined) {
|
if (cachedValue !== undefined) {
|
||||||
if (validator) {
|
if (validator) {
|
||||||
|
@ -259,7 +244,7 @@ export class MemoryKVCache<T, V = T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache MISS
|
// Cache MISS
|
||||||
const value = await fetcher(this.cache.get(key)?.value);
|
const value = await fetcher();
|
||||||
this.set(key, value);
|
this.set(key, value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -267,10 +252,9 @@ export class MemoryKVCache<T, V = T> {
|
||||||
/**
|
/**
|
||||||
* キャッシュがあればそれを返し、無ければfetcherを呼び出して結果をキャッシュ&返します
|
* キャッシュがあればそれを返し、無ければfetcherを呼び出して結果をキャッシュ&返します
|
||||||
* optional: キャッシュが存在してもvalidatorでfalseを返すとキャッシュ無効扱いにします
|
* optional: キャッシュが存在してもvalidatorでfalseを返すとキャッシュ無効扱いにします
|
||||||
* fetcherの引数はcacheに保存されている値があれば渡されます
|
|
||||||
*/
|
*/
|
||||||
@bindThis
|
@bindThis
|
||||||
public async fetchMaybe(key: string, fetcher: (value: V | undefined) => Promise<T | undefined>, validator?: (cachedValue: T) => boolean): Promise<T | undefined> {
|
public async fetchMaybe(key: string, fetcher: () => Promise<T | undefined>, validator?: (cachedValue: T) => boolean): Promise<T | undefined> {
|
||||||
const cachedValue = this.get(key);
|
const cachedValue = this.get(key);
|
||||||
if (cachedValue !== undefined) {
|
if (cachedValue !== undefined) {
|
||||||
if (validator) {
|
if (validator) {
|
||||||
|
@ -285,7 +269,7 @@ export class MemoryKVCache<T, V = T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache MISS
|
// Cache MISS
|
||||||
const value = await fetcher(this.cache.get(key)?.value);
|
const value = await fetcher();
|
||||||
if (value !== undefined) {
|
if (value !== undefined) {
|
||||||
this.set(key, value);
|
this.set(key, value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,17 @@ import { packedEmojiDetailedSchema, packedEmojiSimpleSchema } from '@/models/jso
|
||||||
import { packedFlashSchema } from '@/models/json-schema/flash.js';
|
import { packedFlashSchema } from '@/models/json-schema/flash.js';
|
||||||
import { packedAnnouncementSchema } from '@/models/json-schema/announcement.js';
|
import { packedAnnouncementSchema } from '@/models/json-schema/announcement.js';
|
||||||
import { packedSigninSchema } from '@/models/json-schema/signin.js';
|
import { packedSigninSchema } from '@/models/json-schema/signin.js';
|
||||||
import { packedRoleLiteSchema, packedRoleSchema, packedRolePoliciesSchema } from '@/models/json-schema/role.js';
|
import {
|
||||||
|
packedRoleLiteSchema,
|
||||||
|
packedRoleSchema,
|
||||||
|
packedRolePoliciesSchema,
|
||||||
|
packedRoleCondFormulaLogicsSchema,
|
||||||
|
packedRoleCondFormulaValueNot,
|
||||||
|
packedRoleCondFormulaValueIsLocalOrRemoteSchema,
|
||||||
|
packedRoleCondFormulaValueCreatedSchema,
|
||||||
|
packedRoleCondFormulaFollowersOrFollowingOrNotesSchema,
|
||||||
|
packedRoleCondFormulaValueSchema,
|
||||||
|
} from '@/models/json-schema/role.js';
|
||||||
import { packedAdSchema } from '@/models/json-schema/ad.js';
|
import { packedAdSchema } from '@/models/json-schema/ad.js';
|
||||||
import { packedReversiGameLiteSchema, packedReversiGameDetailedSchema } from '@/models/json-schema/reversi-game.js';
|
import { packedReversiGameLiteSchema, packedReversiGameDetailedSchema } from '@/models/json-schema/reversi-game.js';
|
||||||
|
|
||||||
|
@ -78,6 +88,12 @@ export const refs = {
|
||||||
EmojiDetailed: packedEmojiDetailedSchema,
|
EmojiDetailed: packedEmojiDetailedSchema,
|
||||||
Flash: packedFlashSchema,
|
Flash: packedFlashSchema,
|
||||||
Signin: packedSigninSchema,
|
Signin: packedSigninSchema,
|
||||||
|
RoleCondFormulaLogics: packedRoleCondFormulaLogicsSchema,
|
||||||
|
RoleCondFormulaValueNot: packedRoleCondFormulaValueNot,
|
||||||
|
RoleCondFormulaValueIsLocalOrRemote: packedRoleCondFormulaValueIsLocalOrRemoteSchema,
|
||||||
|
RoleCondFormulaValueCreated: packedRoleCondFormulaValueCreatedSchema,
|
||||||
|
RoleCondFormulaFollowersOrFollowingOrNotes: packedRoleCondFormulaFollowersOrFollowingOrNotesSchema,
|
||||||
|
RoleCondFormulaValue: packedRoleCondFormulaValueSchema,
|
||||||
RoleLite: packedRoleLiteSchema,
|
RoleLite: packedRoleLiteSchema,
|
||||||
Role: packedRoleSchema,
|
Role: packedRoleSchema,
|
||||||
RolePolicies: packedRolePoliciesSchema,
|
RolePolicies: packedRolePoliciesSchema,
|
||||||
|
|
|
@ -48,7 +48,7 @@ export class MiBubbleGameRecord {
|
||||||
@Column('jsonb', {
|
@Column('jsonb', {
|
||||||
default: [],
|
default: [],
|
||||||
})
|
})
|
||||||
public logs: any[];
|
public logs: number[][];
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column('boolean', {
|
||||||
default: false,
|
default: false,
|
||||||
|
|
|
@ -69,7 +69,7 @@ type CondFormulaValueNotesMoreThanOrEq = {
|
||||||
value: number;
|
value: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type RoleCondFormulaValue =
|
export type RoleCondFormulaValue = { id: string } & (
|
||||||
CondFormulaValueAnd |
|
CondFormulaValueAnd |
|
||||||
CondFormulaValueOr |
|
CondFormulaValueOr |
|
||||||
CondFormulaValueNot |
|
CondFormulaValueNot |
|
||||||
|
@ -82,7 +82,8 @@ export type RoleCondFormulaValue =
|
||||||
CondFormulaValueFollowingLessThanOrEq |
|
CondFormulaValueFollowingLessThanOrEq |
|
||||||
CondFormulaValueFollowingMoreThanOrEq |
|
CondFormulaValueFollowingMoreThanOrEq |
|
||||||
CondFormulaValueNotesLessThanOrEq |
|
CondFormulaValueNotesLessThanOrEq |
|
||||||
CondFormulaValueNotesMoreThanOrEq;
|
CondFormulaValueNotesMoreThanOrEq
|
||||||
|
);
|
||||||
|
|
||||||
@Entity('role')
|
@Entity('role')
|
||||||
export class MiRole {
|
export class MiRole {
|
||||||
|
|
|
@ -47,12 +47,12 @@ export const packedReversiGameLiteSchema = {
|
||||||
user1: {
|
user1: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
optional: false, nullable: false,
|
optional: false, nullable: false,
|
||||||
ref: 'User',
|
ref: 'UserLite',
|
||||||
},
|
},
|
||||||
user2: {
|
user2: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
optional: false, nullable: false,
|
optional: false, nullable: false,
|
||||||
ref: 'User',
|
ref: 'UserLite',
|
||||||
},
|
},
|
||||||
winnerId: {
|
winnerId: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
|
@ -62,7 +62,7 @@ export const packedReversiGameLiteSchema = {
|
||||||
winner: {
|
winner: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
optional: false, nullable: true,
|
optional: false, nullable: true,
|
||||||
ref: 'User',
|
ref: 'UserLite',
|
||||||
},
|
},
|
||||||
surrenderedUserId: {
|
surrenderedUserId: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
|
@ -165,12 +165,12 @@ export const packedReversiGameDetailedSchema = {
|
||||||
user1: {
|
user1: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
optional: false, nullable: false,
|
optional: false, nullable: false,
|
||||||
ref: 'User',
|
ref: 'UserLite',
|
||||||
},
|
},
|
||||||
user2: {
|
user2: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
optional: false, nullable: false,
|
optional: false, nullable: false,
|
||||||
ref: 'User',
|
ref: 'UserLite',
|
||||||
},
|
},
|
||||||
winnerId: {
|
winnerId: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
|
@ -180,7 +180,7 @@ export const packedReversiGameDetailedSchema = {
|
||||||
winner: {
|
winner: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
optional: false, nullable: true,
|
optional: false, nullable: true,
|
||||||
ref: 'User',
|
ref: 'UserLite',
|
||||||
},
|
},
|
||||||
surrenderedUserId: {
|
surrenderedUserId: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
|
@ -226,6 +226,9 @@ export const packedReversiGameDetailedSchema = {
|
||||||
items: {
|
items: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
optional: false, nullable: false,
|
optional: false, nullable: false,
|
||||||
|
items: {
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
map: {
|
map: {
|
||||||
|
|
|
@ -1,3 +1,129 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const packedRoleCondFormulaLogicsSchema = {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
id: {
|
||||||
|
type: 'string', optional: false,
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: 'string',
|
||||||
|
nullable: false, optional: false,
|
||||||
|
enum: ['and', 'or'],
|
||||||
|
},
|
||||||
|
values: {
|
||||||
|
type: 'array',
|
||||||
|
nullable: false, optional: false,
|
||||||
|
items: {
|
||||||
|
ref: 'RoleCondFormulaValue',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export const packedRoleCondFormulaValueNot = {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
id: {
|
||||||
|
type: 'string', optional: false,
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: 'string',
|
||||||
|
nullable: false, optional: false,
|
||||||
|
enum: ['not'],
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: 'object',
|
||||||
|
optional: false,
|
||||||
|
ref: 'RoleCondFormulaValue',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export const packedRoleCondFormulaValueIsLocalOrRemoteSchema = {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
id: {
|
||||||
|
type: 'string', optional: false,
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: 'string',
|
||||||
|
nullable: false, optional: false,
|
||||||
|
enum: ['isLocal', 'isRemote'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export const packedRoleCondFormulaValueCreatedSchema = {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
id: {
|
||||||
|
type: 'string', optional: false,
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: 'string',
|
||||||
|
nullable: false, optional: false,
|
||||||
|
enum: [
|
||||||
|
'createdLessThan',
|
||||||
|
'createdMoreThan',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
sec: {
|
||||||
|
type: 'number',
|
||||||
|
nullable: false, optional: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export const packedRoleCondFormulaFollowersOrFollowingOrNotesSchema = {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
id: {
|
||||||
|
type: 'string', optional: false,
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: 'string',
|
||||||
|
nullable: false, optional: false,
|
||||||
|
enum: [
|
||||||
|
'followersLessThanOrEq',
|
||||||
|
'followersMoreThanOrEq',
|
||||||
|
'followingLessThanOrEq',
|
||||||
|
'followingMoreThanOrEq',
|
||||||
|
'notesLessThanOrEq',
|
||||||
|
'notesMoreThanOrEq',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: 'number',
|
||||||
|
nullable: false, optional: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export const packedRoleCondFormulaValueSchema = {
|
||||||
|
type: 'object',
|
||||||
|
oneOf: [
|
||||||
|
{
|
||||||
|
ref: 'RoleCondFormulaLogics',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ref: 'RoleCondFormulaValueNot',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ref: 'RoleCondFormulaValueIsLocalOrRemote',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ref: 'RoleCondFormulaValueCreated',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ref: 'RoleCondFormulaFollowersOrFollowingOrNotes',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
} as const;
|
||||||
|
|
||||||
export const packedRolePoliciesSchema = {
|
export const packedRolePoliciesSchema = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
optional: false, nullable: false,
|
optional: false, nullable: false,
|
||||||
|
@ -174,6 +300,7 @@ export const packedRoleSchema = {
|
||||||
condFormula: {
|
condFormula: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
optional: false, nullable: false,
|
optional: false, nullable: false,
|
||||||
|
ref: 'RoleCondFormulaValue',
|
||||||
},
|
},
|
||||||
isPublic: {
|
isPublic: {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
|
|
|
@ -3,16 +3,38 @@
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const notificationRecieveConfig = {
|
export const notificationRecieveConfig = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
nullable: false, optional: true,
|
oneOf: [
|
||||||
|
{
|
||||||
|
type: 'object',
|
||||||
|
nullable: false,
|
||||||
properties: {
|
properties: {
|
||||||
type: {
|
type: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
nullable: false, optional: false,
|
nullable: false,
|
||||||
enum: ['all', 'following', 'follower', 'mutualFollow', 'list', 'never'],
|
enum: ['all', 'following', 'follower', 'mutualFollow', 'never'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
required: ['type'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'object',
|
||||||
|
nullable: false,
|
||||||
|
properties: {
|
||||||
|
type: {
|
||||||
|
type: 'string',
|
||||||
|
nullable: false,
|
||||||
|
enum: ['list'],
|
||||||
|
},
|
||||||
|
userListId: {
|
||||||
|
type: 'string',
|
||||||
|
format: 'misskey:id',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: ['type', 'userListId'],
|
||||||
|
},
|
||||||
|
],
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const packedUserLiteSchema = {
|
export const packedUserLiteSchema = {
|
||||||
|
@ -546,15 +568,20 @@ export const packedMeDetailedOnlySchema = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
nullable: false, optional: false,
|
nullable: false, optional: false,
|
||||||
properties: {
|
properties: {
|
||||||
app: notificationRecieveConfig,
|
note: { optional: true, ...notificationRecieveConfig },
|
||||||
quote: notificationRecieveConfig,
|
follow: { optional: true, ...notificationRecieveConfig },
|
||||||
reply: notificationRecieveConfig,
|
mention: { optional: true, ...notificationRecieveConfig },
|
||||||
follow: notificationRecieveConfig,
|
reply: { optional: true, ...notificationRecieveConfig },
|
||||||
renote: notificationRecieveConfig,
|
renote: { optional: true, ...notificationRecieveConfig },
|
||||||
mention: notificationRecieveConfig,
|
quote: { optional: true, ...notificationRecieveConfig },
|
||||||
reaction: notificationRecieveConfig,
|
reaction: { optional: true, ...notificationRecieveConfig },
|
||||||
pollEnded: notificationRecieveConfig,
|
pollEnded: { optional: true, ...notificationRecieveConfig },
|
||||||
receiveFollowRequest: notificationRecieveConfig,
|
receiveFollowRequest: { optional: true, ...notificationRecieveConfig },
|
||||||
|
followRequestAccepted: { optional: true, ...notificationRecieveConfig },
|
||||||
|
roleAssigned: { optional: true, ...notificationRecieveConfig },
|
||||||
|
achievementEarned: { optional: true, ...notificationRecieveConfig },
|
||||||
|
app: { optional: true, ...notificationRecieveConfig },
|
||||||
|
test: { optional: true, ...notificationRecieveConfig },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
emailNotificationTypes: {
|
emailNotificationTypes: {
|
||||||
|
|
|
@ -15,9 +15,6 @@ export const meta = {
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
requireAdmin: true,
|
requireAdmin: true,
|
||||||
kind: 'write:admin:delete-account',
|
kind: 'write:admin:delete-account',
|
||||||
|
|
||||||
res: {
|
|
||||||
},
|
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const paramDef = {
|
export const paramDef = {
|
||||||
|
|
|
@ -84,6 +84,24 @@ export const meta = {
|
||||||
properties: {
|
properties: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
optional: false, nullable: false,
|
optional: false, nullable: false,
|
||||||
|
properties: {
|
||||||
|
width: {
|
||||||
|
type: 'number',
|
||||||
|
optional: true, nullable: false,
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: 'number',
|
||||||
|
optional: true, nullable: false,
|
||||||
|
},
|
||||||
|
orientation: {
|
||||||
|
type: 'number',
|
||||||
|
optional: true, nullable: false,
|
||||||
|
},
|
||||||
|
avgColor: {
|
||||||
|
type: 'string',
|
||||||
|
optional: true, nullable: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
storedInternal: {
|
storedInternal: {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
|
|
|
@ -18,6 +18,18 @@ export const meta = {
|
||||||
res: {
|
res: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
optional: false, nullable: false,
|
optional: false, nullable: false,
|
||||||
|
additionalProperties: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
count: {
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: ['count', 'size'],
|
||||||
|
},
|
||||||
example: {
|
example: {
|
||||||
migrations: {
|
migrations: {
|
||||||
count: 66,
|
count: 66,
|
||||||
|
|
|
@ -10,6 +10,7 @@ import { DI } from '@/di-symbols.js';
|
||||||
import { RoleService } from '@/core/RoleService.js';
|
import { RoleService } from '@/core/RoleService.js';
|
||||||
import { RoleEntityService } from '@/core/entities/RoleEntityService.js';
|
import { RoleEntityService } from '@/core/entities/RoleEntityService.js';
|
||||||
import { IdService } from '@/core/IdService.js';
|
import { IdService } from '@/core/IdService.js';
|
||||||
|
import { notificationRecieveConfig } from '@/models/json-schema/user.js';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ['admin'],
|
tags: ['admin'],
|
||||||
|
@ -21,6 +22,157 @@ export const meta = {
|
||||||
res: {
|
res: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
nullable: false, optional: false,
|
nullable: false, optional: false,
|
||||||
|
properties: {
|
||||||
|
email: {
|
||||||
|
type: 'string',
|
||||||
|
optional: false, nullable: true,
|
||||||
|
},
|
||||||
|
emailVerified: {
|
||||||
|
type: 'boolean',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
autoAcceptFollowed: {
|
||||||
|
type: 'boolean',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
noCrawle: {
|
||||||
|
type: 'boolean',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
preventAiLearning: {
|
||||||
|
type: 'boolean',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
alwaysMarkNsfw: {
|
||||||
|
type: 'boolean',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
autoSensitive: {
|
||||||
|
type: 'boolean',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
carefulBot: {
|
||||||
|
type: 'boolean',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
injectFeaturedNote: {
|
||||||
|
type: 'boolean',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
receiveAnnouncementEmail: {
|
||||||
|
type: 'boolean',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
mutedWords: {
|
||||||
|
type: 'array',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
items: {
|
||||||
|
anyOf: [
|
||||||
|
{
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'array',
|
||||||
|
items: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mutedInstances: {
|
||||||
|
type: 'array',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
items: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
notificationRecieveConfig: {
|
||||||
|
type: 'object',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
properties: {
|
||||||
|
note: { optional: true, ...notificationRecieveConfig },
|
||||||
|
follow: { optional: true, ...notificationRecieveConfig },
|
||||||
|
mention: { optional: true, ...notificationRecieveConfig },
|
||||||
|
reply: { optional: true, ...notificationRecieveConfig },
|
||||||
|
renote: { optional: true, ...notificationRecieveConfig },
|
||||||
|
quote: { optional: true, ...notificationRecieveConfig },
|
||||||
|
reaction: { optional: true, ...notificationRecieveConfig },
|
||||||
|
pollEnded: { optional: true, ...notificationRecieveConfig },
|
||||||
|
receiveFollowRequest: { optional: true, ...notificationRecieveConfig },
|
||||||
|
followRequestAccepted: { optional: true, ...notificationRecieveConfig },
|
||||||
|
roleAssigned: { optional: true, ...notificationRecieveConfig },
|
||||||
|
achievementEarned: { optional: true, ...notificationRecieveConfig },
|
||||||
|
app: { optional: true, ...notificationRecieveConfig },
|
||||||
|
test: { optional: true, ...notificationRecieveConfig },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
isModerator: {
|
||||||
|
type: 'boolean',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
isSilenced: {
|
||||||
|
type: 'boolean',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
isSuspended: {
|
||||||
|
type: 'boolean',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
isHibernated: {
|
||||||
|
type: 'boolean',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
lastActiveDate: {
|
||||||
|
type: 'string',
|
||||||
|
optional: false, nullable: true,
|
||||||
|
},
|
||||||
|
moderationNote: {
|
||||||
|
type: 'string',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
signins: {
|
||||||
|
type: 'array',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
items: {
|
||||||
|
ref: 'Signin',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
policies: {
|
||||||
|
type: 'object',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
ref: 'RolePolicies',
|
||||||
|
},
|
||||||
|
roles: {
|
||||||
|
type: 'array',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
items: {
|
||||||
|
type: 'object',
|
||||||
|
ref: 'Role',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
roleAssigns: {
|
||||||
|
type: 'array',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
items: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
createdAt: {
|
||||||
|
type: 'string',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
expiresAt: {
|
||||||
|
type: 'string',
|
||||||
|
optional: false, nullable: true,
|
||||||
|
},
|
||||||
|
roleId: {
|
||||||
|
type: 'string',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
@ -89,7 +241,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
isSilenced: isSilenced,
|
isSilenced: isSilenced,
|
||||||
isSuspended: user.isSuspended,
|
isSuspended: user.isSuspended,
|
||||||
isHibernated: user.isHibernated,
|
isHibernated: user.isHibernated,
|
||||||
lastActiveDate: user.lastActiveDate,
|
lastActiveDate: user.lastActiveDate ? user.lastActiveDate.toISOString() : null,
|
||||||
moderationNote: profile.moderationNote ?? '',
|
moderationNote: profile.moderationNote ?? '',
|
||||||
signins,
|
signins,
|
||||||
policies: await this.roleService.getUserPolicies(user.id),
|
policies: await this.roleService.getUserPolicies(user.id),
|
||||||
|
|
|
@ -24,9 +24,19 @@ export const meta = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
optional: false, nullable: false,
|
optional: false, nullable: false,
|
||||||
properties: {
|
properties: {
|
||||||
id: { type: 'string', format: 'misskey:id' },
|
id: {
|
||||||
score: { type: 'integer' },
|
type: 'string', format: 'misskey:id',
|
||||||
user: { ref: 'UserLite' },
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
score: {
|
||||||
|
type: 'integer',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
user: {
|
||||||
|
type: 'object',
|
||||||
|
optional: true, nullable: false,
|
||||||
|
ref: 'UserLite',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -29,9 +29,6 @@ export const meta = {
|
||||||
id: 'eb627bc7-574b-4a52-a860-3c3eae772b88',
|
id: 'eb627bc7-574b-4a52-a860-3c3eae772b88',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
res: {
|
|
||||||
},
|
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const paramDef = {
|
export const paramDef = {
|
||||||
|
@ -39,7 +36,15 @@ export const paramDef = {
|
||||||
properties: {
|
properties: {
|
||||||
score: { type: 'integer', minimum: 0 },
|
score: { type: 'integer', minimum: 0 },
|
||||||
seed: { type: 'string', minLength: 1, maxLength: 1024 },
|
seed: { type: 'string', minLength: 1, maxLength: 1024 },
|
||||||
logs: { type: 'array' },
|
logs: {
|
||||||
|
type: 'array',
|
||||||
|
items: {
|
||||||
|
type: 'array',
|
||||||
|
items: {
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
gameMode: { type: 'string' },
|
gameMode: { type: 'string' },
|
||||||
gameVersion: { type: 'integer' },
|
gameVersion: { type: 'integer' },
|
||||||
},
|
},
|
||||||
|
|
|
@ -15,6 +15,19 @@ export const meta = {
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
|
||||||
secure: true,
|
secure: true,
|
||||||
|
|
||||||
|
res: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
backupCodes: {
|
||||||
|
type: 'array',
|
||||||
|
optional: false,
|
||||||
|
items: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const paramDef = {
|
export const paramDef = {
|
||||||
|
|
|
@ -47,7 +47,7 @@ export const meta = {
|
||||||
properties: {
|
properties: {
|
||||||
id: {
|
id: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
nullable: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -21,26 +21,31 @@ export const meta = {
|
||||||
properties: {
|
properties: {
|
||||||
id: {
|
id: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
|
optional: false,
|
||||||
format: 'misskey:id',
|
format: 'misskey:id',
|
||||||
},
|
},
|
||||||
name: {
|
name: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
|
optional: true,
|
||||||
},
|
},
|
||||||
createdAt: {
|
createdAt: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
|
optional: false,
|
||||||
format: 'date-time',
|
format: 'date-time',
|
||||||
},
|
},
|
||||||
lastUsedAt: {
|
lastUsedAt: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
|
optional: true,
|
||||||
format: 'date-time',
|
format: 'date-time',
|
||||||
},
|
},
|
||||||
permission: {
|
permission: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
|
optional: false,
|
||||||
uniqueItems: true,
|
uniqueItems: true,
|
||||||
items: {
|
items: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -23,23 +23,27 @@ export const meta = {
|
||||||
id: {
|
id: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
format: 'misskey:id',
|
format: 'misskey:id',
|
||||||
|
optional: false,
|
||||||
},
|
},
|
||||||
name: {
|
name: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
|
optional: false,
|
||||||
},
|
},
|
||||||
callbackUrl: {
|
callbackUrl: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
nullable: true,
|
optional: false, nullable: true,
|
||||||
},
|
},
|
||||||
permission: {
|
permission: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
|
optional: false,
|
||||||
uniqueItems: true,
|
uniqueItems: true,
|
||||||
items: {
|
items: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
isAuthorized: {
|
isAuthorized: {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
|
optional: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -22,7 +22,16 @@ export const meta = {
|
||||||
|
|
||||||
res: {
|
res: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
}
|
properties: {
|
||||||
|
updatedAt: {
|
||||||
|
type: 'string',
|
||||||
|
optional: false,
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
optional: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const paramDef = {
|
export const paramDef = {
|
||||||
|
@ -50,7 +59,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
updatedAt: item.updatedAt,
|
updatedAt: item.updatedAt.toISOString(),
|
||||||
value: item.value,
|
value: item.value,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
@ -13,6 +13,9 @@ export const meta = {
|
||||||
|
|
||||||
res: {
|
res: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
|
additionalProperties: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,13 @@ import { RegistryApiService } from '@/core/RegistryApiService.js';
|
||||||
export const meta = {
|
export const meta = {
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
kind: 'read:account',
|
kind: 'read:account',
|
||||||
|
|
||||||
|
res: {
|
||||||
|
type: 'array',
|
||||||
|
items: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const paramDef = {
|
export const paramDef = {
|
||||||
|
|
|
@ -33,6 +33,7 @@ import { HttpRequestService } from '@/core/HttpRequestService.js';
|
||||||
import type { Config } from '@/config.js';
|
import type { Config } from '@/config.js';
|
||||||
import { safeForSql } from '@/misc/safe-for-sql.js';
|
import { safeForSql } from '@/misc/safe-for-sql.js';
|
||||||
import { AvatarDecorationService } from '@/core/AvatarDecorationService.js';
|
import { AvatarDecorationService } from '@/core/AvatarDecorationService.js';
|
||||||
|
import { notificationRecieveConfig } from '@/models/json-schema/user.js';
|
||||||
import { ApiLoggerService } from '../../ApiLoggerService.js';
|
import { ApiLoggerService } from '../../ApiLoggerService.js';
|
||||||
import { ApiError } from '../../error.js';
|
import { ApiError } from '../../error.js';
|
||||||
|
|
||||||
|
@ -184,7 +185,26 @@ export const paramDef = {
|
||||||
mutedInstances: { type: 'array', items: {
|
mutedInstances: { type: 'array', items: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
} },
|
} },
|
||||||
notificationRecieveConfig: { type: 'object' },
|
notificationRecieveConfig: {
|
||||||
|
type: 'object',
|
||||||
|
nullable: false,
|
||||||
|
properties: {
|
||||||
|
note: notificationRecieveConfig,
|
||||||
|
follow: notificationRecieveConfig,
|
||||||
|
mention: notificationRecieveConfig,
|
||||||
|
reply: notificationRecieveConfig,
|
||||||
|
renote: notificationRecieveConfig,
|
||||||
|
quote: notificationRecieveConfig,
|
||||||
|
reaction: notificationRecieveConfig,
|
||||||
|
pollEnded: notificationRecieveConfig,
|
||||||
|
receiveFollowRequest: notificationRecieveConfig,
|
||||||
|
followRequestAccepted: notificationRecieveConfig,
|
||||||
|
roleAssigned: notificationRecieveConfig,
|
||||||
|
achievementEarned: notificationRecieveConfig,
|
||||||
|
app: notificationRecieveConfig,
|
||||||
|
test: notificationRecieveConfig,
|
||||||
|
},
|
||||||
|
},
|
||||||
emailNotificationTypes: { type: 'array', items: {
|
emailNotificationTypes: { type: 'array', items: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
} },
|
} },
|
||||||
|
|
|
@ -33,7 +33,7 @@ export const meta = {
|
||||||
properties: {
|
properties: {
|
||||||
id: {
|
id: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
format: 'misskey:id'
|
format: 'misskey:id',
|
||||||
},
|
},
|
||||||
userId: {
|
userId: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
|
@ -45,7 +45,7 @@ export const meta = {
|
||||||
items: {
|
items: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
enum: webhookEventTypes,
|
enum: webhookEventTypes,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
url: { type: 'string' },
|
url: { type: 'string' },
|
||||||
secret: { type: 'string' },
|
secret: { type: 'string' },
|
||||||
|
@ -108,7 +108,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
url: webhook.url,
|
url: webhook.url,
|
||||||
secret: webhook.secret,
|
secret: webhook.secret,
|
||||||
active: webhook.active,
|
active: webhook.active,
|
||||||
latestSentAt: webhook.latestSentAt?.toISOString(),
|
latestSentAt: webhook.latestSentAt ? webhook.latestSentAt.toISOString() : null,
|
||||||
latestStatus: webhook.latestStatus,
|
latestStatus: webhook.latestStatus,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
@ -23,7 +23,7 @@ export const meta = {
|
||||||
properties: {
|
properties: {
|
||||||
id: {
|
id: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
format: 'misskey:id'
|
format: 'misskey:id',
|
||||||
},
|
},
|
||||||
userId: {
|
userId: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
|
@ -35,7 +35,7 @@ export const meta = {
|
||||||
items: {
|
items: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
enum: webhookEventTypes,
|
enum: webhookEventTypes,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
url: { type: 'string' },
|
url: { type: 'string' },
|
||||||
secret: { type: 'string' },
|
secret: { type: 'string' },
|
||||||
|
@ -43,8 +43,8 @@ export const meta = {
|
||||||
latestSentAt: { type: 'string', format: 'date-time', nullable: true },
|
latestSentAt: { type: 'string', format: 'date-time', nullable: true },
|
||||||
latestStatus: { type: 'integer', nullable: true },
|
latestStatus: { type: 'integer', nullable: true },
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const paramDef = {
|
export const paramDef = {
|
||||||
|
@ -73,7 +73,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
url: webhook.url,
|
url: webhook.url,
|
||||||
secret: webhook.secret,
|
secret: webhook.secret,
|
||||||
active: webhook.active,
|
active: webhook.active,
|
||||||
latestSentAt: webhook.latestSentAt?.toISOString(),
|
latestSentAt: webhook.latestSentAt ? webhook.latestSentAt.toISOString() : null,
|
||||||
latestStatus: webhook.latestStatus,
|
latestStatus: webhook.latestStatus,
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
|
@ -30,7 +30,7 @@ export const meta = {
|
||||||
properties: {
|
properties: {
|
||||||
id: {
|
id: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
format: 'misskey:id'
|
format: 'misskey:id',
|
||||||
},
|
},
|
||||||
userId: {
|
userId: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
|
@ -42,7 +42,7 @@ export const meta = {
|
||||||
items: {
|
items: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
enum: webhookEventTypes,
|
enum: webhookEventTypes,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
url: { type: 'string' },
|
url: { type: 'string' },
|
||||||
secret: { type: 'string' },
|
secret: { type: 'string' },
|
||||||
|
@ -85,7 +85,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
url: webhook.url,
|
url: webhook.url,
|
||||||
secret: webhook.secret,
|
secret: webhook.secret,
|
||||||
active: webhook.active,
|
active: webhook.active,
|
||||||
latestSentAt: webhook.latestSentAt?.toISOString(),
|
latestSentAt: webhook.latestSentAt ? webhook.latestSentAt.toISOString() : null,
|
||||||
latestStatus: webhook.latestStatus,
|
latestStatus: webhook.latestStatus,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
@ -14,9 +14,6 @@ export const meta = {
|
||||||
|
|
||||||
errors: {
|
errors: {
|
||||||
},
|
},
|
||||||
|
|
||||||
res: {
|
|
||||||
},
|
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const paramDef = {
|
export const paramDef = {
|
||||||
|
|
|
@ -30,6 +30,9 @@ export const meta = {
|
||||||
},
|
},
|
||||||
|
|
||||||
res: {
|
res: {
|
||||||
|
type: 'object',
|
||||||
|
optional: true,
|
||||||
|
ref: 'ReversiGameDetailed',
|
||||||
},
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
|
|
@ -18,24 +18,28 @@ export const meta = {
|
||||||
properties: {
|
properties: {
|
||||||
id: {
|
id: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
format: 'misskey:id'
|
format: 'misskey:id',
|
||||||
|
optional: true, nullable: false,
|
||||||
},
|
},
|
||||||
required: {
|
required: {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
|
optional: false, nullable: false,
|
||||||
},
|
},
|
||||||
string: {
|
string: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
|
optional: true, nullable: false,
|
||||||
},
|
},
|
||||||
default: {
|
default: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
|
optional: true, nullable: false,
|
||||||
},
|
},
|
||||||
nullableDefault: {
|
nullableDefault: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
default: 'hello',
|
default: 'hello',
|
||||||
nullable: true,
|
optional: true, nullable: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
|
||||||
}
|
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const paramDef = {
|
export const paramDef = {
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
"@tabler/icons-webfont": "2.44.0",
|
"@tabler/icons-webfont": "2.44.0",
|
||||||
"@twemoji/parser": "15.0.0",
|
"@twemoji/parser": "15.0.0",
|
||||||
"@vitejs/plugin-vue": "5.0.3",
|
"@vitejs/plugin-vue": "5.0.3",
|
||||||
"@vue/compiler-sfc": "3.4.15",
|
"@vue/compiler-sfc": "3.4.18",
|
||||||
"aiscript-vscode": "github:aiscript-dev/aiscript-vscode#v0.1.2",
|
"aiscript-vscode": "github:aiscript-dev/aiscript-vscode#v0.1.2",
|
||||||
"astring": "1.8.6",
|
"astring": "1.8.6",
|
||||||
"broadcast-channel": "7.0.0",
|
"broadcast-channel": "7.0.0",
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
"uuid": "9.0.1",
|
"uuid": "9.0.1",
|
||||||
"v-code-diff": "1.7.2",
|
"v-code-diff": "1.7.2",
|
||||||
"vite": "5.1.0",
|
"vite": "5.1.0",
|
||||||
"vue": "3.4.15",
|
"vue": "3.4.18",
|
||||||
"vuedraggable": "next"
|
"vuedraggable": "next"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -16,9 +16,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
@closed="$emit('closed')"
|
@closed="$emit('closed')"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template #header>
|
||||||
<template v-if="pageMetadata?.value">
|
<template v-if="pageMetadata">
|
||||||
<i v-if="pageMetadata.value.icon" :class="pageMetadata.value.icon" style="margin-right: 0.5em;"></i>
|
<i v-if="pageMetadata.icon" :class="pageMetadata.icon" style="margin-right: 0.5em;"></i>
|
||||||
<span>{{ pageMetadata.value.title }}</span>
|
<span>{{ pageMetadata.title }}</span>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, ComputedRef, onMounted, onUnmounted, provide, ref, shallowRef } from 'vue';
|
import { computed, onMounted, onUnmounted, provide, ref, shallowRef } from 'vue';
|
||||||
import RouterView from '@/components/global/RouterView.vue';
|
import RouterView from '@/components/global/RouterView.vue';
|
||||||
import MkWindow from '@/components/MkWindow.vue';
|
import MkWindow from '@/components/MkWindow.vue';
|
||||||
import { popout as _popout } from '@/scripts/popout.js';
|
import { popout as _popout } from '@/scripts/popout.js';
|
||||||
|
@ -37,7 +37,7 @@ import copyToClipboard from '@/scripts/copy-to-clipboard.js';
|
||||||
import { url } from '@/config.js';
|
import { url } from '@/config.js';
|
||||||
import { useScrollPositionManager } from '@/nirax.js';
|
import { useScrollPositionManager } from '@/nirax.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { PageMetadata, provideMetadataReceiver } from '@/scripts/page-metadata.js';
|
import { PageMetadata, provideMetadataReceiver, provideReactiveMetadata } from '@/scripts/page-metadata.js';
|
||||||
import { openingWindowsCount } from '@/os.js';
|
import { openingWindowsCount } from '@/os.js';
|
||||||
import { claimAchievement } from '@/scripts/achievements.js';
|
import { claimAchievement } from '@/scripts/achievements.js';
|
||||||
import { getScrollContainer } from '@/scripts/scroll.js';
|
import { getScrollContainer } from '@/scripts/scroll.js';
|
||||||
|
@ -56,7 +56,7 @@ const routerFactory = useRouterFactory();
|
||||||
const windowRouter = routerFactory(props.initialPath);
|
const windowRouter = routerFactory(props.initialPath);
|
||||||
|
|
||||||
const contents = shallowRef<HTMLElement | null>(null);
|
const contents = shallowRef<HTMLElement | null>(null);
|
||||||
const pageMetadata = ref<null | ComputedRef<PageMetadata>>();
|
const pageMetadata = ref<null | PageMetadata>(null);
|
||||||
const windowEl = shallowRef<InstanceType<typeof MkWindow>>();
|
const windowEl = shallowRef<InstanceType<typeof MkWindow>>();
|
||||||
const history = ref<{ path: string; key: any; }[]>([{
|
const history = ref<{ path: string; key: any; }[]>([{
|
||||||
path: windowRouter.getCurrentPath(),
|
path: windowRouter.getCurrentPath(),
|
||||||
|
@ -101,9 +101,11 @@ windowRouter.addListener('replace', ctx => {
|
||||||
windowRouter.init();
|
windowRouter.init();
|
||||||
|
|
||||||
provide('router', windowRouter);
|
provide('router', windowRouter);
|
||||||
provideMetadataReceiver((info) => {
|
provideMetadataReceiver((metadataGetter) => {
|
||||||
|
const info = metadataGetter();
|
||||||
pageMetadata.value = info;
|
pageMetadata.value = info;
|
||||||
});
|
});
|
||||||
|
provideReactiveMetadata(pageMetadata);
|
||||||
provide('shouldOmitHeaderTitle', true);
|
provide('shouldOmitHeaderTitle', true);
|
||||||
provide('shouldHeaderThin', true);
|
provide('shouldHeaderThin', true);
|
||||||
provide('forceSpacerMin', true);
|
provide('forceSpacerMin', true);
|
||||||
|
|
|
@ -11,18 +11,18 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="!thin_ && narrow && !hideTitle" :class="$style.buttonsLeft"/>
|
<div v-else-if="!thin_ && narrow && !hideTitle" :class="$style.buttonsLeft"/>
|
||||||
|
|
||||||
<template v-if="metadata">
|
<template v-if="pageMetadata">
|
||||||
<div v-if="!hideTitle" :class="$style.titleContainer" @click="top">
|
<div v-if="!hideTitle" :class="$style.titleContainer" @click="top">
|
||||||
<div v-if="metadata.avatar" :class="$style.titleAvatarContainer">
|
<div v-if="pageMetadata.avatar" :class="$style.titleAvatarContainer">
|
||||||
<MkAvatar :class="$style.titleAvatar" :user="metadata.avatar" indicator/>
|
<MkAvatar :class="$style.titleAvatar" :user="pageMetadata.avatar" indicator/>
|
||||||
</div>
|
</div>
|
||||||
<i v-else-if="metadata.icon" :class="[$style.titleIcon, metadata.icon]"></i>
|
<i v-else-if="pageMetadata.icon" :class="[$style.titleIcon, pageMetadata.icon]"></i>
|
||||||
|
|
||||||
<div :class="$style.title">
|
<div :class="$style.title">
|
||||||
<MkUserName v-if="metadata.userName" :user="metadata.userName" :nowrap="true"/>
|
<MkUserName v-if="pageMetadata.userName" :user="pageMetadata.userName" :nowrap="true"/>
|
||||||
<div v-else-if="metadata.title">{{ metadata.title }}</div>
|
<div v-else-if="pageMetadata.title">{{ pageMetadata.title }}</div>
|
||||||
<div v-if="metadata.subtitle" :class="$style.subtitle">
|
<div v-if="pageMetadata.subtitle" :class="$style.subtitle">
|
||||||
{{ metadata.subtitle }}
|
{{ pageMetadata.subtitle }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -46,7 +46,7 @@ import tinycolor from 'tinycolor2';
|
||||||
import XTabs, { Tab } from './MkPageHeader.tabs.vue';
|
import XTabs, { Tab } from './MkPageHeader.tabs.vue';
|
||||||
import { scrollToTop } from '@/scripts/scroll.js';
|
import { scrollToTop } from '@/scripts/scroll.js';
|
||||||
import { globalEvents } from '@/events.js';
|
import { globalEvents } from '@/events.js';
|
||||||
import { injectPageMetadata } from '@/scripts/page-metadata.js';
|
import { injectReactiveMetadata } from '@/scripts/page-metadata.js';
|
||||||
import { $i, openAccountMenu as openAccountMenu_ } from '@/account.js';
|
import { $i, openAccountMenu as openAccountMenu_ } from '@/account.js';
|
||||||
import { PageHeaderItem } from '@/types/page-header.js';
|
import { PageHeaderItem } from '@/types/page-header.js';
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ const emit = defineEmits<{
|
||||||
(ev: 'update:tab', key: string);
|
(ev: 'update:tab', key: string);
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const metadata = injectPageMetadata();
|
const pageMetadata = injectReactiveMetadata();
|
||||||
|
|
||||||
const hideTitle = inject('shouldOmitHeaderTitle', false);
|
const hideTitle = inject('shouldOmitHeaderTitle', false);
|
||||||
const thin_ = props.thin || inject('shouldHeaderThin', false);
|
const thin_ = props.thin || inject('shouldHeaderThin', false);
|
||||||
|
|
|
@ -18,7 +18,7 @@ export const langs = _LANGS_;
|
||||||
const preParseLocale = miLocalStorage.getItem('locale');
|
const preParseLocale = miLocalStorage.getItem('locale');
|
||||||
export let locale = preParseLocale ? JSON.parse(preParseLocale) : null;
|
export let locale = preParseLocale ? JSON.parse(preParseLocale) : null;
|
||||||
export const version = _VERSION_;
|
export const version = _VERSION_;
|
||||||
export const instanceName = siteName === 'Misskey' ? host : siteName;
|
export const instanceName = siteName === 'Misskey' || siteName == null ? host : siteName;
|
||||||
export const ui = miLocalStorage.getItem('ui');
|
export const ui = miLocalStorage.getItem('ui');
|
||||||
export const debug = miLocalStorage.getItem('debug') === 'true';
|
export const debug = miLocalStorage.getItem('debug') === 'true';
|
||||||
|
|
||||||
|
|
|
@ -67,10 +67,10 @@ const headerActions = computed(() => []);
|
||||||
|
|
||||||
const headerTabs = computed(() => []);
|
const headerTabs = computed(() => []);
|
||||||
|
|
||||||
definePageMetadata({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.error,
|
title: i18n.ts.error,
|
||||||
icon: 'ti ti-alert-triangle',
|
icon: 'ti ti-alert-triangle',
|
||||||
});
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
|
|
|
@ -363,10 +363,10 @@ const headerActions = computed(() => []);
|
||||||
|
|
||||||
const headerTabs = computed(() => []);
|
const headerTabs = computed(() => []);
|
||||||
|
|
||||||
definePageMetadata({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.aboutMisskey,
|
title: i18n.ts.aboutMisskey,
|
||||||
icon: null,
|
icon: null,
|
||||||
});
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
@ -164,10 +164,10 @@ const headerTabs = computed(() => [{
|
||||||
icon: 'ti ti-chart-line',
|
icon: 'ti ti-chart-line',
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
definePageMetadata(computed(() => ({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.instanceInfo,
|
title: i18n.ts.instanceInfo,
|
||||||
icon: 'ti ti-info-circle',
|
icon: 'ti ti-info-circle',
|
||||||
})));
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
|
|
|
@ -48,10 +48,10 @@ onDeactivated(() => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
definePageMetadata({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.achievements,
|
title: i18n.ts.achievements,
|
||||||
icon: 'ti ti-medal',
|
icon: 'ti ti-medal',
|
||||||
});
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
|
|
|
@ -140,10 +140,10 @@ const headerTabs = computed(() => [{
|
||||||
icon: 'ti ti-code',
|
icon: 'ti ti-code',
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
definePageMetadata(computed(() => ({
|
definePageMetadata(() => ({
|
||||||
title: file.value ? i18n.ts.file + ': ' + file.value.name : i18n.ts.file,
|
title: file.value ? `${i18n.ts.file}: ${file.value.name}` : i18n.ts.file,
|
||||||
icon: 'ti ti-file',
|
icon: 'ti ti-file',
|
||||||
})));
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
@ -518,10 +518,10 @@ const headerTabs = computed(() => [{
|
||||||
icon: 'ti ti-code',
|
icon: 'ti ti-code',
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
definePageMetadata(computed(() => ({
|
definePageMetadata(() => ({
|
||||||
title: user.value ? acct(user.value) : i18n.ts.userInfo,
|
title: user.value ? acct(user.value) : i18n.ts.userInfo,
|
||||||
icon: 'ti ti-user-exclamation',
|
icon: 'ti ti-user-exclamation',
|
||||||
})));
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
@ -5,12 +5,12 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div ref="el" class="fdidabkc" :style="{ background: bg }" @click="onClick">
|
<div ref="el" class="fdidabkc" :style="{ background: bg }" @click="onClick">
|
||||||
<template v-if="metadata">
|
<template v-if="pageMetadata">
|
||||||
<div class="titleContainer" @click="showTabsPopup">
|
<div class="titleContainer" @click="showTabsPopup">
|
||||||
<i v-if="metadata.icon" class="icon" :class="metadata.icon"></i>
|
<i v-if="pageMetadata.icon" class="icon" :class="pageMetadata.icon"></i>
|
||||||
|
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<div class="title">{{ metadata.title }}</div>
|
<div class="title">{{ pageMetadata.title }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
|
@ -39,7 +39,7 @@ import { popupMenu } from '@/os.js';
|
||||||
import { scrollToTop } from '@/scripts/scroll.js';
|
import { scrollToTop } from '@/scripts/scroll.js';
|
||||||
import MkButton from '@/components/MkButton.vue';
|
import MkButton from '@/components/MkButton.vue';
|
||||||
import { globalEvents } from '@/events.js';
|
import { globalEvents } from '@/events.js';
|
||||||
import { injectPageMetadata } from '@/scripts/page-metadata.js';
|
import { injectReactiveMetadata } from '@/scripts/page-metadata.js';
|
||||||
|
|
||||||
type Tab = {
|
type Tab = {
|
||||||
key?: string | null;
|
key?: string | null;
|
||||||
|
@ -65,7 +65,7 @@ const emit = defineEmits<{
|
||||||
(ev: 'update:tab', key: string);
|
(ev: 'update:tab', key: string);
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const metadata = injectPageMetadata();
|
const pageMetadata = injectReactiveMetadata();
|
||||||
|
|
||||||
const el = shallowRef<HTMLElement>(null);
|
const el = shallowRef<HTMLElement>(null);
|
||||||
const tabRefs = {};
|
const tabRefs = {};
|
||||||
|
@ -118,7 +118,7 @@ function onTabClick(tab: Tab, ev: MouseEvent): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
const calcBg = () => {
|
const calcBg = () => {
|
||||||
const rawBg = metadata?.bg ?? 'var(--bg)';
|
const rawBg = pageMetadata.value?.bg ?? 'var(--bg)';
|
||||||
const tinyBg = tinycolor(rawBg.startsWith('var(') ? getComputedStyle(document.documentElement).getPropertyValue(rawBg.slice(4, -1)) : rawBg);
|
const tinyBg = tinycolor(rawBg.startsWith('var(') ? getComputedStyle(document.documentElement).getPropertyValue(rawBg.slice(4, -1)) : rawBg);
|
||||||
tinyBg.setAlpha(0.85);
|
tinyBg.setAlpha(0.85);
|
||||||
bg.value = tinyBg.toRgbString();
|
bg.value = tinyBg.toRgbString();
|
||||||
|
|
|
@ -87,8 +87,8 @@ const headerActions = computed(() => []);
|
||||||
|
|
||||||
const headerTabs = computed(() => []);
|
const headerTabs = computed(() => []);
|
||||||
|
|
||||||
definePageMetadata({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.abuseReports,
|
title: i18n.ts.abuseReports,
|
||||||
icon: 'ti ti-exclamation-circle',
|
icon: 'ti ti-exclamation-circle',
|
||||||
});
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -255,10 +255,10 @@ const headerActions = computed(() => [{
|
||||||
|
|
||||||
const headerTabs = computed(() => []);
|
const headerTabs = computed(() => []);
|
||||||
|
|
||||||
definePageMetadata({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.ads,
|
title: i18n.ts.ads,
|
||||||
icon: 'ti ti-ad',
|
icon: 'ti ti-ad',
|
||||||
});
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
|
|
|
@ -157,8 +157,8 @@ const headerActions = computed(() => [{
|
||||||
|
|
||||||
const headerTabs = computed(() => []);
|
const headerTabs = computed(() => []);
|
||||||
|
|
||||||
definePageMetadata({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.announcements,
|
title: i18n.ts.announcements,
|
||||||
icon: 'ti ti-speakerphone',
|
icon: 'ti ti-speakerphone',
|
||||||
});
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -159,10 +159,10 @@ function save() {
|
||||||
|
|
||||||
const headerTabs = computed(() => []);
|
const headerTabs = computed(() => []);
|
||||||
|
|
||||||
definePageMetadata({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.branding,
|
title: i18n.ts.branding,
|
||||||
icon: 'ti ti-paint',
|
icon: 'ti ti-paint',
|
||||||
});
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
|
|
|
@ -33,8 +33,8 @@ const headerActions = computed(() => []);
|
||||||
|
|
||||||
const headerTabs = computed(() => []);
|
const headerTabs = computed(() => []);
|
||||||
|
|
||||||
definePageMetadata({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.database,
|
title: i18n.ts.database,
|
||||||
icon: 'ti ti-database',
|
icon: 'ti ti-database',
|
||||||
});
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -130,10 +130,10 @@ function save() {
|
||||||
|
|
||||||
const headerTabs = computed(() => []);
|
const headerTabs = computed(() => []);
|
||||||
|
|
||||||
definePageMetadata({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.emailServer,
|
title: i18n.ts.emailServer,
|
||||||
icon: 'ti ti-mail',
|
icon: 'ti ti-mail',
|
||||||
});
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
|
|
|
@ -69,10 +69,10 @@ const headerActions = computed(() => []);
|
||||||
|
|
||||||
const headerTabs = computed(() => []);
|
const headerTabs = computed(() => []);
|
||||||
|
|
||||||
definePageMetadata({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.externalServices,
|
title: i18n.ts.externalServices,
|
||||||
icon: 'ti ti-link',
|
icon: 'ti ti-link',
|
||||||
});
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
|
|
|
@ -102,10 +102,10 @@ const headerActions = computed(() => []);
|
||||||
|
|
||||||
const headerTabs = computed(() => []);
|
const headerTabs = computed(() => []);
|
||||||
|
|
||||||
definePageMetadata(computed(() => ({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.federation,
|
title: i18n.ts.federation,
|
||||||
icon: 'ti ti-whirl',
|
icon: 'ti ti-whirl',
|
||||||
})));
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
|
|
|
@ -108,8 +108,8 @@ const headerActions = computed(() => [{
|
||||||
|
|
||||||
const headerTabs = computed(() => []);
|
const headerTabs = computed(() => []);
|
||||||
|
|
||||||
definePageMetadata(computed(() => ({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.files,
|
title: i18n.ts.files,
|
||||||
icon: 'ti ti-cloud',
|
icon: 'ti ti-cloud',
|
||||||
})));
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -28,7 +28,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ComputedRef, Ref, onActivated, onMounted, onUnmounted, provide, watch, ref, computed } from 'vue';
|
import { onActivated, onMounted, onUnmounted, provide, watch, ref, computed } from 'vue';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import MkSuperMenu from '@/components/MkSuperMenu.vue';
|
import MkSuperMenu from '@/components/MkSuperMenu.vue';
|
||||||
import MkInfo from '@/components/MkInfo.vue';
|
import MkInfo from '@/components/MkInfo.vue';
|
||||||
|
@ -36,7 +36,7 @@ import { instance } from '@/instance.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||||
import { lookupUser, lookupUserByEmail } from '@/scripts/lookup-user.js';
|
import { lookupUser, lookupUserByEmail } from '@/scripts/lookup-user.js';
|
||||||
import { PageMetadata, definePageMetadata, provideMetadataReceiver } from '@/scripts/page-metadata.js';
|
import { PageMetadata, definePageMetadata, provideMetadataReceiver, provideReactiveMetadata } from '@/scripts/page-metadata.js';
|
||||||
import { useRouter } from '@/router/supplier.js';
|
import { useRouter } from '@/router/supplier.js';
|
||||||
|
|
||||||
const isEmpty = (x: string | null) => x == null || x === '';
|
const isEmpty = (x: string | null) => x == null || x === '';
|
||||||
|
@ -52,7 +52,7 @@ const indexInfo = {
|
||||||
provide('shouldOmitHeaderTitle', false);
|
provide('shouldOmitHeaderTitle', false);
|
||||||
|
|
||||||
const INFO = ref(indexInfo);
|
const INFO = ref(indexInfo);
|
||||||
const childInfo: Ref<ComputedRef<PageMetadata> | null> = ref(null);
|
const childInfo = ref<null | PageMetadata>(null);
|
||||||
const narrow = ref(false);
|
const narrow = ref(false);
|
||||||
const view = ref(null);
|
const view = ref(null);
|
||||||
const el = ref<HTMLDivElement | null>(null);
|
const el = ref<HTMLDivElement | null>(null);
|
||||||
|
@ -257,14 +257,16 @@ watch(router.currentRef, (to) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
provideMetadataReceiver((info) => {
|
provideMetadataReceiver((metadataGetter) => {
|
||||||
|
const info = metadataGetter();
|
||||||
if (info == null) {
|
if (info == null) {
|
||||||
childInfo.value = null;
|
childInfo.value = null;
|
||||||
} else {
|
} else {
|
||||||
childInfo.value = info;
|
childInfo.value = info;
|
||||||
INFO.value.needWideArea = info.value.needWideArea ?? undefined;
|
INFO.value.needWideArea = info.needWideArea ?? undefined;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
provideReactiveMetadata(INFO);
|
||||||
|
|
||||||
function invite() {
|
function invite() {
|
||||||
misskeyApi('admin/invite/create').then(x => {
|
misskeyApi('admin/invite/create').then(x => {
|
||||||
|
@ -318,7 +320,7 @@ const headerActions = computed(() => []);
|
||||||
|
|
||||||
const headerTabs = computed(() => []);
|
const headerTabs = computed(() => []);
|
||||||
|
|
||||||
definePageMetadata(INFO.value);
|
definePageMetadata(() => INFO.value);
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
header: {
|
header: {
|
||||||
|
|
|
@ -66,8 +66,8 @@ const headerTabs = computed(() => [{
|
||||||
icon: 'ti ti-eye-off',
|
icon: 'ti ti-eye-off',
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
definePageMetadata({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.instanceBlocking,
|
title: i18n.ts.instanceBlocking,
|
||||||
icon: 'ti ti-ban',
|
icon: 'ti ti-ban',
|
||||||
});
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -113,10 +113,10 @@ function deleted(id: string) {
|
||||||
const headerActions = computed(() => []);
|
const headerActions = computed(() => []);
|
||||||
const headerTabs = computed(() => []);
|
const headerTabs = computed(() => []);
|
||||||
|
|
||||||
definePageMetadata({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.invite,
|
title: i18n.ts.invite,
|
||||||
icon: 'ti ti-user-plus',
|
icon: 'ti ti-user-plus',
|
||||||
});
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
|
|
|
@ -116,10 +116,10 @@ function save() {
|
||||||
|
|
||||||
const headerTabs = computed(() => []);
|
const headerTabs = computed(() => []);
|
||||||
|
|
||||||
definePageMetadata({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.moderation,
|
title: i18n.ts.moderation,
|
||||||
icon: 'ti ti-shield',
|
icon: 'ti ti-shield',
|
||||||
});
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
|
|
|
@ -60,8 +60,8 @@ const headerActions = computed(() => []);
|
||||||
|
|
||||||
const headerTabs = computed(() => []);
|
const headerTabs = computed(() => []);
|
||||||
|
|
||||||
definePageMetadata({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.moderationLogs,
|
title: i18n.ts.moderationLogs,
|
||||||
icon: 'ti ti-list-search',
|
icon: 'ti ti-list-search',
|
||||||
});
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -149,10 +149,10 @@ function save() {
|
||||||
|
|
||||||
const headerTabs = computed(() => []);
|
const headerTabs = computed(() => []);
|
||||||
|
|
||||||
definePageMetadata({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.objectStorage,
|
title: i18n.ts.objectStorage,
|
||||||
icon: 'ti ti-cloud',
|
icon: 'ti ti-cloud',
|
||||||
});
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
|
|
|
@ -86,8 +86,8 @@ const headerActions = computed(() => [{
|
||||||
|
|
||||||
const headerTabs = computed(() => []);
|
const headerTabs = computed(() => []);
|
||||||
|
|
||||||
definePageMetadata({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.other,
|
title: i18n.ts.other,
|
||||||
icon: 'ti ti-adjustments',
|
icon: 'ti ti-adjustments',
|
||||||
});
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -184,10 +184,10 @@ const headerActions = computed(() => []);
|
||||||
|
|
||||||
const headerTabs = computed(() => []);
|
const headerTabs = computed(() => []);
|
||||||
|
|
||||||
definePageMetadata({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.dashboard,
|
title: i18n.ts.dashboard,
|
||||||
icon: 'ti ti-dashboard',
|
icon: 'ti ti-dashboard',
|
||||||
});
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
|
|
|
@ -64,8 +64,8 @@ const headerActions = computed(() => []);
|
||||||
|
|
||||||
const headerTabs = computed(() => []);
|
const headerTabs = computed(() => []);
|
||||||
|
|
||||||
definePageMetadata({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.proxyAccount,
|
title: i18n.ts.proxyAccount,
|
||||||
icon: 'ti ti-ghost',
|
icon: 'ti ti-ghost',
|
||||||
});
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -68,8 +68,8 @@ const headerTabs = computed(() => [{
|
||||||
title: 'Inbox',
|
title: 'Inbox',
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
definePageMetadata({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.jobQueue,
|
title: i18n.ts.jobQueue,
|
||||||
icon: 'ti ti-clock-play',
|
icon: 'ti ti-clock-play',
|
||||||
});
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -84,10 +84,10 @@ const headerActions = computed(() => [{
|
||||||
|
|
||||||
const headerTabs = computed(() => []);
|
const headerTabs = computed(() => []);
|
||||||
|
|
||||||
definePageMetadata({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.relays,
|
title: i18n.ts.relays,
|
||||||
icon: 'ti ti-planet',
|
icon: 'ti ti-planet',
|
||||||
});
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
|
|
|
@ -87,11 +87,8 @@ async function save() {
|
||||||
|
|
||||||
const headerTabs = computed(() => []);
|
const headerTabs = computed(() => []);
|
||||||
|
|
||||||
definePageMetadata(computed(() => role.value ? {
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts._role.edit + ': ' + role.value.name,
|
title: role.value ? `${i18n.ts._role.edit}: ${role.value.name}` : i18n.ts._role.new,
|
||||||
icon: 'ti ti-badge',
|
|
||||||
} : {
|
|
||||||
title: i18n.ts._role.new,
|
|
||||||
icon: 'ti ti-badge',
|
icon: 'ti ti-badge',
|
||||||
}));
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -170,10 +170,10 @@ const headerActions = computed(() => []);
|
||||||
|
|
||||||
const headerTabs = computed(() => []);
|
const headerTabs = computed(() => []);
|
||||||
|
|
||||||
definePageMetadata(computed(() => ({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.role + ': ' + role.name,
|
title: `${i18n.ts.role}: ${role.name}`,
|
||||||
icon: 'ti ti-badge',
|
icon: 'ti ti-badge',
|
||||||
})));
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
|
|
|
@ -270,10 +270,10 @@ const headerActions = computed(() => []);
|
||||||
|
|
||||||
const headerTabs = computed(() => []);
|
const headerTabs = computed(() => []);
|
||||||
|
|
||||||
definePageMetadata(computed(() => ({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.roles,
|
title: i18n.ts.roles,
|
||||||
icon: 'ti ti-badges',
|
icon: 'ti ti-badges',
|
||||||
})));
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
|
|
|
@ -229,8 +229,8 @@ const headerActions = computed(() => []);
|
||||||
|
|
||||||
const headerTabs = computed(() => []);
|
const headerTabs = computed(() => []);
|
||||||
|
|
||||||
definePageMetadata({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.security,
|
title: i18n.ts.security,
|
||||||
icon: 'ti ti-lock',
|
icon: 'ti ti-lock',
|
||||||
});
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -67,10 +67,10 @@ const remove = (index: number): void => {
|
||||||
|
|
||||||
const headerTabs = computed(() => []);
|
const headerTabs = computed(() => []);
|
||||||
|
|
||||||
definePageMetadata({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.serverRules,
|
title: i18n.ts.serverRules,
|
||||||
icon: 'ti ti-checkbox',
|
icon: 'ti ti-checkbox',
|
||||||
});
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
|
|
|
@ -235,10 +235,10 @@ async function save(): void {
|
||||||
|
|
||||||
const headerTabs = computed(() => []);
|
const headerTabs = computed(() => []);
|
||||||
|
|
||||||
definePageMetadata({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.general,
|
title: i18n.ts.general,
|
||||||
icon: 'ti ti-settings',
|
icon: 'ti ti-settings',
|
||||||
});
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
|
|
|
@ -137,10 +137,10 @@ const headerActions = computed(() => [{
|
||||||
|
|
||||||
const headerTabs = computed(() => []);
|
const headerTabs = computed(() => []);
|
||||||
|
|
||||||
definePageMetadata(computed(() => ({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.users,
|
title: i18n.ts.users,
|
||||||
icon: 'ti ti-users',
|
icon: 'ti ti-users',
|
||||||
})));
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
|
|
|
@ -20,9 +20,9 @@ import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { instance } from '@/instance.js';
|
import { instance } from '@/instance.js';
|
||||||
|
|
||||||
definePageMetadata({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.ads,
|
title: i18n.ts.ads,
|
||||||
icon: 'ti ti-ad',
|
icon: 'ti ti-ad',
|
||||||
});
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -106,10 +106,10 @@ const headerTabs = computed(() => [{
|
||||||
icon: 'ti ti-point',
|
icon: 'ti ti-point',
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
definePageMetadata({
|
definePageMetadata(() => ({
|
||||||
title: i18n.ts.announcements,
|
title: i18n.ts.announcements,
|
||||||
icon: 'ti ti-speakerphone',
|
icon: 'ti ti-speakerphone',
|
||||||
});
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
|
|
|
@ -91,10 +91,10 @@ const headerActions = computed(() => antenna.value ? [{
|
||||||
|
|
||||||
const headerTabs = computed(() => []);
|
const headerTabs = computed(() => []);
|
||||||
|
|
||||||
definePageMetadata(computed(() => antenna.value ? {
|
definePageMetadata(() => ({
|
||||||
title: antenna.value.name,
|
title: antenna.value ? antenna.value.name : i18n.ts.antennas,
|
||||||
icon: 'ti ti-antenna',
|
icon: 'ti ti-antenna',
|
||||||
} : null));
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
|
|
|
@ -87,8 +87,8 @@ const headerActions = computed(() => []);
|
||||||
|
|
||||||
const headerTabs = computed(() => []);
|
const headerTabs = computed(() => []);
|
||||||
|
|
||||||
definePageMetadata({
|
definePageMetadata(() => ({
|
||||||
title: 'API console',
|
title: 'API console',
|
||||||
icon: 'ti ti-terminal-2',
|
icon: 'ti ti-terminal-2',
|
||||||
});
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue