diff --git a/.github/reviewer-lottery.yml b/.github/reviewer-lottery.yml deleted file mode 100644 index c88e1342d..000000000 --- a/.github/reviewer-lottery.yml +++ /dev/null @@ -1,9 +0,0 @@ -groups: - - name: devs - reviewers: 2 - internal_reviewers: 1 - usernames: - - syuilo - - acid-chicken - - EbiseLutica - - tamaina diff --git a/.github/workflows/api-misskey-js.yml b/.github/workflows/api-misskey-js.yml index 4cf523a6b..39f29bf77 100644 --- a/.github/workflows/api-misskey-js.yml +++ b/.github/workflows/api-misskey-js.yml @@ -9,7 +9,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v4.0.0 + uses: actions/checkout@v4.1.0 - run: corepack enable diff --git a/.github/workflows/check_copyright_year.yml b/.github/workflows/check_copyright_year.yml index 313265f67..fb04cf1b0 100644 --- a/.github/workflows/check_copyright_year.yml +++ b/.github/workflows/check_copyright_year.yml @@ -10,7 +10,7 @@ jobs: check_copyright_year: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.0.0 + - uses: actions/checkout@v4.1.0 - run: | if [ "$(grep Copyright COPYING | sed -e 's/.*2014-\([0-9]*\) .*/\1/g')" -ne "$(date +%Y)" ]; then echo "Please change copyright year!" diff --git a/.github/workflows/docker-develop.yml b/.github/workflows/docker-develop.yml index e98c75acd..c519c9236 100644 --- a/.github/workflows/docker-develop.yml +++ b/.github/workflows/docker-develop.yml @@ -13,24 +13,24 @@ jobs: if: github.repository == 'laoxong/misskey' steps: - name: Check out the repo - uses: actions/checkout@v4.0.0 + uses: actions/checkout@v4.1.0 - name: Set up Docker Buildx id: buildx - uses: docker/setup-buildx-action@v2.10.0 + uses: docker/setup-buildx-action@v3.0.0 with: platforms: linux/amd64,linux/arm64 - name: Docker meta id: meta - uses: docker/metadata-action@v4 + uses: docker/metadata-action@v5 with: images: laoxong/misskey - name: Log in to Docker Hub - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Build and Push to Docker Hub - uses: docker/build-push-action@v4 + uses: docker/build-push-action@v5 with: builder: ${{ steps.buildx.outputs.name }} context: . diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 6eb64c54f..8538b2748 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -12,15 +12,15 @@ jobs: steps: - name: Check out the repo - uses: actions/checkout@v4.0.0 + uses: actions/checkout@v4.1.0 - name: Set up Docker Buildx id: buildx - uses: docker/setup-buildx-action@v2.10.0 + uses: docker/setup-buildx-action@v3.0.0 with: platforms: linux/amd64,linux/arm64 - name: Docker meta id: meta - uses: docker/metadata-action@v4 + uses: docker/metadata-action@v5 with: images: laoxong/misskey tags: | @@ -31,12 +31,12 @@ jobs: type=semver,pattern={{major}}.{{minor}} type=semver,pattern={{major}} - name: Log in to Docker Hub - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Build and Push to Docker Hub - uses: docker/build-push-action@v4 + uses: docker/build-push-action@v5 with: builder: ${{ steps.buildx.outputs.name }} context: . diff --git a/.github/workflows/dockle.yml b/.github/workflows/dockle.yml index d811944d6..2a1ac3a16 100644 --- a/.github/workflows/dockle.yml +++ b/.github/workflows/dockle.yml @@ -14,7 +14,7 @@ jobs: env: DOCKER_CONTENT_TRUST: 1 steps: - - uses: actions/checkout@v4.0.0 + - uses: actions/checkout@v4.1.0 - run: | curl -L -o dockle.deb "https://github.com/goodwithtech/dockle/releases/download/v0.4.10/dockle_0.4.10_Linux-64bit.deb" sudo dpkg -i dockle.deb diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 7c10c23e7..798e6f49a 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -11,7 +11,7 @@ jobs: pnpm_install: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.0.0 + - uses: actions/checkout@v4.1.0 with: fetch-depth: 0 submodules: true @@ -38,7 +38,7 @@ jobs: - sw - misskey-js steps: - - uses: actions/checkout@v4.0.0 + - uses: actions/checkout@v4.1.0 with: fetch-depth: 0 submodules: true @@ -64,7 +64,7 @@ jobs: - backend - misskey-js steps: - - uses: actions/checkout@v4.0.0 + - uses: actions/checkout@v4.1.0 with: fetch-depth: 0 submodules: true diff --git a/.github/workflows/ok-to-test.yml b/.github/workflows/ok-to-test.yml index 71d09f781..c02b980e4 100644 --- a/.github/workflows/ok-to-test.yml +++ b/.github/workflows/ok-to-test.yml @@ -17,7 +17,7 @@ jobs: # See app.yml for an example app manifest - name: Generate token id: generate_token - uses: tibdex/github-app-token@v1 + uses: tibdex/github-app-token@v2 with: app_id: ${{ secrets.DEPLOYBOT_APP_ID }} private_key: ${{ secrets.DEPLOYBOT_PRIVATE_KEY }} diff --git a/.github/workflows/pr-preview-deploy.yml b/.github/workflows/pr-preview-deploy.yml index 702d8917e..44f97645d 100644 --- a/.github/workflows/pr-preview-deploy.yml +++ b/.github/workflows/pr-preview-deploy.yml @@ -53,7 +53,7 @@ jobs: # Check out merge commit - name: Fork based /deploy checkout - uses: actions/checkout@v4.0.0 + uses: actions/checkout@v4.1.0 with: ref: 'refs/pull/${{ github.event.client_payload.pull_request.number }}/merge' diff --git a/.github/workflows/test-backend.yml b/.github/workflows/test-backend.yml index 19496c895..ac7d1afda 100644 --- a/.github/workflows/test-backend.yml +++ b/.github/workflows/test-backend.yml @@ -29,7 +29,7 @@ jobs: - 56312:6379 steps: - - uses: actions/checkout@v4.0.0 + - uses: actions/checkout@v4.1.0 with: submodules: true - name: Install pnpm diff --git a/.github/workflows/test-frontend.yml b/.github/workflows/test-frontend.yml index 0618a0ef0..e67b51654 100644 --- a/.github/workflows/test-frontend.yml +++ b/.github/workflows/test-frontend.yml @@ -16,7 +16,7 @@ jobs: node-version: [20.5.1] steps: - - uses: actions/checkout@v4.0.0 + - uses: actions/checkout@v4.1.0 with: submodules: true - name: Install pnpm @@ -68,7 +68,7 @@ jobs: - 56312:6379 steps: - - uses: actions/checkout@v4.0.0 + - uses: actions/checkout@v4.1.0 with: submodules: true # https://github.com/cypress-io/cypress-docker-images/issues/150 diff --git a/.github/workflows/test-misskey-js.yml b/.github/workflows/test-misskey-js.yml index 7999c183b..1846b628d 100644 --- a/.github/workflows/test-misskey-js.yml +++ b/.github/workflows/test-misskey-js.yml @@ -21,7 +21,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v4.0.0 + uses: actions/checkout@v4.1.0 - run: corepack enable diff --git a/.github/workflows/test-production.yml b/.github/workflows/test-production.yml index 0504f42d1..c57001896 100644 --- a/.github/workflows/test-production.yml +++ b/.github/workflows/test-production.yml @@ -19,7 +19,7 @@ jobs: node-version: [20.5.1] steps: - - uses: actions/checkout@v4.0.0 + - uses: actions/checkout@v4.1.0 with: submodules: true - name: Install pnpm diff --git a/CHANGELOG.md b/CHANGELOG.md index 03c93f70d..26013c14d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,40 +12,80 @@ --> -## 2023.9.0 (unreleased) +## 2023.9.1 ### General -- OAuth 2.0のサポート -- お知らせ機能の強化 +- Enhance: モデレーションログ機能の強化 + +### Client +- Fix: ノートのメニューにある「詳細」ボタンの表示がログイン/ログアウト状態で統一されていない問題を修正 + +### Server +- Fix: お知らせのページネーションが機能しない +- Fix: 「ユーザーの新規投稿」の通知設定を切り替えるとサーバー内部エラーが出る + +## 2023.9.0 + +### Note +- meilisearchを使用する場合、v1.2以上が必要です + +### General +- Feat: OAuth 2.0のサポート +- Feat: お知らせ機能の強化 - ユーザー個別のお知らせを作成可能に - お知らせのバナー表示やダイアログ表示が可能に - お知らせのアイコンを設定可能に -- チャンネルをセンシティブ指定できるようになりました +- Feat: チャンネルをセンシティブ指定できるようになりました - センシティブチャンネルのNoteのReNoteはデフォルトでHome TLに流れるようになりました - センシティブチャンネルのノートはユーザープロフィールに表示されません -- 二要素認証のバックアップコードが生成されるようになりました ref. https://github.com/MisskeyIO/misskey/pull/121 -- 二要素認証でパスキーをサポートするようになりました +- Feat: 二要素認証のバックアップコードが生成されるようになりました + - ref. https://github.com/MisskeyIO/misskey/pull/121 +- Feat: 二要素認証でパスキーをサポートするようになりました +- Feat: 指定したユーザーが投稿したときに通知できるようになりました +- Feat: プロフィールでのリンク検証 +- Feat: モデレーションログ機能 +- Feat: 通知をテストできるようになりました +- Feat: PWAのアイコンが設定できるようになりました +- Enhance: サーバー名の略称が設定できるようになりました +- Enhance: アンテナの受信ソースに指定したユーザを除外するものを追加 +- Enhance: 二要素認証設定時のセキュリティを強化 + - パスワード入力が必要な操作を行う際、二要素認証が有効であれば確認コードの入力も必要になりました +- Enhance: manifest.jsonをオーバーライド可能に +- Enhance: 依存関係の更新 +- Enhance: ローカリゼーションの更新 ### Client -- プロフィールにその人が作ったPlayの一覧出せるように -- メニューのスイッチの動作を改善 -- 絵文字ピッカーの検索の表示件数を100件に増加 -- 投稿フォームのプレビューの表示状態を記憶するように -- AiScriptからMisskeyサーバーAPIを呼び出す際の制限を撤廃 -- Playで直接投稿フォームを埋め込めるように(`Ui:C:postForm`) -- 通知をテストできるように +- Feat: 任意のユーザーリストをタイムラインページにピン留めできるように + - 設定->クライアント設定->全般 から設定可能です +- Feat: Playで直接投稿フォームを埋め込めるように(`Ui:C:postForm`) +- Feat: クライアントを起動している間、デバイスの画面が自動でオフになるのを防ぐオプションを追加 +- Feat: 新しい実績を追加 +- Enhance: ノート詳細ページでリノート一覧、リアクション一覧タブを追加 + - ノートのメニューからは当該項目は消えました +- Enhance: センシティブなメディアを目立たせる設定を追加 +- Enhance: プロフィールにその人が作ったPlayの一覧出せるように +- Enhance: メニューのスイッチの動作を改善 +- Enhance: 絵文字ピッカーの検索の表示件数を100件に増加 +- Enhance: 投稿フォームのプレビューの表示状態を記憶するように - Enhance: ユーザーメニューでスイッチでユーザーリストに追加・削除できるように - Enhance: 自分が押したリアクションのデザインを改善 - Enhance: ノート検索にローカルのみ検索可能なオプションの追加 -- Enhance: AiScriptで`LOCALE`として現在の設定言語を取得できるように - Enhance: Renote自体を通報できるように - Enhance: データセーバーモードの強化 - Enhance: Renoteを管理者権限で削除可能に -- `$[rainbow ]`記法が、動きのあるMFMが無効になっていても使用できるようになりました -- Playの操作を行うAPI TokenをAPIコンソールから発行できるように -- リアクションの表示サイズをより大きくできるように -- ノート詳細ページ読み込み時のパフォーマンスを改善 -- タイムラインでリスト/アンテナ選択時のパフォーマンスを改善 +- Enhance: `$[rainbow ]`記法が、動きのあるMFMが無効になっていても使用できるようになりました +- Enhance: Playの操作を行うAPI TokenをAPIコンソールから発行できるように +- Enhance: リアクションの表示サイズをより大きくできるように +- Enhance: AiScriptを0.16.0に更新 +- Enhance: AiScriptからMisskeyサーバーAPIを呼び出す際の制限を撤廃 +- Enhance: AiScriptで`LOCALE`として現在の設定言語を取得できるように +- Enhance: Mk:apiが失敗した時にエラー型の値(AiScript 0.16.0で追加)を返すように +- Enhance: ScratchpadでAsync:系関数やボタンのコールバックなどのエラーにもダイアログを出すように(試験的なためPlayなどには未実装) +- Enhance: ノート詳細ページ読み込み時のパフォーマンスが向上しました +- Enhance: タイムラインでリスト/アンテナ選択時のパフォーマンスを改善 +- Enhance: 「Moderation note」、「Add moderation note」をローカライズできるように +- Enhance: プラグインのソースコードを確認・コピーできるように +- Enhance: 細かなデザインの調整 - Fix: サーバー情報画面(`/instance-info/{domain}`)でブロックができないのを修正 - Fix: 未読のお知らせの「わかった」をクリック・タップしてもその場で「わかった」が消えない問題を修正 - Fix: iOSで画面を回転させるとテキストサイズが変わる問題を修正 @@ -53,20 +93,32 @@ - Fix: タイムラインを下にスクロールしてノート画面に移動して再び戻ったら以前のスクロール位置を失う問題を修正 - Fix: Misskeyプラグインをインストールする際のAiScriptバージョンのチェックが0.14.0以降に対応していない問題を修正 - Fix: 他のサーバーのユーザーへ「メッセージを送信」した時の初期テキストのメンションが間違っている問題を修正 +- Fix: 環境によってはMisskey Webが開けない問題を修正 +- Fix: プラグインの権限リストが見れない問題を修正 +- Fix: 複数の階層があるメニューで、短くタップすると正常に動かない場合がある問題を修正 +- Fix: アニメーションがオフのとき、スマホで子メニューの選択ができない問題を修正 +- Fix: ドロワーメニューで、親メニュー項目をマウスでホバーすると子メニューが表示されてしまう問題を修正 +- Fix: AiScriptでMk:apiが外部と通信できる問題を修正 ### Server -- cacheRemoteFilesの初期値はfalseになりました -- ファイルアップロード時等にファイル名の拡張子を修正する関数(correctFilename)の挙動を改善 -- Webhookのペイロードにサーバーのurlが含まれるようになりました -- Webhook設定でsecretを空に出来るように -- 使われていないアンテナの自動停止を設定可能に -- nodeinfo 2.1対応 -- 自分へのメンション一覧を取得する際のパフォーマンスを向上 +- Change: cacheRemoteFilesの初期値はfalseになりました +- Enhance: ファイルアップロード時等にファイル名の拡張子を修正する関数(correctFilename)の挙動を改善 +- Enhance: Webhookのペイロードにサーバーのurlが含まれるようになりました +- Enhance: Webhook設定でsecretを空に出来るように +- Enhance: 使われていないアンテナの自動停止を設定可能に +- Enhance: nodeinfo 2.1対応 +- Enhance: 自分へのメンション一覧を取得する際のパフォーマンスを向上 +- Enhance: Docker環境でjemallocを使用することでメモリ使用量を削減 +- Enhance: ID生成方式としてaidxを追加、かつデフォルトに +- Enhance: Add address bind config option (outgoingAddress) +- Fix: MK_ONLY_SERVERオプションを指定した際にクラッシュする問題を修正 +- Fix: notes/reactionsのページネーションが機能しない問題を修正 - Fix: ノート検索 `notes/search` にてhostを指定した際に検索結果に反映されるように - Fix: 一部のfeatured noteを照会できない問題を修正 - Fix: muteがapiからのuser list timeline取得で機能しない問題を修正 - Fix: ジョブキュー管理画面の認証を回避できる問題を修正 - Fix: 一部のサーバー内部エラーがスタックトレースを返さないように修正 +- Fix: 一部のリモートユーザーをフォローすることができない問題を修正 ## 13.14.2 @@ -81,7 +133,6 @@ ### Server - Fix: APIのオフセットが壊れていたせいで「もっと見る」でもっと見れない問題を修正 - Fix: 外部サーバーの投稿がタイムラインに表示されないことがある問題を修正 -- Enhance: Add address bind config option (outgoingAddress) ## 13.14.1 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e81fecf35..484fd9941 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -436,3 +436,6 @@ marginはそのコンポーネントを使う側が設定する ## その他 ### HTMLのクラス名で follow という単語は使わない 広告ブロッカーで誤ってブロックされる + +### indexというファイル名を使うな +ESMではディレクトリインポートは廃止されているのと、ディレクトリインポートせずともファイル名が index だと何故か一部のライブラリ?でディレクトリインポートだと見做されてエラーになる diff --git a/Dockerfile b/Dockerfile index 678b991e8..d397fe01c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -62,7 +62,8 @@ ARG GID="991" RUN apt-get update \ && apt-get install -y --no-install-recommends \ - ffmpeg tini curl \ + ffmpeg tini curl libjemalloc-dev libjemalloc2 \ + && ln -s /usr/lib/$(uname -m)-linux-gnu/libjemalloc.so.2 /usr/local/lib/libjemalloc.so \ && corepack enable \ && groupadd -g "${GID}" misskey \ && useradd -l -u "${UID}" -g "${GID}" -m -d /misskey misskey \ @@ -81,6 +82,7 @@ COPY --chown=misskey:misskey --from=native-builder /misskey/packages/backend/bui COPY --chown=misskey:misskey --from=native-builder /misskey/fluent-emojis /misskey/fluent-emojis COPY --chown=misskey:misskey . ./ +ENV LD_PRELOAD=/usr/local/lib/libjemalloc.so ENV NODE_ENV=production HEALTHCHECK --interval=5s --retries=20 CMD ["/bin/bash", "/misskey/healthcheck.sh"] ENTRYPOINT ["/usr/bin/tini", "--"] diff --git a/docker-compose.yml.example b/docker-compose.yml.example index a0061c5c2..60ba4dc8c 100644 --- a/docker-compose.yml.example +++ b/docker-compose.yml.example @@ -50,7 +50,7 @@ services: # meilisearch: # restart: always -# image: getmeili/meilisearch:v1.1.1 +# image: getmeili/meilisearch:v1.3.4 # environment: # - MEILI_NO_ANALYTICS=true # - MEILI_ENV=production diff --git a/locales/ar-SA.yml b/locales/ar-SA.yml index 920914ff1..55b7cbb88 100644 --- a/locales/ar-SA.yml +++ b/locales/ar-SA.yml @@ -348,7 +348,6 @@ invite: "دعوة" driveCapacityPerLocalAccount: "حصة التخزين لكل مستخدم محلي" driveCapacityPerRemoteAccount: "حصة التخزين لكل مستخدم بعيد" inMb: "بالميغابايت" -iconUrl: "رابط الأيقونة" bannerUrl: "رابط صورة اللافتة" backgroundImageUrl: "رابط صورة الخلفية" basicInfo: "المعلومات الأساسية " @@ -998,6 +997,8 @@ expirationDate: "تاريخ انتهاء الصلاحية" unused: "غير مستعمَل" expired: "منتهية صلاحيته" icon: "الصورة الرمزية" +replies: "رد" +renotes: "أعد النشر" _initialAccountSetting: accountCreated: "نجح إنشاء حسابك!" letsStartAccountSetup: "إذا كنت جديدًا لنعدّ حسابك الشخصي." @@ -1139,6 +1140,7 @@ _plugin: install: "ثبّت إضافات" installWarn: "رجاءً لا تثبت إضافات غير موثوقة." manage: "إدارة الإضافات" + viewSource: "اظهر المصدر" _preferencesBackups: createdAt: "تم إنشاؤه: {date} {time}" updatedAt: "آخر تحديث: {date} {time}" @@ -1554,3 +1556,6 @@ _webhookSettings: active: "مُفعّل" _events: reaction: "عند التفاعل" +_moderationLogTypes: + suspend: "علِق" + resetPassword: "أعد تعيين كلمتك السرية" diff --git a/locales/bn-BD.yml b/locales/bn-BD.yml index d78b58535..64b32d176 100644 --- a/locales/bn-BD.yml +++ b/locales/bn-BD.yml @@ -328,7 +328,6 @@ invite: "আমন্ত্রণ" driveCapacityPerLocalAccount: "প্রত্যেক স্থানীয় ব্যাবহারকারীর জন্য ড্রাইভের জায়গা" driveCapacityPerRemoteAccount: "প্রত্যেক রিমোট ব্যাবহারকারীর জন্য ড্রাইভের জায়গা" inMb: "মেগাবাইটে লিখুন" -iconUrl: "আইকনের URL (ফ্যাভিকন, ইত্যাদি)" bannerUrl: "ব্যানার ছবির URL" backgroundImageUrl: "পটভূমির চিত্রের URL" basicInfo: "আপনার ব্যক্তিগত তথ্য" @@ -839,6 +838,8 @@ color: "রং" horizontal: "পাশে" youFollowing: "অনুসরণ করা হচ্ছে" icon: "প্রোফাইল ছবি" +replies: "জবাব" +renotes: "রিনোট" _role: priority: "অগ্রাধিকার" _priority: @@ -888,6 +889,7 @@ _plugin: install: "প্লাগইন ইন্সটল করুন" installWarn: "অবিশ্বস্ত প্লাগইন ইনস্টল করবেন না।" manage: "প্লাগইন ম্যানেজ করুন" + viewSource: "উৎস দেখুন" _registry: scope: "স্কোপ" key: "কী" @@ -1331,3 +1333,6 @@ _deck: _webhookSettings: name: "নাম" active: "চালু" +_moderationLogTypes: + suspend: "স্থগিত করা" + resetPassword: "পাসওয়ার্ড রিসেট করুন" diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml index e93b804dc..d1fd73b66 100644 --- a/locales/ca-ES.yml +++ b/locales/ca-ES.yml @@ -381,6 +381,8 @@ user: "Usuaris" global: "Global" searchByGoogle: "Cercar" file: "Fitxers" +replies: "Respondre" +renotes: "Impulsa" _role: _options: antennaMax: "Nombre màxim d'antenes" @@ -477,3 +479,6 @@ _deck: list: "Llistes" mentions: "Mencions" direct: "Publicacions directes" +_moderationLogTypes: + suspend: "Suspèn" + resetPassword: "Restableix la contrasenya" diff --git a/locales/cs-CZ.yml b/locales/cs-CZ.yml index 145421eca..751cc064a 100644 --- a/locales/cs-CZ.yml +++ b/locales/cs-CZ.yml @@ -354,7 +354,6 @@ invite: "Pozvat" driveCapacityPerLocalAccount: "Kapacita disku na lokálního uživatele" driveCapacityPerRemoteAccount: "Kapacita disku na vzdáleného uživatele" inMb: "V megabajtech" -iconUrl: "Favicon URL" bannerUrl: "Baner URL" backgroundImageUrl: "Adresa URL obrázku pozadí" basicInfo: "Základní informace" @@ -1019,7 +1018,6 @@ retryAllQueuesConfirmText: "Tohle dočasně zvýší zatěž na server." enableChartsForRemoteUser: "Vygenerovat grafy dat vzdálených uživatelů" enableChartsForFederatedInstances: "Vygenerovat grafy dat vzdálených instancí" showClipButtonInNoteFooter: "Přidat \"Připnout\" do akčního menu poznámky" -largeNoteReactions: "Zvětšit zobrazované reakce" noteIdOrUrl: "ID nebo URL poznámky" video: "Video" videos: "Videa" @@ -1096,6 +1094,8 @@ doYouAgree: "Souhlasíte?" beSureToReadThisAsItIsImportant: "Přečtěte si prosím tyto důležité informace." iHaveReadXCarefullyAndAgree: "Přečetl jsem si text \"{x}\" a souhlasím s ním." icon: "Avatar" +replies: "Odpovědět" +renotes: "Přeposlat" _initialAccountSetting: accountCreated: "Váš účet byl úspěšně vytvořen!" letsStartAccountSetup: "Pro začátek si nastavte svůj profil." @@ -1113,6 +1113,8 @@ _initialAccountSetting: laterAreYouSure: "Opravdu chcete provést nastavení profilu později?" _serverRules: description: "Soubor pravidel, která se zobrazí před registrací. Doporučuje se nastavit shrnutí podmínek služby." +_serverSettings: + iconUrl: "URL ikony" _accountMigration: moveFrom: "Migrace jiného účtu na tento účet" moveFromSub: "Vytvořit alias na jiný účet" @@ -1490,6 +1492,7 @@ _plugin: install: "Instalovat plugin" installWarn: "Neinstalujte nedůvěryhodné pluginy." manage: "Správce pluginů" + viewSource: "Zobrazit zdroj" _preferencesBackups: list: "Vytvořit backup" saveNew: "Uložit novou zálohu" @@ -1677,7 +1680,6 @@ _timelineTutorial: _2fa: alreadyRegistered: "Již jste zaregistrovali dvoufaktorové ověřovací zařízení." registerTOTP: "Registrovat aplikaci autentizátoru" - passwordToTOTP: "Zadejte své heslo" step1: "Nejprve si do zařízení nainstalujte aplikaci pro ověřování (například {a} nebo {b})." step2: "Poté naskenujte QR kód zobrazený na této obrazovce." step2Click: "Kliknutím na tento QR kód můžete zaregistrovat 2FA do bezpečnostního klíče nebo aplikace autentizace telefonu." @@ -1687,7 +1689,6 @@ _2fa: securityKeyNotSupported: "Váš prohlížeč nepodporuje bezpečnostní klíče." registerTOTPBeforeKey: "Nastavte aplikaci autentizátoru pro registraci bezpečnostního nebo přístupového klíče." securityKeyInfo: "Kromě ověřování otiskem prstu nebo PIN můžete nastavit také ověřování pomocí hardwarových bezpečnostních klíčů, které podporují FIDO2, a svůj účet tak dále zabezpečit." - chromePasskeyNotSupported: "Chrome passkeys nejsou v současné době podporovány." registerSecurityKey: "Registrace bezpečnostního nebo přístupového klíče" securityKeyName: "Zadejte název klíče" tapSecurityKey: "Při registraci bezpečnostního nebo přístupového klíče postupujte podle svého prohlížeče." @@ -2035,3 +2036,6 @@ _webhookSettings: renote: "Při renotaci poznámky" reaction: "Při obdržení reakce" mention: "Při zmínce" +_moderationLogTypes: + suspend: "Zmrazit" + resetPassword: "Resetovat heslo" diff --git a/locales/de-DE.yml b/locales/de-DE.yml index ccc391171..aae5f4504 100644 --- a/locales/de-DE.yml +++ b/locales/de-DE.yml @@ -2,7 +2,7 @@ _lang_: "Deutsch" headlineMisskey: "Ein durch Notizen verbundenes Netzwerk" introMisskey: "Willkommen! Misskey ist eine dezentralisierte Open-Source Microblogging-Platform.\nVerfasse „Notizen“ um mitzuteilen, was gerade passiert oder um Ereignisse mit anderen zu teilen. 📡\nMit „Reaktionen“ kannst du außerdem schnell deine Gefühle über Notizen anderer Benutzer zum Ausdruck bringen. 👍\nEine neue Welt wartet auf dich! 🚀" -poweredByMisskeyDescription: "{name} ist einer der durch die Open-Source-Plattform Misskey betriebenen Dienste (meist als \"Misskey-Instanz\" bezeichnet)." +poweredByMisskeyDescription: "{name} ist einer der durch die Open-Source-Plattform Misskey betriebenen Dienste." monthAndDay: "{day}.{month}." search: "Suchen" notifications: "Benachrichtigungen" @@ -75,7 +75,7 @@ import: "Import" export: "Export" files: "Dateien" download: "Herunterladen" -driveFileDeleteConfirm: "Möchtest du die Datei „{name}“ wirklich löschen? Sie wird in allen Inhalten, die sie verwenden, auch verschwinden." +driveFileDeleteConfirm: "Möchtest du die Datei „{name}“ wirklich löschen? Einige Inhalte, die diese Datei verwenden, werden auch verschwinden." unfollowConfirm: "Möchtest du {name} wirklich nicht mehr folgen?" exportRequested: "Du hast einen Export angefragt. Dies kann etwas Zeit in Anspruch nehmen. Sobald der Export abgeschlossen ist, wird er deiner Drive hinzugefügt." importRequested: "Du hast einen Import angefragt. Dies kann etwas Zeit in Anspruch nehmen." @@ -321,7 +321,7 @@ copyUrl: "URL kopieren" rename: "Umbenennen" avatar: "Profilbild" banner: "Banner" -displayOfSensitiveMedia: "Anzeige von sensiblen Medien" +displayOfSensitiveMedia: "Darstellung sensibler Medien" whenServerDisconnected: "Bei Verbindungsverlust zum Server" disconnectedFromServer: "Die Verbindung zum Server wurde getrennt" reload: "Aktualisieren" @@ -356,7 +356,6 @@ invite: "Einladen" driveCapacityPerLocalAccount: "Drive-Kapazität pro lokalem Benutzerkonto" driveCapacityPerRemoteAccount: "Drive-Kapazität pro Benutzer fremder Instanzen" inMb: "In Megabytes" -iconUrl: "Icon-URL (favicon etc)" bannerUrl: "Banner-URL" backgroundImageUrl: "Hintergrundbild-URL" basicInfo: "Grundlegende Informationen" @@ -417,9 +416,12 @@ totp: "Authentifizierungs-App" totpDescription: "Logge dich via Authentifizierungs-App mit Einmalpasswort ein" moderator: "Moderator" moderation: "Moderation" +moderationNote: "Moderationsnotiz" +addModerationNote: "Moderationsnotiz hinzufügen" +moderationLogs: "Moderationsprotokolle" nUsersMentioned: "Von {n} Benutzern erwähnt" -securityKeyAndPasskey: "Security-Tokens und Passkeys" -securityKey: "Sicherheitsschlüssel" +securityKeyAndPasskey: "Hardware-Sicherheitsschlüssel und Passkeys" +securityKey: "Hardware-Sicherheitsschlüssel" lastUsed: "Zuletzt benutzt" lastUsedAt: "Zuletzt verwendet: {t}" unregister: "Deaktivieren" @@ -634,11 +636,11 @@ regexpErrorDescription: "Im regulären Ausdruck deiner {tab}en Wortstummschaltun instanceMute: "Instanzstummschaltungen" userSaysSomething: "{name} hat etwas gesagt" makeActive: "Aktivieren" -display: "Anzeigen" +display: "Anzeigeart" copy: "Kopieren" metrics: "Metriken" overview: "Übersicht" -logs: "Logs" +logs: "Protokolle" delayed: "Verzögert" database: "Datenbank" channel: "Kanäle" @@ -709,6 +711,7 @@ lockedAccountInfo: "Auch wenn du Follow-Anfragen auf manuelle Bestätigung setzt alwaysMarkSensitive: "Medien standardmäßig als sensibel markieren" loadRawImages: "Anstatt Vorschaubilder immer Originalbilder anzeigen" disableShowingAnimatedImages: "Animierte Bilder nicht abspielen" +highlightSensitiveMedia: "Sensitive Medien markieren" verificationEmailSent: "Eine Bestätigungsmail wurde an deine Email-Adresse versendet. Besuche den dort enthaltenen Link, um die Verifizierung abzuschließen." notSet: "Nicht konfiguriert" emailVerified: "Email-Adresse bestätigt" @@ -912,7 +915,7 @@ typeToConfirm: "Bitte gib zur Bestätigung {x} ein" deleteAccount: "Benutzerkonto löschen" document: "Dokumentation" numberOfPageCache: "Seitencachegröße" -numberOfPageCacheDescription: "Das Erhöhen dieses Caches führt zu einer angenehmerern Benutzererfahrung, erhöht aber Serverlast und Arbeitsspeicherauslastung." +numberOfPageCacheDescription: "Das Erhöhen dieses Caches führt zu einer angenehmerern Benutzererfahrung, aber erhöht Last und Arbeitsspeicherauslastung auf dem Nutzergerät." logoutConfirm: "Wirklich abmelden?" lastActiveDate: "Zuletzt verwendet am" statusbar: "Statusleiste" @@ -1023,7 +1026,7 @@ retryAllQueuesConfirmText: "Dies wird zu einer temporären Erhöhung der Serverl enableChartsForRemoteUser: "Diagramme für Nutzer fremder Instanzen erstellen" enableChartsForFederatedInstances: "Diagramme für fremde Instanzen erstellen" showClipButtonInNoteFooter: "\"Clip\" zum Notizmenu hinzufügen" -largeNoteReactions: "Reaktionen vergrößert anzeigen" +reactionsDisplaySize: "Reaktionsanzeigegröße" noteIdOrUrl: "Notiz-ID oder URL" video: "Video" videos: "Videos" @@ -1047,7 +1050,7 @@ vertical: "Vertikal" horizontal: "Horizontal" position: "Position" serverRules: "Serverregeln" -pleaseConfirmBelowBeforeSignup: "Lies bitte Untenstehendes vor der Registration." +pleaseConfirmBelowBeforeSignup: "Lies bitte diese Informationen und stimme ihnen vor der Registration zu." pleaseAgreeAllToContinue: "Zum Fortfahren muss allen obigen Feldern zugestimmt werden." continue: "Fortfahren" preservedUsernames: "Reservierte Benutzernamen" @@ -1057,7 +1060,7 @@ archive: "Archivieren" channelArchiveConfirmTitle: "{name} wirklich archivieren?" channelArchiveConfirmDescription: "Ein archivierter Kanal taucht nicht mehr in der Kanalliste oder in Suchergebnissen auf. Zudem können ihm keine Beiträge mehr hinzugefügt werden." thisChannelArchived: "Dieser Kanal wurde archiviert." -displayOfNote: "Anzeige von Notizen" +displayOfNote: "Darstellung von Notizen" initialAccountSetting: "Kontoeinrichtung" youFollowing: "Gefolgt" preventAiLearning: "Verwendung in machinellem Lernen (Generative bzw. Prediktive AI/KI) ablehnen" @@ -1105,6 +1108,18 @@ forYou: "Für dich" currentAnnouncements: "Aktuelle Ankündigungen" pastAnnouncements: "Alte Ankündigungen" youHaveUnreadAnnouncements: "Es gibt neue Ankündigungen." +useSecurityKey: "Folge bitten den Anweisungen deines Browsers bzw. Gerätes und verwende deinen Hardware-Sicherheitsschlüssel oder Passkey." +replies: "Antworten" +renotes: "Renotes" +loadReplies: "Antworten anzeigen" +loadConversation: "Unterhaltung anzeigen" +pinnedList: "Angeheftete Liste" +keepScreenOn: "Bildschirm angeschaltet lassen" +verifiedLink: "Link-Besitz wurde verifiziert" +notifyNotes: "Über neue Notizen benachrichtigen" +unnotifyNotes: "Nicht über neue Notizen benachrichtigen" +authentication: "Authentifikation" +authenticationRequiredToContinue: "Bitte authentifiziere dich, um fortzufahren" _announcement: forExistingUsers: "Nur für existierende Nutzer" forExistingUsersDescription: "Ist diese Option aktiviert, wird diese Ankündigung nur Nutzern angezeigt, die zum Zeitpunkt der Ankündigung bereits registriert sind. Ist sie deaktiviert, wird sie auch Nutzern, die sich nach dessen Veröffentlichung registrieren, angezeigt." @@ -1131,6 +1146,15 @@ _initialAccountSetting: laterAreYouSure: "Die Kontoeinrichtung wirklich später erledigen?" _serverRules: description: "Eine Reihe von Regeln, die vor der Registrierung angezeigt werden. Eine Zusammenfassung der Nutzungsbedingungen anzuzeigen ist empfohlen." +_serverSettings: + iconUrl: "Icon-URL" + appIconDescription: "Gibt das zu verwendende Icon bei der Anzeige von {host} als App an." + appIconUsageExample: "Beispielsweise als PWA, oder bei Lesezeichen auf dem Startbildschirm von Smartphones" + appIconStyleRecommendation: "Da das Icon zu einem Kreis oder Quadrat zugeschnitten wird, wird ein Icon mit gefülltem Margin um den Inhalt herum empfohlen." + appIconResolutionMustBe: "Die Mindestauflösung ist {resolution}." + manifestJsonOverride: "Überschreiben von manifest.json" + shortName: "Abkürzung" + shortNameDescription: "Ein Kürzel für den Namen der Instanz, der angezeigt werden kann, falls der volle Instanzname lang ist." _accountMigration: moveFrom: "Von einem anderen Konto zu diesem migrieren" moveFromSub: "Alias für ein anderes Konto erstellen" @@ -1385,6 +1409,9 @@ _achievements: title: "Brain Diver" description: "Sende den Link zu Brain Diver" flavor: "Misskey-Misskey La-Tu-Ma" + _smashTestNotificationButton: + title: "Testüberfluss" + description: "Betätige den Benachrichtigungstest mehrfach innerhalb einer extrem kurzen Zeitspanne" _role: new: "Rolle erstellen" edit: "Rolle bearbeiten" @@ -1508,6 +1535,7 @@ _plugin: install: "Plugins installieren" installWarn: "Installiere bitte nur vertrauenswürdige Plugins." manage: "Plugins verwalten" + viewSource: "Quelltext anzeigen" _preferencesBackups: list: "Erstellte Backups" saveNew: "Neu erstellen" @@ -1695,20 +1723,18 @@ _timelineTutorial: _2fa: alreadyRegistered: "Du hast bereits ein Gerät für Zwei-Faktor-Authentifizierung registriert." registerTOTP: "Authentifizierungs-App registrieren" - passwordToTOTP: "Bitte Passwort eingeben" step1: "Installiere zuerst eine Authentifizierungsapp (z.B. {a} oder {b}) auf deinem Gerät." step2: "Dann, scanne den angezeigten QR-Code mit deinem Gerät." step2Click: "Durch Klicken dieses QR-Codes kannst du Verifikation mit deinem Security-Token oder einer App registrieren." step2Uri: "Nutzt du ein Desktopprogramm, gib folgende URI eingeben" step3Title: "Authentifizierungsscode eingeben" - step3: "Gib zum Abschluss den Token ein, der von deiner App angezeigt wird." + step3: "Gib zum Abschluss den Code (Token) ein, der von deiner App angezeigt wird." setupCompleted: "Einrichtung abgeschlossen" step4: "Alle folgenden Anmeldeversuche werden ab sofort die Eingabe eines solchen Tokens benötigen." - securityKeyNotSupported: "Dein Browser unterstützt keine Security-Tokens." + securityKeyNotSupported: "Dein Browser unterstützt keine Hardware-Sicherheitsschlüssel." registerTOTPBeforeKey: "Um einen Security-Token oder einen Passkey zu registrieren, musst du zuerst eine Authentifizierungs-App registrieren." securityKeyInfo: "Du kannst neben Fingerabdruck- oder PIN-Authentifizierung auf deinem Gerät auch Anmeldung mit Hilfe eines FIDO2-kompatiblen Hardware-Sicherheitsschlüssels einrichten." - chromePasskeyNotSupported: "Chrome-Passkeys werden zur Zeit nicht unterstützt." - registerSecurityKey: "Security-Token oder Passkey registrieren" + registerSecurityKey: "Hardware-Sicherheitsschlüssel oder Passkey registrieren" securityKeyName: "Schlüsselname eingeben" tapSecurityKey: "Bitten folge den Anweisungen deines Browsers zur Registrierung" removeKey: "Sicherheitsschlüssel entfernen" @@ -1775,6 +1801,7 @@ _antennaSources: homeTimeline: "Notizen von Benutzern, denen gefolgt wird" users: "Notizen von einem oder mehreren angegebenen Benutzern" userList: "Notizen von allen Benutzern einer Liste" + userBlacklist: "Alle Notizen abgesehen derer angegebener Benutzer" _weekday: sunday: "Sonntag" monday: "Montag" @@ -1874,6 +1901,7 @@ _profile: metadataContent: "Inhalt" changeAvatar: "Profilbild ändern" changeBanner: "Banner ändern" + verifiedLinkDescription: "Gibst du hier eine URL ein, die einen Link zu deinem Profile enthält, wird neben diesem Feld ein Icon zur Besitzbestätigung angezeigt." _exportOrImport: allNotes: "Alle Notizen" favoritedNotes: "Als Favorit markierte Notizen" @@ -1992,11 +2020,17 @@ _notification: youReceivedFollowRequest: "Du hast eine Follow-Anfrage erhalten" yourFollowRequestAccepted: "Deine Follow-Anfrage wurde akzeptiert" pollEnded: "Umfrageergebnisse sind verfügbar" + newNote: "Neue Notiz" unreadAntennaNote: "Antenne {name}" emptyPushNotificationMessage: "Push-Benachrichtigungen wurden aktualisiert" achievementEarned: "Errungenschaft freigeschaltet" + testNotification: "Testbenachrichtigung" + checkNotificationBehavior: "Aussehen von Benachrichtigungen überprüfen" + sendTestNotification: "Testbenachrichtigung senden" + notificationWillBeDisplayedLikeThis: "Benachrichtigungen sehen so aus" _types: all: "Alle" + note: "Neue Notizen" follow: "Neue Follower" mention: "Erwähnungen" reply: "Antworten" @@ -2066,3 +2100,27 @@ _webhookSettings: renote: "Wenn du ein Renote erhältst" reaction: "Wenn du eine Reaktion erhältst" mention: "Wenn du erwähnt wirst" +_moderationLogTypes: + updateRole: "Rolle aktualisiert" + assignRole: "Zu Rolle zugewiesen" + unassignRole: "Aus Rolle entfernt" + suspend: "Gesperrt" + unsuspend: "Entsperrt" + addCustomEmoji: "Benutzerdefiniertes Emoji hinzugefügt" + updateCustomEmoji: "Benutzerdefiniertes Emoji aktualisiert" + deleteCustomEmoji: "Benutzerdefiniertes Emoji gelöscht" + updateServerSettings: "Servereinstellungen aktualisiert" + updateUserNote: "Moderationsnotiz aktualisiert" + deleteDriveFile: "Datei gelöscht" + deleteNote: "Notiz gelöscht" + createGlobalAnnouncement: "Globale Ankündigung erstellt" + createUserAnnouncement: "Benutzerspezifische Ankündigung erstellt" + updateGlobalAnnouncement: "Globale Ankündigung aktualisiert" + updateUserAnnouncement: "Benutzerspezifische Ankündigung aktualisiert" + deleteGlobalAnnouncement: "Globale Ankündigung gelöscht" + deleteUserAnnouncement: "Benutzerspezifische Ankündigung gelöscht" + resetPassword: "Passwort zurückgesetzt" + suspendRemoteInstance: "Fremde Instanz gesperrt" + unsuspendRemoteInstance: "Fremde Instanz entsperrt" + markSensitiveDriveFile: "Datei als sensitiv markiert" + unmarkSensitiveDriveFile: "Datei als nicht sensitiv markiert" diff --git a/locales/el-GR.yml b/locales/el-GR.yml index 558d466f3..e46efcec1 100644 --- a/locales/el-GR.yml +++ b/locales/el-GR.yml @@ -288,6 +288,8 @@ file: "Αρχεία" recommended: "Προτεινόμενα" cannotUploadBecauseNoFreeSpace: "Το ανέβασμα απέτυχε λόγω ανεπαρκούς Αποθηκευτικού Χώρου" icon: "Εικονίδιο" +replies: "Απάντηση" +renotes: "Κοινοποίηση σημειώματος" _email: _follow: title: "Έχετε ένα νέο ακόλουθο" @@ -395,3 +397,5 @@ _deck: mentions: "Επισημάνσεις" _webhookSettings: name: "Όνομα" +_moderationLogTypes: + suspend: "Αποβολή" diff --git a/locales/en-US.yml b/locales/en-US.yml index 1f4cbe746..920995a95 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -48,7 +48,7 @@ copyLink: "Copy link" copyLinkRenote: "Copy renote link" delete: "Delete" deleteAndEdit: "Delete and edit" -deleteAndEditConfirm: "Are you sure you want to delete this note and edit it? You will lose all reactions, renotes and replies to it." +deleteAndEditConfirm: "Are you sure you want to redraft this note? This means you will lose all reactions, renotes, and replies to it." addToList: "Add to list" addToAntenna: "Add to antenna" sendMessage: "Send a message" @@ -106,7 +106,7 @@ unfollow: "Unfollow" followRequestPending: "Follow request pending" enterEmoji: "Enter an emoji" renote: "Renote" -unrenote: "Take back renote" +unrenote: "Remove renote" renoted: "Renoted." cantRenote: "This post can't be renoted." cantReRenote: "A renote can't be renoted." @@ -356,7 +356,6 @@ invite: "Invite" driveCapacityPerLocalAccount: "Drive capacity per local user" driveCapacityPerRemoteAccount: "Drive capacity per remote user" inMb: "In megabytes" -iconUrl: "Icon URL" bannerUrl: "Banner image URL" backgroundImageUrl: "Background image URL" basicInfo: "Basic info" @@ -417,6 +416,9 @@ totp: "Authenticator App" totpDescription: "Use an authenticator app to enter one-time passwords" moderator: "Moderator" moderation: "Moderation" +moderationNote: "Moderation note" +addModerationNote: "Add moderation note" +moderationLogs: "Moderation logs" nUsersMentioned: "Mentioned by {n} users" securityKeyAndPasskey: "Security- and passkeys" securityKey: "Security key" @@ -582,7 +584,7 @@ serviceworkerInfo: "Must be enabled for push notifications." deletedNote: "Deleted note" invisibleNote: "Invisible note" enableInfiniteScroll: "Automatically load more" -visibility: "Visiblility" +visibility: "Visibility" poll: "Poll" useCw: "Hide content" enablePlayer: "Open video player" @@ -709,6 +711,7 @@ lockedAccountInfo: "Unless you set your note visiblity to \"Followers only\", yo alwaysMarkSensitive: "Mark as sensitive by default" loadRawImages: "Load original images instead of showing thumbnails" disableShowingAnimatedImages: "Don't play animated images" +highlightSensitiveMedia: "Highlight sensitive media" verificationEmailSent: "A verification email has been sent. Please follow the included link to complete verification." notSet: "Not set" emailVerified: "Email has been verified" @@ -912,7 +915,7 @@ typeToConfirm: "Please enter {x} to confirm" deleteAccount: "Delete account" document: "Documentation" numberOfPageCache: "Number of cached pages" -numberOfPageCacheDescription: "Increasing this number will improve convenience for users but cause more server load as well as more memory to be used." +numberOfPageCacheDescription: "Increasing this number will improve convenience for but cause more load as more memory usage on the user's device." logoutConfirm: "Really log out?" lastActiveDate: "Last used at" statusbar: "Status bar" @@ -1023,7 +1026,7 @@ retryAllQueuesConfirmText: "This will temporarily increase the server load." enableChartsForRemoteUser: "Generate remote user data charts" enableChartsForFederatedInstances: "Generate remote instance data charts" showClipButtonInNoteFooter: "Add \"Clip\" to note action menu" -largeNoteReactions: "Enlargen displayed reactions" +reactionsDisplaySize: "Reaction display size" noteIdOrUrl: "Note ID or URL" video: "Video" videos: "Videos" @@ -1105,6 +1108,18 @@ forYou: "For you" currentAnnouncements: "Current announcements" pastAnnouncements: "Past announcements" youHaveUnreadAnnouncements: "There are unread announcements." +useSecurityKey: "Please follow your browser's or device's instructions to use your security- or passkey." +replies: "Reply" +renotes: "Renotes" +loadReplies: "Show replies" +loadConversation: "Show conversation" +pinnedList: "Pinned list" +keepScreenOn: "Keep screen on" +verifiedLink: "Link ownership has been verified" +notifyNotes: "Notify about new notes" +unnotifyNotes: "Stop notifying about new notes" +authentication: "Authentication" +authenticationRequiredToContinue: "Please authenticate to continue" _announcement: forExistingUsers: "Existing users only" forExistingUsersDescription: "This announcement will only be shown to users existing at the point of publishment if enabled. If disabled, those newly signing up after it has been posted will also see it." @@ -1131,6 +1146,15 @@ _initialAccountSetting: laterAreYouSure: "Really do profile setup later?" _serverRules: description: "A set of rules to be displayed before registration. Setting a summary of the Terms of Service is recommended." +_serverSettings: + iconUrl: "Icon URL" + appIconDescription: "Specifies the icon to use when {host} is displayed as an app." + appIconUsageExample: "E.g. As PWA, or when displayed as a home screen bookmark on a phone" + appIconStyleRecommendation: "As the icon may be cropped to a square or circle, an icon with colored margin around the content is recommended." + appIconResolutionMustBe: "The minimum resolution is {resolution}." + manifestJsonOverride: "manifest.json Override" + shortName: "Short name" + shortNameDescription: "A shorthand for the instance's name that can be displayed if the full official name is long." _accountMigration: moveFrom: "Migrate another account to this one" moveFromSub: "Create alias to another account" @@ -1385,6 +1409,9 @@ _achievements: title: "Brain Diver" description: "Post the link to Brain Diver" flavor: "Misskey-Misskey La-Tu-Ma" + _smashTestNotificationButton: + title: "Test overflow" + description: "Trigger the notification test repeatedly within an extremely short time" _role: new: "New role" edit: "Edit role" @@ -1508,6 +1535,7 @@ _plugin: install: "Install plugins" installWarn: "Please do not install untrustworthy plugins." manage: "Manage plugins" + viewSource: "View source" _preferencesBackups: list: "Created backups" saveNew: "Save new backup" @@ -1695,7 +1723,6 @@ _timelineTutorial: _2fa: alreadyRegistered: "You have already registered a 2-factor authentication device." registerTOTP: "Register authenticator app" - passwordToTOTP: "Enter your password" step1: "First, install an authentication app (such as {a} or {b}) on your device." step2: "Then, scan the QR code displayed on this screen." step2Click: "Clicking on this QR code will allow you to register 2FA to your security key or phone authenticator app." @@ -1707,7 +1734,6 @@ _2fa: securityKeyNotSupported: "Your browser does not support security keys." registerTOTPBeforeKey: "Please set up an authenticator app to register a security or pass key." securityKeyInfo: "Besides fingerprint or PIN authentication, you can also setup authentication via hardware security keys that support FIDO2 to further secure your account." - chromePasskeyNotSupported: "Chrome passkeys are currently not supported." registerSecurityKey: "Register a security or pass key" securityKeyName: "Enter a key name" tapSecurityKey: "Please follow your browser to register the security or pass key" @@ -1775,6 +1801,7 @@ _antennaSources: homeTimeline: "Notes from followed users" users: "Notes from specific users" userList: "Notes from a specified list of users" + userBlacklist: "All notes except for those of one or more specified users" _weekday: sunday: "Sunday" monday: "Monday" @@ -1874,6 +1901,7 @@ _profile: metadataContent: "Content" changeAvatar: "Change avatar" changeBanner: "Change banner" + verifiedLinkDescription: "By entering an URL that contains a link to your profile here, an ownership verification icon can be displayed next to the field." _exportOrImport: allNotes: "All notes" favoritedNotes: "Favorite notes" @@ -1992,11 +2020,17 @@ _notification: youReceivedFollowRequest: "You've received a follow request" yourFollowRequestAccepted: "Your follow request was accepted" pollEnded: "Poll results have become available" + newNote: "New note" unreadAntennaNote: "Antenna {name}" emptyPushNotificationMessage: "Push notifications have been updated" achievementEarned: "Achievement unlocked" + testNotification: "Test notification" + checkNotificationBehavior: "Check notification appearance" + sendTestNotification: "Send test notification" + notificationWillBeDisplayedLikeThis: "Notifications look like this" _types: all: "All" + note: "New notes" follow: "New followers" mention: "Mentions" reply: "Replies" @@ -2066,3 +2100,27 @@ _webhookSettings: renote: "When renoted" reaction: "When receiving a reaction" mention: "When being mentioned" +_moderationLogTypes: + updateRole: "Role updated" + assignRole: "Assigned to role" + unassignRole: "Removed from role" + suspend: "Suspended" + unsuspend: "Unsuspended" + addCustomEmoji: "Custom emoji added" + updateCustomEmoji: "Custom emoji updated" + deleteCustomEmoji: "Custom emoji deleted" + updateServerSettings: "Server settings updated" + updateUserNote: "Moderation note updated" + deleteDriveFile: "File deleted" + deleteNote: "Note deleted" + createGlobalAnnouncement: "Global announcement created" + createUserAnnouncement: "User announcement created" + updateGlobalAnnouncement: "Global announcement updated" + updateUserAnnouncement: "User announcement updated" + deleteGlobalAnnouncement: "Global announcement deleted" + deleteUserAnnouncement: "User announcement deleted" + resetPassword: "Password reset" + suspendRemoteInstance: "Remote instance suspended" + unsuspendRemoteInstance: "Remote instance unsuspended" + markSensitiveDriveFile: "File marked as sensitive" + unmarkSensitiveDriveFile: "File unmarked as sensitive" diff --git a/locales/es-ES.yml b/locales/es-ES.yml index 858035421..1f84a0afb 100644 --- a/locales/es-ES.yml +++ b/locales/es-ES.yml @@ -20,7 +20,7 @@ noNotes: "No hay notas" noNotifications: "No hay notificaciones" instance: "Instancia" settings: "Configuración" -notificationSettings: "Configurar las notificaciones" +notificationSettings: "Ajustes de notificaciones" basicSettings: "Configuración básica" otherSettings: "Configuración avanzada" openInWindow: "Abrir en una ventana" @@ -56,8 +56,8 @@ copyRSS: "Copiar RSS" copyUsername: "Copiar nombre de usuario" copyUserId: "Copiar ID del usuario" copyNoteId: "Copiar ID de la nota" -copyFileId: "Copiar un archivo ID" -copyFolderId: "Copiar carpeta ID" +copyFileId: "Copiar ID del archivo" +copyFolderId: "Copiar ID de carpeta" copyProfileUrl: "Copiar la URL del perfil" searchUser: "Buscar un usuario" reply: "Responder" @@ -356,7 +356,6 @@ invite: "Invitar" driveCapacityPerLocalAccount: "Capacidad del drive por usuario local" driveCapacityPerRemoteAccount: "Capacidad del drive por usuario remoto" inMb: "En megabytes" -iconUrl: "URL de la imagen del avatar" bannerUrl: "URL de la imagen del banner" backgroundImageUrl: "URL de la imagen de fondo" basicInfo: "Información básica" @@ -417,6 +416,8 @@ totp: "Aplicación autentícadora" totpDescription: "Ingresa una contaseña de un sólo uso usando la aplicación autenticadora" moderator: "Moderador" moderation: "Moderación" +moderationNote: "Nota de moderación" +addModerationNote: "Añadir nota de moderación" nUsersMentioned: "{n} usuarios mencionados" securityKeyAndPasskey: "Clave de seguridad / clave de paso" securityKey: "Clave de seguridad" @@ -1023,7 +1024,7 @@ retryAllQueuesConfirmText: "La carga del servidor está incrementándose tempora enableChartsForRemoteUser: "Generar gráficas de usuarios remotos." enableChartsForFederatedInstances: "Generar gráficos de servidores remotos" showClipButtonInNoteFooter: "Añadir \"Clip\" al menú de notas" -largeNoteReactions: "Agrandar las reacciones de las notas" +reactionsDisplaySize: "Tamaño de las reacciones" noteIdOrUrl: "ID o URL de la nota" video: "Video" videos: "Video" @@ -1105,6 +1106,9 @@ forYou: "Para ti" currentAnnouncements: "Anuncios actuales" pastAnnouncements: "Anuncios anteriores" youHaveUnreadAnnouncements: "Hay anuncios sin leer" +useSecurityKey: "Por favor, sigue las instrucciones de tu dispositivo o navegador para usar tu clave de seguridad o tu clave de paso." +replies: "Responder" +renotes: "Renotar" _announcement: forExistingUsers: "Solo para usuarios registrados" forExistingUsersDescription: "Este anuncio solo se mostrará a aquellos usuarios registrados en el momento de su publicación. Si se deshabilita esta opción, aquellos usuarios que se registren tras su publicación también lo verán." @@ -1131,6 +1135,9 @@ _initialAccountSetting: laterAreYouSure: "¿Realmente quieres configurar tu perfil después?" _serverRules: description: "Un conjunto de reglas que serán mostradas antes del registro. Configurar un sumario de términos de servicio es recomendado." +_serverSettings: + iconUrl: "URL del ícono" + manifestJsonOverride: "Sobreescribir manifest.json" _accountMigration: moveFrom: "Trasladar de otra cuenta a ésta" moveFromSub: "Crear un alias para otra cuenta." @@ -1385,6 +1392,9 @@ _achievements: title: "Brain Diver" description: "Publicaste un vínculo a \"Brain Diver\"" flavor: "Misskey-Misskey La-Tu-Ma" + _smashTestNotificationButton: + title: "Sobrecarga de pruebas" + description: "Envía muchas notificaciones de prueba en un corto espacio de tiempo" _role: new: "Crear rol" edit: "Editar rol" @@ -1508,6 +1518,7 @@ _plugin: install: "Instalar plugins" installWarn: "Por favor no instale plugins que no son de confianza" manage: "Gestionar plugins" + viewSource: "Ver la fuente" _preferencesBackups: list: "Respaldos creados" saveNew: "Guardar nuevo respaldo" @@ -1695,7 +1706,6 @@ _timelineTutorial: _2fa: alreadyRegistered: "Ya has completado la configuración." registerTOTP: "Registrar aplicación autenticadora" - passwordToTOTP: "Ingresa tu contraseña" step1: "Primero, instale en su dispositivo la aplicación de autenticación {a} o {b} u otra." step2: "Luego, escanee con la aplicación el código QR mostrado en pantalla." step2Click: "Clicking on this QR code will allow you to register 2FA to your security key or phone authenticator app.\nTocar este código QR te permitirá registrar la autenticación 2FA a tu llave de seguridad o aplicación autenticadora." @@ -1707,7 +1717,6 @@ _2fa: securityKeyNotSupported: "Tu navegador no soporta claves de autenticación." registerTOTPBeforeKey: "Please set up an authenticator app to register a security or pass key.\npor favor. configura una aplicación de autenticación para registrar una llave de seguridad." securityKeyInfo: "Se puede configurar el inicio de sesión usando una clave de seguridad de hardware que soporte FIDO2 o con un certificado de huella digital o con un PIN" - chromePasskeyNotSupported: "Las llaves de seguridad de Chrome no son soportadas por el momento." registerSecurityKey: "Registrar una llave de seguridad" securityKeyName: "Ingresa un nombre para la clave" tapSecurityKey: "Por favor, sigue tu navegador para registrar una llave de seguridad" @@ -1995,6 +2004,10 @@ _notification: unreadAntennaNote: "Antena {name}" emptyPushNotificationMessage: "Se han actualizado las notificaciones push" achievementEarned: "Logro desbloqueado" + testNotification: "Notificación de prueba" + checkNotificationBehavior: "Comprobar comportamiento de la notificación" + sendTestNotification: "Enviar notificación de prueba" + notificationWillBeDisplayedLikeThis: "Las notificaciones tendrán este aspecto" _types: all: "Todo" follow: "Siguiendo" @@ -2066,3 +2079,6 @@ _webhookSettings: renote: "Cuando reciba un \"re-note\"" reaction: "Cuando se recibe una reacción" mention: "Cuando hay una mención" +_moderationLogTypes: + suspend: "Suspender" + resetPassword: "Resetear contraseña" diff --git a/locales/fr-FR.yml b/locales/fr-FR.yml index 32ab9f201..db19b6688 100644 --- a/locales/fr-FR.yml +++ b/locales/fr-FR.yml @@ -47,7 +47,7 @@ copyContent: "Copier le contenu" copyLink: "Copier le lien" delete: "Supprimer" deleteAndEdit: "Supprimer et réécrire" -deleteAndEditConfirm: "Êtes-vous sûr·e de vouloir supprimer cette note et la reformuler ? Vous perdrez toutes les réactions, renotes et réponses y afférentes." +deleteAndEditConfirm: "Êtes-vous sûr de vouloir effacer cette note et la modifier ? Vous perdrez toutes les réactions, renotes et réponses." addToList: "Ajouter à une liste" addToAntenna: "Ajouter à l’antenne" sendMessage: "Envoyer un message" @@ -272,6 +272,7 @@ startMessaging: "Commencer à discuter" nUsersRead: "Lu par {n} personnes" agreeTo: "J’accepte {0}" agree: "Accepter" +agreeBelow: "J’accepte ce qui suit" basicNotesBeforeCreateAccount: "Notes importantes" termsOfService: "Conditions d'utilisation" start: "Commencer" @@ -351,7 +352,6 @@ invite: "Inviter" driveCapacityPerLocalAccount: "Volume du Drive par utilisateur local" driveCapacityPerRemoteAccount: "Volume du Drive par utilisateur distant" inMb: "en mégaoctets" -iconUrl: "URL de l'icône" bannerUrl: "URL de l’image de la bannière" backgroundImageUrl: "URL de l'image d'arrière-plan" basicInfo: "Informations basiques" @@ -407,11 +407,15 @@ aboutMisskey: "À propos de Misskey" administrator: "Administrateur" token: "Jeton" 2fa: "Authentification à deux facteurs" +setupOf2fa: "Configuration de l’authentification à deux facteurs" totp: "Application d'authentification" totpDescription: "Entrez un mot de passe à usage unique à l'aide d'une application d'authentification" moderator: "Modérateur·rice·s" moderation: "Modérations" +moderationNote: "Note de modération" +addModerationNote: "Ajouter une note de modération" nUsersMentioned: "{n} utilisateur·rice·s mentionné·e·s" +securityKeyAndPasskey: "Sécurité et clés de sécurité" securityKey: "Clé de sécurité" lastUsed: "Dernier utilisé" lastUsedAt: "Dernière utilisation : {t}" @@ -479,6 +483,7 @@ createAccount: "Créer un compte" existingAccount: "Compte existant" regenerate: "Générer à nouveau" fontSize: "Taille de la police" +limitTo: "Limiter à {x}" noFollowRequests: "Vous n’avez aucune demande d’abonnement en attente" openImageInNewTab: "Ouvrir les images dans un nouvel onglet" dashboard: "Tableau de bord" @@ -795,6 +800,7 @@ popularPosts: "Les plus consultées" shareWithNote: "Partager dans une note" ads: "Publicité" expiration: "Échéance" +startingperiod: "Commencer" memo: "Pense-bête" priority: "Priorité" high: "Haute" @@ -821,6 +827,7 @@ translatedFrom: "Traduit depuis {x}" accountDeletionInProgress: "La suppression de votre compte est en cours" usernameInfo: "C'est un nom qui identifie votre compte sur l'instance de manière unique. Vous pouvez utiliser des lettres de l'alphabet (minuscules et majuscules), des chiffres (de 0 à 9), ou bien le tiret « _ ». Vous ne pourrez pas modifier votre nom d'utilisateur·rice par la suite." aiChanMode: "Mode Ai" +devMode: "Mode développement" keepCw: "Garder le CW" pubSub: "Comptes Pub/Sub" lastCommunication: "Dernière communication" @@ -940,6 +947,7 @@ roles: "Rôles" role: "Rôles" noRole: "Aucun rôle" normalUser: "Simple utilisateur·rice" +undefined: "Non défini" assign: "Attribuer" color: "Couleur" manageCustomEmojis: "Gestion des émojis personnalisés" @@ -947,17 +955,24 @@ preset: "Préréglage" selectFromPresets: "Sélectionner à partir des préréglages" achievements: "Accomplissements" thisPostMayBeAnnoying: "Cette note peut gêner d'autres personnes." +thisPostMayBeAnnoyingHome: "Publier vers le fil principal" thisPostMayBeAnnoyingCancel: "Annuler" thisPostMayBeAnnoyingIgnore: "Publier quand-même" internalServerError: "Erreur interne du serveur" +copyErrorInfo: "Copier les détails de l’erreur" +exploreOtherServers: "Trouver une autre instance" disableFederationOk: "Désactiver" +likeOnly: "Les favoris uniquement" license: "Licence" video: "Vidéo" videos: "Vidéos" dataSaver: "Économiseur de données" accountMigration: "Migration de compte" accountMoved: "Cet·te utilisateur·rice a migré son compte vers :" +accountMovedShort: "Ce compte a migré" +operationForbidden: "Opération non autorisée" addMemo: "Ajouter un mémo" +reactionsList: "Réactions" notificationDisplay: "Style des notifications" leftTop: "En haut à gauche" rightTop: "En haut à droite" @@ -966,7 +981,9 @@ rightBottom: "En bas à droite" vertical: "Vertical" horizontal: "Latéral" serverRules: "Règles du serveur" +archive: "Archive" youFollowing: "Abonné·e" +options: "Options" later: "Plus tard" goToMisskey: "Retour vers Misskey" expirationDate: "Date d’expiration" @@ -977,12 +994,26 @@ expired: "Expiré" doYouAgree: "Êtes-vous d’accord ?" icon: "Avatar" forYou: "Pour vous" +replies: "Répondre" +renotes: "Renoter" +loadReplies: "Inclure les réponses" +pinnedList: "Liste épinglée" +notifyNotes: "Notifier à propos des nouvelles notes" +authentication: "Authentification" +authenticationRequiredToContinue: "Veuillez vous authentifier pour continuer" _announcement: readConfirmTitle: "Marquer comme lu ?" _initialAccountSetting: profileSetting: "Paramètres du profil" privacySetting: "Paramètres de confidentialité" + initialAccountSettingCompleted: "Configuration du profil terminée avec succès !" + ifYouNeedLearnMore: "Si vous voulez en savoir plus comment utiliser {name}(Misskey), veuillez visiter {link}." + skipAreYouSure: "Désirez-vous ignorer la configuration du profile ?" +_serverSettings: + iconUrl: "URL de l’icône" _accountMigration: + moveFrom: "Migrer un autre compte vers le présent compte" + moveFromSub: "Créer un alias vers un autre compte" moveToLabel: "Compte vers lequel vous migrez :" startMigration: "Migrer" movedTo: "Compte vers lequel vous migrez :" @@ -1039,20 +1070,33 @@ _achievements: _login1000: flavor: "Merci d'utiliser Misskey !" _profileFilled: + title: "Bien préparé" description: "Configuration de votre profil" _markedAsCat: title: "Je suis un chat" + description: "Rendre votre compte comme un chat" flavor: "Je n'ai pas encore de nom" + _following1: + title: "Vous suivez votre premier utilisateur·rice" _following50: title: "Beaucoup d'amis" _followers10: title: "Abonnez-moi !" + _followers100: + title: "Populaire" + _followers500: + title: "Tour radio" + _followers1000: + title: "Influenceur·euse" _iLoveMisskey: title: "J’adore Misskey" description: "Publication « J’❤ #Misskey »" + flavor: "L'équipe de développement de Misskey apprécie vraiment votre aide !" _foundTreasure: title: "Chasse au trésor" description: "Vous avez trouvé le trésor caché" + _client30min: + title: "Pause bien méritée" _postedAtLateNight: flavor: "C’est l’heure d’aller au lit." _postedAt0min0sec: @@ -1061,18 +1105,45 @@ _achievements: flavor: "Tic tac, tic tac, tic tac, ding !" _viewInstanceChart: title: "Analyste" + _outputHelloWorldOnScratchpad: + title: "Bonjour tout le monde !" + _open3windows: + title: "Multi-fenêtres" + _driveFolderCircularReference: + title: "Référence circulaire" + _setNameToSyuilo: + description: "Vous avez spécifié « syuilo » comme nom" + _passedSinceAccountCreated1: + title: "Premier anniversaire" + _passedSinceAccountCreated2: + title: "Second anniversaire" + _passedSinceAccountCreated3: + title: "3ème anniversaire" _loggedInOnBirthday: title: "Joyeux Anniversaire !" + description: "Vous vous êtes connecté à la date de votre anniversaire" _loggedInOnNewYearsDay: title: "Bonne année !" _cookieClicked: flavor: "Attendez une minute, vous êtes sur le mauvais site web ?" + _brainDiver: + flavor: "Misskey-Misskey La-Tu-Ma" _role: + new: "Nouveau rôle" + edit: "Modifier le rôle" name: "Nom du rôle" description: "Description du rôle" permission: "Rôle et autorisations" assignTarget: "Attribuer" condition: "Condition" + isPublic: "Rôle public" + options: "Options" + policies: "Stratégies" + baseRole: "Modèle de rôle" + useBaseValue: "Utiliser la valeur du modèle de rôle" + chooseRoleToAssign: "Sélectionner le rôle à assigner" + iconUrl: "URL de l’icône" + displayOrder: "Classement" priority: "Priorité" _priority: low: "Basse" @@ -1131,6 +1202,7 @@ _plugin: install: "Installation de plugin" installWarn: "N’installez que des extensions provenant de sources de confiance." manage: "Gestion des plugins" + viewSource: "Afficher la source" _preferencesBackups: list: "Sauvegardes créées" saveNew: "Nouvelle sauvegarde" @@ -1317,6 +1389,7 @@ _2fa: securityKeyNotSupported: "Votre navigateur ne prend pas en charge les clés de sécurité." securityKeyInfo: "Vous pouvez configurer l'authentification WebAuthN pour sécuriser davantage le processus de connexion grâce à une clé de sécurité matérielle qui prend en charge FIDO2, ou bien en configurant l'authentification par empreinte digitale ou par code PIN sur votre appareil." securityKeyName: "Nom de la clé" + removeKey: "Supprimer la clé de sécurité" removeKeyConfirm: "Voulez-vous supprimer {name} ?" renewTOTPOk: "Reconfigurer" renewTOTPCancel: "Pas maintenant" @@ -1618,3 +1691,6 @@ _deck: _webhookSettings: name: "Nom" active: "Activé" +_moderationLogTypes: + suspend: "Suspendre" + resetPassword: "Réinitialiser le mot de passe" diff --git a/locales/hu-HU.yml b/locales/hu-HU.yml index fdab9645c..023a91494 100644 --- a/locales/hu-HU.yml +++ b/locales/hu-HU.yml @@ -77,6 +77,7 @@ smtpUser: "Felhasználónév" smtpPass: "Jelszó" user: "Felhasználók" searchByGoogle: "Keresés" +renotes: "Renote" _theme: keys: renote: "Renote" diff --git a/locales/id-ID.yml b/locales/id-ID.yml index ee6b7b7ba..56e7f9e4d 100644 --- a/locales/id-ID.yml +++ b/locales/id-ID.yml @@ -354,7 +354,6 @@ invite: "Undang" driveCapacityPerLocalAccount: "Kapasitas drive per pengguna lokal" driveCapacityPerRemoteAccount: "Kapasitas drive per pengguna remote" inMb: "dalam Megabytes" -iconUrl: "URL Gambar ikon" bannerUrl: "URL Banner" backgroundImageUrl: "URL Gambar latar" basicInfo: "Informasi Umum" @@ -1019,7 +1018,6 @@ retryAllQueuesConfirmText: "Hal ini akan meningkatkan beban sementara ke peladen enableChartsForRemoteUser: "Buat bagan data pengguna instansi luar" enableChartsForFederatedInstances: "Buat bagan data peladen instansi luar" showClipButtonInNoteFooter: "Tambahkan \"Klip\" ke menu aksi catatan" -largeNoteReactions: "Besarkan reaksi yang ditampilkan" noteIdOrUrl: "ID catatan atau URL" video: "Video" videos: "Video" @@ -1100,6 +1098,8 @@ icon: "Avatar" forYou: "Untuk Anda" currentAnnouncements: "Pengumuman Saat Ini" pastAnnouncements: "Pengumuman Terdahulu" +replies: "Balas" +renotes: "Renote" _initialAccountSetting: accountCreated: "Akun kamu telah sukses dibuat!" letsStartAccountSetup: "Untuk pemula, ayo atur profilmu dulu." @@ -1117,6 +1117,8 @@ _initialAccountSetting: laterAreYouSure: "Yakin banget untuk atur profil nanti?" _serverRules: description: "Daftar peraturan akan ditampilkan sebelum pendaftaran. Mengatur ringkasan dari Syarat dan Ketentuan sangat direkomendasikan." +_serverSettings: + iconUrl: "URL ikon" _accountMigration: moveFrom: "Pindahkan akun lain ke akun ini" moveFromSub: "Buat alias ke akun lain" @@ -1494,6 +1496,7 @@ _plugin: install: "Memasang plugin" installWarn: "Mohon jangan memasang plugin yang tidak dapat dipercayai." manage: "Manajemen plugin" + viewSource: "Lihat sumber" _preferencesBackups: list: "Cadangan yang dibuat" saveNew: "Simpan cadangan baru" @@ -1681,7 +1684,6 @@ _timelineTutorial: _2fa: alreadyRegistered: "Kamu telah mendaftarkan perangkat otentikasi dua faktor." registerTOTP: "Daftarkan aplikasi autentikator" - passwordToTOTP: "Masukkan kata sandimu" step1: "Pertama, pasang aplikasi otentikasi (seperti {a} atau {b}) di perangkat kamu." step2: "Lalu, pindai kode QR yang ada di layar." step2Click: "Mengeklik kode QR ini akan membolehkanmu untuk mendaftarkan 2FA ke security-key atau aplikasi autentikator ponsel." @@ -1691,7 +1693,6 @@ _2fa: securityKeyNotSupported: "Peramban kamu tidak mendukung security key." registerTOTPBeforeKey: "Mohon atur aplikasi autentikator untuk mendaftarkan security key atau passkey." securityKeyInfo: "Kamu dapat memasang otentikasi WebAuthN untuk mengamankan proses login lebih lanjut dengan tidak hanya perangkat keras kunci keamanan yang mendukung FIDO2, namun juga sidik jari atau otentikasi PIN pada perangkatmu." - chromePasskeyNotSupported: "Passkey Chrome saat ini tidak didukung." registerSecurityKey: "Daftarkan security key atau passkey." securityKeyName: "Masukkan nama key." tapSecurityKey: "Mohon ikuti peramban kamu untuk mendaftarkan security key atau passkey" @@ -2040,3 +2041,6 @@ _webhookSettings: renote: "Ketika direnote" reaction: "Ketika menerima reaksi" mention: "Ketika sedang disebut" +_moderationLogTypes: + suspend: "Tangguhkan" + resetPassword: "Atur ulang kata sandi" diff --git a/locales/index.d.ts b/locales/index.d.ts index 36897285c..4d8123eb5 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -359,7 +359,6 @@ export interface Locale { "driveCapacityPerLocalAccount": string; "driveCapacityPerRemoteAccount": string; "inMb": string; - "iconUrl": string; "bannerUrl": string; "backgroundImageUrl": string; "basicInfo": string; @@ -420,6 +419,9 @@ export interface Locale { "totpDescription": string; "moderator": string; "moderation": string; + "moderationNote": string; + "addModerationNote": string; + "moderationLogs": string; "nUsersMentioned": string; "securityKeyAndPasskey": string; "securityKey": string; @@ -712,6 +714,7 @@ export interface Locale { "alwaysMarkSensitive": string; "loadRawImages": string; "disableShowingAnimatedImages": string; + "highlightSensitiveMedia": string; "verificationEmailSent": string; "notSet": string; "emailVerified": string; @@ -1109,6 +1112,18 @@ export interface Locale { "pastAnnouncements": string; "youHaveUnreadAnnouncements": string; "useSecurityKey": string; + "replies": string; + "renotes": string; + "loadReplies": string; + "loadConversation": string; + "pinnedList": string; + "keepScreenOn": string; + "verifiedLink": string; + "notifyNotes": string; + "unnotifyNotes": string; + "authentication": string; + "authenticationRequiredToContinue": string; + "dateAndTime": string; "_announcement": { "forExistingUsers": string; "forExistingUsersDescription": string; @@ -1138,6 +1153,16 @@ export interface Locale { "_serverRules": { "description": string; }; + "_serverSettings": { + "iconUrl": string; + "appIconDescription": string; + "appIconUsageExample": string; + "appIconStyleRecommendation": string; + "appIconResolutionMustBe": string; + "manifestJsonOverride": string; + "shortName": string; + "shortNameDescription": string; + }; "_accountMigration": { "moveFrom": string; "moveFromSub": string; @@ -1467,6 +1492,10 @@ export interface Locale { "description": string; "flavor": string; }; + "_smashTestNotificationButton": { + "title": string; + "description": string; + }; }; }; "_role": { @@ -1607,6 +1636,7 @@ export interface Locale { "install": string; "installWarn": string; "manage": string; + "viewSource": string; }; "_preferencesBackups": { "list": string; @@ -1811,7 +1841,6 @@ export interface Locale { "_2fa": { "alreadyRegistered": string; "registerTOTP": string; - "passwordToTOTP": string; "step1": string; "step2": string; "step2Click": string; @@ -1893,6 +1922,7 @@ export interface Locale { "homeTimeline": string; "users": string; "userList": string; + "userBlacklist": string; }; "_weekday": { "sunday": string; @@ -2001,6 +2031,7 @@ export interface Locale { "metadataContent": string; "changeAvatar": string; "changeBanner": string; + "verifiedLinkDescription": string; }; "_exportOrImport": { "allNotes": string; @@ -2129,6 +2160,7 @@ export interface Locale { "youReceivedFollowRequest": string; "yourFollowRequestAccepted": string; "pollEnded": string; + "newNote": string; "unreadAntennaNote": string; "emptyPushNotificationMessage": string; "achievementEarned": string; @@ -2138,6 +2170,7 @@ export interface Locale { "notificationWillBeDisplayedLikeThis": string; "_types": { "all": string; + "note": string; "follow": string; "mention": string; "reply": string; @@ -2217,6 +2250,34 @@ export interface Locale { "mention": string; }; }; + "_moderationLogTypes": { + "createRole": string; + "deleteRole": string; + "updateRole": string; + "assignRole": string; + "unassignRole": string; + "suspend": string; + "unsuspend": string; + "addCustomEmoji": string; + "updateCustomEmoji": string; + "deleteCustomEmoji": string; + "updateServerSettings": string; + "updateUserNote": string; + "deleteDriveFile": string; + "deleteNote": string; + "createGlobalAnnouncement": string; + "createUserAnnouncement": string; + "updateGlobalAnnouncement": string; + "updateUserAnnouncement": string; + "deleteGlobalAnnouncement": string; + "deleteUserAnnouncement": string; + "resetPassword": string; + "suspendRemoteInstance": string; + "unsuspendRemoteInstance": string; + "markSensitiveDriveFile": string; + "unmarkSensitiveDriveFile": string; + "resolveAbuseReport": string; + }; } declare const locales: { [lang: string]: Locale; diff --git a/locales/it-IT.yml b/locales/it-IT.yml index e109a9aaa..e99a41b75 100644 --- a/locales/it-IT.yml +++ b/locales/it-IT.yml @@ -106,7 +106,7 @@ unfollow: "Non seguire" followRequestPending: "Richiesta in approvazione" enterEmoji: "Inserisci emoji" renote: "Rinota" -unrenote: "Annulla rinota" +unrenote: "Elimina la Rinota" renoted: "Rinotato!" cantRenote: "È impossibile rinotare questa nota." cantReRenote: "È impossibile rinotare una Rinota." @@ -117,7 +117,7 @@ pinnedNote: "Nota fissata" pinned: "Fissa sul profilo" you: "Tu" clickToShow: "Clicca per visualizzare" -sensitive: "Contenuto sensibile" +sensitive: "Esplicito" add: "Aggiungi" reaction: "Reazioni" reactions: "Reazioni" @@ -125,8 +125,8 @@ reactionSetting: "Reazioni visualizzate sul pannello" reactionSettingDescription2: "Trascina per riorganizzare, clicca per cancellare, usa il pulsante \"+\" per aggiungere." rememberNoteVisibility: "Ricordare le impostazioni di visibilità delle note" attachCancel: "Rimuovi allegato" -markAsSensitive: "Segna come sensibile" -unmarkAsSensitive: "Segna come non sensibile" +markAsSensitive: "Segna come esplicito" +unmarkAsSensitive: "Non segnare come esplicito " enterFileName: "Nome del file" mute: "Silenzia" unmute: "Riattiva l'audio" @@ -134,7 +134,7 @@ renoteMute: "Silenzia i Rinota" renoteUnmute: "Non silenziare i Rinota" block: "Blocca" unblock: "Sblocca" -suspend: "Sospendi" +suspend: "Sospensione" unsuspend: "Revoca la sospensione" blockConfirm: "Vuoi davvero bloccare il profilo?" unblockConfirm: "Vuoi davvero sbloccare il profilo?" @@ -148,7 +148,7 @@ editAntenna: "Modifica Antenna" selectWidget: "Seleziona il riquadro" editWidgets: "Modifica i riquadri" editWidgetsExit: "Conferma le modifiche" -customEmojis: "Emoji personalizzati" +customEmojis: "Emoji personalizzate" emoji: "Emoji" emojis: "Emoji" emojiName: "Nome dell'emoji" @@ -158,8 +158,8 @@ settingGuide: "Configurazione suggerita" cacheRemoteFiles: "Memorizza i file remoti nella cache" cacheRemoteFilesDescription: "Disabilitando questa opzione, i file remoti verranno linkati direttamente senza essere memorizzati nella cache. Sarà possibile risparmiare spazio di archiviazione sul server, ma il traffico aumenterà in quanto non verranno generate anteprime." youCanCleanRemoteFilesCache: "Puoi svuotare tutta la cache cliccando il bottone 🗑️ nella gestione file" -cacheRemoteSensitiveFiles: "Memorizza nella cache i file sensibili remoti" -cacheRemoteSensitiveFilesDescription: "Disattivando questa opzione, i file sensibili verranno caricati direttamente dall'istanza remota senza essere salvati dal server." +cacheRemoteSensitiveFiles: "Copia nella cache locale i file espliciti remoti" +cacheRemoteSensitiveFilesDescription: "Disattivando questa opzione, i file espliciti verranno richiesti direttamente all'istanza remota senza essere salvati nel server locale." flagAsBot: "Io sono un robot" flagAsBotDescription: "Attiva questo campo se il profilo esegue principalmente operazioni automatiche. L'attivazione segnala agli altri sviluppatori come comportarsi per evitare catene d’interazione infinite con altri bot. I sistemi interni di Misskey si adegueranno al fine di trattare questo profilo come bot." flagAsCat: "Sono un gatto" @@ -180,7 +180,7 @@ youHaveNoLists: "Non hai ancora creato nessuna lista" followConfirm: "Vuoi seguire {name}?" proxyAccount: "Profilo proxy" proxyAccountDescription: "Un profilo proxy funziona come follower per i profili remoti, sotto certe condizioni. Ad esempio, quando un profilo locale ne inserisce uno remoto in una lista (senza seguirlo), se nessun altro segue quel profilo remoto, le attività non possono essere distribuite. Dunque, il profilo proxy le seguirà per tutti." -host: "Server remoto" +host: "Host" selectUser: "Seleziona profilo" recipient: "Destinatario" annotation: "Annotazione preventiva" @@ -287,7 +287,7 @@ images: "Immagini" image: "Immagini" birthday: "Compleanno" yearsOld: "{age} anni" -registeredDate: "Iscrizione a.." +registeredDate: "Data iscrizione" location: "Posizione" theme: "Tema" themeForLightMode: "Tema da utilizzare per il modo chiaro" @@ -321,7 +321,7 @@ copyUrl: "Copia URL" rename: "Modifica nome" avatar: "Foto del profilo" banner: "Intestazione" -displayOfSensitiveMedia: "Visibilità dei media sensibili" +displayOfSensitiveMedia: "Visibilità dei media espliciti" whenServerDisconnected: "Quando la connessione col server è persa" disconnectedFromServer: "Il server si è disconnesso" reload: "Ricarica" @@ -356,7 +356,6 @@ invite: "Invita" driveCapacityPerLocalAccount: "Capienza del Drive per profilo locale" driveCapacityPerRemoteAccount: "Capienza del Drive per profilo remoto" inMb: "in Megabytes" -iconUrl: "URL di icona (favicon, ecc.)" bannerUrl: "URL dell'immagine d'intestazione" backgroundImageUrl: "URL dello sfondo" basicInfo: "Informazioni fondamentali" @@ -417,6 +416,9 @@ totp: "App di autenticazione" totpDescription: "Inserisci un codice OTP tramite un'app di autenticazione" moderator: "Moderatore" moderation: "moderazione" +moderationNote: "Promemoria di moderazione" +addModerationNote: "Aggiungi promemoria di moderazione" +moderationLogs: "Cronologia di moderazione" nUsersMentioned: "{n} profili menzionati" securityKeyAndPasskey: "Chiave di sicurezza e accesso" securityKey: "Chiave di sicurezza" @@ -495,7 +497,7 @@ noFollowRequests: "Non hai alcuna richiesta di follow" openImageInNewTab: "Apri le immagini in un nuovo tab" dashboard: "Pannello di controllo" local: "Locale" -remote: "Remoto" +remote: "Remota" total: "Totale" weekOverWeekChanges: "Settimanale" dayOverDayChanges: "Giornaliero" @@ -550,8 +552,8 @@ installedDate: "Data installazione" lastUsedDate: "Data di ultimo uso" state: "Stato" sort: "Ordina per" -ascendingOrder: "Ascendente" -descendingOrder: "Discendente" +ascendingOrder: "Aumenta" +descendingOrder: "Diminuisce" scratchpad: "ScratchPad" scratchpadDescription: "Lo Scratchpad offre un ambiente per esperimenti di AiScript. È possibile scrivere, eseguire e confermare i risultati dell'interazione del codice con Misskey." output: "Uscita" @@ -620,7 +622,7 @@ emailConfigInfo: "Utilizzato per verificare il tuo indirizzo di posta elettronic email: "Email" emailAddress: "Indirizzo di posta elettronica" smtpConfig: "Impostazioni del server SMTP" -smtpHost: "Server remoto" +smtpHost: "Host SMTP" smtpPort: "Porta" smtpUser: "Nome utente" smtpPass: "Password" @@ -706,9 +708,10 @@ driveUsage: "Utilizzazione del Drive" noCrawle: "Rifiuta l'indicizzazione dai robot." noCrawleDescription: "Richiedi che i motori di ricerca non indicizzino la tua pagina di profilo, le tue note, pagine, ecc." lockedAccountInfo: "A meno che non imposti la visibilità delle tue note su \"Solo ai follower\", le tue note sono visibili da tutti, anche se hai configurato l'account per confermare manualmente le richieste di follow." -alwaysMarkSensitive: "Segnare i media come sensibili per impostazione predefinita" +alwaysMarkSensitive: "Segnare gli allegati come espliciti come opzione predefinita" loadRawImages: "Visualizza le intere immagini allegate invece delle miniature." disableShowingAnimatedImages: "Disabilita le immagini animate" +highlightSensitiveMedia: "Evidenzia i media espliciti" verificationEmailSent: "Una mail di verifica è stata inviata. Si prega di accedere al collegamento per compiere la verifica." notSet: "Non impostato" emailVerified: "Il tuo indirizzo email è stato verificato" @@ -925,7 +928,7 @@ type: "Tipo" speed: "Velocità" slow: "Lento" fast: "Veloce" -sensitiveMediaDetection: "Rilevamento dei contenuti sensibili." +sensitiveMediaDetection: "Rilevamento dei contenuti espliciti" localOnly: "Soltanto locale" remoteOnly: "Solo remoto" failedToUpload: "errore di caricamento" @@ -1005,11 +1008,11 @@ cannotBeChangedLater: "Non sarà più modificabile" reactionAcceptance: "Reazioni consentite" likeOnly: "Solo i Like" likeOnlyForRemote: "Solo Like remoti" -nonSensitiveOnly: "Solamente non sensibili" -nonSensitiveOnlyForLocalLikeOnlyForRemote: "Solamente non sensibili (solo Mi piace remoti)" +nonSensitiveOnly: "Soltanto non espliciti" +nonSensitiveOnlyForLocalLikeOnlyForRemote: "Soltanto non espliciti (reazioni remote)" rolesAssignedToMe: "I miei ruoli" resetPasswordConfirm: "Vuoi davvero ripristinare la password?" -sensitiveWords: "Parole sensibili" +sensitiveWords: "Parole esplicite" sensitiveWordsDescription: "Imposta automaticamente \"Home\" alla visibilità delle Note che contengono una qualsiasi parola tra queste configurate. Puoi separarle per riga." sensitiveWordsDescription2: "Gli spazi creano la relazione \"E\" tra parole (questo E quello). Racchiudere una parola nelle slash \"/\" la trasforma in Espressione Regolare." notesSearchNotAvailable: "Non è possibile cercare tra le Note." @@ -1023,7 +1026,7 @@ retryAllQueuesConfirmText: "Potrebbe sovraccaricare il server temporaneamente." enableChartsForRemoteUser: "Abilita i grafici per i profili remoti" enableChartsForFederatedInstances: "Abilita i grafici per le istanze federate" showClipButtonInNoteFooter: "Aggiungi il bottone Clip tra le azioni delle Note" -largeNoteReactions: "Ingrandisci le reazioni" +reactionsDisplaySize: "Grandezza delle reazioni" noteIdOrUrl: "ID della Nota o URL" video: "Video" videos: "Video" @@ -1105,6 +1108,18 @@ forYou: "Per te" currentAnnouncements: "Annunci attuali" pastAnnouncements: "Annunci precedenti" youHaveUnreadAnnouncements: "Ci sono Annunci non letti" +useSecurityKey: "Per utilizzare la chiave di sicurezza o la passkey, segui le indicazioni del dispositivo" +replies: "Rispondi" +renotes: "Rinota" +loadReplies: "Leggi le risposte" +loadConversation: "Leggi la conversazione" +pinnedList: "Elenco in primo piano" +keepScreenOn: "Mantieni lo schermo acceso" +verifiedLink: "Abbiamo confermato la validità di questo collegamento" +notifyNotes: "Notifica nuove Note" +unnotifyNotes: "Interrompi le notifiche di nuove Note" +authentication: "Autenticazione" +authenticationRequiredToContinue: "Per procedere, è richiesta l'autenticazione" _announcement: forExistingUsers: "Solo ai profili attuali" forExistingUsersDescription: "L'annuncio sarà visibile solo ai profili esistenti in questo momento. Se disabilitato, sarà visibile anche ai profili che verranno creati dopo la pubblicazione di questo annuncio." @@ -1131,6 +1146,15 @@ _initialAccountSetting: laterAreYouSure: "Vuoi davvero rimandare la configurazione iniziale?" _serverRules: description: "In Europa è necessario mostrare l'informativa sul trattamento dei dati personali, prima della registrazione al servizio." +_serverSettings: + iconUrl: "URL dell'icona" + appIconDescription: "Indicare l'icona da usare quando {host} viene salvata come App." + appIconUsageExample: "Ad esempio quando si aggiunge il segnalibro alla PWA (Progressive Web App), oppure alla schermata iniziale del dispositivo mobile " + appIconStyleRecommendation: "Poiché l'icona potrebbe essere ritagliata in un quadrato o in un cerchio, si raccomanda che abbia un margine colorato." + appIconResolutionMustBe: "La risoluzione minima è {resolution}" + manifestJsonOverride: "Sostituire il file manifest.json" + shortName: "Abbreviazione" + shortNameDescription: "Un'abbreviazione o un nome comune che può essere visualizzato al posto del nome ufficiale lungo del server." _accountMigration: moveFrom: "Migra un altro profilo dentro a questo" moveFromSub: "Crea un alias verso un altro profilo remoto" @@ -1385,6 +1409,9 @@ _achievements: title: "Brain Diver" description: "Pubblica un link a Brain Diver" flavor: "Sulle note di Brain Diver" + _smashTestNotificationButton: + title: "Prove eccessive" + description: "Hai provato le notifiche consecutivamente in un periodo di tempo molto breve" _role: new: "Nuovo ruolo" edit: "Modifica ruolo" @@ -1445,10 +1472,10 @@ _role: _condition: isLocal: "Profilo locale" isRemote: "Profilo remoto" - createdLessThan: "Creato meno di" - createdMoreThan: "Creato più di" - followersLessThanOrEq: "Ha meno di N follower" - followersMoreThanOrEq: "Ha più di N follower" + createdLessThan: "Profilo creato da meno di N" + createdMoreThan: "Profilo creato da più di N" + followersLessThanOrEq: "Profilo con N follower o meno" + followersMoreThanOrEq: "Profilo con N follower o più" followingLessThanOrEq: "Segue N profili o meno" followingMoreThanOrEq: "Segue N profili o più" notesLessThanOrEq: "Conteggio Note inferiore o uguale a" @@ -1457,9 +1484,9 @@ _role: or: "O" not: "NON" _sensitiveMediaDetection: - description: "L'apprendimento automatico può essere utilizzato per individuare automaticamente i media sensibili da moderare. Il carico del server aumenta leggermente." - sensitivity: "Sensibilità di rilevamento" - sensitivityDescription: "Una minore sensibilità riduce i falsi positivi (false positività). Una maggiore sensibilità riduce le omissioni (falsi negativi)." + description: "Utilizzare l'apprendimento automatico (machine learning) per riconoscere media espliciti e sottoporli alla moderazione. Aumenterà lievemente il carico del server." + sensitivity: "Sensibilità del rilevamento" + sensitivityDescription: "Abbassando la sensibilità si riducono i falsi positivi (rilevazioni errate). Aumentando la sensibilità si riduce il numero di rilevazioni mancate. (rilevazioni ignorate)." setSensitiveFlagAutomatically: "Impostare il flag NSFW." setSensitiveFlagAutomaticallyDescription: "Anche se questa impostazione è disattivata, il risultato della decisione viene conservato internamente." analyzeVideos: "Abilitazione dell'analisi video." @@ -1508,6 +1535,7 @@ _plugin: install: "Installa estensioni" installWarn: "Si prega di installare soltanto estensioni che provengono da fonti affidabili." manage: "Gestisci estensioni" + viewSource: "Visualizza sorgente" _preferencesBackups: list: "Elenco di impostazioni salvate in precedenza" saveNew: "Nuovo salvataggio" @@ -1542,8 +1570,8 @@ _aboutMisskey: morePatrons: "Apprezziamo sinceramente il supporto di tante altre persone. Grazie mille! 🥰" patrons: "Sostenitori" _displayOfSensitiveMedia: - respect: "Nascondere i media sensibili" - ignore: "Non nascondere i media sensibili" + respect: "Nascondere i media espliciti" + ignore: "Non nascondere i media espliciti" force: "Nascondi tutti i media" _instanceTicker: none: "Nascondi" @@ -1695,7 +1723,6 @@ _timelineTutorial: _2fa: alreadyRegistered: "La configurazione è stata già completata." registerTOTP: "Registra un'app di autenticazione" - passwordToTOTP: "Inserire la password" step1: "Innanzitutto, installare sul dispositivo un'applicazione di autenticazione come {a} o {b}." step2: "Quindi, scansionare il codice QR visualizzato con l'app." step2Click: "Cliccando sul codice QR, puoi registrarlo con l'app di autenticazione o il portachiavi installato sul tuo dispositivo." @@ -1707,7 +1734,6 @@ _2fa: securityKeyNotSupported: "Il tuo browser non supporta le chiavi di sicurezza." registerTOTPBeforeKey: "Ti occorre un'app di autenticazione con OTP, prima di registrare la chiave di sicurezza." securityKeyInfo: "È possibile impostare il dispositivo per accedere utilizzando una chiave di sicurezza hardware che supporta FIDO2 o un'impronta digitale o un PIN sul dispositivo." - chromePasskeyNotSupported: "Le passkey di Chrome non sono attualmente supportate." registerSecurityKey: "Registra la chiave di sicurezza" securityKeyName: "Inserisci il nome della chiave" tapSecurityKey: "Segui le istruzioni del browser e registra la chiave di sicurezza." @@ -1775,6 +1801,7 @@ _antennaSources: homeTimeline: "Note dagli utenti che segui" users: "Note dagli utenti selezionati" userList: "Note dagli utenti della lista selezionata" + userBlacklist: "Tutte le Note tranne quelle di uno o più profili specificati" _weekday: sunday: "Domenica" monday: "Lunedì" @@ -1874,6 +1901,7 @@ _profile: metadataContent: "Contenuto" changeAvatar: "Modifica immagine profilo" changeBanner: "Cambia intestazione" + verifiedLinkDescription: "Puoi verificare il tuo profilo mostrando una icona. Devi inserire la URL alla pagina che contiene un link al tuo profilo." _exportOrImport: allNotes: "Tutte le note" favoritedNotes: "Note preferite" @@ -1992,12 +2020,18 @@ _notification: youReceivedFollowRequest: "Hai ricevuto una richiesta di follow" yourFollowRequestAccepted: "La tua richiesta di follow è stata accettata" pollEnded: "Risultati del sondaggio." + newNote: "Nuove Note" unreadAntennaNote: "Antenna {name}" emptyPushNotificationMessage: "Le notifiche push sono state aggiornate." achievementEarned: "Obiettivo raggiunto" + testNotification: "Prova la notifica" + checkNotificationBehavior: "Prova il comportamento della notifica" + sendTestNotification: "Spedisci una notifica di prova" + notificationWillBeDisplayedLikeThis: "La notifica apparirà così" _types: all: "Tutto" - follow: "Novità follower" + note: "Nuove Note" + follow: "Nuovi profili follower" mention: "Menzioni" reply: "Risposte" renote: "Rinota" @@ -2066,3 +2100,27 @@ _webhookSettings: renote: "Quando la Nota è Rinotata" reaction: "Quando ricevo una reazione" mention: "Quando mi menzionano" +_moderationLogTypes: + updateRole: "Ruolo aggiornato" + assignRole: "Ruolo assegnato" + unassignRole: "Ruolo disassegnato" + suspend: "Sospensione" + unsuspend: "Sospensione rimossa" + addCustomEmoji: "Emoji personalizzata aggiunta" + updateCustomEmoji: "Emoji personalizzata aggiornata" + deleteCustomEmoji: "Emoji personalizzata eliminata" + updateServerSettings: "Impostazioni del server aggiornate" + updateUserNote: "Promemoria di moderazione aggiornato" + deleteDriveFile: "File da Drive eliminato" + deleteNote: "Nota eliminata" + createGlobalAnnouncement: "Annuncio globale creato" + createUserAnnouncement: "Annuncio ai profili iscritti creato" + updateGlobalAnnouncement: "Annuncio globale aggiornato" + updateUserAnnouncement: "Annuncio ai profili iscritti aggiornato" + deleteGlobalAnnouncement: "Annuncio globale eliminato" + deleteUserAnnouncement: "Annuncio ai profili iscritti eliminato" + resetPassword: "Password azzerata" + suspendRemoteInstance: "Istanza remota sospesa" + unsuspendRemoteInstance: "Istanza remota riattivata" + markSensitiveDriveFile: "File nel Drive segnato come esplicito" + unmarkSensitiveDriveFile: "File nel Drive segnato come non esplicito" diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index f9427e13e..647f5fb5f 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -15,7 +15,7 @@ gotIt: "わかった" cancel: "キャンセル" noThankYou: "やめておく" enterUsername: "ユーザー名を入力" -renotedBy: "{user}がRenote" +renotedBy: "{user}がリノート" noNotes: "ノートはありません" noNotifications: "通知はありません" instance: "サーバー" @@ -45,10 +45,10 @@ pin: "ピン留め" unpin: "ピン留め解除" copyContent: "内容をコピー" copyLink: "リンクをコピー" -copyLinkRenote: "Renoteのリンクをコピー" +copyLinkRenote: "リノートのリンクをコピー" delete: "削除" deleteAndEdit: "削除して編集" -deleteAndEditConfirm: "このノートを削除してもう一度編集しますか?このノートへのリアクション、Renote、返信も全て削除されます。" +deleteAndEditConfirm: "このノートを削除してもう一度編集しますか?このノートへのリアクション、リノート、返信も全て削除されます。" addToList: "リストに追加" addToAntenna: "アンテナに追加" sendMessage: "メッセージを送信" @@ -105,13 +105,13 @@ followRequests: "フォロー申請" unfollow: "フォロー解除" followRequestPending: "フォロー許可待ち" enterEmoji: "絵文字を入力" -renote: "Renote" -unrenote: "Renote解除" -renoted: "Renoteしました。" -cantRenote: "この投稿はRenoteできません。" -cantReRenote: "RenoteをRenoteすることはできません。" +renote: "リノート" +unrenote: "リノート解除" +renoted: "リノートしました。" +cantRenote: "この投稿はリノートできません。" +cantReRenote: "リノートをリノートすることはできません。" quote: "引用" -inChannelRenote: "チャンネル内Renote" +inChannelRenote: "チャンネル内リノート" inChannelQuote: "チャンネル内引用" pinnedNote: "ピン留めされたノート" pinned: "ピン留め" @@ -356,7 +356,6 @@ invite: "招待" driveCapacityPerLocalAccount: "ローカルユーザーひとりあたりのドライブ容量" driveCapacityPerRemoteAccount: "リモートユーザーひとりあたりのドライブ容量" inMb: "メガバイト単位" -iconUrl: "アイコン画像のURL (faviconなど)" bannerUrl: "バナー画像のURL" backgroundImageUrl: "背景画像のURL" basicInfo: "基本情報" @@ -417,6 +416,9 @@ totp: "認証アプリ" totpDescription: "認証アプリを使ってワンタイムパスワードを入力" moderator: "モデレーター" moderation: "モデレーション" +moderationNote: "モデレーションノート" +addModerationNote: "モデレーションノートを追加する" +moderationLogs: "モデログ" nUsersMentioned: "{n}人が投稿" securityKeyAndPasskey: "セキュリティキー・パスキー" securityKey: "セキュリティキー" @@ -656,7 +658,7 @@ behavior: "動作" sample: "サンプル" abuseReports: "通報" reportAbuse: "通報" -reportAbuseRenote: "Renoteを通報" +reportAbuseRenote: "リノートを通報" reportAbuseOf: "{name}を通報する" fillAbuseReportDescription: "通報理由の詳細を記入してください。対象のノートがある場合はそのURLも記入してください。" abuseReported: "内容が送信されました。ご報告ありがとうございました。" @@ -690,9 +692,9 @@ manageAccessTokens: "アクセストークンの管理" accountInfo: "アカウント情報" notesCount: "ノートの数" repliesCount: "返信した数" -renotesCount: "Renoteした数" +renotesCount: "リノートした数" repliedCount: "返信された数" -renotedCount: "Renoteされた数" +renotedCount: "リノートされた数" followingCount: "フォロー数" followersCount: "フォロワー数" sentReactionsCount: "リアクションした数" @@ -709,6 +711,7 @@ lockedAccountInfo: "フォローを承認制にしても、ノートの公開範 alwaysMarkSensitive: "デフォルトでメディアをセンシティブ設定にする" loadRawImages: "添付画像のサムネイルをオリジナル画質にする" disableShowingAnimatedImages: "アニメーション画像を再生しない" +highlightSensitiveMedia: "メディアがセンシティブであることを分かりやすく表示" verificationEmailSent: "確認のメールを送信しました。メールに記載されたリンクにアクセスして、設定を完了してください。" notSet: "未設定" emailVerified: "メールアドレスが確認されました" @@ -988,7 +991,7 @@ thisPostMayBeAnnoying: "この投稿は迷惑になる可能性があります thisPostMayBeAnnoyingHome: "ホームに投稿" thisPostMayBeAnnoyingCancel: "やめる" thisPostMayBeAnnoyingIgnore: "このまま投稿" -collapseRenotes: "見たことのあるRenoteを省略して表示" +collapseRenotes: "見たことのあるリノートを省略して表示" internalServerError: "サーバー内部エラー" internalServerErrorDescription: "サーバー内部で予期しないエラーが発生しました。" copyErrorInfo: "エラー情報をコピー" @@ -1036,7 +1039,7 @@ forceShowAds: "常に広告を表示する" addMemo: "メモを追加" editMemo: "メモを編集" reactionsList: "リアクション一覧" -renotesList: "Renote一覧" +renotesList: "リノート一覧" notificationDisplay: "通知の表示" leftTop: "左上" rightTop: "右上" @@ -1106,6 +1109,18 @@ currentAnnouncements: "現在のお知らせ" pastAnnouncements: "過去のお知らせ" youHaveUnreadAnnouncements: "未読のお知らせがあります。" useSecurityKey: "ブラウザまたはデバイスの指示に従って、セキュリティキーまたはパスキーを使用してください。" +replies: "返信" +renotes: "リノート" +loadReplies: "返信を見る" +loadConversation: "会話を見る" +pinnedList: "ピン留めされたリスト" +keepScreenOn: "デバイスの画面を常にオンにする" +verifiedLink: "このリンク先の所有者であることが確認されました" +notifyNotes: "投稿を通知" +unnotifyNotes: "投稿の通知を解除" +authentication: "認証" +authenticationRequiredToContinue: "続けるには認証を行ってください" +dateAndTime: "日時" _announcement: forExistingUsers: "既存ユーザーのみ" @@ -1136,6 +1151,16 @@ _initialAccountSetting: _serverRules: description: "新規登録前に表示する、サーバーの簡潔なルールを設定します。内容は利用規約の要約とすることを推奨します。" +_serverSettings: + iconUrl: "アイコン画像のURL" + appIconDescription: "{host}がアプリとして表示される際のアイコンを指定します。" + appIconUsageExample: "例: PWAや、スマートフォンのホーム画面にブックマークとして追加された時など" + appIconStyleRecommendation: "円形もしくは角丸にクロップされる場合があるため、塗り潰された余白のある背景を持つことが推奨されます。" + appIconResolutionMustBe: "解像度は必ず{resolution}である必要があります。" + manifestJsonOverride: "manifest.jsonのオーバーライド" + shortName: "略称" + shortNameDescription: "サーバーの正式名称が長い場合に、代わりに表示することのできる略称や通称。" + _accountMigration: moveFrom: "別のアカウントからこのアカウントに移行" moveFromSub: "別のアカウントへエイリアスを作成" @@ -1391,6 +1416,9 @@ _achievements: title: "Brain Diver" description: "Brain Diverへのリンクを投稿した" flavor: "Misskey-Misskey La-Tu-Ma" + _smashTestNotificationButton: + title: "テスト過剰" + description: "通知のテストをごく短時間のうちに連続して行った" _role: new: "ロールの作成" @@ -1525,6 +1553,7 @@ _plugin: install: "プラグインのインストール" installWarn: "信頼できないプラグインはインストールしないでください。" manage: "プラグインの管理" + viewSource: "ソースを表示" _preferencesBackups: list: "作成したバックアップ" @@ -1729,7 +1758,6 @@ _timelineTutorial: _2fa: alreadyRegistered: "既に設定は完了しています。" registerTOTP: "認証アプリの設定を開始" - passwordToTOTP: "パスワードを入力してください" step1: "まず、{a}や{b}などの認証アプリをお使いのデバイスにインストールします。" step2: "次に、表示されているQRコードをアプリでスキャンします。" step2Click: "QRコードをクリックすると、お使いの端末にインストールされている認証アプリやキーリングに登録できます。" @@ -1811,6 +1839,7 @@ _antennaSources: homeTimeline: "フォローしているユーザーのノート" users: "指定した一人または複数のユーザーのノート" userList: "指定したリストのユーザーのノート" + userBlacklist: "指定した一人または複数のユーザーを除いた全てのノート" _weekday: sunday: "日曜日" @@ -1917,6 +1946,7 @@ _profile: metadataContent: "内容" changeAvatar: "アイコン画像を変更" changeBanner: "バナー画像を変更" + verifiedLinkDescription: "内容にURLを設定すると、リンク先のWebサイトに自分のプロフィールへのリンクが含まれている場合に所有者確認済みアイコンを表示させることができます。" _exportOrImport: allNotes: "全てのノート" @@ -2044,6 +2074,7 @@ _notification: youReceivedFollowRequest: "フォローリクエストが来ました" yourFollowRequestAccepted: "フォローリクエストが承認されました" pollEnded: "アンケートの結果が出ました" + newNote: "新しい投稿" unreadAntennaNote: "アンテナ {name}" emptyPushNotificationMessage: "プッシュ通知の更新をしました" achievementEarned: "実績を獲得" @@ -2054,6 +2085,7 @@ _notification: _types: all: "すべて" + note: "ユーザーの新規投稿" follow: "フォロー" mention: "メンション" reply: "リプライ" @@ -2130,3 +2162,31 @@ _webhookSettings: renote: "Renoteされたとき" reaction: "リアクションがあったとき" mention: "メンションされたとき" + +_moderationLogTypes: + createRole: "ロールを作成" + deleteRole: "ロールを削除" + updateRole: "ロールを更新" + assignRole: "ロールへアサイン" + unassignRole: "ロールのアサイン解除" + suspend: "凍結" + unsuspend: "凍結解除" + addCustomEmoji: "カスタム絵文字追加" + updateCustomEmoji: "カスタム絵文字更新" + deleteCustomEmoji: "カスタム絵文字削除" + updateServerSettings: "サーバー設定更新" + updateUserNote: "モデレーションノート更新" + deleteDriveFile: "ファイルを削除" + deleteNote: "ノートを削除" + createGlobalAnnouncement: "全体のお知らせを作成" + createUserAnnouncement: "ユーザーへお知らせを作成" + updateGlobalAnnouncement: "全体のお知らせを更新" + updateUserAnnouncement: "ユーザーのお知らせを更新" + deleteGlobalAnnouncement: "全体のお知らせを削除" + deleteUserAnnouncement: "ユーザーのお知らせを削除" + resetPassword: "パスワードをリセット" + suspendRemoteInstance: "リモートサーバーを停止" + unsuspendRemoteInstance: "リモートサーバーを再開" + markSensitiveDriveFile: "ファイルをセンシティブ付与" + unmarkSensitiveDriveFile: "ファイルをセンシティブ解除" + resolveAbuseReport: "通報を解決" diff --git a/locales/ja-KS.yml b/locales/ja-KS.yml index 92c8270c7..efbb0ff5f 100644 --- a/locales/ja-KS.yml +++ b/locales/ja-KS.yml @@ -355,7 +355,6 @@ invite: "来てや" driveCapacityPerLocalAccount: "ローカルユーザーはんひとりあたりのドライブ容量" driveCapacityPerRemoteAccount: "リモートユーザーはんひとりあたりのドライブ容量" inMb: "メガバイト単位" -iconUrl: "アイコン画像のURL" bannerUrl: "バナー画像のURL" backgroundImageUrl: "背景画像のURL" basicInfo: "基本情報" @@ -415,6 +414,8 @@ totp: "認証アプリ" totpDescription: "認証アプリ使うてワンタイムパスワードを入れる" moderator: "モデレーター" moderation: "モデレーション" +moderationNote: "モデレーションノート" +addModerationNote: "モデレーションノートを追加するで" nUsersMentioned: "{n}人が投稿" securityKeyAndPasskey: "セキュリティキー・パスキー" securityKey: "セキュリティキー" @@ -1020,7 +1021,6 @@ retryAllQueuesConfirmText: "一時的にサーバー重なるかもしれへん enableChartsForRemoteUser: "リモートユーザーのチャートを作る" enableChartsForFederatedInstances: "リモートサーバーのチャートを作る" showClipButtonInNoteFooter: "ノートのアクションにクリップを追加" -largeNoteReactions: "ノートのツッコミを大きする" noteIdOrUrl: "ノートIDかURL" video: "動画" videos: "動画" @@ -1102,6 +1102,9 @@ forYou: "あんたへ" currentAnnouncements: "現在のお知らせやで" pastAnnouncements: "過去のお知らせやで" youHaveUnreadAnnouncements: "あんたまだこのお知らせ読んどらんやろ。" +useSecurityKey: "ブラウザまたはデバイスの言う通りに、セキュリティキーまたはパスキーを使ってや。" +replies: "返事" +renotes: "Renote" _announcement: forExistingUsers: "もうおるユーザーのみ" forExistingUsersDescription: "有効にすると、このお知らせ作成時点でおるユーザーにのみお知らせが表示されます。無効にすると、このお知らせ作成後にアカウントを作成したユーザーにもお知らせが表示されます。" @@ -1128,6 +1131,8 @@ _initialAccountSetting: laterAreYouSure: "初期設定あとでやり直すん?" _serverRules: description: "新規登録前に見せる、サーバーの簡潔なルールを設定すんで。内容は使うための決め事の要約とすることを推奨するわ。" +_serverSettings: + iconUrl: "アイコン画像のURL" _accountMigration: moveFrom: "別のアカウントからこのアカウントに引っ越す" moveFromSub: "別のアカウントへエイリアスを作る" @@ -1505,6 +1510,7 @@ _plugin: install: "プラグインのインストール" installWarn: "信頼できへんプラグインはインストールせんとってな" manage: "プラグインの管理" + viewSource: "ソースを表示" _preferencesBackups: list: "作ったバックアップ" saveNew: "新しく保存" @@ -1692,7 +1698,6 @@ _timelineTutorial: _2fa: alreadyRegistered: "もう設定終わっとるわ。" registerTOTP: "認証アプリの設定はじめる" - passwordToTOTP: "パスワードを入れてーや" step1: "ほんなら、{a}や{b}とかの認証アプリを使っとるデバイスにインストールしてな。" step2: "次に、ここにあるQRコードをアプリでスキャンしてな~。" step2Click: "QRコードをクリックすると、今使とる端末に入っとる認証アプリとかキーリングに登録できるで。" @@ -1702,7 +1707,6 @@ _2fa: securityKeyNotSupported: "今使とるブラウザはセキュリティキーに対応してへんのやってさ。" registerTOTPBeforeKey: "セキュリティキー・パスキーを登録するんやったら、まず認証アプリを設定してーな。" securityKeyInfo: "FIDO2をサポートするハードウェアセキュリティキーか端末の指紋認証やPINを使ってログインするように設定できるで。" - chromePasskeyNotSupported: "Chromeのパスキーは今んとこ対応してないねん。" registerSecurityKey: "セキュリティキー・パスキーを登録するわ" securityKeyName: "キーの名前を入れてーや" tapSecurityKey: "ブラウザが言うこと聞いて、セキュリティキーとかパスキー登録しといでや" @@ -2054,3 +2058,6 @@ _webhookSettings: renote: "Renoteされるとき~!" reaction: "ツッコミがあるとき~!" mention: "メンションがあるとき~!" +_moderationLogTypes: + suspend: "凍結" + resetPassword: "パスワードをリセット" diff --git a/locales/kab-KAB.yml b/locales/kab-KAB.yml index 18fd8f5a5..22e24d3ba 100644 --- a/locales/kab-KAB.yml +++ b/locales/kab-KAB.yml @@ -56,6 +56,7 @@ accounts: "Imiḍan" searchByGoogle: "Nadi" file: "Ifuyla" account: "Imiḍan" +replies: "Err" _email: _follow: title: "Yeṭṭafaṛ-ik·em-id" diff --git a/locales/kn-IN.yml b/locales/kn-IN.yml index ef66f3fbd..b3ad46f2b 100644 --- a/locales/kn-IN.yml +++ b/locales/kn-IN.yml @@ -61,6 +61,7 @@ smtpPass: "ಗುಪ್ತಪದ" user: "ಬಳಕೆದಾರ" searchByGoogle: "ಹುಡುಕು" file: "ಕಡತಗಳು" +replies: "ಉತ್ತರಿಸು" _email: _follow: title: "ಹಿಂಬಾಲಿಸಿದರು" diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml index 255e88f83..0fcb39ebc 100644 --- a/locales/ko-KR.yml +++ b/locales/ko-KR.yml @@ -45,6 +45,7 @@ pin: "프로필에 고정" unpin: "프로필에서 고정 해제" copyContent: "내용 복사" copyLink: "링크 복사" +copyLinkRenote: "Renote 링크 복사" delete: "삭제" deleteAndEdit: "삭제 후 편집" deleteAndEditConfirm: "이 노트를 삭제한 뒤 다시 편집하시겠습니까? 이 노트에 대한 리액션, 리노트, 답글 또한 모두 삭제됩니다." @@ -355,7 +356,6 @@ invite: "초대" driveCapacityPerLocalAccount: "로컬 유저 한 명당 드라이브 용량" driveCapacityPerRemoteAccount: "리모트 유저 한 명당 드라이브 용량" inMb: "메가바이트 단위" -iconUrl: "아이콘 URL" bannerUrl: "배너 이미지 URL" backgroundImageUrl: "배경 이미지 URL" basicInfo: "기본 정보" @@ -655,6 +655,7 @@ behavior: "동작" sample: "예시" abuseReports: "신고" reportAbuse: "신고" +reportAbuseRenote: "Renote를 신고" reportAbuseOf: "{name}을 신고하기" fillAbuseReportDescription: "신고하려는 이유를 자세히 알려주세요. 특정 게시물을 신고할 때에는 게시물의 URL도 포함해 주세요." abuseReported: "신고를 보냈습니다. 신고해 주셔서 감사합니다." @@ -1021,7 +1022,7 @@ retryAllQueuesConfirmText: "일시적으로 서버의 부하가 증가할 수 enableChartsForRemoteUser: "리모트 유저의 차트를 생성" enableChartsForFederatedInstances: "리모트 서버의 차트를 생성" showClipButtonInNoteFooter: "노트 동작에 클립을 추가" -largeNoteReactions: "노트의 리액션을 크게 표시" +reactionsDisplaySize: "리액션 표시 크기" noteIdOrUrl: "노트 ID 및 URL" video: "동영상" videos: "동영상" @@ -1103,6 +1104,9 @@ forYou: "당신에게" currentAnnouncements: "현재 공지사항" pastAnnouncements: "과거 공지사항" youHaveUnreadAnnouncements: "읽지 않은 공지사항이 있습니다." +useSecurityKey: "브라우저 또는 기기의 안내에 따라 보안 키 또는 패스키를 사용해 주십시오." +replies: "답글" +renotes: "리노트" _announcement: forExistingUsers: "기존 유저에게만 알림" forExistingUsersDescription: "활성화하면 이 공지사항을 게시한 시점에서 이미 가입한 유저에게만 표시합니다. 비활성화하면 게시 후에 가입한 유저에게도 표시합니다." @@ -1129,6 +1133,8 @@ _initialAccountSetting: laterAreYouSure: "초기 설정을 나중에 진행하시겠습니까?" _serverRules: description: "회원 가입 이전에 간단하게 표시할 서버 규칙입니다. 이용 약관의 요약으로 구성하는 것을 추천합니다." +_serverSettings: + iconUrl: "아이콘 URL" _accountMigration: moveFrom: "다른 계정에서 이 계정으로 이사" moveFromSub: "다른 계정에 대한 별칭을 생성" @@ -1506,6 +1512,7 @@ _plugin: install: "플러그인 설치" installWarn: "신뢰할 수 없는 플러그인은 설치하지 않는 것이 좋습니다." manage: "플러그인 관리" + viewSource: "소스 보기" _preferencesBackups: list: "생성한 백업" saveNew: "새 백업 만들기" @@ -1693,7 +1700,6 @@ _timelineTutorial: _2fa: alreadyRegistered: "이미 설정이 완료되었습니다." registerTOTP: "인증 앱 설정 시작" - passwordToTOTP: "비밀번호를 입력하세요." step1: "먼저, {a}나 {b}등의 인증 앱을 사용 중인 디바이스에 설치합니다." step2: "그 후, 표시되어 있는 QR코드를 앱으로 스캔합니다." step2Click: "QR 코드를 클릭하면 기기에 설치된 인증 앱에 등록할 수 있습니다." @@ -1705,7 +1711,6 @@ _2fa: securityKeyNotSupported: "이 브라우저는 보안 키를 지원하지 않습니다." registerTOTPBeforeKey: "보안 키 또는 패스키를 등록하려면 인증 앱을 등록하십시오." securityKeyInfo: "FIDO2를 지원하는 하드웨어 보안 키 혹은 디바이스의 지문인식이나 화면잠금 PIN을 이용해서 로그인하도록 설정할 수 있습니다." - chromePasskeyNotSupported: "현재 Chrome의 패스키는 지원되지 않습니다." registerSecurityKey: "보안 키 또는 패스키 등록" securityKeyName: "키 이름 입력" tapSecurityKey: "브라우저의 지시에 따라 보안 키 또는 패스키를 등록하여 주십시오" @@ -1993,6 +1998,10 @@ _notification: unreadAntennaNote: "안테나 {name}" emptyPushNotificationMessage: "푸시 알림이 갱신되었습니다" achievementEarned: "도전 과제를 달성했습니다" + testNotification: "알림 테스트" + checkNotificationBehavior: "알림 표시를 체크하기" + sendTestNotification: "테스트 알림 보내기" + notificationWillBeDisplayedLikeThis: "알림이 이렇게 표시됩니다" _types: all: "전부" follow: "팔로잉" @@ -2028,6 +2037,8 @@ _deck: introduction2: "나중에라도 화면 우측의 + 버튼을 눌러 새 칼럼을 추가할 수 있습니다." widgetsIntroduction: "칼럼 메뉴의 \"위젯 편집\"에서 위젯을 추가해 주세요" useSimpleUiForNonRootPages: "루트 이외의 페이지로 접속한 경우 UI 간략화하기" + usedAsMinWidthWhenFlexible: "'폭 자동 조정'이 활성화된 경우 최소 폭으로 사용됩니다" + flexible: "폭 자동 조정" _columns: main: "메인" widgets: "위젯" @@ -2062,3 +2073,6 @@ _webhookSettings: renote: "누군가 내 글을 Renote했을 때" reaction: "누군가 내 노트에 리액션했을 때" mention: "누군가 나를 멘션했을 때" +_moderationLogTypes: + suspend: "정지" + resetPassword: "비밀번호 재설정" diff --git a/locales/lo-LA.yml b/locales/lo-LA.yml index 10010e9ce..22cb5857f 100644 --- a/locales/lo-LA.yml +++ b/locales/lo-LA.yml @@ -391,6 +391,8 @@ administration: "ການຈັດການ" middle: "ປານກາງ" searchByGoogle: "ຄົ້ນຫາ" file: "ໄຟລ໌" +replies: "ຕອບໄປທີ" +renotes: "Renote" _role: _priority: middle: "ປານກາງ" @@ -461,3 +463,5 @@ _deck: mentions: "ກ່າວເຖິງ" _webhookSettings: name: "ຊື່" +_moderationLogTypes: + suspend: "ລະງັບ" diff --git a/locales/nl-NL.yml b/locales/nl-NL.yml index 30c7e1dca..fd9ffa33f 100644 --- a/locales/nl-NL.yml +++ b/locales/nl-NL.yml @@ -338,7 +338,6 @@ invite: "Uitnodigen" driveCapacityPerLocalAccount: "Opslagruimte per lokale gebruiker" driveCapacityPerRemoteAccount: "Opslagruimte per externe gebruiker" inMb: "in megabytes" -iconUrl: "Pictogram URL" bannerUrl: "Banner URL" backgroundImageUrl: "URL afbeelding" basicInfo: "Basisinformatie" @@ -427,6 +426,8 @@ windowMaximize: "Maximaliseren" windowRestore: "Herstellen" loggedInAsBot: "Momenteel als bot ingelogd" icon: "Avatar" +replies: "Antwoord" +renotes: "Herdelen" _email: _follow: title: "volgde jou" @@ -493,3 +494,6 @@ _deck: mentions: "Vermeldingen" _webhookSettings: name: "Naam" +_moderationLogTypes: + suspend: "Opschorten" + resetPassword: "Wachtwoord terugzetten" diff --git a/locales/no-NO.yml b/locales/no-NO.yml index 72229ab0d..00f22c0c4 100644 --- a/locales/no-NO.yml +++ b/locales/no-NO.yml @@ -462,6 +462,8 @@ continue: "Fortsett" youFollowing: "Følger" options: "Alternativ" icon: "Avatar" +replies: "Svar" +renotes: "Renote" _initialAccountSetting: theseSettingsCanEditLater: "Du kan endre disse innstillingene senere." _achievements: @@ -723,3 +725,5 @@ _deck: direct: "Direkte" _webhookSettings: name: "Navn" +_moderationLogTypes: + suspend: "Suspender" diff --git a/locales/pl-PL.yml b/locales/pl-PL.yml index c472d42ca..1c7ebe810 100644 --- a/locales/pl-PL.yml +++ b/locales/pl-PL.yml @@ -333,7 +333,6 @@ invite: "Zaproś" driveCapacityPerLocalAccount: "Powierzchnia dyskowa na lokalnego użytkownika" driveCapacityPerRemoteAccount: "Powierzchnia dyskowa na zdalnego użytkownika" inMb: "W megabajtach" -iconUrl: "Adres URL ikony" bannerUrl: "Adres URL banera" backgroundImageUrl: "Adres URL tła" basicInfo: "Podstawowe informacje" @@ -872,6 +871,8 @@ show: "Wyświetlanie" color: "Kolor" youFollowing: "Śledzeni" icon: "Awatar" +replies: "Odpowiedz" +renotes: "Udostępnij" _role: priority: "Priorytet" _priority: @@ -924,6 +925,7 @@ _plugin: install: "Zainstaluj wtyczki" installWarn: "Nie instaluj niezaufanych wtyczek." manage: "Zarządzanie wtyczkami" + viewSource: "Zobacz źródło" _preferencesBackups: list: "Utworzone kopie zapasowe" saveNew: "Zapisz nową kopię zapasową" @@ -1400,3 +1402,6 @@ _webhookSettings: renote: "Po udostępnieniu wpisu" reaction: "Po otrzymaniu reakcji" mention: "Po zostaniu wspomnianym" +_moderationLogTypes: + suspend: "Zawieś" + resetPassword: "Zresetuj hasło" diff --git a/locales/pt-PT.yml b/locales/pt-PT.yml index bda02e24a..f9e777bc7 100644 --- a/locales/pt-PT.yml +++ b/locales/pt-PT.yml @@ -356,7 +356,6 @@ invite: "Convidar" driveCapacityPerLocalAccount: "Capacidade do drive por usuário local" driveCapacityPerRemoteAccount: "Capacidade do drive por usuário remoto" inMb: "Em ‘megabytes’" -iconUrl: "URL da imagem do ícone (favicon, etc.)" bannerUrl: "URL da imagem do ‘banner’" backgroundImageUrl: "URL da imagem de fundo" basicInfo: "Informações básicas" @@ -412,6 +411,7 @@ aboutMisskey: "Sobre Misskey" administrator: "Administrador" token: "Símbolo" 2fa: "Autenticação de dois fatores" +setupOf2fa: "Configuração de autenticação de dois fatores" totp: "Aplicativo Autenticador" totpDescription: "Digite a senha de uso único informado pelo aplicativo autenticador" moderator: "Moderador" @@ -919,6 +919,7 @@ pleaseSelect: "Por favor, selecione." reverse: "Inversão" colored: "Colorido" refreshInterval: "Intervalo de atualização" +label: "Etiqueta" type: "Tipo" speed: "Velocidade" slow: "Lento" @@ -984,6 +985,7 @@ rolesAssignedToMe: "Cargos atribuídos a mim" unfavoriteConfirm: "Deseja realmente remover dos favoritos?" drivecleaner: "Limpeza do drive" retryAllQueuesConfirmTitle: "Gostaria de tentar novamente agora?" +reactionsDisplaySize: "Tamanho de exibição das reações" reactionsList: "Reações" renotesList: "Repostagens" leftTop: "Superior esquerdo" @@ -1006,8 +1008,13 @@ rolesThatCanBeUsedThisEmojiAsReactionEmptyDescription: "Se nenhum cargo for espe rolesThatCanBeUsedThisEmojiAsReactionPublicRoleWarn: "Estes cargos devem ser públicos." waitingForMailAuth: "Verificação de e-mail pendente " icon: "Avatar" +replies: "Responder" +renotes: "Repostar" +keepScreenOn: "Manter a tela do dispositivo sempre ligada" _initialAccountSetting: followUsers: "Siga usuários que lhe interessam para criar a sua linha do tempo." +_serverSettings: + iconUrl: "URL do ícone" _accountMigration: moveFromDescription: "Se você deseja migrar de outra conta para esta, é necessário criar um alias aqui. Por favor, insira a conta de origem da migração no seguinte formato: @username@server.example.com. Para excluir o alias, deixe o campo em branco e clique em salvar (não recomendado)." moveAccountDescription: "Você está migrando para uma nova conta.\n ・Seus seguidores irão automaticamente seguir a nova conta.\n ・Todas as suas conexões de seguidores nesta conta serão removidas.\n ・Você não poderá mais criar novas notas nesta conta.\n\nA migração dos seguidores é automática, mas a migração das pessoas que você segue deve ser feita manualmente. Antes de migrar, exporte quem você está seguindo nesta conta e, assim que migrar, importe essa lista na nova conta.\nO mesmo se aplica para listas, silenciamentos e bloqueios, que também devem ser migrados manualmente.\n\n(Esta descrição se refere ao comportamento do servidor Misskey v13.12.0 ou posterior. Outros softwares ActivityPub, como Mastodon, podem ter comportamentos diferentes.)" @@ -1490,3 +1497,6 @@ _webhookSettings: follow: "Quando seguindo um usuário" followed: "Quando sendo seguido" renote: "Quando repostado" +_moderationLogTypes: + suspend: "Suspender" + resetPassword: "Redefinir senha" diff --git a/locales/ro-RO.yml b/locales/ro-RO.yml index 1861b2833..51c33085a 100644 --- a/locales/ro-RO.yml +++ b/locales/ro-RO.yml @@ -328,7 +328,6 @@ invite: "Invită" driveCapacityPerLocalAccount: "Capacitatea Drive-ului per utilizator local" driveCapacityPerRemoteAccount: "Capacitatea Drive-ului per utilizator extern" inMb: "În megabytes" -iconUrl: "URL-ul iconiței" bannerUrl: "URL-ul imaginii de banner" backgroundImageUrl: "URL-ul imaginii de fundal" basicInfo: "Informații de bază" @@ -631,6 +630,8 @@ searchByGoogle: "Caută" file: "Fișiere" show: "Arată" icon: "Avatar" +replies: "Răspunde" +renotes: "Re-notează" _role: _priority: middle: "Mediu" @@ -703,3 +704,6 @@ _deck: mentions: "Mențiuni" _webhookSettings: name: "Nume" +_moderationLogTypes: + suspend: "Suspendă" + resetPassword: "Resetează parola" diff --git a/locales/ru-RU.yml b/locales/ru-RU.yml index f12481b2c..937158978 100644 --- a/locales/ru-RU.yml +++ b/locales/ru-RU.yml @@ -354,7 +354,6 @@ invite: "Пригласить" driveCapacityPerLocalAccount: "Объём диска на одного локального пользователя" driveCapacityPerRemoteAccount: "Объём диска на одного пользователя с другого сайта" inMb: "В мегабайтах" -iconUrl: "Ссылка на аватар" bannerUrl: "Ссылка на изображение в шапке" backgroundImageUrl: "Ссылка на фоновое изображение" basicInfo: "Общая информация" @@ -1017,7 +1016,6 @@ retryAllQueuesConfirmTitle: "Хотите попробовать ещё раз?" retryAllQueuesConfirmText: "Нагрузка на сервер может увеличиться" enableChartsForRemoteUser: "Создание диаграмм для удалённых пользователей" enableChartsForFederatedInstances: "Создание диаграмм для удалённых серверов" -largeNoteReactions: "Показывать большие реакции на заметки" noteIdOrUrl: "ID или ссылка на заметку" video: "Видео" videos: "Видео" @@ -1067,6 +1065,8 @@ unused: "Неиспользуемый" expired: "Срок действия приглашения истёк" doYouAgree: "Согласны?" icon: "Аватар" +replies: "Ответить" +renotes: "Репост" _initialAccountSetting: accountCreated: "Аккаунт успешно создан!" letsStartAccountSetup: "Давайте настроим вашу учётную запись." @@ -1074,6 +1074,8 @@ _initialAccountSetting: privacySetting: "Настройки конфиденциальности" initialAccountSettingCompleted: "Первоначальная настройка успешно завершена!" skipAreYouSure: "Пропустить настройку?" +_serverSettings: + iconUrl: "Адрес на иконку роли" _achievements: earnedAt: "Разблокировано в" _types: @@ -1425,6 +1427,7 @@ _plugin: install: "Установка расширений" installWarn: "Пожалуйста, не устанавливайте расширения, которым не доверяете." manage: "Управление расширениями" + viewSource: "Просмотр исходника" _preferencesBackups: list: "Существующие резервные копии" saveNew: "Создать резервную копию" @@ -1606,7 +1609,6 @@ _timelineTutorial: _2fa: alreadyRegistered: "Двухфакторная аутентификация уже настроена." registerTOTP: "Начните настраивать приложение-аутентификатор" - passwordToTOTP: "Пожалуйста, введите свой пароль" step1: "Прежде всего, установите на устройство приложение для аутентификации, например, {a} или {b}." step2: "Далее отсканируйте отображаемый QR-код при помощи приложения." step2Click: "Нажав на QR-код, вы можете зарегистрироваться с помощью приложения для аутентификации или брелка для ключей, установленного на вашем устройстве." @@ -1616,7 +1618,6 @@ _2fa: securityKeyNotSupported: "Ваш браузер не поддерживает ключи безопасности." registerTOTPBeforeKey: "Чтобы зарегистрировать ключ безопасности и пароль, сначала настройте приложение аутентификации." securityKeyInfo: "Вы можете настроить вход с помощью аппаратного ключа безопасности, поддерживающего FIDO2, или отпечатка пальца или PIN-кода на устройстве." - chromePasskeyNotSupported: "В настоящее время Chrome не поддерживает пароль-ключи." registerSecurityKey: "Зарегистрируйте ключ безопасности ・Passkey" securityKeyName: "Введите имя для ключа" tapSecurityKey: "Пожалуйста, следуйте инструкциям в вашем браузере, чтобы зарегистрировать свой ключ безопасности или пароль" @@ -1950,3 +1951,6 @@ _webhookSettings: createWebhook: "Создать вебхук" name: "Название" active: "Вкл." +_moderationLogTypes: + suspend: "Заморозить" + resetPassword: "Сброс пароля:" diff --git a/locales/sk-SK.yml b/locales/sk-SK.yml index 9f7e94091..e44aaafc0 100644 --- a/locales/sk-SK.yml +++ b/locales/sk-SK.yml @@ -337,7 +337,6 @@ invite: "Pozvať" driveCapacityPerLocalAccount: "Kapacita disku pre používateľa" driveCapacityPerRemoteAccount: "Kapacita disku pre vzdialeného používateľa" inMb: "V megabajtoch" -iconUrl: "Favicon URL" bannerUrl: "URL obrázku bannera" backgroundImageUrl: "URL obrázku pozadia" basicInfo: "Základné informácie" @@ -920,6 +919,8 @@ color: "Farba" horizontal: "Strana" youFollowing: "Sledované" icon: "Avatar" +replies: "Odpovedať" +renotes: "Preposlať" _role: priority: "Priorita" _priority: @@ -977,6 +978,7 @@ _plugin: install: "Inštalova pluginy" installWarn: "Prosím neinštalujte nedôveryhodné pluginy." manage: "Spravovanie pluginov" + viewSource: "Ukázať zdroj" _preferencesBackups: list: "Vytvorené zálohy" saveNew: "Uložiť novú" @@ -1449,3 +1451,6 @@ _deck: _webhookSettings: name: "Názov" active: "Zapnuté" +_moderationLogTypes: + suspend: "Zmraziť" + resetPassword: "Resetovať heslo" diff --git a/locales/sv-SE.yml b/locales/sv-SE.yml index 5ba206f9f..62e7d412a 100644 --- a/locales/sv-SE.yml +++ b/locales/sv-SE.yml @@ -337,7 +337,6 @@ registration: "Registrera" enableRegistration: "Aktivera registrering av nya användare" invite: "Inbjudan" inMb: "I megabyte" -iconUrl: "URL till profilbilden" bannerUrl: "URL till banner-bilden" basicInfo: "Grundläggande info" pinnedUsers: "Fästa användare" @@ -486,6 +485,8 @@ pleaseDonate: "Misskey är en gratis programvara som används på {host}. Donera resetPasswordConfirm: "Återställ verkligen ditt lösenord?" dataSaver: "Databesparing" icon: "Profilbild" +replies: "Svara" +renotes: "Omnotera" _achievements: _types: _open3windows: @@ -509,7 +510,6 @@ _sfx: chat: "Chatt" antenna: "Antenner" _2fa: - passwordToTOTP: "Skriv in ditt lösenord" renewTOTPCancel: "Nej tack" _antennaSources: all: "Alla noter" @@ -573,3 +573,6 @@ _deck: _webhookSettings: name: "Namn" active: "Aktiverad" +_moderationLogTypes: + suspend: "Suspendera" + resetPassword: "Återställ Lösenord" diff --git a/locales/th-TH.yml b/locales/th-TH.yml index 33a431b1e..c252ce93f 100644 --- a/locales/th-TH.yml +++ b/locales/th-TH.yml @@ -45,6 +45,7 @@ pin: "ปักหมุดไปยังโปรไฟล์" unpin: "เลิกปักหมุดจากโปรไฟล์" copyContent: "คัดลอกเนื้อหา" copyLink: "คัดลอกลิงก์" +copyLinkRenote: "คัดลอกลิงก์รีโน้ต" delete: "ลบ" deleteAndEdit: "ลบและแก้ไข" deleteAndEditConfirm: "นายแน่ใจแล้วเหรอ? ว่าต้องการลบโน้ตนี้และแก้ไข คุณอาจจะสูญเสียการโต้ตอบ, โน้ต, และการตอบกลับทั้งหมดได้นะ" @@ -355,7 +356,6 @@ invite: "เชิญชวน" driveCapacityPerLocalAccount: "ความจุของไดรฟ์ต่อผู้ใช้ภายในเครื่อง" driveCapacityPerRemoteAccount: "ความจุของไดรฟ์ต่อผู้ใช้ระยะไกล" inMb: "เป็นเมกะไบต์" -iconUrl: "ไอคอน URL" bannerUrl: "URL รูปภาพแบนเนอร์" backgroundImageUrl: "URL ภาพพื้นหลัง" basicInfo: "ข้อมูลเบื้องต้น" @@ -411,6 +411,7 @@ aboutMisskey: "เกี่ยวกับ Misskey" administrator: "ผู้ดูแลระบบ" token: "โทเค็น" 2fa: "การยืนยันตัวตนแบบสองชั้น" +setupOf2fa: "ตั้งค่าการยืนยันตัวตนแบบสองชั้น" totp: "แอป Authenticator" totpDescription: "ใช้แอปยืนยันตัวตนเพื่อป้อนรหัสผ่านแบบใช้ครั้งเดียว" moderator: "ผู้ควบคุม" @@ -654,6 +655,7 @@ behavior: "พฤติกรรม" sample: "ตัวอย่าง" abuseReports: "รายงาน" reportAbuse: "รายงาน" +reportAbuseRenote: "รายงานรีโน้ต" reportAbuseOf: "รายงาน {ชื่อ}" fillAbuseReportDescription: "กรุณากรอกรายละเอียดเกี่ยวกับรายงานนี้ หากเป็นเรื่องเกี่ยวกับโน้ตโดยเฉพาะ ได้โปรดระบุ URL" abuseReported: "เราได้ส่งรายงานของคุณไปแล้ว ขอบคุณมากๆนะ" @@ -1020,7 +1022,6 @@ retryAllQueuesConfirmText: "สิ่งนี้จะเพิ่มการ enableChartsForRemoteUser: "สร้างแผนภูมิข้อมูลผู้ใช้ระยะไกล" enableChartsForFederatedInstances: "สร้างแผนภูมิข้อมูลอินสแตนซ์ระยะไกล" showClipButtonInNoteFooter: "เพิ่ม \"คลิป\" เพื่อบันทึกเมนูการทำงาน" -largeNoteReactions: "ขยายรีแอคชั่นการแสดงผล" noteIdOrUrl: "โน้ต ID หรือ URL" video: "วีดีโอ" videos: "วีดีโอ" @@ -1099,6 +1100,10 @@ iHaveReadXCarefullyAndAgree: "ฉันได้อ่านข้อควา dialog: "ไดอะล็อก" icon: "ไอคอน" forYou: "สำหรับคุณ" +replies: "ตอบกลับ" +renotes: "รีโน้ต" +loadReplies: "แสดงการตอบกลับ" +loadConversation: "แสดงบทสนทนา" _announcement: forExistingUsersDescription: "การประกาศนี้จะแสดงต่อผู้ใช้ที่มีอยู่ ณ จุดที่เผยแพร่นั้นๆถ้าหากเปิดใช้งาน ถ้าหากปิดใช้งานผู้ที่กำลังสมัครใหม่หลังจากโพสต์แล้วนั้นก็จะเห็นเช่นกัน" needConfirmationToReadDescription: "ข้อความแจ้งแยก ถ้าหากต้องการเพื่อยืนยันว่ากำลังทำเครื่องหมายประกาศนี้ว่าอ่านแล้วจะแสดงขึ้นถ้าหากเปิดใช้งาน การประกาศนั้นจะไม่รวมอยู่ในฟังก์ชั่นว่า \"ทำเครื่องหมายทั้งหมดว่าอ่านแล้ว\"" @@ -1123,6 +1128,8 @@ _initialAccountSetting: laterAreYouSure: "ต้องการตั้งค่าโปรไฟล์ในภายหลังจริงๆอย่างงั้นหรอ?" _serverRules: description: "ชุดของกฎที่จะแสดงก่อนการลงทะเบียนเราขอแนะนำให้ตั้งค่าสรุปข้อกำหนดในการให้บริการ" +_serverSettings: + iconUrl: "ไอคอน URL" _accountMigration: moveFrom: "ย้ายข้อมูลบัญชีอื่นไปยังอีกบัญชีนี้หนึ่ง" moveFromSub: "สร้างนามแฝงไปยังบัญชีอื่น" @@ -1377,6 +1384,8 @@ _achievements: title: "Brain Diver" description: "โพสต์ลิงก์ไปยัง Brain Diver" flavor: "Misskey-Misskey La-Tu-Ma" + _smashTestNotificationButton: + title: "ทดสอบโอเวอร์โฟลว์" _role: new: "บทบาทใหม่" edit: "แก้ไขบทบาท" @@ -1500,6 +1509,7 @@ _plugin: install: "ติดตั้งปลั๊กอิน" installWarn: "กรุณาอย่าติดตั้งปลั๊กอินที่ไม่น่าเชื่อถือนะคะ" manage: "จัดการปลั๊กอิน" + viewSource: "ดูต้นฉบับ" _preferencesBackups: list: "สร้างการสำรองข้อมูล" saveNew: "บันทึกใหม่" @@ -1687,17 +1697,16 @@ _timelineTutorial: _2fa: alreadyRegistered: "คุณได้ลงทะเบียนอุปกรณ์ยืนยันตัวตนแบบ 2 ชั้นแล้ว" registerTOTP: "ลงทะเบียนแอพตัวตรวจสอบสิทธิ์" - passwordToTOTP: "กรอกรหัสผ่าน" step1: "ขั้นตอนแรก ติดตั้งแอปยืนยันตัวตน (เช่น {a} หรือ {b}) บนอุปกรณ์ของคุณ" step2: "จากนั้นสแกนรหัส QR ที่แสดงบนหน้าจอนี้" step2Click: "การคลิกที่รหัส QR นี้จะช่วยให้คุณนั้นสามารถลงทะเบียน 2FA กับคีย์ความปลอดภัยหรือแอปตรวจสอบความถูกต้องของโทรศัพท์ได้" step3Title: "ป้อนรหัสยืนยัน" step3: "ป้อนโทเค็นที่แอปของคุณให้มาเพื่อเสร็จสิ้นการตั้งค่า" + setupCompleted: "ตั้งค่าสำเร็จแล้ว" step4: "นับจากนี้เป็นต้นไปการพยายามเข้าสู่ระบบในอนาคตนั้น อาจจะต้องขอโทเค็นในการเข้าสู่ระบบดังกล่าว" securityKeyNotSupported: "เบราว์เซอร์ของคุณไม่รองรับคีย์ความปลอดภัยนะ" registerTOTPBeforeKey: "กรุณาตั้งค่าแอปยืนยันตัวตนเพื่อลงทะเบียนรหัสความปลอดภัยหรือรหัสผ่าน" securityKeyInfo: "นอกจากนี้การตรวจสอบความถูกต้องด้วยลายนิ้วมือหรือ PIN แล้ว คุณยังสามารถตั้งค่าการตรวจสอบสิทธิ์ผ่านคีย์ความปลอดภัยของฮาร์ดแวร์ที่รองรับ FIDO2 เพื่อเพิ่มความปลอดภัยให้กับบัญชีของคุณ" - chromePasskeyNotSupported: "ขณะนี้ยังไม่รองรับรหัสผ่านของ Chrome" registerSecurityKey: "ลงทะเบียนรหัสความปลอดภัยหรือรหัสผ่าน" securityKeyName: "ป้อนชื่อคีย์" tapSecurityKey: "กรุณาทำตามเบราว์เซอร์ของคุณเพื่อลงทะเบียนรหัสความปลอดภัยหรือรหัสผ่าน" @@ -1708,6 +1717,7 @@ _2fa: renewTOTPConfirm: "วิธีการแบบนี้จะทําให้รหัสยืนยันจากแอพก่อนหน้าของคุณหยุดทํางานเลยนะ" renewTOTPOk: "ตั้งค่าคอนฟิกใหม่" renewTOTPCancel: "ไม่เป็นไร" + backupCodes: "รหัสสำรองข้อมูล" _permissions: "read:account": "ดูข้อมูลบัญชีของคุณ" "write:account": "แก้ไขข้อมูลบัญชีของคุณ" @@ -1741,6 +1751,10 @@ _permissions: "write:gallery": "แก้ไขแกลเลอรี่ของคุณ" "read:gallery-likes": "ดูรายการโพสต์ในแกลเลอรีที่ชอบของคุณ" "write:gallery-likes": "แก้ไขรายการโพสต์ในแกลเลอรีที่ชอบของคุณ" + "read:flash": "วิว เพลย์" + "write:flash": "แก้ไขเพลย์" + "read:flash-likes": "ดูรายชื่อของไลค์ เพลย์" + "write:flash-likes": "แก้ไขรายชื่อของไลค์ เพลย์" _auth: shareAccessTitle: "การให้สิทธิ์แอปพลิเคชัน" shareAccess: "คุณต้องการอนุญาตให้ \"{name}\" เข้าถึงบัญชีนี้เลยมั้ย?" @@ -1976,6 +1990,10 @@ _notification: unreadAntennaNote: "เสาอากาศ {name}" emptyPushNotificationMessage: "การแจ้งเตือนแบบพุชได้รับการอัพเดทแล้ว" achievementEarned: "รับความสำเร็จ" + testNotification: "ทดสอบการแจ้งเตือน" + checkNotificationBehavior: "ตรวจสอบลักษณะที่ปรากฏการแจ้งเตือน" + sendTestNotification: "ส่งทดสอบการแจ้งเตือน" + notificationWillBeDisplayedLikeThis: "การแจ้งเตือนมีลักษณะแบบนี้" _types: all: "ทั้งหมด" follow: "กำลังติดตาม" @@ -2011,6 +2029,8 @@ _deck: introduction2: "คลิกที่เครื่องหมาย + ทางขวาของหน้าจอเพื่อเพิ่มคอลัมน์ใหม่ทุกครั้งที่คุณต้องการ" widgetsIntroduction: "กรุณาเลือก \"แก้ไขวิดเจ็ต\" ในเมนูคอลัมน์และเพิ่มวิดเจ็ต" useSimpleUiForNonRootPages: "แสดง UI ของ Root Page อย่างง่าย " + usedAsMinWidthWhenFlexible: "ความกว้างขั้นต่ำนั้นจะถูกใช้งานสำหรับสิ่งนี้เมื่อเปิดใช้งานตัวเลือก \"ปรับความกว้างอัตโนมัติ\" หากเลือกเปิดใช้งานแล้ว" + flexible: "ปรับความกว้างอัตโนมัติ" _columns: main: "หลัก" widgets: "วิดเจ็ต" @@ -2045,3 +2065,6 @@ _webhookSettings: renote: "รีโน้ตแล้วเมื่อ" reaction: "เมื่อได้รับรีแอคชั่น" mention: "เมื่อกำลังถูกกล่าวถึง" +_moderationLogTypes: + suspend: "ถูกระงับ" + resetPassword: "รีเซ็ตรหัสผ่าน" diff --git a/locales/tr-TR.yml b/locales/tr-TR.yml index d0b610917..1111c2309 100644 --- a/locales/tr-TR.yml +++ b/locales/tr-TR.yml @@ -371,6 +371,8 @@ noRole: "Rol bulunamadı" color: "Renk" addMemo: "Kısa not ekle" icon: "Avatar" +replies: "yanıt" +renotes: "vazgeçme" _accountDelete: started: "Silme işlemi başlatıldı" _email: @@ -446,3 +448,6 @@ _deck: tl: "Zaman çizelgesi" list: "Listeler" mentions: "Bahsetmeler" +_moderationLogTypes: + suspend: "askıya al" + resetPassword: "Şifre sıfırlama" diff --git a/locales/uk-UA.yml b/locales/uk-UA.yml index a6c1c94e6..09b3eba74 100644 --- a/locales/uk-UA.yml +++ b/locales/uk-UA.yml @@ -338,7 +338,6 @@ invite: "Запросити" driveCapacityPerLocalAccount: "Об'єм диска на одного локального користувача" driveCapacityPerRemoteAccount: "Об'єм диска на одного віддаленого користувача" inMb: "В мегабайтах" -iconUrl: "URL аватара" bannerUrl: "URL банера" backgroundImageUrl: "URL-адреса фонового зображення" basicInfo: "Основна інформація" @@ -906,6 +905,8 @@ letsLookAtTimeline: "Перегляд історії" horizontal: "Збоку" youFollowing: "Підписки" icon: "Аватар" +replies: "Відповісти" +renotes: "Поширити" _achievements: earnedAt: "Відкрито" _types: @@ -1179,6 +1180,7 @@ _plugin: install: "Встановити плагін" installWarn: "Будь ласка, не встановлюйте плагінів, яким ви не довіряєте." manage: "Керування плагінами" + viewSource: "Переглянути вихідний код" _preferencesBackups: list: "Створені бекапи" saveNew: "Зберегти як новий" @@ -1618,3 +1620,6 @@ _deck: _webhookSettings: name: "Ім'я" active: "Увімкнено" +_moderationLogTypes: + suspend: "Призупинити" + resetPassword: "Скинути пароль" diff --git a/locales/uz-UZ.yml b/locales/uz-UZ.yml index 52577d2d8..726333958 100644 --- a/locales/uz-UZ.yml +++ b/locales/uz-UZ.yml @@ -355,7 +355,6 @@ invite: "Taklif qilish" driveCapacityPerLocalAccount: "Har bir mahalliy foydalanuvchi uchun disk maydoni" driveCapacityPerRemoteAccount: "Har bir masofaviy foydalanuvchi uchun disk maydoni" inMb: "Megabaytlarda" -iconUrl: "Ikonkaning URL manzili (masalan: favicon)" bannerUrl: "Banner URLi" backgroundImageUrl: "Fon rasmi URL manzili" basicInfo: "Asosiy ma'lumot" @@ -844,6 +843,8 @@ rolesAssignedToMe: "Mening rollarim" resetPasswordConfirm: "Qayta parol o'rnatmoqchimisiz?" sensitiveWords: "Ta'sirchan so'zlar" icon: "Avatar" +replies: "Javob berish" +renotes: "Qayta qayd etish" _achievements: _types: _viewInstanceChart: @@ -1083,3 +1084,6 @@ _webhookSettings: _events: renote: "Qayta qayd qilinganda" mention: "Eslanganda" +_moderationLogTypes: + suspend: "To'xtatish" + resetPassword: "Parolni tiklash" diff --git a/locales/vi-VN.yml b/locales/vi-VN.yml index 735723765..3b34e4711 100644 --- a/locales/vi-VN.yml +++ b/locales/vi-VN.yml @@ -1,5 +1,5 @@ --- -_lang_: "Tiếng Việt" +_lang_: "Tiếng Nhật" headlineMisskey: "Mạng xã hội liên hợp" introMisskey: "Xin chào! Misskey là một nền tảng tiểu blog phi tập trung mã nguồn mở.\nViết \"tút\" để chia sẻ những suy nghĩ của bạn 📡\nBằng \"biểu cảm\", bạn có thể bày tỏ nhanh chóng cảm xúc của bạn với các tút 👍\nHãy khám phá một thế giới mới! 🚀" poweredByMisskeyDescription: "{name} là một trong những chủ máy của Misskey là nền tảng mã nguồn mở" @@ -45,6 +45,7 @@ pin: "Ghim" unpin: "Bỏ ghim" copyContent: "Chép nội dung" copyLink: "Chép liên kết" +copyLinkRenote: "Sao chép liên kết ghi chú" delete: "Xóa" deleteAndEdit: "Sửa" deleteAndEditConfirm: "Bạn có chắc muốn sửa tút này? Những biểu cảm, lượt trả lời và đăng lại sẽ bị mất." @@ -156,6 +157,7 @@ addEmoji: "Thêm emoji" settingGuide: "Cài đặt đề xuất" cacheRemoteFiles: "Tập tin cache từ xa" cacheRemoteFilesDescription: "Khi tùy chọn này bị tắt, các tập tin từ xa sẽ được tải trực tiếp từ máy chủ khác. Điều này sẽ giúp giảm dung lượng lưu trữ nhưng lại tăng lưu lượng truy cập, vì hình thu nhỏ sẽ không được tạo." +youCanCleanRemoteFilesCache: "Bạn có thể xoá bộ nhớ đệm bằng cách nhấn vào nút🗑️ở trong phần quản lý tệp." cacheRemoteSensitiveFiles: "Lưu các tập tin nhạy cảm vào bộ nhớ tạm từ xa" cacheRemoteSensitiveFilesDescription: "Khi bạn tắt tính năng này, các tệp nhạy cảm sẽ được tải trực tiếp từ máy chủ và không được lưu vào bộ nhớ tạm" flagAsBot: "Đánh dấu đây là tài khoản bot" @@ -354,7 +356,6 @@ invite: "Mời" driveCapacityPerLocalAccount: "Dung lượng ổ đĩa tối đa cho mỗi người dùng" driveCapacityPerRemoteAccount: "Dung lượng ổ đĩa tối đa cho mỗi người dùng từ xa" inMb: "Tính bằng MB" -iconUrl: "URL Icon" bannerUrl: "URL Ảnh bìa" backgroundImageUrl: "URL Ảnh nền" basicInfo: "Thông tin cơ bản" @@ -410,10 +411,13 @@ aboutMisskey: "Về Misskey" administrator: "Quản trị viên" token: "Token" 2fa: "Xác thực 2 yếu tố" +setupOf2fa: "Thiết lập xác thực 2 yếu tố" totp: "Ứng dụng xác thực" totpDescription: "Nhắn mã OTP bằng ứng dụng xác thực" moderator: "Kiểm duyệt viên" moderation: "Kiểm duyệt" +moderationNote: "Ghi chú kiểm duyệt" +addModerationNote: "Thêm ghi chú kiểm duyệt" nUsersMentioned: "Dùng bởi {n} người" securityKeyAndPasskey: "Mã bảo mật・Passkey" securityKey: "Khóa bảo mật" @@ -989,9 +993,95 @@ copyErrorInfo: "Sao chép thông tin lỗi" joinThisServer: "Đăng ký trên chủ máy này" exploreOtherServers: "Tìm chủ máy khác" letsLookAtTimeline: "Thử xem Timeline" +emailNotSupported: "Máy chủ này không hỗ trợ gửi email" +postToTheChannel: "Đăng lên kênh" +cannotBeChangedLater: "Không thể thay đổi sau này." +rolesAssignedToMe: "Vai trò được giao cho tôi" +resetPasswordConfirm: "Bạn thực sự muốn đặt lại mật khẩu?" +sensitiveWords: "Các từ nhạy cảm" +license: "Giấy phép" +unfavoriteConfirm: "Bạn thực sự muốn xoá khỏi mục yêu thích?" +retryAllQueuesConfirmText: "Điều này sẽ tạm thời làm tăng mức độ tải của máy chủ." +enableChartsForRemoteUser: "Tạo biểu đồ người dùng từ xa" +video: "Video" +videos: "Các video" +dataSaver: "Tiết kiệm dung lượng" +accountMigration: "Chuyển tài khoản" +accountMoved: "Người dùng này đã chuyển sang một tài khoản mới:" +accountMovedShort: "Tài khoản này đã được chuyển" +operationForbidden: "Thao tác này không thể thực hiện" +forceShowAds: "Luôn hiện quảng cáo" +notificationDisplay: "Thông báo" +leftTop: "Phía trên bên tráí" +rightTop: "Phía trên bên phải" +leftBottom: "Phía dưới bên trái" +rightBottom: "Phía dưới bên phải" +stackAxis: "Hướng chồng" +vertical: "Dọc" horizontal: "Thanh bên" +position: "Vị trí" +serverRules: "Luật của máy chủ" youFollowing: "Đang theo dõi" +later: "Để sau" +goToMisskey: "Tới Misskey" +installed: "Đã tải xuống" +branding: "Thương hiệu" +turnOffToImprovePerformance: "Tắt mục này có thể cải thiện hiệu năng." +expirationDate: "Ngày hết hạn" +noExpirationDate: "Vô thời hạn" +waitingForMailAuth: "Đang chờ xác nhận email" +unused: "Chưa được sử dụng" +used: "Đã được sử dụng" +expired: "Đã hết hạn" +doYouAgree: "Đồng ý?" +iHaveReadXCarefullyAndAgree: "Tôi đã đọc và đồng ý với \"x\"." +dialog: "Hộp thoại" icon: "Ảnh đại diện" +forYou: "Dành cho bạn" +currentAnnouncements: "Thông báo hiện tại" +pastAnnouncements: "Thông báo trước đó" +youHaveUnreadAnnouncements: "Có thông báo chưa đọc." +replies: "Trả lời" +renotes: "Đăng lại" +loadReplies: "Hiển thị các trả lời" +pinnedList: "Các mục đã được ghim" +keepScreenOn: "Giữ màn hình luôn bật" +verifiedLink: "Chúng tôi đã xác nhận bạn là chủ sở hữu của đường dẫn này" +_announcement: + forExistingUsers: "Chỉ những người dùng đã tồn tại" + forExistingUsersDescription: "Nếu được bật, thông báo này sẽ chỉ hiển thị với những người dùng đã tồn tại vào lúc thông báo được tạo. Nếu tắt đi, những tài khoản mới đăng ký sau khi thông báo được đăng lên cũng sẽ thấy nó." + end: "Lưu trữ thông báo" + tooManyActiveAnnouncementDescription: "Có quá nhiều thông báo sẽ làm trải nghiệm của người dùng tệ đi. Vui lòng lưu trữ những thông báo đã hết hiệu lực." + readConfirmTitle: "Đánh dấu là đã đọc?" + readConfirmText: "Điều này sẽ đánh dấu nội dung của \"{title}\" là đã đọc." +_initialAccountSetting: + accountCreated: "Tài khoản của bạn đã được tạo thành công!" + letsStartAccountSetup: "Để bắt đầu, hãy cùng thiết lập tài khoản nhé." + letsFillYourProfile: "Đầu tiên, hãy thiết lập hồ sơ của bạn." + profileSetting: "Thiết lập hồ sơ" + privacySetting: "Cài đặt quyền riêng tư" + theseSettingsCanEditLater: "Bạn vẫn có thể thay đổi những cài đặt này." + youCanEditMoreSettingsInSettingsPageLater: "Còn rất nhiều những cài đặt khác bạn có thể thay đổi ở trang \"Cài đặt\". Hãy nhớ ghé thăm trong lần sau nhé." + followUsers: "Thử theo dõi một vài người mà bạn có thể thích để xây dựng dòng thời gian của mình." + pushNotificationDescription: "Bật thông báo đẩy sẽ cho phép bạn nhận thông báo từ {name} trực tiếp từ thiết bị của bạn." + initialAccountSettingCompleted: "Thiết lập tài khoản thành công!" + haveFun: "Hãy tận hưởng {name} nhé!" + ifYouNeedLearnMore: "Nếu bạn muốn tìm hiểu thêm về cách sử dụng {name} (Misskey), hãy vào {link}." + skipAreYouSure: "Bạn thực sự muốn bỏ qua mục thiết lập tài khoản?" + laterAreYouSure: "Bạn thực sự muốn thiết lập tài khoản vào lúc khác?" +_serverSettings: + iconUrl: "Biểu tượng URL" + appIconResolutionMustBe: "Độ phân giải tối thiểu là {resolution}." + manifestJsonOverride: "Ghi đè manifest.json" +_accountMigration: + moveFrom: "Chuyển một tài khoản khác vào tài khoản này" + moveFromLabel: "Tài khoản gốc #{n}" + moveTo: "Chuyển tài khoản này vào một tài khoản khác" + moveCannotBeUndone: "Việc chuyển tài khoản không thể huỷ." + moveAccountDescription: "Điều này sẽ chuyển tài khoản này sang một tài khoản khác.\n ・Những người theo dõi sẽ tự động được chuyển sang tài khoản mới\n ・Tài khoản này sẽ tự bỏ theo dõi những người mà bạn đã theo dõi trước đây\n ・Bạn sẽ không thể đăng tút mới, v.v trên tài khoản này\n\nDù việc chuyển người theo dõi được diễn ra tự động, bạn vẫn phải tự chuẩn bị một vài bước để chuyển danh sách những người dùng bạn đang theo dõi. Để làm vậy, vui lòng thực hiện việc xuất dữ liệu những người dùng đã theo dõi mà sau này bạn sẽ dùng để nhập vào tài khoản mới ở menu Cài đặt. Hành động tương tự áp dụng với danh sách những người dùng bị chặn hoặc tắt tiếng.\n\n(Điều này áp dụng cho phiên bản Misskey v13.12.0 và sau này. Các phần mềm ActivityPub khác , ví dụ như Mastodon, sẽ có thể hoạt động khác đi.)" + startMigration: "Chuyển" + movedAndCannotBeUndone: "\nTài khoản này đã được chuyển đi.\nViệc di chuyển tài khoản không thể bị huỷ bỏ." + movedTo: "Tài khoản mới:" _achievements: earnedAt: "Ngày thu nhận" _types: @@ -1030,6 +1120,8 @@ _achievements: title: "Hàng tinh đăng bài" description: "Đã đăng bài 50,000 lần rồi" _notes100000: + title: "ALL YOUR NOTE ARE BELONG TO US" + description: "Đăng 100,000 tút" flavor: "Liệu viết bài gì tầm này vậy? " _login3: title: "Sơ cấp I" @@ -1061,6 +1153,15 @@ _achievements: _login400: title: "Khách hàng thường xuyên cấp III" description: "Tổng số ngày đăng nhập đạt 400 ngày" + _login1000: + flavor: "Cảm ơn bạn đã sử dụng Misskey!" + _noteFavorited1: + title: "Nhà thiên văn học" + _myNoteFavorited1: + title: "Đi tìm những ngôi sao" + _profileFilled: + title: "Luôn sẵn sàng" + description: "Thiết lập tài khoản của bạn" _markedAsCat: title: "Tôi là một con mèo" description: "Bật chế độ mèo" @@ -1086,8 +1187,18 @@ _achievements: _followers10: title: "FOLLOW ME!!" description: "Người theo dõi bạn vượt lên 10 người" + _followers50: + title: "Từng chút một" + description: "Đạt được 50 lượt theo dõi" + _followers100: + title: "Người nổi tiếng" + description: "Đạt được 100 lượt theo dõi" + _followers300: + title: "Vui lòng xếp thành hàng nào" + description: "Đạt được 300 lượt theo dõi" _followers500: title: "Trạm phát sóng" + description: "Đạt được 500 lượt theo dõi" _followers1000: title: "Người có tầm ảnh hưởng" description: "Người theo dõi bạn vượt lên 1000 người" @@ -1106,11 +1217,15 @@ _achievements: description: "Tìm thấy được những kho báu cất giấu" _client30min: title: "Giải lao xỉu" + description: "Giữ Misskey mở trong ít nhất 30 phút" + _client60min: + description: "Giữ Misskey mở trong ít nhất 60 phút" _noteDeletedWithin1min: title: "Xem như không có gì đâu nha" _postedAtLateNight: title: "Loài ăn đêm" description: "Đăng bài trong đêm khuya " + flavor: "Đến giờ đi ngủ rồi." _postedAt0min0sec: title: "Tín hiệu báo giờ" description: "Đăng bài vào 0 phút 0 giây" @@ -1141,6 +1256,8 @@ _achievements: _setNameToSyuilo: title: "Ngưỡng mộ với vị thần" description: "Đạt tên là syuilo" + _passedSinceAccountCreated1: + title: "Kỷ niệm một năm" _loggedInOnBirthday: title: "Sinh nhật vủi vẻ" description: "Đăng nhập vào ngày sinh" @@ -1226,6 +1343,7 @@ _plugin: install: "Cài đặt tiện ích" installWarn: "Vui lòng không cài đặt những tiện ích đáng ngờ." manage: "Quản lý plugin" + viewSource: "Xem mã nguồn" _preferencesBackups: list: "Tạo sao lưu" saveNew: "Lưu bản sao lưu" @@ -1400,7 +1518,6 @@ _timelineTutorial: _2fa: alreadyRegistered: "Bạn đã đăng ký thiết bị xác minh 2 bước." registerTOTP: "Đăng ký ứng dụng xác thực" - passwordToTOTP: "Nhắn mật mã" step1: "Trước tiên, hãy cài đặt một ứng dụng xác minh (chẳng hạn như {a} hoặc {b}) trên thiết bị của bạn." step2: "Sau đó, quét mã QR hiển thị trên màn hình này." step2Click: "Quét mã QR trên ứng dụng xác thực (Authy, Google authenticator, v.v.)" @@ -1410,7 +1527,6 @@ _2fa: securityKeyNotSupported: "Trình duyệt của bạn không hỗ trợ khóa bảo mật" registerTOTPBeforeKey: "Vui lòng thiết lập một ứng dụng xác thực để đăng ký khóa bảo mật hoặc mật khẩu." securityKeyInfo: "Bên cạnh xác minh bằng vân tay hoặc mã PIN, bạn cũng có thể thiết lập xác minh thông qua khóa bảo mật phần cứng hỗ trợ FIDO2 để bảo mật hơn nữa cho tài khoản của mình." - chromePasskeyNotSupported: "Mật khẩu Chrome hiện không được hỗ trợ." registerSecurityKey: "Tạo khóa bảo mật hoặc mã bảo mật" securityKeyName: "Nhập tên khóa bảo mật" tapSecurityKey: "Vui lòng làm theo hướng dẫn của trình duyệt để đăng ký mã bảo mật hoặc mã khóa" @@ -1744,3 +1860,6 @@ _webhookSettings: _events: reaction: "Khi nhận được sự kiện" mention: "Khi có người nhắc tới bạn" +_moderationLogTypes: + suspend: "Vô hiệu hóa" + resetPassword: "Đặt lại mật khẩu" diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index 939449cef..27f95eb37 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -163,7 +163,7 @@ cacheRemoteSensitiveFilesDescription: "如果禁用这项设定,远程服务 flagAsBot: "这是一个机器人账号" flagAsBotDescription: "如果此账户由程序控制,请启用此项。启用后,此标志可以帮助其他开发人员防止机器人之间产生无限互动的行为,并让 Misskey 的内部系统将此账户识别为机器人。" flagAsCat: "喵!!!!!!!!!!!!" -flagAsCatDescription: "如果您想表明此帐户是一只猫,请打开此标志。\n开启后,会在您的头像上出现猫耳朵,并将你的帖子中的「na」替换为「nya」,日文同理。" +flagAsCatDescription: "喵喵喵??" flagShowTimelineReplies: "在时间线上显示帖子的回复" flagShowTimelineRepliesDescription: "启用时,时间线除了显示用户的帖子外,还会显示其他用户对帖子的回复。" autoAcceptFollowed: "自动允许来自我关注的用户对我的关注请求" @@ -356,7 +356,6 @@ invite: "邀请" driveCapacityPerLocalAccount: "每个用户的网盘容量" driveCapacityPerRemoteAccount: "每个远程用户的网盘容量" inMb: "以兆字节(MegaByte)为单位" -iconUrl: "图标 URL" bannerUrl: "横幅 URL" backgroundImageUrl: "背景图 URL" basicInfo: "基本信息" @@ -417,6 +416,9 @@ totp: "身份验证应用" totpDescription: "使用认证应用输入一次性密码。" moderator: "监察员" moderation: "管理" +moderationNote: "管理笔记" +addModerationNote: "添加管理笔记" +moderationLogs: "管理日志" nUsersMentioned: "{n} 被提到" securityKeyAndPasskey: "安全密钥或 Passkey" securityKey: "安全密钥" @@ -709,6 +711,7 @@ lockedAccountInfo: "即使启用该功能,只要您不将帖子可见范围设 alwaysMarkSensitive: "默认将媒体文件标记为敏感内容" loadRawImages: "添加附件图像的缩略图时使用原始图像质量" disableShowingAnimatedImages: "不播放动画" +highlightSensitiveMedia: "高亮显示敏感媒体" verificationEmailSent: "已发送确认电子邮件。请访问电子邮件中的链接以完成设置。" notSet: "未设置" emailVerified: "电子邮件地址已验证" @@ -1023,7 +1026,7 @@ retryAllQueuesConfirmText: "可能会使服务器负荷在一定时间内增加" enableChartsForRemoteUser: "生成远程用户的图表" enableChartsForFederatedInstances: "生成远程服务器的图表" showClipButtonInNoteFooter: "在贴文下方显示便签按钮" -largeNoteReactions: "使用大图标来显示回应" +reactionsDisplaySize: "回应显示大小" noteIdOrUrl: "帖子 ID 或 URL" video: "视频" videos: "视频" @@ -1105,6 +1108,18 @@ forYou: "您的" currentAnnouncements: "现在的公告" pastAnnouncements: "过去的公告" youHaveUnreadAnnouncements: "您有未读的公告" +useSecurityKey: "请根据浏览器或设备的提示,使用安全密钥或通行密钥。" +replies: "回复" +renotes: "转发" +loadReplies: "查看回复" +loadConversation: "查看对话" +pinnedList: "已置顶的列表" +keepScreenOn: "保持设备屏幕开启" +verifiedLink: "已验证的链接" +notifyNotes: "打开发帖通知" +unnotifyNotes: "关闭发帖通知" +authentication: "验证" +authenticationRequiredToContinue: "要继续,请先进行验证" _announcement: forExistingUsers: "仅限现有用户" forExistingUsersDescription: "若启用,该公告将仅对创建此公告时存在的用户可见。 如果禁用,则在创建此公告后注册的用户也可以看到该公告。" @@ -1131,6 +1146,15 @@ _initialAccountSetting: laterAreYouSure: "要稍后再进行初始设定吗?" _serverRules: description: "在新用户注册前显示服务器的简单规则。推荐显示服务条款的主要内容。" +_serverSettings: + iconUrl: "图标 URL" + appIconDescription: "指定当 {host} 显示为 app 时的图标。" + appIconUsageExample: "例如:作为书签添加到 PWA 或手机主屏幕的时候" + appIconStyleRecommendation: "因为有可能会被裁切为圆形或者圆角矩形,建议使用边缘带有留白背景的图标。" + appIconResolutionMustBe: "分辨率必须为 {resolution}。" + manifestJsonOverride: "覆盖 mainfest.json" + shortName: "简称" + shortNameDescription: "如果服务器的正式名称很长,可以用简称或者別名来替代。" _accountMigration: moveFrom: "从别的账号迁移到此账户" moveFromSub: "为另一个账户建立别名" @@ -1385,6 +1409,9 @@ _achievements: title: "Brain Diver" description: "发布了包含 Brain Diver 链接的帖子" flavor: "Misskey-Misskey La-Tu-Ma" + _smashTestNotificationButton: + title: "过度测试" + description: "短时间内连续测试通知" _role: new: "创建角色" edit: "编辑角色" @@ -1508,6 +1535,7 @@ _plugin: install: "安装插件" installWarn: "请不要安装不可信的插件。" manage: "管理插件..." + viewSource: "查看源代码" _preferencesBackups: list: "已创建的备份" saveNew: "另存为" @@ -1695,7 +1723,6 @@ _timelineTutorial: _2fa: alreadyRegistered: "此设备已被注册" registerTOTP: "开始设置认证应用" - passwordToTOTP: "请输入您的密码" step1: "首先,在您的设备上安装验证应用,例如 {a} 或 {b}。" step2: "然后,扫描屏幕上显示的二维码。" step2Click: "通过点击二维码,您可以使用设备上安装的身份验证器应用程序或密钥环进行注册" @@ -1707,7 +1734,6 @@ _2fa: securityKeyNotSupported: "您的浏览器不支持安全密钥。" registerTOTPBeforeKey: "要注册安全密钥或 Passkey,请先设置验证器应用程序。" securityKeyInfo: "注册兼容 WebAuthn 的密钥,例如支持 FIDO2 的硬件安全密钥、设备上的生物识别功能、PIN 码以及 Passkey 等。" - chromePasskeyNotSupported: "目前不支持 Chrome 的 Passkey。" registerSecurityKey: "注册安全密钥或 Passkey" securityKeyName: "输入密钥名称" tapSecurityKey: "请按照浏览器说明操作来注册安全密钥或 Passkey。" @@ -1775,6 +1801,7 @@ _antennaSources: homeTimeline: "已关注用户的帖子" users: "来自指定用户的帖子" userList: "来自指定列表中的帖子" + userBlacklist: "除掉已选择用户后所有的帖子" _weekday: sunday: "星期日" monday: "星期一" @@ -1874,6 +1901,7 @@ _profile: metadataContent: "内容" changeAvatar: "修改头像" changeBanner: "修改横幅" + verifiedLinkDescription: "如果将内容设置为 URL,当链接所指向的网页内包含自己的个人资料链接时,可以显示一个已验证图标。" _exportOrImport: allNotes: "所有帖子" favoritedNotes: "收藏的帖子" @@ -1992,11 +2020,17 @@ _notification: youReceivedFollowRequest: "您有新的关注请求" yourFollowRequestAccepted: "您的关注请求已通过" pollEnded: "问卷调查结果已生成。" + newNote: "新的帖子" unreadAntennaNote: "天线 {name}" emptyPushNotificationMessage: "推送通知已更新" achievementEarned: "获得成就" + testNotification: "测试通知" + checkNotificationBehavior: "检查通知显示" + sendTestNotification: "发送测试通知" + notificationWillBeDisplayedLikeThis: "通知将会这样表示" _types: all: "全部" + note: "用户的新帖子" follow: "关注中" mention: "提及" reply: "回复" @@ -2066,3 +2100,25 @@ _webhookSettings: renote: "被转发时" reaction: "被回应时" mention: "被提及时" +_moderationLogTypes: + updateRole: "更新角色" + assignRole: "分配角色" + unassignRole: "取消分配角色" + suspend: "冻结" + unsuspend: "解除冻结" + addCustomEmoji: "添加自定义表情符号" + updateCustomEmoji: "更新自定义表情符号" + deleteCustomEmoji: "删除自定义表情符号" + updateServerSettings: "更新服务器设置" + updateUserNote: "更新管理笔记" + deleteDriveFile: "删除文件" + deleteNote: "删除帖子" + createGlobalAnnouncement: "创建全体通知" + createUserAnnouncement: "创建用户通知" + updateGlobalAnnouncement: "更新全体通知" + updateUserAnnouncement: "更新用户通知" + deleteGlobalAnnouncement: "删除全体通知" + deleteUserAnnouncement: "删除用户通知" + resetPassword: "重置密码" + markSensitiveDriveFile: "标记网盘文件为敏感媒体" + unmarkSensitiveDriveFile: "取消标记网盘文件为敏感媒体" diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml index 528a3ea63..7cea24409 100644 --- a/locales/zh-TW.yml +++ b/locales/zh-TW.yml @@ -1,6 +1,6 @@ --- -_lang_: "繁體中文" -headlineMisskey: "貼文連繫網絡" +_lang_: "繁體中文(台灣)" +headlineMisskey: "貼文連繫網路" introMisskey: "歡迎!Misskey 是一個開放原始碼且去中心化的社群網路服務。\n發布「貼文」向身邊的人分享您的想法!📡\n利用「反應」表達您對貼文的感覺!👍\n讓我們一起探索新的世界吧!🚀" poweredByMisskeyDescription: "{name}是開放原始碼平臺 Misskey 的伺服器之一。" monthAndDay: "{month} 月 {day} 日" @@ -15,7 +15,7 @@ gotIt: "知道了" cancel: "取消" noThankYou: "現在不要" enterUsername: "輸入使用者名稱" -renotedBy: "{user} 轉發了" +renotedBy: "{user} 轉發" noNotes: "無貼文" noNotifications: "沒有通知" instance: "伺服器" @@ -45,6 +45,7 @@ pin: "置頂" unpin: "取消置頂" copyContent: "複製內容" copyLink: "複製連結" +copyLinkRenote: "複製轉發的連結" delete: "刪除" deleteAndEdit: "刪除並編輯" deleteAndEditConfirm: "要刪除並再次編輯嗎?此貼文的所有反應、轉發和回覆也將會消失。" @@ -106,7 +107,7 @@ followRequestPending: "追隨許可待批准" enterEmoji: "輸入表情符號" renote: "轉發" unrenote: "取消轉發" -renoted: "轉發成功" +renoted: "轉發成功。" cantRenote: "無法轉發此貼文。" cantReRenote: "無法轉發之前已經轉發過的內容。" quote: "引用" @@ -137,8 +138,8 @@ suspend: "凍結" unsuspend: "解除凍結" blockConfirm: "確定要封鎖此使用者嗎?" unblockConfirm: "確定要解除封鎖此使用者嗎?" -suspendConfirm: "確定凍結此帳戶?" -unsuspendConfirm: "確定解凍此帳戶?" +suspendConfirm: "確定凍結此使用者?" +unsuspendConfirm: "確定解凍此使用者?" selectList: "選擇清單" editList: "編輯清單" selectChannel: "選擇頻道" @@ -151,12 +152,12 @@ customEmojis: "自訂表情符號" emoji: "表情符號" emojis: "表情符號" emojiName: "表情符號名稱" -emojiUrl: "表情符號URL" +emojiUrl: "表情符號 URL" addEmoji: "新增表情符號" settingGuide: "推薦設定" cacheRemoteFiles: "快取遠端檔案" -cacheRemoteFilesDescription: "禁用此設定會停止建立遠端檔案快取,從而節省伺服器儲存空間,但會因從遠端讀取資料而增加網路數據用量。" -youCanCleanRemoteFilesCache: "按檔案管理的🗑️按鈕,將快取全部刪除。" +cacheRemoteFilesDescription: "啟用此設定後,遠端檔案會被快取在本伺服器的儲存空間中。雖然顯示圖片會變快,但會消耗較多伺服器的儲存空間。至於要快取遠端使用者到什麼程度,是依照角色的雲端硬碟容量而定。當超過這個限制時,從較舊的檔案開始自快取中刪除並改為連結。關閉這個設定時,遠端檔案從一開始就維持連結的方式,但為了產生圖片的縮圖並保護使用者的隱私,建議將 default.yml 的 proxyRemoteFiles 設為 true。" +youCanCleanRemoteFilesCache: "按檔案管理的🗑️按鈕,可將快取全部刪除。" cacheRemoteSensitiveFiles: "快取遠端的敏感檔案" cacheRemoteSensitiveFilesDescription: "若停用這個設定,則不會快取遠端的敏感檔案,而是直接連結。" flagAsBot: "此使用者是機器人" @@ -320,7 +321,7 @@ copyUrl: "複製URL" rename: "重新命名" avatar: "大頭貼" banner: "橫幅" -displayOfSensitiveMedia: "顯示敏感媒體" +displayOfSensitiveMedia: "敏感檔案的顯示" whenServerDisconnected: "與伺服器的連接中斷時" disconnectedFromServer: "與伺服器中斷連線" reload: "重新整理" @@ -355,7 +356,6 @@ invite: "邀請" driveCapacityPerLocalAccount: "每個本地使用者的雲端硬碟容量" driveCapacityPerRemoteAccount: "每個非本地用戶的雲端空間大小" inMb: "以Mbps為單位" -iconUrl: "圖標 URL(例如 favicon)" bannerUrl: "橫幅圖片URL" backgroundImageUrl: "背景圖片的來源網址 " basicInfo: "基本資訊" @@ -416,12 +416,15 @@ totp: "驗證應用程式" totpDescription: "以驗證應用程式輸入一次性密碼" moderator: "審查員" moderation: "審查" -nUsersMentioned: "被提及到 {n} 次" +moderationNote: "管理筆記" +addModerationNote: "新增管理筆記" +moderationLogs: "管理日誌" +nUsersMentioned: "被 {n} 個人提及" securityKeyAndPasskey: "安全金鑰、Passkey" securityKey: "安全金鑰" lastUsed: "上次使用" lastUsedAt: "上次使用:{t}" -unregister: "註銷帳戶" +unregister: "註銷" passwordLessLogin: "設置無密碼登入" passwordLessLoginDescription: "不使用密碼,以安全金鑰或 Passkey 登入" resetPassword: "重設密碼" @@ -488,7 +491,7 @@ createAccount: "建立帳戶" existingAccount: "現有帳戶" regenerate: "再次生成" fontSize: "字體大小" -mediaListWithOneImageAppearance: "只有一張圖片時的媒體列表高度" +mediaListWithOneImageAppearance: "只有一張圖片時的檔案列表高度" limitTo: "上限為 {x}" noFollowRequests: "沒有追隨您的請求" openImageInNewTab: "於新分頁中開啟圖片" @@ -506,8 +509,8 @@ promote: "推廣" numberOfDays: "有效天數" hideThisNote: "隱藏此貼文" showFeaturedNotesInTimeline: "在時間軸上顯示熱門推薦" -objectStorage: "對象存儲" -useObjectStorage: "使用對象存儲" +objectStorage: "物件儲存" +useObjectStorage: "使用物件儲存" objectStorageBaseUrl: "Base URL" objectStorageBaseUrlDesc: "用於引用的 URL。如果您使用的是 CDN 或反向代理,請指定其 URL,例如 S3(https://.s3.amazonaws.com)、GCS(https://storage.googleapis.com/)。" objectStorageBucket: "儲存空間(Bucket)" @@ -544,7 +547,7 @@ recentUsed: "最近使用" install: "安裝" uninstall: "解除安裝" installedApps: "已授權的應用程式" -nothing: "無" +nothing: "查無項目" installedDate: "安裝時間" lastUsedDate: "最後上線日期" state: "狀態" @@ -655,6 +658,7 @@ behavior: "行為" sample: "範例" abuseReports: "檢舉" reportAbuse: "檢舉" +reportAbuseRenote: "檢舉轉發貼文" reportAbuseOf: "檢舉{name}" fillAbuseReportDescription: "請填寫檢舉的詳細理由。如有需要,請附上相關 URL。" abuseReported: "檢舉完成。感謝您的報告。" @@ -704,9 +708,10 @@ driveUsage: "雲端硬碟使用量" noCrawle: "拒絕搜尋引擎索引" noCrawleDescription: "要求網路搜尋引擎不要索引你的個人資料頁、貼文及頁面等。" lockedAccountInfo: "即使你通過了追隨者請求,除非你將貼文的可見性設定為 「追隨者」,否則任何人都能看見你的貼文。" -alwaysMarkSensitive: "預設將多媒體標記為敏感內容" +alwaysMarkSensitive: "預設標記檔案為敏感內容" loadRawImages: "以原始圖檔顯示附件圖檔的縮圖" disableShowingAnimatedImages: "不播放動態圖檔" +highlightSensitiveMedia: "強調敏感標記" verificationEmailSent: "已發送驗證電子郵件。請點擊進入電子郵件中的鏈接完成驗證。" notSet: "未設定" emailVerified: "已成功驗證您的電郵" @@ -923,7 +928,7 @@ type: "類型" speed: "速度" slow: "慢" fast: "快" -sensitiveMediaDetection: "敏感性媒體的檢測" +sensitiveMediaDetection: "敏感檔案的檢測" localOnly: "僅限本地" remoteOnly: "僅限遠端" failedToUpload: "上傳失敗" @@ -932,7 +937,7 @@ cannotUploadBecauseNoFreeSpace: "由於雲端硬碟沒有可用空間,因此 cannotUploadBecauseExceedsFileSizeLimit: "由於超過了檔案大小的限制,無法上傳。" beta: "測試版" enableAutoSensitive: "自動 NSFW 判定" -enableAutoSensitiveDescription: "如果可用,它將使用機器學習技術判斷多媒體內容是否需要標記 NSFW。即使關閉此功能,也可能會依實例規則而自動啟用。" +enableAutoSensitiveDescription: "如果可用,它將使用機器學習技術判斷檔案是否需要標記為敏感。即使關閉此功能,也可能會依實例規則而自動啟用。" activeEmailValidationDescription: "積極驗證使用者的電郵地址,以判斷它是否可以通訊。關閉此選項代表只會檢查地址是否符合格式。" navbar: "導覽列" shuffle: "隨機" @@ -1021,7 +1026,7 @@ retryAllQueuesConfirmText: "伺服器的負荷可能會暫時增加。" enableChartsForRemoteUser: "生成遠端使用者的圖表" enableChartsForFederatedInstances: "生成遠端伺服器的圖表" showClipButtonInNoteFooter: "新增摘錄至貼文" -largeNoteReactions: "放大顯示貼文反應" +reactionsDisplaySize: "表情回應的顯示尺寸" noteIdOrUrl: "貼文ID或URL" video: "影片" videos: "影片" @@ -1103,6 +1108,19 @@ forYou: "給您" currentAnnouncements: "最新公告" pastAnnouncements: "歷史公告" youHaveUnreadAnnouncements: "有未讀的公告。" +useSecurityKey: "請按照瀏覽器或設備上的說明使用安全金鑰或 Passkey。" +replies: "回覆" +renotes: "轉發" +loadReplies: "閱覽回覆" +loadConversation: "閱覽對話" +pinnedList: "已置頂的清單" +keepScreenOn: "保持設備螢幕開啟" +verifiedLink: "已驗證連結" +notifyNotes: "開啟貼文通知" +unnotifyNotes: "關閉貼文通知" +authentication: "驗證" +authenticationRequiredToContinue: "請於繼續前完成驗證" +dateAndTime: "日期與時間" _announcement: forExistingUsers: "僅限既有的使用者" forExistingUsersDescription: "啟用代表僅向現存使用者顯示;停用代表張貼後註冊的新使用者也會看到。" @@ -1129,6 +1147,15 @@ _initialAccountSetting: laterAreYouSure: "稍後再重新進行初始設定嗎?" _serverRules: description: "設定在註冊頁面顯示的伺服器簡要規則。建議是服務條款的摘要。" +_serverSettings: + iconUrl: "圖示的 URL" + appIconDescription: "指定顯示 {host} 為應用程式時的圖示。" + appIconUsageExample: "例如:漸進式網路應用程式(PWA)、於手機桌面新增書籤" + appIconStyleRecommendation: "因為可能會裁剪成圓形或圓角,所以建議用單色填滿邊框及背景。" + appIconResolutionMustBe: "解析度必須為 {resolution}。" + manifestJsonOverride: "覆寫 manifest.json" + shortName: "簡稱" + shortNameDescription: "如果伺服器的正式名稱很長,可用簡稱或通稱代替。" _accountMigration: moveFrom: "從其他帳戶遷移到這個帳戶" moveFromSub: "為另一個帳戶建立別名" @@ -1383,6 +1410,9 @@ _achievements: title: "Brain Driver" description: "發佈一篇含歌曲《Brain Driver》連結的貼文" flavor: "Misskey-Misskey La-Tu-Ma" + _smashTestNotificationButton: + title: "過度測試" + description: "極短時間內連續測試通知" _role: new: "建立角色" edit: "編輯角色" @@ -1455,7 +1485,7 @@ _role: or: "~或~" not: "~否" _sensitiveMediaDetection: - description: "您可以使用機器學習自動檢測敏感媒體並將其用於審查。 伺服器的負荷會稍微增加。" + description: "您可以使用機器學習自動檢測敏感檔案以便審查。這會稍微增加伺服器負荷。" sensitivity: "檢測敏感度" sensitivityDescription: "敏感度低時,誤檢測(偽陽性)會減少。敏感度高時,漏檢(偽陰性)會減少。" setSensitiveFlagAutomatically: "設定 NSFW 標籤" @@ -1506,6 +1536,7 @@ _plugin: install: "安裝外掛組件" installWarn: "請不要安裝來源不明的外掛。" manage: "管理外掛" + viewSource: "檢視原始碼" _preferencesBackups: list: "已備份的設定檔" saveNew: "另存新檔" @@ -1540,9 +1571,9 @@ _aboutMisskey: morePatrons: "還有許許多多幫助我們的其他人,非常感謝你們。 🥰" patrons: "贊助者" _displayOfSensitiveMedia: - respect: "隱藏被標記為敏感的多媒體內容" - ignore: "不隱藏被標記為敏感的多媒體內容" - force: "隱藏所有多媒體內容" + respect: "隱藏敏感檔案" + ignore: "顯示敏感檔案" + force: "隱藏所有檔案" _instanceTicker: none: "隱藏" remote: "向遠端使用者顯示" @@ -1668,7 +1699,7 @@ _ago: future: "未來" justNow: "剛剛" secondsAgo: "{n} 秒前" - minutesAgo: "{n}分鐘前 " + minutesAgo: "{n} 分鐘前 " hoursAgo: "{n} 小時前" daysAgo: "{n} 天前" weeksAgo: "{n} 週前" @@ -1693,7 +1724,6 @@ _timelineTutorial: _2fa: alreadyRegistered: "此裝置已被註冊過了" registerTOTP: "開始設定驗證應用程式" - passwordToTOTP: "請輸入密碼" step1: "首先,在您的裝置上安裝驗證程式,例如 {a} 或 {b}。" step2: "然後,掃描螢幕上的 QR 碼。" step2Click: "您可以點擊 QR 碼,以使用裝置上的驗證應用程式或金鑰環註冊。" @@ -1705,7 +1735,6 @@ _2fa: securityKeyNotSupported: "您的瀏覽器不支援安全金鑰。" registerTOTPBeforeKey: "如要註冊安全金鑰或 Passkey,請先設定驗證應用程式。" securityKeyInfo: "您可以設定使用支援 FIDO2 的硬體安全鎖、終端設備的指紋認證,或者 PIN 碼來登入。" - chromePasskeyNotSupported: "目前不支援 Chrome 的 Passkey。" registerSecurityKey: "註冊安全金鑰或 Passkey" securityKeyName: "輸入金鑰名稱" tapSecurityKey: "按照瀏覽器的說明註冊安全金鑰或 Passkey。" @@ -1773,6 +1802,7 @@ _antennaSources: homeTimeline: "來自已追隨使用者的貼文" users: "來自特定使用者的貼文" userList: "來自特定清單中的貼文" + userBlacklist: "除指定使用者外的所有貼文" _weekday: sunday: "週日" monday: "週一" @@ -1872,6 +1902,7 @@ _profile: metadataContent: "内容" changeAvatar: "更換大頭貼" changeBanner: "變更橫幅圖像" + verifiedLinkDescription: "如果輸入包含您個人資料的網站 URL,欄位旁邊將出現驗證圖示。" _exportOrImport: allNotes: "所有貼文" favoritedNotes: "「我的最愛」貼文" @@ -1990,11 +2021,17 @@ _notification: youReceivedFollowRequest: "您有新的追隨請求" yourFollowRequestAccepted: "您的追隨請求已通過" pollEnded: "問卷調查已產生結果" + newNote: "新的貼文" unreadAntennaNote: "天線 {name}" emptyPushNotificationMessage: "推送通知已更新" achievementEarned: "獲得成就" + testNotification: "通知測試" + checkNotificationBehavior: "確認通知的顯示行為" + sendTestNotification: "發送測試通知" + notificationWillBeDisplayedLikeThis: "通知會以這樣的方式顯示" _types: all: "全部 " + note: "使用者的最新貼文" follow: "追隨中" mention: "提及" reply: "回覆" @@ -2064,3 +2101,29 @@ _webhookSettings: renote: "當被轉發時" reaction: "當獲得反應時" mention: "當被提到時" +_moderationLogTypes: + createRole: "新增角色" + deleteRole: "刪除角色 " + updateRole: "更新角色設定" + assignRole: "指派角色" + unassignRole: "撤銷角色" + suspend: "凍結" + unsuspend: "解除凍結" + addCustomEmoji: "新增自訂表情符號" + updateCustomEmoji: "更新自訂表情符號" + deleteCustomEmoji: "刪除自訂表情符號" + updateServerSettings: "更新伺服器設定" + updateUserNote: "更新管理筆記" + deleteDriveFile: "刪除檔案" + deleteNote: "刪除貼文" + createGlobalAnnouncement: "建立全網通知" + createUserAnnouncement: "建立使用者通知" + updateGlobalAnnouncement: "更新全部的公告" + updateUserAnnouncement: "更新使用者的公告" + deleteGlobalAnnouncement: "刪除全部的公告" + deleteUserAnnouncement: "刪除使用者的公告" + resetPassword: "重設密碼" + suspendRemoteInstance: "封鎖遠端伺服器" + unsuspendRemoteInstance: "解除封鎖遠端伺服器" + markSensitiveDriveFile: "標記為敏感檔案" + unmarkSensitiveDriveFile: "撤銷標記為敏感檔案" diff --git a/package.json b/package.json index 5c1f9203a..eb82b503a 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,12 @@ { "name": "misskey", - "version": "2023.9.0-beta.5", + "version": "2023.9.1", "codename": "nasubi", "repository": { "type": "git", "url": "https://github.com/misskey-dev/misskey.git" }, - "packageManager": "pnpm@8.7.4", + "packageManager": "pnpm@8.7.6", "workspaces": [ "packages/frontend", "packages/backend", @@ -18,8 +18,8 @@ "build-assets": "node ./scripts/build-assets.mjs", "build": "pnpm build-pre && pnpm -r build && pnpm build-assets", "build-storybook": "pnpm --filter frontend build-storybook", - "start": "pnpm check:connect && cd packages/backend && node ./built/boot/index.js", - "start:test": "cd packages/backend && cross-env NODE_ENV=test node ./built/boot/index.js", + "start": "pnpm check:connect && cd packages/backend && node ./built/boot/entry.js", + "start:test": "cd packages/backend && cross-env NODE_ENV=test node ./built/boot/entry.js", "init": "pnpm migrate", "migrate": "cd packages/backend && pnpm migrate", "check:connect": "cd packages/backend && pnpm check:connect", @@ -46,17 +46,17 @@ "execa": "8.0.1", "cssnano": "6.0.1", "js-yaml": "4.1.0", - "postcss": "8.4.27", - "terser": "5.19.2", + "postcss": "8.4.30", + "terser": "5.20.0", "typescript": "5.2.2" }, "devDependencies": { - "@typescript-eslint/eslint-plugin": "6.6.0", - "@typescript-eslint/parser": "6.6.0", + "@typescript-eslint/eslint-plugin": "6.7.2", + "@typescript-eslint/parser": "6.7.2", "cross-env": "7.0.3", - "cypress": "13.1.0", - "eslint": "8.48.0", - "start-server-and-test": "2.0.0" + "cypress": "13.2.0", + "eslint": "8.50.0", + "start-server-and-test": "2.0.1" }, "optionalDependencies": { "@tensorflow/tfjs-core": "4.4.0" diff --git a/packages/backend/.swcrc b/packages/backend/.swcrc index 0504a2d38..d9f047b6a 100644 --- a/packages/backend/.swcrc +++ b/packages/backend/.swcrc @@ -11,7 +11,7 @@ "decoratorMetadata": true }, "experimental": { - "keepImportAssertions": true + "keepImportAttributes": true }, "baseUrl": "src", "paths": { diff --git a/packages/backend/migration/1689325027964-UserBlacklistAnntena.js b/packages/backend/migration/1689325027964-UserBlacklistAnntena.js new file mode 100644 index 000000000..ce246b20f --- /dev/null +++ b/packages/backend/migration/1689325027964-UserBlacklistAnntena.js @@ -0,0 +1,10 @@ +export class UserBlacklistAnntena1689325027964 { + name = 'UserBlacklistAnntena1689325027964' + + async up(queryRunner) { + await queryRunner.query(`ALTER TYPE "antenna_src_enum" ADD VALUE 'users_blacklist' AFTER 'list'`); + } + + async down(queryRunner) { + } +} diff --git a/packages/backend/migration/1694850832075-server-icons-and-manifest.js b/packages/backend/migration/1694850832075-server-icons-and-manifest.js new file mode 100644 index 000000000..1bd8979d9 --- /dev/null +++ b/packages/backend/migration/1694850832075-server-icons-and-manifest.js @@ -0,0 +1,20 @@ +/* + * SPDX-FileCopyrightText: syuilo and other misskey contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +export class ServerIconsAndManifest1694850832075 { + name = 'ServerIconsAndManifest1694850832075' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" ADD "app192IconUrl" character varying(1024)`); + await queryRunner.query(`ALTER TABLE "meta" ADD "app512IconUrl" character varying(1024)`); + await queryRunner.query(`ALTER TABLE "meta" ADD "manifestJsonOverride" character varying(8192) NOT NULL DEFAULT '{}'`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "manifestJsonOverride"`); + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "app512IconUrl"`); + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "app192IconUrl"`); + } +} diff --git a/packages/backend/migration/1694915420864-clipped-count.js b/packages/backend/migration/1694915420864-clipped-count.js new file mode 100644 index 000000000..1ad8e04ce --- /dev/null +++ b/packages/backend/migration/1694915420864-clipped-count.js @@ -0,0 +1,16 @@ +/* + * SPDX-FileCopyrightText: syuilo and other misskey contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +export class ClippedCount1694915420864 { + name = 'ClippedCount1694915420864' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "note" ADD "clippedCount" smallint NOT NULL DEFAULT '0'`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "note" DROP COLUMN "clippedCount"`); + } +} diff --git a/packages/backend/migration/1695260774117-verified-links.js b/packages/backend/migration/1695260774117-verified-links.js new file mode 100644 index 000000000..18e0571d8 --- /dev/null +++ b/packages/backend/migration/1695260774117-verified-links.js @@ -0,0 +1,11 @@ +export class VerifiedLinks1695260774117 { + name = 'VerifiedLinks1695260774117' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "user_profile" ADD "verifiedLinks" character varying array NOT NULL DEFAULT '{}'`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "verifiedLinks"`); + } +} diff --git a/packages/backend/migration/1695288787870-following-notify.js b/packages/backend/migration/1695288787870-following-notify.js new file mode 100644 index 000000000..e7e2194b1 --- /dev/null +++ b/packages/backend/migration/1695288787870-following-notify.js @@ -0,0 +1,13 @@ +export class FollowingNotify1695288787870 { + name = 'FollowingNotify1695288787870' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "following" ADD "notify" character varying(32)`); + await queryRunner.query(`CREATE INDEX "IDX_5108098457488634a4768e1d12" ON "following" ("notify") `); + } + + async down(queryRunner) { + await queryRunner.query(`DROP INDEX "public"."IDX_5108098457488634a4768e1d12"`); + await queryRunner.query(`ALTER TABLE "following" DROP COLUMN "notify"`); + } +} diff --git a/packages/backend/migration/1695440131671-short-name.js b/packages/backend/migration/1695440131671-short-name.js new file mode 100644 index 000000000..2c37297fc --- /dev/null +++ b/packages/backend/migration/1695440131671-short-name.js @@ -0,0 +1,11 @@ +export class ShortName1695440131671 { + name = 'ShortName1695440131671' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" ADD "shortName" character varying(64)`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "shortName"`); + } +} diff --git a/packages/backend/migration/1695605508898-mutingNotificationTypes.js b/packages/backend/migration/1695605508898-mutingNotificationTypes.js new file mode 100644 index 000000000..8c0e52a2f --- /dev/null +++ b/packages/backend/migration/1695605508898-mutingNotificationTypes.js @@ -0,0 +1,21 @@ +export class MutingNotificationTypes1695605508898 { + name = 'MutingNotificationTypes1695605508898' + + async up(queryRunner) { + await queryRunner.query(`ALTER TYPE "public"."user_profile_mutingnotificationtypes_enum" RENAME TO "user_profile_mutingnotificationtypes_enum_old"`); + await queryRunner.query(`CREATE TYPE "public"."user_profile_mutingnotificationtypes_enum" AS ENUM('note', 'follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'achievementEarned', 'app', 'test', 'pollVote', 'groupInvited')`); + await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "mutingNotificationTypes" DROP DEFAULT`); + await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "mutingNotificationTypes" TYPE "public"."user_profile_mutingnotificationtypes_enum"[] USING "mutingNotificationTypes"::"text"::"public"."user_profile_mutingnotificationtypes_enum"[]`); + await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "mutingNotificationTypes" SET DEFAULT '{}'`); + await queryRunner.query(`DROP TYPE "public"."user_profile_mutingnotificationtypes_enum_old"`); + } + + async down(queryRunner) { + await queryRunner.query(`CREATE TYPE "public"."user_profile_mutingnotificationtypes_enum_old" AS ENUM('follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'achievementEarned', 'app')`); + await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "mutingNotificationTypes" DROP DEFAULT`); + await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "mutingNotificationTypes" TYPE "public"."user_profile_mutingnotificationtypes_enum_old"[] USING "mutingNotificationTypes"::"text"::"public"."user_profile_mutingnotificationtypes_enum_old"[]`); + await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "mutingNotificationTypes" SET DEFAULT '{}'`); + await queryRunner.query(`DROP TYPE "public"."user_profile_mutingnotificationtypes_enum"`); + await queryRunner.query(`ALTER TYPE "public"."user_profile_mutingnotificationtypes_enum_old" RENAME TO "user_profile_mutingnotificationtypes_enum"`); + } +} diff --git a/packages/backend/package.json b/packages/backend/package.json index c8ccad156..c26b1238d 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -56,29 +56,29 @@ "utf-8-validate": "^6.0.3" }, "dependencies": { - "@aws-sdk/client-s3": "3.400.0", - "@aws-sdk/lib-storage": "3.400.0", - "@aws-sdk/node-http-handler": "3.374.0", - "@bull-board/api": "5.8.1", - "@bull-board/fastify": "5.8.1", - "@bull-board/ui": "5.8.1", + "@aws-sdk/client-s3": "3.412.0", + "@aws-sdk/lib-storage": "3.412.0", + "@smithy/node-http-handler": "2.1.5", + "@bull-board/api": "5.8.4", + "@bull-board/fastify": "5.8.4", + "@bull-board/ui": "5.8.4", "@discordapp/twemoji": "14.1.2", "@fastify/accepts": "4.2.0", - "@fastify/cookie": "9.0.4", - "@fastify/cors": "8.3.0", + "@fastify/cookie": "9.1.0", + "@fastify/cors": "8.4.0", "@fastify/express": "2.3.0", "@fastify/http-proxy": "9.2.1", "@fastify/multipart": "7.7.3", - "@fastify/static": "6.11.0", - "@fastify/view": "8.0.0", - "@nestjs/common": "10.2.4", - "@nestjs/core": "10.2.4", - "@nestjs/testing": "10.2.4", + "@fastify/static": "6.11.2", + "@fastify/view": "8.2.0", + "@nestjs/common": "10.2.6", + "@nestjs/core": "10.2.6", + "@nestjs/testing": "10.2.6", "@peertube/http-signature": "1.7.0", "@simplewebauthn/server": "8.1.1", "@sinonjs/fake-timers": "11.1.0", "@swc/cli": "0.1.62", - "@swc/core": "1.3.82", + "@swc/core": "1.3.87", "accepts": "1.3.8", "ajv": "8.12.0", "archiver": "6.0.1", @@ -86,7 +86,7 @@ "bcryptjs": "2.4.3", "blurhash": "2.0.5", "body-parser": "1.20.2", - "bullmq": "4.8.0", + "bullmq": "4.11.4", "cacheable-lookup": "7.0.0", "cbor": "9.0.1", "chalk": "5.3.0", @@ -97,7 +97,7 @@ "content-disposition": "0.5.4", "date-fns": "2.30.0", "deep-email-validator": "0.1.21", - "fastify": "4.22.2", + "fastify": "4.23.2", "feed": "4.2.2", "file-type": "18.5.0", "fluent-ffmpeg": "2.1.2", @@ -113,18 +113,18 @@ "js-yaml": "4.1.0", "jsdom": "22.1.0", "json5": "2.2.3", - "jsonld": "8.2.1", + "jsonld": "8.3.1", "jsrsasign": "10.8.6", - "meilisearch": "0.34.1", + "meilisearch": "0.34.2", "mfm-js": "0.23.3", - "microformats-parser": "1.4.1", + "microformats-parser": "1.5.2", "mime-types": "2.1.35", "misskey-js": "workspace:*", "ms": "3.0.0-canary.1", - "nanoid": "4.0.2", + "nanoid": "5.0.1", "nested-property": "4.0.0", "node-fetch": "3.3.2", - "nodemailer": "6.9.4", + "nodemailer": "6.9.5", "nsfwjs": "2.4.2", "oauth": "0.10.0", "oauth2orize": "1.11.1", @@ -149,49 +149,49 @@ "rss-parser": "3.13.0", "rxjs": "7.8.1", "sanitize-html": "2.11.0", - "sharp": "0.32.5", + "sharp": "0.32.6", "sharp-read-bmp": "github:misskey-dev/sharp-read-bmp", "slacc": "0.0.10", "strict-event-emitter-types": "2.0.0", "stringz": "2.1.0", "summaly": "github:misskey-dev/summaly", - "systeminformation": "5.21.4", + "systeminformation": "5.21.8", "tinycolor2": "1.6.0", "tmp": "0.2.1", - "tsc-alias": "1.8.7", + "tsc-alias": "1.8.8", "tsconfig-paths": "4.2.0", "twemoji-parser": "14.0.0", "typeorm": "0.3.17", "typescript": "5.2.2", "ulid": "2.3.0", "vary": "1.1.2", - "web-push": "3.6.5", - "ws": "8.13.0", + "web-push": "3.6.6", + "ws": "8.14.2", "xev": "3.0.2" }, "devDependencies": { - "@jest/globals": "29.6.4", + "@jest/globals": "29.7.0", "@simplewebauthn/typescript-types": "8.0.0", "@swc/jest": "0.2.29", "@types/accepts": "1.3.5", - "@types/archiver": "5.3.2", - "@types/bcryptjs": "2.4.3", - "@types/body-parser": "1.19.2", + "@types/archiver": "5.3.3", + "@types/bcryptjs": "2.4.4", + "@types/body-parser": "1.19.3", "@types/cbor": "6.0.0", "@types/color-convert": "2.0.1", "@types/content-disposition": "0.5.6", - "@types/fluent-ffmpeg": "2.1.21", + "@types/fluent-ffmpeg": "2.1.22", "@types/http-link-header": "1.0.3", - "@types/jest": "29.5.4", - "@types/js-yaml": "4.0.5", - "@types/jsdom": "21.1.2", - "@types/jsonld": "1.5.9", - "@types/jsrsasign": "10.5.8", + "@types/jest": "29.5.5", + "@types/js-yaml": "4.0.6", + "@types/jsdom": "21.1.3", + "@types/jsonld": "1.5.10", + "@types/jsrsasign": "10.5.9", "@types/mime-types": "2.1.1", "@types/ms": "0.7.31", - "@types/node": "20.5.9", + "@types/node": "20.6.4", "@types/node-fetch": "3.0.3", - "@types/nodemailer": "6.4.9", + "@types/nodemailer": "6.4.11", "@types/oauth": "0.9.2", "@types/oauth2orize": "1.11.1", "@types/oauth2orize-pkce": "0.1.0", @@ -203,24 +203,24 @@ "@types/ratelimiter": "3.4.4", "@types/rename": "1.0.4", "@types/sanitize-html": "2.9.0", - "@types/semver": "7.5.1", + "@types/semver": "7.5.2", "@types/sharp": "0.32.0", "@types/simple-oauth2": "5.0.4", "@types/sinonjs__fake-timers": "8.1.2", - "@types/tinycolor2": "1.4.3", - "@types/tmp": "0.2.3", + "@types/tinycolor2": "1.4.4", + "@types/tmp": "0.2.4", "@types/vary": "1.1.0", "@types/web-push": "3.6.0", "@types/ws": "8.5.5", - "@typescript-eslint/eslint-plugin": "6.6.0", - "@typescript-eslint/parser": "6.6.0", + "@typescript-eslint/eslint-plugin": "6.7.2", + "@typescript-eslint/parser": "6.7.2", "aws-sdk-client-mock": "3.0.0", "cross-env": "7.0.3", - "eslint": "8.48.0", + "eslint": "8.50.0", "eslint-plugin-import": "2.28.1", "execa": "8.0.1", - "jest": "29.6.4", - "jest-mock": "29.6.3", + "jest": "29.7.0", + "jest-mock": "29.7.0", "simple-oauth2": "5.0.0" } } diff --git a/packages/backend/src/boot/index.ts b/packages/backend/src/boot/entry.ts similarity index 100% rename from packages/backend/src/boot/index.ts rename to packages/backend/src/boot/entry.ts diff --git a/packages/backend/src/boot/master.ts b/packages/backend/src/boot/master.ts index 0bf23c770..a45ea2bb8 100644 --- a/packages/backend/src/boot/master.ts +++ b/packages/backend/src/boot/master.ts @@ -68,21 +68,34 @@ export async function masterMain() { process.exit(1); } - if (envOption.onlyServer) { - await server(); - } else if (envOption.onlyQueue) { - await jobQueue(); - } else { - await server(); - } - bootLogger.succ('Misskey initialized'); - if (!envOption.disableClustering) { + if (envOption.disableClustering) { + if (envOption.onlyServer) { + await server(); + } else if (envOption.onlyQueue) { + await jobQueue(); + } else { + await server(); + await jobQueue(); + } + } else { + if (envOption.onlyServer) { + // nop + } else if (envOption.onlyQueue) { + // nop + } else { + await server(); + } + await spawnWorkers(config.clusterLimit); } - bootLogger.succ(config.socket ? `Now listening on socket ${config.socket} on ${config.url}` : `Now listening on port ${config.port} on ${config.url}`, null, true); + if (envOption.onlyQueue) { + bootLogger.succ('Queue started', null, true); + } else { + bootLogger.succ(config.socket ? `Now listening on socket ${config.socket} on ${config.url}` : `Now listening on port ${config.port} on ${config.url}`, null, true); + } } function showEnvironment(): void { diff --git a/packages/backend/src/core/AccountMoveService.ts b/packages/backend/src/core/AccountMoveService.ts index 84cc5def1..ec1d01392 100644 --- a/packages/backend/src/core/AccountMoveService.ts +++ b/packages/backend/src/core/AccountMoveService.ts @@ -8,8 +8,8 @@ import { IsNull, In, MoreThan, Not } from 'typeorm'; import { bindThis } from '@/decorators.js'; import { DI } from '@/di-symbols.js'; -import type { MiLocalUser, MiRemoteUser, MiUser } from '@/models/entities/User.js'; -import type { BlockingsRepository, FollowingsRepository, InstancesRepository, MutingsRepository, UserListJoiningsRepository, UsersRepository } from '@/models/index.js'; +import type { MiLocalUser, MiRemoteUser, MiUser } from '@/models/User.js'; +import type { BlockingsRepository, FollowingsRepository, InstancesRepository, MutingsRepository, UserListJoiningsRepository, UsersRepository } from '@/models/_.js'; import type { RelationshipJobData, ThinUser } from '@/queue/types.js'; import { IdService } from '@/core/IdService.js'; diff --git a/packages/backend/src/core/AccountUpdateService.ts b/packages/backend/src/core/AccountUpdateService.ts index 6a796407d..664700ea6 100644 --- a/packages/backend/src/core/AccountUpdateService.ts +++ b/packages/backend/src/core/AccountUpdateService.ts @@ -5,8 +5,8 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { UsersRepository } from '@/models/index.js'; -import type { MiUser } from '@/models/entities/User.js'; +import type { UsersRepository } from '@/models/_.js'; +import type { MiUser } from '@/models/User.js'; import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; import { RelayService } from '@/core/RelayService.js'; import { ApDeliverManagerService } from '@/core/activitypub/ApDeliverManagerService.js'; diff --git a/packages/backend/src/core/AchievementService.ts b/packages/backend/src/core/AchievementService.ts index aa810015e..1b8718335 100644 --- a/packages/backend/src/core/AchievementService.ts +++ b/packages/backend/src/core/AchievementService.ts @@ -4,8 +4,8 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { UserProfilesRepository } from '@/models/index.js'; -import type { MiUser } from '@/models/entities/User.js'; +import type { UserProfilesRepository } from '@/models/_.js'; +import type { MiUser } from '@/models/User.js'; import { DI } from '@/di-symbols.js'; import { bindThis } from '@/decorators.js'; import { NotificationService } from '@/core/NotificationService.js'; @@ -85,6 +85,7 @@ export const ACHIEVEMENT_TYPES = [ 'setNameToSyuilo', 'cookieClicked', 'brainDiver', + 'smashTestNotificationButton', ] as const; @Injectable() diff --git a/packages/backend/src/core/AnnouncementService.ts b/packages/backend/src/core/AnnouncementService.ts index 64e8ae758..ddacc0936 100644 --- a/packages/backend/src/core/AnnouncementService.ts +++ b/packages/backend/src/core/AnnouncementService.ts @@ -6,12 +6,13 @@ import { Inject, Injectable } from '@nestjs/common'; import { Brackets } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { MiUser } from '@/models/entities/User.js'; -import type { AnnouncementReadsRepository, AnnouncementsRepository, MiAnnouncement, MiAnnouncementRead } from '@/models/index.js'; +import type { MiUser } from '@/models/User.js'; +import type { AnnouncementReadsRepository, AnnouncementsRepository, MiAnnouncement, MiAnnouncementRead, UsersRepository } from '@/models/_.js'; import { bindThis } from '@/decorators.js'; import { Packed } from '@/misc/json-schema.js'; import { IdService } from '@/core/IdService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; +import { ModerationLogService } from '@/core/ModerationLogService.js'; @Injectable() export class AnnouncementService { @@ -22,8 +23,12 @@ export class AnnouncementService { @Inject(DI.announcementReadsRepository) private announcementReadsRepository: AnnouncementReadsRepository, + @Inject(DI.usersRepository) + private usersRepository: UsersRepository, + private idService: IdService, private globalEventService: GlobalEventService, + private moderationLogService: ModerationLogService, ) { } @@ -58,7 +63,7 @@ export class AnnouncementService { } @bindThis - public async create(values: Partial): Promise<{ raw: MiAnnouncement; packed: Packed<'Announcement'> }> { + public async create(values: Partial, moderator?: MiUser): Promise<{ raw: MiAnnouncement; packed: Packed<'Announcement'> }> { const announcement = await this.announcementsRepository.insert({ id: this.idService.genId(), createdAt: new Date(), @@ -79,10 +84,28 @@ export class AnnouncementService { this.globalEventService.publishMainStream(values.userId, 'announcementCreated', { announcement: packed, }); + + if (moderator) { + const user = await this.usersRepository.findOneByOrFail({ id: values.userId }); + this.moderationLogService.log(moderator, 'createUserAnnouncement', { + announcementId: announcement.id, + announcement: announcement, + userId: values.userId, + userUsername: user.username, + userHost: user.host, + }); + } } else { this.globalEventService.publishBroadcastStream('announcementCreated', { announcement: packed, }); + + if (moderator) { + this.moderationLogService.log(moderator, 'createGlobalAnnouncement', { + announcementId: announcement.id, + announcement: announcement, + }); + } } return { @@ -91,6 +114,63 @@ export class AnnouncementService { }; } + @bindThis + public async update(announcement: MiAnnouncement, values: Partial, moderator?: MiUser): Promise { + await this.announcementsRepository.update(announcement.id, { + updatedAt: new Date(), + title: values.title, + text: values.text, + /* eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- 空の文字列の場合、nullを渡すようにするため */ + imageUrl: values.imageUrl || null, + display: values.display, + icon: values.icon, + forExistingUsers: values.forExistingUsers, + needConfirmationToRead: values.needConfirmationToRead, + isActive: values.isActive, + }); + + const after = await this.announcementsRepository.findOneByOrFail({ id: announcement.id }); + + if (moderator) { + if (announcement.userId) { + const user = await this.usersRepository.findOneByOrFail({ id: announcement.userId }); + this.moderationLogService.log(moderator, 'updateUserAnnouncement', { + announcementId: announcement.id, + before: announcement, + after: after, + userId: announcement.userId, + userUsername: user.username, + userHost: user.host, + }); + } else { + this.moderationLogService.log(moderator, 'updateGlobalAnnouncement', { + announcementId: announcement.id, + before: announcement, + after: after, + }); + } + } + } + + @bindThis + public async delete(announcement: MiAnnouncement, moderator?: MiUser): Promise { + await this.announcementsRepository.delete(announcement.id); + + if (moderator) { + if (announcement.userId) { + this.moderationLogService.log(moderator, 'deleteUserAnnouncement', { + announcementId: announcement.id, + announcement: announcement, + }); + } else { + this.moderationLogService.log(moderator, 'deleteGlobalAnnouncement', { + announcementId: announcement.id, + announcement: announcement, + }); + } + } + } + @bindThis public async read(user: MiUser, announcementId: MiAnnouncement['id']): Promise { try { diff --git a/packages/backend/src/core/AntennaService.ts b/packages/backend/src/core/AntennaService.ts index c64b94141..841ce4b84 100644 --- a/packages/backend/src/core/AntennaService.ts +++ b/packages/backend/src/core/AntennaService.ts @@ -5,14 +5,14 @@ import { Inject, Injectable } from '@nestjs/common'; import * as Redis from 'ioredis'; -import type { MiAntenna } from '@/models/entities/Antenna.js'; -import type { MiNote } from '@/models/entities/Note.js'; -import type { MiUser } from '@/models/entities/User.js'; +import type { MiAntenna } from '@/models/Antenna.js'; +import type { MiNote } from '@/models/Note.js'; +import type { MiUser } from '@/models/User.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import * as Acct from '@/misc/acct.js'; import type { Packed } from '@/misc/json-schema.js'; import { DI } from '@/di-symbols.js'; -import type { AntennasRepository, UserListJoiningsRepository } from '@/models/index.js'; +import type { AntennasRepository, UserListJoiningsRepository } from '@/models/_.js'; import { UtilityService } from '@/core/UtilityService.js'; import { bindThis } from '@/decorators.js'; import { StreamMessages } from '@/server/api/stream/types.js'; @@ -119,6 +119,12 @@ export class AntennaService implements OnApplicationShutdown { return this.utilityService.getFullApAccount(username, host).toLowerCase(); }); if (!accts.includes(this.utilityService.getFullApAccount(noteUser.username, noteUser.host).toLowerCase())) return false; + } else if (antenna.src === 'users_blacklist') { + const accts = antenna.users.map(x => { + const { username, host } = Acct.parse(x); + return this.utilityService.getFullApAccount(username, host).toLowerCase(); + }); + if (accts.includes(this.utilityService.getFullApAccount(noteUser.username, noteUser.host).toLowerCase())) return false; } const keywords = antenna.keywords diff --git a/packages/backend/src/core/CacheService.ts b/packages/backend/src/core/CacheService.ts index 15be5f398..6ca684d53 100644 --- a/packages/backend/src/core/CacheService.ts +++ b/packages/backend/src/core/CacheService.ts @@ -5,9 +5,9 @@ import { Inject, Injectable } from '@nestjs/common'; import * as Redis from 'ioredis'; -import type { BlockingsRepository, ChannelFollowingsRepository, FollowingsRepository, MutingsRepository, RenoteMutingsRepository, MiUserProfile, UserProfilesRepository, UsersRepository } from '@/models/index.js'; +import type { BlockingsRepository, ChannelFollowingsRepository, FollowingsRepository, MutingsRepository, RenoteMutingsRepository, MiUserProfile, UserProfilesRepository, UsersRepository } from '@/models/_.js'; import { MemoryKVCache, RedisKVCache } from '@/misc/cache.js'; -import type { MiLocalUser, MiUser } from '@/models/entities/User.js'; +import type { MiLocalUser, MiUser } from '@/models/User.js'; import { DI } from '@/di-symbols.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { bindThis } from '@/decorators.js'; diff --git a/packages/backend/src/core/ClipService.ts b/packages/backend/src/core/ClipService.ts new file mode 100644 index 000000000..3d9982e80 --- /dev/null +++ b/packages/backend/src/core/ClipService.ts @@ -0,0 +1,159 @@ +/* + * SPDX-FileCopyrightText: syuilo and other misskey contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Inject, Injectable } from '@nestjs/common'; +import { QueryFailedError } from 'typeorm'; +import { DI } from '@/di-symbols.js'; +import type { ClipsRepository, MiNote, MiClip, ClipNotesRepository, NotesRepository } from '@/models/_.js'; +import { bindThis } from '@/decorators.js'; +import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js'; +import { RoleService } from '@/core/RoleService.js'; +import { IdService } from '@/core/IdService.js'; +import type { MiLocalUser } from '@/models/User.js'; + +@Injectable() +export class ClipService { + public static NoSuchNoteError = class extends Error {}; + public static NoSuchClipError = class extends Error {}; + public static AlreadyAddedError = class extends Error {}; + public static TooManyClipNotesError = class extends Error {}; + public static TooManyClipsError = class extends Error {}; + + constructor( + @Inject(DI.clipsRepository) + private clipsRepository: ClipsRepository, + + @Inject(DI.clipNotesRepository) + private clipNotesRepository: ClipNotesRepository, + + @Inject(DI.notesRepository) + private notesRepository: NotesRepository, + + private roleService: RoleService, + private idService: IdService, + ) { + } + + @bindThis + public async create(me: MiLocalUser, name: string, isPublic: boolean, description: string | null): Promise { + const currentCount = await this.clipsRepository.countBy({ + userId: me.id, + }); + if (currentCount > (await this.roleService.getUserPolicies(me.id)).clipLimit) { + throw new ClipService.TooManyClipsError(); + } + + const clip = await this.clipsRepository.insert({ + id: this.idService.genId(), + createdAt: new Date(), + userId: me.id, + name: name, + isPublic: isPublic, + description: description, + }).then(x => this.clipsRepository.findOneByOrFail(x.identifiers[0])); + + return clip; + } + + @bindThis + public async update(me: MiLocalUser, clipId: MiClip['id'], name: string | undefined, isPublic: boolean | undefined, description: string | null | undefined): Promise { + const clip = await this.clipsRepository.findOneBy({ + id: clipId, + userId: me.id, + }); + + if (clip == null) { + throw new ClipService.NoSuchClipError(); + } + + await this.clipsRepository.update(clip.id, { + name: name, + description: description, + isPublic: isPublic, + }); + } + + @bindThis + public async delete(me: MiLocalUser, clipId: MiClip['id']): Promise { + const clip = await this.clipsRepository.findOneBy({ + id: clipId, + userId: me.id, + }); + + if (clip == null) { + throw new ClipService.NoSuchClipError(); + } + + await this.clipsRepository.delete(clip.id); + } + + @bindThis + public async addNote(me: MiLocalUser, clipId: MiClip['id'], noteId: MiNote['id']): Promise { + const clip = await this.clipsRepository.findOneBy({ + id: clipId, + userId: me.id, + }); + + if (clip == null) { + throw new ClipService.NoSuchClipError(); + } + + const currentCount = await this.clipNotesRepository.countBy({ + clipId: clip.id, + }); + if (currentCount > (await this.roleService.getUserPolicies(me.id)).noteEachClipsLimit) { + throw new ClipService.TooManyClipNotesError(); + } + + try { + await this.clipNotesRepository.insert({ + id: this.idService.genId(), + noteId: noteId, + clipId: clip.id, + }); + } catch (e: unknown) { + if (e instanceof QueryFailedError) { + if (isDuplicateKeyValueError(e)) { + throw new ClipService.AlreadyAddedError(); + } else if (e.driverError.detail.includes('is not present in table "note".')) { + throw new ClipService.NoSuchNoteError(); + } + } + + throw e; + } + + this.clipsRepository.update(clip.id, { + lastClippedAt: new Date(), + }); + + this.notesRepository.increment({ id: noteId }, 'clippedCount', 1); + } + + @bindThis + public async removeNote(me: MiLocalUser, clipId: MiClip['id'], noteId: MiNote['id']): Promise { + const clip = await this.clipsRepository.findOneBy({ + id: clipId, + userId: me.id, + }); + + if (clip == null) { + throw new ClipService.NoSuchClipError(); + } + + const note = await this.notesRepository.findOneBy({ id: noteId }); + + if (note == null) { + throw new ClipService.NoSuchNoteError(); + } + + await this.clipNotesRepository.delete({ + noteId: noteId, + clipId: clip.id, + }); + + this.notesRepository.decrement({ id: noteId }, 'clippedCount', 1); + } +} diff --git a/packages/backend/src/core/CoreModule.ts b/packages/backend/src/core/CoreModule.ts index 863f1a2fd..78333e70a 100644 --- a/packages/backend/src/core/CoreModule.ts +++ b/packages/backend/src/core/CoreModule.ts @@ -51,12 +51,14 @@ import { UserKeypairService } from './UserKeypairService.js'; import { UserListService } from './UserListService.js'; import { UserMutingService } from './UserMutingService.js'; import { UserSuspendService } from './UserSuspendService.js'; +import { UserAuthService } from './UserAuthService.js'; import { VideoProcessingService } from './VideoProcessingService.js'; import { WebhookService } from './WebhookService.js'; import { ProxyAccountService } from './ProxyAccountService.js'; import { UtilityService } from './UtilityService.js'; import { FileInfoService } from './FileInfoService.js'; import { SearchService } from './SearchService.js'; +import { ClipService } from './ClipService.js'; import { ChartLoggerService } from './chart/ChartLoggerService.js'; import FederationChart from './chart/charts/federation.js'; import NotesChart from './chart/charts/notes.js'; @@ -176,11 +178,13 @@ const $UserKeypairService: Provider = { provide: 'UserKeypairService', useExisti const $UserListService: Provider = { provide: 'UserListService', useExisting: UserListService }; const $UserMutingService: Provider = { provide: 'UserMutingService', useExisting: UserMutingService }; const $UserSuspendService: Provider = { provide: 'UserSuspendService', useExisting: UserSuspendService }; +const $UserAuthService: Provider = { provide: 'UserAuthService', useExisting: UserAuthService }; const $VideoProcessingService: Provider = { provide: 'VideoProcessingService', useExisting: VideoProcessingService }; const $WebhookService: Provider = { provide: 'WebhookService', useExisting: WebhookService }; const $UtilityService: Provider = { provide: 'UtilityService', useExisting: UtilityService }; const $FileInfoService: Provider = { provide: 'FileInfoService', useExisting: FileInfoService }; const $SearchService: Provider = { provide: 'SearchService', useExisting: SearchService }; +const $ClipService: Provider = { provide: 'ClipService', useExisting: ClipService }; const $ChartLoggerService: Provider = { provide: 'ChartLoggerService', useExisting: ChartLoggerService }; const $FederationChart: Provider = { provide: 'FederationChart', useExisting: FederationChart }; @@ -304,11 +308,13 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting UserListService, UserMutingService, UserSuspendService, + UserAuthService, VideoProcessingService, WebhookService, UtilityService, FileInfoService, SearchService, + ClipService, ChartLoggerService, FederationChart, NotesChart, @@ -425,11 +431,13 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting $UserListService, $UserMutingService, $UserSuspendService, + $UserAuthService, $VideoProcessingService, $WebhookService, $UtilityService, $FileInfoService, $SearchService, + $ClipService, $ChartLoggerService, $FederationChart, $NotesChart, @@ -547,11 +555,13 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting UserListService, UserMutingService, UserSuspendService, + UserAuthService, VideoProcessingService, WebhookService, UtilityService, FileInfoService, SearchService, + ClipService, FederationChart, NotesChart, UsersChart, @@ -667,11 +677,13 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting $UserListService, $UserMutingService, $UserSuspendService, + $UserAuthService, $VideoProcessingService, $WebhookService, $UtilityService, $FileInfoService, $SearchService, + $ClipService, $FederationChart, $NotesChart, $UsersChart, diff --git a/packages/backend/src/core/CreateSystemUserService.ts b/packages/backend/src/core/CreateSystemUserService.ts index 7f57128ba..3419d0b49 100644 --- a/packages/backend/src/core/CreateSystemUserService.ts +++ b/packages/backend/src/core/CreateSystemUserService.ts @@ -8,11 +8,11 @@ import { Inject, Injectable } from '@nestjs/common'; import bcrypt from 'bcryptjs'; import { IsNull, DataSource } from 'typeorm'; import { genRsaKeyPair } from '@/misc/gen-key-pair.js'; -import { MiUser } from '@/models/entities/User.js'; -import { MiUserProfile } from '@/models/entities/UserProfile.js'; +import { MiUser } from '@/models/User.js'; +import { MiUserProfile } from '@/models/UserProfile.js'; import { IdService } from '@/core/IdService.js'; -import { MiUserKeypair } from '@/models/entities/UserKeypair.js'; -import { MiUsedUsername } from '@/models/entities/UsedUsername.js'; +import { MiUserKeypair } from '@/models/UserKeypair.js'; +import { MiUsedUsername } from '@/models/UsedUsername.js'; import { DI } from '@/di-symbols.js'; import generateNativeUserToken from '@/misc/generate-native-user-token.js'; import { bindThis } from '@/decorators.js'; diff --git a/packages/backend/src/core/CustomEmojiService.ts b/packages/backend/src/core/CustomEmojiService.ts index 8fd993345..1b545a124 100644 --- a/packages/backend/src/core/CustomEmojiService.ts +++ b/packages/backend/src/core/CustomEmojiService.ts @@ -10,14 +10,15 @@ import { DI } from '@/di-symbols.js'; import { IdService } from '@/core/IdService.js'; import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; -import type { MiDriveFile } from '@/models/entities/DriveFile.js'; -import type { MiEmoji } from '@/models/entities/Emoji.js'; -import type { EmojisRepository, MiRole } from '@/models/index.js'; +import type { MiDriveFile } from '@/models/DriveFile.js'; +import type { MiEmoji } from '@/models/Emoji.js'; +import type { EmojisRepository, MiRole, MiUser } from '@/models/_.js'; import { bindThis } from '@/decorators.js'; import { MemoryKVCache, RedisSingleCache } from '@/misc/cache.js'; import { UtilityService } from '@/core/UtilityService.js'; import { query } from '@/misc/prelude/url.js'; import type { Serialized } from '@/server/api/stream/types.js'; +import { ModerationLogService } from '@/core/ModerationLogService.js'; const parseEmojiStrRegexp = /^(\w+)(?:@([\w.-]+))?$/; @@ -36,6 +37,7 @@ export class CustomEmojiService implements OnApplicationShutdown { private utilityService: UtilityService, private idService: IdService, private emojiEntityService: EmojiEntityService, + private moderationLogService: ModerationLogService, private globalEventService: GlobalEventService, ) { this.cache = new MemoryKVCache(1000 * 60 * 60 * 12); @@ -66,7 +68,7 @@ export class CustomEmojiService implements OnApplicationShutdown { isSensitive: boolean; localOnly: boolean; roleIdsThatCanBeUsedThisEmojiAsReaction: MiRole['id'][]; - }): Promise { + }, moderator?: MiUser): Promise { const emoji = await this.emojisRepository.insert({ id: this.idService.genId(), updatedAt: new Date(), @@ -89,6 +91,13 @@ export class CustomEmojiService implements OnApplicationShutdown { this.globalEventService.publishBroadcastStream('emojiAdded', { emoji: await this.emojiEntityService.packDetailed(emoji.id), }); + + if (moderator) { + this.moderationLogService.log(moderator, 'addCustomEmoji', { + emojiId: emoji.id, + emoji: emoji, + }); + } } return emoji; @@ -104,7 +113,7 @@ export class CustomEmojiService implements OnApplicationShutdown { isSensitive?: boolean; localOnly?: boolean; roleIdsThatCanBeUsedThisEmojiAsReaction?: MiRole['id'][]; - }): Promise { + }, moderator?: MiUser): Promise { const emoji = await this.emojisRepository.findOneByOrFail({ id: id }); const sameNameEmoji = await this.emojisRepository.findOneBy({ name: data.name, host: IsNull() }); if (sameNameEmoji != null && sameNameEmoji.id !== id) throw new Error('name already exists'); @@ -125,11 +134,11 @@ export class CustomEmojiService implements OnApplicationShutdown { this.localEmojisCache.refresh(); - const updated = await this.emojiEntityService.packDetailed(emoji.id); + const packed = await this.emojiEntityService.packDetailed(emoji.id); if (emoji.name === data.name) { this.globalEventService.publishBroadcastStream('emojiUpdated', { - emojis: [updated], + emojis: [packed], }); } else { this.globalEventService.publishBroadcastStream('emojiDeleted', { @@ -137,7 +146,16 @@ export class CustomEmojiService implements OnApplicationShutdown { }); this.globalEventService.publishBroadcastStream('emojiAdded', { - emoji: updated, + emoji: packed, + }); + } + + if (moderator) { + const updated = await this.emojisRepository.findOneByOrFail({ id: id }); + this.moderationLogService.log(moderator, 'updateCustomEmoji', { + emojiId: emoji.id, + before: emoji, + after: updated, }); } } @@ -231,7 +249,7 @@ export class CustomEmojiService implements OnApplicationShutdown { } @bindThis - public async delete(id: MiEmoji['id']) { + public async delete(id: MiEmoji['id'], moderator?: MiUser) { const emoji = await this.emojisRepository.findOneByOrFail({ id: id }); await this.emojisRepository.delete(emoji.id); @@ -241,16 +259,30 @@ export class CustomEmojiService implements OnApplicationShutdown { this.globalEventService.publishBroadcastStream('emojiDeleted', { emojis: [await this.emojiEntityService.packDetailed(emoji)], }); + + if (moderator) { + this.moderationLogService.log(moderator, 'deleteCustomEmoji', { + emojiId: emoji.id, + emoji: emoji, + }); + } } @bindThis - public async deleteBulk(ids: MiEmoji['id'][]) { + public async deleteBulk(ids: MiEmoji['id'][], moderator?: MiUser) { const emojis = await this.emojisRepository.findBy({ id: In(ids), }); for (const emoji of emojis) { await this.emojisRepository.delete(emoji.id); + + if (moderator) { + this.moderationLogService.log(moderator, 'deleteCustomEmoji', { + emojiId: emoji.id, + emoji: emoji, + }); + } } this.localEmojisCache.refresh(); diff --git a/packages/backend/src/core/DeleteAccountService.ts b/packages/backend/src/core/DeleteAccountService.ts index 3e90d3945..570bd440e 100644 --- a/packages/backend/src/core/DeleteAccountService.ts +++ b/packages/backend/src/core/DeleteAccountService.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { UsersRepository } from '@/models/index.js'; +import type { UsersRepository } from '@/models/_.js'; import { QueueService } from '@/core/QueueService.js'; import { UserSuspendService } from '@/core/UserSuspendService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/core/DriveService.ts b/packages/backend/src/core/DriveService.ts index 77f60bf6e..cecbec963 100644 --- a/packages/backend/src/core/DriveService.ts +++ b/packages/backend/src/core/DriveService.ts @@ -11,12 +11,12 @@ import { sharpBmp } from 'sharp-read-bmp'; import { IsNull } from 'typeorm'; import { DeleteObjectCommandInput, PutObjectCommandInput, NoSuchKey } from '@aws-sdk/client-s3'; import { DI } from '@/di-symbols.js'; -import type { DriveFilesRepository, UsersRepository, DriveFoldersRepository, UserProfilesRepository } from '@/models/index.js'; +import type { DriveFilesRepository, UsersRepository, DriveFoldersRepository, UserProfilesRepository } from '@/models/_.js'; import type { Config } from '@/config.js'; import Logger from '@/logger.js'; -import type { MiRemoteUser, MiUser } from '@/models/entities/User.js'; +import type { MiRemoteUser, MiUser } from '@/models/User.js'; import { MetaService } from '@/core/MetaService.js'; -import { MiDriveFile } from '@/models/entities/DriveFile.js'; +import { MiDriveFile } from '@/models/DriveFile.js'; import { IdService } from '@/core/IdService.js'; import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js'; import { FILE_TYPE_BROWSERSAFE } from '@/const.js'; @@ -27,7 +27,7 @@ import { VideoProcessingService } from '@/core/VideoProcessingService.js'; import { ImageProcessingService } from '@/core/ImageProcessingService.js'; import type { IImage } from '@/core/ImageProcessingService.js'; import { QueueService } from '@/core/QueueService.js'; -import type { MiDriveFolder } from '@/models/entities/DriveFolder.js'; +import type { MiDriveFolder } from '@/models/DriveFolder.js'; import { createTemp } from '@/misc/create-temp.js'; import DriveChart from '@/core/chart/charts/drive.js'; import PerUserDriveChart from '@/core/chart/charts/per-user-drive.js'; @@ -42,6 +42,7 @@ import { bindThis } from '@/decorators.js'; import { RoleService } from '@/core/RoleService.js'; import { correctFilename } from '@/misc/correct-filename.js'; import { isMimeImage } from '@/misc/is-mime-image.js'; +import { ModerationLogService } from '@/core/ModerationLogService.js'; type AddFileArgs = { /** User who wish to add file */ @@ -86,6 +87,9 @@ type UploadFromUrlArgs = { @Injectable() export class DriveService { + public static NoSuchFolderError = class extends Error {}; + public static InvalidFileNameError = class extends Error {}; + public static CannotUnmarkSensitiveError = class extends Error {}; private registerLogger: Logger; private downloaderLogger: Logger; private deleteLogger: Logger; @@ -119,6 +123,7 @@ export class DriveService { private globalEventService: GlobalEventService, private queueService: QueueService, private roleService: RoleService, + private moderationLogService: ModerationLogService, private driveChart: DriveChart, private perUserDriveChart: PerUserDriveChart, private instanceChart: InstanceChart, @@ -648,7 +653,63 @@ export class DriveService { } @bindThis - public async deleteFile(file: MiDriveFile, isExpired = false) { + public async updateFile(file: MiDriveFile, values: Partial, updater: MiUser) { + const alwaysMarkNsfw = (await this.roleService.getUserPolicies(file.userId)).alwaysMarkNsfw; + + if (values.name && !this.driveFileEntityService.validateFileName(file.name)) { + throw new DriveService.InvalidFileNameError(); + } + + if (values.isSensitive !== undefined && values.isSensitive !== file.isSensitive && alwaysMarkNsfw && !values.isSensitive) { + throw new DriveService.CannotUnmarkSensitiveError(); + } + + if (values.folderId != null) { + const folder = await this.driveFoldersRepository.findOneBy({ + id: values.folderId, + userId: file.userId!, + }); + + if (folder == null) { + throw new DriveService.NoSuchFolderError(); + } + } + + await this.driveFilesRepository.update(file.id, values); + + const fileObj = await this.driveFileEntityService.pack(file.id, { self: true }); + + // Publish fileUpdated event + if (file.userId) { + this.globalEventService.publishDriveStream(file.userId, 'fileUpdated', fileObj); + } + + if (await this.roleService.isModerator(updater) && (file.userId !== updater.id)) { + if (values.isSensitive !== undefined && values.isSensitive !== file.isSensitive) { + const user = file.userId ? await this.usersRepository.findOneByOrFail({ id: file.userId }) : null; + if (values.isSensitive) { + this.moderationLogService.log(updater, 'markSensitiveDriveFile', { + fileId: file.id, + fileUserId: file.userId, + fileUserUsername: user?.username ?? null, + fileUserHost: user?.host ?? null, + }); + } else { + this.moderationLogService.log(updater, 'unmarkSensitiveDriveFile', { + fileId: file.id, + fileUserId: file.userId, + fileUserUsername: user?.username ?? null, + fileUserHost: user?.host ?? null, + }); + } + } + } + + return fileObj; + } + + @bindThis + public async deleteFile(file: MiDriveFile, isExpired = false, deleter?: MiUser) { if (file.storedInternal) { this.internalStorageService.del(file.accessKey!); @@ -671,11 +732,11 @@ export class DriveService { } } - this.deletePostProcess(file, isExpired); + this.deletePostProcess(file, isExpired, deleter); } @bindThis - public async deleteFileSync(file: MiDriveFile, isExpired = false) { + public async deleteFileSync(file: MiDriveFile, isExpired = false, deleter?: MiUser) { if (file.storedInternal) { this.internalStorageService.del(file.accessKey!); @@ -702,11 +763,11 @@ export class DriveService { await Promise.all(promises); } - this.deletePostProcess(file, isExpired); + this.deletePostProcess(file, isExpired, deleter); } @bindThis - private async deletePostProcess(file: MiDriveFile, isExpired = false) { + private async deletePostProcess(file: MiDriveFile, isExpired = false, deleter?: MiUser) { // リモートファイル期限切れ削除後は直リンクにする if (isExpired && file.userHost !== null && file.uri != null) { this.driveFilesRepository.update(file.id, { @@ -733,6 +794,20 @@ export class DriveService { this.instanceChart.updateDrive(file, false); } } + + if (file.userId) { + this.globalEventService.publishDriveStream(file.userId, 'fileDeleted', file.id); + } + + if (deleter && await this.roleService.isModerator(deleter) && (file.userId !== deleter.id)) { + const user = file.userId ? await this.usersRepository.findOneByOrFail({ id: file.userId }) : null; + this.moderationLogService.log(deleter, 'deleteDriveFile', { + fileId: file.id, + fileUserId: file.userId, + fileUserUsername: user?.username ?? null, + fileUserHost: user?.host ?? null, + }); + } } @bindThis diff --git a/packages/backend/src/core/EmailService.ts b/packages/backend/src/core/EmailService.ts index 162634593..c9da3f77c 100644 --- a/packages/backend/src/core/EmailService.ts +++ b/packages/backend/src/core/EmailService.ts @@ -10,7 +10,7 @@ import { MetaService } from '@/core/MetaService.js'; import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; import type Logger from '@/logger.js'; -import type { UserProfilesRepository } from '@/models/index.js'; +import type { UserProfilesRepository } from '@/models/_.js'; import { LoggerService } from '@/core/LoggerService.js'; import { bindThis } from '@/decorators.js'; diff --git a/packages/backend/src/core/FederatedInstanceService.ts b/packages/backend/src/core/FederatedInstanceService.ts index e7b85b750..61806583c 100644 --- a/packages/backend/src/core/FederatedInstanceService.ts +++ b/packages/backend/src/core/FederatedInstanceService.ts @@ -5,8 +5,8 @@ import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common'; import * as Redis from 'ioredis'; -import type { InstancesRepository } from '@/models/index.js'; -import type { MiInstance } from '@/models/entities/Instance.js'; +import type { InstancesRepository } from '@/models/_.js'; +import type { MiInstance } from '@/models/Instance.js'; import { MemoryKVCache, RedisKVCache } from '@/misc/cache.js'; import { IdService } from '@/core/IdService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/core/FetchInstanceMetadataService.ts b/packages/backend/src/core/FetchInstanceMetadataService.ts index 4563006f6..682acef15 100644 --- a/packages/backend/src/core/FetchInstanceMetadataService.ts +++ b/packages/backend/src/core/FetchInstanceMetadataService.ts @@ -8,7 +8,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { JSDOM } from 'jsdom'; import tinycolor from 'tinycolor2'; import * as Redis from 'ioredis'; -import type { MiInstance } from '@/models/entities/Instance.js'; +import type { MiInstance } from '@/models/Instance.js'; import type Logger from '@/logger.js'; import { DI } from '@/di-symbols.js'; import { LoggerService } from '@/core/LoggerService.js'; diff --git a/packages/backend/src/core/GlobalEventService.ts b/packages/backend/src/core/GlobalEventService.ts index 224eb3c59..4bc4f54c2 100644 --- a/packages/backend/src/core/GlobalEventService.ts +++ b/packages/backend/src/core/GlobalEventService.ts @@ -5,10 +5,10 @@ import { Inject, Injectable } from '@nestjs/common'; import * as Redis from 'ioredis'; -import type { MiUser } from '@/models/entities/User.js'; -import type { MiNote } from '@/models/entities/Note.js'; -import type { MiUserList } from '@/models/entities/UserList.js'; -import type { MiAntenna } from '@/models/entities/Antenna.js'; +import type { MiUser } from '@/models/User.js'; +import type { MiNote } from '@/models/Note.js'; +import type { MiUserList } from '@/models/UserList.js'; +import type { MiAntenna } from '@/models/Antenna.js'; import type { StreamChannels, AdminStreamTypes, @@ -25,7 +25,7 @@ import type { Packed } from '@/misc/json-schema.js'; import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; import { bindThis } from '@/decorators.js'; -import { MiRole } from '@/models/index.js'; +import { MiRole } from '@/models/_.js'; @Injectable() export class GlobalEventService { diff --git a/packages/backend/src/core/HashtagService.ts b/packages/backend/src/core/HashtagService.ts index eec160275..c72c7460f 100644 --- a/packages/backend/src/core/HashtagService.ts +++ b/packages/backend/src/core/HashtagService.ts @@ -5,11 +5,11 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { MiUser } from '@/models/entities/User.js'; +import type { MiUser } from '@/models/User.js'; import { normalizeForSearch } from '@/misc/normalize-for-search.js'; import { IdService } from '@/core/IdService.js'; -import type { MiHashtag } from '@/models/entities/Hashtag.js'; -import type { HashtagsRepository } from '@/models/index.js'; +import type { MiHashtag } from '@/models/Hashtag.js'; +import type { HashtagsRepository } from '@/models/_.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { bindThis } from '@/decorators.js'; diff --git a/packages/backend/src/core/InstanceActorService.ts b/packages/backend/src/core/InstanceActorService.ts index 8e576774d..b40fd4629 100644 --- a/packages/backend/src/core/InstanceActorService.ts +++ b/packages/backend/src/core/InstanceActorService.ts @@ -5,8 +5,8 @@ import { Inject, Injectable } from '@nestjs/common'; import { IsNull } from 'typeorm'; -import type { MiLocalUser } from '@/models/entities/User.js'; -import type { UsersRepository } from '@/models/index.js'; +import type { MiLocalUser } from '@/models/User.js'; +import type { UsersRepository } from '@/models/_.js'; import { MemorySingleCache } from '@/misc/cache.js'; import { DI } from '@/di-symbols.js'; import { CreateSystemUserService } from '@/core/CreateSystemUserService.js'; diff --git a/packages/backend/src/core/MetaService.ts b/packages/backend/src/core/MetaService.ts index 42ce4de43..00e1e3c1f 100644 --- a/packages/backend/src/core/MetaService.ts +++ b/packages/backend/src/core/MetaService.ts @@ -7,7 +7,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { DataSource } from 'typeorm'; import * as Redis from 'ioredis'; import { DI } from '@/di-symbols.js'; -import { MiMeta } from '@/models/entities/Meta.js'; +import { MiMeta } from '@/models/Meta.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { bindThis } from '@/decorators.js'; import { StreamMessages } from '@/server/api/stream/types.js'; diff --git a/packages/backend/src/core/MfmService.ts b/packages/backend/src/core/MfmService.ts index b6f84da47..b275d1b14 100644 --- a/packages/backend/src/core/MfmService.ts +++ b/packages/backend/src/core/MfmService.ts @@ -10,7 +10,7 @@ import { Window } from 'happy-dom'; import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; import { intersperse } from '@/misc/prelude/array.js'; -import type { IMentionedRemoteUsers } from '@/models/entities/Note.js'; +import type { IMentionedRemoteUsers } from '@/models/Note.js'; import { bindThis } from '@/decorators.js'; import * as TreeAdapter from '../../node_modules/parse5/dist/tree-adapters/default.js'; import type * as mfm from 'mfm-js'; diff --git a/packages/backend/src/core/ModerationLogService.ts b/packages/backend/src/core/ModerationLogService.ts index be01fbf9f..f7f9063d9 100644 --- a/packages/backend/src/core/ModerationLogService.ts +++ b/packages/backend/src/core/ModerationLogService.ts @@ -5,10 +5,11 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { ModerationLogsRepository } from '@/models/index.js'; -import type { MiUser } from '@/models/entities/User.js'; +import type { ModerationLogsRepository } from '@/models/_.js'; +import type { MiUser } from '@/models/User.js'; import { IdService } from '@/core/IdService.js'; import { bindThis } from '@/decorators.js'; +import { ModerationLogPayloads, moderationLogTypes } from '@/types.js'; @Injectable() export class ModerationLogService { @@ -21,13 +22,13 @@ export class ModerationLogService { } @bindThis - public async insertModerationLog(moderator: { id: MiUser['id'] }, type: string, info?: Record) { + public async log(moderator: { id: MiUser['id'] }, type: T, info?: ModerationLogPayloads[T]) { await this.moderationLogsRepository.insert({ id: this.idService.genId(), createdAt: new Date(), userId: moderator.id, type: type, - info: info ?? {}, + info: (info as any) ?? {}, }); } } diff --git a/packages/backend/src/core/NoteCreateService.ts b/packages/backend/src/core/NoteCreateService.ts index dc440f568..972319ddc 100644 --- a/packages/backend/src/core/NoteCreateService.ts +++ b/packages/backend/src/core/NoteCreateService.ts @@ -12,22 +12,22 @@ import RE2 from 're2'; import { extractMentions } from '@/misc/extract-mentions.js'; import { extractCustomEmojisFromMfm } from '@/misc/extract-custom-emojis-from-mfm.js'; import { extractHashtags } from '@/misc/extract-hashtags.js'; -import type { IMentionedRemoteUsers } from '@/models/entities/Note.js'; -import { MiNote } from '@/models/entities/Note.js'; -import type { ChannelsRepository, InstancesRepository, MutedNotesRepository, MutingsRepository, NotesRepository, NoteThreadMutingsRepository, UserProfilesRepository, UsersRepository } from '@/models/index.js'; -import type { MiDriveFile } from '@/models/entities/DriveFile.js'; -import type { MiApp } from '@/models/entities/App.js'; +import type { IMentionedRemoteUsers } from '@/models/Note.js'; +import { MiNote } from '@/models/Note.js'; +import type { ChannelsRepository, FollowingsRepository, InstancesRepository, MutedNotesRepository, MutingsRepository, NotesRepository, NoteThreadMutingsRepository, UserProfilesRepository, UsersRepository } from '@/models/_.js'; +import type { MiDriveFile } from '@/models/DriveFile.js'; +import type { MiApp } from '@/models/App.js'; import { concat } from '@/misc/prelude/array.js'; import { IdService } from '@/core/IdService.js'; -import type { MiUser, MiLocalUser, MiRemoteUser } from '@/models/entities/User.js'; -import type { IPoll } from '@/models/entities/Poll.js'; -import { MiPoll } from '@/models/entities/Poll.js'; +import type { MiUser, MiLocalUser, MiRemoteUser } from '@/models/User.js'; +import type { IPoll } from '@/models/Poll.js'; +import { MiPoll } from '@/models/Poll.js'; import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js'; import { checkWordMute } from '@/misc/check-word-mute.js'; -import type { MiChannel } from '@/models/entities/Channel.js'; +import type { MiChannel } from '@/models/Channel.js'; import { normalizeForSearch } from '@/misc/normalize-for-search.js'; import { MemorySingleCache } from '@/misc/cache.js'; -import type { MiUserProfile } from '@/models/entities/UserProfile.js'; +import type { MiUserProfile } from '@/models/UserProfile.js'; import { RelayService } from '@/core/RelayService.js'; import { FederatedInstanceService } from '@/core/FederatedInstanceService.js'; import { DI } from '@/di-symbols.js'; @@ -185,6 +185,9 @@ export class NoteCreateService implements OnApplicationShutdown { @Inject(DI.noteThreadMutingsRepository) private noteThreadMutingsRepository: NoteThreadMutingsRepository, + @Inject(DI.followingsRepository) + private followingsRepository: FollowingsRepository, + private userEntityService: UserEntityService, private noteEntityService: NoteEntityService, private idService: IdService, @@ -505,6 +508,20 @@ export class NoteCreateService implements OnApplicationShutdown { this.saveReply(data.reply, note); } + if (data.reply == null) { + this.followingsRepository.findBy({ + followeeId: user.id, + notify: 'normal', + }).then(followings => { + for (const following of followings) { + this.notificationService.createNotification(following.followerId, 'note', { + notifierId: user.id, + noteId: note.id, + }); + } + }); + } + // この投稿を除く指定したユーザーによる指定したノートのリノートが存在しないとき if (data.renote && (await this.noteEntityService.countSameRenotes(user.id, data.renote.id, note.id) === 0)) { if (!user.isBot) this.incRenoteCount(data.renote); diff --git a/packages/backend/src/core/NoteDeleteService.ts b/packages/backend/src/core/NoteDeleteService.ts index 07708bd02..87979f22a 100644 --- a/packages/backend/src/core/NoteDeleteService.ts +++ b/packages/backend/src/core/NoteDeleteService.ts @@ -5,9 +5,9 @@ import { Brackets, In } from 'typeorm'; import { Injectable, Inject } from '@nestjs/common'; -import type { MiUser, MiLocalUser, MiRemoteUser } from '@/models/entities/User.js'; -import type { MiNote, IMentionedRemoteUsers } from '@/models/entities/Note.js'; -import type { InstancesRepository, NotesRepository, UsersRepository } from '@/models/index.js'; +import type { MiUser, MiLocalUser, MiRemoteUser } from '@/models/User.js'; +import type { MiNote, IMentionedRemoteUsers } from '@/models/Note.js'; +import type { InstancesRepository, NotesRepository, UsersRepository } from '@/models/_.js'; import { RelayService } from '@/core/RelayService.js'; import { FederatedInstanceService } from '@/core/FederatedInstanceService.js'; import { DI } from '@/di-symbols.js'; @@ -23,6 +23,7 @@ import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { bindThis } from '@/decorators.js'; import { MetaService } from '@/core/MetaService.js'; import { SearchService } from '@/core/SearchService.js'; +import { ModerationLogService } from '@/core/ModerationLogService.js'; @Injectable() export class NoteDeleteService { @@ -48,6 +49,7 @@ export class NoteDeleteService { private apDeliverManagerService: ApDeliverManagerService, private metaService: MetaService, private searchService: SearchService, + private moderationLogService: ModerationLogService, private notesChart: NotesChart, private perUserNotesChart: PerUserNotesChart, private instanceChart: InstanceChart, @@ -58,7 +60,7 @@ export class NoteDeleteService { * @param user 投稿者 * @param note 投稿 */ - async delete(user: { id: MiUser['id']; uri: MiUser['uri']; host: MiUser['host']; isBot: MiUser['isBot']; }, note: MiNote, quiet = false) { + async delete(user: { id: MiUser['id']; uri: MiUser['uri']; host: MiUser['host']; isBot: MiUser['isBot']; }, note: MiNote, quiet = false, deleter?: MiUser) { const deletedAt = new Date(); const cascadingNotes = await this.findCascadingNotes(note); @@ -131,6 +133,17 @@ export class NoteDeleteService { id: note.id, userId: user.id, }); + + if (deleter && (note.userId !== deleter.id)) { + const user = await this.usersRepository.findOneByOrFail({ id: note.userId }); + this.moderationLogService.log(deleter, 'deleteNote', { + noteId: note.id, + noteUserId: note.userId, + noteUserUsername: user.username, + noteUserHost: user.host, + note: note, + }); + } } @bindThis diff --git a/packages/backend/src/core/NotePiningService.ts b/packages/backend/src/core/NotePiningService.ts index 7f1381a41..147554ee9 100644 --- a/packages/backend/src/core/NotePiningService.ts +++ b/packages/backend/src/core/NotePiningService.ts @@ -5,12 +5,12 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { NotesRepository, UserNotePiningsRepository, UsersRepository } from '@/models/index.js'; +import type { NotesRepository, UserNotePiningsRepository, UsersRepository } from '@/models/_.js'; import { IdentifiableError } from '@/misc/identifiable-error.js'; -import type { MiUser } from '@/models/entities/User.js'; -import type { MiNote } from '@/models/entities/Note.js'; +import type { MiUser } from '@/models/User.js'; +import type { MiNote } from '@/models/Note.js'; import { IdService } from '@/core/IdService.js'; -import type { MiUserNotePining } from '@/models/entities/UserNotePining.js'; +import type { MiUserNotePining } from '@/models/UserNotePining.js'; import { RelayService } from '@/core/RelayService.js'; import type { Config } from '@/config.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; diff --git a/packages/backend/src/core/NoteReadService.ts b/packages/backend/src/core/NoteReadService.ts index 019748626..422e0192c 100644 --- a/packages/backend/src/core/NoteReadService.ts +++ b/packages/backend/src/core/NoteReadService.ts @@ -7,12 +7,12 @@ import { setTimeout } from 'node:timers/promises'; import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common'; import { In } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { MiUser } from '@/models/entities/User.js'; +import type { MiUser } from '@/models/User.js'; import type { Packed } from '@/misc/json-schema.js'; -import type { MiNote } from '@/models/entities/Note.js'; +import type { MiNote } from '@/models/Note.js'; import { IdService } from '@/core/IdService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; -import type { NoteUnreadsRepository, MutingsRepository, NoteThreadMutingsRepository } from '@/models/index.js'; +import type { NoteUnreadsRepository, MutingsRepository, NoteThreadMutingsRepository } from '@/models/_.js'; import { bindThis } from '@/decorators.js'; @Injectable() diff --git a/packages/backend/src/core/NotificationService.ts b/packages/backend/src/core/NotificationService.ts index a3ce7d32a..258ae44f7 100644 --- a/packages/backend/src/core/NotificationService.ts +++ b/packages/backend/src/core/NotificationService.ts @@ -8,9 +8,9 @@ import * as Redis from 'ioredis'; import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common'; import { In } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { UsersRepository } from '@/models/index.js'; -import type { MiUser } from '@/models/entities/User.js'; -import type { MiNotification } from '@/models/entities/Notification.js'; +import type { UsersRepository } from '@/models/_.js'; +import type { MiUser } from '@/models/User.js'; +import type { MiNotification } from '@/models/Notification.js'; import { bindThis } from '@/decorators.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { PushNotificationService } from '@/core/PushNotificationService.js'; diff --git a/packages/backend/src/core/PollService.ts b/packages/backend/src/core/PollService.ts index 551c77976..940aa9834 100644 --- a/packages/backend/src/core/PollService.ts +++ b/packages/backend/src/core/PollService.ts @@ -5,8 +5,8 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { NotesRepository, UsersRepository, PollsRepository, PollVotesRepository, MiUser } from '@/models/index.js'; -import type { MiNote } from '@/models/entities/Note.js'; +import type { NotesRepository, UsersRepository, PollsRepository, PollVotesRepository, MiUser } from '@/models/_.js'; +import type { MiNote } from '@/models/Note.js'; import { RelayService } from '@/core/RelayService.js'; import { IdService } from '@/core/IdService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; diff --git a/packages/backend/src/core/ProxyAccountService.ts b/packages/backend/src/core/ProxyAccountService.ts index 9fb0a45df..b1bc60701 100644 --- a/packages/backend/src/core/ProxyAccountService.ts +++ b/packages/backend/src/core/ProxyAccountService.ts @@ -4,8 +4,8 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { UsersRepository } from '@/models/index.js'; -import type { MiLocalUser } from '@/models/entities/User.js'; +import type { UsersRepository } from '@/models/_.js'; +import type { MiLocalUser } from '@/models/User.js'; import { DI } from '@/di-symbols.js'; import { MetaService } from '@/core/MetaService.js'; import { bindThis } from '@/decorators.js'; diff --git a/packages/backend/src/core/PushNotificationService.ts b/packages/backend/src/core/PushNotificationService.ts index 93928e3cd..40d1decee 100644 --- a/packages/backend/src/core/PushNotificationService.ts +++ b/packages/backend/src/core/PushNotificationService.ts @@ -10,7 +10,7 @@ import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; import type { Packed } from '@/misc/json-schema.js'; import { getNoteSummary } from '@/misc/get-note-summary.js'; -import type { MiSwSubscription, SwSubscriptionsRepository } from '@/models/index.js'; +import type { MiSwSubscription, SwSubscriptionsRepository } from '@/models/_.js'; import { MetaService } from '@/core/MetaService.js'; import { bindThis } from '@/decorators.js'; import { RedisKVCache } from '@/misc/cache.js'; diff --git a/packages/backend/src/core/QueryService.ts b/packages/backend/src/core/QueryService.ts index 30fc67158..9145726f8 100644 --- a/packages/backend/src/core/QueryService.ts +++ b/packages/backend/src/core/QueryService.ts @@ -6,8 +6,8 @@ import { Inject, Injectable } from '@nestjs/common'; import { Brackets, ObjectLiteral } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { MiUser } from '@/models/entities/User.js'; -import type { UserProfilesRepository, FollowingsRepository, ChannelFollowingsRepository, MutedNotesRepository, BlockingsRepository, NoteThreadMutingsRepository, MutingsRepository, RenoteMutingsRepository } from '@/models/index.js'; +import type { MiUser } from '@/models/User.js'; +import type { UserProfilesRepository, FollowingsRepository, ChannelFollowingsRepository, MutedNotesRepository, BlockingsRepository, NoteThreadMutingsRepository, MutingsRepository, RenoteMutingsRepository } from '@/models/_.js'; import { bindThis } from '@/decorators.js'; import type { SelectQueryBuilder } from 'typeorm'; diff --git a/packages/backend/src/core/QueueService.ts b/packages/backend/src/core/QueueService.ts index 310d5e5d9..d8c725003 100644 --- a/packages/backend/src/core/QueueService.ts +++ b/packages/backend/src/core/QueueService.ts @@ -6,8 +6,8 @@ import { randomUUID } from 'node:crypto'; import { Inject, Injectable } from '@nestjs/common'; import type { IActivity } from '@/core/activitypub/type.js'; -import type { MiDriveFile } from '@/models/entities/DriveFile.js'; -import type { MiWebhook, webhookEventTypes } from '@/models/entities/Webhook.js'; +import type { MiDriveFile } from '@/models/DriveFile.js'; +import type { MiWebhook, webhookEventTypes } from '@/models/Webhook.js'; import type { Config } from '@/config.js'; import { DI } from '@/di-symbols.js'; import { bindThis } from '@/decorators.js'; diff --git a/packages/backend/src/core/ReactionService.ts b/packages/backend/src/core/ReactionService.ts index b8bdfff02..d9bde502c 100644 --- a/packages/backend/src/core/ReactionService.ts +++ b/packages/backend/src/core/ReactionService.ts @@ -5,12 +5,12 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { EmojisRepository, NoteReactionsRepository, UsersRepository, NotesRepository } from '@/models/index.js'; +import type { EmojisRepository, NoteReactionsRepository, UsersRepository, NotesRepository } from '@/models/_.js'; import { IdentifiableError } from '@/misc/identifiable-error.js'; -import type { MiRemoteUser, MiUser } from '@/models/entities/User.js'; -import type { MiNote } from '@/models/entities/Note.js'; +import type { MiRemoteUser, MiUser } from '@/models/User.js'; +import type { MiNote } from '@/models/Note.js'; import { IdService } from '@/core/IdService.js'; -import type { MiNoteReaction } from '@/models/entities/NoteReaction.js'; +import type { MiNoteReaction } from '@/models/NoteReaction.js'; import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { NotificationService } from '@/core/NotificationService.js'; diff --git a/packages/backend/src/core/RelayService.ts b/packages/backend/src/core/RelayService.ts index 89f245e86..7171bf84c 100644 --- a/packages/backend/src/core/RelayService.ts +++ b/packages/backend/src/core/RelayService.ts @@ -5,11 +5,11 @@ import { Inject, Injectable } from '@nestjs/common'; import { IsNull } from 'typeorm'; -import type { MiLocalUser, MiUser } from '@/models/entities/User.js'; -import type { RelaysRepository, UsersRepository } from '@/models/index.js'; +import type { MiLocalUser, MiUser } from '@/models/User.js'; +import type { RelaysRepository, UsersRepository } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; import { MemorySingleCache } from '@/misc/cache.js'; -import type { MiRelay } from '@/models/entities/Relay.js'; +import type { MiRelay } from '@/models/Relay.js'; import { QueueService } from '@/core/QueueService.js'; import { CreateSystemUserService } from '@/core/CreateSystemUserService.js'; import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; diff --git a/packages/backend/src/core/RemoteUserResolveService.ts b/packages/backend/src/core/RemoteUserResolveService.ts index ca538ed6c..75c5f14aa 100644 --- a/packages/backend/src/core/RemoteUserResolveService.ts +++ b/packages/backend/src/core/RemoteUserResolveService.ts @@ -8,8 +8,8 @@ import { Inject, Injectable } from '@nestjs/common'; import chalk from 'chalk'; import { IsNull } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { UsersRepository } from '@/models/index.js'; -import type { MiLocalUser, MiRemoteUser } from '@/models/entities/User.js'; +import type { UsersRepository } from '@/models/_.js'; +import type { MiLocalUser, MiRemoteUser } from '@/models/User.js'; import type { Config } from '@/config.js'; import type Logger from '@/logger.js'; import { UtilityService } from '@/core/UtilityService.js'; diff --git a/packages/backend/src/core/RoleService.ts b/packages/backend/src/core/RoleService.ts index f755f3ecf..934b7d676 100644 --- a/packages/backend/src/core/RoleService.ts +++ b/packages/backend/src/core/RoleService.ts @@ -6,18 +6,19 @@ import { Inject, Injectable } from '@nestjs/common'; import * as Redis from 'ioredis'; import { In } from 'typeorm'; -import type { MiRole, MiRoleAssignment, RoleAssignmentsRepository, RolesRepository, UsersRepository } from '@/models/index.js'; +import type { MiRole, MiRoleAssignment, RoleAssignmentsRepository, RolesRepository, UsersRepository } from '@/models/_.js'; import { MemoryKVCache, MemorySingleCache } from '@/misc/cache.js'; -import type { MiUser } from '@/models/entities/User.js'; +import type { MiUser } from '@/models/User.js'; import { DI } from '@/di-symbols.js'; import { bindThis } from '@/decorators.js'; import { MetaService } from '@/core/MetaService.js'; import { CacheService } from '@/core/CacheService.js'; -import type { RoleCondFormulaValue } from '@/models/entities/Role.js'; +import type { RoleCondFormulaValue } from '@/models/Role.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { StreamMessages } from '@/server/api/stream/types.js'; import { IdService } from '@/core/IdService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; +import { ModerationLogService } from '@/core/ModerationLogService.js'; import type { Packed } from '@/misc/json-schema.js'; import type { OnApplicationShutdown } from '@nestjs/common'; @@ -98,6 +99,7 @@ export class RoleService implements OnApplicationShutdown { private userEntityService: UserEntityService, private globalEventService: GlobalEventService, private idService: IdService, + private moderationLogService: ModerationLogService, ) { //this.onMessage = this.onMessage.bind(this); @@ -374,9 +376,11 @@ export class RoleService implements OnApplicationShutdown { } @bindThis - public async assign(userId: MiUser['id'], roleId: MiRole['id'], expiresAt: Date | null = null): Promise { + public async assign(userId: MiUser['id'], roleId: MiRole['id'], expiresAt: Date | null = null, moderator?: MiUser): Promise { const now = new Date(); + const role = await this.rolesRepository.findOneByOrFail({ id: roleId }); + const existing = await this.roleAssignmentsRepository.findOneBy({ roleId: roleId, userId: userId, @@ -406,10 +410,22 @@ export class RoleService implements OnApplicationShutdown { }); this.globalEventService.publishInternalEvent('userRoleAssigned', created); + + if (moderator) { + const user = await this.usersRepository.findOneByOrFail({ id: userId }); + this.moderationLogService.log(moderator, 'assignRole', { + roleId: roleId, + roleName: role.name, + userId: userId, + userUsername: user.username, + userHost: user.host, + expiresAt: expiresAt ? expiresAt.toISOString() : null, + }); + } } @bindThis - public async unassign(userId: MiUser['id'], roleId: MiRole['id']): Promise { + public async unassign(userId: MiUser['id'], roleId: MiRole['id'], moderator?: MiUser): Promise { const now = new Date(); const existing = await this.roleAssignmentsRepository.findOneBy({ roleId, userId }); @@ -430,6 +446,20 @@ export class RoleService implements OnApplicationShutdown { }); this.globalEventService.publishInternalEvent('userRoleUnassigned', existing); + + if (moderator) { + const [user, role] = await Promise.all([ + this.usersRepository.findOneByOrFail({ id: userId }), + this.rolesRepository.findOneByOrFail({ id: roleId }), + ]); + this.moderationLogService.log(moderator, 'unassignRole', { + roleId: roleId, + roleName: role.name, + userId: userId, + userUsername: user.username, + userHost: user.host, + }); + } } @bindThis @@ -451,6 +481,75 @@ export class RoleService implements OnApplicationShutdown { redisPipeline.exec(); } + @bindThis + public async create(values: Partial, moderator?: MiUser): Promise { + const date = new Date(); + const created = await this.rolesRepository.insert({ + id: this.idService.genId(), + createdAt: date, + updatedAt: date, + lastUsedAt: date, + name: values.name, + description: values.description, + color: values.color, + iconUrl: values.iconUrl, + target: values.target, + condFormula: values.condFormula, + isPublic: values.isPublic, + isAdministrator: values.isAdministrator, + isModerator: values.isModerator, + isExplorable: values.isExplorable, + asBadge: values.asBadge, + canEditMembersByModerator: values.canEditMembersByModerator, + displayOrder: values.displayOrder, + policies: values.policies, + }).then(x => this.rolesRepository.findOneByOrFail(x.identifiers[0])); + + this.globalEventService.publishInternalEvent('roleCreated', created); + + if (moderator) { + this.moderationLogService.log(moderator, 'createRole', { + roleId: created.id, + role: created, + }); + } + + return created; + } + + @bindThis + public async update(role: MiRole, params: Partial, moderator?: MiUser): Promise { + const date = new Date(); + await this.rolesRepository.update(role.id, { + updatedAt: date, + ...params, + }); + + const updated = await this.rolesRepository.findOneByOrFail({ id: role.id }); + this.globalEventService.publishInternalEvent('roleUpdated', updated); + + if (moderator) { + this.moderationLogService.log(moderator, 'updateRole', { + roleId: role.id, + before: role, + after: updated, + }); + } + } + + @bindThis + public async delete(role: MiRole, moderator?: MiUser): Promise { + await this.rolesRepository.delete({ id: role.id }); + this.globalEventService.publishInternalEvent('roleDeleted', role); + + if (moderator) { + this.moderationLogService.log(moderator, 'deleteRole', { + roleId: role.id, + role: role, + }); + } + } + @bindThis public dispose(): void { this.redisForSub.off('message', this.onMessage); diff --git a/packages/backend/src/core/S3Service.ts b/packages/backend/src/core/S3Service.ts index eb0458f53..df0991539 100644 --- a/packages/backend/src/core/S3Service.ts +++ b/packages/backend/src/core/S3Service.ts @@ -9,8 +9,8 @@ import * as https from 'node:https'; import { Injectable } from '@nestjs/common'; import { DeleteObjectCommand, S3Client } from '@aws-sdk/client-s3'; import { Upload } from '@aws-sdk/lib-storage'; -import { NodeHttpHandler, NodeHttpHandlerOptions } from '@aws-sdk/node-http-handler'; -import type { MiMeta } from '@/models/entities/Meta.js'; +import { NodeHttpHandler, NodeHttpHandlerOptions } from '@smithy/node-http-handler'; +import type { MiMeta } from '@/models/Meta.js'; import { HttpRequestService } from '@/core/HttpRequestService.js'; import { bindThis } from '@/decorators.js'; import type { DeleteObjectCommandInput, PutObjectCommandInput } from '@aws-sdk/client-s3'; diff --git a/packages/backend/src/core/SearchService.ts b/packages/backend/src/core/SearchService.ts index f21bd790b..3ef321dd3 100644 --- a/packages/backend/src/core/SearchService.ts +++ b/packages/backend/src/core/SearchService.ts @@ -8,9 +8,9 @@ import { In } from 'typeorm'; import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; import { bindThis } from '@/decorators.js'; -import { MiNote } from '@/models/entities/Note.js'; -import { MiUser } from '@/models/index.js'; -import type { NotesRepository } from '@/models/index.js'; +import { MiNote } from '@/models/Note.js'; +import { MiUser } from '@/models/_.js'; +import type { NotesRepository } from '@/models/_.js'; import { sqlLikeEscape } from '@/misc/sql-like-escape.js'; import { QueryService } from '@/core/QueryService.js'; import { IdService } from '@/core/IdService.js'; diff --git a/packages/backend/src/core/SignupService.ts b/packages/backend/src/core/SignupService.ts index e719d5918..dfec0cfcf 100644 --- a/packages/backend/src/core/SignupService.ts +++ b/packages/backend/src/core/SignupService.ts @@ -8,12 +8,12 @@ import { Inject, Injectable } from '@nestjs/common'; import bcrypt from 'bcryptjs'; import { DataSource, IsNull } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { UsedUsernamesRepository, UsersRepository } from '@/models/index.js'; -import { MiUser } from '@/models/entities/User.js'; -import { MiUserProfile } from '@/models/entities/UserProfile.js'; +import type { UsedUsernamesRepository, UsersRepository } from '@/models/_.js'; +import { MiUser } from '@/models/User.js'; +import { MiUserProfile } from '@/models/UserProfile.js'; import { IdService } from '@/core/IdService.js'; -import { MiUserKeypair } from '@/models/entities/UserKeypair.js'; -import { MiUsedUsername } from '@/models/entities/UsedUsername.js'; +import { MiUserKeypair } from '@/models/UserKeypair.js'; +import { MiUsedUsername } from '@/models/UsedUsername.js'; import generateUserToken from '@/misc/generate-native-user-token.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { bindThis } from '@/decorators.js'; diff --git a/packages/backend/src/core/UserAuthService.ts b/packages/backend/src/core/UserAuthService.ts new file mode 100644 index 000000000..ccf4dfc6b --- /dev/null +++ b/packages/backend/src/core/UserAuthService.ts @@ -0,0 +1,45 @@ +/* + * SPDX-FileCopyrightText: syuilo and other misskey contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Inject, Injectable } from '@nestjs/common'; +import { QueryFailedError } from 'typeorm'; +import * as OTPAuth from 'otpauth'; +import { DI } from '@/di-symbols.js'; +import type { MiUserProfile, UserProfilesRepository, UsersRepository } from '@/models/_.js'; +import { bindThis } from '@/decorators.js'; +import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js'; +import type { MiLocalUser } from '@/models/User.js'; + +@Injectable() +export class UserAuthService { + constructor( + @Inject(DI.usersRepository) + private usersRepository: UsersRepository, + + @Inject(DI.userProfilesRepository) + private userProfilesRepository: UserProfilesRepository, + ) { + } + + @bindThis + public async twoFactorAuthenticate(profile: MiUserProfile, token: string): Promise { + if (profile.twoFactorBackupSecret?.includes(token)) { + await this.userProfilesRepository.update({ userId: profile.userId }, { + twoFactorBackupSecret: profile.twoFactorBackupSecret.filter((secret) => secret !== token), + }); + } else { + const delta = OTPAuth.TOTP.validate({ + secret: OTPAuth.Secret.fromBase32(profile.twoFactorSecret!), + digits: 6, + token, + window: 5, + }); + + if (delta === null) { + throw new Error('authentication failed'); + } + } + } +} diff --git a/packages/backend/src/core/UserBlockingService.ts b/packages/backend/src/core/UserBlockingService.ts index 44e2066a1..37031e341 100644 --- a/packages/backend/src/core/UserBlockingService.ts +++ b/packages/backend/src/core/UserBlockingService.ts @@ -6,12 +6,12 @@ import { Inject, Injectable, OnModuleInit } from '@nestjs/common'; import { ModuleRef } from '@nestjs/core'; import { IdService } from '@/core/IdService.js'; -import type { MiUser } from '@/models/entities/User.js'; -import type { MiBlocking } from '@/models/entities/Blocking.js'; +import type { MiUser } from '@/models/User.js'; +import type { MiBlocking } from '@/models/Blocking.js'; import { QueueService } from '@/core/QueueService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; -import type { FollowRequestsRepository, BlockingsRepository, UserListsRepository, UserListJoiningsRepository } from '@/models/index.js'; +import type { FollowRequestsRepository, BlockingsRepository, UserListsRepository, UserListJoiningsRepository } from '@/models/_.js'; import Logger from '@/logger.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; diff --git a/packages/backend/src/core/UserFollowingService.ts b/packages/backend/src/core/UserFollowingService.ts index c99a3e6a1..5b2b0205d 100644 --- a/packages/backend/src/core/UserFollowingService.ts +++ b/packages/backend/src/core/UserFollowingService.ts @@ -6,7 +6,7 @@ import { Inject, Injectable, OnModuleInit, forwardRef } from '@nestjs/common'; import { ModuleRef } from '@nestjs/core'; import { IsNull } from 'typeorm'; -import type { MiLocalUser, MiPartialLocalUser, MiPartialRemoteUser, MiRemoteUser, MiUser } from '@/models/entities/User.js'; +import type { MiLocalUser, MiPartialLocalUser, MiPartialRemoteUser, MiRemoteUser, MiUser } from '@/models/User.js'; import { IdentifiableError } from '@/misc/identifiable-error.js'; import { QueueService } from '@/core/QueueService.js'; import PerUserFollowingChart from '@/core/chart/charts/per-user-following.js'; @@ -19,7 +19,7 @@ import { FederatedInstanceService } from '@/core/FederatedInstanceService.js'; import { WebhookService } from '@/core/WebhookService.js'; import { NotificationService } from '@/core/NotificationService.js'; import { DI } from '@/di-symbols.js'; -import type { FollowingsRepository, FollowRequestsRepository, InstancesRepository, UserProfilesRepository, UsersRepository } from '@/models/index.js'; +import type { FollowingsRepository, FollowRequestsRepository, InstancesRepository, UserProfilesRepository, UsersRepository } from '@/models/_.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; import { bindThis } from '@/decorators.js'; diff --git a/packages/backend/src/core/UserKeypairService.ts b/packages/backend/src/core/UserKeypairService.ts index f32172760..425a97f3f 100644 --- a/packages/backend/src/core/UserKeypairService.ts +++ b/packages/backend/src/core/UserKeypairService.ts @@ -5,10 +5,10 @@ import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common'; import * as Redis from 'ioredis'; -import type { MiUser } from '@/models/entities/User.js'; -import type { UserKeypairsRepository } from '@/models/index.js'; +import type { MiUser } from '@/models/User.js'; +import type { UserKeypairsRepository } from '@/models/_.js'; import { RedisKVCache } from '@/misc/cache.js'; -import type { MiUserKeypair } from '@/models/entities/UserKeypair.js'; +import type { MiUserKeypair } from '@/models/UserKeypair.js'; import { DI } from '@/di-symbols.js'; import { bindThis } from '@/decorators.js'; diff --git a/packages/backend/src/core/UserListService.ts b/packages/backend/src/core/UserListService.ts index 3a56a2e96..a71d50bba 100644 --- a/packages/backend/src/core/UserListService.ts +++ b/packages/backend/src/core/UserListService.ts @@ -4,10 +4,10 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { UserListJoiningsRepository } from '@/models/index.js'; -import type { MiUser } from '@/models/entities/User.js'; -import type { MiUserList } from '@/models/entities/UserList.js'; -import type { MiUserListJoining } from '@/models/entities/UserListJoining.js'; +import type { UserListJoiningsRepository } from '@/models/_.js'; +import type { MiUser } from '@/models/User.js'; +import type { MiUserList } from '@/models/UserList.js'; +import type { MiUserListJoining } from '@/models/UserListJoining.js'; import { IdService } from '@/core/IdService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/core/UserMutingService.ts b/packages/backend/src/core/UserMutingService.ts index 1f0b2c215..2387c9d64 100644 --- a/packages/backend/src/core/UserMutingService.ts +++ b/packages/backend/src/core/UserMutingService.ts @@ -5,9 +5,9 @@ import { Inject, Injectable } from '@nestjs/common'; import { In } from 'typeorm'; -import type { MutingsRepository, MiMuting } from '@/models/index.js'; +import type { MutingsRepository, MiMuting } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; -import type { MiUser } from '@/models/entities/User.js'; +import type { MiUser } from '@/models/User.js'; import { DI } from '@/di-symbols.js'; import { bindThis } from '@/decorators.js'; import { CacheService } from '@/core/CacheService.js'; diff --git a/packages/backend/src/core/UserSuspendService.ts b/packages/backend/src/core/UserSuspendService.ts index 938aeb600..8940a142d 100644 --- a/packages/backend/src/core/UserSuspendService.ts +++ b/packages/backend/src/core/UserSuspendService.ts @@ -5,8 +5,8 @@ import { Inject, Injectable } from '@nestjs/common'; import { Not, IsNull } from 'typeorm'; -import type { FollowingsRepository } from '@/models/index.js'; -import type { MiUser } from '@/models/entities/User.js'; +import type { FollowingsRepository } from '@/models/_.js'; +import type { MiUser } from '@/models/User.js'; import { QueueService } from '@/core/QueueService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/core/WebAuthnService.ts b/packages/backend/src/core/WebAuthnService.ts index 1c344eabe..5945dc291 100644 --- a/packages/backend/src/core/WebAuthnService.ts +++ b/packages/backend/src/core/WebAuthnService.ts @@ -12,11 +12,11 @@ import { } from '@simplewebauthn/server'; import { AttestationFormat, isoCBOR } from '@simplewebauthn/server/helpers'; import { DI } from '@/di-symbols.js'; -import type { UserSecurityKeysRepository } from '@/models/index.js'; +import type { UserSecurityKeysRepository } from '@/models/_.js'; import type { Config } from '@/config.js'; import { bindThis } from '@/decorators.js'; import { MetaService } from '@/core/MetaService.js'; -import { MiUser } from '@/models/index.js'; +import { MiUser } from '@/models/_.js'; import { IdentifiableError } from '@/misc/identifiable-error.js'; import type { AuthenticationResponseJSON, diff --git a/packages/backend/src/core/WebhookService.ts b/packages/backend/src/core/WebhookService.ts index 3b43c1224..1344f0ac9 100644 --- a/packages/backend/src/core/WebhookService.ts +++ b/packages/backend/src/core/WebhookService.ts @@ -5,8 +5,8 @@ import { Inject, Injectable } from '@nestjs/common'; import * as Redis from 'ioredis'; -import type { WebhooksRepository } from '@/models/index.js'; -import type { MiWebhook } from '@/models/entities/Webhook.js'; +import type { WebhooksRepository } from '@/models/_.js'; +import type { MiWebhook } from '@/models/Webhook.js'; import { DI } from '@/di-symbols.js'; import { bindThis } from '@/decorators.js'; import { StreamMessages } from '@/server/api/stream/types.js'; diff --git a/packages/backend/src/core/activitypub/ApAudienceService.ts b/packages/backend/src/core/activitypub/ApAudienceService.ts index f3432f833..440852bdf 100644 --- a/packages/backend/src/core/activitypub/ApAudienceService.ts +++ b/packages/backend/src/core/activitypub/ApAudienceService.ts @@ -5,7 +5,7 @@ import { Injectable } from '@nestjs/common'; import promiseLimit from 'promise-limit'; -import type { MiRemoteUser, MiUser } from '@/models/entities/User.js'; +import type { MiRemoteUser, MiUser } from '@/models/User.js'; import { concat, unique } from '@/misc/prelude/array.js'; import { bindThis } from '@/decorators.js'; import { getApIds } from './type.js'; diff --git a/packages/backend/src/core/activitypub/ApDbResolverService.ts b/packages/backend/src/core/activitypub/ApDbResolverService.ts index b69158832..995c5dcd5 100644 --- a/packages/backend/src/core/activitypub/ApDbResolverService.ts +++ b/packages/backend/src/core/activitypub/ApDbResolverService.ts @@ -5,14 +5,14 @@ import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { NotesRepository, UserPublickeysRepository, UsersRepository } from '@/models/index.js'; +import type { NotesRepository, UserPublickeysRepository, UsersRepository } from '@/models/_.js'; import type { Config } from '@/config.js'; import { MemoryKVCache } from '@/misc/cache.js'; -import type { MiUserPublickey } from '@/models/entities/UserPublickey.js'; +import type { MiUserPublickey } from '@/models/UserPublickey.js'; import { CacheService } from '@/core/CacheService.js'; -import type { MiNote } from '@/models/entities/Note.js'; +import type { MiNote } from '@/models/Note.js'; import { bindThis } from '@/decorators.js'; -import { MiLocalUser, MiRemoteUser } from '@/models/entities/User.js'; +import { MiLocalUser, MiRemoteUser } from '@/models/User.js'; import { getApId } from './type.js'; import { ApPersonService } from './models/ApPersonService.js'; import type { IObject } from './type.js'; diff --git a/packages/backend/src/core/activitypub/ApDeliverManagerService.ts b/packages/backend/src/core/activitypub/ApDeliverManagerService.ts index da1e17106..81003bcf1 100644 --- a/packages/backend/src/core/activitypub/ApDeliverManagerService.ts +++ b/packages/backend/src/core/activitypub/ApDeliverManagerService.ts @@ -6,8 +6,8 @@ import { Inject, Injectable } from '@nestjs/common'; import { IsNull, Not } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { FollowingsRepository } from '@/models/index.js'; -import type { MiLocalUser, MiRemoteUser, MiUser } from '@/models/entities/User.js'; +import type { FollowingsRepository } from '@/models/_.js'; +import type { MiLocalUser, MiRemoteUser, MiUser } from '@/models/User.js'; import { QueueService } from '@/core/QueueService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { bindThis } from '@/decorators.js'; diff --git a/packages/backend/src/core/activitypub/ApInboxService.ts b/packages/backend/src/core/activitypub/ApInboxService.ts index d29e2cd68..b921ee745 100644 --- a/packages/backend/src/core/activitypub/ApInboxService.ts +++ b/packages/backend/src/core/activitypub/ApInboxService.ts @@ -24,9 +24,9 @@ import { UtilityService } from '@/core/UtilityService.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { QueueService } from '@/core/QueueService.js'; -import type { UsersRepository, NotesRepository, FollowingsRepository, AbuseUserReportsRepository, FollowRequestsRepository } from '@/models/index.js'; +import type { UsersRepository, NotesRepository, FollowingsRepository, AbuseUserReportsRepository, FollowRequestsRepository } from '@/models/_.js'; import { bindThis } from '@/decorators.js'; -import type { MiRemoteUser } from '@/models/entities/User.js'; +import type { MiRemoteUser } from '@/models/User.js'; import { getApHrefNullable, getApId, getApIds, getApType, isAccept, isActor, isAdd, isAnnounce, isBlock, isCollection, isCollectionOrOrderedCollection, isCreate, isDelete, isFlag, isFollow, isLike, isMove, isPost, isReject, isRemove, isTombstone, isUndo, isUpdate, validActor, validPost } from './type.js'; import { ApNoteService } from './models/ApNoteService.js'; import { ApLoggerService } from './ApLoggerService.js'; diff --git a/packages/backend/src/core/activitypub/ApMfmService.ts b/packages/backend/src/core/activitypub/ApMfmService.ts index 5dd4b7f6d..60868627a 100644 --- a/packages/backend/src/core/activitypub/ApMfmService.ts +++ b/packages/backend/src/core/activitypub/ApMfmService.ts @@ -6,7 +6,7 @@ import { Injectable } from '@nestjs/common'; import * as mfm from 'mfm-js'; import { MfmService } from '@/core/MfmService.js'; -import type { MiNote } from '@/models/entities/Note.js'; +import type { MiNote } from '@/models/Note.js'; import { bindThis } from '@/decorators.js'; import { extractApHashtagObjects } from './models/tag.js'; import type { IObject } from './type.js'; diff --git a/packages/backend/src/core/activitypub/ApRendererService.ts b/packages/backend/src/core/activitypub/ApRendererService.ts index f345494ed..7a9d2e21d 100644 --- a/packages/backend/src/core/activitypub/ApRendererService.ts +++ b/packages/backend/src/core/activitypub/ApRendererService.ts @@ -9,21 +9,21 @@ import { In } from 'typeorm'; import * as mfm from 'mfm-js'; import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; -import type { MiPartialLocalUser, MiLocalUser, MiPartialRemoteUser, MiRemoteUser, MiUser } from '@/models/entities/User.js'; -import type { IMentionedRemoteUsers, MiNote } from '@/models/entities/Note.js'; -import type { MiBlocking } from '@/models/entities/Blocking.js'; -import type { MiRelay } from '@/models/entities/Relay.js'; -import type { MiDriveFile } from '@/models/entities/DriveFile.js'; -import type { MiNoteReaction } from '@/models/entities/NoteReaction.js'; -import type { MiEmoji } from '@/models/entities/Emoji.js'; -import type { MiPoll } from '@/models/entities/Poll.js'; -import type { MiPollVote } from '@/models/entities/PollVote.js'; +import type { MiPartialLocalUser, MiLocalUser, MiPartialRemoteUser, MiRemoteUser, MiUser } from '@/models/User.js'; +import type { IMentionedRemoteUsers, MiNote } from '@/models/Note.js'; +import type { MiBlocking } from '@/models/Blocking.js'; +import type { MiRelay } from '@/models/Relay.js'; +import type { MiDriveFile } from '@/models/DriveFile.js'; +import type { MiNoteReaction } from '@/models/NoteReaction.js'; +import type { MiEmoji } from '@/models/Emoji.js'; +import type { MiPoll } from '@/models/Poll.js'; +import type { MiPollVote } from '@/models/PollVote.js'; import { UserKeypairService } from '@/core/UserKeypairService.js'; import { MfmService } from '@/core/MfmService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js'; -import type { MiUserKeypair } from '@/models/entities/UserKeypair.js'; -import type { UsersRepository, UserProfilesRepository, NotesRepository, DriveFilesRepository, PollsRepository } from '@/models/index.js'; +import type { MiUserKeypair } from '@/models/UserKeypair.js'; +import type { UsersRepository, UserProfilesRepository, NotesRepository, DriveFilesRepository, PollsRepository } from '@/models/_.js'; import { bindThis } from '@/decorators.js'; import { CustomEmojiService } from '@/core/CustomEmojiService.js'; import { isNotNull } from '@/misc/is-not-null.js'; diff --git a/packages/backend/src/core/activitypub/ApRequestService.ts b/packages/backend/src/core/activitypub/ApRequestService.ts index fb44a55de..b59ce5241 100644 --- a/packages/backend/src/core/activitypub/ApRequestService.ts +++ b/packages/backend/src/core/activitypub/ApRequestService.ts @@ -8,7 +8,7 @@ import { URL } from 'node:url'; import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; -import type { MiUser } from '@/models/entities/User.js'; +import type { MiUser } from '@/models/User.js'; import { UserKeypairService } from '@/core/UserKeypairService.js'; import { HttpRequestService } from '@/core/HttpRequestService.js'; import { LoggerService } from '@/core/LoggerService.js'; diff --git a/packages/backend/src/core/activitypub/ApResolverService.ts b/packages/backend/src/core/activitypub/ApResolverService.ts index 34913fabe..9ca63c9ec 100644 --- a/packages/backend/src/core/activitypub/ApResolverService.ts +++ b/packages/backend/src/core/activitypub/ApResolverService.ts @@ -4,9 +4,10 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { MiLocalUser, MiRemoteUser } from '@/models/entities/User.js'; +import { IsNull, Not } from 'typeorm'; +import type { MiLocalUser, MiRemoteUser } from '@/models/User.js'; import { InstanceActorService } from '@/core/InstanceActorService.js'; -import type { NotesRepository, PollsRepository, NoteReactionsRepository, UsersRepository } from '@/models/index.js'; +import type { NotesRepository, PollsRepository, NoteReactionsRepository, UsersRepository, FollowRequestsRepository } from '@/models/_.js'; import type { Config } from '@/config.js'; import { MetaService } from '@/core/MetaService.js'; import { HttpRequestService } from '@/core/HttpRequestService.js'; @@ -32,6 +33,7 @@ export class Resolver { private notesRepository: NotesRepository, private pollsRepository: PollsRepository, private noteReactionsRepository: NoteReactionsRepository, + private followRequestsRepository: FollowRequestsRepository, private utilityService: UtilityService, private instanceActorService: InstanceActorService, private metaService: MetaService, @@ -146,13 +148,24 @@ export class Resolver { return this.noteReactionsRepository.findOneByOrFail({ id: parsed.id }).then(async reaction => this.apRendererService.addContext(await this.apRendererService.renderLike(reaction, { uri: null }))); case 'follows': - // rest should be - if (parsed.rest == null || !/^\w+$/.test(parsed.rest)) throw new Error('resolveLocal: invalid follow URI'); - - return Promise.all( - [parsed.id, parsed.rest].map(id => this.usersRepository.findOneByOrFail({ id })), - ) - .then(([follower, followee]) => this.apRendererService.addContext(this.apRendererService.renderFollow(follower as MiLocalUser | MiRemoteUser, followee as MiLocalUser | MiRemoteUser, url))); + return this.followRequestsRepository.findOneBy({ id: parsed.id }) + .then(async followRequest => { + if (followRequest == null) throw new Error('resolveLocal: invalid follow request ID'); + const [follower, followee] = await Promise.all([ + this.usersRepository.findOneBy({ + id: followRequest.followerId, + host: IsNull(), + }), + this.usersRepository.findOneBy({ + id: followRequest.followeeId, + host: Not(IsNull()), + }), + ]); + if (follower == null || followee == null) { + throw new Error('resolveLocal: follower or followee does not exist'); + } + return this.apRendererService.addContext(this.apRendererService.renderFollow(follower as MiLocalUser | MiRemoteUser, followee as MiLocalUser | MiRemoteUser, url)); + }); default: throw new Error(`resolveLocal: type ${parsed.type} unhandled`); } @@ -177,6 +190,9 @@ export class ApResolverService { @Inject(DI.noteReactionsRepository) private noteReactionsRepository: NoteReactionsRepository, + @Inject(DI.followRequestsRepository) + private followRequestsRepository: FollowRequestsRepository, + private utilityService: UtilityService, private instanceActorService: InstanceActorService, private metaService: MetaService, @@ -196,6 +212,7 @@ export class ApResolverService { this.notesRepository, this.pollsRepository, this.noteReactionsRepository, + this.followRequestsRepository, this.utilityService, this.instanceActorService, this.metaService, diff --git a/packages/backend/src/core/activitypub/models/ApImageService.ts b/packages/backend/src/core/activitypub/models/ApImageService.ts index fa17a778b..a4cd53389 100644 --- a/packages/backend/src/core/activitypub/models/ApImageService.ts +++ b/packages/backend/src/core/activitypub/models/ApImageService.ts @@ -5,9 +5,9 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { DriveFilesRepository } from '@/models/index.js'; -import type { MiRemoteUser } from '@/models/entities/User.js'; -import type { MiDriveFile } from '@/models/entities/DriveFile.js'; +import type { DriveFilesRepository } from '@/models/_.js'; +import type { MiRemoteUser } from '@/models/User.js'; +import type { MiDriveFile } from '@/models/DriveFile.js'; import { MetaService } from '@/core/MetaService.js'; import { truncate } from '@/misc/truncate.js'; import { DB_MAX_IMAGE_COMMENT_LENGTH } from '@/const.js'; diff --git a/packages/backend/src/core/activitypub/models/ApMentionService.ts b/packages/backend/src/core/activitypub/models/ApMentionService.ts index f4045301d..9aa8ba5ed 100644 --- a/packages/backend/src/core/activitypub/models/ApMentionService.ts +++ b/packages/backend/src/core/activitypub/models/ApMentionService.ts @@ -5,7 +5,7 @@ import { Injectable } from '@nestjs/common'; import promiseLimit from 'promise-limit'; -import type { MiUser } from '@/models/index.js'; +import type { MiUser } from '@/models/_.js'; import { toArray, unique } from '@/misc/prelude/array.js'; import { bindThis } from '@/decorators.js'; import { isMention } from '../type.js'; diff --git a/packages/backend/src/core/activitypub/models/ApNoteService.ts b/packages/backend/src/core/activitypub/models/ApNoteService.ts index 6a9c69696..573dff5b9 100644 --- a/packages/backend/src/core/activitypub/models/ApNoteService.ts +++ b/packages/backend/src/core/activitypub/models/ApNoteService.ts @@ -7,15 +7,15 @@ import { forwardRef, Inject, Injectable } from '@nestjs/common'; import promiseLimit from 'promise-limit'; import { In } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { PollsRepository, EmojisRepository } from '@/models/index.js'; +import type { PollsRepository, EmojisRepository } from '@/models/_.js'; import type { Config } from '@/config.js'; -import type { MiRemoteUser } from '@/models/entities/User.js'; -import type { MiNote } from '@/models/entities/Note.js'; +import type { MiRemoteUser } from '@/models/User.js'; +import type { MiNote } from '@/models/Note.js'; import { toArray, toSingle, unique } from '@/misc/prelude/array.js'; -import type { MiEmoji } from '@/models/entities/Emoji.js'; +import type { MiEmoji } from '@/models/Emoji.js'; import { MetaService } from '@/core/MetaService.js'; import { AppLockService } from '@/core/AppLockService.js'; -import type { MiDriveFile } from '@/models/entities/DriveFile.js'; +import type { MiDriveFile } from '@/models/DriveFile.js'; import { NoteCreateService } from '@/core/NoteCreateService.js'; import type Logger from '@/logger.js'; import { IdService } from '@/core/IdService.js'; diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts index ff0133993..ea6488339 100644 --- a/packages/backend/src/core/activitypub/models/ApPersonService.ts +++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts @@ -8,28 +8,28 @@ import promiseLimit from 'promise-limit'; import { DataSource } from 'typeorm'; import { ModuleRef } from '@nestjs/core'; import { DI } from '@/di-symbols.js'; -import type { FollowingsRepository, InstancesRepository, UserProfilesRepository, UserPublickeysRepository, UsersRepository } from '@/models/index.js'; +import type { FollowingsRepository, InstancesRepository, UserProfilesRepository, UserPublickeysRepository, UsersRepository } from '@/models/_.js'; import type { Config } from '@/config.js'; -import type { MiLocalUser, MiRemoteUser } from '@/models/entities/User.js'; -import { MiUser } from '@/models/entities/User.js'; +import type { MiLocalUser, MiRemoteUser } from '@/models/User.js'; +import { MiUser } from '@/models/User.js'; import { truncate } from '@/misc/truncate.js'; import type { CacheService } from '@/core/CacheService.js'; import { normalizeForSearch } from '@/misc/normalize-for-search.js'; import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js'; import type Logger from '@/logger.js'; -import type { MiNote } from '@/models/entities/Note.js'; +import type { MiNote } from '@/models/Note.js'; import type { IdService } from '@/core/IdService.js'; import type { MfmService } from '@/core/MfmService.js'; import { toArray } from '@/misc/prelude/array.js'; import type { GlobalEventService } from '@/core/GlobalEventService.js'; import type { FederatedInstanceService } from '@/core/FederatedInstanceService.js'; import type { FetchInstanceMetadataService } from '@/core/FetchInstanceMetadataService.js'; -import { MiUserProfile } from '@/models/entities/UserProfile.js'; -import { MiUserPublickey } from '@/models/entities/UserPublickey.js'; +import { MiUserProfile } from '@/models/UserProfile.js'; +import { MiUserPublickey } from '@/models/UserPublickey.js'; import type UsersChart from '@/core/chart/charts/users.js'; import type InstanceChart from '@/core/chart/charts/instance.js'; import type { HashtagService } from '@/core/HashtagService.js'; -import { MiUserNotePining } from '@/models/entities/UserNotePining.js'; +import { MiUserNotePining } from '@/models/UserNotePining.js'; import { StatusError } from '@/misc/status-error.js'; import type { UtilityService } from '@/core/UtilityService.js'; import type { UserEntityService } from '@/core/entities/UserEntityService.js'; diff --git a/packages/backend/src/core/activitypub/models/ApQuestionService.ts b/packages/backend/src/core/activitypub/models/ApQuestionService.ts index 8d8c0a581..27bd62268 100644 --- a/packages/backend/src/core/activitypub/models/ApQuestionService.ts +++ b/packages/backend/src/core/activitypub/models/ApQuestionService.ts @@ -5,9 +5,9 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { NotesRepository, PollsRepository } from '@/models/index.js'; +import type { NotesRepository, PollsRepository } from '@/models/_.js'; import type { Config } from '@/config.js'; -import type { IPoll } from '@/models/entities/Poll.js'; +import type { IPoll } from '@/models/Poll.js'; import type Logger from '@/logger.js'; import { bindThis } from '@/decorators.js'; import { isQuestion } from '../type.js'; diff --git a/packages/backend/src/core/chart/charts/active-users.ts b/packages/backend/src/core/chart/charts/active-users.ts index ff9db46bc..55da1469e 100644 --- a/packages/backend/src/core/chart/charts/active-users.ts +++ b/packages/backend/src/core/chart/charts/active-users.ts @@ -6,7 +6,7 @@ import { Injectable, Inject } from '@nestjs/common'; import { DataSource } from 'typeorm'; import { AppLockService } from '@/core/AppLockService.js'; -import type { MiUser } from '@/models/entities/User.js'; +import type { MiUser } from '@/models/User.js'; import { DI } from '@/di-symbols.js'; import { bindThis } from '@/decorators.js'; import Chart from '../core.js'; diff --git a/packages/backend/src/core/chart/charts/drive.ts b/packages/backend/src/core/chart/charts/drive.ts index 2fe0f7616..bbcbf1a95 100644 --- a/packages/backend/src/core/chart/charts/drive.ts +++ b/packages/backend/src/core/chart/charts/drive.ts @@ -5,7 +5,7 @@ import { Injectable, Inject } from '@nestjs/common'; import { DataSource } from 'typeorm'; -import type { MiDriveFile } from '@/models/entities/DriveFile.js'; +import type { MiDriveFile } from '@/models/DriveFile.js'; import { AppLockService } from '@/core/AppLockService.js'; import { DI } from '@/di-symbols.js'; import { bindThis } from '@/decorators.js'; diff --git a/packages/backend/src/core/chart/charts/federation.ts b/packages/backend/src/core/chart/charts/federation.ts index f7d084d3e..fc474b002 100644 --- a/packages/backend/src/core/chart/charts/federation.ts +++ b/packages/backend/src/core/chart/charts/federation.ts @@ -5,7 +5,7 @@ import { Injectable, Inject } from '@nestjs/common'; import { DataSource } from 'typeorm'; -import type { FollowingsRepository, InstancesRepository } from '@/models/index.js'; +import type { FollowingsRepository, InstancesRepository } from '@/models/_.js'; import { AppLockService } from '@/core/AppLockService.js'; import { DI } from '@/di-symbols.js'; import { MetaService } from '@/core/MetaService.js'; diff --git a/packages/backend/src/core/chart/charts/instance.ts b/packages/backend/src/core/chart/charts/instance.ts index 8dbb132e2..9df0afb02 100644 --- a/packages/backend/src/core/chart/charts/instance.ts +++ b/packages/backend/src/core/chart/charts/instance.ts @@ -5,9 +5,9 @@ import { Injectable, Inject } from '@nestjs/common'; import { DataSource } from 'typeorm'; -import type { DriveFilesRepository, FollowingsRepository, UsersRepository, NotesRepository } from '@/models/index.js'; -import type { MiDriveFile } from '@/models/entities/DriveFile.js'; -import type { MiNote } from '@/models/entities/Note.js'; +import type { DriveFilesRepository, FollowingsRepository, UsersRepository, NotesRepository } from '@/models/_.js'; +import type { MiDriveFile } from '@/models/DriveFile.js'; +import type { MiNote } from '@/models/Note.js'; import { AppLockService } from '@/core/AppLockService.js'; import { DI } from '@/di-symbols.js'; import { UtilityService } from '@/core/UtilityService.js'; diff --git a/packages/backend/src/core/chart/charts/notes.ts b/packages/backend/src/core/chart/charts/notes.ts index 31dfad224..df3295dba 100644 --- a/packages/backend/src/core/chart/charts/notes.ts +++ b/packages/backend/src/core/chart/charts/notes.ts @@ -5,8 +5,8 @@ import { Injectable, Inject } from '@nestjs/common'; import { Not, IsNull, DataSource } from 'typeorm'; -import type { NotesRepository } from '@/models/index.js'; -import type { MiNote } from '@/models/entities/Note.js'; +import type { NotesRepository } from '@/models/_.js'; +import type { MiNote } from '@/models/Note.js'; import { AppLockService } from '@/core/AppLockService.js'; import { DI } from '@/di-symbols.js'; import { bindThis } from '@/decorators.js'; diff --git a/packages/backend/src/core/chart/charts/per-user-drive.ts b/packages/backend/src/core/chart/charts/per-user-drive.ts index be5adc71c..18354359c 100644 --- a/packages/backend/src/core/chart/charts/per-user-drive.ts +++ b/packages/backend/src/core/chart/charts/per-user-drive.ts @@ -5,8 +5,8 @@ import { Injectable, Inject } from '@nestjs/common'; import { DataSource } from 'typeorm'; -import type { DriveFilesRepository } from '@/models/index.js'; -import type { MiDriveFile } from '@/models/entities/DriveFile.js'; +import type { DriveFilesRepository } from '@/models/_.js'; +import type { MiDriveFile } from '@/models/DriveFile.js'; import { AppLockService } from '@/core/AppLockService.js'; import { DI } from '@/di-symbols.js'; import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js'; diff --git a/packages/backend/src/core/chart/charts/per-user-following.ts b/packages/backend/src/core/chart/charts/per-user-following.ts index 7536e1dcb..79bff2cb6 100644 --- a/packages/backend/src/core/chart/charts/per-user-following.ts +++ b/packages/backend/src/core/chart/charts/per-user-following.ts @@ -5,11 +5,11 @@ import { Injectable, Inject } from '@nestjs/common'; import { Not, IsNull, DataSource } from 'typeorm'; -import type { MiUser } from '@/models/entities/User.js'; +import type { MiUser } from '@/models/User.js'; import { AppLockService } from '@/core/AppLockService.js'; import { DI } from '@/di-symbols.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; -import type { FollowingsRepository } from '@/models/index.js'; +import type { FollowingsRepository } from '@/models/_.js'; import { bindThis } from '@/decorators.js'; import Chart from '../core.js'; import { ChartLoggerService } from '../ChartLoggerService.js'; diff --git a/packages/backend/src/core/chart/charts/per-user-notes.ts b/packages/backend/src/core/chart/charts/per-user-notes.ts index 4a6dae769..0db0e6f07 100644 --- a/packages/backend/src/core/chart/charts/per-user-notes.ts +++ b/packages/backend/src/core/chart/charts/per-user-notes.ts @@ -5,11 +5,11 @@ import { Injectable, Inject } from '@nestjs/common'; import { DataSource } from 'typeorm'; -import type { MiUser } from '@/models/entities/User.js'; -import type { MiNote } from '@/models/entities/Note.js'; +import type { MiUser } from '@/models/User.js'; +import type { MiNote } from '@/models/Note.js'; import { AppLockService } from '@/core/AppLockService.js'; import { DI } from '@/di-symbols.js'; -import type { NotesRepository } from '@/models/index.js'; +import type { NotesRepository } from '@/models/_.js'; import { bindThis } from '@/decorators.js'; import Chart from '../core.js'; import { ChartLoggerService } from '../ChartLoggerService.js'; diff --git a/packages/backend/src/core/chart/charts/per-user-pv.ts b/packages/backend/src/core/chart/charts/per-user-pv.ts index ad01e0483..cf1b4c71f 100644 --- a/packages/backend/src/core/chart/charts/per-user-pv.ts +++ b/packages/backend/src/core/chart/charts/per-user-pv.ts @@ -5,7 +5,7 @@ import { Injectable, Inject } from '@nestjs/common'; import { DataSource } from 'typeorm'; -import type { MiUser } from '@/models/entities/User.js'; +import type { MiUser } from '@/models/User.js'; import { AppLockService } from '@/core/AppLockService.js'; import { DI } from '@/di-symbols.js'; import { bindThis } from '@/decorators.js'; diff --git a/packages/backend/src/core/chart/charts/per-user-reactions.ts b/packages/backend/src/core/chart/charts/per-user-reactions.ts index d6d54bef3..9f4f6e965 100644 --- a/packages/backend/src/core/chart/charts/per-user-reactions.ts +++ b/packages/backend/src/core/chart/charts/per-user-reactions.ts @@ -5,8 +5,8 @@ import { Injectable, Inject } from '@nestjs/common'; import { DataSource } from 'typeorm'; -import type { MiUser } from '@/models/entities/User.js'; -import type { MiNote } from '@/models/entities/Note.js'; +import type { MiUser } from '@/models/User.js'; +import type { MiNote } from '@/models/Note.js'; import { AppLockService } from '@/core/AppLockService.js'; import { DI } from '@/di-symbols.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; diff --git a/packages/backend/src/core/chart/charts/users.ts b/packages/backend/src/core/chart/charts/users.ts index ca1e93349..c2026c2ae 100644 --- a/packages/backend/src/core/chart/charts/users.ts +++ b/packages/backend/src/core/chart/charts/users.ts @@ -5,11 +5,11 @@ import { Injectable, Inject } from '@nestjs/common'; import { Not, IsNull, DataSource } from 'typeorm'; -import type { MiUser } from '@/models/entities/User.js'; +import type { MiUser } from '@/models/User.js'; import { AppLockService } from '@/core/AppLockService.js'; import { DI } from '@/di-symbols.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; -import type { UsersRepository } from '@/models/index.js'; +import type { UsersRepository } from '@/models/_.js'; import { bindThis } from '@/decorators.js'; import Chart from '../core.js'; import { ChartLoggerService } from '../ChartLoggerService.js'; diff --git a/packages/backend/src/core/entities/AbuseUserReportEntityService.ts b/packages/backend/src/core/entities/AbuseUserReportEntityService.ts index f9f11a62b..0e65a10d2 100644 --- a/packages/backend/src/core/entities/AbuseUserReportEntityService.ts +++ b/packages/backend/src/core/entities/AbuseUserReportEntityService.ts @@ -5,9 +5,9 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { AbuseUserReportsRepository } from '@/models/index.js'; +import type { AbuseUserReportsRepository } from '@/models/_.js'; import { awaitAll } from '@/misc/prelude/await-all.js'; -import type { MiAbuseUserReport } from '@/models/entities/AbuseUserReport.js'; +import type { MiAbuseUserReport } from '@/models/AbuseUserReport.js'; import { bindThis } from '@/decorators.js'; import { UserEntityService } from './UserEntityService.js'; diff --git a/packages/backend/src/core/entities/AntennaEntityService.ts b/packages/backend/src/core/entities/AntennaEntityService.ts index 7826ca5d7..ed108f2ce 100644 --- a/packages/backend/src/core/entities/AntennaEntityService.ts +++ b/packages/backend/src/core/entities/AntennaEntityService.ts @@ -5,9 +5,9 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { AntennasRepository } from '@/models/index.js'; +import type { AntennasRepository } from '@/models/_.js'; import type { Packed } from '@/misc/json-schema.js'; -import type { MiAntenna } from '@/models/entities/Antenna.js'; +import type { MiAntenna } from '@/models/Antenna.js'; import { bindThis } from '@/decorators.js'; @Injectable() diff --git a/packages/backend/src/core/entities/AppEntityService.ts b/packages/backend/src/core/entities/AppEntityService.ts index cdcbc635a..14a93cda5 100644 --- a/packages/backend/src/core/entities/AppEntityService.ts +++ b/packages/backend/src/core/entities/AppEntityService.ts @@ -5,10 +5,10 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { AccessTokensRepository, AppsRepository } from '@/models/index.js'; +import type { AccessTokensRepository, AppsRepository } from '@/models/_.js'; import type { Packed } from '@/misc/json-schema.js'; -import type { MiApp } from '@/models/entities/App.js'; -import type { MiUser } from '@/models/entities/User.js'; +import type { MiApp } from '@/models/App.js'; +import type { MiUser } from '@/models/User.js'; import { bindThis } from '@/decorators.js'; @Injectable() diff --git a/packages/backend/src/core/entities/AuthSessionEntityService.ts b/packages/backend/src/core/entities/AuthSessionEntityService.ts index f6bac7f04..fd356cc89 100644 --- a/packages/backend/src/core/entities/AuthSessionEntityService.ts +++ b/packages/backend/src/core/entities/AuthSessionEntityService.ts @@ -5,10 +5,10 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { AuthSessionsRepository } from '@/models/index.js'; +import type { AuthSessionsRepository } from '@/models/_.js'; import { awaitAll } from '@/misc/prelude/await-all.js'; -import type { MiAuthSession } from '@/models/entities/AuthSession.js'; -import type { MiUser } from '@/models/entities/User.js'; +import type { MiAuthSession } from '@/models/AuthSession.js'; +import type { MiUser } from '@/models/User.js'; import { bindThis } from '@/decorators.js'; import { AppEntityService } from './AppEntityService.js'; diff --git a/packages/backend/src/core/entities/BlockingEntityService.ts b/packages/backend/src/core/entities/BlockingEntityService.ts index 4a810a2f0..44466e24e 100644 --- a/packages/backend/src/core/entities/BlockingEntityService.ts +++ b/packages/backend/src/core/entities/BlockingEntityService.ts @@ -5,11 +5,11 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { BlockingsRepository } from '@/models/index.js'; +import type { BlockingsRepository } from '@/models/_.js'; import { awaitAll } from '@/misc/prelude/await-all.js'; import type { Packed } from '@/misc/json-schema.js'; -import type { MiBlocking } from '@/models/entities/Blocking.js'; -import type { MiUser } from '@/models/entities/User.js'; +import type { MiBlocking } from '@/models/Blocking.js'; +import type { MiUser } from '@/models/User.js'; import { bindThis } from '@/decorators.js'; import { UserEntityService } from './UserEntityService.js'; diff --git a/packages/backend/src/core/entities/ChannelEntityService.ts b/packages/backend/src/core/entities/ChannelEntityService.ts index e4586d194..094de4d2d 100644 --- a/packages/backend/src/core/entities/ChannelEntityService.ts +++ b/packages/backend/src/core/entities/ChannelEntityService.ts @@ -5,11 +5,11 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { ChannelFavoritesRepository, ChannelFollowingsRepository, ChannelsRepository, DriveFilesRepository, NoteUnreadsRepository, NotesRepository } from '@/models/index.js'; +import type { ChannelFavoritesRepository, ChannelFollowingsRepository, ChannelsRepository, DriveFilesRepository, NoteUnreadsRepository, NotesRepository } from '@/models/_.js'; import type { Packed } from '@/misc/json-schema.js'; -import type { } from '@/models/entities/Blocking.js'; -import type { MiUser } from '@/models/entities/User.js'; -import type { MiChannel } from '@/models/entities/Channel.js'; +import type { } from '@/models/Blocking.js'; +import type { MiUser } from '@/models/User.js'; +import type { MiChannel } from '@/models/Channel.js'; import { bindThis } from '@/decorators.js'; import { DriveFileEntityService } from './DriveFileEntityService.js'; import { NoteEntityService } from './NoteEntityService.js'; diff --git a/packages/backend/src/core/entities/ClipEntityService.ts b/packages/backend/src/core/entities/ClipEntityService.ts index 63619ac9d..e141db03f 100644 --- a/packages/backend/src/core/entities/ClipEntityService.ts +++ b/packages/backend/src/core/entities/ClipEntityService.ts @@ -5,11 +5,11 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { ClipFavoritesRepository, ClipsRepository, MiUser } from '@/models/index.js'; +import type { ClipFavoritesRepository, ClipsRepository, MiUser } from '@/models/_.js'; import { awaitAll } from '@/misc/prelude/await-all.js'; import type { Packed } from '@/misc/json-schema.js'; -import type { } from '@/models/entities/Blocking.js'; -import type { MiClip } from '@/models/entities/Clip.js'; +import type { } from '@/models/Blocking.js'; +import type { MiClip } from '@/models/Clip.js'; import { bindThis } from '@/decorators.js'; import { UserEntityService } from './UserEntityService.js'; diff --git a/packages/backend/src/core/entities/DriveFileEntityService.ts b/packages/backend/src/core/entities/DriveFileEntityService.ts index a09de58b4..23273b041 100644 --- a/packages/backend/src/core/entities/DriveFileEntityService.ts +++ b/packages/backend/src/core/entities/DriveFileEntityService.ts @@ -6,12 +6,12 @@ import { forwardRef, Inject, Injectable } from '@nestjs/common'; import { In } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { DriveFilesRepository } from '@/models/index.js'; +import type { DriveFilesRepository } from '@/models/_.js'; import type { Config } from '@/config.js'; import type { Packed } from '@/misc/json-schema.js'; import { awaitAll } from '@/misc/prelude/await-all.js'; -import type { MiUser } from '@/models/entities/User.js'; -import type { MiDriveFile } from '@/models/entities/DriveFile.js'; +import type { MiUser } from '@/models/User.js'; +import type { MiDriveFile } from '@/models/DriveFile.js'; import { appendQuery, query } from '@/misc/prelude/url.js'; import { deepClone } from '@/misc/clone.js'; import { bindThis } from '@/decorators.js'; diff --git a/packages/backend/src/core/entities/DriveFolderEntityService.ts b/packages/backend/src/core/entities/DriveFolderEntityService.ts index da401c41f..55014284b 100644 --- a/packages/backend/src/core/entities/DriveFolderEntityService.ts +++ b/packages/backend/src/core/entities/DriveFolderEntityService.ts @@ -5,11 +5,11 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { DriveFilesRepository, DriveFoldersRepository } from '@/models/index.js'; +import type { DriveFilesRepository, DriveFoldersRepository } from '@/models/_.js'; import { awaitAll } from '@/misc/prelude/await-all.js'; import type { Packed } from '@/misc/json-schema.js'; -import type { } from '@/models/entities/Blocking.js'; -import type { MiDriveFolder } from '@/models/entities/DriveFolder.js'; +import type { } from '@/models/Blocking.js'; +import type { MiDriveFolder } from '@/models/DriveFolder.js'; import { bindThis } from '@/decorators.js'; @Injectable() diff --git a/packages/backend/src/core/entities/EmojiEntityService.ts b/packages/backend/src/core/entities/EmojiEntityService.ts index cabd46b95..5b97cfad5 100644 --- a/packages/backend/src/core/entities/EmojiEntityService.ts +++ b/packages/backend/src/core/entities/EmojiEntityService.ts @@ -5,10 +5,10 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { EmojisRepository } from '@/models/index.js'; +import type { EmojisRepository } from '@/models/_.js'; import type { Packed } from '@/misc/json-schema.js'; -import type { } from '@/models/entities/Blocking.js'; -import type { MiEmoji } from '@/models/entities/Emoji.js'; +import type { } from '@/models/Blocking.js'; +import type { MiEmoji } from '@/models/Emoji.js'; import { bindThis } from '@/decorators.js'; @Injectable() diff --git a/packages/backend/src/core/entities/FlashEntityService.ts b/packages/backend/src/core/entities/FlashEntityService.ts index be0d176af..4701cddcb 100644 --- a/packages/backend/src/core/entities/FlashEntityService.ts +++ b/packages/backend/src/core/entities/FlashEntityService.ts @@ -5,12 +5,12 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { FlashsRepository, FlashLikesRepository } from '@/models/index.js'; +import type { FlashsRepository, FlashLikesRepository } from '@/models/_.js'; import { awaitAll } from '@/misc/prelude/await-all.js'; import type { Packed } from '@/misc/json-schema.js'; -import type { } from '@/models/entities/Blocking.js'; -import type { MiUser } from '@/models/entities/User.js'; -import type { MiFlash } from '@/models/entities/Flash.js'; +import type { } from '@/models/Blocking.js'; +import type { MiUser } from '@/models/User.js'; +import type { MiFlash } from '@/models/Flash.js'; import { bindThis } from '@/decorators.js'; import { UserEntityService } from './UserEntityService.js'; diff --git a/packages/backend/src/core/entities/FlashLikeEntityService.ts b/packages/backend/src/core/entities/FlashLikeEntityService.ts index 0db82fee0..2eff86217 100644 --- a/packages/backend/src/core/entities/FlashLikeEntityService.ts +++ b/packages/backend/src/core/entities/FlashLikeEntityService.ts @@ -5,10 +5,10 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { FlashLikesRepository } from '@/models/index.js'; -import type { } from '@/models/entities/Blocking.js'; -import type { MiUser } from '@/models/entities/User.js'; -import type { MiFlashLike } from '@/models/entities/FlashLike.js'; +import type { FlashLikesRepository } from '@/models/_.js'; +import type { } from '@/models/Blocking.js'; +import type { MiUser } from '@/models/User.js'; +import type { MiFlashLike } from '@/models/FlashLike.js'; import { bindThis } from '@/decorators.js'; import { FlashEntityService } from './FlashEntityService.js'; diff --git a/packages/backend/src/core/entities/FollowRequestEntityService.ts b/packages/backend/src/core/entities/FollowRequestEntityService.ts index bcf0deb5b..0e0fec9f4 100644 --- a/packages/backend/src/core/entities/FollowRequestEntityService.ts +++ b/packages/backend/src/core/entities/FollowRequestEntityService.ts @@ -5,10 +5,10 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { FollowRequestsRepository } from '@/models/index.js'; -import type { } from '@/models/entities/Blocking.js'; -import type { MiUser } from '@/models/entities/User.js'; -import type { MiFollowRequest } from '@/models/entities/FollowRequest.js'; +import type { FollowRequestsRepository } from '@/models/_.js'; +import type { } from '@/models/Blocking.js'; +import type { MiUser } from '@/models/User.js'; +import type { MiFollowRequest } from '@/models/FollowRequest.js'; import { bindThis } from '@/decorators.js'; import { UserEntityService } from './UserEntityService.js'; diff --git a/packages/backend/src/core/entities/FollowingEntityService.ts b/packages/backend/src/core/entities/FollowingEntityService.ts index d292584ac..9f6eb51e8 100644 --- a/packages/backend/src/core/entities/FollowingEntityService.ts +++ b/packages/backend/src/core/entities/FollowingEntityService.ts @@ -5,12 +5,12 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { FollowingsRepository } from '@/models/index.js'; +import type { FollowingsRepository } from '@/models/_.js'; import { awaitAll } from '@/misc/prelude/await-all.js'; import type { Packed } from '@/misc/json-schema.js'; -import type { } from '@/models/entities/Blocking.js'; -import type { MiUser } from '@/models/entities/User.js'; -import type { MiFollowing } from '@/models/entities/Following.js'; +import type { } from '@/models/Blocking.js'; +import type { MiUser } from '@/models/User.js'; +import type { MiFollowing } from '@/models/Following.js'; import { bindThis } from '@/decorators.js'; import { UserEntityService } from './UserEntityService.js'; diff --git a/packages/backend/src/core/entities/GalleryLikeEntityService.ts b/packages/backend/src/core/entities/GalleryLikeEntityService.ts index 68d50606f..e74070188 100644 --- a/packages/backend/src/core/entities/GalleryLikeEntityService.ts +++ b/packages/backend/src/core/entities/GalleryLikeEntityService.ts @@ -5,9 +5,9 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { GalleryLikesRepository } from '@/models/index.js'; -import type { } from '@/models/entities/Blocking.js'; -import type { MiGalleryLike } from '@/models/entities/GalleryLike.js'; +import type { GalleryLikesRepository } from '@/models/_.js'; +import type { } from '@/models/Blocking.js'; +import type { MiGalleryLike } from '@/models/GalleryLike.js'; import { bindThis } from '@/decorators.js'; import { GalleryPostEntityService } from './GalleryPostEntityService.js'; diff --git a/packages/backend/src/core/entities/GalleryPostEntityService.ts b/packages/backend/src/core/entities/GalleryPostEntityService.ts index 35d1a11f5..bbaf70f0f 100644 --- a/packages/backend/src/core/entities/GalleryPostEntityService.ts +++ b/packages/backend/src/core/entities/GalleryPostEntityService.ts @@ -5,12 +5,12 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { GalleryLikesRepository, GalleryPostsRepository } from '@/models/index.js'; +import type { GalleryLikesRepository, GalleryPostsRepository } from '@/models/_.js'; import { awaitAll } from '@/misc/prelude/await-all.js'; import type { Packed } from '@/misc/json-schema.js'; -import type { } from '@/models/entities/Blocking.js'; -import type { MiUser } from '@/models/entities/User.js'; -import type { MiGalleryPost } from '@/models/entities/GalleryPost.js'; +import type { } from '@/models/Blocking.js'; +import type { MiUser } from '@/models/User.js'; +import type { MiGalleryPost } from '@/models/GalleryPost.js'; import { bindThis } from '@/decorators.js'; import { UserEntityService } from './UserEntityService.js'; import { DriveFileEntityService } from './DriveFileEntityService.js'; diff --git a/packages/backend/src/core/entities/HashtagEntityService.ts b/packages/backend/src/core/entities/HashtagEntityService.ts index 21c5d1392..006e267b1 100644 --- a/packages/backend/src/core/entities/HashtagEntityService.ts +++ b/packages/backend/src/core/entities/HashtagEntityService.ts @@ -5,8 +5,8 @@ import { Injectable } from '@nestjs/common'; import type { Packed } from '@/misc/json-schema.js'; -import type { } from '@/models/entities/Blocking.js'; -import type { MiHashtag } from '@/models/entities/Hashtag.js'; +import type { } from '@/models/Blocking.js'; +import type { MiHashtag } from '@/models/Hashtag.js'; import { bindThis } from '@/decorators.js'; @Injectable() diff --git a/packages/backend/src/core/entities/InstanceEntityService.ts b/packages/backend/src/core/entities/InstanceEntityService.ts index 1de7564b0..0e27e9df7 100644 --- a/packages/backend/src/core/entities/InstanceEntityService.ts +++ b/packages/backend/src/core/entities/InstanceEntityService.ts @@ -5,8 +5,8 @@ import { Injectable } from '@nestjs/common'; import type { Packed } from '@/misc/json-schema.js'; -import type { } from '@/models/entities/Blocking.js'; -import type { MiInstance } from '@/models/entities/Instance.js'; +import type { } from '@/models/Blocking.js'; +import type { MiInstance } from '@/models/Instance.js'; import { MetaService } from '@/core/MetaService.js'; import { bindThis } from '@/decorators.js'; import { UtilityService } from '../UtilityService.js'; diff --git a/packages/backend/src/core/entities/InviteCodeEntityService.ts b/packages/backend/src/core/entities/InviteCodeEntityService.ts index 03248ada7..914eaafe6 100644 --- a/packages/backend/src/core/entities/InviteCodeEntityService.ts +++ b/packages/backend/src/core/entities/InviteCodeEntityService.ts @@ -5,11 +5,11 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { RegistrationTicketsRepository } from '@/models/index.js'; +import type { RegistrationTicketsRepository } from '@/models/_.js'; import { awaitAll } from '@/misc/prelude/await-all.js'; import type { Packed } from '@/misc/json-schema.js'; -import type { MiUser } from '@/models/entities/User.js'; -import type { MiRegistrationTicket } from '@/models/entities/RegistrationTicket.js'; +import type { MiUser } from '@/models/User.js'; +import type { MiRegistrationTicket } from '@/models/RegistrationTicket.js'; import { bindThis } from '@/decorators.js'; import { UserEntityService } from './UserEntityService.js'; diff --git a/packages/backend/src/core/entities/ModerationLogEntityService.ts b/packages/backend/src/core/entities/ModerationLogEntityService.ts index 399de8d4d..83b024d83 100644 --- a/packages/backend/src/core/entities/ModerationLogEntityService.ts +++ b/packages/backend/src/core/entities/ModerationLogEntityService.ts @@ -5,10 +5,10 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { ModerationLogsRepository } from '@/models/index.js'; +import type { ModerationLogsRepository } from '@/models/_.js'; import { awaitAll } from '@/misc/prelude/await-all.js'; -import type { } from '@/models/entities/Blocking.js'; -import type { MiModerationLog } from '@/models/entities/ModerationLog.js'; +import type { } from '@/models/Blocking.js'; +import type { MiModerationLog } from '@/models/ModerationLog.js'; import { bindThis } from '@/decorators.js'; import { UserEntityService } from './UserEntityService.js'; diff --git a/packages/backend/src/core/entities/MutingEntityService.ts b/packages/backend/src/core/entities/MutingEntityService.ts index 423904410..e3d5d2e21 100644 --- a/packages/backend/src/core/entities/MutingEntityService.ts +++ b/packages/backend/src/core/entities/MutingEntityService.ts @@ -5,12 +5,12 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { MutingsRepository } from '@/models/index.js'; +import type { MutingsRepository } from '@/models/_.js'; import { awaitAll } from '@/misc/prelude/await-all.js'; import type { Packed } from '@/misc/json-schema.js'; -import type { } from '@/models/entities/Blocking.js'; -import type { MiUser } from '@/models/entities/User.js'; -import type { MiMuting } from '@/models/entities/Muting.js'; +import type { } from '@/models/Blocking.js'; +import type { MiUser } from '@/models/User.js'; +import type { MiMuting } from '@/models/Muting.js'; import { bindThis } from '@/decorators.js'; import { UserEntityService } from './UserEntityService.js'; diff --git a/packages/backend/src/core/entities/NoteEntityService.ts b/packages/backend/src/core/entities/NoteEntityService.ts index 52c1378b6..bf42e98ce 100644 --- a/packages/backend/src/core/entities/NoteEntityService.ts +++ b/packages/backend/src/core/entities/NoteEntityService.ts @@ -11,10 +11,10 @@ import { DI } from '@/di-symbols.js'; import type { Packed } from '@/misc/json-schema.js'; import { nyaize } from '@/misc/nyaize.js'; import { awaitAll } from '@/misc/prelude/await-all.js'; -import type { MiUser } from '@/models/entities/User.js'; -import type { MiNote } from '@/models/entities/Note.js'; -import type { MiNoteReaction } from '@/models/entities/NoteReaction.js'; -import type { UsersRepository, NotesRepository, FollowingsRepository, PollsRepository, PollVotesRepository, NoteReactionsRepository, ChannelsRepository } from '@/models/index.js'; +import type { MiUser } from '@/models/User.js'; +import type { MiNote } from '@/models/Note.js'; +import type { MiNoteReaction } from '@/models/NoteReaction.js'; +import type { UsersRepository, NotesRepository, FollowingsRepository, PollsRepository, PollVotesRepository, NoteReactionsRepository, ChannelsRepository } from '@/models/_.js'; import { bindThis } from '@/decorators.js'; import { isNotNull } from '@/misc/is-not-null.js'; import type { OnModuleInit } from '@nestjs/common'; @@ -340,6 +340,8 @@ export class NoteEntityService implements OnModuleInit { url: note.url ?? undefined, ...(opts.detail ? { + clippedCount: note.clippedCount, + reply: note.replyId ? this.pack(note.reply ?? note.replyId, me, { detail: false, _hint_: options?._hint_, diff --git a/packages/backend/src/core/entities/NoteFavoriteEntityService.ts b/packages/backend/src/core/entities/NoteFavoriteEntityService.ts index c0f43cac9..808c8c9f6 100644 --- a/packages/backend/src/core/entities/NoteFavoriteEntityService.ts +++ b/packages/backend/src/core/entities/NoteFavoriteEntityService.ts @@ -5,10 +5,10 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { NoteFavoritesRepository } from '@/models/index.js'; -import type { } from '@/models/entities/Blocking.js'; -import type { MiUser } from '@/models/entities/User.js'; -import type { MiNoteFavorite } from '@/models/entities/NoteFavorite.js'; +import type { NoteFavoritesRepository } from '@/models/_.js'; +import type { } from '@/models/Blocking.js'; +import type { MiUser } from '@/models/User.js'; +import type { MiNoteFavorite } from '@/models/NoteFavorite.js'; import { bindThis } from '@/decorators.js'; import { NoteEntityService } from './NoteEntityService.js'; diff --git a/packages/backend/src/core/entities/NoteReactionEntityService.ts b/packages/backend/src/core/entities/NoteReactionEntityService.ts index c50533a32..9701f37fd 100644 --- a/packages/backend/src/core/entities/NoteReactionEntityService.ts +++ b/packages/backend/src/core/entities/NoteReactionEntityService.ts @@ -5,13 +5,13 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { NoteReactionsRepository } from '@/models/index.js'; +import type { NoteReactionsRepository } from '@/models/_.js'; import type { Packed } from '@/misc/json-schema.js'; import { bindThis } from '@/decorators.js'; import type { OnModuleInit } from '@nestjs/common'; -import type { } from '@/models/entities/Blocking.js'; -import type { MiUser } from '@/models/entities/User.js'; -import type { MiNoteReaction } from '@/models/entities/NoteReaction.js'; +import type { } from '@/models/Blocking.js'; +import type { MiUser } from '@/models/User.js'; +import type { MiNoteReaction } from '@/models/NoteReaction.js'; import type { ReactionService } from '../ReactionService.js'; import type { UserEntityService } from './UserEntityService.js'; import type { NoteEntityService } from './NoteEntityService.js'; diff --git a/packages/backend/src/core/entities/NotificationEntityService.ts b/packages/backend/src/core/entities/NotificationEntityService.ts index 42419d61a..3ee7c91f3 100644 --- a/packages/backend/src/core/entities/NotificationEntityService.ts +++ b/packages/backend/src/core/entities/NotificationEntityService.ts @@ -7,10 +7,10 @@ import { Inject, Injectable } from '@nestjs/common'; import { ModuleRef } from '@nestjs/core'; import { In } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { AccessTokensRepository, FollowRequestsRepository, NotesRepository, MiUser, UsersRepository } from '@/models/index.js'; +import type { AccessTokensRepository, FollowRequestsRepository, NotesRepository, MiUser, UsersRepository } from '@/models/_.js'; import { awaitAll } from '@/misc/prelude/await-all.js'; -import type { MiNotification } from '@/models/entities/Notification.js'; -import type { MiNote } from '@/models/entities/Note.js'; +import type { MiNotification } from '@/models/Notification.js'; +import type { MiNote } from '@/models/Note.js'; import type { Packed } from '@/misc/json-schema.js'; import { bindThis } from '@/decorators.js'; import { isNotNull } from '@/misc/is-not-null.js'; @@ -20,7 +20,7 @@ import type { CustomEmojiService } from '../CustomEmojiService.js'; import type { UserEntityService } from './UserEntityService.js'; import type { NoteEntityService } from './NoteEntityService.js'; -const NOTE_REQUIRED_NOTIFICATION_TYPES = new Set(['mention', 'reply', 'renote', 'quote', 'reaction', 'pollEnded'] as (typeof notificationTypes[number])[]); +const NOTE_REQUIRED_NOTIFICATION_TYPES = new Set(['note', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollEnded'] as (typeof notificationTypes[number])[]); @Injectable() export class NotificationEntityService implements OnModuleInit { diff --git a/packages/backend/src/core/entities/PageEntityService.ts b/packages/backend/src/core/entities/PageEntityService.ts index 382ff31b4..e3a1e19dd 100644 --- a/packages/backend/src/core/entities/PageEntityService.ts +++ b/packages/backend/src/core/entities/PageEntityService.ts @@ -5,13 +5,13 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { DriveFilesRepository, PagesRepository, PageLikesRepository } from '@/models/index.js'; +import type { DriveFilesRepository, PagesRepository, PageLikesRepository } from '@/models/_.js'; import { awaitAll } from '@/misc/prelude/await-all.js'; import type { Packed } from '@/misc/json-schema.js'; -import type { } from '@/models/entities/Blocking.js'; -import type { MiUser } from '@/models/entities/User.js'; -import type { MiPage } from '@/models/entities/Page.js'; -import type { MiDriveFile } from '@/models/entities/DriveFile.js'; +import type { } from '@/models/Blocking.js'; +import type { MiUser } from '@/models/User.js'; +import type { MiPage } from '@/models/Page.js'; +import type { MiDriveFile } from '@/models/DriveFile.js'; import { bindThis } from '@/decorators.js'; import { UserEntityService } from './UserEntityService.js'; import { DriveFileEntityService } from './DriveFileEntityService.js'; diff --git a/packages/backend/src/core/entities/PageLikeEntityService.ts b/packages/backend/src/core/entities/PageLikeEntityService.ts index 4af0deb06..4dc691ab9 100644 --- a/packages/backend/src/core/entities/PageLikeEntityService.ts +++ b/packages/backend/src/core/entities/PageLikeEntityService.ts @@ -5,10 +5,10 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { PageLikesRepository } from '@/models/index.js'; -import type { } from '@/models/entities/Blocking.js'; -import type { MiUser } from '@/models/entities/User.js'; -import type { MiPageLike } from '@/models/entities/PageLike.js'; +import type { PageLikesRepository } from '@/models/_.js'; +import type { } from '@/models/Blocking.js'; +import type { MiUser } from '@/models/User.js'; +import type { MiPageLike } from '@/models/PageLike.js'; import { bindThis } from '@/decorators.js'; import { PageEntityService } from './PageEntityService.js'; diff --git a/packages/backend/src/core/entities/RenoteMutingEntityService.ts b/packages/backend/src/core/entities/RenoteMutingEntityService.ts index ddc5b971c..7111fab08 100644 --- a/packages/backend/src/core/entities/RenoteMutingEntityService.ts +++ b/packages/backend/src/core/entities/RenoteMutingEntityService.ts @@ -5,12 +5,12 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { RenoteMutingsRepository } from '@/models/index.js'; +import type { RenoteMutingsRepository } from '@/models/_.js'; import { awaitAll } from '@/misc/prelude/await-all.js'; import type { Packed } from '@/misc/json-schema.js'; -import type { } from '@/models/entities/Blocking.js'; -import type { MiUser } from '@/models/entities/User.js'; -import type { MiRenoteMuting } from '@/models/entities/RenoteMuting.js'; +import type { } from '@/models/Blocking.js'; +import type { MiUser } from '@/models/User.js'; +import type { MiRenoteMuting } from '@/models/RenoteMuting.js'; import { bindThis } from '@/decorators.js'; import { UserEntityService } from './UserEntityService.js'; diff --git a/packages/backend/src/core/entities/RoleEntityService.ts b/packages/backend/src/core/entities/RoleEntityService.ts index cd6ecee4c..23e82561d 100644 --- a/packages/backend/src/core/entities/RoleEntityService.ts +++ b/packages/backend/src/core/entities/RoleEntityService.ts @@ -6,10 +6,10 @@ import { Inject, Injectable } from '@nestjs/common'; import { Brackets } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { RoleAssignmentsRepository, RolesRepository } from '@/models/index.js'; +import type { RoleAssignmentsRepository, RolesRepository } from '@/models/_.js'; import { awaitAll } from '@/misc/prelude/await-all.js'; -import type { MiUser } from '@/models/entities/User.js'; -import type { MiRole } from '@/models/entities/Role.js'; +import type { MiUser } from '@/models/User.js'; +import type { MiRole } from '@/models/Role.js'; import { bindThis } from '@/decorators.js'; import { DEFAULT_POLICIES } from '@/core/RoleService.js'; diff --git a/packages/backend/src/core/entities/SigninEntityService.ts b/packages/backend/src/core/entities/SigninEntityService.ts index 59ad57e4a..8c88e8560 100644 --- a/packages/backend/src/core/entities/SigninEntityService.ts +++ b/packages/backend/src/core/entities/SigninEntityService.ts @@ -4,8 +4,8 @@ */ import { Injectable } from '@nestjs/common'; -import type { } from '@/models/entities/Blocking.js'; -import type { MiSignin } from '@/models/entities/Signin.js'; +import type { } from '@/models/Blocking.js'; +import type { MiSignin } from '@/models/Signin.js'; import { bindThis } from '@/decorators.js'; @Injectable() diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts index d12fd1b62..3dd64ce62 100644 --- a/packages/backend/src/core/entities/UserEntityService.ts +++ b/packages/backend/src/core/entities/UserEntityService.ts @@ -13,9 +13,9 @@ import type { Packed } from '@/misc/json-schema.js'; import type { Promiseable } from '@/misc/prelude/await-all.js'; import { awaitAll } from '@/misc/prelude/await-all.js'; import { USER_ACTIVE_THRESHOLD, USER_ONLINE_THRESHOLD } from '@/const.js'; -import type { MiLocalUser, MiPartialLocalUser, MiPartialRemoteUser, MiRemoteUser, MiUser } from '@/models/entities/User.js'; -import { birthdaySchema, descriptionSchema, localUsernameSchema, locationSchema, nameSchema, passwordSchema } from '@/models/entities/User.js'; -import type { UsersRepository, UserSecurityKeysRepository, FollowingsRepository, FollowRequestsRepository, BlockingsRepository, MutingsRepository, DriveFilesRepository, NoteUnreadsRepository, UserNotePiningsRepository, UserProfilesRepository, AnnouncementReadsRepository, AnnouncementsRepository, MiUserProfile, RenoteMutingsRepository, UserMemoRepository } from '@/models/index.js'; +import type { MiLocalUser, MiPartialLocalUser, MiPartialRemoteUser, MiRemoteUser, MiUser } from '@/models/User.js'; +import { birthdaySchema, descriptionSchema, localUsernameSchema, locationSchema, nameSchema, passwordSchema } from '@/models/User.js'; +import type { UsersRepository, UserSecurityKeysRepository, FollowingsRepository, FollowRequestsRepository, BlockingsRepository, MutingsRepository, DriveFilesRepository, NoteUnreadsRepository, UserNotePiningsRepository, UserProfilesRepository, AnnouncementReadsRepository, AnnouncementsRepository, MiUserProfile, RenoteMutingsRepository, UserMemoRepository } from '@/models/_.js'; import { bindThis } from '@/decorators.js'; import { RoleService } from '@/core/RoleService.js'; import { ApPersonService } from '@/core/activitypub/models/ApPersonService.js'; @@ -146,15 +146,14 @@ export class UserEntityService implements OnModuleInit { @bindThis public async getRelation(me: MiUser['id'], target: MiUser['id']) { + const following = await this.followingsRepository.findOneBy({ + followerId: me, + followeeId: target, + }); return awaitAll({ id: target, - isFollowing: this.followingsRepository.count({ - where: { - followerId: me, - followeeId: target, - }, - take: 1, - }).then(n => n > 0), + following, + isFollowing: following != null, isFollowed: this.followingsRepository.count({ where: { followerId: target, @@ -384,6 +383,7 @@ export class UserEntityService implements OnModuleInit { birthday: profile!.birthday, lang: profile!.lang, fields: profile!.fields, + verifiedLinks: profile!.verifiedLinks, followersCount: followersCount ?? 0, followingCount: followingCount ?? 0, notesCount: user.notesCount, @@ -485,6 +485,7 @@ export class UserEntityService implements OnModuleInit { isBlocked: relation.isBlocked, isMuted: relation.isMuted, isRenoteMuted: relation.isRenoteMuted, + notify: relation.following?.notify ?? 'none', } : {}), } as Promiseable> as Promiseable>; diff --git a/packages/backend/src/core/entities/UserListEntityService.ts b/packages/backend/src/core/entities/UserListEntityService.ts index d1d9838df..a7f288519 100644 --- a/packages/backend/src/core/entities/UserListEntityService.ts +++ b/packages/backend/src/core/entities/UserListEntityService.ts @@ -5,10 +5,10 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { UserListJoiningsRepository, UserListsRepository } from '@/models/index.js'; +import type { UserListJoiningsRepository, UserListsRepository } from '@/models/_.js'; import type { Packed } from '@/misc/json-schema.js'; -import type { } from '@/models/entities/Blocking.js'; -import type { MiUserList } from '@/models/entities/UserList.js'; +import type { } from '@/models/Blocking.js'; +import type { MiUserList } from '@/models/UserList.js'; import { bindThis } from '@/decorators.js'; @Injectable() diff --git a/packages/backend/src/misc/check-word-mute.ts b/packages/backend/src/misc/check-word-mute.ts index a7a60c20e..cef559545 100644 --- a/packages/backend/src/misc/check-word-mute.ts +++ b/packages/backend/src/misc/check-word-mute.ts @@ -5,8 +5,8 @@ import { AhoCorasick } from 'slacc'; import RE2 from 're2'; -import type { MiNote } from '@/models/entities/Note.js'; -import type { MiUser } from '@/models/entities/User.js'; +import type { MiNote } from '@/models/Note.js'; +import type { MiUser } from '@/models/User.js'; type NoteLike = { userId: MiNote['userId']; diff --git a/packages/backend/src/misc/is-quote.ts b/packages/backend/src/misc/is-quote.ts index c9f3af15f..059f6a4b5 100644 --- a/packages/backend/src/misc/is-quote.ts +++ b/packages/backend/src/misc/is-quote.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import type { MiNote } from '@/models/entities/Note.js'; +import type { MiNote } from '@/models/Note.js'; // eslint-disable-next-line import/no-default-export export default function(note: MiNote): boolean { diff --git a/packages/backend/src/models/entities/AbuseUserReport.ts b/packages/backend/src/models/AbuseUserReport.ts similarity index 97% rename from packages/backend/src/models/entities/AbuseUserReport.ts rename to packages/backend/src/models/AbuseUserReport.ts index 522cc502c..2551af7cb 100644 --- a/packages/backend/src/models/entities/AbuseUserReport.ts +++ b/packages/backend/src/models/AbuseUserReport.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; @Entity('abuse_user_report') diff --git a/packages/backend/src/models/entities/AccessToken.ts b/packages/backend/src/models/AccessToken.ts similarity index 97% rename from packages/backend/src/models/entities/AccessToken.ts rename to packages/backend/src/models/AccessToken.ts index 08bd2483e..5a6269a72 100644 --- a/packages/backend/src/models/entities/AccessToken.ts +++ b/packages/backend/src/models/AccessToken.ts @@ -4,7 +4,7 @@ */ import { Entity, PrimaryColumn, Index, Column, ManyToOne, JoinColumn } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; import { MiApp } from './App.js'; diff --git a/packages/backend/src/models/entities/Ad.ts b/packages/backend/src/models/Ad.ts similarity index 97% rename from packages/backend/src/models/entities/Ad.ts rename to packages/backend/src/models/Ad.ts index 2f84e7144..6dfc9cb30 100644 --- a/packages/backend/src/models/entities/Ad.ts +++ b/packages/backend/src/models/Ad.ts @@ -4,7 +4,7 @@ */ import { Entity, Index, Column, PrimaryColumn } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; @Entity('ad') export class MiAd { diff --git a/packages/backend/src/models/entities/Announcement.ts b/packages/backend/src/models/Announcement.ts similarity index 98% rename from packages/backend/src/models/entities/Announcement.ts rename to packages/backend/src/models/Announcement.ts index 9a2722b39..34b092a8d 100644 --- a/packages/backend/src/models/entities/Announcement.ts +++ b/packages/backend/src/models/Announcement.ts @@ -4,7 +4,7 @@ */ import { Entity, Index, Column, PrimaryColumn, ManyToOne, JoinColumn } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; @Entity('announcement') diff --git a/packages/backend/src/models/entities/AnnouncementRead.ts b/packages/backend/src/models/AnnouncementRead.ts similarity index 96% rename from packages/backend/src/models/entities/AnnouncementRead.ts rename to packages/backend/src/models/AnnouncementRead.ts index 89dadaab3..3d6ec5652 100644 --- a/packages/backend/src/models/entities/AnnouncementRead.ts +++ b/packages/backend/src/models/AnnouncementRead.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; import { MiAnnouncement } from './Announcement.js'; diff --git a/packages/backend/src/models/entities/Antenna.ts b/packages/backend/src/models/Antenna.ts similarity index 90% rename from packages/backend/src/models/entities/Antenna.ts rename to packages/backend/src/models/Antenna.ts index e73a4d55c..dc398b6dd 100644 --- a/packages/backend/src/models/entities/Antenna.ts +++ b/packages/backend/src/models/Antenna.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; import { MiUserList } from './UserList.js'; @@ -41,8 +41,8 @@ export class MiAntenna { }) public name: string; - @Column('enum', { enum: ['home', 'all', 'users', 'list'] }) - public src: 'home' | 'all' | 'users' | 'list'; + @Column('enum', { enum: ['home', 'all', 'users', 'list', 'users_blacklist'] }) + public src: 'home' | 'all' | 'users' | 'list' | 'users_blacklist'; @Column({ ...id(), diff --git a/packages/backend/src/models/entities/App.ts b/packages/backend/src/models/App.ts similarity index 97% rename from packages/backend/src/models/entities/App.ts rename to packages/backend/src/models/App.ts index 99c41a203..c599ef8be 100644 --- a/packages/backend/src/models/entities/App.ts +++ b/packages/backend/src/models/App.ts @@ -4,7 +4,7 @@ */ import { Entity, PrimaryColumn, Column, Index, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; @Entity('app') diff --git a/packages/backend/src/models/entities/AuthSession.ts b/packages/backend/src/models/AuthSession.ts similarity index 96% rename from packages/backend/src/models/entities/AuthSession.ts rename to packages/backend/src/models/AuthSession.ts index 1aabf836d..d9de6b697 100644 --- a/packages/backend/src/models/entities/AuthSession.ts +++ b/packages/backend/src/models/AuthSession.ts @@ -4,7 +4,7 @@ */ import { Entity, PrimaryColumn, Index, Column, ManyToOne, JoinColumn } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; import { MiApp } from './App.js'; diff --git a/packages/backend/src/models/entities/Blocking.ts b/packages/backend/src/models/Blocking.ts similarity index 96% rename from packages/backend/src/models/entities/Blocking.ts rename to packages/backend/src/models/Blocking.ts index 8bedb4395..1e3dd3a64 100644 --- a/packages/backend/src/models/entities/Blocking.ts +++ b/packages/backend/src/models/Blocking.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; @Entity('blocking') diff --git a/packages/backend/src/models/entities/Channel.ts b/packages/backend/src/models/Channel.ts similarity index 98% rename from packages/backend/src/models/entities/Channel.ts rename to packages/backend/src/models/Channel.ts index 9a89b650a..ae3886a65 100644 --- a/packages/backend/src/models/entities/Channel.ts +++ b/packages/backend/src/models/Channel.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; import { MiDriveFile } from './DriveFile.js'; diff --git a/packages/backend/src/models/entities/ChannelFavorite.ts b/packages/backend/src/models/ChannelFavorite.ts similarity index 96% rename from packages/backend/src/models/entities/ChannelFavorite.ts rename to packages/backend/src/models/ChannelFavorite.ts index c2be68ab7..ab74aa553 100644 --- a/packages/backend/src/models/entities/ChannelFavorite.ts +++ b/packages/backend/src/models/ChannelFavorite.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; import { MiChannel } from './Channel.js'; diff --git a/packages/backend/src/models/entities/ChannelFollowing.ts b/packages/backend/src/models/ChannelFollowing.ts similarity index 96% rename from packages/backend/src/models/entities/ChannelFollowing.ts rename to packages/backend/src/models/ChannelFollowing.ts index dc33eb144..c62a95332 100644 --- a/packages/backend/src/models/entities/ChannelFollowing.ts +++ b/packages/backend/src/models/ChannelFollowing.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; import { MiChannel } from './Channel.js'; diff --git a/packages/backend/src/models/entities/Clip.ts b/packages/backend/src/models/Clip.ts similarity index 96% rename from packages/backend/src/models/entities/Clip.ts rename to packages/backend/src/models/Clip.ts index f8bc2f217..c60b2964e 100644 --- a/packages/backend/src/models/entities/Clip.ts +++ b/packages/backend/src/models/Clip.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; @Entity('clip') diff --git a/packages/backend/src/models/entities/ClipFavorite.ts b/packages/backend/src/models/ClipFavorite.ts similarity index 95% rename from packages/backend/src/models/entities/ClipFavorite.ts rename to packages/backend/src/models/ClipFavorite.ts index 74d765411..054764389 100644 --- a/packages/backend/src/models/entities/ClipFavorite.ts +++ b/packages/backend/src/models/ClipFavorite.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; import { MiClip } from './Clip.js'; diff --git a/packages/backend/src/models/entities/ClipNote.ts b/packages/backend/src/models/ClipNote.ts similarity index 95% rename from packages/backend/src/models/entities/ClipNote.ts rename to packages/backend/src/models/ClipNote.ts index ed5458864..b7cc5ee39 100644 --- a/packages/backend/src/models/entities/ClipNote.ts +++ b/packages/backend/src/models/ClipNote.ts @@ -4,7 +4,7 @@ */ import { Entity, Index, JoinColumn, Column, ManyToOne, PrimaryColumn } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiNote } from './Note.js'; import { MiClip } from './Clip.js'; diff --git a/packages/backend/src/models/entities/DriveFile.ts b/packages/backend/src/models/DriveFile.ts similarity index 99% rename from packages/backend/src/models/entities/DriveFile.ts rename to packages/backend/src/models/DriveFile.ts index 55d6a9826..c12f0e0f0 100644 --- a/packages/backend/src/models/entities/DriveFile.ts +++ b/packages/backend/src/models/DriveFile.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; import { MiDriveFolder } from './DriveFolder.js'; diff --git a/packages/backend/src/models/entities/DriveFolder.ts b/packages/backend/src/models/DriveFolder.ts similarity index 96% rename from packages/backend/src/models/entities/DriveFolder.ts rename to packages/backend/src/models/DriveFolder.ts index 614974af1..3e049136b 100644 --- a/packages/backend/src/models/entities/DriveFolder.ts +++ b/packages/backend/src/models/DriveFolder.ts @@ -4,7 +4,7 @@ */ import { JoinColumn, ManyToOne, Entity, PrimaryColumn, Index, Column } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; @Entity('drive_folder') diff --git a/packages/backend/src/models/entities/Emoji.ts b/packages/backend/src/models/Emoji.ts similarity index 97% rename from packages/backend/src/models/entities/Emoji.ts rename to packages/backend/src/models/Emoji.ts index a3ae1f258..563ac1d9d 100644 --- a/packages/backend/src/models/entities/Emoji.ts +++ b/packages/backend/src/models/Emoji.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, Column } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; @Entity('emoji') @Index(['name', 'host'], { unique: true }) diff --git a/packages/backend/src/models/entities/Flash.ts b/packages/backend/src/models/Flash.ts similarity index 97% rename from packages/backend/src/models/entities/Flash.ts rename to packages/backend/src/models/Flash.ts index 38e023332..185063029 100644 --- a/packages/backend/src/models/entities/Flash.ts +++ b/packages/backend/src/models/Flash.ts @@ -4,7 +4,7 @@ */ import { Entity, Index, JoinColumn, Column, PrimaryColumn, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; @Entity('flash') diff --git a/packages/backend/src/models/entities/FlashLike.ts b/packages/backend/src/models/FlashLike.ts similarity index 95% rename from packages/backend/src/models/entities/FlashLike.ts rename to packages/backend/src/models/FlashLike.ts index 9486be3ea..7c66010ae 100644 --- a/packages/backend/src/models/entities/FlashLike.ts +++ b/packages/backend/src/models/FlashLike.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; import { MiFlash } from './Flash.js'; diff --git a/packages/backend/src/models/entities/FollowRequest.ts b/packages/backend/src/models/FollowRequest.ts similarity index 98% rename from packages/backend/src/models/entities/FollowRequest.ts rename to packages/backend/src/models/FollowRequest.ts index 28385931b..769b9a6cb 100644 --- a/packages/backend/src/models/entities/FollowRequest.ts +++ b/packages/backend/src/models/FollowRequest.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; @Entity('follow_request') diff --git a/packages/backend/src/models/entities/Following.ts b/packages/backend/src/models/Following.ts similarity index 92% rename from packages/backend/src/models/entities/Following.ts rename to packages/backend/src/models/Following.ts index df509cf94..8c9f965fa 100644 --- a/packages/backend/src/models/entities/Following.ts +++ b/packages/backend/src/models/Following.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; @Entity('following') @@ -45,6 +45,13 @@ export class MiFollowing { @JoinColumn() public follower: MiUser | null; + @Index() + @Column('varchar', { + length: 32, + nullable: true, + }) + public notify: 'normal' | null; + //#region Denormalized fields @Index() @Column('varchar', { diff --git a/packages/backend/src/models/entities/GalleryLike.ts b/packages/backend/src/models/GalleryLike.ts similarity index 95% rename from packages/backend/src/models/entities/GalleryLike.ts rename to packages/backend/src/models/GalleryLike.ts index 40aeeaad0..b5f71764a 100644 --- a/packages/backend/src/models/entities/GalleryLike.ts +++ b/packages/backend/src/models/GalleryLike.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; import { MiGalleryPost } from './GalleryPost.js'; diff --git a/packages/backend/src/models/entities/GalleryPost.ts b/packages/backend/src/models/GalleryPost.ts similarity index 97% rename from packages/backend/src/models/entities/GalleryPost.ts rename to packages/backend/src/models/GalleryPost.ts index 777fe942e..4c6063f32 100644 --- a/packages/backend/src/models/entities/GalleryPost.ts +++ b/packages/backend/src/models/GalleryPost.ts @@ -4,7 +4,7 @@ */ import { Entity, Index, JoinColumn, Column, PrimaryColumn, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; import type { MiDriveFile } from './DriveFile.js'; diff --git a/packages/backend/src/models/entities/Hashtag.ts b/packages/backend/src/models/Hashtag.ts similarity index 97% rename from packages/backend/src/models/entities/Hashtag.ts rename to packages/backend/src/models/Hashtag.ts index 30fea91b7..149377475 100644 --- a/packages/backend/src/models/entities/Hashtag.ts +++ b/packages/backend/src/models/Hashtag.ts @@ -4,7 +4,7 @@ */ import { Entity, PrimaryColumn, Index, Column } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import type { MiUser } from './User.js'; @Entity('hashtag') diff --git a/packages/backend/src/models/entities/Instance.ts b/packages/backend/src/models/Instance.ts similarity index 98% rename from packages/backend/src/models/entities/Instance.ts rename to packages/backend/src/models/Instance.ts index 8c562ffa8..b225d918d 100644 --- a/packages/backend/src/models/entities/Instance.ts +++ b/packages/backend/src/models/Instance.ts @@ -4,7 +4,7 @@ */ import { Entity, PrimaryColumn, Index, Column } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; @Entity('instance') export class MiInstance { diff --git a/packages/backend/src/models/entities/Meta.ts b/packages/backend/src/models/Meta.ts similarity index 95% rename from packages/backend/src/models/entities/Meta.ts rename to packages/backend/src/models/Meta.ts index 5a9c875a7..e69bef8e9 100644 --- a/packages/backend/src/models/entities/Meta.ts +++ b/packages/backend/src/models/Meta.ts @@ -4,7 +4,7 @@ */ import { Entity, Column, PrimaryColumn, ManyToOne, JoinColumn } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; @Entity('meta') @@ -20,6 +20,11 @@ export class MiMeta { }) public name: string | null; + @Column('varchar', { + length: 64, nullable: true, + }) + public shortName: string | null; + @Column('varchar', { length: 1024, nullable: true, }) @@ -107,6 +112,18 @@ export class MiMeta { }) public iconUrl: string | null; + @Column('varchar', { + length: 1024, + nullable: true, + }) + public app192IconUrl: string | null; + + @Column('varchar', { + length: 1024, + nullable: true, + }) + public app512IconUrl: string | null; + @Column('varchar', { length: 1024, nullable: true, @@ -444,6 +461,12 @@ export class MiMeta { }) public serverRules: string[]; + @Column('varchar', { + length: 8192, + default: '{}', + }) + public manifestJsonOverride: string; + @Column('varchar', { length: 1024, array: true, default: '{ "admin", "administrator", "root", "system", "maintainer", "host", "mod", "moderator", "owner", "superuser", "staff", "auth", "i", "me", "everyone", "all", "mention", "mentions", "example", "user", "users", "account", "accounts", "official", "help", "helps", "support", "supports", "info", "information", "informations", "announce", "announces", "announcement", "announcements", "notice", "notification", "notifications", "dev", "developer", "developers", "tech", "misskey" }', }) diff --git a/packages/backend/src/models/entities/ModerationLog.ts b/packages/backend/src/models/ModerationLog.ts similarity index 95% rename from packages/backend/src/models/entities/ModerationLog.ts rename to packages/backend/src/models/ModerationLog.ts index 027645de6..a12b6ab61 100644 --- a/packages/backend/src/models/entities/ModerationLog.ts +++ b/packages/backend/src/models/ModerationLog.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; @Entity('moderation_log') diff --git a/packages/backend/src/models/entities/MutedNote.ts b/packages/backend/src/models/MutedNote.ts similarity index 92% rename from packages/backend/src/models/entities/MutedNote.ts rename to packages/backend/src/models/MutedNote.ts index d33af90a9..89a678a2a 100644 --- a/packages/backend/src/models/entities/MutedNote.ts +++ b/packages/backend/src/models/MutedNote.ts @@ -4,8 +4,8 @@ */ import { Entity, Index, JoinColumn, Column, ManyToOne, PrimaryColumn } from 'typeorm'; -import { id } from '../id.js'; -import { mutedNoteReasons } from '../../types.js'; +import { mutedNoteReasons } from '@/types.js'; +import { id } from './util/id.js'; import { MiNote } from './Note.js'; import { MiUser } from './User.js'; diff --git a/packages/backend/src/models/entities/Muting.ts b/packages/backend/src/models/Muting.ts similarity index 96% rename from packages/backend/src/models/entities/Muting.ts rename to packages/backend/src/models/Muting.ts index b1f12f011..2f06ca8e5 100644 --- a/packages/backend/src/models/entities/Muting.ts +++ b/packages/backend/src/models/Muting.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; @Entity('muting') diff --git a/packages/backend/src/models/entities/Note.ts b/packages/backend/src/models/Note.ts similarity index 96% rename from packages/backend/src/models/entities/Note.ts rename to packages/backend/src/models/Note.ts index 42343f015..ed86d4549 100644 --- a/packages/backend/src/models/entities/Note.ts +++ b/packages/backend/src/models/Note.ts @@ -4,8 +4,8 @@ */ import { Entity, Index, JoinColumn, Column, PrimaryColumn, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; -import { noteVisibilities } from '../../types.js'; +import { noteVisibilities } from '@/types.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; import { MiChannel } from './Channel.js'; import type { MiDriveFile } from './DriveFile.js'; @@ -107,6 +107,11 @@ export class MiNote { }) public repliesCount: number; + @Column('smallint', { + default: 0, + }) + public clippedCount: number; + @Column('jsonb', { default: {}, }) diff --git a/packages/backend/src/models/entities/NoteFavorite.ts b/packages/backend/src/models/NoteFavorite.ts similarity index 96% rename from packages/backend/src/models/entities/NoteFavorite.ts rename to packages/backend/src/models/NoteFavorite.ts index 1b637e6b9..1171684bc 100644 --- a/packages/backend/src/models/entities/NoteFavorite.ts +++ b/packages/backend/src/models/NoteFavorite.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiNote } from './Note.js'; import { MiUser } from './User.js'; diff --git a/packages/backend/src/models/entities/NoteReaction.ts b/packages/backend/src/models/NoteReaction.ts similarity index 96% rename from packages/backend/src/models/entities/NoteReaction.ts rename to packages/backend/src/models/NoteReaction.ts index 19511abd1..7c08d31c6 100644 --- a/packages/backend/src/models/entities/NoteReaction.ts +++ b/packages/backend/src/models/NoteReaction.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; import { MiNote } from './Note.js'; diff --git a/packages/backend/src/models/entities/NoteThreadMuting.ts b/packages/backend/src/models/NoteThreadMuting.ts similarity index 95% rename from packages/backend/src/models/entities/NoteThreadMuting.ts rename to packages/backend/src/models/NoteThreadMuting.ts index d8ccbe0f7..2d120e4c2 100644 --- a/packages/backend/src/models/entities/NoteThreadMuting.ts +++ b/packages/backend/src/models/NoteThreadMuting.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; @Entity('note_thread_muting') diff --git a/packages/backend/src/models/entities/NoteUnread.ts b/packages/backend/src/models/NoteUnread.ts similarity index 97% rename from packages/backend/src/models/entities/NoteUnread.ts rename to packages/backend/src/models/NoteUnread.ts index 0f111cc1b..d86a47455 100644 --- a/packages/backend/src/models/entities/NoteUnread.ts +++ b/packages/backend/src/models/NoteUnread.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; import { MiNote } from './Note.js'; import type { MiChannel } from './Channel.js'; diff --git a/packages/backend/src/models/entities/Notification.ts b/packages/backend/src/models/Notification.ts similarity index 65% rename from packages/backend/src/models/entities/Notification.ts rename to packages/backend/src/models/Notification.ts index fb7f67dfd..c0a9df2e2 100644 --- a/packages/backend/src/models/entities/Notification.ts +++ b/packages/backend/src/models/Notification.ts @@ -22,18 +22,6 @@ export type MiNotification = { /** * 通知の種類。 - * follow - フォローされた - * mention - 投稿で自分が言及された - * reply - 投稿に返信された - * renote - 投稿がRenoteされた - * quote - 投稿が引用Renoteされた - * reaction - 投稿にリアクションされた - * pollEnded - 自分のアンケートもしくは自分が投票したアンケートが終了した - * receiveFollowRequest - フォローリクエストされた - * followRequestAccepted - 自分の送ったフォローリクエストが承認された - * achievementEarned - 実績を獲得 - * app - アプリ通知 - * test - テスト通知(サーバー側) */ type: typeof notificationTypes[number]; diff --git a/packages/backend/src/models/entities/Page.ts b/packages/backend/src/models/Page.ts similarity index 98% rename from packages/backend/src/models/entities/Page.ts rename to packages/backend/src/models/Page.ts index 30131af85..3cb986f4e 100644 --- a/packages/backend/src/models/entities/Page.ts +++ b/packages/backend/src/models/Page.ts @@ -4,7 +4,7 @@ */ import { Entity, Index, JoinColumn, Column, PrimaryColumn, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; import { MiDriveFile } from './DriveFile.js'; diff --git a/packages/backend/src/models/entities/PageLike.ts b/packages/backend/src/models/PageLike.ts similarity index 95% rename from packages/backend/src/models/entities/PageLike.ts rename to packages/backend/src/models/PageLike.ts index 36f5177cf..92adf9bcc 100644 --- a/packages/backend/src/models/entities/PageLike.ts +++ b/packages/backend/src/models/PageLike.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; import { MiPage } from './Page.js'; diff --git a/packages/backend/src/models/entities/PasswordResetRequest.ts b/packages/backend/src/models/PasswordResetRequest.ts similarity index 95% rename from packages/backend/src/models/entities/PasswordResetRequest.ts rename to packages/backend/src/models/PasswordResetRequest.ts index 4c608d979..79f2e984b 100644 --- a/packages/backend/src/models/entities/PasswordResetRequest.ts +++ b/packages/backend/src/models/PasswordResetRequest.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, Column, ManyToOne, JoinColumn } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; @Entity('password_reset_request') diff --git a/packages/backend/src/models/entities/Poll.ts b/packages/backend/src/models/Poll.ts similarity index 94% rename from packages/backend/src/models/entities/Poll.ts rename to packages/backend/src/models/Poll.ts index 557fd1be1..5ce0b9a2f 100644 --- a/packages/backend/src/models/entities/Poll.ts +++ b/packages/backend/src/models/Poll.ts @@ -4,8 +4,8 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, OneToOne } from 'typeorm'; -import { id } from '../id.js'; -import { noteVisibilities } from '../../types.js'; +import { noteVisibilities } from '@/types.js'; +import { id } from './util/id.js'; import { MiNote } from './Note.js'; import type { MiUser } from './User.js'; diff --git a/packages/backend/src/models/entities/PollVote.ts b/packages/backend/src/models/PollVote.ts similarity index 96% rename from packages/backend/src/models/entities/PollVote.ts rename to packages/backend/src/models/PollVote.ts index 5070ab16c..37cd55fc1 100644 --- a/packages/backend/src/models/entities/PollVote.ts +++ b/packages/backend/src/models/PollVote.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; import { MiNote } from './Note.js'; diff --git a/packages/backend/src/models/entities/PromoNote.ts b/packages/backend/src/models/PromoNote.ts similarity index 95% rename from packages/backend/src/models/entities/PromoNote.ts rename to packages/backend/src/models/PromoNote.ts index 9daf915b5..f4425fe88 100644 --- a/packages/backend/src/models/entities/PromoNote.ts +++ b/packages/backend/src/models/PromoNote.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, OneToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiNote } from './Note.js'; import type { MiUser } from './User.js'; diff --git a/packages/backend/src/models/entities/PromoRead.ts b/packages/backend/src/models/PromoRead.ts similarity index 95% rename from packages/backend/src/models/entities/PromoRead.ts rename to packages/backend/src/models/PromoRead.ts index 83a12858e..09ebfc834 100644 --- a/packages/backend/src/models/entities/PromoRead.ts +++ b/packages/backend/src/models/PromoRead.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiNote } from './Note.js'; import { MiUser } from './User.js'; diff --git a/packages/backend/src/models/entities/RegistrationTicket.ts b/packages/backend/src/models/RegistrationTicket.ts similarity index 97% rename from packages/backend/src/models/entities/RegistrationTicket.ts rename to packages/backend/src/models/RegistrationTicket.ts index 2b1c541a2..d94f46591 100644 --- a/packages/backend/src/models/entities/RegistrationTicket.ts +++ b/packages/backend/src/models/RegistrationTicket.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, Column, ManyToOne, JoinColumn, OneToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; @Entity('registration_ticket') diff --git a/packages/backend/src/models/entities/RegistryItem.ts b/packages/backend/src/models/RegistryItem.ts similarity index 97% rename from packages/backend/src/models/entities/RegistryItem.ts rename to packages/backend/src/models/RegistryItem.ts index fdfa4212d..fdce57c46 100644 --- a/packages/backend/src/models/entities/RegistryItem.ts +++ b/packages/backend/src/models/RegistryItem.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; // TODO: 同じdomain、同じscope、同じkeyのレコードは二つ以上存在しないように制約付けたい diff --git a/packages/backend/src/models/entities/Relay.ts b/packages/backend/src/models/Relay.ts similarity index 93% rename from packages/backend/src/models/entities/Relay.ts rename to packages/backend/src/models/Relay.ts index f73ab193a..293fccecf 100644 --- a/packages/backend/src/models/entities/Relay.ts +++ b/packages/backend/src/models/Relay.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, Column } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; @Entity('relay') export class MiRelay { diff --git a/packages/backend/src/models/entities/RenoteMuting.ts b/packages/backend/src/models/RenoteMuting.ts similarity index 96% rename from packages/backend/src/models/entities/RenoteMuting.ts rename to packages/backend/src/models/RenoteMuting.ts index fc87b82b7..d2a36249d 100644 --- a/packages/backend/src/models/entities/RenoteMuting.ts +++ b/packages/backend/src/models/RenoteMuting.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; @Entity('renote_muting') diff --git a/packages/backend/src/models/RepositoryModule.ts b/packages/backend/src/models/RepositoryModule.ts index 9b3599651..766e7ce21 100644 --- a/packages/backend/src/models/RepositoryModule.ts +++ b/packages/backend/src/models/RepositoryModule.ts @@ -5,7 +5,7 @@ import { Module } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import { MiAbuseUserReport, MiAccessToken, MiAd, MiAnnouncement, MiAnnouncementRead, MiAntenna, MiApp, MiAuthSession, MiBlocking, MiChannel, MiChannelFavorite, MiChannelFollowing, MiClip, MiClipFavorite, MiClipNote, MiDriveFile, MiDriveFolder, MiEmoji, MiFlash, MiFlashLike, MiFollowRequest, MiFollowing, MiGalleryLike, MiGalleryPost, MiHashtag, MiInstance, MiMeta, MiModerationLog, MiMutedNote, MiMuting, MiNote, MiNoteFavorite, MiNoteReaction, MiNoteThreadMuting, MiNoteUnread, MiPage, MiPageLike, MiPasswordResetRequest, MiPoll, MiPollVote, MiPromoNote, MiPromoRead, MiRegistrationTicket, MiRegistryItem, MiRelay, MiRenoteMuting, MiRetentionAggregation, MiRole, MiRoleAssignment, MiSignin, MiSwSubscription, MiUsedUsername, MiUser, MiUserIp, MiUserKeypair, MiUserList, MiUserListFavorite, MiUserListJoining, MiUserMemo, MiUserNotePining, MiUserPending, MiUserProfile, MiUserPublickey, MiUserSecurityKey, MiWebhook } from './index.js'; +import { MiAbuseUserReport, MiAccessToken, MiAd, MiAnnouncement, MiAnnouncementRead, MiAntenna, MiApp, MiAuthSession, MiBlocking, MiChannel, MiChannelFavorite, MiChannelFollowing, MiClip, MiClipFavorite, MiClipNote, MiDriveFile, MiDriveFolder, MiEmoji, MiFlash, MiFlashLike, MiFollowRequest, MiFollowing, MiGalleryLike, MiGalleryPost, MiHashtag, MiInstance, MiMeta, MiModerationLog, MiMutedNote, MiMuting, MiNote, MiNoteFavorite, MiNoteReaction, MiNoteThreadMuting, MiNoteUnread, MiPage, MiPageLike, MiPasswordResetRequest, MiPoll, MiPollVote, MiPromoNote, MiPromoRead, MiRegistrationTicket, MiRegistryItem, MiRelay, MiRenoteMuting, MiRetentionAggregation, MiRole, MiRoleAssignment, MiSignin, MiSwSubscription, MiUsedUsername, MiUser, MiUserIp, MiUserKeypair, MiUserList, MiUserListFavorite, MiUserListJoining, MiUserMemo, MiUserNotePining, MiUserPending, MiUserProfile, MiUserPublickey, MiUserSecurityKey, MiWebhook } from './_.js'; import type { DataSource } from 'typeorm'; import type { Provider } from '@nestjs/common'; diff --git a/packages/backend/src/models/entities/RetentionAggregation.ts b/packages/backend/src/models/RetentionAggregation.ts similarity index 96% rename from packages/backend/src/models/entities/RetentionAggregation.ts rename to packages/backend/src/models/RetentionAggregation.ts index 7d7874a60..9da401597 100644 --- a/packages/backend/src/models/entities/RetentionAggregation.ts +++ b/packages/backend/src/models/RetentionAggregation.ts @@ -4,7 +4,7 @@ */ import { Entity, PrimaryColumn, Index, Column } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import type { MiUser } from './User.js'; @Entity('retention_aggregation') diff --git a/packages/backend/src/models/entities/Role.ts b/packages/backend/src/models/Role.ts similarity index 99% rename from packages/backend/src/models/entities/Role.ts rename to packages/backend/src/models/Role.ts index 52e1f0c34..df7541db3 100644 --- a/packages/backend/src/models/entities/Role.ts +++ b/packages/backend/src/models/Role.ts @@ -4,7 +4,7 @@ */ import { Entity, Column, PrimaryColumn } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; type CondFormulaValueAnd = { type: 'and'; diff --git a/packages/backend/src/models/entities/RoleAssignment.ts b/packages/backend/src/models/RoleAssignment.ts similarity index 96% rename from packages/backend/src/models/entities/RoleAssignment.ts rename to packages/backend/src/models/RoleAssignment.ts index 5a2dacb91..4e5322c60 100644 --- a/packages/backend/src/models/entities/RoleAssignment.ts +++ b/packages/backend/src/models/RoleAssignment.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiRole } from './Role.js'; import { MiUser } from './User.js'; diff --git a/packages/backend/src/models/entities/Signin.ts b/packages/backend/src/models/Signin.ts similarity index 95% rename from packages/backend/src/models/entities/Signin.ts rename to packages/backend/src/models/Signin.ts index 709a99888..a8b1a45c5 100644 --- a/packages/backend/src/models/entities/Signin.ts +++ b/packages/backend/src/models/Signin.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; @Entity('signin') diff --git a/packages/backend/src/models/entities/SwSubscription.ts b/packages/backend/src/models/SwSubscription.ts similarity index 96% rename from packages/backend/src/models/entities/SwSubscription.ts rename to packages/backend/src/models/SwSubscription.ts index 9c3f97cf9..be1e4e368 100644 --- a/packages/backend/src/models/entities/SwSubscription.ts +++ b/packages/backend/src/models/SwSubscription.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; @Entity('sw_subscription') diff --git a/packages/backend/src/models/entities/UsedUsername.ts b/packages/backend/src/models/UsedUsername.ts similarity index 100% rename from packages/backend/src/models/entities/UsedUsername.ts rename to packages/backend/src/models/UsedUsername.ts diff --git a/packages/backend/src/models/entities/User.ts b/packages/backend/src/models/User.ts similarity index 99% rename from packages/backend/src/models/entities/User.ts rename to packages/backend/src/models/User.ts index 9db141bec..b040d302c 100644 --- a/packages/backend/src/models/entities/User.ts +++ b/packages/backend/src/models/User.ts @@ -4,7 +4,7 @@ */ import { Entity, Column, Index, OneToOne, JoinColumn, PrimaryColumn } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiDriveFile } from './DriveFile.js'; @Entity('user') diff --git a/packages/backend/src/models/entities/UserIp.ts b/packages/backend/src/models/UserIp.ts similarity index 94% rename from packages/backend/src/models/entities/UserIp.ts rename to packages/backend/src/models/UserIp.ts index 8384984e6..60a7bc8b0 100644 --- a/packages/backend/src/models/entities/UserIp.ts +++ b/packages/backend/src/models/UserIp.ts @@ -4,7 +4,7 @@ */ import { Entity, Index, Column, PrimaryGeneratedColumn } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import type { MiUser } from './User.js'; @Entity('user_ip') diff --git a/packages/backend/src/models/entities/UserKeypair.ts b/packages/backend/src/models/UserKeypair.ts similarity index 95% rename from packages/backend/src/models/entities/UserKeypair.ts rename to packages/backend/src/models/UserKeypair.ts index c9ea7d11f..a316dbaeb 100644 --- a/packages/backend/src/models/entities/UserKeypair.ts +++ b/packages/backend/src/models/UserKeypair.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, JoinColumn, Column, OneToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; @Entity('user_keypair') diff --git a/packages/backend/src/models/entities/UserList.ts b/packages/backend/src/models/UserList.ts similarity index 95% rename from packages/backend/src/models/entities/UserList.ts rename to packages/backend/src/models/UserList.ts index a6216b567..9af85af97 100644 --- a/packages/backend/src/models/entities/UserList.ts +++ b/packages/backend/src/models/UserList.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; @Entity('user_list') diff --git a/packages/backend/src/models/entities/UserListFavorite.ts b/packages/backend/src/models/UserListFavorite.ts similarity index 95% rename from packages/backend/src/models/entities/UserListFavorite.ts rename to packages/backend/src/models/UserListFavorite.ts index f3c4c1a4d..d0b054b93 100644 --- a/packages/backend/src/models/entities/UserListFavorite.ts +++ b/packages/backend/src/models/UserListFavorite.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; import { MiUserList } from './UserList.js'; diff --git a/packages/backend/src/models/entities/UserListJoining.ts b/packages/backend/src/models/UserListJoining.ts similarity index 96% rename from packages/backend/src/models/entities/UserListJoining.ts rename to packages/backend/src/models/UserListJoining.ts index e4912024c..4918f2f70 100644 --- a/packages/backend/src/models/entities/UserListJoining.ts +++ b/packages/backend/src/models/UserListJoining.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; import { MiUserList } from './UserList.js'; diff --git a/packages/backend/src/models/entities/UserMemo.ts b/packages/backend/src/models/UserMemo.ts similarity index 96% rename from packages/backend/src/models/entities/UserMemo.ts rename to packages/backend/src/models/UserMemo.ts index 9b8908050..ab5e812c4 100644 --- a/packages/backend/src/models/entities/UserMemo.ts +++ b/packages/backend/src/models/UserMemo.ts @@ -4,7 +4,7 @@ */ import { Column, Entity, Index, JoinColumn, ManyToOne, PrimaryColumn } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; @Entity('user_memo') diff --git a/packages/backend/src/models/entities/UserNotePining.ts b/packages/backend/src/models/UserNotePining.ts similarity index 96% rename from packages/backend/src/models/entities/UserNotePining.ts rename to packages/backend/src/models/UserNotePining.ts index 95bcb158b..1d50a5068 100644 --- a/packages/backend/src/models/entities/UserNotePining.ts +++ b/packages/backend/src/models/UserNotePining.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiNote } from './Note.js'; import { MiUser } from './User.js'; diff --git a/packages/backend/src/models/entities/UserPending.ts b/packages/backend/src/models/UserPending.ts similarity index 94% rename from packages/backend/src/models/entities/UserPending.ts rename to packages/backend/src/models/UserPending.ts index 8c9e01e59..b15ededa1 100644 --- a/packages/backend/src/models/entities/UserPending.ts +++ b/packages/backend/src/models/UserPending.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, Column } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; @Entity('user_pending') export class MiUserPending { diff --git a/packages/backend/src/models/entities/UserProfile.ts b/packages/backend/src/models/UserProfile.ts similarity index 97% rename from packages/backend/src/models/entities/UserProfile.ts rename to packages/backend/src/models/UserProfile.ts index 0fd26f4d6..e4405c9da 100644 --- a/packages/backend/src/models/entities/UserProfile.ts +++ b/packages/backend/src/models/UserProfile.ts @@ -5,7 +5,7 @@ import { Entity, Column, Index, OneToOne, JoinColumn, PrimaryColumn } from 'typeorm'; import { obsoleteNotificationTypes, ffVisibility, notificationTypes } from '@/types.js'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; import { MiPage } from './Page.js'; @@ -48,6 +48,12 @@ export class MiUserProfile { value: string; }[]; + @Column('varchar', { + array: true, + default: '{}', + }) + public verifiedLinks: string[]; + @Column('varchar', { length: 32, nullable: true, }) diff --git a/packages/backend/src/models/entities/UserPublickey.ts b/packages/backend/src/models/UserPublickey.ts similarity index 95% rename from packages/backend/src/models/entities/UserPublickey.ts rename to packages/backend/src/models/UserPublickey.ts index afa37cf7e..33de73c63 100644 --- a/packages/backend/src/models/entities/UserPublickey.ts +++ b/packages/backend/src/models/UserPublickey.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, OneToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; @Entity('user_publickey') diff --git a/packages/backend/src/models/entities/UserSecurityKey.ts b/packages/backend/src/models/UserSecurityKey.ts similarity index 98% rename from packages/backend/src/models/entities/UserSecurityKey.ts rename to packages/backend/src/models/UserSecurityKey.ts index 96dd27d08..02c29bfbb 100644 --- a/packages/backend/src/models/entities/UserSecurityKey.ts +++ b/packages/backend/src/models/UserSecurityKey.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, JoinColumn, Column, ManyToOne, Index } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; @Entity('user_security_key') diff --git a/packages/backend/src/models/entities/Webhook.ts b/packages/backend/src/models/Webhook.ts similarity index 97% rename from packages/backend/src/models/entities/Webhook.ts rename to packages/backend/src/models/Webhook.ts index f08d15825..5b009c18a 100644 --- a/packages/backend/src/models/entities/Webhook.ts +++ b/packages/backend/src/models/Webhook.ts @@ -4,7 +4,7 @@ */ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; +import { id } from './util/id.js'; import { MiUser } from './User.js'; export const webhookEventTypes = ['mention', 'unfollow', 'follow', 'followed', 'note', 'reply', 'renote', 'reaction'] as const; diff --git a/packages/backend/src/models/index.ts b/packages/backend/src/models/_.ts similarity index 55% rename from packages/backend/src/models/index.ts rename to packages/backend/src/models/_.ts index e4f4dce7d..6be7bd0df 100644 --- a/packages/backend/src/models/index.ts +++ b/packages/backend/src/models/_.ts @@ -3,71 +3,71 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { MiAbuseUserReport } from '@/models/entities/AbuseUserReport.js'; -import { MiAccessToken } from '@/models/entities/AccessToken.js'; -import { MiAd } from '@/models/entities/Ad.js'; -import { MiAnnouncement } from '@/models/entities/Announcement.js'; -import { MiAnnouncementRead } from '@/models/entities/AnnouncementRead.js'; -import { MiAntenna } from '@/models/entities/Antenna.js'; -import { MiApp } from '@/models/entities/App.js'; -import { MiAuthSession } from '@/models/entities/AuthSession.js'; -import { MiBlocking } from '@/models/entities/Blocking.js'; -import { MiChannelFollowing } from '@/models/entities/ChannelFollowing.js'; -import { MiChannelFavorite } from '@/models/entities/ChannelFavorite.js'; -import { MiClip } from '@/models/entities/Clip.js'; -import { MiClipNote } from '@/models/entities/ClipNote.js'; -import { MiClipFavorite } from '@/models/entities/ClipFavorite.js'; -import { MiDriveFile } from '@/models/entities/DriveFile.js'; -import { MiDriveFolder } from '@/models/entities/DriveFolder.js'; -import { MiEmoji } from '@/models/entities/Emoji.js'; -import { MiFollowing } from '@/models/entities/Following.js'; -import { MiFollowRequest } from '@/models/entities/FollowRequest.js'; -import { MiGalleryLike } from '@/models/entities/GalleryLike.js'; -import { MiGalleryPost } from '@/models/entities/GalleryPost.js'; -import { MiHashtag } from '@/models/entities/Hashtag.js'; -import { MiInstance } from '@/models/entities/Instance.js'; -import { MiMeta } from '@/models/entities/Meta.js'; -import { MiModerationLog } from '@/models/entities/ModerationLog.js'; -import { MiMutedNote } from '@/models/entities/MutedNote.js'; -import { MiMuting } from '@/models/entities/Muting.js'; -import { MiRenoteMuting } from '@/models/entities/RenoteMuting.js'; -import { MiNote } from '@/models/entities/Note.js'; -import { MiNoteFavorite } from '@/models/entities/NoteFavorite.js'; -import { MiNoteReaction } from '@/models/entities/NoteReaction.js'; -import { MiNoteThreadMuting } from '@/models/entities/NoteThreadMuting.js'; -import { MiNoteUnread } from '@/models/entities/NoteUnread.js'; -import { MiPage } from '@/models/entities/Page.js'; -import { MiPageLike } from '@/models/entities/PageLike.js'; -import { MiPasswordResetRequest } from '@/models/entities/PasswordResetRequest.js'; -import { MiPoll } from '@/models/entities/Poll.js'; -import { MiPollVote } from '@/models/entities/PollVote.js'; -import { MiPromoNote } from '@/models/entities/PromoNote.js'; -import { MiPromoRead } from '@/models/entities/PromoRead.js'; -import { MiRegistrationTicket } from '@/models/entities/RegistrationTicket.js'; -import { MiRegistryItem } from '@/models/entities/RegistryItem.js'; -import { MiRelay } from '@/models/entities/Relay.js'; -import { MiSignin } from '@/models/entities/Signin.js'; -import { MiSwSubscription } from '@/models/entities/SwSubscription.js'; -import { MiUsedUsername } from '@/models/entities/UsedUsername.js'; -import { MiUser } from '@/models/entities/User.js'; -import { MiUserIp } from '@/models/entities/UserIp.js'; -import { MiUserKeypair } from '@/models/entities/UserKeypair.js'; -import { MiUserList } from '@/models/entities/UserList.js'; -import { MiUserListJoining } from '@/models/entities/UserListJoining.js'; -import { MiUserNotePining } from '@/models/entities/UserNotePining.js'; -import { MiUserPending } from '@/models/entities/UserPending.js'; -import { MiUserProfile } from '@/models/entities/UserProfile.js'; -import { MiUserPublickey } from '@/models/entities/UserPublickey.js'; -import { MiUserSecurityKey } from '@/models/entities/UserSecurityKey.js'; -import { MiUserMemo } from '@/models/entities/UserMemo.js'; -import { MiWebhook } from '@/models/entities/Webhook.js'; -import { MiChannel } from '@/models/entities/Channel.js'; -import { MiRetentionAggregation } from '@/models/entities/RetentionAggregation.js'; -import { MiRole } from '@/models/entities/Role.js'; -import { MiRoleAssignment } from '@/models/entities/RoleAssignment.js'; -import { MiFlash } from '@/models/entities/Flash.js'; -import { MiFlashLike } from '@/models/entities/FlashLike.js'; -import { MiUserListFavorite } from './entities/UserListFavorite.js'; +import { MiAbuseUserReport } from '@/models/AbuseUserReport.js'; +import { MiAccessToken } from '@/models/AccessToken.js'; +import { MiAd } from '@/models/Ad.js'; +import { MiAnnouncement } from '@/models/Announcement.js'; +import { MiAnnouncementRead } from '@/models/AnnouncementRead.js'; +import { MiAntenna } from '@/models/Antenna.js'; +import { MiApp } from '@/models/App.js'; +import { MiAuthSession } from '@/models/AuthSession.js'; +import { MiBlocking } from '@/models/Blocking.js'; +import { MiChannelFollowing } from '@/models/ChannelFollowing.js'; +import { MiChannelFavorite } from '@/models/ChannelFavorite.js'; +import { MiClip } from '@/models/Clip.js'; +import { MiClipNote } from '@/models/ClipNote.js'; +import { MiClipFavorite } from '@/models/ClipFavorite.js'; +import { MiDriveFile } from '@/models/DriveFile.js'; +import { MiDriveFolder } from '@/models/DriveFolder.js'; +import { MiEmoji } from '@/models/Emoji.js'; +import { MiFollowing } from '@/models/Following.js'; +import { MiFollowRequest } from '@/models/FollowRequest.js'; +import { MiGalleryLike } from '@/models/GalleryLike.js'; +import { MiGalleryPost } from '@/models/GalleryPost.js'; +import { MiHashtag } from '@/models/Hashtag.js'; +import { MiInstance } from '@/models/Instance.js'; +import { MiMeta } from '@/models/Meta.js'; +import { MiModerationLog } from '@/models/ModerationLog.js'; +import { MiMutedNote } from '@/models/MutedNote.js'; +import { MiMuting } from '@/models/Muting.js'; +import { MiRenoteMuting } from '@/models/RenoteMuting.js'; +import { MiNote } from '@/models/Note.js'; +import { MiNoteFavorite } from '@/models/NoteFavorite.js'; +import { MiNoteReaction } from '@/models/NoteReaction.js'; +import { MiNoteThreadMuting } from '@/models/NoteThreadMuting.js'; +import { MiNoteUnread } from '@/models/NoteUnread.js'; +import { MiPage } from '@/models/Page.js'; +import { MiPageLike } from '@/models/PageLike.js'; +import { MiPasswordResetRequest } from '@/models/PasswordResetRequest.js'; +import { MiPoll } from '@/models/Poll.js'; +import { MiPollVote } from '@/models/PollVote.js'; +import { MiPromoNote } from '@/models/PromoNote.js'; +import { MiPromoRead } from '@/models/PromoRead.js'; +import { MiRegistrationTicket } from '@/models/RegistrationTicket.js'; +import { MiRegistryItem } from '@/models/RegistryItem.js'; +import { MiRelay } from '@/models/Relay.js'; +import { MiSignin } from '@/models/Signin.js'; +import { MiSwSubscription } from '@/models/SwSubscription.js'; +import { MiUsedUsername } from '@/models/UsedUsername.js'; +import { MiUser } from '@/models/User.js'; +import { MiUserIp } from '@/models/UserIp.js'; +import { MiUserKeypair } from '@/models/UserKeypair.js'; +import { MiUserList } from '@/models/UserList.js'; +import { MiUserListJoining } from '@/models/UserListJoining.js'; +import { MiUserNotePining } from '@/models/UserNotePining.js'; +import { MiUserPending } from '@/models/UserPending.js'; +import { MiUserProfile } from '@/models/UserProfile.js'; +import { MiUserPublickey } from '@/models/UserPublickey.js'; +import { MiUserSecurityKey } from '@/models/UserSecurityKey.js'; +import { MiUserMemo } from '@/models/UserMemo.js'; +import { MiWebhook } from '@/models/Webhook.js'; +import { MiChannel } from '@/models/Channel.js'; +import { MiRetentionAggregation } from '@/models/RetentionAggregation.js'; +import { MiRole } from '@/models/Role.js'; +import { MiRoleAssignment } from '@/models/RoleAssignment.js'; +import { MiFlash } from '@/models/Flash.js'; +import { MiFlashLike } from '@/models/FlashLike.js'; +import { MiUserListFavorite } from '@/models/UserListFavorite.js'; import type { Repository } from 'typeorm'; export { diff --git a/packages/backend/src/models/json-schema/antenna.ts b/packages/backend/src/models/json-schema/antenna.ts index 3f58cbee6..7b6475919 100644 --- a/packages/backend/src/models/json-schema/antenna.ts +++ b/packages/backend/src/models/json-schema/antenna.ts @@ -47,7 +47,7 @@ export const packedAntennaSchema = { src: { type: 'string', optional: false, nullable: false, - enum: ['home', 'all', 'users', 'list'], + enum: ['home', 'all', 'users', 'list', 'users_blacklist'], }, userListId: { type: 'string', diff --git a/packages/backend/src/models/json-schema/user.ts b/packages/backend/src/models/json-schema/user.ts index 3314464c3..f15b225a3 100644 --- a/packages/backend/src/models/json-schema/user.ts +++ b/packages/backend/src/models/json-schema/user.ts @@ -169,6 +169,15 @@ export const packedUserDetailedNotMeOnlySchema = { }, }, }, + verifiedLinks: { + type: 'array', + nullable: false, optional: false, + items: { + type: 'string', + nullable: false, optional: false, + format: 'url', + }, + }, followersCount: { type: 'number', nullable: false, optional: false, @@ -264,6 +273,10 @@ export const packedUserDetailedNotMeOnlySchema = { type: 'string', nullable: false, optional: true, }, + notify: { + type: 'string', + nullable: false, optional: true, + }, //#endregion }, } as const; diff --git a/packages/backend/src/models/id.ts b/packages/backend/src/models/util/id.ts similarity index 100% rename from packages/backend/src/models/id.ts rename to packages/backend/src/models/util/id.ts diff --git a/packages/backend/src/postgres.ts b/packages/backend/src/postgres.ts index c5d9e4146..10126eab2 100644 --- a/packages/backend/src/postgres.ts +++ b/packages/backend/src/postgres.ts @@ -11,71 +11,71 @@ import { DataSource, Logger } from 'typeorm'; import * as highlight from 'cli-highlight'; import { entities as charts } from '@/core/chart/entities.js'; -import { MiAbuseUserReport } from '@/models/entities/AbuseUserReport.js'; -import { MiAccessToken } from '@/models/entities/AccessToken.js'; -import { MiAd } from '@/models/entities/Ad.js'; -import { MiAnnouncement } from '@/models/entities/Announcement.js'; -import { MiAnnouncementRead } from '@/models/entities/AnnouncementRead.js'; -import { MiAntenna } from '@/models/entities/Antenna.js'; -import { MiApp } from '@/models/entities/App.js'; -import { MiAuthSession } from '@/models/entities/AuthSession.js'; -import { MiBlocking } from '@/models/entities/Blocking.js'; -import { MiChannelFollowing } from '@/models/entities/ChannelFollowing.js'; -import { MiChannelFavorite } from '@/models/entities/ChannelFavorite.js'; -import { MiClip } from '@/models/entities/Clip.js'; -import { MiClipNote } from '@/models/entities/ClipNote.js'; -import { MiClipFavorite } from '@/models/entities/ClipFavorite.js'; -import { MiDriveFile } from '@/models/entities/DriveFile.js'; -import { MiDriveFolder } from '@/models/entities/DriveFolder.js'; -import { MiEmoji } from '@/models/entities/Emoji.js'; -import { MiFollowing } from '@/models/entities/Following.js'; -import { MiFollowRequest } from '@/models/entities/FollowRequest.js'; -import { MiGalleryLike } from '@/models/entities/GalleryLike.js'; -import { MiGalleryPost } from '@/models/entities/GalleryPost.js'; -import { MiHashtag } from '@/models/entities/Hashtag.js'; -import { MiInstance } from '@/models/entities/Instance.js'; -import { MiMeta } from '@/models/entities/Meta.js'; -import { MiModerationLog } from '@/models/entities/ModerationLog.js'; -import { MiMutedNote } from '@/models/entities/MutedNote.js'; -import { MiMuting } from '@/models/entities/Muting.js'; -import { MiRenoteMuting } from '@/models/entities/RenoteMuting.js'; -import { MiNote } from '@/models/entities/Note.js'; -import { MiNoteFavorite } from '@/models/entities/NoteFavorite.js'; -import { MiNoteReaction } from '@/models/entities/NoteReaction.js'; -import { MiNoteThreadMuting } from '@/models/entities/NoteThreadMuting.js'; -import { MiNoteUnread } from '@/models/entities/NoteUnread.js'; -import { MiPage } from '@/models/entities/Page.js'; -import { MiPageLike } from '@/models/entities/PageLike.js'; -import { MiPasswordResetRequest } from '@/models/entities/PasswordResetRequest.js'; -import { MiPoll } from '@/models/entities/Poll.js'; -import { MiPollVote } from '@/models/entities/PollVote.js'; -import { MiPromoNote } from '@/models/entities/PromoNote.js'; -import { MiPromoRead } from '@/models/entities/PromoRead.js'; -import { MiRegistrationTicket } from '@/models/entities/RegistrationTicket.js'; -import { MiRegistryItem } from '@/models/entities/RegistryItem.js'; -import { MiRelay } from '@/models/entities/Relay.js'; -import { MiSignin } from '@/models/entities/Signin.js'; -import { MiSwSubscription } from '@/models/entities/SwSubscription.js'; -import { MiUsedUsername } from '@/models/entities/UsedUsername.js'; -import { MiUser } from '@/models/entities/User.js'; -import { MiUserIp } from '@/models/entities/UserIp.js'; -import { MiUserKeypair } from '@/models/entities/UserKeypair.js'; -import { MiUserList } from '@/models/entities/UserList.js'; -import { MiUserListFavorite } from '@/models/entities/UserListFavorite.js'; -import { MiUserListJoining } from '@/models/entities/UserListJoining.js'; -import { MiUserNotePining } from '@/models/entities/UserNotePining.js'; -import { MiUserPending } from '@/models/entities/UserPending.js'; -import { MiUserProfile } from '@/models/entities/UserProfile.js'; -import { MiUserPublickey } from '@/models/entities/UserPublickey.js'; -import { MiUserSecurityKey } from '@/models/entities/UserSecurityKey.js'; -import { MiWebhook } from '@/models/entities/Webhook.js'; -import { MiChannel } from '@/models/entities/Channel.js'; -import { MiRetentionAggregation } from '@/models/entities/RetentionAggregation.js'; -import { MiRole } from '@/models/entities/Role.js'; -import { MiRoleAssignment } from '@/models/entities/RoleAssignment.js'; -import { MiFlash } from '@/models/entities/Flash.js'; -import { MiFlashLike } from '@/models/entities/FlashLike.js'; -import { MiUserMemo } from '@/models/entities/UserMemo.js'; +import { MiAbuseUserReport } from '@/models/AbuseUserReport.js'; +import { MiAccessToken } from '@/models/AccessToken.js'; +import { MiAd } from '@/models/Ad.js'; +import { MiAnnouncement } from '@/models/Announcement.js'; +import { MiAnnouncementRead } from '@/models/AnnouncementRead.js'; +import { MiAntenna } from '@/models/Antenna.js'; +import { MiApp } from '@/models/App.js'; +import { MiAuthSession } from '@/models/AuthSession.js'; +import { MiBlocking } from '@/models/Blocking.js'; +import { MiChannelFollowing } from '@/models/ChannelFollowing.js'; +import { MiChannelFavorite } from '@/models/ChannelFavorite.js'; +import { MiClip } from '@/models/Clip.js'; +import { MiClipNote } from '@/models/ClipNote.js'; +import { MiClipFavorite } from '@/models/ClipFavorite.js'; +import { MiDriveFile } from '@/models/DriveFile.js'; +import { MiDriveFolder } from '@/models/DriveFolder.js'; +import { MiEmoji } from '@/models/Emoji.js'; +import { MiFollowing } from '@/models/Following.js'; +import { MiFollowRequest } from '@/models/FollowRequest.js'; +import { MiGalleryLike } from '@/models/GalleryLike.js'; +import { MiGalleryPost } from '@/models/GalleryPost.js'; +import { MiHashtag } from '@/models/Hashtag.js'; +import { MiInstance } from '@/models/Instance.js'; +import { MiMeta } from '@/models/Meta.js'; +import { MiModerationLog } from '@/models/ModerationLog.js'; +import { MiMutedNote } from '@/models/MutedNote.js'; +import { MiMuting } from '@/models/Muting.js'; +import { MiRenoteMuting } from '@/models/RenoteMuting.js'; +import { MiNote } from '@/models/Note.js'; +import { MiNoteFavorite } from '@/models/NoteFavorite.js'; +import { MiNoteReaction } from '@/models/NoteReaction.js'; +import { MiNoteThreadMuting } from '@/models/NoteThreadMuting.js'; +import { MiNoteUnread } from '@/models/NoteUnread.js'; +import { MiPage } from '@/models/Page.js'; +import { MiPageLike } from '@/models/PageLike.js'; +import { MiPasswordResetRequest } from '@/models/PasswordResetRequest.js'; +import { MiPoll } from '@/models/Poll.js'; +import { MiPollVote } from '@/models/PollVote.js'; +import { MiPromoNote } from '@/models/PromoNote.js'; +import { MiPromoRead } from '@/models/PromoRead.js'; +import { MiRegistrationTicket } from '@/models/RegistrationTicket.js'; +import { MiRegistryItem } from '@/models/RegistryItem.js'; +import { MiRelay } from '@/models/Relay.js'; +import { MiSignin } from '@/models/Signin.js'; +import { MiSwSubscription } from '@/models/SwSubscription.js'; +import { MiUsedUsername } from '@/models/UsedUsername.js'; +import { MiUser } from '@/models/User.js'; +import { MiUserIp } from '@/models/UserIp.js'; +import { MiUserKeypair } from '@/models/UserKeypair.js'; +import { MiUserList } from '@/models/UserList.js'; +import { MiUserListFavorite } from '@/models/UserListFavorite.js'; +import { MiUserListJoining } from '@/models/UserListJoining.js'; +import { MiUserNotePining } from '@/models/UserNotePining.js'; +import { MiUserPending } from '@/models/UserPending.js'; +import { MiUserProfile } from '@/models/UserProfile.js'; +import { MiUserPublickey } from '@/models/UserPublickey.js'; +import { MiUserSecurityKey } from '@/models/UserSecurityKey.js'; +import { MiWebhook } from '@/models/Webhook.js'; +import { MiChannel } from '@/models/Channel.js'; +import { MiRetentionAggregation } from '@/models/RetentionAggregation.js'; +import { MiRole } from '@/models/Role.js'; +import { MiRoleAssignment } from '@/models/RoleAssignment.js'; +import { MiFlash } from '@/models/Flash.js'; +import { MiFlashLike } from '@/models/FlashLike.js'; +import { MiUserMemo } from '@/models/UserMemo.js'; import { Config } from '@/config.js'; import MisskeyLogger from '@/logger.js'; diff --git a/packages/backend/src/queue/processors/AggregateRetentionProcessorService.ts b/packages/backend/src/queue/processors/AggregateRetentionProcessorService.ts index 757bfa307..5aac3f19e 100644 --- a/packages/backend/src/queue/processors/AggregateRetentionProcessorService.ts +++ b/packages/backend/src/queue/processors/AggregateRetentionProcessorService.ts @@ -8,7 +8,7 @@ import { IsNull, MoreThan } from 'typeorm'; import { DI } from '@/di-symbols.js'; import type Logger from '@/logger.js'; import { bindThis } from '@/decorators.js'; -import type { RetentionAggregationsRepository, UsersRepository } from '@/models/index.js'; +import type { RetentionAggregationsRepository, UsersRepository } from '@/models/_.js'; import { deepClone } from '@/misc/clone.js'; import { IdService } from '@/core/IdService.js'; import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js'; diff --git a/packages/backend/src/queue/processors/CheckExpiredMutingsProcessorService.ts b/packages/backend/src/queue/processors/CheckExpiredMutingsProcessorService.ts index d87f4537c..9b07389dc 100644 --- a/packages/backend/src/queue/processors/CheckExpiredMutingsProcessorService.ts +++ b/packages/backend/src/queue/processors/CheckExpiredMutingsProcessorService.ts @@ -6,7 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { In } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { MutingsRepository } from '@/models/index.js'; +import type { MutingsRepository } from '@/models/_.js'; import type Logger from '@/logger.js'; import { bindThis } from '@/decorators.js'; import { UserMutingService } from '@/core/UserMutingService.js'; diff --git a/packages/backend/src/queue/processors/CleanProcessorService.ts b/packages/backend/src/queue/processors/CleanProcessorService.ts index 3b974c240..f0453f705 100644 --- a/packages/backend/src/queue/processors/CleanProcessorService.ts +++ b/packages/backend/src/queue/processors/CleanProcessorService.ts @@ -6,7 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { In, LessThan } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { AntennasRepository, MutedNotesRepository, RoleAssignmentsRepository, UserIpsRepository } from '@/models/index.js'; +import type { AntennasRepository, MutedNotesRepository, RoleAssignmentsRepository, UserIpsRepository } from '@/models/_.js'; import type Logger from '@/logger.js'; import { bindThis } from '@/decorators.js'; import { IdService } from '@/core/IdService.js'; diff --git a/packages/backend/src/queue/processors/CleanRemoteFilesProcessorService.ts b/packages/backend/src/queue/processors/CleanRemoteFilesProcessorService.ts index 12cedd7d3..b62cc8a8f 100644 --- a/packages/backend/src/queue/processors/CleanRemoteFilesProcessorService.ts +++ b/packages/backend/src/queue/processors/CleanRemoteFilesProcessorService.ts @@ -6,7 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { IsNull, MoreThan, Not } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { MiDriveFile, DriveFilesRepository } from '@/models/index.js'; +import type { MiDriveFile, DriveFilesRepository } from '@/models/_.js'; import type Logger from '@/logger.js'; import { DriveService } from '@/core/DriveService.js'; import { bindThis } from '@/decorators.js'; diff --git a/packages/backend/src/queue/processors/DeleteAccountProcessorService.ts b/packages/backend/src/queue/processors/DeleteAccountProcessorService.ts index 39155bf38..39967165d 100644 --- a/packages/backend/src/queue/processors/DeleteAccountProcessorService.ts +++ b/packages/backend/src/queue/processors/DeleteAccountProcessorService.ts @@ -6,11 +6,11 @@ import { Inject, Injectable } from '@nestjs/common'; import { MoreThan } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { DriveFilesRepository, NotesRepository, UserProfilesRepository, UsersRepository } from '@/models/index.js'; +import type { DriveFilesRepository, NotesRepository, UserProfilesRepository, UsersRepository } from '@/models/_.js'; import type Logger from '@/logger.js'; import { DriveService } from '@/core/DriveService.js'; -import type { MiDriveFile } from '@/models/entities/DriveFile.js'; -import type { MiNote } from '@/models/entities/Note.js'; +import type { MiDriveFile } from '@/models/DriveFile.js'; +import type { MiNote } from '@/models/Note.js'; import { EmailService } from '@/core/EmailService.js'; import { bindThis } from '@/decorators.js'; import { SearchService } from '@/core/SearchService.js'; diff --git a/packages/backend/src/queue/processors/DeleteDriveFilesProcessorService.ts b/packages/backend/src/queue/processors/DeleteDriveFilesProcessorService.ts index ae395f540..6d0a45bcc 100644 --- a/packages/backend/src/queue/processors/DeleteDriveFilesProcessorService.ts +++ b/packages/backend/src/queue/processors/DeleteDriveFilesProcessorService.ts @@ -6,7 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { MoreThan } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { UsersRepository, DriveFilesRepository, MiDriveFile } from '@/models/index.js'; +import type { UsersRepository, DriveFilesRepository, MiDriveFile } from '@/models/_.js'; import type Logger from '@/logger.js'; import { DriveService } from '@/core/DriveService.js'; import { bindThis } from '@/decorators.js'; diff --git a/packages/backend/src/queue/processors/DeliverProcessorService.ts b/packages/backend/src/queue/processors/DeliverProcessorService.ts index 17fa32c2a..4a1d9f28b 100644 --- a/packages/backend/src/queue/processors/DeliverProcessorService.ts +++ b/packages/backend/src/queue/processors/DeliverProcessorService.ts @@ -6,14 +6,14 @@ import { Inject, Injectable } from '@nestjs/common'; import * as Bull from 'bullmq'; import { DI } from '@/di-symbols.js'; -import type { InstancesRepository } from '@/models/index.js'; +import type { InstancesRepository } from '@/models/_.js'; import type Logger from '@/logger.js'; import { MetaService } from '@/core/MetaService.js'; import { ApRequestService } from '@/core/activitypub/ApRequestService.js'; import { FederatedInstanceService } from '@/core/FederatedInstanceService.js'; import { FetchInstanceMetadataService } from '@/core/FetchInstanceMetadataService.js'; import { MemorySingleCache } from '@/misc/cache.js'; -import type { MiInstance } from '@/models/entities/Instance.js'; +import type { MiInstance } from '@/models/Instance.js'; import InstanceChart from '@/core/chart/charts/instance.js'; import ApRequestChart from '@/core/chart/charts/ap-request.js'; import FederationChart from '@/core/chart/charts/federation.js'; diff --git a/packages/backend/src/queue/processors/EndedPollNotificationProcessorService.ts b/packages/backend/src/queue/processors/EndedPollNotificationProcessorService.ts index d855ee570..4a4808443 100644 --- a/packages/backend/src/queue/processors/EndedPollNotificationProcessorService.ts +++ b/packages/backend/src/queue/processors/EndedPollNotificationProcessorService.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { PollVotesRepository, NotesRepository } from '@/models/index.js'; +import type { PollVotesRepository, NotesRepository } from '@/models/_.js'; import type Logger from '@/logger.js'; import { NotificationService } from '@/core/NotificationService.js'; import { bindThis } from '@/decorators.js'; diff --git a/packages/backend/src/queue/processors/ExportAntennasProcessorService.ts b/packages/backend/src/queue/processors/ExportAntennasProcessorService.ts index 243a4f97f..f941fb6e8 100644 --- a/packages/backend/src/queue/processors/ExportAntennasProcessorService.ts +++ b/packages/backend/src/queue/processors/ExportAntennasProcessorService.ts @@ -8,7 +8,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { format as DateFormat } from 'date-fns'; import { In } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { AntennasRepository, UsersRepository, UserListJoiningsRepository, MiUser } from '@/models/index.js'; +import type { AntennasRepository, UsersRepository, UserListJoiningsRepository, MiUser } from '@/models/_.js'; import Logger from '@/logger.js'; import { DriveService } from '@/core/DriveService.js'; import { bindThis } from '@/decorators.js'; diff --git a/packages/backend/src/queue/processors/ExportBlockingProcessorService.ts b/packages/backend/src/queue/processors/ExportBlockingProcessorService.ts index 8e27cacb5..0a37e3ca1 100644 --- a/packages/backend/src/queue/processors/ExportBlockingProcessorService.ts +++ b/packages/backend/src/queue/processors/ExportBlockingProcessorService.ts @@ -8,7 +8,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { MoreThan } from 'typeorm'; import { format as dateFormat } from 'date-fns'; import { DI } from '@/di-symbols.js'; -import type { UsersRepository, BlockingsRepository, MiBlocking } from '@/models/index.js'; +import type { UsersRepository, BlockingsRepository, MiBlocking } from '@/models/_.js'; import type Logger from '@/logger.js'; import { DriveService } from '@/core/DriveService.js'; import { createTemp } from '@/misc/create-temp.js'; diff --git a/packages/backend/src/queue/processors/ExportCustomEmojisProcessorService.ts b/packages/backend/src/queue/processors/ExportCustomEmojisProcessorService.ts index 688a0a1cc..d5387fe42 100644 --- a/packages/backend/src/queue/processors/ExportCustomEmojisProcessorService.ts +++ b/packages/backend/src/queue/processors/ExportCustomEmojisProcessorService.ts @@ -10,7 +10,7 @@ import { format as dateFormat } from 'date-fns'; import mime from 'mime-types'; import archiver from 'archiver'; import { DI } from '@/di-symbols.js'; -import type { EmojisRepository, UsersRepository } from '@/models/index.js'; +import type { EmojisRepository, UsersRepository } from '@/models/_.js'; import type { Config } from '@/config.js'; import type Logger from '@/logger.js'; import { DriveService } from '@/core/DriveService.js'; diff --git a/packages/backend/src/queue/processors/ExportFavoritesProcessorService.ts b/packages/backend/src/queue/processors/ExportFavoritesProcessorService.ts index afa1fa4ce..7248c7a64 100644 --- a/packages/backend/src/queue/processors/ExportFavoritesProcessorService.ts +++ b/packages/backend/src/queue/processors/ExportFavoritesProcessorService.ts @@ -8,12 +8,12 @@ import { Inject, Injectable } from '@nestjs/common'; import { MoreThan } from 'typeorm'; import { format as dateFormat } from 'date-fns'; import { DI } from '@/di-symbols.js'; -import type { MiNoteFavorite, NoteFavoritesRepository, PollsRepository, MiUser, UsersRepository } from '@/models/index.js'; +import type { MiNoteFavorite, NoteFavoritesRepository, PollsRepository, MiUser, UsersRepository } from '@/models/_.js'; import type Logger from '@/logger.js'; import { DriveService } from '@/core/DriveService.js'; import { createTemp } from '@/misc/create-temp.js'; -import type { MiPoll } from '@/models/entities/Poll.js'; -import type { MiNote } from '@/models/entities/Note.js'; +import type { MiPoll } from '@/models/Poll.js'; +import type { MiNote } from '@/models/Note.js'; import { bindThis } from '@/decorators.js'; import { QueueLoggerService } from '../QueueLoggerService.js'; import type * as Bull from 'bullmq'; diff --git a/packages/backend/src/queue/processors/ExportFollowingProcessorService.ts b/packages/backend/src/queue/processors/ExportFollowingProcessorService.ts index 7f29d7299..c9739eb1c 100644 --- a/packages/backend/src/queue/processors/ExportFollowingProcessorService.ts +++ b/packages/backend/src/queue/processors/ExportFollowingProcessorService.ts @@ -8,11 +8,11 @@ import { Inject, Injectable } from '@nestjs/common'; import { In, MoreThan, Not } from 'typeorm'; import { format as dateFormat } from 'date-fns'; import { DI } from '@/di-symbols.js'; -import type { UsersRepository, FollowingsRepository, MutingsRepository } from '@/models/index.js'; +import type { UsersRepository, FollowingsRepository, MutingsRepository } from '@/models/_.js'; import type Logger from '@/logger.js'; import { DriveService } from '@/core/DriveService.js'; import { createTemp } from '@/misc/create-temp.js'; -import type { MiFollowing } from '@/models/entities/Following.js'; +import type { MiFollowing } from '@/models/Following.js'; import { UtilityService } from '@/core/UtilityService.js'; import { bindThis } from '@/decorators.js'; import { QueueLoggerService } from '../QueueLoggerService.js'; diff --git a/packages/backend/src/queue/processors/ExportMutingProcessorService.ts b/packages/backend/src/queue/processors/ExportMutingProcessorService.ts index 1bb8da06f..c8425c1f2 100644 --- a/packages/backend/src/queue/processors/ExportMutingProcessorService.ts +++ b/packages/backend/src/queue/processors/ExportMutingProcessorService.ts @@ -8,7 +8,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { IsNull, MoreThan } from 'typeorm'; import { format as dateFormat } from 'date-fns'; import { DI } from '@/di-symbols.js'; -import type { MutingsRepository, UsersRepository, MiMuting } from '@/models/index.js'; +import type { MutingsRepository, UsersRepository, MiMuting } from '@/models/_.js'; import type Logger from '@/logger.js'; import { DriveService } from '@/core/DriveService.js'; import { createTemp } from '@/misc/create-temp.js'; diff --git a/packages/backend/src/queue/processors/ExportNotesProcessorService.ts b/packages/backend/src/queue/processors/ExportNotesProcessorService.ts index 0dcda341f..e0bc80e19 100644 --- a/packages/backend/src/queue/processors/ExportNotesProcessorService.ts +++ b/packages/backend/src/queue/processors/ExportNotesProcessorService.ts @@ -8,12 +8,12 @@ import { Inject, Injectable } from '@nestjs/common'; import { MoreThan } from 'typeorm'; import { format as dateFormat } from 'date-fns'; import { DI } from '@/di-symbols.js'; -import type { NotesRepository, PollsRepository, UsersRepository } from '@/models/index.js'; +import type { NotesRepository, PollsRepository, UsersRepository } from '@/models/_.js'; import type Logger from '@/logger.js'; import { DriveService } from '@/core/DriveService.js'; import { createTemp } from '@/misc/create-temp.js'; -import type { MiPoll } from '@/models/entities/Poll.js'; -import type { MiNote } from '@/models/entities/Note.js'; +import type { MiPoll } from '@/models/Poll.js'; +import type { MiNote } from '@/models/Note.js'; import { bindThis } from '@/decorators.js'; import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js'; import { Packed } from '@/misc/json-schema.js'; diff --git a/packages/backend/src/queue/processors/ExportUserListsProcessorService.ts b/packages/backend/src/queue/processors/ExportUserListsProcessorService.ts index ba3e18b56..7baaa7081 100644 --- a/packages/backend/src/queue/processors/ExportUserListsProcessorService.ts +++ b/packages/backend/src/queue/processors/ExportUserListsProcessorService.ts @@ -8,7 +8,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { In } from 'typeorm'; import { format as dateFormat } from 'date-fns'; import { DI } from '@/di-symbols.js'; -import type { UserListJoiningsRepository, UserListsRepository, UsersRepository } from '@/models/index.js'; +import type { UserListJoiningsRepository, UserListsRepository, UsersRepository } from '@/models/_.js'; import type Logger from '@/logger.js'; import { DriveService } from '@/core/DriveService.js'; import { createTemp } from '@/misc/create-temp.js'; diff --git a/packages/backend/src/queue/processors/ImportAntennasProcessorService.ts b/packages/backend/src/queue/processors/ImportAntennasProcessorService.ts index 9ff9a8a52..7c95bccaf 100644 --- a/packages/backend/src/queue/processors/ImportAntennasProcessorService.ts +++ b/packages/backend/src/queue/processors/ImportAntennasProcessorService.ts @@ -8,7 +8,7 @@ import _Ajv from 'ajv'; import { IdService } from '@/core/IdService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import Logger from '@/logger.js'; -import type { AntennasRepository } from '@/models/index.js'; +import type { AntennasRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { bindThis } from '@/decorators.js'; import { QueueLoggerService } from '../QueueLoggerService.js'; diff --git a/packages/backend/src/queue/processors/ImportBlockingProcessorService.ts b/packages/backend/src/queue/processors/ImportBlockingProcessorService.ts index 1d4c3d907..64520b770 100644 --- a/packages/backend/src/queue/processors/ImportBlockingProcessorService.ts +++ b/packages/backend/src/queue/processors/ImportBlockingProcessorService.ts @@ -6,7 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { IsNull } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { UsersRepository, DriveFilesRepository } from '@/models/index.js'; +import type { UsersRepository, DriveFilesRepository } from '@/models/_.js'; import type Logger from '@/logger.js'; import * as Acct from '@/misc/acct.js'; import { RemoteUserResolveService } from '@/core/RemoteUserResolveService.js'; diff --git a/packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts b/packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts index 54e92d312..a52af54a3 100644 --- a/packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts +++ b/packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts @@ -7,7 +7,7 @@ import * as fs from 'node:fs'; import { Inject, Injectable } from '@nestjs/common'; import { ZipReader } from 'slacc'; import { DI } from '@/di-symbols.js'; -import type { EmojisRepository, DriveFilesRepository } from '@/models/index.js'; +import type { EmojisRepository, DriveFilesRepository } from '@/models/_.js'; import type Logger from '@/logger.js'; import { CustomEmojiService } from '@/core/CustomEmojiService.js'; import { createTempDir } from '@/misc/create-temp.js'; diff --git a/packages/backend/src/queue/processors/ImportFollowingProcessorService.ts b/packages/backend/src/queue/processors/ImportFollowingProcessorService.ts index 585311982..2b5e41a12 100644 --- a/packages/backend/src/queue/processors/ImportFollowingProcessorService.ts +++ b/packages/backend/src/queue/processors/ImportFollowingProcessorService.ts @@ -6,7 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { IsNull } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { UsersRepository, DriveFilesRepository } from '@/models/index.js'; +import type { UsersRepository, DriveFilesRepository } from '@/models/_.js'; import type Logger from '@/logger.js'; import * as Acct from '@/misc/acct.js'; import { RemoteUserResolveService } from '@/core/RemoteUserResolveService.js'; diff --git a/packages/backend/src/queue/processors/ImportMutingProcessorService.ts b/packages/backend/src/queue/processors/ImportMutingProcessorService.ts index 174046c56..9db4e5d8e 100644 --- a/packages/backend/src/queue/processors/ImportMutingProcessorService.ts +++ b/packages/backend/src/queue/processors/ImportMutingProcessorService.ts @@ -6,7 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { IsNull } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { UsersRepository, DriveFilesRepository } from '@/models/index.js'; +import type { UsersRepository, DriveFilesRepository } from '@/models/_.js'; import type Logger from '@/logger.js'; import * as Acct from '@/misc/acct.js'; import { RemoteUserResolveService } from '@/core/RemoteUserResolveService.js'; diff --git a/packages/backend/src/queue/processors/ImportUserListsProcessorService.ts b/packages/backend/src/queue/processors/ImportUserListsProcessorService.ts index a434b4da9..54ca1a86d 100644 --- a/packages/backend/src/queue/processors/ImportUserListsProcessorService.ts +++ b/packages/backend/src/queue/processors/ImportUserListsProcessorService.ts @@ -6,7 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { IsNull } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { UsersRepository, DriveFilesRepository, UserListJoiningsRepository, UserListsRepository } from '@/models/index.js'; +import type { UsersRepository, DriveFilesRepository, UserListJoiningsRepository, UserListsRepository } from '@/models/_.js'; import type Logger from '@/logger.js'; import * as Acct from '@/misc/acct.js'; import { RemoteUserResolveService } from '@/core/RemoteUserResolveService.js'; diff --git a/packages/backend/src/queue/processors/InboxProcessorService.ts b/packages/backend/src/queue/processors/InboxProcessorService.ts index ba00cc2ac..99e823f9f 100644 --- a/packages/backend/src/queue/processors/InboxProcessorService.ts +++ b/packages/backend/src/queue/processors/InboxProcessorService.ts @@ -15,8 +15,8 @@ import InstanceChart from '@/core/chart/charts/instance.js'; import ApRequestChart from '@/core/chart/charts/ap-request.js'; import FederationChart from '@/core/chart/charts/federation.js'; import { getApId } from '@/core/activitypub/type.js'; -import type { MiRemoteUser } from '@/models/entities/User.js'; -import type { MiUserPublickey } from '@/models/entities/UserPublickey.js'; +import type { MiRemoteUser } from '@/models/User.js'; +import type { MiUserPublickey } from '@/models/UserPublickey.js'; import { ApDbResolverService } from '@/core/activitypub/ApDbResolverService.js'; import { StatusError } from '@/misc/status-error.js'; import { UtilityService } from '@/core/UtilityService.js'; diff --git a/packages/backend/src/queue/processors/RelationshipProcessorService.ts b/packages/backend/src/queue/processors/RelationshipProcessorService.ts index 67a50dc78..5b2d2ef31 100644 --- a/packages/backend/src/queue/processors/RelationshipProcessorService.ts +++ b/packages/backend/src/queue/processors/RelationshipProcessorService.ts @@ -10,9 +10,9 @@ import { UserBlockingService } from '@/core/UserBlockingService.js'; import { bindThis } from '@/decorators.js'; import type Logger from '@/logger.js'; -import type { UsersRepository } from '@/models/index.js'; +import type { UsersRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; -import { MiLocalUser, MiRemoteUser } from '@/models/entities/User.js'; +import { MiLocalUser, MiRemoteUser } from '@/models/User.js'; import { RelationshipJobData } from '../types.js'; import { QueueLoggerService } from '../QueueLoggerService.js'; import type * as Bull from 'bullmq'; diff --git a/packages/backend/src/queue/processors/WebhookDeliverProcessorService.ts b/packages/backend/src/queue/processors/WebhookDeliverProcessorService.ts index 92b3720a5..a41f5565c 100644 --- a/packages/backend/src/queue/processors/WebhookDeliverProcessorService.ts +++ b/packages/backend/src/queue/processors/WebhookDeliverProcessorService.ts @@ -6,7 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import * as Bull from 'bullmq'; import { DI } from '@/di-symbols.js'; -import type { WebhooksRepository } from '@/models/index.js'; +import type { WebhooksRepository } from '@/models/_.js'; import type { Config } from '@/config.js'; import type Logger from '@/logger.js'; import { HttpRequestService } from '@/core/HttpRequestService.js'; diff --git a/packages/backend/src/queue/types.ts b/packages/backend/src/queue/types.ts index 85af9d531..c9122f5ca 100644 --- a/packages/backend/src/queue/types.ts +++ b/packages/backend/src/queue/types.ts @@ -4,10 +4,10 @@ */ import type { Antenna } from '@/server/api/endpoints/i/import-antennas.js'; -import type { MiDriveFile } from '@/models/entities/DriveFile.js'; -import type { MiNote } from '@/models/entities/Note.js'; -import type { MiUser } from '@/models/entities/User.js'; -import type { MiWebhook } from '@/models/entities/Webhook.js'; +import type { MiDriveFile } from '@/models/DriveFile.js'; +import type { MiNote } from '@/models/Note.js'; +import type { MiUser } from '@/models/User.js'; +import type { MiWebhook } from '@/models/Webhook.js'; import type { IActivity } from '@/core/activitypub/type.js'; import type httpSignature from '@peertube/http-signature'; diff --git a/packages/backend/src/server/ActivityPubServerService.ts b/packages/backend/src/server/ActivityPubServerService.ts index 86edab396..2428fa279 100644 --- a/packages/backend/src/server/ActivityPubServerService.ts +++ b/packages/backend/src/server/ActivityPubServerService.ts @@ -11,16 +11,16 @@ import { Brackets, In, IsNull, LessThan, Not } from 'typeorm'; import accepts from 'accepts'; import vary from 'vary'; import { DI } from '@/di-symbols.js'; -import type { FollowingsRepository, NotesRepository, EmojisRepository, NoteReactionsRepository, UserProfilesRepository, UserNotePiningsRepository, UsersRepository, FollowRequestsRepository } from '@/models/index.js'; +import type { FollowingsRepository, NotesRepository, EmojisRepository, NoteReactionsRepository, UserProfilesRepository, UserNotePiningsRepository, UsersRepository, FollowRequestsRepository } from '@/models/_.js'; import * as url from '@/misc/prelude/url.js'; import type { Config } from '@/config.js'; import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; import { QueueService } from '@/core/QueueService.js'; -import type { MiLocalUser, MiRemoteUser, MiUser } from '@/models/entities/User.js'; +import type { MiLocalUser, MiRemoteUser, MiUser } from '@/models/User.js'; import { UserKeypairService } from '@/core/UserKeypairService.js'; -import type { MiFollowing } from '@/models/entities/Following.js'; +import type { MiFollowing } from '@/models/Following.js'; import { countIf } from '@/misc/prelude/array.js'; -import type { MiNote } from '@/models/entities/Note.js'; +import type { MiNote } from '@/models/Note.js'; import { QueryService } from '@/core/QueryService.js'; import { UtilityService } from '@/core/UtilityService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; diff --git a/packages/backend/src/server/FileServerService.ts b/packages/backend/src/server/FileServerService.ts index 9df6ba2a7..11721263d 100644 --- a/packages/backend/src/server/FileServerService.ts +++ b/packages/backend/src/server/FileServerService.ts @@ -11,7 +11,7 @@ import rename from 'rename'; import sharp from 'sharp'; import { sharpBmp } from 'sharp-read-bmp'; import type { Config } from '@/config.js'; -import type { MiDriveFile, DriveFilesRepository } from '@/models/index.js'; +import type { MiDriveFile, DriveFilesRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { createTemp } from '@/misc/create-temp.js'; import { FILE_TYPE_BROWSERSAFE } from '@/const.js'; diff --git a/packages/backend/src/server/NodeinfoServerService.ts b/packages/backend/src/server/NodeinfoServerService.ts index 1a1a3bf5a..79f130dab 100644 --- a/packages/backend/src/server/NodeinfoServerService.ts +++ b/packages/backend/src/server/NodeinfoServerService.ts @@ -18,6 +18,7 @@ import type { FastifyInstance, FastifyPluginOptions } from 'fastify'; const nodeinfo2_1path = '/nodeinfo/2.1'; const nodeinfo2_0path = '/nodeinfo/2.0'; +const nodeinfo_homepage = 'https://misskey-hub.net'; @Injectable() export class NodeinfoServerService { @@ -78,6 +79,8 @@ export class NodeinfoServerService { software: { name: 'misskey', version: this.config.version, + homepage: nodeinfo_homepage, + repository: meta.repositoryUrl, }, protocols: ['activitypub'], services: { diff --git a/packages/backend/src/server/ServerService.ts b/packages/backend/src/server/ServerService.ts index b40eeb31b..0e4a5ece3 100644 --- a/packages/backend/src/server/ServerService.ts +++ b/packages/backend/src/server/ServerService.ts @@ -12,7 +12,7 @@ import fastifyStatic from '@fastify/static'; import { IsNull } from 'typeorm'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import type { Config } from '@/config.js'; -import type { EmojisRepository, UserProfilesRepository, UsersRepository } from '@/models/index.js'; +import type { EmojisRepository, UserProfilesRepository, UsersRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import type Logger from '@/logger.js'; import * as Acct from '@/misc/acct.js'; diff --git a/packages/backend/src/server/WellKnownServerService.ts b/packages/backend/src/server/WellKnownServerService.ts index 04e1a3a17..8fc3c96de 100644 --- a/packages/backend/src/server/WellKnownServerService.ts +++ b/packages/backend/src/server/WellKnownServerService.ts @@ -8,10 +8,10 @@ import { IsNull } from 'typeorm'; import vary from 'vary'; import fastifyAccepts from '@fastify/accepts'; import { DI } from '@/di-symbols.js'; -import type { UsersRepository } from '@/models/index.js'; +import type { UsersRepository } from '@/models/_.js'; import type { Config } from '@/config.js'; import { escapeAttribute, escapeValue } from '@/misc/prelude/xml.js'; -import type { MiUser } from '@/models/entities/User.js'; +import type { MiUser } from '@/models/User.js'; import * as Acct from '@/misc/acct.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { bindThis } from '@/decorators.js'; diff --git a/packages/backend/src/server/api/ApiCallService.ts b/packages/backend/src/server/api/ApiCallService.ts index b90c8a519..085a0fd58 100644 --- a/packages/backend/src/server/api/ApiCallService.ts +++ b/packages/backend/src/server/api/ApiCallService.ts @@ -9,10 +9,10 @@ import * as stream from 'node:stream/promises'; import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; import { getIpHash } from '@/misc/get-ip-hash.js'; -import type { MiLocalUser, MiUser } from '@/models/entities/User.js'; -import type { MiAccessToken } from '@/models/entities/AccessToken.js'; +import type { MiLocalUser, MiUser } from '@/models/User.js'; +import type { MiAccessToken } from '@/models/AccessToken.js'; import type Logger from '@/logger.js'; -import type { UserIpsRepository } from '@/models/index.js'; +import type { UserIpsRepository } from '@/models/_.js'; import { MetaService } from '@/core/MetaService.js'; import { createTemp } from '@/misc/create-temp.js'; import { bindThis } from '@/decorators.js'; diff --git a/packages/backend/src/server/api/ApiServerService.ts b/packages/backend/src/server/api/ApiServerService.ts index 96b6a821d..1758c03ac 100644 --- a/packages/backend/src/server/api/ApiServerService.ts +++ b/packages/backend/src/server/api/ApiServerService.ts @@ -9,7 +9,7 @@ import multipart from '@fastify/multipart'; import fastifyCookie from '@fastify/cookie'; import { ModuleRef } from '@nestjs/core'; import type { Config } from '@/config.js'; -import type { InstancesRepository, AccessTokensRepository } from '@/models/index.js'; +import type { InstancesRepository, AccessTokensRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { bindThis } from '@/decorators.js'; diff --git a/packages/backend/src/server/api/AuthenticateService.ts b/packages/backend/src/server/api/AuthenticateService.ts index 8b031ab33..f07568819 100644 --- a/packages/backend/src/server/api/AuthenticateService.ts +++ b/packages/backend/src/server/api/AuthenticateService.ts @@ -5,11 +5,11 @@ import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { AccessTokensRepository, AppsRepository, UsersRepository } from '@/models/index.js'; -import type { MiLocalUser } from '@/models/entities/User.js'; -import type { MiAccessToken } from '@/models/entities/AccessToken.js'; +import type { AccessTokensRepository, AppsRepository, UsersRepository } from '@/models/_.js'; +import type { MiLocalUser } from '@/models/User.js'; +import type { MiAccessToken } from '@/models/AccessToken.js'; import { MemoryKVCache } from '@/misc/cache.js'; -import type { MiApp } from '@/models/entities/App.js'; +import type { MiApp } from '@/models/App.js'; import { CacheService } from '@/core/CacheService.js'; import isNativeToken from '@/misc/is-native-token.js'; import { bindThis } from '@/decorators.js'; diff --git a/packages/backend/src/server/api/EndpointsModule.ts b/packages/backend/src/server/api/EndpointsModule.ts index 7b9fa6c3b..41a11bfb1 100644 --- a/packages/backend/src/server/api/EndpointsModule.ts +++ b/packages/backend/src/server/api/EndpointsModule.ts @@ -160,6 +160,7 @@ import * as ep___federation_users from './endpoints/federation/users.js'; import * as ep___federation_stats from './endpoints/federation/stats.js'; import * as ep___following_create from './endpoints/following/create.js'; import * as ep___following_delete from './endpoints/following/delete.js'; +import * as ep___following_update from './endpoints/following/update.js'; import * as ep___following_invalidate from './endpoints/following/invalidate.js'; import * as ep___following_requests_accept from './endpoints/following/requests/accept.js'; import * as ep___following_requests_cancel from './endpoints/following/requests/cancel.js'; @@ -507,6 +508,7 @@ const $federation_users: Provider = { provide: 'ep:federation/users', useClass: const $federation_stats: Provider = { provide: 'ep:federation/stats', useClass: ep___federation_stats.default }; const $following_create: Provider = { provide: 'ep:following/create', useClass: ep___following_create.default }; const $following_delete: Provider = { provide: 'ep:following/delete', useClass: ep___following_delete.default }; +const $following_update: Provider = { provide: 'ep:following/update', useClass: ep___following_update.default }; const $following_invalidate: Provider = { provide: 'ep:following/invalidate', useClass: ep___following_invalidate.default }; const $following_requests_accept: Provider = { provide: 'ep:following/requests/accept', useClass: ep___following_requests_accept.default }; const $following_requests_cancel: Provider = { provide: 'ep:following/requests/cancel', useClass: ep___following_requests_cancel.default }; @@ -858,6 +860,7 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention $federation_stats, $following_create, $following_delete, + $following_update, $following_invalidate, $following_requests_accept, $following_requests_cancel, @@ -1203,6 +1206,7 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention $federation_stats, $following_create, $following_delete, + $following_update, $following_invalidate, $following_requests_accept, $following_requests_cancel, diff --git a/packages/backend/src/server/api/GetterService.ts b/packages/backend/src/server/api/GetterService.ts index 834a6ce4c..e2b98c34e 100644 --- a/packages/backend/src/server/api/GetterService.ts +++ b/packages/backend/src/server/api/GetterService.ts @@ -5,10 +5,10 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { NotesRepository, UsersRepository } from '@/models/index.js'; +import type { NotesRepository, UsersRepository } from '@/models/_.js'; import { IdentifiableError } from '@/misc/identifiable-error.js'; -import type { MiLocalUser, MiRemoteUser, MiUser } from '@/models/entities/User.js'; -import type { MiNote } from '@/models/entities/Note.js'; +import type { MiLocalUser, MiRemoteUser, MiUser } from '@/models/User.js'; +import type { MiNote } from '@/models/Note.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { bindThis } from '@/decorators.js'; diff --git a/packages/backend/src/server/api/SigninApiService.ts b/packages/backend/src/server/api/SigninApiService.ts index ac8371d8d..150f3f24d 100644 --- a/packages/backend/src/server/api/SigninApiService.ts +++ b/packages/backend/src/server/api/SigninApiService.ts @@ -12,13 +12,14 @@ import type { SigninsRepository, UserProfilesRepository, UsersRepository, -} from '@/models/index.js'; +} from '@/models/_.js'; import type { Config } from '@/config.js'; import { getIpHash } from '@/misc/get-ip-hash.js'; -import type { MiLocalUser } from '@/models/entities/User.js'; +import type { MiLocalUser } from '@/models/User.js'; import { IdService } from '@/core/IdService.js'; import { bindThis } from '@/decorators.js'; import { WebAuthnService } from '@/core/WebAuthnService.js'; +import { UserAuthService } from '@/core/UserAuthService.js'; import { RateLimiterService } from './RateLimiterService.js'; import { SigninService } from './SigninService.js'; import type { AuthenticationResponseJSON } from '@simplewebauthn/typescript-types'; @@ -42,6 +43,7 @@ export class SigninApiService { private idService: IdService, private rateLimiterService: RateLimiterService, private signinService: SigninService, + private userAuthService: UserAuthService, private webAuthnService: WebAuthnService, ) { } @@ -124,7 +126,7 @@ export class SigninApiService { const same = await bcrypt.compare(password, profile.password!); const fail = async (status?: number, failure?: { id: string }) => { - // Append signin history + // Append signin history await this.signinsRepository.insert({ id: this.idService.genId(), createdAt: new Date(), @@ -154,27 +156,15 @@ export class SigninApiService { }); } - if (profile.twoFactorBackupSecret?.includes(token)) { - await this.userProfilesRepository.update({ userId: profile.userId }, { - twoFactorBackupSecret: profile.twoFactorBackupSecret.filter((secret) => secret !== token), - }); - return this.signinService.signin(request, reply, user); - } - - const delta = OTPAuth.TOTP.validate({ - secret: OTPAuth.Secret.fromBase32(profile.twoFactorSecret!), - digits: 6, - token, - window: 1, - }); - - if (delta === null) { + try { + await this.userAuthService.twoFactorAuthenticate(profile, token); + } catch (e) { return await fail(403, { id: 'cdf1235b-ac71-46d4-a3a6-84ccce48df6f', }); - } else { - return this.signinService.signin(request, reply, user); } + + return this.signinService.signin(request, reply, user); } else if (body.credential) { if (!same && !profile.usePasswordLessLogin) { return await fail(403, { @@ -203,6 +193,6 @@ export class SigninApiService { reply.code(200); return authRequest; } - // never get here + // never get here } } diff --git a/packages/backend/src/server/api/SigninService.ts b/packages/backend/src/server/api/SigninService.ts index 9f731e01b..cebba8c8e 100644 --- a/packages/backend/src/server/api/SigninService.ts +++ b/packages/backend/src/server/api/SigninService.ts @@ -5,9 +5,9 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { SigninsRepository } from '@/models/index.js'; +import type { SigninsRepository } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; -import type { MiLocalUser } from '@/models/entities/User.js'; +import type { MiLocalUser } from '@/models/User.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { SigninEntityService } from '@/core/entities/SigninEntityService.js'; import { bindThis } from '@/decorators.js'; diff --git a/packages/backend/src/server/api/SignupApiService.ts b/packages/backend/src/server/api/SignupApiService.ts index 6e0351d29..431df581b 100644 --- a/packages/backend/src/server/api/SignupApiService.ts +++ b/packages/backend/src/server/api/SignupApiService.ts @@ -7,7 +7,7 @@ import { Inject, Injectable } from '@nestjs/common'; import bcrypt from 'bcryptjs'; import { IsNull } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { RegistrationTicketsRepository, UsedUsernamesRepository, UserPendingsRepository, UserProfilesRepository, UsersRepository, MiRegistrationTicket } from '@/models/index.js'; +import type { RegistrationTicketsRepository, UsedUsernamesRepository, UserPendingsRepository, UserProfilesRepository, UsersRepository, MiRegistrationTicket } from '@/models/_.js'; import type { Config } from '@/config.js'; import { MetaService } from '@/core/MetaService.js'; import { CaptchaService } from '@/core/CaptchaService.js'; @@ -15,7 +15,7 @@ import { IdService } from '@/core/IdService.js'; import { SignupService } from '@/core/SignupService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { EmailService } from '@/core/EmailService.js'; -import { MiLocalUser } from '@/models/entities/User.js'; +import { MiLocalUser } from '@/models/User.js'; import { FastifyReplyError } from '@/misc/fastify-reply-error.js'; import { bindThis } from '@/decorators.js'; import { L_CHARS, secureRndstr } from '@/misc/secure-rndstr.js'; diff --git a/packages/backend/src/server/api/StreamingApiServerService.ts b/packages/backend/src/server/api/StreamingApiServerService.ts index 74c469143..9acaa688c 100644 --- a/packages/backend/src/server/api/StreamingApiServerService.ts +++ b/packages/backend/src/server/api/StreamingApiServerService.ts @@ -8,14 +8,14 @@ import { Inject, Injectable } from '@nestjs/common'; import * as Redis from 'ioredis'; import * as WebSocket from 'ws'; import { DI } from '@/di-symbols.js'; -import type { UsersRepository, MiAccessToken } from '@/models/index.js'; +import type { UsersRepository, MiAccessToken } from '@/models/_.js'; import { NoteReadService } from '@/core/NoteReadService.js'; import { NotificationService } from '@/core/NotificationService.js'; import { bindThis } from '@/decorators.js'; import { CacheService } from '@/core/CacheService.js'; -import { MiLocalUser } from '@/models/entities/User.js'; +import { MiLocalUser } from '@/models/User.js'; import { AuthenticateService, AuthenticationError } from './AuthenticateService.js'; -import MainStreamConnection from './stream/index.js'; +import MainStreamConnection from './stream/Connection.js'; import { ChannelsService } from './stream/ChannelsService.js'; import type * as http from 'node:http'; diff --git a/packages/backend/src/server/api/endpoint-base.ts b/packages/backend/src/server/api/endpoint-base.ts index 531311e47..d5279faa1 100644 --- a/packages/backend/src/server/api/endpoint-base.ts +++ b/packages/backend/src/server/api/endpoint-base.ts @@ -6,8 +6,8 @@ import * as fs from 'node:fs'; import _Ajv from 'ajv'; import type { Schema, SchemaType } from '@/misc/json-schema.js'; -import type { MiLocalUser } from '@/models/entities/User.js'; -import type { MiAccessToken } from '@/models/entities/AccessToken.js'; +import type { MiLocalUser } from '@/models/User.js'; +import type { MiAccessToken } from '@/models/AccessToken.js'; import { ApiError } from './error.js'; import type { IEndpointMeta } from './endpoints.js'; diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index a9cb7c341..ab20a708e 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -160,6 +160,7 @@ import * as ep___federation_users from './endpoints/federation/users.js'; import * as ep___federation_stats from './endpoints/federation/stats.js'; import * as ep___following_create from './endpoints/following/create.js'; import * as ep___following_delete from './endpoints/following/delete.js'; +import * as ep___following_update from './endpoints/following/update.js'; import * as ep___following_invalidate from './endpoints/following/invalidate.js'; import * as ep___following_requests_accept from './endpoints/following/requests/accept.js'; import * as ep___following_requests_cancel from './endpoints/following/requests/cancel.js'; @@ -505,6 +506,7 @@ const eps = [ ['federation/stats', ep___federation_stats], ['following/create', ep___following_create], ['following/delete', ep___following_delete], + ['following/update', ep___following_update], ['following/invalidate', ep___following_invalidate], ['following/requests/accept', ep___following_requests_accept], ['following/requests/cancel', ep___following_requests_cancel], diff --git a/packages/backend/src/server/api/endpoints/admin/abuse-user-reports.ts b/packages/backend/src/server/api/endpoints/admin/abuse-user-reports.ts index 9a07b3181..be4fc82f0 100644 --- a/packages/backend/src/server/api/endpoints/admin/abuse-user-reports.ts +++ b/packages/backend/src/server/api/endpoints/admin/abuse-user-reports.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { AbuseUserReportsRepository } from '@/models/index.js'; +import type { AbuseUserReportsRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { DI } from '@/di-symbols.js'; import { AbuseUserReportEntityService } from '@/core/entities/AbuseUserReportEntityService.js'; diff --git a/packages/backend/src/server/api/endpoints/admin/accounts/create.ts b/packages/backend/src/server/api/endpoints/admin/accounts/create.ts index 48af74f10..070e88f6f 100644 --- a/packages/backend/src/server/api/endpoints/admin/accounts/create.ts +++ b/packages/backend/src/server/api/endpoints/admin/accounts/create.ts @@ -6,10 +6,10 @@ import { Inject, Injectable } from '@nestjs/common'; import { IsNull } from 'typeorm'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { UsersRepository } from '@/models/index.js'; +import type { UsersRepository } from '@/models/_.js'; import { SignupService } from '@/core/SignupService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; -import { localUsernameSchema, passwordSchema } from '@/models/entities/User.js'; +import { localUsernameSchema, passwordSchema } from '@/models/User.js'; import { DI } from '@/di-symbols.js'; export const meta = { diff --git a/packages/backend/src/server/api/endpoints/admin/accounts/delete.ts b/packages/backend/src/server/api/endpoints/admin/accounts/delete.ts index 1dd60eb26..60e928ccb 100644 --- a/packages/backend/src/server/api/endpoints/admin/accounts/delete.ts +++ b/packages/backend/src/server/api/endpoints/admin/accounts/delete.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { UsersRepository } from '@/models/index.js'; +import type { UsersRepository } from '@/models/_.js'; import { QueueService } from '@/core/QueueService.js'; import { UserSuspendService } from '@/core/UserSuspendService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/admin/ad/create.ts b/packages/backend/src/server/api/endpoints/admin/ad/create.ts index 5ebb10308..a13d08fd3 100644 --- a/packages/backend/src/server/api/endpoints/admin/ad/create.ts +++ b/packages/backend/src/server/api/endpoints/admin/ad/create.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { AdsRepository } from '@/models/index.js'; +import type { AdsRepository } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/admin/ad/delete.ts b/packages/backend/src/server/api/endpoints/admin/ad/delete.ts index 8ee99c228..d3c53d4f6 100644 --- a/packages/backend/src/server/api/endpoints/admin/ad/delete.ts +++ b/packages/backend/src/server/api/endpoints/admin/ad/delete.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { AdsRepository } from '@/models/index.js'; +import type { AdsRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/admin/ad/list.ts b/packages/backend/src/server/api/endpoints/admin/ad/list.ts index 97b1b25dc..adff3ed0a 100644 --- a/packages/backend/src/server/api/endpoints/admin/ad/list.ts +++ b/packages/backend/src/server/api/endpoints/admin/ad/list.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { AdsRepository } from '@/models/index.js'; +import type { AdsRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/admin/ad/update.ts b/packages/backend/src/server/api/endpoints/admin/ad/update.ts index 9b07ee51a..5b77f67e1 100644 --- a/packages/backend/src/server/api/endpoints/admin/ad/update.ts +++ b/packages/backend/src/server/api/endpoints/admin/ad/update.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { AdsRepository } from '@/models/index.js'; +import type { AdsRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/admin/announcements/create.ts b/packages/backend/src/server/api/endpoints/admin/announcements/create.ts index c2f69bb15..262b36b9a 100644 --- a/packages/backend/src/server/api/endpoints/admin/announcements/create.ts +++ b/packages/backend/src/server/api/endpoints/admin/announcements/create.ts @@ -81,7 +81,7 @@ export default class extends Endpoint { // eslint- forExistingUsers: ps.forExistingUsers, needConfirmationToRead: ps.needConfirmationToRead, userId: ps.userId, - }); + }, me); return packed; }); diff --git a/packages/backend/src/server/api/endpoints/admin/announcements/delete.ts b/packages/backend/src/server/api/endpoints/admin/announcements/delete.ts index 1a4061624..80ec28125 100644 --- a/packages/backend/src/server/api/endpoints/admin/announcements/delete.ts +++ b/packages/backend/src/server/api/endpoints/admin/announcements/delete.ts @@ -5,8 +5,9 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { AnnouncementsRepository } from '@/models/index.js'; +import type { AnnouncementsRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; +import { AnnouncementService } from '@/core/AnnouncementService.js'; import { ApiError } from '../../../error.js'; export const meta = { @@ -37,13 +38,15 @@ export default class extends Endpoint { // eslint- constructor( @Inject(DI.announcementsRepository) private announcementsRepository: AnnouncementsRepository, + + private announcementService: AnnouncementService, ) { super(meta, paramDef, async (ps, me) => { const announcement = await this.announcementsRepository.findOneBy({ id: ps.id }); if (announcement == null) throw new ApiError(meta.errors.noSuchAnnouncement); - await this.announcementsRepository.delete(announcement.id); + await this.announcementService.delete(announcement, me); }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/announcements/list.ts b/packages/backend/src/server/api/endpoints/admin/announcements/list.ts index 2b4080bb0..c82e702ee 100644 --- a/packages/backend/src/server/api/endpoints/admin/announcements/list.ts +++ b/packages/backend/src/server/api/endpoints/admin/announcements/list.ts @@ -4,8 +4,8 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { AnnouncementsRepository, AnnouncementReadsRepository } from '@/models/index.js'; -import type { MiAnnouncement } from '@/models/entities/Announcement.js'; +import type { AnnouncementsRepository, AnnouncementReadsRepository } from '@/models/_.js'; +import type { MiAnnouncement } from '@/models/Announcement.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/admin/announcements/update.ts b/packages/backend/src/server/api/endpoints/admin/announcements/update.ts index 1b35f7ecd..d36590c26 100644 --- a/packages/backend/src/server/api/endpoints/admin/announcements/update.ts +++ b/packages/backend/src/server/api/endpoints/admin/announcements/update.ts @@ -5,8 +5,9 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { AnnouncementsRepository } from '@/models/index.js'; +import type { AnnouncementsRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; +import { AnnouncementService } from '@/core/AnnouncementService.js'; import { ApiError } from '../../../error.js'; export const meta = { @@ -45,13 +46,15 @@ export default class extends Endpoint { // eslint- constructor( @Inject(DI.announcementsRepository) private announcementsRepository: AnnouncementsRepository, + + private announcementService: AnnouncementService, ) { super(meta, paramDef, async (ps, me) => { const announcement = await this.announcementsRepository.findOneBy({ id: ps.id }); if (announcement == null) throw new ApiError(meta.errors.noSuchAnnouncement); - await this.announcementsRepository.update(announcement.id, { + await this.announcementService.update(announcement, { updatedAt: new Date(), title: ps.title, text: ps.text, @@ -62,7 +65,7 @@ export default class extends Endpoint { // eslint- forExistingUsers: ps.forExistingUsers, needConfirmationToRead: ps.needConfirmationToRead, isActive: ps.isActive, - }); + }, me); }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/delete-account.ts b/packages/backend/src/server/api/endpoints/admin/delete-account.ts index 2738550a5..9ef09b172 100644 --- a/packages/backend/src/server/api/endpoints/admin/delete-account.ts +++ b/packages/backend/src/server/api/endpoints/admin/delete-account.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { UsersRepository } from '@/models/index.js'; +import type { UsersRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DeleteAccountService } from '@/core/DeleteAccountService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/admin/delete-all-files-of-a-user.ts b/packages/backend/src/server/api/endpoints/admin/delete-all-files-of-a-user.ts index f6bb5c24d..e47ecd81c 100644 --- a/packages/backend/src/server/api/endpoints/admin/delete-all-files-of-a-user.ts +++ b/packages/backend/src/server/api/endpoints/admin/delete-all-files-of-a-user.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { DriveFilesRepository } from '@/models/index.js'; +import type { DriveFilesRepository } from '@/models/_.js'; import { DriveService } from '@/core/DriveService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/admin/drive/cleanup.ts b/packages/backend/src/server/api/endpoints/admin/drive/cleanup.ts index 995deb5f3..75d689966 100644 --- a/packages/backend/src/server/api/endpoints/admin/drive/cleanup.ts +++ b/packages/backend/src/server/api/endpoints/admin/drive/cleanup.ts @@ -6,7 +6,7 @@ import { IsNull } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { DriveFilesRepository } from '@/models/index.js'; +import type { DriveFilesRepository } from '@/models/_.js'; import { DriveService } from '@/core/DriveService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/admin/drive/files.ts b/packages/backend/src/server/api/endpoints/admin/drive/files.ts index 1a319cef9..ac8a70e3d 100644 --- a/packages/backend/src/server/api/endpoints/admin/drive/files.ts +++ b/packages/backend/src/server/api/endpoints/admin/drive/files.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { DriveFilesRepository } from '@/models/index.js'; +import type { DriveFilesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts b/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts index fa0c92df7..7fb5342f8 100644 --- a/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts +++ b/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { DriveFilesRepository, UsersRepository } from '@/models/index.js'; +import type { DriveFilesRepository, UsersRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; import { RoleService } from '@/core/RoleService.js'; diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/add.ts b/packages/backend/src/server/api/endpoints/admin/emoji/add.ts index 412b91217..24d3a8a94 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/add.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/add.ts @@ -5,10 +5,9 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { DriveFilesRepository } from '@/models/index.js'; +import type { DriveFilesRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { CustomEmojiService } from '@/core/CustomEmojiService.js'; -import { ModerationLogService } from '@/core/ModerationLogService.js'; import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js'; import { ApiError } from '../../../error.js'; @@ -61,7 +60,6 @@ export default class extends Endpoint { // eslint- private customEmojiService: CustomEmojiService, private emojiEntityService: EmojiEntityService, - private moderationLogService: ModerationLogService, ) { super(meta, paramDef, async (ps, me) => { const driveFile = await this.driveFilesRepository.findOneBy({ id: ps.fileId }); @@ -77,11 +75,7 @@ export default class extends Endpoint { // eslint- isSensitive: ps.isSensitive ?? false, localOnly: ps.localOnly ?? false, roleIdsThatCanBeUsedThisEmojiAsReaction: ps.roleIdsThatCanBeUsedThisEmojiAsReaction ?? [], - }); - - this.moderationLogService.insertModerationLog(me, 'addEmoji', { - emojiId: emoji.id, - }); + }, me); return this.emojiEntityService.packDetailed(emoji); }); diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts b/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts index 57bf56326..c5f986ff0 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts @@ -5,9 +5,9 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { EmojisRepository } from '@/models/index.js'; +import type { EmojisRepository } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; -import type { MiDriveFile } from '@/models/entities/DriveFile.js'; +import type { MiDriveFile } from '@/models/DriveFile.js'; import { DI } from '@/di-symbols.js'; import { DriveService } from '@/core/DriveService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/delete-bulk.ts b/packages/backend/src/server/api/endpoints/admin/emoji/delete-bulk.ts index 422191304..e6c1bf317 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/delete-bulk.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/delete-bulk.ts @@ -30,7 +30,7 @@ export default class extends Endpoint { // eslint- private customEmojiService: CustomEmojiService, ) { super(meta, paramDef, async (ps, me) => { - await this.customEmojiService.deleteBulk(ps.ids); + await this.customEmojiService.deleteBulk(ps.ids, me); }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts b/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts index f020e2218..58aa0b995 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts @@ -36,7 +36,7 @@ export default class extends Endpoint { // eslint- private customEmojiService: CustomEmojiService, ) { super(meta, paramDef, async (ps, me) => { - await this.customEmojiService.delete(ps.id); + await this.customEmojiService.delete(ps.id, me); }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts b/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts index 88190cb7c..855ab8cd2 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { EmojisRepository } from '@/models/index.js'; +import type { EmojisRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { UtilityService } from '@/core/UtilityService.js'; import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js'; diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/list.ts b/packages/backend/src/server/api/endpoints/admin/emoji/list.ts index a58ca4b8d..ab16d86a3 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/list.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/list.ts @@ -5,8 +5,8 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { EmojisRepository } from '@/models/index.js'; -import type { MiEmoji } from '@/models/entities/Emoji.js'; +import type { EmojisRepository } from '@/models/_.js'; +import type { MiEmoji } from '@/models/Emoji.js'; import { QueryService } from '@/core/QueryService.js'; import { DI } from '@/di-symbols.js'; import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js'; diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts index f3bd3dc71..2d6985740 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts @@ -6,7 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { CustomEmojiService } from '@/core/CustomEmojiService.js'; -import type { DriveFilesRepository } from '@/models/index.js'; +import type { DriveFilesRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; @@ -84,7 +84,7 @@ export default class extends Endpoint { // eslint- isSensitive: ps.isSensitive, localOnly: ps.localOnly, roleIdsThatCanBeUsedThisEmojiAsReaction: ps.roleIdsThatCanBeUsedThisEmojiAsReaction, - }); + }, me); }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/federation/delete-all-files.ts b/packages/backend/src/server/api/endpoints/admin/federation/delete-all-files.ts index 4ac5640b2..b63f01bec 100644 --- a/packages/backend/src/server/api/endpoints/admin/federation/delete-all-files.ts +++ b/packages/backend/src/server/api/endpoints/admin/federation/delete-all-files.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { DriveFilesRepository } from '@/models/index.js'; +import type { DriveFilesRepository } from '@/models/_.js'; import { DriveService } from '@/core/DriveService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/admin/federation/refresh-remote-instance-metadata.ts b/packages/backend/src/server/api/endpoints/admin/federation/refresh-remote-instance-metadata.ts index 6b3f1a68d..6dbfe3c4f 100644 --- a/packages/backend/src/server/api/endpoints/admin/federation/refresh-remote-instance-metadata.ts +++ b/packages/backend/src/server/api/endpoints/admin/federation/refresh-remote-instance-metadata.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { InstancesRepository } from '@/models/index.js'; +import type { InstancesRepository } from '@/models/_.js'; import { FetchInstanceMetadataService } from '@/core/FetchInstanceMetadataService.js'; import { UtilityService } from '@/core/UtilityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/admin/federation/remove-all-following.ts b/packages/backend/src/server/api/endpoints/admin/federation/remove-all-following.ts index 31debfc9a..36ea390e4 100644 --- a/packages/backend/src/server/api/endpoints/admin/federation/remove-all-following.ts +++ b/packages/backend/src/server/api/endpoints/admin/federation/remove-all-following.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { FollowingsRepository, UsersRepository } from '@/models/index.js'; +import type { FollowingsRepository, UsersRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { QueueService } from '@/core/QueueService.js'; diff --git a/packages/backend/src/server/api/endpoints/admin/federation/update-instance.ts b/packages/backend/src/server/api/endpoints/admin/federation/update-instance.ts index 3d36f5e3a..357bf83e8 100644 --- a/packages/backend/src/server/api/endpoints/admin/federation/update-instance.ts +++ b/packages/backend/src/server/api/endpoints/admin/federation/update-instance.ts @@ -5,10 +5,11 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { InstancesRepository } from '@/models/index.js'; +import type { InstancesRepository } from '@/models/_.js'; import { UtilityService } from '@/core/UtilityService.js'; import { DI } from '@/di-symbols.js'; import { FederatedInstanceService } from '@/core/FederatedInstanceService.js'; +import { ModerationLogService } from '@/core/ModerationLogService.js'; export const meta = { tags: ['admin'], @@ -34,6 +35,7 @@ export default class extends Endpoint { // eslint- private utilityService: UtilityService, private federatedInstanceService: FederatedInstanceService, + private moderationLogService: ModerationLogService, ) { super(meta, paramDef, async (ps, me) => { const instance = await this.instancesRepository.findOneBy({ host: this.utilityService.toPuny(ps.host) }); @@ -42,9 +44,23 @@ export default class extends Endpoint { // eslint- throw new Error('instance not found'); } - this.federatedInstanceService.update(instance.id, { + await this.federatedInstanceService.update(instance.id, { isSuspended: ps.isSuspended, }); + + if (instance.isSuspended !== ps.isSuspended) { + if (ps.isSuspended) { + this.moderationLogService.log(me, 'suspendRemoteInstance', { + id: instance.id, + host: instance.host, + }); + } else { + this.moderationLogService.log(me, 'unsuspendRemoteInstance', { + id: instance.id, + host: instance.host, + }); + } + } }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/get-user-ips.ts b/packages/backend/src/server/api/endpoints/admin/get-user-ips.ts index d50fdb377..cf94c998f 100644 --- a/packages/backend/src/server/api/endpoints/admin/get-user-ips.ts +++ b/packages/backend/src/server/api/endpoints/admin/get-user-ips.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { UserIpsRepository } from '@/models/index.js'; +import type { UserIpsRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/admin/invite/create.ts b/packages/backend/src/server/api/endpoints/admin/invite/create.ts index eca633405..7112e06bd 100644 --- a/packages/backend/src/server/api/endpoints/admin/invite/create.ts +++ b/packages/backend/src/server/api/endpoints/admin/invite/create.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { RegistrationTicketsRepository } from '@/models/index.js'; +import type { RegistrationTicketsRepository } from '@/models/_.js'; import { InviteCodeEntityService } from '@/core/entities/InviteCodeEntityService.js'; import { IdService } from '@/core/IdService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/admin/invite/list.ts b/packages/backend/src/server/api/endpoints/admin/invite/list.ts index 8ac1b332d..a20a51121 100644 --- a/packages/backend/src/server/api/endpoints/admin/invite/list.ts +++ b/packages/backend/src/server/api/endpoints/admin/invite/list.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { RegistrationTicketsRepository } from '@/models/index.js'; +import type { RegistrationTicketsRepository } from '@/models/_.js'; import { InviteCodeEntityService } from '@/core/entities/InviteCodeEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts index 9b6dee296..c3ba07cdd 100644 --- a/packages/backend/src/server/api/endpoints/admin/meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/meta.ts @@ -85,6 +85,14 @@ export const meta = { type: 'string', optional: false, nullable: true, }, + app192IconUrl: { + type: 'string', + optional: false, nullable: true, + }, + app512IconUrl: { + type: 'string', + optional: false, nullable: true, + }, enableEmail: { type: 'boolean', optional: false, nullable: false, @@ -278,6 +286,10 @@ export const meta = { type: 'boolean', optional: false, nullable: false, }, + manifestJsonOverride: { + type: 'string', + optional: true, nullable: false, + }, policies: { type: 'object', optional: false, nullable: false, @@ -309,6 +321,7 @@ export default class extends Endpoint { // eslint- maintainerEmail: instance.maintainerEmail, version: this.config.version, name: instance.name, + shortName: instance.shortName, uri: this.config.url, description: instance.description, langs: instance.langs, @@ -331,6 +344,8 @@ export default class extends Endpoint { // eslint- notFoundImageUrl: instance.notFoundImageUrl, infoImageUrl: instance.infoImageUrl, iconUrl: instance.iconUrl, + app192IconUrl: instance.app192IconUrl, + app512IconUrl: instance.app512IconUrl, backgroundImageUrl: instance.backgroundImageUrl, logoImageUrl: instance.logoImageUrl, defaultLightTheme: instance.defaultLightTheme, @@ -383,6 +398,7 @@ export default class extends Endpoint { // eslint- enableServerMachineStats: instance.enableServerMachineStats, enableIdenticonGeneration: instance.enableIdenticonGeneration, policies: { ...DEFAULT_POLICIES, ...instance.policies }, + manifestJsonOverride: instance.manifestJsonOverride, }; }); } diff --git a/packages/backend/src/server/api/endpoints/admin/promo/create.ts b/packages/backend/src/server/api/endpoints/admin/promo/create.ts index d20d5d625..4061e1b5d 100644 --- a/packages/backend/src/server/api/endpoints/admin/promo/create.ts +++ b/packages/backend/src/server/api/endpoints/admin/promo/create.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { PromoNotesRepository } from '@/models/index.js'; +import type { PromoNotesRepository } from '@/models/_.js'; import { GetterService } from '@/server/api/GetterService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/admin/queue/clear.ts b/packages/backend/src/server/api/endpoints/admin/queue/clear.ts index b61c58003..c9142e988 100644 --- a/packages/backend/src/server/api/endpoints/admin/queue/clear.ts +++ b/packages/backend/src/server/api/endpoints/admin/queue/clear.ts @@ -30,7 +30,7 @@ export default class extends Endpoint { // eslint- super(meta, paramDef, async (ps, me) => { this.queueService.destroy(); - this.moderationLogService.insertModerationLog(me, 'clearQueue'); + this.moderationLogService.log(me, 'clearQueue'); }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/queue/promote.ts b/packages/backend/src/server/api/endpoints/admin/queue/promote.ts index 8d16cddd0..0cba5b4e2 100644 --- a/packages/backend/src/server/api/endpoints/admin/queue/promote.ts +++ b/packages/backend/src/server/api/endpoints/admin/queue/promote.ts @@ -70,7 +70,7 @@ export default class extends Endpoint { // eslint- break; } - this.moderationLogService.insertModerationLog(me, 'promoteQueue'); + this.moderationLogService.log(me, 'promoteQueue'); }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/reset-password.ts b/packages/backend/src/server/api/endpoints/admin/reset-password.ts index 77217e2ed..13e9c30ed 100644 --- a/packages/backend/src/server/api/endpoints/admin/reset-password.ts +++ b/packages/backend/src/server/api/endpoints/admin/reset-password.ts @@ -6,9 +6,10 @@ import { Inject, Injectable } from '@nestjs/common'; import bcrypt from 'bcryptjs'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { UsersRepository, UserProfilesRepository } from '@/models/index.js'; +import type { UsersRepository, UserProfilesRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { secureRndstr } from '@/misc/secure-rndstr.js'; +import { ModerationLogService } from '@/core/ModerationLogService.js'; export const meta = { tags: ['admin'], @@ -46,8 +47,10 @@ export default class extends Endpoint { // eslint- @Inject(DI.userProfilesRepository) private userProfilesRepository: UserProfilesRepository, + + private moderationLogService: ModerationLogService, ) { - super(meta, paramDef, async (ps) => { + super(meta, paramDef, async (ps, me) => { const user = await this.usersRepository.findOneBy({ id: ps.userId }); if (user == null) { @@ -69,6 +72,12 @@ export default class extends Endpoint { // eslint- password: hash, }); + this.moderationLogService.log(me, 'resetPassword', { + userId: user.id, + userUsername: user.username, + userHost: user.host, + }); + return { password: passwd, }; diff --git a/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts b/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts index 973dc2e70..fb5ac7a33 100644 --- a/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts +++ b/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts @@ -5,11 +5,12 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { UsersRepository, AbuseUserReportsRepository } from '@/models/index.js'; +import type { UsersRepository, AbuseUserReportsRepository } from '@/models/_.js'; import { InstanceActorService } from '@/core/InstanceActorService.js'; import { QueueService } from '@/core/QueueService.js'; import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; import { DI } from '@/di-symbols.js'; +import { ModerationLogService } from '@/core/ModerationLogService.js'; export const meta = { tags: ['admin'], @@ -41,6 +42,7 @@ export default class extends Endpoint { // eslint- private queueService: QueueService, private instanceActorService: InstanceActorService, private apRendererService: ApRendererService, + private moderationLogService: ModerationLogService, ) { super(meta, paramDef, async (ps, me) => { const report = await this.abuseUserReportsRepository.findOneBy({ id: ps.reportId }); @@ -61,6 +63,12 @@ export default class extends Endpoint { // eslint- assigneeId: me.id, forwarded: ps.forward && report.targetUserHost != null, }); + + this.moderationLogService.log(me, 'resolveAbuseReport', { + reportId: report.id, + report: report, + forwarded: ps.forward && report.targetUserHost != null, + }); }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/roles/assign.ts b/packages/backend/src/server/api/endpoints/admin/roles/assign.ts index 96887d219..a0f3edd86 100644 --- a/packages/backend/src/server/api/endpoints/admin/roles/assign.ts +++ b/packages/backend/src/server/api/endpoints/admin/roles/assign.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { RolesRepository, UsersRepository } from '@/models/index.js'; +import type { RolesRepository, UsersRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '@/server/api/error.js'; import { RoleService } from '@/core/RoleService.js'; @@ -83,7 +83,7 @@ export default class extends Endpoint { // eslint- return; } - await this.roleService.assign(user.id, role.id, ps.expiresAt ? new Date(ps.expiresAt) : null); + await this.roleService.assign(user.id, role.id, ps.expiresAt ? new Date(ps.expiresAt) : null, me); }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/roles/create.ts b/packages/backend/src/server/api/endpoints/admin/roles/create.ts index 37602490d..8451b1955 100644 --- a/packages/backend/src/server/api/endpoints/admin/roles/create.ts +++ b/packages/backend/src/server/api/endpoints/admin/roles/create.ts @@ -5,11 +5,8 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { RolesRepository } from '@/models/index.js'; -import { GlobalEventService } from '@/core/GlobalEventService.js'; -import { DI } from '@/di-symbols.js'; -import { IdService } from '@/core/IdService.js'; import { RoleEntityService } from '@/core/entities/RoleEntityService.js'; +import { RoleService } from '@/core/RoleService.js'; export const meta = { tags: ['admin', 'role'], @@ -58,37 +55,11 @@ export const paramDef = { @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( - @Inject(DI.rolesRepository) - private rolesRepository: RolesRepository, - - private globalEventService: GlobalEventService, - private idService: IdService, private roleEntityService: RoleEntityService, + private roleService: RoleService, ) { super(meta, paramDef, async (ps, me) => { - const date = new Date(); - const created = await this.rolesRepository.insert({ - id: this.idService.genId(), - createdAt: date, - updatedAt: date, - lastUsedAt: date, - name: ps.name, - description: ps.description, - color: ps.color, - iconUrl: ps.iconUrl, - target: ps.target, - condFormula: ps.condFormula, - isPublic: ps.isPublic, - isAdministrator: ps.isAdministrator, - isModerator: ps.isModerator, - isExplorable: ps.isExplorable, - asBadge: ps.asBadge, - canEditMembersByModerator: ps.canEditMembersByModerator, - displayOrder: ps.displayOrder, - policies: ps.policies, - }).then(x => this.rolesRepository.findOneByOrFail(x.identifiers[0])); - - this.globalEventService.publishInternalEvent('roleCreated', created); + const created = await this.roleService.create(ps, me); return await this.roleEntityService.pack(created, me); }); diff --git a/packages/backend/src/server/api/endpoints/admin/roles/delete.ts b/packages/backend/src/server/api/endpoints/admin/roles/delete.ts index 4a7694c3a..7b989050e 100644 --- a/packages/backend/src/server/api/endpoints/admin/roles/delete.ts +++ b/packages/backend/src/server/api/endpoints/admin/roles/delete.ts @@ -5,10 +5,10 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { RolesRepository } from '@/models/index.js'; -import { GlobalEventService } from '@/core/GlobalEventService.js'; +import type { RolesRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '@/server/api/error.js'; +import { RoleService } from '@/core/RoleService.js'; export const meta = { tags: ['admin', 'role'], @@ -41,17 +41,14 @@ export default class extends Endpoint { // eslint- @Inject(DI.rolesRepository) private rolesRepository: RolesRepository, - private globalEventService: GlobalEventService, + private roleService: RoleService, ) { - super(meta, paramDef, async (ps) => { + super(meta, paramDef, async (ps, me) => { const role = await this.rolesRepository.findOneBy({ id: ps.roleId }); if (role == null) { throw new ApiError(meta.errors.noSuchRole); } - await this.rolesRepository.delete({ - id: ps.roleId, - }); - this.globalEventService.publishInternalEvent('roleDeleted', role); + await this.roleService.delete(role, me); }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/roles/list.ts b/packages/backend/src/server/api/endpoints/admin/roles/list.ts index 07e4ec157..3ed4b324d 100644 --- a/packages/backend/src/server/api/endpoints/admin/roles/list.ts +++ b/packages/backend/src/server/api/endpoints/admin/roles/list.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { RolesRepository } from '@/models/index.js'; +import type { RolesRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { RoleEntityService } from '@/core/entities/RoleEntityService.js'; diff --git a/packages/backend/src/server/api/endpoints/admin/roles/show.ts b/packages/backend/src/server/api/endpoints/admin/roles/show.ts index c5908ed47..5f0accab6 100644 --- a/packages/backend/src/server/api/endpoints/admin/roles/show.ts +++ b/packages/backend/src/server/api/endpoints/admin/roles/show.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { RolesRepository } from '@/models/index.js'; +import type { RolesRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '@/server/api/error.js'; import { RoleEntityService } from '@/core/entities/RoleEntityService.js'; diff --git a/packages/backend/src/server/api/endpoints/admin/roles/unassign.ts b/packages/backend/src/server/api/endpoints/admin/roles/unassign.ts index 15bebdc33..4c2758311 100644 --- a/packages/backend/src/server/api/endpoints/admin/roles/unassign.ts +++ b/packages/backend/src/server/api/endpoints/admin/roles/unassign.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { RolesRepository, UsersRepository } from '@/models/index.js'; +import type { RolesRepository, UsersRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '@/server/api/error.js'; import { RoleService } from '@/core/RoleService.js'; @@ -81,7 +81,7 @@ export default class extends Endpoint { // eslint- throw new ApiError(meta.errors.noSuchUser); } - await this.roleService.unassign(user.id, role.id); + await this.roleService.unassign(user.id, role.id, me); }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/roles/update.ts b/packages/backend/src/server/api/endpoints/admin/roles/update.ts index a622e99f3..6031e2363 100644 --- a/packages/backend/src/server/api/endpoints/admin/roles/update.ts +++ b/packages/backend/src/server/api/endpoints/admin/roles/update.ts @@ -5,10 +5,11 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { RolesRepository } from '@/models/index.js'; +import type { RolesRepository } from '@/models/_.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '@/server/api/error.js'; +import { RoleService } from '@/core/RoleService.js'; export const meta = { tags: ['admin', 'role'], @@ -70,17 +71,15 @@ export default class extends Endpoint { // eslint- @Inject(DI.rolesRepository) private rolesRepository: RolesRepository, - private globalEventService: GlobalEventService, + private roleService: RoleService, ) { - super(meta, paramDef, async (ps) => { - const roleExist = await this.rolesRepository.exist({ where: { id: ps.roleId } }); - if (!roleExist) { + super(meta, paramDef, async (ps, me) => { + const role = await this.rolesRepository.findOneBy({ id: ps.roleId }); + if (role == null) { throw new ApiError(meta.errors.noSuchRole); } - const date = new Date(); - await this.rolesRepository.update(ps.roleId, { - updatedAt: date, + await this.roleService.update(role, { name: ps.name, description: ps.description, color: ps.color, @@ -95,9 +94,7 @@ export default class extends Endpoint { // eslint- canEditMembersByModerator: ps.canEditMembersByModerator, displayOrder: ps.displayOrder, policies: ps.policies, - }); - const updated = await this.rolesRepository.findOneByOrFail({ id: ps.roleId }); - this.globalEventService.publishInternalEvent('roleUpdated', updated); + }, me); }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/roles/users.ts b/packages/backend/src/server/api/endpoints/admin/roles/users.ts index a7fe9562a..b1772be77 100644 --- a/packages/backend/src/server/api/endpoints/admin/roles/users.ts +++ b/packages/backend/src/server/api/endpoints/admin/roles/users.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Brackets } from 'typeorm'; -import type { RoleAssignmentsRepository, RolesRepository } from '@/models/index.js'; +import type { RoleAssignmentsRepository, RolesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/admin/show-moderation-logs.ts b/packages/backend/src/server/api/endpoints/admin/show-moderation-logs.ts index 43c9a12c5..f87a5a357 100644 --- a/packages/backend/src/server/api/endpoints/admin/show-moderation-logs.ts +++ b/packages/backend/src/server/api/endpoints/admin/show-moderation-logs.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { ModerationLogsRepository } from '@/models/index.js'; +import type { ModerationLogsRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { DI } from '@/di-symbols.js'; import { ModerationLogEntityService } from '@/core/entities/ModerationLogEntityService.js'; @@ -62,6 +62,8 @@ export const paramDef = { limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, sinceId: { type: 'string', format: 'misskey:id' }, untilId: { type: 'string', format: 'misskey:id' }, + type: { type: 'string', nullable: true }, + userId: { type: 'string', format: 'misskey:id', nullable: true }, }, required: [], } as const; @@ -78,6 +80,14 @@ export default class extends Endpoint { // eslint- super(meta, paramDef, async (ps, me) => { const query = this.queryService.makePaginationQuery(this.moderationLogsRepository.createQueryBuilder('report'), ps.sinceId, ps.untilId); + if (ps.type != null) { + query.andWhere('report.type = :type', { type: ps.type }); + } + + if (ps.userId != null) { + query.andWhere('report.userId = :userId', { userId: ps.userId }); + } + const reports = await query.limit(ps.limit).getMany(); return await this.moderationLogEntityService.packMany(reports); diff --git a/packages/backend/src/server/api/endpoints/admin/show-user.ts b/packages/backend/src/server/api/endpoints/admin/show-user.ts index 26f4c91f7..e065b99e9 100644 --- a/packages/backend/src/server/api/endpoints/admin/show-user.ts +++ b/packages/backend/src/server/api/endpoints/admin/show-user.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { UsersRepository, SigninsRepository, UserProfilesRepository } from '@/models/index.js'; +import type { UsersRepository, SigninsRepository, UserProfilesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; import { RoleService } from '@/core/RoleService.js'; diff --git a/packages/backend/src/server/api/endpoints/admin/show-users.ts b/packages/backend/src/server/api/endpoints/admin/show-users.ts index 4008f8d78..e89e1a149 100644 --- a/packages/backend/src/server/api/endpoints/admin/show-users.ts +++ b/packages/backend/src/server/api/endpoints/admin/show-users.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { UsersRepository } from '@/models/index.js'; +import type { UsersRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; diff --git a/packages/backend/src/server/api/endpoints/admin/suspend-user.ts b/packages/backend/src/server/api/endpoints/admin/suspend-user.ts index d885e47de..9464f4b67 100644 --- a/packages/backend/src/server/api/endpoints/admin/suspend-user.ts +++ b/packages/backend/src/server/api/endpoints/admin/suspend-user.ts @@ -6,8 +6,8 @@ import { IsNull, Not } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { UsersRepository, FollowingsRepository } from '@/models/index.js'; -import type { MiUser } from '@/models/entities/User.js'; +import type { UsersRepository, FollowingsRepository } from '@/models/_.js'; +import type { MiUser } from '@/models/User.js'; import type { RelationshipJobData } from '@/queue/types.js'; import { ModerationLogService } from '@/core/ModerationLogService.js'; import { UserSuspendService } from '@/core/UserSuspendService.js'; @@ -60,8 +60,10 @@ export default class extends Endpoint { // eslint- isSuspended: true, }); - this.moderationLogService.insertModerationLog(me, 'suspend', { - targetId: user.id, + this.moderationLogService.log(me, 'suspend', { + userId: user.id, + userUsername: user.username, + userHost: user.host, }); (async () => { diff --git a/packages/backend/src/server/api/endpoints/admin/unsuspend-user.ts b/packages/backend/src/server/api/endpoints/admin/unsuspend-user.ts index 0980e3d42..5e523bbc3 100644 --- a/packages/backend/src/server/api/endpoints/admin/unsuspend-user.ts +++ b/packages/backend/src/server/api/endpoints/admin/unsuspend-user.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { UsersRepository } from '@/models/index.js'; +import type { UsersRepository } from '@/models/_.js'; import { ModerationLogService } from '@/core/ModerationLogService.js'; import { UserSuspendService } from '@/core/UserSuspendService.js'; import { DI } from '@/di-symbols.js'; @@ -45,8 +45,10 @@ export default class extends Endpoint { // eslint- isSuspended: false, }); - this.moderationLogService.insertModerationLog(me, 'unsuspend', { - targetId: user.id, + this.moderationLogService.log(me, 'unsuspend', { + userId: user.id, + userUsername: user.username, + userHost: user.host, }); this.userSuspendService.doPostUnsuspend(user); diff --git a/packages/backend/src/server/api/endpoints/admin/update-meta.ts b/packages/backend/src/server/api/endpoints/admin/update-meta.ts index 17d5a1f91..ea6ebdd1f 100644 --- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts @@ -4,7 +4,7 @@ */ import { Injectable } from '@nestjs/common'; -import type { MiMeta } from '@/models/entities/Meta.js'; +import type { MiMeta } from '@/models/Meta.js'; import { ModerationLogService } from '@/core/ModerationLogService.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { MetaService } from '@/core/MetaService.js'; @@ -39,9 +39,12 @@ export const paramDef = { infoImageUrl: { type: 'string', nullable: true }, notFoundImageUrl: { type: 'string', nullable: true }, iconUrl: { type: 'string', nullable: true }, + app192IconUrl: { type: 'string', nullable: true }, + app512IconUrl: { type: 'string', nullable: true }, backgroundImageUrl: { type: 'string', nullable: true }, logoImageUrl: { type: 'string', nullable: true }, name: { type: 'string', nullable: true }, + shortName: { type: 'string', nullable: true }, description: { type: 'string', nullable: true }, defaultLightTheme: { type: 'string', nullable: true }, defaultDarkTheme: { type: 'string', nullable: true }, @@ -104,6 +107,7 @@ export const paramDef = { enableIdenticonGeneration: { type: 'boolean' }, serverRules: { type: 'array', items: { type: 'string' } }, preservedUsernames: { type: 'array', items: { type: 'string' } }, + manifestJsonOverride: { type: 'string' }, }, required: [], } as const; @@ -153,6 +157,14 @@ export default class extends Endpoint { // eslint- set.iconUrl = ps.iconUrl; } + if (ps.app192IconUrl !== undefined) { + set.app192IconUrl = ps.app192IconUrl; + } + + if (ps.app512IconUrl !== undefined) { + set.app512IconUrl = ps.app512IconUrl; + } + if (ps.serverErrorImageUrl !== undefined) { set.serverErrorImageUrl = ps.serverErrorImageUrl; } @@ -177,6 +189,10 @@ export default class extends Endpoint { // eslint- set.name = ps.name; } + if (ps.shortName !== undefined) { + set.shortName = ps.shortName; + } + if (ps.description !== undefined) { set.description = ps.description; } @@ -421,8 +437,20 @@ export default class extends Endpoint { // eslint- set.preservedUsernames = ps.preservedUsernames; } + if (ps.manifestJsonOverride !== undefined) { + set.manifestJsonOverride = ps.manifestJsonOverride; + } + + const before = await this.metaService.fetch(true); + await this.metaService.update(set); - this.moderationLogService.insertModerationLog(me, 'updateMeta'); + + const after = await this.metaService.fetch(true); + + this.moderationLogService.log(me, 'updateServerSettings', { + before, + after, + }); }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/update-user-note.ts b/packages/backend/src/server/api/endpoints/admin/update-user-note.ts index e155f8c93..bfccc2a2a 100644 --- a/packages/backend/src/server/api/endpoints/admin/update-user-note.ts +++ b/packages/backend/src/server/api/endpoints/admin/update-user-note.ts @@ -4,9 +4,10 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { UserProfilesRepository, UsersRepository } from '@/models/index.js'; +import type { UserProfilesRepository, UsersRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; +import { ModerationLogService } from '@/core/ModerationLogService.js'; export const meta = { tags: ['admin'], @@ -32,6 +33,8 @@ export default class extends Endpoint { // eslint- @Inject(DI.userProfilesRepository) private userProfilesRepository: UserProfilesRepository, + + private moderationLogService: ModerationLogService, ) { super(meta, paramDef, async (ps, me) => { const user = await this.usersRepository.findOneBy({ id: ps.userId }); @@ -40,9 +43,19 @@ export default class extends Endpoint { // eslint- throw new Error('user not found'); } + const currentProfile = await this.userProfilesRepository.findOneByOrFail({ userId: user.id }); + await this.userProfilesRepository.update({ userId: user.id }, { moderationNote: ps.text, }); + + this.moderationLogService.log(me, 'updateUserNote', { + userId: user.id, + userUsername: user.username, + userHost: user.host, + before: currentProfile.moderationNote, + after: ps.text, + }); }); } } diff --git a/packages/backend/src/server/api/endpoints/announcements.ts b/packages/backend/src/server/api/endpoints/announcements.ts index bd4dc0b8b..7c242dbcd 100644 --- a/packages/backend/src/server/api/endpoints/announcements.ts +++ b/packages/backend/src/server/api/endpoints/announcements.ts @@ -9,7 +9,7 @@ import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; import { AnnouncementService } from '@/core/AnnouncementService.js'; import { DI } from '@/di-symbols.js'; -import type { AnnouncementReadsRepository, AnnouncementsRepository } from '@/models/index.js'; +import type { AnnouncementReadsRepository, AnnouncementsRepository } from '@/models/_.js'; export const meta = { tags: ['meta'], @@ -52,7 +52,7 @@ export default class extends Endpoint { // eslint- ) { super(meta, paramDef, async (ps, me) => { const query = this.queryService.makePaginationQuery(this.announcementsRepository.createQueryBuilder('announcement'), ps.sinceId, ps.untilId) - .where('announcement.isActive = :isActive', { isActive: ps.isActive }) + .andWhere('announcement.isActive = :isActive', { isActive: ps.isActive }) .andWhere(new Brackets(qb => { if (me) qb.orWhere('announcement.userId = :meId', { meId: me.id }); qb.orWhere('announcement.userId IS NULL'); diff --git a/packages/backend/src/server/api/endpoints/antennas/create.ts b/packages/backend/src/server/api/endpoints/antennas/create.ts index 1f6a3fa73..15fca4904 100644 --- a/packages/backend/src/server/api/endpoints/antennas/create.ts +++ b/packages/backend/src/server/api/endpoints/antennas/create.ts @@ -6,7 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { IdService } from '@/core/IdService.js'; -import type { UserListsRepository, AntennasRepository } from '@/models/index.js'; +import type { UserListsRepository, AntennasRepository } from '@/models/_.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { AntennaEntityService } from '@/core/entities/AntennaEntityService.js'; import { DI } from '@/di-symbols.js'; @@ -47,7 +47,7 @@ export const paramDef = { type: 'object', properties: { name: { type: 'string', minLength: 1, maxLength: 100 }, - src: { type: 'string', enum: ['home', 'all', 'users', 'list'] }, + src: { type: 'string', enum: ['home', 'all', 'users', 'list', 'users_blacklist'] }, userListId: { type: 'string', format: 'misskey:id', nullable: true }, keywords: { type: 'array', items: { type: 'array', items: { diff --git a/packages/backend/src/server/api/endpoints/antennas/delete.ts b/packages/backend/src/server/api/endpoints/antennas/delete.ts index f59911017..e6240aec6 100644 --- a/packages/backend/src/server/api/endpoints/antennas/delete.ts +++ b/packages/backend/src/server/api/endpoints/antennas/delete.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { AntennasRepository } from '@/models/index.js'; +import type { AntennasRepository } from '@/models/_.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/antennas/list.ts b/packages/backend/src/server/api/endpoints/antennas/list.ts index 71d5b746a..3a9f969d2 100644 --- a/packages/backend/src/server/api/endpoints/antennas/list.ts +++ b/packages/backend/src/server/api/endpoints/antennas/list.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { AntennasRepository } from '@/models/index.js'; +import type { AntennasRepository } from '@/models/_.js'; import { AntennaEntityService } from '@/core/entities/AntennaEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/antennas/notes.ts b/packages/backend/src/server/api/endpoints/antennas/notes.ts index 4b49f8aea..eaae7bff6 100644 --- a/packages/backend/src/server/api/endpoints/antennas/notes.ts +++ b/packages/backend/src/server/api/endpoints/antennas/notes.ts @@ -6,7 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import * as Redis from 'ioredis'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { NotesRepository, AntennasRepository } from '@/models/index.js'; +import type { NotesRepository, AntennasRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { NoteReadService } from '@/core/NoteReadService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/antennas/show.ts b/packages/backend/src/server/api/endpoints/antennas/show.ts index b2168dacf..77c9b3176 100644 --- a/packages/backend/src/server/api/endpoints/antennas/show.ts +++ b/packages/backend/src/server/api/endpoints/antennas/show.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { AntennasRepository } from '@/models/index.js'; +import type { AntennasRepository } from '@/models/_.js'; import { AntennaEntityService } from '@/core/entities/AntennaEntityService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/antennas/update.ts b/packages/backend/src/server/api/endpoints/antennas/update.ts index 6247c5469..0e9874688 100644 --- a/packages/backend/src/server/api/endpoints/antennas/update.ts +++ b/packages/backend/src/server/api/endpoints/antennas/update.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { AntennasRepository, UserListsRepository } from '@/models/index.js'; +import type { AntennasRepository, UserListsRepository } from '@/models/_.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { AntennaEntityService } from '@/core/entities/AntennaEntityService.js'; import { DI } from '@/di-symbols.js'; @@ -46,7 +46,7 @@ export const paramDef = { properties: { antennaId: { type: 'string', format: 'misskey:id' }, name: { type: 'string', minLength: 1, maxLength: 100 }, - src: { type: 'string', enum: ['home', 'all', 'users', 'list'] }, + src: { type: 'string', enum: ['home', 'all', 'users', 'list', 'users_blacklist'] }, userListId: { type: 'string', format: 'misskey:id', nullable: true }, keywords: { type: 'array', items: { type: 'array', items: { diff --git a/packages/backend/src/server/api/endpoints/ap/show.ts b/packages/backend/src/server/api/endpoints/ap/show.ts index f3ca931f2..f442fbdd2 100644 --- a/packages/backend/src/server/api/endpoints/ap/show.ts +++ b/packages/backend/src/server/api/endpoints/ap/show.ts @@ -6,8 +6,8 @@ import { Injectable } from '@nestjs/common'; import ms from 'ms'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { MiNote } from '@/models/entities/Note.js'; -import type { MiLocalUser, MiUser } from '@/models/entities/User.js'; +import type { MiNote } from '@/models/Note.js'; +import type { MiLocalUser, MiUser } from '@/models/User.js'; import { isActor, isPost, getApId } from '@/core/activitypub/type.js'; import type { SchemaType } from '@/misc/json-schema.js'; import { ApResolverService } from '@/core/activitypub/ApResolverService.js'; diff --git a/packages/backend/src/server/api/endpoints/app/create.ts b/packages/backend/src/server/api/endpoints/app/create.ts index 2afd98ffe..cb0022150 100644 --- a/packages/backend/src/server/api/endpoints/app/create.ts +++ b/packages/backend/src/server/api/endpoints/app/create.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { AppsRepository } from '@/models/index.js'; +import type { AppsRepository } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; import { unique } from '@/misc/prelude/array.js'; import { secureRndstr } from '@/misc/secure-rndstr.js'; diff --git a/packages/backend/src/server/api/endpoints/app/show.ts b/packages/backend/src/server/api/endpoints/app/show.ts index 5291bbb4f..cb968a1c6 100644 --- a/packages/backend/src/server/api/endpoints/app/show.ts +++ b/packages/backend/src/server/api/endpoints/app/show.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { AppsRepository } from '@/models/index.js'; +import type { AppsRepository } from '@/models/_.js'; import { AppEntityService } from '@/core/entities/AppEntityService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/auth/accept.ts b/packages/backend/src/server/api/endpoints/auth/accept.ts index 31457afaa..1b1893fd9 100644 --- a/packages/backend/src/server/api/endpoints/auth/accept.ts +++ b/packages/backend/src/server/api/endpoints/auth/accept.ts @@ -6,7 +6,7 @@ import * as crypto from 'node:crypto'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { AuthSessionsRepository, AppsRepository, AccessTokensRepository } from '@/models/index.js'; +import type { AuthSessionsRepository, AppsRepository, AccessTokensRepository } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; import { secureRndstr } from '@/misc/secure-rndstr.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/auth/session/generate.ts b/packages/backend/src/server/api/endpoints/auth/session/generate.ts index ed906f816..8b6a2c213 100644 --- a/packages/backend/src/server/api/endpoints/auth/session/generate.ts +++ b/packages/backend/src/server/api/endpoints/auth/session/generate.ts @@ -6,7 +6,7 @@ import { randomUUID } from 'node:crypto'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { AppsRepository, AuthSessionsRepository } from '@/models/index.js'; +import type { AppsRepository, AuthSessionsRepository } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; import type { Config } from '@/config.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/auth/session/show.ts b/packages/backend/src/server/api/endpoints/auth/session/show.ts index 4cf47d238..0f5da0f25 100644 --- a/packages/backend/src/server/api/endpoints/auth/session/show.ts +++ b/packages/backend/src/server/api/endpoints/auth/session/show.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { AuthSessionsRepository } from '@/models/index.js'; +import type { AuthSessionsRepository } from '@/models/_.js'; import { AuthSessionEntityService } from '@/core/entities/AuthSessionEntityService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/auth/session/userkey.ts b/packages/backend/src/server/api/endpoints/auth/session/userkey.ts index ab7393f99..ffddda090 100644 --- a/packages/backend/src/server/api/endpoints/auth/session/userkey.ts +++ b/packages/backend/src/server/api/endpoints/auth/session/userkey.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { AppsRepository, AccessTokensRepository, AuthSessionsRepository } from '@/models/index.js'; +import type { AppsRepository, AccessTokensRepository, AuthSessionsRepository } from '@/models/_.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/blocking/create.ts b/packages/backend/src/server/api/endpoints/blocking/create.ts index dc1d7379d..3c7d7ac8c 100644 --- a/packages/backend/src/server/api/endpoints/blocking/create.ts +++ b/packages/backend/src/server/api/endpoints/blocking/create.ts @@ -6,7 +6,7 @@ import ms from 'ms'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { UsersRepository, BlockingsRepository } from '@/models/index.js'; +import type { UsersRepository, BlockingsRepository } from '@/models/_.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { UserBlockingService } from '@/core/UserBlockingService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/blocking/delete.ts b/packages/backend/src/server/api/endpoints/blocking/delete.ts index c5cf104b8..0ce334d55 100644 --- a/packages/backend/src/server/api/endpoints/blocking/delete.ts +++ b/packages/backend/src/server/api/endpoints/blocking/delete.ts @@ -6,7 +6,7 @@ import ms from 'ms'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { UsersRepository, BlockingsRepository } from '@/models/index.js'; +import type { UsersRepository, BlockingsRepository } from '@/models/_.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { UserBlockingService } from '@/core/UserBlockingService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/blocking/list.ts b/packages/backend/src/server/api/endpoints/blocking/list.ts index 40534cb57..58d24540d 100644 --- a/packages/backend/src/server/api/endpoints/blocking/list.ts +++ b/packages/backend/src/server/api/endpoints/blocking/list.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { BlockingsRepository } from '@/models/index.js'; +import type { BlockingsRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { BlockingEntityService } from '@/core/entities/BlockingEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/channels/create.ts b/packages/backend/src/server/api/endpoints/channels/create.ts index 95d9b07c2..e72120e15 100644 --- a/packages/backend/src/server/api/endpoints/channels/create.ts +++ b/packages/backend/src/server/api/endpoints/channels/create.ts @@ -6,8 +6,8 @@ import { Inject, Injectable } from '@nestjs/common'; import ms from 'ms'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { ChannelsRepository, DriveFilesRepository } from '@/models/index.js'; -import type { MiChannel } from '@/models/entities/Channel.js'; +import type { ChannelsRepository, DriveFilesRepository } from '@/models/_.js'; +import type { MiChannel } from '@/models/Channel.js'; import { IdService } from '@/core/IdService.js'; import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/channels/favorite.ts b/packages/backend/src/server/api/endpoints/channels/favorite.ts index 4baadac04..1f78a86dd 100644 --- a/packages/backend/src/server/api/endpoints/channels/favorite.ts +++ b/packages/backend/src/server/api/endpoints/channels/favorite.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { ChannelFavoritesRepository, ChannelsRepository } from '@/models/index.js'; +import type { ChannelFavoritesRepository, ChannelsRepository } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/channels/featured.ts b/packages/backend/src/server/api/endpoints/channels/featured.ts index b608ae7cc..412ea1bb1 100644 --- a/packages/backend/src/server/api/endpoints/channels/featured.ts +++ b/packages/backend/src/server/api/endpoints/channels/featured.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { ChannelsRepository } from '@/models/index.js'; +import type { ChannelsRepository } from '@/models/_.js'; import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/channels/follow.ts b/packages/backend/src/server/api/endpoints/channels/follow.ts index 83a612a49..5a43e8be1 100644 --- a/packages/backend/src/server/api/endpoints/channels/follow.ts +++ b/packages/backend/src/server/api/endpoints/channels/follow.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { ChannelFollowingsRepository, ChannelsRepository } from '@/models/index.js'; +import type { ChannelFollowingsRepository, ChannelsRepository } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/channels/followed.ts b/packages/backend/src/server/api/endpoints/channels/followed.ts index 60279f74e..6514f1ea3 100644 --- a/packages/backend/src/server/api/endpoints/channels/followed.ts +++ b/packages/backend/src/server/api/endpoints/channels/followed.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { ChannelFollowingsRepository } from '@/models/index.js'; +import type { ChannelFollowingsRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/channels/my-favorites.ts b/packages/backend/src/server/api/endpoints/channels/my-favorites.ts index 2ef3420dc..057a438ac 100644 --- a/packages/backend/src/server/api/endpoints/channels/my-favorites.ts +++ b/packages/backend/src/server/api/endpoints/channels/my-favorites.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { ChannelFavoritesRepository } from '@/models/index.js'; +import type { ChannelFavoritesRepository } from '@/models/_.js'; import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/channels/owned.ts b/packages/backend/src/server/api/endpoints/channels/owned.ts index 878d834f3..b1dd69353 100644 --- a/packages/backend/src/server/api/endpoints/channels/owned.ts +++ b/packages/backend/src/server/api/endpoints/channels/owned.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { ChannelsRepository } from '@/models/index.js'; +import type { ChannelsRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/channels/search.ts b/packages/backend/src/server/api/endpoints/channels/search.ts index ab25e2b9c..65df45706 100644 --- a/packages/backend/src/server/api/endpoints/channels/search.ts +++ b/packages/backend/src/server/api/endpoints/channels/search.ts @@ -7,7 +7,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Brackets } from 'typeorm'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; -import type { ChannelsRepository } from '@/models/index.js'; +import type { ChannelsRepository } from '@/models/_.js'; import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js'; import { DI } from '@/di-symbols.js'; import { sqlLikeEscape } from '@/misc/sql-like-escape.js'; diff --git a/packages/backend/src/server/api/endpoints/channels/show.ts b/packages/backend/src/server/api/endpoints/channels/show.ts index c7ed443e2..3eaa83c7e 100644 --- a/packages/backend/src/server/api/endpoints/channels/show.ts +++ b/packages/backend/src/server/api/endpoints/channels/show.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { ChannelsRepository } from '@/models/index.js'; +import type { ChannelsRepository } from '@/models/_.js'; import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/channels/timeline.ts b/packages/backend/src/server/api/endpoints/channels/timeline.ts index dd0db515b..026b64953 100644 --- a/packages/backend/src/server/api/endpoints/channels/timeline.ts +++ b/packages/backend/src/server/api/endpoints/channels/timeline.ts @@ -6,7 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import * as Redis from 'ioredis'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { ChannelsRepository, MiNote, NotesRepository } from '@/models/index.js'; +import type { ChannelsRepository, MiNote, NotesRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import ActiveUsersChart from '@/core/chart/charts/active-users.js'; diff --git a/packages/backend/src/server/api/endpoints/channels/unfavorite.ts b/packages/backend/src/server/api/endpoints/channels/unfavorite.ts index 8c2ffda98..b4c7af815 100644 --- a/packages/backend/src/server/api/endpoints/channels/unfavorite.ts +++ b/packages/backend/src/server/api/endpoints/channels/unfavorite.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { ChannelFavoritesRepository, ChannelsRepository } from '@/models/index.js'; +import type { ChannelFavoritesRepository, ChannelsRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/channels/unfollow.ts b/packages/backend/src/server/api/endpoints/channels/unfollow.ts index 774baa068..46883dd54 100644 --- a/packages/backend/src/server/api/endpoints/channels/unfollow.ts +++ b/packages/backend/src/server/api/endpoints/channels/unfollow.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { ChannelFollowingsRepository, ChannelsRepository } from '@/models/index.js'; +import type { ChannelFollowingsRepository, ChannelsRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/channels/update.ts b/packages/backend/src/server/api/endpoints/channels/update.ts index f5d64bd53..ab69f62a7 100644 --- a/packages/backend/src/server/api/endpoints/channels/update.ts +++ b/packages/backend/src/server/api/endpoints/channels/update.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { DriveFilesRepository, ChannelsRepository } from '@/models/index.js'; +import type { DriveFilesRepository, ChannelsRepository } from '@/models/_.js'; import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js'; import { DI } from '@/di-symbols.js'; import { RoleService } from '@/core/RoleService.js'; diff --git a/packages/backend/src/server/api/endpoints/clips/add-note.ts b/packages/backend/src/server/api/endpoints/clips/add-note.ts index 40bbad4e6..749593aa6 100644 --- a/packages/backend/src/server/api/endpoints/clips/add-note.ts +++ b/packages/backend/src/server/api/endpoints/clips/add-note.ts @@ -6,11 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import ms from 'ms'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import { IdService } from '@/core/IdService.js'; -import { DI } from '@/di-symbols.js'; -import type { ClipNotesRepository, ClipsRepository } from '@/models/index.js'; -import { GetterService } from '@/server/api/GetterService.js'; -import { RoleService } from '@/core/RoleService.js'; +import { ClipService } from '@/core/ClipService.js'; import { ApiError } from '../../error.js'; export const meta = { @@ -66,58 +62,24 @@ export const paramDef = { @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( - @Inject(DI.clipsRepository) - private clipsRepository: ClipsRepository, - - @Inject(DI.clipNotesRepository) - private clipNotesRepository: ClipNotesRepository, - - private idService: IdService, - private roleService: RoleService, - private getterService: GetterService, + private clipService: ClipService, ) { super(meta, paramDef, async (ps, me) => { - const clip = await this.clipsRepository.findOneBy({ - id: ps.clipId, - userId: me.id, - }); - - if (clip == null) { - throw new ApiError(meta.errors.noSuchClip); + try { + await this.clipService.addNote(me, ps.clipId, ps.noteId); + } catch (e) { + if (e instanceof ClipService.NoSuchClipError) { + throw new ApiError(meta.errors.noSuchClip); + } else if (e instanceof ClipService.NoSuchNoteError) { + throw new ApiError(meta.errors.noSuchNote); + } else if (e instanceof ClipService.AlreadyAddedError) { + throw new ApiError(meta.errors.alreadyClipped); + } else if (e instanceof ClipService.TooManyClipNotesError) { + throw new ApiError(meta.errors.tooManyClipNotes); + } else { + throw e; + } } - - const note = await this.getterService.getNote(ps.noteId).catch(e => { - if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); - throw e; - }); - - const exist = await this.clipNotesRepository.exist({ - where: { - noteId: note.id, - clipId: clip.id, - }, - }); - - if (exist) { - throw new ApiError(meta.errors.alreadyClipped); - } - - const currentCount = await this.clipNotesRepository.countBy({ - clipId: clip.id, - }); - if (currentCount > (await this.roleService.getUserPolicies(me.id)).noteEachClipsLimit) { - throw new ApiError(meta.errors.tooManyClipNotes); - } - - await this.clipNotesRepository.insert({ - id: this.idService.genId(), - noteId: note.id, - clipId: clip.id, - }); - - await this.clipsRepository.update(clip.id, { - lastClippedAt: new Date(), - }); }); } } diff --git a/packages/backend/src/server/api/endpoints/clips/create.ts b/packages/backend/src/server/api/endpoints/clips/create.ts index 29eaf0577..b4c7b52e7 100644 --- a/packages/backend/src/server/api/endpoints/clips/create.ts +++ b/packages/backend/src/server/api/endpoints/clips/create.ts @@ -5,12 +5,10 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import { IdService } from '@/core/IdService.js'; -import type { ClipsRepository } from '@/models/index.js'; +import type { MiClip } from '@/models/_.js'; import { ClipEntityService } from '@/core/entities/ClipEntityService.js'; -import { DI } from '@/di-symbols.js'; -import { RoleService } from '@/core/RoleService.js'; import { ApiError } from '@/server/api/error.js'; +import { ClipService } from '@/core/ClipService.js'; export const meta = { tags: ['clips'], @@ -49,30 +47,19 @@ export const paramDef = { @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( - @Inject(DI.clipsRepository) - private clipsRepository: ClipsRepository, - private clipEntityService: ClipEntityService, - private roleService: RoleService, - private idService: IdService, + private clipService: ClipService, ) { super(meta, paramDef, async (ps, me) => { - const currentCount = await this.clipsRepository.countBy({ - userId: me.id, - }); - if (currentCount > (await this.roleService.getUserPolicies(me.id)).clipLimit) { - throw new ApiError(meta.errors.tooManyClips); + let clip: MiClip; + try { + clip = await this.clipService.create(me, ps.name, ps.isPublic, ps.description ?? null); + } catch (e) { + if (e instanceof ClipService.TooManyClipsError) { + throw new ApiError(meta.errors.tooManyClips); + } + throw e; } - - const clip = await this.clipsRepository.insert({ - id: this.idService.genId(), - createdAt: new Date(), - userId: me.id, - name: ps.name, - isPublic: ps.isPublic, - description: ps.description, - }).then(x => this.clipsRepository.findOneByOrFail(x.identifiers[0])); - return await this.clipEntityService.pack(clip, me); }); } diff --git a/packages/backend/src/server/api/endpoints/clips/delete.ts b/packages/backend/src/server/api/endpoints/clips/delete.ts index cfad66f6e..239945e8a 100644 --- a/packages/backend/src/server/api/endpoints/clips/delete.ts +++ b/packages/backend/src/server/api/endpoints/clips/delete.ts @@ -5,8 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { ClipsRepository } from '@/models/index.js'; -import { DI } from '@/di-symbols.js'; +import { ClipService } from '@/core/ClipService.js'; import { ApiError } from '../../error.js'; export const meta = { @@ -36,20 +35,17 @@ export const paramDef = { @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( - @Inject(DI.clipsRepository) - private clipsRepository: ClipsRepository, + private clipService: ClipService, ) { super(meta, paramDef, async (ps, me) => { - const clip = await this.clipsRepository.findOneBy({ - id: ps.clipId, - userId: me.id, - }); - - if (clip == null) { - throw new ApiError(meta.errors.noSuchClip); + try { + await this.clipService.delete(me, ps.clipId); + } catch (e) { + if (e instanceof ClipService.NoSuchClipError) { + throw new ApiError(meta.errors.noSuchClip); + } + throw e; } - - await this.clipsRepository.delete(clip.id); }); } } diff --git a/packages/backend/src/server/api/endpoints/clips/favorite.ts b/packages/backend/src/server/api/endpoints/clips/favorite.ts index 668a374c0..6cd34f0a5 100644 --- a/packages/backend/src/server/api/endpoints/clips/favorite.ts +++ b/packages/backend/src/server/api/endpoints/clips/favorite.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { ClipsRepository, ClipFavoritesRepository } from '@/models/index.js'; +import type { ClipsRepository, ClipFavoritesRepository } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/clips/list.ts b/packages/backend/src/server/api/endpoints/clips/list.ts index 45f38c7bb..c124762e3 100644 --- a/packages/backend/src/server/api/endpoints/clips/list.ts +++ b/packages/backend/src/server/api/endpoints/clips/list.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { ClipsRepository } from '@/models/index.js'; +import type { ClipsRepository } from '@/models/_.js'; import { ClipEntityService } from '@/core/entities/ClipEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/clips/my-favorites.ts b/packages/backend/src/server/api/endpoints/clips/my-favorites.ts index 827217974..c58c16e25 100644 --- a/packages/backend/src/server/api/endpoints/clips/my-favorites.ts +++ b/packages/backend/src/server/api/endpoints/clips/my-favorites.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { ClipFavoritesRepository } from '@/models/index.js'; +import type { ClipFavoritesRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { ClipEntityService } from '@/core/entities/ClipEntityService.js'; diff --git a/packages/backend/src/server/api/endpoints/clips/notes.ts b/packages/backend/src/server/api/endpoints/clips/notes.ts index 4efd17051..1427d8d0a 100644 --- a/packages/backend/src/server/api/endpoints/clips/notes.ts +++ b/packages/backend/src/server/api/endpoints/clips/notes.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { NotesRepository, ClipsRepository, ClipNotesRepository } from '@/models/index.js'; +import type { NotesRepository, ClipsRepository, ClipNotesRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/clips/remove-note.ts b/packages/backend/src/server/api/endpoints/clips/remove-note.ts index ef3c32a1f..7b153cb55 100644 --- a/packages/backend/src/server/api/endpoints/clips/remove-note.ts +++ b/packages/backend/src/server/api/endpoints/clips/remove-note.ts @@ -5,9 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { ClipNotesRepository, ClipsRepository } from '@/models/index.js'; -import { DI } from '@/di-symbols.js'; -import { GetterService } from '@/server/api/GetterService.js'; +import { ClipService } from '@/core/ClipService.js'; import { ApiError } from '../../error.js'; export const meta = { @@ -46,33 +44,19 @@ export const paramDef = { @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( - @Inject(DI.clipsRepository) - private clipsRepository: ClipsRepository, - - @Inject(DI.clipNotesRepository) - private clipNotesRepository: ClipNotesRepository, - - private getterService: GetterService, + private clipService: ClipService, ) { super(meta, paramDef, async (ps, me) => { - const clip = await this.clipsRepository.findOneBy({ - id: ps.clipId, - userId: me.id, - }); - - if (clip == null) { - throw new ApiError(meta.errors.noSuchClip); + try { + await this.clipService.removeNote(me, ps.clipId, ps.noteId); + } catch (e) { + if (e instanceof ClipService.NoSuchClipError) { + throw new ApiError(meta.errors.noSuchClip); + } else if (e instanceof ClipService.NoSuchNoteError) { + throw new ApiError(meta.errors.noSuchNote); + } + throw e; } - - const note = await this.getterService.getNote(ps.noteId).catch(err => { - if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); - throw err; - }); - - await this.clipNotesRepository.delete({ - noteId: note.id, - clipId: clip.id, - }); }); } } diff --git a/packages/backend/src/server/api/endpoints/clips/show.ts b/packages/backend/src/server/api/endpoints/clips/show.ts index 2132ceb7d..03b1e09df 100644 --- a/packages/backend/src/server/api/endpoints/clips/show.ts +++ b/packages/backend/src/server/api/endpoints/clips/show.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { ClipsRepository } from '@/models/index.js'; +import type { ClipsRepository } from '@/models/_.js'; import { ClipEntityService } from '@/core/entities/ClipEntityService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/clips/unfavorite.ts b/packages/backend/src/server/api/endpoints/clips/unfavorite.ts index 139fbab96..d1007f7a1 100644 --- a/packages/backend/src/server/api/endpoints/clips/unfavorite.ts +++ b/packages/backend/src/server/api/endpoints/clips/unfavorite.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { ClipsRepository, ClipFavoritesRepository } from '@/models/index.js'; +import type { ClipsRepository, ClipFavoritesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/clips/update.ts b/packages/backend/src/server/api/endpoints/clips/update.ts index 58609b01e..0b9878578 100644 --- a/packages/backend/src/server/api/endpoints/clips/update.ts +++ b/packages/backend/src/server/api/endpoints/clips/update.ts @@ -5,9 +5,8 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { ClipsRepository } from '@/models/index.js'; import { ClipEntityService } from '@/core/entities/ClipEntityService.js'; -import { DI } from '@/di-symbols.js'; +import { ClipService } from '@/core/ClipService.js'; import { ApiError } from '../../error.js'; export const meta = { @@ -48,29 +47,21 @@ export const paramDef = { @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( - @Inject(DI.clipsRepository) - private clipsRepository: ClipsRepository, + private clipService: ClipService, private clipEntityService: ClipEntityService, ) { super(meta, paramDef, async (ps, me) => { - // Fetch the clip - const clip = await this.clipsRepository.findOneBy({ - id: ps.clipId, - userId: me.id, - }); - - if (clip == null) { - throw new ApiError(meta.errors.noSuchClip); + try { + await this.clipService.update(me, ps.clipId, ps.name, ps.isPublic, ps.description); + } catch (e) { + if (e instanceof ClipService.NoSuchClipError) { + throw new ApiError(meta.errors.noSuchClip); + } + throw e; } - await this.clipsRepository.update(clip.id, { - name: ps.name, - description: ps.description, - isPublic: ps.isPublic, - }); - - return await this.clipEntityService.pack(clip.id, me); + return await this.clipEntityService.pack(ps.clipId, me); }); } } diff --git a/packages/backend/src/server/api/endpoints/drive/files.ts b/packages/backend/src/server/api/endpoints/drive/files.ts index 81db4b974..6f3a62977 100644 --- a/packages/backend/src/server/api/endpoints/drive/files.ts +++ b/packages/backend/src/server/api/endpoints/drive/files.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { DriveFilesRepository } from '@/models/index.js'; +import type { DriveFilesRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/drive/files/attached-notes.ts b/packages/backend/src/server/api/endpoints/drive/files/attached-notes.ts index 49f79a1ab..779231a85 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/attached-notes.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/attached-notes.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { NotesRepository, DriveFilesRepository } from '@/models/index.js'; +import type { NotesRepository, DriveFilesRepository } from '@/models/_.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/drive/files/check-existence.ts b/packages/backend/src/server/api/endpoints/drive/files/check-existence.ts index 9bb0b12f5..85e6312b6 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/check-existence.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/check-existence.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { DriveFilesRepository } from '@/models/index.js'; +import type { DriveFilesRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; export const meta = { diff --git a/packages/backend/src/server/api/endpoints/drive/files/delete.ts b/packages/backend/src/server/api/endpoints/drive/files/delete.ts index 49fc2d0a8..f46bf4996 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/delete.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/delete.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { DriveFilesRepository } from '@/models/index.js'; +import type { DriveFilesRepository } from '@/models/_.js'; import { DriveService } from '@/core/DriveService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; @@ -65,11 +65,7 @@ export default class extends Endpoint { // eslint- throw new ApiError(meta.errors.accessDenied); } - // Delete - await this.driveService.deleteFile(file); - - // Publish fileDeleted event - this.globalEventService.publishDriveStream(me.id, 'fileDeleted', file.id); + await this.driveService.deleteFile(file, false, me); }); } } diff --git a/packages/backend/src/server/api/endpoints/drive/files/find-by-hash.ts b/packages/backend/src/server/api/endpoints/drive/files/find-by-hash.ts index 4eede4e34..7b784f253 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/find-by-hash.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/find-by-hash.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { DriveFilesRepository } from '@/models/index.js'; +import type { DriveFilesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/drive/files/find.ts b/packages/backend/src/server/api/endpoints/drive/files/find.ts index ecd7f7934..0ceb31e58 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/find.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/find.ts @@ -6,7 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { IsNull } from 'typeorm'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { DriveFilesRepository } from '@/models/index.js'; +import type { DriveFilesRepository } from '@/models/_.js'; import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/drive/files/show.ts b/packages/backend/src/server/api/endpoints/drive/files/show.ts index 941be2079..474c7f02d 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/show.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/show.ts @@ -4,8 +4,8 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { MiDriveFile } from '@/models/entities/DriveFile.js'; -import type { DriveFilesRepository } from '@/models/index.js'; +import type { MiDriveFile } from '@/models/DriveFile.js'; +import type { DriveFilesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/drive/files/update.ts b/packages/backend/src/server/api/endpoints/drive/files/update.ts index 902570016..c01f3de03 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/update.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/update.ts @@ -4,12 +4,11 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { DriveFilesRepository, DriveFoldersRepository } from '@/models/index.js'; +import type { DriveFilesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js'; -import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; import { RoleService } from '@/core/RoleService.js'; +import { DriveService } from '@/core/DriveService.js'; import { ApiError } from '../../../error.js'; export const meta = { @@ -77,16 +76,11 @@ export default class extends Endpoint { // eslint- @Inject(DI.driveFilesRepository) private driveFilesRepository: DriveFilesRepository, - @Inject(DI.driveFoldersRepository) - private driveFoldersRepository: DriveFoldersRepository, - - private driveFileEntityService: DriveFileEntityService, + private driveService: DriveService, private roleService: RoleService, - private globalEventService: GlobalEventService, ) { super(meta, paramDef, async (ps, me) => { const file = await this.driveFilesRepository.findOneBy({ id: ps.fileId }); - const alwaysMarkNsfw = (await this.roleService.getUserPolicies(me.id)).alwaysMarkNsfw; if (file == null) { throw new ApiError(meta.errors.noSuchFile); } @@ -95,49 +89,28 @@ export default class extends Endpoint { // eslint- throw new ApiError(meta.errors.accessDenied); } - if (ps.name) file.name = ps.name; - if (!this.driveFileEntityService.validateFileName(file.name)) { - throw new ApiError(meta.errors.invalidFileName); - } + let packedFile; - if (ps.comment !== undefined) file.comment = ps.comment; - - if (ps.isSensitive !== undefined && ps.isSensitive !== file.isSensitive && alwaysMarkNsfw && !ps.isSensitive) { - throw new ApiError(meta.errors.restrictedByRole); - } - - if (ps.isSensitive !== undefined) file.isSensitive = ps.isSensitive; - - if (ps.folderId !== undefined) { - if (ps.folderId === null) { - file.folderId = null; + try { + packedFile = await this.driveService.updateFile(file, { + folderId: ps.folderId, + name: ps.name, + isSensitive: ps.isSensitive, + comment: ps.comment, + }, me); + } catch (e) { + if (e instanceof DriveService.InvalidFileNameError) { + throw new ApiError(meta.errors.invalidFileName); + } else if (e instanceof DriveService.NoSuchFolderError) { + throw new ApiError(meta.errors.noSuchFolder); + } else if (e instanceof DriveService.CannotUnmarkSensitiveError) { + throw new ApiError(meta.errors.restrictedByRole); } else { - const folder = await this.driveFoldersRepository.findOneBy({ - id: ps.folderId, - userId: me.id, - }); - - if (folder == null) { - throw new ApiError(meta.errors.noSuchFolder); - } - - file.folderId = folder.id; + throw e; } } - await this.driveFilesRepository.update(file.id, { - name: file.name, - comment: file.comment, - folderId: file.folderId, - isSensitive: file.isSensitive, - }); - - const fileObj = await this.driveFileEntityService.pack(file, { self: true }); - - // Publish fileUpdated event - this.globalEventService.publishDriveStream(me.id, 'fileUpdated', fileObj); - - return fileObj; + return packedFile; }); } } diff --git a/packages/backend/src/server/api/endpoints/drive/folders.ts b/packages/backend/src/server/api/endpoints/drive/folders.ts index fd65df46f..3a0926659 100644 --- a/packages/backend/src/server/api/endpoints/drive/folders.ts +++ b/packages/backend/src/server/api/endpoints/drive/folders.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { DriveFoldersRepository } from '@/models/index.js'; +import type { DriveFoldersRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { DriveFolderEntityService } from '@/core/entities/DriveFolderEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/drive/folders/create.ts b/packages/backend/src/server/api/endpoints/drive/folders/create.ts index 6e5e71194..bc3a9bbe2 100644 --- a/packages/backend/src/server/api/endpoints/drive/folders/create.ts +++ b/packages/backend/src/server/api/endpoints/drive/folders/create.ts @@ -6,7 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import ms from 'ms'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { DriveFoldersRepository } from '@/models/index.js'; +import type { DriveFoldersRepository } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; import { DriveFolderEntityService } from '@/core/entities/DriveFolderEntityService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; diff --git a/packages/backend/src/server/api/endpoints/drive/folders/delete.ts b/packages/backend/src/server/api/endpoints/drive/folders/delete.ts index e6832b29b..46a00ca3d 100644 --- a/packages/backend/src/server/api/endpoints/drive/folders/delete.ts +++ b/packages/backend/src/server/api/endpoints/drive/folders/delete.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { DriveFoldersRepository, DriveFilesRepository } from '@/models/index.js'; +import type { DriveFoldersRepository, DriveFilesRepository } from '@/models/_.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/drive/folders/find.ts b/packages/backend/src/server/api/endpoints/drive/folders/find.ts index 3625e6882..2f5cdcc64 100644 --- a/packages/backend/src/server/api/endpoints/drive/folders/find.ts +++ b/packages/backend/src/server/api/endpoints/drive/folders/find.ts @@ -6,7 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { IsNull } from 'typeorm'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { DriveFoldersRepository } from '@/models/index.js'; +import type { DriveFoldersRepository } from '@/models/_.js'; import { DriveFolderEntityService } from '@/core/entities/DriveFolderEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/drive/folders/show.ts b/packages/backend/src/server/api/endpoints/drive/folders/show.ts index 5fffd2552..dd44fc46c 100644 --- a/packages/backend/src/server/api/endpoints/drive/folders/show.ts +++ b/packages/backend/src/server/api/endpoints/drive/folders/show.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { DriveFoldersRepository } from '@/models/index.js'; +import type { DriveFoldersRepository } from '@/models/_.js'; import { DriveFolderEntityService } from '@/core/entities/DriveFolderEntityService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/drive/folders/update.ts b/packages/backend/src/server/api/endpoints/drive/folders/update.ts index 4035e3c0d..f8683132b 100644 --- a/packages/backend/src/server/api/endpoints/drive/folders/update.ts +++ b/packages/backend/src/server/api/endpoints/drive/folders/update.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { DriveFoldersRepository } from '@/models/index.js'; +import type { DriveFoldersRepository } from '@/models/_.js'; import { DriveFolderEntityService } from '@/core/entities/DriveFolderEntityService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/drive/stream.ts b/packages/backend/src/server/api/endpoints/drive/stream.ts index 264163ecc..27e1656f8 100644 --- a/packages/backend/src/server/api/endpoints/drive/stream.ts +++ b/packages/backend/src/server/api/endpoints/drive/stream.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { DriveFilesRepository } from '@/models/index.js'; +import type { DriveFilesRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/emoji.ts b/packages/backend/src/server/api/endpoints/emoji.ts index 5509e6037..ead8c9979 100644 --- a/packages/backend/src/server/api/endpoints/emoji.ts +++ b/packages/backend/src/server/api/endpoints/emoji.ts @@ -5,7 +5,7 @@ import { IsNull } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { EmojisRepository } from '@/models/index.js'; +import type { EmojisRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/emojis.ts b/packages/backend/src/server/api/endpoints/emojis.ts index 9b014eb57..2adf0a21b 100644 --- a/packages/backend/src/server/api/endpoints/emojis.ts +++ b/packages/backend/src/server/api/endpoints/emojis.ts @@ -5,7 +5,7 @@ import { IsNull } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { EmojisRepository } from '@/models/index.js'; +import type { EmojisRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/federation/followers.ts b/packages/backend/src/server/api/endpoints/federation/followers.ts index 52ca48586..a92cf6a9d 100644 --- a/packages/backend/src/server/api/endpoints/federation/followers.ts +++ b/packages/backend/src/server/api/endpoints/federation/followers.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { FollowingsRepository } from '@/models/index.js'; +import type { FollowingsRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { FollowingEntityService } from '@/core/entities/FollowingEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/federation/following.ts b/packages/backend/src/server/api/endpoints/federation/following.ts index 28fa5ca84..d72ceeeea 100644 --- a/packages/backend/src/server/api/endpoints/federation/following.ts +++ b/packages/backend/src/server/api/endpoints/federation/following.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { FollowingsRepository } from '@/models/index.js'; +import type { FollowingsRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { FollowingEntityService } from '@/core/entities/FollowingEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/federation/instances.ts b/packages/backend/src/server/api/endpoints/federation/instances.ts index 35f1f5164..be73e5dbb 100644 --- a/packages/backend/src/server/api/endpoints/federation/instances.ts +++ b/packages/backend/src/server/api/endpoints/federation/instances.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { InstancesRepository } from '@/models/index.js'; +import type { InstancesRepository } from '@/models/_.js'; import { InstanceEntityService } from '@/core/entities/InstanceEntityService.js'; import { MetaService } from '@/core/MetaService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/federation/show-instance.ts b/packages/backend/src/server/api/endpoints/federation/show-instance.ts index fb55a2e44..71eec1123 100644 --- a/packages/backend/src/server/api/endpoints/federation/show-instance.ts +++ b/packages/backend/src/server/api/endpoints/federation/show-instance.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { InstancesRepository } from '@/models/index.js'; +import type { InstancesRepository } from '@/models/_.js'; import { InstanceEntityService } from '@/core/entities/InstanceEntityService.js'; import { UtilityService } from '@/core/UtilityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/federation/stats.ts b/packages/backend/src/server/api/endpoints/federation/stats.ts index ba7f2807b..e3ffea7b7 100644 --- a/packages/backend/src/server/api/endpoints/federation/stats.ts +++ b/packages/backend/src/server/api/endpoints/federation/stats.ts @@ -5,7 +5,7 @@ import { IsNull, MoreThan, Not } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { FollowingsRepository, InstancesRepository } from '@/models/index.js'; +import type { FollowingsRepository, InstancesRepository } from '@/models/_.js'; import { awaitAll } from '@/misc/prelude/await-all.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { InstanceEntityService } from '@/core/entities/InstanceEntityService.js'; diff --git a/packages/backend/src/server/api/endpoints/federation/users.ts b/packages/backend/src/server/api/endpoints/federation/users.ts index 5b414e12f..d97171865 100644 --- a/packages/backend/src/server/api/endpoints/federation/users.ts +++ b/packages/backend/src/server/api/endpoints/federation/users.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { UsersRepository } from '@/models/index.js'; +import type { UsersRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/flash/create.ts b/packages/backend/src/server/api/endpoints/flash/create.ts index 8727be201..b46660d21 100644 --- a/packages/backend/src/server/api/endpoints/flash/create.ts +++ b/packages/backend/src/server/api/endpoints/flash/create.ts @@ -5,7 +5,7 @@ import ms from 'ms'; import { Inject, Injectable } from '@nestjs/common'; -import type { FlashsRepository } from '@/models/index.js'; +import type { FlashsRepository } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/flash/delete.ts b/packages/backend/src/server/api/endpoints/flash/delete.ts index 86cdd7281..e5448c816 100644 --- a/packages/backend/src/server/api/endpoints/flash/delete.ts +++ b/packages/backend/src/server/api/endpoints/flash/delete.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { FlashsRepository } from '@/models/index.js'; +import type { FlashsRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/flash/featured.ts b/packages/backend/src/server/api/endpoints/flash/featured.ts index 3be7ddebb..1fa5612ac 100644 --- a/packages/backend/src/server/api/endpoints/flash/featured.ts +++ b/packages/backend/src/server/api/endpoints/flash/featured.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { FlashsRepository } from '@/models/index.js'; +import type { FlashsRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { FlashEntityService } from '@/core/entities/FlashEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/flash/like.ts b/packages/backend/src/server/api/endpoints/flash/like.ts index 16818c53a..a90e5f653 100644 --- a/packages/backend/src/server/api/endpoints/flash/like.ts +++ b/packages/backend/src/server/api/endpoints/flash/like.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { FlashsRepository, FlashLikesRepository } from '@/models/index.js'; +import type { FlashsRepository, FlashLikesRepository } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/flash/my-likes.ts b/packages/backend/src/server/api/endpoints/flash/my-likes.ts index 48897ea74..e328bdbee 100644 --- a/packages/backend/src/server/api/endpoints/flash/my-likes.ts +++ b/packages/backend/src/server/api/endpoints/flash/my-likes.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { FlashLikesRepository } from '@/models/index.js'; +import type { FlashLikesRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { FlashLikeEntityService } from '@/core/entities/FlashLikeEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/flash/my.ts b/packages/backend/src/server/api/endpoints/flash/my.ts index 1d74bfe63..442d8dcd7 100644 --- a/packages/backend/src/server/api/endpoints/flash/my.ts +++ b/packages/backend/src/server/api/endpoints/flash/my.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { FlashsRepository } from '@/models/index.js'; +import type { FlashsRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { FlashEntityService } from '@/core/entities/FlashEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/flash/show.ts b/packages/backend/src/server/api/endpoints/flash/show.ts index d65520330..c41a27c92 100644 --- a/packages/backend/src/server/api/endpoints/flash/show.ts +++ b/packages/backend/src/server/api/endpoints/flash/show.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { FlashsRepository } from '@/models/index.js'; +import type { FlashsRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { FlashEntityService } from '@/core/entities/FlashEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/flash/unlike.ts b/packages/backend/src/server/api/endpoints/flash/unlike.ts index 6e723c5a1..d5c20a116 100644 --- a/packages/backend/src/server/api/endpoints/flash/unlike.ts +++ b/packages/backend/src/server/api/endpoints/flash/unlike.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { FlashsRepository, FlashLikesRepository } from '@/models/index.js'; +import type { FlashsRepository, FlashLikesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/flash/update.ts b/packages/backend/src/server/api/endpoints/flash/update.ts index 9da29b50e..8b5e1f99e 100644 --- a/packages/backend/src/server/api/endpoints/flash/update.ts +++ b/packages/backend/src/server/api/endpoints/flash/update.ts @@ -5,7 +5,7 @@ import ms from 'ms'; import { Inject, Injectable } from '@nestjs/common'; -import type { FlashsRepository } from '@/models/index.js'; +import type { FlashsRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../error.js'; @@ -75,6 +75,7 @@ export default class extends Endpoint { // eslint- summary: ps.summary, script: ps.script, permissions: ps.permissions, + visibility: ps.visibility, }); }); } diff --git a/packages/backend/src/server/api/endpoints/following/create.ts b/packages/backend/src/server/api/endpoints/following/create.ts index 3f90c29b2..e0e7fed87 100644 --- a/packages/backend/src/server/api/endpoints/following/create.ts +++ b/packages/backend/src/server/api/endpoints/following/create.ts @@ -6,7 +6,7 @@ import ms from 'ms'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { FollowingsRepository } from '@/models/index.js'; +import type { FollowingsRepository } from '@/models/_.js'; import { IdentifiableError } from '@/misc/identifiable-error.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { UserFollowingService } from '@/core/UserFollowingService.js'; @@ -19,7 +19,7 @@ export const meta = { limit: { duration: ms('1hour'), - max: 50, + max: 100, }, requireCredential: true, diff --git a/packages/backend/src/server/api/endpoints/following/delete.ts b/packages/backend/src/server/api/endpoints/following/delete.ts index 87a21a95e..f44692ba6 100644 --- a/packages/backend/src/server/api/endpoints/following/delete.ts +++ b/packages/backend/src/server/api/endpoints/following/delete.ts @@ -6,7 +6,7 @@ import ms from 'ms'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { FollowingsRepository } from '@/models/index.js'; +import type { FollowingsRepository } from '@/models/_.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { UserFollowingService } from '@/core/UserFollowingService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/following/invalidate.ts b/packages/backend/src/server/api/endpoints/following/invalidate.ts index e786ccd09..53ef925b2 100644 --- a/packages/backend/src/server/api/endpoints/following/invalidate.ts +++ b/packages/backend/src/server/api/endpoints/following/invalidate.ts @@ -6,7 +6,7 @@ import ms from 'ms'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { FollowingsRepository } from '@/models/index.js'; +import type { FollowingsRepository } from '@/models/_.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { UserFollowingService } from '@/core/UserFollowingService.js'; import { DI } from '@/di-symbols.js'; @@ -29,7 +29,7 @@ export const meta = { noSuchUser: { message: 'No such user.', code: 'NO_SUCH_USER', - id: '5b12c78d-2b28-4dca-99d2-f56139b42ff8', + id: 'b77e6ae6-a3e5-40da-9cc8-c240115479cc', }, followerIsYourself: { @@ -41,7 +41,7 @@ export const meta = { notFollowing: { message: 'The other use is not following you.', code: 'NOT_FOLLOWING', - id: '5dbf82f5-c92b-40b1-87d1-6c8c0741fd09', + id: '918faac3-074f-41ae-9c43-ed5d2946770d', }, }, diff --git a/packages/backend/src/server/api/endpoints/following/requests/list.ts b/packages/backend/src/server/api/endpoints/following/requests/list.ts index 6214bce7a..c4faa88f6 100644 --- a/packages/backend/src/server/api/endpoints/following/requests/list.ts +++ b/packages/backend/src/server/api/endpoints/following/requests/list.ts @@ -6,7 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; -import type { FollowRequestsRepository } from '@/models/index.js'; +import type { FollowRequestsRepository } from '@/models/_.js'; import { FollowRequestEntityService } from '@/core/entities/FollowRequestEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/following/update.ts b/packages/backend/src/server/api/endpoints/following/update.ts new file mode 100644 index 000000000..25f393e51 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/following/update.ts @@ -0,0 +1,107 @@ +/* + * SPDX-FileCopyrightText: syuilo and other misskey contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import ms from 'ms'; +import { Inject, Injectable } from '@nestjs/common'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import type { FollowingsRepository } from '@/models/_.js'; +import { UserEntityService } from '@/core/entities/UserEntityService.js'; +import { UserFollowingService } from '@/core/UserFollowingService.js'; +import { DI } from '@/di-symbols.js'; +import { GetterService } from '@/server/api/GetterService.js'; +import { ApiError } from '../../error.js'; + +export const meta = { + tags: ['following', 'users'], + + limit: { + duration: ms('1hour'), + max: 100, + }, + + requireCredential: true, + + kind: 'write:following', + + errors: { + noSuchUser: { + message: 'No such user.', + code: 'NO_SUCH_USER', + id: '14318698-f67e-492a-99da-5353a5ac52be', + }, + + followeeIsYourself: { + message: 'Followee is yourself.', + code: 'FOLLOWEE_IS_YOURSELF', + id: '4c4cbaf9-962a-463b-8418-a5e365dbf2eb', + }, + + notFollowing: { + message: 'You are not following that user.', + code: 'NOT_FOLLOWING', + id: 'b8dc75cf-1cb5-46c9-b14b-5f1ffbd782c9', + }, + }, + + res: { + type: 'object', + optional: false, nullable: false, + ref: 'UserLite', + }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, + notify: { type: 'string', enum: ['normal', 'none'] }, + }, + required: ['userId', 'notify'], +} as const; + +@Injectable() +export default class extends Endpoint { // eslint-disable-line import/no-default-export + constructor( + @Inject(DI.followingsRepository) + private followingsRepository: FollowingsRepository, + + private userEntityService: UserEntityService, + private getterService: GetterService, + private userFollowingService: UserFollowingService, + ) { + super(meta, paramDef, async (ps, me) => { + const follower = me; + + // Check if the follower is yourself + if (me.id === ps.userId) { + throw new ApiError(meta.errors.followeeIsYourself); + } + + // Get followee + const followee = await this.getterService.getUser(ps.userId).catch(err => { + if (err.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); + throw err; + }); + + // Check not following + const exist = await this.followingsRepository.findOneBy({ + followerId: follower.id, + followeeId: followee.id, + }); + + if (exist == null) { + throw new ApiError(meta.errors.notFollowing); + } + + await this.followingsRepository.update({ + id: exist.id, + }, { + notify: ps.notify === 'none' ? null : ps.notify, + }); + + return await this.userEntityService.pack(follower.id, me); + }); + } +} diff --git a/packages/backend/src/server/api/endpoints/gallery/featured.ts b/packages/backend/src/server/api/endpoints/gallery/featured.ts index 512be6111..cbab3a83a 100644 --- a/packages/backend/src/server/api/endpoints/gallery/featured.ts +++ b/packages/backend/src/server/api/endpoints/gallery/featured.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { GalleryPostsRepository } from '@/models/index.js'; +import type { GalleryPostsRepository } from '@/models/_.js'; import { GalleryPostEntityService } from '@/core/entities/GalleryPostEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/gallery/popular.ts b/packages/backend/src/server/api/endpoints/gallery/popular.ts index e1f3b8a14..c5d06f67d 100644 --- a/packages/backend/src/server/api/endpoints/gallery/popular.ts +++ b/packages/backend/src/server/api/endpoints/gallery/popular.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { GalleryPostsRepository } from '@/models/index.js'; +import type { GalleryPostsRepository } from '@/models/_.js'; import { GalleryPostEntityService } from '@/core/entities/GalleryPostEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/gallery/posts.ts b/packages/backend/src/server/api/endpoints/gallery/posts.ts index 729904117..3ca5f4989 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { GalleryPostsRepository } from '@/models/index.js'; +import type { GalleryPostsRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { GalleryPostEntityService } from '@/core/entities/GalleryPostEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/create.ts b/packages/backend/src/server/api/endpoints/gallery/posts/create.ts index 25def8451..94701712d 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/create.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/create.ts @@ -6,9 +6,9 @@ import ms from 'ms'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { DriveFilesRepository, GalleryPostsRepository } from '@/models/index.js'; -import { MiGalleryPost } from '@/models/entities/GalleryPost.js'; -import type { MiDriveFile } from '@/models/entities/DriveFile.js'; +import type { DriveFilesRepository, GalleryPostsRepository } from '@/models/_.js'; +import { MiGalleryPost } from '@/models/GalleryPost.js'; +import type { MiDriveFile } from '@/models/DriveFile.js'; import { IdService } from '@/core/IdService.js'; import { GalleryPostEntityService } from '@/core/entities/GalleryPostEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/delete.ts b/packages/backend/src/server/api/endpoints/gallery/posts/delete.ts index 43713dd1f..deef2912b 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/delete.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/delete.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { GalleryPostsRepository } from '@/models/index.js'; +import type { GalleryPostsRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/like.ts b/packages/backend/src/server/api/endpoints/gallery/posts/like.ts index 172f59a65..c55705406 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/like.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/like.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { GalleryLikesRepository, GalleryPostsRepository } from '@/models/index.js'; +import type { GalleryLikesRepository, GalleryPostsRepository } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/show.ts b/packages/backend/src/server/api/endpoints/gallery/posts/show.ts index 04ceb07f3..b3eda1be5 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/show.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/show.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { GalleryPostsRepository } from '@/models/index.js'; +import type { GalleryPostsRepository } from '@/models/_.js'; import { GalleryPostEntityService } from '@/core/entities/GalleryPostEntityService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/unlike.ts b/packages/backend/src/server/api/endpoints/gallery/posts/unlike.ts index 6929e5e69..832b62282 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/unlike.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/unlike.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { GalleryPostsRepository, GalleryLikesRepository } from '@/models/index.js'; +import type { GalleryPostsRepository, GalleryLikesRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/update.ts b/packages/backend/src/server/api/endpoints/gallery/posts/update.ts index bc7e8b0a6..632214a0c 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/update.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/update.ts @@ -6,8 +6,8 @@ import ms from 'ms'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { DriveFilesRepository, GalleryPostsRepository } from '@/models/index.js'; -import type { MiDriveFile } from '@/models/entities/DriveFile.js'; +import type { DriveFilesRepository, GalleryPostsRepository } from '@/models/_.js'; +import type { MiDriveFile } from '@/models/DriveFile.js'; import { GalleryPostEntityService } from '@/core/entities/GalleryPostEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/get-online-users-count.ts b/packages/backend/src/server/api/endpoints/get-online-users-count.ts index 4e6a68d50..8a61168f2 100644 --- a/packages/backend/src/server/api/endpoints/get-online-users-count.ts +++ b/packages/backend/src/server/api/endpoints/get-online-users-count.ts @@ -6,7 +6,7 @@ import { MoreThan } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; import { USER_ONLINE_THRESHOLD } from '@/const.js'; -import type { UsersRepository } from '@/models/index.js'; +import type { UsersRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/hashtags/list.ts b/packages/backend/src/server/api/endpoints/hashtags/list.ts index f4f230a42..21d863107 100644 --- a/packages/backend/src/server/api/endpoints/hashtags/list.ts +++ b/packages/backend/src/server/api/endpoints/hashtags/list.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { HashtagsRepository } from '@/models/index.js'; +import type { HashtagsRepository } from '@/models/_.js'; import { HashtagEntityService } from '@/core/entities/HashtagEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/hashtags/search.ts b/packages/backend/src/server/api/endpoints/hashtags/search.ts index a4ec9a51d..acfef16b1 100644 --- a/packages/backend/src/server/api/endpoints/hashtags/search.ts +++ b/packages/backend/src/server/api/endpoints/hashtags/search.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { HashtagsRepository } from '@/models/index.js'; +import type { HashtagsRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { sqlLikeEscape } from '@/misc/sql-like-escape.js'; diff --git a/packages/backend/src/server/api/endpoints/hashtags/show.ts b/packages/backend/src/server/api/endpoints/hashtags/show.ts index 88ce4c5fe..3ba16fdc8 100644 --- a/packages/backend/src/server/api/endpoints/hashtags/show.ts +++ b/packages/backend/src/server/api/endpoints/hashtags/show.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { HashtagsRepository } from '@/models/index.js'; +import type { HashtagsRepository } from '@/models/_.js'; import { normalizeForSearch } from '@/misc/normalize-for-search.js'; import { HashtagEntityService } from '@/core/entities/HashtagEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/hashtags/trend.ts b/packages/backend/src/server/api/endpoints/hashtags/trend.ts index 4137562de..75d4fe381 100644 --- a/packages/backend/src/server/api/endpoints/hashtags/trend.ts +++ b/packages/backend/src/server/api/endpoints/hashtags/trend.ts @@ -6,8 +6,8 @@ import { Brackets } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { NotesRepository } from '@/models/index.js'; -import type { MiNote } from '@/models/entities/Note.js'; +import type { NotesRepository } from '@/models/_.js'; +import type { MiNote } from '@/models/Note.js'; import { safeForSql } from '@/misc/safe-for-sql.js'; import { normalizeForSearch } from '@/misc/normalize-for-search.js'; import { MetaService } from '@/core/MetaService.js'; diff --git a/packages/backend/src/server/api/endpoints/hashtags/users.ts b/packages/backend/src/server/api/endpoints/hashtags/users.ts index 9918ddab0..1cef76d3d 100644 --- a/packages/backend/src/server/api/endpoints/hashtags/users.ts +++ b/packages/backend/src/server/api/endpoints/hashtags/users.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { UsersRepository } from '@/models/index.js'; +import type { UsersRepository } from '@/models/_.js'; import { normalizeForSearch } from '@/misc/normalize-for-search.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/i.ts b/packages/backend/src/server/api/endpoints/i.ts index 56c770761..c0530bf39 100644 --- a/packages/backend/src/server/api/endpoints/i.ts +++ b/packages/backend/src/server/api/endpoints/i.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { UserProfilesRepository } from '@/models/index.js'; +import type { UserProfilesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/i/2fa/done.ts b/packages/backend/src/server/api/endpoints/i/2fa/done.ts index 2d1457b9b..9f8e2894b 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/done.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/done.ts @@ -7,7 +7,7 @@ import * as OTPAuth from 'otpauth'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; -import type { UserProfilesRepository } from '@/models/index.js'; +import type { UserProfilesRepository } from '@/models/_.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; @@ -47,7 +47,7 @@ export default class extends Endpoint { // eslint- secret: OTPAuth.Secret.fromBase32(profile.twoFactorTempSecret), digits: 6, token, - window: 1, + window: 5, }); if (delta === null) { diff --git a/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts b/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts index 87a15da0c..6d530aba3 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts @@ -9,9 +9,10 @@ import { Endpoint } from '@/server/api/endpoint-base.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { DI } from '@/di-symbols.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; -import type { UserProfilesRepository, UserSecurityKeysRepository } from '@/models/index.js'; +import type { UserProfilesRepository, UserSecurityKeysRepository } from '@/models/_.js'; import { WebAuthnService } from '@/core/WebAuthnService.js'; import { ApiError } from '@/server/api/error.js'; +import { UserAuthService } from '@/core/UserAuthService.js'; export const meta = { requireCredential: true, @@ -37,6 +38,7 @@ export const paramDef = { type: 'object', properties: { password: { type: 'string' }, + token: { type: 'string', nullable: true }, name: { type: 'string', minLength: 1, maxLength: 30 }, credential: { type: 'object' }, }, @@ -54,16 +56,28 @@ export default class extends Endpoint { private userSecurityKeysRepository: UserSecurityKeysRepository, private webAuthnService: WebAuthnService, + private userAuthService: UserAuthService, private userEntityService: UserEntityService, private globalEventService: GlobalEventService, ) { super(meta, paramDef, async (ps, me) => { + const token = ps.token; const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id }); - // Compare password - const same = await bcrypt.compare(ps.password, profile.password ?? ''); + if (profile.twoFactorEnabled) { + if (token == null) { + throw new Error('authentication failed'); + } - if (!same) { + try { + await this.userAuthService.twoFactorAuthenticate(profile, token); + } catch (e) { + throw new Error('authentication failed'); + } + } + + const passwordMatched = await bcrypt.compare(ps.password, profile.password ?? ''); + if (!passwordMatched) { throw new ApiError(meta.errors.incorrectPassword); } diff --git a/packages/backend/src/server/api/endpoints/i/2fa/password-less.ts b/packages/backend/src/server/api/endpoints/i/2fa/password-less.ts index 41277de59..2ed701014 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/password-less.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/password-less.ts @@ -6,7 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; -import type { UserProfilesRepository, UserSecurityKeysRepository } from '@/models/index.js'; +import type { UserProfilesRepository, UserSecurityKeysRepository } from '@/models/_.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/i/2fa/register-key.ts b/packages/backend/src/server/api/endpoints/i/2fa/register-key.ts index cae4f5ab5..c39005f2d 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/register-key.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/register-key.ts @@ -6,10 +6,11 @@ import bcrypt from 'bcryptjs'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { UserProfilesRepository } from '@/models/index.js'; +import type { UserProfilesRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { WebAuthnService } from '@/core/WebAuthnService.js'; import { ApiError } from '@/server/api/error.js'; +import { UserAuthService } from '@/core/UserAuthService.js'; export const meta = { requireCredential: true, @@ -41,6 +42,7 @@ export const paramDef = { type: 'object', properties: { password: { type: 'string' }, + token: { type: 'string', nullable: true }, }, required: ['password'], } as const; @@ -53,8 +55,10 @@ export default class extends Endpoint { private userProfilesRepository: UserProfilesRepository, private webAuthnService: WebAuthnService, + private userAuthService: UserAuthService, ) { super(meta, paramDef, async (ps, me) => { + const token = ps.token; const profile = await this.userProfilesRepository.findOne({ where: { userId: me.id, @@ -66,10 +70,20 @@ export default class extends Endpoint { throw new ApiError(meta.errors.userNotFound); } - // Compare password - const same = await bcrypt.compare(ps.password, profile.password ?? ''); + if (profile.twoFactorEnabled) { + if (token == null) { + throw new Error('authentication failed'); + } - if (!same) { + try { + await this.userAuthService.twoFactorAuthenticate(profile, token); + } catch (e) { + throw new Error('authentication failed'); + } + } + + const passwordMatched = await bcrypt.compare(ps.password, profile.password ?? ''); + if (!passwordMatched) { throw new ApiError(meta.errors.incorrectPassword); } diff --git a/packages/backend/src/server/api/endpoints/i/2fa/register.ts b/packages/backend/src/server/api/endpoints/i/2fa/register.ts index c60343d25..b358c812e 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/register.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/register.ts @@ -7,11 +7,12 @@ import bcrypt from 'bcryptjs'; import * as OTPAuth from 'otpauth'; import * as QRCode from 'qrcode'; import { Inject, Injectable } from '@nestjs/common'; -import type { UserProfilesRepository } from '@/models/index.js'; +import type { UserProfilesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; import { ApiError } from '@/server/api/error.js'; +import { UserAuthService } from '@/core/UserAuthService.js'; export const meta = { requireCredential: true, @@ -31,6 +32,7 @@ export const paramDef = { type: 'object', properties: { password: { type: 'string' }, + token: { type: 'string', nullable: true }, }, required: ['password'], } as const; @@ -43,14 +45,27 @@ export default class extends Endpoint { // eslint- @Inject(DI.userProfilesRepository) private userProfilesRepository: UserProfilesRepository, + + private userAuthService: UserAuthService, ) { super(meta, paramDef, async (ps, me) => { + const token = ps.token; const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id }); - // Compare password - const same = await bcrypt.compare(ps.password, profile.password ?? ''); + if (profile.twoFactorEnabled) { + if (token == null) { + throw new Error('authentication failed'); + } - if (!same) { + try { + await this.userAuthService.twoFactorAuthenticate(profile, token); + } catch (e) { + throw new Error('authentication failed'); + } + } + + const passwordMatched = await bcrypt.compare(ps.password, profile.password ?? ''); + if (!passwordMatched) { throw new ApiError(meta.errors.incorrectPassword); } diff --git a/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts b/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts index 90d23d11f..da8ac9855 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts @@ -6,11 +6,12 @@ import bcrypt from 'bcryptjs'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { UserProfilesRepository, UserSecurityKeysRepository } from '@/models/index.js'; +import type { UserProfilesRepository, UserSecurityKeysRepository } from '@/models/_.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '@/server/api/error.js'; +import { UserAuthService } from '@/core/UserAuthService.js'; export const meta = { requireCredential: true, @@ -30,6 +31,7 @@ export const paramDef = { type: 'object', properties: { password: { type: 'string' }, + token: { type: 'string', nullable: true }, credentialId: { type: 'string' }, }, required: ['password', 'credentialId'], @@ -45,15 +47,27 @@ export default class extends Endpoint { // eslint- private userProfilesRepository: UserProfilesRepository, private userEntityService: UserEntityService, + private userAuthService: UserAuthService, private globalEventService: GlobalEventService, ) { super(meta, paramDef, async (ps, me) => { + const token = ps.token; const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id }); - // Compare password - const same = await bcrypt.compare(ps.password, profile.password ?? ''); + if (profile.twoFactorEnabled) { + if (token == null) { + throw new Error('authentication failed'); + } - if (!same) { + try { + await this.userAuthService.twoFactorAuthenticate(profile, token); + } catch (e) { + throw new Error('authentication failed'); + } + } + + const passwordMatched = await bcrypt.compare(ps.password, profile.password ?? ''); + if (!passwordMatched) { throw new ApiError(meta.errors.incorrectPassword); } diff --git a/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts b/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts index 33910f773..338f12c5c 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts @@ -7,10 +7,11 @@ import bcrypt from 'bcryptjs'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; -import type { UserProfilesRepository } from '@/models/index.js'; +import type { UserProfilesRepository } from '@/models/_.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '@/server/api/error.js'; +import { UserAuthService } from '@/core/UserAuthService.js'; export const meta = { requireCredential: true, @@ -30,6 +31,7 @@ export const paramDef = { type: 'object', properties: { password: { type: 'string' }, + token: { type: 'string', nullable: true }, }, required: ['password'], } as const; @@ -41,15 +43,27 @@ export default class extends Endpoint { // eslint- private userProfilesRepository: UserProfilesRepository, private userEntityService: UserEntityService, + private userAuthService: UserAuthService, private globalEventService: GlobalEventService, ) { super(meta, paramDef, async (ps, me) => { + const token = ps.token; const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id }); - // Compare password - const same = await bcrypt.compare(ps.password, profile.password ?? ''); + if (profile.twoFactorEnabled) { + if (token == null) { + throw new Error('authentication failed'); + } - if (!same) { + try { + await this.userAuthService.twoFactorAuthenticate(profile, token); + } catch (e) { + throw new Error('authentication failed'); + } + } + + const passwordMatched = await bcrypt.compare(ps.password, profile.password ?? ''); + if (!passwordMatched) { throw new ApiError(meta.errors.incorrectPassword); } diff --git a/packages/backend/src/server/api/endpoints/i/2fa/update-key.ts b/packages/backend/src/server/api/endpoints/i/2fa/update-key.ts index 90640fd57..1a140c1d0 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/update-key.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/update-key.ts @@ -6,7 +6,7 @@ import bcrypt from 'bcryptjs'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { UserSecurityKeysRepository } from '@/models/index.js'; +import type { UserSecurityKeysRepository } from '@/models/_.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/i/apps.ts b/packages/backend/src/server/api/endpoints/i/apps.ts index 1318535a0..daa3e536a 100644 --- a/packages/backend/src/server/api/endpoints/i/apps.ts +++ b/packages/backend/src/server/api/endpoints/i/apps.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { AccessTokensRepository } from '@/models/index.js'; +import type { AccessTokensRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; export const meta = { diff --git a/packages/backend/src/server/api/endpoints/i/authorized-apps.ts b/packages/backend/src/server/api/endpoints/i/authorized-apps.ts index 91f75d2a2..32061c2aa 100644 --- a/packages/backend/src/server/api/endpoints/i/authorized-apps.ts +++ b/packages/backend/src/server/api/endpoints/i/authorized-apps.ts @@ -6,7 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { IsNull, Not } from 'typeorm'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { AccessTokensRepository } from '@/models/index.js'; +import type { AccessTokensRepository } from '@/models/_.js'; import { AppEntityService } from '@/core/entities/AppEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/i/change-password.ts b/packages/backend/src/server/api/endpoints/i/change-password.ts index 93168b003..a3c37ffdb 100644 --- a/packages/backend/src/server/api/endpoints/i/change-password.ts +++ b/packages/backend/src/server/api/endpoints/i/change-password.ts @@ -6,8 +6,9 @@ import bcrypt from 'bcryptjs'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { UserProfilesRepository } from '@/models/index.js'; +import type { UserProfilesRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; +import { UserAuthService } from '@/core/UserAuthService.js'; export const meta = { requireCredential: true, @@ -20,6 +21,7 @@ export const paramDef = { properties: { currentPassword: { type: 'string' }, newPassword: { type: 'string', minLength: 1 }, + token: { type: 'string', nullable: true }, }, required: ['currentPassword', 'newPassword'], } as const; @@ -29,14 +31,28 @@ export default class extends Endpoint { // eslint- constructor( @Inject(DI.userProfilesRepository) private userProfilesRepository: UserProfilesRepository, + + private userAuthService: UserAuthService, ) { super(meta, paramDef, async (ps, me) => { + const token = ps.token; const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id }); - // Compare password - const same = await bcrypt.compare(ps.currentPassword, profile.password!); + if (profile.twoFactorEnabled) { + if (token == null) { + throw new Error('authentication failed'); + } - if (!same) { + try { + await this.userAuthService.twoFactorAuthenticate(profile, token); + } catch (e) { + throw new Error('authentication failed'); + } + } + + const passwordMatched = await bcrypt.compare(ps.currentPassword, profile.password!); + + if (!passwordMatched) { throw new Error('incorrect password'); } diff --git a/packages/backend/src/server/api/endpoints/i/delete-account.ts b/packages/backend/src/server/api/endpoints/i/delete-account.ts index 7609353ac..fbac845fd 100644 --- a/packages/backend/src/server/api/endpoints/i/delete-account.ts +++ b/packages/backend/src/server/api/endpoints/i/delete-account.ts @@ -5,10 +5,11 @@ import bcrypt from 'bcryptjs'; import { Inject, Injectable } from '@nestjs/common'; -import type { UsersRepository, UserProfilesRepository } from '@/models/index.js'; +import type { UsersRepository, UserProfilesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DeleteAccountService } from '@/core/DeleteAccountService.js'; import { DI } from '@/di-symbols.js'; +import { UserAuthService } from '@/core/UserAuthService.js'; export const meta = { requireCredential: true, @@ -20,6 +21,7 @@ export const paramDef = { type: 'object', properties: { password: { type: 'string' }, + token: { type: 'string', nullable: true }, }, required: ['password'], } as const; @@ -33,19 +35,32 @@ export default class extends Endpoint { // eslint- @Inject(DI.userProfilesRepository) private userProfilesRepository: UserProfilesRepository, + private userAuthService: UserAuthService, private deleteAccountService: DeleteAccountService, ) { super(meta, paramDef, async (ps, me) => { + const token = ps.token; const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id }); + + if (profile.twoFactorEnabled) { + if (token == null) { + throw new Error('authentication failed'); + } + + try { + await this.userAuthService.twoFactorAuthenticate(profile, token); + } catch (e) { + throw new Error('authentication failed'); + } + } + const userDetailed = await this.usersRepository.findOneByOrFail({ id: me.id }); if (userDetailed.isDeleted) { return; } - // Compare password - const same = await bcrypt.compare(ps.password, profile.password!); - - if (!same) { + const passwordMatched = await bcrypt.compare(ps.password, profile.password!); + if (!passwordMatched) { throw new Error('incorrect password'); } diff --git a/packages/backend/src/server/api/endpoints/i/favorites.ts b/packages/backend/src/server/api/endpoints/i/favorites.ts index dd59683f0..d6f13c535 100644 --- a/packages/backend/src/server/api/endpoints/i/favorites.ts +++ b/packages/backend/src/server/api/endpoints/i/favorites.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { NoteFavoritesRepository } from '@/models/index.js'; +import type { NoteFavoritesRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { NoteFavoriteEntityService } from '@/core/entities/NoteFavoriteEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/i/gallery/likes.ts b/packages/backend/src/server/api/endpoints/i/gallery/likes.ts index c01aeb2d1..7e37adc4a 100644 --- a/packages/backend/src/server/api/endpoints/i/gallery/likes.ts +++ b/packages/backend/src/server/api/endpoints/i/gallery/likes.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { GalleryLikesRepository } from '@/models/index.js'; +import type { GalleryLikesRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { GalleryLikeEntityService } from '@/core/entities/GalleryLikeEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/i/gallery/posts.ts b/packages/backend/src/server/api/endpoints/i/gallery/posts.ts index 0309d93a7..148d38aa5 100644 --- a/packages/backend/src/server/api/endpoints/i/gallery/posts.ts +++ b/packages/backend/src/server/api/endpoints/i/gallery/posts.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { GalleryPostsRepository } from '@/models/index.js'; +import type { GalleryPostsRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { GalleryPostEntityService } from '@/core/entities/GalleryPostEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/i/get-word-muted-notes-count.ts b/packages/backend/src/server/api/endpoints/i/get-word-muted-notes-count.ts index b889cfda6..d62bfbb3e 100644 --- a/packages/backend/src/server/api/endpoints/i/get-word-muted-notes-count.ts +++ b/packages/backend/src/server/api/endpoints/i/get-word-muted-notes-count.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { MutedNotesRepository } from '@/models/index.js'; +import type { MutedNotesRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; export const meta = { diff --git a/packages/backend/src/server/api/endpoints/i/import-antennas.ts b/packages/backend/src/server/api/endpoints/i/import-antennas.ts index 8feb0007a..71db8710a 100644 --- a/packages/backend/src/server/api/endpoints/i/import-antennas.ts +++ b/packages/backend/src/server/api/endpoints/i/import-antennas.ts @@ -7,7 +7,7 @@ import { Inject, Injectable } from '@nestjs/common'; import ms from 'ms'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueueService } from '@/core/QueueService.js'; -import type { AntennasRepository, DriveFilesRepository, UsersRepository, MiAntenna as _Antenna } from '@/models/index.js'; +import type { AntennasRepository, DriveFilesRepository, UsersRepository, MiAntenna as _Antenna } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { RoleService } from '@/core/RoleService.js'; import { DownloadService } from '@/core/DownloadService.js'; diff --git a/packages/backend/src/server/api/endpoints/i/import-blocking.ts b/packages/backend/src/server/api/endpoints/i/import-blocking.ts index 27bbc9cd3..965ad3054 100644 --- a/packages/backend/src/server/api/endpoints/i/import-blocking.ts +++ b/packages/backend/src/server/api/endpoints/i/import-blocking.ts @@ -8,7 +8,7 @@ import ms from 'ms'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueueService } from '@/core/QueueService.js'; import { AccountMoveService } from '@/core/AccountMoveService.js'; -import type { DriveFilesRepository } from '@/models/index.js'; +import type { DriveFilesRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/i/import-following.ts b/packages/backend/src/server/api/endpoints/i/import-following.ts index 30cf116fb..38c928304 100644 --- a/packages/backend/src/server/api/endpoints/i/import-following.ts +++ b/packages/backend/src/server/api/endpoints/i/import-following.ts @@ -8,7 +8,7 @@ import ms from 'ms'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueueService } from '@/core/QueueService.js'; import { AccountMoveService } from '@/core/AccountMoveService.js'; -import type { DriveFilesRepository } from '@/models/index.js'; +import type { DriveFilesRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/i/import-muting.ts b/packages/backend/src/server/api/endpoints/i/import-muting.ts index 227d32ece..926cf13d7 100644 --- a/packages/backend/src/server/api/endpoints/i/import-muting.ts +++ b/packages/backend/src/server/api/endpoints/i/import-muting.ts @@ -8,7 +8,7 @@ import ms from 'ms'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueueService } from '@/core/QueueService.js'; import { AccountMoveService } from '@/core/AccountMoveService.js'; -import type { DriveFilesRepository } from '@/models/index.js'; +import type { DriveFilesRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/i/import-user-lists.ts b/packages/backend/src/server/api/endpoints/i/import-user-lists.ts index 288b5eee7..216799643 100644 --- a/packages/backend/src/server/api/endpoints/i/import-user-lists.ts +++ b/packages/backend/src/server/api/endpoints/i/import-user-lists.ts @@ -8,7 +8,7 @@ import ms from 'ms'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueueService } from '@/core/QueueService.js'; import { AccountMoveService } from '@/core/AccountMoveService.js'; -import type { DriveFilesRepository } from '@/models/index.js'; +import type { DriveFilesRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/i/move.ts b/packages/backend/src/server/api/endpoints/i/move.ts index eb67e171f..86b726e05 100644 --- a/packages/backend/src/server/api/endpoints/i/move.ts +++ b/packages/backend/src/server/api/endpoints/i/move.ts @@ -9,7 +9,7 @@ import ms from 'ms'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { ApiError } from '@/server/api/error.js'; -import { MiLocalUser, MiRemoteUser } from '@/models/entities/User.js'; +import { MiLocalUser, MiRemoteUser } from '@/models/User.js'; import { AccountMoveService } from '@/core/AccountMoveService.js'; import { RemoteUserResolveService } from '@/core/RemoteUserResolveService.js'; diff --git a/packages/backend/src/server/api/endpoints/i/notifications.ts b/packages/backend/src/server/api/endpoints/i/notifications.ts index efc37a626..91dd72e80 100644 --- a/packages/backend/src/server/api/endpoints/i/notifications.ts +++ b/packages/backend/src/server/api/endpoints/i/notifications.ts @@ -6,7 +6,7 @@ import { Brackets, In } from 'typeorm'; import * as Redis from 'ioredis'; import { Inject, Injectable } from '@nestjs/common'; -import type { NotesRepository } from '@/models/index.js'; +import type { NotesRepository } from '@/models/_.js'; import { obsoleteNotificationTypes, notificationTypes } from '@/types.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { NoteReadService } from '@/core/NoteReadService.js'; @@ -14,7 +14,7 @@ import { NotificationEntityService } from '@/core/entities/NotificationEntitySer import { NotificationService } from '@/core/NotificationService.js'; import { DI } from '@/di-symbols.js'; import { IdService } from '@/core/IdService.js'; -import { MiNotification } from '@/models/entities/Notification.js'; +import { MiNotification } from '@/models/Notification.js'; export const meta = { tags: ['account', 'notifications'], diff --git a/packages/backend/src/server/api/endpoints/i/page-likes.ts b/packages/backend/src/server/api/endpoints/i/page-likes.ts index 36f42c9f9..6bf7e6aa9 100644 --- a/packages/backend/src/server/api/endpoints/i/page-likes.ts +++ b/packages/backend/src/server/api/endpoints/i/page-likes.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { PageLikesRepository } from '@/models/index.js'; +import type { PageLikesRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { PageLikeEntityService } from '@/core/entities/PageLikeEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/i/pages.ts b/packages/backend/src/server/api/endpoints/i/pages.ts index cc56041f6..b8082c018 100644 --- a/packages/backend/src/server/api/endpoints/i/pages.ts +++ b/packages/backend/src/server/api/endpoints/i/pages.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { PagesRepository } from '@/models/index.js'; +import type { PagesRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { PageEntityService } from '@/core/entities/PageEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/i/read-all-unread-notes.ts b/packages/backend/src/server/api/endpoints/i/read-all-unread-notes.ts index 9a29d5c9e..e43ab7c15 100644 --- a/packages/backend/src/server/api/endpoints/i/read-all-unread-notes.ts +++ b/packages/backend/src/server/api/endpoints/i/read-all-unread-notes.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { NoteUnreadsRepository } from '@/models/index.js'; +import type { NoteUnreadsRepository } from '@/models/_.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/i/regenerate-token.ts b/packages/backend/src/server/api/endpoints/i/regenerate-token.ts index ad63369a2..b70dcfbac 100644 --- a/packages/backend/src/server/api/endpoints/i/regenerate-token.ts +++ b/packages/backend/src/server/api/endpoints/i/regenerate-token.ts @@ -6,7 +6,7 @@ import bcrypt from 'bcryptjs'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { UsersRepository, UserProfilesRepository } from '@/models/index.js'; +import type { UsersRepository, UserProfilesRepository } from '@/models/_.js'; import generateUserToken from '@/misc/generate-native-user-token.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/i/registry/get-all.ts b/packages/backend/src/server/api/endpoints/i/registry/get-all.ts index 926bdeee1..211e6637d 100644 --- a/packages/backend/src/server/api/endpoints/i/registry/get-all.ts +++ b/packages/backend/src/server/api/endpoints/i/registry/get-all.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { RegistryItemsRepository } from '@/models/index.js'; +import type { RegistryItemsRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; export const meta = { diff --git a/packages/backend/src/server/api/endpoints/i/registry/get-detail.ts b/packages/backend/src/server/api/endpoints/i/registry/get-detail.ts index 8e93b3a7c..9c6f2d678 100644 --- a/packages/backend/src/server/api/endpoints/i/registry/get-detail.ts +++ b/packages/backend/src/server/api/endpoints/i/registry/get-detail.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { RegistryItemsRepository } from '@/models/index.js'; +import type { RegistryItemsRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/i/registry/get.ts b/packages/backend/src/server/api/endpoints/i/registry/get.ts index 229e3b346..729e729b8 100644 --- a/packages/backend/src/server/api/endpoints/i/registry/get.ts +++ b/packages/backend/src/server/api/endpoints/i/registry/get.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { RegistryItemsRepository } from '@/models/index.js'; +import type { RegistryItemsRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/i/registry/keys-with-type.ts b/packages/backend/src/server/api/endpoints/i/registry/keys-with-type.ts index 4e8d01ff8..ffd2860fd 100644 --- a/packages/backend/src/server/api/endpoints/i/registry/keys-with-type.ts +++ b/packages/backend/src/server/api/endpoints/i/registry/keys-with-type.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { RegistryItemsRepository } from '@/models/index.js'; +import type { RegistryItemsRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; export const meta = { diff --git a/packages/backend/src/server/api/endpoints/i/registry/keys.ts b/packages/backend/src/server/api/endpoints/i/registry/keys.ts index 4aa2bd4b5..7239bb66e 100644 --- a/packages/backend/src/server/api/endpoints/i/registry/keys.ts +++ b/packages/backend/src/server/api/endpoints/i/registry/keys.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { RegistryItemsRepository } from '@/models/index.js'; +import type { RegistryItemsRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; export const meta = { diff --git a/packages/backend/src/server/api/endpoints/i/registry/remove.ts b/packages/backend/src/server/api/endpoints/i/registry/remove.ts index d1e999945..ae687fefe 100644 --- a/packages/backend/src/server/api/endpoints/i/registry/remove.ts +++ b/packages/backend/src/server/api/endpoints/i/registry/remove.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { RegistryItemsRepository } from '@/models/index.js'; +import type { RegistryItemsRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/i/registry/scopes.ts b/packages/backend/src/server/api/endpoints/i/registry/scopes.ts index 45ff06321..7637cdcf7 100644 --- a/packages/backend/src/server/api/endpoints/i/registry/scopes.ts +++ b/packages/backend/src/server/api/endpoints/i/registry/scopes.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { RegistryItemsRepository } from '@/models/index.js'; +import type { RegistryItemsRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; export const meta = { diff --git a/packages/backend/src/server/api/endpoints/i/registry/set.ts b/packages/backend/src/server/api/endpoints/i/registry/set.ts index 663cfe9f1..c074b152d 100644 --- a/packages/backend/src/server/api/endpoints/i/registry/set.ts +++ b/packages/backend/src/server/api/endpoints/i/registry/set.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { RegistryItemsRepository } from '@/models/index.js'; +import type { RegistryItemsRepository } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/i/revoke-token.ts b/packages/backend/src/server/api/endpoints/i/revoke-token.ts index 256a3ff7f..8e2f27100 100644 --- a/packages/backend/src/server/api/endpoints/i/revoke-token.ts +++ b/packages/backend/src/server/api/endpoints/i/revoke-token.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { AccessTokensRepository } from '@/models/index.js'; +import type { AccessTokensRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; export const meta = { diff --git a/packages/backend/src/server/api/endpoints/i/signin-history.ts b/packages/backend/src/server/api/endpoints/i/signin-history.ts index 5543a844b..139bede7b 100644 --- a/packages/backend/src/server/api/endpoints/i/signin-history.ts +++ b/packages/backend/src/server/api/endpoints/i/signin-history.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { SigninsRepository } from '@/models/index.js'; +import type { SigninsRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { SigninEntityService } from '@/core/entities/SigninEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/i/update-email.ts b/packages/backend/src/server/api/endpoints/i/update-email.ts index 37996db9b..a36b3a732 100644 --- a/packages/backend/src/server/api/endpoints/i/update-email.ts +++ b/packages/backend/src/server/api/endpoints/i/update-email.ts @@ -7,13 +7,14 @@ import { Inject, Injectable } from '@nestjs/common'; import ms from 'ms'; import bcrypt from 'bcryptjs'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { UserProfilesRepository } from '@/models/index.js'; +import type { UserProfilesRepository } from '@/models/_.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { EmailService } from '@/core/EmailService.js'; import type { Config } from '@/config.js'; import { DI } from '@/di-symbols.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { L_CHARS, secureRndstr } from '@/misc/secure-rndstr.js'; +import { UserAuthService } from '@/core/UserAuthService.js'; import { ApiError } from '../../error.js'; export const meta = { @@ -46,6 +47,7 @@ export const paramDef = { properties: { password: { type: 'string' }, email: { type: 'string', nullable: true }, + token: { type: 'string', nullable: true }, }, required: ['password'], } as const; @@ -61,15 +63,27 @@ export default class extends Endpoint { // eslint- private userEntityService: UserEntityService, private emailService: EmailService, + private userAuthService: UserAuthService, private globalEventService: GlobalEventService, ) { super(meta, paramDef, async (ps, me) => { + const token = ps.token; const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id }); - // Compare password - const same = await bcrypt.compare(ps.password, profile.password!); + if (profile.twoFactorEnabled) { + if (token == null) { + throw new Error('authentication failed'); + } - if (!same) { + try { + await this.userAuthService.twoFactorAuthenticate(profile, token); + } catch (e) { + throw new Error('authentication failed'); + } + } + + const passwordMatched = await bcrypt.compare(ps.password, profile.password!); + if (!passwordMatched) { throw new ApiError(meta.errors.incorrectPassword); } diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts index 89125392d..b11e09195 100644 --- a/packages/backend/src/server/api/endpoints/i/update.ts +++ b/packages/backend/src/server/api/endpoints/i/update.ts @@ -6,13 +6,15 @@ import RE2 from 're2'; import * as mfm from 'mfm-js'; import { Inject, Injectable } from '@nestjs/common'; +import ms from 'ms'; +import { JSDOM } from 'jsdom'; import { extractCustomEmojisFromMfm } from '@/misc/extract-custom-emojis-from-mfm.js'; import { extractHashtags } from '@/misc/extract-hashtags.js'; import * as Acct from '@/misc/acct.js'; -import type { UsersRepository, DriveFilesRepository, UserProfilesRepository, PagesRepository } from '@/models/index.js'; -import type { MiUser } from '@/models/entities/User.js'; -import { birthdaySchema, descriptionSchema, locationSchema, nameSchema } from '@/models/entities/User.js'; -import type { MiUserProfile } from '@/models/entities/UserProfile.js'; +import type { UsersRepository, DriveFilesRepository, UserProfilesRepository, PagesRepository } from '@/models/_.js'; +import type { MiLocalUser, MiUser } from '@/models/User.js'; +import { birthdaySchema, descriptionSchema, locationSchema, nameSchema } from '@/models/User.js'; +import type { MiUserProfile } from '@/models/UserProfile.js'; import { notificationTypes } from '@/types.js'; import { normalizeForSearch } from '@/misc/normalize-for-search.js'; import { langmap } from '@/misc/langmap.js'; @@ -27,6 +29,9 @@ import { RoleService } from '@/core/RoleService.js'; import { CacheService } from '@/core/CacheService.js'; import { RemoteUserResolveService } from '@/core/RemoteUserResolveService.js'; import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js'; +import { HttpRequestService } from '@/core/HttpRequestService.js'; +import type { Config } from '@/config.js'; +import { safeForSql } from '@/misc/safe-for-sql.js'; import { ApiLoggerService } from '../../ApiLoggerService.js'; import { ApiError } from '../../error.js'; @@ -37,6 +42,11 @@ export const meta = { kind: 'write:account', + limit: { + duration: ms('1hour'), + max: 10, + }, + errors: { noSuchAvatar: { message: 'No such avatar file.', @@ -173,6 +183,9 @@ export const paramDef = { @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( + @Inject(DI.config) + private config: Config, + @Inject(DI.usersRepository) private usersRepository: UsersRepository, @@ -195,9 +208,10 @@ export default class extends Endpoint { // eslint- private hashtagService: HashtagService, private roleService: RoleService, private cacheService: CacheService, + private httpRequestService: HttpRequestService, ) { super(meta, paramDef, async (ps, _user, token) => { - const user = await this.usersRepository.findOneByOrFail({ id: _user.id }); + const user = await this.usersRepository.findOneByOrFail({ id: _user.id }) as MiLocalUser; const isSecure = token == null; const updates = {} as Partial; @@ -296,9 +310,9 @@ export default class extends Endpoint { // eslint- if (ps.fields) { profileUpdates.fields = ps.fields - .filter(x => typeof x.name === 'string' && x.name !== '' && typeof x.value === 'string' && x.value !== '') + .filter(x => typeof x.name === 'string' && x.name.trim() !== '' && typeof x.value === 'string' && x.value.trim() !== '') .map(x => { - return { name: x.name, value: x.value }; + return { name: x.name.trim(), value: x.value.trim() }; }); } @@ -364,7 +378,11 @@ export default class extends Endpoint { // eslint- if (Object.keys(updates).includes('alsoKnownAs')) { this.cacheService.uriPersonCache.set(this.userEntityService.genLocalUserUri(user.id), { ...user, ...updates }); } - if (Object.keys(profileUpdates).length > 0) await this.userProfilesRepository.update(user.id, profileUpdates); + + await this.userProfilesRepository.update(user.id, { + ...profileUpdates, + verifiedLinks: [], + }); const iObj = await this.userEntityService.pack(user.id, user, { detail: true, @@ -386,7 +404,34 @@ export default class extends Endpoint { // eslint- // フォロワーにUpdateを配信 this.accountUpdateService.publishToFollowers(user.id); + const urls = updatedProfile.fields.filter(x => x.value.startsWith('https://')); + for (const url of urls) { + this.verifyLink(url.value, user); + } + return iObj; }); } + + private async verifyLink(url: string, user: MiLocalUser) { + if (!safeForSql(url)) return; + + const html = await this.httpRequestService.getHtml(url); + + const { window } = new JSDOM(html); + const doc = window.document; + + const myLink = `${this.config.url}/@${user.username}`; + + const includesMyLink = Array.from(doc.getElementsByTagName('a')).some(a => a.href === myLink); + + if (includesMyLink) { + await this.userProfilesRepository.createQueryBuilder('profile').update() + .where('userId = :userId', { userId: user.id }) + .set({ + verifiedLinks: () => `array_append("verifiedLinks", '${url}')`, // ここでSQLインジェクションされそうなのでとりあえず safeForSql で弾いている + }) + .execute(); + } + } } diff --git a/packages/backend/src/server/api/endpoints/i/webhooks/create.ts b/packages/backend/src/server/api/endpoints/i/webhooks/create.ts index 6daaacac0..48eaeff40 100644 --- a/packages/backend/src/server/api/endpoints/i/webhooks/create.ts +++ b/packages/backend/src/server/api/endpoints/i/webhooks/create.ts @@ -6,8 +6,8 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { IdService } from '@/core/IdService.js'; -import type { WebhooksRepository } from '@/models/index.js'; -import { webhookEventTypes } from '@/models/entities/Webhook.js'; +import type { WebhooksRepository } from '@/models/_.js'; +import { webhookEventTypes } from '@/models/Webhook.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; import { RoleService } from '@/core/RoleService.js'; diff --git a/packages/backend/src/server/api/endpoints/i/webhooks/delete.ts b/packages/backend/src/server/api/endpoints/i/webhooks/delete.ts index da0002858..db7d0db13 100644 --- a/packages/backend/src/server/api/endpoints/i/webhooks/delete.ts +++ b/packages/backend/src/server/api/endpoints/i/webhooks/delete.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { WebhooksRepository } from '@/models/index.js'; +import type { WebhooksRepository } from '@/models/_.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/i/webhooks/list.ts b/packages/backend/src/server/api/endpoints/i/webhooks/list.ts index 478b34296..aa8921fe2 100644 --- a/packages/backend/src/server/api/endpoints/i/webhooks/list.ts +++ b/packages/backend/src/server/api/endpoints/i/webhooks/list.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { WebhooksRepository } from '@/models/index.js'; +import type { WebhooksRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; export const meta = { diff --git a/packages/backend/src/server/api/endpoints/i/webhooks/show.ts b/packages/backend/src/server/api/endpoints/i/webhooks/show.ts index f774840e9..f1294bb5c 100644 --- a/packages/backend/src/server/api/endpoints/i/webhooks/show.ts +++ b/packages/backend/src/server/api/endpoints/i/webhooks/show.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { WebhooksRepository } from '@/models/index.js'; +import type { WebhooksRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/i/webhooks/update.ts b/packages/backend/src/server/api/endpoints/i/webhooks/update.ts index 012bacbbe..b3e000524 100644 --- a/packages/backend/src/server/api/endpoints/i/webhooks/update.ts +++ b/packages/backend/src/server/api/endpoints/i/webhooks/update.ts @@ -5,8 +5,8 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { WebhooksRepository } from '@/models/index.js'; -import { webhookEventTypes } from '@/models/entities/Webhook.js'; +import type { WebhooksRepository } from '@/models/_.js'; +import { webhookEventTypes } from '@/models/Webhook.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/invite/create.ts b/packages/backend/src/server/api/endpoints/invite/create.ts index 8532beceb..7361ab616 100644 --- a/packages/backend/src/server/api/endpoints/invite/create.ts +++ b/packages/backend/src/server/api/endpoints/invite/create.ts @@ -6,7 +6,7 @@ import { MoreThan } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { RegistrationTicketsRepository } from '@/models/index.js'; +import type { RegistrationTicketsRepository } from '@/models/_.js'; import { InviteCodeEntityService } from '@/core/entities/InviteCodeEntityService.js'; import { IdService } from '@/core/IdService.js'; import { RoleService } from '@/core/RoleService.js'; diff --git a/packages/backend/src/server/api/endpoints/invite/delete.ts b/packages/backend/src/server/api/endpoints/invite/delete.ts index 8991bfef2..3b5777573 100644 --- a/packages/backend/src/server/api/endpoints/invite/delete.ts +++ b/packages/backend/src/server/api/endpoints/invite/delete.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { RegistrationTicketsRepository } from '@/models/index.js'; +import type { RegistrationTicketsRepository } from '@/models/_.js'; import { RoleService } from '@/core/RoleService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/invite/limit.ts b/packages/backend/src/server/api/endpoints/invite/limit.ts index 386fd676b..43b94e4f0 100644 --- a/packages/backend/src/server/api/endpoints/invite/limit.ts +++ b/packages/backend/src/server/api/endpoints/invite/limit.ts @@ -6,7 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { MoreThan } from 'typeorm'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { RegistrationTicketsRepository } from '@/models/index.js'; +import type { RegistrationTicketsRepository } from '@/models/_.js'; import { RoleService } from '@/core/RoleService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/invite/list.ts b/packages/backend/src/server/api/endpoints/invite/list.ts index dcd101758..06139b680 100644 --- a/packages/backend/src/server/api/endpoints/invite/list.ts +++ b/packages/backend/src/server/api/endpoints/invite/list.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { RegistrationTicketsRepository } from '@/models/index.js'; +import type { RegistrationTicketsRepository } from '@/models/_.js'; import { InviteCodeEntityService } from '@/core/entities/InviteCodeEntityService.js'; import { QueryService } from '@/core/QueryService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts index fbcb8dc34..fa6486ed1 100644 --- a/packages/backend/src/server/api/endpoints/meta.ts +++ b/packages/backend/src/server/api/endpoints/meta.ts @@ -6,7 +6,7 @@ import { IsNull, LessThanOrEqual, MoreThan, Brackets } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; import JSON5 from 'json5'; -import type { AdsRepository, UsersRepository } from '@/models/index.js'; +import type { AdsRepository, UsersRepository } from '@/models/_.js'; import { MAX_NOTE_TEXT_LENGTH } from '@/const.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; @@ -40,6 +40,10 @@ export const meta = { type: 'string', optional: false, nullable: false, }, + shortName: { + type: 'string', + optional: false, nullable: true, + }, uri: { type: 'string', optional: false, nullable: false, @@ -288,6 +292,7 @@ export default class extends Endpoint { // eslint- version: this.config.version, name: instance.name, + shortName: instance.shortName, uri: this.config.url, description: instance.description, langs: instance.langs, diff --git a/packages/backend/src/server/api/endpoints/miauth/gen-token.ts b/packages/backend/src/server/api/endpoints/miauth/gen-token.ts index 7f14342d9..e40656cb6 100644 --- a/packages/backend/src/server/api/endpoints/miauth/gen-token.ts +++ b/packages/backend/src/server/api/endpoints/miauth/gen-token.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { AccessTokensRepository } from '@/models/index.js'; +import type { AccessTokensRepository } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; import { secureRndstr } from '@/misc/secure-rndstr.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/mute/create.ts b/packages/backend/src/server/api/endpoints/mute/create.ts index d896a41d6..49c2b5707 100644 --- a/packages/backend/src/server/api/endpoints/mute/create.ts +++ b/packages/backend/src/server/api/endpoints/mute/create.ts @@ -6,7 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import ms from 'ms'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { MutingsRepository } from '@/models/index.js'; +import type { MutingsRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { GetterService } from '@/server/api/GetterService.js'; import { UserMutingService } from '@/core/UserMutingService.js'; diff --git a/packages/backend/src/server/api/endpoints/mute/delete.ts b/packages/backend/src/server/api/endpoints/mute/delete.ts index 51005206b..a3fd2dd82 100644 --- a/packages/backend/src/server/api/endpoints/mute/delete.ts +++ b/packages/backend/src/server/api/endpoints/mute/delete.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { MutingsRepository } from '@/models/index.js'; +import type { MutingsRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { GetterService } from '@/server/api/GetterService.js'; import { UserMutingService } from '@/core/UserMutingService.js'; diff --git a/packages/backend/src/server/api/endpoints/mute/list.ts b/packages/backend/src/server/api/endpoints/mute/list.ts index 710d59c25..2a41182eb 100644 --- a/packages/backend/src/server/api/endpoints/mute/list.ts +++ b/packages/backend/src/server/api/endpoints/mute/list.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { MutingsRepository } from '@/models/index.js'; +import type { MutingsRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { MutingEntityService } from '@/core/entities/MutingEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/my/apps.ts b/packages/backend/src/server/api/endpoints/my/apps.ts index e35920e2e..98c317346 100644 --- a/packages/backend/src/server/api/endpoints/my/apps.ts +++ b/packages/backend/src/server/api/endpoints/my/apps.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { AppsRepository } from '@/models/index.js'; +import type { AppsRepository } from '@/models/_.js'; import { AppEntityService } from '@/core/entities/AppEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/notes.ts b/packages/backend/src/server/api/endpoints/notes.ts index 4e451b04e..95ba5e8b6 100644 --- a/packages/backend/src/server/api/endpoints/notes.ts +++ b/packages/backend/src/server/api/endpoints/notes.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { NotesRepository } from '@/models/index.js'; +import type { NotesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; diff --git a/packages/backend/src/server/api/endpoints/notes/children.ts b/packages/backend/src/server/api/endpoints/notes/children.ts index 93bfe964b..1a82a4b5d 100644 --- a/packages/backend/src/server/api/endpoints/notes/children.ts +++ b/packages/backend/src/server/api/endpoints/notes/children.ts @@ -5,7 +5,7 @@ import { Brackets } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { NotesRepository } from '@/models/index.js'; +import type { NotesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; diff --git a/packages/backend/src/server/api/endpoints/notes/clips.ts b/packages/backend/src/server/api/endpoints/notes/clips.ts index ea43043d4..677c0ea30 100644 --- a/packages/backend/src/server/api/endpoints/notes/clips.ts +++ b/packages/backend/src/server/api/endpoints/notes/clips.ts @@ -5,7 +5,7 @@ import { In } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { ClipNotesRepository, ClipsRepository } from '@/models/index.js'; +import type { ClipNotesRepository, ClipsRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { ClipEntityService } from '@/core/entities/ClipEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/notes/conversation.ts b/packages/backend/src/server/api/endpoints/notes/conversation.ts index 0a919c217..b94a019da 100644 --- a/packages/backend/src/server/api/endpoints/notes/conversation.ts +++ b/packages/backend/src/server/api/endpoints/notes/conversation.ts @@ -4,8 +4,8 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { MiNote } from '@/models/entities/Note.js'; -import type { NotesRepository } from '@/models/index.js'; +import type { MiNote } from '@/models/Note.js'; +import type { NotesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/notes/create.ts b/packages/backend/src/server/api/endpoints/notes/create.ts index 22e772d1a..2e4d316c4 100644 --- a/packages/backend/src/server/api/endpoints/notes/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/create.ts @@ -6,11 +6,11 @@ import ms from 'ms'; import { In } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { MiUser } from '@/models/entities/User.js'; -import type { UsersRepository, NotesRepository, BlockingsRepository, DriveFilesRepository, ChannelsRepository } from '@/models/index.js'; -import type { MiDriveFile } from '@/models/entities/DriveFile.js'; -import type { MiNote } from '@/models/entities/Note.js'; -import type { MiChannel } from '@/models/entities/Channel.js'; +import type { MiUser } from '@/models/User.js'; +import type { UsersRepository, NotesRepository, BlockingsRepository, DriveFilesRepository, ChannelsRepository } from '@/models/_.js'; +import type { MiDriveFile } from '@/models/DriveFile.js'; +import type { MiNote } from '@/models/Note.js'; +import type { MiChannel } from '@/models/Channel.js'; import { MAX_NOTE_TEXT_LENGTH } from '@/const.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; diff --git a/packages/backend/src/server/api/endpoints/notes/delete.ts b/packages/backend/src/server/api/endpoints/notes/delete.ts index 33bea250c..55aaaf4f7 100644 --- a/packages/backend/src/server/api/endpoints/notes/delete.ts +++ b/packages/backend/src/server/api/endpoints/notes/delete.ts @@ -5,7 +5,7 @@ import ms from 'ms'; import { Inject, Injectable } from '@nestjs/common'; -import type { UsersRepository } from '@/models/index.js'; +import type { UsersRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { NoteDeleteService } from '@/core/NoteDeleteService.js'; import { DI } from '@/di-symbols.js'; @@ -70,7 +70,7 @@ export default class extends Endpoint { // eslint- } // この操作を行うのが投稿者とは限らない(例えばモデレーター)ため - await this.noteDeleteService.delete(await this.usersRepository.findOneByOrFail({ id: note.userId }), note); + await this.noteDeleteService.delete(await this.usersRepository.findOneByOrFail({ id: note.userId }), note, false, me); }); } } diff --git a/packages/backend/src/server/api/endpoints/notes/favorites/create.ts b/packages/backend/src/server/api/endpoints/notes/favorites/create.ts index 7207404ff..cc648e22a 100644 --- a/packages/backend/src/server/api/endpoints/notes/favorites/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/favorites/create.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import ms from 'ms'; -import type { NoteFavoritesRepository } from '@/models/index.js'; +import type { NoteFavoritesRepository } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { GetterService } from '@/server/api/GetterService.js'; diff --git a/packages/backend/src/server/api/endpoints/notes/favorites/delete.ts b/packages/backend/src/server/api/endpoints/notes/favorites/delete.ts index 1be51d02d..8ab9775a2 100644 --- a/packages/backend/src/server/api/endpoints/notes/favorites/delete.ts +++ b/packages/backend/src/server/api/endpoints/notes/favorites/delete.ts @@ -7,7 +7,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { GetterService } from '@/server/api/GetterService.js'; import { DI } from '@/di-symbols.js'; -import type { NoteFavoritesRepository } from '@/models/index.js'; +import type { NoteFavoritesRepository } from '@/models/_.js'; import { ApiError } from '../../../error.js'; export const meta = { diff --git a/packages/backend/src/server/api/endpoints/notes/featured.ts b/packages/backend/src/server/api/endpoints/notes/featured.ts index b65a7ed7b..5283b0e0b 100644 --- a/packages/backend/src/server/api/endpoints/notes/featured.ts +++ b/packages/backend/src/server/api/endpoints/notes/featured.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { NotesRepository } from '@/models/index.js'; +import type { NotesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; diff --git a/packages/backend/src/server/api/endpoints/notes/global-timeline.ts b/packages/backend/src/server/api/endpoints/notes/global-timeline.ts index 9e2dcc532..0b3b5c902 100644 --- a/packages/backend/src/server/api/endpoints/notes/global-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/global-timeline.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { NotesRepository } from '@/models/index.js'; +import type { NotesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; diff --git a/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts b/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts index 69e0f218e..e9ae5dc75 100644 --- a/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts @@ -5,7 +5,7 @@ import { Brackets } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { NotesRepository, FollowingsRepository } from '@/models/index.js'; +import type { NotesRepository, FollowingsRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; import ActiveUsersChart from '@/core/chart/charts/active-users.js'; diff --git a/packages/backend/src/server/api/endpoints/notes/local-timeline.ts b/packages/backend/src/server/api/endpoints/notes/local-timeline.ts index 3fea8eb3c..af1e0398d 100644 --- a/packages/backend/src/server/api/endpoints/notes/local-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/local-timeline.ts @@ -5,7 +5,7 @@ import { Brackets } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { NotesRepository } from '@/models/index.js'; +import type { NotesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; diff --git a/packages/backend/src/server/api/endpoints/notes/mentions.ts b/packages/backend/src/server/api/endpoints/notes/mentions.ts index 6afe13be6..65e7bd8cd 100644 --- a/packages/backend/src/server/api/endpoints/notes/mentions.ts +++ b/packages/backend/src/server/api/endpoints/notes/mentions.ts @@ -5,7 +5,7 @@ import { Brackets } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { NotesRepository, FollowingsRepository } from '@/models/index.js'; +import type { NotesRepository, FollowingsRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; diff --git a/packages/backend/src/server/api/endpoints/notes/polls/recommendation.ts b/packages/backend/src/server/api/endpoints/notes/polls/recommendation.ts index 744f275a5..29190af62 100644 --- a/packages/backend/src/server/api/endpoints/notes/polls/recommendation.ts +++ b/packages/backend/src/server/api/endpoints/notes/polls/recommendation.ts @@ -5,7 +5,7 @@ import { Brackets, In } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { NotesRepository, MutingsRepository, PollsRepository, PollVotesRepository } from '@/models/index.js'; +import type { NotesRepository, MutingsRepository, PollsRepository, PollVotesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/notes/polls/vote.ts b/packages/backend/src/server/api/endpoints/notes/polls/vote.ts index 53ceeb5a2..a58bf09b8 100644 --- a/packages/backend/src/server/api/endpoints/notes/polls/vote.ts +++ b/packages/backend/src/server/api/endpoints/notes/polls/vote.ts @@ -4,8 +4,8 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { UsersRepository, PollsRepository, PollVotesRepository } from '@/models/index.js'; -import type { MiRemoteUser } from '@/models/entities/User.js'; +import type { UsersRepository, PollsRepository, PollVotesRepository } from '@/models/_.js'; +import type { MiRemoteUser } from '@/models/User.js'; import { IdService } from '@/core/IdService.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { GetterService } from '@/server/api/GetterService.js'; diff --git a/packages/backend/src/server/api/endpoints/notes/reactions.ts b/packages/backend/src/server/api/endpoints/notes/reactions.ts index 695760118..a2c177819 100644 --- a/packages/backend/src/server/api/endpoints/notes/reactions.ts +++ b/packages/backend/src/server/api/endpoints/notes/reactions.ts @@ -4,12 +4,13 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { NoteReactionsRepository } from '@/models/index.js'; -import type { MiNoteReaction } from '@/models/entities/NoteReaction.js'; +import { Brackets, type FindOptionsWhere } from 'typeorm'; +import type { NoteReactionsRepository } from '@/models/_.js'; +import type { MiNoteReaction } from '@/models/NoteReaction.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { NoteReactionEntityService } from '@/core/entities/NoteReactionEntityService.js'; import { DI } from '@/di-symbols.js'; -import type { FindOptionsWhere } from 'typeorm'; +import { QueryService } from '@/core/QueryService.js'; export const meta = { tags: ['notes', 'reactions'], @@ -44,7 +45,6 @@ export const paramDef = { noteId: { type: 'string', format: 'misskey:id' }, type: { type: 'string', nullable: true }, limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, - offset: { type: 'integer', default: 0 }, sinceId: { type: 'string', format: 'misskey:id' }, untilId: { type: 'string', format: 'misskey:id' }, }, @@ -58,29 +58,23 @@ export default class extends Endpoint { // eslint- private noteReactionsRepository: NoteReactionsRepository, private noteReactionEntityService: NoteReactionEntityService, + private queryService: QueryService, ) { super(meta, paramDef, async (ps, me) => { - const query = { - noteId: ps.noteId, - } as FindOptionsWhere; + const query = this.queryService.makePaginationQuery(this.noteReactionsRepository.createQueryBuilder('reaction'), ps.sinceId, ps.untilId) + .andWhere('reaction.noteId = :noteId', { noteId: ps.noteId }) + .leftJoinAndSelect('reaction.user', 'user') + .leftJoinAndSelect('reaction.note', 'note'); if (ps.type) { // ローカルリアクションはホスト名が . とされているが // DB 上ではそうではないので、必要に応じて変換 const suffix = '@.:'; const type = ps.type.endsWith(suffix) ? ps.type.slice(0, ps.type.length - suffix.length) + ':' : ps.type; - query.reaction = type; + query.andWhere('reaction.reaction = :type', { type }); } - const reactions = await this.noteReactionsRepository.find({ - where: query, - take: ps.limit, - skip: ps.offset, - order: { - id: -1, - }, - relations: ['user', 'note'], - }); + const reactions = await query.limit(ps.limit).getMany(); return await Promise.all(reactions.map(reaction => this.noteReactionEntityService.pack(reaction, me))); }); diff --git a/packages/backend/src/server/api/endpoints/notes/renotes.ts b/packages/backend/src/server/api/endpoints/notes/renotes.ts index a7bd47df8..9f16181a3 100644 --- a/packages/backend/src/server/api/endpoints/notes/renotes.ts +++ b/packages/backend/src/server/api/endpoints/notes/renotes.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { NotesRepository } from '@/models/index.js'; +import type { NotesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; diff --git a/packages/backend/src/server/api/endpoints/notes/replies.ts b/packages/backend/src/server/api/endpoints/notes/replies.ts index ea5d55776..70142c981 100644 --- a/packages/backend/src/server/api/endpoints/notes/replies.ts +++ b/packages/backend/src/server/api/endpoints/notes/replies.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { NotesRepository } from '@/models/index.js'; +import type { NotesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; diff --git a/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts b/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts index 786282c64..b00f5207d 100644 --- a/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts +++ b/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts @@ -5,7 +5,7 @@ import { Brackets } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { NotesRepository } from '@/models/index.js'; +import type { NotesRepository } from '@/models/_.js'; import { safeForSql } from '@/misc/safe-for-sql.js'; import { normalizeForSearch } from '@/misc/normalize-for-search.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; diff --git a/packages/backend/src/server/api/endpoints/notes/state.ts b/packages/backend/src/server/api/endpoints/notes/state.ts index ac05c747d..b5fd47723 100644 --- a/packages/backend/src/server/api/endpoints/notes/state.ts +++ b/packages/backend/src/server/api/endpoints/notes/state.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { NotesRepository, NoteThreadMutingsRepository, NoteFavoritesRepository } from '@/models/index.js'; +import type { NotesRepository, NoteThreadMutingsRepository, NoteFavoritesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/notes/thread-muting/create.ts b/packages/backend/src/server/api/endpoints/notes/thread-muting/create.ts index afd8276d9..449a83860 100644 --- a/packages/backend/src/server/api/endpoints/notes/thread-muting/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/thread-muting/create.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import ms from 'ms'; -import type { NotesRepository, NoteThreadMutingsRepository } from '@/models/index.js'; +import type { NotesRepository, NoteThreadMutingsRepository } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { GetterService } from '@/server/api/GetterService.js'; diff --git a/packages/backend/src/server/api/endpoints/notes/thread-muting/delete.ts b/packages/backend/src/server/api/endpoints/notes/thread-muting/delete.ts index 8ef573e98..d3f1787ee 100644 --- a/packages/backend/src/server/api/endpoints/notes/thread-muting/delete.ts +++ b/packages/backend/src/server/api/endpoints/notes/thread-muting/delete.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { NoteThreadMutingsRepository } from '@/models/index.js'; +import type { NoteThreadMutingsRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { GetterService } from '@/server/api/GetterService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/notes/timeline.ts b/packages/backend/src/server/api/endpoints/notes/timeline.ts index c53ebcbf4..042115ab8 100644 --- a/packages/backend/src/server/api/endpoints/notes/timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/timeline.ts @@ -5,7 +5,7 @@ import { Brackets } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { NotesRepository, FollowingsRepository } from '@/models/index.js'; +import type { NotesRepository, FollowingsRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; import ActiveUsersChart from '@/core/chart/charts/active-users.js'; diff --git a/packages/backend/src/server/api/endpoints/notes/unrenote.ts b/packages/backend/src/server/api/endpoints/notes/unrenote.ts index a6e4eb01a..f67e9365f 100644 --- a/packages/backend/src/server/api/endpoints/notes/unrenote.ts +++ b/packages/backend/src/server/api/endpoints/notes/unrenote.ts @@ -5,7 +5,7 @@ import ms from 'ms'; import { Inject, Injectable } from '@nestjs/common'; -import type { UsersRepository, NotesRepository } from '@/models/index.js'; +import type { UsersRepository, NotesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { NoteDeleteService } from '@/core/NoteDeleteService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts b/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts index 8b8d24e72..693207379 100644 --- a/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts @@ -5,7 +5,7 @@ import { Brackets } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { NotesRepository, UserListsRepository, UserListJoiningsRepository } from '@/models/index.js'; +import type { NotesRepository, UserListsRepository, UserListJoiningsRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; diff --git a/packages/backend/src/server/api/endpoints/notifications/create.ts b/packages/backend/src/server/api/endpoints/notifications/create.ts index 020fc2d3d..268628cf7 100644 --- a/packages/backend/src/server/api/endpoints/notifications/create.ts +++ b/packages/backend/src/server/api/endpoints/notifications/create.ts @@ -14,6 +14,11 @@ export const meta = { kind: 'write:notifications', + limit: { + duration: 1000 * 60, + max: 10, + }, + errors: { }, } as const; diff --git a/packages/backend/src/server/api/endpoints/notifications/test-notification.ts b/packages/backend/src/server/api/endpoints/notifications/test-notification.ts index 04a68a805..8f5f8485c 100644 --- a/packages/backend/src/server/api/endpoints/notifications/test-notification.ts +++ b/packages/backend/src/server/api/endpoints/notifications/test-notification.ts @@ -13,6 +13,11 @@ export const meta = { requireCredential: true, kind: 'write:notifications', + + limit: { + duration: 1000 * 60, + max: 10, + }, } as const; export const paramDef = { diff --git a/packages/backend/src/server/api/endpoints/page-push.ts b/packages/backend/src/server/api/endpoints/page-push.ts index 8fff9a926..0a6851658 100644 --- a/packages/backend/src/server/api/endpoints/page-push.ts +++ b/packages/backend/src/server/api/endpoints/page-push.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { PagesRepository } from '@/models/index.js'; +import type { PagesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; diff --git a/packages/backend/src/server/api/endpoints/pages/create.ts b/packages/backend/src/server/api/endpoints/pages/create.ts index 1b6ba4075..c0e8fab16 100644 --- a/packages/backend/src/server/api/endpoints/pages/create.ts +++ b/packages/backend/src/server/api/endpoints/pages/create.ts @@ -5,9 +5,9 @@ import ms from 'ms'; import { Inject, Injectable } from '@nestjs/common'; -import type { DriveFilesRepository, PagesRepository } from '@/models/index.js'; +import type { DriveFilesRepository, PagesRepository } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; -import { MiPage } from '@/models/entities/Page.js'; +import { MiPage } from '@/models/Page.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { PageEntityService } from '@/core/entities/PageEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/pages/delete.ts b/packages/backend/src/server/api/endpoints/pages/delete.ts index ac55abffb..1291c0d20 100644 --- a/packages/backend/src/server/api/endpoints/pages/delete.ts +++ b/packages/backend/src/server/api/endpoints/pages/delete.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { PagesRepository } from '@/models/index.js'; +import type { PagesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/pages/featured.ts b/packages/backend/src/server/api/endpoints/pages/featured.ts index 68c06adb7..1f43d6606 100644 --- a/packages/backend/src/server/api/endpoints/pages/featured.ts +++ b/packages/backend/src/server/api/endpoints/pages/featured.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { PagesRepository } from '@/models/index.js'; +import type { PagesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { PageEntityService } from '@/core/entities/PageEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/pages/like.ts b/packages/backend/src/server/api/endpoints/pages/like.ts index 155f6db55..6c69cad9d 100644 --- a/packages/backend/src/server/api/endpoints/pages/like.ts +++ b/packages/backend/src/server/api/endpoints/pages/like.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { PagesRepository, PageLikesRepository } from '@/models/index.js'; +import type { PagesRepository, PageLikesRepository } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/pages/show.ts b/packages/backend/src/server/api/endpoints/pages/show.ts index f74b67a62..efb0bd067 100644 --- a/packages/backend/src/server/api/endpoints/pages/show.ts +++ b/packages/backend/src/server/api/endpoints/pages/show.ts @@ -5,8 +5,8 @@ import { IsNull } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { UsersRepository, PagesRepository } from '@/models/index.js'; -import type { MiPage } from '@/models/entities/Page.js'; +import type { UsersRepository, PagesRepository } from '@/models/_.js'; +import type { MiPage } from '@/models/Page.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { PageEntityService } from '@/core/entities/PageEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/pages/unlike.ts b/packages/backend/src/server/api/endpoints/pages/unlike.ts index 143cb6965..7a76cd740 100644 --- a/packages/backend/src/server/api/endpoints/pages/unlike.ts +++ b/packages/backend/src/server/api/endpoints/pages/unlike.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { PagesRepository, PageLikesRepository } from '@/models/index.js'; +import type { PagesRepository, PageLikesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/pages/update.ts b/packages/backend/src/server/api/endpoints/pages/update.ts index 4d54d82b7..aaea1efa8 100644 --- a/packages/backend/src/server/api/endpoints/pages/update.ts +++ b/packages/backend/src/server/api/endpoints/pages/update.ts @@ -6,7 +6,7 @@ import ms from 'ms'; import { Not } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { PagesRepository, DriveFilesRepository } from '@/models/index.js'; +import type { PagesRepository, DriveFilesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/pinned-users.ts b/packages/backend/src/server/api/endpoints/pinned-users.ts index 78c65e020..390042c81 100644 --- a/packages/backend/src/server/api/endpoints/pinned-users.ts +++ b/packages/backend/src/server/api/endpoints/pinned-users.ts @@ -5,9 +5,9 @@ import { IsNull } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { UsersRepository } from '@/models/index.js'; +import type { UsersRepository } from '@/models/_.js'; import * as Acct from '@/misc/acct.js'; -import type { MiUser } from '@/models/entities/User.js'; +import type { MiUser } from '@/models/User.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { MetaService } from '@/core/MetaService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; diff --git a/packages/backend/src/server/api/endpoints/promo/read.ts b/packages/backend/src/server/api/endpoints/promo/read.ts index 2e11be4dc..b197756ac 100644 --- a/packages/backend/src/server/api/endpoints/promo/read.ts +++ b/packages/backend/src/server/api/endpoints/promo/read.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { PromoReadsRepository } from '@/models/index.js'; +import type { PromoReadsRepository } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/renote-mute/create.ts b/packages/backend/src/server/api/endpoints/renote-mute/create.ts index a1e9c7055..3c9d266e2 100644 --- a/packages/backend/src/server/api/endpoints/renote-mute/create.ts +++ b/packages/backend/src/server/api/endpoints/renote-mute/create.ts @@ -7,8 +7,8 @@ import { Inject, Injectable } from '@nestjs/common'; import ms from 'ms'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { IdService } from '@/core/IdService.js'; -import type { RenoteMutingsRepository } from '@/models/index.js'; -import type { MiRenoteMuting } from '@/models/entities/RenoteMuting.js'; +import type { RenoteMutingsRepository } from '@/models/_.js'; +import type { MiRenoteMuting } from '@/models/RenoteMuting.js'; import { DI } from '@/di-symbols.js'; import { GetterService } from '@/server/api/GetterService.js'; import { ApiError } from '../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/renote-mute/delete.ts b/packages/backend/src/server/api/endpoints/renote-mute/delete.ts index b390380e4..f4969896d 100644 --- a/packages/backend/src/server/api/endpoints/renote-mute/delete.ts +++ b/packages/backend/src/server/api/endpoints/renote-mute/delete.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { RenoteMutingsRepository } from '@/models/index.js'; +import type { RenoteMutingsRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { GetterService } from '@/server/api/GetterService.js'; import { ApiError } from '../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/renote-mute/list.ts b/packages/backend/src/server/api/endpoints/renote-mute/list.ts index f6fae38bc..493593ae2 100644 --- a/packages/backend/src/server/api/endpoints/renote-mute/list.ts +++ b/packages/backend/src/server/api/endpoints/renote-mute/list.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { RenoteMutingsRepository } from '@/models/index.js'; +import type { RenoteMutingsRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { RenoteMutingEntityService } from '@/core/entities/RenoteMutingEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/request-reset-password.ts b/packages/backend/src/server/api/endpoints/request-reset-password.ts index 117eac687..adb160c58 100644 --- a/packages/backend/src/server/api/endpoints/request-reset-password.ts +++ b/packages/backend/src/server/api/endpoints/request-reset-password.ts @@ -6,7 +6,7 @@ import ms from 'ms'; import { IsNull } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { PasswordResetRequestsRepository, UserProfilesRepository, UsersRepository } from '@/models/index.js'; +import type { PasswordResetRequestsRepository, UserProfilesRepository, UsersRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { IdService } from '@/core/IdService.js'; import type { Config } from '@/config.js'; diff --git a/packages/backend/src/server/api/endpoints/reset-password.ts b/packages/backend/src/server/api/endpoints/reset-password.ts index 41b6e5e65..1858c922a 100644 --- a/packages/backend/src/server/api/endpoints/reset-password.ts +++ b/packages/backend/src/server/api/endpoints/reset-password.ts @@ -5,7 +5,7 @@ import bcrypt from 'bcryptjs'; import { Inject, Injectable } from '@nestjs/common'; -import type { UserProfilesRepository, PasswordResetRequestsRepository } from '@/models/index.js'; +import type { UserProfilesRepository, PasswordResetRequestsRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/retention.ts b/packages/backend/src/server/api/endpoints/retention.ts index 7689c2a1d..dac6d6540 100644 --- a/packages/backend/src/server/api/endpoints/retention.ts +++ b/packages/backend/src/server/api/endpoints/retention.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { RetentionAggregationsRepository } from '@/models/index.js'; +import type { RetentionAggregationsRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/roles/list.ts b/packages/backend/src/server/api/endpoints/roles/list.ts index 225736bd7..d1de73ad3 100644 --- a/packages/backend/src/server/api/endpoints/roles/list.ts +++ b/packages/backend/src/server/api/endpoints/roles/list.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { RolesRepository } from '@/models/index.js'; +import type { RolesRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { RoleEntityService } from '@/core/entities/RoleEntityService.js'; diff --git a/packages/backend/src/server/api/endpoints/roles/notes.ts b/packages/backend/src/server/api/endpoints/roles/notes.ts index 8a5f41267..6dc35907e 100644 --- a/packages/backend/src/server/api/endpoints/roles/notes.ts +++ b/packages/backend/src/server/api/endpoints/roles/notes.ts @@ -6,7 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import * as Redis from 'ioredis'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { NotesRepository, RolesRepository } from '@/models/index.js'; +import type { NotesRepository, RolesRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { DI } from '@/di-symbols.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; diff --git a/packages/backend/src/server/api/endpoints/roles/show.ts b/packages/backend/src/server/api/endpoints/roles/show.ts index a28d65ec3..2afa0e7b7 100644 --- a/packages/backend/src/server/api/endpoints/roles/show.ts +++ b/packages/backend/src/server/api/endpoints/roles/show.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { RolesRepository } from '@/models/index.js'; +import type { RolesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; import { RoleEntityService } from '@/core/entities/RoleEntityService.js'; diff --git a/packages/backend/src/server/api/endpoints/roles/users.ts b/packages/backend/src/server/api/endpoints/roles/users.ts index 56d17211b..37aac908b 100644 --- a/packages/backend/src/server/api/endpoints/roles/users.ts +++ b/packages/backend/src/server/api/endpoints/roles/users.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Brackets } from 'typeorm'; -import type { RoleAssignmentsRepository, RolesRepository } from '@/models/index.js'; +import type { RoleAssignmentsRepository, RolesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/stats.ts b/packages/backend/src/server/api/endpoints/stats.ts index 464ba5011..05468240d 100644 --- a/packages/backend/src/server/api/endpoints/stats.ts +++ b/packages/backend/src/server/api/endpoints/stats.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { InstancesRepository, NoteReactionsRepository } from '@/models/index.js'; +import type { InstancesRepository, NoteReactionsRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; import NotesChart from '@/core/chart/charts/notes.js'; diff --git a/packages/backend/src/server/api/endpoints/sw/register.ts b/packages/backend/src/server/api/endpoints/sw/register.ts index d32b36bf9..5cfbeab73 100644 --- a/packages/backend/src/server/api/endpoints/sw/register.ts +++ b/packages/backend/src/server/api/endpoints/sw/register.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { IdService } from '@/core/IdService.js'; -import type { SwSubscriptionsRepository } from '@/models/index.js'; +import type { SwSubscriptionsRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { MetaService } from '@/core/MetaService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/sw/show-registration.ts b/packages/backend/src/server/api/endpoints/sw/show-registration.ts index 396e5824d..126299e3f 100644 --- a/packages/backend/src/server/api/endpoints/sw/show-registration.ts +++ b/packages/backend/src/server/api/endpoints/sw/show-registration.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { SwSubscriptionsRepository } from '@/models/index.js'; +import type { SwSubscriptionsRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/sw/unregister.ts b/packages/backend/src/server/api/endpoints/sw/unregister.ts index 2704a0234..f00fdd669 100644 --- a/packages/backend/src/server/api/endpoints/sw/unregister.ts +++ b/packages/backend/src/server/api/endpoints/sw/unregister.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { SwSubscriptionsRepository } from '@/models/index.js'; +import type { SwSubscriptionsRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/sw/update-registration.ts b/packages/backend/src/server/api/endpoints/sw/update-registration.ts index d91771233..a1a97df0b 100644 --- a/packages/backend/src/server/api/endpoints/sw/update-registration.ts +++ b/packages/backend/src/server/api/endpoints/sw/update-registration.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { SwSubscriptionsRepository } from '@/models/index.js'; +import type { SwSubscriptionsRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/username/available.ts b/packages/backend/src/server/api/endpoints/username/available.ts index 56e096f10..e37df62c0 100644 --- a/packages/backend/src/server/api/endpoints/username/available.ts +++ b/packages/backend/src/server/api/endpoints/username/available.ts @@ -5,9 +5,9 @@ import { IsNull } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { UsedUsernamesRepository, UsersRepository } from '@/models/index.js'; +import type { UsedUsernamesRepository, UsersRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import { localUsernameSchema } from '@/models/entities/User.js'; +import { localUsernameSchema } from '@/models/User.js'; import { DI } from '@/di-symbols.js'; import { MetaService } from '@/core/MetaService.js'; diff --git a/packages/backend/src/server/api/endpoints/users.ts b/packages/backend/src/server/api/endpoints/users.ts index daad3ce47..21c585f1a 100644 --- a/packages/backend/src/server/api/endpoints/users.ts +++ b/packages/backend/src/server/api/endpoints/users.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { UsersRepository } from '@/models/index.js'; +import type { UsersRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; diff --git a/packages/backend/src/server/api/endpoints/users/achievements.ts b/packages/backend/src/server/api/endpoints/users/achievements.ts index f1ddc98ea..e4845d57b 100644 --- a/packages/backend/src/server/api/endpoints/users/achievements.ts +++ b/packages/backend/src/server/api/endpoints/users/achievements.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { UserProfilesRepository } from '@/models/index.js'; +import type { UserProfilesRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; export const meta = { diff --git a/packages/backend/src/server/api/endpoints/users/clips.ts b/packages/backend/src/server/api/endpoints/users/clips.ts index eb752fb9d..725e07db3 100644 --- a/packages/backend/src/server/api/endpoints/users/clips.ts +++ b/packages/backend/src/server/api/endpoints/users/clips.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { ClipsRepository } from '@/models/index.js'; +import type { ClipsRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; import { ClipEntityService } from '@/core/entities/ClipEntityService.js'; diff --git a/packages/backend/src/server/api/endpoints/users/flashs.ts b/packages/backend/src/server/api/endpoints/users/flashs.ts index 4e267f900..18026dcef 100644 --- a/packages/backend/src/server/api/endpoints/users/flashs.ts +++ b/packages/backend/src/server/api/endpoints/users/flashs.ts @@ -7,7 +7,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; import { FlashEntityService } from '@/core/entities/FlashEntityService.js'; -import type { FlashsRepository } from '@/models/index.js'; +import type { FlashsRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; export const meta = { diff --git a/packages/backend/src/server/api/endpoints/users/followers.ts b/packages/backend/src/server/api/endpoints/users/followers.ts index f3b7ec66e..b22fd2ff7 100644 --- a/packages/backend/src/server/api/endpoints/users/followers.ts +++ b/packages/backend/src/server/api/endpoints/users/followers.ts @@ -5,7 +5,7 @@ import { IsNull } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { UsersRepository, FollowingsRepository, UserProfilesRepository } from '@/models/index.js'; +import type { UsersRepository, FollowingsRepository, UserProfilesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; import { FollowingEntityService } from '@/core/entities/FollowingEntityService.js'; diff --git a/packages/backend/src/server/api/endpoints/users/following.ts b/packages/backend/src/server/api/endpoints/users/following.ts index 43adcad45..03487275a 100644 --- a/packages/backend/src/server/api/endpoints/users/following.ts +++ b/packages/backend/src/server/api/endpoints/users/following.ts @@ -5,7 +5,7 @@ import { IsNull } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { UsersRepository, FollowingsRepository, UserProfilesRepository } from '@/models/index.js'; +import type { UsersRepository, FollowingsRepository, UserProfilesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; import { FollowingEntityService } from '@/core/entities/FollowingEntityService.js'; diff --git a/packages/backend/src/server/api/endpoints/users/gallery/posts.ts b/packages/backend/src/server/api/endpoints/users/gallery/posts.ts index f92788c1c..757af98e0 100644 --- a/packages/backend/src/server/api/endpoints/users/gallery/posts.ts +++ b/packages/backend/src/server/api/endpoints/users/gallery/posts.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { GalleryPostsRepository } from '@/models/index.js'; +import type { GalleryPostsRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { GalleryPostEntityService } from '@/core/entities/GalleryPostEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/users/get-frequently-replied-users.ts b/packages/backend/src/server/api/endpoints/users/get-frequently-replied-users.ts index 30f0059c0..d6fb65cec 100644 --- a/packages/backend/src/server/api/endpoints/users/get-frequently-replied-users.ts +++ b/packages/backend/src/server/api/endpoints/users/get-frequently-replied-users.ts @@ -6,7 +6,7 @@ import { Not, In, IsNull } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; import { maximum } from '@/misc/prelude/array.js'; -import type { NotesRepository } from '@/models/index.js'; +import type { NotesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/users/lists/create-from-public.ts b/packages/backend/src/server/api/endpoints/users/lists/create-from-public.ts index fd4fff0e5..fd1bb48a4 100644 --- a/packages/backend/src/server/api/endpoints/users/lists/create-from-public.ts +++ b/packages/backend/src/server/api/endpoints/users/lists/create-from-public.ts @@ -4,9 +4,9 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { UserListsRepository, UserListJoiningsRepository, BlockingsRepository } from '@/models/index.js'; +import type { UserListsRepository, UserListJoiningsRepository, BlockingsRepository } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; -import type { MiUserList } from '@/models/entities/UserList.js'; +import type { MiUserList } from '@/models/UserList.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { GetterService } from '@/server/api/GetterService.js'; import { UserListEntityService } from '@/core/entities/UserListEntityService.js'; diff --git a/packages/backend/src/server/api/endpoints/users/lists/create.ts b/packages/backend/src/server/api/endpoints/users/lists/create.ts index f8ad88c2a..60b2b3f17 100644 --- a/packages/backend/src/server/api/endpoints/users/lists/create.ts +++ b/packages/backend/src/server/api/endpoints/users/lists/create.ts @@ -4,9 +4,9 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { UserListsRepository } from '@/models/index.js'; +import type { UserListsRepository } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; -import type { MiUserList } from '@/models/entities/UserList.js'; +import type { MiUserList } from '@/models/UserList.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { UserListEntityService } from '@/core/entities/UserListEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/users/lists/delete.ts b/packages/backend/src/server/api/endpoints/users/lists/delete.ts index 46349eedf..763f5afd9 100644 --- a/packages/backend/src/server/api/endpoints/users/lists/delete.ts +++ b/packages/backend/src/server/api/endpoints/users/lists/delete.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { UserListsRepository } from '@/models/index.js'; +import type { UserListsRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; diff --git a/packages/backend/src/server/api/endpoints/users/lists/favorite.ts b/packages/backend/src/server/api/endpoints/users/lists/favorite.ts index 0c4a96560..1707afee6 100644 --- a/packages/backend/src/server/api/endpoints/users/lists/favorite.ts +++ b/packages/backend/src/server/api/endpoints/users/lists/favorite.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { UserListFavoritesRepository, UserListsRepository } from '@/models/index.js'; +import type { UserListFavoritesRepository, UserListsRepository } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; import { ApiError } from '@/server/api/error.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/users/lists/list.ts b/packages/backend/src/server/api/endpoints/users/lists/list.ts index db481fc2e..0e86dd3a6 100644 --- a/packages/backend/src/server/api/endpoints/users/lists/list.ts +++ b/packages/backend/src/server/api/endpoints/users/lists/list.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { UserListsRepository, UsersRepository } from '@/models/index.js'; +import type { UserListsRepository, UsersRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { UserListEntityService } from '@/core/entities/UserListEntityService.js'; import { ApiError } from '@/server/api/error.js'; diff --git a/packages/backend/src/server/api/endpoints/users/lists/pull.ts b/packages/backend/src/server/api/endpoints/users/lists/pull.ts index 8b63a35cf..0b0106174 100644 --- a/packages/backend/src/server/api/endpoints/users/lists/pull.ts +++ b/packages/backend/src/server/api/endpoints/users/lists/pull.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { UserListsRepository, UserListJoiningsRepository } from '@/models/index.js'; +import type { UserListsRepository, UserListJoiningsRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { GetterService } from '@/server/api/GetterService.js'; diff --git a/packages/backend/src/server/api/endpoints/users/lists/push.ts b/packages/backend/src/server/api/endpoints/users/lists/push.ts index f70c15a95..9bb1a71f5 100644 --- a/packages/backend/src/server/api/endpoints/users/lists/push.ts +++ b/packages/backend/src/server/api/endpoints/users/lists/push.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import ms from 'ms'; -import type { UserListsRepository, UserListJoiningsRepository, BlockingsRepository } from '@/models/index.js'; +import type { UserListsRepository, UserListJoiningsRepository, BlockingsRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { GetterService } from '@/server/api/GetterService.js'; import { UserListService } from '@/core/UserListService.js'; diff --git a/packages/backend/src/server/api/endpoints/users/lists/show.ts b/packages/backend/src/server/api/endpoints/users/lists/show.ts index cb86e25d9..df44870b0 100644 --- a/packages/backend/src/server/api/endpoints/users/lists/show.ts +++ b/packages/backend/src/server/api/endpoints/users/lists/show.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { UserListsRepository, UserListFavoritesRepository } from '@/models/index.js'; +import type { UserListsRepository, UserListFavoritesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { UserListEntityService } from '@/core/entities/UserListEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/users/lists/unfavorite.ts b/packages/backend/src/server/api/endpoints/users/lists/unfavorite.ts index 280a06285..23611ab8c 100644 --- a/packages/backend/src/server/api/endpoints/users/lists/unfavorite.ts +++ b/packages/backend/src/server/api/endpoints/users/lists/unfavorite.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { UserListFavoritesRepository, UserListsRepository } from '@/models/index.js'; +import type { UserListFavoritesRepository, UserListsRepository } from '@/models/_.js'; import { ApiError } from '@/server/api/error.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/users/lists/update.ts b/packages/backend/src/server/api/endpoints/users/lists/update.ts index e9a022bf3..eb6cfbaf2 100644 --- a/packages/backend/src/server/api/endpoints/users/lists/update.ts +++ b/packages/backend/src/server/api/endpoints/users/lists/update.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { UserListsRepository } from '@/models/index.js'; +import type { UserListsRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { UserListEntityService } from '@/core/entities/UserListEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/users/notes.ts b/packages/backend/src/server/api/endpoints/users/notes.ts index 5192713b9..5934baef4 100644 --- a/packages/backend/src/server/api/endpoints/users/notes.ts +++ b/packages/backend/src/server/api/endpoints/users/notes.ts @@ -5,7 +5,7 @@ import { Brackets } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { NotesRepository } from '@/models/index.js'; +import type { NotesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; diff --git a/packages/backend/src/server/api/endpoints/users/pages.ts b/packages/backend/src/server/api/endpoints/users/pages.ts index 963340e2e..cf2f274c7 100644 --- a/packages/backend/src/server/api/endpoints/users/pages.ts +++ b/packages/backend/src/server/api/endpoints/users/pages.ts @@ -7,7 +7,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; import { PageEntityService } from '@/core/entities/PageEntityService.js'; -import type { PagesRepository } from '@/models/index.js'; +import type { PagesRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; export const meta = { diff --git a/packages/backend/src/server/api/endpoints/users/reactions.ts b/packages/backend/src/server/api/endpoints/users/reactions.ts index 57f16d11c..372ab80c4 100644 --- a/packages/backend/src/server/api/endpoints/users/reactions.ts +++ b/packages/backend/src/server/api/endpoints/users/reactions.ts @@ -4,7 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { UserProfilesRepository, NoteReactionsRepository } from '@/models/index.js'; +import type { UserProfilesRepository, NoteReactionsRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; import { NoteReactionEntityService } from '@/core/entities/NoteReactionEntityService.js'; diff --git a/packages/backend/src/server/api/endpoints/users/recommendation.ts b/packages/backend/src/server/api/endpoints/users/recommendation.ts index d7794ad1a..1b30e99b1 100644 --- a/packages/backend/src/server/api/endpoints/users/recommendation.ts +++ b/packages/backend/src/server/api/endpoints/users/recommendation.ts @@ -5,7 +5,7 @@ import ms from 'ms'; import { Inject, Injectable } from '@nestjs/common'; -import type { UsersRepository, FollowingsRepository } from '@/models/index.js'; +import type { UsersRepository, FollowingsRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; diff --git a/packages/backend/src/server/api/endpoints/users/report-abuse.ts b/packages/backend/src/server/api/endpoints/users/report-abuse.ts index ea77d1796..50aa6fa09 100644 --- a/packages/backend/src/server/api/endpoints/users/report-abuse.ts +++ b/packages/backend/src/server/api/endpoints/users/report-abuse.ts @@ -5,7 +5,7 @@ import sanitizeHtml from 'sanitize-html'; import { Inject, Injectable } from '@nestjs/common'; -import type { AbuseUserReportsRepository } from '@/models/index.js'; +import type { AbuseUserReportsRepository } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; diff --git a/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts b/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts index 8ab1a122c..74408cc64 100644 --- a/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts +++ b/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts @@ -5,9 +5,9 @@ import { Brackets } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { UsersRepository, FollowingsRepository } from '@/models/index.js'; +import type { UsersRepository, FollowingsRepository } from '@/models/_.js'; import type { Config } from '@/config.js'; -import type { MiUser } from '@/models/entities/User.js'; +import type { MiUser } from '@/models/User.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/users/search.ts b/packages/backend/src/server/api/endpoints/users/search.ts index 5a738a893..aff5b9877 100644 --- a/packages/backend/src/server/api/endpoints/users/search.ts +++ b/packages/backend/src/server/api/endpoints/users/search.ts @@ -5,8 +5,8 @@ import { Brackets } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { UsersRepository, UserProfilesRepository } from '@/models/index.js'; -import type { MiUser } from '@/models/entities/User.js'; +import type { UsersRepository, UserProfilesRepository } from '@/models/_.js'; +import type { MiUser } from '@/models/User.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/users/show.ts b/packages/backend/src/server/api/endpoints/users/show.ts index 4b215ffd1..389497301 100644 --- a/packages/backend/src/server/api/endpoints/users/show.ts +++ b/packages/backend/src/server/api/endpoints/users/show.ts @@ -5,8 +5,8 @@ import { In, IsNull } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import type { UsersRepository } from '@/models/index.js'; -import type { MiUser } from '@/models/entities/User.js'; +import type { UsersRepository } from '@/models/_.js'; +import type { MiUser } from '@/models/User.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { RemoteUserResolveService } from '@/core/RemoteUserResolveService.js'; diff --git a/packages/backend/src/server/api/endpoints/users/update-memo.ts b/packages/backend/src/server/api/endpoints/users/update-memo.ts index 39d02443a..194d48805 100644 --- a/packages/backend/src/server/api/endpoints/users/update-memo.ts +++ b/packages/backend/src/server/api/endpoints/users/update-memo.ts @@ -6,7 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { IdService } from '@/core/IdService.js'; -import type { UserMemoRepository } from '@/models/index.js'; +import type { UserMemoRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { GetterService } from '@/server/api/GetterService.js'; import { ApiError } from '../../error.js'; diff --git a/packages/backend/src/server/api/stream/index.ts b/packages/backend/src/server/api/stream/Connection.ts similarity index 97% rename from packages/backend/src/server/api/stream/index.ts rename to packages/backend/src/server/api/stream/Connection.ts index 232ec5700..fd91681fc 100644 --- a/packages/backend/src/server/api/stream/index.ts +++ b/packages/backend/src/server/api/stream/Connection.ts @@ -4,14 +4,14 @@ */ import * as WebSocket from 'ws'; -import type { MiUser } from '@/models/entities/User.js'; -import type { MiAccessToken } from '@/models/entities/AccessToken.js'; +import type { MiUser } from '@/models/User.js'; +import type { MiAccessToken } from '@/models/AccessToken.js'; import type { Packed } from '@/misc/json-schema.js'; import type { NoteReadService } from '@/core/NoteReadService.js'; import type { NotificationService } from '@/core/NotificationService.js'; import { bindThis } from '@/decorators.js'; import { CacheService } from '@/core/CacheService.js'; -import { MiUserProfile } from '@/models/index.js'; +import { MiUserProfile } from '@/models/_.js'; import type { ChannelsService } from './ChannelsService.js'; import type { EventEmitter } from 'events'; import type Channel from './channel.js'; diff --git a/packages/backend/src/server/api/stream/channel.ts b/packages/backend/src/server/api/stream/channel.ts index 93c673838..ad32d08fe 100644 --- a/packages/backend/src/server/api/stream/channel.ts +++ b/packages/backend/src/server/api/stream/channel.ts @@ -4,7 +4,7 @@ */ import { bindThis } from '@/decorators.js'; -import type Connection from './index.js'; +import type Connection from './Connection.js'; /** * Stream channel diff --git a/packages/backend/src/server/api/stream/channels/user-list.ts b/packages/backend/src/server/api/stream/channels/user-list.ts index f7001e41c..8bbba0b6d 100644 --- a/packages/backend/src/server/api/stream/channels/user-list.ts +++ b/packages/backend/src/server/api/stream/channels/user-list.ts @@ -4,8 +4,8 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import type { UserListJoiningsRepository, UserListsRepository } from '@/models/index.js'; -import type { MiUser } from '@/models/entities/User.js'; +import type { UserListJoiningsRepository, UserListsRepository } from '@/models/_.js'; +import type { MiUser } from '@/models/User.js'; import { isUserRelated } from '@/misc/is-user-related.js'; import type { Packed } from '@/misc/json-schema.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; diff --git a/packages/backend/src/server/api/stream/types.ts b/packages/backend/src/server/api/stream/types.ts index 531c00bdf..90e0a61f2 100644 --- a/packages/backend/src/server/api/stream/types.ts +++ b/packages/backend/src/server/api/stream/types.ts @@ -3,21 +3,21 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import type { MiChannel } from '@/models/entities/Channel.js'; -import type { MiUser } from '@/models/entities/User.js'; -import type { MiUserProfile } from '@/models/entities/UserProfile.js'; -import type { MiNote } from '@/models/entities/Note.js'; -import type { MiAntenna } from '@/models/entities/Antenna.js'; -import type { MiDriveFile } from '@/models/entities/DriveFile.js'; -import type { MiDriveFolder } from '@/models/entities/DriveFolder.js'; -import type { MiUserList } from '@/models/entities/UserList.js'; -import type { MiAbuseUserReport } from '@/models/entities/AbuseUserReport.js'; -import type { MiSignin } from '@/models/entities/Signin.js'; -import type { MiPage } from '@/models/entities/Page.js'; +import type { MiChannel } from '@/models/Channel.js'; +import type { MiUser } from '@/models/User.js'; +import type { MiUserProfile } from '@/models/UserProfile.js'; +import type { MiNote } from '@/models/Note.js'; +import type { MiAntenna } from '@/models/Antenna.js'; +import type { MiDriveFile } from '@/models/DriveFile.js'; +import type { MiDriveFolder } from '@/models/DriveFolder.js'; +import type { MiUserList } from '@/models/UserList.js'; +import type { MiAbuseUserReport } from '@/models/AbuseUserReport.js'; +import type { MiSignin } from '@/models/Signin.js'; +import type { MiPage } from '@/models/Page.js'; import type { Packed } from '@/misc/json-schema.js'; -import type { MiWebhook } from '@/models/entities/Webhook.js'; -import type { MiMeta } from '@/models/entities/Meta.js'; -import { MiRole, MiRoleAssignment } from '@/models/index.js'; +import type { MiWebhook } from '@/models/Webhook.js'; +import type { MiMeta } from '@/models/Meta.js'; +import { MiRole, MiRoleAssignment } from '@/models/_.js'; import type Emitter from 'strict-event-emitter-types'; import type { EventEmitter } from 'events'; diff --git a/packages/backend/src/server/oauth/OAuth2ProviderService.ts b/packages/backend/src/server/oauth/OAuth2ProviderService.ts index 6ad8da0ce..c3a78561c 100644 --- a/packages/backend/src/server/oauth/OAuth2ProviderService.ts +++ b/packages/backend/src/server/oauth/OAuth2ProviderService.ts @@ -23,10 +23,10 @@ import { kinds } from '@/misc/api-permissions.js'; import type { Config } from '@/config.js'; import { DI } from '@/di-symbols.js'; import { bindThis } from '@/decorators.js'; -import type { AccessTokensRepository, UsersRepository } from '@/models/index.js'; +import type { AccessTokensRepository, UsersRepository } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; import { CacheService } from '@/core/CacheService.js'; -import type { MiLocalUser } from '@/models/entities/User.js'; +import type { MiLocalUser } from '@/models/User.js'; import { MemoryKVCache } from '@/misc/cache.js'; import { LoggerService } from '@/core/LoggerService.js'; import Logger from '@/logger.js'; @@ -125,7 +125,7 @@ async function discoverClientInformation(logger: Logger, httpRequestService: Htt let name = id; if (text) { const microformats = mf2(text, { baseUrl: res.url }); - const nameProperty = microformats.items.find(item => item.type?.includes('h-app') && item.properties.url?.includes(id))?.properties.name[0]; + const nameProperty = microformats.items.find(item => item.type?.includes('h-app') && item.properties.url.includes(id))?.properties.name[0]; if (typeof nameProperty === 'string') { name = nameProperty; } diff --git a/packages/backend/src/server/web/ClientServerService.ts b/packages/backend/src/server/web/ClientServerService.ts index 75f305be5..1faff2420 100644 --- a/packages/backend/src/server/web/ClientServerService.ts +++ b/packages/backend/src/server/web/ClientServerService.ts @@ -31,7 +31,7 @@ import { PageEntityService } from '@/core/entities/PageEntityService.js'; import { GalleryPostEntityService } from '@/core/entities/GalleryPostEntityService.js'; import { ClipEntityService } from '@/core/entities/ClipEntityService.js'; import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js'; -import type { ChannelsRepository, ClipsRepository, FlashsRepository, GalleryPostsRepository, MiMeta, NotesRepository, PagesRepository, UserProfilesRepository, UsersRepository } from '@/models/index.js'; +import type { ChannelsRepository, ClipsRepository, FlashsRepository, GalleryPostsRepository, MiMeta, NotesRepository, PagesRepository, UserProfilesRepository, UsersRepository } from '@/models/_.js'; import type Logger from '@/logger.js'; import { deepClone } from '@/misc/clone.js'; import { bindThis } from '@/decorators.js'; @@ -51,45 +51,6 @@ const assets = `${_dirname}/../../../../../built/_frontend_dist_/`; const swAssets = `${_dirname}/../../../../../built/_sw_dist_/`; const viteOut = `${_dirname}/../../../../../built/_vite_/`; -const manifest = { - 'short_name': 'Misskey', - 'name': 'Misskey', - 'start_url': '/', - 'display': 'standalone', - 'background_color': '#313a42', - 'theme_color': '#86b300', - 'icons': [ - { - 'src': '/static-assets/icons/192.png', - 'sizes': '192x192', - 'type': 'image/png', - 'purpose': 'maskable', - }, - { - 'src': '/static-assets/icons/512.png', - 'sizes': '512x512', - 'type': 'image/png', - 'purpose': 'maskable', - }, - { - 'src': '/static-assets/splash.png', - 'sizes': '300x300', - 'type': 'image/png', - 'purpose': 'any', - }, - ], - 'share_target': { - 'action': '/share/', - 'method': 'GET', - 'enctype': 'application/x-www-form-urlencoded', - 'params': { - 'title': 'title', - 'text': 'text', - 'url': 'url', - }, - }, -}; - @Injectable() export class ClientServerService { private logger: Logger; @@ -148,16 +109,60 @@ export class ClientServerService { @bindThis private async manifestHandler(reply: FastifyReply) { - const res = deepClone(manifest); - const instance = await this.metaService.fetch(true); - res.short_name = instance.name ?? 'Misskey'; - res.name = instance.name ?? 'Misskey'; - if (instance.themeColor) res.theme_color = instance.themeColor; + let manifest = { + // 空文字列の場合右辺を使いたいため + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + 'short_name': instance.shortName || instance.name || this.config.host, + // 空文字列の場合右辺を使いたいため + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + 'name': instance.name || this.config.host, + 'start_url': '/', + 'display': 'standalone', + 'background_color': '#313a42', + // 空文字列の場合右辺を使いたいため + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + 'theme_color': instance.themeColor || '#86b300', + 'icons': [{ + // 空文字列の場合右辺を使いたいため + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + 'src': instance.app192IconUrl || '/static-assets/icons/192.png', + 'sizes': '192x192', + 'type': 'image/png', + 'purpose': 'maskable', + }, { + // 空文字列の場合右辺を使いたいため + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + 'src': instance.app512IconUrl || '/static-assets/icons/512.png', + 'sizes': '512x512', + 'type': 'image/png', + 'purpose': 'maskable', + }, { + 'src': '/static-assets/splash.png', + 'sizes': '300x300', + 'type': 'image/png', + 'purpose': 'any', + }], + 'share_target': { + 'action': '/share/', + 'method': 'GET', + 'enctype': 'application/x-www-form-urlencoded', + 'params': { + 'title': 'title', + 'text': 'text', + 'url': 'url', + }, + }, + }; + + manifest = { + ...manifest, + ...JSON.parse(instance.manifestJsonOverride === '' ? '{}' : instance.manifestJsonOverride), + }; reply.header('Cache-Control', 'max-age=300'); - return (res); + return (manifest); } @bindThis @@ -165,6 +170,7 @@ export class ClientServerService { return { instanceName: meta.name ?? 'Misskey', icon: meta.iconUrl, + appleTouchIcon: meta.app512IconUrl, themeColor: meta.themeColor, serverErrorImageUrl: meta.serverErrorImageUrl ?? 'https://xn--931a.moe/assets/error.jpg', infoImageUrl: meta.infoImageUrl ?? 'https://xn--931a.moe/assets/info.jpg', diff --git a/packages/backend/src/server/web/FeedService.ts b/packages/backend/src/server/web/FeedService.ts index 27e843183..78551e800 100644 --- a/packages/backend/src/server/web/FeedService.ts +++ b/packages/backend/src/server/web/FeedService.ts @@ -7,9 +7,9 @@ import { Inject, Injectable } from '@nestjs/common'; import { In, IsNull } from 'typeorm'; import { Feed } from 'feed'; import { DI } from '@/di-symbols.js'; -import type { DriveFilesRepository, NotesRepository, UserProfilesRepository } from '@/models/index.js'; +import type { DriveFilesRepository, NotesRepository, UserProfilesRepository } from '@/models/_.js'; import type { Config } from '@/config.js'; -import type { MiUser } from '@/models/entities/User.js'; +import type { MiUser } from '@/models/User.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js'; import { bindThis } from '@/decorators.js'; diff --git a/packages/backend/src/server/web/views/base.pug b/packages/backend/src/server/web/views/base.pug index c2053517d..71bcf9462 100644 --- a/packages/backend/src/server/web/views/base.pug +++ b/packages/backend/src/server/web/views/base.pug @@ -28,14 +28,14 @@ html meta(property='og:site_name' content= instanceName || 'Misskey') meta(name='viewport' content='width=device-width, initial-scale=1') link(rel='icon' href= icon || '/favicon.ico') - link(rel='apple-touch-icon' href= icon || '/apple-touch-icon.png') + link(rel='apple-touch-icon' href= appleTouchIcon || '/apple-touch-icon.png') link(rel='manifest' href='/manifest.json') link(rel='search' type='application/opensearchdescription+xml' title=(title || "Misskey") href=`${url}/opensearch.xml`) link(rel='prefetch' href=serverErrorImageUrl) link(rel='prefetch' href=infoImageUrl) link(rel='prefetch' href=notFoundImageUrl) //- https://github.com/misskey-dev/misskey/issues/9842 - link(rel='stylesheet' href='/assets/tabler-icons/tabler-icons.min.css?v2.32.0') + link(rel='stylesheet' href='/assets/tabler-icons/tabler-icons.min.css?v2.35.0') link(rel='modulepreload' href=`/vite/${clientEntry.file}`) if !config.clientManifestExists diff --git a/packages/backend/src/types.ts b/packages/backend/src/types.ts index 024ba01e3..35ea710f9 100644 --- a/packages/backend/src/types.ts +++ b/packages/backend/src/types.ts @@ -3,7 +3,22 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -export const notificationTypes = ['follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'achievementEarned', 'app', 'test'] as const; +/** + * note - 通知オンにしているユーザーが投稿した + * follow - フォローされた + * mention - 投稿で自分が言及された + * reply - 投稿に返信された + * renote - 投稿がRenoteされた + * quote - 投稿が引用Renoteされた + * reaction - 投稿にリアクションされた + * pollEnded - 自分のアンケートもしくは自分が投票したアンケートが終了した + * receiveFollowRequest - フォローリクエストされた + * followRequestAccepted - 自分の送ったフォローリクエストが承認された + * achievementEarned - 実績を獲得 + * app - アプリ通知 + * test - テスト通知(サーバー側) + */ +export const notificationTypes = ['note', 'follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'achievementEarned', 'app', 'test'] as const; export const obsoleteNotificationTypes = ['pollVote', 'groupInvited'] as const; export const noteVisibilities = ['public', 'home', 'followers', 'specified'] as const; @@ -11,3 +26,176 @@ export const noteVisibilities = ['public', 'home', 'followers', 'specified'] as export const mutedNoteReasons = ['word', 'manual', 'spam', 'other'] as const; export const ffVisibility = ['public', 'followers', 'private'] as const; + +export const moderationLogTypes = [ + 'updateServerSettings', + 'suspend', + 'unsuspend', + 'updateUserNote', + 'addCustomEmoji', + 'updateCustomEmoji', + 'deleteCustomEmoji', + 'assignRole', + 'unassignRole', + 'createRole', + 'updateRole', + 'deleteRole', + 'clearQueue', + 'promoteQueue', + 'deleteDriveFile', + 'deleteNote', + 'createGlobalAnnouncement', + 'createUserAnnouncement', + 'updateGlobalAnnouncement', + 'updateUserAnnouncement', + 'deleteGlobalAnnouncement', + 'deleteUserAnnouncement', + 'resetPassword', + 'suspendRemoteInstance', + 'unsuspendRemoteInstance', + 'markSensitiveDriveFile', + 'unmarkSensitiveDriveFile', + 'resolveAbuseReport', +] as const; + +export type ModerationLogPayloads = { + updateServerSettings: { + before: any | null; + after: any | null; + }; + suspend: { + userId: string; + userUsername: string; + userHost: string | null; + }; + unsuspend: { + userId: string; + userUsername: string; + userHost: string | null; + }; + updateUserNote: { + userId: string; + userUsername: string; + userHost: string | null; + before: string | null; + after: string | null; + }; + addCustomEmoji: { + emojiId: string; + emoji: any; + }; + updateCustomEmoji: { + emojiId: string; + before: any; + after: any; + }; + deleteCustomEmoji: { + emojiId: string; + emoji: any; + }; + assignRole: { + userId: string; + userUsername: string; + userHost: string | null; + roleId: string; + roleName: string; + expiresAt: string | null; + }; + unassignRole: { + userId: string; + userUsername: string; + userHost: string | null; + roleId: string; + roleName: string; + }; + createRole: { + roleId: string; + role: any; + }; + updateRole: { + roleId: string; + before: any; + after: any; + }; + deleteRole: { + roleId: string; + role: any; + }; + clearQueue: Record; + promoteQueue: Record; + deleteDriveFile: { + fileId: string; + fileUserId: string | null; + fileUserUsername: string | null; + fileUserHost: string | null; + }; + deleteNote: { + noteId: string; + noteUserId: string; + noteUserUsername: string; + noteUserHost: string | null; + note: any; + }; + createGlobalAnnouncement: { + announcementId: string; + announcement: any; + }; + createUserAnnouncement: { + announcementId: string; + announcement: any; + userId: string; + userUsername: string; + userHost: string | null; + }; + updateGlobalAnnouncement: { + announcementId: string; + before: any; + after: any; + }; + updateUserAnnouncement: { + announcementId: string; + before: any; + after: any; + userId: string; + userUsername: string; + userHost: string | null; + }; + deleteGlobalAnnouncement: { + announcementId: string; + announcement: any; + }; + deleteUserAnnouncement: { + announcementId: string; + announcement: any; + }; + resetPassword: { + userId: string; + userUsername: string; + userHost: string | null; + }; + suspendRemoteInstance: { + id: string; + host: string; + }; + unsuspendRemoteInstance: { + id: string; + host: string; + }; + markSensitiveDriveFile: { + fileId: string; + fileUserId: string | null; + fileUserUsername: string | null; + fileUserHost: string | null; + }; + unmarkSensitiveDriveFile: { + fileId: string; + fileUserId: string | null; + fileUserUsername: string | null; + fileUserHost: string | null; + }; + resolveAbuseReport: { + reportId: string; + report: any; + forwarded: boolean; + }; +}; diff --git a/packages/backend/test/e2e/2fa.ts b/packages/backend/test/e2e/2fa.ts index 80d2e9d35..ed967d262 100644 --- a/packages/backend/test/e2e/2fa.ts +++ b/packages/backend/test/e2e/2fa.ts @@ -60,10 +60,12 @@ describe('2要素認証', () => { }; const keyDoneParam = (param: { + token: string, keyName: string, credentialId: Buffer, creationOptions: PublicKeyCredentialCreationOptionsJSON, }): { + token: string, password: string, name: string, credential: RegistrationResponseJSON, @@ -94,6 +96,7 @@ describe('2要素認証', () => { return { password, + token: param.token, name: param.keyName, credential: { id: param.credentialId.toString('base64url'), @@ -218,6 +221,12 @@ describe('2要素認証', () => { }); assert.strictEqual(signinResponse.status, 200); assert.notEqual(signinResponse.body.i, undefined); + + // 後片付け + await api('/i/2fa/unregister', { + password, + token: otpToken(registerResponse.body.secret), + }, alice); }); test('が設定でき、セキュリティキーでログインできる。', async () => { @@ -233,6 +242,7 @@ describe('2要素認証', () => { const registerKeyResponse = await api('/i/2fa/register-key', { password, + token: otpToken(registerResponse.body.secret), }, alice); assert.strictEqual(registerKeyResponse.status, 200); assert.notEqual(registerKeyResponse.body.rp, undefined); @@ -241,6 +251,7 @@ describe('2要素認証', () => { const keyName = 'example-key'; const credentialId = crypto.randomBytes(0x41); const keyDoneResponse = await api('/i/2fa/key-done', keyDoneParam({ + token: otpToken(registerResponse.body.secret), keyName, credentialId, creationOptions: registerKeyResponse.body, @@ -271,6 +282,12 @@ describe('2要素認証', () => { })); assert.strictEqual(signinResponse2.status, 200); assert.notEqual(signinResponse2.body.i, undefined); + + // 後片付け + await api('/i/2fa/unregister', { + password, + token: otpToken(registerResponse.body.secret), + }, alice); }); test('が設定でき、セキュリティキーでパスワードレスログインできる。', async () => { @@ -285,6 +302,7 @@ describe('2要素認証', () => { assert.strictEqual(doneResponse.status, 200); const registerKeyResponse = await api('/i/2fa/register-key', { + token: otpToken(registerResponse.body.secret), password, }, alice); assert.strictEqual(registerKeyResponse.status, 200); @@ -292,6 +310,7 @@ describe('2要素認証', () => { const keyName = 'example-key'; const credentialId = crypto.randomBytes(0x41); const keyDoneResponse = await api('/i/2fa/key-done', keyDoneParam({ + token: otpToken(registerResponse.body.secret), keyName, credentialId, creationOptions: registerKeyResponse.body, @@ -326,6 +345,12 @@ describe('2要素認証', () => { }); assert.strictEqual(signinResponse2.status, 200); assert.notEqual(signinResponse2.body.i, undefined); + + // 後片付け + await api('/i/2fa/unregister', { + password, + token: otpToken(registerResponse.body.secret), + }, alice); }); test('が設定でき、設定したセキュリティキーの名前を変更できる。', async () => { @@ -340,6 +365,7 @@ describe('2要素認証', () => { assert.strictEqual(doneResponse.status, 200); const registerKeyResponse = await api('/i/2fa/register-key', { + token: otpToken(registerResponse.body.secret), password, }, alice); assert.strictEqual(registerKeyResponse.status, 200); @@ -347,6 +373,7 @@ describe('2要素認証', () => { const keyName = 'example-key'; const credentialId = crypto.randomBytes(0x41); const keyDoneResponse = await api('/i/2fa/key-done', keyDoneParam({ + token: otpToken(registerResponse.body.secret), keyName, credentialId, creationOptions: registerKeyResponse.body, @@ -367,6 +394,12 @@ describe('2要素認証', () => { assert.strictEqual(securityKeys.length, 1); assert.strictEqual(securityKeys[0].name, renamedKey); assert.notEqual(securityKeys[0].lastUsed, undefined); + + // 後片付け + await api('/i/2fa/unregister', { + password, + token: otpToken(registerResponse.body.secret), + }, alice); }); test('が設定でき、設定したセキュリティキーを削除できる。', async () => { @@ -381,6 +414,7 @@ describe('2要素認証', () => { assert.strictEqual(doneResponse.status, 200); const registerKeyResponse = await api('/i/2fa/register-key', { + token: otpToken(registerResponse.body.secret), password, }, alice); assert.strictEqual(registerKeyResponse.status, 200); @@ -388,6 +422,7 @@ describe('2要素認証', () => { const keyName = 'example-key'; const credentialId = crypto.randomBytes(0x41); const keyDoneResponse = await api('/i/2fa/key-done', keyDoneParam({ + token: otpToken(registerResponse.body.secret), keyName, credentialId, creationOptions: registerKeyResponse.body, @@ -400,6 +435,7 @@ describe('2要素認証', () => { assert.strictEqual(iResponse.status, 200); for (const key of iResponse.body.securityKeysList) { const removeKeyResponse = await api('/i/2fa/remove-key', { + token: otpToken(registerResponse.body.secret), password, credentialId: key.id, }, alice); @@ -418,6 +454,12 @@ describe('2要素認証', () => { }); assert.strictEqual(signinResponse.status, 200); assert.notEqual(signinResponse.body.i, undefined); + + // 後片付け + await api('/i/2fa/unregister', { + password, + token: otpToken(registerResponse.body.secret), + }, alice); }); test('が設定でき、設定解除できる。(パスワードのみでログインできる。)', async () => { @@ -438,6 +480,7 @@ describe('2要素認証', () => { assert.strictEqual(usersShowResponse.body.twoFactorEnabled, true); const unregisterResponse = await api('/i/2fa/unregister', { + token: otpToken(registerResponse.body.secret), password, }, alice); assert.strictEqual(unregisterResponse.status, 204); @@ -447,5 +490,11 @@ describe('2要素認証', () => { }); assert.strictEqual(signinResponse.status, 200); assert.notEqual(signinResponse.body.i, undefined); + + // 後片付け + await api('/i/2fa/unregister', { + password, + token: otpToken(registerResponse.body.secret), + }, alice); }); }); diff --git a/packages/backend/test/e2e/clips.ts b/packages/backend/test/e2e/clips.ts index 833b48f73..dfdc044ca 100644 --- a/packages/backend/test/e2e/clips.ts +++ b/packages/backend/test/e2e/clips.ts @@ -721,7 +721,7 @@ describe('クリップ', () => { await addNote({ clipId: aliceClip.id, noteId: aliceNote.id }); const res = await show({ clipId: aliceClip.id }); assert.strictEqual(res.lastClippedAt, new Date(res.lastClippedAt ?? '').toISOString()); - assert.deepStrictEqual(await notes({ clipId: aliceClip.id }), [aliceNote]); + assert.deepStrictEqual((await notes({ clipId: aliceClip.id })).map(x => x.id), [aliceNote.id]); // 他人の非公開ノートも突っ込める await addNote({ clipId: aliceClip.id, noteId: bobHomeNote.id }); @@ -861,8 +861,8 @@ describe('クリップ', () => { bobNote, bobHomeNote, ]; assert.deepStrictEqual( - res.sort(compareBy(s => s.id)), - expects.sort(compareBy(s => s.id))); + res.sort(compareBy(s => s.id)).map(x => x.id), + expects.sort(compareBy(s => s.id)).map(x => x.id)); }); test('を始端IDとlimitで取得できる。', async () => { @@ -881,8 +881,8 @@ describe('クリップ', () => { // Promise.allで返ってくる配列はID順で並んでないのでソートして厳密比較 const expects = [noteList[3], noteList[4], noteList[5]]; assert.deepStrictEqual( - res.sort(compareBy(s => s.id)), - expects.sort(compareBy(s => s.id))); + res.sort(compareBy(s => s.id)).map(x => x.id), + expects.sort(compareBy(s => s.id)).map(x => x.id)); }); test('をID範囲指定で取得できる。', async () => { @@ -901,8 +901,8 @@ describe('クリップ', () => { // Promise.allで返ってくる配列はID順で並んでないのでソートして厳密比較 const expects = [noteList[2], noteList[3]]; assert.deepStrictEqual( - res.sort(compareBy(s => s.id)), - expects.sort(compareBy(s => s.id))); + res.sort(compareBy(s => s.id)).map(x => x.id), + expects.sort(compareBy(s => s.id)).map(x => x.id)); }); test.todo('Remoteのノートもクリップできる。どうテストしよう?'); @@ -911,7 +911,7 @@ describe('クリップ', () => { const bobClip = await create({ isPublic: true }, { user: bob } ); await addNote({ clipId: bobClip.id, noteId: aliceNote.id }, { user: bob }); const res = await notes({ clipId: bobClip.id }); - assert.deepStrictEqual(res, [aliceNote]); + assert.deepStrictEqual(res.map(x => x.id), [aliceNote.id]); }); test('はPublicなクリップなら認証なしでも取得できる。(非公開ノートはhideされて返ってくる)', async () => { @@ -928,8 +928,8 @@ describe('クリップ', () => { hiddenNote(aliceFollowersNote), hiddenNote(aliceSpecifiedNote), ]; assert.deepStrictEqual( - res.sort(compareBy(s => s.id)), - expects.sort(compareBy(s => s.id))); + res.sort(compareBy(s => s.id)).map(x => x.id), + expects.sort(compareBy(s => s.id)).map(x => x.id)); }); test.todo('ブロック、ミュートされたユーザーからの設定&取得etc.'); diff --git a/packages/backend/test/e2e/endpoints.ts b/packages/backend/test/e2e/endpoints.ts index 6e9178641..2ef3434bc 100644 --- a/packages/backend/test/e2e/endpoints.ts +++ b/packages/backend/test/e2e/endpoints.ts @@ -9,7 +9,7 @@ import * as assert from 'assert'; // node-fetch only supports it's own Blob yet // https://github.com/node-fetch/node-fetch/pull/1664 import { Blob } from 'node-fetch'; -import { MiUser } from '@/models/index.js'; +import { MiUser } from '@/models/_.js'; import { startServer, signup, post, api, uploadFile, simpleGet, initTestDb } from '../utils.js'; import type { INestApplicationContext } from '@nestjs/common'; import type * as misskey from 'misskey-js'; diff --git a/packages/backend/test/e2e/move.ts b/packages/backend/test/e2e/move.ts index 24c9473ae..3f158f9f1 100644 --- a/packages/backend/test/e2e/move.ts +++ b/packages/backend/test/e2e/move.ts @@ -7,7 +7,7 @@ process.env.NODE_ENV = 'test'; import * as assert from 'assert'; import { loadConfig } from '@/config.js'; -import { MiUser, UsersRepository } from '@/models/index.js'; +import { MiUser, UsersRepository } from '@/models/_.js'; import { jobQueue } from '@/boot/common.js'; import { secureRndstr } from '@/misc/secure-rndstr.js'; import { uploadFile, signup, startServer, initTestDb, api, sleep, successfulApiCall } from '../utils.js'; diff --git a/packages/backend/test/e2e/note.ts b/packages/backend/test/e2e/note.ts index 20208c457..961df99cc 100644 --- a/packages/backend/test/e2e/note.ts +++ b/packages/backend/test/e2e/note.ts @@ -6,7 +6,7 @@ process.env.NODE_ENV = 'test'; import * as assert from 'assert'; -import { MiNote } from '@/models/entities/Note.js'; +import { MiNote } from '@/models/Note.js'; import { MAX_NOTE_TEXT_LENGTH } from '@/const.js'; import { signup, post, uploadUrl, startServer, initTestDb, api, uploadFile } from '../utils.js'; import type { INestApplicationContext } from '@nestjs/common'; diff --git a/packages/backend/test/e2e/streaming.ts b/packages/backend/test/e2e/streaming.ts index 0dd97069a..77de14488 100644 --- a/packages/backend/test/e2e/streaming.ts +++ b/packages/backend/test/e2e/streaming.ts @@ -6,7 +6,7 @@ process.env.NODE_ENV = 'test'; import * as assert from 'assert'; -import { MiFollowing } from '@/models/entities/Following.js'; +import { MiFollowing } from '@/models/Following.js'; import { connectStream, signup, api, post, startServer, initTestDb, waitFire } from '../utils.js'; import type { INestApplicationContext } from '@nestjs/common'; import type * as misskey from 'misskey-js'; diff --git a/packages/backend/test/e2e/users.ts b/packages/backend/test/e2e/users.ts index 2c396813f..0b3f20026 100644 --- a/packages/backend/test/e2e/users.ts +++ b/packages/backend/test/e2e/users.ts @@ -102,6 +102,7 @@ describe('ユーザー', () => { birthday: user.birthday, lang: user.lang, fields: user.fields, + verifiedLinks: user.verifiedLinks, followersCount: user.followersCount, followingCount: user.followingCount, notesCount: user.notesCount, @@ -131,6 +132,7 @@ describe('ユーザー', () => { isBlocked: user.isBlocked ?? false, isMuted: user.isMuted ?? false, isRenoteMuted: user.isRenoteMuted ?? false, + notify: user.notify ?? 'none', }); }; @@ -369,6 +371,7 @@ describe('ユーザー', () => { assert.strictEqual(response.birthday, null); assert.strictEqual(response.lang, null); assert.deepStrictEqual(response.fields, []); + assert.deepStrictEqual(response.verifiedLinks, []); assert.strictEqual(response.followersCount, 0); assert.strictEqual(response.followingCount, 0); assert.strictEqual(response.notesCount, 0); @@ -492,7 +495,7 @@ describe('ユーザー', () => { { parameters: (): object => ({ mutedWords: [] }) }, { parameters: (): object => ({ mutedInstances: ['xxxx.xxxxx'] }) }, { parameters: (): object => ({ mutedInstances: [] }) }, - { parameters: (): object => ({ mutingNotificationTypes: ['follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'achievementEarned', 'app'] }) }, + { parameters: (): object => ({ mutingNotificationTypes: ['note', 'follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'achievementEarned', 'app'] }) }, { parameters: (): object => ({ mutingNotificationTypes: [] }) }, { parameters: (): object => ({ emailNotificationTypes: ['mention', 'reply', 'quote', 'follow', 'receiveFollowRequest'] }) }, { parameters: (): object => ({ emailNotificationTypes: [] }) }, diff --git a/packages/backend/test/misc/mock-resolver.ts b/packages/backend/test/misc/mock-resolver.ts index 257a9c859..7cba7a2aa 100644 --- a/packages/backend/test/misc/mock-resolver.ts +++ b/packages/backend/test/misc/mock-resolver.ts @@ -15,7 +15,7 @@ import type { LoggerService } from '@/core/LoggerService.js'; import type { MetaService } from '@/core/MetaService.js'; import type { UtilityService } from '@/core/UtilityService.js'; import { bindThis } from '@/decorators.js'; -import type { NoteReactionsRepository, NotesRepository, PollsRepository, UsersRepository } from '@/models/index.js'; +import type { NoteReactionsRepository, NotesRepository, PollsRepository, UsersRepository, FollowRequestsRepository } from '@/models/_.js'; type MockResponse = { type: string; @@ -33,6 +33,7 @@ export class MockResolver extends Resolver { {} as NotesRepository, {} as PollsRepository, {} as NoteReactionsRepository, + {} as FollowRequestsRepository, {} as UtilityService, {} as InstanceActorService, {} as MetaService, diff --git a/packages/backend/test/unit/AnnouncementService.ts b/packages/backend/test/unit/AnnouncementService.ts index d11808a4d..8f61d91ba 100644 --- a/packages/backend/test/unit/AnnouncementService.ts +++ b/packages/backend/test/unit/AnnouncementService.ts @@ -10,12 +10,13 @@ import { ModuleMocker } from 'jest-mock'; import { Test } from '@nestjs/testing'; import { GlobalModule } from '@/GlobalModule.js'; import { AnnouncementService } from '@/core/AnnouncementService.js'; -import type { MiAnnouncement, AnnouncementsRepository, AnnouncementReadsRepository, UsersRepository, MiUser } from '@/models/index.js'; +import type { MiAnnouncement, AnnouncementsRepository, AnnouncementReadsRepository, UsersRepository, MiUser } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { genAidx } from '@/misc/id/aidx.js'; import { CacheService } from '@/core/CacheService.js'; import { IdService } from '@/core/IdService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; +import { ModerationLogService } from '@/core/ModerationLogService.js'; import { secureRndstr } from '@/misc/secure-rndstr.js'; import type { TestingModule } from '@nestjs/testing'; import type { MockFunctionMetadata } from 'jest-mock'; @@ -29,6 +30,7 @@ describe('AnnouncementService', () => { let announcementsRepository: AnnouncementsRepository; let announcementReadsRepository: AnnouncementReadsRepository; let globalEventService: jest.Mocked; + let moderationLogService: jest.Mocked; function createUser(data: Partial = {}) { const un = secureRndstr(16); @@ -71,8 +73,11 @@ describe('AnnouncementService', () => { publishMainStream: jest.fn(), publishBroadcastStream: jest.fn(), }; - } - if (typeof token === 'function') { + } else if (token === ModerationLogService) { + return { + log: jest.fn(), + }; + } else if (typeof token === 'function') { const mockMetadata = moduleMocker.getMetadata(token) as MockFunctionMetadata; const Mock = moduleMocker.generateFromMetadata(mockMetadata); return new Mock(); @@ -87,6 +92,7 @@ describe('AnnouncementService', () => { announcementsRepository = app.get(DI.announcementsRepository); announcementReadsRepository = app.get(DI.announcementReadsRepository); globalEventService = app.get(GlobalEventService) as jest.Mocked; + moderationLogService = app.get(ModerationLogService) as jest.Mocked; }); afterEach(async () => { @@ -155,10 +161,11 @@ describe('AnnouncementService', () => { describe('create', () => { test('通常', async () => { + const me = await createUser(); const result = await announcementService.create({ title: 'Title', text: 'Text', - }); + }, me); expect(result.raw.title).toBe('Title'); expect(result.packed.title).toBe('Title'); @@ -166,15 +173,17 @@ describe('AnnouncementService', () => { expect(globalEventService.publishBroadcastStream).toHaveBeenCalled(); expect(globalEventService.publishBroadcastStream.mock.lastCall![0]).toBe('announcementCreated'); expect((globalEventService.publishBroadcastStream.mock.lastCall![1] as any).announcement).toBe(result.packed); + expect(moderationLogService.log).toHaveBeenCalled(); }); test('ユーザー指定', async () => { + const me = await createUser(); const user = await createUser(); const result = await announcementService.create({ title: 'Title', text: 'Text', userId: user.id, - }); + }, me); expect(result.raw.title).toBe('Title'); expect(result.packed.title).toBe('Title'); @@ -184,6 +193,7 @@ describe('AnnouncementService', () => { expect(globalEventService.publishMainStream.mock.lastCall![0]).toBe(user.id); expect(globalEventService.publishMainStream.mock.lastCall![1]).toBe('announcementCreated'); expect((globalEventService.publishMainStream.mock.lastCall![2] as any).announcement).toBe(result.packed); + expect(moderationLogService.log).toHaveBeenCalled(); }); }); diff --git a/packages/backend/test/unit/MetaService.ts b/packages/backend/test/unit/MetaService.ts index 2b6e52914..ab30f4828 100644 --- a/packages/backend/test/unit/MetaService.ts +++ b/packages/backend/test/unit/MetaService.ts @@ -9,7 +9,7 @@ import { jest } from '@jest/globals'; import { ModuleMocker } from 'jest-mock'; import { Test } from '@nestjs/testing'; import { GlobalModule } from '@/GlobalModule.js'; -import type { MetasRepository } from '@/models/index.js'; +import type { MetasRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { MetaService } from '@/core/MetaService.js'; import { CoreModule } from '@/core/CoreModule.js'; diff --git a/packages/backend/test/unit/RelayService.ts b/packages/backend/test/unit/RelayService.ts index ae20acd06..f780a2538 100644 --- a/packages/backend/test/unit/RelayService.ts +++ b/packages/backend/test/unit/RelayService.ts @@ -15,7 +15,7 @@ import { CreateSystemUserService } from '@/core/CreateSystemUserService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { QueueService } from '@/core/QueueService.js'; import { IdService } from '@/core/IdService.js'; -import type { RelaysRepository } from '@/models/index.js'; +import type { RelaysRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import type { TestingModule } from '@nestjs/testing'; import type { MockFunctionMetadata } from 'jest-mock'; diff --git a/packages/backend/test/unit/RoleService.ts b/packages/backend/test/unit/RoleService.ts index 52224acab..c6a14702a 100644 --- a/packages/backend/test/unit/RoleService.ts +++ b/packages/backend/test/unit/RoleService.ts @@ -11,7 +11,7 @@ import { Test } from '@nestjs/testing'; import * as lolex from '@sinonjs/fake-timers'; import { GlobalModule } from '@/GlobalModule.js'; import { RoleService } from '@/core/RoleService.js'; -import type { MiRole, RolesRepository, RoleAssignmentsRepository, UsersRepository, MiUser } from '@/models/index.js'; +import type { MiRole, RolesRepository, RoleAssignmentsRepository, UsersRepository, MiUser } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { MetaService } from '@/core/MetaService.js'; import { genAidx } from '@/misc/id/aidx.js'; diff --git a/packages/backend/test/unit/S3Service.ts b/packages/backend/test/unit/S3Service.ts index 94d8d83a0..c1eafc96b 100644 --- a/packages/backend/test/unit/S3Service.ts +++ b/packages/backend/test/unit/S3Service.ts @@ -11,7 +11,7 @@ import { mockClient } from 'aws-sdk-client-mock'; import { GlobalModule } from '@/GlobalModule.js'; import { CoreModule } from '@/core/CoreModule.js'; import { S3Service } from '@/core/S3Service.js'; -import { MiMeta } from '@/models/index.js'; +import { MiMeta } from '@/models/_.js'; import type { TestingModule } from '@nestjs/testing'; describe('S3Service', () => { diff --git a/packages/backend/test/unit/activitypub.ts b/packages/backend/test/unit/activitypub.ts index a6e8409e0..dbc446d12 100644 --- a/packages/backend/test/unit/activitypub.ts +++ b/packages/backend/test/unit/activitypub.ts @@ -18,11 +18,11 @@ import { CoreModule } from '@/core/CoreModule.js'; import { FederatedInstanceService } from '@/core/FederatedInstanceService.js'; import { LoggerService } from '@/core/LoggerService.js'; import type { IActor, IApDocument, ICollection, IPost } from '@/core/activitypub/type.js'; -import { MiMeta, MiNote } from '@/models/index.js'; +import { MiMeta, MiNote } from '@/models/_.js'; import { secureRndstr } from '@/misc/secure-rndstr.js'; import { DownloadService } from '@/core/DownloadService.js'; import { MetaService } from '@/core/MetaService.js'; -import type { MiRemoteUser } from '@/models/entities/User.js'; +import type { MiRemoteUser } from '@/models/User.js'; import { MockResolver } from '../misc/mock-resolver.js'; const host = 'https://host1.test'; diff --git a/packages/frontend/.eslintrc.js b/packages/frontend/.eslintrc.cjs similarity index 100% rename from packages/frontend/.eslintrc.js rename to packages/frontend/.eslintrc.cjs diff --git a/packages/frontend/.storybook/fakes.ts b/packages/frontend/.storybook/fakes.ts index 14481deee..811c24392 100644 --- a/packages/frontend/.storybook/fakes.ts +++ b/packages/frontend/.storybook/fakes.ts @@ -89,6 +89,7 @@ export function userDetailed(id = 'someuserid', username = 'miskist', host = 'mi value: 'https://misskey-hub.net', }, ], + verifiedLinks: [], followersCount: 1024, followingCount: 16, hasPendingFollowRequestFromYou: false, @@ -119,6 +120,7 @@ export function userDetailed(id = 'someuserid', username = 'miskist', host = 'mi updatedAt: null, uri: null, url: null, + notify: 'none', }; } diff --git a/packages/frontend/@types/theme.d.ts b/packages/frontend/@types/theme.d.ts index f4ba42b89..376bbb0e9 100644 --- a/packages/frontend/@types/theme.d.ts +++ b/packages/frontend/@types/theme.d.ts @@ -4,7 +4,7 @@ */ declare module '@/themes/*.json5' { - import { Theme } from '@/scripts/theme'; + import { Theme } from '@/scripts/theme.js'; const theme: Theme; diff --git a/packages/frontend/package.json b/packages/frontend/package.json index 254985b17..f579da3cb 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -1,6 +1,7 @@ { "name": "frontend", "private": true, + "type": "module", "scripts": { "watch": "vite", "build": "vite build", @@ -21,10 +22,10 @@ "@rollup/plugin-json": "6.0.0", "@rollup/plugin-replace": "5.0.2", "@rollup/pluginutils": "5.0.4", - "@syuilo/aiscript": "0.15.0", - "@tabler/icons-webfont": "2.32.0", + "@syuilo/aiscript": "0.16.0", + "@tabler/icons-webfont": "2.35.0", "@vitejs/plugin-vue": "4.3.4", - "@vue-macros/reactivity-transform": "0.3.22", + "@vue-macros/reactivity-transform": "0.3.23", "@vue/compiler-sfc": "3.3.4", "astring": "1.8.6", "autosize": "6.0.1", @@ -37,7 +38,7 @@ "chartjs-chart-matrix": "2.0.1", "chartjs-plugin-gradient": "0.6.1", "chartjs-plugin-zoom": "2.0.1", - "chromatic": "6.24.1", + "chromatic": "7.2.0", "compare-versions": "6.1.0", "cropperjs": "2.0.0-beta.4", "date-fns": "2.30.0", @@ -52,25 +53,24 @@ "matter-js": "0.19.0", "mfm-js": "0.23.3", "misskey-js": "workspace:*", - "photoswipe": "5.3.9", + "photoswipe": "5.4.1", "prismjs": "1.29.0", "punycode": "2.3.0", "querystring": "0.2.1", - "rollup": "3.28.1", - "s-age": "1.1.2", + "rollup": "3.29.2", "sanitize-html": "2.11.0", - "sass": "1.66.1", + "sass": "1.68.0", "strict-event-emitter-types": "2.0.0", - "syuilo-password-strength": "0.0.1", "textarea-caret": "3.1.0", - "three": "0.156.0", + "three": "0.156.1", "throttle-debounce": "5.0.0", "tinycolor2": "1.6.0", - "tsc-alias": "1.8.7", + "tsc-alias": "1.8.8", "tsconfig-paths": "4.2.0", "twemoji-parser": "14.0.0", "typescript": "5.2.2", - "uuid": "9.0.0", + "uuid": "9.0.1", + "v-code-diff": "^1.7.1", "vanilla-tilt": "1.8.1", "vite": "4.4.9", "vue": "3.3.4", @@ -78,64 +78,64 @@ "vuedraggable": "next" }, "devDependencies": { - "@storybook/addon-actions": "7.4.0", - "@storybook/addon-essentials": "7.4.0", - "@storybook/addon-interactions": "7.4.0", - "@storybook/addon-links": "7.4.0", - "@storybook/addon-storysource": "7.4.0", - "@storybook/addons": "7.4.0", - "@storybook/blocks": "7.4.0", - "@storybook/core-events": "7.4.0", + "@storybook/addon-actions": "7.4.4", + "@storybook/addon-essentials": "7.4.4", + "@storybook/addon-interactions": "7.4.4", + "@storybook/addon-links": "7.4.4", + "@storybook/addon-storysource": "7.4.4", + "@storybook/addons": "7.4.4", + "@storybook/blocks": "7.4.4", + "@storybook/core-events": "7.4.4", "@storybook/jest": "0.2.2", - "@storybook/manager-api": "7.4.0", - "@storybook/preview-api": "7.4.0", - "@storybook/react": "7.4.0", - "@storybook/react-vite": "7.4.0", - "@storybook/testing-library": "0.2.0", - "@storybook/theming": "7.4.0", - "@storybook/types": "7.4.0", - "@storybook/vue3": "7.4.0", - "@storybook/vue3-vite": "7.4.0", + "@storybook/manager-api": "7.4.4", + "@storybook/preview-api": "7.4.4", + "@storybook/react": "7.4.4", + "@storybook/react-vite": "7.4.4", + "@storybook/testing-library": "0.2.1", + "@storybook/theming": "7.4.4", + "@storybook/types": "7.4.4", + "@storybook/vue3": "7.4.4", + "@storybook/vue3-vite": "7.4.4", "@testing-library/vue": "7.0.0", "@types/escape-regexp": "0.0.1", - "@types/estree": "1.0.1", + "@types/estree": "1.0.2", "@types/matter-js": "0.19.0", "@types/micromatch": "4.0.2", - "@types/node": "20.5.9", + "@types/node": "20.6.4", "@types/punycode": "2.1.0", "@types/sanitize-html": "2.9.0", "@types/throttle-debounce": "5.0.0", - "@types/tinycolor2": "1.4.3", - "@types/uuid": "9.0.3", + "@types/tinycolor2": "1.4.4", + "@types/uuid": "9.0.4", "@types/websocket": "1.0.6", "@types/ws": "8.5.5", - "@typescript-eslint/eslint-plugin": "6.6.0", - "@typescript-eslint/parser": "6.6.0", - "@vitest/coverage-v8": "0.34.3", + "@typescript-eslint/eslint-plugin": "6.7.2", + "@typescript-eslint/parser": "6.7.2", + "@vitest/coverage-v8": "0.34.5", "@vue/runtime-core": "3.3.4", "acorn": "8.10.0", "cross-env": "7.0.3", - "cypress": "13.1.0", - "eslint": "8.48.0", + "cypress": "13.2.0", + "eslint": "8.50.0", "eslint-plugin-import": "2.28.1", "eslint-plugin-vue": "9.17.0", "fast-glob": "3.3.1", "happy-dom": "10.0.3", "micromatch": "4.0.5", - "msw": "1.3.0", + "msw": "1.3.1", "msw-storybook-addon": "1.8.0", "nodemon": "3.0.1", "prettier": "3.0.3", "react": "18.2.0", "react-dom": "18.2.0", - "start-server-and-test": "2.0.0", - "storybook": "7.4.0", + "start-server-and-test": "2.0.1", + "storybook": "7.4.4", "storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme", "summaly": "github:misskey-dev/summaly", - "vite-plugin-turbosnap": "1.0.2", - "vitest": "0.34.3", + "vite-plugin-turbosnap": "1.0.3", + "vitest": "0.34.5", "vitest-fetch-mock": "0.2.2", "vue-eslint-parser": "9.3.1", - "vue-tsc": "1.8.8" + "vue-tsc": "1.8.13" } } diff --git a/packages/frontend/src/_boot_.ts b/packages/frontend/src/_boot_.ts index a397e57ad..efb78fe44 100644 --- a/packages/frontend/src/_boot_.ts +++ b/packages/frontend/src/_boot_.ts @@ -7,8 +7,8 @@ import 'vite/modulepreload-polyfill'; import '@/style.scss'; -import { mainBoot } from './boot/main-boot'; -import { subBoot } from './boot/sub-boot'; +import { mainBoot } from '@/boot/main-boot.js'; +import { subBoot } from '@/boot/sub-boot.js'; const subBootPaths = ['/share', '/auth', '/miauth', '/signup-complete']; diff --git a/packages/frontend/src/account.ts b/packages/frontend/src/account.ts index 43bda37b6..0e4e4b50f 100644 --- a/packages/frontend/src/account.ts +++ b/packages/frontend/src/account.ts @@ -5,14 +5,14 @@ import { defineAsyncComponent, reactive, ref } from 'vue'; import * as Misskey from 'misskey-js'; -import { showSuspendedDialog } from './scripts/show-suspended-dialog'; -import { i18n } from './i18n'; -import { miLocalStorage } from './local-storage'; -import { MenuButton } from './types/menu'; -import { del, get, set } from '@/scripts/idb-proxy'; -import { apiUrl } from '@/config'; -import { waiting, api, popup, popupMenu, success, alert } from '@/os'; -import { unisonReload, reloadChannel } from '@/scripts/unison-reload'; +import { showSuspendedDialog } from '@/scripts/show-suspended-dialog.js'; +import { i18n } from '@/i18n.js'; +import { miLocalStorage } from '@/local-storage.js'; +import { MenuButton } from '@/types/menu.js'; +import { del, get, set } from '@/scripts/idb-proxy.js'; +import { apiUrl } from '@/config.js'; +import { waiting, api, popup, popupMenu, success, alert } from '@/os.js'; +import { unisonReload, reloadChannel } from '@/scripts/unison-reload.js'; // TODO: 他のタブと永続化されたstateを同期 diff --git a/packages/frontend/src/boot/common.ts b/packages/frontend/src/boot/common.ts index 8f5de88cc..8346962e0 100644 --- a/packages/frontend/src/boot/common.ts +++ b/packages/frontend/src/boot/common.ts @@ -5,26 +5,26 @@ import { computed, createApp, watch, markRaw, version as vueVersion, defineAsyncComponent, App } from 'vue'; import { compareVersions } from 'compare-versions'; -import widgets from '@/widgets'; -import directives from '@/directives'; -import components from '@/components'; -import { version, ui, lang, updateLocale } from '@/config'; -import { applyTheme } from '@/scripts/theme'; -import { isDeviceDarkmode } from '@/scripts/is-device-darkmode'; -import { i18n, updateI18n } from '@/i18n'; -import { confirm, alert, post, popup, toast } from '@/os'; -import { $i, refreshAccount, login, updateAccount, signout } from '@/account'; -import { defaultStore, ColdDeviceStorage } from '@/store'; -import { fetchInstance, instance } from '@/instance'; -import { deviceKind } from '@/scripts/device-kind'; -import { reloadChannel } from '@/scripts/unison-reload'; -import { reactionPicker } from '@/scripts/reaction-picker'; -import { getUrlWithoutLoginId } from '@/scripts/login-id'; -import { getAccountFromId } from '@/scripts/get-account-from-id'; -import { deckStore } from '@/ui/deck/deck-store'; -import { miLocalStorage } from '@/local-storage'; -import { fetchCustomEmojis } from '@/custom-emojis'; -import { mainRouter } from '@/router'; +import widgets from '@/widgets/index.js'; +import directives from '@/directives/index.js'; +import components from '@/components/index.js'; +import { version, ui, lang, updateLocale } from '@/config.js'; +import { applyTheme } from '@/scripts/theme.js'; +import { isDeviceDarkmode } from '@/scripts/is-device-darkmode.js'; +import { i18n, updateI18n } from '@/i18n.js'; +import { confirm, alert, post, popup, toast } from '@/os.js'; +import { $i, refreshAccount, login, updateAccount, signout } from '@/account.js'; +import { defaultStore, ColdDeviceStorage } from '@/store.js'; +import { fetchInstance, instance } from '@/instance.js'; +import { deviceKind } from '@/scripts/device-kind.js'; +import { reloadChannel } from '@/scripts/unison-reload.js'; +import { reactionPicker } from '@/scripts/reaction-picker.js'; +import { getUrlWithoutLoginId } from '@/scripts/login-id.js'; +import { getAccountFromId } from '@/scripts/get-account-from-id.js'; +import { deckStore } from '@/ui/deck/deck-store.js'; +import { miLocalStorage } from '@/local-storage.js'; +import { fetchCustomEmojis } from '@/custom-emojis.js'; +import { mainRouter } from '@/router.js'; export async function common(createVue: () => App) { console.info(`Misskey v${version}`); @@ -202,6 +202,18 @@ export async function common(createVue: () => App) { } }, { immediate: true }); + if (defaultStore.state.keepScreenOn) { + if ('wakeLock' in navigator) { + navigator.wakeLock.request('screen'); + + document.addEventListener('visibilitychange', async () => { + if (document.visibilityState === 'visible') { + navigator.wakeLock.request('screen'); + } + }); + } + } + //#region Fetch user if ($i && $i.token) { if (_DEV_) { diff --git a/packages/frontend/src/boot/main-boot.ts b/packages/frontend/src/boot/main-boot.ts index 9ab1f6e14..f2af951d6 100644 --- a/packages/frontend/src/boot/main-boot.ts +++ b/packages/frontend/src/boot/main-boot.ts @@ -4,21 +4,21 @@ */ import { computed, createApp, watch, markRaw, version as vueVersion, defineAsyncComponent } from 'vue'; -import { common } from './common'; -import { version, ui, lang, updateLocale } from '@/config'; -import { i18n, updateI18n } from '@/i18n'; -import { confirm, alert, post, popup, toast } from '@/os'; -import { useStream } from '@/stream'; -import * as sound from '@/scripts/sound'; -import { $i, refreshAccount, login, updateAccount, signout } from '@/account'; -import { defaultStore, ColdDeviceStorage } from '@/store'; -import { makeHotkey } from '@/scripts/hotkey'; -import { reactionPicker } from '@/scripts/reaction-picker'; -import { miLocalStorage } from '@/local-storage'; -import { claimAchievement, claimedAchievements } from '@/scripts/achievements'; -import { mainRouter } from '@/router'; -import { initializeSw } from '@/scripts/initialize-sw'; -import { deckStore } from '@/ui/deck/deck-store'; +import { common } from './common.js'; +import { version, ui, lang, updateLocale } from '@/config.js'; +import { i18n, updateI18n } from '@/i18n.js'; +import { confirm, alert, post, popup, toast } from '@/os.js'; +import { useStream } from '@/stream.js'; +import * as sound from '@/scripts/sound.js'; +import { $i, refreshAccount, login, updateAccount, signout } from '@/account.js'; +import { defaultStore, ColdDeviceStorage } from '@/store.js'; +import { makeHotkey } from '@/scripts/hotkey.js'; +import { reactionPicker } from '@/scripts/reaction-picker.js'; +import { miLocalStorage } from '@/local-storage.js'; +import { claimAchievement, claimedAchievements } from '@/scripts/achievements.js'; +import { mainRouter } from '@/router.js'; +import { initializeSw } from '@/scripts/initialize-sw.js'; +import { deckStore } from '@/ui/deck/deck-store.js'; export async function mainBoot() { const { isClientUpdated } = await common(() => createApp( diff --git a/packages/frontend/src/boot/sub-boot.ts b/packages/frontend/src/boot/sub-boot.ts index 2cc19f2df..9b4670e13 100644 --- a/packages/frontend/src/boot/sub-boot.ts +++ b/packages/frontend/src/boot/sub-boot.ts @@ -4,7 +4,7 @@ */ import { computed, createApp, watch, markRaw, version as vueVersion, defineAsyncComponent } from 'vue'; -import { common } from './common'; +import { common } from './common.js'; export async function subBoot() { const { isClientUpdated } = await common(() => createApp( diff --git a/packages/frontend/src/cache.ts b/packages/frontend/src/cache.ts index 1f3d28ba5..25d2b3c15 100644 --- a/packages/frontend/src/cache.ts +++ b/packages/frontend/src/cache.ts @@ -4,8 +4,8 @@ */ import * as Misskey from 'misskey-js'; -import { Cache } from '@/scripts/cache'; -import { api } from '@/os'; +import { Cache } from '@/scripts/cache.js'; +import { api } from '@/os.js'; export const clipsCache = new Cache(1000 * 60 * 30, () => api('clips/list')); export const rolesCache = new Cache(1000 * 60 * 30, () => api('admin/roles/list')); diff --git a/packages/frontend/src/components/MkAbuseReport.vue b/packages/frontend/src/components/MkAbuseReport.vue index cb97875bc..66114b873 100644 --- a/packages/frontend/src/components/MkAbuseReport.vue +++ b/packages/frontend/src/components/MkAbuseReport.vue @@ -44,9 +44,9 @@ SPDX-License-Identifier: AGPL-3.0-only import MkButton from '@/components/MkButton.vue'; import MkSwitch from '@/components/MkSwitch.vue'; import MkKeyValue from '@/components/MkKeyValue.vue'; -import * as os from '@/os'; -import { i18n } from '@/i18n'; -import { dateString } from '@/filters/date'; +import * as os from '@/os.js'; +import { i18n } from '@/i18n.js'; +import { dateString } from '@/filters/date.js'; const props = defineProps<{ report: any; diff --git a/packages/frontend/src/components/MkAbuseReportWindow.vue b/packages/frontend/src/components/MkAbuseReportWindow.vue index 6e0dee697..7814681ea 100644 --- a/packages/frontend/src/components/MkAbuseReportWindow.vue +++ b/packages/frontend/src/components/MkAbuseReportWindow.vue @@ -35,8 +35,8 @@ import * as Misskey from 'misskey-js'; import MkWindow from '@/components/MkWindow.vue'; import MkTextarea from '@/components/MkTextarea.vue'; import MkButton from '@/components/MkButton.vue'; -import * as os from '@/os'; -import { i18n } from '@/i18n'; +import * as os from '@/os.js'; +import { i18n } from '@/i18n.js'; const props = defineProps<{ user: Misskey.entities.User; diff --git a/packages/frontend/src/components/MkAccountMoved.vue b/packages/frontend/src/components/MkAccountMoved.vue index e68efb1a3..155d9fe3a 100644 --- a/packages/frontend/src/components/MkAccountMoved.vue +++ b/packages/frontend/src/components/MkAccountMoved.vue @@ -15,9 +15,9 @@ SPDX-License-Identifier: AGPL-3.0-only import { ref } from 'vue'; import * as Misskey from 'misskey-js'; import MkMention from './MkMention.vue'; -import { i18n } from '@/i18n'; -import { host as localHost } from '@/config'; -import { api } from '@/os'; +import { i18n } from '@/i18n.js'; +import { host as localHost } from '@/config.js'; +import { api } from '@/os.js'; const user = ref(); diff --git a/packages/frontend/src/components/MkAchievements.stories.impl.ts b/packages/frontend/src/components/MkAchievements.stories.impl.ts index fd971e5ac..a67e1def1 100644 --- a/packages/frontend/src/components/MkAchievements.stories.impl.ts +++ b/packages/frontend/src/components/MkAchievements.stories.impl.ts @@ -9,7 +9,7 @@ import { rest } from 'msw'; import { userDetailed } from '../../.storybook/fakes'; import { commonHandlers } from '../../.storybook/mocks'; import MkAchievements from './MkAchievements.vue'; -import { ACHIEVEMENT_TYPES } from '@/scripts/achievements'; +import { ACHIEVEMENT_TYPES } from '@/scripts/achievements.js'; export const Empty = { render(args) { return { diff --git a/packages/frontend/src/components/MkAchievements.vue b/packages/frontend/src/components/MkAchievements.vue index f9d62773f..bea0ed26d 100644 --- a/packages/frontend/src/components/MkAchievements.vue +++ b/packages/frontend/src/components/MkAchievements.vue @@ -54,9 +54,9 @@ SPDX-License-Identifier: AGPL-3.0-only diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue index f7578dd39..06663d047 100644 --- a/packages/frontend/src/components/MkNoteDetailed.vue +++ b/packages/frontend/src/components/MkNoteDetailed.vue @@ -11,7 +11,12 @@ SPDX-License-Identifier: AGPL-3.0-only v-hotkey="keymap" :class="$style.root" > - + + + {{ i18n.ts.loadConversation }} + + + @@ -125,7 +130,47 @@ SPDX-License-Identifier: AGPL-3.0-only - + + {{ i18n.ts.replies }} + {{ i18n.ts.renotes }} + {{ i18n.ts.reactions }} + + + + + {{ i18n.ts.loadReplies }} + + + + + + + + + + + + + + + + + + + {{ appearNote.reactions[reaction] }} + + + + + + + + + + + + + @@ -151,24 +196,28 @@ import MkPoll from '@/components/MkPoll.vue'; import MkUsersTooltip from '@/components/MkUsersTooltip.vue'; import MkUrlPreview from '@/components/MkUrlPreview.vue'; import MkInstanceTicker from '@/components/MkInstanceTicker.vue'; -import { pleaseLogin } from '@/scripts/please-login'; -import { checkWordMute } from '@/scripts/check-word-mute'; -import { userPage } from '@/filters/user'; -import { notePage } from '@/filters/note'; -import * as os from '@/os'; -import { defaultStore, noteViewInterruptors } from '@/store'; -import { reactionPicker } from '@/scripts/reaction-picker'; -import { extractUrlFromMfm } from '@/scripts/extract-url-from-mfm'; -import { $i } from '@/account'; -import { i18n } from '@/i18n'; -import { getNoteClipMenu, getNoteMenu } from '@/scripts/get-note-menu'; -import { useNoteCapture } from '@/scripts/use-note-capture'; -import { deepClone } from '@/scripts/clone'; -import { useTooltip } from '@/scripts/use-tooltip'; -import { claimAchievement } from '@/scripts/achievements'; +import { pleaseLogin } from '@/scripts/please-login.js'; +import { checkWordMute } from '@/scripts/check-word-mute.js'; +import { userPage } from '@/filters/user.js'; +import { notePage } from '@/filters/note.js'; +import * as os from '@/os.js'; +import { defaultStore, noteViewInterruptors } from '@/store.js'; +import { reactionPicker } from '@/scripts/reaction-picker.js'; +import { extractUrlFromMfm } from '@/scripts/extract-url-from-mfm.js'; +import { $i } from '@/account.js'; +import { i18n } from '@/i18n.js'; +import { getNoteClipMenu, getNoteMenu } from '@/scripts/get-note-menu.js'; +import { useNoteCapture } from '@/scripts/use-note-capture.js'; +import { deepClone } from '@/scripts/clone.js'; +import { useTooltip } from '@/scripts/use-tooltip.js'; +import { claimAchievement } from '@/scripts/achievements.js'; import { MenuItem } from '@/types/menu'; import MkRippleEffect from '@/components/MkRippleEffect.vue'; -import { showMovedDialog } from '@/scripts/show-moved-dialog'; +import { showMovedDialog } from '@/scripts/show-moved-dialog.js'; +import MkUserCardMini from '@/components/MkUserCardMini.vue'; +import MkPagination, { Paging } from '@/components/MkPagination.vue'; +import MkReactionIcon from '@/components/MkReactionIcon.vue'; +import MkButton from '@/components/MkButton.vue'; const props = defineProps<{ note: Misskey.entities.Note; @@ -224,6 +273,26 @@ const keymap = { 's': () => showContent.value !== showContent.value, }; +let tab = $ref('replies'); +let reactionTabType = $ref(null); + +const renotesPagination = $computed(() => ({ + endpoint: 'notes/renotes', + limit: 10, + params: { + noteId: appearNote.id, + }, +})); + +const reactionsPagination = $computed(() => ({ + endpoint: 'notes/reactions', + limit: 10, + params: { + noteId: appearNote.id, + type: reactionTabType, + }, +})); + useNoteCapture({ rootEl: el, note: $$(appearNote), @@ -426,14 +495,20 @@ function blur() { el.value.blur(); } -os.api('notes/children', { - noteId: appearNote.id, - limit: 30, -}).then(res => { - replies.value = res; -}); +const repliesLoaded = ref(false); +function loadReplies() { + repliesLoaded.value = true; + os.api('notes/children', { + noteId: appearNote.id, + limit: 30, + }).then(res => { + replies.value = res; + }); +} -if (appearNote.replyId) { +const conversationLoaded = ref(false); +function loadConversation() { + conversationLoaded.value = true; os.api('notes/conversation', { noteId: appearNote.replyId, }).then(res => { @@ -640,10 +715,52 @@ if (appearNote.replyId) { } } -.reply { +.reply:not(:first-child) { border-top: solid 0.5px var(--divider); } +.tabs { + border-top: solid 0.5px var(--divider); + border-bottom: solid 0.5px var(--divider); + display: flex; +} + +.tab { + flex: 1; + padding: 12px 8px; + border-top: solid 2px transparent; + border-bottom: solid 2px transparent; +} + +.tabActive { + border-bottom: solid 2px var(--accent); +} + +.tab_renotes { + padding: 16px; +} + +.tab_reactions { + padding: 16px; +} + +.reactionTabs { + display: flex; + gap: 8px; + flex-wrap: wrap; + margin-bottom: 8px; +} + +.reactionTab { + padding: 4px 6px; + border: solid 1px var(--divider); + border-radius: 6px; +} + +.reactionTabActive { + border-color: var(--accent); +} + @container (max-width: 500px) { .root { font-size: 0.9em; diff --git a/packages/frontend/src/components/MkNoteHeader.vue b/packages/frontend/src/components/MkNoteHeader.vue index 81d0c1f9c..dda7238d2 100644 --- a/packages/frontend/src/components/MkNoteHeader.vue +++ b/packages/frontend/src/components/MkNoteHeader.vue @@ -31,9 +31,9 @@ SPDX-License-Identifier: AGPL-3.0-only diff --git a/packages/frontend/src/components/MkPlusOneEffect.vue b/packages/frontend/src/components/MkPlusOneEffect.vue index 8086b97ae..0bc98f433 100644 --- a/packages/frontend/src/components/MkPlusOneEffect.vue +++ b/packages/frontend/src/components/MkPlusOneEffect.vue @@ -11,7 +11,7 @@ SPDX-License-Identifier: AGPL-3.0-only - - diff --git a/packages/frontend/src/components/MkReactionEffect.vue b/packages/frontend/src/components/MkReactionEffect.vue index f373d179e..88e262d88 100644 --- a/packages/frontend/src/components/MkReactionEffect.vue +++ b/packages/frontend/src/components/MkReactionEffect.vue @@ -13,7 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only - - diff --git a/packages/frontend/src/components/MkRetentionHeatmap.vue b/packages/frontend/src/components/MkRetentionHeatmap.vue index 737ddff6a..3dc9a94ae 100644 --- a/packages/frontend/src/components/MkRetentionHeatmap.vue +++ b/packages/frontend/src/components/MkRetentionHeatmap.vue @@ -15,11 +15,11 @@ SPDX-License-Identifier: AGPL-3.0-only + + diff --git a/packages/frontend/src/pages/admin/modlog.vue b/packages/frontend/src/pages/admin/modlog.vue new file mode 100644 index 000000000..4b5ef5f77 --- /dev/null +++ b/packages/frontend/src/pages/admin/modlog.vue @@ -0,0 +1,67 @@ + + + + + + + + + + {{ i18n.ts.type }} + {{ i18n.ts.all }} + {{ i18n.ts._moderationLogTypes[t] ?? t }} + + + {{ i18n.ts.moderator }}(ID) + + + + + + + + + + + + + + diff --git a/packages/frontend/src/pages/admin/object-storage.vue b/packages/frontend/src/pages/admin/object-storage.vue index 6ebf3f738..dbcf135c8 100644 --- a/packages/frontend/src/pages/admin/object-storage.vue +++ b/packages/frontend/src/pages/admin/object-storage.vue @@ -89,10 +89,10 @@ import MkSwitch from '@/components/MkSwitch.vue'; import MkInput from '@/components/MkInput.vue'; import FormSuspense from '@/components/form/suspense.vue'; import FormSplit from '@/components/form/split.vue'; -import * as os from '@/os'; -import { fetchInstance } from '@/instance'; -import { i18n } from '@/i18n'; -import { definePageMetadata } from '@/scripts/page-metadata'; +import * as os from '@/os.js'; +import { fetchInstance } from '@/instance.js'; +import { i18n } from '@/i18n.js'; +import { definePageMetadata } from '@/scripts/page-metadata.js'; import MkButton from '@/components/MkButton.vue'; let useObjectStorage: boolean = $ref(false); diff --git a/packages/frontend/src/pages/admin/other-settings.vue b/packages/frontend/src/pages/admin/other-settings.vue index 7a4d3831a..7574c9d7d 100644 --- a/packages/frontend/src/pages/admin/other-settings.vue +++ b/packages/frontend/src/pages/admin/other-settings.vue @@ -46,10 +46,10 @@ SPDX-License-Identifier: AGPL-3.0-only import { } from 'vue'; import XHeader from './_header_.vue'; import FormSuspense from '@/components/form/suspense.vue'; -import * as os from '@/os'; -import { fetchInstance } from '@/instance'; -import { i18n } from '@/i18n'; -import { definePageMetadata } from '@/scripts/page-metadata'; +import * as os from '@/os.js'; +import { fetchInstance } from '@/instance.js'; +import { i18n } from '@/i18n.js'; +import { definePageMetadata } from '@/scripts/page-metadata.js'; import MkSwitch from '@/components/MkSwitch.vue'; let enableServerMachineStats: boolean = $ref(false); diff --git a/packages/frontend/src/pages/admin/overview.active-users.vue b/packages/frontend/src/pages/admin/overview.active-users.vue index d15e4651d..8426c463d 100644 --- a/packages/frontend/src/pages/admin/overview.active-users.vue +++ b/packages/frontend/src/pages/admin/overview.active-users.vue @@ -16,11 +16,11 @@ SPDX-License-Identifier: AGPL-3.0-only import { onMounted } from 'vue'; import { Chart } from 'chart.js'; import gradient from 'chartjs-plugin-gradient'; -import * as os from '@/os'; -import { defaultStore } from '@/store'; -import { useChartTooltip } from '@/scripts/use-chart-tooltip'; -import { chartVLine } from '@/scripts/chart-vline'; -import { initChart } from '@/scripts/init-chart'; +import * as os from '@/os.js'; +import { defaultStore } from '@/store.js'; +import { useChartTooltip } from '@/scripts/use-chart-tooltip.js'; +import { chartVLine } from '@/scripts/chart-vline.js'; +import { initChart } from '@/scripts/init-chart.js'; initChart(); diff --git a/packages/frontend/src/pages/admin/overview.ap-requests.vue b/packages/frontend/src/pages/admin/overview.ap-requests.vue index d3e026709..cd54041c3 100644 --- a/packages/frontend/src/pages/admin/overview.ap-requests.vue +++ b/packages/frontend/src/pages/admin/overview.ap-requests.vue @@ -23,12 +23,12 @@ SPDX-License-Identifier: AGPL-3.0-only import { onMounted } from 'vue'; import { Chart } from 'chart.js'; import gradient from 'chartjs-plugin-gradient'; -import * as os from '@/os'; -import { useChartTooltip } from '@/scripts/use-chart-tooltip'; -import { chartVLine } from '@/scripts/chart-vline'; -import { defaultStore } from '@/store'; -import { alpha } from '@/scripts/color'; -import { initChart } from '@/scripts/init-chart'; +import * as os from '@/os.js'; +import { useChartTooltip } from '@/scripts/use-chart-tooltip.js'; +import { chartVLine } from '@/scripts/chart-vline.js'; +import { defaultStore } from '@/store.js'; +import { alpha } from '@/scripts/color.js'; +import { initChart } from '@/scripts/init-chart.js'; initChart(); diff --git a/packages/frontend/src/pages/admin/overview.federation.vue b/packages/frontend/src/pages/admin/overview.federation.vue index afb4b7f87..346a9c025 100644 --- a/packages/frontend/src/pages/admin/overview.federation.vue +++ b/packages/frontend/src/pages/admin/overview.federation.vue @@ -48,11 +48,11 @@ SPDX-License-Identifier: AGPL-3.0-only