From 464884c1ab1a2dff5bad69de700e4feb949ba346 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=BE=E3=81=A3=E3=81=A1=E3=82=83=E3=81=A8=E3=83=BC?= =?UTF-8?q?=E3=81=AB=E3=82=85?= <17376330+u1-liquid@users.noreply.github.com> Date: Tue, 23 Jan 2024 23:03:05 +0900 Subject: [PATCH 1/3] =?UTF-8?q?fix(pizzax):=20`null`=E3=81=AE=E8=A8=AD?= =?UTF-8?q?=E5=AE=9A=E5=80=A4=E3=81=8C=E3=83=87=E3=83=95=E3=82=A9=E3=83=AB?= =?UTF-8?q?=E3=83=88=E3=81=AB=E7=BD=AE=E3=81=8D=E6=8F=9B=E3=81=88=E3=82=89?= =?UTF-8?q?=E3=82=8C=E3=81=A6=E3=81=97=E3=81=BE=E3=81=86=E5=95=8F=E9=A1=8C?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/frontend/package.json | 3 ++- packages/frontend/src/pizzax.ts | 20 ++++---------------- pnpm-lock.yaml | 20 +++++++++++++++++--- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/packages/frontend/package.json b/packages/frontend/package.json index 31afdcb5ea..939b983896 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -44,7 +44,6 @@ "compare-versions": "6.1.0", "cropperjs": "2.0.0-beta.4", "date-fns": "2.30.0", - "defu": "^6.1.4", "escape-regexp": "0.0.1", "estree-walker": "3.0.3", "eventemitter3": "5.0.1", @@ -52,6 +51,7 @@ "insert-text-at-cursor": "0.3.0", "is-file-animated": "1.0.2", "json5": "2.2.3", + "lodash.defaultsdeep": "4.6.1", "matter-js": "0.19.0", "mfm-js": "0.24.0", "misskey-bubble-game": "workspace:*", @@ -101,6 +101,7 @@ "@testing-library/vue": "8.0.1", "@types/escape-regexp": "0.0.3", "@types/estree": "1.0.5", + "@types/lodash.defaultsdeep": "4.6.9", "@types/matter-js": "0.19.6", "@types/micromatch": "4.0.6", "@types/node": "20.11.5", diff --git a/packages/frontend/src/pizzax.ts b/packages/frontend/src/pizzax.ts index b3d2374899..9644b8afad 100644 --- a/packages/frontend/src/pizzax.ts +++ b/packages/frontend/src/pizzax.ts @@ -7,7 +7,7 @@ import { onUnmounted, Ref, ref, watch } from 'vue'; import { BroadcastChannel } from 'broadcast-channel'; -import { defu } from 'defu'; +import defaultsDeep from 'lodash.defaultsdeep'; import { $i } from '@/account.js'; import { misskeyApi } from '@/scripts/misskey-api.js'; import { get, set } from '@/scripts/idb-proxy.js'; @@ -81,18 +81,6 @@ export class Storage { this.loaded = this.ready.then(() => this.load()); } - private isPureObject(value: unknown): value is Record { - return typeof value === 'object' && value !== null && !Array.isArray(value); - } - - private mergeState(value: T, def: T): T { - if (this.isPureObject(value) && this.isPureObject(def)) { - if (_DEV_) console.log('Merging state. Incoming: ', value, ' Default: ', def); - return defu(value, def) as T; - } - return value; - } - private async init(): Promise { await this.migrate(); @@ -102,11 +90,11 @@ export class Storage { for (const [k, v] of Object.entries(this.def) as [keyof T, T[keyof T]['default']][]) { if (v.where === 'device' && Object.prototype.hasOwnProperty.call(deviceState, k)) { - this.reactiveState[k].value = this.state[k] = this.mergeState(deviceState[k], v.default); + this.reactiveState[k].value = this.state[k] = defaultsDeep(deviceState[k], v.default); } else if (v.where === 'account' && $i && Object.prototype.hasOwnProperty.call(registryCache, k)) { - this.reactiveState[k].value = this.state[k] = this.mergeState(registryCache[k], v.default); + this.reactiveState[k].value = this.state[k] = defaultsDeep(registryCache[k], v.default); } else if (v.where === 'deviceAccount' && Object.prototype.hasOwnProperty.call(deviceAccountState, k)) { - this.reactiveState[k].value = this.state[k] = this.mergeState(deviceAccountState[k], v.default); + this.reactiveState[k].value = this.state[k] = defaultsDeep(deviceAccountState[k], v.default); } else { this.reactiveState[k].value = this.state[k] = v.default; if (_DEV_) console.log('Use default value', k, v.default); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 185440fa19..c78a9bb64c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -746,9 +746,6 @@ importers: date-fns: specifier: 2.30.0 version: 2.30.0 - defu: - specifier: ^6.1.4 - version: 6.1.4 escape-regexp: specifier: 0.0.1 version: 0.0.1 @@ -770,6 +767,9 @@ importers: json5: specifier: 2.2.3 version: 2.2.3 + lodash.defaultsdeep: + specifier: 4.6.1 + version: 4.6.1 matter-js: specifier: 0.19.0 version: 0.19.0 @@ -912,6 +912,9 @@ importers: '@types/estree': specifier: 1.0.5 version: 1.0.5 + '@types/lodash.defaultsdeep': + specifier: 4.6.9 + version: 4.6.9 '@types/matter-js': specifier: 0.19.6 version: 0.19.6 @@ -7813,6 +7816,12 @@ packages: '@types/node': 20.11.5 dev: false + /@types/lodash.defaultsdeep@4.6.9: + resolution: {integrity: sha512-pLtCFK0YkHfGtGLYLNMTbFB5/G5+RsmQCIbbHH8GOAXjv+gDkVilY98kILfe8JH2Kev0OCReYxp1AjxEjP8ixA==} + dependencies: + '@types/lodash': 4.14.202 + dev: true + /@types/lodash@4.14.202: resolution: {integrity: sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==} dev: true @@ -10589,6 +10598,7 @@ packages: /defu@6.1.4: resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + dev: true /del@6.1.1: resolution: {integrity: sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==} @@ -14155,6 +14165,10 @@ packages: resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} dev: false + /lodash.defaultsdeep@4.6.1: + resolution: {integrity: sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==} + dev: false + /lodash.get@4.4.2: resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} dev: true From 1dde8653e8e0ae76b52f6a3c8e3aa9a684619aa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=BE=E3=81=A3=E3=81=A1=E3=82=83=E3=81=A8=E3=83=BC?= =?UTF-8?q?=E3=81=AB=E3=82=85?= <17376330+u1-liquid@users.noreply.github.com> Date: Tue, 23 Jan 2024 23:20:34 +0900 Subject: [PATCH 2/3] =?UTF-8?q?fix(stream):=20=E3=83=81=E3=83=A3=E3=83=B3?= =?UTF-8?q?=E3=83=8D=E3=83=AB=E6=8E=A5=E7=B6=9A=E4=B8=BB=E3=81=AB=E8=A6=8B?= =?UTF-8?q?=E3=81=88=E3=81=AA=E3=81=84=E3=81=AF=E3=81=9A=E3=81=AE=E3=83=8E?= =?UTF-8?q?=E3=83=BC=E3=83=88=E3=81=8C=E8=A1=A8=E7=A4=BA=E3=81=95=E3=82=8C?= =?UTF-8?q?=E3=82=8B=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/server/api/stream/channels/antenna.ts | 8 ++++++++ .../src/server/api/stream/channels/channel.ts | 8 ++++++++ .../server/api/stream/channels/global-timeline.ts | 15 ++++++++++++--- .../src/server/api/stream/channels/hashtag.ts | 8 ++++++++ .../server/api/stream/channels/home-timeline.ts | 2 ++ .../server/api/stream/channels/hybrid-timeline.ts | 2 ++ .../server/api/stream/channels/local-timeline.ts | 13 ++++++++++--- .../server/api/stream/channels/role-timeline.ts | 8 ++++++++ .../src/server/api/stream/channels/user-list.ts | 2 ++ 9 files changed, 60 insertions(+), 6 deletions(-) diff --git a/packages/backend/src/server/api/stream/channels/antenna.ts b/packages/backend/src/server/api/stream/channels/antenna.ts index 200db8eb0e..a20e74bfb2 100644 --- a/packages/backend/src/server/api/stream/channels/antenna.ts +++ b/packages/backend/src/server/api/stream/channels/antenna.ts @@ -40,6 +40,14 @@ class AntennaChannel extends Channel { if (data.type === 'note') { const note = await this.noteEntityService.pack(data.body.id, this.user, { detail: true }); + if (note.reply) { + const reply = note.reply; + // 自分のフォローしていないユーザーの visibility: followers な投稿への返信は弾く + if (reply.visibility === 'followers' && !Object.hasOwn(this.following, reply.userId)) return; + // 自分の見ることができないユーザーの visibility: specified な投稿への返信は弾く + if (reply.visibility === 'specified' && !reply.visibleUserIds!.includes(this.user!.id)) return; + } + // 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する if (isUserRelated(note, this.userIdsWhoMeMuting)) return; // 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する diff --git a/packages/backend/src/server/api/stream/channels/channel.ts b/packages/backend/src/server/api/stream/channels/channel.ts index 20275249b8..9d6feb0d1e 100644 --- a/packages/backend/src/server/api/stream/channels/channel.ts +++ b/packages/backend/src/server/api/stream/channels/channel.ts @@ -38,6 +38,14 @@ class ChannelChannel extends Channel { private async onNote(note: Packed<'Note'>) { if (note.channelId !== this.channelId) return; + if (note.reply) { + const reply = note.reply; + // 自分のフォローしていないユーザーの visibility: followers な投稿への返信は弾く + if (reply.visibility === 'followers' && !Object.hasOwn(this.following, reply.userId)) return; + // 自分の見ることができないユーザーの visibility: specified な投稿への返信は弾く + if (reply.visibility === 'specified' && !reply.visibleUserIds!.includes(this.user!.id)) return; + } + // 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する if (isUserRelated(note, this.userIdsWhoMeMuting)) return; // 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する diff --git a/packages/backend/src/server/api/stream/channels/global-timeline.ts b/packages/backend/src/server/api/stream/channels/global-timeline.ts index 15a32f4512..ddc74566bb 100644 --- a/packages/backend/src/server/api/stream/channels/global-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/global-timeline.ts @@ -19,6 +19,7 @@ class GlobalTimelineChannel extends Channel { public static shouldShare = false; public static requireCredential = false as const; private withRenotes: boolean; + private withReplies: boolean; private withFiles: boolean; constructor( @@ -39,6 +40,7 @@ class GlobalTimelineChannel extends Channel { if (!policies.gtlAvailable) return; this.withRenotes = params.withRenotes ?? true; + this.withReplies = params.withReplies ?? false; this.withFiles = params.withFiles ?? false; // Subscribe events @@ -56,10 +58,17 @@ class GlobalTimelineChannel extends Channel { if (this.withFiles && (note.files === undefined || note.files.length === 0)) return; // 関係ない返信は除外 - if (note.reply && !this.following[note.userId]?.withReplies) { + if (note.reply) { const reply = note.reply; - // 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合 - if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return; + if ((this.following[note.userId]?.withReplies ?? false) || this.withReplies) { + // 自分のフォローしていないユーザーの visibility: followers な投稿への返信は弾く + if (reply.visibility === 'followers' && !Object.hasOwn(this.following, reply.userId)) return; + // 自分の見ることができないユーザーの visibility: specified な投稿への返信は弾く + if (reply.visibility === 'specified' && !reply.visibleUserIds!.includes(this.user!.id)) return; + } else { + // 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合 + if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return; + } } if (note.renote && note.text == null && (note.fileIds == null || note.fileIds.length === 0) && !this.withRenotes) return; diff --git a/packages/backend/src/server/api/stream/channels/hashtag.ts b/packages/backend/src/server/api/stream/channels/hashtag.ts index 3d4f2fc528..8fdb9c7808 100644 --- a/packages/backend/src/server/api/stream/channels/hashtag.ts +++ b/packages/backend/src/server/api/stream/channels/hashtag.ts @@ -43,6 +43,14 @@ class HashtagChannel extends Channel { const matched = this.q.some(tags => tags.every(tag => noteTags.includes(normalizeForSearch(tag)))); if (!matched) return; + if (note.reply) { + const reply = note.reply; + // 自分のフォローしていないユーザーの visibility: followers な投稿への返信は弾く + if (reply.visibility === 'followers' && !Object.hasOwn(this.following, reply.userId)) return; + // 自分の見ることができないユーザーの visibility: specified な投稿への返信は弾く + if (reply.visibility === 'specified' && !reply.visibleUserIds!.includes(this.user!.id)) return; + } + // 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する if (isUserRelated(note, this.userIdsWhoMeMuting)) return; // 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する diff --git a/packages/backend/src/server/api/stream/channels/home-timeline.ts b/packages/backend/src/server/api/stream/channels/home-timeline.ts index 1f3dd18810..e489a30665 100644 --- a/packages/backend/src/server/api/stream/channels/home-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/home-timeline.ts @@ -68,6 +68,8 @@ class HomeTimelineChannel extends Channel { if (this.following[note.userId]?.withReplies) { // 自分のフォローしていないユーザーの visibility: followers な投稿への返信は弾く if (reply.visibility === 'followers' && !Object.hasOwn(this.following, reply.userId)) return; + // 自分の見ることができないユーザーの visibility: specified な投稿への返信は弾く + if (reply.visibility === 'specified' && !reply.visibleUserIds!.includes(this.user!.id)) return; } else { // 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合 if (reply.userId !== this.user!.id && !isMe && reply.userId !== note.userId) return; diff --git a/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts b/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts index ffa4b8902f..7229297231 100644 --- a/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts @@ -82,6 +82,8 @@ class HybridTimelineChannel extends Channel { if ((this.following[note.userId]?.withReplies ?? false) || this.withReplies) { // 自分のフォローしていないユーザーの visibility: followers な投稿への返信は弾く if (reply.visibility === 'followers' && !Object.hasOwn(this.following, reply.userId)) return; + // 自分の見ることができないユーザーの visibility: specified な投稿への返信は弾く + if (reply.visibility === 'specified' && !reply.visibleUserIds!.includes(this.user!.id)) return; } else { // 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合 if (reply.userId !== this.user!.id && !isMe && reply.userId !== note.userId) return; diff --git a/packages/backend/src/server/api/stream/channels/local-timeline.ts b/packages/backend/src/server/api/stream/channels/local-timeline.ts index 7819b655af..6400ff5fc9 100644 --- a/packages/backend/src/server/api/stream/channels/local-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/local-timeline.ts @@ -58,10 +58,17 @@ class LocalTimelineChannel extends Channel { if (this.withFiles && (note.files === undefined || note.files.length === 0)) return; // 関係ない返信は除外 - if (note.reply && this.user && !this.following[note.userId]?.withReplies && !this.withReplies) { + if (note.reply) { const reply = note.reply; - // 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合 - if (reply.userId !== this.user.id && note.userId !== this.user.id && reply.userId !== note.userId) return; + if ((this.following[note.userId]?.withReplies ?? false) || this.withReplies) { + // 自分のフォローしていないユーザーの visibility: followers な投稿への返信は弾く + if (reply.visibility === 'followers' && !Object.hasOwn(this.following, reply.userId)) return; + // 自分の見ることができないユーザーの visibility: specified な投稿への返信は弾く + if (reply.visibility === 'specified' && !reply.visibleUserIds!.includes(this.user!.id)) return; + } else { + // 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合 + if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return; + } } if (note.renote && note.text == null && (note.fileIds == null || note.fileIds.length === 0) && !this.withRenotes) return; diff --git a/packages/backend/src/server/api/stream/channels/role-timeline.ts b/packages/backend/src/server/api/stream/channels/role-timeline.ts index 8aab6fc6a6..be762c5a3f 100644 --- a/packages/backend/src/server/api/stream/channels/role-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/role-timeline.ts @@ -46,6 +46,14 @@ class RoleTimelineChannel extends Channel { } if (note.visibility !== 'public') return; + if (note.reply) { + const reply = note.reply; + // 自分のフォローしていないユーザーの visibility: followers な投稿への返信は弾く + if (reply.visibility === 'followers' && !Object.hasOwn(this.following, reply.userId)) return; + // 自分の見ることができないユーザーの visibility: specified な投稿への返信は弾く + if (reply.visibility === 'specified' && !reply.visibleUserIds!.includes(this.user!.id)) return; + } + // 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する if (isUserRelated(note, this.userIdsWhoMeMuting)) return; // 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する diff --git a/packages/backend/src/server/api/stream/channels/user-list.ts b/packages/backend/src/server/api/stream/channels/user-list.ts index e0245814c4..d59ef5500c 100644 --- a/packages/backend/src/server/api/stream/channels/user-list.ts +++ b/packages/backend/src/server/api/stream/channels/user-list.ts @@ -100,6 +100,8 @@ class UserListChannel extends Channel { if (this.membershipsMap[note.userId]?.withReplies) { // 自分のフォローしていないユーザーの visibility: followers な投稿への返信は弾く if (reply.visibility === 'followers' && !Object.hasOwn(this.following, reply.userId)) return; + // 自分の見ることができないユーザーの visibility: specified な投稿への返信は弾く + if (reply.visibility === 'specified' && !reply.visibleUserIds!.includes(this.user!.id)) return; } else { // 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合 if (reply.userId !== this.user!.id && !isMe && reply.userId !== note.userId) return; From 905e093066952236439a15c3931ef47be0ac2146 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=BE=E3=81=A3=E3=81=A1=E3=82=83=E3=81=A8=E3=83=BC?= =?UTF-8?q?=E3=81=AB=E3=82=85?= <17376330+u1-liquid@users.noreply.github.com> Date: Tue, 23 Jan 2024 23:28:33 +0900 Subject: [PATCH 3/3] Bump up version to 2024.1.0-io.1 --- package.json | 2 +- packages/misskey-js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 6932f513ba..8308ccfec1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "2024.1.0-io", + "version": "2024.1.0-io.1", "codename": "nasubi", "repository": { "type": "git", diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json index 606270d293..5dafc0f430 100644 --- a/packages/misskey-js/package.json +++ b/packages/misskey-js/package.json @@ -1,7 +1,7 @@ { "type": "module", "name": "misskey-js", - "version": "2024.1.0-io", + "version": "2024.1.0-io.1", "description": "Misskey SDK for JavaScript", "types": "./built/dts/index.d.ts", "exports": {