From 19035c676cd1a8afc1d798ff85147a523df95985 Mon Sep 17 00:00:00 2001 From: tamaina Date: Thu, 9 Feb 2023 12:39:24 +0000 Subject: [PATCH 001/294] =?UTF-8?q?/proxy=E3=81=A7emoji,=20avatar=E3=81=AA?= =?UTF-8?q?=E3=81=A9=E3=81=AE=E5=91=BD=E4=BB=A4=E3=81=8C=E3=81=82=E3=82=8A?= =?UTF-8?q?=E3=81=8B=E3=81=A4=E7=94=BB=E5=83=8F=E3=81=A7=E3=81=AA=E3=81=84?= =?UTF-8?q?=E3=81=AA=E3=82=89404=E3=82=92=E8=BF=94=E3=81=99=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 --- .../backend/src/server/FileServerService.ts | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/packages/backend/src/server/FileServerService.ts b/packages/backend/src/server/FileServerService.ts index 4bd6d0f556..49ded6c28e 100644 --- a/packages/backend/src/server/FileServerService.ts +++ b/packages/backend/src/server/FileServerService.ts @@ -255,8 +255,21 @@ export class FileServerService { const isConvertibleImage = isMimeImage(file.mime, 'sharp-convertible-image'); const isAnimationConvertibleImage = isMimeImage(file.mime, 'sharp-animation-convertible-image'); + if ( + 'emoji' in request.query || + 'avatar' in request.query || + 'static' in request.query || + 'preview' in request.query || + 'badge' in request.query + ) { + if (!isConvertibleImage) { + // 画像でないなら404でお茶を濁す + throw new StatusError('Unexpected mime', 404); + } + } + let image: IImageStreamable | null = null; - if (('emoji' in request.query || 'avatar' in request.query) && isConvertibleImage) { + if ('emoji' in request.query || 'avatar' in request.query) { if (!isAnimationConvertibleImage && !('static' in request.query)) { image = { data: fs.createReadStream(file.path), @@ -277,16 +290,11 @@ export class FileServerService { type: 'image/webp', }; } - } else if ('static' in request.query && isConvertibleImage) { + } else if ('static' in request.query) { image = this.imageProcessingService.convertToWebpStream(file.path, 498, 280); - } else if ('preview' in request.query && isConvertibleImage) { + } else if ('preview' in request.query) { image = this.imageProcessingService.convertToWebpStream(file.path, 200, 200); } else if ('badge' in request.query) { - if (!isConvertibleImage) { - // 画像でないなら404でお茶を濁す - throw new StatusError('Unexpected mime', 404); - } - const mask = sharp(file.path) .resize(96, 96, { fit: 'inside', From 35eeeb25e35b269211864351f8ea684a0b4ba145 Mon Sep 17 00:00:00 2001 From: tamaina Date: Thu, 9 Feb 2023 15:05:23 +0000 Subject: [PATCH 002/294] update pnpm to 7.27.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 578bcb76a4..59e331be9e 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "type": "git", "url": "https://github.com/misskey-dev/misskey.git" }, - "packageManager": "pnpm@7.24.3", + "packageManager": "pnpm@7.27.0", "workspaces": [ "packages/frontend", "packages/backend", From 83fb629f0b09f6799151b0115e3b4dc7ed17ce01 Mon Sep 17 00:00:00 2001 From: tamaina Date: Thu, 9 Feb 2023 15:34:49 +0000 Subject: [PATCH 003/294] :art: --- .../frontend/src/ui/_common_/navbar-for-mobile.vue | 13 +++++++++---- packages/frontend/src/ui/_common_/navbar.vue | 13 +++++++++---- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/packages/frontend/src/ui/_common_/navbar-for-mobile.vue b/packages/frontend/src/ui/_common_/navbar-for-mobile.vue index 989d861d27..357db5599f 100644 --- a/packages/frontend/src/ui/_common_/navbar-for-mobile.vue +++ b/packages/frontend/src/ui/_common_/navbar-for-mobile.vue @@ -35,7 +35,7 @@ {{ i18n.ts.note }} @@ -168,20 +168,25 @@ function more() { display: flex; align-items: center; padding-left: 30px; - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; width: 100%; text-align: left; box-sizing: border-box; margin-top: 16px; > .avatar { + display: block; + flex-shrink: 0; position: relative; width: 32px; aspect-ratio: 1; margin-right: 8px; } + + > .text { + display: block; + flex-shrink: 1; + padding-right: 8px; + } } } diff --git a/packages/frontend/src/ui/_common_/navbar.vue b/packages/frontend/src/ui/_common_/navbar.vue index e90098397a..3c161f6797 100644 --- a/packages/frontend/src/ui/_common_/navbar.vue +++ b/packages/frontend/src/ui/_common_/navbar.vue @@ -45,7 +45,7 @@ {{ i18n.ts.note }} @@ -217,20 +217,25 @@ function more(ev: MouseEvent) { display: flex; align-items: center; padding-left: 30px; - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; width: 100%; text-align: left; box-sizing: border-box; margin-top: 16px; > .avatar { + display: block; + flex-shrink: 0; position: relative; width: 32px; aspect-ratio: 1; margin-right: 8px; } + + > .text { + display: block; + flex-shrink: 1; + padding-right: 8px; + } } } From 686a709e87b6358e066ce32a6edc06034b4a3760 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Fri, 10 Feb 2023 00:36:05 +0900 Subject: [PATCH 004/294] chore: determine dimensions of the helix of cat ears based on the size of avatars (#9836) * chore: determine dimensions of the helix of cat ears based on the size of avatars * Update MkAvatar.vue * Update packages/frontend/src/components/global/MkAvatar.vue --------- Co-authored-by: tamaina --- .../src/components/global/MkAvatar.vue | 39 +++++++++++++------ 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/packages/frontend/src/components/global/MkAvatar.vue b/packages/frontend/src/components/global/MkAvatar.vue index 812f30439b..9ad06545f2 100644 --- a/packages/frontend/src/components/global/MkAvatar.vue +++ b/packages/frontend/src/components/global/MkAvatar.vue @@ -1,11 +1,19 @@ @@ -110,32 +118,41 @@ watch(() => props.user.avatarBlurhash, () => { } .cat { - &:before, &:after { - background: #df548f; - border: solid 4px currentColor; - box-sizing: border-box; - content: ''; + > .earLeft, + > .earRight { + contain: strict; display: inline-block; height: 50%; width: 50%; + background: currentColor; + + &::before { + contain: strict; + content: ''; + display: block; + width: 60%; + height: 60%; + margin: 20%; + background: #df548f; + } } - &:before { + > .earLeft { border-radius: 0 75% 75%; transform: rotate(37.5deg) skew(30deg); } - &:after { + > .earRight { border-radius: 75% 0 75% 75%; transform: rotate(-37.5deg) skew(-30deg); } &:hover { - &:before { + > .earLeft { animation: earwiggleleft 1s infinite; } - &:after { + > .earRight { animation: earwiggleright 1s infinite; } } From ca0d53ec5df747bbfba583f161a38af9dfe4d96c Mon Sep 17 00:00:00 2001 From: tamaina Date: Thu, 9 Feb 2023 17:18:27 +0000 Subject: [PATCH 005/294] =?UTF-8?q?enhance(client):=20/auth=E3=81=8A?= =?UTF-8?q?=E3=82=88=E3=81=B3MiAuth=E3=81=AEUI=E3=82=92=E3=83=96=E3=83=A9?= =?UTF-8?q?=E3=83=83=E3=82=B7=E3=83=A5=E3=82=A2=E3=83=83=E3=83=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix #9742 --- CHANGELOG.md | 9 ++ locales/ja-JP.yml | 2 + packages/frontend/src/pages/auth.form.vue | 108 +++++++------- packages/frontend/src/pages/auth.vue | 170 ++++++++++++---------- packages/frontend/src/pages/miauth.vue | 78 ++++++---- 5 files changed, 207 insertions(+), 160 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9bda35348..d3ccb5f864 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,15 @@ You should also include the user name that made the change. --> +## 13.x.x (unreleased) + +### Improvements +- 非ログイン時にMiAuthを踏んだ際にMiAuthであることを表示する +- /auth/のUIをアップデート + +### Bugfixes +- + ## 13.5.4 (2023/02/09) ### Improvements diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 09069e7801..60f492d66e 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1628,12 +1628,14 @@ _permissions: "write:gallery-likes": "ギャラリーのいいねを操作する" _auth: + shareAccessTitle: "アプリへのアクセス許可" shareAccess: "「{name}」がアカウントにアクセスすることを許可しますか?" shareAccessAsk: "アカウントへのアクセスを許可しますか?" permissionAsk: "このアプリは次の権限を要求しています" pleaseGoBack: "アプリケーションに戻ってやっていってください" callback: "アプリケーションに戻っています" denied: "アクセスを拒否しました" + pleaseLogin: "アプリケーションにアクセス許可を与えるには、ログインが必要です。" _antennaSources: all: "全てのノート" diff --git a/packages/frontend/src/pages/auth.form.vue b/packages/frontend/src/pages/auth.form.vue index 801295fce9..1a1cd55eee 100644 --- a/packages/frontend/src/pages/auth.form.vue +++ b/packages/frontend/src/pages/auth.form.vue @@ -1,60 +1,66 @@ - + + diff --git a/packages/frontend/src/pages/auth.vue b/packages/frontend/src/pages/auth.vue index b7727ca30d..50afffc460 100644 --- a/packages/frontend/src/pages/auth.vue +++ b/packages/frontend/src/pages/auth.vue @@ -1,93 +1,105 @@ - - diff --git a/packages/frontend/src/pages/miauth.vue b/packages/frontend/src/pages/miauth.vue index 9a4019e5b1..0a82ef8e44 100644 --- a/packages/frontend/src/pages/miauth.vue +++ b/packages/frontend/src/pages/miauth.vue @@ -1,41 +1,39 @@ - From 512e451f2411b468860e286d88b8cd6118c249f4 Mon Sep 17 00:00:00 2001 From: tamaina Date: Thu, 9 Feb 2023 17:29:22 +0000 Subject: [PATCH 006/294] =?UTF-8?q?app=20auth=20/=20miauth=E3=81=AE?= =?UTF-8?q?=E6=96=87=E8=A8=80=E7=B7=A8=E9=9B=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- locales/ja-JP.yml | 1 + packages/frontend/src/pages/auth.form.vue | 2 +- packages/frontend/src/pages/miauth.vue | 7 ++++--- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 60f492d66e..9edaa53a9b 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1631,6 +1631,7 @@ _auth: shareAccessTitle: "アプリへのアクセス許可" shareAccess: "「{name}」がアカウントにアクセスすることを許可しますか?" shareAccessAsk: "アカウントへのアクセスを許可しますか?" + permission: "{name}は次の権限を要求しています" permissionAsk: "このアプリは次の権限を要求しています" pleaseGoBack: "アプリケーションに戻ってやっていってください" callback: "アプリケーションに戻っています" diff --git a/packages/frontend/src/pages/auth.form.vue b/packages/frontend/src/pages/auth.form.vue index 1a1cd55eee..f8484185f5 100644 --- a/packages/frontend/src/pages/auth.form.vue +++ b/packages/frontend/src/pages/auth.form.vue @@ -1,7 +1,7 @@ - - - - + + + From adad4bcfe3a8dac2c8f6b053b2e0229852b5cd47 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 10 Feb 2023 10:45:32 +0900 Subject: [PATCH 009/294] =?UTF-8?q?=E3=82=AF=E3=83=AD=E3=83=83=E3=83=97?= =?UTF-8?q?=E6=99=82=E3=81=AE=E8=B3=AA=E5=95=8F=E3=82=92=E5=88=86=E3=81=8B?= =?UTF-8?q?=E3=82=8A=E3=82=84=E3=81=99=E3=81=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- locales/ja-JP.yml | 2 ++ packages/frontend/src/components/MkDialog.vue | 6 ++++-- packages/frontend/src/os.ts | 2 ++ packages/frontend/src/pages/settings/profile.vue | 4 ++++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 14ab9d7c72..79b78f3f98 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -864,6 +864,8 @@ failedToFetchAccountInformation: "アカウント情報の取得に失敗しま rateLimitExceeded: "レート制限を超えました" cropImage: "画像のクロップ" cropImageAsk: "画像をクロップしますか?" +cropYes: "クロップする" +cropNo: "そのまま使う" file: "ファイル" recentNHours: "直近{n}時間" recentNDays: "直近{n}日" diff --git a/packages/frontend/src/components/MkDialog.vue b/packages/frontend/src/components/MkDialog.vue index 74cb534859..da4db63406 100644 --- a/packages/frontend/src/components/MkDialog.vue +++ b/packages/frontend/src/components/MkDialog.vue @@ -28,8 +28,8 @@
- {{ (showCancelButton || input || select) ? i18n.ts.ok : i18n.ts.gotIt }} - {{ i18n.ts.cancel }} + {{ okText ?? ((showCancelButton || input || select) ? i18n.ts.ok : i18n.ts.gotIt) }} + {{ cancelText ?? i18n.ts.cancel }}
{{ action.text }} @@ -82,6 +82,8 @@ const props = withDefaults(defineProps<{ showOkButton?: boolean; showCancelButton?: boolean; cancelableByBgClick?: boolean; + okText?: string; + cancelText?: string; }>(), { type: 'info', showOkButton: true, diff --git a/packages/frontend/src/os.ts b/packages/frontend/src/os.ts index 52469b6d04..e21a21ef76 100644 --- a/packages/frontend/src/os.ts +++ b/packages/frontend/src/os.ts @@ -171,6 +171,8 @@ export function confirm(props: { type: 'error' | 'info' | 'success' | 'warning' | 'waiting' | 'question'; title?: string | null; text?: string | null; + okText?: string; + cancelText?: string; }): Promise<{ canceled: boolean }> { return new Promise((resolve, reject) => { popup(MkDialog, { diff --git a/packages/frontend/src/pages/settings/profile.vue b/packages/frontend/src/pages/settings/profile.vue index da7d3d3703..3647e90ce7 100644 --- a/packages/frontend/src/pages/settings/profile.vue +++ b/packages/frontend/src/pages/settings/profile.vue @@ -150,6 +150,8 @@ function changeAvatar(ev) { const { canceled } = await os.confirm({ type: 'question', text: i18n.t('cropImageAsk'), + okText: i18n.ts.cropYes, + cancelText: i18n.ts.cropNo, }); if (!canceled) { @@ -174,6 +176,8 @@ function changeBanner(ev) { const { canceled } = await os.confirm({ type: 'question', text: i18n.t('cropImageAsk'), + okText: i18n.ts.cropYes, + cancelText: i18n.ts.cropNo, }); if (!canceled) { From 3c504b4b08ee22af1f2b668e97929aafa03c60ad Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 10 Feb 2023 11:04:11 +0900 Subject: [PATCH 010/294] chore(client): improve usability --- packages/frontend/src/components/MkCwButton.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/components/MkCwButton.vue b/packages/frontend/src/components/MkCwButton.vue index 651b20cefe..e0885f5550 100644 --- a/packages/frontend/src/components/MkCwButton.vue +++ b/packages/frontend/src/components/MkCwButton.vue @@ -1,5 +1,5 @@
@@ -418,68 +302,4 @@ onUnmounted(() => { } } } - -.tabs { - display: block; - position: relative; - margin: 0; - height: var(--height); - font-size: 0.8em; - text-align: center; - overflow-x: auto; - overflow-y: hidden; - scrollbar-width: none; - - &::-webkit-scrollbar { - display: none; - } -} - -.tabsInner { - display: inline-block; - height: var(--height); - white-space: nowrap; -} - -.tab { - display: inline-block; - position: relative; - padding: 0 10px; - height: 100%; - font-weight: normal; - opacity: 0.7; - transition: opacity 0.2s ease; - - &:hover { - opacity: 1; - } - - &.active { - opacity: 1; - } -} - -.tabInner { - display: flex; - align-items: center; -} - -.tabIcon + .tabTitle { - margin-left: 8px; -} - -.tabTitle { - overflow: hidden; - transition: width 0.15s ease-in-out; -} - -.tabHighlight { - position: absolute; - bottom: 0; - height: 3px; - background: var(--accent); - border-radius: 999px; - transition: width 0.15s ease, left 0.15s ease; - pointer-events: none; -} diff --git a/packages/frontend/src/pages/timeline.vue b/packages/frontend/src/pages/timeline.vue index 31f4793dc4..a071361150 100644 --- a/packages/frontend/src/pages/timeline.vue +++ b/packages/frontend/src/pages/timeline.vue @@ -32,6 +32,7 @@ import { i18n } from '@/i18n'; import { instance } from '@/instance'; import { $i } from '@/account'; import { definePageMetadata } from '@/scripts/page-metadata'; +import type { Tab } from '@/components/global/MkPageHeader.tabs.vue'; provide('shouldOmitHeaderTitle', true); @@ -57,7 +58,7 @@ function queueUpdated(q: number): void { } function top(): void { - scroll(rootEl, { top: 0 }); + if (rootEl) scroll(rootEl, { top: 0 }); } async function chooseList(ev: MouseEvent): Promise { @@ -150,7 +151,7 @@ const headerTabs = $computed(() => [{ title: i18n.ts.channel, iconOnly: true, onClick: chooseChannel, -}]); +}] as Tab[]); const headerTabsWhenNotLogin = $computed(() => [ ...(isLocalTimelineAvailable ? [{ @@ -165,7 +166,7 @@ const headerTabsWhenNotLogin = $computed(() => [ icon: 'ti ti-whirl', iconOnly: true, }] : []), -]); +] as Tab[]); definePageMetadata(computed(() => ({ title: i18n.ts.timeline, From 19c0027605dca3bb2af3a2943d7984165badc9c2 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sat, 11 Feb 2023 07:17:50 +0000 Subject: [PATCH 037/294] =?UTF-8?q?fix(client):=20=E3=83=A6=E3=83=BC?= =?UTF-8?q?=E3=82=B6=E3=83=BC=E3=83=9A=E3=83=BC=E3=82=B8=E3=81=A7=E3=82=A2?= =?UTF-8?q?=E3=82=AF=E3=83=86=E3=82=A3=E3=83=93=E3=83=86=E3=82=A3=E3=82=92?= =?UTF-8?q?=E8=A6=8B=E3=82=8B=E3=81=93=E3=81=A8=E3=81=8C=E3=81=A7=E3=81=8D?= =?UTF-8?q?=E3=81=AA=E3=81=84=E3=81=AE=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 +- packages/frontend/src/pages/user/index.vue | 10 +++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 097195d531..c11d186926 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ You should also include the user name that made the change. - アニメーションを少なくする設定の時、MkPageHeaderのタブアニメーションを無効化 ### Bugfixes -- +- Client: ユーザーページでアクティビティを見ることができない問題を修正 ## 13.6.0 (2023/02/11) diff --git a/packages/frontend/src/pages/user/index.vue b/packages/frontend/src/pages/user/index.vue index 84909f72c2..29aef21859 100644 --- a/packages/frontend/src/pages/user/index.vue +++ b/packages/frontend/src/pages/user/index.vue @@ -6,6 +6,7 @@
+ @@ -20,13 +21,10 @@ + + From 451bc0b44483840da4b82394d077d07a35b5c71a Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 12 Feb 2023 18:47:30 +0900 Subject: [PATCH 066/294] refactor: fix types --- .../backend/src/core/AccountUpdateService.ts | 2 +- packages/backend/src/core/MessagingService.ts | 8 +- .../backend/src/core/NoteCreateService.ts | 2 +- .../backend/src/core/NoteDeleteService.ts | 4 +- .../backend/src/core/NotePiningService.ts | 2 +- packages/backend/src/core/PollService.ts | 2 +- packages/backend/src/core/ReactionService.ts | 6 +- packages/backend/src/core/RelayService.ts | 4 +- .../backend/src/core/UserBlockingService.ts | 12 +-- packages/backend/src/core/UserCacheService.ts | 6 +- .../backend/src/core/UserFollowingService.ts | 16 ++-- .../backend/src/core/UserSuspendService.ts | 4 +- .../core/activitypub/ApDbResolverService.ts | 4 +- .../src/core/activitypub/ApInboxService.ts | 6 +- .../src/core/activitypub/ApRendererService.ts | 94 +++++++++---------- .../src/core/activitypub/ApResolverService.ts | 15 +-- .../core/activitypub/models/ApNoteService.ts | 6 +- .../activitypub/models/ApPersonService.ts | 6 +- packages/backend/src/core/activitypub/type.ts | 30 +++++- .../core/entities/DriveFileEntityService.ts | 10 +- packages/backend/src/models/entities/User.ts | 1 + .../src/server/ActivityPubServerService.ts | 28 +++--- .../admin/resolve-abuse-user-report.ts | 2 +- .../server/api/endpoints/notes/polls/vote.ts | 2 +- 24 files changed, 142 insertions(+), 130 deletions(-) diff --git a/packages/backend/src/core/AccountUpdateService.ts b/packages/backend/src/core/AccountUpdateService.ts index 5f6dfca0ca..d8ba7b169d 100644 --- a/packages/backend/src/core/AccountUpdateService.ts +++ b/packages/backend/src/core/AccountUpdateService.ts @@ -32,7 +32,7 @@ export class AccountUpdateService { // フォロワーがリモートユーザーかつ投稿者がローカルユーザーならUpdateを配信 if (this.userEntityService.isLocalUser(user)) { - const content = this.apRendererService.renderActivity(this.apRendererService.renderUpdate(await this.apRendererService.renderPerson(user), user)); + const content = this.apRendererService.addContext(this.apRendererService.renderUpdate(await this.apRendererService.renderPerson(user), user)); this.apDeliverManagerService.deliverToFollowers(user, content); this.relayService.deliverToRelays(user, content); } diff --git a/packages/backend/src/core/MessagingService.ts b/packages/backend/src/core/MessagingService.ts index f4a1090658..1c36d04d41 100644 --- a/packages/backend/src/core/MessagingService.ts +++ b/packages/backend/src/core/MessagingService.ts @@ -135,7 +135,7 @@ export class MessagingService { }))), } as Note; - const activity = this.apRendererService.renderActivity(this.apRendererService.renderCreate(await this.apRendererService.renderNote(note, false, true), note)); + const activity = this.apRendererService.addContext(this.apRendererService.renderCreate(await this.apRendererService.renderNote(note, false, true), note)); this.queueService.deliver(user, activity, recipientUser.inbox); } @@ -158,7 +158,7 @@ export class MessagingService { if (this.userEntityService.isLocalUser(recipient)) this.globalEventService.publishMessagingStream(message.recipientId, message.userId, 'deleted', message.id); if (this.userEntityService.isLocalUser(user) && this.userEntityService.isRemoteUser(recipient)) { - const activity = this.apRendererService.renderActivity(this.apRendererService.renderDelete(this.apRendererService.renderTombstone(`${this.config.url}/notes/${message.id}`), user)); + const activity = this.apRendererService.addContext(this.apRendererService.renderDelete(this.apRendererService.renderTombstone(`${this.config.url}/notes/${message.id}`), user)); this.queueService.deliver(user, activity, recipient.inbox); } } else if (message.groupId) { @@ -297,10 +297,10 @@ export class MessagingService { if (contents.length > 1) { const collection = this.apRendererService.renderOrderedCollection(null, contents.length, undefined, undefined, contents); - this.queueService.deliver(user, this.apRendererService.renderActivity(collection), recipient.inbox); + this.queueService.deliver(user, this.apRendererService.addContext(collection), recipient.inbox); } else { for (const content of contents) { - this.queueService.deliver(user, this.apRendererService.renderActivity(content), recipient.inbox); + this.queueService.deliver(user, this.apRendererService.addContext(content), recipient.inbox); } } } diff --git a/packages/backend/src/core/NoteCreateService.ts b/packages/backend/src/core/NoteCreateService.ts index 4a81f764dc..04c057f6cd 100644 --- a/packages/backend/src/core/NoteCreateService.ts +++ b/packages/backend/src/core/NoteCreateService.ts @@ -711,7 +711,7 @@ export class NoteCreateService { ? this.apRendererService.renderAnnounce(data.renote.uri ? data.renote.uri : `${this.config.url}/notes/${data.renote.id}`, note) : this.apRendererService.renderCreate(await this.apRendererService.renderNote(note, false), note); - return this.apRendererService.renderActivity(content); + return this.apRendererService.addContext(content); } @bindThis diff --git a/packages/backend/src/core/NoteDeleteService.ts b/packages/backend/src/core/NoteDeleteService.ts index 4dad825097..fbcac2eff3 100644 --- a/packages/backend/src/core/NoteDeleteService.ts +++ b/packages/backend/src/core/NoteDeleteService.ts @@ -78,7 +78,7 @@ export class NoteDeleteService { }); } - const content = this.apRendererService.renderActivity(renote + const content = this.apRendererService.addContext(renote ? this.apRendererService.renderUndo(this.apRendererService.renderAnnounce(renote.uri ?? `${this.config.url}/notes/${renote.id}`, note), user) : this.apRendererService.renderDelete(this.apRendererService.renderTombstone(`${this.config.url}/notes/${note.id}`), user)); @@ -90,7 +90,7 @@ export class NoteDeleteService { for (const cascadingNote of cascadingNotes) { if (!cascadingNote.user) continue; if (!this.userEntityService.isLocalUser(cascadingNote.user)) continue; - const content = this.apRendererService.renderActivity(this.apRendererService.renderDelete(this.apRendererService.renderTombstone(`${this.config.url}/notes/${cascadingNote.id}`), cascadingNote.user)); + const content = this.apRendererService.addContext(this.apRendererService.renderDelete(this.apRendererService.renderTombstone(`${this.config.url}/notes/${cascadingNote.id}`), cascadingNote.user)); this.deliverToConcerned(cascadingNote.user, cascadingNote, content); } //#endregion diff --git a/packages/backend/src/core/NotePiningService.ts b/packages/backend/src/core/NotePiningService.ts index bb6def1edb..3a9f832ac0 100644 --- a/packages/backend/src/core/NotePiningService.ts +++ b/packages/backend/src/core/NotePiningService.ts @@ -115,7 +115,7 @@ export class NotePiningService { const target = `${this.config.url}/users/${user.id}/collections/featured`; const item = `${this.config.url}/notes/${noteId}`; - const content = this.apRendererService.renderActivity(isAddition ? this.apRendererService.renderAdd(user, target, item) : this.apRendererService.renderRemove(user, target, item)); + const content = this.apRendererService.addContext(isAddition ? this.apRendererService.renderAdd(user, target, item) : this.apRendererService.renderRemove(user, target, item)); this.apDeliverManagerService.deliverToFollowers(user, content); this.relayService.deliverToRelays(user, content); diff --git a/packages/backend/src/core/PollService.ts b/packages/backend/src/core/PollService.ts index 042dcb3e67..018e83f8cd 100644 --- a/packages/backend/src/core/PollService.ts +++ b/packages/backend/src/core/PollService.ts @@ -97,7 +97,7 @@ export class PollService { if (user == null) throw new Error('note not found'); if (this.userEntityService.isLocalUser(user)) { - const content = this.apRendererService.renderActivity(this.apRendererService.renderUpdate(await this.apRendererService.renderNote(note, false), user)); + const content = this.apRendererService.addContext(this.apRendererService.renderUpdate(await this.apRendererService.renderNote(note, false), user)); this.apDeliverManagerService.deliverToFollowers(user, content); this.relayService.deliverToRelays(user, content); } diff --git a/packages/backend/src/core/ReactionService.ts b/packages/backend/src/core/ReactionService.ts index 3806590059..9ac3058ef9 100644 --- a/packages/backend/src/core/ReactionService.ts +++ b/packages/backend/src/core/ReactionService.ts @@ -85,7 +85,7 @@ export class ReactionService { } @bindThis - public async create(user: { id: User['id']; host: User['host']; isBot: User['isBot'] }, note: Note, reaction?: string) { + public async create(user: { id: User['id']; host: User['host']; isBot: User['isBot'] }, note: Note, reaction?: string | null) { // Check blocking if (note.userId !== user.id) { const blocked = await this.userBlockingService.checkBlocked(note.userId, user.id); @@ -177,7 +177,7 @@ export class ReactionService { //#region 配信 if (this.userEntityService.isLocalUser(user) && !note.localOnly) { - const content = this.apRendererService.renderActivity(await this.apRendererService.renderLike(record, note)); + const content = this.apRendererService.addContext(await this.apRendererService.renderLike(record, note)); const dm = this.apDeliverManagerService.createDeliverManager(user, content); if (note.userHost !== null) { const reactee = await this.usersRepository.findOneBy({ id: note.userId }); @@ -235,7 +235,7 @@ export class ReactionService { //#region 配信 if (this.userEntityService.isLocalUser(user) && !note.localOnly) { - const content = this.apRendererService.renderActivity(this.apRendererService.renderUndo(await this.apRendererService.renderLike(exist, note), user)); + const content = this.apRendererService.addContext(this.apRendererService.renderUndo(await this.apRendererService.renderLike(exist, note), user)); const dm = this.apDeliverManagerService.createDeliverManager(user, content); if (note.userHost !== null) { const reactee = await this.usersRepository.findOneBy({ id: note.userId }); diff --git a/packages/backend/src/core/RelayService.ts b/packages/backend/src/core/RelayService.ts index a7408649b8..326fd0af1f 100644 --- a/packages/backend/src/core/RelayService.ts +++ b/packages/backend/src/core/RelayService.ts @@ -56,7 +56,7 @@ export class RelayService { const relayActor = await this.getRelayActor(); const follow = await this.apRendererService.renderFollowRelay(relay, relayActor); - const activity = this.apRendererService.renderActivity(follow); + const activity = this.apRendererService.addContext(follow); this.queueService.deliver(relayActor, activity, relay.inbox); return relay; @@ -75,7 +75,7 @@ export class RelayService { const relayActor = await this.getRelayActor(); const follow = this.apRendererService.renderFollowRelay(relay, relayActor); const undo = this.apRendererService.renderUndo(follow, relayActor); - const activity = this.apRendererService.renderActivity(undo); + const activity = this.apRendererService.addContext(undo); this.queueService.deliver(relayActor, activity, relay.inbox); await this.relaysRepository.delete(relay.id); diff --git a/packages/backend/src/core/UserBlockingService.ts b/packages/backend/src/core/UserBlockingService.ts index d734328669..89de72b9aa 100644 --- a/packages/backend/src/core/UserBlockingService.ts +++ b/packages/backend/src/core/UserBlockingService.ts @@ -117,7 +117,7 @@ export class UserBlockingService implements OnApplicationShutdown { }); if (this.userEntityService.isLocalUser(blocker) && this.userEntityService.isRemoteUser(blockee)) { - const content = this.apRendererService.renderActivity(this.apRendererService.renderBlock(blocking)); + const content = this.apRendererService.addContext(this.apRendererService.renderBlock(blocking)); this.queueService.deliver(blocker, content, blockee.inbox); } } @@ -162,13 +162,13 @@ export class UserBlockingService implements OnApplicationShutdown { // リモートにフォローリクエストをしていたらUndoFollow送信 if (this.userEntityService.isLocalUser(follower) && this.userEntityService.isRemoteUser(followee)) { - const content = this.apRendererService.renderActivity(this.apRendererService.renderUndo(this.apRendererService.renderFollow(follower, followee), follower)); + const content = this.apRendererService.addContext(this.apRendererService.renderUndo(this.apRendererService.renderFollow(follower, followee), follower)); this.queueService.deliver(follower, content, followee.inbox); } // リモートからフォローリクエストを受けていたらReject送信 if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) { - const content = this.apRendererService.renderActivity(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee, request.requestId!), followee)); + const content = this.apRendererService.addContext(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee, request.requestId!), followee)); this.queueService.deliver(followee, content, follower.inbox); } } @@ -210,13 +210,13 @@ export class UserBlockingService implements OnApplicationShutdown { // リモートにフォローをしていたらUndoFollow送信 if (this.userEntityService.isLocalUser(follower) && this.userEntityService.isRemoteUser(followee)) { - const content = this.apRendererService.renderActivity(this.apRendererService.renderUndo(this.apRendererService.renderFollow(follower, followee), follower)); + const content = this.apRendererService.addContext(this.apRendererService.renderUndo(this.apRendererService.renderFollow(follower, followee), follower)); this.queueService.deliver(follower, content, followee.inbox); } // リモートからフォローをされていたらRejectFollow送信 if (this.userEntityService.isLocalUser(followee) && this.userEntityService.isRemoteUser(follower)) { - const content = this.apRendererService.renderActivity(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee), followee)); + const content = this.apRendererService.addContext(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee), followee)); this.queueService.deliver(followee, content, follower.inbox); } } @@ -261,7 +261,7 @@ export class UserBlockingService implements OnApplicationShutdown { // deliver if remote bloking if (this.userEntityService.isLocalUser(blocker) && this.userEntityService.isRemoteUser(blockee)) { - const content = this.apRendererService.renderActivity(this.apRendererService.renderUndo(this.apRendererService.renderBlock(blocking), blocker)); + const content = this.apRendererService.addContext(this.apRendererService.renderUndo(this.apRendererService.renderBlock(blocking), blocker)); this.queueService.deliver(blocker, content, blockee.inbox); } } diff --git a/packages/backend/src/core/UserCacheService.ts b/packages/backend/src/core/UserCacheService.ts index 29a64f5848..52cedbd105 100644 --- a/packages/backend/src/core/UserCacheService.ts +++ b/packages/backend/src/core/UserCacheService.ts @@ -45,10 +45,10 @@ export class UserCacheService implements OnApplicationShutdown { case 'userChangeSuspendedState': case 'remoteUserUpdated': { const user = await this.usersRepository.findOneByOrFail({ id: body.id }); - this.userByIdCache.set(user.id, user); + this.userByIdCache.set(user.id, user as CacheableUser); for (const [k, v] of this.uriPersonCache.cache.entries()) { if (v.value?.id === user.id) { - this.uriPersonCache.set(k, user); + this.uriPersonCache.set(k, user as CacheableUser); } } if (this.userEntityService.isLocalUser(user)) { @@ -78,7 +78,7 @@ export class UserCacheService implements OnApplicationShutdown { @bindThis public findById(userId: User['id']) { - return this.userByIdCache.fetch(userId, () => this.usersRepository.findOneByOrFail({ id: userId })); + return this.userByIdCache.fetch(userId, () => this.usersRepository.findOneByOrFail({ id: userId }) as Promise); } @bindThis diff --git a/packages/backend/src/core/UserFollowingService.ts b/packages/backend/src/core/UserFollowingService.ts index 2214a4862a..a50f19a477 100644 --- a/packages/backend/src/core/UserFollowingService.ts +++ b/packages/backend/src/core/UserFollowingService.ts @@ -81,7 +81,7 @@ export class UserFollowingService { if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee) && blocked) { // リモートフォローを受けてブロックしていた場合は、エラーにするのではなくRejectを送り返しておしまい。 - const content = this.apRendererService.renderActivity(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee, requestId), followee)); + const content = this.apRendererService.addContext(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee, requestId), followee)); this.queueService.deliver(followee, content, follower.inbox); return; } else if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee) && blocking) { @@ -130,7 +130,7 @@ export class UserFollowingService { await this.insertFollowingDoc(followee, follower); if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) { - const content = this.apRendererService.renderActivity(this.apRendererService.renderAccept(this.apRendererService.renderFollow(follower, followee, requestId), followee)); + const content = this.apRendererService.addContext(this.apRendererService.renderAccept(this.apRendererService.renderFollow(follower, followee, requestId), followee)); this.queueService.deliver(followee, content, follower.inbox); } } @@ -293,13 +293,13 @@ export class UserFollowingService { } if (this.userEntityService.isLocalUser(follower) && this.userEntityService.isRemoteUser(followee)) { - const content = this.apRendererService.renderActivity(this.apRendererService.renderUndo(this.apRendererService.renderFollow(follower, followee), follower)); + const content = this.apRendererService.addContext(this.apRendererService.renderUndo(this.apRendererService.renderFollow(follower, followee), follower)); this.queueService.deliver(follower, content, followee.inbox); } if (this.userEntityService.isLocalUser(followee) && this.userEntityService.isRemoteUser(follower)) { // local user has null host - const content = this.apRendererService.renderActivity(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee), followee)); + const content = this.apRendererService.addContext(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee), followee)); this.queueService.deliver(followee, content, follower.inbox); } } @@ -388,7 +388,7 @@ export class UserFollowingService { } if (this.userEntityService.isLocalUser(follower) && this.userEntityService.isRemoteUser(followee)) { - const content = this.apRendererService.renderActivity(this.apRendererService.renderFollow(follower, followee)); + const content = this.apRendererService.addContext(this.apRendererService.renderFollow(follower, followee)); this.queueService.deliver(follower, content, followee.inbox); } } @@ -403,7 +403,7 @@ export class UserFollowingService { }, ): Promise { if (this.userEntityService.isRemoteUser(followee)) { - const content = this.apRendererService.renderActivity(this.apRendererService.renderUndo(this.apRendererService.renderFollow(follower, followee), follower)); + const content = this.apRendererService.addContext(this.apRendererService.renderUndo(this.apRendererService.renderFollow(follower, followee), follower)); if (this.userEntityService.isLocalUser(follower)) { // 本来このチェックは不要だけどTSに怒られるので this.queueService.deliver(follower, content, followee.inbox); @@ -448,7 +448,7 @@ export class UserFollowingService { await this.insertFollowingDoc(followee, follower); if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) { - const content = this.apRendererService.renderActivity(this.apRendererService.renderAccept(this.apRendererService.renderFollow(follower, followee, request.requestId!), followee)); + const content = this.apRendererService.addContext(this.apRendererService.renderAccept(this.apRendererService.renderFollow(follower, followee, request.requestId!), followee)); this.queueService.deliver(followee, content, follower.inbox); } @@ -556,7 +556,7 @@ export class UserFollowingService { followerId: follower.id, }); - const content = this.apRendererService.renderActivity(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee, request?.requestId ?? undefined), followee)); + const content = this.apRendererService.addContext(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee, request?.requestId ?? undefined), followee)); this.queueService.deliver(followee, content, follower.inbox); } diff --git a/packages/backend/src/core/UserSuspendService.ts b/packages/backend/src/core/UserSuspendService.ts index df1664942f..02903a0590 100644 --- a/packages/backend/src/core/UserSuspendService.ts +++ b/packages/backend/src/core/UserSuspendService.ts @@ -35,7 +35,7 @@ export class UserSuspendService { if (this.userEntityService.isLocalUser(user)) { // 知り得る全SharedInboxにDelete配信 - const content = this.apRendererService.renderActivity(this.apRendererService.renderDelete(`${this.config.url}/users/${user.id}`, user)); + const content = this.apRendererService.addContext(this.apRendererService.renderDelete(`${this.config.url}/users/${user.id}`, user)); const queue: string[] = []; @@ -65,7 +65,7 @@ export class UserSuspendService { if (this.userEntityService.isLocalUser(user)) { // 知り得る全SharedInboxにUndo Delete配信 - const content = this.apRendererService.renderActivity(this.apRendererService.renderUndo(this.apRendererService.renderDelete(`${this.config.url}/users/${user.id}`, user), user)); + const content = this.apRendererService.addContext(this.apRendererService.renderUndo(this.apRendererService.renderDelete(`${this.config.url}/users/${user.id}`, user), user)); const queue: string[] = []; diff --git a/packages/backend/src/core/activitypub/ApDbResolverService.ts b/packages/backend/src/core/activitypub/ApDbResolverService.ts index 1d0c2d5da4..b057f39b05 100644 --- a/packages/backend/src/core/activitypub/ApDbResolverService.ts +++ b/packages/backend/src/core/activitypub/ApDbResolverService.ts @@ -130,11 +130,11 @@ export class ApDbResolverService { return await this.userCacheService.userByIdCache.fetchMaybe(parsed.id, () => this.usersRepository.findOneBy({ id: parsed.id, - }).then(x => x ?? undefined)) ?? null; + }).then(x => (x as CacheableUser | null) ?? undefined)) ?? null; } else { return await this.userCacheService.uriPersonCache.fetch(parsed.uri, () => this.usersRepository.findOneBy({ uri: parsed.uri, - })); + }) as Promise); } } diff --git a/packages/backend/src/core/activitypub/ApInboxService.ts b/packages/backend/src/core/activitypub/ApInboxService.ts index 76c8bf68df..02bb0ca4ec 100644 --- a/packages/backend/src/core/activitypub/ApInboxService.ts +++ b/packages/backend/src/core/activitypub/ApInboxService.ts @@ -2,7 +2,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { In } from 'typeorm'; import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; -import type { CacheableRemoteUser } from '@/models/entities/User.js'; +import type { CacheableRemoteUser, CacheableUser } from '@/models/entities/User.js'; import { UserFollowingService } from '@/core/UserFollowingService.js'; import { ReactionService } from '@/core/ReactionService.js'; import { RelayService } from '@/core/RelayService.js'; @@ -22,6 +22,7 @@ import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { QueueService } from '@/core/QueueService.js'; import { MessagingService } from '@/core/MessagingService.js'; import type { UsersRepository, NotesRepository, FollowingsRepository, MessagingMessagesRepository, AbuseUserReportsRepository, FollowRequestsRepository } from '@/models/index.js'; +import { bindThis } from '@/decorators.js'; import { getApId, getApIds, getApType, isAccept, isActor, isAdd, isAnnounce, isBlock, isCollection, isCollectionOrOrderedCollection, isCreate, isDelete, isFlag, isFollow, isLike, isPost, isRead, isReject, isRemove, isTombstone, isUndo, isUpdate, validActor, validPost } from './type.js'; import { ApNoteService } from './models/ApNoteService.js'; import { ApLoggerService } from './ApLoggerService.js'; @@ -32,7 +33,6 @@ import { ApPersonService } from './models/ApPersonService.js'; import { ApQuestionService } from './models/ApQuestionService.js'; import type { Resolver } from './ApResolverService.js'; import type { IAccept, IAdd, IAnnounce, IBlock, ICreate, IDelete, IFlag, IFollow, ILike, IObject, IRead, IReject, IRemove, IUndo, IUpdate } from './type.js'; -import { bindThis } from '@/decorators.js'; @Injectable() export class ApInboxService { @@ -687,7 +687,7 @@ export class ApInboxService { return 'skip: ブロック解除しようとしているユーザーはローカルユーザーではありません'; } - await this.userBlockingService.unblock(await this.usersRepository.findOneByOrFail({ id: actor.id }), blockee); + await this.userBlockingService.unblock(await this.usersRepository.findOneByOrFail({ id: actor.id }) as CacheableUser, blockee); return 'ok'; } diff --git a/packages/backend/src/core/activitypub/ApRendererService.ts b/packages/backend/src/core/activitypub/ApRendererService.ts index 648f30229a..b87aee8804 100644 --- a/packages/backend/src/core/activitypub/ApRendererService.ts +++ b/packages/backend/src/core/activitypub/ApRendererService.ts @@ -24,7 +24,7 @@ import type { UsersRepository, UserProfilesRepository, NotesRepository, DriveFil import { bindThis } from '@/decorators.js'; import { LdSignatureService } from './LdSignatureService.js'; import { ApMfmService } from './ApMfmService.js'; -import type { IActivity, IObject } from './type.js'; +import type { IAccept, IActivity, IAdd, IAnnounce, IApDocument, IApEmoji, IApHashtag, IApImage, IApMention, IBlock, ICreate, IDelete, IFlag, IFollow, IKey, ILike, IObject, IQuestion, IRead, IReject, IRemove, ITombstone, IUndo, IUpdate } from './type.js'; import type { IIdentifier } from './models/identifier.js'; @Injectable() @@ -61,7 +61,7 @@ export class ApRendererService { } @bindThis - public renderAccept(object: any, user: { id: User['id']; host: null }) { + public renderAccept(object: any, user: { id: User['id']; host: null }): IAccept { return { type: 'Accept', actor: `${this.config.url}/users/${user.id}`, @@ -70,7 +70,7 @@ export class ApRendererService { } @bindThis - public renderAdd(user: ILocalUser, target: any, object: any) { + public renderAdd(user: ILocalUser, target: any, object: any): IAdd { return { type: 'Add', actor: `${this.config.url}/users/${user.id}`, @@ -80,7 +80,7 @@ export class ApRendererService { } @bindThis - public renderAnnounce(object: any, note: Note) { + public renderAnnounce(object: any, note: Note): IAnnounce { const attributedTo = `${this.config.url}/users/${note.userId}`; let to: string[] = []; @@ -93,7 +93,7 @@ export class ApRendererService { to = [`${attributedTo}/followers`]; cc = ['https://www.w3.org/ns/activitystreams#Public']; } else { - return null; + throw new Error('renderAnnounce: cannot render non-public note'); } return { @@ -113,7 +113,7 @@ export class ApRendererService { * @param block The block to be rendered. The blockee relation must be loaded. */ @bindThis - public renderBlock(block: Blocking) { + public renderBlock(block: Blocking): IBlock { if (block.blockee?.uri == null) { throw new Error('renderBlock: missing blockee uri'); } @@ -127,14 +127,14 @@ export class ApRendererService { } @bindThis - public renderCreate(object: any, note: Note) { + public renderCreate(object: IObject, note: Note): ICreate { const activity = { id: `${this.config.url}/notes/${note.id}/activity`, actor: `${this.config.url}/users/${note.userId}`, type: 'Create', published: note.createdAt.toISOString(), object, - } as any; + } as ICreate; if (object.to) activity.to = object.to; if (object.cc) activity.cc = object.cc; @@ -143,7 +143,7 @@ export class ApRendererService { } @bindThis - public renderDelete(object: any, user: { id: User['id']; host: null }) { + public renderDelete(object: IObject | string, user: { id: User['id']; host: null }): IDelete { return { type: 'Delete', actor: `${this.config.url}/users/${user.id}`, @@ -153,7 +153,7 @@ export class ApRendererService { } @bindThis - public renderDocument(file: DriveFile) { + public renderDocument(file: DriveFile): IApDocument { return { type: 'Document', mediaType: file.type, @@ -163,12 +163,12 @@ export class ApRendererService { } @bindThis - public renderEmoji(emoji: Emoji) { + public renderEmoji(emoji: Emoji): IApEmoji { return { id: `${this.config.url}/emojis/${emoji.name}`, type: 'Emoji', name: `:${emoji.name}:`, - updated: emoji.updatedAt != null ? emoji.updatedAt.toISOString() : new Date().toISOString, + updated: emoji.updatedAt != null ? emoji.updatedAt.toISOString() : new Date().toISOString(), icon: { type: 'Image', mediaType: emoji.type ?? 'image/png', @@ -181,7 +181,7 @@ export class ApRendererService { // to anonymise reporters, the reporting actor must be a system user // object has to be a uri or array of uris @bindThis - public renderFlag(user: ILocalUser, object: [string], content: string) { + public renderFlag(user: ILocalUser, object: IObject, content: string): IFlag { return { type: 'Flag', actor: `${this.config.url}/users/${user.id}`, @@ -191,15 +191,13 @@ export class ApRendererService { } @bindThis - public renderFollowRelay(relay: Relay, relayActor: ILocalUser) { - const follow = { + public renderFollowRelay(relay: Relay, relayActor: ILocalUser): IFollow { + return { id: `${this.config.url}/activities/follow-relay/${relay.id}`, type: 'Follow', actor: `${this.config.url}/users/${relayActor.id}`, object: 'https://www.w3.org/ns/activitystreams#Public', }; - - return follow; } /** @@ -217,19 +215,17 @@ export class ApRendererService { follower: { id: User['id']; host: User['host']; uri: User['host'] }, followee: { id: User['id']; host: User['host']; uri: User['host'] }, requestId?: string, - ) { - const follow = { + ): IFollow { + return { id: requestId ?? `${this.config.url}/follows/${follower.id}/${followee.id}`, type: 'Follow', - actor: this.userEntityService.isLocalUser(follower) ? `${this.config.url}/users/${follower.id}` : follower.uri, - object: this.userEntityService.isLocalUser(followee) ? `${this.config.url}/users/${followee.id}` : followee.uri, - } as any; - - return follow; + actor: this.userEntityService.isLocalUser(follower) ? `${this.config.url}/users/${follower.id}` : follower.uri!, + object: this.userEntityService.isLocalUser(followee) ? `${this.config.url}/users/${followee.id}` : followee.uri!, + }; } @bindThis - public renderHashtag(tag: string) { + public renderHashtag(tag: string): IApHashtag { return { type: 'Hashtag', href: `${this.config.url}/tags/${encodeURIComponent(tag)}`, @@ -238,7 +234,7 @@ export class ApRendererService { } @bindThis - public renderImage(file: DriveFile) { + public renderImage(file: DriveFile): IApImage { return { type: 'Image', url: this.driveFileEntityService.getPublicUrl(file), @@ -248,7 +244,7 @@ export class ApRendererService { } @bindThis - public renderKey(user: ILocalUser, key: UserKeypair, postfix?: string) { + public renderKey(user: ILocalUser, key: UserKeypair, postfix?: string): IKey { return { id: `${this.config.url}/users/${user.id}${postfix ?? '/publickey'}`, type: 'Key', @@ -261,7 +257,7 @@ export class ApRendererService { } @bindThis - public async renderLike(noteReaction: NoteReaction, note: { uri: string | null }) { + public async renderLike(noteReaction: NoteReaction, note: { uri: string | null }): Promise { const reaction = noteReaction.reaction; const object = { @@ -271,10 +267,11 @@ export class ApRendererService { object: note.uri ? note.uri : `${this.config.url}/notes/${noteReaction.noteId}`, content: reaction, _misskey_reaction: reaction, - } as any; + } as ILike; if (reaction.startsWith(':')) { const name = reaction.replaceAll(':', ''); + // TODO: cache const emoji = await this.emojisRepository.findOneBy({ name, host: IsNull(), @@ -287,10 +284,10 @@ export class ApRendererService { } @bindThis - public renderMention(mention: User) { + public renderMention(mention: User): IApMention { return { type: 'Mention', - href: this.userEntityService.isRemoteUser(mention) ? mention.uri : `${this.config.url}/users/${(mention as ILocalUser).id}`, + href: this.userEntityService.isRemoteUser(mention) ? mention.uri! : `${this.config.url}/users/${(mention as ILocalUser).id}`, name: this.userEntityService.isRemoteUser(mention) ? `@${mention.username}@${mention.host}` : `@${(mention as ILocalUser).username}`, }; } @@ -518,8 +515,8 @@ export class ApRendererService { } @bindThis - public async renderQuestion(user: { id: User['id'] }, note: Note, poll: Poll) { - const question = { + public async renderQuestion(user: { id: User['id'] }, note: Note, poll: Poll): IQuestion { + return { type: 'Question', id: `${this.config.url}/questions/${note.id}`, actor: `${this.config.url}/users/${user.id}`, @@ -533,21 +530,19 @@ export class ApRendererService { }, })), }; - - return question; } @bindThis - public renderRead(user: { id: User['id'] }, message: MessagingMessage) { + public renderRead(user: { id: User['id'] }, message: MessagingMessage): IRead { return { type: 'Read', actor: `${this.config.url}/users/${user.id}`, - object: message.uri, + object: message.uri!, }; } @bindThis - public renderReject(object: any, user: { id: User['id'] }) { + public renderReject(object: any, user: { id: User['id'] }): IReject { return { type: 'Reject', actor: `${this.config.url}/users/${user.id}`, @@ -556,7 +551,7 @@ export class ApRendererService { } @bindThis - public renderRemove(user: { id: User['id'] }, target: any, object: any) { + public renderRemove(user: { id: User['id'] }, target: any, object: any): IRemove { return { type: 'Remove', actor: `${this.config.url}/users/${user.id}`, @@ -566,7 +561,7 @@ export class ApRendererService { } @bindThis - public renderTombstone(id: string) { + public renderTombstone(id: string): ITombstone { return { id, type: 'Tombstone', @@ -574,8 +569,7 @@ export class ApRendererService { } @bindThis - public renderUndo(object: any, user: { id: User['id'] }) { - if (object == null) return null; + public renderUndo(object: any, user: { id: User['id'] }): IUndo { const id = typeof object.id === 'string' && object.id.startsWith(this.config.url) ? `${object.id}/undo` : undefined; return { @@ -588,21 +582,19 @@ export class ApRendererService { } @bindThis - public renderUpdate(object: any, user: { id: User['id'] }) { - const activity = { + public renderUpdate(object: any, user: { id: User['id'] }): IUpdate { + return { id: `${this.config.url}/users/${user.id}#updates/${new Date().getTime()}`, actor: `${this.config.url}/users/${user.id}`, type: 'Update', to: ['https://www.w3.org/ns/activitystreams#Public'], object, published: new Date().toISOString(), - } as any; - - return activity; + }; } @bindThis - public renderVote(user: { id: User['id'] }, vote: PollVote, note: Note, poll: Poll, pollOwner: IRemoteUser) { + public renderVote(user: { id: User['id'] }, vote: PollVote, note: Note, poll: Poll, pollOwner: IRemoteUser): ICreate { return { id: `${this.config.url}/users/${user.id}#votes/${vote.id}/activity`, actor: `${this.config.url}/users/${user.id}`, @@ -621,9 +613,7 @@ export class ApRendererService { } @bindThis - public renderActivity(x: any): IActivity | null { - if (x == null) return null; - + public addContext(x: T): T & { '@context': any; id: string; } { if (typeof x === 'object' && x.id == null) { x.id = `${this.config.url}/${uuid()}`; } @@ -659,7 +649,7 @@ export class ApRendererService { vcard: 'http://www.w3.org/2006/vcard/ns#', }, ], - }, x); + }, x as T & { id: string; }); } @bindThis diff --git a/packages/backend/src/core/activitypub/ApResolverService.ts b/packages/backend/src/core/activitypub/ApResolverService.ts index 7e962cb127..65026cc4c5 100644 --- a/packages/backend/src/core/activitypub/ApResolverService.ts +++ b/packages/backend/src/core/activitypub/ApResolverService.ts @@ -38,8 +38,7 @@ export class Resolver { private recursionLimit = 100, ) { this.history = new Set(); - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - this.logger = this.loggerService?.getLogger('ap-resolve'); // なぜか TypeError: Cannot read properties of undefined (reading 'getLogger') と言われる + this.logger = this.loggerService.getLogger('ap-resolve'); } @bindThis @@ -124,10 +123,10 @@ export class Resolver { switch (parsed.type) { case 'notes': return this.notesRepository.findOneByOrFail({ id: parsed.id }) - .then(note => { + .then(async note => { if (parsed.rest === 'activity') { // this refers to the create activity and not the note itself - return this.apRendererService.renderActivity(this.apRendererService.renderCreate(this.apRendererService.renderNote(note), note)); + return this.apRendererService.addContext(this.apRendererService.renderCreate(await this.apRendererService.renderNote(note), note)); } else { return this.apRendererService.renderNote(note); } @@ -143,8 +142,8 @@ export class Resolver { ]) .then(([note, poll]) => this.apRendererService.renderQuestion({ id: note.userId }, note, poll)); case 'likes': - return this.noteReactionsRepository.findOneByOrFail({ id: parsed.id }).then(reaction => - this.apRendererService.renderActivity(this.apRendererService.renderLike(reaction, { uri: null }))!); + return this.noteReactionsRepository.findOneByOrFail({ id: parsed.id }).then(async reaction => + this.apRendererService.addContext(await this.apRendererService.renderLike(reaction, { uri: null }))); case 'follows': // rest should be if (parsed.rest == null || !/^\w+$/.test(parsed.rest)) throw new Error('resolveLocal: invalid follow URI'); @@ -152,7 +151,7 @@ export class Resolver { return Promise.all( [parsed.id, parsed.rest].map(id => this.usersRepository.findOneByOrFail({ id })), ) - .then(([follower, followee]) => this.apRendererService.renderActivity(this.apRendererService.renderFollow(follower, followee, url))); + .then(([follower, followee]) => this.apRendererService.addContext(this.apRendererService.renderFollow(follower, followee, url))); default: throw new Error(`resolveLocal: type ${parsed.type} unhandled`); } @@ -184,6 +183,7 @@ export class ApResolverService { private httpRequestService: HttpRequestService, private apRendererService: ApRendererService, private apDbResolverService: ApDbResolverService, + private loggerService: LoggerService, ) { } @@ -202,6 +202,7 @@ export class ApResolverService { this.httpRequestService, this.apRendererService, this.apDbResolverService, + this.loggerService, ); } } diff --git a/packages/backend/src/core/activitypub/models/ApNoteService.ts b/packages/backend/src/core/activitypub/models/ApNoteService.ts index 813415e6f6..dc47fdf800 100644 --- a/packages/backend/src/core/activitypub/models/ApNoteService.ts +++ b/packages/backend/src/core/activitypub/models/ApNoteService.ts @@ -114,7 +114,7 @@ export class ApNoteService { public async createNote(value: string | IObject, resolver?: Resolver, silent = false): Promise { if (resolver == null) resolver = this.apResolverService.createResolver(); - const object: any = await resolver.resolve(value); + const object = await resolver.resolve(value); const entryUri = getApId(value); const err = this.validateNote(object, entryUri); @@ -129,7 +129,7 @@ export class ApNoteService { throw new Error('invalid note'); } - const note: IPost = object; + const note: IPost = object as any; this.logger.debug(`Note fetched: ${JSON.stringify(note, null, 2)}`); @@ -146,7 +146,7 @@ export class ApNoteService { this.logger.info(`Creating the Note: ${note.id}`); // 投稿者をフェッチ - const actor = await this.apPersonService.resolvePerson(getOneApId(note.attributedTo), resolver) as CacheableRemoteUser; + const actor = await this.apPersonService.resolvePerson(getOneApId(note.attributedTo!), resolver) as CacheableRemoteUser; // 投稿者が凍結されていたらスキップ if (actor.isSuspended) { diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts index 76f820cda0..4869656f1d 100644 --- a/packages/backend/src/core/activitypub/models/ApPersonService.ts +++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts @@ -206,13 +206,13 @@ export class ApPersonService implements OnModuleInit { // URIがこのサーバーを指しているならデータベースからフェッチ if (uri.startsWith(this.config.url + '/')) { const id = uri.split('/').pop(); - const u = await this.usersRepository.findOneBy({ id }); + const u = await this.usersRepository.findOneBy({ id }) as null | CacheableUser; if (u) this.userCacheService.uriPersonCache.set(uri, u); return u; } //#region このサーバーに既に登録されていたらそれを返す - const exist = await this.usersRepository.findOneBy({ uri }); + const exist = await this.usersRepository.findOneBy({ uri }) as null | CacheableUser; if (exist) { this.userCacheService.uriPersonCache.set(uri, exist); @@ -513,7 +513,7 @@ export class ApPersonService implements OnModuleInit { // リモートサーバーからフェッチしてきて登録 if (resolver == null) resolver = this.apResolverService.createResolver(); - return await this.createPerson(uri, resolver); + return await this.createPerson(uri, resolver) as CacheableUser; } @bindThis diff --git a/packages/backend/src/core/activitypub/type.ts b/packages/backend/src/core/activitypub/type.ts index dcc5110aa5..b900e375bd 100644 --- a/packages/backend/src/core/activitypub/type.ts +++ b/packages/backend/src/core/activitypub/type.ts @@ -2,24 +2,24 @@ export type obj = { [x: string]: any }; export type ApObject = IObject | string | (IObject | string)[]; export interface IObject { - '@context': string | string[] | obj | obj[]; + '@context'?: string | string[] | obj | obj[]; type: string | string[]; id?: string; + name?: string | null; summary?: string; published?: string; cc?: ApObject; to?: ApObject; - attributedTo: ApObject; + attributedTo?: ApObject; attachment?: any[]; inReplyTo?: any; replies?: ICollection; content?: string; - name?: string; startTime?: Date; endTime?: Date; icon?: any; image?: any; - url?: ApObject; + url?: ApObject | string; href?: string; tag?: IObject | IObject[]; sensitive?: boolean; @@ -118,6 +118,7 @@ export interface IPost extends IObject { export interface IQuestion extends IObject { type: 'Note' | 'Question'; + actor: string; source?: { content: string; mediaType: string; @@ -200,6 +201,7 @@ export const isPropertyValue = (object: IObject): object is IApPropertyValue => export interface IApMention extends IObject { type: 'Mention'; href: string; + name: string; } export const isMention = (object: IObject): object is IApMention => @@ -217,12 +219,30 @@ export const isHashtag = (object: IObject): object is IApHashtag => export interface IApEmoji extends IObject { type: 'Emoji'; - updated: Date; + name: string; + updated: string; } export const isEmoji = (object: IObject): object is IApEmoji => getApType(object) === 'Emoji' && !Array.isArray(object.icon) && object.icon.url != null; +export interface IKey extends IObject { + type: 'Key'; + owner: string; + publicKeyPem: string | Buffer; +} + +export interface IApDocument extends IObject { + type: 'Document'; + name: string | null; + mediaType: string; +} + +export interface IApImage extends IObject { + type: 'Image'; + name: string | null; +} + export interface ICreate extends IActivity { type: 'Create'; } diff --git a/packages/backend/src/core/entities/DriveFileEntityService.ts b/packages/backend/src/core/entities/DriveFileEntityService.ts index b8550cd73e..38af51a196 100644 --- a/packages/backend/src/core/entities/DriveFileEntityService.ts +++ b/packages/backend/src/core/entities/DriveFileEntityService.ts @@ -11,9 +11,9 @@ import type { DriveFile } from '@/models/entities/DriveFile.js'; import { appendQuery, query } from '@/misc/prelude/url.js'; import { deepClone } from '@/misc/clone.js'; import { UtilityService } from '../UtilityService.js'; +import { VideoProcessingService } from '../VideoProcessingService.js'; import { UserEntityService } from './UserEntityService.js'; import { DriveFolderEntityService } from './DriveFolderEntityService.js'; -import { VideoProcessingService } from '../VideoProcessingService.js'; type PackOptions = { detail?: boolean, @@ -74,14 +74,14 @@ export class DriveFileEntityService { } @bindThis - private getProxiedUrl(url: string, mode?: 'static' | 'avatar'): string | null { + private getProxiedUrl(url: string, mode?: 'static' | 'avatar'): string { return appendQuery( `${this.config.mediaProxy}/${mode ?? 'image'}.webp`, query({ url, ...(mode ? { [mode]: '1' } : {}), - }) - ) + }), + ); } @bindThis @@ -110,7 +110,7 @@ export class DriveFileEntityService { } @bindThis - public getPublicUrl(file: DriveFile, mode?: 'avatar'): string | null { // static = thumbnail + public getPublicUrl(file: DriveFile, mode?: 'avatar'): string { // static = thumbnail // リモートかつメディアプロキシ if (file.uri != null && file.userHost != null && this.config.externalMediaProxyEnabled) { return this.getProxiedUrl(file.uri, mode); diff --git a/packages/backend/src/models/entities/User.ts b/packages/backend/src/models/entities/User.ts index 1cfcc814ea..9cfe79787a 100644 --- a/packages/backend/src/models/entities/User.ts +++ b/packages/backend/src/models/entities/User.ts @@ -221,6 +221,7 @@ export interface ILocalUser extends User { export interface IRemoteUser extends User { host: string; + uri: string; } export type CacheableLocalUser = ILocalUser; diff --git a/packages/backend/src/server/ActivityPubServerService.ts b/packages/backend/src/server/ActivityPubServerService.ts index 5480395eeb..c3795223ad 100644 --- a/packages/backend/src/server/ActivityPubServerService.ts +++ b/packages/backend/src/server/ActivityPubServerService.ts @@ -183,13 +183,13 @@ export class ActivityPubServerService { ); this.setResponseType(request, reply); - return (this.apRendererService.renderActivity(rendered)); + return (this.apRendererService.addContext(rendered)); } else { // index page const rendered = this.apRendererService.renderOrderedCollection(partOf, user.followersCount, `${partOf}?page=true`); reply.header('Cache-Control', 'public, max-age=180'); this.setResponseType(request, reply); - return (this.apRendererService.renderActivity(rendered)); + return (this.apRendererService.addContext(rendered)); } } @@ -271,13 +271,13 @@ export class ActivityPubServerService { ); this.setResponseType(request, reply); - return (this.apRendererService.renderActivity(rendered)); + return (this.apRendererService.addContext(rendered)); } else { // index page const rendered = this.apRendererService.renderOrderedCollection(partOf, user.followingCount, `${partOf}?page=true`); reply.header('Cache-Control', 'public, max-age=180'); this.setResponseType(request, reply); - return (this.apRendererService.renderActivity(rendered)); + return (this.apRendererService.addContext(rendered)); } } @@ -312,7 +312,7 @@ export class ActivityPubServerService { reply.header('Cache-Control', 'public, max-age=180'); this.setResponseType(request, reply); - return (this.apRendererService.renderActivity(rendered)); + return (this.apRendererService.addContext(rendered)); } @bindThis @@ -389,7 +389,7 @@ export class ActivityPubServerService { ); this.setResponseType(request, reply); - return (this.apRendererService.renderActivity(rendered)); + return (this.apRendererService.addContext(rendered)); } else { // index page const rendered = this.apRendererService.renderOrderedCollection(partOf, user.notesCount, @@ -398,7 +398,7 @@ export class ActivityPubServerService { ); reply.header('Cache-Control', 'public, max-age=180'); this.setResponseType(request, reply); - return (this.apRendererService.renderActivity(rendered)); + return (this.apRendererService.addContext(rendered)); } } @@ -411,7 +411,7 @@ export class ActivityPubServerService { reply.header('Cache-Control', 'public, max-age=180'); this.setResponseType(request, reply); - return (this.apRendererService.renderActivity(await this.apRendererService.renderPerson(user as ILocalUser))); + return (this.apRendererService.addContext(await this.apRendererService.renderPerson(user as ILocalUser))); } @bindThis @@ -481,7 +481,7 @@ export class ActivityPubServerService { reply.header('Cache-Control', 'public, max-age=180'); this.setResponseType(request, reply); - return (this.apRendererService.renderActivity(await this.apRendererService.renderNote(note, false))); + return this.apRendererService.addContext(await this.apRendererService.renderNote(note, false)); }); // note activity @@ -502,7 +502,7 @@ export class ActivityPubServerService { reply.header('Cache-Control', 'public, max-age=180'); this.setResponseType(request, reply); - return (this.apRendererService.renderActivity(await this.packActivity(note))); + return (this.apRendererService.addContext(await this.packActivity(note))); }); // outbox @@ -545,7 +545,7 @@ export class ActivityPubServerService { if (this.userEntityService.isLocalUser(user)) { reply.header('Cache-Control', 'public, max-age=180'); this.setResponseType(request, reply); - return (this.apRendererService.renderActivity(this.apRendererService.renderKey(user, keypair))); + return (this.apRendererService.addContext(this.apRendererService.renderKey(user, keypair))); } else { reply.code(400); return; @@ -589,7 +589,7 @@ export class ActivityPubServerService { reply.header('Cache-Control', 'public, max-age=180'); this.setResponseType(request, reply); - return (this.apRendererService.renderActivity(await this.apRendererService.renderEmoji(emoji))); + return (this.apRendererService.addContext(await this.apRendererService.renderEmoji(emoji))); }); // like @@ -610,7 +610,7 @@ export class ActivityPubServerService { reply.header('Cache-Control', 'public, max-age=180'); this.setResponseType(request, reply); - return (this.apRendererService.renderActivity(await this.apRendererService.renderLike(reaction, note))); + return (this.apRendererService.addContext(await this.apRendererService.renderLike(reaction, note))); }); // follow @@ -636,7 +636,7 @@ export class ActivityPubServerService { reply.header('Cache-Control', 'public, max-age=180'); this.setResponseType(request, reply); - return (this.apRendererService.renderActivity(this.apRendererService.renderFollow(follower, followee))); + return (this.apRendererService.addContext(this.apRendererService.renderFollow(follower, followee))); }); done(); diff --git a/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts b/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts index cdaec13a3f..84fcc05edc 100644 --- a/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts +++ b/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts @@ -49,7 +49,7 @@ export default class extends Endpoint { const actor = await this.instanceActorService.getInstanceActor(); const targetUser = await this.usersRepository.findOneByOrFail({ id: report.targetUserId }); - this.queueService.deliver(actor, this.apRendererService.renderActivity(this.apRendererService.renderFlag(actor, [targetUser.uri!], report.comment)), targetUser.inbox); + this.queueService.deliver(actor, this.apRendererService.addContext(this.apRendererService.renderFlag(actor, [targetUser.uri!], report.comment)), targetUser.inbox); } await this.abuseUserReportsRepository.update(report.id, { diff --git a/packages/backend/src/server/api/endpoints/notes/polls/vote.ts b/packages/backend/src/server/api/endpoints/notes/polls/vote.ts index befaea4664..d8e1a1149f 100644 --- a/packages/backend/src/server/api/endpoints/notes/polls/vote.ts +++ b/packages/backend/src/server/api/endpoints/notes/polls/vote.ts @@ -162,7 +162,7 @@ export default class extends Endpoint { if (note.userHost != null) { const pollOwner = await this.usersRepository.findOneByOrFail({ id: note.userId }) as IRemoteUser; - this.queueService.deliver(me, this.apRendererService.renderActivity(await this.apRendererService.renderVote(me, vote, note, poll, pollOwner)), pollOwner.inbox); + this.queueService.deliver(me, this.apRendererService.addContext(await this.apRendererService.renderVote(me, vote, note, poll, pollOwner)), pollOwner.inbox); } // リモートフォロワーにUpdate配信 From 5d3d5cd59cd10cf9fbba40c04caf5ab8675632e1 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 12 Feb 2023 18:54:38 +0900 Subject: [PATCH 067/294] refactor: fix types --- packages/backend/src/core/UserFollowingService.ts | 2 +- packages/backend/src/core/activitypub/type.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/core/UserFollowingService.ts b/packages/backend/src/core/UserFollowingService.ts index a50f19a477..c0347c60eb 100644 --- a/packages/backend/src/core/UserFollowingService.ts +++ b/packages/backend/src/core/UserFollowingService.ts @@ -434,7 +434,7 @@ export class UserFollowingService { followee: { id: User['id']; host: User['host']; uri: User['host']; inbox: User['inbox']; sharedInbox: User['sharedInbox']; }, - follower: CacheableUser, + follower: User | CacheableUser, ): Promise { const request = await this.followRequestsRepository.findOneBy({ followeeId: followee.id, diff --git a/packages/backend/src/core/activitypub/type.ts b/packages/backend/src/core/activitypub/type.ts index b900e375bd..9dc7ed4e31 100644 --- a/packages/backend/src/core/activitypub/type.ts +++ b/packages/backend/src/core/activitypub/type.ts @@ -14,7 +14,7 @@ export interface IObject { attachment?: any[]; inReplyTo?: any; replies?: ICollection; - content?: string; + content?: string | null; startTime?: Date; endTime?: Date; icon?: any; From a71682f6f0639bcedcc664f89615a54cbe397b68 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 12 Feb 2023 20:06:10 +0900 Subject: [PATCH 068/294] refactor: fix types --- .../backend/src/core/activitypub/ApRendererService.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/backend/src/core/activitypub/ApRendererService.ts b/packages/backend/src/core/activitypub/ApRendererService.ts index b87aee8804..996ff625e8 100644 --- a/packages/backend/src/core/activitypub/ApRendererService.ts +++ b/packages/backend/src/core/activitypub/ApRendererService.ts @@ -24,7 +24,7 @@ import type { UsersRepository, UserProfilesRepository, NotesRepository, DriveFil import { bindThis } from '@/decorators.js'; import { LdSignatureService } from './LdSignatureService.js'; import { ApMfmService } from './ApMfmService.js'; -import type { IAccept, IActivity, IAdd, IAnnounce, IApDocument, IApEmoji, IApHashtag, IApImage, IApMention, IBlock, ICreate, IDelete, IFlag, IFollow, IKey, ILike, IObject, IQuestion, IRead, IReject, IRemove, ITombstone, IUndo, IUpdate } from './type.js'; +import type { IAccept, IActivity, IAdd, IAnnounce, IApDocument, IApEmoji, IApHashtag, IApImage, IApMention, IBlock, ICreate, IDelete, IFlag, IFollow, IKey, ILike, IObject, IPost, IQuestion, IRead, IReject, IRemove, ITombstone, IUndo, IUpdate } from './type.js'; import type { IIdentifier } from './models/identifier.js'; @Injectable() @@ -293,7 +293,7 @@ export class ApRendererService { } @bindThis - public async renderNote(note: Note, dive = true, isTalk = false): Promise { + public async renderNote(note: Note, dive = true, isTalk = false): Promise { const getPromisedFiles = async (ids: string[]) => { if (!ids || ids.length === 0) return []; const items = await this.driveFilesRepository.findBy({ id: In(ids) }); @@ -406,11 +406,11 @@ export class ApRendererService { totalItems: poll!.votes[i], }, })), - } : {}; + } as const : {}; const asTalk = isTalk ? { _misskey_talk: true, - } : {}; + } as const : {}; return { id: `${this.config.url}/notes/${note.id}`, @@ -515,7 +515,7 @@ export class ApRendererService { } @bindThis - public async renderQuestion(user: { id: User['id'] }, note: Note, poll: Poll): IQuestion { + public renderQuestion(user: { id: User['id'] }, note: Note, poll: Poll): IQuestion { return { type: 'Question', id: `${this.config.url}/questions/${note.id}`, From 9f0e0dc8ce9ca2a04f8bfbfb95c33a7b20288e21 Mon Sep 17 00:00:00 2001 From: Kagami Sascha Rosylight Date: Sun, 12 Feb 2023 16:31:37 +0100 Subject: [PATCH 069/294] refactor(sw): Fix type errors in packages/sw (#9909) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix type errors in packages/sw * mouhitotsu * @typesは越境しない * Update packages/sw/src/scripts/create-notification.ts --------- Co-authored-by: tamaina --- packages/sw/src/@types/global.d.ts | 7 ++++ .../sw/src/scripts/create-notification.ts | 24 ++++++------- packages/sw/src/scripts/get-user-name.ts | 4 +++ packages/sw/src/scripts/notification-read.ts | 2 +- packages/sw/src/sw.ts | 34 +++++++++---------- 5 files changed, 41 insertions(+), 30 deletions(-) create mode 100644 packages/sw/src/@types/global.d.ts diff --git a/packages/sw/src/@types/global.d.ts b/packages/sw/src/@types/global.d.ts new file mode 100644 index 0000000000..5aaef9412c --- /dev/null +++ b/packages/sw/src/@types/global.d.ts @@ -0,0 +1,7 @@ +type FIXME = any; + +declare const _LANGS_: string[][]; +declare const _VERSION_: string; +declare const _ENV_: string; +declare const _DEV_: boolean; +declare const _PERF_PREFIX_: string; diff --git a/packages/sw/src/scripts/create-notification.ts b/packages/sw/src/scripts/create-notification.ts index 6744687fcc..6e7845f667 100644 --- a/packages/sw/src/scripts/create-notification.ts +++ b/packages/sw/src/scripts/create-notification.ts @@ -30,7 +30,7 @@ export async function createNotification(data: pushNotificationDataMap[K]): Promise<[string, NotificationOptions] | null> { +async function composeNotification(data: pushNotificationDataMap[keyof pushNotificationDataMap]): Promise<[string, NotificationOptions] | null> { if (!swLang.i18n) swLang.fetchLocale(); const i18n = await swLang.i18n as I18n; const { t } = i18n; @@ -66,7 +66,7 @@ async function composeNotification(data case 'mention': return [t('_notification.youGotMention', { name: getUserName(data.body.user) }), { - body: data.body.note.text || '', + body: data.body.note.text ?? '', icon: data.body.user.avatarUrl, badge: iconUrl('at'), data, @@ -80,7 +80,7 @@ async function composeNotification(data case 'reply': return [t('_notification.youGotReply', { name: getUserName(data.body.user) }), { - body: data.body.note.text || '', + body: data.body.note.text ?? '', icon: data.body.user.avatarUrl, badge: iconUrl('arrow-back-up'), data, @@ -94,7 +94,7 @@ async function composeNotification(data case 'renote': return [t('_notification.youRenoted', { name: getUserName(data.body.user) }), { - body: data.body.note.text || '', + body: data.body.note.text ?? '', icon: data.body.user.avatarUrl, badge: iconUrl('repeat'), data, @@ -108,7 +108,7 @@ async function composeNotification(data case 'quote': return [t('_notification.youGotQuote', { name: getUserName(data.body.user) }), { - body: data.body.note.text || '', + body: data.body.note.text ?? '', icon: data.body.user.avatarUrl, badge: iconUrl('quote'), data, @@ -162,7 +162,7 @@ async function composeNotification(data } return [`${reaction} ${getUserName(data.body.user)}`, { - body: data.body.note.text || '', + body: data.body.note.text ?? '', icon: data.body.user.avatarUrl, badge, data, @@ -227,9 +227,9 @@ async function composeNotification(data }]; case 'app': - return [data.body.header || data.body.body, { - body: data.body.header && data.body.body, - icon: data.body.icon, + return [data.body.header ?? data.body.body, { + body: data.body.header ? data.body.body : '', + icon: data.body.icon ?? undefined, data, }]; @@ -246,7 +246,7 @@ async function composeNotification(data renotify: true, }]; } - return [t('_notification.youGotMessagingMessageFromGroup', { name: data.body.group.name }), { + return [t('_notification.youGotMessagingMessageFromGroup', { name: data.body.group?.name ?? '' }), { icon: data.body.user.avatarUrl, badge: iconUrl('messages'), tag: `messaging:group:${data.body.groupId}`, @@ -255,7 +255,7 @@ async function composeNotification(data }]; case 'unreadAntennaNote': return [t('_notification.unreadAntennaNote', { name: data.body.antenna.name }), { - body: `${getUserName(data.body.note.user)}: ${data.body.note.text || ''}`, + body: `${getUserName(data.body.note.user)}: ${data.body.note.text ?? ''}`, icon: data.body.note.user.avatarUrl, badge: iconUrl('antenna'), tag: `antenna:${data.body.antenna.id}`, @@ -272,7 +272,7 @@ export async function createEmptyNotification() { if (!swLang.i18n) swLang.fetchLocale(); const i18n = await swLang.i18n as I18n; const { t } = i18n; - + await self.registration.showNotification( t('_notification.emptyPushNotificationMessage'), { diff --git a/packages/sw/src/scripts/get-user-name.ts b/packages/sw/src/scripts/get-user-name.ts index d499ea0203..ccc38c298e 100644 --- a/packages/sw/src/scripts/get-user-name.ts +++ b/packages/sw/src/scripts/get-user-name.ts @@ -1,3 +1,7 @@ export default function(user: { name?: string | null, username: string }): string { + // Show username if name is empty. + // XXX: typescript-eslint has no configuration to allow using `||` against string. + // https://github.com/typescript-eslint/typescript-eslint/issues/4906 + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing return user.name || user.username; } diff --git a/packages/sw/src/scripts/notification-read.ts b/packages/sw/src/scripts/notification-read.ts index 5ad748b849..3b1dde0cd5 100644 --- a/packages/sw/src/scripts/notification-read.ts +++ b/packages/sw/src/scripts/notification-read.ts @@ -28,7 +28,7 @@ class SwNotificationReadManager { } // プッシュ通知の既読をサーバーに送信 - public async read(data: pushNotificationDataMap[K]) { + public async read(data: pushNotificationDataMap[keyof pushNotificationDataMap]) { if (data.type !== 'notification' || !(data.userId in this.accounts)) return; const account = this.accounts[data.userId]; diff --git a/packages/sw/src/sw.ts b/packages/sw/src/sw.ts index d47563939a..55f881cd43 100644 --- a/packages/sw/src/sw.ts +++ b/packages/sw/src/sw.ts @@ -5,11 +5,11 @@ import { pushNotificationDataMap } from '@/types'; import * as swos from '@/scripts/operations'; import { acct as getAcct } from '@/filters/user'; -self.addEventListener('install', ev => { +globalThis.addEventListener('install', ev => { ev.waitUntil(self.skipWaiting()); }); -self.addEventListener('activate', ev => { +globalThis.addEventListener('activate', ev => { ev.waitUntil( caches.keys() .then(cacheNames => Promise.all( @@ -21,7 +21,7 @@ self.addEventListener('activate', ev => { ); }); -self.addEventListener('fetch', ev => { +globalThis.addEventListener('fetch', ev => { let isHTMLRequest = false; if (ev.request.headers.get('sec-fetch-dest') === 'document') { isHTMLRequest = true; @@ -38,13 +38,13 @@ self.addEventListener('fetch', ev => { ); }); -self.addEventListener('push', ev => { +globalThis.addEventListener('push', ev => { // クライアント取得 ev.waitUntil(self.clients.matchAll({ includeUncontrolled: true, type: 'window' - }).then(async (clients: readonly WindowClient[]) => { - const data: pushNotificationDataMap[K] = ev.data?.json(); + }).then(async (clients: readonly WindowClient[]) => { + const data: pushNotificationDataMap[keyof pushNotificationDataMap] = ev.data?.json(); switch (data.type) { // case 'driveFileCreated': @@ -104,17 +104,17 @@ self.addEventListener('push', ev => { })); }); -self.addEventListener('notificationclick', (ev: ServiceWorkerGlobalScopeEventMap['notificationclick']) => { +globalThis.addEventListener('notificationclick', (ev: ServiceWorkerGlobalScopeEventMap['notificationclick']) => { ev.waitUntil((async () => { if (_DEV_) { console.log('notificationclick', ev.action, ev.notification.data); } - + const { action, notification } = ev; - const data: pushNotificationDataMap[K] = notification.data; + const data: pushNotificationDataMap[keyof pushNotificationDataMap] = notification.data; const { userId: loginId } = data; let client: WindowClient | null = null; - + switch (data.type) { case 'notification': switch (action) { @@ -180,27 +180,27 @@ self.addEventListener('notificationclick', that.read(data)); } - + notification.close(); })()); }); -self.addEventListener('notificationclose', (ev: ServiceWorkerGlobalScopeEventMap['notificationclose']) => { - const data: pushNotificationDataMap[K] = ev.notification.data; +globalThis.addEventListener('notificationclose', (ev: ServiceWorkerGlobalScopeEventMap['notificationclose']) => { + const data: pushNotificationDataMap[keyof pushNotificationDataMap] = ev.notification.data; if (data.type === 'notification') { swNotificationRead.then(that => that.read(data)); } }); -self.addEventListener('message', (ev: ServiceWorkerGlobalScopeEventMap['message']) => { +globalThis.addEventListener('message', (ev: ServiceWorkerGlobalScopeEventMap['message']) => { ev.waitUntil((async () => { switch (ev.data) { case 'clear': @@ -211,11 +211,11 @@ self.addEventListener('message', (ev: ServiceWorkerGlobalScopeEventMap['message' )); return; // TODO } - + if (typeof ev.data === 'object') { // E.g. '[object Array]' → 'array' const otype = Object.prototype.toString.call(ev.data).slice(8, -1).toLowerCase(); - + if (otype === 'object') { if (ev.data.msg === 'initialize') { swLang.setLang(ev.data.lang); From 2f41f12aea9f3a1e0ed5da28d703a718e5de3a1a Mon Sep 17 00:00:00 2001 From: Kagami Sascha Rosylight Date: Sun, 12 Feb 2023 16:40:36 +0100 Subject: [PATCH 070/294] fix(client): Make `isTimelineAvailable` a reference (#9906) * Make `isTimelineAvailable` a reference * Update b.vue --- packages/frontend/src/ui/visitor/b.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/ui/visitor/b.vue b/packages/frontend/src/ui/visitor/b.vue index 058a9482fa..42283fe95b 100644 --- a/packages/frontend/src/ui/visitor/b.vue +++ b/packages/frontend/src/ui/visitor/b.vue @@ -83,7 +83,7 @@ const announcements = { limit: 10, }; -const isTimelineAvailable = instance.policies.ltlAvailable || instance.policies.gtlAvailable; +const isTimelineAvailable = $ref(instance.policies?.ltlAvailable || instance.policies?.gtlAvailable); let showMenu = $ref(false); let isDesktop = $ref(window.innerWidth >= DESKTOP_THRESHOLD); From 8d4c5deb8dc173d59975e998dc1295c698af362b Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Feb 2023 15:48:56 +0000 Subject: [PATCH 071/294] =?UTF-8?q?perf(sw):=20skipWaiting=E3=81=97?= =?UTF-8?q?=E3=81=AA=E3=81=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/sw/src/sw.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sw/src/sw.ts b/packages/sw/src/sw.ts index 55f881cd43..7bcf4d5976 100644 --- a/packages/sw/src/sw.ts +++ b/packages/sw/src/sw.ts @@ -6,7 +6,7 @@ import * as swos from '@/scripts/operations'; import { acct as getAcct } from '@/filters/user'; globalThis.addEventListener('install', ev => { - ev.waitUntil(self.skipWaiting()); + //ev.waitUntil(self.skipWaiting()); }); globalThis.addEventListener('activate', ev => { From f34f9f6ea583a5455600eea9dbf5ffdf38802d21 Mon Sep 17 00:00:00 2001 From: syuilo Date: Mon, 13 Feb 2023 15:28:07 +0900 Subject: [PATCH 072/294] refactor: fix types --- packages/backend/src/core/MessagingService.ts | 4 +- packages/backend/src/core/PollService.ts | 5 +- packages/backend/src/core/RoleService.ts | 2 +- .../backend/src/core/UserBlockingService.ts | 4 +- packages/backend/src/core/UserCacheService.ts | 24 ++++---- .../backend/src/core/UserFollowingService.ts | 4 +- .../src/core/activitypub/ApAudienceService.ts | 16 ++--- .../core/activitypub/ApDbResolverService.ts | 16 ++--- .../src/core/activitypub/ApInboxService.ts | 58 +++++++++---------- .../core/activitypub/models/ApImageService.ts | 6 +- .../activitypub/models/ApMentionService.ts | 9 ++- .../core/activitypub/models/ApNoteService.ts | 4 +- .../activitypub/models/ApPersonService.ts | 12 ++-- packages/backend/src/models/entities/User.ts | 7 +-- .../queue/processors/InboxProcessorService.ts | 4 +- .../backend/src/server/api/ApiCallService.ts | 4 +- .../src/server/api/AuthenticateService.ts | 4 +- .../backend/src/server/api/endpoint-base.ts | 8 +-- .../src/server/api/endpoints/ap/show.ts | 6 +- 19 files changed, 95 insertions(+), 102 deletions(-) diff --git a/packages/backend/src/core/MessagingService.ts b/packages/backend/src/core/MessagingService.ts index 1c36d04d41..0721f63d5e 100644 --- a/packages/backend/src/core/MessagingService.ts +++ b/packages/backend/src/core/MessagingService.ts @@ -5,7 +5,7 @@ import type { Config } from '@/config.js'; import type { DriveFile } from '@/models/entities/DriveFile.js'; import type { MessagingMessage } from '@/models/entities/MessagingMessage.js'; import type { Note } from '@/models/entities/Note.js'; -import type { User, CacheableUser, IRemoteUser } from '@/models/entities/User.js'; +import type { User, IRemoteUser } from '@/models/entities/User.js'; import type { UserGroup } from '@/models/entities/UserGroup.js'; import { QueueService } from '@/core/QueueService.js'; import { toArray } from '@/misc/prelude/array.js'; @@ -48,7 +48,7 @@ export class MessagingService { } @bindThis - public async createMessage(user: { id: User['id']; host: User['host']; }, recipientUser: CacheableUser | undefined, recipientGroup: UserGroup | undefined, text: string | null | undefined, file: DriveFile | null, uri?: string) { + public async createMessage(user: { id: User['id']; host: User['host']; }, recipientUser: User | undefined, recipientGroup: UserGroup | undefined, text: string | null | undefined, file: DriveFile | null, uri?: string) { const message = { id: this.idService.genId(), createdAt: new Date(), diff --git a/packages/backend/src/core/PollService.ts b/packages/backend/src/core/PollService.ts index 018e83f8cd..94adbf2756 100644 --- a/packages/backend/src/core/PollService.ts +++ b/packages/backend/src/core/PollService.ts @@ -1,10 +1,9 @@ import { Inject, Injectable } from '@nestjs/common'; import { Not } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { NotesRepository, UsersRepository, PollsRepository, PollVotesRepository } from '@/models/index.js'; +import type { NotesRepository, UsersRepository, PollsRepository, PollVotesRepository, User } from '@/models/index.js'; import type { Note } from '@/models/entities/Note.js'; import { RelayService } from '@/core/RelayService.js'; -import type { CacheableUser } from '@/models/entities/User.js'; import { IdService } from '@/core/IdService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; @@ -39,7 +38,7 @@ export class PollService { } @bindThis - public async vote(user: CacheableUser, note: Note, choice: number) { + public async vote(user: User, note: Note, choice: number) { const poll = await this.pollsRepository.findOneBy({ noteId: note.id }); if (poll == null) throw new Error('poll not found'); diff --git a/packages/backend/src/core/RoleService.ts b/packages/backend/src/core/RoleService.ts index 9a782780d1..b84d5e7585 100644 --- a/packages/backend/src/core/RoleService.ts +++ b/packages/backend/src/core/RoleService.ts @@ -3,7 +3,7 @@ import Redis from 'ioredis'; import { In } from 'typeorm'; import type { Role, RoleAssignment, RoleAssignmentsRepository, RolesRepository, UsersRepository } from '@/models/index.js'; import { Cache } from '@/misc/cache.js'; -import type { CacheableLocalUser, CacheableUser, ILocalUser, User } from '@/models/entities/User.js'; +import type { User } from '@/models/entities/User.js'; import { DI } from '@/di-symbols.js'; import { bindThis } from '@/decorators.js'; import { MetaService } from '@/core/MetaService.js'; diff --git a/packages/backend/src/core/UserBlockingService.ts b/packages/backend/src/core/UserBlockingService.ts index 89de72b9aa..be37bad52e 100644 --- a/packages/backend/src/core/UserBlockingService.ts +++ b/packages/backend/src/core/UserBlockingService.ts @@ -2,7 +2,7 @@ import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common'; import Redis from 'ioredis'; import { IdService } from '@/core/IdService.js'; -import type { CacheableUser, User } from '@/models/entities/User.js'; +import type { User } from '@/models/entities/User.js'; import type { Blocking } from '@/models/entities/Blocking.js'; import { QueueService } from '@/core/QueueService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; @@ -236,7 +236,7 @@ export class UserBlockingService implements OnApplicationShutdown { } @bindThis - public async unblock(blocker: CacheableUser, blockee: CacheableUser) { + public async unblock(blocker: User, blockee: User) { const blocking = await this.blockingsRepository.findOneBy({ blockerId: blocker.id, blockeeId: blockee.id, diff --git a/packages/backend/src/core/UserCacheService.ts b/packages/backend/src/core/UserCacheService.ts index 52cedbd105..5f0a919088 100644 --- a/packages/backend/src/core/UserCacheService.ts +++ b/packages/backend/src/core/UserCacheService.ts @@ -2,7 +2,7 @@ import { Inject, Injectable } from '@nestjs/common'; import Redis from 'ioredis'; import type { UsersRepository } from '@/models/index.js'; import { Cache } from '@/misc/cache.js'; -import type { CacheableLocalUser, CacheableUser, ILocalUser, User } from '@/models/entities/User.js'; +import type { ILocalUser, User } from '@/models/entities/User.js'; import { DI } from '@/di-symbols.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { bindThis } from '@/decorators.js'; @@ -11,10 +11,10 @@ import type { OnApplicationShutdown } from '@nestjs/common'; @Injectable() export class UserCacheService implements OnApplicationShutdown { - public userByIdCache: Cache; - public localUserByNativeTokenCache: Cache; - public localUserByIdCache: Cache; - public uriPersonCache: Cache; + public userByIdCache: Cache; + public localUserByNativeTokenCache: Cache; + public localUserByIdCache: Cache; + public uriPersonCache: Cache; constructor( @Inject(DI.redisSubscriber) @@ -27,10 +27,10 @@ export class UserCacheService implements OnApplicationShutdown { ) { //this.onMessage = this.onMessage.bind(this); - this.userByIdCache = new Cache(Infinity); - this.localUserByNativeTokenCache = new Cache(Infinity); - this.localUserByIdCache = new Cache(Infinity); - this.uriPersonCache = new Cache(Infinity); + this.userByIdCache = new Cache(Infinity); + this.localUserByNativeTokenCache = new Cache(Infinity); + this.localUserByIdCache = new Cache(Infinity); + this.uriPersonCache = new Cache(Infinity); this.redisSubscriber.on('message', this.onMessage); } @@ -45,10 +45,10 @@ export class UserCacheService implements OnApplicationShutdown { case 'userChangeSuspendedState': case 'remoteUserUpdated': { const user = await this.usersRepository.findOneByOrFail({ id: body.id }); - this.userByIdCache.set(user.id, user as CacheableUser); + this.userByIdCache.set(user.id, user); for (const [k, v] of this.uriPersonCache.cache.entries()) { if (v.value?.id === user.id) { - this.uriPersonCache.set(k, user as CacheableUser); + this.uriPersonCache.set(k, user); } } if (this.userEntityService.isLocalUser(user)) { @@ -78,7 +78,7 @@ export class UserCacheService implements OnApplicationShutdown { @bindThis public findById(userId: User['id']) { - return this.userByIdCache.fetch(userId, () => this.usersRepository.findOneByOrFail({ id: userId }) as Promise); + return this.userByIdCache.fetch(userId, () => this.usersRepository.findOneByOrFail({ id: userId })); } @bindThis diff --git a/packages/backend/src/core/UserFollowingService.ts b/packages/backend/src/core/UserFollowingService.ts index c0347c60eb..589842a419 100644 --- a/packages/backend/src/core/UserFollowingService.ts +++ b/packages/backend/src/core/UserFollowingService.ts @@ -1,5 +1,5 @@ import { Inject, Injectable } from '@nestjs/common'; -import type { CacheableUser, ILocalUser, IRemoteUser, User } from '@/models/entities/User.js'; +import type { ILocalUser, IRemoteUser, User } from '@/models/entities/User.js'; import { IdentifiableError } from '@/misc/identifiable-error.js'; import { QueueService } from '@/core/QueueService.js'; import PerUserFollowingChart from '@/core/chart/charts/per-user-following.js'; @@ -434,7 +434,7 @@ export class UserFollowingService { followee: { id: User['id']; host: User['host']; uri: User['host']; inbox: User['inbox']; sharedInbox: User['sharedInbox']; }, - follower: User | CacheableUser, + follower: User, ): Promise { const request = await this.followRequestsRepository.findOneBy({ followeeId: followee.id, diff --git a/packages/backend/src/core/activitypub/ApAudienceService.ts b/packages/backend/src/core/activitypub/ApAudienceService.ts index 64f01644a7..ee14f4ddd7 100644 --- a/packages/backend/src/core/activitypub/ApAudienceService.ts +++ b/packages/backend/src/core/activitypub/ApAudienceService.ts @@ -2,7 +2,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { In } from 'typeorm'; import promiseLimit from 'promise-limit'; import { DI } from '@/di-symbols.js'; -import type { CacheableRemoteUser, CacheableUser } from '@/models/entities/User.js'; +import type { IRemoteUser, User } from '@/models/entities/User.js'; import { concat, toArray, toSingle, unique } from '@/misc/prelude/array.js'; import { bindThis } from '@/decorators.js'; import { getApId, getApIds, getApType, isAccept, isActor, isAdd, isAnnounce, isBlock, isCollection, isCollectionOrOrderedCollection, isCreate, isDelete, isFlag, isFollow, isLike, isPost, isRead, isReject, isRemove, isTombstone, isUndo, isUpdate, validActor, validPost } from './type.js'; @@ -14,8 +14,8 @@ type Visibility = 'public' | 'home' | 'followers' | 'specified'; type AudienceInfo = { visibility: Visibility, - mentionedUsers: CacheableUser[], - visibleUsers: CacheableUser[], + mentionedUsers: User[], + visibleUsers: User[], }; @Injectable() @@ -26,16 +26,16 @@ export class ApAudienceService { } @bindThis - public async parseAudience(actor: CacheableRemoteUser, to?: ApObject, cc?: ApObject, resolver?: Resolver): Promise { + public async parseAudience(actor: IRemoteUser, to?: ApObject, cc?: ApObject, resolver?: Resolver): Promise { const toGroups = this.groupingAudience(getApIds(to), actor); const ccGroups = this.groupingAudience(getApIds(cc), actor); const others = unique(concat([toGroups.other, ccGroups.other])); - const limit = promiseLimit(2); + const limit = promiseLimit(2); const mentionedUsers = (await Promise.all( others.map(id => limit(() => this.apPersonService.resolvePerson(id, resolver).catch(() => null))), - )).filter((x): x is CacheableUser => x != null); + )).filter((x): x is User => x != null); if (toGroups.public.length > 0) { return { @@ -69,7 +69,7 @@ export class ApAudienceService { } @bindThis - private groupingAudience(ids: string[], actor: CacheableRemoteUser) { + private groupingAudience(ids: string[], actor: IRemoteUser) { const groups = { public: [] as string[], followers: [] as string[], @@ -101,7 +101,7 @@ export class ApAudienceService { } @bindThis - private isFollowers(id: string, actor: CacheableRemoteUser) { + private isFollowers(id: string, actor: IRemoteUser) { return ( id === (actor.followersUri ?? `${actor.uri}/followers`) ); diff --git a/packages/backend/src/core/activitypub/ApDbResolverService.ts b/packages/backend/src/core/activitypub/ApDbResolverService.ts index b057f39b05..5af9e29069 100644 --- a/packages/backend/src/core/activitypub/ApDbResolverService.ts +++ b/packages/backend/src/core/activitypub/ApDbResolverService.ts @@ -3,13 +3,13 @@ import escapeRegexp from 'escape-regexp'; import { DI } from '@/di-symbols.js'; import type { MessagingMessagesRepository, NotesRepository, UserPublickeysRepository, UsersRepository } from '@/models/index.js'; import type { Config } from '@/config.js'; -import type { CacheableRemoteUser, CacheableUser } from '@/models/entities/User.js'; import { Cache } from '@/misc/cache.js'; import type { UserPublickey } from '@/models/entities/UserPublickey.js'; import { UserCacheService } from '@/core/UserCacheService.js'; import type { Note } from '@/models/entities/Note.js'; import type { MessagingMessage } from '@/models/entities/MessagingMessage.js'; import { bindThis } from '@/decorators.js'; +import { IRemoteUser, User } from '@/models/entities/User.js'; import { getApId } from './type.js'; import { ApPersonService } from './models/ApPersonService.js'; import type { IObject } from './type.js'; @@ -122,7 +122,7 @@ export class ApDbResolverService { * AP Person => Misskey User in DB */ @bindThis - public async getUserFromApId(value: string | IObject): Promise { + public async getUserFromApId(value: string | IObject): Promise { const parsed = this.parseUri(value); if (parsed.local) { @@ -130,11 +130,11 @@ export class ApDbResolverService { return await this.userCacheService.userByIdCache.fetchMaybe(parsed.id, () => this.usersRepository.findOneBy({ id: parsed.id, - }).then(x => (x as CacheableUser | null) ?? undefined)) ?? null; + }).then(x => x ?? undefined)) ?? null; } else { return await this.userCacheService.uriPersonCache.fetch(parsed.uri, () => this.usersRepository.findOneBy({ uri: parsed.uri, - }) as Promise); + })); } } @@ -143,7 +143,7 @@ export class ApDbResolverService { */ @bindThis public async getAuthUserFromKeyId(keyId: string): Promise<{ - user: CacheableRemoteUser; + user: IRemoteUser; key: UserPublickey; } | null> { const key = await this.publicKeyCache.fetch(keyId, async () => { @@ -159,7 +159,7 @@ export class ApDbResolverService { if (key == null) return null; return { - user: await this.userCacheService.findById(key.userId) as CacheableRemoteUser, + user: await this.userCacheService.findById(key.userId) as IRemoteUser, key, }; } @@ -169,10 +169,10 @@ export class ApDbResolverService { */ @bindThis public async getAuthUserFromApId(uri: string): Promise<{ - user: CacheableRemoteUser; + user: IRemoteUser; key: UserPublickey | null; } | null> { - const user = await this.apPersonService.resolvePerson(uri) as CacheableRemoteUser; + const user = await this.apPersonService.resolvePerson(uri) as IRemoteUser; if (user == null) return null; diff --git a/packages/backend/src/core/activitypub/ApInboxService.ts b/packages/backend/src/core/activitypub/ApInboxService.ts index 02bb0ca4ec..d514e9845e 100644 --- a/packages/backend/src/core/activitypub/ApInboxService.ts +++ b/packages/backend/src/core/activitypub/ApInboxService.ts @@ -2,7 +2,6 @@ import { Inject, Injectable } from '@nestjs/common'; import { In } from 'typeorm'; import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; -import type { CacheableRemoteUser, CacheableUser } from '@/models/entities/User.js'; import { UserFollowingService } from '@/core/UserFollowingService.js'; import { ReactionService } from '@/core/ReactionService.js'; import { RelayService } from '@/core/RelayService.js'; @@ -23,6 +22,7 @@ import { QueueService } from '@/core/QueueService.js'; import { MessagingService } from '@/core/MessagingService.js'; import type { UsersRepository, NotesRepository, FollowingsRepository, MessagingMessagesRepository, AbuseUserReportsRepository, FollowRequestsRepository } from '@/models/index.js'; import { bindThis } from '@/decorators.js'; +import type { IRemoteUser } from '@/models/entities/User.js'; import { getApId, getApIds, getApType, isAccept, isActor, isAdd, isAnnounce, isBlock, isCollection, isCollectionOrOrderedCollection, isCreate, isDelete, isFlag, isFollow, isLike, isPost, isRead, isReject, isRemove, isTombstone, isUndo, isUpdate, validActor, validPost } from './type.js'; import { ApNoteService } from './models/ApNoteService.js'; import { ApLoggerService } from './ApLoggerService.js'; @@ -87,7 +87,7 @@ export class ApInboxService { } @bindThis - public async performActivity(actor: CacheableRemoteUser, activity: IObject) { + public async performActivity(actor: IRemoteUser, activity: IObject) { if (isCollectionOrOrderedCollection(activity)) { const resolver = this.apResolverService.createResolver(); for (const item of toArray(isCollection(activity) ? activity.items : activity.orderedItems)) { @@ -115,7 +115,7 @@ export class ApInboxService { } @bindThis - public async performOneActivity(actor: CacheableRemoteUser, activity: IObject): Promise { + public async performOneActivity(actor: IRemoteUser, activity: IObject): Promise { if (actor.isSuspended) return; if (isCreate(activity)) { @@ -152,7 +152,7 @@ export class ApInboxService { } @bindThis - private async follow(actor: CacheableRemoteUser, activity: IFollow): Promise { + private async follow(actor: IRemoteUser, activity: IFollow): Promise { const followee = await this.apDbResolverService.getUserFromApId(activity.object); if (followee == null) { @@ -168,7 +168,7 @@ export class ApInboxService { } @bindThis - private async like(actor: CacheableRemoteUser, activity: ILike): Promise { + private async like(actor: IRemoteUser, activity: ILike): Promise { const targetUri = getApId(activity.object); const note = await this.apNoteService.fetchNote(targetUri); @@ -186,7 +186,7 @@ export class ApInboxService { } @bindThis - private async read(actor: CacheableRemoteUser, activity: IRead): Promise { + private async read(actor: IRemoteUser, activity: IRead): Promise { const id = await getApId(activity.object); if (!this.utilityService.isSelfHost(this.utilityService.extractDbHost(id))) { @@ -209,7 +209,7 @@ export class ApInboxService { } @bindThis - private async accept(actor: CacheableRemoteUser, activity: IAccept): Promise { + private async accept(actor: IRemoteUser, activity: IAccept): Promise { const uri = activity.id ?? activity; this.logger.info(`Accept: ${uri}`); @@ -227,7 +227,7 @@ export class ApInboxService { } @bindThis - private async acceptFollow(actor: CacheableRemoteUser, activity: IFollow): Promise { + private async acceptFollow(actor: IRemoteUser, activity: IFollow): Promise { // ※ activityはこっちから投げたフォローリクエストなので、activity.actorは存在するローカルユーザーである必要がある const follower = await this.apDbResolverService.getUserFromApId(activity.actor); @@ -251,7 +251,7 @@ export class ApInboxService { } @bindThis - private async add(actor: CacheableRemoteUser, activity: IAdd): Promise { + private async add(actor: IRemoteUser, activity: IAdd): Promise { if ('actor' in activity && actor.uri !== activity.actor) { throw new Error('invalid actor'); } @@ -271,7 +271,7 @@ export class ApInboxService { } @bindThis - private async announce(actor: CacheableRemoteUser, activity: IAnnounce): Promise { + private async announce(actor: IRemoteUser, activity: IAnnounce): Promise { const uri = getApId(activity); this.logger.info(`Announce: ${uri}`); @@ -282,7 +282,7 @@ export class ApInboxService { } @bindThis - private async announceNote(actor: CacheableRemoteUser, activity: IAnnounce, targetUri: string): Promise { + private async announceNote(actor: IRemoteUser, activity: IAnnounce, targetUri: string): Promise { const uri = getApId(activity); if (actor.isSuspended) { @@ -342,7 +342,7 @@ export class ApInboxService { } @bindThis - private async block(actor: CacheableRemoteUser, activity: IBlock): Promise { + private async block(actor: IRemoteUser, activity: IBlock): Promise { // ※ activity.objectにブロック対象があり、それは存在するローカルユーザーのはず const blockee = await this.apDbResolverService.getUserFromApId(activity.object); @@ -360,7 +360,7 @@ export class ApInboxService { } @bindThis - private async create(actor: CacheableRemoteUser, activity: ICreate): Promise { + private async create(actor: IRemoteUser, activity: ICreate): Promise { const uri = getApId(activity); this.logger.info(`Create: ${uri}`); @@ -396,7 +396,7 @@ export class ApInboxService { } @bindThis - private async createNote(resolver: Resolver, actor: CacheableRemoteUser, note: IObject, silent = false, activity?: ICreate): Promise { + private async createNote(resolver: Resolver, actor: IRemoteUser, note: IObject, silent = false, activity?: ICreate): Promise { const uri = getApId(note); if (typeof note === 'object') { @@ -431,7 +431,7 @@ export class ApInboxService { } @bindThis - private async delete(actor: CacheableRemoteUser, activity: IDelete): Promise { + private async delete(actor: IRemoteUser, activity: IDelete): Promise { if ('actor' in activity && actor.uri !== activity.actor) { throw new Error('invalid actor'); } @@ -473,7 +473,7 @@ export class ApInboxService { } @bindThis - private async deleteActor(actor: CacheableRemoteUser, uri: string): Promise { + private async deleteActor(actor: IRemoteUser, uri: string): Promise { this.logger.info(`Deleting the Actor: ${uri}`); if (actor.uri !== uri) { @@ -495,7 +495,7 @@ export class ApInboxService { } @bindThis - private async deleteNote(actor: CacheableRemoteUser, uri: string): Promise { + private async deleteNote(actor: IRemoteUser, uri: string): Promise { this.logger.info(`Deleting the Note: ${uri}`); const unlock = await this.appLockService.getApLock(uri); @@ -528,7 +528,7 @@ export class ApInboxService { } @bindThis - private async flag(actor: CacheableRemoteUser, activity: IFlag): Promise { + private async flag(actor: IRemoteUser, activity: IFlag): Promise { // objectは `(User|Note) | (User|Note)[]` だけど、全パターンDBスキーマと対応させられないので // 対象ユーザーは一番最初のユーザー として あとはコメントとして格納する const uris = getApIds(activity.object); @@ -553,7 +553,7 @@ export class ApInboxService { } @bindThis - private async reject(actor: CacheableRemoteUser, activity: IReject): Promise { + private async reject(actor: IRemoteUser, activity: IReject): Promise { const uri = activity.id ?? activity; this.logger.info(`Reject: ${uri}`); @@ -571,7 +571,7 @@ export class ApInboxService { } @bindThis - private async rejectFollow(actor: CacheableRemoteUser, activity: IFollow): Promise { + private async rejectFollow(actor: IRemoteUser, activity: IFollow): Promise { // ※ activityはこっちから投げたフォローリクエストなので、activity.actorは存在するローカルユーザーである必要がある const follower = await this.apDbResolverService.getUserFromApId(activity.actor); @@ -595,7 +595,7 @@ export class ApInboxService { } @bindThis - private async remove(actor: CacheableRemoteUser, activity: IRemove): Promise { + private async remove(actor: IRemoteUser, activity: IRemove): Promise { if ('actor' in activity && actor.uri !== activity.actor) { throw new Error('invalid actor'); } @@ -615,7 +615,7 @@ export class ApInboxService { } @bindThis - private async undo(actor: CacheableRemoteUser, activity: IUndo): Promise { + private async undo(actor: IRemoteUser, activity: IUndo): Promise { if ('actor' in activity && actor.uri !== activity.actor) { throw new Error('invalid actor'); } @@ -641,7 +641,7 @@ export class ApInboxService { } @bindThis - private async undoAccept(actor: CacheableRemoteUser, activity: IAccept): Promise { + private async undoAccept(actor: IRemoteUser, activity: IAccept): Promise { const follower = await this.apDbResolverService.getUserFromApId(activity.object); if (follower == null) { return 'skip: follower not found'; @@ -661,7 +661,7 @@ export class ApInboxService { } @bindThis - private async undoAnnounce(actor: CacheableRemoteUser, activity: IAnnounce): Promise { + private async undoAnnounce(actor: IRemoteUser, activity: IAnnounce): Promise { const uri = getApId(activity); const note = await this.notesRepository.findOneBy({ @@ -676,7 +676,7 @@ export class ApInboxService { } @bindThis - private async undoBlock(actor: CacheableRemoteUser, activity: IBlock): Promise { + private async undoBlock(actor: IRemoteUser, activity: IBlock): Promise { const blockee = await this.apDbResolverService.getUserFromApId(activity.object); if (blockee == null) { @@ -687,12 +687,12 @@ export class ApInboxService { return 'skip: ブロック解除しようとしているユーザーはローカルユーザーではありません'; } - await this.userBlockingService.unblock(await this.usersRepository.findOneByOrFail({ id: actor.id }) as CacheableUser, blockee); + await this.userBlockingService.unblock(await this.usersRepository.findOneByOrFail({ id: actor.id }), blockee); return 'ok'; } @bindThis - private async undoFollow(actor: CacheableRemoteUser, activity: IFollow): Promise { + private async undoFollow(actor: IRemoteUser, activity: IFollow): Promise { const followee = await this.apDbResolverService.getUserFromApId(activity.object); if (followee == null) { return 'skip: followee not found'; @@ -726,7 +726,7 @@ export class ApInboxService { } @bindThis - private async undoLike(actor: CacheableRemoteUser, activity: ILike): Promise { + private async undoLike(actor: IRemoteUser, activity: ILike): Promise { const targetUri = getApId(activity.object); const note = await this.apNoteService.fetchNote(targetUri); @@ -741,7 +741,7 @@ export class ApInboxService { } @bindThis - private async update(actor: CacheableRemoteUser, activity: IUpdate): Promise { + private async update(actor: IRemoteUser, activity: IUpdate): Promise { if ('actor' in activity && actor.uri !== activity.actor) { return 'skip: invalid actor'; } diff --git a/packages/backend/src/core/activitypub/models/ApImageService.ts b/packages/backend/src/core/activitypub/models/ApImageService.ts index 928ef1ae79..f14b150138 100644 --- a/packages/backend/src/core/activitypub/models/ApImageService.ts +++ b/packages/backend/src/core/activitypub/models/ApImageService.ts @@ -2,7 +2,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; import type { DriveFilesRepository } from '@/models/index.js'; import type { Config } from '@/config.js'; -import type { CacheableRemoteUser } from '@/models/entities/User.js'; +import type { IRemoteUser } from '@/models/entities/User.js'; import type { DriveFile } from '@/models/entities/DriveFile.js'; import { MetaService } from '@/core/MetaService.js'; import { truncate } from '@/misc/truncate.js'; @@ -36,7 +36,7 @@ export class ApImageService { * Imageを作成します。 */ @bindThis - public async createImage(actor: CacheableRemoteUser, value: any): Promise { + public async createImage(actor: IRemoteUser, value: any): Promise { // 投稿者が凍結されていたらスキップ if (actor.isSuspended) { throw new Error('actor has been suspended'); @@ -88,7 +88,7 @@ export class ApImageService { * リモートサーバーからフェッチしてMisskeyに登録しそれを返します。 */ @bindThis - public async resolveImage(actor: CacheableRemoteUser, value: any): Promise { + public async resolveImage(actor: IRemoteUser, value: any): Promise { // TODO // リモートサーバーからフェッチしてきて登録 diff --git a/packages/backend/src/core/activitypub/models/ApMentionService.ts b/packages/backend/src/core/activitypub/models/ApMentionService.ts index 41e6c6b14f..1ed9fb89dd 100644 --- a/packages/backend/src/core/activitypub/models/ApMentionService.ts +++ b/packages/backend/src/core/activitypub/models/ApMentionService.ts @@ -1,15 +1,14 @@ import { Inject, Injectable } from '@nestjs/common'; import promiseLimit from 'promise-limit'; import { DI } from '@/di-symbols.js'; -import type { UsersRepository } from '@/models/index.js'; +import type { User, UsersRepository } from '@/models/index.js'; import type { Config } from '@/config.js'; import { toArray, unique } from '@/misc/prelude/array.js'; -import type { CacheableUser } from '@/models/entities/User.js'; +import { bindThis } from '@/decorators.js'; import { isMention } from '../type.js'; import { ApResolverService, Resolver } from '../ApResolverService.js'; import { ApPersonService } from './ApPersonService.js'; import type { IObject, IApMention } from '../type.js'; -import { bindThis } from '@/decorators.js'; @Injectable() export class ApMentionService { @@ -26,10 +25,10 @@ export class ApMentionService { public async extractApMentions(tags: IObject | IObject[] | null | undefined, resolver: Resolver) { const hrefs = unique(this.extractApMentionObjects(tags).map(x => x.href as string)); - const limit = promiseLimit(2); + const limit = promiseLimit(2); const mentionedUsers = (await Promise.all( hrefs.map(x => limit(() => this.apPersonService.resolvePerson(x, resolver).catch(() => null))), - )).filter((x): x is CacheableUser => x != null); + )).filter((x): x is User => x != null); return mentionedUsers; } diff --git a/packages/backend/src/core/activitypub/models/ApNoteService.ts b/packages/backend/src/core/activitypub/models/ApNoteService.ts index dc47fdf800..0292a27d94 100644 --- a/packages/backend/src/core/activitypub/models/ApNoteService.ts +++ b/packages/backend/src/core/activitypub/models/ApNoteService.ts @@ -3,7 +3,7 @@ import promiseLimit from 'promise-limit'; import { DI } from '@/di-symbols.js'; import type { MessagingMessagesRepository, PollsRepository, EmojisRepository, UsersRepository } from '@/models/index.js'; import type { Config } from '@/config.js'; -import type { CacheableRemoteUser } from '@/models/entities/User.js'; +import type { IRemoteUser } from '@/models/entities/User.js'; import type { Note } from '@/models/entities/Note.js'; import { toArray, toSingle, unique } from '@/misc/prelude/array.js'; import type { Emoji } from '@/models/entities/Emoji.js'; @@ -146,7 +146,7 @@ export class ApNoteService { this.logger.info(`Creating the Note: ${note.id}`); // 投稿者をフェッチ - const actor = await this.apPersonService.resolvePerson(getOneApId(note.attributedTo!), resolver) as CacheableRemoteUser; + const actor = await this.apPersonService.resolvePerson(getOneApId(note.attributedTo!), resolver) as IRemoteUser; // 投稿者が凍結されていたらスキップ if (actor.isSuspended) { diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts index 4869656f1d..9dca065529 100644 --- a/packages/backend/src/core/activitypub/models/ApPersonService.ts +++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts @@ -5,7 +5,7 @@ import { ModuleRef } from '@nestjs/core'; import { DI } from '@/di-symbols.js'; import type { FollowingsRepository, InstancesRepository, UserProfilesRepository, UserPublickeysRepository, UsersRepository } from '@/models/index.js'; import type { Config } from '@/config.js'; -import type { CacheableUser, IRemoteUser } from '@/models/entities/User.js'; +import type { IRemoteUser } from '@/models/entities/User.js'; import { User } from '@/models/entities/User.js'; import { truncate } from '@/misc/truncate.js'; import type { UserCacheService } from '@/core/UserCacheService.js'; @@ -197,7 +197,7 @@ export class ApPersonService implements OnModuleInit { * Misskeyに対象のPersonが登録されていればそれを返します。 */ @bindThis - public async fetchPerson(uri: string, resolver?: Resolver): Promise { + public async fetchPerson(uri: string, resolver?: Resolver): Promise { if (typeof uri !== 'string') throw new Error('uri is not string'); const cached = this.userCacheService.uriPersonCache.get(uri); @@ -206,13 +206,13 @@ export class ApPersonService implements OnModuleInit { // URIがこのサーバーを指しているならデータベースからフェッチ if (uri.startsWith(this.config.url + '/')) { const id = uri.split('/').pop(); - const u = await this.usersRepository.findOneBy({ id }) as null | CacheableUser; + const u = await this.usersRepository.findOneBy({ id }); if (u) this.userCacheService.uriPersonCache.set(uri, u); return u; } //#region このサーバーに既に登録されていたらそれを返す - const exist = await this.usersRepository.findOneBy({ uri }) as null | CacheableUser; + const exist = await this.usersRepository.findOneBy({ uri }); if (exist) { this.userCacheService.uriPersonCache.set(uri, exist); @@ -500,7 +500,7 @@ export class ApPersonService implements OnModuleInit { * リモートサーバーからフェッチしてMisskeyに登録しそれを返します。 */ @bindThis - public async resolvePerson(uri: string, resolver?: Resolver): Promise { + public async resolvePerson(uri: string, resolver?: Resolver): Promise { if (typeof uri !== 'string') throw new Error('uri is not string'); //#region このサーバーに既に登録されていたらそれを返す @@ -513,7 +513,7 @@ export class ApPersonService implements OnModuleInit { // リモートサーバーからフェッチしてきて登録 if (resolver == null) resolver = this.apResolverService.createResolver(); - return await this.createPerson(uri, resolver) as CacheableUser; + return await this.createPerson(uri, resolver); } @bindThis diff --git a/packages/backend/src/models/entities/User.ts b/packages/backend/src/models/entities/User.ts index 9cfe79787a..8d476ab0a6 100644 --- a/packages/backend/src/models/entities/User.ts +++ b/packages/backend/src/models/entities/User.ts @@ -217,6 +217,7 @@ export class User { export interface ILocalUser extends User { host: null; + uri: null; } export interface IRemoteUser extends User { @@ -224,12 +225,6 @@ export interface IRemoteUser extends User { uri: string; } -export type CacheableLocalUser = ILocalUser; - -export type CacheableRemoteUser = IRemoteUser; - -export type CacheableUser = CacheableLocalUser | CacheableRemoteUser; - export const localUsernameSchema = { type: 'string', pattern: /^\w{1,20}$/.toString().slice(1, -1) } as const; export const passwordSchema = { type: 'string', minLength: 1 } as const; export const nameSchema = { type: 'string', minLength: 1, maxLength: 50 } as const; diff --git a/packages/backend/src/queue/processors/InboxProcessorService.ts b/packages/backend/src/queue/processors/InboxProcessorService.ts index f814368a7a..a41222c487 100644 --- a/packages/backend/src/queue/processors/InboxProcessorService.ts +++ b/packages/backend/src/queue/processors/InboxProcessorService.ts @@ -16,7 +16,7 @@ import InstanceChart from '@/core/chart/charts/instance.js'; import ApRequestChart from '@/core/chart/charts/ap-request.js'; import FederationChart from '@/core/chart/charts/federation.js'; import { getApId } from '@/core/activitypub/type.js'; -import type { CacheableRemoteUser } from '@/models/entities/User.js'; +import type { IRemoteUser } from '@/models/entities/User.js'; import type { UserPublickey } from '@/models/entities/UserPublickey.js'; import { ApDbResolverService } from '@/core/activitypub/ApDbResolverService.js'; import { StatusError } from '@/misc/status-error.js'; @@ -87,7 +87,7 @@ export class InboxProcessorService { // HTTP-Signature keyIdを元にDBから取得 let authUser: { - user: CacheableRemoteUser; + user: IRemoteUser; key: UserPublickey | null; } | null = await this.apDbResolverService.getAuthUserFromKeyId(signature.keyId); diff --git a/packages/backend/src/server/api/ApiCallService.ts b/packages/backend/src/server/api/ApiCallService.ts index 2f3e7a44a9..3a05413bc8 100644 --- a/packages/backend/src/server/api/ApiCallService.ts +++ b/packages/backend/src/server/api/ApiCallService.ts @@ -5,7 +5,7 @@ import { promisify } from 'node:util'; import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; import { getIpHash } from '@/misc/get-ip-hash.js'; -import type { CacheableLocalUser, ILocalUser, User } from '@/models/entities/User.js'; +import type { ILocalUser, User } from '@/models/entities/User.js'; import type { AccessToken } from '@/models/entities/AccessToken.js'; import type Logger from '@/logger.js'; import type { UserIpsRepository } from '@/models/index.js'; @@ -194,7 +194,7 @@ export class ApiCallService implements OnApplicationShutdown { @bindThis private async call( ep: IEndpoint & { exec: any }, - user: CacheableLocalUser | null | undefined, + user: ILocalUser | null | undefined, token: AccessToken | null | undefined, data: any, file: { diff --git a/packages/backend/src/server/api/AuthenticateService.ts b/packages/backend/src/server/api/AuthenticateService.ts index 8b39f6c924..b9f6af4ffe 100644 --- a/packages/backend/src/server/api/AuthenticateService.ts +++ b/packages/backend/src/server/api/AuthenticateService.ts @@ -1,7 +1,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; import type { AccessTokensRepository, AppsRepository, UsersRepository } from '@/models/index.js'; -import type { CacheableLocalUser, ILocalUser } from '@/models/entities/User.js'; +import type { ILocalUser } from '@/models/entities/User.js'; import type { AccessToken } from '@/models/entities/AccessToken.js'; import { Cache } from '@/misc/cache.js'; import type { App } from '@/models/entities/App.js'; @@ -36,7 +36,7 @@ export class AuthenticateService { } @bindThis - public async authenticate(token: string | null | undefined): Promise<[CacheableLocalUser | null | undefined, AccessToken | null | undefined]> { + public async authenticate(token: string | null | undefined): Promise<[ILocalUser | null | undefined, AccessToken | null | undefined]> { if (token == null) { return [null, null]; } diff --git a/packages/backend/src/server/api/endpoint-base.ts b/packages/backend/src/server/api/endpoint-base.ts index b27329b9a9..56dad62862 100644 --- a/packages/backend/src/server/api/endpoint-base.ts +++ b/packages/backend/src/server/api/endpoint-base.ts @@ -1,7 +1,7 @@ import * as fs from 'node:fs'; import Ajv from 'ajv'; import type { Schema, SchemaType } from '@/misc/schema.js'; -import type { CacheableLocalUser } from '@/models/entities/User.js'; +import type { ILocalUser } from '@/models/entities/User.js'; import type { AccessToken } from '@/models/entities/AccessToken.js'; import { ApiError } from './error.js'; import type { IEndpointMeta } from './endpoints.js'; @@ -21,16 +21,16 @@ type File = { // TODO: paramsの型をT['params']のスキーマ定義から推論する type executor = - (params: SchemaType, user: T['requireCredential'] extends true ? CacheableLocalUser : CacheableLocalUser | null, token: AccessToken | null, file?: File, cleanup?: () => any, ip?: string | null, headers?: Record | null) => + (params: SchemaType, user: T['requireCredential'] extends true ? ILocalUser : ILocalUser | null, token: AccessToken | null, file?: File, cleanup?: () => any, ip?: string | null, headers?: Record | null) => Promise>>; export abstract class Endpoint { - public exec: (params: any, user: T['requireCredential'] extends true ? CacheableLocalUser : CacheableLocalUser | null, token: AccessToken | null, file?: File, ip?: string | null, headers?: Record | null) => Promise; + public exec: (params: any, user: T['requireCredential'] extends true ? ILocalUser : ILocalUser | null, token: AccessToken | null, file?: File, ip?: string | null, headers?: Record | null) => Promise; constructor(meta: T, paramDef: Ps, cb: executor) { const validate = ajv.compile(paramDef); - this.exec = (params: any, user: T['requireCredential'] extends true ? CacheableLocalUser : CacheableLocalUser | null, token: AccessToken | null, file?: File, ip?: string | null, headers?: Record | null) => { + this.exec = (params: any, user: T['requireCredential'] extends true ? ILocalUser : ILocalUser | null, token: AccessToken | null, file?: File, ip?: string | null, headers?: Record | null) => { let cleanup: undefined | (() => void) = undefined; if (meta.requireFile) { diff --git a/packages/backend/src/server/api/endpoints/ap/show.ts b/packages/backend/src/server/api/endpoints/ap/show.ts index 9470dd3cbb..e758c5e3fa 100644 --- a/packages/backend/src/server/api/endpoints/ap/show.ts +++ b/packages/backend/src/server/api/endpoints/ap/show.ts @@ -3,7 +3,7 @@ import ms from 'ms'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { UsersRepository, NotesRepository } from '@/models/index.js'; import type { Note } from '@/models/entities/Note.js'; -import type { CacheableLocalUser, User } from '@/models/entities/User.js'; +import type { ILocalUser, User } from '@/models/entities/User.js'; import { isActor, isPost, getApId } from '@/core/activitypub/type.js'; import type { SchemaType } from '@/misc/schema.js'; import { ApResolverService } from '@/core/activitypub/ApResolverService.js'; @@ -114,7 +114,7 @@ export default class extends Endpoint { * URIからUserかNoteを解決する */ @bindThis - private async fetchAny(uri: string, me: CacheableLocalUser | null | undefined): Promise | null> { + private async fetchAny(uri: string, me: ILocalUser | null | undefined): Promise | null> { // ブロックしてたら中断 const fetchedMeta = await this.metaService.fetch(); if (this.utilityService.isBlockedHost(fetchedMeta.blockedHosts, this.utilityService.extractDbHost(uri))) return null; @@ -147,7 +147,7 @@ export default class extends Endpoint { } @bindThis - private async mergePack(me: CacheableLocalUser | null | undefined, user: User | null | undefined, note: Note | null | undefined): Promise | null> { + private async mergePack(me: ILocalUser | null | undefined, user: User | null | undefined, note: Note | null | undefined): Promise | null> { if (user != null) { return { type: 'User', From 1b21bad202db9d30adc3f71d2ffa11b3b5187482 Mon Sep 17 00:00:00 2001 From: syuilo Date: Mon, 13 Feb 2023 15:50:22 +0900 Subject: [PATCH 073/294] refactor --- packages/backend/src/core/DriveService.ts | 8 +-- .../backend/src/core/InstanceActorService.ts | 12 ++-- packages/backend/src/core/MessagingService.ts | 4 +- .../backend/src/core/NoteCreateService.ts | 8 +-- .../backend/src/core/NoteDeleteService.ts | 6 +- .../backend/src/core/ProxyAccountService.ts | 6 +- packages/backend/src/core/ReactionService.ts | 8 +-- packages/backend/src/core/RelayService.ts | 8 +-- .../src/core/RemoteUserResolveService.ts | 6 +- packages/backend/src/core/UserCacheService.ts | 12 ++-- .../backend/src/core/UserFollowingService.ts | 20 +++---- .../src/core/activitypub/ApAudienceService.ts | 8 +-- .../core/activitypub/ApDbResolverService.ts | 10 ++-- .../activitypub/ApDeliverManagerService.ts | 10 ++-- .../src/core/activitypub/ApInboxService.ts | 56 +++++++++---------- .../src/core/activitypub/ApRendererService.ts | 18 +++--- .../src/core/activitypub/ApResolverService.ts | 6 +- .../core/activitypub/models/ApImageService.ts | 6 +- .../core/activitypub/models/ApNoteService.ts | 4 +- .../activitypub/models/ApPersonService.ts | 10 ++-- .../src/core/entities/UserEntityService.ts | 6 +- packages/backend/src/models/entities/User.ts | 4 +- .../queue/processors/InboxProcessorService.ts | 4 +- .../src/server/ActivityPubServerService.ts | 4 +- .../backend/src/server/api/ApiCallService.ts | 6 +- .../src/server/api/AuthenticateService.ts | 8 +-- .../src/server/api/SigninApiService.ts | 4 +- .../backend/src/server/api/SigninService.ts | 4 +- .../src/server/api/SignupApiService.ts | 4 +- .../backend/src/server/api/endpoint-base.ts | 8 +-- .../src/server/api/endpoints/ap/show.ts | 6 +- .../server/api/endpoints/notes/polls/vote.ts | 4 +- .../server/api/stream/channels/messaging.ts | 4 +- 33 files changed, 146 insertions(+), 146 deletions(-) diff --git a/packages/backend/src/core/DriveService.ts b/packages/backend/src/core/DriveService.ts index 42a430ea75..b15c967c85 100644 --- a/packages/backend/src/core/DriveService.ts +++ b/packages/backend/src/core/DriveService.ts @@ -7,7 +7,7 @@ import { DI } from '@/di-symbols.js'; import type { DriveFilesRepository, UsersRepository, DriveFoldersRepository, UserProfilesRepository } from '@/models/index.js'; import type { Config } from '@/config.js'; import Logger from '@/logger.js'; -import type { IRemoteUser, User } from '@/models/entities/User.js'; +import type { RemoteUser, User } from '@/models/entities/User.js'; import { MetaService } from '@/core/MetaService.js'; import { DriveFile } from '@/models/entities/DriveFile.js'; import { IdService } from '@/core/IdService.js'; @@ -255,7 +255,7 @@ export class DriveService { return { webpublic: null, thumbnail: null, - } + }; } try { @@ -399,7 +399,7 @@ export class DriveService { } @bindThis - private async deleteOldFile(user: IRemoteUser) { + private async deleteOldFile(user: RemoteUser) { const q = this.driveFilesRepository.createQueryBuilder('file') .where('file.userId = :userId', { userId: user.id }) .andWhere('file.isLink = FALSE'); @@ -500,7 +500,7 @@ export class DriveService { throw new IdentifiableError('c6244ed2-a39a-4e1c-bf93-f0fbd7764fa6', 'No free space.'); } else { // (アバターまたはバナーを含まず)最も古いファイルを削除する - this.deleteOldFile(await this.usersRepository.findOneByOrFail({ id: user.id }) as IRemoteUser); + this.deleteOldFile(await this.usersRepository.findOneByOrFail({ id: user.id }) as RemoteUser); } } } diff --git a/packages/backend/src/core/InstanceActorService.ts b/packages/backend/src/core/InstanceActorService.ts index 0b4a83c634..ee9ae0733f 100644 --- a/packages/backend/src/core/InstanceActorService.ts +++ b/packages/backend/src/core/InstanceActorService.ts @@ -1,6 +1,6 @@ import { Inject, Injectable } from '@nestjs/common'; import { IsNull } from 'typeorm'; -import type { ILocalUser } from '@/models/entities/User.js'; +import type { LocalUser } from '@/models/entities/User.js'; import type { UsersRepository } from '@/models/index.js'; import { Cache } from '@/misc/cache.js'; import { DI } from '@/di-symbols.js'; @@ -11,7 +11,7 @@ const ACTOR_USERNAME = 'instance.actor' as const; @Injectable() export class InstanceActorService { - private cache: Cache; + private cache: Cache; constructor( @Inject(DI.usersRepository) @@ -19,24 +19,24 @@ export class InstanceActorService { private createSystemUserService: CreateSystemUserService, ) { - this.cache = new Cache(Infinity); + this.cache = new Cache(Infinity); } @bindThis - public async getInstanceActor(): Promise { + public async getInstanceActor(): Promise { const cached = this.cache.get(null); if (cached) return cached; const user = await this.usersRepository.findOneBy({ host: IsNull(), username: ACTOR_USERNAME, - }) as ILocalUser | undefined; + }) as LocalUser | undefined; if (user) { this.cache.set(null, user); return user; } else { - const created = await this.createSystemUserService.createSystemUser(ACTOR_USERNAME) as ILocalUser; + const created = await this.createSystemUserService.createSystemUser(ACTOR_USERNAME) as LocalUser; this.cache.set(null, created); return created; } diff --git a/packages/backend/src/core/MessagingService.ts b/packages/backend/src/core/MessagingService.ts index 0721f63d5e..3a8a25c602 100644 --- a/packages/backend/src/core/MessagingService.ts +++ b/packages/backend/src/core/MessagingService.ts @@ -5,7 +5,7 @@ import type { Config } from '@/config.js'; import type { DriveFile } from '@/models/entities/DriveFile.js'; import type { MessagingMessage } from '@/models/entities/MessagingMessage.js'; import type { Note } from '@/models/entities/Note.js'; -import type { User, IRemoteUser } from '@/models/entities/User.js'; +import type { User, RemoteUser } from '@/models/entities/User.js'; import type { UserGroup } from '@/models/entities/UserGroup.js'; import { QueueService } from '@/core/QueueService.js'; import { toArray } from '@/misc/prelude/array.js'; @@ -291,7 +291,7 @@ export class MessagingService { } @bindThis - public async deliverReadActivity(user: { id: User['id']; host: null; }, recipient: IRemoteUser, messages: MessagingMessage | MessagingMessage[]) { + public async deliverReadActivity(user: { id: User['id']; host: null; }, recipient: RemoteUser, messages: MessagingMessage | MessagingMessage[]) { messages = toArray(messages).filter(x => x.uri); const contents = messages.map(x => this.apRendererService.renderRead(user, x)); diff --git a/packages/backend/src/core/NoteCreateService.ts b/packages/backend/src/core/NoteCreateService.ts index 04c057f6cd..2484cfc6c1 100644 --- a/packages/backend/src/core/NoteCreateService.ts +++ b/packages/backend/src/core/NoteCreateService.ts @@ -11,7 +11,7 @@ import type { DriveFile } from '@/models/entities/DriveFile.js'; import type { App } from '@/models/entities/App.js'; import { concat } from '@/misc/prelude/array.js'; import { IdService } from '@/core/IdService.js'; -import type { User, ILocalUser, IRemoteUser } from '@/models/entities/User.js'; +import type { User, LocalUser, RemoteUser } from '@/models/entities/User.js'; import type { IPoll } from '@/models/entities/Poll.js'; import { Poll } from '@/models/entities/Poll.js'; import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js'; @@ -52,7 +52,7 @@ class NotificationManager { private notifier: { id: User['id']; }; private note: Note; private queue: { - target: ILocalUser['id']; + target: LocalUser['id']; reason: NotificationType; }[]; @@ -68,7 +68,7 @@ class NotificationManager { } @bindThis - public push(notifiee: ILocalUser['id'], reason: NotificationType) { + public push(notifiee: LocalUser['id'], reason: NotificationType) { // 自分自身へは通知しない if (this.notifier.id === notifiee) return; @@ -605,7 +605,7 @@ export class NoteCreateService { // メンションされたリモートユーザーに配送 for (const u of mentionedUsers.filter(u => this.userEntityService.isRemoteUser(u))) { - dm.addDirectRecipe(u as IRemoteUser); + dm.addDirectRecipe(u as RemoteUser); } // 投稿がリプライかつ投稿者がローカルユーザーかつリプライ先の投稿の投稿者がリモートユーザーなら配送 diff --git a/packages/backend/src/core/NoteDeleteService.ts b/packages/backend/src/core/NoteDeleteService.ts index fbcac2eff3..571b625523 100644 --- a/packages/backend/src/core/NoteDeleteService.ts +++ b/packages/backend/src/core/NoteDeleteService.ts @@ -1,6 +1,6 @@ import { Brackets, In } from 'typeorm'; import { Injectable, Inject } from '@nestjs/common'; -import type { User, ILocalUser, IRemoteUser } from '@/models/entities/User.js'; +import type { User, LocalUser, RemoteUser } from '@/models/entities/User.js'; import type { Note, IMentionedRemoteUsers } from '@/models/entities/Note.js'; import type { InstancesRepository, NotesRepository, UsersRepository } from '@/models/index.js'; import { RelayService } from '@/core/RelayService.js'; @@ -159,11 +159,11 @@ export class NoteDeleteService { return await this.usersRepository.find({ where, - }) as IRemoteUser[]; + }) as RemoteUser[]; } @bindThis - private async deliverToConcerned(user: { id: ILocalUser['id']; host: null; }, note: Note, content: any) { + private async deliverToConcerned(user: { id: LocalUser['id']; host: null; }, note: Note, content: any) { this.apDeliverManagerService.deliverToFollowers(user, content); this.relayService.deliverToRelays(user, content); const remoteUsers = await this.getMentionedRemoteUsers(note); diff --git a/packages/backend/src/core/ProxyAccountService.ts b/packages/backend/src/core/ProxyAccountService.ts index 55b70bfc94..7ed322ae65 100644 --- a/packages/backend/src/core/ProxyAccountService.ts +++ b/packages/backend/src/core/ProxyAccountService.ts @@ -1,6 +1,6 @@ import { Inject, Injectable } from '@nestjs/common'; import type { UsersRepository } from '@/models/index.js'; -import type { ILocalUser, User } from '@/models/entities/User.js'; +import type { LocalUser, User } from '@/models/entities/User.js'; import { DI } from '@/di-symbols.js'; import { MetaService } from '@/core/MetaService.js'; import { bindThis } from '@/decorators.js'; @@ -16,9 +16,9 @@ export class ProxyAccountService { } @bindThis - public async fetch(): Promise { + public async fetch(): Promise { const meta = await this.metaService.fetch(); if (meta.proxyAccountId == null) return null; - return await this.usersRepository.findOneByOrFail({ id: meta.proxyAccountId }) as ILocalUser; + return await this.usersRepository.findOneByOrFail({ id: meta.proxyAccountId }) as LocalUser; } } diff --git a/packages/backend/src/core/ReactionService.ts b/packages/backend/src/core/ReactionService.ts index 9ac3058ef9..9fccc14ee4 100644 --- a/packages/backend/src/core/ReactionService.ts +++ b/packages/backend/src/core/ReactionService.ts @@ -3,7 +3,7 @@ import { IsNull } from 'typeorm'; import { DI } from '@/di-symbols.js'; import type { EmojisRepository, BlockingsRepository, NoteReactionsRepository, UsersRepository, NotesRepository } from '@/models/index.js'; import { IdentifiableError } from '@/misc/identifiable-error.js'; -import type { IRemoteUser, User } from '@/models/entities/User.js'; +import type { RemoteUser, User } from '@/models/entities/User.js'; import type { Note } from '@/models/entities/Note.js'; import { IdService } from '@/core/IdService.js'; import type { NoteReaction } from '@/models/entities/NoteReaction.js'; @@ -181,7 +181,7 @@ export class ReactionService { const dm = this.apDeliverManagerService.createDeliverManager(user, content); if (note.userHost !== null) { const reactee = await this.usersRepository.findOneBy({ id: note.userId }); - dm.addDirectRecipe(reactee as IRemoteUser); + dm.addDirectRecipe(reactee as RemoteUser); } if (['public', 'home', 'followers'].includes(note.visibility)) { @@ -189,7 +189,7 @@ export class ReactionService { } else if (note.visibility === 'specified') { const visibleUsers = await Promise.all(note.visibleUserIds.map(id => this.usersRepository.findOneBy({ id }))); for (const u of visibleUsers.filter(u => u && this.userEntityService.isRemoteUser(u))) { - dm.addDirectRecipe(u as IRemoteUser); + dm.addDirectRecipe(u as RemoteUser); } } @@ -239,7 +239,7 @@ export class ReactionService { const dm = this.apDeliverManagerService.createDeliverManager(user, content); if (note.userHost !== null) { const reactee = await this.usersRepository.findOneBy({ id: note.userId }); - dm.addDirectRecipe(reactee as IRemoteUser); + dm.addDirectRecipe(reactee as RemoteUser); } dm.addFollowersRecipe(); dm.execute(); diff --git a/packages/backend/src/core/RelayService.ts b/packages/backend/src/core/RelayService.ts index 326fd0af1f..2e07825e9b 100644 --- a/packages/backend/src/core/RelayService.ts +++ b/packages/backend/src/core/RelayService.ts @@ -1,6 +1,6 @@ import { Inject, Injectable } from '@nestjs/common'; import { IsNull } from 'typeorm'; -import type { ILocalUser, User } from '@/models/entities/User.js'; +import type { LocalUser, User } from '@/models/entities/User.js'; import type { RelaysRepository, UsersRepository } from '@/models/index.js'; import { IdService } from '@/core/IdService.js'; import { Cache } from '@/misc/cache.js'; @@ -34,16 +34,16 @@ export class RelayService { } @bindThis - private async getRelayActor(): Promise { + private async getRelayActor(): Promise { const user = await this.usersRepository.findOneBy({ host: IsNull(), username: ACTOR_USERNAME, }); - if (user) return user as ILocalUser; + if (user) return user as LocalUser; const created = await this.createSystemUserService.createSystemUser(ACTOR_USERNAME); - return created as ILocalUser; + return created as LocalUser; } @bindThis diff --git a/packages/backend/src/core/RemoteUserResolveService.ts b/packages/backend/src/core/RemoteUserResolveService.ts index dde4098624..b72dce5180 100644 --- a/packages/backend/src/core/RemoteUserResolveService.ts +++ b/packages/backend/src/core/RemoteUserResolveService.ts @@ -4,7 +4,7 @@ import chalk from 'chalk'; import { IsNull } from 'typeorm'; import { DI } from '@/di-symbols.js'; import type { UsersRepository } from '@/models/index.js'; -import type { IRemoteUser, User } from '@/models/entities/User.js'; +import type { RemoteUser, User } from '@/models/entities/User.js'; import type { Config } from '@/config.js'; import type Logger from '@/logger.js'; import { UtilityService } from '@/core/UtilityService.js'; @@ -60,7 +60,7 @@ export class RemoteUserResolveService { }); } - const user = await this.usersRepository.findOneBy({ usernameLower, host }) as IRemoteUser | null; + const user = await this.usersRepository.findOneBy({ usernameLower, host }) as RemoteUser | null; const acctLower = `${usernameLower}@${host}`; @@ -82,7 +82,7 @@ export class RemoteUserResolveService { const self = await this.resolveSelf(acctLower); if (user.uri !== self.href) { - // if uri mismatch, Fix (user@host <=> AP's Person id(IRemoteUser.uri)) mapping. + // if uri mismatch, Fix (user@host <=> AP's Person id(RemoteUser.uri)) mapping. this.logger.info(`uri missmatch: ${acctLower}`); this.logger.info(`recovery missmatch uri for (username=${username}, host=${host}) from ${user.uri} to ${self.href}`); diff --git a/packages/backend/src/core/UserCacheService.ts b/packages/backend/src/core/UserCacheService.ts index 5f0a919088..fc383d1c08 100644 --- a/packages/backend/src/core/UserCacheService.ts +++ b/packages/backend/src/core/UserCacheService.ts @@ -2,7 +2,7 @@ import { Inject, Injectable } from '@nestjs/common'; import Redis from 'ioredis'; import type { UsersRepository } from '@/models/index.js'; import { Cache } from '@/misc/cache.js'; -import type { ILocalUser, User } from '@/models/entities/User.js'; +import type { LocalUser, User } from '@/models/entities/User.js'; import { DI } from '@/di-symbols.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { bindThis } from '@/decorators.js'; @@ -12,8 +12,8 @@ import type { OnApplicationShutdown } from '@nestjs/common'; @Injectable() export class UserCacheService implements OnApplicationShutdown { public userByIdCache: Cache; - public localUserByNativeTokenCache: Cache; - public localUserByIdCache: Cache; + public localUserByNativeTokenCache: Cache; + public localUserByIdCache: Cache; public uriPersonCache: Cache; constructor( @@ -28,8 +28,8 @@ export class UserCacheService implements OnApplicationShutdown { //this.onMessage = this.onMessage.bind(this); this.userByIdCache = new Cache(Infinity); - this.localUserByNativeTokenCache = new Cache(Infinity); - this.localUserByIdCache = new Cache(Infinity); + this.localUserByNativeTokenCache = new Cache(Infinity); + this.localUserByIdCache = new Cache(Infinity); this.uriPersonCache = new Cache(Infinity); this.redisSubscriber.on('message', this.onMessage); @@ -58,7 +58,7 @@ export class UserCacheService implements OnApplicationShutdown { break; } case 'userTokenRegenerated': { - const user = await this.usersRepository.findOneByOrFail({ id: body.id }) as ILocalUser; + const user = await this.usersRepository.findOneByOrFail({ id: body.id }) as LocalUser; this.localUserByNativeTokenCache.delete(body.oldToken); this.localUserByNativeTokenCache.set(body.newToken, user); break; diff --git a/packages/backend/src/core/UserFollowingService.ts b/packages/backend/src/core/UserFollowingService.ts index 589842a419..d8426512bf 100644 --- a/packages/backend/src/core/UserFollowingService.ts +++ b/packages/backend/src/core/UserFollowingService.ts @@ -1,5 +1,5 @@ import { Inject, Injectable } from '@nestjs/common'; -import type { ILocalUser, IRemoteUser, User } from '@/models/entities/User.js'; +import type { LocalUser, RemoteUser, User } from '@/models/entities/User.js'; import { IdentifiableError } from '@/misc/identifiable-error.js'; import { QueueService } from '@/core/QueueService.js'; import PerUserFollowingChart from '@/core/chart/charts/per-user-following.js'; @@ -21,16 +21,16 @@ import Logger from '../logger.js'; const logger = new Logger('following/create'); -type Local = ILocalUser | { - id: ILocalUser['id']; - host: ILocalUser['host']; - uri: ILocalUser['uri'] +type Local = LocalUser | { + id: LocalUser['id']; + host: LocalUser['host']; + uri: LocalUser['uri'] }; -type Remote = IRemoteUser | { - id: IRemoteUser['id']; - host: IRemoteUser['host']; - uri: IRemoteUser['uri']; - inbox: IRemoteUser['inbox']; +type Remote = RemoteUser | { + id: RemoteUser['id']; + host: RemoteUser['host']; + uri: RemoteUser['uri']; + inbox: RemoteUser['inbox']; }; type Both = Local | Remote; diff --git a/packages/backend/src/core/activitypub/ApAudienceService.ts b/packages/backend/src/core/activitypub/ApAudienceService.ts index ee14f4ddd7..4c22297b37 100644 --- a/packages/backend/src/core/activitypub/ApAudienceService.ts +++ b/packages/backend/src/core/activitypub/ApAudienceService.ts @@ -2,7 +2,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { In } from 'typeorm'; import promiseLimit from 'promise-limit'; import { DI } from '@/di-symbols.js'; -import type { IRemoteUser, User } from '@/models/entities/User.js'; +import type { RemoteUser, User } from '@/models/entities/User.js'; import { concat, toArray, toSingle, unique } from '@/misc/prelude/array.js'; import { bindThis } from '@/decorators.js'; import { getApId, getApIds, getApType, isAccept, isActor, isAdd, isAnnounce, isBlock, isCollection, isCollectionOrOrderedCollection, isCreate, isDelete, isFlag, isFollow, isLike, isPost, isRead, isReject, isRemove, isTombstone, isUndo, isUpdate, validActor, validPost } from './type.js'; @@ -26,7 +26,7 @@ export class ApAudienceService { } @bindThis - public async parseAudience(actor: IRemoteUser, to?: ApObject, cc?: ApObject, resolver?: Resolver): Promise { + public async parseAudience(actor: RemoteUser, to?: ApObject, cc?: ApObject, resolver?: Resolver): Promise { const toGroups = this.groupingAudience(getApIds(to), actor); const ccGroups = this.groupingAudience(getApIds(cc), actor); @@ -69,7 +69,7 @@ export class ApAudienceService { } @bindThis - private groupingAudience(ids: string[], actor: IRemoteUser) { + private groupingAudience(ids: string[], actor: RemoteUser) { const groups = { public: [] as string[], followers: [] as string[], @@ -101,7 +101,7 @@ export class ApAudienceService { } @bindThis - private isFollowers(id: string, actor: IRemoteUser) { + private isFollowers(id: string, actor: RemoteUser) { return ( id === (actor.followersUri ?? `${actor.uri}/followers`) ); diff --git a/packages/backend/src/core/activitypub/ApDbResolverService.ts b/packages/backend/src/core/activitypub/ApDbResolverService.ts index 5af9e29069..9a894826c8 100644 --- a/packages/backend/src/core/activitypub/ApDbResolverService.ts +++ b/packages/backend/src/core/activitypub/ApDbResolverService.ts @@ -9,7 +9,7 @@ import { UserCacheService } from '@/core/UserCacheService.js'; import type { Note } from '@/models/entities/Note.js'; import type { MessagingMessage } from '@/models/entities/MessagingMessage.js'; import { bindThis } from '@/decorators.js'; -import { IRemoteUser, User } from '@/models/entities/User.js'; +import { RemoteUser, User } from '@/models/entities/User.js'; import { getApId } from './type.js'; import { ApPersonService } from './models/ApPersonService.js'; import type { IObject } from './type.js'; @@ -143,7 +143,7 @@ export class ApDbResolverService { */ @bindThis public async getAuthUserFromKeyId(keyId: string): Promise<{ - user: IRemoteUser; + user: RemoteUser; key: UserPublickey; } | null> { const key = await this.publicKeyCache.fetch(keyId, async () => { @@ -159,7 +159,7 @@ export class ApDbResolverService { if (key == null) return null; return { - user: await this.userCacheService.findById(key.userId) as IRemoteUser, + user: await this.userCacheService.findById(key.userId) as RemoteUser, key, }; } @@ -169,10 +169,10 @@ export class ApDbResolverService { */ @bindThis public async getAuthUserFromApId(uri: string): Promise<{ - user: IRemoteUser; + user: RemoteUser; key: UserPublickey | null; } | null> { - const user = await this.apPersonService.resolvePerson(uri) as IRemoteUser; + const user = await this.apPersonService.resolvePerson(uri) as RemoteUser; if (user == null) return null; diff --git a/packages/backend/src/core/activitypub/ApDeliverManagerService.ts b/packages/backend/src/core/activitypub/ApDeliverManagerService.ts index 256cf12651..5e6ea69846 100644 --- a/packages/backend/src/core/activitypub/ApDeliverManagerService.ts +++ b/packages/backend/src/core/activitypub/ApDeliverManagerService.ts @@ -3,7 +3,7 @@ import { IsNull, Not } from 'typeorm'; import { DI } from '@/di-symbols.js'; import type { FollowingsRepository, UsersRepository } from '@/models/index.js'; import type { Config } from '@/config.js'; -import type { ILocalUser, IRemoteUser, User } from '@/models/entities/User.js'; +import type { LocalUser, RemoteUser, User } from '@/models/entities/User.js'; import { QueueService } from '@/core/QueueService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { bindThis } from '@/decorators.js'; @@ -18,7 +18,7 @@ interface IFollowersRecipe extends IRecipe { interface IDirectRecipe extends IRecipe { type: 'Direct'; - to: IRemoteUser; + to: RemoteUser; } const isFollowers = (recipe: any): recipe is IFollowersRecipe => @@ -50,7 +50,7 @@ export class ApDeliverManagerService { * @param from Followee */ @bindThis - public async deliverToFollowers(actor: { id: ILocalUser['id']; host: null; }, activity: any) { + public async deliverToFollowers(actor: { id: LocalUser['id']; host: null; }, activity: any) { const manager = new DeliverManager( this.userEntityService, this.followingsRepository, @@ -68,7 +68,7 @@ export class ApDeliverManagerService { * @param to Target user */ @bindThis - public async deliverToUser(actor: { id: ILocalUser['id']; host: null; }, activity: any, to: IRemoteUser) { + public async deliverToUser(actor: { id: LocalUser['id']; host: null; }, activity: any, to: RemoteUser) { const manager = new DeliverManager( this.userEntityService, this.followingsRepository, @@ -132,7 +132,7 @@ class DeliverManager { * @param to To */ @bindThis - public addDirectRecipe(to: IRemoteUser) { + public addDirectRecipe(to: RemoteUser) { const recipe = { type: 'Direct', to, diff --git a/packages/backend/src/core/activitypub/ApInboxService.ts b/packages/backend/src/core/activitypub/ApInboxService.ts index d514e9845e..62f3827343 100644 --- a/packages/backend/src/core/activitypub/ApInboxService.ts +++ b/packages/backend/src/core/activitypub/ApInboxService.ts @@ -22,7 +22,7 @@ import { QueueService } from '@/core/QueueService.js'; import { MessagingService } from '@/core/MessagingService.js'; import type { UsersRepository, NotesRepository, FollowingsRepository, MessagingMessagesRepository, AbuseUserReportsRepository, FollowRequestsRepository } from '@/models/index.js'; import { bindThis } from '@/decorators.js'; -import type { IRemoteUser } from '@/models/entities/User.js'; +import type { RemoteUser } from '@/models/entities/User.js'; import { getApId, getApIds, getApType, isAccept, isActor, isAdd, isAnnounce, isBlock, isCollection, isCollectionOrOrderedCollection, isCreate, isDelete, isFlag, isFollow, isLike, isPost, isRead, isReject, isRemove, isTombstone, isUndo, isUpdate, validActor, validPost } from './type.js'; import { ApNoteService } from './models/ApNoteService.js'; import { ApLoggerService } from './ApLoggerService.js'; @@ -87,7 +87,7 @@ export class ApInboxService { } @bindThis - public async performActivity(actor: IRemoteUser, activity: IObject) { + public async performActivity(actor: RemoteUser, activity: IObject) { if (isCollectionOrOrderedCollection(activity)) { const resolver = this.apResolverService.createResolver(); for (const item of toArray(isCollection(activity) ? activity.items : activity.orderedItems)) { @@ -115,7 +115,7 @@ export class ApInboxService { } @bindThis - public async performOneActivity(actor: IRemoteUser, activity: IObject): Promise { + public async performOneActivity(actor: RemoteUser, activity: IObject): Promise { if (actor.isSuspended) return; if (isCreate(activity)) { @@ -152,7 +152,7 @@ export class ApInboxService { } @bindThis - private async follow(actor: IRemoteUser, activity: IFollow): Promise { + private async follow(actor: RemoteUser, activity: IFollow): Promise { const followee = await this.apDbResolverService.getUserFromApId(activity.object); if (followee == null) { @@ -168,7 +168,7 @@ export class ApInboxService { } @bindThis - private async like(actor: IRemoteUser, activity: ILike): Promise { + private async like(actor: RemoteUser, activity: ILike): Promise { const targetUri = getApId(activity.object); const note = await this.apNoteService.fetchNote(targetUri); @@ -186,7 +186,7 @@ export class ApInboxService { } @bindThis - private async read(actor: IRemoteUser, activity: IRead): Promise { + private async read(actor: RemoteUser, activity: IRead): Promise { const id = await getApId(activity.object); if (!this.utilityService.isSelfHost(this.utilityService.extractDbHost(id))) { @@ -209,7 +209,7 @@ export class ApInboxService { } @bindThis - private async accept(actor: IRemoteUser, activity: IAccept): Promise { + private async accept(actor: RemoteUser, activity: IAccept): Promise { const uri = activity.id ?? activity; this.logger.info(`Accept: ${uri}`); @@ -227,7 +227,7 @@ export class ApInboxService { } @bindThis - private async acceptFollow(actor: IRemoteUser, activity: IFollow): Promise { + private async acceptFollow(actor: RemoteUser, activity: IFollow): Promise { // ※ activityはこっちから投げたフォローリクエストなので、activity.actorは存在するローカルユーザーである必要がある const follower = await this.apDbResolverService.getUserFromApId(activity.actor); @@ -251,7 +251,7 @@ export class ApInboxService { } @bindThis - private async add(actor: IRemoteUser, activity: IAdd): Promise { + private async add(actor: RemoteUser, activity: IAdd): Promise { if ('actor' in activity && actor.uri !== activity.actor) { throw new Error('invalid actor'); } @@ -271,7 +271,7 @@ export class ApInboxService { } @bindThis - private async announce(actor: IRemoteUser, activity: IAnnounce): Promise { + private async announce(actor: RemoteUser, activity: IAnnounce): Promise { const uri = getApId(activity); this.logger.info(`Announce: ${uri}`); @@ -282,7 +282,7 @@ export class ApInboxService { } @bindThis - private async announceNote(actor: IRemoteUser, activity: IAnnounce, targetUri: string): Promise { + private async announceNote(actor: RemoteUser, activity: IAnnounce, targetUri: string): Promise { const uri = getApId(activity); if (actor.isSuspended) { @@ -342,7 +342,7 @@ export class ApInboxService { } @bindThis - private async block(actor: IRemoteUser, activity: IBlock): Promise { + private async block(actor: RemoteUser, activity: IBlock): Promise { // ※ activity.objectにブロック対象があり、それは存在するローカルユーザーのはず const blockee = await this.apDbResolverService.getUserFromApId(activity.object); @@ -360,7 +360,7 @@ export class ApInboxService { } @bindThis - private async create(actor: IRemoteUser, activity: ICreate): Promise { + private async create(actor: RemoteUser, activity: ICreate): Promise { const uri = getApId(activity); this.logger.info(`Create: ${uri}`); @@ -396,7 +396,7 @@ export class ApInboxService { } @bindThis - private async createNote(resolver: Resolver, actor: IRemoteUser, note: IObject, silent = false, activity?: ICreate): Promise { + private async createNote(resolver: Resolver, actor: RemoteUser, note: IObject, silent = false, activity?: ICreate): Promise { const uri = getApId(note); if (typeof note === 'object') { @@ -431,7 +431,7 @@ export class ApInboxService { } @bindThis - private async delete(actor: IRemoteUser, activity: IDelete): Promise { + private async delete(actor: RemoteUser, activity: IDelete): Promise { if ('actor' in activity && actor.uri !== activity.actor) { throw new Error('invalid actor'); } @@ -473,7 +473,7 @@ export class ApInboxService { } @bindThis - private async deleteActor(actor: IRemoteUser, uri: string): Promise { + private async deleteActor(actor: RemoteUser, uri: string): Promise { this.logger.info(`Deleting the Actor: ${uri}`); if (actor.uri !== uri) { @@ -495,7 +495,7 @@ export class ApInboxService { } @bindThis - private async deleteNote(actor: IRemoteUser, uri: string): Promise { + private async deleteNote(actor: RemoteUser, uri: string): Promise { this.logger.info(`Deleting the Note: ${uri}`); const unlock = await this.appLockService.getApLock(uri); @@ -528,7 +528,7 @@ export class ApInboxService { } @bindThis - private async flag(actor: IRemoteUser, activity: IFlag): Promise { + private async flag(actor: RemoteUser, activity: IFlag): Promise { // objectは `(User|Note) | (User|Note)[]` だけど、全パターンDBスキーマと対応させられないので // 対象ユーザーは一番最初のユーザー として あとはコメントとして格納する const uris = getApIds(activity.object); @@ -553,7 +553,7 @@ export class ApInboxService { } @bindThis - private async reject(actor: IRemoteUser, activity: IReject): Promise { + private async reject(actor: RemoteUser, activity: IReject): Promise { const uri = activity.id ?? activity; this.logger.info(`Reject: ${uri}`); @@ -571,7 +571,7 @@ export class ApInboxService { } @bindThis - private async rejectFollow(actor: IRemoteUser, activity: IFollow): Promise { + private async rejectFollow(actor: RemoteUser, activity: IFollow): Promise { // ※ activityはこっちから投げたフォローリクエストなので、activity.actorは存在するローカルユーザーである必要がある const follower = await this.apDbResolverService.getUserFromApId(activity.actor); @@ -595,7 +595,7 @@ export class ApInboxService { } @bindThis - private async remove(actor: IRemoteUser, activity: IRemove): Promise { + private async remove(actor: RemoteUser, activity: IRemove): Promise { if ('actor' in activity && actor.uri !== activity.actor) { throw new Error('invalid actor'); } @@ -615,7 +615,7 @@ export class ApInboxService { } @bindThis - private async undo(actor: IRemoteUser, activity: IUndo): Promise { + private async undo(actor: RemoteUser, activity: IUndo): Promise { if ('actor' in activity && actor.uri !== activity.actor) { throw new Error('invalid actor'); } @@ -641,7 +641,7 @@ export class ApInboxService { } @bindThis - private async undoAccept(actor: IRemoteUser, activity: IAccept): Promise { + private async undoAccept(actor: RemoteUser, activity: IAccept): Promise { const follower = await this.apDbResolverService.getUserFromApId(activity.object); if (follower == null) { return 'skip: follower not found'; @@ -661,7 +661,7 @@ export class ApInboxService { } @bindThis - private async undoAnnounce(actor: IRemoteUser, activity: IAnnounce): Promise { + private async undoAnnounce(actor: RemoteUser, activity: IAnnounce): Promise { const uri = getApId(activity); const note = await this.notesRepository.findOneBy({ @@ -676,7 +676,7 @@ export class ApInboxService { } @bindThis - private async undoBlock(actor: IRemoteUser, activity: IBlock): Promise { + private async undoBlock(actor: RemoteUser, activity: IBlock): Promise { const blockee = await this.apDbResolverService.getUserFromApId(activity.object); if (blockee == null) { @@ -692,7 +692,7 @@ export class ApInboxService { } @bindThis - private async undoFollow(actor: IRemoteUser, activity: IFollow): Promise { + private async undoFollow(actor: RemoteUser, activity: IFollow): Promise { const followee = await this.apDbResolverService.getUserFromApId(activity.object); if (followee == null) { return 'skip: followee not found'; @@ -726,7 +726,7 @@ export class ApInboxService { } @bindThis - private async undoLike(actor: IRemoteUser, activity: ILike): Promise { + private async undoLike(actor: RemoteUser, activity: ILike): Promise { const targetUri = getApId(activity.object); const note = await this.apNoteService.fetchNote(targetUri); @@ -741,7 +741,7 @@ export class ApInboxService { } @bindThis - private async update(actor: IRemoteUser, activity: IUpdate): Promise { + private async update(actor: RemoteUser, activity: IUpdate): Promise { if ('actor' in activity && actor.uri !== activity.actor) { return 'skip: invalid actor'; } diff --git a/packages/backend/src/core/activitypub/ApRendererService.ts b/packages/backend/src/core/activitypub/ApRendererService.ts index 996ff625e8..308393f9fb 100644 --- a/packages/backend/src/core/activitypub/ApRendererService.ts +++ b/packages/backend/src/core/activitypub/ApRendererService.ts @@ -5,7 +5,7 @@ import { v4 as uuid } from 'uuid'; import * as mfm from 'mfm-js'; import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; -import type { ILocalUser, IRemoteUser, User } from '@/models/entities/User.js'; +import type { LocalUser, RemoteUser, User } from '@/models/entities/User.js'; import type { IMentionedRemoteUsers, Note } from '@/models/entities/Note.js'; import type { Blocking } from '@/models/entities/Blocking.js'; import type { Relay } from '@/models/entities/Relay.js'; @@ -70,7 +70,7 @@ export class ApRendererService { } @bindThis - public renderAdd(user: ILocalUser, target: any, object: any): IAdd { + public renderAdd(user: LocalUser, target: any, object: any): IAdd { return { type: 'Add', actor: `${this.config.url}/users/${user.id}`, @@ -181,7 +181,7 @@ export class ApRendererService { // to anonymise reporters, the reporting actor must be a system user // object has to be a uri or array of uris @bindThis - public renderFlag(user: ILocalUser, object: IObject, content: string): IFlag { + public renderFlag(user: LocalUser, object: IObject, content: string): IFlag { return { type: 'Flag', actor: `${this.config.url}/users/${user.id}`, @@ -191,7 +191,7 @@ export class ApRendererService { } @bindThis - public renderFollowRelay(relay: Relay, relayActor: ILocalUser): IFollow { + public renderFollowRelay(relay: Relay, relayActor: LocalUser): IFollow { return { id: `${this.config.url}/activities/follow-relay/${relay.id}`, type: 'Follow', @@ -244,7 +244,7 @@ export class ApRendererService { } @bindThis - public renderKey(user: ILocalUser, key: UserKeypair, postfix?: string): IKey { + public renderKey(user: LocalUser, key: UserKeypair, postfix?: string): IKey { return { id: `${this.config.url}/users/${user.id}${postfix ?? '/publickey'}`, type: 'Key', @@ -287,8 +287,8 @@ export class ApRendererService { public renderMention(mention: User): IApMention { return { type: 'Mention', - href: this.userEntityService.isRemoteUser(mention) ? mention.uri! : `${this.config.url}/users/${(mention as ILocalUser).id}`, - name: this.userEntityService.isRemoteUser(mention) ? `@${mention.username}@${mention.host}` : `@${(mention as ILocalUser).username}`, + href: this.userEntityService.isRemoteUser(mention) ? mention.uri! : `${this.config.url}/users/${(mention as LocalUser).id}`, + name: this.userEntityService.isRemoteUser(mention) ? `@${mention.username}@${mention.host}` : `@${(mention as LocalUser).username}`, }; } @@ -438,7 +438,7 @@ export class ApRendererService { } @bindThis - public async renderPerson(user: ILocalUser) { + public async renderPerson(user: LocalUser) { const id = `${this.config.url}/users/${user.id}`; const isSystem = !!user.username.match(/\./); @@ -594,7 +594,7 @@ export class ApRendererService { } @bindThis - public renderVote(user: { id: User['id'] }, vote: PollVote, note: Note, poll: Poll, pollOwner: IRemoteUser): ICreate { + public renderVote(user: { id: User['id'] }, vote: PollVote, note: Note, poll: Poll, pollOwner: RemoteUser): ICreate { return { id: `${this.config.url}/users/${user.id}#votes/${vote.id}/activity`, actor: `${this.config.url}/users/${user.id}`, diff --git a/packages/backend/src/core/activitypub/ApResolverService.ts b/packages/backend/src/core/activitypub/ApResolverService.ts index 65026cc4c5..df7bb46405 100644 --- a/packages/backend/src/core/activitypub/ApResolverService.ts +++ b/packages/backend/src/core/activitypub/ApResolverService.ts @@ -1,5 +1,5 @@ import { Inject, Injectable } from '@nestjs/common'; -import type { ILocalUser } from '@/models/entities/User.js'; +import type { LocalUser } from '@/models/entities/User.js'; import { InstanceActorService } from '@/core/InstanceActorService.js'; import type { NotesRepository, PollsRepository, NoteReactionsRepository, UsersRepository } from '@/models/index.js'; import type { Config } from '@/config.js'; @@ -18,7 +18,7 @@ import type { IObject, ICollection, IOrderedCollection } from './type.js'; export class Resolver { private history: Set; - private user?: ILocalUser; + private user?: LocalUser; private logger: Logger; constructor( @@ -133,7 +133,7 @@ export class Resolver { }); case 'users': return this.usersRepository.findOneByOrFail({ id: parsed.id }) - .then(user => this.apRendererService.renderPerson(user as ILocalUser)); + .then(user => this.apRendererService.renderPerson(user as LocalUser)); case 'questions': // Polls are indexed by the note they are attached to. return Promise.all([ diff --git a/packages/backend/src/core/activitypub/models/ApImageService.ts b/packages/backend/src/core/activitypub/models/ApImageService.ts index f14b150138..3b671af127 100644 --- a/packages/backend/src/core/activitypub/models/ApImageService.ts +++ b/packages/backend/src/core/activitypub/models/ApImageService.ts @@ -2,7 +2,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; import type { DriveFilesRepository } from '@/models/index.js'; import type { Config } from '@/config.js'; -import type { IRemoteUser } from '@/models/entities/User.js'; +import type { RemoteUser } from '@/models/entities/User.js'; import type { DriveFile } from '@/models/entities/DriveFile.js'; import { MetaService } from '@/core/MetaService.js'; import { truncate } from '@/misc/truncate.js'; @@ -36,7 +36,7 @@ export class ApImageService { * Imageを作成します。 */ @bindThis - public async createImage(actor: IRemoteUser, value: any): Promise { + public async createImage(actor: RemoteUser, value: any): Promise { // 投稿者が凍結されていたらスキップ if (actor.isSuspended) { throw new Error('actor has been suspended'); @@ -88,7 +88,7 @@ export class ApImageService { * リモートサーバーからフェッチしてMisskeyに登録しそれを返します。 */ @bindThis - public async resolveImage(actor: IRemoteUser, value: any): Promise { + public async resolveImage(actor: RemoteUser, value: any): Promise { // TODO // リモートサーバーからフェッチしてきて登録 diff --git a/packages/backend/src/core/activitypub/models/ApNoteService.ts b/packages/backend/src/core/activitypub/models/ApNoteService.ts index 0292a27d94..d4c4836887 100644 --- a/packages/backend/src/core/activitypub/models/ApNoteService.ts +++ b/packages/backend/src/core/activitypub/models/ApNoteService.ts @@ -3,7 +3,7 @@ import promiseLimit from 'promise-limit'; import { DI } from '@/di-symbols.js'; import type { MessagingMessagesRepository, PollsRepository, EmojisRepository, UsersRepository } from '@/models/index.js'; import type { Config } from '@/config.js'; -import type { IRemoteUser } from '@/models/entities/User.js'; +import type { RemoteUser } from '@/models/entities/User.js'; import type { Note } from '@/models/entities/Note.js'; import { toArray, toSingle, unique } from '@/misc/prelude/array.js'; import type { Emoji } from '@/models/entities/Emoji.js'; @@ -146,7 +146,7 @@ export class ApNoteService { this.logger.info(`Creating the Note: ${note.id}`); // 投稿者をフェッチ - const actor = await this.apPersonService.resolvePerson(getOneApId(note.attributedTo!), resolver) as IRemoteUser; + const actor = await this.apPersonService.resolvePerson(getOneApId(note.attributedTo!), resolver) as RemoteUser; // 投稿者が凍結されていたらスキップ if (actor.isSuspended) { diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts index 9dca065529..35d6985f7a 100644 --- a/packages/backend/src/core/activitypub/models/ApPersonService.ts +++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts @@ -5,7 +5,7 @@ import { ModuleRef } from '@nestjs/core'; import { DI } from '@/di-symbols.js'; import type { FollowingsRepository, InstancesRepository, UserProfilesRepository, UserPublickeysRepository, UsersRepository } from '@/models/index.js'; import type { Config } from '@/config.js'; -import type { IRemoteUser } from '@/models/entities/User.js'; +import type { RemoteUser } from '@/models/entities/User.js'; import { User } from '@/models/entities/User.js'; import { truncate } from '@/misc/truncate.js'; import type { UserCacheService } from '@/core/UserCacheService.js'; @@ -259,7 +259,7 @@ export class ApPersonService implements OnModuleInit { } // Create user - let user: IRemoteUser; + let user: RemoteUser; try { // Start transaction await this.db.transaction(async transactionalEntityManager => { @@ -284,7 +284,7 @@ export class ApPersonService implements OnModuleInit { isBot, isCat: (person as any).isCat === true, showTimelineReplies: false, - })) as IRemoteUser; + })) as RemoteUser; await transactionalEntityManager.save(new UserProfile({ userId: user.id, @@ -313,7 +313,7 @@ export class ApPersonService implements OnModuleInit { }); if (u) { - user = u as IRemoteUser; + user = u as RemoteUser; } else { throw new Error('already registered'); } @@ -392,7 +392,7 @@ export class ApPersonService implements OnModuleInit { } //#region このサーバーに既に登録されているか - const exist = await this.usersRepository.findOneBy({ uri }) as IRemoteUser; + const exist = await this.usersRepository.findOneBy({ uri }) as RemoteUser; if (exist == null) { return; diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts index eea9d5567d..fa3337c019 100644 --- a/packages/backend/src/core/entities/UserEntityService.ts +++ b/packages/backend/src/core/entities/UserEntityService.ts @@ -10,7 +10,7 @@ import { awaitAll } from '@/misc/prelude/await-all.js'; import { USER_ACTIVE_THRESHOLD, USER_ONLINE_THRESHOLD } from '@/const.js'; import { Cache } from '@/misc/cache.js'; import type { Instance } from '@/models/entities/Instance.js'; -import type { ILocalUser, IRemoteUser, User } from '@/models/entities/User.js'; +import type { LocalUser, RemoteUser, User } from '@/models/entities/User.js'; import { birthdaySchema, descriptionSchema, localUsernameSchema, locationSchema, nameSchema, passwordSchema } from '@/models/entities/User.js'; import type { UsersRepository, UserSecurityKeysRepository, FollowingsRepository, FollowRequestsRepository, BlockingsRepository, MutingsRepository, DriveFilesRepository, NoteUnreadsRepository, ChannelFollowingsRepository, NotificationsRepository, UserNotePiningsRepository, UserProfilesRepository, InstancesRepository, AnnouncementReadsRepository, MessagingMessagesRepository, UserGroupJoiningsRepository, AnnouncementsRepository, AntennaNotesRepository, PagesRepository, UserProfile } from '@/models/index.js'; import { bindThis } from '@/decorators.js'; @@ -32,13 +32,13 @@ type IsMeAndIsUserDetailed(user: T): user is T & { host: null; }; function isLocalUser(user: User | { host: User['host'] }): boolean { return user.host == null; } -function isRemoteUser(user: User): user is IRemoteUser; +function isRemoteUser(user: User): user is RemoteUser; function isRemoteUser(user: T): user is T & { host: string; }; function isRemoteUser(user: User | { host: User['host'] }): boolean { return !isLocalUser(user); diff --git a/packages/backend/src/models/entities/User.ts b/packages/backend/src/models/entities/User.ts index 8d476ab0a6..0a8b89ea06 100644 --- a/packages/backend/src/models/entities/User.ts +++ b/packages/backend/src/models/entities/User.ts @@ -215,12 +215,12 @@ export class User { } } -export interface ILocalUser extends User { +export type LocalUser = User & { host: null; uri: null; } -export interface IRemoteUser extends User { +export type RemoteUser = User & { host: string; uri: string; } diff --git a/packages/backend/src/queue/processors/InboxProcessorService.ts b/packages/backend/src/queue/processors/InboxProcessorService.ts index a41222c487..fb4ab0c62e 100644 --- a/packages/backend/src/queue/processors/InboxProcessorService.ts +++ b/packages/backend/src/queue/processors/InboxProcessorService.ts @@ -16,7 +16,7 @@ import InstanceChart from '@/core/chart/charts/instance.js'; import ApRequestChart from '@/core/chart/charts/ap-request.js'; import FederationChart from '@/core/chart/charts/federation.js'; import { getApId } from '@/core/activitypub/type.js'; -import type { IRemoteUser } from '@/models/entities/User.js'; +import type { RemoteUser } from '@/models/entities/User.js'; import type { UserPublickey } from '@/models/entities/UserPublickey.js'; import { ApDbResolverService } from '@/core/activitypub/ApDbResolverService.js'; import { StatusError } from '@/misc/status-error.js'; @@ -87,7 +87,7 @@ export class InboxProcessorService { // HTTP-Signature keyIdを元にDBから取得 let authUser: { - user: IRemoteUser; + user: RemoteUser; key: UserPublickey | null; } | null = await this.apDbResolverService.getAuthUserFromKeyId(signature.keyId); diff --git a/packages/backend/src/server/ActivityPubServerService.ts b/packages/backend/src/server/ActivityPubServerService.ts index c3795223ad..da8d0114e5 100644 --- a/packages/backend/src/server/ActivityPubServerService.ts +++ b/packages/backend/src/server/ActivityPubServerService.ts @@ -11,7 +11,7 @@ import * as url from '@/misc/prelude/url.js'; import type { Config } from '@/config.js'; import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; import { QueueService } from '@/core/QueueService.js'; -import type { ILocalUser, User } from '@/models/entities/User.js'; +import type { LocalUser, User } from '@/models/entities/User.js'; import { UserKeypairStoreService } from '@/core/UserKeypairStoreService.js'; import type { Following } from '@/models/entities/Following.js'; import { countIf } from '@/misc/prelude/array.js'; @@ -411,7 +411,7 @@ export class ActivityPubServerService { reply.header('Cache-Control', 'public, max-age=180'); this.setResponseType(request, reply); - return (this.apRendererService.addContext(await this.apRendererService.renderPerson(user as ILocalUser))); + return (this.apRendererService.addContext(await this.apRendererService.renderPerson(user as LocalUser))); } @bindThis diff --git a/packages/backend/src/server/api/ApiCallService.ts b/packages/backend/src/server/api/ApiCallService.ts index 3a05413bc8..4a8b8a1c12 100644 --- a/packages/backend/src/server/api/ApiCallService.ts +++ b/packages/backend/src/server/api/ApiCallService.ts @@ -5,7 +5,7 @@ import { promisify } from 'node:util'; import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; import { getIpHash } from '@/misc/get-ip-hash.js'; -import type { ILocalUser, User } from '@/models/entities/User.js'; +import type { LocalUser, User } from '@/models/entities/User.js'; import type { AccessToken } from '@/models/entities/AccessToken.js'; import type Logger from '@/logger.js'; import type { UserIpsRepository } from '@/models/index.js'; @@ -168,7 +168,7 @@ export class ApiCallService implements OnApplicationShutdown { } @bindThis - private async logIp(request: FastifyRequest, user: ILocalUser) { + private async logIp(request: FastifyRequest, user: LocalUser) { const meta = await this.metaService.fetch(); if (!meta.enableIpLogging) return; const ip = request.ip; @@ -194,7 +194,7 @@ export class ApiCallService implements OnApplicationShutdown { @bindThis private async call( ep: IEndpoint & { exec: any }, - user: ILocalUser | null | undefined, + user: LocalUser | null | undefined, token: AccessToken | null | undefined, data: any, file: { diff --git a/packages/backend/src/server/api/AuthenticateService.ts b/packages/backend/src/server/api/AuthenticateService.ts index b9f6af4ffe..87438c348d 100644 --- a/packages/backend/src/server/api/AuthenticateService.ts +++ b/packages/backend/src/server/api/AuthenticateService.ts @@ -1,7 +1,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; import type { AccessTokensRepository, AppsRepository, UsersRepository } from '@/models/index.js'; -import type { ILocalUser } from '@/models/entities/User.js'; +import type { LocalUser } from '@/models/entities/User.js'; import type { AccessToken } from '@/models/entities/AccessToken.js'; import { Cache } from '@/misc/cache.js'; import type { App } from '@/models/entities/App.js'; @@ -36,14 +36,14 @@ export class AuthenticateService { } @bindThis - public async authenticate(token: string | null | undefined): Promise<[ILocalUser | null | undefined, AccessToken | null | undefined]> { + public async authenticate(token: string | null | undefined): Promise<[LocalUser | null | undefined, AccessToken | null | undefined]> { if (token == null) { return [null, null]; } if (isNativeToken(token)) { const user = await this.userCacheService.localUserByNativeTokenCache.fetch(token, - () => this.usersRepository.findOneBy({ token }) as Promise); + () => this.usersRepository.findOneBy({ token }) as Promise); if (user == null) { throw new AuthenticationError('user not found'); @@ -70,7 +70,7 @@ export class AuthenticateService { const user = await this.userCacheService.localUserByIdCache.fetch(accessToken.userId, () => this.usersRepository.findOneBy({ id: accessToken.userId, - }) as Promise); + }) as Promise); if (accessToken.appId) { const app = await this.appCache.fetch(accessToken.appId, diff --git a/packages/backend/src/server/api/SigninApiService.ts b/packages/backend/src/server/api/SigninApiService.ts index d490097dea..f1164b9957 100644 --- a/packages/backend/src/server/api/SigninApiService.ts +++ b/packages/backend/src/server/api/SigninApiService.ts @@ -7,7 +7,7 @@ import { DI } from '@/di-symbols.js'; import type { UserSecurityKeysRepository, SigninsRepository, UserProfilesRepository, AttestationChallengesRepository, UsersRepository } from '@/models/index.js'; import type { Config } from '@/config.js'; import { getIpHash } from '@/misc/get-ip-hash.js'; -import type { ILocalUser } from '@/models/entities/User.js'; +import type { LocalUser } from '@/models/entities/User.js'; import { IdService } from '@/core/IdService.js'; import { TwoFactorAuthenticationService } from '@/core/TwoFactorAuthenticationService.js'; import { bindThis } from '@/decorators.js'; @@ -105,7 +105,7 @@ export class SigninApiService { const user = await this.usersRepository.findOneBy({ usernameLower: username.toLowerCase(), host: IsNull(), - }) as ILocalUser; + }) as LocalUser; if (user == null) { return error(404, { diff --git a/packages/backend/src/server/api/SigninService.ts b/packages/backend/src/server/api/SigninService.ts index c78d9f85cd..f821dbb500 100644 --- a/packages/backend/src/server/api/SigninService.ts +++ b/packages/backend/src/server/api/SigninService.ts @@ -3,7 +3,7 @@ import { DI } from '@/di-symbols.js'; import type { SigninsRepository, UsersRepository } from '@/models/index.js'; import type { Config } from '@/config.js'; import { IdService } from '@/core/IdService.js'; -import type { ILocalUser } from '@/models/entities/User.js'; +import type { LocalUser } from '@/models/entities/User.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { SigninEntityService } from '@/core/entities/SigninEntityService.js'; import { bindThis } from '@/decorators.js'; @@ -25,7 +25,7 @@ export class SigninService { } @bindThis - public signin(request: FastifyRequest, reply: FastifyReply, user: ILocalUser) { + public signin(request: FastifyRequest, reply: FastifyReply, user: LocalUser) { setImmediate(async () => { // Append signin history const record = await this.signinsRepository.insert({ diff --git a/packages/backend/src/server/api/SignupApiService.ts b/packages/backend/src/server/api/SignupApiService.ts index ffd7e203ea..41e8365d08 100644 --- a/packages/backend/src/server/api/SignupApiService.ts +++ b/packages/backend/src/server/api/SignupApiService.ts @@ -10,7 +10,7 @@ import { IdService } from '@/core/IdService.js'; import { SignupService } from '@/core/SignupService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { EmailService } from '@/core/EmailService.js'; -import { ILocalUser } from '@/models/entities/User.js'; +import { LocalUser } from '@/models/entities/User.js'; import { FastifyReplyError } from '@/misc/fastify-reply-error.js'; import { bindThis } from '@/decorators.js'; import { SigninService } from './SigninService.js'; @@ -194,7 +194,7 @@ export class SignupApiService { emailVerifyCode: null, }); - return this.signinService.signin(request, reply, account as ILocalUser); + return this.signinService.signin(request, reply, account as LocalUser); } catch (err) { throw new FastifyReplyError(400, typeof err === 'string' ? err : (err as Error).toString()); } diff --git a/packages/backend/src/server/api/endpoint-base.ts b/packages/backend/src/server/api/endpoint-base.ts index 56dad62862..115526d997 100644 --- a/packages/backend/src/server/api/endpoint-base.ts +++ b/packages/backend/src/server/api/endpoint-base.ts @@ -1,7 +1,7 @@ import * as fs from 'node:fs'; import Ajv from 'ajv'; import type { Schema, SchemaType } from '@/misc/schema.js'; -import type { ILocalUser } from '@/models/entities/User.js'; +import type { LocalUser } from '@/models/entities/User.js'; import type { AccessToken } from '@/models/entities/AccessToken.js'; import { ApiError } from './error.js'; import type { IEndpointMeta } from './endpoints.js'; @@ -21,16 +21,16 @@ type File = { // TODO: paramsの型をT['params']のスキーマ定義から推論する type executor = - (params: SchemaType, user: T['requireCredential'] extends true ? ILocalUser : ILocalUser | null, token: AccessToken | null, file?: File, cleanup?: () => any, ip?: string | null, headers?: Record | null) => + (params: SchemaType, user: T['requireCredential'] extends true ? LocalUser : LocalUser | null, token: AccessToken | null, file?: File, cleanup?: () => any, ip?: string | null, headers?: Record | null) => Promise>>; export abstract class Endpoint { - public exec: (params: any, user: T['requireCredential'] extends true ? ILocalUser : ILocalUser | null, token: AccessToken | null, file?: File, ip?: string | null, headers?: Record | null) => Promise; + public exec: (params: any, user: T['requireCredential'] extends true ? LocalUser : LocalUser | null, token: AccessToken | null, file?: File, ip?: string | null, headers?: Record | null) => Promise; constructor(meta: T, paramDef: Ps, cb: executor) { const validate = ajv.compile(paramDef); - this.exec = (params: any, user: T['requireCredential'] extends true ? ILocalUser : ILocalUser | null, token: AccessToken | null, file?: File, ip?: string | null, headers?: Record | null) => { + this.exec = (params: any, user: T['requireCredential'] extends true ? LocalUser : LocalUser | null, token: AccessToken | null, file?: File, ip?: string | null, headers?: Record | null) => { let cleanup: undefined | (() => void) = undefined; if (meta.requireFile) { diff --git a/packages/backend/src/server/api/endpoints/ap/show.ts b/packages/backend/src/server/api/endpoints/ap/show.ts index e758c5e3fa..61e05531e6 100644 --- a/packages/backend/src/server/api/endpoints/ap/show.ts +++ b/packages/backend/src/server/api/endpoints/ap/show.ts @@ -3,7 +3,7 @@ import ms from 'ms'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { UsersRepository, NotesRepository } from '@/models/index.js'; import type { Note } from '@/models/entities/Note.js'; -import type { ILocalUser, User } from '@/models/entities/User.js'; +import type { LocalUser, User } from '@/models/entities/User.js'; import { isActor, isPost, getApId } from '@/core/activitypub/type.js'; import type { SchemaType } from '@/misc/schema.js'; import { ApResolverService } from '@/core/activitypub/ApResolverService.js'; @@ -114,7 +114,7 @@ export default class extends Endpoint { * URIからUserかNoteを解決する */ @bindThis - private async fetchAny(uri: string, me: ILocalUser | null | undefined): Promise | null> { + private async fetchAny(uri: string, me: LocalUser | null | undefined): Promise | null> { // ブロックしてたら中断 const fetchedMeta = await this.metaService.fetch(); if (this.utilityService.isBlockedHost(fetchedMeta.blockedHosts, this.utilityService.extractDbHost(uri))) return null; @@ -147,7 +147,7 @@ export default class extends Endpoint { } @bindThis - private async mergePack(me: ILocalUser | null | undefined, user: User | null | undefined, note: Note | null | undefined): Promise | null> { + private async mergePack(me: LocalUser | null | undefined, user: User | null | undefined, note: Note | null | undefined): Promise | null> { if (user != null) { return { type: 'User', diff --git a/packages/backend/src/server/api/endpoints/notes/polls/vote.ts b/packages/backend/src/server/api/endpoints/notes/polls/vote.ts index d8e1a1149f..f734e4e778 100644 --- a/packages/backend/src/server/api/endpoints/notes/polls/vote.ts +++ b/packages/backend/src/server/api/endpoints/notes/polls/vote.ts @@ -1,7 +1,7 @@ import { Not } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; import type { UsersRepository, PollsRepository, PollVotesRepository } from '@/models/index.js'; -import type { IRemoteUser } from '@/models/entities/User.js'; +import type { RemoteUser } from '@/models/entities/User.js'; import { IdService } from '@/core/IdService.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { GetterService } from '@/server/api/GetterService.js'; @@ -160,7 +160,7 @@ export default class extends Endpoint { // リモート投票の場合リプライ送信 if (note.userHost != null) { - const pollOwner = await this.usersRepository.findOneByOrFail({ id: note.userId }) as IRemoteUser; + const pollOwner = await this.usersRepository.findOneByOrFail({ id: note.userId }) as RemoteUser; this.queueService.deliver(me, this.apRendererService.addContext(await this.apRendererService.renderVote(me, vote, note, poll, pollOwner)), pollOwner.inbox); } diff --git a/packages/backend/src/server/api/stream/channels/messaging.ts b/packages/backend/src/server/api/stream/channels/messaging.ts index 92af6b591c..b544e297c5 100644 --- a/packages/backend/src/server/api/stream/channels/messaging.ts +++ b/packages/backend/src/server/api/stream/channels/messaging.ts @@ -1,6 +1,6 @@ import { Inject, Injectable } from '@nestjs/common'; import type { UserGroupJoiningsRepository, UsersRepository, MessagingMessagesRepository } from '@/models/index.js'; -import type { User, ILocalUser, IRemoteUser } from '@/models/entities/User.js'; +import type { User, LocalUser, RemoteUser } from '@/models/entities/User.js'; import type { UserGroup } from '@/models/entities/UserGroup.js'; import { MessagingService } from '@/core/MessagingService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; @@ -89,7 +89,7 @@ class MessagingChannel extends Channel { // リモートユーザーからのメッセージだったら既読配信 if (this.userEntityService.isLocalUser(this.user!) && this.userEntityService.isRemoteUser(this.otherparty!)) { this.messagingMessagesRepository.findOneBy({ id: body.id }).then(message => { - if (message) this.messagingService.deliverReadActivity(this.user as ILocalUser, this.otherparty as IRemoteUser, message); + if (message) this.messagingService.deliverReadActivity(this.user as LocalUser, this.otherparty as RemoteUser, message); }); } } else if (this.groupId) { From e8d4f3eac35f39f664379b7c8b0a3c9db2f3a7ac Mon Sep 17 00:00:00 2001 From: syuilo Date: Mon, 13 Feb 2023 16:19:29 +0900 Subject: [PATCH 074/294] refactor: fix types --- packages/backend/src/core/activitypub/ApRendererService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/core/activitypub/ApRendererService.ts b/packages/backend/src/core/activitypub/ApRendererService.ts index 308393f9fb..92bc1869e5 100644 --- a/packages/backend/src/core/activitypub/ApRendererService.ts +++ b/packages/backend/src/core/activitypub/ApRendererService.ts @@ -181,7 +181,7 @@ export class ApRendererService { // to anonymise reporters, the reporting actor must be a system user // object has to be a uri or array of uris @bindThis - public renderFlag(user: LocalUser, object: IObject, content: string): IFlag { + public renderFlag(user: LocalUser, object: IObject | string | string[], content: string): IFlag { return { type: 'Flag', actor: `${this.config.url}/users/${user.id}`, From 1c8419cea00ffea7e28161429f81873b26944c40 Mon Sep 17 00:00:00 2001 From: "Kohei Ota (inductor)" Date: Tue, 14 Feb 2023 09:59:50 +0900 Subject: [PATCH 075/294] Update Docker GHA (#9920) * Update Docker GHA * add id --- .github/workflows/docker-develop.yml | 8 +++++++- .github/workflows/docker.yml | 12 +++++++++++- Dockerfile | 14 ++++++++------ 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/.github/workflows/docker-develop.yml b/.github/workflows/docker-develop.yml index a999dc51e6..09a2c33e0c 100644 --- a/.github/workflows/docker-develop.yml +++ b/.github/workflows/docker-develop.yml @@ -15,7 +15,10 @@ jobs: - name: Check out the repo uses: actions/checkout@v3.3.0 - name: Set up Docker Buildx + id: buildx uses: docker/setup-buildx-action@v2.3.0 + with: + platforms: linux/amd64,linux/arm64 - name: Docker meta id: meta uses: docker/metadata-action@v4 @@ -27,10 +30,13 @@ jobs: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Build and Push to Docker Hub - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v4 with: + builder: ${{ steps.buildx.outputs.name }} context: . push: true + platforms: ${{ steps.buildx.outputs.platforms }} + provenance: false tags: misskey/misskey:develop labels: develop cache-from: type=gha diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index d7803ce3ec..a465d92eaf 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -13,6 +13,11 @@ jobs: steps: - name: Check out the repo uses: actions/checkout@v3.3.0 + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v2.3.0 + with: + platforms: linux/amd64,linux/arm64 - name: Docker meta id: meta uses: docker/metadata-action@v4 @@ -31,9 +36,14 @@ jobs: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Build and Push to Docker Hub - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v4 with: + builder: ${{ steps.buildx.outputs.name }} context: . push: true + platforms: ${{ steps.buildx.outputs.platforms }} + provenance: false tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/Dockerfile b/Dockerfile index 0bfd24bd9a..b439716bea 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,5 @@ +# syntax = docker/dockerfile:1.4 + ARG NODE_VERSION=18.13.0-bullseye FROM node:${NODE_VERSION} AS builder @@ -14,16 +16,16 @@ RUN corepack enable WORKDIR /misskey -COPY ["pnpm-lock.yaml", "pnpm-workspace.yaml", "package.json", "./"] -COPY ["scripts", "./scripts"] -COPY ["packages/backend/package.json", "./packages/backend/"] -COPY ["packages/frontend/package.json", "./packages/frontend/"] -COPY ["packages/sw/package.json", "./packages/sw/"] +COPY --link ["pnpm-lock.yaml", "pnpm-workspace.yaml", "package.json", "./"] +COPY --link ["scripts", "./scripts"] +COPY --link ["packages/backend/package.json", "./packages/backend/"] +COPY --link ["packages/frontend/package.json", "./packages/frontend/"] +COPY --link ["packages/sw/package.json", "./packages/sw/"] RUN --mount=type=cache,target=/root/.local/share/pnpm/store,sharing=locked \ pnpm i --frozen-lockfile --aggregate-output -COPY . ./ +COPY --link . ./ ARG NODE_ENV=production From 55d4d3418e8f1967a79f027f69849c6295a6864f Mon Sep 17 00:00:00 2001 From: tamaina Date: Tue, 14 Feb 2023 04:08:56 +0000 Subject: [PATCH 076/294] =?UTF-8?q?fix(server):=20HttpRequestService.send?= =?UTF-8?q?=E3=81=A7=E3=81=AF=E5=B8=B8=E3=81=ABUser-Agent=E3=82=92?= =?UTF-8?q?=E5=90=AB=E3=82=80=E3=82=88=E3=81=86=E3=81=AB=20Fix=20#9817=20(?= =?UTF-8?q?maybe)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/backend/src/core/HttpRequestService.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/backend/src/core/HttpRequestService.ts b/packages/backend/src/core/HttpRequestService.ts index e32026b04f..375aa846cb 100644 --- a/packages/backend/src/core/HttpRequestService.ts +++ b/packages/backend/src/core/HttpRequestService.ts @@ -99,7 +99,6 @@ export class HttpRequestService { const res = await this.send(url, { method: 'GET', headers: Object.assign({ - 'User-Agent': this.config.userAgent, Accept: accept, }, headers ?? {}), timeout: 5000, @@ -114,7 +113,6 @@ export class HttpRequestService { const res = await this.send(url, { method: 'GET', headers: Object.assign({ - 'User-Agent': this.config.userAgent, Accept: accept, }, headers ?? {}), timeout: 5000, @@ -144,7 +142,10 @@ export class HttpRequestService { const res = await fetch(url, { method: args.method ?? 'GET', - headers: args.headers, + headers: { + 'User-Agent': this.config.userAgent, + ...(args.headers ?? {}) + }, body: args.body, size: args.size ?? 10 * 1024 * 1024, agent: (url) => this.getAgentByUrl(url), From 7436a58ea17edf8758c29dfa9876816354ec6b1a Mon Sep 17 00:00:00 2001 From: Neko7sora <75793267+Neko7sora@users.noreply.github.com> Date: Tue, 14 Feb 2023 13:13:34 +0900 Subject: [PATCH 077/294] =?UTF-8?q?=E6=94=B9=E8=A1=8C=E3=82=B3=E3=83=BC?= =?UTF-8?q?=E3=83=89=E3=82=92LF=E3=81=AB=E7=B5=B1=E4=B8=80=20(#9926)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: update gitattribute editorconfig * Normalize all the line endings --- .editorconfig | 1 + .gitattributes | 1 + .github/workflows/check_copyright_year.yml | 36 ++--- .github/workflows/lint.yml | 108 ++++++------- .../server/api/endpoints/clips/remove-note.ts | 144 +++++++++--------- packages/frontend/assets/label-red.svg | 12 +- packages/frontend/assets/label.svg | 12 +- packages/frontend/assets/unread.svg | 14 +- 8 files changed, 165 insertions(+), 163 deletions(-) diff --git a/.editorconfig b/.editorconfig index edccf3a9d5..6db1367645 100644 --- a/.editorconfig +++ b/.editorconfig @@ -5,6 +5,7 @@ indent_style = tab indent_size = 2 charset = utf-8 insert_final_newline = true +end_of_line = lf [*.yml] indent_style = space diff --git a/.gitattributes b/.gitattributes index a175917f31..246ecb0a60 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5,3 +5,4 @@ *.glb -diff -text *.blend -diff -text *.afdesign -diff -text +* text=auto eol=lf diff --git a/.github/workflows/check_copyright_year.yml b/.github/workflows/check_copyright_year.yml index 99799672f2..8daea44a83 100644 --- a/.github/workflows/check_copyright_year.yml +++ b/.github/workflows/check_copyright_year.yml @@ -1,18 +1,18 @@ -name: Check copyright year - -on: - push: - branches: - - master - - develop - -jobs: - check_copyright_year: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3.2.0 - - run: | - if [ "$(grep Copyright COPYING | sed -e 's/.*2014-\([0-9]*\) .*/\1/g')" -ne "$(date +%Y)" ]; then - echo "Please change copyright year!" - exit 1 - fi +name: Check copyright year + +on: + push: + branches: + - master + - develop + +jobs: + check_copyright_year: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3.2.0 + - run: | + if [ "$(grep Copyright COPYING | sed -e 's/.*2014-\([0-9]*\) .*/\1/g')" -ne "$(date +%Y)" ]; then + echo "Please change copyright year!" + exit 1 + fi diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index b88b97ab0c..6a579bffc8 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,54 +1,54 @@ -name: Lint - -on: - push: - branches: - - master - - develop - pull_request: - -jobs: - pnpm_install: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3.3.0 - with: - fetch-depth: 0 - submodules: true - - uses: pnpm/action-setup@v2 - with: - version: 7 - run_install: false - - uses: actions/setup-node@v3.6.0 - with: - node-version: 18.x - cache: 'pnpm' - - run: corepack enable - - run: pnpm i --frozen-lockfile - - lint: - needs: [pnpm_install] - runs-on: ubuntu-latest - continue-on-error: true - strategy: - matrix: - workspace: - - backend - - frontend - - sw - steps: - - uses: actions/checkout@v3.3.0 - with: - fetch-depth: 0 - submodules: true - - uses: pnpm/action-setup@v2 - with: - version: 7 - run_install: false - - uses: actions/setup-node@v3.6.0 - with: - node-version: 18.x - cache: 'pnpm' - - run: corepack enable - - run: pnpm i --frozen-lockfile - - run: pnpm --filter ${{ matrix.workspace }} run lint +name: Lint + +on: + push: + branches: + - master + - develop + pull_request: + +jobs: + pnpm_install: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3.3.0 + with: + fetch-depth: 0 + submodules: true + - uses: pnpm/action-setup@v2 + with: + version: 7 + run_install: false + - uses: actions/setup-node@v3.6.0 + with: + node-version: 18.x + cache: 'pnpm' + - run: corepack enable + - run: pnpm i --frozen-lockfile + + lint: + needs: [pnpm_install] + runs-on: ubuntu-latest + continue-on-error: true + strategy: + matrix: + workspace: + - backend + - frontend + - sw + steps: + - uses: actions/checkout@v3.3.0 + with: + fetch-depth: 0 + submodules: true + - uses: pnpm/action-setup@v2 + with: + version: 7 + run_install: false + - uses: actions/setup-node@v3.6.0 + with: + node-version: 18.x + cache: 'pnpm' + - run: corepack enable + - run: pnpm i --frozen-lockfile + - run: pnpm --filter ${{ matrix.workspace }} run lint diff --git a/packages/backend/src/server/api/endpoints/clips/remove-note.ts b/packages/backend/src/server/api/endpoints/clips/remove-note.ts index 55778c7ecb..5d88870ed2 100644 --- a/packages/backend/src/server/api/endpoints/clips/remove-note.ts +++ b/packages/backend/src/server/api/endpoints/clips/remove-note.ts @@ -1,72 +1,72 @@ -import { Inject, Injectable } from '@nestjs/common'; -import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { ClipNotesRepository, ClipsRepository } from '@/models/index.js'; -import { DI } from '@/di-symbols.js'; -import { ApiError } from '../../error.js'; -import { GetterService } from '@/server/api/GetterService.js'; - -export const meta = { - tags: ['account', 'notes', 'clips'], - - requireCredential: true, - - kind: 'write:account', - - errors: { - noSuchClip: { - message: 'No such clip.', - code: 'NO_SUCH_CLIP', - id: 'b80525c6-97f7-49d7-a42d-ebccd49cfd52', - }, - - noSuchNote: { - message: 'No such note.', - code: 'NO_SUCH_NOTE', - id: 'aff017de-190e-434b-893e-33a9ff5049d8', - }, - }, -} as const; - -export const paramDef = { - type: 'object', - properties: { - clipId: { type: 'string', format: 'misskey:id' }, - noteId: { type: 'string', format: 'misskey:id' }, - }, - required: ['clipId', 'noteId'], -} as const; - -// eslint-disable-next-line import/no-default-export -@Injectable() -export default class extends Endpoint { - constructor( - @Inject(DI.clipsRepository) - private clipsRepository: ClipsRepository, - - @Inject(DI.clipNotesRepository) - private clipNotesRepository: ClipNotesRepository, - - private getterService: GetterService, - ) { - super(meta, paramDef, async (ps, me) => { - const clip = await this.clipsRepository.findOneBy({ - id: ps.clipId, - userId: me.id, - }); - - if (clip == null) { - throw new ApiError(meta.errors.noSuchClip); - } - - const note = await this.getterService.getNote(ps.noteId).catch(err => { - if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); - throw err; - }); - - await this.clipNotesRepository.delete({ - noteId: note.id, - clipId: clip.id, - }); - }); - } -} +import { Inject, Injectable } from '@nestjs/common'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import type { ClipNotesRepository, ClipsRepository } from '@/models/index.js'; +import { DI } from '@/di-symbols.js'; +import { ApiError } from '../../error.js'; +import { GetterService } from '@/server/api/GetterService.js'; + +export const meta = { + tags: ['account', 'notes', 'clips'], + + requireCredential: true, + + kind: 'write:account', + + errors: { + noSuchClip: { + message: 'No such clip.', + code: 'NO_SUCH_CLIP', + id: 'b80525c6-97f7-49d7-a42d-ebccd49cfd52', + }, + + noSuchNote: { + message: 'No such note.', + code: 'NO_SUCH_NOTE', + id: 'aff017de-190e-434b-893e-33a9ff5049d8', + }, + }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + clipId: { type: 'string', format: 'misskey:id' }, + noteId: { type: 'string', format: 'misskey:id' }, + }, + required: ['clipId', 'noteId'], +} as const; + +// eslint-disable-next-line import/no-default-export +@Injectable() +export default class extends Endpoint { + constructor( + @Inject(DI.clipsRepository) + private clipsRepository: ClipsRepository, + + @Inject(DI.clipNotesRepository) + private clipNotesRepository: ClipNotesRepository, + + private getterService: GetterService, + ) { + super(meta, paramDef, async (ps, me) => { + const clip = await this.clipsRepository.findOneBy({ + id: ps.clipId, + userId: me.id, + }); + + if (clip == null) { + throw new ApiError(meta.errors.noSuchClip); + } + + const note = await this.getterService.getNote(ps.noteId).catch(err => { + if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); + throw err; + }); + + await this.clipNotesRepository.delete({ + noteId: note.id, + clipId: clip.id, + }); + }); + } +} diff --git a/packages/frontend/assets/label-red.svg b/packages/frontend/assets/label-red.svg index 45996aa9ce..c89d3f5f3a 100644 --- a/packages/frontend/assets/label-red.svg +++ b/packages/frontend/assets/label-red.svg @@ -1,6 +1,6 @@ - - - - - + + + + + diff --git a/packages/frontend/assets/label.svg b/packages/frontend/assets/label.svg index b1f85f3c07..997335f505 100644 --- a/packages/frontend/assets/label.svg +++ b/packages/frontend/assets/label.svg @@ -1,6 +1,6 @@ - - - - - + + + + + diff --git a/packages/frontend/assets/unread.svg b/packages/frontend/assets/unread.svg index 8c3cc9f475..8bd4156e51 100644 --- a/packages/frontend/assets/unread.svg +++ b/packages/frontend/assets/unread.svg @@ -1,7 +1,7 @@ - - - - - - + + + + + + From 5cf5b666965067b44f58eeb946b05fc153d8e35d Mon Sep 17 00:00:00 2001 From: taiy <53635909+taiyme@users.noreply.github.com> Date: Tue, 14 Feb 2023 13:17:00 +0900 Subject: [PATCH 078/294] fix(client): use tabler icons (#9915) --- packages/frontend/src/components/MkNote.vue | 2 +- .../frontend/src/pages/antenna-timeline.vue | 2 +- packages/frontend/src/pages/explore.users.vue | 12 ++-- .../page-editor/els/page-editor.el.image.vue | 4 +- .../page-editor/els/page-editor.el.text.vue | 2 +- .../frontend/src/pages/settings/drive.vue | 2 +- .../frontend/src/pages/settings/sounds.vue | 2 +- .../frontend/src/pages/user-list-timeline.vue | 2 +- .../frontend/src/scripts/get-note-menu.ts | 2 +- packages/frontend/src/scripts/hpml/index.ts | 12 ++-- packages/frontend/src/scripts/hpml/lib.ts | 56 +++++++++---------- packages/frontend/src/scripts/search.ts | 2 +- packages/frontend/src/ui/classic.vue | 2 +- .../src/widgets/server-metric/mem.vue | 2 +- 14 files changed, 52 insertions(+), 52 deletions(-) diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue index c9c512c36e..dd2c358f10 100644 --- a/packages/frontend/src/components/MkNote.vue +++ b/packages/frontend/src/components/MkNote.vue @@ -9,7 +9,7 @@ >
{{ i18n.ts.pinnedNote }}
- +
diff --git a/packages/frontend/src/pages/antenna-timeline.vue b/packages/frontend/src/pages/antenna-timeline.vue index ff31c3ab2c..5f0168ee3c 100644 --- a/packages/frontend/src/pages/antenna-timeline.vue +++ b/packages/frontend/src/pages/antenna-timeline.vue @@ -72,7 +72,7 @@ watch(() => props.antennaId, async () => { }, { immediate: true }); const headerActions = $computed(() => antenna ? [{ - icon: 'fas fa-calendar-alt', + icon: 'ti ti-calendar-time', text: i18n.ts.jumpToSpecifiedDate, handler: timetravel, }, { diff --git a/packages/frontend/src/pages/explore.users.vue b/packages/frontend/src/pages/explore.users.vue index 3a74e8518d..8defc35b70 100644 --- a/packages/frontend/src/pages/explore.users.vue +++ b/packages/frontend/src/pages/explore.users.vue @@ -7,15 +7,15 @@
diff --git a/packages/frontend/src/components/MkReactionsViewer.vue b/packages/frontend/src/components/MkReactionsViewer.vue index cdd6f528e7..76faffe926 100644 --- a/packages/frontend/src/components/MkReactionsViewer.vue +++ b/packages/frontend/src/components/MkReactionsViewer.vue @@ -51,7 +51,7 @@ watch([() => props.note.reactions, () => props.maxNumber], ([newSource, maxNumbe ...Object.entries(newSource) .sort(([, a], [, b]) => b - a) .filter(([y], i) => i < maxNumber && !newReactionsNames.includes(y)), - ] + ]; newReactions = newReactions.slice(0, props.maxNumber); diff --git a/packages/frontend/src/components/global/MkPageHeader.tabs.vue b/packages/frontend/src/components/global/MkPageHeader.tabs.vue index d650122cf6..b181b62986 100644 --- a/packages/frontend/src/components/global/MkPageHeader.tabs.vue +++ b/packages/frontend/src/components/global/MkPageHeader.tabs.vue @@ -8,8 +8,8 @@
{{ t.title }}
- +
{{ t.title }}
diff --git a/packages/frontend/src/components/global/MkPageHeader.vue b/packages/frontend/src/components/global/MkPageHeader.vue index 803efb1690..98233b02e0 100644 --- a/packages/frontend/src/components/global/MkPageHeader.vue +++ b/packages/frontend/src/components/global/MkPageHeader.vue @@ -19,7 +19,7 @@
- +
@@ -40,7 +40,7 @@ import { scrollToTop } from '@/scripts/scroll'; import { globalEvents } from '@/events'; import { injectPageMetadata } from '@/scripts/page-metadata'; import { $i, openAccountMenu as openAccountMenu_ } from '@/account'; -import XTabs, { Tab } from './MkPageHeader.tabs.vue' +import XTabs, { Tab } from './MkPageHeader.tabs.vue'; const props = withDefaults(defineProps<{ tabs?: Tab[]; diff --git a/packages/frontend/src/ui/classic.vue b/packages/frontend/src/ui/classic.vue index d8b800b873..92997ffb66 100644 --- a/packages/frontend/src/ui/classic.vue +++ b/packages/frontend/src/ui/classic.vue @@ -124,7 +124,7 @@ function onAiClick(ev) { } if (window.innerWidth < 1024) { - const currentUI = miLocalStorage.getItem('ui') + const currentUI = miLocalStorage.getItem('ui'); miLocalStorage.setItem('ui_temp', currentUI || 'default'); miLocalStorage.setItem('ui', 'default'); location.reload(); From 8f9ce23e521d15ff1d7796d637d5bd64d9ee4375 Mon Sep 17 00:00:00 2001 From: Kagami Sascha Rosylight Date: Fri, 17 Feb 2023 02:56:59 +0100 Subject: [PATCH 094/294] style(backend): fix all eslint errors (#9967) --- packages/backend/src/core/ImageProcessingService.ts | 2 +- packages/backend/src/core/PushNotificationService.ts | 1 - packages/backend/src/core/VideoProcessingService.ts | 2 +- packages/backend/src/core/entities/EmojiEntityService.ts | 2 +- packages/backend/src/server/FileServerService.ts | 6 +++--- packages/backend/src/server/api/endpoints/admin/ad/list.ts | 2 +- .../backend/src/server/api/endpoints/admin/emoji/delete.ts | 2 +- .../backend/src/server/api/endpoints/admin/emoji/update.ts | 4 ++-- packages/backend/src/server/api/endpoints/notes/create.ts | 2 +- 9 files changed, 11 insertions(+), 12 deletions(-) diff --git a/packages/backend/src/core/ImageProcessingService.ts b/packages/backend/src/core/ImageProcessingService.ts index fbc02f504b..7c88f5e9a0 100644 --- a/packages/backend/src/core/ImageProcessingService.ts +++ b/packages/backend/src/core/ImageProcessingService.ts @@ -107,7 +107,7 @@ export class ImageProcessingService { withoutEnlargement: true, }) .rotate() - .webp(options) + .webp(options); return { data, diff --git a/packages/backend/src/core/PushNotificationService.ts b/packages/backend/src/core/PushNotificationService.ts index aff233a3e4..75bf4b0e01 100644 --- a/packages/backend/src/core/PushNotificationService.ts +++ b/packages/backend/src/core/PushNotificationService.ts @@ -40,7 +40,6 @@ function truncateBody(type: T, body: pus }, } : {}), }; - } @Injectable() diff --git a/packages/backend/src/core/VideoProcessingService.ts b/packages/backend/src/core/VideoProcessingService.ts index dd6c51c217..eccfeb0e7d 100644 --- a/packages/backend/src/core/VideoProcessingService.ts +++ b/packages/backend/src/core/VideoProcessingService.ts @@ -53,7 +53,7 @@ export class VideoProcessingService { thumbnail: '1', url, }) - ) + ); } } diff --git a/packages/backend/src/core/entities/EmojiEntityService.ts b/packages/backend/src/core/entities/EmojiEntityService.ts index cf5637a670..f4a01ab032 100644 --- a/packages/backend/src/core/entities/EmojiEntityService.ts +++ b/packages/backend/src/core/entities/EmojiEntityService.ts @@ -22,7 +22,7 @@ export class EmojiEntityService { src: Emoji['id'] | Emoji, opts: { omitHost?: boolean; omitId?: boolean; withUrl?: boolean; } = { omitHost: true, omitId: true, withUrl: true }, ): Promise> { - opts = { omitHost: true, omitId: true, withUrl: true, ...opts } + opts = { omitHost: true, omitId: true, withUrl: true, ...opts }; const emoji = typeof src === 'object' ? src : await this.emojisRepository.findOneByOrFail({ id: src }); diff --git a/packages/backend/src/server/FileServerService.ts b/packages/backend/src/server/FileServerService.ts index f4bc568fdc..c12ae9b824 100644 --- a/packages/backend/src/server/FileServerService.ts +++ b/packages/backend/src/server/FileServerService.ts @@ -395,7 +395,7 @@ export class FileServerService { state: 'remote', mime, ext, path, cleanup, - } + }; } catch (e) { cleanup(); throw e; @@ -429,7 +429,7 @@ export class FileServerService { url: file.uri, fileRole: isThumbnail ? 'thumbnail' : isWebpublic ? 'webpublic' : 'original', file, - } + }; } const path = this.internalStorageService.resolvePath(key); @@ -452,6 +452,6 @@ export class FileServerService { mime: file.type, ext: null, path, - } + }; } } diff --git a/packages/backend/src/server/api/endpoints/admin/ad/list.ts b/packages/backend/src/server/api/endpoints/admin/ad/list.ts index 905036c40f..0b6d006052 100644 --- a/packages/backend/src/server/api/endpoints/admin/ad/list.ts +++ b/packages/backend/src/server/api/endpoints/admin/ad/list.ts @@ -31,7 +31,7 @@ export default class extends Endpoint { private queryService: QueryService, ) { super(meta, paramDef, async (ps, me) => { - const query = this.queryService.makePaginationQuery(this.adsRepository.createQueryBuilder('ad'), ps.sinceId, ps.untilId) + const query = this.queryService.makePaginationQuery(this.adsRepository.createQueryBuilder('ad'), ps.sinceId, ps.untilId); const ads = await query.take(ps.limit).getMany(); return ads; diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts b/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts index c1a60a2773..c51e7fd1a8 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts @@ -57,7 +57,7 @@ export default class extends Endpoint { await this.db.queryResultCache!.remove(['meta_emojis']); this.globalEventService.publishBroadcastStream('emojiDeleted', { - emojis: [ await this.emojiEntityService.pack(emoji) ], + emojis: [await this.emojiEntityService.pack(emoji)], }); this.moderationLogService.insertModerationLog(me, 'deleteEmoji', { diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts index 22bedc7100..af610ddf9c 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts @@ -72,11 +72,11 @@ export default class extends Endpoint { if (emoji.name === ps.name) { this.globalEventService.publishBroadcastStream('emojiUpdated', { - emojis: [ updated ], + emojis: [updated], }); } else { this.globalEventService.publishBroadcastStream('emojiDeleted', { - emojis: [ await this.emojiEntityService.pack(emoji) ], + emojis: [await this.emojiEntityService.pack(emoji)], }); this.globalEventService.publishBroadcastStream('emojiAdded', { diff --git a/packages/backend/src/server/api/endpoints/notes/create.ts b/packages/backend/src/server/api/endpoints/notes/create.ts index 700921cd92..593444968e 100644 --- a/packages/backend/src/server/api/endpoints/notes/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/create.ts @@ -280,7 +280,7 @@ export default class extends Endpoint { files: files, poll: ps.poll ? { choices: ps.poll.choices, - multiple: ps.poll.multiple || false, + multiple: ps.poll.multiple ?? false, expiresAt: ps.poll.expiresAt ? new Date(ps.poll.expiresAt) : null, } : undefined, text: ps.text ?? undefined, From dd52be3a01fca4831cccb82d7fe1585cfbfd01cf Mon Sep 17 00:00:00 2001 From: Kagami Sascha Rosylight Date: Fri, 17 Feb 2023 02:57:40 +0100 Subject: [PATCH 095/294] ci: run typecheck and eslint separately (#9966) * ci: run typecheck and eslint separately * fix syntax --- .github/workflows/lint.yml | 5 ++++- packages/backend/package.json | 4 +++- packages/frontend/package.json | 4 +++- packages/sw/package.json | 4 +++- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 6a579bffc8..94d7d1371c 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -36,6 +36,9 @@ jobs: - backend - frontend - sw + lint: + - typecheck + - eslint steps: - uses: actions/checkout@v3.3.0 with: @@ -51,4 +54,4 @@ jobs: cache: 'pnpm' - run: corepack enable - run: pnpm i --frozen-lockfile - - run: pnpm --filter ${{ matrix.workspace }} run lint + - run: pnpm --filter ${{ matrix.workspace }} run ${{ matrix.lint }} diff --git a/packages/backend/package.json b/packages/backend/package.json index 90acaac754..52b0d74ad0 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -11,7 +11,9 @@ "watch:swc": "swc src -d built -D -w", "build": "tsc -p tsconfig.json || echo done. && tsc-alias -p tsconfig.json", "watch": "node watch.mjs", - "lint": "tsc --noEmit && eslint --quiet \"src/**/*.ts\"", + "typecheck": "tsc --noEmit", + "eslint": "eslint --quiet \"src/**/*.ts\"", + "lint": "pnpm typecheck && pnpm eslint", "jest": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --forceExit --runInBand", "jest-and-coverage": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --coverage --forceExit --runInBand", "jest-clear": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --clearCache", diff --git a/packages/frontend/package.json b/packages/frontend/package.json index bf22f7aaad..61c0135ba3 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -4,7 +4,9 @@ "scripts": { "watch": "vite", "build": "vite build", - "lint": "vue-tsc --noEmit && eslint --quiet \"src/**/*.{ts,vue}\"" + "typecheck": "vue-tsc --noEmit", + "eslint": "eslint --quiet \"src/**/*.{ts,vue}\"", + "lint": "pnpm typecheck && pnpm eslint" }, "dependencies": { "@discordapp/twemoji": "14.0.2", diff --git a/packages/sw/package.json b/packages/sw/package.json index 8650f9597b..4de260fcfc 100644 --- a/packages/sw/package.json +++ b/packages/sw/package.json @@ -4,7 +4,9 @@ "scripts": { "watch": "node build.js watch", "build": "node build.js", - "lint": "tsc --noEmit && eslint --quiet src/**/*.ts" + "typecheck": "tsc --noEmit", + "eslint": "eslint --quiet src/**/*.ts", + "lint": "pnpm typecheck && pnpm eslint" }, "dependencies": { "esbuild": "0.14.42", From e8c5307f669e0ff45b71e65384a182237a7a9ccd Mon Sep 17 00:00:00 2001 From: tamaina Date: Fri, 17 Feb 2023 12:38:30 +0900 Subject: [PATCH 096/294] =?UTF-8?q?perf(client):=20=E3=82=A6=E3=82=A7?= =?UTF-8?q?=E3=83=AB=E3=82=AB=E3=83=A0=E3=83=9A=E3=83=BC=E3=82=B8=E3=82=92?= =?UTF-8?q?=E6=9C=80=E9=81=A9=E5=8C=96=20(#9960)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * perf(client): ウェルカムページの最適化 * remove max --- .../api/endpoints/federation/instances.ts | 2 + .../server/api/endpoints/notes/featured.ts | 5 +- .../frontend/src/pages/welcome.entrance.a.vue | 30 ++--- .../frontend/src/pages/welcome.timeline.vue | 104 ++++++++---------- 4 files changed, 60 insertions(+), 81 deletions(-) diff --git a/packages/backend/src/server/api/endpoints/federation/instances.ts b/packages/backend/src/server/api/endpoints/federation/instances.ts index e5d1df0018..60b24e9585 100644 --- a/packages/backend/src/server/api/endpoints/federation/instances.ts +++ b/packages/backend/src/server/api/endpoints/federation/instances.ts @@ -10,6 +10,8 @@ export const meta = { tags: ['federation'], requireCredential: false, + allowGet: true, + cacheSec: 3600, res: { type: 'array', diff --git a/packages/backend/src/server/api/endpoints/notes/featured.ts b/packages/backend/src/server/api/endpoints/notes/featured.ts index 76834cfde9..8eff8fdb22 100644 --- a/packages/backend/src/server/api/endpoints/notes/featured.ts +++ b/packages/backend/src/server/api/endpoints/notes/featured.ts @@ -9,6 +9,8 @@ export const meta = { tags: ['notes'], requireCredential: false, + allowGet: true, + cacheSec: 3600, res: { type: 'array', @@ -41,7 +43,6 @@ export default class extends Endpoint { private queryService: QueryService, ) { super(meta, paramDef, async (ps, me) => { - const max = 30; const day = 1000 * 60 * 60 * 24 * 3; // 3日前まで const query = this.notesRepository.createQueryBuilder('note') @@ -67,7 +68,7 @@ export default class extends Endpoint { let notes = await query .orderBy('note.score', 'DESC') - .take(max) + .take(ps.limit) .getMany(); notes.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()); diff --git a/packages/frontend/src/pages/welcome.entrance.a.vue b/packages/frontend/src/pages/welcome.entrance.a.vue index f438603199..05c55fdf31 100644 --- a/packages/frontend/src/pages/welcome.entrance.a.vue +++ b/packages/frontend/src/pages/welcome.entrance.a.vue @@ -32,7 +32,7 @@
-
+
@@ -56,33 +56,16 @@ import MkFeaturedPhotos from '@/components/MkFeaturedPhotos.vue'; import { instanceName } from '@/config'; import * as os from '@/os'; import { i18n } from '@/i18n'; +import { Instance } from 'misskey-js/built/entities'; -let meta = $ref(); -let stats = $ref(); -let tags = $ref(); -let onlineUsersCount = $ref(); -let instances = $ref(); +let meta = $ref(); +let instances = $ref(); os.api('meta', { detail: true }).then(_meta => { meta = _meta; }); -os.api('stats').then(_stats => { - stats = _stats; -}); - -os.api('get-online-users-count').then(res => { - onlineUsersCount = res.count; -}); - -os.api('hashtags/list', { - sort: '+mentionedLocalUsers', - limit: 8, -}).then(_tags => { - tags = _tags; -}); - -os.api('federation/instances', { +os.apiGet('federation/instances', { sort: '+pubSub', limit: 20, }).then(_instances => { @@ -147,8 +130,9 @@ function showMenu(ev) { bottom: 0; right: 64px; margin: auto; + padding: 128px 0; width: 500px; - height: calc(100% - 128px); + height: calc(100% - 256px); overflow: hidden; -webkit-mask-image: linear-gradient(0deg, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 128px, rgba(0,0,0,1) calc(100% - 128px), rgba(0,0,0,0) 100%); mask-image: linear-gradient(0deg, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 128px, rgba(0,0,0,1) calc(100% - 128px), rgba(0,0,0,0) 100%); diff --git a/packages/frontend/src/pages/welcome.timeline.vue b/packages/frontend/src/pages/welcome.timeline.vue index ed3c5a4af7..c34d43dc1c 100644 --- a/packages/frontend/src/pages/welcome.timeline.vue +++ b/packages/frontend/src/pages/welcome.timeline.vue @@ -1,62 +1,54 @@ - - From 14cff15c898fcead49de8e9688d166f2d7e567b5 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 17 Feb 2023 14:57:05 +0900 Subject: [PATCH 097/294] enhance(client): add quiz preset for play --- .../frontend/src/pages/flash/flash-edit.vue | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) diff --git a/packages/frontend/src/pages/flash/flash-edit.vue b/packages/frontend/src/pages/flash/flash-edit.vue index f8435c48f8..2b7fcf74e1 100644 --- a/packages/frontend/src/pages/flash/flash-edit.vue +++ b/packages/frontend/src/pages/flash/flash-edit.vue @@ -173,6 +173,119 @@ var cursor = 0 do() `; +const PRESET_QUIZ = `/// @ 0.12.4 +let title = '地理クイズ' + +let qas = [{ + q: 'オーストラリアの首都は?' + choices: ['シドニー' 'キャンベラ' 'メルボルン'] + a: 'キャンベラ' + aDescription: '最大の都市はシドニーですが首都はキャンベラです。' +} { + q: '国土面積2番目の国は?' + choices: ['カナダ' 'アメリカ' '中国'] + a: 'カナダ' + aDescription: '大きい順にロシア、カナダ、アメリカ、中国です。' +} { + q: '二重内陸国ではないのは?' + choices: ['リヒテンシュタイン' 'ウズベキスタン' 'レソト'] + a: 'レソト' + aDescription: 'レソトは(一重)内陸国です。' +} { + q: '閘門がない運河は?' + choices: ['キール運河' 'スエズ運河' 'パナマ運河'] + a: 'スエズ運河' + aDescription: 'スエズ運河は高低差がないので閘門はありません。' +}] + +let qaEls = [Ui:C:container({ + align: 'center' + children: [ + Ui:C:text({ + size: 1.5 + bold: true + text: title + }) + ] +})] + +var qn = 0 +each (let qa, qas) { + qn += 1 + qa.id = Util:uuid() + qaEls.push(Ui:C:container({ + align: 'center' + bgColor: '#000' + fgColor: '#fff' + padding: 16 + rounded: true + children: [ + Ui:C:text({ + text: \`Q{qn} {qa.q}\` + }) + Ui:C:select({ + items: qa.choices.map(@(c) {{ text: c, value: c }}) + onChange: @(v) { qa.userAnswer = v } + }) + Ui:C:container({ + children: [] + } \`{qa.id}:a\`) + ] + } qa.id)) +} + +@finish() { + var score = 0 + + each (let qa, qas) { + let correct = qa.userAnswer == qa.a + if (correct) score += 1 + let el = Ui:get(\`{qa.id}:a\`) + el.update({ + children: [ + Ui:C:text({ + size: 1.2 + bold: true + color: if (correct) '#f00' else '#00f' + text: if (correct) '🎉正解' else '不正解' + }) + Ui:C:text({ + text: qa.aDescription + }) + ] + }) + } + + let result = \`{title}の結果は{qas.len}問中{score}問正解でした。\` + Ui:get('footer').update({ + children: [ + Ui:C:postFormButton({ + text: '結果を共有' + rounded: true + primary: true + form: { + text: \`{result}{Str:lf}{THIS_URL}\` + } + }) + ] + }) +} + +qaEls.push(Ui:C:container({ + align: 'center' + children: [ + Ui:C:button({ + text: '答え合わせ' + primary: true + rounded: true + onClick: finish + }) + ] +} 'footer')) + +Ui:render(qaEls) +`; + const PRESET_TIMELINE = `/// @ 0.12.4 // APIリクエストを行いローカルタイムラインを表示するプリセット @@ -258,6 +371,11 @@ function selectPreset(ev: MouseEvent) { action: () => { script = PRESET_SHUFFLE; }, + }, { + text: 'Quiz', + action: () => { + script = PRESET_QUIZ; + }, }, { text: 'Timeline viewer', action: () => { From d4eb1def61ba1cf465fcaa528aaa600cac180f1d Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 17 Feb 2023 14:59:11 +0900 Subject: [PATCH 098/294] =?UTF-8?q?fix(client):=20MkHeader=E5=8F=8A?= =?UTF-8?q?=E3=81=B3=E3=83=87=E3=83=83=E3=82=AD=E3=81=AE=E3=82=AB=E3=83=A9?= =?UTF-8?q?=E3=83=A0=E3=81=A7=E3=83=81=E3=83=A3=E3=83=B3=E3=83=8D=E3=83=AB?= =?UTF-8?q?=E4=B8=80=E8=A6=A7=E3=82=92=E9=81=B8=E6=8A=9E=E3=81=97=E3=81=9F?= =?UTF-8?q?=E3=81=A8=E3=81=8D=E3=80=81=E6=9C=80=E5=A4=A75=E5=80=8B?= =?UTF-8?q?=E3=81=BE=E3=81=A7=E3=81=97=E3=81=8B=E8=A1=A8=E7=A4=BA=E3=81=95?= =?UTF-8?q?=E3=82=8C=E3=81=AA=E3=81=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix #9904 --- packages/frontend/src/pages/timeline.vue | 6 ++++-- packages/frontend/src/ui/deck/channel-column.vue | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/frontend/src/pages/timeline.vue b/packages/frontend/src/pages/timeline.vue index a071361150..f9ad609f56 100644 --- a/packages/frontend/src/pages/timeline.vue +++ b/packages/frontend/src/pages/timeline.vue @@ -23,6 +23,7 @@ + + diff --git a/packages/frontend/src/pages/settings/2fa.vue b/packages/frontend/src/pages/settings/2fa.vue index e6ef09668c..891934d706 100644 --- a/packages/frontend/src/pages/settings/2fa.vue +++ b/packages/frontend/src/pages/settings/2fa.vue @@ -1,216 +1,258 @@ diff --git a/packages/frontend/src/pages/settings/security.vue b/packages/frontend/src/pages/settings/security.vue index b09c4ffd2f..0cc2df09c5 100644 --- a/packages/frontend/src/pages/settings/security.vue +++ b/packages/frontend/src/pages/settings/security.vue @@ -5,11 +5,8 @@ {{ i18n.ts.changePassword }} - - - - - + + @@ -56,18 +53,21 @@ async function change() { const { canceled: canceled1, result: currentPassword } = await os.inputText({ title: i18n.ts.currentPassword, type: 'password', + autocomplete: 'current-password', }); if (canceled1) return; const { canceled: canceled2, result: newPassword } = await os.inputText({ title: i18n.ts.newPassword, type: 'password', + autocomplete: 'new-password', }); if (canceled2) return; const { canceled: canceled3, result: newPassword2 } = await os.inputText({ title: i18n.ts.newPasswordRetype, type: 'password', + autocomplete: 'new-password', }); if (canceled3) return; @@ -109,7 +109,7 @@ definePageMetadata({ diff --git a/packages/frontend/src/components/MkModal.vue b/packages/frontend/src/components/MkModal.vue index eba0f5847d..dbad02fb7e 100644 --- a/packages/frontend/src/components/MkModal.vue +++ b/packages/frontend/src/components/MkModal.vue @@ -125,7 +125,7 @@ function onBgClick() { } if (type === 'drawer') { - maxHeight = window.innerHeight / 1.5; + maxHeight = (window.innerHeight - SCROLLBAR_THICKNESS) / 1.5; } const keymap = { @@ -133,6 +133,7 @@ const keymap = { }; const MARGIN = 16; +const SCROLLBAR_THICKNESS = 16; const align = () => { if (props.src == null) return; @@ -170,15 +171,15 @@ const align = () => { if (fixed) { // 画面から横にはみ出る場合 - if (left + width > window.innerWidth) { - left = window.innerWidth - width; + if (left + width > (window.innerWidth - SCROLLBAR_THICKNESS)) { + left = (window.innerWidth - SCROLLBAR_THICKNESS) - width; } - const underSpace = (window.innerHeight - MARGIN) - top; + const underSpace = ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN) - top; const upperSpace = (srcRect.top - MARGIN); // 画面から縦にはみ出る場合 - if (top + height > (window.innerHeight - MARGIN)) { + if (top + height > ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN)) { if (props.noOverlap && props.anchor.x === 'center') { if (underSpace >= (upperSpace / 3)) { maxHeight = underSpace; @@ -187,22 +188,22 @@ const align = () => { top = (upperSpace + MARGIN) - height; } } else { - top = (window.innerHeight - MARGIN) - height; + top = ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN) - height; } } else { maxHeight = underSpace; } } else { // 画面から横にはみ出る場合 - if (left + width - window.pageXOffset > window.innerWidth) { - left = window.innerWidth - width + window.pageXOffset - 1; + if (left + width - window.pageXOffset > (window.innerWidth - SCROLLBAR_THICKNESS)) { + left = (window.innerWidth - SCROLLBAR_THICKNESS) - width + window.pageXOffset - 1; } - const underSpace = (window.innerHeight - MARGIN) - (top - window.pageYOffset); + const underSpace = ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN) - (top - window.pageYOffset); const upperSpace = (srcRect.top - MARGIN); // 画面から縦にはみ出る場合 - if (top + height - window.pageYOffset > (window.innerHeight - MARGIN)) { + if (top + height - window.pageYOffset > ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN)) { if (props.noOverlap && props.anchor.x === 'center') { if (underSpace >= (upperSpace / 3)) { maxHeight = underSpace; @@ -211,7 +212,7 @@ const align = () => { top = window.pageYOffset + ((upperSpace + MARGIN) - height); } } else { - top = (window.innerHeight - MARGIN) - height + window.pageYOffset - 1; + top = ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN) - height + window.pageYOffset - 1; } } else { maxHeight = underSpace; From 86eab355c61d336482433f8b7801ef63a04b5f7c Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 25 Feb 2023 17:49:54 +0900 Subject: [PATCH 212/294] :art: --- packages/frontend/src/components/MkNote.vue | 42 ++++++++++++++++++--- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue index 37fa3e6fec..1040dac12e 100644 --- a/packages/frontend/src/components/MkNote.vue +++ b/packages/frontend/src/components/MkNote.vue @@ -673,9 +673,17 @@ function showReactions(): void { opacity: 0.7; } -@container (max-width: 500px) { +@container (max-width: 580px) { .root { - font-size: 0.9em; + font-size: 0.95em; + } + + .renote { + padding: 12px 26px 0 26px; + } + + .article { + padding: 24px 26px 14px; } .avatar { @@ -684,7 +692,21 @@ function showReactions(): void { } } -@container (max-width: 450px) { +@container (max-width: 500px) { + .root { + font-size: 0.9em; + } + + .renote { + padding: 10px 22px 0 22px; + } + + .article { + padding: 20px 22px 12px; + } +} + +@container (max-width: 480px) { .renote { padding: 8px 16px 0 16px; } @@ -701,7 +723,9 @@ function showReactions(): void { .article { padding: 14px 16px 9px; } +} +@container (max-width: 450px) { .avatar { margin: 0 10px 8px 0; width: 46px; @@ -710,7 +734,7 @@ function showReactions(): void { } } -@container (max-width: 350px) { +@container (max-width: 400px) { .footerButton { &:not(:last-child) { margin-right: 18px; @@ -718,6 +742,14 @@ function showReactions(): void { } } +@container (max-width: 350px) { + .footerButton { + &:not(:last-child) { + margin-right: 12px; + } + } +} + @container (max-width: 300px) { .avatar { width: 44px; @@ -726,7 +758,7 @@ function showReactions(): void { .footerButton { &:not(:last-child) { - margin-right: 12px; + margin-right: 8px; } } } From 24553eb69a7208e946aa1eb547bdb9e749d439ab Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 25 Feb 2023 18:03:16 +0900 Subject: [PATCH 213/294] :art: --- .../frontend/src/components/global/MkPageHeader.tabs.vue | 2 +- packages/frontend/src/components/global/MkPageHeader.vue | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/frontend/src/components/global/MkPageHeader.tabs.vue b/packages/frontend/src/components/global/MkPageHeader.tabs.vue index 3beedf34b2..42760da08f 100644 --- a/packages/frontend/src/components/global/MkPageHeader.tabs.vue +++ b/packages/frontend/src/components/global/MkPageHeader.tabs.vue @@ -103,7 +103,7 @@ function onTabWheel(ev: WheelEvent) { ev.stopPropagation(); (ev.currentTarget as HTMLElement).scrollBy({ left: ev.deltaY, - behavior: 'smooth', + behavior: 'instant', }); } return false; diff --git a/packages/frontend/src/components/global/MkPageHeader.vue b/packages/frontend/src/components/global/MkPageHeader.vue index a4e25bbe1a..589ca92d75 100644 --- a/packages/frontend/src/components/global/MkPageHeader.vue +++ b/packages/frontend/src/components/global/MkPageHeader.vue @@ -147,10 +147,7 @@ onUnmounted(() => { .tabs:first-child { margin-left: auto; - } - .tabs:not(:first-child) { - padding-left: 16px; - mask-image: linear-gradient(90deg, rgba(0,0,0,0), rgb(0,0,0) 16px, rgb(0,0,0) 100%); + padding: 0 12px; } .tabs { margin-right: auto; From ea04778649f24719c40ff40f16438175f62da534 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 25 Feb 2023 18:26:35 +0900 Subject: [PATCH 214/294] feat: in-channel featured note Resolve #9938 --- CHANGELOG.md | 1 + .../server/api/endpoints/notes/featured.ts | 3 ++ packages/frontend/src/pages/channel.vue | 36 +++++++++++++------ 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d885c47ca0..489fcff2cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ You should also include the user name that made the change. ## 13.x.x (unreleased) ### Improvements +- チャンネル内ハイライト - renoteした際の表示を改善 - バックグラウンドで一定時間経過したらページネーションのアイテム更新をしない - enhance(client): MkUrlPreviewの閉じるボタンを見やすく diff --git a/packages/backend/src/server/api/endpoints/notes/featured.ts b/packages/backend/src/server/api/endpoints/notes/featured.ts index 26f69373d1..cf939f6631 100644 --- a/packages/backend/src/server/api/endpoints/notes/featured.ts +++ b/packages/backend/src/server/api/endpoints/notes/featured.ts @@ -28,6 +28,7 @@ export const paramDef = { properties: { limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, offset: { type: 'integer', default: 0 }, + channelId: { type: 'string', nullable: true, format: 'misskey:id' }, }, required: [], } as const; @@ -63,6 +64,8 @@ export default class extends Endpoint { .leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar') .leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner'); + if (ps.channelId) query.andWhere('note.channelId = :channelId', { channelId: ps.channelId }); + if (me) this.queryService.generateMutedUserQuery(query, me); if (me) this.queryService.generateBlockedUserQuery(query, me); diff --git a/packages/frontend/src/pages/channel.vue b/packages/frontend/src/pages/channel.vue index f59b7d7f90..6b4fcb32f8 100644 --- a/packages/frontend/src/pages/channel.vue +++ b/packages/frontend/src/pages/channel.vue @@ -1,9 +1,9 @@ @@ -49,7 +49,7 @@ const props = defineProps<{ aspectRatio: number; }>(); -const imgUrl = getProxiedImageUrl(props.file.url); +const imgUrl = getProxiedImageUrl(props.file.url, undefined, true); let dialogEl = $shallowRef>(); let imgEl = $shallowRef(); let cropper: Cropper | null = null; diff --git a/packages/frontend/src/scripts/media-proxy.ts b/packages/frontend/src/scripts/media-proxy.ts index 274e96e0a1..2fe5bdcf8f 100644 --- a/packages/frontend/src/scripts/media-proxy.ts +++ b/packages/frontend/src/scripts/media-proxy.ts @@ -1,20 +1,20 @@ -import { query, appendQuery } from '@/scripts/url'; +import { query } from '@/scripts/url'; import { url } from '@/config'; import { instance } from '@/instance'; -export function getProxiedImageUrl(imageUrl: string, type?: 'preview'): string { - if (imageUrl.startsWith(instance.mediaProxy + '/') || imageUrl.startsWith('/proxy/')) { - // もう既にproxyっぽそうだったらsearchParams付けるだけ - return appendQuery(imageUrl, query({ - fallback: '1', - ...(type ? { [type]: '1' } : {}), - })); +export function getProxiedImageUrl(imageUrl: string, type?: 'preview', mustOrigin: boolean = false): string { + const localProxy = `${url}/proxy`; + + if (imageUrl.startsWith(instance.mediaProxy + '/') || imageUrl.startsWith('/proxy/') || imageUrl.startsWith(localProxy + '/')) { + // もう既にproxyっぽそうだったらurlを取り出す + imageUrl = (new URL(imageUrl)).searchParams.get('url') ?? imageUrl; } - return `${instance.mediaProxy}/image.webp?${query({ + return `${mustOrigin ? localProxy : instance.mediaProxy}/image.webp?${query({ url: imageUrl, fallback: '1', ...(type ? { [type]: '1' } : {}), + ...(mustOrigin ? { origin: '1' } : {}), })}`; } From 4ea978000d6ff115454dd3f88acbb50c848ac93b Mon Sep 17 00:00:00 2001 From: syuilo Date: Tue, 28 Feb 2023 17:14:55 +0900 Subject: [PATCH 249/294] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 50cfc746bf..88a6ab705e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ You should also include the user name that made the change. - ### Bugfixes +- 外部メディアプロキシ使用時にアバタークロップができない問題を修正 - fix(server): メールアドレス更新時にバリデーションが正しく行われていないのを修正 ## 13.8.1 (2023/02/26) From 17d0bde50eba66d6990e9cd35dbff3a2a9e21383 Mon Sep 17 00:00:00 2001 From: tamaina Date: Tue, 28 Feb 2023 17:26:42 +0900 Subject: [PATCH 250/294] =?UTF-8?q?fix(client):=20photoswipe=EF=BC=88?= =?UTF-8?q?=E7=94=BB=E5=83=8F=E3=81=AE=E6=8B=A1=E5=A4=A7=E8=A1=A8=E7=A4=BA?= =?UTF-8?q?=EF=BC=89=E3=81=8C=E3=81=AA=E3=82=93=E3=81=8B=E5=A4=89=20(#1013?= =?UTF-8?q?8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(client): photoswipe(画像の拡大表示)がなんか変 Fix #10037 * important --------- Co-authored-by: syuilo --- .../frontend/src/components/MkMediaList.vue | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/packages/frontend/src/components/MkMediaList.vue b/packages/frontend/src/components/MkMediaList.vue index fafa0bd232..c768a086cd 100644 --- a/packages/frontend/src/components/MkMediaList.vue +++ b/packages/frontend/src/components/MkMediaList.vue @@ -13,7 +13,7 @@ diff --git a/packages/frontend/src/pages/my-lists/list.vue b/packages/frontend/src/pages/my-lists/list.vue index f47b4bf90f..a6a3974d0c 100644 --- a/packages/frontend/src/pages/my-lists/list.vue +++ b/packages/frontend/src/pages/my-lists/list.vue @@ -2,13 +2,13 @@ -
+
-
+
{{ i18n.ts.addUser }} {{ i18n.ts.rename }} - {{ i18n.ts.delete }} + {{ i18n.ts.delete }}
@@ -16,18 +16,12 @@
{{ i18n.ts.members }}
-
-
-
- -
- - -
-
- -
-
+
+
+ + + +
@@ -44,6 +38,8 @@ import * as os from '@/os'; import { mainRouter } from '@/router'; import { definePageMetadata } from '@/scripts/page-metadata'; import { i18n } from '@/i18n'; +import { userPage } from '@/filters/user'; +import MkUserCardMini from '@/components/MkUserCardMini.vue'; const props = defineProps<{ listId: string; @@ -76,13 +72,20 @@ function addUser() { }); } -function removeUser(user) { - os.api('users/lists/pull', { - listId: list.id, - userId: user.id, - }).then(() => { - users = users.filter(x => x.id !== user.id); - }); +async function removeUser(user, ev) { + os.popupMenu([{ + text: i18n.ts.remove, + icon: 'ti ti-x', + danger: true, + action: async () => { + os.api('users/lists/pull', { + listId: list.id, + userId: user.id, + }).then(() => { + users = users.filter(x => x.id !== user.id); + }); + }, + }], ev.currentTarget ?? ev.target); } async function renameList() { @@ -126,37 +129,24 @@ definePageMetadata(computed(() => list ? { } : null)); - From 44f041587cc3ef298242ffce710b51c1ac57327b Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 1 Mar 2023 14:46:53 +0900 Subject: [PATCH 261/294] :art: --- packages/frontend/src/components/MkNote.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue index 1e78c69601..35d5ef77d1 100644 --- a/packages/frontend/src/components/MkNote.vue +++ b/packages/frontend/src/components/MkNote.vue @@ -453,12 +453,12 @@ function showReactions(): void { padding: 0 4px; margin-bottom: 0 !important; background: var(--popup); - border-radius: 6px; + border-radius: 8px; box-shadow: 0px 4px 32px var(--shadow); } .footerButton { - font-size: 80%; + font-size: 90%; &:not(:last-child) { margin-right: 0; From 78d66d3806fc78cac5964e00fe8cec72afea5052 Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 1 Mar 2023 14:54:02 +0900 Subject: [PATCH 262/294] :art: --- packages/frontend/src/components/MkNote.vue | 1 + packages/frontend/src/components/MkNoteHeader.vue | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue index 35d5ef77d1..7842566b88 100644 --- a/packages/frontend/src/components/MkNote.vue +++ b/packages/frontend/src/components/MkNote.vue @@ -32,6 +32,7 @@ +
diff --git a/packages/frontend/src/components/MkNoteHeader.vue b/packages/frontend/src/components/MkNoteHeader.vue index ffd9a20ef7..15d7ea2e14 100644 --- a/packages/frontend/src/components/MkNoteHeader.vue +++ b/packages/frontend/src/components/MkNoteHeader.vue @@ -18,6 +18,7 @@ +
From c34e7e6e08c66fb4ed539c4d4f967af3843dca7b Mon Sep 17 00:00:00 2001 From: Khsmty Date: Wed, 1 Mar 2023 14:55:57 +0900 Subject: [PATCH 263/294] =?UTF-8?q?enhance(client):=20Renote=20=E3=81=97?= =?UTF-8?q?=E3=81=9F=E6=99=82=E3=81=AE=E8=A1=A8=E7=A4=BA=E3=82=92=E3=83=AA?= =?UTF-8?q?=E3=83=83=E3=83=97=E3=83=AB=E3=82=A8=E3=83=95=E3=82=A7=E3=82=AF?= =?UTF-8?q?=E3=83=88=E3=81=A8=20toast=20=E3=81=AB=20(#10116)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * enhance(client): Renote した時の表示を toast に * fix: lint エラー * enhance(client): Renote した時の表示をリップルエフェクトに * toast も追加 * rippleeffect のタイミング変更 * toast の位置を header に被らないように --- packages/frontend/src/components/MkNote.vue | 25 +++++++++++++++++-- .../src/components/MkNoteDetailed.vue | 25 +++++++++++++++++-- packages/frontend/src/components/MkToast.vue | 2 +- 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue index 7842566b88..b87d46ee94 100644 --- a/packages/frontend/src/components/MkNote.vue +++ b/packages/frontend/src/components/MkNote.vue @@ -157,6 +157,7 @@ import { useTooltip } from '@/scripts/use-tooltip'; import { claimAchievement } from '@/scripts/achievements'; import { getNoteSummary } from '@/scripts/get-note-summary'; import { MenuItem } from '@/types/menu'; +import MkRippleEffect from '@/components/MkRippleEffect.vue'; const props = defineProps<{ note: misskey.entities.Note; @@ -256,9 +257,19 @@ function renote(viaKeyboard = false) { text: i18n.ts.inChannelRenote, icon: 'ti ti-repeat', action: () => { - os.apiWithDialog('notes/create', { + const el = renoteButton.value as HTMLElement | null | undefined; + if (el) { + const rect = el.getBoundingClientRect(); + const x = rect.left + (el.offsetWidth / 2); + const y = rect.top + (el.offsetHeight / 2); + os.popup(MkRippleEffect, { x, y }, {}, 'end'); + } + + os.api('notes/create', { renoteId: appearNote.id, channelId: appearNote.channelId, + }).then(() => { + os.toast(i18n.ts.renoted); }); }, }, { @@ -277,8 +288,18 @@ function renote(viaKeyboard = false) { text: i18n.ts.renote, icon: 'ti ti-repeat', action: () => { - os.apiWithDialog('notes/create', { + const el = renoteButton.value as HTMLElement | null | undefined; + if (el) { + const rect = el.getBoundingClientRect(); + const x = rect.left + (el.offsetWidth / 2); + const y = rect.top + (el.offsetHeight / 2); + os.popup(MkRippleEffect, { x, y }, {}, 'end'); + } + + os.api('notes/create', { renoteId: appearNote.id, + }).then(() => { + os.toast(i18n.ts.renoted); }); }, }, { diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue index 2eebe999a5..f5f4a2afc1 100644 --- a/packages/frontend/src/components/MkNoteDetailed.vue +++ b/packages/frontend/src/components/MkNoteDetailed.vue @@ -161,6 +161,7 @@ import { deepClone } from '@/scripts/clone'; import { useTooltip } from '@/scripts/use-tooltip'; import { claimAchievement } from '@/scripts/achievements'; import { MenuItem } from '@/types/menu'; +import MkRippleEffect from '@/components/MkRippleEffect.vue'; const props = defineProps<{ note: misskey.entities.Note; @@ -250,9 +251,19 @@ function renote(viaKeyboard = false) { text: i18n.ts.inChannelRenote, icon: 'ti ti-repeat', action: () => { - os.apiWithDialog('notes/create', { + const el = renoteButton.value as HTMLElement | null | undefined; + if (el) { + const rect = el.getBoundingClientRect(); + const x = rect.left + (el.offsetWidth / 2); + const y = rect.top + (el.offsetHeight / 2); + os.popup(MkRippleEffect, { x, y }, {}, 'end'); + } + + os.api('notes/create', { renoteId: appearNote.id, channelId: appearNote.channelId, + }).then(() => { + os.toast(i18n.ts.renoted); }); }, }, { @@ -271,8 +282,18 @@ function renote(viaKeyboard = false) { text: i18n.ts.renote, icon: 'ti ti-repeat', action: () => { - os.apiWithDialog('notes/create', { + const el = renoteButton.value as HTMLElement | null | undefined; + if (el) { + const rect = el.getBoundingClientRect(); + const x = rect.left + (el.offsetWidth / 2); + const y = rect.top + (el.offsetHeight / 2); + os.popup(MkRippleEffect, { x, y }, {}, 'end'); + } + + os.api('notes/create', { renoteId: appearNote.id, + }).then(() => { + os.toast(i18n.ts.renoted); }); }, }, { diff --git a/packages/frontend/src/components/MkToast.vue b/packages/frontend/src/components/MkToast.vue index 1aa48f88e6..6d59702569 100644 --- a/packages/frontend/src/components/MkToast.vue +++ b/packages/frontend/src/components/MkToast.vue @@ -53,7 +53,7 @@ onMounted(() => { position: fixed; left: 0; right: 0; - top: 0; + top: 50px; margin: 0 auto; margin-top: 16px; min-width: 300px; From 830fabef12c6ef91eaaee3ad7bc73a5c110ff939 Mon Sep 17 00:00:00 2001 From: KokiSakano <61353435+KokiSakano@users.noreply.github.com> Date: Wed, 1 Mar 2023 15:19:20 +0900 Subject: [PATCH 264/294] =?UTF-8?q?refactor:=20plugin.ts=E3=81=AE=E5=9E=8B?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3=E3=81=99=E3=82=8B=20(#10027)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor:plugin内のすべての関数にreturn typeを設定 * fix:pluginContextsから取得できない場合は早期リターンする * fix:valueがstring以外の時は早期リターンする * fix:valueが取得できる時以外は早期リターンする * fix:pluginに型をつける * fix:絞り込みをassertStringに変更 * fix:修正漏れ * fix:valToJsからvalueを取得するように変更 --- packages/frontend/src/plugin.ts | 70 +++++++++++++++++++++++---------- packages/frontend/src/store.ts | 5 ++- 2 files changed, 54 insertions(+), 21 deletions(-) diff --git a/packages/frontend/src/plugin.ts b/packages/frontend/src/plugin.ts index 17eb99be22..a1a36480fd 100644 --- a/packages/frontend/src/plugin.ts +++ b/packages/frontend/src/plugin.ts @@ -1,12 +1,12 @@ import { Interpreter, Parser, utils, values } from '@syuilo/aiscript'; import { createAiScriptEnv } from '@/scripts/aiscript/api'; import { inputText } from '@/os'; -import { noteActions, notePostInterruptors, noteViewInterruptors, postFormActions, userActions } from '@/store'; +import { Plugin, noteActions, notePostInterruptors, noteViewInterruptors, postFormActions, userActions } from '@/store'; const parser = new Parser(); const pluginContexts = new Map(); -export function install(plugin) { +export function install(plugin: Plugin): void { // 後方互換性のため if (plugin.src == null) return; console.info('Plugin installed:', plugin.name, 'v' + plugin.version); @@ -15,7 +15,7 @@ export function install(plugin) { plugin: plugin, storageKey: 'plugins:' + plugin.id, }), { - in: (q) => { + in: (q): Promise => { return new Promise(ok => { inputText({ title: q, @@ -28,10 +28,10 @@ export function install(plugin) { }); }); }, - out: (value) => { + out: (value): void => { console.log(value); }, - log: (type, params) => { + log: (): void => { }, }); @@ -40,9 +40,9 @@ export function install(plugin) { aiscript.exec(parser.parse(plugin.src)); } -function createPluginEnv(opts) { - const config = new Map(); - for (const [k, v] of Object.entries(opts.plugin.config || {})) { +function createPluginEnv(opts: { plugin: Plugin; storageKey: string }): Record { + const config = new Map(); + for (const [k, v] of Object.entries(opts.plugin.config ?? {})) { config.set(k, utils.jsToVal(typeof opts.plugin.configData[k] !== 'undefined' ? opts.plugin.configData[k] : v.default)); } @@ -50,22 +50,28 @@ function createPluginEnv(opts) { ...createAiScriptEnv({ ...opts, token: opts.plugin.token }), //#region Deprecated 'Mk:register_post_form_action': values.FN_NATIVE(([title, handler]) => { + utils.assertString(title); registerPostFormAction({ pluginId: opts.plugin.id, title: title.value, handler }); }), 'Mk:register_user_action': values.FN_NATIVE(([title, handler]) => { + utils.assertString(title); registerUserAction({ pluginId: opts.plugin.id, title: title.value, handler }); }), 'Mk:register_note_action': values.FN_NATIVE(([title, handler]) => { + utils.assertString(title); registerNoteAction({ pluginId: opts.plugin.id, title: title.value, handler }); }), //#endregion 'Plugin:register_post_form_action': values.FN_NATIVE(([title, handler]) => { + utils.assertString(title); registerPostFormAction({ pluginId: opts.plugin.id, title: title.value, handler }); }), 'Plugin:register_user_action': values.FN_NATIVE(([title, handler]) => { + utils.assertString(title); registerUserAction({ pluginId: opts.plugin.id, title: title.value, handler }); }), 'Plugin:register_note_action': values.FN_NATIVE(([title, handler]) => { + utils.assertString(title); registerNoteAction({ pluginId: opts.plugin.id, title: title.value, handler }); }), 'Plugin:register_note_view_interruptor': values.FN_NATIVE(([handler]) => { @@ -75,54 +81,78 @@ function createPluginEnv(opts) { registerNotePostInterruptor({ pluginId: opts.plugin.id, handler }); }), 'Plugin:open_url': values.FN_NATIVE(([url]) => { + utils.assertString(url); window.open(url.value, '_blank'); }), 'Plugin:config': values.OBJ(config), }; } -function initPlugin({ plugin, aiscript }) { +function initPlugin({ plugin, aiscript }): void { pluginContexts.set(plugin.id, aiscript); } -function registerPostFormAction({ pluginId, title, handler }) { +function registerPostFormAction({ pluginId, title, handler }): void { postFormActions.push({ title, handler: (form, update) => { - pluginContexts.get(pluginId).execFn(handler, [utils.jsToVal(form), values.FN_NATIVE(([key, value]) => { - update(key.value, value.value); + const pluginContext = pluginContexts.get(pluginId); + if (!pluginContext) { + return; + } + pluginContext.execFn(handler, [utils.jsToVal(form), values.FN_NATIVE(([key, value]) => { + if (!key || !value) { + return; + } + update(utils.valToJs(key), utils.valToJs(value)); })]); }, }); } -function registerUserAction({ pluginId, title, handler }) { +function registerUserAction({ pluginId, title, handler }): void { userActions.push({ title, handler: (user) => { - pluginContexts.get(pluginId).execFn(handler, [utils.jsToVal(user)]); + const pluginContext = pluginContexts.get(pluginId); + if (!pluginContext) { + return; + } + pluginContext.execFn(handler, [utils.jsToVal(user)]); }, }); } -function registerNoteAction({ pluginId, title, handler }) { +function registerNoteAction({ pluginId, title, handler }): void { noteActions.push({ title, handler: (note) => { - pluginContexts.get(pluginId).execFn(handler, [utils.jsToVal(note)]); + const pluginContext = pluginContexts.get(pluginId); + if (!pluginContext) { + return; + } + pluginContext.execFn(handler, [utils.jsToVal(note)]); }, }); } -function registerNoteViewInterruptor({ pluginId, handler }) { +function registerNoteViewInterruptor({ pluginId, handler }): void { noteViewInterruptors.push({ handler: async (note) => { - return utils.valToJs(await pluginContexts.get(pluginId).execFn(handler, [utils.jsToVal(note)])); + const pluginContext = pluginContexts.get(pluginId); + if (!pluginContext) { + return; + } + return utils.valToJs(await pluginContext.execFn(handler, [utils.jsToVal(note)])); }, }); } -function registerNotePostInterruptor({ pluginId, handler }) { +function registerNotePostInterruptor({ pluginId, handler }): void { notePostInterruptors.push({ handler: async (note) => { - return utils.valToJs(await pluginContexts.get(pluginId).execFn(handler, [utils.jsToVal(note)])); + const pluginContext = pluginContexts.get(pluginId); + if (!pluginContext) { + return; + } + return utils.valToJs(await pluginContext.execFn(handler, [utils.jsToVal(note)])); }, }); } diff --git a/packages/frontend/src/store.ts b/packages/frontend/src/store.ts index fd2f2523c9..14226468eb 100644 --- a/packages/frontend/src/store.ts +++ b/packages/frontend/src/store.ts @@ -287,12 +287,15 @@ export const defaultStore = markRaw(new Storage('base', { const PREFIX = 'miux:' as const; -type Plugin = { +export type Plugin = { id: string; name: string; active: boolean; + config?: Record; configData: Record; token: string; + src: string | null; + version: string; ast: any[]; }; From 6d82371449cc97f1ee8a7425b17ec536a3095640 Mon Sep 17 00:00:00 2001 From: Kagami Sascha Rosylight Date: Wed, 1 Mar 2023 07:24:09 +0100 Subject: [PATCH 265/294] fix(frontend): read KeyboardEvent.key instead of which/code (#10083) --- cypress/e2e/basic.cy.js | 17 +++++++++++++++-- packages/frontend/src/components/MkPostForm.vue | 10 +++++----- packages/frontend/src/scripts/hotkey.ts | 6 +++--- packages/frontend/src/scripts/keycode.ts | 15 --------------- 4 files changed, 23 insertions(+), 25 deletions(-) diff --git a/cypress/e2e/basic.cy.js b/cypress/e2e/basic.cy.js index eb5195c4b2..fc3e6f35bc 100644 --- a/cypress/e2e/basic.cy.js +++ b/cypress/e2e/basic.cy.js @@ -17,7 +17,7 @@ describe('Before setup instance', () => { cy.visit('/'); cy.intercept('POST', '/api/admin/accounts/create').as('signup'); - + cy.get('[data-cy-admin-username] input').type('admin'); cy.get('[data-cy-admin-password] input').type('admin1234'); cy.get('[data-cy-admin-ok]').click(); @@ -112,7 +112,7 @@ describe('After user signup', () => { }); }); -describe('After user singed in', () => { +describe('After user signed in', () => { beforeEach(() => { cy.resetState(); @@ -141,6 +141,19 @@ describe('After user singed in', () => { cy.get('[data-cy-open-post-form-submit]').click(); cy.contains('Hello, Misskey!'); + }); + + it('open note form with hotkey', () => { + // Wait until the page loads + cy.get('[data-cy-open-post-form]').should('be.visible'); + // Use trigger() to give different `code` to test if hotkeys also work on non-QWERTY keyboards. + cy.document().trigger("keydown", { eventConstructor: 'KeyboardEvent', key: "n", code: "KeyL" }); + // See if the form is opened + cy.get('[data-cy-post-form-text]').should('be.visible'); + // Close it + cy.focused().trigger("keydown", { eventConstructor: 'KeyboardEvent', key: "Escape", code: "Escape" }); + // See if the form is closed + cy.get('[data-cy-post-form-text]').should('not.be.visible'); }); }); diff --git a/packages/frontend/src/components/MkPostForm.vue b/packages/frontend/src/components/MkPostForm.vue index f73eab5b86..2b3e2c8646 100644 --- a/packages/frontend/src/components/MkPostForm.vue +++ b/packages/frontend/src/components/MkPostForm.vue @@ -437,8 +437,8 @@ function clear() { } function onKeydown(ev: KeyboardEvent) { - if ((ev.which === 10 || ev.which === 13) && (ev.ctrlKey || ev.metaKey) && canPost) post(); - if (ev.which === 27) emit('esc'); + if (ev.key === 'Enter' && (ev.ctrlKey || ev.metaKey) && canPost) post(); + if (ev.key === 'Escape') emit('esc'); } function onCompositionUpdate(ev: CompositionEvent) { @@ -489,9 +489,9 @@ function onDragover(ev) { switch (ev.dataTransfer.effectAllowed) { case 'all': case 'uninitialized': - case 'copy': - case 'copyLink': - case 'copyMove': + case 'copy': + case 'copyLink': + case 'copyMove': ev.dataTransfer.dropEffect = 'copy'; break; case 'linkMove': diff --git a/packages/frontend/src/scripts/hotkey.ts b/packages/frontend/src/scripts/hotkey.ts index 4a0ded637d..b7238016c6 100644 --- a/packages/frontend/src/scripts/hotkey.ts +++ b/packages/frontend/src/scripts/hotkey.ts @@ -53,10 +53,10 @@ const parseKeymap = (keymap: Keymap) => Object.entries(keymap).map(([patterns, c return result; }); -const ignoreElemens = ['input', 'textarea']; +const ignoreElements = ['input', 'textarea']; function match(ev: KeyboardEvent, patterns: Action['patterns']): boolean { - const key = ev.code.toLowerCase(); + const key = ev.key.toLowerCase(); return patterns.some(pattern => pattern.which.includes(key) && pattern.ctrl === ev.ctrlKey && pattern.shift === ev.shiftKey && @@ -70,7 +70,7 @@ export const makeHotkey = (keymap: Keymap) => { return (ev: KeyboardEvent) => { if (document.activeElement) { - if (ignoreElemens.some(el => document.activeElement!.matches(el))) return; + if (ignoreElements.some(el => document.activeElement!.matches(el))) return; if (document.activeElement.attributes['contenteditable']) return; } diff --git a/packages/frontend/src/scripts/keycode.ts b/packages/frontend/src/scripts/keycode.ts index 69f6a82803..35813edbd5 100644 --- a/packages/frontend/src/scripts/keycode.ts +++ b/packages/frontend/src/scripts/keycode.ts @@ -16,18 +16,3 @@ export const aliases = { 'right': 'ArrowRight', 'plus': ['NumpadAdd', 'Semicolon'], }; - -/*! -* Programmatically add the following -*/ - -// lower case chars -for (let i = 97; i < 123; i++) { - const char = String.fromCharCode(i); - aliases[char] = `Key${char.toUpperCase()}`; -} - -// numbers -for (let i = 0; i < 10; i++) { - aliases[i] = [`Numpad${i}`, `Digit${i}`]; -} From 44058f8b855ddffb1451241f0c28fb0cf3d9845c Mon Sep 17 00:00:00 2001 From: Kagami Sascha Rosylight Date: Wed, 1 Mar 2023 07:32:53 +0100 Subject: [PATCH 266/294] enhance(e2e): more resilient version of `visit('/')` (#10128) --- cypress/e2e/basic.cy.js | 14 +++++++------- cypress/support/commands.js | 7 ++++++- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/cypress/e2e/basic.cy.js b/cypress/e2e/basic.cy.js index fc3e6f35bc..b1b856119c 100644 --- a/cypress/e2e/basic.cy.js +++ b/cypress/e2e/basic.cy.js @@ -10,11 +10,11 @@ describe('Before setup instance', () => { }); it('successfully loads', () => { - cy.visit('/'); + cy.visitHome(); }); it('setup instance', () => { - cy.visit('/'); + cy.visitHome(); cy.intercept('POST', '/api/admin/accounts/create').as('signup'); @@ -43,11 +43,11 @@ describe('After setup instance', () => { }); it('successfully loads', () => { - cy.visit('/'); + cy.visitHome(); }); it('signup', () => { - cy.visit('/'); + cy.visitHome(); cy.intercept('POST', '/api/signup').as('signup'); @@ -79,11 +79,11 @@ describe('After user signup', () => { }); it('successfully loads', () => { - cy.visit('/'); + cy.visitHome(); }); it('signin', () => { - cy.visit('/'); + cy.visitHome(); cy.intercept('POST', '/api/signin').as('signin'); @@ -101,7 +101,7 @@ describe('After user signup', () => { userId: this.alice.id, }); - cy.visit('/'); + cy.visitHome(); cy.get('[data-cy-signin]').click(); cy.get('[data-cy-signin-username] input').type('alice'); diff --git a/cypress/support/commands.js b/cypress/support/commands.js index 04a6d98b01..91a4d7abe6 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -24,6 +24,11 @@ // -- This will overwrite an existing command -- // Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +Cypress.Commands.add('visitHome', () => { + cy.visit('/'); + cy.get('button', { timeout: 30000 }).should('be.visible'); +}) + Cypress.Commands.add('resetState', () => { cy.window(win => { win.indexedDB.deleteDatabase('keyval-store'); @@ -43,7 +48,7 @@ Cypress.Commands.add('registerUser', (username, password, isAdmin = false) => { }); Cypress.Commands.add('login', (username, password) => { - cy.visit('/'); + cy.visitHome(); cy.intercept('POST', '/api/signin').as('signin'); From 47b1b09b21d09d8cdc07265b9eb0a83dbd38e5b5 Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 1 Mar 2023 17:22:17 +0900 Subject: [PATCH 267/294] enhance(client): add new sounds --- .../assets/sounds/syuilo/new-aec-oct.mp3 | Bin 0 -> 27943 bytes .../frontend/assets/sounds/syuilo/new-aec.mp3 | Bin 0 -> 27943 bytes .../assets/sounds/syuilo/new-cea-oct.mp3 | Bin 0 -> 27943 bytes .../frontend/assets/sounds/syuilo/new-cea.mp3 | Bin 0 -> 27943 bytes .../assets/sounds/syuilo/new-eca-oct.mp3 | Bin 0 -> 27943 bytes .../frontend/assets/sounds/syuilo/new-eca.mp3 | Bin 0 -> 27943 bytes packages/frontend/src/scripts/sound.ts | 6 ++++++ 7 files changed, 6 insertions(+) create mode 100644 packages/frontend/assets/sounds/syuilo/new-aec-oct.mp3 create mode 100644 packages/frontend/assets/sounds/syuilo/new-aec.mp3 create mode 100644 packages/frontend/assets/sounds/syuilo/new-cea-oct.mp3 create mode 100644 packages/frontend/assets/sounds/syuilo/new-cea.mp3 create mode 100644 packages/frontend/assets/sounds/syuilo/new-eca-oct.mp3 create mode 100644 packages/frontend/assets/sounds/syuilo/new-eca.mp3 diff --git a/packages/frontend/assets/sounds/syuilo/new-aec-oct.mp3 b/packages/frontend/assets/sounds/syuilo/new-aec-oct.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..d66406a95429e31f0ed34f0de5a1ade242b88ea5 GIT binary patch literal 27943 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 Hrvv{1)ROWa literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/sounds/syuilo/new-aec.mp3 b/packages/frontend/assets/sounds/syuilo/new-aec.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..054883e08f007d163b41e33fe2ac337fdce3f26e GIT binary patch literal 27943 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 I=kE~z15Hh97XSbN literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/sounds/syuilo/new-cea-oct.mp3 b/packages/frontend/assets/sounds/syuilo/new-cea-oct.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..24ccdf4486ee31504c02ba021f5185ff1d95ca38 GIT binary patch literal 27943 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 literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/sounds/syuilo/new-cea.mp3 b/packages/frontend/assets/sounds/syuilo/new-cea.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..bd3c7d551bc1cdc5aba65a670eb108e8e5ba73ba GIT binary patch literal 27943 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 G|9=3k{KeV; literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/sounds/syuilo/new-eca-oct.mp3 b/packages/frontend/assets/sounds/syuilo/new-eca-oct.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..17c71cb98e4ad3760c8669cb130e09a54be43dd7 GIT binary patch literal 27943 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 F{{TtF0c`*P literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/sounds/syuilo/new-eca.mp3 b/packages/frontend/assets/sounds/syuilo/new-eca.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..433da56cbaa715c84be291899643d1391570581e GIT binary patch literal 27943 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 export const soundsTypes = [ null, + 'syuilo/new-eca', + 'syuilo/new-cea', + 'syuilo/new-aec', + 'syuilo/new-eca-oct', + 'syuilo/new-cea-oct', + 'syuilo/new-aec-oct', 'syuilo/up', 'syuilo/down', 'syuilo/pope1', From afa9c1f6f074f2ff1e64b1203e18446700103010 Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 1 Mar 2023 17:22:32 +0900 Subject: [PATCH 268/294] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee941d479f..f0887dcced 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ You should also include the user name that made the change. - プッシュ通知でカスタム絵文字リアクションを表示できるように - アンテナでCWも検索対象にするように - ノートの操作部をホバー時のみ表示するオプションを追加 +- サウンドを追加 ### Bugfixes - 外部メディアプロキシ使用時にアバタークロップができない問題を修正 From 39e41d74249616ee878425cf43c0b22117303c84 Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 1 Mar 2023 17:30:23 +0900 Subject: [PATCH 269/294] :art: --- packages/frontend/src/components/MkWindow.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/components/MkWindow.vue b/packages/frontend/src/components/MkWindow.vue index 7e53507f2e..f7565ca59f 100644 --- a/packages/frontend/src/components/MkWindow.vue +++ b/packages/frontend/src/components/MkWindow.vue @@ -465,7 +465,7 @@ defineExpose({ -webkit-backdrop-filter: var(--blur, blur(15px)); backdrop-filter: var(--blur, blur(15px)); //border-bottom: solid 1px var(--divider); - font-size: 95%; + font-size: 90%; font-weight: bold; } From b39256416581373d7b0b7c6902a4a8d871a813ca Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 2 Mar 2023 08:36:06 +0900 Subject: [PATCH 270/294] Update about-misskey.vue --- packages/frontend/src/pages/about-misskey.vue | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/frontend/src/pages/about-misskey.vue b/packages/frontend/src/pages/about-misskey.vue index a49025c920..a72e5bb4c9 100644 --- a/packages/frontend/src/pages/about-misskey.vue +++ b/packages/frontend/src/pages/about-misskey.vue @@ -121,6 +121,9 @@ const patronsWithIcon = [{ }, { name: 'ひとぅ', icon: 'https://misskey-hub.net/patrons/8cc0d0a0a6d84c88bca1aedabf6ed5ab.jpg', +}, { + name: 'ぱーこ', + icon: 'https://misskey-hub.net/patrons/79c6602ffade489e8df2fcf2c2bc5d9d.jpg', }]; const patrons = [ From ea1cff499a5a40d24a671e0352d47234e318b64e Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 2 Mar 2023 08:36:15 +0900 Subject: [PATCH 271/294] update sounds --- .../assets/sounds/syuilo/new-aec-4va.mp3 | Bin 0 -> 26880 bytes .../assets/sounds/syuilo/new-aec-4vb.mp3 | Bin 0 -> 26880 bytes .../assets/sounds/syuilo/new-aec-8va.mp3 | Bin 0 -> 26880 bytes .../assets/sounds/syuilo/new-aec-8vb.mp3 | Bin 0 -> 26880 bytes .../assets/sounds/syuilo/new-aec-oct.mp3 | Bin 27943 -> 0 bytes .../frontend/assets/sounds/syuilo/new-aec.mp3 | Bin 27943 -> 26880 bytes .../assets/sounds/syuilo/new-cea-4va.mp3 | Bin 0 -> 26880 bytes .../assets/sounds/syuilo/new-cea-4vb.mp3 | Bin 0 -> 26880 bytes .../assets/sounds/syuilo/new-cea-8va.mp3 | Bin 0 -> 26880 bytes .../assets/sounds/syuilo/new-cea-8vb.mp3 | Bin 0 -> 26880 bytes .../assets/sounds/syuilo/new-cea-oct.mp3 | Bin 27943 -> 0 bytes .../frontend/assets/sounds/syuilo/new-cea.mp3 | Bin 27943 -> 26880 bytes .../assets/sounds/syuilo/new-eca-4va.mp3 | Bin 0 -> 26880 bytes .../assets/sounds/syuilo/new-eca-4vb.mp3 | Bin 0 -> 26880 bytes .../assets/sounds/syuilo/new-eca-8va.mp3 | Bin 0 -> 26880 bytes .../assets/sounds/syuilo/new-eca-8vb.mp3 | Bin 0 -> 26880 bytes .../assets/sounds/syuilo/new-eca-oct.mp3 | Bin 27943 -> 0 bytes .../frontend/assets/sounds/syuilo/new-eca.mp3 | Bin 27943 -> 26880 bytes packages/frontend/src/scripts/sound.ts | 19 +++++++++++++----- 19 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 packages/frontend/assets/sounds/syuilo/new-aec-4va.mp3 create mode 100644 packages/frontend/assets/sounds/syuilo/new-aec-4vb.mp3 create mode 100644 packages/frontend/assets/sounds/syuilo/new-aec-8va.mp3 create mode 100644 packages/frontend/assets/sounds/syuilo/new-aec-8vb.mp3 delete mode 100644 packages/frontend/assets/sounds/syuilo/new-aec-oct.mp3 create mode 100644 packages/frontend/assets/sounds/syuilo/new-cea-4va.mp3 create mode 100644 packages/frontend/assets/sounds/syuilo/new-cea-4vb.mp3 create mode 100644 packages/frontend/assets/sounds/syuilo/new-cea-8va.mp3 create mode 100644 packages/frontend/assets/sounds/syuilo/new-cea-8vb.mp3 delete mode 100644 packages/frontend/assets/sounds/syuilo/new-cea-oct.mp3 create mode 100644 packages/frontend/assets/sounds/syuilo/new-eca-4va.mp3 create mode 100644 packages/frontend/assets/sounds/syuilo/new-eca-4vb.mp3 create mode 100644 packages/frontend/assets/sounds/syuilo/new-eca-8va.mp3 create mode 100644 packages/frontend/assets/sounds/syuilo/new-eca-8vb.mp3 delete mode 100644 packages/frontend/assets/sounds/syuilo/new-eca-oct.mp3 diff --git a/packages/frontend/assets/sounds/syuilo/new-aec-4va.mp3 b/packages/frontend/assets/sounds/syuilo/new-aec-4va.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..0c5a4fb15b79db04e4134a7bcf9fd3bbb6ac9afa GIT binary patch literal 26880 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 literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/sounds/syuilo/new-aec-4vb.mp3 b/packages/frontend/assets/sounds/syuilo/new-aec-4vb.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..0842fe004b9046fae5d4b216be0b4e65a2e370b0 GIT binary patch literal 26880 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

#yryDHZK>ad77;CgM0DZfo9x4-VP1Mit5 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 literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/sounds/syuilo/new-aec-8vb.mp3 b/packages/frontend/assets/sounds/syuilo/new-aec-8vb.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..59a355f563d84af009b34f9f0889dcf28a8f8b2b GIT binary patch literal 26880 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 Hrvv{1)ROWa diff --git a/packages/frontend/assets/sounds/syuilo/new-aec.mp3 b/packages/frontend/assets/sounds/syuilo/new-aec.mp3 index 054883e08f007d163b41e33fe2ac337fdce3f26e..cd4b7a50acf208d8444ad7c427c1c58e702e7020 100644 GIT binary patch literal 26880 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 I=kE~z15Hh97XSbN diff --git a/packages/frontend/assets/sounds/syuilo/new-cea-4va.mp3 b/packages/frontend/assets/sounds/syuilo/new-cea-4va.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..6e9fbacfeb1af58f913c3edcfc798ce9189eccdf GIT binary patch literal 26880 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 G1^zz{T;TNp literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/sounds/syuilo/new-cea-8va.mp3 b/packages/frontend/assets/sounds/syuilo/new-cea-8va.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..6fc6652809179e4a2db886768d6c9d96eb4df4dd GIT binary patch literal 26880 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 literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/sounds/syuilo/new-cea-8vb.mp3 b/packages/frontend/assets/sounds/syuilo/new-cea-8vb.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..2df97a1a884a9c55dbc801be4ea1498cfcb0c63b GIT binary patch literal 26880 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 diff --git a/packages/frontend/assets/sounds/syuilo/new-cea.mp3 b/packages/frontend/assets/sounds/syuilo/new-cea.mp3 index bd3c7d551bc1cdc5aba65a670eb108e8e5ba73ba..16581990ea3b9657c924a51994266255dede5db4 100644 GIT binary patch literal 26880 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 IyDRX&03D2hEdT%j literal 27943 zcmeI2XIK+y*T*N779b!cv^6vZM4W`6fFPktq(~D%WEm1fsF{>*@bEyk1OUKn+YlPI88Fh<1A(u5MUlPCu+XpjESwyWBk{<-FUPpLS|ejgWNhyn z?r&hIw`{2%1q6|O-vXX^_U-Baxn*qf-;BJ7OamwbKnNd@l9EzHLS0>57YQ1TW{QN3 zjm>H#5V0Pv_Y-?!a@t-yhQq5}xOegGiU44JF!CL;!j zld}Podd>-g!XyV7(xQ+D0I=KEEHi2USL5Y+jSzcfQK+RNCb2Uoxld79ym216((tjv z19Cu*NM&MZibn${j<5#(t^yJxh;fB0=u+`~&WoORp33%A`!LTiAPUUpDut(ehY2qr zLFD>PoGpK)Ls#PrZ>Xhh{`@QX=Hop+S9-7MEg^aj-A;05-h?F|hWCCxDP6BLlvB@s zK3T+I#45b(ayw+Bd4wh1wDC#mfejtim$tnhV=&7oqzh#e=hm`S>*WIn23~)FeQrc_ znFYT7FmfvKX(3!coS*-E_pZeHiI}9#rLGU&pVZV`K-zeGZxMr(-=&%O@=z`*-J7k+ zs}si>S!NNzMyv?9WKSiiiJAbd_tb!EP-7IW?L8~baNMaWi3g0j@h~XMmo$*W?f{j5 z1dzf%1KOc(QB?VwAc+$McJpaizXa2G?(V; z5*eNF(;=uErTB#zhApvJo~`Qs-xnWw=-Yd8qPtv7G%hllT;T+gsl4DVr$=1Q+`NCc zhFhO~M62z%X0P4gUjy!2*IetKf+tj09{$B+>8>g{m5J-+pGv(?@BaXg6>#o7_0RlZ z^ezP3nr-TRcdZxU1iNhPY}?JPQr0q>7V!02E;{I4U{%5*gAs05IJKP(wpM3PZBMC&&%80s?^uC^b6Swhue_(C7}JB1gH(D^tIz|VGqlW-0Eh${n!A~PxG{IgU% z&If$LIgY|S)WG#*^=uS6f=*rRXQq;wcRMAOZ7P53 zXBhxb!EpO6Hr%XB?e1Se+g|Qy2aj#M9fb)I!=QP>`j}DCJX|U9l9-!L)h`Se*Jq{t z5*KG7&l3e+7c}FNn}&If7WVvPo)x;ll@*2u4o~>iJx*&ksmVhYCN{$GOpKR*I`Ch1 z!T*=Now>%(Z0r5fKVx$3sWJN?1lXDWSw(h-SjGf0`qDpxEPx40@ehJ7=5N8Mn0=IA zW61_0dZ|m7lx5J+)-9Bw>PfK5>Ij%(nMUcVOakwkn}O1NZ((!;p9CnF#c+f%ay6kF z8^x-}`>+lzCeSO}F-$yT;_NSV=WZv4o}6K85_vT49=VDFbtoP5v$$eHKsm7p(vWPzZlYxa zDmkzVP!!=qd@`!Im4tT?euTmCi3E8xK*9h}#2)T`vI}0sqFez19&L*^jSeH>gz3J? z2A}<__Q>sA{|(Du#8*qZ=B#DfsmGzxWrw|G(1(XU%N~zVy#yarSo}edQPFpT)bVpC#W7A`E@)pEtdF zmfr`^F=;4Bcq^JOHi9n1ji93CS)$eEeezjJeQOMi`*i7RM#S>X`h*BNQ9?3uEX*?z z7Rm(G3js%vubf-~GEhPSeTjguD3(e$?bp=;qQ#@4o-dXN`%^VnR{8+h$O_9-?)4JW z@=vJVqUsWnYm`S_#|+pSwN|1vz`e3=8AZ7jZN0jkp`&&C@;blN0b@63>;6mH8n?n* z2N5WkR_v)1G<#SJBmxe|4I~Z}18#z{6?!0wn{-0{VoCrQpq6@XH^x>;n-ir?UH`kp702S@T`xwBTHwZRguR(4 z%RL4U5)-7R2T#5s=sO!Xgz97kXMpy0AkIkssWd0_!rRl*$AgvpI3P1Y7!3SCFefV9p*YxNilIR~&3MJazcnqM2AWK69}DoVdvEOLtMX0*Ra)jUd9N`!k{q?hvBXMHO};`i?@Q=snW zIPjHUKl@8jpLM?RE2Ax4EBgt-7obIQ04&lw%PXQ9$jFi#A>xW&Ph{bo)Llghp;aoV zc+0n!m*uSIZAH(WTqok|ngCW-+Hh4cYiTpy-Pb{>$eh(R}#SSlq0 zeHy`KtX?-uj3N-@iYYUhCl|f=5~h>ritZH3!vI(e5Q5qYT*iS!Voxx{kqx7h2sscH z4cw6jq_SC7Tr%^aCZ)!@HjAf60d%w)Zg0w{vKYT1Opbi8PBE|`GcY^m0sFlImvAJbM^`+;$N7Pu6^Sh8EhUQkk*~dpuufKc%klMLS_SQHDNkxl7_;oEn zH!tKc_n^2j00}=fKvW^g_4pb(awE-YcrkhhNfiy504RWV~Kw910JB=_GnZhrFOhouQgte@M z$YB!Fh8Z-4K!echyi&2er6xp5jeWAZn(hmmJ2F?N%o}U3-|+Xh>Rr$C)Tb!MjJSKT zHy_5;T9HZvG7K+{|2clW^kv~KhNh-#-t^7H>UKs(+3kL%!sc;qu64B;T;vaWPQpFg<}uN00q!OfJp-iS$r0d7%gjT%}6OVs?xEKtwRX`#s_K#7a8^&WfY&bE%RC6 zxX?I$Q7eOy`{v2&u`w7fzlKO_J>s6a8vaz!{lCBB%NK4&Ym`|_ zt4PcN`>h+mAdD$!Qi;b{t)*9mawsB0gj6v!qnV^B99U$0v6tp;9~;Lf=xL$(nrCty zr2LBW`|saq*e-u)FgGc_B~;1yX_3Z}KQ6o1|9T#Vec-Wl3`*MH{~$b4m~JJda~y_E z$9+b5Ez*APj1md4DOyK&l6M%7?*}AuQYtsK#O=agNNBTZ`B<~-w^Tj%6wVXXKu)Pt z3nyKaN6Ki%+pXjtB+yx0GESia>ba2R40V*OvF~Z(0v!Q*T+fZEUgV=)j0~lKR~y>~ zb{%7^opAr1{eBwfkzB6HDR^=Xp#>pm+^<@u&6V0W4O8?;vc#F+CTFh zX&80}{VTr`y@oXs`=Y<`YjF6Ifdu8kC0in`bl!_dFpfS!k&eF)zUA%!ix?YM>`)q` zgbFPoi}v#|xH3Kw;~|X=mnLkj3~6|svxHi8YhvT7-eC0w>uewHm2u9$ z>LBmpczM&4Bd;03<*%j@f#FFjh1c-ZMV)RK?l&zV)xQLtp4DikQKS=#8Q>;P2#Bil zr=TndprmNNSz#EOvaLoB)J1Oqr7J8zG*FJgG!t7eS{zIQCS^Z*t%g{v&GS~Q1KA7^ ziPU8txEq}3wf2VNNn^J|si{6Ii?8LuQ%EWpezg$!4DL)ro(;?`BIcIbpTZdBJ@-DP z+3GOZ6bq@TLzV5Kmn%<+wpFGH)A_ox&+a4%X;c@IOg{YjakL^{b+q!VIKA>Xn#XU$ zk@z5%z=zTHd^Sq=&yf}TnhIShz@XDob3)L_t~SQb!!E(jDN5iS98X3S%x|b2{ga|$ zA9wf+gduSVm(j{t(_v(SwP~rAdTnR> z@}?o(2o*ka-Z|3zr9{B!ovo0B#cwKM$?E5bB5_QGP;#=Dt%lZe>Gmv=y5Rz=@YNCg z;k$TQeKSsl6<#Pg<96jrIg-`m&%u(0J;SFTJ!aOOaXsCACuy4BeUjtmz9pDXtl_Wx z>dE%smi(~l8^1w!m3)SD<6jwF8>-5Bn)&qO#iRQkO(m%-&j;c@4q$~|L}0g6^{D?M z#FZMJU)r$psN;Yw=?*iM_qpmGuN39Wvt-(lj;h`xIrg3-tyVjq;ajYt1XBVOuRph$ ze_mbLLOH92el#Q_gQKA+SFG?cjK@<`SmCFzk4{>l#CvC(fz{zf-}T99-UXQaHlV!C zQn>M%et_Gy3unVN;^I?jgM@zIf$#hP!`5jGEU&Ebsnq zv{Qf=%GD$Hg-7$J7v9cS73((;jE=1A*qW&6d+yB6V`ffb#@uYVt*U!7M-Q}YDePVw z{@arsMO{Ze9ecb#Xt~pv*d@ITHuKWz(b1EWSG4zUw#s?+8*hi9zrKrs-c5z{_JpQ~ ziR&^F{y0>#c~zcg-G(cg)TgOM+dCRFTaOx?d^A|UQ|Dx5=Fx3ew>u=(1&;;pTz6D7 zD75u)yFqbV*J-=DhsE#z+58$hkH1^K(vGHI6I)Idst%{vVa&mHiv=JXxz*S4lfb{w zZ^1`#PpO~cEh!Z4N8@~qL8+L2HHpeop=1%IWt@f}Cuzu#NJcgDqM3A&9jR-)+H)4A zj!_Rk>2lqW+rEyq)cef62RjwFdPaEfzjY@pyJL$Cp6(RpNQk5ta`q@-ZDN=e*@Y2V z+g#N2Y)!Nk)ipF_W$Akk#SLPrt2LFVR%>iT;vCgY>@D)dRXxKMEiNA1ARS~XTEDbT z(=GIno!*P&lgolMdPW!NRkbV>x_B`xXw}JOv|`si?pccQcDJdHlKzawR`-H|MTRRD ztzSxstywD`NeVb1fsZ>h%`b=Zaal-F)a0sf{8HOrcpjY4M3&>3{<)CD3plW7QD_av zy(o|KricaZI-17#^K{hKJB_Z^wuODB4c=Q@d-=wD=T~jd-A;=%c9kDZrQEW0wbXE; zc`ux|j2l9^FZDnM6#!0>(s0Qmpp}>^vNU0ROjVx}7yw^^l>SJ=XA5FusW z_h0n9)bhP*duOa#wuC5MhpfBfPqpjG)i%Ul^{99tJCwShHLYF3lA9nACFt zbb7UJ%^Jl`NuA8&mp4@U>1xL;TQAV}_Ws=`7x4Rc zuh75IC*b$r81&!$vVh+?US9#fbG(4xCttwt_xU&LXAAh9^%Bgc00FHZJME#UVD zm^gQ*5b!&9Yd51@!0#L{;P=TF@cVuK&HC8_erLS|vnfEp?`*pN19A)a{Q)M<-6;h8 z&fVJ0C>QWM#|!v<@&){UpMSG{wt(MRFTrdI5b!&j?*D+?0)BshiF0=f0l#y%b~DNa z{Lb+LexG~+zu)KIte-95ch*ZVn*s#<&Zhf6Ah&?uA7J9#okGCx+^yY=asj_{ynx>) G|9=3k{KeV; diff --git a/packages/frontend/assets/sounds/syuilo/new-eca-4va.mp3 b/packages/frontend/assets/sounds/syuilo/new-eca-4va.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..99f9361a31e8bb0eb4b475caa8fb8556157fa50a GIT binary patch literal 26880 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 literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/sounds/syuilo/new-eca-4vb.mp3 b/packages/frontend/assets/sounds/syuilo/new-eca-4vb.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..64cff5f2e76bd344ee37dc8f027e7906cde83861 GIT binary patch literal 26880 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 literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/sounds/syuilo/new-eca-8va.mp3 b/packages/frontend/assets/sounds/syuilo/new-eca-8va.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..2e39af1ede9b741ba97cda808edb5215291fe766 GIT binary patch literal 26880 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 literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/sounds/syuilo/new-eca-oct.mp3 b/packages/frontend/assets/sounds/syuilo/new-eca-oct.mp3 deleted file mode 100644 index 17c71cb98e4ad3760c8669cb130e09a54be43dd7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27943 zcmeI1X;>4<*2lZE6T%vnuuf!&fGiCJ2#OjIB4BXXWLKLl?uwuzib_K;AVwAujEI7Q z2#5-ZE6xxW5hVzSGCGbLK>>G0aJdNN4URMS{c=CdtIuVaH|NQd?y7WEo%~Pz`c!p$ zxY}ZXNn7e46ci*qk^lg`DSBPZ2EftQ5(2)|5~Z~fG3&n6xp;d?uf$2~e!s@g&rMoZ zl9t)wKXB|AmJaro)(|AE`@+%DXNXXBZhgi#owkd~VchoM?Ey6_r? zmlPMg`IPtc(uT46iz_DY7aJTyCw|sViw*Xm@E19HL=Jb%e-PhXlS6`Kw1RkyWvHsf83zQM6QfM{qc(0yWW|a>3{H*6ic}`|GkWRa$23|9&ZuyG zVmK2U$feG3TS-((ilJzs^8&#I?_w`2%W)Ai97fEEtt$&ydmtwsit~Psj7ZablL$r&fjsKFtTJ%5KcF3Arme^KH>neLJ{l)+`xfC zfC|eYVK|@)IJ%9y(?Pd8)!T}abG0u@H#*hPIs>GlP*h@isq4s<$jug>n=ZTc8T_`@ z=pd)or|bESUJzm1pW!ntKZ+AM?0J zgZf?AeqnUWqN1VlVQWI`QF{*(p^7ddi`gVWINM&khO+-k5fg0yz;~r^G(#kGK-jz~Ij~zTf5m1)= zW&4w-zuZ#R;2)sC@BF^A^sYhI`wmU!UjP7=b6r~$Cn}`ue&%;h?;MBtN6<%z$mPi4 zapq|(bsSBV&zhxN8luHHQo<@XEmbjb;pukn<~aWAI&S;91*zBLtxLUNFP5^ffQ1PU z>}PoI>Q`{L;$f84IiP^p0>IclssdGELv?FdzE)<)X!hWP^fied>vLin5Jf;&Ys3C~ zWOZZX8Jy7SlF|ZRxk@c3YC)~*)|;g_?}WB@OUC!@5_(7z#8|J-+~#^ocFD8is*Y-Z zVHJB5h{po3t1clMWGSF%L^&Ekr3HVOgNlJ#uxVlaibbQmIIG>btJmkUPv4tTeiXh9myhZq0x4`(GPTHqcip0BuS70GSA_RdEaw zZk2SlKSs_2PDE+;BEmX=81_Rds6eZ5BPy-Y2^ZfmfGub$(AfS2|5W_AaUP+u2SiAh z_*BPtN07Ufll;;EEa-h2yHlEPe_ubFq72cFpQI(=^ZMByt>j`(B7s7Pr^aO9u}w(` zOrRjqZJ5g)*(pxVHOs7M2RDjD9ofv)m~M-be0irm2Kj43&)OQKXS>aPctdjg{dm1Z z5@@X-DxL379G6Q*000FjGo>TAh81J!s6OIK*CveX613tbE6kuj&49X~g(DWUkS{xN z#_OC6i!c-dq9zdb%@8nQuKvJM8l{FMOy9~R@sq_i<~~55&kgjZ6>HlINXs#ZHAxR? zEYb!l7&zKhrWQ);6*m!$Wx^@|(>mEe*vPO&Q^3eRdq5bY^Q-xGYX(ICG9w}5ByQ(( zAgPsP##Oqev(I2)-pm*Z5r9jG2=hBMK!r#I0D%Z#{gpzWVg>~SXZ(ml(nx3kSbq@@ zD8~>bh4kP7Is}LTg_oKm7Eabd%aUSvze#G=xOWyTeH_z^!e7BjyEwAosD^iJGNLwL z@*wBvmL=8ab;S??z-?b_5T^#5;-&3x*}j>SD%EQI{@D$jN0JF!w0?k2#1m6~+Vu>0 zK*`X4wmT%AkwV{i=TCnB0m(%67yhyWpYt#2gYow+2NDq}P6|}%`dQg{-dn|qG->&B z{?&YkYNLQu1qu!}pva3E6vZM2MGiI-V3245gnSarXXXlYlURbp#tgx^UH1+LbXFfc z-TX%I%B4)O0eCBr2Y3`)ctE%Or%05~;hQ)=3YvTUISgp63^w<)(~kDU6t&Nm3knFs zC<_?GuqAdm^b(%iil^^aEFKwYt9eox?8MS*)Q&xNpBH^6+UiA};w{Fa%X*n}7W=Pp zxO07l&ETF-7LECK+6N*-dY*0UuNjZdTl&DlGW6sMz37lb`E6F$bT^K_t))M5+bCs1 z^7O!b^Eye!{E3^rCdrRK7!;Dx8;(F8pgbc`-x-kgRQZ4YNCtH z!iK*VLm9t+O|O60)xWQwhkL)jz^y+dX}x#gr%dU> zU~=5iYx0SbiKBUml1F*d2#RUs>OTyfzs2AA!tbNS)!f1gEE(F>sECen6Sl2F z^yj0RVU!snyy$Q%{>tM09=U3YwAD!m(_M$;0WABsPp2N(oifVL&pUl6V9y-W`9Ewv zxvlf(Ns=UGmC~C;TDT0A_(MunL010Vz~M6QHaR35b*;(Sve6)FKf8Z{n*s z8?d)3n`O`wQ}`~vh5VgG*GXjYGCr}$N<D!F110}P{H*~W#NkLIYF>_sQ2h4x{Xq+(1I$q%T+M$Tv+jnr7HlS8Q`_W_#> zVqg>p6v}ZxD!`NOuF`J8#h@a*IN29=00B4z)P|*dFqj5xQwAwa>?#%VA&3logc5`w zAv%%*c_6ir9N0HCAg|6Z>H z0VemqQhxiTyK25J7>)#?!V!0Xk%j69s{ofG>5C1jH5rJ90Yn+bAOuZ7ewK#A!_gC# zA)Ahm)~{J}YV*QJtF)iKTqxO5-|>o7Z@ESPBX@VsSzE2+2lLvOjJ=XfR1G{f&v3J7 z%8h<27rJ??V~AbIp>wC=3P04{OpKdod*1Tu?4`}ScU+IwGpad#!Ltz#S$eOZ(eoMe z|MfLiZth<_QgFesZp+F0Ek_=G`RUD)db5>oiYXqZX`Vo_PcqXq>n!SVmA4Auc4P*Q z;zXFCdeD1xHRoB~QBK(bLByu5-Pzo9J#crriBG1EUe|{+Se29e;;VD=EV6fLpvt)^ z%DcH&6jmkAlLM1ZqoFbk4HyDXdtT**yg1f#^mX_0v7fdCFZnUFF0b##o#O#Dy!>uO z2n6K4g4=?ZoDCGb_;h;Myn3vrP4aH^&2aFRw{7+H<6GW6y7t|TLofW;RjRLBLfUdH zZ+6(UUF`eVC#re<+t|jQ;GK*K#`AL()d$zQv3=g#Ke-xHO2oU?Pb?hI{gdCnMLLi< z@n2Tp_x$^AxjzHFyrSw${?)YeZdDvVBPIFs{@123(>X^~`KgZ`w|z#Ac~m8;OI5!P z#btv+fP@-SW0R3!wmfv1Z|uEHM1}R(a>zpwvsZVommox`#g4}haPAY4I^XcY&J1RI z4`MfGyMkFL+FkmhiY<>{l&oRka(K!k#cI`m@=)vu}I*eDK*yCpC^B%JJ)R zy$-mEvO_9L-q+mTxA)4vAnCm^%ck0&DjLNVN;Oz$x@8e$3F#>BkpztR{+))m55@$JKFjsA6J z+0ga#)Un2HW$y-axfEeERw!JAjuK`AQ5ZQnqyhk9&>0DGS?2_fNvvY0+dtS=1m%{S zpTDsFmgsq9sou$etD8-<0iQd21KO5cSP}TVFM~#-m4~F?+voW@-T&nB0gE6`~CT-v(Qaj2~2MR=e$I(?>>Q|Jn?Y@%z{G`iEWpJHPLV{#NKmYs6pp zC3~x^w|bK#I^j;a%%)A6P~&gB}ZEXiCnC*}ZOugF)VTs4b?qbiBO z7zGjxLcKm~m&S?0`}-v0`D~Av1flSx z0AJ)Iz*6-Nr-t%^KPH|KqML65`ruHLA_FS31P_rU!FFMhRT zIN@4C%Zp&N60S|%psaFDen#w^fQ)rNOZ*ch<4E>r2Y+)noJjdUQv2^&IKBC`32p>! zC|BP>uXruirU(`~)EEgJa2|*38jPUzU>W2K2q0Y$f&!BKA!ooBGIZ920-TNUnEh}a zm;z6rTVY3#2urXCEJ9t0{6O2c;{(|x@)+R??3v7gm6F!O&B-hn2MofqlPuvCN%}Af zfj8Ic4YW`$)$NP9waZl}h$gyNR_v73PB6pUoM4yP0JyMLEp1&AT=bY=AKsLT_Cl-b z)~{qkfJVf^ymdjH;rgK?WzN@f9lN~x!_y>abAx-O7FhKW-7}t{u1=+aGjV~BG<@H@`}vb%+?Jk4$8JpWTa-Ck zx6uMU8twaqU+B(Yt9;3#H=b2Q_lcm$L5(z(v8(k&|U`n3>ejy5$a%DIf9QM7|%LOny#Wa*@`D?QSB8oz~hSUmAffWf-LM zw9O;JiIi{yoIWO>L()d6`z*i`@OYEzWG)Ug+l_z+jxXS2K-(Pm8qek<$Bze=mn@@| z=DMTSKD)s^6A@?R_fx_3T}tKY`Ax*A(?xbROT9xHYwlWy=f~Zux><{=g9GnvQEF&a zwO3@O15fa|DMj~!k_{@AQ#j44u^Tb@DGGZ$T*-ae#vVbQtRY|mK>J~3e+8na<<*BD_ z)p5U^>p76H=*QgJuwnb@&F{bOLtl5sF#Gs=j@}}cZ58gE^_Xj{^+Ikibk8LZN=teM zu^P-E0ydTEfUmewn_(NWJLrm2|s0igp^p1s2sxH796x({rch9>MWBZ0^ zsDY$H$1zP9L|q>hTZTzTFsipg441E*Ri1S|pzDxr-jion_A*q|cB7#Z+Ke1Rqe-v7 zMdmT@xBeEpW*Ya=Q5%g)cCL;HSRB7LV%Z$;ZBe{xt!KBin-^X){myq&ZdzuB_km;c z9K)~Wm9D#%SKGY)^scBiA*((F+BCgBz3SqTP;BqJ&Rce;?4PVT7~v4Y%M2D+kwp#h z4_1$Ct8&l_;bmXG?J&vjcI4y5wI|RM5wTzRwR&*dYs0W9^9#Sb`(u9#K6GpLxovYp zx?ik2(Y2QDnu>Py^k=f^uDR6)1c0}2=Y~hT9EWqX9hhp~)kW6*n?ZXP=VNneARNbI z37qUDrD?~mTFH!fU#c zGiWG=fO#d-`l1Ch3-K&d57Ih5_jyFCnn|5;g$mA)%7Rnqw-XAYjJU2u1DmSnE~;%8 z8^lIlIKBpZNm2lKO5j4BTcSx-N#z_2hM?u-{hWJOv(ODBaQT*ga~RC6Fo}tc`x3 zdH-zeuS+I=SVnu^v5fE_?d0sm{v0X>Q5#ti^TaLJ*prZorYdM@=rw279$&&PVeoMo zdk&8s;t7ZeGgtpmi4NUqys^KxQ4o3!aE?t+$kz0z`U%1~Pzn#XnX=oB>&TriUIACW zSHpW;iW_apakD?jO(psD@Pd7X75mC<91N@?d>>oo#sA6gKl%Zb?9crN1%6*Y4*|d` z000PI_?5mwDv=hcU-*?xk^dmx-=SI-oWDa9rpyN!zf>w;5Q*@3+x$n)V{&cbW$7 z54UCf{-MPG%cG3nX&!bNztcQ`U+2Dz->=he%3I6$o$?S&r2{g4r&9fIFt&`}Zy@6I z?Lx-y^o`wT&t?2h^8kLG`!asNPQNK{E#r5}Lok&N$oQQ~^}oT`GJd~-h|{+V8Nbsv zcAq_$@jJ}}_;v2f`29Nlro6R`-zg8lR5~EzcPiEY24l-3xQ)-rylJOoqefQ;X%RR0@{E#vnah&X+_knuZxWB1u}8Nbs!fM4hS F{{TtF0c`*P diff --git a/packages/frontend/assets/sounds/syuilo/new-eca.mp3 b/packages/frontend/assets/sounds/syuilo/new-eca.mp3 index 433da56cbaa715c84be291899643d1391570581e..82969479dc7188101a18040a10a4f85224a78158 100644 GIT binary patch literal 26880 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 K|LOm!8~ATl{Bc|W literal 27943 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 export const soundsTypes = [ null, - 'syuilo/new-eca', - 'syuilo/new-cea', + 'syuilo/new-aec-4va', + 'syuilo/new-aec-4vb', + 'syuilo/new-aec-8va', + 'syuilo/new-aec-8vb', 'syuilo/new-aec', - 'syuilo/new-eca-oct', - 'syuilo/new-cea-oct', - 'syuilo/new-aec-oct', + 'syuilo/new-cea-4va', + 'syuilo/new-cea-4vb', + 'syuilo/new-cea-8va', + 'syuilo/new-cea-8vb', + 'syuilo/new-cea', + 'syuilo/new-eca-4va', + 'syuilo/new-eca-4vb', + 'syuilo/new-eca-8va', + 'syuilo/new-eca-8vb', + 'syuilo/new-eca', 'syuilo/up', 'syuilo/down', 'syuilo/pope1', From fdf760507492ffe40d822e1753545612bfcdb760 Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 2 Mar 2023 14:38:45 +0900 Subject: [PATCH 272/294] refactor(client): use css modules --- packages/frontend/src/pages/admin/users.vue | 115 +++++++++----------- 1 file changed, 51 insertions(+), 64 deletions(-) diff --git a/packages/frontend/src/pages/admin/users.vue b/packages/frontend/src/pages/admin/users.vue index fc1c1c1dc5..819ced826d 100644 --- a/packages/frontend/src/pages/admin/users.vue +++ b/packages/frontend/src/pages/admin/users.vue @@ -3,48 +3,48 @@ -

-
-
- - - - - - - - - - - - - - - - - - - - - -
-
- - - - - - - - -
+
+
+ + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
- - + +
+ - -
+
+
@@ -138,33 +138,20 @@ definePageMetadata(computed(() => ({ }))); - From 896400a6c90500f8f9c02b578fecf50cbadf7621 Mon Sep 17 00:00:00 2001 From: Kagami Sascha Rosylight Date: Thu, 2 Mar 2023 07:05:05 +0100 Subject: [PATCH 273/294] refactor(frontend): add explicit `Promise` return types in `os.ts` (#10156) --- packages/frontend/src/os.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/frontend/src/os.ts b/packages/frontend/src/os.ts index 7e38fe5f6d..f0af9f081b 100644 --- a/packages/frontend/src/os.ts +++ b/packages/frontend/src/os.ts @@ -362,7 +362,7 @@ export function select(props: { }); } -export function success() { +export function success(): Promise { return new Promise((resolve, reject) => { const showing = ref(true); window.setTimeout(() => { @@ -377,7 +377,7 @@ export function success() { }); } -export function waiting() { +export function waiting(): Promise { return new Promise((resolve, reject) => { const showing = ref(true); popup(MkWaitingDialog, { @@ -528,7 +528,7 @@ export function popupMenu(items: MenuItem[] | Ref, src?: HTMLElement width?: number; viaKeyboard?: boolean; onClosing?: () => void; -}) { +}): Promise { return new Promise((resolve, reject) => { let dispose; popup(MkPopupMenu, { @@ -551,7 +551,7 @@ export function popupMenu(items: MenuItem[] | Ref, src?: HTMLElement }); } -export function contextMenu(items: MenuItem[] | Ref, ev: MouseEvent) { +export function contextMenu(items: MenuItem[] | Ref, ev: MouseEvent): Promise { ev.preventDefault(); return new Promise((resolve, reject) => { let dispose; @@ -569,7 +569,7 @@ export function contextMenu(items: MenuItem[] | Ref, ev: MouseEvent) }); } -export function post(props: Record = {}) { +export function post(props: Record = {}): Promise { return new Promise((resolve, reject) => { // NOTE: MkPostFormDialogをdynamic importするとiOSでテキストエリアに自動フォーカスできない // NOTE: ただ、dynamic importしない場合、MkPostFormDialogインスタンスが使いまわされ、 From dad915e5221d99ceeb7b35b3ca1cbbf52a02f0f3 Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 2 Mar 2023 18:40:43 +0900 Subject: [PATCH 274/294] enhance(client): provide sticktyFooter --- packages/frontend/src/components/MkNote.vue | 16 +++++----- .../components/global/MkStickyContainer.vue | 32 +++++++++++++++---- packages/frontend/src/const.ts | 6 ++++ packages/frontend/src/ui/universal.vue | 25 ++++++++++++--- 4 files changed, 60 insertions(+), 19 deletions(-) diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue index b87d46ee94..bb1269562d 100644 --- a/packages/frontend/src/components/MkNote.vue +++ b/packages/frontend/src/components/MkNote.vue @@ -289,12 +289,12 @@ function renote(viaKeyboard = false) { icon: 'ti ti-repeat', action: () => { const el = renoteButton.value as HTMLElement | null | undefined; - if (el) { - const rect = el.getBoundingClientRect(); - const x = rect.left + (el.offsetWidth / 2); - const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); - } + if (el) { + const rect = el.getBoundingClientRect(); + const x = rect.left + (el.offsetWidth / 2); + const y = rect.top + (el.offsetHeight / 2); + os.popup(MkRippleEffect, { x, y }, {}, 'end'); + } os.api('notes/create', { renoteId: appearNote.id, @@ -622,9 +622,9 @@ function showReactions(): void { .showLess { width: 100%; - margin-top: 1em; + margin-top: 14px; position: sticky; - bottom: 1em; + bottom: calc(var(--stickyBottom, 0px) + 14px); } .showLessLabel { diff --git a/packages/frontend/src/components/global/MkStickyContainer.vue b/packages/frontend/src/components/global/MkStickyContainer.vue index a3fee91a36..3f9c1bc353 100644 --- a/packages/frontend/src/components/global/MkStickyContainer.vue +++ b/packages/frontend/src/components/global/MkStickyContainer.vue @@ -6,20 +6,19 @@
+
+ +
- - diff --git a/packages/frontend/src/pages/admin/object-storage.vue b/packages/frontend/src/pages/admin/object-storage.vue index bd7c203512..cbe38b2d81 100644 --- a/packages/frontend/src/pages/admin/object-storage.vue +++ b/packages/frontend/src/pages/admin/object-storage.vue @@ -1,6 +1,6 @@ @@ -79,6 +86,7 @@ import * as os from '@/os'; import { fetchInstance } from '@/instance'; import { i18n } from '@/i18n'; import { definePageMetadata } from '@/scripts/page-metadata'; +import MkButton from '@/components/MkButton.vue'; let useObjectStorage: boolean = $ref(false); let objectStorageBaseUrl: string | null = $ref(null); @@ -131,13 +139,6 @@ function save() { }); } -const headerActions = $computed(() => [{ - asFullButton: true, - icon: 'ti ti-check', - text: i18n.ts.save, - handler: save, -}]); - const headerTabs = $computed(() => []); definePageMetadata({ @@ -145,3 +146,10 @@ definePageMetadata({ icon: 'ti ti-cloud', }); + + diff --git a/packages/frontend/src/pages/admin/roles.edit.vue b/packages/frontend/src/pages/admin/roles.edit.vue index ae884c0111..2a65a75187 100644 --- a/packages/frontend/src/pages/admin/roles.edit.vue +++ b/packages/frontend/src/pages/admin/roles.edit.vue @@ -1,22 +1,31 @@ diff --git a/packages/frontend/src/pages/admin/roles.editor.vue b/packages/frontend/src/pages/admin/roles.editor.vue index 4eea827de7..2fb605f8c0 100644 --- a/packages/frontend/src/pages/admin/roles.editor.vue +++ b/packages/frontend/src/pages/admin/roles.editor.vue @@ -1,19 +1,19 @@ diff --git a/packages/frontend/src/pages/my-lists/list.vue b/packages/frontend/src/pages/my-lists/list.vue index a6a3974d0c..037d00d8ff 100644 --- a/packages/frontend/src/pages/my-lists/list.vue +++ b/packages/frontend/src/pages/my-lists/list.vue @@ -1,33 +1,30 @@ @@ -130,6 +127,10 @@ definePageMetadata(computed(() => list ? { From cf8a7f93d5b67163272bb75064b090d82a6700e9 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 3 Mar 2023 08:48:52 +0900 Subject: [PATCH 277/294] :art: --- packages/frontend/src/components/MkWindow.vue | 2 +- packages/frontend/src/directives/container.ts | 21 +++++++++++++++++++ packages/frontend/src/directives/index.ts | 2 ++ packages/frontend/src/pages/my-lists/list.vue | 2 +- packages/frontend/src/ui/deck/column.vue | 2 +- packages/frontend/src/ui/universal.vue | 2 +- 6 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 packages/frontend/src/directives/container.ts diff --git a/packages/frontend/src/components/MkWindow.vue b/packages/frontend/src/components/MkWindow.vue index f7565ca59f..e7ad2b9a43 100644 --- a/packages/frontend/src/components/MkWindow.vue +++ b/packages/frontend/src/components/MkWindow.vue @@ -23,7 +23,7 @@
-
+
diff --git a/packages/frontend/src/directives/container.ts b/packages/frontend/src/directives/container.ts new file mode 100644 index 0000000000..a8a93eb9be --- /dev/null +++ b/packages/frontend/src/directives/container.ts @@ -0,0 +1,21 @@ +import { Directive } from 'vue'; + +const map = new WeakMap(); + +export default { + mounted(el: HTMLElement, binding, vn) { + const ro = new ResizeObserver((entries, observer) => { + el.style.setProperty('--containerHeight', el.offsetHeight + 'px'); + }); + ro.observe(el); + map.set(el, ro); + }, + + unmounted(el, binding, vn) { + const ro = map.get(el); + if (ro) { + ro.disconnect(); + map.delete(el); + } + }, +} as Directive; diff --git a/packages/frontend/src/directives/index.ts b/packages/frontend/src/directives/index.ts index a690fd6c42..854f0a544e 100644 --- a/packages/frontend/src/directives/index.ts +++ b/packages/frontend/src/directives/index.ts @@ -11,6 +11,7 @@ import clickAnime from './click-anime'; import panel from './panel'; import adaptiveBorder from './adaptive-border'; import adaptiveBg from './adaptive-bg'; +import container from './container'; export default function(app: App) { app.directive('userPreview', userPreview); @@ -25,4 +26,5 @@ export default function(app: App) { app.directive('panel', panel); app.directive('adaptive-border', adaptiveBorder); app.directive('adaptive-bg', adaptiveBg); + app.directive('container', container); } diff --git a/packages/frontend/src/pages/my-lists/list.vue b/packages/frontend/src/pages/my-lists/list.vue index 037d00d8ff..205434971d 100644 --- a/packages/frontend/src/pages/my-lists/list.vue +++ b/packages/frontend/src/pages/my-lists/list.vue @@ -128,7 +128,7 @@ definePageMetadata(computed(() => list ? { diff --git a/packages/frontend/src/components/MkUserPreview.vue b/packages/frontend/src/components/MkUserPreview.vue deleted file mode 100644 index 1086a2c651..0000000000 --- a/packages/frontend/src/components/MkUserPreview.vue +++ /dev/null @@ -1,199 +0,0 @@ - - - - - diff --git a/packages/frontend/src/directives/user-preview.ts b/packages/frontend/src/directives/user-preview.ts index ed5f00ca65..2f5936de3d 100644 --- a/packages/frontend/src/directives/user-preview.ts +++ b/packages/frontend/src/directives/user-preview.ts @@ -24,7 +24,7 @@ export class UserPreview { const showing = ref(true); - popup(defineAsyncComponent(() => import('@/components/MkUserPreview.vue')), { + popup(defineAsyncComponent(() => import('@/components/MkUserPopup.vue')), { showing, q: this.user, source: this.el, From af24011eecbf327dc664971aaba126554383f9e5 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 3 Mar 2023 12:31:41 +0900 Subject: [PATCH 287/294] clean up --- packages/frontend/src/pages/about-misskey.vue | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/frontend/src/pages/about-misskey.vue b/packages/frontend/src/pages/about-misskey.vue index a72e5bb4c9..51c3de43fe 100644 --- a/packages/frontend/src/pages/about-misskey.vue +++ b/packages/frontend/src/pages/about-misskey.vue @@ -84,10 +84,6 @@

{{ i18n.ts._aboutMisskey.morePatrons }}

- - -

Misskeyで使われる画像の一部は、許可を得て「あの子がこっちを見てるメーカー」で作成したものが含まれます。

-
From 1b33653f1ba6963b08de56fdcfaa9d177abe7db4 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 3 Mar 2023 12:32:05 +0900 Subject: [PATCH 288/294] 13.9.0 --- CHANGELOG.md | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 199660542f..2bf0aed022 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ You should also include the user name that made the change. --> -## 13.x.x (unreleased) +## 13.9.0 (2023/03/03) ### Improvements - 時限ロール diff --git a/package.json b/package.json index 2dec3f31fd..b870d8507d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "13.8.1", + "version": "13.9.0", "codename": "nasubi", "repository": { "type": "git", From 5d46c1c9bbad06a56b180a072f4b9a998662b041 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 3 Mar 2023 14:55:56 +0900 Subject: [PATCH 289/294] =?UTF-8?q?=EF=BC=88CSS=E5=AE=8C=E5=85=A8=E3=81=AB?= =?UTF-8?q?=EF=BC=89=E7=90=86=E8=A7=A3=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/frontend/src/components/MkUserPopup.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/components/MkUserPopup.vue b/packages/frontend/src/components/MkUserPopup.vue index 0720c8eea6..93e914f6dd 100644 --- a/packages/frontend/src/components/MkUserPopup.vue +++ b/packages/frontend/src/components/MkUserPopup.vue @@ -215,7 +215,7 @@ onMounted(() => { } .follow { - position: absolute; + position: absolute !important; top: 8px; right: 8px; } From da3fcf178e45ccaf7b2ca81fa03f029968777018 Mon Sep 17 00:00:00 2001 From: tamaina Date: Fri, 3 Mar 2023 06:12:34 +0000 Subject: [PATCH 290/294] fix CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2bf0aed022..9a5e6da4f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,6 @@ You should also include the user name that made the change. ### Improvements - 時限ロール -- プッシュ通知でカスタム絵文字リアクションを表示できるように - アンテナでCWも検索対象にするように - ノートの操作部をホバー時のみ表示するオプションを追加 - サウンドを追加 @@ -24,6 +23,7 @@ You should also include the user name that made the change. - 外部メディアプロキシ使用時にアバタークロップができない問題を修正 - fix(server): メールアドレス更新時にバリデーションが正しく行われていないのを修正 - fix(server): チャンネルでミュートが正しく機能していないのを修正 +- プッシュ通知でカスタム絵文字リアクションを表示できなかった問題を修正 ## 13.8.1 (2023/02/26) From a7c82eeabcc732e76c5c358c98812cac8457d57f Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 3 Mar 2023 20:26:44 +0900 Subject: [PATCH 291/294] Revert "fix(server): DriveFile related N+1 query when call note packMany (#10133)" This reverts commit 452a48e7f4782cf9bdf08b554264ab3cdcb12685. --- .../core/entities/DriveFileEntityService.ts | 24 +----- .../core/entities/GalleryPostEntityService.ts | 3 +- .../src/core/entities/NoteEntityService.ts | 8 +- .../entities/NotificationEntityService.ts | 84 ++++++++++++------- packages/backend/src/misc/is-not-null.ts | 5 -- 5 files changed, 58 insertions(+), 66 deletions(-) delete mode 100644 packages/backend/src/misc/is-not-null.ts diff --git a/packages/backend/src/core/entities/DriveFileEntityService.ts b/packages/backend/src/core/entities/DriveFileEntityService.ts index f5b1f98153..158fafa9d5 100644 --- a/packages/backend/src/core/entities/DriveFileEntityService.ts +++ b/packages/backend/src/core/entities/DriveFileEntityService.ts @@ -1,5 +1,5 @@ import { forwardRef, Inject, Injectable } from '@nestjs/common'; -import { DataSource, In } from 'typeorm'; +import { DataSource } from 'typeorm'; import { DI } from '@/di-symbols.js'; import type { NotesRepository, DriveFilesRepository } from '@/models/index.js'; import type { Config } from '@/config.js'; @@ -21,7 +21,6 @@ type PackOptions = { }; import { bindThis } from '@/decorators.js'; import { isMimeImage } from '@/misc/is-mime-image.js'; -import { isNotNull } from '@/misc/is-not-null.js'; @Injectable() export class DriveFileEntityService { @@ -256,29 +255,10 @@ export class DriveFileEntityService { @bindThis public async packMany( - files: DriveFile[], + files: (DriveFile['id'] | DriveFile)[], options?: PackOptions, ): Promise[]> { const items = await Promise.all(files.map(f => this.packNullable(f, options))); return items.filter((x): x is Packed<'DriveFile'> => x != null); } - - @bindThis - public async packManyByIdsMap( - fileIds: DriveFile['id'][], - options?: PackOptions, - ): Promise['id'], Packed<'DriveFile'>>> { - const files = await this.driveFilesRepository.findBy({ id: In(fileIds) }); - const packedFiles = await this.packMany(files, options); - return new Map(packedFiles.map(f => [f.id, f])); - } - - @bindThis - public async packManyByIds( - fileIds: DriveFile['id'][], - options?: PackOptions, - ): Promise[]> { - const filesMap = await this.packManyByIdsMap(fileIds, options); - return fileIds.map(id => filesMap.get(id)).filter(isNotNull); - } } diff --git a/packages/backend/src/core/entities/GalleryPostEntityService.ts b/packages/backend/src/core/entities/GalleryPostEntityService.ts index fb147ae181..ab29e7dba1 100644 --- a/packages/backend/src/core/entities/GalleryPostEntityService.ts +++ b/packages/backend/src/core/entities/GalleryPostEntityService.ts @@ -41,8 +41,7 @@ export class GalleryPostEntityService { title: post.title, description: post.description, fileIds: post.fileIds, - // TODO: packMany causes N+1 queries - files: this.driveFileEntityService.packManyByIds(post.fileIds), + files: this.driveFileEntityService.packMany(post.fileIds), tags: post.tags.length > 0 ? post.tags : undefined, isSensitive: post.isSensitive, likedCount: post.likedCount, diff --git a/packages/backend/src/core/entities/NoteEntityService.ts b/packages/backend/src/core/entities/NoteEntityService.ts index c732a98a11..2ffe5f1c21 100644 --- a/packages/backend/src/core/entities/NoteEntityService.ts +++ b/packages/backend/src/core/entities/NoteEntityService.ts @@ -11,7 +11,6 @@ import type { Note } from '@/models/entities/Note.js'; import type { NoteReaction } from '@/models/entities/NoteReaction.js'; import type { UsersRepository, NotesRepository, FollowingsRepository, PollsRepository, PollVotesRepository, NoteReactionsRepository, ChannelsRepository, DriveFilesRepository } from '@/models/index.js'; import { bindThis } from '@/decorators.js'; -import { isNotNull } from '@/misc/is-not-null.js'; import type { OnModuleInit } from '@nestjs/common'; import type { CustomEmojiService } from '../CustomEmojiService.js'; import type { ReactionService } from '../ReactionService.js'; @@ -258,7 +257,6 @@ export class NoteEntityService implements OnModuleInit { skipHide?: boolean; _hint_?: { myReactions: Map; - packedFiles: Map>; }; }, ): Promise> { @@ -286,7 +284,6 @@ export class NoteEntityService implements OnModuleInit { const reactionEmojiNames = Object.keys(note.reactions) .filter(x => x.startsWith(':') && x.includes('@') && !x.includes('@.')) // リモートカスタム絵文字のみ .map(x => this.reactionService.decodeReaction(x).reaction.replaceAll(':', '')); - const packedFiles = options?._hint_?.packedFiles; const packed: Packed<'Note'> = await awaitAll({ id: note.id, @@ -307,7 +304,7 @@ export class NoteEntityService implements OnModuleInit { emojis: host != null ? this.customEmojiService.populateEmojis(note.emojis, host) : undefined, tags: note.tags.length > 0 ? note.tags : undefined, fileIds: note.fileIds, - files: packedFiles != null ? note.fileIds.map(fi => packedFiles.get(fi)).filter(isNotNull) : this.driveFileEntityService.packManyByIds(note.fileIds), + files: this.driveFileEntityService.packMany(note.fileIds), replyId: note.replyId, renoteId: note.renoteId, channelId: note.channelId ?? undefined, @@ -391,14 +388,11 @@ export class NoteEntityService implements OnModuleInit { } await this.customEmojiService.prefetchEmojis(this.customEmojiService.aggregateNoteEmojis(notes)); - const fileIds = notes.flatMap(n => n.fileIds); - const packedFiles = await this.driveFileEntityService.packManyByIdsMap(fileIds); return await Promise.all(notes.map(n => this.pack(n, me, { ...options, _hint_: { myReactions: myReactionsMap, - packedFiles, }, }))); } diff --git a/packages/backend/src/core/entities/NotificationEntityService.ts b/packages/backend/src/core/entities/NotificationEntityService.ts index be88a213f4..33c76c6937 100644 --- a/packages/backend/src/core/entities/NotificationEntityService.ts +++ b/packages/backend/src/core/entities/NotificationEntityService.ts @@ -1,21 +1,19 @@ import { Inject, Injectable } from '@nestjs/common'; +import { In } from 'typeorm'; import { ModuleRef } from '@nestjs/core'; import { DI } from '@/di-symbols.js'; import type { AccessTokensRepository, NoteReactionsRepository, NotificationsRepository, User } from '@/models/index.js'; import { awaitAll } from '@/misc/prelude/await-all.js'; import type { Notification } from '@/models/entities/Notification.js'; +import type { NoteReaction } from '@/models/entities/NoteReaction.js'; import type { Note } from '@/models/entities/Note.js'; import type { Packed } from '@/misc/schema.js'; import { bindThis } from '@/decorators.js'; -import { isNotNull } from '@/misc/is-not-null.js'; -import { notificationTypes } from '@/types.js'; import type { OnModuleInit } from '@nestjs/common'; import type { CustomEmojiService } from '../CustomEmojiService.js'; import type { UserEntityService } from './UserEntityService.js'; import type { NoteEntityService } from './NoteEntityService.js'; -const NOTE_REQUIRED_NOTIFICATION_TYPES = new Set(['mention', 'reply', 'renote', 'quote', 'reaction', 'pollEnded'] as (typeof notificationTypes[number])[]); - @Injectable() export class NotificationEntityService implements OnModuleInit { private userEntityService: UserEntityService; @@ -50,20 +48,13 @@ export class NotificationEntityService implements OnModuleInit { public async pack( src: Notification['id'] | Notification, options: { - _hint_?: { - packedNotes: Map>; + _hintForEachNotes_?: { + myReactions: Map; }; }, ): Promise> { const notification = typeof src === 'object' ? src : await this.notificationsRepository.findOneByOrFail({ id: src }); const token = notification.appAccessTokenId ? await this.accessTokensRepository.findOneByOrFail({ id: notification.appAccessTokenId }) : null; - const noteIfNeed = NOTE_REQUIRED_NOTIFICATION_TYPES.has(notification.type) && notification.noteId != null ? ( - options._hint_?.packedNotes != null - ? options._hint_.packedNotes.get(notification.noteId) - : this.noteEntityService.pack(notification.note ?? notification.noteId!, { id: notification.notifieeId }, { - detail: true, - }) - ) : undefined; return await awaitAll({ id: notification.id, @@ -72,10 +63,43 @@ export class NotificationEntityService implements OnModuleInit { isRead: notification.isRead, userId: notification.notifierId, user: notification.notifierId ? this.userEntityService.pack(notification.notifier ?? notification.notifierId) : null, - ...(noteIfNeed != null ? { note: noteIfNeed } : {}), + ...(notification.type === 'mention' ? { + note: this.noteEntityService.pack(notification.note ?? notification.noteId!, { id: notification.notifieeId }, { + detail: true, + _hint_: options._hintForEachNotes_, + }), + } : {}), + ...(notification.type === 'reply' ? { + note: this.noteEntityService.pack(notification.note ?? notification.noteId!, { id: notification.notifieeId }, { + detail: true, + _hint_: options._hintForEachNotes_, + }), + } : {}), + ...(notification.type === 'renote' ? { + note: this.noteEntityService.pack(notification.note ?? notification.noteId!, { id: notification.notifieeId }, { + detail: true, + _hint_: options._hintForEachNotes_, + }), + } : {}), + ...(notification.type === 'quote' ? { + note: this.noteEntityService.pack(notification.note ?? notification.noteId!, { id: notification.notifieeId }, { + detail: true, + _hint_: options._hintForEachNotes_, + }), + } : {}), ...(notification.type === 'reaction' ? { + note: this.noteEntityService.pack(notification.note ?? notification.noteId!, { id: notification.notifieeId }, { + detail: true, + _hint_: options._hintForEachNotes_, + }), reaction: notification.reaction, } : {}), + ...(notification.type === 'pollEnded' ? { + note: this.noteEntityService.pack(notification.note ?? notification.noteId!, { id: notification.notifieeId }, { + detail: true, + _hint_: options._hintForEachNotes_, + }), + } : {}), ...(notification.type === 'achievementEarned' ? { achievement: notification.achievement, } : {}), @@ -87,32 +111,32 @@ export class NotificationEntityService implements OnModuleInit { }); } - /** - * @param notifications you should join "note" property when fetch from DB, and all notifieeId should be same as meId - */ @bindThis public async packMany( notifications: Notification[], meId: User['id'], ) { if (notifications.length === 0) return []; - - for (const notification of notifications) { - if (meId !== notification.notifieeId) { - // because we call note packMany with meId, all notifieeId should be same as meId - throw new Error('TRY_TO_PACK_ANOTHER_USER_NOTIFICATION'); - } + + const notes = notifications.filter(x => x.note != null).map(x => x.note!); + const noteIds = notes.map(n => n.id); + const myReactionsMap = new Map(); + const renoteIds = notes.filter(n => n.renoteId != null).map(n => n.renoteId!); + const targets = [...noteIds, ...renoteIds]; + const myReactions = await this.noteReactionsRepository.findBy({ + userId: meId, + noteId: In(targets), + }); + + for (const target of targets) { + myReactionsMap.set(target, myReactions.find(reaction => reaction.noteId === target) ?? null); } - const notes = notifications.map(x => x.note).filter(isNotNull); - const packedNotesArray = await this.noteEntityService.packMany(notes, { id: meId }, { - detail: true, - }); - const packedNotes = new Map(packedNotesArray.map(p => [p.id, p])); + await this.customEmojiService.prefetchEmojis(this.customEmojiService.aggregateNoteEmojis(notes)); return await Promise.all(notifications.map(x => this.pack(x, { - _hint_: { - packedNotes, + _hintForEachNotes_: { + myReactions: myReactionsMap, }, }))); } diff --git a/packages/backend/src/misc/is-not-null.ts b/packages/backend/src/misc/is-not-null.ts deleted file mode 100644 index d89a1957be..0000000000 --- a/packages/backend/src/misc/is-not-null.ts +++ /dev/null @@ -1,5 +0,0 @@ -// we are using {} as "any non-nullish value" as expected -// eslint-disable-next-line @typescript-eslint/ban-types -export function isNotNull(input: T | undefined | null): input is T { - return input != null; -} From ad7ecbaf376d87f5f870572129aeee334e65443b Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 3 Mar 2023 20:43:31 +0900 Subject: [PATCH 292/294] =?UTF-8?q?=E9=80=9A=E7=9F=A5=E9=83=A8=E5=88=86?= =?UTF-8?q?=E3=81=AF=E6=AE=8B=E3=81=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: rinsuki <428rinsuki+contact.github@gmail.com> --- .../entities/NotificationEntityService.ts | 84 +++++++------------ packages/backend/src/misc/is-not-null.ts | 5 ++ 2 files changed, 35 insertions(+), 54 deletions(-) create mode 100644 packages/backend/src/misc/is-not-null.ts diff --git a/packages/backend/src/core/entities/NotificationEntityService.ts b/packages/backend/src/core/entities/NotificationEntityService.ts index 33c76c6937..be88a213f4 100644 --- a/packages/backend/src/core/entities/NotificationEntityService.ts +++ b/packages/backend/src/core/entities/NotificationEntityService.ts @@ -1,19 +1,21 @@ import { Inject, Injectable } from '@nestjs/common'; -import { In } from 'typeorm'; import { ModuleRef } from '@nestjs/core'; import { DI } from '@/di-symbols.js'; import type { AccessTokensRepository, NoteReactionsRepository, NotificationsRepository, User } from '@/models/index.js'; import { awaitAll } from '@/misc/prelude/await-all.js'; import type { Notification } from '@/models/entities/Notification.js'; -import type { NoteReaction } from '@/models/entities/NoteReaction.js'; import type { Note } from '@/models/entities/Note.js'; import type { Packed } from '@/misc/schema.js'; import { bindThis } from '@/decorators.js'; +import { isNotNull } from '@/misc/is-not-null.js'; +import { notificationTypes } from '@/types.js'; import type { OnModuleInit } from '@nestjs/common'; import type { CustomEmojiService } from '../CustomEmojiService.js'; import type { UserEntityService } from './UserEntityService.js'; import type { NoteEntityService } from './NoteEntityService.js'; +const NOTE_REQUIRED_NOTIFICATION_TYPES = new Set(['mention', 'reply', 'renote', 'quote', 'reaction', 'pollEnded'] as (typeof notificationTypes[number])[]); + @Injectable() export class NotificationEntityService implements OnModuleInit { private userEntityService: UserEntityService; @@ -48,13 +50,20 @@ export class NotificationEntityService implements OnModuleInit { public async pack( src: Notification['id'] | Notification, options: { - _hintForEachNotes_?: { - myReactions: Map; + _hint_?: { + packedNotes: Map>; }; }, ): Promise> { const notification = typeof src === 'object' ? src : await this.notificationsRepository.findOneByOrFail({ id: src }); const token = notification.appAccessTokenId ? await this.accessTokensRepository.findOneByOrFail({ id: notification.appAccessTokenId }) : null; + const noteIfNeed = NOTE_REQUIRED_NOTIFICATION_TYPES.has(notification.type) && notification.noteId != null ? ( + options._hint_?.packedNotes != null + ? options._hint_.packedNotes.get(notification.noteId) + : this.noteEntityService.pack(notification.note ?? notification.noteId!, { id: notification.notifieeId }, { + detail: true, + }) + ) : undefined; return await awaitAll({ id: notification.id, @@ -63,43 +72,10 @@ export class NotificationEntityService implements OnModuleInit { isRead: notification.isRead, userId: notification.notifierId, user: notification.notifierId ? this.userEntityService.pack(notification.notifier ?? notification.notifierId) : null, - ...(notification.type === 'mention' ? { - note: this.noteEntityService.pack(notification.note ?? notification.noteId!, { id: notification.notifieeId }, { - detail: true, - _hint_: options._hintForEachNotes_, - }), - } : {}), - ...(notification.type === 'reply' ? { - note: this.noteEntityService.pack(notification.note ?? notification.noteId!, { id: notification.notifieeId }, { - detail: true, - _hint_: options._hintForEachNotes_, - }), - } : {}), - ...(notification.type === 'renote' ? { - note: this.noteEntityService.pack(notification.note ?? notification.noteId!, { id: notification.notifieeId }, { - detail: true, - _hint_: options._hintForEachNotes_, - }), - } : {}), - ...(notification.type === 'quote' ? { - note: this.noteEntityService.pack(notification.note ?? notification.noteId!, { id: notification.notifieeId }, { - detail: true, - _hint_: options._hintForEachNotes_, - }), - } : {}), + ...(noteIfNeed != null ? { note: noteIfNeed } : {}), ...(notification.type === 'reaction' ? { - note: this.noteEntityService.pack(notification.note ?? notification.noteId!, { id: notification.notifieeId }, { - detail: true, - _hint_: options._hintForEachNotes_, - }), reaction: notification.reaction, } : {}), - ...(notification.type === 'pollEnded' ? { - note: this.noteEntityService.pack(notification.note ?? notification.noteId!, { id: notification.notifieeId }, { - detail: true, - _hint_: options._hintForEachNotes_, - }), - } : {}), ...(notification.type === 'achievementEarned' ? { achievement: notification.achievement, } : {}), @@ -111,32 +87,32 @@ export class NotificationEntityService implements OnModuleInit { }); } + /** + * @param notifications you should join "note" property when fetch from DB, and all notifieeId should be same as meId + */ @bindThis public async packMany( notifications: Notification[], meId: User['id'], ) { if (notifications.length === 0) return []; - - const notes = notifications.filter(x => x.note != null).map(x => x.note!); - const noteIds = notes.map(n => n.id); - const myReactionsMap = new Map(); - const renoteIds = notes.filter(n => n.renoteId != null).map(n => n.renoteId!); - const targets = [...noteIds, ...renoteIds]; - const myReactions = await this.noteReactionsRepository.findBy({ - userId: meId, - noteId: In(targets), - }); - - for (const target of targets) { - myReactionsMap.set(target, myReactions.find(reaction => reaction.noteId === target) ?? null); + + for (const notification of notifications) { + if (meId !== notification.notifieeId) { + // because we call note packMany with meId, all notifieeId should be same as meId + throw new Error('TRY_TO_PACK_ANOTHER_USER_NOTIFICATION'); + } } - await this.customEmojiService.prefetchEmojis(this.customEmojiService.aggregateNoteEmojis(notes)); + const notes = notifications.map(x => x.note).filter(isNotNull); + const packedNotesArray = await this.noteEntityService.packMany(notes, { id: meId }, { + detail: true, + }); + const packedNotes = new Map(packedNotesArray.map(p => [p.id, p])); return await Promise.all(notifications.map(x => this.pack(x, { - _hintForEachNotes_: { - myReactions: myReactionsMap, + _hint_: { + packedNotes, }, }))); } diff --git a/packages/backend/src/misc/is-not-null.ts b/packages/backend/src/misc/is-not-null.ts new file mode 100644 index 0000000000..d89a1957be --- /dev/null +++ b/packages/backend/src/misc/is-not-null.ts @@ -0,0 +1,5 @@ +// we are using {} as "any non-nullish value" as expected +// eslint-disable-next-line @typescript-eslint/ban-types +export function isNotNull(input: T | undefined | null): input is T { + return input != null; +} From 1fed0ff564954329b42171aa2da3d1cc00e39b52 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 3 Mar 2023 20:44:43 +0900 Subject: [PATCH 293/294] New Crowdin updates (#10176) * New translations ja-JP.yml (French) * New translations ja-JP.yml (Korean) * New translations ja-JP.yml (English) * New translations ja-JP.yml (Vietnamese) * New translations ja-JP.yml (Spanish) * New translations ja-JP.yml (Vietnamese) * New translations ja-JP.yml (Vietnamese) * New translations ja-JP.yml (Vietnamese) * New translations ja-JP.yml (Chinese Traditional) * New translations ja-JP.yml (Vietnamese) * New translations ja-JP.yml (Vietnamese) --- locales/en-US.yml | 2 +- locales/es-ES.yml | 1 + locales/fr-FR.yml | 2 +- locales/ko-KR.yml | 77 ++++++------ locales/vi-VN.yml | 307 +++++++++++++++++++++++++++++++++++++++++++--- locales/zh-TW.yml | 3 + 6 files changed, 335 insertions(+), 57 deletions(-) diff --git a/locales/en-US.yml b/locales/en-US.yml index 48cce35a44..638c470916 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -1182,7 +1182,7 @@ _achievements: _loggedInOnNewYearsDay: title: "Happy New Year!" description: "Logged in on the first day of the year" - flavor: "To another great year on this instance" + flavor: "To another great year!" _cookieClicked: title: "A game in which you click cookies" description: "Clicked the cookie" diff --git a/locales/es-ES.yml b/locales/es-ES.yml index b29ffc12df..3ad2c21ff7 100644 --- a/locales/es-ES.yml +++ b/locales/es-ES.yml @@ -854,6 +854,7 @@ tenMinutes: "10 minutos" oneHour: "1 hora" oneDay: "1 día" oneWeek: "1 semana" +oneMonth: "1 mes" reflectMayTakeTime: "Puede pasar un tiempo hasta que se reflejen los cambios" failedToFetchAccountInformation: "No se pudo obtener información de la cuenta" rateLimitExceeded: "Se excedió el límite de peticiones" diff --git a/locales/fr-FR.yml b/locales/fr-FR.yml index 88f20dfc41..f9b8939e8b 100644 --- a/locales/fr-FR.yml +++ b/locales/fr-FR.yml @@ -527,7 +527,7 @@ updateRemoteUser: "Mettre à jour les informations de l’utilisateur·rice dist deleteAllFiles: "Supprimer tous les fichiers" deleteAllFilesConfirm: "Êtes-vous sûr·e de vouloir supprimer tous les fichiers ?" removeAllFollowing: "Retenir tous les abonnements" -removeAllFollowingDescription: "Se désabonner de tous les comptes de {host}. Veuillez lancer cette action uniquement si l’instance n’existe plus." +removeAllFollowingDescription: "Se désabonner de tous les comptes de {host}. Veuillez lancer cette action dans les cas où l’instance n’existe plus, etc." userSuspended: "Cet·te utilisateur·rice a été suspendu·e." userSilenced: "Cette utilisateur·trice a été mis·e en sourdine." yourAccountSuspendedTitle: "Ce compte est suspendu" diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml index b43e5e7abe..9115afe5a5 100644 --- a/locales/ko-KR.yml +++ b/locales/ko-KR.yml @@ -2,7 +2,7 @@ _lang_: "한국어" headlineMisskey: "노트로 연결되는 네트워크" introMisskey: "환영합니다! Misskey는 오픈 소스 분산형 마이크로 블로그 서비스입니다.\n'노트'를 작성해서 지금 일어나고 있는 일을 공유하거나, 당신만의 이야기를 모두에게 발신하세요📡\n'리액션' 기능으로 친구의 노트에 총알같이 반응을 추가할 수도 있습니다👍\n새로운 세계를 탐험해 보세요🚀" -poweredByMisskeyDescription: "{name}은(는) 오픈소스 플랫폼Misskey를 사용한 서비스(Misskey 인스턴스라고 불립니다) 중 하나입니다." +poweredByMisskeyDescription: "{name}은(는) 오픈소스 플랫폼Misskey를 사용한 서버 중 하나입니다." monthAndDay: "{month}월 {day}일" search: "검색" notifications: "알림" @@ -18,7 +18,7 @@ enterUsername: "유저명 입력" renotedBy: "{user}님의 리노트" noNotes: "노트가 없습니다" noNotifications: "표시할 알림이 없습니다" -instance: "인스턴스" +instance: "서버" settings: "설정" basicSettings: "기본 설정" otherSettings: "기타 설정" @@ -163,13 +163,13 @@ searchWith: "검색: {q}" youHaveNoLists: "리스트가 없습니다" followConfirm: "{name}님을 팔로우 하시겠습니까?" proxyAccount: "프록시 계정" -proxyAccountDescription: "프록시 계정은 특정 조건 하에서 유저의 리모트 팔로우를 대행하는 계정입니다. 예를 들면, 유저가 리모트 유저를 리스트에 넣었을 때, 리스트에 들어간 유저를 아무도 팔로우한 적이 없다면 액티비티가 인스턴스로 배달되지 않기 때문에, 대신 프록시 계정이 해당 유저를 팔로우하도록 합니다." +proxyAccountDescription: "프록시 계정은 특정 조건 하에서 유저의 리모트 팔로우를 대행하는 계정입니다. 예를 들면, 유저가 리모트 유저를 리스트에 넣었을 때, 리스트에 들어간 유저를 아무도 팔로우한 적이 없다면 액티비티가 서버로 배달되지 않기 때문에, 대신 프록시 계정이 해당 유저를 팔로우하도록 합니다." host: "호스트" selectUser: "유저 선택" recipient: "수신인" annotation: "내용에 대한 주석" federation: "연합" -instances: "인스턴스" +instances: "서버" registeredAt: "등록 날짜" latestRequestReceivedAt: "마지막으로 요청을 받은 시간" latestStatus: "마지막 상태" @@ -178,7 +178,7 @@ charts: "차트" perHour: "1시간마다" perDay: "1일마다" stopActivityDelivery: "액티비티 보내지 않기" -blockThisInstance: "이 인스턴스를 차단" +blockThisInstance: "이 서버를 차단" operations: "작업" software: "소프트웨어" version: "버전" @@ -189,15 +189,15 @@ jobQueue: "작업 대기열" cpuAndMemory: "CPU와 메모리" network: "네트워크" disk: "디스크" -instanceInfo: "인스턴스 정보" +instanceInfo: "서버 정보" statistics: "통계" clearQueue: "대기열 비우기" clearQueueConfirmTitle: "대기열을 비우시겠습니까?" clearQueueConfirmText: "대기열에 남아 있는 노트는 더이상 연합되지 않습니다. 보통의 경우 이 작업은 필요하지 않습니다." clearCachedFiles: "캐시 비우기" clearCachedFilesConfirm: "캐시된 리모트 파일을 모두 삭제하시겠습니까?" -blockedInstances: "차단된 인스턴스" -blockedInstancesDescription: "차단하려는 인스턴스의 호스트 이름을 줄바꿈으로 구분하여 설정합니다. 차단된 인스턴스는 이 인스턴스와 통신할 수 없게 됩니다." +blockedInstances: "차단된 서버" +blockedInstancesDescription: "차단하려는 서버의 호스트 이름을 줄바꿈으로 구분하여 설정합니다. 차단된 인스턴스는 이 인스턴스와 통신할 수 없게 됩니다." muteAndBlock: "뮤트 및 차단" mutedUsers: "뮤트한 유저" blockedUsers: "차단한 유저" @@ -220,9 +220,9 @@ all: "전체" subscribing: "구독 중" publishing: "배포 중" notResponding: "응답 없음" -instanceFollowing: "인스턴스의 팔로잉" -instanceFollowers: "인스턴스의 팔로워" -instanceUsers: "인스턴스의 유저" +instanceFollowing: "서버의 팔로잉" +instanceFollowers: "서버의 팔로워" +instanceUsers: "서버의 유저" changePassword: "비밀번호 변경" security: "보안" retypedNotMatch: "입력이 일치하지 않습니다." @@ -314,8 +314,8 @@ unwatch: "지켜보기 해제" accept: "허가" reject: "거부" normal: "정상" -instanceName: "인스턴스 이름" -instanceDescription: "인스턴스 소개" +instanceName: "서버 이름" +instanceDescription: "서버 소개" maintainerName: "관리자 이름" maintainerEmail: "관리자 이메일" tosUrl: "이용약관 URL" @@ -345,7 +345,7 @@ basicInfo: "기본 정보" pinnedUsers: "고정된 유저" pinnedUsersDescription: "\"발견하기\" 페이지 등에 고정하고 싶은 유저를 한 줄에 한 명씩 적습니다." pinnedPages: "고정한 페이지" -pinnedPagesDescription: "인스턴스의 대문에 고정하고 싶은 페이지의 경로를 한 줄에 하나씩 적습니다." +pinnedPagesDescription: "서버의 대문에 고정하고 싶은 페이지의 경로를 한 줄에 하나씩 적습니다." pinnedClipId: "고정할 클립의 ID" pinnedNotes: "고정해놓은 노트" hcaptcha: "hCaptcha" @@ -457,6 +457,7 @@ aboutX: "{x}에 대하여" emojiStyle: "이모지 스타일" native: "네이티브" disableDrawer: "드로어 메뉴를 사용하지 않기" +showNoteActionsOnlyHover: "노트 액션 버튼을 마우스를 올렸을 때에만 표시" noHistory: "기록이 없습니다" signinHistory: "로그인 기록" enableAdvancedMfm: "고급 MFM을 활성화" @@ -537,7 +538,7 @@ updateRemoteUser: "리모트 유저 정보 갱신" deleteAllFiles: "모든 파일 삭제" deleteAllFilesConfirm: "모든 파일을 삭제하시겠습니까?" removeAllFollowing: "모든 팔로잉 해제" -removeAllFollowingDescription: "{host}(으)로부터 모든 팔로잉을 해제합니다. 해당 인스턴스가 더 이상 존재하지 않게 된 경우 등에 실행해 주세요." +removeAllFollowingDescription: "{host}(으)로부터 모든 팔로잉을 해제합니다. 해당 서버가 더 이상 존재하지 않게 된 경우 등에 실행해 주세요." userSuspended: "이 계정은 정지된 상태입니다." userSilenced: "이 계정은 사일런스된 상태입니다." yourAccountSuspendedTitle: "계정이 정지되었습니다" @@ -603,7 +604,7 @@ testEmail: "이메일 전송 테스트" wordMute: "단어 뮤트" regexpError: "정규 표현식 오류" regexpErrorDescription: "{tab}단어 뮤트 {line}행의 정규 표현식에 오류가 발생했습니다:" -instanceMute: "인스턴스 뮤트" +instanceMute: "서버 뮤트" userSaysSomething: "{name}님이 무언가를 말했습니다" makeActive: "활성화" display: "표시" @@ -634,15 +635,15 @@ abuseReported: "신고를 보냈습니다. 신고해 주셔서 감사합니다." reporter: "신고자" reporteeOrigin: "피신고자" reporterOrigin: "신고자" -forwardReport: "리모트 인스턴스에도 신고 내용 보내기" -forwardReportIsAnonymous: "리모트 인스턴스에서는 나의 정보를 볼 수 없으며, 익명의 시스템 계정으로 표시됩니다." +forwardReport: "리모트 서버에도 신고 내용 보내기" +forwardReportIsAnonymous: "리모트 서버에서는 나의 정보를 볼 수 없으며, 익명의 시스템 계정으로 표시됩니다." send: "전송" abuseMarkAsResolved: "해결됨으로 표시" openInNewTab: "새 탭에서 열기" openInSideView: "사이드뷰로 열기" defaultNavigationBehaviour: "기본 탐색 동작" editTheseSettingsMayBreakAccount: "이 설정을 변경하면 계정이 손상될 수 있습니다." -instanceTicker: "노트의 인스턴스 정보" +instanceTicker: "노트의 서버 정보" waitingFor: "{x}을(를) 기다리고 있습니다" random: "랜덤" system: "시스템" @@ -731,7 +732,7 @@ capacity: "용량" inUse: "사용중" editCode: "코드 수정" apply: "적용" -receiveAnnouncementFromInstance: "이 인스턴스의 알림을 이메일로 수신할게요" +receiveAnnouncementFromInstance: "이 서버의 알림을 이메일로 수신할게요" emailNotification: "메일 알림" publish: "게시" inChannelSearch: "채널에서 검색" @@ -759,7 +760,7 @@ active: "최근에 활동함" offline: "오프라인" notRecommended: "추천하지 않음" botProtection: "Bot 방어" -instanceBlocking: "인스턴스 차단" +instanceBlocking: "서버 차단" selectAccount: "계정 선택" switchAccount: "계정 바꾸기" enabled: "활성화" @@ -843,8 +844,8 @@ themeColor: "테마 컬러" size: "크기" numberOfColumn: "한 줄에 보일 리액션의 수" searchByGoogle: "검색" -instanceDefaultLightTheme: "인스턴스 기본 라이트 테마" -instanceDefaultDarkTheme: "인스턴스 기본 다크 테마" +instanceDefaultLightTheme: "서버 기본 라이트 테마" +instanceDefaultDarkTheme: "서버 기본 다크 테마" instanceDefaultThemeDescription: "객체 형식의 테마 코드를 입력해 주세요." mutePeriod: "뮤트할 기간" period: "투표 기한" @@ -897,7 +898,7 @@ cannotUploadBecauseInappropriate: "이 파일은 부적절한 내용을 포함 cannotUploadBecauseNoFreeSpace: "드라이브 용량이 부족하여 업로드할 수 없습니다." beta: "베타" enableAutoSensitive: "자동 NSFW 탐지" -enableAutoSensitiveDescription: "이용 가능할 경우 기계학습을 통해 자동으로 미디어 NSFW를 설정합니다. 이 기능을 해제하더라도, 인스턴스 정책에 따라 자동으로 설정될 수 있습니다." +enableAutoSensitiveDescription: "이용 가능할 경우 기계학습을 통해 자동으로 미디어 NSFW를 설정합니다. 이 기능을 해제하더라도, 서버 정책에 따라 자동으로 설정될 수 있습니다." activeEmailValidationDescription: "유저가 입력한 메일 주소가 일회용 메일인지, 실제로 통신할 수 있는 지 엄격하게 검사합니다. 해제할 경우 이메일 형식에 대해서만 검사합니다." navbar: "내비게이션 바" shuffle: "셔플" @@ -907,7 +908,7 @@ pushNotification: "푸시 알림" subscribePushNotification: "푸시 알림 켜기" unsubscribePushNotification: "푸시 알림 끄기" pushNotificationAlreadySubscribed: "푸시 알림이 이미 켜져 있습니다" -pushNotificationNotSupported: "브라우저나 인스턴스에서 푸시 알림이 지원되지 않습니다" +pushNotificationNotSupported: "브라우저나 서버에서 푸시 알림이 지원되지 않습니다" sendPushNotificationReadMessage: "푸시 알림이나 메시지를 읽은 뒤 푸시 알림을 삭제" sendPushNotificationReadMessageCaption: "「{emptyPushNotificationMessage}」이라는 알림이 잠깐 표시됩니다. 기기의 전력 소비량이 증가할 수 있습니다." windowMaximize: "최대화" @@ -953,7 +954,7 @@ joinThisServer: "이 서버에 가입" exploreOtherServers: "다른 서버 둘러보기" letsLookAtTimeline: "타임라인 구경하기" disableFederationWarn: "연합이 비활성화됩니다. 비활성화해도 게시물이 비공개가 되지는 않습니다. 대부분의 경우 이 옵션을 활성화할 필요가 없습니다." -invitationRequiredToRegister: "현재 이 서버는 비공개입니다. 회원가입을 하시려면 초대번호가 필요합니다." +invitationRequiredToRegister: "현재 이 서버는 비공개입니다. 회원가입을 하시려면 초대 코드가 필요합니다." _achievements: earnedAt: "달성 일시" _types: @@ -1144,7 +1145,7 @@ _achievements: description: "1분 사이에 홈 타임라인에 노트가 20개 넘게 생성되었습니다" _viewInstanceChart: title: "애널리스트" - description: "인스턴스의 차트를 열었습니다" + description: "서버의 차트를 열었습니다" _outputHelloWorldOnScratchpad: title: "Hello, world!" description: "스크래치패드에서 hello world를 출력했습니다" @@ -1181,7 +1182,7 @@ _achievements: _loggedInOnNewYearsDay: title: "새해 복 많이 받으세요" description: "새해 첫 날에 로그인했습니다" - flavor: "올해에도 저희 인스턴스에 관심을 가져 주셔서 감사합니다" + flavor: "올해에도 저희 서버에 관심을 가져 주셔서 감사합니다" _cookieClicked: title: "쿠키를 클릭하는 게임" description: "쿠키를 클릭했습니다" @@ -1196,7 +1197,7 @@ _role: name: "역할 이름" description: "역할 설명" permission: "역할 권한" - descriptionOfPermission: "모더레이터는 기본적인 중재와 관련된 작업을 수행할 수 있습니다.\n관리자는 인스턴스의 모든 설정을 변경할 수 있습니다." + descriptionOfPermission: "모더레이터는 기본적인 중재와 관련된 작업을 수행할 수 있습니다.\n관리자는 서버의 모든 설정을 변경할 수 있습니다." assignTarget: "할당 대상" descriptionOfAssignTarget: "수동을 선택하면 누가 이 역할에 포함되는지를 수동으로 관리할 수 있습니다.\n조건부를 선택하면 조건을 설정해 일치하는 사용자를 자동으로 포함되게 할 수 있습니다." manual: "수동" @@ -1224,7 +1225,7 @@ _role: gtlAvailable: "글로벌 타임라인 보이기" ltlAvailable: "로컬 타임라인 보이기" canPublicNote: "공개 노트 허용" - canInvite: "인스턴스 초대 코드 발행" + canInvite: "서버 초대 코드 발행" canManageCustomEmojis: "커스텀 이모지 관리" driveCapacity: "드라이브 용량" pinMax: "고정할 수 있는 노트 수" @@ -1286,7 +1287,7 @@ _ad: _forgotPassword: enterEmail: "여기에 계정에 등록한 메일 주소를 입력해 주세요. 입력한 메일 주소로 비밀번호 재설정 링크를 발송합니다." ifNoEmail: "메일 주소를 등록하지 않은 경우, 관리자에 문의해 주십시오." - contactAdmin: "이 인스턴스에서는 메일 기능이 지원되지 않습니다. 비밀번호를 재설정하려면 관리자에게 문의해 주십시오." + contactAdmin: "이 서버에서는 메일 기능이 지원되지 않습니다. 비밀번호를 재설정하려면 관리자에게 문의해 주십시오." _gallery: my: "내 갤러리" liked: "좋아요 한 갤러리" @@ -1371,10 +1372,10 @@ _wordMute: hard: "보다 높은 수준" mutedNotes: "뮤트된 노트" _instanceMute: - instanceMuteDescription: "뮤트한 인스턴스에서 오는 답글을 포함한 모든 노트와 Renote를 뮤트합니다." + instanceMuteDescription: "뮤트한 서버에서 오는 답글을 포함한 모든 노트와 Renote를 뮤트합니다." instanceMuteDescription2: "한 줄에 하나씩 입력해 주세요" - title: "지정한 인스턴스의 노트를 숨깁니다." - heading: "뮤트할 인스턴스" + title: "지정한 서버의 노트를 숨깁니다." + heading: "뮤트할 서버" _theme: explore: "테마 찾아보기" install: "테마 설치" @@ -1487,7 +1488,7 @@ _tutorial: step4_1: "노트 작성을 끝내셨나요?" step4_2: "당신의 노트가 타임라인에 표시되어 있다면 성공입니다." step5_1: "이제, 다른 사람을 팔로우하여 타임라인을 활기차게 만들어보도록 합시다." - step5_2: "{featured}에서 이 인스턴스의 인기 노트를 보실 수 있습니다. {explore}에서는 인기 사용자를 찾을 수 있구요. 마음에 드는 사람을 골라 팔로우해 보세요!" + step5_2: "{featured}에서 이 서버의 인기 노트를 보실 수 있습니다. {explore}에서는 인기 사용자를 찾을 수 있구요. 마음에 드는 사람을 골라 팔로우해 보세요!" step5_3: "다른 유저를 팔로우하려면 해당 유저의 아이콘을 클릭하여 프로필 페이지를 띄운 후, 팔로우 버튼을 눌러 주세요." step5_4: "사용자에 따라 팔로우가 승인될 때까지 시간이 걸릴 수 있습니다." step6_1: "타임라인에 다른 사용자의 노트가 나타난다면 성공입니다." @@ -1582,7 +1583,7 @@ _weekday: saturday: "토요일" _widgets: profile: "프로필" - instanceInfo: "인스턴스 정보" + instanceInfo: "서버 정보" memo: "스티커 메모" notifications: "알림" timeline: "타임라인" @@ -1596,7 +1597,7 @@ _widgets: digitalClock: "디지털 시계" unixClock: "UNIX 시계" federation: "연합" - instanceCloud: "인스턴스 구름" + instanceCloud: "서버 구름" postForm: "글 입력란" slideshow: "슬라이드 쇼" button: "버튼" @@ -1647,7 +1648,7 @@ _visibility: specified: "다이렉트" specifiedDescription: "지정한 유저에게만 공개" disableFederation: "연합에 보내지 않기" - disableFederationDescription: "다른 인스턴스로 보내지 않습니다" + disableFederationDescription: "다른 서버로 보내지 않습니다" _postForm: replyPlaceholder: "이 노트에 답글..." quotePlaceholder: "이 노트를 인용..." diff --git a/locales/vi-VN.yml b/locales/vi-VN.yml index 89d94961d1..ce36de03db 100644 --- a/locales/vi-VN.yml +++ b/locales/vi-VN.yml @@ -2,6 +2,7 @@ _lang_: "Tiếng Việt" headlineMisskey: "Mạng xã hội liên hợp" introMisskey: "Xin chào! Misskey là một nền tảng tiểu blog phi tập trung mã nguồn mở.\nViết \"tút\" để chia sẻ những suy nghĩ của bạn 📡\nBằng \"biểu cảm\", bạn có thể bày tỏ nhanh chóng cảm xúc của bạn với các tút 👍\nHãy khám phá một thế giới mới! 🚀" +poweredByMisskeyDescription: "{name} là một trong những chủ máy của Misskey là nền tảng mã nguồn mở" monthAndDay: "{day} tháng {month}" search: "Tìm kiếm" notifications: "Thông báo" @@ -10,12 +11,13 @@ password: "Mật khẩu" forgotPassword: "Quên mật khẩu" fetchingAsApObject: "Đang nạp dữ liệu từ Fediverse..." ok: "Đồng ý" -gotIt: "Đã hiểu!" +gotIt: "Hiểu rồi!" cancel: "Hủy" +noThankYou: "Không, cảm ơn" enterUsername: "Nhập tên người dùng" renotedBy: "Chia sẻ bởi {user}" -noNotes: "Chưa có tút nào." -noNotifications: "Không có thông báo" +noNotes: "Chưa có bài viết nào." +noNotifications: "Chưa có thông báo" instance: "Máy chủ" settings: "Cài đặt" basicSettings: "Thiết lập chung" @@ -47,6 +49,7 @@ deleteAndEdit: "Sửa" deleteAndEditConfirm: "Bạn có chắc muốn sửa tút này? Những biểu cảm, lượt trả lời và đăng lại sẽ bị mất." addToList: "Thêm vào danh sách" sendMessage: "Gửi tin nhắn" +copyRSS: "Sao chép RSS" copyUsername: "Chép tên người dùng" searchUser: "Tìm kiếm người dùng" reply: "Trả lời" @@ -65,13 +68,13 @@ export: "Xuất dữ liệu" files: "Tập tin" download: "Tải xuống" driveFileDeleteConfirm: "Bạn có chắc muốn xóa tập tin \"{name}\"? Tút liên quan cũng sẽ bị xóa theo." -unfollowConfirm: "Bạn có chắc muốn ngưng theo dõi {name}?" +unfollowConfirm: "Bạn ngừng theo dõi {name}?" exportRequested: "Đang chuẩn bị xuất tập tin. Quá trình này có thể mất ít phút. Nó sẽ được tự động thêm vào Drive sau khi hoàn thành." importRequested: "Bạn vừa yêu cầu nhập dữ liệu. Quá trình này có thể mất ít phút." lists: "Danh sách" noLists: "Bạn chưa có danh sách nào" -note: "Tút" -notes: "Tút" +note: "Bài viết" +notes: "Bài Viết" following: "Đang theo dõi" followers: "Người theo dõi" followsYou: "Theo dõi bạn" @@ -88,7 +91,7 @@ enterListName: "Đặt tên cho danh sách" privacy: "Bảo mật" makeFollowManuallyApprove: "Yêu cầu theo dõi cần được duyệt" defaultNoteVisibility: "Kiểu tút mặc định" -follow: "Đang theo dõi" +follow: "Theo dõi" followRequest: "Gửi yêu cầu theo dõi" followRequests: "Yêu cầu theo dõi" unfollow: "Ngưng theo dõi" @@ -100,7 +103,9 @@ renoted: "Đã đăng lại." cantRenote: "Không thể đăng lại tút này." cantReRenote: "Không thể đăng lại một tút đăng lại." quote: "Trích dẫn" -pinnedNote: "Tút ghim" +inChannelRenote: "Chia sẻ trong kênh này" +inChannelQuote: "Trích dẫn trong kênh này" +pinnedNote: "Bài viết đã ghim" pinned: "Ghim" you: "Bạn" clickToShow: "Nhấn để xem" @@ -126,6 +131,7 @@ unblockConfirm: "Bạn có chắc muốn bỏ chặn người này?" suspendConfirm: "Bạn có chắc muốn vô hiệu hóa người này?" unsuspendConfirm: "Bạn có chắc muốn bỏ vô hiệu hóa người này?" selectList: "Chọn danh sách" +selectChannel: "Lựa chọn kênh" selectAntenna: "Chọn một antenna" selectWidget: "Chọn tiện ích" editWidgets: "Sửa tiện ích" @@ -141,8 +147,8 @@ cacheRemoteFiles: "Tập tin cache từ xa" cacheRemoteFilesDescription: "Khi tùy chọn này bị tắt, các tập tin từ xa sẽ được tải trực tiếp từ máy chủ khác. Điều này sẽ giúp giảm dung lượng lưu trữ nhưng lại tăng lưu lượng truy cập, vì hình thu nhỏ sẽ không được tạo." flagAsBot: "Đánh dấu đây là tài khoản bot" flagAsBotDescription: "Bật tùy chọn này nếu tài khoản này được kiểm soát bởi một chương trình. Nếu được bật, nó sẽ được đánh dấu để các nhà phát triển khác ngăn chặn chuỗi tương tác vô tận với các bot khác và điều chỉnh hệ thống nội bộ của Misskey để coi tài khoản này như một bot." -flagAsCat: "Tài khoản này là mèo" -flagAsCatDescription: "Bật tùy chọn này để đánh dấu tài khoản là một con mèo." +flagAsCat: "Chế độ Mèeeeeeeeeeo!!" +flagAsCatDescription: "Nếu mà em là một con mèo thì cứ bật nó kiu mèo mèo mèeeeeeeo!! " flagShowTimelineReplies: "Hiện lượt trả lời trong bảng tin" flagShowTimelineRepliesDescription: "Hiện lượt trả lời của người bạn theo dõi trên tút của những người khác." autoAcceptFollowed: "Tự động phê duyệt theo dõi từ những người mà bạn đang theo dõi" @@ -155,7 +161,7 @@ setWallpaper: "Đặt ảnh bìa" removeWallpaper: "Xóa ảnh bìa" searchWith: "Tìm kiếm: {q}" youHaveNoLists: "Bạn chưa có danh sách nào" -followConfirm: "Bạn có chắc muốn theo dõi {name}?" +followConfirm: "Bạn theo dõi {name}?" proxyAccount: "Tài khoản proxy" proxyAccountDescription: "Tài khoản proxy là tài khoản hoạt động như một người theo dõi từ xa cho người dùng trong những điều kiện nhất định. Ví dụ: khi người dùng thêm người dùng từ xa vào danh sách, hoạt động của người dùng từ xa sẽ không được chuyển đến phiên bản nếu không có người dùng cục bộ nào theo dõi người dùng đó, vì vậy tài khoản proxy sẽ theo dõi." host: "Host" @@ -198,7 +204,7 @@ blockedUsers: "Người đã chặn" noUsers: "Chưa có ai" editProfile: "Sửa hồ sơ" noteDeleteConfirm: "Bạn có chắc muốn xóa tút này?" -pinLimitExceeded: "Bạn đã đạt giới hạn số lượng tút có thể ghim" +pinLimitExceeded: "Bạn không thể ghim bài viết nữa" intro: "Đã cài đặt Misskey! Xin hãy tạo tài khoản admin." done: "Xong" processing: "Đang xử lý" @@ -253,6 +259,8 @@ noMoreHistory: "Không còn gì để đọc" startMessaging: "Bắt đầu trò chuyện" nUsersRead: "đọc bởi {n}" agreeTo: "Tôi đồng ý {0}" +agreeBelow: "Đồng ý với nội dung dưới đây" +basicNotesBeforeCreateAccount: "Những điều cơ bản cần chú ý " tos: "Điều khoản dịch vụ" start: "Bắt đầu" home: "Trang chính" @@ -339,7 +347,7 @@ pinnedUsersDescription: "Liệt kê mỗi hàng một tên người dùng xuốn pinnedPages: "Trang đã ghim" pinnedPagesDescription: "Liệt kê các trang thú vị để ghim trên máy chủ." pinnedClipId: "ID của clip muốn ghim" -pinnedNotes: "Tút ghim" +pinnedNotes: "Bài viết đã ghim" hcaptcha: "hCaptcha" enableHcaptcha: "Bật hCaptcha" hcaptchaSiteKey: "Khóa của trang" @@ -348,6 +356,8 @@ recaptcha: "reCAPTCHA" enableRecaptcha: "Bật reCAPTCHA" recaptchaSiteKey: "Khóa của trang" recaptchaSecretKey: "Khóa bí mật" +turnstile: "Turnstile" +enableTurnstile: "Áp dụng Turnstile" turnstileSiteKey: "Khóa của trang" turnstileSecretKey: "Khóa bí mật" avoidMultiCaptchaConfirm: "Dùng nhiều hệ thống Captcha có thể gây nhiễu giữa chúng. Bạn có muốn tắt các hệ thống Captcha khác hiện đang hoạt động không? Nếu bạn muốn chúng tiếp tục được bật, hãy nhấn hủy." @@ -383,13 +393,19 @@ about: "Giới thiệu" aboutMisskey: "Về Misskey" administrator: "Quản trị viên" token: "Token" +2fa: "Xác thực 2 yếu tố" +totp: "Ứng dụng xác thực" +totpDescription: "Nhắn mã OTP bằng ứng dụng xác thực" moderator: "Kiểm duyệt viên" moderation: "Kiểm duyệt" nUsersMentioned: "Dùng bởi {n} người" +securityKeyAndPasskey: "Mã bảo mật・Passkey" securityKey: "Khóa bảo mật" lastUsed: "Dùng lần cuối" +lastUsedAt: "Lần cuối sử dụng: {t}" unregister: "Hủy đăng ký" passwordLessLogin: "Đăng nhập không mật khẩu" +passwordLessLoginDescription: "Đăng nhập bằng chỉ mã bảo mật hoặc passkey, không sử dụng mật khẩu." resetPassword: "Đặt lại mật khẩu" newPasswordIs: "Mật khẩu mới là \"{password}\"" reduceUiAnimation: "Giảm chuyển động UI" @@ -423,7 +439,7 @@ invitations: "Mời" invitationCode: "Mã mời" checking: "Đang kiểm tra..." available: "Khả dụng" -unavailable: "Không khả dụng" +unavailable: "Không sử dụng được" usernameInvalidFormat: "Bạn có thể dùng viết hoa/viết thường, chữ số, và dấu gạch dưới." tooShort: "Quá ngắn" tooLong: "Quá dài" @@ -438,9 +454,13 @@ or: "Hoặc" language: "Ngôn ngữ" uiLanguage: "Ngôn ngữ giao diện" aboutX: "Giới thiệu {x}" +emojiStyle: "Kiểu cách Emoji" +native: "Bản xứ" disableDrawer: "Không dùng menu thanh bên" noHistory: "Không có dữ liệu" signinHistory: "Lịch sử đăng nhập" +enableAdvancedMfm: "Xem bài MFM chất lượng cao." +enableAnimatedMfm: "Xem bài MFM có chuyển động" doing: "Đang xử lý..." category: "Phân loại" tags: "Thẻ" @@ -628,7 +648,7 @@ random: "Ngẫu nhiên" system: "Hệ thống" switchUi: "Chuyển đổi giao diện người dùng" desktop: "Desktop" -clip: "Ghim" +clip: "Lưu bài viết" createNew: "Tạo mới" optional: "Không bắt buộc" createNewClip: "Tạo một ghim mới" @@ -667,7 +687,7 @@ pageLikesCount: "Số lượng trang đã thích" pageLikedCount: "Số lượng thích trang đã nhận" contact: "Liên hệ" useSystemFont: "Dùng phông chữ mặc định của hệ thống" -clips: "Ghim" +clips: "Lưu bài viết" experimentalFeatures: "Tính năng thử nghiệm" developer: "Nhà phát triển" makeExplorable: "Không hiện tôi trong \"Khám phá\"" @@ -693,6 +713,7 @@ accentColor: "Màu phụ" textColor: "Màu chữ" saveAs: "Lưu thành" advanced: "Nâng cao" +advancedSettings: "Cài đặt nâng cao" value: "Giá trị" createdAt: "Ngày tạo" updatedAt: "Cập nhật lúc" @@ -758,6 +779,7 @@ popularPosts: "Tút được xem nhiều nhất" shareWithNote: "Chia sẻ kèm với tút" ads: "Quảng cáo" expiration: "Thời hạn" +startingperiod: "Thời gian bắt đầu\n" memo: "Lưu ý" priority: "Ưu tiên" high: "Cao" @@ -790,6 +812,7 @@ lastCommunication: "Lần giao tiếp cuối" resolved: "Đã xử lý" unresolved: "Chờ xử lý" breakFollow: "Xóa người theo dõi" +breakFollowConfirm: "Bạn bỏ theo dõi tài khoản này không?" itsOn: "Đã bật" itsOff: "Đã tắt" emailRequiredForSignup: "Yêu cầu địa chỉ email khi đăng ký" @@ -830,11 +853,13 @@ tenMinutes: "10 phút" oneHour: "1 giờ" oneDay: "1 ngày" oneWeek: "1 tuần" +oneMonth: "1 tháng" reflectMayTakeTime: "Có thể mất một thời gian để điều này được áp dụng." failedToFetchAccountInformation: "Không thể lấy thông tin tài khoản" rateLimitExceeded: "Giới hạn quá mức" cropImage: "Cắt hình ảnh" cropImageAsk: "Bạn có muốn cắt ảnh này?" +cropNo: "Để nguyên" file: "Tập tin" recentNHours: "{n}h trước" recentNDays: "{n} ngày trước" @@ -877,15 +902,231 @@ navbar: "Thanh điều hướng" shuffle: "Xáo trộn" account: "Tài khoản của bạn" move: "Di chuyển" +pushNotification: "Thông báo đẩy" +subscribePushNotification: "Bật thông báo đẩy" +unsubscribePushNotification: "Tắt thông báo đẩy" +pushNotificationAlreadySubscribed: "Đang bật thông báo đẩy" +sendPushNotificationReadMessage: "Xóa thông báo đẩy sau khi đọc thông báo hay tin nhắn" +sendPushNotificationReadMessageCaption: "Thông báo như {emptyPushNotificationMessage} sẽ hiển thị trong giây phút. Tiêu tốn pin của máy bạn có thể tăng lên hơn nữa." +windowMaximize: "Phóng to" +windowRestore: "Khôi phục" +caption: "Mô tả" +loggedInAsBot: "Đang đăng nhập bằng tài khoản Bot" +tools: "Công Cụ" +cannotLoad: "Không tải được" +numberOfProfileView: "Số lần mở hồ sơ" like: "Thích" +unlike: "Bỏ lượt thích" +numberOfLikes: "Lượt thích" show: "Hiển thị" +neverShow: "Không hiển thị nữa" +remindMeLater: "Để sau" +didYouLikeMisskey: "Bạn có ưa thích Mískey không?" +pleaseDonate: "Misskey là phần mềm miễn phí mà {host} đang sử dụng. Xin mong bạn quyên góp cho chúng tôi để chúng tôi có thể tiếp tục phát triển dịch vụ này. Xin cảm ơn!!" +roles: "Vai trò" +role: "Vai trò" +normalUser: "Người dùng bình thường" +undefined: "Chưa xác định" color: "Màu sắc" +manageCustomEmojis: "Quản lý CustomEmoji" +cannotPerformTemporary: "Tạm thời không sử dụng được" +cannotPerformTemporaryDescription: "Tạm thời không sử dụng được vì lần số điều kiện quá giới hạn. Thử lại sau mọt lát nữa." +achievements: "Thành tích" +gotInvalidResponseError: "Không nhận được trả lời chủ máy" +gotInvalidResponseErrorDescription: "Chủ máy có lẻ ngừng hoạt động hoặc bảo trí. Thử lại sau một lát nữa. " +thisPostMayBeAnnoying: "Bạn đăng bài này có thể làm phiền cho người ta." +thisPostMayBeAnnoyingHome: "Đăng trên trang chính" +thisPostMayBeAnnoyingCancel: "Từ chối" +thisPostMayBeAnnoyingIgnore: "Đăng bài để nguyên" +collapseRenotes: "Không hiển thị bài viết đã từng xem" +internalServerError: "Lỗi trong chủ máy" +internalServerErrorDescription: "Trong chủ máy lỗi bất ngờ xảy ra" +copyErrorInfo: "Sao chép thông tin lỗi" +joinThisServer: "Đăng ký trên chủ máy này" +exploreOtherServers: "Tìm chủ máy khác" +letsLookAtTimeline: "Thử xem Timeline" +_achievements: + earnedAt: "Ngày thu nhận" + _types: + _notes1: + title: "just setting up my msky" + description: "Lần đầu tiên đăng bài" + flavor: "Chúc bạn trên Miskey vui vẻ nha!!" + _notes10: + title: "Một số bài viết" + description: "Đăng bài 10 lần" + _notes100: + title: "Rất nhiều bài biết" + description: "Đăng bài 100 lần" + _notes500: + title: "Như đầy bài viết" + description: "Đăng bài 500 lần" + _notes1000: + title: "Ngọn núi bài viết" + description: "Đăng bài 1000 lần" + _notes5000: + title: "Bài viết chảy như suối" + description: "Đăng bài 5000 lần" + _notes10000: + title: "Bài Viết siu nhìu" + description: "Đăng bài 10000 lần" + _notes20000: + title: "Need more note" + description: "Đã đăng bài 20,000 lần rồi" + _notes30000: + title: "ĐĂNG VỚI BÀI" + description: "Đã đăng bài 30,000 lần rồi" + _notes40000: + title: "Nhà xưởng dăng bài" + description: "Đã đăng bài 40,000 lần rồi" + _notes50000: + title: "Hàng tinh đăng bài" + description: "Đã đăng bài 50,000 lần rồi" + _notes100000: + flavor: "Liệu viết bài gì tầm này vậy? " + _login3: + title: "Sơ cấp I" + description: "Tổng số ngày đăng nhập đạt 3 ngày" + flavor: "Từ nay các bạn cứ xem như mình là một Misskist đó" + _login7: + title: "Sơ cấp II" + description: "Tổng số ngày đăng nhập đạt 7 ngày" + flavor: "Bạn dần quen chưa? " + _login15: + title: "Sơ cấp III" + description: "Tổng số ngày đăng nhập đạt 7 ngày" + _login30: + title: "Misskist cấp I" + description: "Tổng số ngày đăng nhập đạt 30 ngày" + _login60: + title: "Misskist cấp II" + description: "Tổng số ngày đăng nhập đạt 60 ngày" + _login100: + title: "Misskist cấp III" + description: "Tổng số ngày đăng nhập đạt 100 ngày" + flavor: "Người dùng này, chính vì đó là một Misskist" + _login200: + title: "Khách hàng thường xuyên cấp I" + description: "Tổng số ngày đăng nhập đạt 200 ngày" + _login300: + title: "Khách hàng thường xuyên cấp II" + description: "Tổng số ngày đăng nhập đạt 300 ngày" + _login400: + title: "Khách hàng thường xuyên cấp III" + description: "Tổng số ngày đăng nhập đạt 400 ngày" + _markedAsCat: + title: "Tôi là một con mèo" + description: "Bật chế độ mèo" + flavor: "Mà tên chưa có" + _following1: + title: "Theo dõi đầu tiên" + description: "Lần đầu tiên theo dõi " + _following10: + title: "Cứ theo dõi và theo dõi" + description: "Vừa theo dõi hơn 10 người" + _following50: + title: "Bạn bè nhiều quá" + description: "Vừa theo dõi hơn 50 người" + _following100: + title: "Trăm bạn bè" + description: "Vừa theo dõi vượt lên 100 người" + _following300: + title: "Quá nhiều bạn bè" + description: "Vừa theo dõi vượt lên 300 người" + _followers1: + title: "Ai đầu tiên theo dõi bạn" + description: "Lần đầu tiên được theo dõi" + _followers10: + title: "FOLLOW ME!!" + description: "Người theo dõi bạn vượt lên 10 người" + _followers500: + title: "Trạm phát sóng" + _followers1000: + title: "Người có tầm ảnh hưởng" + description: "Người theo dõi bạn vượt lên 1000 người" + _collectAchievements30: + title: "Người sưu tập thành tích" + description: "Vừa lấy thành tích hơn 30 cái" + _viewAchievements3min: + title: "Yêu Thành tích" + description: "Ngắm danh sách thành tích đến tận hơn 3 phút" + _iLoveMisskey: + title: "Tôi Yêu Misskey" + description: "Đăng lời nói \"I ❤ #Misskey\"" + flavor: "Xin chân thành cảm ơn bạn đã sử dụng Misskey!! by Đội ngũ phát triển" + _foundTreasure: + title: "Tìm kiếm kho báu" + description: "Tìm thấy được những kho báu cất giấu" + _client30min: + title: "Giải lao xỉu" + _noteDeletedWithin1min: + title: "Xem như không có gì đâu nha" + _postedAtLateNight: + title: "Loài ăn đêm" + description: "Đăng bài trong đêm khuya " + _postedAt0min0sec: + title: "Tín hiệu báo giờ" + description: "Đăng bài vào 0 phút 0 giây" + flavor: "Piiiiiii ĐÂY LÀ TIẾNG NÓI VIỆT NAM" + _selfQuote: + title: "Nói đến bản thân" + description: "Trích dẫn bài viết của mình" + _htl20npm: + title: "Timeline trôi như con sông" + description: "Timeline trang chính tốc độ vượt lên 20npm" + _viewInstanceChart: + title: "Nhà phân tích" + description: "Xem biểu đồ của chủ máy" + _outputHelloWorldOnScratchpad: + title: "Chào thế giới!" + _open3windows: + title: "Nhiều cửa sổ" + description: "Mở cửa sổ hơn 3 cửa sổ" + _reactWithoutRead: + title: "Bài này bạn đọc kỹ chứ? " + description: "Phản hồi trong vọng 3 giây sau bài viết có hơn 100 ký tự mới được đăng lên" + _clickedClickHere: + title: "Bấm đây" + description: "Bấm chỗ này" + _justPlainLucky: + title: "Chỉ là một cuộc máy mắn" + description: "Mỗi 10 giây thu nhận được với tỷ lệ 0.005%" + _setNameToSyuilo: + title: "Ngưỡng mộ với vị thần" + description: "Đạt tên là syuilo" + _loggedInOnBirthday: + title: "Sinh nhật vủi vẻ" + description: "Đăng nhập vào ngày sinh" + _loggedInOnNewYearsDay: + title: "Chức mừng năm mới" + description: "Đăng nhập vào Tết Nguyên đàn dương lịch" + flavor: "Chúc bạn năm mới AN KHANG THỊNH VƯỢNG, VẠN SỰ NHƯ Ý!!" + _cookieClicked: + flavor: "Bạn nhầm phầm mềm chứ?" _role: priority: "Ưu tiên" _priority: low: "Thấp" middle: "Vừa" high: "Cao" + _options: + gtlAvailable: "Xem Timeline xã hội" + ltlAvailable: "Xem Timeline trong máy chủ này" + canPublicNote: "Cho phép đăng bài công khai" + canManageCustomEmojis: "Quản lý CustomEmoji" + driveCapacity: "Dữ liệu Drive" + pinMax: "Giới hạn ghim bài viết" + antennaMax: "Giới hạn tạo ăng ten" + canHideAds: "Tắt quảng cáo" + _condition: + createdMoreThan: "Trôi qua ~ sau khi lập tài khoản" + followersLessThanOrEq: "Người theo dõi ít hơn ~" + followersMoreThanOrEq: "Người theo dõi có ~ trở lên" + followingLessThanOrEq: "Theo dõi ít hơn ~" + followingMoreThanOrEq: "Theo dõi có ~ trở lên" + and: "~ mà ~" + or: "~ hay là ~" + not: "Không phải ~" _sensitiveMediaDetection: description: "Giảm nỗ lực kiểm duyệt máy chủ thông qua việc tự động nhận dạng media NSFW thông qua học máy. Điều này sẽ làm tăng một chút áp lực trên máy chủ." sensitivity: "Phát hiện nhạy cảm" @@ -1132,15 +1373,23 @@ _tutorial: step7_1: "Xin chúc mừng! Bây giờ bạn đã hoàn thành phần hướng dẫn cơ bản của Misskey." step7_2: "Nếu bạn muốn tìm hiểu thêm về Misskey, hãy thử phần {help}." step7_3: "Bây giờ, chúc may mắn và vui vẻ với Misskey! 🚀" + step8_1: "Cuối cùng, bạn hãy bật thông báo đẩy nha!" + step8_2: "Nhận thông báo đẩy bạn sẽ có thể thấy phản hồi, theo dõi, lượt nhắc được trong khi đóng Misskey" _2fa: alreadyRegistered: "Bạn đã đăng ký thiết bị xác minh 2 bước." + passwordToTOTP: "Nhắn mật mã" step1: "Trước tiên, hãy cài đặt một ứng dụng xác minh (chẳng hạn như {a} hoặc {b}) trên thiết bị của bạn." step2: "Sau đó, quét mã QR hiển thị trên màn hình này." step2Url: "Bạn cũng có thể nhập URL này nếu sử dụng một chương trình máy tính:" step3: "Nhập mã token do ứng dụng của bạn cung cấp để hoàn tất thiết lập." step4: "Kể từ bây giờ, những lần đăng nhập trong tương lai sẽ yêu cầu mã token đăng nhập đó." securityKeyInfo: "Bên cạnh xác minh bằng vân tay hoặc mã PIN, bạn cũng có thể thiết lập xác minh thông qua khóa bảo mật phần cứng hỗ trợ FIDO2 để bảo mật hơn nữa cho tài khoản của mình." + removeKey: "Xóa mã bảo mật" removeKeyConfirm: "Xóa bản sao lưu {name}?" + renewTOTP: "Cài đặt lại ứng dụng xác thực" + renewTOTPConfirm: "Mã xác nhận cũ của ứng dụng xác thực không thể sử dụng được nữa" + renewTOTPOk: "Cài đặt lại" + renewTOTPCancel: "Không, cảm ơn" _permissions: "read:account": "Xem thông tin tài khoản của bạn" "write:account": "Sửa thông tin tài khoản của bạn" @@ -1175,12 +1424,15 @@ _permissions: "read:gallery-likes": "Xem danh sách các tút đã thích trong thư viện của tôi" "write:gallery-likes": "Sửa danh sách các tút đã thích trong thư viện của tôi" _auth: + shareAccessTitle: "Cho phép truy cập app" shareAccess: "Bạn có muốn cho phép \"{name}\" truy cập vào tài khoản này không?" shareAccessAsk: "Bạn có chắc muốn cho phép ứng dụng này truy cập vào tài khoản của mình không?" + permission: "{name} đang yêu cầu quyền hạn dưới đây" permissionAsk: "Ứng dụng này yêu cầu các quyền sau" pleaseGoBack: "Vui lòng quay lại ứng dụng" callback: "Quay lại ứng dụng" denied: "Truy cập bị từ chối" + pleaseLogin: "Bạn phải đăng nhập để cho ứng dụng phép truy cập" _antennaSources: all: "Toàn bộ tút" homeTimeline: "Tút từ những người đã theo dõi" @@ -1218,9 +1470,12 @@ _widgets: jobQueue: "Công việc chờ xử lý" serverMetric: "Thống kê máy chủ" aiscript: "AiScript console" + aiscriptApp: "AiScript App" aichan: "Ai" + userList: "Danh sách người dùng" _userList: chooseList: "Chọn danh sách" + clicker: "clicker" _cw: hide: "Ẩn" show: "Tải thêm" @@ -1257,6 +1512,8 @@ _visibility: followersDescription: "Dành riêng cho người theo dõi" specified: "Nhắn riêng" specifiedDescription: "Chỉ người được nhắc đến mới thấy" + disableFederation: "Không liên hợp" + disableFederationDescription: "Không đưa tin cho chủ máy khác" _postForm: replyPlaceholder: "Trả lời tút này" quotePlaceholder: "Trích dẫn tút này" @@ -1266,7 +1523,7 @@ _postForm: b: "Hôm nay bạn có gì vui?" c: "Bạn đang nghĩ gì?" d: "Bạn muốn nói gì?" - e: "Bắt đầu viết..." + e: "Cứ viết trên đây" f: "Đang chờ bạn viết..." _profile: name: "Tên" @@ -1282,6 +1539,7 @@ _profile: changeBanner: "Đổi ảnh bìa" _exportOrImport: allNotes: "Toàn bộ tút" + favoritedNotes: "Bài viết đã thích" followingList: "Đang theo dõi" muteList: "Ẩn" blockingList: "Chặn" @@ -1320,7 +1578,16 @@ _timelines: social: "Xã hội" global: "Liên hợp" _play: + new: "Tạo Play mới" + edit: "Edit play" + created: "Bạn vừa tạo play rồi" + updated: "Bạn vừa cập nhật play rồi" + deleted: "Bạn vừa xóa play rồi" + pageSetting: "Cài đặt play" + editThisPage: "Edit play này" viewSource: "Xem mã nguồn" + my: "Play của mình" + liked: "Play đã thích" featured: "Nổi tiếng" title: "Tựa đề" script: "Kịch bản" @@ -1388,7 +1655,9 @@ _notification: youReceivedFollowRequest: "Bạn vừa có một yêu cầu theo dõi" yourFollowRequestAccepted: "Yêu cầu theo dõi của bạn đã được chấp nhận" pollEnded: "Cuộc bình chọn đã kết thúc" + unreadAntennaNote: "Ăng ten" emptyPushNotificationMessage: "Đã cập nhật thông báo đẩy" + achievementEarned: "Hoàn thành Achievement" _types: all: "Toàn bộ" follow: "Đang theo dõi" @@ -1400,6 +1669,7 @@ _notification: pollEnded: "Bình chọn kết thúc" receiveFollowRequest: "Yêu cầu theo dõi" followRequestAccepted: "Yêu cầu theo dõi được chấp nhận" + achievementEarned: "Hoàn thành Achievement" app: "Từ app liên kết" _actions: followBack: "đã theo dõi lại bạn" @@ -1432,3 +1702,6 @@ _deck: channel: "Kênh" mentions: "Lượt nhắc" direct: "Nhắn riêng" +_dialog: + charactersExceeded: "Bạn nhắn quá giới hạn ký tự!! Hiện nay {current} / giới hạn {max}" + charactersBelow: "Bạn nhắn quá ít tối thiểu ký tự!! Hiện nay {current} / Tối thiểu {min}" diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml index 218df5d9f3..43ab334be7 100644 --- a/locales/zh-TW.yml +++ b/locales/zh-TW.yml @@ -457,6 +457,7 @@ aboutX: "關於{x}" emojiStyle: "表情符號的風格" native: "原生" disableDrawer: "不顯示下拉式選單" +showNoteActionsOnlyHover: "僅在游標停留時顯示貼文的操作選項" noHistory: "沒有歷史紀錄" signinHistory: "登入歷史" enableAdvancedMfm: "啟用高級MFM" @@ -853,6 +854,7 @@ tenMinutes: "10分鐘" oneHour: "1小時" oneDay: "1天" oneWeek: "1週" +oneMonth: "1個月" reflectMayTakeTime: "可能需要一些時間才會出現效果。" failedToFetchAccountInformation: "取得帳戶資訊失敗" rateLimitExceeded: "已超過速率限制" @@ -952,6 +954,7 @@ joinThisServer: "在此伺服器上註冊" exploreOtherServers: "探索其他伺服器" letsLookAtTimeline: "看看時間軸" disableFederationWarn: "聯邦被停用了。即使停用也不會讓您的貼文不公開,在大多數情況下,不需要啟用這個選項。" +invitationRequiredToRegister: "目前這個伺服器為邀請制,必須擁有邀請碼才能註冊。" _achievements: earnedAt: "獲得日期" _types: From 7e8700514f18409874737cd5b439280bb03b829c Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 3 Mar 2023 20:45:17 +0900 Subject: [PATCH 294/294] 13.9.1 --- CHANGELOG.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a5e6da4f2..37a5ab3e1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,11 @@ You should also include the user name that made the change. --> +## 13.9.1 (2023/03/03) + +### Bugfixes +- ノートに添付したファイルが表示されない場合があるのを修正 + ## 13.9.0 (2023/03/03) ### Improvements diff --git a/package.json b/package.json index b870d8507d..a2d04030f2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "13.9.0", + "version": "13.9.1", "codename": "nasubi", "repository": { "type": "git",