From b56f4b27ee8accbff040de5679fbf1c85481556b Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 9 Apr 2023 17:01:03 +0900 Subject: fix(backend): ストリーミングのLTLチャンネルでサーバー側にエラーログが出るのを修正 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/backend/src/server/api/stream/channels/local-timeline.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'packages/backend/src/server') 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 836c5aae6c..09b0005ac1 100644 --- a/packages/backend/src/server/api/stream/channels/local-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/local-timeline.ts @@ -54,10 +54,10 @@ class LocalTimelineChannel extends Channel { } // 関係ない返信は除外 - if (note.reply && !this.user!.showTimelineReplies) { + if (note.reply && this.user && !this.user.showTimelineReplies) { 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 && note.userId !== this.user.id && reply.userId !== note.userId) return; } // 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する -- cgit v1.2.3-freya From 39cf80e19f10676b263004e0a1402fdc5a9613f9 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 9 Apr 2023 17:09:27 +0900 Subject: fix(backend): イベント用redis分離が上手く動かない問題を修正 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/backend/src/GlobalModule.ts | 30 +++++++++++++++++----- packages/backend/src/core/AntennaService.ts | 8 +++--- packages/backend/src/core/CacheService.ts | 8 +++--- packages/backend/src/core/GlobalEventService.ts | 6 ++--- packages/backend/src/core/MetaService.ts | 8 +++--- packages/backend/src/core/RoleService.ts | 8 +++--- packages/backend/src/core/WebhookService.ts | 8 +++--- packages/backend/src/di-symbols.ts | 3 ++- .../src/server/api/StreamingApiServerService.ts | 8 +++--- 9 files changed, 53 insertions(+), 34 deletions(-) (limited to 'packages/backend/src/server') diff --git a/packages/backend/src/GlobalModule.ts b/packages/backend/src/GlobalModule.ts index cb713b25ad..174d0d8beb 100644 --- a/packages/backend/src/GlobalModule.ts +++ b/packages/backend/src/GlobalModule.ts @@ -37,8 +37,24 @@ const $redis: Provider = { inject: [DI.config], }; -const $redisForPubsub: Provider = { - provide: DI.redisForPubsub, +const $redisForPub: Provider = { + provide: DI.redisForPub, + useFactory: (config) => { + const redis = new Redis({ + port: config.redisForPubsub.port, + host: config.redisForPubsub.host, + family: config.redisForPubsub.family == null ? 0 : config.redisForPubsub.family, + password: config.redisForPubsub.pass, + keyPrefix: `${config.redisForPubsub.prefix}:`, + db: config.redisForPubsub.db ?? 0, + }); + return redis; + }, + inject: [DI.config], +}; + +const $redisForSub: Provider = { + provide: DI.redisForSub, useFactory: (config) => { const redis = new Redis({ port: config.redisForPubsub.port, @@ -57,14 +73,15 @@ const $redisForPubsub: Provider = { @Global() @Module({ imports: [RepositoryModule], - providers: [$config, $db, $redis, $redisForPubsub], - exports: [$config, $db, $redis, $redisForPubsub, RepositoryModule], + providers: [$config, $db, $redis, $redisForPub, $redisForSub], + exports: [$config, $db, $redis, $redisForPub, $redisForSub, RepositoryModule], }) export class GlobalModule implements OnApplicationShutdown { constructor( @Inject(DI.db) private db: DataSource, @Inject(DI.redis) private redisClient: Redis.Redis, - @Inject(DI.redisForPubsub) private redisForPubsub: Redis.Redis, + @Inject(DI.redisForPub) private redisForPub: Redis.Redis, + @Inject(DI.redisForSub) private redisForSub: Redis.Redis, ) {} async onApplicationShutdown(signal: string): Promise { @@ -79,7 +96,8 @@ export class GlobalModule implements OnApplicationShutdown { await Promise.all([ this.db.destroy(), this.redisClient.disconnect(), - this.redisForPubsub.disconnect(), + this.redisForPub.disconnect(), + this.redisForSub.disconnect(), ]); } } diff --git a/packages/backend/src/core/AntennaService.ts b/packages/backend/src/core/AntennaService.ts index 35266ac16d..47ebd4c748 100644 --- a/packages/backend/src/core/AntennaService.ts +++ b/packages/backend/src/core/AntennaService.ts @@ -27,8 +27,8 @@ export class AntennaService implements OnApplicationShutdown { @Inject(DI.redis) private redisClient: Redis.Redis, - @Inject(DI.redisForPubsub) - private redisForPubsub: Redis.Redis, + @Inject(DI.redisForSub) + private redisForSub: Redis.Redis, @Inject(DI.mutingsRepository) private mutingsRepository: MutingsRepository, @@ -52,12 +52,12 @@ export class AntennaService implements OnApplicationShutdown { this.antennasFetched = false; this.antennas = []; - this.redisForPubsub.on('message', this.onRedisMessage); + this.redisForSub.on('message', this.onRedisMessage); } @bindThis public onApplicationShutdown(signal?: string | undefined) { - this.redisForPubsub.off('message', this.onRedisMessage); + this.redisForSub.off('message', this.onRedisMessage); } @bindThis diff --git a/packages/backend/src/core/CacheService.ts b/packages/backend/src/core/CacheService.ts index d74f3e8788..561face5c3 100644 --- a/packages/backend/src/core/CacheService.ts +++ b/packages/backend/src/core/CacheService.ts @@ -27,8 +27,8 @@ export class CacheService implements OnApplicationShutdown { @Inject(DI.redis) private redisClient: Redis.Redis, - @Inject(DI.redisForPubsub) - private redisForPubsub: Redis.Redis, + @Inject(DI.redisForSub) + private redisForSub: Redis.Redis, @Inject(DI.usersRepository) private usersRepository: UsersRepository, @@ -116,7 +116,7 @@ export class CacheService implements OnApplicationShutdown { fromRedisConverter: (value) => new Set(JSON.parse(value)), }); - this.redisForPubsub.on('message', this.onMessage); + this.redisForSub.on('message', this.onMessage); } @bindThis @@ -167,6 +167,6 @@ export class CacheService implements OnApplicationShutdown { @bindThis public onApplicationShutdown(signal?: string | undefined) { - this.redisForPubsub.off('message', this.onMessage); + this.redisForSub.off('message', this.onMessage); } } diff --git a/packages/backend/src/core/GlobalEventService.ts b/packages/backend/src/core/GlobalEventService.ts index 25c064a2b4..9f4de5f985 100644 --- a/packages/backend/src/core/GlobalEventService.ts +++ b/packages/backend/src/core/GlobalEventService.ts @@ -26,8 +26,8 @@ export class GlobalEventService { @Inject(DI.config) private config: Config, - @Inject(DI.redis) - private redisClient: Redis.Redis, + @Inject(DI.redisForPub) + private redisForPub: Redis.Redis, ) { } @@ -37,7 +37,7 @@ export class GlobalEventService { { type: type, body: null } : { type: type, body: value }; - this.redisClient.publish(this.config.host, JSON.stringify({ + this.redisForPub.publish(this.config.host, JSON.stringify({ channel: channel, message: message, })); diff --git a/packages/backend/src/core/MetaService.ts b/packages/backend/src/core/MetaService.ts index 2b6160c82e..1322927c2c 100644 --- a/packages/backend/src/core/MetaService.ts +++ b/packages/backend/src/core/MetaService.ts @@ -14,8 +14,8 @@ export class MetaService implements OnApplicationShutdown { private intervalId: NodeJS.Timer; constructor( - @Inject(DI.redisForPubsub) - private redisForPubsub: Redis.Redis, + @Inject(DI.redisForSub) + private redisForSub: Redis.Redis, @Inject(DI.db) private db: DataSource, @@ -33,7 +33,7 @@ export class MetaService implements OnApplicationShutdown { }, 1000 * 60 * 5); } - this.redisForPubsub.on('message', this.onMessage); + this.redisForSub.on('message', this.onMessage); } @bindThis @@ -122,6 +122,6 @@ export class MetaService implements OnApplicationShutdown { @bindThis public onApplicationShutdown(signal?: string | undefined) { clearInterval(this.intervalId); - this.redisForPubsub.off('message', this.onMessage); + this.redisForSub.off('message', this.onMessage); } } diff --git a/packages/backend/src/core/RoleService.ts b/packages/backend/src/core/RoleService.ts index c8ebe1adb7..77645e3f06 100644 --- a/packages/backend/src/core/RoleService.ts +++ b/packages/backend/src/core/RoleService.ts @@ -64,8 +64,8 @@ export class RoleService implements OnApplicationShutdown { public static NotAssignedError = class extends Error {}; constructor( - @Inject(DI.redisForPubsub) - private redisForPubsub: Redis.Redis, + @Inject(DI.redisForSub) + private redisForSub: Redis.Redis, @Inject(DI.usersRepository) private usersRepository: UsersRepository, @@ -87,7 +87,7 @@ export class RoleService implements OnApplicationShutdown { this.rolesCache = new MemorySingleCache(1000 * 60 * 60 * 1); this.roleAssignmentByUserIdCache = new MemoryKVCache(1000 * 60 * 60 * 1); - this.redisForPubsub.on('message', this.onMessage); + this.redisForSub.on('message', this.onMessage); } @bindThis @@ -400,6 +400,6 @@ export class RoleService implements OnApplicationShutdown { @bindThis public onApplicationShutdown(signal?: string | undefined) { - this.redisForPubsub.off('message', this.onMessage); + this.redisForSub.off('message', this.onMessage); } } diff --git a/packages/backend/src/core/WebhookService.ts b/packages/backend/src/core/WebhookService.ts index 85594f8557..926115613b 100644 --- a/packages/backend/src/core/WebhookService.ts +++ b/packages/backend/src/core/WebhookService.ts @@ -13,14 +13,14 @@ export class WebhookService implements OnApplicationShutdown { private webhooks: Webhook[] = []; constructor( - @Inject(DI.redisForPubsub) - private redisForPubsub: Redis.Redis, + @Inject(DI.redisForSub) + private redisForSub: Redis.Redis, @Inject(DI.webhooksRepository) private webhooksRepository: WebhooksRepository, ) { //this.onMessage = this.onMessage.bind(this); - this.redisForPubsub.on('message', this.onMessage); + this.redisForSub.on('message', this.onMessage); } @bindThis @@ -82,6 +82,6 @@ export class WebhookService implements OnApplicationShutdown { @bindThis public onApplicationShutdown(signal?: string | undefined) { - this.redisForPubsub.off('message', this.onMessage); + this.redisForSub.off('message', this.onMessage); } } diff --git a/packages/backend/src/di-symbols.ts b/packages/backend/src/di-symbols.ts index 482e8f83e1..d4b1fb31b1 100644 --- a/packages/backend/src/di-symbols.ts +++ b/packages/backend/src/di-symbols.ts @@ -2,7 +2,8 @@ export const DI = { config: Symbol('config'), db: Symbol('db'), redis: Symbol('redis'), - redisForPubsub: Symbol('redisForPubsub'), + redisForPub: Symbol('redisForPub'), + redisForSub: Symbol('redisForSub'), //#region Repositories usersRepository: Symbol('usersRepository'), diff --git a/packages/backend/src/server/api/StreamingApiServerService.ts b/packages/backend/src/server/api/StreamingApiServerService.ts index e0e5b71a82..769a4490d6 100644 --- a/packages/backend/src/server/api/StreamingApiServerService.ts +++ b/packages/backend/src/server/api/StreamingApiServerService.ts @@ -22,8 +22,8 @@ export class StreamingApiServerService { @Inject(DI.config) private config: Config, - @Inject(DI.redisForPubsub) - private redisForPubsub: Redis.Redis, + @Inject(DI.redisForSub) + private redisForSub: Redis.Redis, @Inject(DI.usersRepository) private usersRepository: UsersRepository, @@ -81,7 +81,7 @@ export class StreamingApiServerService { ev.emit(parsed.channel, parsed.message); } - this.redisForPubsub.on('message', onRedisMessage); + this.redisForSub.on('message', onRedisMessage); const main = new MainStreamConnection( this.channelsService, @@ -111,7 +111,7 @@ export class StreamingApiServerService { connection.once('close', () => { ev.removeAllListeners(); main.dispose(); - this.redisForPubsub.off('message', onRedisMessage); + this.redisForSub.off('message', onRedisMessage); if (intervalId) clearInterval(intervalId); }); -- cgit v1.2.3-freya From f6dc100748ef403be1fdde8dd28b62ab4e11c5b3 Mon Sep 17 00:00:00 2001 From: たーびん Date: Tue, 11 Apr 2023 07:42:27 +0900 Subject: fix #10554 チャンネルの検索用ページとAPIの追加 (#10555) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add channel search * move channel search to channel list page --------- Co-authored-by: tamaina Co-authored-by: syuilo Co-authored-by: atsuchan <83960488+atsu1125@users.noreply.github.com> Co-authored-by: Masaya Suzuki <15100604+massongit@users.noreply.github.com> Co-authored-by: Kagami Sascha Rosylight Co-authored-by: taiy <53635909+taiyme@users.noreply.github.com> Co-authored-by: xianon Co-authored-by: kabo2468 <28654659+kabo2468@users.noreply.github.com> Co-authored-by: YS <47836716+yszkst@users.noreply.github.com> Co-authored-by: Khsmty Co-authored-by: Soni L Co-authored-by: mei23 Co-authored-by: daima3629 <52790780+daima3629@users.noreply.github.com> Co-authored-by: Windymelt <1113940+windymelt@users.noreply.github.com> --- locales/ja-JP.yml | 2 + packages/backend/src/server/api/EndpointsModule.ts | 4 ++ packages/backend/src/server/api/endpoints.ts | 2 + .../src/server/api/endpoints/channels/search.ts | 67 ++++++++++++++++++++++ packages/frontend/src/components/MkChannelList.vue | 31 ++++++++++ packages/frontend/src/pages/channels.vue | 62 +++++++++++++++++++- 6 files changed, 166 insertions(+), 2 deletions(-) create mode 100644 packages/backend/src/server/api/endpoints/channels/search.ts create mode 100644 packages/frontend/src/components/MkChannelList.vue (limited to 'packages/backend/src/server') diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index b01699cab4..bdf2cada86 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1427,6 +1427,8 @@ _channel: following: "フォロー中" usersCount: "{n}人が参加中" notesCount: "{n}投稿があります" + nameAndDescription: "名前と説明" + nameOnly: "名前のみ" _menuDisplay: sideFull: "横" diff --git a/packages/backend/src/server/api/EndpointsModule.ts b/packages/backend/src/server/api/EndpointsModule.ts index 5a53b3faf7..ca89d82853 100644 --- a/packages/backend/src/server/api/EndpointsModule.ts +++ b/packages/backend/src/server/api/EndpointsModule.ts @@ -98,6 +98,7 @@ import * as ep___channels_update from './endpoints/channels/update.js'; import * as ep___channels_favorite from './endpoints/channels/favorite.js'; import * as ep___channels_unfavorite from './endpoints/channels/unfavorite.js'; import * as ep___channels_myFavorites from './endpoints/channels/my-favorites.js'; +import * as ep___channels_search from './endpoints/channels/search.js'; import * as ep___charts_activeUsers from './endpoints/charts/active-users.js'; import * as ep___charts_apRequest from './endpoints/charts/ap-request.js'; import * as ep___charts_drive from './endpoints/charts/drive.js'; @@ -431,6 +432,7 @@ const $channels_update: Provider = { provide: 'ep:channels/update', useClass: ep const $channels_favorite: Provider = { provide: 'ep:channels/favorite', useClass: ep___channels_favorite.default }; const $channels_unfavorite: Provider = { provide: 'ep:channels/unfavorite', useClass: ep___channels_unfavorite.default }; const $channels_myFavorites: Provider = { provide: 'ep:channels/my-favorites', useClass: ep___channels_myFavorites.default }; +const $channels_search: Provider = { provide: 'ep:channels/search', useClass: ep___channels_search.default }; const $charts_activeUsers: Provider = { provide: 'ep:charts/active-users', useClass: ep___charts_activeUsers.default }; const $charts_apRequest: Provider = { provide: 'ep:charts/ap-request', useClass: ep___charts_apRequest.default }; const $charts_drive: Provider = { provide: 'ep:charts/drive', useClass: ep___charts_drive.default }; @@ -768,6 +770,7 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention $channels_favorite, $channels_unfavorite, $channels_myFavorites, + $channels_search, $charts_activeUsers, $charts_apRequest, $charts_drive, @@ -1099,6 +1102,7 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention $channels_favorite, $channels_unfavorite, $channels_myFavorites, + $channels_search, $charts_activeUsers, $charts_apRequest, $charts_drive, diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index fd268c7912..dab897117d 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -98,6 +98,7 @@ import * as ep___channels_update from './endpoints/channels/update.js'; import * as ep___channels_favorite from './endpoints/channels/favorite.js'; import * as ep___channels_unfavorite from './endpoints/channels/unfavorite.js'; import * as ep___channels_myFavorites from './endpoints/channels/my-favorites.js'; +import * as ep___channels_search from './endpoints/channels/search.js'; import * as ep___charts_activeUsers from './endpoints/charts/active-users.js'; import * as ep___charts_apRequest from './endpoints/charts/ap-request.js'; import * as ep___charts_drive from './endpoints/charts/drive.js'; @@ -429,6 +430,7 @@ const eps = [ ['channels/favorite', ep___channels_favorite], ['channels/unfavorite', ep___channels_unfavorite], ['channels/my-favorites', ep___channels_myFavorites], + ['channels/search', ep___channels_search], ['charts/active-users', ep___charts_activeUsers], ['charts/ap-request', ep___charts_apRequest], ['charts/drive', ep___charts_drive], diff --git a/packages/backend/src/server/api/endpoints/channels/search.ts b/packages/backend/src/server/api/endpoints/channels/search.ts new file mode 100644 index 0000000000..a954ba224c --- /dev/null +++ b/packages/backend/src/server/api/endpoints/channels/search.ts @@ -0,0 +1,67 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { Brackets } from 'typeorm'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import { QueryService } from '@/core/QueryService.js'; +import type { ChannelsRepository } from '@/models/index.js'; +import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js'; +import { DI } from '@/di-symbols.js'; +import { sqlLikeEscape } from '@/misc/sql-like-escape.js'; + +export const meta = { + tags: ['channels'], + + requireCredential: false, + + res: { + type: 'array', + optional: false, nullable: false, + items: { + type: 'object', + optional: false, nullable: false, + ref: 'Channel', + }, + }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + query: { type: 'string' }, + type: { type: 'string', enum: ['nameAndDescription', 'nameOnly'], default: 'nameAndDescription' }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 5 }, + }, + required: ['query'], +} as const; + +// eslint-disable-next-line import/no-default-export +@Injectable() +export default class extends Endpoint { + constructor( + @Inject(DI.channelsRepository) + private channelsRepository: ChannelsRepository, + + private channelEntityService: ChannelEntityService, + private queryService: QueryService, + ) { + super(meta, paramDef, async (ps, me) => { + const query = this.queryService.makePaginationQuery(this.channelsRepository.createQueryBuilder('channel'), ps.sinceId, ps.untilId); + + if (ps.type === 'nameAndDescription') { + query.andWhere(new Brackets(qb => { qb + .where('channel.name ILIKE :q', { q: `%${ sqlLikeEscape(ps.query) }%` }) + .orWhere('channel.description ILIKE :q', { q: `%${ sqlLikeEscape(ps.query) }%` }); + })); + } else { + query.andWhere('channel.name ILIKE :q', { q: `%${ sqlLikeEscape(ps.query) }%` }); + } + + const channels = await query + .take(ps.limit) + .getMany(); + + return await Promise.all(channels.map(x => this.channelEntityService.pack(x, me))); + }); + } +} diff --git a/packages/frontend/src/components/MkChannelList.vue b/packages/frontend/src/components/MkChannelList.vue new file mode 100644 index 0000000000..408eab7399 --- /dev/null +++ b/packages/frontend/src/components/MkChannelList.vue @@ -0,0 +1,31 @@ + + + + + diff --git a/packages/frontend/src/pages/channels.vue b/packages/frontend/src/pages/channels.vue index 3a5aa00c5b..bc6a6e4952 100644 --- a/packages/frontend/src/pages/channels.vue +++ b/packages/frontend/src/pages/channels.vue @@ -2,6 +2,23 @@ +
+
+ + + + + + + + {{ i18n.ts.search }} +
+ + + + + +
@@ -28,17 +45,35 @@