From c150d1edce71a2667905b0842f5e88d044526b6a Mon Sep 17 00:00:00 2001 From: koke Date: Tue, 7 Mar 2023 04:43:26 +0900 Subject: [PATCH 001/284] Create docker-image.yml add action file --- .github/workflows/docker-image.yml | 48 ++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 .github/workflows/docker-image.yml diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml new file mode 100644 index 000000000000..cd65b3841773 --- /dev/null +++ b/.github/workflows/docker-image.yml @@ -0,0 +1,48 @@ +name: Build and Push Image (Docker Buildx; GitHub Actions) + +on: + workflow_dispatch: + +env: + DOCKER_REGISTRY_NAME: ghcr.io + DOCKER_IMAGE_NAME: ${{ github.repository }} + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@v3 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + + - name: Setup Docker Buildx + uses: docker/setup-buildx-action@v1 + + - name: Login to Docker hub + uses: docker/login-action@v1 + with: + registry: ${{ env.DOCKER_REGISTRY_NAME }} + username: ${{ github.repository_owner }} + password: ${{ github.token }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v3 + with: + images: ${{ env.DOCKER_REGISTRY_NAME }}/${{ env.DOCKER_IMAGE_NAME }} + + - name: Build & Push + uses: docker/build-push-action@v2 + env: + DOCKER_BUILDKIT: 1 + with: + context: . + push: true + platforms: linux/amd64,linux/arm64 + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: ${{ env.DOCKER_REGISTRY_NAME }}/${{ env.DOCKER_IMAGE_NAME }}:latest + build-args: BUILDKIT_INLINE_CACHE=1 From d50225878351c790e7e1034983c8ffe0f3176733 Mon Sep 17 00:00:00 2001 From: koke Date: Thu, 9 Mar 2023 17:33:40 +0900 Subject: [PATCH 002/284] Update docker-image.yml add token --- .github/workflows/docker-image.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index cd65b3841773..58791b3b9903 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -26,7 +26,7 @@ jobs: with: registry: ${{ env.DOCKER_REGISTRY_NAME }} username: ${{ github.repository_owner }} - password: ${{ github.token }} + password: ${{ secrets.GITHUB_TOKEN }} # github.token - name: Extract metadata (tags, labels) for Docker id: meta From c5f17cc2976ac2d459e55e0abcfe9d8a7056cf52 Mon Sep 17 00:00:00 2001 From: koke Date: Thu, 9 Mar 2023 21:26:06 +0900 Subject: [PATCH 003/284] Update docker-image.yml --- .github/workflows/docker-image.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 58791b3b9903..c61e7f4a6b87 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -26,7 +26,7 @@ jobs: with: registry: ${{ env.DOCKER_REGISTRY_NAME }} username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} # github.token + password: ${{ github.token }} # github.token - name: Extract metadata (tags, labels) for Docker id: meta From a7894df20b046c13e555c0452f9d771a43a174ca Mon Sep 17 00:00:00 2001 From: koke Date: Wed, 10 May 2023 00:23:04 +0900 Subject: [PATCH 004/284] Update docker-image.yml Change trigger timing --- .github/workflows/docker-image.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index c61e7f4a6b87..b54795f8ce93 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -1,7 +1,9 @@ name: Build and Push Image (Docker Buildx; GitHub Actions) on: - workflow_dispatch: + push: + tags: + - 'v*' env: DOCKER_REGISTRY_NAME: ghcr.io From 200556a4664d442f994acb6dc1e1d2a654324dcc Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Thu, 6 Jul 2023 08:49:07 +0900 Subject: [PATCH 005/284] =?UTF-8?q?feat(frontend):=20=E7=94=BB=E5=83=8F?= =?UTF-8?q?=E3=82=92=E5=8B=95=E7=94=BB=E3=81=A8=E5=90=8C=E6=A7=98=E3=81=AB?= =?UTF-8?q?=E7=B0=A1=E5=8D=98=E3=81=AB=E9=9A=A0=E3=81=9B=E3=82=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB=20(#11127)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: hide image easily * docs(changelog): add 画像を動画と同様に簡単に隠せるように Cherry-picks: dc8763215ada27149e8b4370bb86b8fb6ad3a002 --- CHANGELOG.md | 9 +++++++++ .../frontend/src/components/MkMediaImage.vue | 16 ++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 45dc0e3c905c..6bbc5967dff1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,15 @@ --> +## 13.x.x (unreleased) + +### General + +### Client +- 画像を動画と同様に簡単に隠せるように + +### Server + ## 13.13.2 ### General diff --git a/packages/frontend/src/components/MkMediaImage.vue b/packages/frontend/src/components/MkMediaImage.vue index b29871c3635e..df49bcb26d1c 100644 --- a/packages/frontend/src/components/MkMediaImage.vue +++ b/packages/frontend/src/components/MkMediaImage.vue @@ -33,6 +33,7 @@
NSFW
+ @@ -113,6 +114,21 @@ function showMenu(ev: MouseEvent) { align-items: center; } +.hide { + display: block; + position: absolute; + border-radius: 6px; + background-color: var(--fg); + color: var(--accentLighten); + font-size: 14px; + opacity: .5; + padding: 3px 6px; + text-align: center; + cursor: pointer; + top: 12px; + right: 12px; +} + .hiddenTextWrapper { display: table-cell; text-align: center; From a45e320d9ced247a0ba3aa79dc7e5a123a78d2f6 Mon Sep 17 00:00:00 2001 From: Sayamame-beans <61457993+sayamame-beans@users.noreply.github.com> Date: Mon, 10 Jul 2023 13:30:41 +0900 Subject: [PATCH 006/284] =?UTF-8?q?feat:=20=E3=83=95=E3=82=A9=E3=83=AD?= =?UTF-8?q?=E3=83=BC=E3=82=84=E3=81=8A=E6=B0=97=E3=81=AB=E5=85=A5=E3=82=8A?= =?UTF-8?q?=E7=99=BB=E9=8C=B2=E3=82=92=E3=81=97=E3=81=A6=E3=81=84=E3=81=AA?= =?UTF-8?q?=E3=81=84=E3=83=81=E3=83=A3=E3=83=B3=E3=83=8D=E3=83=AB=E3=82=92?= =?UTF-8?q?=E9=96=8B=E3=81=8F=E6=99=82=E3=81=AF=E6=A6=82=E8=A6=81=E3=83=9A?= =?UTF-8?q?=E3=83=BC=E3=82=B8=E3=82=92=E9=96=8B=E3=81=8F=E3=82=88=E3=81=86?= =?UTF-8?q?=E3=81=AB=20(#11218)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: フォローやお気に入り登録をしていないチャンネルを開く時は概要ページを開くように * Update CHANGELOG.md --------- Co-authored-by: tamaina Cherry-picks: 239ea39d6f06c42d692b1ea8a874a8755a66dc15 --- CHANGELOG.md | 1 + packages/frontend/src/pages/channel.vue | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bbc5967dff1..3a611276eca3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ ### Client - 画像を動画と同様に簡単に隠せるように +- フォローやお気に入り登録をしていないチャンネルを開く時は概要ページを開くように ### Server diff --git a/packages/frontend/src/pages/channel.vue b/packages/frontend/src/pages/channel.vue index bcc0fc6860c0..2a056f21d40c 100644 --- a/packages/frontend/src/pages/channel.vue +++ b/packages/frontend/src/pages/channel.vue @@ -87,7 +87,7 @@ const props = defineProps<{ channelId: string; }>(); -let tab = $ref('timeline'); +let tab = $ref('overview'); let channel = $ref(null); let favorited = $ref(false); let searchQuery = $ref(''); @@ -107,6 +107,9 @@ watch(() => props.channelId, async () => { channelId: props.channelId, }); favorited = channel.isFavorited; + if (favorited || channel.isFollowing) { + tab = 'timeline'; + } }, { immediate: true }); function edit() { From a7d3c3a41d8fc57ec8fa615845eed8a4d8b09e6d Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 8 Jul 2023 18:55:02 +0900 Subject: [PATCH 007/284] =?UTF-8?q?fix(frontend):=20=E9=95=B7=E3=81=84?= =?UTF-8?q?=E6=96=87=E7=AB=A0=E3=82=92=E6=8A=95=E7=A8=BF=E3=81=99=E3=82=8B?= =?UTF-8?q?=E9=9A=9B=E3=80=81=E3=83=97=E3=83=AC=E3=83=93=E3=83=A5=E3=83=BC?= =?UTF-8?q?=E3=81=8C=E7=94=BB=E9=9D=A2=E3=81=8B=E3=82=89=E3=81=AF=E3=81=BF?= =?UTF-8?q?=E5=87=BA=E3=82=8B=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix #11186 Cherry-picks: 6a015341efc5f268ab86d11ba75b44a46cfbd33d --- CHANGELOG.md | 1 + packages/frontend/src/components/MkPostForm.vue | 2 ++ packages/frontend/src/components/MkPostFormDialog.vue | 9 ++++++++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a611276eca3..d3cfea9ebba4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ ### Client - 画像を動画と同様に簡単に隠せるように - フォローやお気に入り登録をしていないチャンネルを開く時は概要ページを開くように +- Fix: 長い文章を投稿する際、プレビューが画面からはみ出る問題を修正 ### Server diff --git a/packages/frontend/src/components/MkPostForm.vue b/packages/frontend/src/components/MkPostForm.vue index 5c6556968304..f9edc048ece9 100644 --- a/packages/frontend/src/components/MkPostForm.vue +++ b/packages/frontend/src/components/MkPostForm.vue @@ -1015,6 +1015,8 @@ defineExpose({ .preview { padding: 16px 20px 0 20px; + max-height: 150px; + overflow: auto; } .targetNote { diff --git a/packages/frontend/src/components/MkPostFormDialog.vue b/packages/frontend/src/components/MkPostFormDialog.vue index 98af92c6f844..989c138e813f 100644 --- a/packages/frontend/src/components/MkPostFormDialog.vue +++ b/packages/frontend/src/components/MkPostFormDialog.vue @@ -1,6 +1,6 @@ @@ -44,3 +44,10 @@ function onModalClosed() { emit('closed'); } + + From b1a297c8e45552ca2fc0d730888d229949857a8b Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 8 Jul 2023 19:01:47 +0900 Subject: [PATCH 008/284] =?UTF-8?q?enhance(frontend):=20=E5=BC=95=E7=94=A8?= =?UTF-8?q?=E5=AF=BE=E8=B1=A1=E3=82=92=E3=80=8C=E3=82=82=E3=81=A3=E3=81=A8?= =?UTF-8?q?=E8=A6=8B=E3=82=8B=E3=80=8D=E3=81=A7=E5=B1=95=E9=96=8B=E3=81=97?= =?UTF-8?q?=E3=81=9F=E5=A0=B4=E5=90=88=E3=80=81=E3=80=8C=E9=96=89=E3=81=98?= =?UTF-8?q?=E3=82=8B=E3=80=8D=E3=81=A7=E7=95=B3=E3=82=81=E3=82=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolve #11185 Cherry-picks: ac6d6fdeb813e9c99e0d843a24cce81a99fd91da --- CHANGELOG.md | 1 + .../src/components/MkSubNoteContent.vue | 27 ++++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d3cfea9ebba4..2c8d7948516e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ ### Client - 画像を動画と同様に簡単に隠せるように - フォローやお気に入り登録をしていないチャンネルを開く時は概要ページを開くように +- 引用対象を「もっと見る」で展開した場合、「閉じる」で畳めるように - Fix: 長い文章を投稿する際、プレビューが画面からはみ出る問題を修正 ### Server diff --git a/packages/frontend/src/components/MkSubNoteContent.vue b/packages/frontend/src/components/MkSubNoteContent.vue index 3a050889c8d6..c76ce7315d08 100644 --- a/packages/frontend/src/components/MkSubNoteContent.vue +++ b/packages/frontend/src/components/MkSubNoteContent.vue @@ -15,9 +15,12 @@ {{ i18n.ts.poll }} - + @@ -33,11 +36,13 @@ const props = defineProps<{ note: misskey.entities.Note; }>(); -const collapsed = $ref( +const isLong = props.note.cw == null && props.note.text != null && ( (props.note.text.split('\n').length > 9) || (props.note.text.length > 500) - )); + ); + +const collapsed = $ref(isLong); From 353aecc6dde49d20cb510a3048f7b53b0dd16ca8 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Tue, 11 Jul 2023 16:16:14 +0900 Subject: [PATCH 009/284] chore: use saved visibility on renote --- packages/frontend/src/components/MkNote.vue | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue index 7c9ddadbf8e3..0002fb57794f 100644 --- a/packages/frontend/src/components/MkNote.vue +++ b/packages/frontend/src/components/MkNote.vue @@ -259,6 +259,16 @@ useTooltip(renoteButton, async (showing) => { }, {}, 'closed'); }); +type Visibility = 'public' | 'home' | 'followers' | 'specified'; + +function smallerVisibility(a: Visibility | string, b: Visibility | string): Visibility { + if (a === 'specified' || b === 'specified') return 'specified'; + if (a === 'followers' || b === 'followers') return 'followers'; + if (a === 'home' || b === 'home') return 'home'; + // if (a === 'public' || b === 'public') + return 'public'; +} + function renote(viaKeyboard = false) { pleaseLogin(); showMovedDialog(); @@ -309,7 +319,10 @@ function renote(viaKeyboard = false) { os.popup(MkRippleEffect, { x, y }, {}, 'end'); } + const configuredVisibility = defaultStore.state.rememberNoteVisibility ? defaultStore.state.visibility : defaultStore.state.defaultNoteVisibility; + os.api('notes/create', { + visibility: smallerVisibility(appearNote.visibility, configuredVisibility), renoteId: appearNote.id, }).then(() => { os.toast(i18n.ts.renoted); From 33f408098e7202226d0e2f0fc17c2ac9e2a47416 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Tue, 11 Jul 2023 16:29:29 +0900 Subject: [PATCH 010/284] chore: use saved localOnly on renote --- packages/frontend/src/components/MkNote.vue | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue index 0002fb57794f..b8db888e322b 100644 --- a/packages/frontend/src/components/MkNote.vue +++ b/packages/frontend/src/components/MkNote.vue @@ -320,8 +320,10 @@ function renote(viaKeyboard = false) { } const configuredVisibility = defaultStore.state.rememberNoteVisibility ? defaultStore.state.visibility : defaultStore.state.defaultNoteVisibility; + const localOnly = defaultStore.state.rememberNoteVisibility ? defaultStore.state.localOnly : defaultStore.state.defaultNoteLocalOnly; os.api('notes/create', { + localOnly, visibility: smallerVisibility(appearNote.visibility, configuredVisibility), renoteId: appearNote.id, }).then(() => { From 102623a18b2f3c38dd2b0c7efce0cc4e7570e1a3 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Tue, 11 Jul 2023 16:41:23 +0900 Subject: [PATCH 011/284] docs: add comment about why smallerVisibility accepts string --- packages/frontend/src/components/MkNote.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue index b8db888e322b..a32cfe9ea96f 100644 --- a/packages/frontend/src/components/MkNote.vue +++ b/packages/frontend/src/components/MkNote.vue @@ -261,6 +261,7 @@ useTooltip(renoteButton, async (showing) => { type Visibility = 'public' | 'home' | 'followers' | 'specified'; +// defaultStore.state.visibilityがstringなためstringも受け付けている function smallerVisibility(a: Visibility | string, b: Visibility | string): Visibility { if (a === 'specified' || b === 'specified') return 'specified'; if (a === 'followers' || b === 'followers') return 'followers'; From 150118cca1234e118e1541530b1217d8eb15cb56 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Tue, 11 Jul 2023 17:08:22 +0900 Subject: [PATCH 012/284] =?UTF-8?q?docs(changelog):=20add=20Renote?= =?UTF-8?q?=E6=99=82=E3=81=AB=E5=85=AC=E9=96=8B=E7=AF=84=E5=9B=B2=E3=81=AE?= =?UTF-8?q?=E3=83=87=E3=83=95=E3=82=A9=E3=83=AB=E3=83=88=E8=A8=AD=E5=AE=9A?= =?UTF-8?q?=E3=81=8C=E9=81=A9=E7=94=A8=E3=81=95=E3=82=8C=E3=82=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c8d7948516e..42a4a0ce930d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ - 画像を動画と同様に簡単に隠せるように - フォローやお気に入り登録をしていないチャンネルを開く時は概要ページを開くように - 引用対象を「もっと見る」で展開した場合、「閉じる」で畳めるように +- Renote時に公開範囲のデフォルト設定が適用されるように - Fix: 長い文章を投稿する際、プレビューが画面からはみ出る問題を修正 ### Server From 064e6e28b0ed1d427d7b0b10f6e8fa3607637fed Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Wed, 5 Jul 2023 13:04:27 +0900 Subject: [PATCH 013/284] =?UTF-8?q?feat(frontend):=20deck=20UI=E3=81=AE?= =?UTF-8?q?=E3=82=AB=E3=83=A9=E3=83=A0=E3=81=8B=E3=82=89=E3=82=A2=E3=83=B3?= =?UTF-8?q?=E3=83=86=E3=83=8A=E3=80=81=E3=83=AA=E3=82=B9=E3=83=88=E3=81=AE?= =?UTF-8?q?=E7=B7=A8=E9=9B=86=E7=94=BB=E9=9D=A2=E3=82=92=E9=96=8B=E3=81=91?= =?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=20(#11104)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add edit antenna button onto deck column * feat: add edit list button onto deck column * docs(changelog): add deck UIのカラムのメニューからアンテナとリストの編集画面を開けるようになりました Cherry-picks: 1ab9f096c36da6fcb552a289cdf6e658b434445f --- CHANGELOG.md | 1 + locales/index.d.ts | 2 ++ locales/ja-JP.yml | 2 ++ .../frontend/src/ui/deck/antenna-column.vue | 21 ++++++++++++++----- packages/frontend/src/ui/deck/list-column.vue | 21 ++++++++++++++----- 5 files changed, 37 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42a4a0ce930d..cf383aa2240a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ ### General ### Client +- deck UIのカラムのメニューからアンテナとリストの編集画面を開けるように - 画像を動画と同様に簡単に隠せるように - フォローやお気に入り登録をしていないチャンネルを開く時は概要ページを開くように - 引用対象を「もっと見る」で展開した場合、「閉じる」で畳めるように diff --git a/locales/index.d.ts b/locales/index.d.ts index eed29f408c0b..4763d21400ce 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -139,8 +139,10 @@ export interface Locale { "suspendConfirm": string; "unsuspendConfirm": string; "selectList": string; + "editList": string; "selectChannel": string; "selectAntenna": string; + "editAntenna": string; "selectWidget": string; "editWidgets": string; "editWidgetsExit": string; diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 8004e53575f6..587fabdf04ba 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -136,8 +136,10 @@ unblockConfirm: "ブロック解除しますか?" suspendConfirm: "凍結しますか?" unsuspendConfirm: "解凍しますか?" selectList: "リストを選択" +editList: "リストを編集" selectChannel: "チャンネルを選択" selectAntenna: "アンテナを選択" +editAntenna: "アンテナを編集" selectWidget: "ウィジェットを選択" editWidgets: "ウィジェットを編集" editWidgetsExit: "編集を終了" diff --git a/packages/frontend/src/ui/deck/antenna-column.vue b/packages/frontend/src/ui/deck/antenna-column.vue index d21a9cc5809c..a1ca32724f7b 100644 --- a/packages/frontend/src/ui/deck/antenna-column.vue +++ b/packages/frontend/src/ui/deck/antenna-column.vue @@ -44,11 +44,22 @@ async function setAntenna() { }); } -const menu = [{ - icon: 'ti ti-pencil', - text: i18n.ts.selectAntenna, - action: setAntenna, -}]; +function editAntenna() { + os.pageWindow('my/antennas/' + props.column.antennaId); +} + +const menu = [ + { + icon: 'ti ti-pencil', + text: i18n.ts.selectAntenna, + action: setAntenna, + }, + { + icon: 'ti ti-settings', + text: i18n.ts.editAntenna, + action: editAntenna, + }, +]; /* function focus() { diff --git a/packages/frontend/src/ui/deck/list-column.vue b/packages/frontend/src/ui/deck/list-column.vue index f36dc6151c56..3d6256c4fd08 100644 --- a/packages/frontend/src/ui/deck/list-column.vue +++ b/packages/frontend/src/ui/deck/list-column.vue @@ -42,9 +42,20 @@ async function setList() { }); } -const menu = [{ - icon: 'ti ti-pencil', - text: i18n.ts.selectList, - action: setList, -}]; +function editList() { + os.pageWindow('my/lists/' + props.column.listId); +} + +const menu = [ + { + icon: 'ti ti-pencil', + text: i18n.ts.selectList, + action: setList, + }, + { + icon: 'ti ti-settings', + text: i18n.ts.editList, + action: editList, + }, +]; From 67c80c364fe89ef24a81f29b7f20a1d59ba60bac Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Fri, 7 Jul 2023 20:05:11 +0900 Subject: [PATCH 014/284] chore: collapse renote of my note (#11166) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(frontend): 自分のnoteのrenoteも省略するように Co-authored-by: madorama * docs(changelog): add 見たことのあるRenoteを省略して表示をオンのときに自分のnoteのrenoteを省略するように --------- Co-authored-by: madorama Cherry-picks: 2606167f0da856a200d61c0f1cecf0e02844c0f4 --- CHANGELOG.md | 1 + packages/frontend/src/components/MkNote.vue | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf383aa2240a..60a9b4de2c2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ ### Client - deck UIのカラムのメニューからアンテナとリストの編集画面を開けるように - 画像を動画と同様に簡単に隠せるように +- 見たことのあるRenoteを省略して表示をオンのときに自分のnoteのrenoteを省略するように - フォローやお気に入り登録をしていないチャンネルを開く時は概要ページを開くように - 引用対象を「もっと見る」で展開した場合、「閉じる」で畳めるように - Renote時に公開範囲のデフォルト設定が適用されるように diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue index a32cfe9ea96f..7a7406931ba8 100644 --- a/packages/frontend/src/components/MkNote.vue +++ b/packages/frontend/src/components/MkNote.vue @@ -222,7 +222,7 @@ const translation = ref(null); const translating = ref(false); const showTicker = (defaultStore.state.instanceTicker === 'always') || (defaultStore.state.instanceTicker === 'remote' && appearNote.user.instance); const canRenote = computed(() => ['public', 'home'].includes(appearNote.visibility) || appearNote.userId === $i.id); -let renoteCollapsed = $ref(defaultStore.state.collapseRenotes && isRenote && (($i && ($i.id === note.userId)) || (appearNote.myReaction != null))); +let renoteCollapsed = $ref(defaultStore.state.collapseRenotes && isRenote && (($i && ($i.id === note.userId || $i.id === appearNote.userId)) || (appearNote.myReaction != null))); const keymap = { 'r': () => reply(true), From 60f48f5bb9661472f577f65c4696afe813b2c90b Mon Sep 17 00:00:00 2001 From: akanevrc <93204493+akanevrc@users.noreply.github.com> Date: Mon, 10 Jul 2023 13:26:05 +0900 Subject: [PATCH 015/284] =?UTF-8?q?fix(frontend):=20=E7=94=BB=E9=9D=A2?= =?UTF-8?q?=E3=83=93=E3=83=A5=E3=83=BC=E3=83=AF=E3=82=92=E3=82=BF=E3=83=83?= =?UTF-8?q?=E3=83=97=E3=81=97=E3=81=9F=E5=A0=B4=E5=90=88=E3=80=81=E3=83=9E?= =?UTF-8?q?=E3=82=A6=E3=82=B9=E3=82=AF=E3=83=AA=E3=83=83=E3=82=AF=E3=81=A8?= =?UTF-8?q?=E5=90=8C=E6=A7=98=E3=81=AB=E7=94=BB=E5=83=8F=E3=83=93=E3=83=A5?= =?UTF-8?q?=E3=83=BC=E3=83=AF=E3=82=92=E9=96=89=E3=81=98=E3=82=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB=20(#11211)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: change tapAction of photoswipe to 'close' * doc: update CHANGELOG.md --------- Co-authored-by: tamaina Cherry-pics: 63e21a4ee3b4f97d17dedcec387ce5cdd2e5e518 --- CHANGELOG.md | 1 + packages/frontend/src/components/MkMediaList.vue | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60a9b4de2c2b..0ecb6b3ede33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ - フォローやお気に入り登録をしていないチャンネルを開く時は概要ページを開くように - 引用対象を「もっと見る」で展開した場合、「閉じる」で畳めるように - Renote時に公開範囲のデフォルト設定が適用されるように +- 画面ビューワをタップした場合、マウスクリックと同様に画像ビューワを閉じるように - Fix: 長い文章を投稿する際、プレビューが画面からはみ出る問題を修正 ### Server diff --git a/packages/frontend/src/components/MkMediaList.vue b/packages/frontend/src/components/MkMediaList.vue index a0a2450054b1..16328e1a3f4f 100644 --- a/packages/frontend/src/components/MkMediaList.vue +++ b/packages/frontend/src/components/MkMediaList.vue @@ -113,7 +113,7 @@ onMounted(() => { right: 0, }, imageClickAction: 'close', - tapAction: 'toggle-controls', + tapAction: 'close', bgOpacity: 1, pswpModule: PhotoSwipe, }); From a80c60bdc5f96e1e06da88b3d4d19e8f5610b7fb Mon Sep 17 00:00:00 2001 From: niwaniwa Date: Fri, 14 Jul 2023 16:12:58 +0900 Subject: [PATCH 016/284] 13.13.2-kinel-0.0.1 --- CHANGELOG.md | 2 +- package.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ecb6b3ede33..7f1970dee932 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ --> -## 13.x.x (unreleased) +## 13.13.2-kinel-0.0.1 ### General diff --git a/package.json b/package.json index dd0c1d57e7a7..6fa64ca105d9 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { "name": "misskey", - "version": "13.13.2", + "version": "13.13.2-kinel-0.0.1", "codename": "nasubi", "repository": { "type": "git", - "url": "https://github.com/misskey-dev/misskey.git" + "url": "https://github.com/niri-la/misskey.niri.la" }, "packageManager": "pnpm@8.6.0", "workspaces": [ From 1fb6dc05afdf0a6e0ef5f806222afadca729678d Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Fri, 21 Jul 2023 21:52:39 +0900 Subject: [PATCH 017/284] chore: bump version to 13.14.1-kinel.1 --- CHANGELOG.md | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cfb12963bf9b..2d0d85ee1bea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ --> -## 13.14.1 +## 13.14.1-kinel.1 ### General - 招待機能を改善しました diff --git a/package.json b/package.json index cf71738d20b7..ac1522a26c38 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "13.14.1", + "version": "13.14.1-kinel.1", "codename": "nasubi", "repository": { "type": "git", From 5c50a677e86414de0fddf4c50d60debff6d1bead Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Sat, 22 Jul 2023 16:07:11 +0900 Subject: [PATCH 018/284] feat: keep show showPreview --- packages/frontend/src/components/MkPostForm.vue | 3 ++- packages/frontend/src/store.ts | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/frontend/src/components/MkPostForm.vue b/packages/frontend/src/components/MkPostForm.vue index f516ccbad818..daf20039983b 100644 --- a/packages/frontend/src/components/MkPostForm.vue +++ b/packages/frontend/src/components/MkPostForm.vue @@ -166,7 +166,8 @@ let poll = $ref<{ expiredAfter: string | null; } | null>(null); let useCw = $ref(false); -let showPreview = $ref(false); +let showPreview = $ref(defaultStore.state.showPreview); +watch($$(showPreview), () => defaultStore.set('showPreview', showPreview)); let cw = $ref(null); let localOnly = $ref(props.initialLocalOnly ?? defaultStore.state.rememberNoteVisibility ? defaultStore.state.localOnly : defaultStore.state.defaultNoteLocalOnly); let visibility = $ref(props.initialVisibility ?? (defaultStore.state.rememberNoteVisibility ? defaultStore.state.visibility : defaultStore.state.defaultNoteVisibility) as typeof misskey.noteVisibilities[number]); diff --git a/packages/frontend/src/store.ts b/packages/frontend/src/store.ts index 6ba05c36abbd..52421330adbd 100644 --- a/packages/frontend/src/store.ts +++ b/packages/frontend/src/store.ts @@ -130,6 +130,10 @@ export const defaultStore = markRaw(new Storage('base', { where: 'deviceAccount', default: false, }, + showPreview: { + where: 'deviceAccount', + default: false, + }, statusbars: { where: 'deviceAccount', default: [] as { From f2fffd64e33905639c3be85e67a9b74b2c592048 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Sat, 22 Jul 2023 16:08:51 +0900 Subject: [PATCH 019/284] =?UTF-8?q?docs(changelog):=20add=20=E3=83=97?= =?UTF-8?q?=E3=83=AC=E3=83=93=E3=83=A5=E3=83=BC=E3=81=AE=E8=A1=A8=E7=A4=BA?= =?UTF-8?q?=E3=81=97=E3=81=9F=E7=8A=B6=E6=85=8B=E3=82=92=E3=82=92=E3=83=80?= =?UTF-8?q?=E3=82=A4=E3=82=A2=E3=83=AD=E3=82=B0=E3=82=92=E9=96=89=E3=81=98?= =?UTF-8?q?=E3=81=A6=E3=82=82=E4=BF=9D=E5=AD=98=E3=81=99=E3=82=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 35c01aff0762..9fd2164513ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,15 @@ --> +## 13.x.x (unreleased) + +### General + +### Client +- プレビューの表示状態を記憶するように + +### Server + ## 13.14.1 ### General From 009a8c434513bf3db1d8a08e16f025fc2270f7e6 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Mon, 24 Jul 2023 12:07:31 +0900 Subject: [PATCH 020/284] feat: admin only note on other user webhooks --- .../backend/src/core/NoteCreateService.ts | 3 ++- packages/backend/src/core/QueueService.ts | 4 ++-- .../backend/src/models/entities/Webhook.ts | 3 ++- .../server/api/endpoints/i/webhooks/create.ts | 20 ++++++++++++++--- .../server/api/endpoints/i/webhooks/update.ts | 22 ++++++++++++++++--- 5 files changed, 42 insertions(+), 10 deletions(-) diff --git a/packages/backend/src/core/NoteCreateService.ts b/packages/backend/src/core/NoteCreateService.ts index 1c8491bf573b..78be741fa515 100644 --- a/packages/backend/src/core/NoteCreateService.ts +++ b/packages/backend/src/core/NoteCreateService.ts @@ -554,7 +554,8 @@ export class NoteCreateService implements OnApplicationShutdown { this.roleService.addNoteToRoleTimeline(noteObj); this.webhookService.getActiveWebhooks().then(webhooks => { - webhooks = webhooks.filter(x => x.userId === user.id && x.on.includes('note')); + const userNoteEvent = `note@${user.username}` as const; + webhooks = webhooks.filter(x => (x.userId === user.id && x.on.includes('note')) || x.on.includes(userNoteEvent)); for (const webhook of webhooks) { this.queueService.webhookDeliver(webhook, 'note', { note: noteObj, diff --git a/packages/backend/src/core/QueueService.ts b/packages/backend/src/core/QueueService.ts index 2ae8a2b7548f..837bc8dad955 100644 --- a/packages/backend/src/core/QueueService.ts +++ b/packages/backend/src/core/QueueService.ts @@ -2,7 +2,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { v4 as uuid } from 'uuid'; import type { IActivity } from '@/core/activitypub/type.js'; import type { DriveFile } from '@/models/entities/DriveFile.js'; -import type { Webhook, webhookEventTypes } from '@/models/entities/Webhook.js'; +import type { Webhook, WebhookEventType } from '@/models/entities/Webhook.js'; import type { Config } from '@/config.js'; import { DI } from '@/di-symbols.js'; import { bindThis } from '@/decorators.js'; @@ -373,7 +373,7 @@ export class QueueService { } @bindThis - public webhookDeliver(webhook: Webhook, type: typeof webhookEventTypes[number], content: unknown) { + public webhookDeliver(webhook: Webhook, type: WebhookEventType, content: unknown) { const data = { type, content, diff --git a/packages/backend/src/models/entities/Webhook.ts b/packages/backend/src/models/entities/Webhook.ts index eabb604de94f..39fb04bc5abf 100644 --- a/packages/backend/src/models/entities/Webhook.ts +++ b/packages/backend/src/models/entities/Webhook.ts @@ -3,6 +3,7 @@ import { id } from '../id.js'; import { User } from './User.js'; export const webhookEventTypes = ['mention', 'unfollow', 'follow', 'followed', 'note', 'reply', 'renote', 'reaction'] as const; +export type WebhookEventType = (typeof webhookEventTypes)[number] | `note@${string}`; @Entity() export class Webhook { @@ -37,7 +38,7 @@ export class Webhook { @Column('varchar', { length: 128, array: true, default: '{}', }) - public on: (typeof webhookEventTypes)[number][]; + public on: WebhookEventType[]; @Column('varchar', { length: 1024, 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 51fcce6cf006..c72257d3babf 100644 --- a/packages/backend/src/server/api/endpoints/i/webhooks/create.ts +++ b/packages/backend/src/server/api/endpoints/i/webhooks/create.ts @@ -2,7 +2,7 @@ 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 { webhookEventTypes, WebhookEventType } from '@/models/entities/Webhook.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; import { RoleService } from '@/core/RoleService.js'; @@ -21,6 +21,11 @@ export const meta = { code: 'TOO_MANY_WEBHOOKS', id: '87a9bb19-111e-4e37-81d3-a3e7426453b0', }, + adminWebhookDenied: { + message: 'You cannot create webhook for other users.', + code: 'ADMIN_WEBHOOK_DENIED', + id: '0d3321b1-6f66-41aa-9fbe-233c60ce19b0', + }, }, } as const; @@ -31,7 +36,10 @@ export const paramDef = { url: { type: 'string', minLength: 1, maxLength: 1024 }, secret: { type: 'string', minLength: 1, maxLength: 1024 }, on: { type: 'array', items: { - type: 'string', enum: webhookEventTypes, + oneOf: [ + { type: 'string', enum: webhookEventTypes }, + { type: 'string', pattern: '^note@[a-zA-Z0-9]{1,20}$' }, + ], } }, }, required: ['name', 'url', 'secret', 'on'], @@ -58,6 +66,12 @@ export default class extends Endpoint { throw new ApiError(meta.errors.tooManyWebhooks); } + if (ps.on.some(x => !(webhookEventTypes as readonly string[]).includes(x))) { + if (!await this.roleService.isAdministrator(me)) { + throw new ApiError(meta.errors.adminWebhookDenied); + } + } + const webhook = await this.webhooksRepository.insert({ id: this.idService.genId(), createdAt: new Date(), @@ -65,7 +79,7 @@ export default class extends Endpoint { name: ps.name, url: ps.url, secret: ps.secret, - on: ps.on, + on: ps.on as WebhookEventType[], }).then(x => this.webhooksRepository.findOneByOrFail(x.identifiers[0])); this.globalEventService.publishInternalEvent('webhookCreated', webhook); 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 8ec308eda777..18601c994158 100644 --- a/packages/backend/src/server/api/endpoints/i/webhooks/update.ts +++ b/packages/backend/src/server/api/endpoints/i/webhooks/update.ts @@ -1,9 +1,10 @@ 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 { webhookEventTypes, WebhookEventType } from '@/models/entities/Webhook.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; +import { RoleService } from '@/core/RoleService.js'; import { ApiError } from '../../../error.js'; export const meta = { @@ -19,6 +20,11 @@ export const meta = { code: 'NO_SUCH_WEBHOOK', id: 'fb0fea69-da18-45b1-828d-bd4fd1612518', }, + adminWebhookDenied: { + message: 'You cannot create webhook for other users.', + code: 'UPDATE_ADMIN_WEBHOOK_DENIED', + id: 'eb43c0c4-24a3-487d-b139-f3e4e58f87a4', + }, }, } as const; @@ -31,7 +37,10 @@ export const paramDef = { url: { type: 'string', minLength: 1, maxLength: 1024 }, secret: { type: 'string', minLength: 1, maxLength: 1024 }, on: { type: 'array', items: { - type: 'string', enum: webhookEventTypes, + oneOf: [ + { type: 'string', enum: webhookEventTypes }, + { type: 'string', pattern: '^note@[a-zA-Z0-9]{1,20}$' }, + ], } }, active: { type: 'boolean' }, }, @@ -48,6 +57,7 @@ export default class extends Endpoint { private webhooksRepository: WebhooksRepository, private globalEventService: GlobalEventService, + private roleService: RoleService, ) { super(meta, paramDef, async (ps, me) => { const webhook = await this.webhooksRepository.findOneBy({ @@ -59,11 +69,17 @@ export default class extends Endpoint { throw new ApiError(meta.errors.noSuchWebhook); } + if (ps.on.some(x => !(webhookEventTypes as readonly string[]).includes(x))) { + if (!await this.roleService.isAdministrator(me)) { + throw new ApiError(meta.errors.adminWebhookDenied); + } + } + await this.webhooksRepository.update(webhook.id, { name: ps.name, url: ps.url, secret: ps.secret, - on: ps.on, + on: ps.on as WebhookEventType[], active: ps.active, }); From c2633e807ffe0c3ccf0862be83b2c9d0ef862d24 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Mon, 24 Jul 2023 15:14:13 +0900 Subject: [PATCH 021/284] feat(frontend): create admin only webhook --- locales/index.d.ts | 2 ++ locales/ja-JP.yml | 2 ++ .../src/pages/settings/webhook.edit.vue | 19 ++++++++++++++++++- .../src/pages/settings/webhook.new.vue | 11 ++++++++++- 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/locales/index.d.ts b/locales/index.d.ts index 4763d21400ce..717f2edb38e2 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -2144,6 +2144,8 @@ export interface Locale { "renote": string; "reaction": string; "mention": string; + "usersLabel": string; + "usersCaption": string; }; }; } diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 587fabdf04ba..25496aae8930 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -2059,3 +2059,5 @@ _webhookSettings: renote: "Renoteされたとき" reaction: "リアクションがあったとき" mention: "メンションされたとき" + usersLabel: "以下のユーザがnoteしたとき" + usersCaption: "このサーバーのユーザの@に挟まれた部分を改行で区切って指定します" diff --git a/packages/frontend/src/pages/settings/webhook.edit.vue b/packages/frontend/src/pages/settings/webhook.edit.vue index 3c782973aec6..b76fc7c6af69 100644 --- a/packages/frontend/src/pages/settings/webhook.edit.vue +++ b/packages/frontend/src/pages/settings/webhook.edit.vue @@ -24,6 +24,11 @@ {{ i18n.ts._webhookSettings._events.renote }} {{ i18n.ts._webhookSettings._events.reaction }} {{ i18n.ts._webhookSettings._events.mention }} + + + + + @@ -46,6 +51,8 @@ import * as os from '@/os'; import { i18n } from '@/i18n'; import { definePageMetadata } from '@/scripts/page-metadata'; import { useRouter } from '@/router'; +import { $i } from '@/account'; +import MkTextarea from '@/components/MkTextarea.vue'; const router = useRouter(); @@ -69,9 +76,10 @@ let event_reply = $ref(webhook.on.includes('reply')); let event_renote = $ref(webhook.on.includes('renote')); let event_reaction = $ref(webhook.on.includes('reaction')); let event_mention = $ref(webhook.on.includes('mention')); +let users = $ref((webhook.on as string[]).filter(x => x.startsWith('note@')).map(x => x.substring('note@'.length)).join('\n')); async function save(): Promise { - const events = []; + const events: string[] = []; if (event_follow) events.push('follow'); if (event_followed) events.push('followed'); if (event_note) events.push('note'); @@ -79,6 +87,7 @@ async function save(): Promise { if (event_renote) events.push('renote'); if (event_reaction) events.push('reaction'); if (event_mention) events.push('mention'); + if (users !== '') events.push(...users.split('\n').filter(x => x).map(x => `note@${x}`)); os.apiWithDialog('i/webhooks/update', { name, @@ -112,3 +121,11 @@ definePageMetadata({ icon: 'ti ti-webhook', }); + + diff --git a/packages/frontend/src/pages/settings/webhook.new.vue b/packages/frontend/src/pages/settings/webhook.new.vue index 6eb8a654f55d..b3728e876459 100644 --- a/packages/frontend/src/pages/settings/webhook.new.vue +++ b/packages/frontend/src/pages/settings/webhook.new.vue @@ -24,6 +24,11 @@ {{ i18n.ts._webhookSettings._events.renote }} {{ i18n.ts._webhookSettings._events.reaction }} {{ i18n.ts._webhookSettings._events.mention }} + + + + + @@ -42,6 +47,8 @@ import MkButton from '@/components/MkButton.vue'; import * as os from '@/os'; import { i18n } from '@/i18n'; import { definePageMetadata } from '@/scripts/page-metadata'; +import { $i } from '@/account'; +import MkTextarea from '@/components/MkTextarea.vue'; let name = $ref(''); let url = $ref(''); @@ -54,9 +61,10 @@ let event_reply = $ref(true); let event_renote = $ref(true); let event_reaction = $ref(true); let event_mention = $ref(true); +let users = $ref(''); async function create(): Promise { - const events = []; + const events: string[] = []; if (event_follow) events.push('follow'); if (event_followed) events.push('followed'); if (event_note) events.push('note'); @@ -64,6 +72,7 @@ async function create(): Promise { if (event_renote) events.push('renote'); if (event_reaction) events.push('reaction'); if (event_mention) events.push('mention'); + if (users !== '') events.push(...users.split('\n').filter(x => x).map(x => `note@${x}`)); os.apiWithDialog('i/webhooks/create', { name, From 355d40dc901446839621d542b529724f1cbaa844 Mon Sep 17 00:00:00 2001 From: ibuki2003 Date: Mon, 24 Jul 2023 20:16:37 +0900 Subject: [PATCH 022/284] feat: increase emoji picker search results --- CHANGELOG.md | 1 + packages/frontend/src/components/MkEmojiPicker.vue | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 00ca2982cd2a..70f7677bf866 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ ### Client - リストTLで、ユーザーが追加・削除されてもTLを初期化しないように +- 絵文字ピッカーの検索の表示件数を100件に増加 ### Server - diff --git a/packages/frontend/src/components/MkEmojiPicker.vue b/packages/frontend/src/components/MkEmojiPicker.vue index cf856fd31f0a..be7e38a34382 100644 --- a/packages/frontend/src/components/MkEmojiPicker.vue +++ b/packages/frontend/src/components/MkEmojiPicker.vue @@ -151,7 +151,7 @@ watch(q, () => { const newQ = q.value.replace(/:/g, '').toLowerCase(); const searchCustom = () => { - const max = 8; + const max = 100; const emojis = customEmojis.value; const matches = new Set(); @@ -214,7 +214,7 @@ watch(q, () => { }; const searchUnicode = () => { - const max = 8; + const max = 100; const emojis = emojilist; const matches = new Set(); From 2710f01be61e0f03c928b8b0754489caa7ee76bd Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Thu, 27 Jul 2023 13:44:13 +0900 Subject: [PATCH 023/284] chore: bump version to 13.14.2-kinel.1 --- CHANGELOG.md | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3814d56fe26d..52196147458a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ --> -## 13.14.1-kinel.1 +## 13.14.2-kinel.1 ### General - 招待機能を改善しました diff --git a/package.json b/package.json index 20b038520208..729700acba43 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "13.14.1-kinel.1", + "version": "13.14.2-kinel.1", "codename": "nasubi", "repository": { "type": "git", From 9edd865c2eb71eb11b1711ad25b526e5b9a29b38 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Thu, 27 Jul 2023 17:07:56 +0900 Subject: [PATCH 024/284] =?UTF-8?q?chore:=20=E3=83=8F=E3=82=A4=E3=83=A9?= =?UTF-8?q?=E3=82=A4=E3=83=88=E3=81=8B=E3=82=89=E5=86=99=E7=9C=9F=E3=81=AE?= =?UTF-8?q?=E3=81=AA=E3=81=84=E3=81=8A=E3=81=AFnote=E3=81=A8=E3=83=81?= =?UTF-8?q?=E3=83=A3=E3=83=B3=E3=83=8D=E3=83=AB=E6=8A=95=E7=A8=BF=E3=82=92?= =?UTF-8?q?=E9=99=A4=E5=A4=96=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 3 +++ .../src/server/api/endpoints/notes/featured.ts | 13 +++++++++++++ 2 files changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f1970dee932..ef831ed310af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,9 @@ --> +### Server +- + ## 13.13.2-kinel-0.0.1 ### General diff --git a/packages/backend/src/server/api/endpoints/notes/featured.ts b/packages/backend/src/server/api/endpoints/notes/featured.ts index bdb06498bc6f..ebe026c5a1dd 100644 --- a/packages/backend/src/server/api/endpoints/notes/featured.ts +++ b/packages/backend/src/server/api/endpoints/notes/featured.ts @@ -1,4 +1,5 @@ import { Inject, Injectable } from '@nestjs/common'; +import { Brackets } from 'typeorm'; import type { NotesRepository } from '@/models/index.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; @@ -60,6 +61,18 @@ export default class extends Endpoint { if (ps.channelId) query.andWhere('note.channelId = :channelId', { channelId: ps.channelId }); + if (!ps.channelId) { + // featured for welcome page. filter some notes + query.andWhere('note.channelId IS NULL', { channelId: ps.channelId }); + query.andWhere( + new Brackets(qb => { + qb.where('note.text NOT LIKE \'%おはよう%\'') + .andWhere('note.text NOT LIKE \'%:ohayo_nirila_misskey:%\'') + .orWhere('note.fileIds != \'{}\''); + }), + ); + } + if (me) this.queryService.generateMutedUserQuery(query, me); if (me) this.queryService.generateBlockedUserQuery(query, me); From 972a6e5964fe4cd0698d5cc198d290dd3179ff38 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Thu, 27 Jul 2023 17:14:02 +0900 Subject: [PATCH 025/284] docs: mark (unreleased) --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66c6dec58fa3..47f59b7864fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ --> -## 13.14.2-kinel.1 +## 13.14.2-kinel.1 (unreleased) ### General - 招待機能を改善しました From a41f97294747144b7fa626969de34362ff7a9e9e Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Thu, 27 Jul 2023 17:36:02 +0900 Subject: [PATCH 026/284] ci: remove reviewer_lottery and storybook test --- .github/workflows/reviewer_lottery.yml | 4 +--- .github/workflows/storybook.yml | 7 +------ 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/.github/workflows/reviewer_lottery.yml b/.github/workflows/reviewer_lottery.yml index 33228d7465a6..686e3300b2a7 100644 --- a/.github/workflows/reviewer_lottery.yml +++ b/.github/workflows/reviewer_lottery.yml @@ -1,7 +1,5 @@ name: "Reviewer lottery" -on: - pull_request_target: - types: [opened, ready_for_review, reopened] +on: {} jobs: test: diff --git a/.github/workflows/storybook.yml b/.github/workflows/storybook.yml index 6cb1b34997ed..978b35fd1aee 100644 --- a/.github/workflows/storybook.yml +++ b/.github/workflows/storybook.yml @@ -1,11 +1,6 @@ name: Storybook -on: - push: - branches: - - master - - develop - pull_request_target: +on: {} jobs: build: From 490e17ea6a49c89626832ab422fa33bcef6641bd Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Thu, 27 Jul 2023 17:46:48 +0900 Subject: [PATCH 027/284] =?UTF-8?q?docs(changelog):=20add=20=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E8=80=85=E5=B0=82=E7=94=A8=E3=81=AE=E4=BB=96=E4=BA=BA?= =?UTF-8?q?=E3=82=92=E8=A6=8B=E3=82=8Bwebhook=E3=81=8C=E5=A2=97=E3=81=88?= =?UTF-8?q?=E3=81=BE=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 47f59b7864fa..9fce11441df8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ - リストTLで、ユーザーが追加・削除されてもTLを初期化しないように - URL取得変数を関数に変更 CURRENT_URL -> Mk:url() - プレビューの表示状態を記憶するように +- 管理者専用の他人を見るwebhookが増えました - Fix: サーバーメトリクスが90度傾いている - Fix: 非ログイン時にクレデンシャルが必要なページに行くとエラーが出る問題を修正 - Fix: sparkle内にリンクを入れるとクリック不能になる問題の修正 From bbdc2aee9e50c44a694689f5f45063ba89f742fe Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Thu, 27 Jul 2023 19:22:07 +0900 Subject: [PATCH 028/284] =?UTF-8?q?feat:=20=E9=80=9A=E5=A0=B1=E3=82=92Disc?= =?UTF-8?q?ord=E3=81=AEWebhook=E3=81=AB=E9=80=81=E4=BF=A1=E3=81=A7?= =?UTF-8?q?=E3=81=8D=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + packages/backend/src/config.ts | 4 ++ .../src/core/AbuseDiscordHookService.ts | 40 +++++++++++++++++++ packages/backend/src/core/CoreModule.ts | 3 ++ .../src/core/activitypub/ApInboxService.ts | 8 +++- .../api/endpoints/users/report-abuse.ts | 4 ++ 6 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 packages/backend/src/core/AbuseDiscordHookService.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 47f59b7864fa..bfd9bb22c332 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -67,6 +67,7 @@ - Export notes with file detail - Add unix socket support - 設定ファイルでioredisの全てのオプションを指定可能に +- 通報をDiscordのWebhookに送信できるように - Fix: エクスポートしたカスタム絵文字のzipが大きいと読み込めない問題を修正 - Fix: リモートサーバーに無意味なActivityPubの配信を行うことがあるのを修正 - Fix: Remove Meilisearch index when notes are deleted diff --git a/packages/backend/src/config.ts b/packages/backend/src/config.ts index 253975096e2d..9252712c495b 100644 --- a/packages/backend/src/config.ts +++ b/packages/backend/src/config.ts @@ -87,6 +87,10 @@ export type Source = { videoThumbnailGenerator?: string; signToActivityPubGet?: boolean; + + nirila?: { + abuseDiscordHook: string; + } }; /** diff --git a/packages/backend/src/core/AbuseDiscordHookService.ts b/packages/backend/src/core/AbuseDiscordHookService.ts new file mode 100644 index 000000000000..be69bf17a8cf --- /dev/null +++ b/packages/backend/src/core/AbuseDiscordHookService.ts @@ -0,0 +1,40 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { DI } from '@/di-symbols.js'; +import type { User } from '@/models/entities/User.js'; +import { bindThis } from '@/decorators.js'; +import type { Config } from '@/config.js'; +import { HttpRequestService } from '@/core/HttpRequestService.js'; + +@Injectable() +export class AbuseDiscordHookService { + constructor( + @Inject(DI.config) + private config: Config, + + private httpRequestService: HttpRequestService, + ) { + } + + @bindThis + public send(me: User, user: User, comment: string): void { + const webhookUrl = this.config.nirila?.abuseDiscordHook; + if (webhookUrl) { + setImmediate(async () => { + const content = 'New abuse report created!\n' + + `author: \`@${me.username}${me.host ? `@${me.host}` : ''}\`\n` + + `target user: \`@${user.username}${user.host ? `@${user.host}` : ''}\`\n` + + 'Comment:\n' + + comment; + + await this.httpRequestService.send(webhookUrl, { + method: 'POST', + headers: { + 'User-Agent': 'Niri-la-Misskey-Hooks', + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ content }), + }); + }); + } + } +} diff --git a/packages/backend/src/core/CoreModule.ts b/packages/backend/src/core/CoreModule.ts index c7c98b3bdd71..31c7123d7f1a 100644 --- a/packages/backend/src/core/CoreModule.ts +++ b/packages/backend/src/core/CoreModule.ts @@ -118,6 +118,7 @@ import { ApQuestionService } from './activitypub/models/ApQuestionService.js'; import { QueueModule } from './QueueModule.js'; import { QueueService } from './QueueService.js'; import { LoggerService } from './LoggerService.js'; +import { AbuseDiscordHookService } from './AbuseDiscordHookService.js'; import type { Provider } from '@nestjs/common'; //#region 文字列ベースでのinjection用(循環参照対応のため) @@ -366,6 +367,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting ApPersonService, ApQuestionService, QueueService, + AbuseDiscordHookService, //#region 文字列ベースでのinjection用(循環参照対応のため) $LoggerService, @@ -606,6 +608,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting ApPersonService, ApQuestionService, QueueService, + AbuseDiscordHookService, //#region 文字列ベースでのinjection用(循環参照対応のため) $LoggerService, diff --git a/packages/backend/src/core/activitypub/ApInboxService.ts b/packages/backend/src/core/activitypub/ApInboxService.ts index 8d5f4883e4c5..8b80753a552e 100644 --- a/packages/backend/src/core/activitypub/ApInboxService.ts +++ b/packages/backend/src/core/activitypub/ApInboxService.ts @@ -24,6 +24,7 @@ import { QueueService } from '@/core/QueueService.js'; import type { UsersRepository, NotesRepository, FollowingsRepository, AbuseUserReportsRepository, FollowRequestsRepository } from '@/models/index.js'; import { bindThis } from '@/decorators.js'; import type { RemoteUser } from '@/models/entities/User.js'; +import { AbuseDiscordHookService } from '@/core/AbuseDiscordHookService.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'; @@ -81,6 +82,7 @@ export class ApInboxService { private accountMoveService: AccountMoveService, private cacheService: CacheService, private queueService: QueueService, + private abuseDiscordHookService: AbuseDiscordHookService, ) { this.logger = this.apLoggerService.logger; } @@ -512,6 +514,8 @@ export class ApInboxService { }); if (users.length < 1) return 'skip'; + const comment = `${activity.content}\n${JSON.stringify(uris, null, 2)}`; + await this.abuseUserReportsRepository.insert({ id: this.idService.genId(), createdAt: new Date(), @@ -519,9 +523,11 @@ export class ApInboxService { targetUserHost: users[0].host, reporterId: actor.id, reporterHost: actor.host, - comment: `${activity.content}\n${JSON.stringify(uris, null, 2)}`, + comment, }); + this.abuseDiscordHookService.send(actor, users[0], comment); + return 'ok'; } 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 be361e02c404..b2cbe8e2993a 100644 --- a/packages/backend/src/server/api/endpoints/users/report-abuse.ts +++ b/packages/backend/src/server/api/endpoints/users/report-abuse.ts @@ -9,6 +9,7 @@ import { EmailService } from '@/core/EmailService.js'; import { DI } from '@/di-symbols.js'; import { GetterService } from '@/server/api/GetterService.js'; import { RoleService } from '@/core/RoleService.js'; +import { AbuseDiscordHookService } from '@/core/AbuseDiscordHookService.js'; import { ApiError } from '../../error.js'; export const meta = { @@ -64,6 +65,7 @@ export default class extends Endpoint { private getterService: GetterService, private roleService: RoleService, private globalEventService: GlobalEventService, + private abuseDiscordHookService: AbuseDiscordHookService, ) { super(meta, paramDef, async (ps, me) => { // Lookup user @@ -110,6 +112,8 @@ export default class extends Endpoint { sanitizeHtml(ps.comment)); } }); + + this.abuseDiscordHookService.send(me, user, ps.comment); }); } } From c35883f18111a023d24fa1821c28267615c80acb Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Thu, 27 Jul 2023 19:49:59 +0900 Subject: [PATCH 029/284] =?UTF-8?q?docs:=20=E7=AE=A1=E7=90=86=E8=80=85?= =?UTF-8?q?=E5=B0=82=E7=94=A8=E3=81=AE=E4=BB=96=E4=BA=BA=E3=82=92=E8=A6=8B?= =?UTF-8?q?=E3=82=8Bwebhook=E3=81=8C=E5=A2=97=E3=81=88=E3=81=BE=E3=81=97?= =?UTF-8?q?=E3=81=9F=E3=81=AE=E5=A0=B4=E6=89=80=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9fce11441df8..02f4ad27ad27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ - ユーザーにロールが期限付きでアサインされている場合、その期限をユーザーのモデレーションページで確認できるようになりました - identicon生成を無効にしてパフォーマンスを向上させることができるようになりました - サーバーのマシン情報の公開を無効にしてパフォーマンスを向上させることができるようになりました +- 管理者専用の他人を見るwebhookが増えました ### Client - ドライブファイルのメニューで画像をクロップできるように @@ -42,7 +43,6 @@ - リストTLで、ユーザーが追加・削除されてもTLを初期化しないように - URL取得変数を関数に変更 CURRENT_URL -> Mk:url() - プレビューの表示状態を記憶するように -- 管理者専用の他人を見るwebhookが増えました - Fix: サーバーメトリクスが90度傾いている - Fix: 非ログイン時にクレデンシャルが必要なページに行くとエラーが出る問題を修正 - Fix: sparkle内にリンクを入れるとクリック不能になる問題の修正 From fef4d712ff384a0557a3afd0d21c8b230ac638de Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Thu, 27 Jul 2023 20:45:15 +0900 Subject: [PATCH 030/284] =?UTF-8?q?docs:=20=E7=8B=AC=E8=87=AA=E3=81=AE?= =?UTF-8?q?=E5=A4=89=E6=9B=B4=E3=82=92=E3=82=8F=E3=81=8B=E3=82=8A=E3=82=84?= =?UTF-8?q?=E3=81=99=E3=81=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5420e8637769..72192396886c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ - ユーザーにロールが期限付きでアサインされている場合、その期限をユーザーのモデレーションページで確認できるようになりました - identicon生成を無効にしてパフォーマンスを向上させることができるようになりました - サーバーのマシン情報の公開を無効にしてパフォーマンスを向上させることができるようになりました + - 管理者専用の他人を見るwebhookが増えました - ハイライトからおはnoteとチャンネル投稿を除外するようになりました @@ -43,8 +44,6 @@ - AiScriptを0.15.0に更新 - リストTLで、ユーザーが追加・削除されてもTLを初期化しないように - URL取得変数を関数に変更 CURRENT_URL -> Mk:url() -- プレビューの表示状態を記憶するように -- 絵文字ピッカーの検索の表示件数を100件に増加 - Fix: サーバーメトリクスが90度傾いている - Fix: 非ログイン時にクレデンシャルが必要なページに行くとエラーが出る問題を修正 - Fix: sparkle内にリンクを入れるとクリック不能になる問題の修正 @@ -59,6 +58,9 @@ - Fix: Selecting all emojis in Custom emoji is impossible - Fix: PhotoSwipeによるメモリリークの修正 +- プレビューの表示状態を記憶するように +- 絵文字ピッカーの検索の表示件数を100件に増加 + ### Server - JSON.parse の回数を削減することで、ストリーミングのパフォーマンスを向上しました - nsfwjs のモデルロードを排他することで、重複ロードによってメモリ使用量が増加しないように @@ -70,7 +72,6 @@ - Export notes with file detail - Add unix socket support - 設定ファイルでioredisの全てのオプションを指定可能に -- 通報をDiscordのWebhookに送信できるように - Fix: エクスポートしたカスタム絵文字のzipが大きいと読み込めない問題を修正 - Fix: リモートサーバーに無意味なActivityPubの配信を行うことがあるのを修正 - Fix: Remove Meilisearch index when notes are deleted @@ -81,6 +82,8 @@ - Fix: APIのオフセットが壊れていたせいで「もっと見る」でもっと見れない問題を修正 - Fix: 外部サーバーの投稿がタイムラインに表示されないことがある問題を修正 +- 通報をDiscordのWebhookに送信できるように + ## 13.13.2-kinel-0.0.1 ### General From 574f4d803f506e14c9f1ea9cc668cd5d397a2e1a Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Thu, 27 Jul 2023 20:51:44 +0900 Subject: [PATCH 031/284] release 13.14.2-kinel.1 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72192396886c..3657e3afc783 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ --> -## 13.14.2-kinel.1 (unreleased) +## 13.14.2-kinel.1 ### General - 招待機能を改善しました From 0f21568cf107d1f6c834d1673f1b612b2a7e04a0 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Mon, 31 Jul 2023 13:59:27 +0900 Subject: [PATCH 032/284] =?UTF-8?q?fix:=20=E3=81=8A=E3=81=AFnote=E3=81=AE?= =?UTF-8?q?=E9=99=A4=E5=A4=96=E3=81=A7cw=E3=82=92=E8=A6=8B=E5=BF=98?= =?UTF-8?q?=E3=82=8C=E3=81=A6=E3=81=84=E3=82=8B=E3=81=AE=E3=82=92=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/backend/src/server/api/endpoints/notes/featured.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/backend/src/server/api/endpoints/notes/featured.ts b/packages/backend/src/server/api/endpoints/notes/featured.ts index 1979c4c08e87..85ac02fed450 100644 --- a/packages/backend/src/server/api/endpoints/notes/featured.ts +++ b/packages/backend/src/server/api/endpoints/notes/featured.ts @@ -68,6 +68,8 @@ export default class extends Endpoint { new Brackets(qb => { qb.where('note.text NOT LIKE \'%おはよう%\'') .andWhere('note.text NOT LIKE \'%:ohayo_nirila_misskey:%\'') + .andWhere('note.cw NOT LIKE \'%おはよう%\'') + .andWhere('note.cw NOT LIKE \'%:ohayo_nirila_misskey:%\'') .orWhere('note.fileIds != \'{}\''); }), ); From bb8abb0db37e7dbdf9781db5da16523cd9712571 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Wed, 2 Aug 2023 20:53:53 +0900 Subject: [PATCH 033/284] feat: disableAbuseRepository in server config --- packages/backend/src/config.ts | 1 + .../backend/src/server/api/endpoints/users/report-abuse.ts | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/backend/src/config.ts b/packages/backend/src/config.ts index 9252712c495b..b942fa2c9340 100644 --- a/packages/backend/src/config.ts +++ b/packages/backend/src/config.ts @@ -90,6 +90,7 @@ export type Source = { nirila?: { abuseDiscordHook: string; + disableAbuseRepository: string; } }; 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 b2cbe8e2993a..f15a9dd8ae54 100644 --- a/packages/backend/src/server/api/endpoints/users/report-abuse.ts +++ b/packages/backend/src/server/api/endpoints/users/report-abuse.ts @@ -10,6 +10,7 @@ import { DI } from '@/di-symbols.js'; import { GetterService } from '@/server/api/GetterService.js'; import { RoleService } from '@/core/RoleService.js'; import { AbuseDiscordHookService } from '@/core/AbuseDiscordHookService.js'; +import type { Config } from '@/config.js'; import { ApiError } from '../../error.js'; export const meta = { @@ -58,6 +59,8 @@ export default class extends Endpoint { @Inject(DI.abuseUserReportsRepository) private abuseUserReportsRepository: AbuseUserReportsRepository, + @Inject(DI.config) + private config: Config, private idService: IdService, private metaService: MetaService, @@ -106,7 +109,7 @@ export default class extends Endpoint { } const meta = await this.metaService.fetch(); - if (meta.email) { + if (meta.email && !config.nirila?.disableAbuseRepository) { this.emailService.sendEmail(meta.email, 'New abuse report', sanitizeHtml(ps.comment), sanitizeHtml(ps.comment)); From 00f21cf516990c259fe541317f5549442f0daa65 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Wed, 2 Aug 2023 21:08:59 +0900 Subject: [PATCH 034/284] fix: disableAbuseRepository type --- packages/backend/src/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/config.ts b/packages/backend/src/config.ts index b942fa2c9340..a41fd8b38aa1 100644 --- a/packages/backend/src/config.ts +++ b/packages/backend/src/config.ts @@ -90,7 +90,7 @@ export type Source = { nirila?: { abuseDiscordHook: string; - disableAbuseRepository: string; + disableAbuseRepository?: boolean; } }; From d6194d40988b689426a51374aa9fb17214aabb69 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Sat, 5 Aug 2023 13:58:31 +0900 Subject: [PATCH 035/284] feat: sensitive channel (#11438) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(backend): add isSensitive to Channel * feat(backend): support isSensitive in channel endpoints * feat(frontend/channel-editor): support isSensitive in create/edit channel page * feat(frontend/channel): show sensitive indicator for sensitive channels * docs(changelog): add チャンネルをセンシティブ指定できるようになりました * chore: license header for each file * chore: add isSensitive of channel to Note object --- CHANGELOG.md | 1 + .../migration/1690782653311-SensitiveChannel.js | 17 +++++++++++++++++ .../src/core/entities/ChannelEntityService.ts | 1 + .../src/core/entities/NoteEntityService.ts | 1 + packages/backend/src/models/entities/Channel.ts | 5 +++++ .../backend/src/models/json-schema/channel.ts | 4 ++++ packages/backend/src/models/json-schema/note.ts | 4 ++++ .../src/server/api/endpoints/channels/create.ts | 2 ++ .../src/server/api/endpoints/channels/update.ts | 2 ++ .../src/components/MkChannelPreview.vue | 14 ++++++++++++++ packages/frontend/src/pages/channel-editor.vue | 8 ++++++++ packages/frontend/src/pages/channel.vue | 14 ++++++++++++++ 12 files changed, 73 insertions(+) create mode 100644 packages/backend/migration/1690782653311-SensitiveChannel.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 3657e3afc783..c63204ee7edc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ - ユーザーにロールが期限付きでアサインされている場合、その期限をユーザーのモデレーションページで確認できるようになりました - identicon生成を無効にしてパフォーマンスを向上させることができるようになりました - サーバーのマシン情報の公開を無効にしてパフォーマンスを向上させることができるようになりました +- チャンネルをセンシティブ指定できるようになりました - 管理者専用の他人を見るwebhookが増えました - ハイライトからおはnoteとチャンネル投稿を除外するようになりました diff --git a/packages/backend/migration/1690782653311-SensitiveChannel.js b/packages/backend/migration/1690782653311-SensitiveChannel.js new file mode 100644 index 000000000000..e76dda518073 --- /dev/null +++ b/packages/backend/migration/1690782653311-SensitiveChannel.js @@ -0,0 +1,17 @@ +/* + * SPDX-FileCopyrightText: syuilo and other misskey contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +export class SensitiveChannel1690782653311 { + name = 'SensitiveChannel1690782653311' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "channel" + ADD "isSensitive" boolean NOT NULL DEFAULT false`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "channel" DROP COLUMN "isSensitive"`); + } +} diff --git a/packages/backend/src/core/entities/ChannelEntityService.ts b/packages/backend/src/core/entities/ChannelEntityService.ts index de99ce72c436..0be200554855 100644 --- a/packages/backend/src/core/entities/ChannelEntityService.ts +++ b/packages/backend/src/core/entities/ChannelEntityService.ts @@ -87,6 +87,7 @@ export class ChannelEntityService { isArchived: channel.isArchived, usersCount: channel.usersCount, notesCount: channel.notesCount, + isSensitive: channel.isSensitive, ...(me ? { isFollowing, diff --git a/packages/backend/src/core/entities/NoteEntityService.ts b/packages/backend/src/core/entities/NoteEntityService.ts index 546e5f56d2a2..c9ba9b227f52 100644 --- a/packages/backend/src/core/entities/NoteEntityService.ts +++ b/packages/backend/src/core/entities/NoteEntityService.ts @@ -334,6 +334,7 @@ export class NoteEntityService implements OnModuleInit { id: channel.id, name: channel.name, color: channel.color, + isSensitive: channel.isSensitive, } : undefined, mentions: note.mentions.length > 0 ? note.mentions : undefined, uri: note.uri ?? undefined, diff --git a/packages/backend/src/models/entities/Channel.ts b/packages/backend/src/models/entities/Channel.ts index d7c4583da34c..e5e2b579aa2a 100644 --- a/packages/backend/src/models/entities/Channel.ts +++ b/packages/backend/src/models/entities/Channel.ts @@ -89,4 +89,9 @@ export class Channel { comment: 'The count of users.', }) public usersCount: number; + + @Column('boolean', { + default: false, + }) + public isSensitive: boolean; } diff --git a/packages/backend/src/models/json-schema/channel.ts b/packages/backend/src/models/json-schema/channel.ts index fd61a70c0ecc..996888724b0f 100644 --- a/packages/backend/src/models/json-schema/channel.ts +++ b/packages/backend/src/models/json-schema/channel.ts @@ -67,5 +67,9 @@ export const packedChannelSchema = { type: 'string', optional: false, nullable: false, }, + isSensitive: { + type: 'boolean', + optional: false, nullable: false, + }, }, } as const; diff --git a/packages/backend/src/models/json-schema/note.ts b/packages/backend/src/models/json-schema/note.ts index 58ef425dcdfa..3d6067a7df88 100644 --- a/packages/backend/src/models/json-schema/note.ts +++ b/packages/backend/src/models/json-schema/note.ts @@ -134,6 +134,10 @@ export const packedNoteSchema = { type: 'string', optional: false, nullable: true, }, + isSensitive: { + type: 'boolean', + optional: true, nullable: false, + } }, }, }, diff --git a/packages/backend/src/server/api/endpoints/channels/create.ts b/packages/backend/src/server/api/endpoints/channels/create.ts index 69e2f2504c67..371033231dea 100644 --- a/packages/backend/src/server/api/endpoints/channels/create.ts +++ b/packages/backend/src/server/api/endpoints/channels/create.ts @@ -44,6 +44,7 @@ export const paramDef = { description: { type: 'string', nullable: true, minLength: 1, maxLength: 2048 }, bannerId: { type: 'string', format: 'misskey:id', nullable: true }, color: { type: 'string', minLength: 1, maxLength: 16 }, + isSensitive: { type: 'boolean', nullable: true }, }, required: ['name'], } as const; @@ -81,6 +82,7 @@ export default class extends Endpoint { name: ps.name, description: ps.description ?? null, bannerId: banner ? banner.id : null, + isSensitive: ps.isSensitive ?? false, ...(ps.color !== undefined ? { color: ps.color } : {}), } as Channel).then(x => this.channelsRepository.findOneByOrFail(x.identifiers[0])); diff --git a/packages/backend/src/server/api/endpoints/channels/update.ts b/packages/backend/src/server/api/endpoints/channels/update.ts index 30d7f8b244e7..e1e8df811191 100644 --- a/packages/backend/src/server/api/endpoints/channels/update.ts +++ b/packages/backend/src/server/api/endpoints/channels/update.ts @@ -55,6 +55,7 @@ export const paramDef = { }, }, color: { type: 'string', minLength: 1, maxLength: 16 }, + isSensitive: { type: 'boolean', nullable: true }, }, required: ['channelId'], } as const; @@ -109,6 +110,7 @@ export default class extends Endpoint { ...(ps.color !== undefined ? { color: ps.color } : {}), ...(typeof ps.isArchived === 'boolean' ? { isArchived: ps.isArchived } : {}), ...(banner ? { bannerId: banner.id } : {}), + ...(typeof ps.isSensitive === 'boolean' ? { isSensitive: ps.isSensitive } : {}), }); return await this.channelEntityService.pack(channel.id, me); diff --git a/packages/frontend/src/components/MkChannelPreview.vue b/packages/frontend/src/components/MkChannelPreview.vue index 6ef50bddcfc0..422a5847be16 100644 --- a/packages/frontend/src/components/MkChannelPreview.vue +++ b/packages/frontend/src/components/MkChannelPreview.vue @@ -3,6 +3,7 @@
- +
@@ -206,7 +206,7 @@ const renoteTime = shallowRef(); const reactButton = shallowRef(); const clipButton = shallowRef(); let appearNote = $computed(() => isRenote ? note.renote as Misskey.entities.Note : note); -const sensitiveChannelCW = collapseSensitiveChannel && appearNote.cw == null && note.channel?.isSensitive; +const sensitiveChannelCW = collapseSensitiveChannel && appearNote.cw == null && appearNote.channel?.isSensitive; const cwExists = sensitiveChannelCW || appearNote.cw != null; const isMyRenote = $i && ($i.id === note.userId); const showContent = ref(false); diff --git a/packages/frontend/src/scripts/get-note-summary.ts b/packages/frontend/src/scripts/get-note-summary.ts index 1fd9f04d4616..2b0c74173cfd 100644 --- a/packages/frontend/src/scripts/get-note-summary.ts +++ b/packages/frontend/src/scripts/get-note-summary.ts @@ -10,7 +10,7 @@ import { i18n } from '@/i18n.js'; * 投稿を表す文字列を取得します。 * @param {*} note (packされた)投稿 */ -export const getNoteSummary = (note: Misskey.entities.Note): string => { +export const getNoteSummary = (note: Misskey.entities.Note, sensitiveChannelCW?: boolean): string => { if (note.deletedAt) { return `(${i18n.ts.deletedNote})`; } @@ -19,6 +19,10 @@ export const getNoteSummary = (note: Misskey.entities.Note): string => { return `(${i18n.ts.invisibleNote})`; } + if (sensitiveChannelCW) { + return i18n.ts.sensitiveChannelAutoCW; + } + let summary = ''; // 本文 From a6be950953a0550d9c154c22e5c3aa478d95f676 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Thu, 12 Oct 2023 13:16:08 +0900 Subject: [PATCH 133/284] =?UTF-8?q?docs(changelog):=20Renote=E3=81=AE?= =?UTF-8?q?=E7=9C=81=E7=95=A5=E8=A1=A8=E7=A4=BA=E3=81=A7=E3=82=BB=E3=83=B3?= =?UTF-8?q?=E3=82=B7=E3=83=86=E3=82=A3=E3=83=96=E3=83=81=E3=83=A3=E3=83=B3?= =?UTF-8?q?=E3=83=8D=E3=83=AB=E3=81=AE=E8=87=AA=E5=8B=95CW=E3=81=8C?= =?UTF-8?q?=E8=81=9E=E3=81=8B=E3=81=AA=E3=81=84=E5=95=8F=E9=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4f9e3a11b55..7f9d7da0a882 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ ### General ### Client +- Fix: Renoteの省略表示でセンシティブチャンネルの自動CWが聞かない問題 ### Server From 3fe6c54e183096dd0a8c421ee012d3bcfe96c26e Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Wed, 18 Oct 2023 10:18:56 +0900 Subject: [PATCH 134/284] 2023.9.3-kinel.4 --- CHANGELOG.md | 4 +--- package.json | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e749ede62be4..49ca213a44ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,9 +12,7 @@ --> -## 2023.9.3-kinel.4 (unreleased) - -### General +## 2023.9.3-kinel.4 ### Client - Fix: Renoteの省略表示でセンシティブチャンネルの自動CWが聞かない問題 diff --git a/package.json b/package.json index 22afc8b52056..ad201e5fa561 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "2023.9.3-kinel.3", + "version": "2023.9.3-kinel.4", "codename": "nasubi", "repository": { "type": "git", From f4c3c55a85a13cb00c5f32cb8ac53c173fe9abbe Mon Sep 17 00:00:00 2001 From: Sayamame-beans <61457993+Sayamame-beans@users.noreply.github.com> Date: Wed, 18 Oct 2023 18:53:15 +0900 Subject: [PATCH 135/284] docs: refine changelog of 2023.9.3-kinel.4 --- CHANGELOG.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49ca213a44ec..358c7594310d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,12 +15,13 @@ ## 2023.9.3-kinel.4 ### Client -- Fix: Renoteの省略表示でセンシティブチャンネルの自動CWが聞かない問題 +- Fix: Renoteの省略表示でセンシティブチャンネルの自動CWが効かない問題 ### Server - 2023.10.x向けのTLを内部的に構築するようになりました - - これによりこの2023.10.x以降に更新したあとも2023.9.3-kinel.4更新後のnoteが見れるようになります - - 本来の2023.10.xでは更新以前のnoteがTLで見えないという仕様がありました。 + - これにより、2023.9.3-kinel.4更新後のnoteは2023.10.x以降に更新した後でも見ることが出来ます + - 2023.10.xには、更新以前のnoteをTLで見ることが出来ないという仕様がありました + - 2023.9.xを利用している内は特に影響ありません ## 2023.9.3-kinel.3 (unreleased) From 2093a93d71b4c56b49bccbb0259fe75d186ea6f4 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Fri, 24 Nov 2023 18:53:47 +0900 Subject: [PATCH 136/284] chore: RedisTimeline => FunoutTimeline --- packages/backend/src/core/AntennaService.ts | 6 ++-- packages/backend/src/core/CoreModule.ts | 12 +++---- ...ineService.ts => FunoutTimelineService.ts} | 2 +- .../backend/src/core/NoteCreateService.ts | 36 +++++++++---------- packages/backend/src/core/RoleService.ts | 6 ++-- 5 files changed, 31 insertions(+), 31 deletions(-) rename packages/backend/src/core/{RedisTimelineService.ts => FunoutTimelineService.ts} (98%) diff --git a/packages/backend/src/core/AntennaService.ts b/packages/backend/src/core/AntennaService.ts index 6d761d579e43..fd151bd92d9a 100644 --- a/packages/backend/src/core/AntennaService.ts +++ b/packages/backend/src/core/AntennaService.ts @@ -16,7 +16,7 @@ import type { AntennasRepository, UserListJoiningsRepository } from '@/models/_. import { UtilityService } from '@/core/UtilityService.js'; import { bindThis } from '@/decorators.js'; import type { GlobalEvents } from '@/core/GlobalEventService.js'; -import { RedisTimelineService } from '@/core/RedisTimelineService.js'; +import { FunoutTimelineService } from '@/core/FunoutTimelineService.js'; import type { OnApplicationShutdown } from '@nestjs/common'; @Injectable() @@ -39,7 +39,7 @@ export class AntennaService implements OnApplicationShutdown { private utilityService: UtilityService, private globalEventService: GlobalEventService, - private redisTimelineService: RedisTimelineService, + private funoutTimelineService: FunoutTimelineService, ) { this.antennasFetched = false; this.antennas = []; @@ -92,7 +92,7 @@ export class AntennaService implements OnApplicationShutdown { '*', 'note', note.id); - this.redisTimelineService.push(`antennaTimeline:${antenna.id}`, note.id, 200, redisPipeline); + this.funoutTimelineService.push(`antennaTimeline:${antenna.id}`, note.id, 200, redisPipeline); this.globalEventService.publishAntennaStream(antenna.id, 'note', note); } diff --git a/packages/backend/src/core/CoreModule.ts b/packages/backend/src/core/CoreModule.ts index 3d8d64786126..7851f00ab69c 100644 --- a/packages/backend/src/core/CoreModule.ts +++ b/packages/backend/src/core/CoreModule.ts @@ -59,7 +59,7 @@ import { UtilityService } from './UtilityService.js'; import { FileInfoService } from './FileInfoService.js'; import { SearchService } from './SearchService.js'; import { ClipService } from './ClipService.js'; -import { RedisTimelineService } from './RedisTimelineService.js'; +import { FunoutTimelineService } from './FunoutTimelineService.js'; import { ChartLoggerService } from './chart/ChartLoggerService.js'; import FederationChart from './chart/charts/federation.js'; import NotesChart from './chart/charts/notes.js'; @@ -187,7 +187,7 @@ const $UtilityService: Provider = { provide: 'UtilityService', useExisting: Util const $FileInfoService: Provider = { provide: 'FileInfoService', useExisting: FileInfoService }; const $SearchService: Provider = { provide: 'SearchService', useExisting: SearchService }; const $ClipService: Provider = { provide: 'ClipService', useExisting: ClipService }; -const $RedisTimelineService: Provider = { provide: 'RedisTimelineService', useExisting: RedisTimelineService }; +const $FunoutTimelineService: Provider = { provide: 'FunoutTimelineService', useExisting: FunoutTimelineService }; const $ChartLoggerService: Provider = { provide: 'ChartLoggerService', useExisting: ChartLoggerService }; const $FederationChart: Provider = { provide: 'FederationChart', useExisting: FederationChart }; @@ -318,7 +318,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting FileInfoService, SearchService, ClipService, - RedisTimelineService, + FunoutTimelineService, ChartLoggerService, FederationChart, NotesChart, @@ -443,7 +443,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting $FileInfoService, $SearchService, $ClipService, - $RedisTimelineService, + $FunoutTimelineService, $ChartLoggerService, $FederationChart, $NotesChart, @@ -568,7 +568,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting FileInfoService, SearchService, ClipService, - RedisTimelineService, + FunoutTimelineService, FederationChart, NotesChart, UsersChart, @@ -692,7 +692,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting $FileInfoService, $SearchService, $ClipService, - $RedisTimelineService, + $FunoutTimelineService, $FederationChart, $NotesChart, $UsersChart, diff --git a/packages/backend/src/core/RedisTimelineService.ts b/packages/backend/src/core/FunoutTimelineService.ts similarity index 98% rename from packages/backend/src/core/RedisTimelineService.ts rename to packages/backend/src/core/FunoutTimelineService.ts index bff134a93b4b..2d1c85141178 100644 --- a/packages/backend/src/core/RedisTimelineService.ts +++ b/packages/backend/src/core/FunoutTimelineService.ts @@ -10,7 +10,7 @@ import { bindThis } from '@/decorators.js'; import { IdService } from '@/core/IdService.js'; @Injectable() -export class RedisTimelineService { +export class FunoutTimelineService { constructor( @Inject(DI.redis) private redisClient: Redis.Redis, diff --git a/packages/backend/src/core/NoteCreateService.ts b/packages/backend/src/core/NoteCreateService.ts index b917550cfd4f..2ad63ce03cd0 100644 --- a/packages/backend/src/core/NoteCreateService.ts +++ b/packages/backend/src/core/NoteCreateService.ts @@ -53,7 +53,7 @@ import { DB_MAX_NOTE_TEXT_LENGTH } from '@/const.js'; import { RoleService } from '@/core/RoleService.js'; import { MetaService } from '@/core/MetaService.js'; import { SearchService } from '@/core/SearchService.js'; -import { RedisTimelineService } from '@/core/RedisTimelineService.js'; +import { FunoutTimelineService } from '@/core/FunoutTimelineService.js'; const mutedWordsCache = new MemorySingleCache<{ userId: MiUserProfile['userId']; mutedWords: MiUserProfile['mutedWords']; }[]>(1000 * 60 * 5); @@ -199,7 +199,7 @@ export class NoteCreateService implements OnApplicationShutdown { private idService: IdService, private globalEventService: GlobalEventService, private queueService: QueueService, - private redisTimelineService: RedisTimelineService, + private funoutTimelineService: FunoutTimelineService, private noteReadService: NoteReadService, private notificationService: NotificationService, private relayService: RelayService, @@ -829,9 +829,9 @@ export class NoteCreateService implements OnApplicationShutdown { const r = this.redisClient.pipeline(); if (note.channelId) { - this.redisTimelineService.push(`channelTimeline:${note.channelId}`, note.id, this.config.perChannelMaxNoteCacheCount, r); + this.funoutTimelineService.push(`channelTimeline:${note.channelId}`, note.id, this.config.perChannelMaxNoteCacheCount, r); - this.redisTimelineService.push(`userTimelineWithChannel:${user.id}`, note.id, 300, r); + this.funoutTimelineService.push(`userTimelineWithChannel:${user.id}`, note.id, 300, r); const channelFollowings = await this.channelFollowingsRepository.find({ where: { @@ -841,9 +841,9 @@ export class NoteCreateService implements OnApplicationShutdown { }); for (const channelFollowing of channelFollowings) { - this.redisTimelineService.push(`homeTimeline:${channelFollowing.followerId}`, note.id, 300, r); + this.funoutTimelineService.push(`homeTimeline:${channelFollowing.followerId}`, note.id, 300, r); if (note.fileIds.length > 0) { - this.redisTimelineService.push(`homeTimelineWithFiles:${channelFollowing.followerId}`, note.id, 300 / 2, r); + this.funoutTimelineService.push(`homeTimelineWithFiles:${channelFollowing.followerId}`, note.id, 300 / 2, r); } } } else { @@ -881,9 +881,9 @@ export class NoteCreateService implements OnApplicationShutdown { if (!this.config.nirila.withRepliesInHomeTL) continue; } - this.redisTimelineService.push(`homeTimeline:${following.followerId}`, note.id, 300, r); + this.funoutTimelineService.push(`homeTimeline:${following.followerId}`, note.id, 300, r); if (note.fileIds.length > 0) { - this.redisTimelineService.push(`homeTimelineWithFiles:${following.followerId}`, note.id, 300 / 2, r); + this.funoutTimelineService.push(`homeTimelineWithFiles:${following.followerId}`, note.id, 300 / 2, r); } } @@ -899,36 +899,36 @@ export class NoteCreateService implements OnApplicationShutdown { if (!this.config.nirila.withRepliesInHomeTL) continue; } - this.redisTimelineService.push(`userListTimeline:${userListMembership.userListId}`, note.id, 300, r); + this.funoutTimelineService.push(`userListTimeline:${userListMembership.userListId}`, note.id, 300, r); if (note.fileIds.length > 0) { - this.redisTimelineService.push(`userListTimelineWithFiles:${userListMembership.userListId}`, note.id, 300 / 2, r); + this.funoutTimelineService.push(`userListTimelineWithFiles:${userListMembership.userListId}`, note.id, 300 / 2, r); } } if (note.visibility !== 'specified' || !note.visibleUserIds.some(v => v === user.id)) { // 自分自身のHTL - this.redisTimelineService.push(`homeTimeline:${user.id}`, note.id, 300, r); + this.funoutTimelineService.push(`homeTimeline:${user.id}`, note.id, 300, r); if (note.fileIds.length > 0) { - this.redisTimelineService.push(`homeTimelineWithFiles:${user.id}`, note.id, 300 / 2, r); + this.funoutTimelineService.push(`homeTimelineWithFiles:${user.id}`, note.id, 300 / 2, r); } } // 自分自身以外への返信 if (note.replyId && note.replyUserId !== note.userId) { - this.redisTimelineService.push(`userTimelineWithReplies:${user.id}`, note.id, 300, r); + this.funoutTimelineService.push(`userTimelineWithReplies:${user.id}`, note.id, 300, r); if (note.visibility === 'public' && note.userHost == null) { - this.redisTimelineService.push('localTimelineWithReplies', note.id, 300, r); + this.funoutTimelineService.push('localTimelineWithReplies', note.id, 300, r); } } else { - this.redisTimelineService.push(`userTimeline:${user.id}`, note.id, 300, r); + this.funoutTimelineService.push(`userTimeline:${user.id}`, note.id, 300, r); if (note.fileIds.length > 0) { - this.redisTimelineService.push(`userTimelineWithFiles:${user.id}`, note.id, 300 / 2, r); + this.funoutTimelineService.push(`userTimelineWithFiles:${user.id}`, note.id, 300 / 2, r); } if (note.visibility === 'public' && note.userHost == null) { - this.redisTimelineService.push('localTimeline', note.id, 1000, r); + this.funoutTimelineService.push('localTimeline', note.id, 1000, r); if (note.fileIds.length > 0) { - this.redisTimelineService.push('localTimelineWithFiles', note.id, 500, r); + this.funoutTimelineService.push('localTimelineWithFiles', note.id, 500, r); } } } diff --git a/packages/backend/src/core/RoleService.ts b/packages/backend/src/core/RoleService.ts index d8f9f4639c84..c29c10ccc44e 100644 --- a/packages/backend/src/core/RoleService.ts +++ b/packages/backend/src/core/RoleService.ts @@ -20,7 +20,7 @@ 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 { RedisTimelineService } from '@/core/RedisTimelineService.js'; +import { FunoutTimelineService } from '@/core/FunoutTimelineService.js'; import type { OnApplicationShutdown } from '@nestjs/common'; export type RolePolicies = { @@ -103,7 +103,7 @@ export class RoleService implements OnApplicationShutdown { private globalEventService: GlobalEventService, private idService: IdService, private moderationLogService: ModerationLogService, - private redisTimelineService: RedisTimelineService, + private funoutTimelineService: FunoutTimelineService, ) { //this.onMessage = this.onMessage.bind(this); @@ -479,7 +479,7 @@ export class RoleService implements OnApplicationShutdown { 'MAXLEN', '~', '1000', '*', 'note', note.id); - this.redisTimelineService.push(`roleTimeline:${role.id}`, note.id, 1000, redisPipeline); + this.funoutTimelineService.push(`roleTimeline:${role.id}`, note.id, 1000, redisPipeline); this.globalEventService.publishRoleTimelineStream(role.id, 'note', note); } From 957f102809528614ab24dce4aa4478e84b272205 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Fri, 24 Nov 2023 18:55:16 +0900 Subject: [PATCH 137/284] remove legacy anntena timeline redis --- packages/backend/src/core/AntennaService.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/backend/src/core/AntennaService.ts b/packages/backend/src/core/AntennaService.ts index fd151bd92d9a..084b39561c43 100644 --- a/packages/backend/src/core/AntennaService.ts +++ b/packages/backend/src/core/AntennaService.ts @@ -86,12 +86,6 @@ export class AntennaService implements OnApplicationShutdown { const redisPipeline = this.redisClient.pipeline(); for (const antenna of matchedAntennas) { - redisPipeline.xadd( - `antennaTimeline:${antenna.id}`, - 'MAXLEN', '~', '200', - '*', - 'note', note.id); - this.funoutTimelineService.push(`antennaTimeline:${antenna.id}`, note.id, 200, redisPipeline); this.globalEventService.publishAntennaStream(antenna.id, 'note', note); } From bd2f5f52b7aefff7e4c0acb3d4e546eed9be6cc3 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Fri, 24 Nov 2023 20:48:57 +0900 Subject: [PATCH 138/284] remove legacy role timeline redis --- packages/backend/src/core/RoleService.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/packages/backend/src/core/RoleService.ts b/packages/backend/src/core/RoleService.ts index c29c10ccc44e..8af13534e676 100644 --- a/packages/backend/src/core/RoleService.ts +++ b/packages/backend/src/core/RoleService.ts @@ -474,11 +474,6 @@ export class RoleService implements OnApplicationShutdown { const redisPipeline = this.redisClient.pipeline(); for (const role of roles) { - redisPipeline.xadd( - `roleTimeline:${role.id}`, - 'MAXLEN', '~', '1000', - '*', - 'note', note.id); this.funoutTimelineService.push(`roleTimeline:${role.id}`, note.id, 1000, redisPipeline); this.globalEventService.publishRoleTimelineStream(role.id, 'note', note); } From 70c5f91277ed6bb8cb9bc44302ad833234f23e2b Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Fri, 24 Nov 2023 21:13:35 +0900 Subject: [PATCH 139/284] chore: move featured filter to FeaturedService --- packages/backend/src/core/FeaturedService.ts | 6 ++++++ packages/backend/src/core/NoteCreateService.ts | 2 +- packages/backend/src/core/ReactionService.ts | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/core/FeaturedService.ts b/packages/backend/src/core/FeaturedService.ts index 9617f83880f1..704210fb3720 100644 --- a/packages/backend/src/core/FeaturedService.ts +++ b/packages/backend/src/core/FeaturedService.ts @@ -74,6 +74,12 @@ export class FeaturedService { return Array.from(ranking.keys()); } + // TODO: find better place? + @bindThis + public shouldBeIncludedInGlobalOrUserFeatured(note: MiNote): boolean { + return note.visibility === 'public' && note.userHost == null && note.replyId == null; + } + @bindThis public updateGlobalNotesRanking(noteId: MiNote['id'], score = 1): Promise { return this.updateRankingOf('featuredGlobalNotesRanking', GLOBAL_NOTES_RANKING_WINDOW, noteId, score); diff --git a/packages/backend/src/core/NoteCreateService.ts b/packages/backend/src/core/NoteCreateService.ts index 8bc60390f55a..940604ff4dcf 100644 --- a/packages/backend/src/core/NoteCreateService.ts +++ b/packages/backend/src/core/NoteCreateService.ts @@ -745,7 +745,7 @@ export class NoteCreateService implements OnApplicationShutdown { this.featuredService.updateInChannelNotesRanking(renote.channelId, renote.id, 5); } } else { - if (renote.visibility === 'public' && renote.userHost == null && renote.replyId == null) { + if (this.featuredService.shouldBeIncludedInGlobalOrUserFeatured(renote)) { this.featuredService.updateGlobalNotesRanking(renote.id, 5); this.featuredService.updatePerUserNotesRanking(renote.userId, renote.id, 5); } diff --git a/packages/backend/src/core/ReactionService.ts b/packages/backend/src/core/ReactionService.ts index 4233b8d4c348..b5a9998b35a5 100644 --- a/packages/backend/src/core/ReactionService.ts +++ b/packages/backend/src/core/ReactionService.ts @@ -206,7 +206,7 @@ export class ReactionService { this.featuredService.updateInChannelNotesRanking(note.channelId, note.id, 1); } } else { - if (note.visibility === 'public' && note.userHost == null && note.replyId == null) { + if (this.featuredService.shouldBeIncludedInGlobalOrUserFeatured(note)) { this.featuredService.updateGlobalNotesRanking(note.id, 1); this.featuredService.updatePerUserNotesRanking(note.userId, note.id, 1); } From ec50aefde00c91b23e1d45767bbaa2e994c16ab9 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Fri, 24 Nov 2023 21:16:16 +0900 Subject: [PATCH 140/284] chore: change style in shouldBeIncludedInGlobalOrUserFeatured --- packages/backend/src/core/FeaturedService.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/backend/src/core/FeaturedService.ts b/packages/backend/src/core/FeaturedService.ts index 704210fb3720..fa1281bf4f76 100644 --- a/packages/backend/src/core/FeaturedService.ts +++ b/packages/backend/src/core/FeaturedService.ts @@ -77,7 +77,12 @@ export class FeaturedService { // TODO: find better place? @bindThis public shouldBeIncludedInGlobalOrUserFeatured(note: MiNote): boolean { - return note.visibility === 'public' && note.userHost == null && note.replyId == null; + if (note.visibility !== 'public') return false; // non-public note + if (note.userHost != null) return false; // remote + if (note.replyId != null) return false; // reply + // Channels are checked outside + + return true; } @bindThis From 45f0a720dbd197661b66cc8fed5f6aa22e298ab4 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Fri, 24 Nov 2023 21:44:46 +0900 Subject: [PATCH 141/284] =?UTF-8?q?chore:=20exclude=20=E3=81=8A=E3=81=AFno?= =?UTF-8?q?te=20from=20featured?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/backend/src/core/FeaturedService.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/backend/src/core/FeaturedService.ts b/packages/backend/src/core/FeaturedService.ts index fa1281bf4f76..97d1e4fe4cc4 100644 --- a/packages/backend/src/core/FeaturedService.ts +++ b/packages/backend/src/core/FeaturedService.ts @@ -82,6 +82,16 @@ export class FeaturedService { if (note.replyId != null) return false; // reply // Channels are checked outside + // In nirila misskey, it was very common to notes with `:ohayo_nirila_misskey:` or `:oyasumi_nirila_misskey:` + // Will get many reaction`:ohayo_nirila_misskey:` or `:oyasumi_nirila_misskey:` so exclude them + // if they don't have any images. + if (note.fileIds.length === 0) { + for (const exclusion of ["おはよう", "おやすみ", ":ohayo_nirila_misskey:", ":oyasumi_nirila_misskey:"]) { + if (note.text?.includes(exclusion)) return false; + if (note.cw?.includes(exclusion)) return false; + } + } + return true; } From 3a213e483f4c6be7a44b56ddc5df01c85811a3b9 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Thu, 23 Nov 2023 18:56:20 +0900 Subject: [PATCH 142/284] Hard mute (#12376) * feat(backend,misskey-js): hard mute storage in backend * fix(backend,misskey-js): mute word record type * chore(frontend): generalize XWordMute * feat(frontend): configure hard mute * feat(frontend): hard mute notes on the timelines * lint(backend,frontend): fix lint failure * chore(misskey-js): update api.md * fix(backend): test failure * chore(frontend): check word mute for reply * chore: limit hard mute count --- locales/index.d.ts | 1 + locales/ja-JP.yml | 1 + .../migration/1700383825690-hard-mute.js | 11 ++++++ .../src/core/entities/UserEntityService.ts | 1 + packages/backend/src/models/UserProfile.ts | 7 +++- .../backend/src/models/json-schema/user.ts | 12 +++++++ .../src/server/api/endpoints/i/update.ts | 34 +++++++++++++++---- packages/backend/test/e2e/users.ts | 1 + packages/frontend/src/components/MkNote.vue | 17 ++++++++-- packages/frontend/src/components/MkNotes.vue | 2 +- .../src/components/MkNotifications.vue | 2 +- .../src/pages/settings/mute-block.vue | 18 +++++++++- .../pages/settings/mute-block.word-mute.vue | 22 ++++++------ packages/misskey-js/etc/misskey-js.api.md | 12 ++++--- packages/misskey-js/src/api.types.ts | 3 +- packages/misskey-js/src/entities.ts | 3 +- 16 files changed, 114 insertions(+), 33 deletions(-) create mode 100644 packages/backend/migration/1700383825690-hard-mute.js diff --git a/locales/index.d.ts b/locales/index.d.ts index b197c3d0b127..422f371fe609 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -639,6 +639,7 @@ export interface Locale { "smtpSecureInfo": string; "testEmail": string; "wordMute": string; + "hardWordMute": string; "regexpError": string; "regexpErrorDescription": string; "instanceMute": string; diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 44830e32f1c6..50d07773f5df 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -636,6 +636,7 @@ smtpSecure: "SMTP 接続に暗黙的なSSL/TLSを使用する" smtpSecureInfo: "STARTTLS使用時はオフにします。" testEmail: "配信テスト" wordMute: "ワードミュート" +hardWordMute: "ハードワードミュート" regexpError: "正規表現エラー" regexpErrorDescription: "{tab}ワードミュートの{line}行目の正規表現にエラーが発生しました:" instanceMute: "サーバーミュート" diff --git a/packages/backend/migration/1700383825690-hard-mute.js b/packages/backend/migration/1700383825690-hard-mute.js new file mode 100644 index 000000000000..afd3247f5cae --- /dev/null +++ b/packages/backend/migration/1700383825690-hard-mute.js @@ -0,0 +1,11 @@ +export class HardMute1700383825690 { + name = 'HardMute1700383825690' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "user_profile" ADD "hardMutedWords" jsonb NOT NULL DEFAULT '[]'`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "hardMutedWords"`); + } +} diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts index 17e79881765a..917f4e06d060 100644 --- a/packages/backend/src/core/entities/UserEntityService.ts +++ b/packages/backend/src/core/entities/UserEntityService.ts @@ -473,6 +473,7 @@ export class UserEntityService implements OnModuleInit { hasPendingReceivedFollowRequest: this.getHasPendingReceivedFollowRequest(user.id), unreadNotificationsCount: notificationsInfo?.unreadCount, mutedWords: profile!.mutedWords, + hardMutedWords: profile!.hardMutedWords, mutedInstances: profile!.mutedInstances, mutingNotificationTypes: [], // 後方互換性のため notificationRecieveConfig: profile!.notificationRecieveConfig, diff --git a/packages/backend/src/models/UserProfile.ts b/packages/backend/src/models/UserProfile.ts index d6d85c560930..8a43b60039a6 100644 --- a/packages/backend/src/models/UserProfile.ts +++ b/packages/backend/src/models/UserProfile.ts @@ -215,7 +215,12 @@ export class MiUserProfile { @Column('jsonb', { default: [], }) - public mutedWords: string[][]; + public mutedWords: (string[] | string)[]; + + @Column('jsonb', { + default: [], + }) + public hardMutedWords: (string[] | string)[]; @Column('jsonb', { default: [], diff --git a/packages/backend/src/models/json-schema/user.ts b/packages/backend/src/models/json-schema/user.ts index 37bdcbe281f2..99da1ef569ca 100644 --- a/packages/backend/src/models/json-schema/user.ts +++ b/packages/backend/src/models/json-schema/user.ts @@ -415,6 +415,18 @@ export const packedMeDetailedOnlySchema = { }, }, }, + hardMutedWords: { + type: 'array', + nullable: false, optional: false, + items: { + type: 'array', + nullable: false, optional: false, + items: { + type: 'string', + nullable: false, optional: false, + }, + }, + }, mutedInstances: { type: 'array', nullable: true, optional: false, diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts index b00aa87bee29..8ba29c56588a 100644 --- a/packages/backend/src/server/api/endpoints/i/update.ts +++ b/packages/backend/src/server/api/endpoints/i/update.ts @@ -123,6 +123,11 @@ export const meta = { }, } as const; +const muteWords = { type: 'array', items: { oneOf: [ + { type: 'array', items: { type: 'string' } }, + { type: 'string' } +] } } as const; + export const paramDef = { type: 'object', properties: { @@ -171,7 +176,8 @@ export const paramDef = { autoSensitive: { type: 'boolean' }, ffVisibility: { type: 'string', enum: ['public', 'followers', 'private'] }, pinnedPageId: { type: 'string', format: 'misskey:id', nullable: true }, - mutedWords: { type: 'array' }, + mutedWords: muteWords, + hardMutedWords: muteWords, mutedInstances: { type: 'array', items: { type: 'string', } }, @@ -234,16 +240,20 @@ export default class extends Endpoint { // eslint- if (ps.location !== undefined) profileUpdates.location = ps.location; if (ps.birthday !== undefined) profileUpdates.birthday = ps.birthday; if (ps.ffVisibility !== undefined) profileUpdates.ffVisibility = ps.ffVisibility; - if (ps.mutedWords !== undefined) { + + function checkMuteWordCount(mutedWords: (string[] | string)[], limit: number) { // TODO: ちゃんと数える const length = JSON.stringify(ps.mutedWords).length; - if (length > (await this.roleService.getUserPolicies(user.id)).wordMuteLimit) { + if (length > limit) { throw new ApiError(meta.errors.tooManyMutedWords); } + } + + function validateMuteWordRegex(mutedWords: (string[] | string)[]) { + for (const mutedWord of mutedWords) { + if (typeof mutedWord !== "string") continue; - // validate regular expression syntax - ps.mutedWords.filter(x => !Array.isArray(x)).forEach(x => { - const regexp = x.match(/^\/(.+)\/(.*)$/); + const regexp = mutedWord.match(/^\/(.+)\/(.*)$/); if (!regexp) throw new ApiError(meta.errors.invalidRegexp); try { @@ -251,11 +261,21 @@ export default class extends Endpoint { // eslint- } catch (err) { throw new ApiError(meta.errors.invalidRegexp); } - }); + } + } + + if (ps.mutedWords !== undefined) { + checkMuteWordCount(ps.mutedWords, (await this.roleService.getUserPolicies(user.id)).wordMuteLimit); + validateMuteWordRegex(ps.mutedWords); profileUpdates.mutedWords = ps.mutedWords; profileUpdates.enableWordMute = ps.mutedWords.length > 0; } + if (ps.hardMutedWords !== undefined) { + checkMuteWordCount(ps.hardMutedWords, (await this.roleService.getUserPolicies(user.id)).wordMuteLimit); + validateMuteWordRegex(ps.hardMutedWords); + profileUpdates.hardMutedWords = ps.hardMutedWords; + } if (ps.mutedInstances !== undefined) profileUpdates.mutedInstances = ps.mutedInstances; if (ps.notificationRecieveConfig !== undefined) profileUpdates.notificationRecieveConfig = ps.notificationRecieveConfig; if (typeof ps.isLocked === 'boolean') updates.isLocked = ps.isLocked; diff --git a/packages/backend/test/e2e/users.ts b/packages/backend/test/e2e/users.ts index 1867525cc8da..2ce8fbc12942 100644 --- a/packages/backend/test/e2e/users.ts +++ b/packages/backend/test/e2e/users.ts @@ -168,6 +168,7 @@ describe('ユーザー', () => { hasPendingReceivedFollowRequest: user.hasPendingReceivedFollowRequest, unreadAnnouncements: user.unreadAnnouncements, mutedWords: user.mutedWords, + hardMutedWords: user.hardMutedWords, mutedInstances: user.mutedInstances, mutingNotificationTypes: user.mutingNotificationTypes, notificationRecieveConfig: user.notificationRecieveConfig, diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue index e0c6369c2f8f..653fb19c6334 100644 --- a/packages/frontend/src/components/MkNote.vue +++ b/packages/frontend/src/components/MkNote.vue @@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only