Merge branch 'main' into forkey-rebrand
Some checks failed
Check Misskey JS version / Check version (pull_request) Successful in 1m24s
Lint / pnpm_install (pull_request) Successful in 2m48s
API report (misskey.js) / report (push) Successful in 8m24s
Test (backend) / unit (22.x) (pull_request) Successful in 9m5s
Test (frontend) / vitest (22.x) (pull_request) Successful in 3m35s
Test (backend) / e2e (22.x) (pull_request) Successful in 9m54s
Test (production install and build) / production (22.x) (pull_request) Successful in 2m59s
Test (backend) / validate-api-json (22.x) (pull_request) Successful in 3m52s
Lint / lint (backend) (pull_request) Successful in 3m9s
Lint / lint (misskey-js) (pull_request) Successful in 2m45s
Lint / lint (sw) (pull_request) Successful in 2m58s
Lint / lint (frontend) (pull_request) Failing after 9m17s
Lint / typecheck (backend) (pull_request) Successful in 3m33s
Lint / typecheck (misskey-js) (pull_request) Successful in 2m52s

This commit is contained in:
ashten 2025-01-18 23:56:50 +00:00
commit b94aadf72f
47 changed files with 126 additions and 350 deletions

View file

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

View file

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

View file

@ -21,7 +21,7 @@ jobs:
submodules: true submodules: true
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v4 uses: pnpm/action-setup@v4.0.0
with: with:
run_install: false run_install: false

View file

@ -3,9 +3,7 @@ name: Check Misskey JS version
on: on:
push: push:
branches: branches:
- beta - main
- io
- host
paths: paths:
- packages/misskey-js/package.json - packages/misskey-js/package.json
- package.json - package.json

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -161,7 +161,7 @@ pnpm dev
### Run test ### Run test
Create a config file. Create a config file.
``` ```
cp .github/misskey/test.yml .config/ cp .forgejo/misskey/test.yml .config/
``` ```
Prepare DB/Redis for testing. Prepare DB/Redis for testing.
``` ```
@ -188,8 +188,8 @@ TODO
- `MISSKEY_WEBFINGER_USE_HTTP`: If it's set true, WebFinger requests will be http instead of https, useful for testing federation between servers in localhost. NEVER USE IN PRODUCTION. - `MISSKEY_WEBFINGER_USE_HTTP`: If it's set true, WebFinger requests will be http instead of https, useful for testing federation between servers in localhost. NEVER USE IN PRODUCTION.
## Continuous integration ## Continuous integration
Misskey uses GitHub Actions for executing automated tests. Misskey uses Forgejo Actions for executing automated tests.
Configuration files are located in [`/.github/workflows`](/.github/workflows). Configuration files are located in [`/.forgejo/workflows`](/.forgejo/workflows).
## Vue ## Vue
Misskey uses Vue(v3) as its front-end framework. Misskey uses Vue(v3) as its front-end framework.

View file

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

View file

@ -9,17 +9,9 @@ export const L_CHARS = '0123456789abcdefghijklmnopqrstuvwxyz';
const LU_CHARS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; const LU_CHARS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
export function secureRndstr(length = 32, { chars = LU_CHARS } = {}): string { export function secureRndstr(length = 32, { chars = LU_CHARS } = {}): string {
const chars_len = chars.length;
let str = ''; let str = '';
for (let i = 0; i < length; i++) { for (let i = 0; i < length; i++) {
let rand = Math.floor((crypto.randomBytes(1).readUInt8(0) / 0xFF) * chars_len); str += chars.charAt(crypto.randomInt(chars.length));
if (rand === chars_len) {
rand = chars_len - 1;
}
str += chars.charAt(rand);
} }
return str; return str;
} }

View file

