From 5686e1d2d02d246171bcc175d2f0a03fa9e69ec7 Mon Sep 17 00:00:00 2001 From: syuilo Date: Tue, 17 Oct 2023 09:00:42 +0900 Subject: [PATCH 1/3] refactor --- packages/backend/src/core/NoteCreateService.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/core/NoteCreateService.ts b/packages/backend/src/core/NoteCreateService.ts index a308e1aaa8..3aefde50e0 100644 --- a/packages/backend/src/core/NoteCreateService.ts +++ b/packages/backend/src/core/NoteCreateService.ts @@ -252,8 +252,10 @@ export class NoteCreateService implements OnApplicationShutdown { if (data.channel != null) data.visibleUsers = []; if (data.channel != null) data.localOnly = true; + const meta = await this.metaService.fetch(); + if (data.visibility === 'public' && data.channel == null) { - const sensitiveWords = (await this.metaService.fetch()).sensitiveWords; + const sensitiveWords = meta.sensitiveWords; if (this.isSensitive(data, sensitiveWords)) { data.visibility = 'home'; } else if ((await this.roleService.getUserPolicies(user.id)).canPublicNote === false) { @@ -261,7 +263,7 @@ export class NoteCreateService implements OnApplicationShutdown { } } - const inSilencedInstance = this.utilityService.isSilencedHost((await this.metaService.fetch()).silencedHosts, user.host); + const inSilencedInstance = this.utilityService.isSilencedHost(meta.silencedHosts, user.host); if (data.visibility === 'public' && inSilencedInstance && user.host !== null) { data.visibility = 'home'; From e9db0680c42cab649d105897a7c6628a2d2f8d85 Mon Sep 17 00:00:00 2001 From: syuilo Date: Tue, 17 Oct 2023 09:04:17 +0900 Subject: [PATCH 2/3] update deps --- package.json | 4 +- packages/backend/package.json | 4 +- packages/frontend/package.json | 4 +- packages/misskey-js/package.json | 4 +- packages/sw/package.json | 2 +- pnpm-lock.yaml | 122 +++++++++++++++---------------- 6 files changed, 70 insertions(+), 70 deletions(-) diff --git a/package.json b/package.json index 5ba90b5d15..01ad0b621f 100644 --- a/package.json +++ b/package.json @@ -51,8 +51,8 @@ "typescript": "5.2.2" }, "devDependencies": { - "@typescript-eslint/eslint-plugin": "6.7.5", - "@typescript-eslint/parser": "6.7.5", + "@typescript-eslint/eslint-plugin": "6.8.0", + "@typescript-eslint/parser": "6.8.0", "cross-env": "7.0.3", "cypress": "13.3.1", "eslint": "8.51.0", diff --git a/packages/backend/package.json b/packages/backend/package.json index 476f0c02f7..dc8daff1ef 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -212,8 +212,8 @@ "@types/vary": "1.1.1", "@types/web-push": "3.6.1", "@types/ws": "8.5.7", - "@typescript-eslint/eslint-plugin": "6.7.5", - "@typescript-eslint/parser": "6.7.5", + "@typescript-eslint/eslint-plugin": "6.8.0", + "@typescript-eslint/parser": "6.8.0", "aws-sdk-client-mock": "3.0.0", "cross-env": "7.0.3", "eslint": "8.51.0", diff --git a/packages/frontend/package.json b/packages/frontend/package.json index c0a6e763fb..44ecacd992 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -109,8 +109,8 @@ "@types/uuid": "9.0.5", "@types/websocket": "1.0.7", "@types/ws": "8.5.7", - "@typescript-eslint/eslint-plugin": "6.7.5", - "@typescript-eslint/parser": "6.7.5", + "@typescript-eslint/eslint-plugin": "6.8.0", + "@typescript-eslint/parser": "6.8.0", "@vitest/coverage-v8": "0.34.6", "@vue/runtime-core": "3.3.4", "acorn": "8.10.0", diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json index f124c678c9..2f65c3b95f 100644 --- a/packages/misskey-js/package.json +++ b/packages/misskey-js/package.json @@ -24,8 +24,8 @@ "@swc/jest": "0.2.29", "@types/jest": "29.5.5", "@types/node": "20.8.6", - "@typescript-eslint/eslint-plugin": "6.7.5", - "@typescript-eslint/parser": "6.7.5", + "@typescript-eslint/eslint-plugin": "6.8.0", + "@typescript-eslint/parser": "6.8.0", "eslint": "8.51.0", "jest": "29.7.0", "jest-fetch-mock": "3.0.3", diff --git a/packages/sw/package.json b/packages/sw/package.json index 24878a6e2f..c045b32165 100644 --- a/packages/sw/package.json +++ b/packages/sw/package.json @@ -14,7 +14,7 @@ "misskey-js": "workspace:*" }, "devDependencies": { - "@typescript-eslint/parser": "6.7.5", + "@typescript-eslint/parser": "6.8.0", "@typescript/lib-webworker": "npm:@types/serviceworker@0.0.67", "eslint": "8.51.0", "eslint-plugin-import": "2.28.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d4e5749da5..69030bf52c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -36,11 +36,11 @@ importers: version: 4.4.0 devDependencies: '@typescript-eslint/eslint-plugin': - specifier: 6.7.5 - version: 6.7.5(@typescript-eslint/parser@6.7.5)(eslint@8.51.0)(typescript@5.2.2) + specifier: 6.8.0 + version: 6.8.0(@typescript-eslint/parser@6.8.0)(eslint@8.51.0)(typescript@5.2.2) '@typescript-eslint/parser': - specifier: 6.7.5 - version: 6.7.5(eslint@8.51.0)(typescript@5.2.2) + specifier: 6.8.0 + version: 6.8.0(eslint@8.51.0)(typescript@5.2.2) cross-env: specifier: 7.0.3 version: 7.0.3 @@ -608,11 +608,11 @@ importers: specifier: 8.5.7 version: 8.5.7 '@typescript-eslint/eslint-plugin': - specifier: 6.7.5 - version: 6.7.5(@typescript-eslint/parser@6.7.5)(eslint@8.51.0)(typescript@5.2.2) + specifier: 6.8.0 + version: 6.8.0(@typescript-eslint/parser@6.8.0)(eslint@8.51.0)(typescript@5.2.2) '@typescript-eslint/parser': - specifier: 6.7.5 - version: 6.7.5(eslint@8.51.0)(typescript@5.2.2) + specifier: 6.8.0 + version: 6.8.0(eslint@8.51.0)(typescript@5.2.2) aws-sdk-client-mock: specifier: 3.0.0 version: 3.0.0 @@ -624,7 +624,7 @@ importers: version: 8.51.0 eslint-plugin-import: specifier: 2.28.1 - version: 2.28.1(@typescript-eslint/parser@6.7.5)(eslint@8.51.0) + version: 2.28.1(@typescript-eslint/parser@6.8.0)(eslint@8.51.0) execa: specifier: 8.0.1 version: 8.0.1 @@ -915,11 +915,11 @@ importers: specifier: 8.5.7 version: 8.5.7 '@typescript-eslint/eslint-plugin': - specifier: 6.7.5 - version: 6.7.5(@typescript-eslint/parser@6.7.5)(eslint@8.51.0)(typescript@5.2.2) + specifier: 6.8.0 + version: 6.8.0(@typescript-eslint/parser@6.8.0)(eslint@8.51.0)(typescript@5.2.2) '@typescript-eslint/parser': - specifier: 6.7.5 - version: 6.7.5(eslint@8.51.0)(typescript@5.2.2) + specifier: 6.8.0 + version: 6.8.0(eslint@8.51.0)(typescript@5.2.2) '@vitest/coverage-v8': specifier: 0.34.6 version: 0.34.6(vitest@0.34.6) @@ -940,7 +940,7 @@ importers: version: 8.51.0 eslint-plugin-import: specifier: 2.28.1 - version: 2.28.1(@typescript-eslint/parser@6.7.5)(eslint@8.51.0) + version: 2.28.1(@typescript-eslint/parser@6.8.0)(eslint@8.51.0) eslint-plugin-vue: specifier: 9.17.0 version: 9.17.0(eslint@8.51.0) @@ -1027,11 +1027,11 @@ importers: specifier: 20.8.6 version: 20.8.6 '@typescript-eslint/eslint-plugin': - specifier: 6.7.5 - version: 6.7.5(@typescript-eslint/parser@6.7.5)(eslint@8.51.0)(typescript@5.2.2) + specifier: 6.8.0 + version: 6.8.0(@typescript-eslint/parser@6.8.0)(eslint@8.51.0)(typescript@5.2.2) '@typescript-eslint/parser': - specifier: 6.7.5 - version: 6.7.5(eslint@8.51.0)(typescript@5.2.2) + specifier: 6.8.0 + version: 6.8.0(eslint@8.51.0)(typescript@5.2.2) eslint: specifier: 8.51.0 version: 8.51.0 @@ -1067,8 +1067,8 @@ importers: version: link:../misskey-js devDependencies: '@typescript-eslint/parser': - specifier: 6.7.5 - version: 6.7.5(eslint@8.51.0)(typescript@5.2.2) + specifier: 6.8.0 + version: 6.8.0(eslint@8.51.0)(typescript@5.2.2) '@typescript/lib-webworker': specifier: npm:@types/serviceworker@0.0.67 version: /@types/serviceworker@0.0.67 @@ -1077,7 +1077,7 @@ importers: version: 8.51.0 eslint-plugin-import: specifier: 2.28.1 - version: 2.28.1(@typescript-eslint/parser@6.7.5)(eslint@8.51.0) + version: 2.28.1(@typescript-eslint/parser@6.8.0)(eslint@8.51.0) typescript: specifier: 5.2.2 version: 5.2.2 @@ -8040,8 +8040,8 @@ packages: dev: true optional: true - /@typescript-eslint/eslint-plugin@6.7.5(@typescript-eslint/parser@6.7.5)(eslint@8.51.0)(typescript@5.2.2): - resolution: {integrity: sha512-JhtAwTRhOUcP96D0Y6KYnwig/MRQbOoLGXTON2+LlyB/N35SP9j1boai2zzwXb7ypKELXMx3DVk9UTaEq1vHEw==} + /@typescript-eslint/eslint-plugin@6.8.0(@typescript-eslint/parser@6.8.0)(eslint@8.51.0)(typescript@5.2.2): + resolution: {integrity: sha512-GosF4238Tkes2SHPQ1i8f6rMtG6zlKwMEB0abqSJ3Npvos+doIlc/ATG+vX1G9coDF3Ex78zM3heXHLyWEwLUw==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha @@ -8052,11 +8052,11 @@ packages: optional: true dependencies: '@eslint-community/regexpp': 4.6.2 - '@typescript-eslint/parser': 6.7.5(eslint@8.51.0)(typescript@5.2.2) - '@typescript-eslint/scope-manager': 6.7.5 - '@typescript-eslint/type-utils': 6.7.5(eslint@8.51.0)(typescript@5.2.2) - '@typescript-eslint/utils': 6.7.5(eslint@8.51.0)(typescript@5.2.2) - '@typescript-eslint/visitor-keys': 6.7.5 + '@typescript-eslint/parser': 6.8.0(eslint@8.51.0)(typescript@5.2.2) + '@typescript-eslint/scope-manager': 6.8.0 + '@typescript-eslint/type-utils': 6.8.0(eslint@8.51.0)(typescript@5.2.2) + '@typescript-eslint/utils': 6.8.0(eslint@8.51.0)(typescript@5.2.2) + '@typescript-eslint/visitor-keys': 6.8.0 debug: 4.3.4(supports-color@8.1.1) eslint: 8.51.0 graphemer: 1.4.0 @@ -8069,8 +8069,8 @@ packages: - supports-color dev: true - /@typescript-eslint/parser@6.7.5(eslint@8.51.0)(typescript@5.2.2): - resolution: {integrity: sha512-bIZVSGx2UME/lmhLcjdVc7ePBwn7CLqKarUBL4me1C5feOd663liTGjMBGVcGr+BhnSLeP4SgwdvNnnkbIdkCw==} + /@typescript-eslint/parser@6.8.0(eslint@8.51.0)(typescript@5.2.2): + resolution: {integrity: sha512-5tNs6Bw0j6BdWuP8Fx+VH4G9fEPDxnVI7yH1IAPkQH5RUtvKwRoqdecAPdQXv4rSOADAaz1LFBZvZG7VbXivSg==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -8079,10 +8079,10 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 6.7.5 - '@typescript-eslint/types': 6.7.5 - '@typescript-eslint/typescript-estree': 6.7.5(typescript@5.2.2) - '@typescript-eslint/visitor-keys': 6.7.5 + '@typescript-eslint/scope-manager': 6.8.0 + '@typescript-eslint/types': 6.8.0 + '@typescript-eslint/typescript-estree': 6.8.0(typescript@5.2.2) + '@typescript-eslint/visitor-keys': 6.8.0 debug: 4.3.4(supports-color@8.1.1) eslint: 8.51.0 typescript: 5.2.2 @@ -8090,16 +8090,16 @@ packages: - supports-color dev: true - /@typescript-eslint/scope-manager@6.7.5: - resolution: {integrity: sha512-GAlk3eQIwWOJeb9F7MKQ6Jbah/vx1zETSDw8likab/eFcqkjSD7BI75SDAeC5N2L0MmConMoPvTsmkrg71+B1A==} + /@typescript-eslint/scope-manager@6.8.0: + resolution: {integrity: sha512-xe0HNBVwCph7rak+ZHcFD6A+q50SMsFwcmfdjs9Kz4qDh5hWhaPhFjRs/SODEhroBI5Ruyvyz9LfwUJ624O40g==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.7.5 - '@typescript-eslint/visitor-keys': 6.7.5 + '@typescript-eslint/types': 6.8.0 + '@typescript-eslint/visitor-keys': 6.8.0 dev: true - /@typescript-eslint/type-utils@6.7.5(eslint@8.51.0)(typescript@5.2.2): - resolution: {integrity: sha512-Gs0qos5wqxnQrvpYv+pf3XfcRXW6jiAn9zE/K+DlmYf6FcpxeNYN0AIETaPR7rHO4K2UY+D0CIbDP9Ut0U4m1g==} + /@typescript-eslint/type-utils@6.8.0(eslint@8.51.0)(typescript@5.2.2): + resolution: {integrity: sha512-RYOJdlkTJIXW7GSldUIHqc/Hkto8E+fZN96dMIFhuTJcQwdRoGN2rEWA8U6oXbLo0qufH7NPElUb+MceHtz54g==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -8108,8 +8108,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 6.7.5(typescript@5.2.2) - '@typescript-eslint/utils': 6.7.5(eslint@8.51.0)(typescript@5.2.2) + '@typescript-eslint/typescript-estree': 6.8.0(typescript@5.2.2) + '@typescript-eslint/utils': 6.8.0(eslint@8.51.0)(typescript@5.2.2) debug: 4.3.4(supports-color@8.1.1) eslint: 8.51.0 ts-api-utils: 1.0.1(typescript@5.2.2) @@ -8118,13 +8118,13 @@ packages: - supports-color dev: true - /@typescript-eslint/types@6.7.5: - resolution: {integrity: sha512-WboQBlOXtdj1tDFPyIthpKrUb+kZf2VroLZhxKa/VlwLlLyqv/PwUNgL30BlTVZV1Wu4Asu2mMYPqarSO4L5ZQ==} + /@typescript-eslint/types@6.8.0: + resolution: {integrity: sha512-p5qOxSum7W3k+llc7owEStXlGmSl8FcGvhYt8Vjy7FqEnmkCVlM3P57XQEGj58oqaBWDQXbJDZxwUWMS/EAPNQ==} engines: {node: ^16.0.0 || >=18.0.0} dev: true - /@typescript-eslint/typescript-estree@6.7.5(typescript@5.2.2): - resolution: {integrity: sha512-NhJiJ4KdtwBIxrKl0BqG1Ur+uw7FiOnOThcYx9DpOGJ/Abc9z2xNzLeirCG02Ig3vkvrc2qFLmYSSsaITbKjlg==} + /@typescript-eslint/typescript-estree@6.8.0(typescript@5.2.2): + resolution: {integrity: sha512-ISgV0lQ8XgW+mvv5My/+iTUdRmGspducmQcDw5JxznasXNnZn3SKNrTRuMsEXv+V/O+Lw9AGcQCfVaOPCAk/Zg==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: typescript: '*' @@ -8132,8 +8132,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 6.7.5 - '@typescript-eslint/visitor-keys': 6.7.5 + '@typescript-eslint/types': 6.8.0 + '@typescript-eslint/visitor-keys': 6.8.0 debug: 4.3.4(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 @@ -8144,8 +8144,8 @@ packages: - supports-color dev: true - /@typescript-eslint/utils@6.7.5(eslint@8.51.0)(typescript@5.2.2): - resolution: {integrity: sha512-pfRRrH20thJbzPPlPc4j0UNGvH1PjPlhlCMq4Yx7EGjV7lvEeGX0U6MJYe8+SyFutWgSHsdbJ3BXzZccYggezA==} + /@typescript-eslint/utils@6.8.0(eslint@8.51.0)(typescript@5.2.2): + resolution: {integrity: sha512-dKs1itdE2qFG4jr0dlYLQVppqTE+Itt7GmIf/vX6CSvsW+3ov8PbWauVKyyfNngokhIO9sKZeRGCUo1+N7U98Q==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -8153,9 +8153,9 @@ packages: '@eslint-community/eslint-utils': 4.4.0(eslint@8.51.0) '@types/json-schema': 7.0.12 '@types/semver': 7.5.3 - '@typescript-eslint/scope-manager': 6.7.5 - '@typescript-eslint/types': 6.7.5 - '@typescript-eslint/typescript-estree': 6.7.5(typescript@5.2.2) + '@typescript-eslint/scope-manager': 6.8.0 + '@typescript-eslint/types': 6.8.0 + '@typescript-eslint/typescript-estree': 6.8.0(typescript@5.2.2) eslint: 8.51.0 semver: 7.5.4 transitivePeerDependencies: @@ -8163,11 +8163,11 @@ packages: - typescript dev: true - /@typescript-eslint/visitor-keys@6.7.5: - resolution: {integrity: sha512-3MaWdDZtLlsexZzDSdQWsFQ9l9nL8B80Z4fImSpyllFC/KLqWQRdEcB+gGGO+N3Q2uL40EsG66wZLsohPxNXvg==} + /@typescript-eslint/visitor-keys@6.8.0: + resolution: {integrity: sha512-oqAnbA7c+pgOhW2OhGvxm0t1BULX5peQI/rLsNDpGM78EebV3C9IGbX5HNZabuZ6UQrYveCLjKo8Iy/lLlBkkg==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.7.5 + '@typescript-eslint/types': 6.8.0 eslint-visitor-keys: 3.4.3 dev: true @@ -11075,7 +11075,7 @@ packages: - supports-color dev: true - /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.7.5)(eslint-import-resolver-node@0.3.7)(eslint@8.51.0): + /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.8.0)(eslint-import-resolver-node@0.3.7)(eslint@8.51.0): resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} engines: {node: '>=4'} peerDependencies: @@ -11096,7 +11096,7 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 6.7.5(eslint@8.51.0)(typescript@5.2.2) + '@typescript-eslint/parser': 6.8.0(eslint@8.51.0)(typescript@5.2.2) debug: 3.2.7(supports-color@5.5.0) eslint: 8.51.0 eslint-import-resolver-node: 0.3.7 @@ -11104,7 +11104,7 @@ packages: - supports-color dev: true - /eslint-plugin-import@2.28.1(@typescript-eslint/parser@6.7.5)(eslint@8.51.0): + /eslint-plugin-import@2.28.1(@typescript-eslint/parser@6.8.0)(eslint@8.51.0): resolution: {integrity: sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==} engines: {node: '>=4'} peerDependencies: @@ -11114,7 +11114,7 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 6.7.5(eslint@8.51.0)(typescript@5.2.2) + '@typescript-eslint/parser': 6.8.0(eslint@8.51.0)(typescript@5.2.2) array-includes: 3.1.6 array.prototype.findlastindex: 1.2.2 array.prototype.flat: 1.3.1 @@ -11123,7 +11123,7 @@ packages: doctrine: 2.1.0 eslint: 8.51.0 eslint-import-resolver-node: 0.3.7 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.7.5)(eslint-import-resolver-node@0.3.7)(eslint@8.51.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.8.0)(eslint-import-resolver-node@0.3.7)(eslint@8.51.0) has: 1.0.3 is-core-module: 2.13.0 is-glob: 4.0.3 From 5a3c6575dd5d97dc0dc193771b80898fca4cfdc0 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Tue, 17 Oct 2023 20:56:17 +0900 Subject: [PATCH 3/3] =?UTF-8?q?=E6=96=B0=E8=A6=8F=E3=81=AB=E3=83=95?= =?UTF-8?q?=E3=82=A9=E3=83=AD=E3=83=BC=E3=81=97=E3=81=9F=E4=BA=BA=E3=81=AE?= =?UTF-8?q?withReplies=E3=82=92true=E3=81=AB=E3=81=99=E3=82=8B=E6=A9=9F?= =?UTF-8?q?=E8=83=BD=E3=82=92=E8=BF=BD=E5=8A=A0=20(#12048)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add defaultWithReplies to MiUser * feat: use defaultWithReplies when creating MiFollowing * feat: update defaultWithReplies from API * feat: return defaultWithReplies as a part of $i * feat(frontend): configure defaultWithReplies * docs(changelog): 新規にフォローした人のをデフォルトでTL二追加できるように * fix: typo * style: fix lint failure * chore: improve UI text * chore: make optional params of UserFollowingService.follow() object * chore: UserFollowingService.follow() accept withReplies * chore: add withReplies to MiFollowRequest * chore: process withReplies for follow request * feat: accept withReplies on 'following/create' endpoint * feat: store defaultWithReplies in client store * Revert "feat: return defaultWithReplies as a part of $i" This reverts commit f2cc4fe6 * Revert "feat: update defaultWithReplies from API" This reverts commit 95e3cee6 * Revert "feat: add defaultWithReplies to MiUser" This reverts commit 9f5ab14d7063532de2b049bc2ed40a15658168f5. * feat: configuring withReplies in import-following * feat(frontend): configure withReplies * fix(frontend): incorrectly showRepliesToOthersInTimeline can be shown * fix(backend): withReplies of following/create not working * fix(frontend): importFollowing error * fix: withReplies is not working with follow import * fix(frontend): use v-model * style: fix lint --------- Co-authored-by: Sayamame-beans <61457993+sayamame-beans@users.noreply.github.com> Co-authored-by: syuilo --- CHANGELOG.md | 1 + locales/index.d.ts | 2 ++ locales/ja-JP.yml | 2 ++ .../1697441463087-FollowRequestWithReplies.js | 17 ++++++++++++++++ packages/backend/src/core/QueueService.ts | 10 ++++++---- .../backend/src/core/UserFollowingService.ts | 20 +++++++++++++++---- .../src/core/activitypub/ApInboxService.ts | 2 +- packages/backend/src/models/FollowRequest.ts | 5 +++++ .../ImportFollowingProcessorService.ts | 6 +++--- .../RelationshipProcessorService.ts | 8 ++++++-- packages/backend/src/queue/types.ts | 3 +++ .../server/api/endpoints/following/create.ts | 3 ++- .../api/endpoints/i/import-following.ts | 3 ++- .../src/components/MkFollowButton.vue | 10 ++++++++++ .../frontend/src/components/MkUserPopup.vue | 2 +- packages/frontend/src/pages/follow.vue | 3 +++ packages/frontend/src/pages/gallery/post.vue | 2 +- .../frontend/src/pages/settings/general.vue | 2 ++ .../src/pages/settings/import-export.vue | 10 +++++++++- packages/frontend/src/pages/user/home.vue | 5 +++-- packages/frontend/src/store.ts | 4 ++++ packages/misskey-js/etc/misskey-js.api.md | 3 ++- packages/misskey-js/src/api.types.ts | 5 ++++- 23 files changed, 105 insertions(+), 23 deletions(-) create mode 100644 packages/backend/migration/1697441463087-FollowRequestWithReplies.js diff --git a/CHANGELOG.md b/CHANGELOG.md index af68dabcd6..87c9967c46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - Feat: アンテナでローカルの投稿のみ収集できるようになりました - Feat: サーバーサイレンス機能が追加されました - Enhance: 依存関係の更新 +- Enhance: 新規にフォローした人のをデフォルトでTLに追加できるように ### Client - Enhance: TLの返信表示オプションを記憶するように diff --git a/locales/index.d.ts b/locales/index.d.ts index 483c470be8..363032eaa2 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -537,6 +537,7 @@ export interface Locale { "deleteAll": string; "showFixedPostForm": string; "showFixedPostFormInChannel": string; + "withRepliesByDefaultForNewlyFollowed": string; "newNoteRecived": string; "sounds": string; "sound": string; @@ -2054,6 +2055,7 @@ export interface Locale { "userLists": string; "excludeMutingUsers": string; "excludeInactiveUsers": string; + "withReplies": string; }; "_charts": { "federation": string; diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 725d1e7a87..bc539d17dd 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -534,6 +534,7 @@ serverLogs: "サーバーログ" deleteAll: "全て削除" showFixedPostForm: "タイムライン上部に投稿フォームを表示する" showFixedPostFormInChannel: "タイムライン上部に投稿フォームを表示する(チャンネル)" +withRepliesByDefaultForNewlyFollowed: "フォローする際、デフォルトで返信をTLに含むようにする" newNoteRecived: "新しいノートがあります" sounds: "サウンド" sound: "サウンド" @@ -1969,6 +1970,7 @@ _exportOrImport: userLists: "リスト" excludeMutingUsers: "ミュートしているユーザーを除外" excludeInactiveUsers: "使われていないアカウントを除外" + withReplies: "インポートした人による返信をTLに含むようにする" _charts: federation: "連合" diff --git a/packages/backend/migration/1697441463087-FollowRequestWithReplies.js b/packages/backend/migration/1697441463087-FollowRequestWithReplies.js new file mode 100644 index 0000000000..214c6f6680 --- /dev/null +++ b/packages/backend/migration/1697441463087-FollowRequestWithReplies.js @@ -0,0 +1,17 @@ +/* + * SPDX-FileCopyrightText: syuilo and other misskey contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + + +export class FollowRequestWithReplies1697441463087 { + name = 'FollowRequestWithReplies1697441463087' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "follow_request" ADD "withReplies" boolean NOT NULL DEFAULT false`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "follow_request" DROP COLUMN "withReplies"`); + } +} diff --git a/packages/backend/src/core/QueueService.ts b/packages/backend/src/core/QueueService.ts index d8c7250034..be378a899b 100644 --- a/packages/backend/src/core/QueueService.ts +++ b/packages/backend/src/core/QueueService.ts @@ -237,10 +237,11 @@ export class QueueService { } @bindThis - public createImportFollowingJob(user: ThinUser, fileId: MiDriveFile['id']) { + public createImportFollowingJob(user: ThinUser, fileId: MiDriveFile['id'], withReplies?: boolean) { return this.dbQueue.add('importFollowing', { user: { id: user.id }, fileId: fileId, + withReplies, }, { removeOnComplete: true, removeOnFail: true, @@ -248,8 +249,8 @@ export class QueueService { } @bindThis - public createImportFollowingToDbJob(user: ThinUser, targets: string[]) { - const jobs = targets.map(rel => this.generateToDbJobData('importFollowingToDb', { user, target: rel })); + public createImportFollowingToDbJob(user: ThinUser, targets: string[], withReplies?: boolean) { + const jobs = targets.map(rel => this.generateToDbJobData('importFollowingToDb', { user, target: rel, withReplies })); return this.dbQueue.addBulk(jobs); } @@ -342,7 +343,7 @@ export class QueueService { } @bindThis - public createFollowJob(followings: { from: ThinUser, to: ThinUser, requestId?: string, silent?: boolean }[]) { + public createFollowJob(followings: { from: ThinUser, to: ThinUser, requestId?: string, silent?: boolean, withReplies?: boolean }[]) { const jobs = followings.map(rel => this.generateRelationshipJobData('follow', rel)); return this.relationshipQueue.addBulk(jobs); } @@ -384,6 +385,7 @@ export class QueueService { to: { id: data.to.id }, silent: data.silent, requestId: data.requestId, + withReplies: data.withReplies, }, opts: { removeOnComplete: true, diff --git a/packages/backend/src/core/UserFollowingService.ts b/packages/backend/src/core/UserFollowingService.ts index 87484f0383..7548e3d28f 100644 --- a/packages/backend/src/core/UserFollowingService.ts +++ b/packages/backend/src/core/UserFollowingService.ts @@ -93,7 +93,15 @@ export class UserFollowingService implements OnModuleInit { } @bindThis - public async follow(_follower: { id: MiUser['id'] }, _followee: { id: MiUser['id'] }, requestId?: string, silent = false): Promise { + public async follow( + _follower: { id: MiUser['id'] }, + _followee: { id: MiUser['id'] }, + { requestId, silent = false, withReplies }: { + requestId?: string, + silent?: boolean, + withReplies?: boolean, + } = {}, + ): Promise { const [follower, followee] = await Promise.all([ this.usersRepository.findOneByOrFail({ id: _follower.id }), this.usersRepository.findOneByOrFail({ id: _followee.id }), @@ -171,12 +179,12 @@ export class UserFollowingService implements OnModuleInit { } if (!autoAccept) { - await this.createFollowRequest(follower, followee, requestId); + await this.createFollowRequest(follower, followee, requestId, withReplies); return; } } - await this.insertFollowingDoc(followee, follower, silent); + await this.insertFollowingDoc(followee, follower, silent, withReplies); if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) { const content = this.apRendererService.addContext(this.apRendererService.renderAccept(this.apRendererService.renderFollow(follower, followee, requestId), followee)); @@ -193,6 +201,7 @@ export class UserFollowingService implements OnModuleInit { id: MiUser['id']; host: MiUser['host']; uri: MiUser['host']; inbox: MiUser['inbox']; sharedInbox: MiUser['sharedInbox'] }, silent = false, + withReplies?: boolean, ): Promise { if (follower.id === followee.id) return; @@ -202,6 +211,7 @@ export class UserFollowingService implements OnModuleInit { id: this.idService.gen(), followerId: follower.id, followeeId: followee.id, + withReplies: withReplies, // 非正規化 followerHost: follower.host, @@ -454,6 +464,7 @@ export class UserFollowingService implements OnModuleInit { id: MiUser['id']; host: MiUser['host']; uri: MiUser['host']; inbox: MiUser['inbox']; sharedInbox: MiUser['sharedInbox']; }, requestId?: string, + withReplies?: boolean, ): Promise { if (follower.id === followee.id) return; @@ -471,6 +482,7 @@ export class UserFollowingService implements OnModuleInit { followerId: follower.id, followeeId: followee.id, requestId, + withReplies, // 非正規化 followerHost: follower.host, @@ -555,7 +567,7 @@ export class UserFollowingService implements OnModuleInit { throw new IdentifiableError('8884c2dd-5795-4ac9-b27e-6a01d38190f9', 'No follow request.'); } - await this.insertFollowingDoc(followee, follower); + await this.insertFollowingDoc(followee, follower, false, request.withReplies); if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) { const content = this.apRendererService.addContext(this.apRendererService.renderAccept(this.apRendererService.renderFollow(follower, followee as MiPartialLocalUser, request.requestId!), followee)); diff --git a/packages/backend/src/core/activitypub/ApInboxService.ts b/packages/backend/src/core/activitypub/ApInboxService.ts index 8d5d34d40b..7aba140689 100644 --- a/packages/backend/src/core/activitypub/ApInboxService.ts +++ b/packages/backend/src/core/activitypub/ApInboxService.ts @@ -164,7 +164,7 @@ export class ApInboxService { } // don't queue because the sender may attempt again when timeout - await this.userFollowingService.follow(actor, followee, activity.id); + await this.userFollowingService.follow(actor, followee, { requestId: activity.id }); return 'ok'; } diff --git a/packages/backend/src/models/FollowRequest.ts b/packages/backend/src/models/FollowRequest.ts index 1e907f3d68..9899694dd6 100644 --- a/packages/backend/src/models/FollowRequest.ts +++ b/packages/backend/src/models/FollowRequest.ts @@ -45,6 +45,11 @@ export class MiFollowRequest { }) public requestId: string | null; + @Column('boolean', { + default: false, + }) + public withReplies: boolean; + //#region Denormalized fields @Column('varchar', { length: 128, nullable: true, diff --git a/packages/backend/src/queue/processors/ImportFollowingProcessorService.ts b/packages/backend/src/queue/processors/ImportFollowingProcessorService.ts index 2b5e41a12d..e75499a56f 100644 --- a/packages/backend/src/queue/processors/ImportFollowingProcessorService.ts +++ b/packages/backend/src/queue/processors/ImportFollowingProcessorService.ts @@ -56,7 +56,7 @@ export class ImportFollowingProcessorService { const csv = await this.downloadService.downloadTextFile(file.url); const targets = csv.trim().split('\n'); - this.queueService.createImportFollowingToDbJob({ id: user.id }, targets); + this.queueService.createImportFollowingToDbJob({ id: user.id }, targets, job.data.withReplies); this.logger.succ('Import jobs created'); } @@ -93,9 +93,9 @@ export class ImportFollowingProcessorService { // skip myself if (target.id === job.data.user.id) return; - this.logger.info(`Follow ${target.id} ...`); + this.logger.info(`Follow ${target.id} ${job.data.withReplies ? 'with replies' : 'without replies'} ...`); - this.queueService.createFollowJob([{ from: user, to: { id: target.id }, silent: true }]); + this.queueService.createFollowJob([{ from: user, to: { id: target.id }, silent: true, withReplies: job.data.withReplies }]); } catch (e) { this.logger.warn(`Error: ${e}`); } diff --git a/packages/backend/src/queue/processors/RelationshipProcessorService.ts b/packages/backend/src/queue/processors/RelationshipProcessorService.ts index 5b2d2ef313..b2d8e3631f 100644 --- a/packages/backend/src/queue/processors/RelationshipProcessorService.ts +++ b/packages/backend/src/queue/processors/RelationshipProcessorService.ts @@ -34,8 +34,12 @@ export class RelationshipProcessorService { @bindThis public async processFollow(job: Bull.Job): Promise { - this.logger.info(`${job.data.from.id} is trying to follow ${job.data.to.id}`); - await this.userFollowingService.follow(job.data.from, job.data.to, job.data.requestId, job.data.silent); + this.logger.info(`${job.data.from.id} is trying to follow ${job.data.to.id} ${job.data.withReplies ? "with replies" : "without replies"}`); + await this.userFollowingService.follow(job.data.from, job.data.to, { + requestId: job.data.requestId, + silent: job.data.silent, + withReplies: job.data.withReplies, + }); return 'ok'; } diff --git a/packages/backend/src/queue/types.ts b/packages/backend/src/queue/types.ts index c9122f5ca2..9330c01528 100644 --- a/packages/backend/src/queue/types.ts +++ b/packages/backend/src/queue/types.ts @@ -32,6 +32,7 @@ export type RelationshipJobData = { to: ThinUser; silent?: boolean; requestId?: string; + withReplies?: boolean; } export type DbJobData = DbJobMap[T]; @@ -79,6 +80,7 @@ export type DbUserDeleteJobData = { export type DbUserImportJobData = { user: ThinUser; fileId: MiDriveFile['id']; + withReplies?: boolean; }; export type DBAntennaImportJobData = { @@ -89,6 +91,7 @@ export type DBAntennaImportJobData = { export type DbUserImportToDbJobData = { user: ThinUser; target: string; + withReplies?: boolean; }; export type ObjectStorageJobData = ObjectStorageFileJobData | Record; diff --git a/packages/backend/src/server/api/endpoints/following/create.ts b/packages/backend/src/server/api/endpoints/following/create.ts index e0e7fed87a..9037944ef9 100644 --- a/packages/backend/src/server/api/endpoints/following/create.ts +++ b/packages/backend/src/server/api/endpoints/following/create.ts @@ -71,6 +71,7 @@ export const paramDef = { type: 'object', properties: { userId: { type: 'string', format: 'misskey:id' }, + withReplies: { type: 'boolean' } }, required: ['userId'], } as const; @@ -112,7 +113,7 @@ export default class extends Endpoint { // eslint- } try { - await this.userFollowingService.follow(follower, followee); + await this.userFollowingService.follow(follower, followee, { withReplies: ps.withReplies }); } catch (e) { if (e instanceof IdentifiableError) { if (e.id === '710e8fb0-b8c3-4922-be49-d5d93d8e6a6e') throw new ApiError(meta.errors.blocking); diff --git a/packages/backend/src/server/api/endpoints/i/import-following.ts b/packages/backend/src/server/api/endpoints/i/import-following.ts index 38c9283043..e5fa2ac96a 100644 --- a/packages/backend/src/server/api/endpoints/i/import-following.ts +++ b/packages/backend/src/server/api/endpoints/i/import-following.ts @@ -52,6 +52,7 @@ export const paramDef = { type: 'object', properties: { fileId: { type: 'string', format: 'misskey:id' }, + withReplies: { type: 'boolean' }, }, required: ['fileId'], } as const; @@ -79,7 +80,7 @@ export default class extends Endpoint { // eslint- ); if (checkMoving ? file.size > 32 * 1024 * 1024 : file.size > 64 * 1024) throw new ApiError(meta.errors.tooBigFile); - this.queueService.createImportFollowingJob(me, file.id); + this.queueService.createImportFollowingJob(me, file.id, ps.withReplies); }); } } diff --git a/packages/frontend/src/components/MkFollowButton.vue b/packages/frontend/src/components/MkFollowButton.vue index 15043fcd0b..b8de71e3b7 100644 --- a/packages/frontend/src/components/MkFollowButton.vue +++ b/packages/frontend/src/components/MkFollowButton.vue @@ -42,6 +42,7 @@ import { useStream } from '@/stream.js'; import { i18n } from '@/i18n.js'; import { claimAchievement } from '@/scripts/achievements.js'; import { $i } from '@/account.js'; +import { defaultStore } from "@/store.js"; const props = withDefaults(defineProps<{ user: Misskey.entities.UserDetailed, @@ -52,6 +53,10 @@ const props = withDefaults(defineProps<{ large: false, }); +const emit = defineEmits<{ + (_: 'update:user', value: Misskey.entities.UserDetailed): void +}>(); + let isFollowing = $ref(props.user.isFollowing); let hasPendingFollowRequestFromYou = $ref(props.user.hasPendingFollowRequestFromYou); let wait = $ref(false); @@ -95,6 +100,11 @@ async function onClick() { } else { await os.api('following/create', { userId: props.user.id, + withReplies: defaultStore.state.defaultWithReplies, + }); + emit('update:user', { + ...props.user, + withReplies: defaultStore.state.defaultWithReplies }); hasPendingFollowRequestFromYou = true; diff --git a/packages/frontend/src/components/MkUserPopup.vue b/packages/frontend/src/components/MkUserPopup.vue index 33ef07d54b..bcba4196b5 100644 --- a/packages/frontend/src/components/MkUserPopup.vue +++ b/packages/frontend/src/components/MkUserPopup.vue @@ -45,7 +45,7 @@ SPDX-License-Identifier: AGPL-3.0-only - +
diff --git a/packages/frontend/src/pages/follow.vue b/packages/frontend/src/pages/follow.vue index e382cabd74..a0a4a480b5 100644 --- a/packages/frontend/src/pages/follow.vue +++ b/packages/frontend/src/pages/follow.vue @@ -14,6 +14,7 @@ import * as Misskey from 'misskey-js'; import * as os from '@/os.js'; import { mainRouter } from '@/router.js'; import { i18n } from '@/i18n.js'; +import { defaultStore } from "@/store.js"; async function follow(user): Promise { const { canceled } = await os.confirm({ @@ -28,7 +29,9 @@ async function follow(user): Promise { os.apiWithDialog('following/create', { userId: user.id, + withReplies: defaultStore.state.defaultWithReplies, }); + user.withReplies = defaultStore.state.defaultWithReplies; } const acct = new URL(location.href).searchParams.get('acct'); diff --git a/packages/frontend/src/pages/gallery/post.vue b/packages/frontend/src/pages/gallery/post.vue index 3f4f657e94..3863348eae 100644 --- a/packages/frontend/src/pages/gallery/post.vue +++ b/packages/frontend/src/pages/gallery/post.vue @@ -38,7 +38,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- + diff --git a/packages/frontend/src/pages/settings/general.vue b/packages/frontend/src/pages/settings/general.vue index 55de53fb07..30443fded6 100644 --- a/packages/frontend/src/pages/settings/general.vue +++ b/packages/frontend/src/pages/settings/general.vue @@ -29,6 +29,7 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts.showFixedPostForm }} {{ i18n.ts.showFixedPostFormInChannel }} + {{ i18n.ts.withRepliesByDefaultForNewlyFollowed }} @@ -249,6 +250,7 @@ const mediaListWithOneImageAppearance = computed(defaultStore.makeGetterSetter(' const notificationPosition = computed(defaultStore.makeGetterSetter('notificationPosition')); const notificationStackAxis = computed(defaultStore.makeGetterSetter('notificationStackAxis')); const keepScreenOn = computed(defaultStore.makeGetterSetter('keepScreenOn')); +const defaultWithReplies = computed(defaultStore.makeGetterSetter('defaultWithReplies')); watch(lang, () => { miLocalStorage.setItem('lang', lang.value as string); diff --git a/packages/frontend/src/pages/settings/import-export.vue b/packages/frontend/src/pages/settings/import-export.vue index 0574a878ae..0f01fda26f 100644 --- a/packages/frontend/src/pages/settings/import-export.vue +++ b/packages/frontend/src/pages/settings/import-export.vue @@ -40,6 +40,9 @@ SPDX-License-Identifier: AGPL-3.0-only + + {{ i18n.ts._exportOrImport.withReplies }} + {{ i18n.ts.import }}
@@ -118,9 +121,11 @@ import { selectFile } from '@/scripts/select-file.js'; import { i18n } from '@/i18n.js'; import { definePageMetadata } from '@/scripts/page-metadata.js'; import { $i } from '@/account.js'; +import { defaultStore } from "@/store.js"; const excludeMutingUsers = ref(false); const excludeInactiveUsers = ref(false); +const withReplies = ref(defaultStore.state.defaultWithReplies); const onExportSuccess = () => { os.alert({ @@ -177,7 +182,10 @@ const exportAntennas = () => { const importFollowing = async (ev) => { const file = await selectFile(ev.currentTarget ?? ev.target); - os.api('i/import-following', { fileId: file.id }).then(onImportSuccess).catch(onError); + os.api('i/import-following', { + fileId: file.id, + withReplies: withReplies.value, + }).then(onImportSuccess).catch(onError); }; const importUserLists = async (ev) => { diff --git a/packages/frontend/src/pages/user/home.vue b/packages/frontend/src/pages/user/home.vue index 605e9fbb76..4c425898d5 100644 --- a/packages/frontend/src/pages/user/home.vue +++ b/packages/frontend/src/pages/user/home.vue @@ -34,7 +34,7 @@ SPDX-License-Identifier: AGPL-3.0-only {{ i18n.ts.followsYou }}
- +
@@ -198,6 +198,7 @@ const props = withDefaults(defineProps<{ const router = useRouter(); +let user = $ref(props.user); let parallaxAnimationId = $ref(null); let narrow = $ref(null); let rootEl = $ref(null); @@ -232,7 +233,7 @@ const age = $computed(() => { }); function menu(ev) { - const { menu, cleanup } = getUserMenu(props.user, router); + const { menu, cleanup } = getUserMenu(user, router); os.popupMenu(menu, ev.currentTarget ?? ev.target).finally(cleanup); } diff --git a/packages/frontend/src/store.ts b/packages/frontend/src/store.ts index 2829411ae5..92d01e4caf 100644 --- a/packages/frontend/src/store.ts +++ b/packages/frontend/src/store.ts @@ -361,6 +361,10 @@ export const defaultStore = markRaw(new Storage('base', { where: 'device', default: false, }, + defaultWithReplies: { + where: 'account', + default: false, + }, })); // TODO: 他のタブと永続化されたstateを同期 diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md index 6b01321047..895f34689b 100644 --- a/packages/misskey-js/etc/misskey-js.api.md +++ b/packages/misskey-js/etc/misskey-js.api.md @@ -1185,6 +1185,7 @@ export type Endpoints = { 'following/create': { req: { userId: User['id']; + withReplies?: boolean; }; res: User; }; @@ -2985,7 +2986,7 @@ type UserSorting = '+follower' | '-follower' | '+createdAt' | '-createdAt' | '+u // // src/api.types.ts:16:32 - (ae-forgotten-export) The symbol "TODO" needs to be exported by the entry point index.d.ts // src/api.types.ts:18:25 - (ae-forgotten-export) The symbol "NoParams" needs to be exported by the entry point index.d.ts -// src/api.types.ts:630:18 - (ae-forgotten-export) The symbol "ShowUserReq" needs to be exported by the entry point index.d.ts +// src/api.types.ts:633:18 - (ae-forgotten-export) The symbol "ShowUserReq" needs to be exported by the entry point index.d.ts // src/entities.ts:107:2 - (ae-forgotten-export) The symbol "notificationTypes_2" needs to be exported by the entry point index.d.ts // src/entities.ts:603:2 - (ae-forgotten-export) The symbol "ModerationLogPayloads" needs to be exported by the entry point index.d.ts // src/streaming.types.ts:33:4 - (ae-forgotten-export) The symbol "FIXME" needs to be exported by the entry point index.d.ts diff --git a/packages/misskey-js/src/api.types.ts b/packages/misskey-js/src/api.types.ts index a7a2ea1b36..8c6205bf51 100644 --- a/packages/misskey-js/src/api.types.ts +++ b/packages/misskey-js/src/api.types.ts @@ -321,7 +321,10 @@ export type Endpoints = { 'federation/users': { req: { host: string; limit?: number; sinceId?: User['id']; untilId?: User['id']; }; res: UserDetailed[]; }; // following - 'following/create': { req: { userId: User['id'] }; res: User; }; + 'following/create': { req: { + userId: User['id'], + withReplies?: boolean, + }; res: User; }; 'following/delete': { req: { userId: User['id'] }; res: User; }; 'following/requests/accept': { req: { userId: User['id'] }; res: null; }; 'following/requests/cancel': { req: { userId: User['id'] }; res: User; };