From 6ff5bfd2bc6c286c689fee9577b9e9036112e689 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 20 Oct 2023 07:48:31 +0900 Subject: [PATCH 01/21] clean up --- .../backend/src/core/NoteCreateService.ts | 1 - .../core/entities/InstanceEntityService.ts | 2 +- packages/backend/src/misc/nyaize.ts | 20 ------------------- .../api/endpoints/notes/user-list-timeline.ts | 8 +------- 4 files changed, 2 insertions(+), 29 deletions(-) delete mode 100644 packages/backend/src/misc/nyaize.ts diff --git a/packages/backend/src/core/NoteCreateService.ts b/packages/backend/src/core/NoteCreateService.ts index f5cfe03122..364a300d23 100644 --- a/packages/backend/src/core/NoteCreateService.ts +++ b/packages/backend/src/core/NoteCreateService.ts @@ -55,7 +55,6 @@ import { MetaService } from '@/core/MetaService.js'; import { SearchService } from '@/core/SearchService.js'; import { FeaturedService } from '@/core/FeaturedService.js'; import { FunoutTimelineService } from '@/core/FunoutTimelineService.js'; -import { nyaize } from '@/misc/nyaize.js'; import { UtilityService } from '@/core/UtilityService.js'; type NotificationType = 'reply' | 'renote' | 'quote' | 'mention'; diff --git a/packages/backend/src/core/entities/InstanceEntityService.ts b/packages/backend/src/core/entities/InstanceEntityService.ts index 9afe87eab7..8bba150ece 100644 --- a/packages/backend/src/core/entities/InstanceEntityService.ts +++ b/packages/backend/src/core/entities/InstanceEntityService.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { Inject, Injectable } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import type { Packed } from '@/misc/json-schema.js'; import type { MiInstance } from '@/models/Instance.js'; import { MetaService } from '@/core/MetaService.js'; diff --git a/packages/backend/src/misc/nyaize.ts b/packages/backend/src/misc/nyaize.ts deleted file mode 100644 index 0ac77e1006..0000000000 --- a/packages/backend/src/misc/nyaize.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and other misskey contributors - * SPDX-License-Identifier: AGPL-3.0-only - */ - -export function nyaize(text: string): string { - return text - // ja-JP - .replaceAll('な', 'にゃ').replaceAll('ナ', 'ニャ').replaceAll('ナ', 'ニャ') - // en-US - .replace(/(?<=n)a/gi, x => x === 'A' ? 'YA' : 'ya') - .replace(/(?<=morn)ing/gi, x => x === 'ING' ? 'YAN' : 'yan') - .replace(/(?<=every)one/gi, x => x === 'ONE' ? 'NYAN' : 'nyan') - // ko-KR - .replace(/[나-낳]/g, match => String.fromCharCode( - match.charCodeAt(0)! + '냐'.charCodeAt(0) - '나'.charCodeAt(0), - )) - .replace(/(다$)|(다(?=\.))|(다(?= ))|(다(?=!))|(다(?=\?))/gm, '다냥') - .replace(/(야(?=\?))|(야$)|(야(?= ))/gm, '냥'); -} diff --git a/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts b/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts index 2b31e6169c..96e1e94f7c 100644 --- a/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts @@ -3,12 +3,9 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { Brackets } from 'typeorm'; import { Inject, Injectable } from '@nestjs/common'; -import * as Redis from 'ioredis'; -import type { NotesRepository, UserListsRepository, UserListMembershipsRepository, MiNote } from '@/models/_.js'; +import type { NotesRepository, UserListsRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import { QueryService } from '@/core/QueryService.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import ActiveUsersChart from '@/core/chart/charts/active-users.js'; import { DI } from '@/di-symbols.js'; @@ -67,9 +64,6 @@ export const paramDef = { @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( - @Inject(DI.redisForTimelines) - private redisForTimelines: Redis.Redis, - @Inject(DI.notesRepository) private notesRepository: NotesRepository, From 216b20d2dbbc042c59bf421502904da468c931fb Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 20 Oct 2023 08:02:32 +0900 Subject: [PATCH 02/21] =?UTF-8?q?fix(backend):=20=E8=87=AA=E5=88=86?= =?UTF-8?q?=E3=81=AE=E3=83=95=E3=82=A9=E3=83=AD=E3=83=AF=E3=83=BC=E9=99=90?= =?UTF-8?q?=E5=AE=9A=E3=83=8E=E3=83=BC=E3=83=88=E3=81=8CWebsoket=E3=81=AB?= =?UTF-8?q?=E4=B9=97=E3=81=A3=E3=81=A6=E3=81=93=E3=81=AA=E3=81=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix #12081 --- .../src/server/api/stream/channels/home-timeline.ts | 8 +++++--- .../src/server/api/stream/channels/hybrid-timeline.ts | 8 +++++--- .../backend/src/server/api/stream/channels/user-list.ts | 6 ++++-- 3 files changed, 14 insertions(+), 8 deletions(-) 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 2b235b9822..46071e82fa 100644 --- a/packages/backend/src/server/api/stream/channels/home-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/home-timeline.ts @@ -39,20 +39,22 @@ class HomeTimelineChannel extends Channel { @bindThis private async onNote(note: Packed<'Note'>) { + const isMe = this.user!.id === note.userId; + if (this.withFiles && (note.fileIds == null || note.fileIds.length === 0)) return; if (note.channelId) { if (!this.followingChannels.has(note.channelId)) return; } else { // その投稿のユーザーをフォローしていなかったら弾く - if ((this.user!.id !== note.userId) && !Object.hasOwn(this.following, note.userId)) return; + if (!isMe && !Object.hasOwn(this.following, note.userId)) return; } // Ignore notes from instances the user has muted if (isInstanceMuted(note, new Set(this.userProfile!.mutedInstances))) return; if (note.visibility === 'followers') { - if (!Object.hasOwn(this.following, note.userId)) return; + if (!isMe && !Object.hasOwn(this.following, note.userId)) return; } else if (note.visibility === 'specified') { if (!note.visibleUserIds!.includes(this.user!.id)) return; } @@ -61,7 +63,7 @@ class HomeTimelineChannel extends Channel { if (note.reply && !this.following[note.userId]?.withReplies) { const reply = note.reply; // 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合 - if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return; + if (reply.userId !== this.user!.id && !isMe && 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/hybrid-timeline.ts b/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts index 4e90912084..2722ebcd50 100644 --- a/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts @@ -49,6 +49,8 @@ class HybridTimelineChannel extends Channel { @bindThis private async onNote(note: Packed<'Note'>) { + const isMe = this.user!.id === note.userId; + if (this.withFiles && (note.fileIds == null || note.fileIds.length === 0)) return; // チャンネルの投稿ではなく、自分自身の投稿 または @@ -56,14 +58,14 @@ class HybridTimelineChannel extends Channel { // チャンネルの投稿ではなく、全体公開のローカルの投稿 または // フォローしているチャンネルの投稿 の場合だけ if (!( - (note.channelId == null && this.user!.id === note.userId) || + (note.channelId == null && isMe) || (note.channelId == null && Object.hasOwn(this.following, note.userId)) || (note.channelId == null && (note.user.host == null && note.visibility === 'public')) || (note.channelId != null && this.followingChannels.has(note.channelId)) )) return; if (note.visibility === 'followers') { - if (!Object.hasOwn(this.following, note.userId)) return; + if (!isMe && !Object.hasOwn(this.following, note.userId)) return; } else if (note.visibility === 'specified') { if (!note.visibleUserIds!.includes(this.user!.id)) return; } @@ -75,7 +77,7 @@ class HybridTimelineChannel extends Channel { if (note.reply && !this.following[note.userId]?.withReplies && !this.withReplies) { const reply = note.reply; // 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合 - if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return; + if (reply.userId !== this.user!.id && !isMe && 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/user-list.ts b/packages/backend/src/server/api/stream/channels/user-list.ts index 6d83d4cb5b..68927987d6 100644 --- a/packages/backend/src/server/api/stream/channels/user-list.ts +++ b/packages/backend/src/server/api/stream/channels/user-list.ts @@ -78,12 +78,14 @@ class UserListChannel extends Channel { @bindThis private async onNote(note: Packed<'Note'>) { + const isMe = this.user!.id === note.userId; + if (this.withFiles && (note.fileIds == null || note.fileIds.length === 0)) return; if (!Object.hasOwn(this.membershipsMap, note.userId)) return; if (note.visibility === 'followers') { - if (!Object.hasOwn(this.following, note.userId)) return; + if (!isMe && !Object.hasOwn(this.following, note.userId)) return; } else if (note.visibility === 'specified') { if (!note.visibleUserIds!.includes(this.user!.id)) return; } @@ -92,7 +94,7 @@ class UserListChannel extends Channel { if (note.reply && !this.membershipsMap[note.userId]?.withReplies) { const reply = note.reply; // 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合 - if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return; + if (reply.userId !== this.user!.id && !isMe && reply.userId !== note.userId) return; } // 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する From 683b71fc7e4c2c041a4990555e2e72409e96397c Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 20 Oct 2023 08:13:20 +0900 Subject: [PATCH 03/21] add timeline tests --- packages/backend/test/e2e/streaming.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/packages/backend/test/e2e/streaming.ts b/packages/backend/test/e2e/streaming.ts index 5a83bbb7da..43bbacd207 100644 --- a/packages/backend/test/e2e/streaming.ts +++ b/packages/backend/test/e2e/streaming.ts @@ -115,6 +115,16 @@ describe('Streaming', () => { assert.strictEqual(fired, true); }); + test('自分の visibility: followers な投稿が流れる', async () => { + const fired = await waitFire( + ayano, 'homeTimeline', // ayano:Home + () => api('notes/create', { text: 'foo', visibility: 'followers' }, ayano), // ayano posts + msg => msg.type === 'note' && msg.body.text === 'foo', + ); + + assert.strictEqual(fired, true); + }); + test('フォローしているユーザーの投稿が流れる', async () => { const fired = await waitFire( ayano, 'homeTimeline', // ayano:home @@ -125,6 +135,16 @@ describe('Streaming', () => { assert.strictEqual(fired, true); }); + test('フォローしているユーザーの visibility: followers な投稿が流れる', async () => { + const fired = await waitFire( + ayano, 'homeTimeline', // ayano:home + () => api('notes/create', { text: 'foo', visibility: 'followers' }, kyoko), // kyoko posts + msg => msg.type === 'note' && msg.body.userId === kyoko.id, // wait kyoko + ); + + assert.strictEqual(fired, true); + }); + test('フォローしていないユーザーの投稿は流れない', async () => { const fired = await waitFire( kyoko, 'homeTimeline', // kyoko:home From d962ea3889abf6c4396de2449636415587070de4 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 20 Oct 2023 08:15:31 +0900 Subject: [PATCH 04/21] add timeline tests --- packages/backend/test/e2e/streaming.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/packages/backend/test/e2e/streaming.ts b/packages/backend/test/e2e/streaming.ts index 43bbacd207..b3b5f1955f 100644 --- a/packages/backend/test/e2e/streaming.ts +++ b/packages/backend/test/e2e/streaming.ts @@ -261,6 +261,16 @@ describe('Streaming', () => { assert.strictEqual(fired, true); }); + test('自分の visibility: followers な投稿が流れる', async () => { + const fired = await waitFire( + ayano, 'hybridTimeline', + () => api('notes/create', { text: 'foo', visibility: 'followers' }, ayano), // ayano posts + msg => msg.type === 'note' && msg.body.text === 'foo', + ); + + assert.strictEqual(fired, true); + }); + test('フォローしていないローカルユーザーの投稿が流れる', async () => { const fired = await waitFire( ayano, 'hybridTimeline', // ayano:Hybrid @@ -313,6 +323,16 @@ describe('Streaming', () => { assert.strictEqual(fired, true); }); + test('フォローしているユーザーの visibility: followers な投稿が流れる', async () => { + const fired = await waitFire( + ayano, 'hybridTimeline', // ayano:Hybrid + () => api('notes/create', { text: 'foo', visibility: 'followers' }, kyoko), + msg => msg.type === 'note' && msg.body.userId === kyoko.id, // wait kyoko + ); + + assert.strictEqual(fired, true); + }); + test('フォローしていないローカルユーザーのホーム投稿は流れない', async () => { const fired = await waitFire( ayano, 'hybridTimeline', // ayano:Hybrid From 18af290b18cb73659a2421704ee9c7e474eaeca7 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 20 Oct 2023 11:33:33 +0900 Subject: [PATCH 05/21] chore: tweak MkNotifications --- packages/frontend/src/components/MkNotifications.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/components/MkNotifications.vue b/packages/frontend/src/components/MkNotifications.vue index 6ba2e513c5..263e0aa1c2 100644 --- a/packages/frontend/src/components/MkNotifications.vue +++ b/packages/frontend/src/components/MkNotifications.vue @@ -41,7 +41,7 @@ const pagingComponent = shallowRef>(); const pagination: Paging = { endpoint: 'i/notifications' as const, - limit: 10, + limit: 20, params: computed(() => ({ excludeTypes: props.excludeTypes ?? undefined, })), From 21986a2168d9c13725daef71ac8fd9722ee0fa91 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 20 Oct 2023 11:51:01 +0900 Subject: [PATCH 06/21] =?UTF-8?q?enhance(frontend):=20=E6=8A=95=E7=A8=BF?= =?UTF-8?q?=E3=81=95=E3=82=8C=E3=81=A6=E3=81=8B=E3=82=89=E6=99=82=E9=96=93?= =?UTF-8?q?=E3=81=8C=E7=B5=8C=E9=81=8E=E3=81=97=E3=81=A6=E3=81=84=E3=82=8B?= =?UTF-8?q?=E3=83=8E=E3=83=BC=E3=83=88=E3=81=A7=E3=81=82=E3=82=8B=E3=81=93?= =?UTF-8?q?=E3=81=A8=E3=82=92=E8=A6=96=E8=A6=9A=E7=9A=84=E3=81=AB=E5=88=86?= =?UTF-8?q?=E3=81=8B=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 --- CHANGELOG.md | 1 + packages/frontend/src/components/MkNoteDetailed.vue | 2 +- packages/frontend/src/components/MkNoteHeader.vue | 2 +- packages/frontend/src/components/global/MkTime.vue | 13 ++++++++++++- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5feec00c4..4b10c8d123 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ ### Client - Enhance: TLの返信表示オプションを記憶するように +- Enhance: 投稿されてから時間が経過しているノートであることを視覚的に分かりやすく ### Server - Enhance: タイムライン取得時のパフォーマンスを向上 diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue index 273984cc0a..4f40feffdd 100644 --- a/packages/frontend/src/components/MkNoteDetailed.vue +++ b/packages/frontend/src/components/MkNoteDetailed.vue @@ -94,7 +94,7 @@ SPDX-License-Identifier: AGPL-3.0-only