@ -651,6 +651,14 @@ export const packedMeDetailedOnlySchema = {
type: 'boolean', type: 'boolean',
nullable: true, optional: true, nullable: true, optional: true,
}, },
approved: {
type: 'boolean',
nullable: false, optional: true,
},
signupReason: {
type: 'string',
nullable: true, optional: true,
},
securityKeysList: { securityKeysList: {
type: 'array', type: 'array',
nullable: false, optional: true, nullable: false, optional: true,

View file

@ -48,20 +48,18 @@ export class CleanChartsProcessorService {
public async process(): Promise<void> { public async process(): Promise<void> {
this.logger.info('Clean charts...'); this.logger.info('Clean charts...');
await Promise.all([ await this.federationChart.clean();
this.federationChart.clean(), await this.notesChart.clean();
this.notesChart.clean(), await this.usersChart.clean();
this.usersChart.clean(), await this.activeUsersChart.clean();
this.activeUsersChart.clean(), await this.instanceChart.clean();
this.instanceChart.clean(), await this.perUserNotesChart.clean();
this.perUserNotesChart.clean(), await this.perUserPvChart.clean();
this.perUserPvChart.clean(), await this.driveChart.clean();
this.driveChart.clean(), await this.perUserReactionsChart.clean();
this.perUserReactionsChart.clean(), await this.perUserFollowingChart.clean();
this.perUserFollowingChart.clean(), await this.perUserDriveChart.clean();
this.perUserDriveChart.clean(), await this.apRequestChart.clean();
this.apRequestChart.clean(),
]);
this.logger.succ('All charts successfully cleaned.'); this.logger.succ('All charts successfully cleaned.');
} }

View file

@ -31,11 +31,9 @@ export class ResyncChartsProcessorService {
// TODO: ユーザーごとのチャートも更新する // TODO: ユーザーごとのチャートも更新する
// TODO: インスタンスごとのチャートも更新する // TODO: インスタンスごとのチャートも更新する
await Promise.all([ await this.driveChart.resync();
this.driveChart.resync(), await this.notesChart.resync();
this.notesChart.resync(), await this.usersChart.resync();
this.usersChart.resync(),
]);
this.logger.succ('All charts successfully resynced.'); this.logger.succ('All charts successfully resynced.');
} }

View file

@ -48,20 +48,18 @@ export class TickChartsProcessorService {
public async process(): Promise<void> { public async process(): Promise<void> {
this.logger.info('Tick charts...'); this.logger.info('Tick charts...');
await Promise.all([ await this.federationChart.tick(false);
this.federationChart.tick(false), await this.notesChart.tick(false);
this.notesChart.tick(false), await this.usersChart.tick(false);
this.usersChart.tick(false), await this.activeUsersChart.tick(false);
this.activeUsersChart.tick(false), await this.instanceChart.tick(false);
this.instanceChart.tick(false), await this.perUserNotesChart.tick(false);
this.perUserNotesChart.tick(false), await this.perUserPvChart.tick(false);
this.perUserPvChart.tick(false), await this.driveChart.tick(false);
this.driveChart.tick(false), await this.perUserReactionsChart.tick(false);
this.perUserReactionsChart.tick(false), await this.perUserFollowingChart.tick(false);
this.perUserFollowingChart.tick(false), await this.perUserDriveChart.tick(false);
this.perUserDriveChart.tick(false), await this.apRequestChart.tick(false);
this.apRequestChart.tick(false),
]);
this.logger.succ('All charts successfully ticked.'); this.logger.succ('All charts successfully ticked.');
} }

View file

@ -244,14 +244,14 @@ export class SignupApiService {
} else { } else {
try { try {
const { account, secret } = await this.signupService.signup({ const { account, secret } = await this.signupService.signup({
username, password, host, reason username, password, host, reason,
}); });
if (instance.approvalRequiredForSignup) { if (instance.approvalRequiredForSignup) {
if (emailAddress) { if (emailAddress) {
this.emailService.sendEmail(emailAddress, 'Approval pending', this.emailService.sendEmail(emailAddress, 'Approval pending',
'Congratulations! Your account is now pending approval. You will get notified when you have been accepted.', 'Congratulations! Your account is now pending approval. You will get notified when you have been accepted.',
'Congratulations! Your account is now pending approval. You will get notified when you have been accepted.'); 'Congratulations! Your account is now pending approval. You will get notified when you have been accepted.');
} }
} }

View file

@ -63,12 +63,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
await this.usedUsernamesRepository.delete({ username: user.username }); await this.usedUsernamesRepository.delete({ username: user.username });
//Actually delete it since the last function doesnt actually delete the account //Actually delete it since the last function doesnt actually delete the account
//Note: Before approval these accounts wont federate so this is totally fine. //Note: Before approval these accounts wont federate so this is totally fine.
await this.usersRepository.delete(user.id); await this.usersRepository.delete(user.id);
this.moderationLogService.log(me, 'decline', { this.moderationLogService.log(me, 'decline', {
userId: user.id, userId: user.id,
userUsername: user.username, userUsername: user.username,

View file

@ -37,9 +37,9 @@ export const meta = {
unapprovedUser: { unapprovedUser: {
message: 'The user has not been approved yet.', message: 'The user has not been approved yet.',
code: 'UNAPPROVED_USER', code: 'UNAPPROVED_USER',
id: '8d66f136-b3e1-48fd-92c4-30ecfd7fdb7a', id: '8d66f136-b3e1-48fd-92c4-30ecfd7fdb7a',
}, },
followeeIsYourself: { followeeIsYourself: {
message: 'Followee is yourself.', message: 'Followee is yourself.',

View file

@ -40,7 +40,7 @@ export const meta = {
res: { res: {
type: 'object', type: 'object',
optional: false, nullable: false, optional: true, nullable: false,
properties: { properties: {
createdNote: { createdNote: {
type: 'object', type: 'object',
@ -207,6 +207,7 @@ export const paramDef = {
}, },
required: ['choices'], required: ['choices'],
}, },
noCreatedNote: { type: 'boolean', default: false },
}, },
// (re)note with text, files and poll are optional // (re)note with text, files and poll are optional
if: { if: {
@ -281,7 +282,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
const note = await this.notesRepository.findOneBy({ id: idempotent }); const note = await this.notesRepository.findOneBy({ id: idempotent });
if (note) { if (note) {
logger.info('The request has already been processed.', { noteId: note.id }); logger.info('The request has already been processed.', { noteId: note.id });
return { createdNote: await this.noteEntityService.pack(note, me) }; if (ps.noCreatedNote) return;
else return { createdNote: await this.noteEntityService.pack(note, me) };
} }
} }
@ -453,7 +455,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
await this.redisForTimelines.set(`note:idempotent:${me.id}:${hash}`, note.id, 'EX', 60); await this.redisForTimelines.set(`note:idempotent:${me.id}:${hash}`, note.id, 'EX', 60);
logger.info('Successfully created a note.', { noteId: note.id }); logger.info('Successfully created a note.', { noteId: note.id });
return { if (ps.noCreatedNote) return;
else return {
createdNote: await this.noteEntityService.pack(note, me), createdNote: await this.noteEntityService.pack(note, me),
}; };
} catch (err) { } catch (err) {

View file

@ -41,7 +41,8 @@ window.onload = async () => {
document.getElementById('submit').addEventListener('click', () => { document.getElementById('submit').addEventListener('click', () => {
api('notes/create', { api('notes/create', {
text: document.getElementById('text').value text: document.getElementById('text').value,
noCreatedNote: true,
}).then(() => { }).then(() => {
location.reload(); location.reload();
}); });

View file

@ -151,6 +151,8 @@ describe('ユーザー', () => {
...(security ? { ...(security ? {
email: user.email, email: user.email,
emailVerified: user.emailVerified, emailVerified: user.emailVerified,
approved: user.approved,
signupReason: user.signupReason,
securityKeysList: user.securityKeysList, securityKeysList: user.securityKeysList,
} : {}), } : {}),
}); });

View file

@ -798,6 +798,7 @@ async function post(ev?: MouseEvent) {
visibility: visibility.value, visibility: visibility.value,
visibleUserIds: visibility.value === 'specified' ? visibleUsers.value.map(u => u.id) : undefined, visibleUserIds: visibility.value === 'specified' ? visibleUsers.value.map(u => u.id) : undefined,
reactionAcceptance: reactionAcceptance.value, reactionAcceptance: reactionAcceptance.value,
noCreatedNote: true,
}; };
if (withHashtags.value && hashtags.value && hashtags.value.trim() !== '') { if (withHashtags.value && hashtags.value && hashtags.value.trim() !== '') {

View file

@ -46,8 +46,8 @@ const pagination = {
function deleted(id: string) { function deleted(id: string) {
if (paginationComponent.value) { if (paginationComponent.value) {
paginationComponent.value.items = paginationComponent.value.items.filter( paginationComponent.value.items = paginationComponent.value.items.filter(
(item: any) => item.id !== id (item: any) => item.id !== id,
); );
} }
} }

View file

@ -46,6 +46,7 @@ function start(_game: Misskey.entities.ReversiGameDetailed) {
misskeyApi('notes/create', { misskeyApi('notes/create', {
text: i18n.ts._reversi.iStartedAGame + '\n' + location.href, text: i18n.ts._reversi.iStartedAGame + '\n' + location.href,
visibility: 'home', visibility: 'home',
noCreatedNote: true,
}); });
} }

View file

@ -484,13 +484,13 @@ const routes: RouteDef[] = [{
component: page(() => import('@/pages/admin/invites.vue')), component: page(() => import('@/pages/admin/invites.vue')),
}, { }, {
path: '/approvals', path: '/approvals',
name: 'approvals', name: 'approvals',
component: page(() => import('@/pages/admin/approvals.vue')), component: page(() => import('@/pages/admin/approvals.vue')),
}, { }, {
path: '/', path: '/',
component: page(() => import('@/pages/_empty_.vue')), component: page(() => import('@/pages/_empty_.vue')),
}], }],
},{ }, {
path: '/my/notifications', path: '/my/notifications',
component: page(() => import('@/pages/notifications.vue')), component: page(() => import('@/pages/notifications.vue')),
loginRequired: true, loginRequired: true,

View file

@ -543,6 +543,7 @@ export function getRenoteMenu(props: {
misskeyApi('notes/create', { misskeyApi('notes/create', {
renoteId: appearNote.id, renoteId: appearNote.id,
channelId: appearNote.channelId, channelId: appearNote.channelId,
noCreatedNote: true,
}).then(() => { }).then(() => {
os.toast(i18n.ts.renoted); os.toast(i18n.ts.renoted);
}); });
@ -589,6 +590,7 @@ export function getRenoteMenu(props: {
localOnly, localOnly,
visibility, visibility,
renoteId: appearNote.id, renoteId: appearNote.id,
noCreatedNote: true,
}).then(() => { }).then(() => {
os.toast(i18n.ts.renoted); os.toast(i18n.ts.renoted);
}); });
@ -630,6 +632,7 @@ export function getRenoteMenu(props: {
misskeyApi('notes/create', { misskeyApi('notes/create', {
renoteId: appearNote.id, renoteId: appearNote.id,
channelId: channel.id, channelId: channel.id,
noCreatedNote: true,
}).then(() => { }).then(() => {
os.toast(i18n.tsx.renotedToX({ name: channel.name })); os.toast(i18n.tsx.renotedToX({ name: channel.name }));
}); });

View file

@ -298,7 +298,7 @@ export function getUserMenu(user: Misskey.entities.UserDetailed, router: IRouter
const { canceled: canceled3, result: memo } = await os.inputText({ const { canceled: canceled3, result: memo } = await os.inputText({
title: i18n.ts.addMemo, title: i18n.ts.addMemo,
type: 'textarea', type: 'textarea',
placeholder: i18n.ts.memo, default: '',
}); });
if (canceled3) return; if (canceled3) return;

View file

@ -4103,6 +4103,8 @@ export type components = {
policies: components['schemas']['RolePolicies']; policies: components['schemas']['RolePolicies'];
email?: string | null; email?: string | null;
emailVerified?: boolean | null; emailVerified?: boolean | null;
approved?: boolean;
signupReason?: string | null;
securityKeysList?: { securityKeysList?: {
/** /**
* Format: id * Format: id
@ -15517,6 +15519,8 @@ export type operations = {
type?: string | null; type?: string | null;
/** @enum {string|null} */ /** @enum {string|null} */
sort?: '+createdAt' | '-createdAt' | '+name' | '-name' | '+size' | '-size' | null; sort?: '+createdAt' | '-createdAt' | '+name' | '-name' | '+size' | '-size' | null;
/** @default */
searchQuery?: string;
}; };
}; };
}; };
@ -16116,6 +16120,8 @@ export type operations = {
* @default null * @default null
*/ */
folderId?: string | null; folderId?: string | null;
/** @default */
searchQuery?: string;
}; };
}; };
}; };
@ -23459,6 +23465,8 @@ export type operations = {
expiresAt?: number | null; expiresAt?: number | null;
expiredAfter?: number | null; expiredAfter?: number | null;
}) | null; }) | null;
/** @default false */
noCreatedNote?: boolean;
}; };
}; };
}; };
@ -23471,6 +23479,10 @@ export type operations = {
}; };
}; };
}; };
/** @description OK (without any results) */
204: {
content: never;
};
/** @description Client error */ /** @description Client error */
400: { 400: {
content: { content: {

View file

@ -114,7 +114,7 @@ globalThis.addEventListener('notificationclick', (ev: ServiceWorkerGlobalScopeEv
if ('note' in data.body) client = await swos.openPost({ reply: data.body.note }, loginId); if ('note' in data.body) client = await swos.openPost({ reply: data.body.note }, loginId);
break; break;
case 'renote': case 'renote':
if ('note' in data.body) await swos.api('notes/create', loginId, { renoteId: data.body.note.id }); if ('note' in data.body) await swos.api('notes/create', loginId, { renoteId: data.body.note.id, noCreatedNote: true });
break; break;
case 'accept': case 'accept':
switch (data.body.type) { switch (data.body.type) {