1
0
mirror of https://github.com/misskey-dev/misskey.git synced 2026-05-23 04:04:08 +02:00

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 699d50c6ec.

* fixed

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
This commit is contained in:
おさむのひと
2025-11-07 08:39:21 +09:00
committed by GitHub
parent e74ab35de3
commit 729abbef62
53 changed files with 3564 additions and 151 deletions

View File

@@ -1391,6 +1391,39 @@ declare module '../api.js' {
credential?: string | null,
): Promise<SwitchCaseResponseType<E, P>>;
/**
* No description provided.
*
* **Credential required**: *Yes* / **Permission**: *write:channels*
*/
request<E extends 'channels/mute/create', P extends Endpoints[E]['req']>(
endpoint: E,
params: P,
credential?: string | null,
): Promise<SwitchCaseResponseType<E, P>>;
/**
* No description provided.
*
* **Credential required**: *Yes* / **Permission**: *write:channels*
*/
request<E extends 'channels/mute/delete', P extends Endpoints[E]['req']>(
endpoint: E,
params: P,
credential?: string | null,
): Promise<SwitchCaseResponseType<E, P>>;
/**
* No description provided.
*
* **Credential required**: *Yes* / **Permission**: *read:channels*
*/
request<E extends 'channels/mute/list', P extends Endpoints[E]['req']>(
endpoint: E,
params: P,
credential?: string | null,
): Promise<SwitchCaseResponseType<E, P>>;
/**
* No description provided.
*

View File

@@ -182,6 +182,9 @@ import type {
ChannelsFollowRequest,
ChannelsFollowedRequest,
ChannelsFollowedResponse,
ChannelsMuteCreateRequest,
ChannelsMuteDeleteRequest,
ChannelsMuteListResponse,
ChannelsMyFavoritesResponse,
ChannelsOwnedRequest,
ChannelsOwnedResponse,
@@ -782,6 +785,9 @@ export type Endpoints = {
'channels/featured': { req: EmptyRequest; res: ChannelsFeaturedResponse };
'channels/follow': { req: ChannelsFollowRequest; res: EmptyResponse };
'channels/followed': { req: ChannelsFollowedRequest; res: ChannelsFollowedResponse };
'channels/mute/create': { req: ChannelsMuteCreateRequest; res: EmptyResponse };
'channels/mute/delete': { req: ChannelsMuteDeleteRequest; res: EmptyResponse };
'channels/mute/list': { req: EmptyRequest; res: ChannelsMuteListResponse };
'channels/my-favorites': { req: EmptyRequest; res: ChannelsMyFavoritesResponse };
'channels/owned': { req: ChannelsOwnedRequest; res: ChannelsOwnedResponse };
'channels/search': { req: ChannelsSearchRequest; res: ChannelsSearchResponse };

View File

@@ -185,6 +185,9 @@ export type ChannelsFeaturedResponse = operations['channels___featured']['respon
export type ChannelsFollowRequest = operations['channels___follow']['requestBody']['content']['application/json'];
export type ChannelsFollowedRequest = operations['channels___followed']['requestBody']['content']['application/json'];
export type ChannelsFollowedResponse = operations['channels___followed']['responses']['200']['content']['application/json'];
export type ChannelsMuteCreateRequest = operations['channels___mute___create']['requestBody']['content']['application/json'];
export type ChannelsMuteDeleteRequest = operations['channels___mute___delete']['requestBody']['content']['application/json'];
export type ChannelsMuteListResponse = operations['channels___mute___list']['responses']['200']['content']['application/json'];
export type ChannelsMyFavoritesResponse = operations['channels___my-favorites']['responses']['200']['content']['application/json'];
export type ChannelsOwnedRequest = operations['channels___owned']['requestBody']['content']['application/json'];
export type ChannelsOwnedResponse = operations['channels___owned']['responses']['200']['content']['application/json'];

View File

@@ -1140,6 +1140,33 @@ export type paths = {
*/
post: operations['channels___followed'];
};
'/channels/mute/create': {
/**
* channels/mute/create
* @description No description provided.
*
* **Credential required**: *Yes* / **Permission**: *write:channels*
*/
post: operations['channels___mute___create'];
};
'/channels/mute/delete': {
/**
* channels/mute/delete
* @description No description provided.
*
* **Credential required**: *Yes* / **Permission**: *write:channels*
*/
post: operations['channels___mute___delete'];
};
'/channels/mute/list': {
/**
* channels/mute/list
* @description No description provided.
*
* **Credential required**: *Yes* / **Permission**: *read:channels*
*/
post: operations['channels___mute___list'];
};
'/channels/my-favorites': {
/**
* channels/my-favorites
@@ -4929,6 +4956,7 @@ export type components = {
allowRenoteToExternal: boolean;
isFollowing?: boolean;
isFavorited?: boolean;
isMuting?: boolean;
pinnedNotes?: components['schemas']['Note'][];
};
QueueCount: {
@@ -14790,6 +14818,192 @@ export interface operations {
};
};
};
channels___mute___create: {
requestBody: {
content: {
'application/json': {
/** Format: misskey:id */
channelId: string;
/** @description A Unix Epoch timestamp that must lie in the future. `null` means an indefinite mute. */
expiresAt?: number | null;
};
};
};
responses: {
/** @description OK (without any results) */
204: {
headers: {
[name: string]: unknown;
};
};
/** @description Client error */
400: {
headers: {
[name: string]: unknown;
};
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Authentication error */
401: {
headers: {
[name: string]: unknown;
};
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Forbidden error */
403: {
headers: {
[name: string]: unknown;
};
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description I'm Ai */
418: {
headers: {
[name: string]: unknown;
};
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Internal server error */
500: {
headers: {
[name: string]: unknown;
};
content: {
'application/json': components['schemas']['Error'];
};
};
};
};
channels___mute___delete: {
requestBody: {
content: {
'application/json': {
/** Format: misskey:id */
channelId: string;
};
};
};
responses: {
/** @description OK (without any results) */
204: {
headers: {
[name: string]: unknown;
};
};
/** @description Client error */
400: {
headers: {
[name: string]: unknown;
};
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Authentication error */
401: {
headers: {
[name: string]: unknown;
};
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Forbidden error */
403: {
headers: {
[name: string]: unknown;
};
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description I'm Ai */
418: {
headers: {
[name: string]: unknown;
};
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Internal server error */
500: {
headers: {
[name: string]: unknown;
};
content: {
'application/json': components['schemas']['Error'];
};
};
};
};
channels___mute___list: {
responses: {
/** @description OK (with results) */
200: {
headers: {
[name: string]: unknown;
};
content: {
'application/json': components['schemas']['Channel'][];
};
};
/** @description Client error */
400: {
headers: {
[name: string]: unknown;
};
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Authentication error */
401: {
headers: {
[name: string]: unknown;
};
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Forbidden error */
403: {
headers: {
[name: string]: unknown;
};
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description I'm Ai */
418: {
headers: {
[name: string]: unknown;
};
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Internal server error */
500: {
headers: {
[name: string]: unknown;
};
content: {
'application/json': components['schemas']['Error'];
};
};
};
};
'channels___my-favorites': {
responses: {
/** @description OK (with results) */