diff options
| author | おさむのひと <46447427+samunohito@users.noreply.github.com> | 2025-11-07 08:39:21 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-11-07 08:39:21 +0900 |
| commit | 729abbef621aea5b8b697644181915935b74bbf8 (patch) | |
| tree | 27545c0cfd3e6272dd40de2c77daf0d2adec3e6c /packages/backend/src/core/ChannelFollowingService.ts | |
| parent | Bump version to 2025.11.0-alpha.1 (diff) | |
| download | misskey-729abbef621aea5b8b697644181915935b74bbf8.tar.gz misskey-729abbef621aea5b8b697644181915935b74bbf8.tar.bz2 misskey-729abbef621aea5b8b697644181915935b74bbf8.zip | |
feat: チャンネルミュートの実装 (#14105)
* add channel_muting table and entities
* add channel_muting services
* タイムライン取得処理への組み込み
* misskey-jsの型とインターフェース生成
* Channelスキーマにミュート情報を追加
* フロントエンドの実装
* 条件が逆だったのを修正
* 期限切れミュートを掃除する機能を実装
* TLの抽出条件調節
* 名前の変更と変更不要の差分をロールバック
* 修正漏れ
* isChannelRelatedの条件に誤りがあった
* [wip] テスト追加
* テストの追加と検出した不備の修正
* fix test
* fix CHANGELOG.md
* 通常はFTTにしておく
* 実装忘れ対応
* fix merge
* fix merge
* add channel tl test
* fix CHANGELOG.md
* remove unused import
* fix lint
* fix test
* fix favorite -> favorited
* exclude -> include
* fix CHANGELOG.md
* fix CHANGELOG.md
* maintenance
* fix CHANGELOG.md
* fix
* fix ci
* regenerate
* fix
* Revert "fix"
This reverts commit 699d50c6ec798777d8e9667cb5d45a26b06bfc93.
* fixed
---------
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
Diffstat (limited to 'packages/backend/src/core/ChannelFollowingService.ts')
| -rw-r--r-- | packages/backend/src/core/ChannelFollowingService.ts | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/packages/backend/src/core/ChannelFollowingService.ts b/packages/backend/src/core/ChannelFollowingService.ts index 12251595e2..d320a5ea36 100644 --- a/packages/backend/src/core/ChannelFollowingService.ts +++ b/packages/backend/src/core/ChannelFollowingService.ts @@ -6,7 +6,7 @@ import { Inject, Injectable, OnModuleInit } from '@nestjs/common'; import Redis from 'ioredis'; import { DI } from '@/di-symbols.js'; -import type { ChannelFollowingsRepository } from '@/models/_.js'; +import type { ChannelFollowingsRepository, ChannelsRepository, MiUser } from '@/models/_.js'; import { MiChannel } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; import { GlobalEvents, GlobalEventService } from '@/core/GlobalEventService.js'; @@ -23,6 +23,8 @@ export class ChannelFollowingService implements OnModuleInit { private redisClient: Redis.Redis, @Inject(DI.redisForSub) private redisForSub: Redis.Redis, + @Inject(DI.channelsRepository) + private channelsRepository: ChannelsRepository, @Inject(DI.channelFollowingsRepository) private channelFollowingsRepository: ChannelFollowingsRepository, private idService: IdService, @@ -45,6 +47,50 @@ export class ChannelFollowingService implements OnModuleInit { onModuleInit() { } + /** + * フォローしているチャンネルの一覧を取得する. + * @param params + * @param [opts] + * @param {(boolean|undefined)} [opts.idOnly=false] チャンネルIDのみを取得するかどうか. ID以外のフィールドに値がセットされなくなり、他テーブルとのJOINも一切されなくなるので注意. + * @param {(boolean|undefined)} [opts.joinUser=undefined] チャンネルオーナーのユーザ情報をJOINするかどうか(falseまたは省略時はJOINしない). + * @param {(boolean|undefined)} [opts.joinBannerFile=undefined] バナー画像のドライブファイルをJOINするかどうか(falseまたは省略時はJOINしない). + */ + @bindThis + public async list( + params: { + requestUserId: MiUser['id'], + }, + opts?: { + idOnly?: boolean; + joinUser?: boolean; + joinBannerFile?: boolean; + }, + ): Promise<MiChannel[]> { + if (opts?.idOnly) { + const q = this.channelFollowingsRepository.createQueryBuilder('channel_following') + .select('channel_following.followeeId') + .where('channel_following.followerId = :userId', { userId: params.requestUserId }); + + return q + .getRawMany<{ channel_following_followeeId: string }>() + .then(xs => xs.map(x => ({ id: x.channel_following_followeeId } as MiChannel))); + } else { + const q = this.channelsRepository.createQueryBuilder('channel') + .innerJoin('channel_following', 'channel_following', 'channel_following.followeeId = channel.id') + .where('channel_following.followerId = :userId', { userId: params.requestUserId }); + + if (opts?.joinUser) { + q.innerJoinAndSelect('channel.user', 'user'); + } + + if (opts?.joinBannerFile) { + q.leftJoinAndSelect('channel.banner', 'drive_file'); + } + + return q.getMany(); + } + } + @bindThis public async follow( requestUser: MiLocalUser, |