diff --git a/locales/index.d.ts b/locales/index.d.ts index d194382c8c..988bedfdfc 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -5358,31 +5358,63 @@ export interface Locale extends ILocale { * チャット */ "chat": string; - /** - * 個人チャット - */ - "individualChat": string; - /** - * 特定ユーザーとの一対一のチャットができます。 - */ - "individualChat_description": string; - /** - * ルームチャット - */ - "roomChat": string; - /** - * 複数人でのチャットができます。 - * また、個人チャットを許可していないユーザーとでも、相手が受け入れればチャットができます。 - */ - "roomChat_description": string; - /** - * このユーザーとのチャットを開始できません - */ - "cannotChatWithTheUser": string; - /** - * チャットが使えない状態になっているか、相手がチャットを開放していません。 - */ - "cannotChatWithTheUser_description": string; + "_chat": { + /** + * 個人チャット + */ + "individualChat": string; + /** + * 特定ユーザーとの一対一のチャットができます。 + */ + "individualChat_description": string; + /** + * ルームチャット + */ + "roomChat": string; + /** + * 複数人でのチャットができます。 + * また、個人チャットを許可していないユーザーとでも、相手が受け入れればチャットができます。 + */ + "roomChat_description": string; + /** + * このユーザーとのチャットを開始できません + */ + "cannotChatWithTheUser": string; + /** + * チャットが使えない状態になっているか、相手がチャットを開放していません。 + */ + "cannotChatWithTheUser_description": string; + /** + * チャットを許可する相手 + */ + "chatAllowedUsers": string; + /** + * 自分からチャットメッセージを送った相手とはこの設定に関わらずチャットが可能です。 + */ + "chatAllowedUsers_note": string; + "_chatAllowedUsers": { + /** + * 誰でも + */ + "everyone": string; + /** + * 自分のフォロワーのみ + */ + "followers": string; + /** + * 自分がフォローしているユーザーのみ + */ + "following": string; + /** + * 相互フォローのユーザーのみ + */ + "mutual": string; + /** + * 誰も許可しない + */ + "none": string; + }; + }; "_emojiPalette": { /** * パレット diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index ab433dd39c..ac2f037e95 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1335,12 +1335,23 @@ postForm: "投稿フォーム" textCount: "文字数" information: "情報" chat: "チャット" -individualChat: "個人チャット" -individualChat_description: "特定ユーザーとの一対一のチャットができます。" -roomChat: "ルームチャット" -roomChat_description: "複数人でのチャットができます。\nまた、個人チャットを許可していないユーザーとでも、相手が受け入れればチャットができます。" -cannotChatWithTheUser: "このユーザーとのチャットを開始できません" -cannotChatWithTheUser_description: "チャットが使えない状態になっているか、相手がチャットを開放していません。" + +_chat: + individualChat: "個人チャット" + individualChat_description: "特定ユーザーとの一対一のチャットができます。" + roomChat: "ルームチャット" + roomChat_description: "複数人でのチャットができます。\nまた、個人チャットを許可していないユーザーとでも、相手が受け入れればチャットができます。" + cannotChatWithTheUser: "このユーザーとのチャットを開始できません" + cannotChatWithTheUser_description: "チャットが使えない状態になっているか、相手がチャットを開放していません。" + + chatAllowedUsers: "チャットを許可する相手" + chatAllowedUsers_note: "自分からチャットメッセージを送った相手とはこの設定に関わらずチャットが可能です。" + _chatAllowedUsers: + everyone: "誰でも" + followers: "自分のフォロワーのみ" + following: "自分がフォローしているユーザーのみ" + mutual: "相互フォローのユーザーのみ" + none: "誰も許可しない" _emojiPalette: palettes: "パレット" diff --git a/packages/backend/migration/1742617546147-chat-3.js b/packages/backend/migration/1742617546147-chat-3.js new file mode 100644 index 0000000000..116b9a738b --- /dev/null +++ b/packages/backend/migration/1742617546147-chat-3.js @@ -0,0 +1,26 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +export class Chat31742617546147 { + name = 'Chat31742617546147' + + async up(queryRunner) { + await queryRunner.query(`CREATE TABLE "chat_approval" ("id" character varying(32) NOT NULL, "userId" character varying(32) NOT NULL, "otherId" character varying(32) NOT NULL, CONSTRAINT "PK_fbbb95d60acf5c85388345b5f5d" PRIMARY KEY ("id"))`); + await queryRunner.query(`CREATE INDEX "IDX_530257863e1381a7f2f1d3282f" ON "chat_approval" ("userId") `); + await queryRunner.query(`CREATE INDEX "IDX_b1d46037f23d170da5c05fdf75" ON "chat_approval" ("otherId") `); + await queryRunner.query(`CREATE UNIQUE INDEX "IDX_12c4768a2f706fc267f2078903" ON "chat_approval" ("userId", "otherId") `); + await queryRunner.query(`ALTER TABLE "chat_approval" ADD CONSTRAINT "FK_530257863e1381a7f2f1d3282fe" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE "chat_approval" ADD CONSTRAINT "FK_b1d46037f23d170da5c05fdf755" FOREIGN KEY ("otherId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "chat_approval" DROP CONSTRAINT "FK_b1d46037f23d170da5c05fdf755"`); + await queryRunner.query(`ALTER TABLE "chat_approval" DROP CONSTRAINT "FK_530257863e1381a7f2f1d3282fe"`); + await queryRunner.query(`DROP INDEX "public"."IDX_12c4768a2f706fc267f2078903"`); + await queryRunner.query(`DROP INDEX "public"."IDX_b1d46037f23d170da5c05fdf75"`); + await queryRunner.query(`DROP INDEX "public"."IDX_530257863e1381a7f2f1d3282f"`); + await queryRunner.query(`DROP TABLE "chat_approval"`); + } +} diff --git a/packages/backend/src/core/ChatService.ts b/packages/backend/src/core/ChatService.ts index 37288b75fe..dde7c77787 100644 --- a/packages/backend/src/core/ChatService.ts +++ b/packages/backend/src/core/ChatService.ts @@ -16,7 +16,7 @@ import { ChatMessageEntityService } from '@/core/entities/ChatMessageEntityServi import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; import { PushNotificationService } from '@/core/PushNotificationService.js'; import { bindThis } from '@/decorators.js'; -import type { ChatMessagesRepository, MiChatMessage, MiChatRoom, MiDriveFile, MiUser, MutingsRepository, UsersRepository } from '@/models/_.js'; +import type { ChatApprovalsRepository, ChatMessagesRepository, ChatRoomMembershipsRepository, ChatRoomsRepository, MiChatMessage, MiChatRoom, MiDriveFile, MiUser, MutingsRepository, UsersRepository } from '@/models/_.js'; import { UserBlockingService } from '@/core/UserBlockingService.js'; import { QueryService } from '@/core/QueryService.js'; import { RoleService } from '@/core/RoleService.js'; @@ -37,6 +37,15 @@ export class ChatService { @Inject(DI.chatMessagesRepository) private chatMessagesRepository: ChatMessagesRepository, + @Inject(DI.chatApprovalsRepository) + private chatApprovalsRepository: ChatApprovalsRepository, + + @Inject(DI.chatRoomsRepository) + private chatRoomsRepository: ChatRoomsRepository, + + @Inject(DI.chatRoomMembershipsRepository) + private chatRoomMembershipsRepository: ChatRoomMembershipsRepository, + @Inject(DI.mutingsRepository) private mutingsRepository: MutingsRepository, @@ -64,22 +73,39 @@ export class ChatService { throw new Error('yourself'); } - if (toUser.chatScope === 'none') { - throw new Error('recipient is cannot chat'); - } else if (toUser.chatScope === 'followers') { - const isFollower = await this.userFollowingService.isFollowing(fromUser.id, toUser.id); - if (!isFollower) { - throw new Error('recipient is cannot chat'); - } - } else if (toUser.chatScope === 'following') { - const isFollowing = await this.userFollowingService.isFollowing(toUser.id, fromUser.id); - if (!isFollowing) { - throw new Error('recipient is cannot chat'); - } - } else if (toUser.chatScope === 'mutual') { - const isMutual = await this.userFollowingService.isMutual(fromUser.id, toUser.id); - if (!isMutual) { + const approvals = await this.chatApprovalsRepository.createQueryBuilder('approval') + .where(new Brackets(qb => { // 自分が相手を許可しているか + qb.where('approval.userId = :fromUserId', { fromUserId: fromUser.id }) + .andWhere('approval.otherId = :toUserId', { toUserId: toUser.id }); + })) + .orWhere(new Brackets(qb => { // 相手が自分を許可しているか + qb.where('approval.userId = :toUserId', { toUserId: toUser.id }) + .andWhere('approval.otherId = :fromUserId', { fromUserId: fromUser.id }); + })) + .take(2) + .getMany(); + + const otherApprovedMe = approvals.some(approval => approval.userId === toUser.id); + const iApprovedOther = approvals.some(approval => approval.userId === fromUser.id); + + if (!otherApprovedMe) { + if (toUser.chatScope === 'none') { throw new Error('recipient is cannot chat'); + } else if (toUser.chatScope === 'followers') { + const isFollower = await this.userFollowingService.isFollowing(fromUser.id, toUser.id); + if (!isFollower) { + throw new Error('recipient is cannot chat'); + } + } else if (toUser.chatScope === 'following') { + const isFollowing = await this.userFollowingService.isFollowing(toUser.id, fromUser.id); + if (!isFollowing) { + throw new Error('recipient is cannot chat'); + } + } else if (toUser.chatScope === 'mutual') { + const isMutual = await this.userFollowingService.isMutual(fromUser.id, toUser.id); + if (!isMutual) { + throw new Error('recipient is cannot chat'); + } } } @@ -104,6 +130,15 @@ export class ChatService { const inserted = await this.chatMessagesRepository.insertOne(message); + // 相手を許可しておく + if (!iApprovedOther) { + this.chatApprovalsRepository.insertOne({ + id: this.idService.gen(), + userId: fromUser.id, + otherId: toUser.id, + }); + } + const packedMessage = await this.chatMessageEntityService.packLite(inserted); if (this.userEntityService.isLocalUser(toUser)) { diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts index 69f698d9cb..7f024a1194 100644 --- a/packages/backend/src/core/entities/UserEntityService.ts +++ b/packages/backend/src/core/entities/UserEntityService.ts @@ -558,6 +558,7 @@ export class UserEntityService implements OnModuleInit { publicReactions: this.isLocalUser(user) ? profile!.publicReactions : false, // https://github.com/misskey-dev/misskey/issues/12964 followersVisibility: profile!.followersVisibility, followingVisibility: profile!.followingVisibility, + chatScope: user.chatScope, roles: this.roleService.getUserRoles(user.id).then(roles => roles.filter(role => role.isPublic).sort((a, b) => b.displayOrder - a.displayOrder).map(role => ({ id: role.id, name: role.name, diff --git a/packages/backend/src/di-symbols.ts b/packages/backend/src/di-symbols.ts index d07cb23d47..dec40e6a6a 100644 --- a/packages/backend/src/di-symbols.ts +++ b/packages/backend/src/di-symbols.ts @@ -84,6 +84,7 @@ export const DI = { flashLikesRepository: Symbol('flashLikesRepository'), userMemosRepository: Symbol('userMemosRepository'), chatMessagesRepository: Symbol('chatMessagesRepository'), + chatApprovalsRepository: Symbol('chatApprovalsRepository'), chatRoomsRepository: Symbol('chatRoomsRepository'), chatRoomMembershipsRepository: Symbol('chatRoomMembershipsRepository'), bubbleGameRecordsRepository: Symbol('bubbleGameRecordsRepository'), diff --git a/packages/backend/src/models/ChatApproval.ts b/packages/backend/src/models/ChatApproval.ts new file mode 100644 index 0000000000..55c9f07e9a --- /dev/null +++ b/packages/backend/src/models/ChatApproval.ts @@ -0,0 +1,39 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; +import { id } from './util/id.js'; +import { MiUser } from './User.js'; + +@Entity('chat_approval') +@Index(['userId', 'otherId'], { unique: true }) +export class MiChatApproval { + @PrimaryColumn(id()) + public id: string; + + @Index() + @Column({ + ...id(), + }) + public userId: MiUser['id']; + + @ManyToOne(type => MiUser, { + onDelete: 'CASCADE', + }) + @JoinColumn() + public user: MiUser | null; + + @Index() + @Column({ + ...id(), + }) + public otherId: MiUser['id']; + + @ManyToOne(type => MiUser, { + onDelete: 'CASCADE', + }) + @JoinColumn() + public other: MiUser | null; +} diff --git a/packages/backend/src/models/RepositoryModule.ts b/packages/backend/src/models/RepositoryModule.ts index 15aa620b37..584c9eb0d2 100644 --- a/packages/backend/src/models/RepositoryModule.ts +++ b/packages/backend/src/models/RepositoryModule.ts @@ -81,6 +81,7 @@ import { MiChatMessage, MiChatRoom, MiChatRoomMembership, + MiChatApproval, } from './_.js'; import type { Provider } from '@nestjs/common'; import type { DataSource } from 'typeorm'; @@ -511,6 +512,12 @@ const $chatRoomMembershipsRepository: Provider = { inject: [DI.db], }; +const $chatApprovalsRepository: Provider = { + provide: DI.chatApprovalsRepository, + useFactory: (db: DataSource) => db.getRepository(MiChatApproval), + inject: [DI.db], +}; + const $bubbleGameRecordsRepository: Provider = { provide: DI.bubbleGameRecordsRepository, useFactory: (db: DataSource) => db.getRepository(MiBubbleGameRecord).extend(miRepository as MiRepository), @@ -597,6 +604,7 @@ const $reversiGamesRepository: Provider = { $chatMessagesRepository, $chatRoomsRepository, $chatRoomMembershipsRepository, + $chatApprovalsRepository, $bubbleGameRecordsRepository, $reversiGamesRepository, ], @@ -672,6 +680,7 @@ const $reversiGamesRepository: Provider = { $chatMessagesRepository, $chatRoomsRepository, $chatRoomMembershipsRepository, + $chatApprovalsRepository, $bubbleGameRecordsRepository, $reversiGamesRepository, ], diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index d1d664dd20..778d24ec43 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -78,6 +78,7 @@ import { MiUserListFavorite } from '@/models/UserListFavorite.js'; import { MiChatMessage } from '@/models/ChatMessage.js'; import { MiChatRoom } from '@/models/ChatRoom.js'; import { MiChatRoomMembership } from '@/models/ChatRoomMembership.js'; +import { MiChatApproval } from '@/models/ChatApproval.js'; import { MiBubbleGameRecord } from '@/models/BubbleGameRecord.js'; import { MiReversiGame } from '@/models/ReversiGame.js'; import type { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity.js'; @@ -197,6 +198,7 @@ export { MiChatMessage, MiChatRoom, MiChatRoomMembership, + MiChatApproval, MiBubbleGameRecord, MiReversiGame, }; @@ -272,5 +274,6 @@ export type UserMemoRepository = Repository & MiRepository & MiRepository; export type ChatRoomsRepository = Repository & MiRepository; export type ChatRoomMembershipsRepository = Repository & MiRepository; +export type ChatApprovalsRepository = Repository & MiRepository; export type BubbleGameRecordsRepository = Repository & MiRepository; export type ReversiGamesRepository = Repository & MiRepository; diff --git a/packages/backend/src/models/json-schema/user.ts b/packages/backend/src/models/json-schema/user.ts index 38631f907d..8147cc36a1 100644 --- a/packages/backend/src/models/json-schema/user.ts +++ b/packages/backend/src/models/json-schema/user.ts @@ -358,6 +358,11 @@ export const packedUserDetailedNotMeOnlySchema = { nullable: false, optional: false, enum: ['public', 'followers', 'private'], }, + chatScope: { + type: 'string', + nullable: false, optional: false, + enum: ['everyone', 'following', 'followers', 'mutual', 'none'], + }, roles: { type: 'array', nullable: false, optional: false, diff --git a/packages/backend/src/postgres.ts b/packages/backend/src/postgres.ts index a08635ac99..db37807efc 100644 --- a/packages/backend/src/postgres.ts +++ b/packages/backend/src/postgres.ts @@ -8,6 +8,9 @@ import pg from 'pg'; import { DataSource, Logger } from 'typeorm'; import * as highlight from 'cli-highlight'; import { entities as charts } from '@/core/chart/entities.js'; +import { Config } from '@/config.js'; +import MisskeyLogger from '@/logger.js'; +import { bindThis } from '@/decorators.js'; import { MiAbuseUserReport } from '@/models/AbuseUserReport.js'; import { MiAbuseReportNotificationRecipient } from '@/models/AbuseReportNotificationRecipient.js'; @@ -81,11 +84,8 @@ import { MiChatRoom } from '@/models/ChatRoom.js'; import { MiChatRoomMembership } from '@/models/ChatRoomMembership.js'; import { MiBubbleGameRecord } from '@/models/BubbleGameRecord.js'; import { MiReversiGame } from '@/models/ReversiGame.js'; - -import { Config } from '@/config.js'; -import MisskeyLogger from '@/logger.js'; -import { bindThis } from '@/decorators.js'; -import { MiSystemAccount } from './models/SystemAccount.js'; +import { MiChatApproval } from '@/models/ChatApproval.js'; +import { MiSystemAccount } from '@/models/SystemAccount.js'; pg.types.setTypeParser(20, Number); @@ -242,6 +242,7 @@ export const entities = [ MiChatMessage, MiChatRoom, MiChatRoomMembership, + MiChatApproval, MiBubbleGameRecord, MiReversiGame, ...charts, diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts index 4c72879b73..baf397bf06 100644 --- a/packages/backend/src/server/api/endpoints/i/update.ts +++ b/packages/backend/src/server/api/endpoints/i/update.ts @@ -190,6 +190,7 @@ export const paramDef = { autoSensitive: { type: 'boolean' }, followingVisibility: { type: 'string', enum: ['public', 'followers', 'private'] }, followersVisibility: { type: 'string', enum: ['public', 'followers', 'private'] }, + chatScope: { type: 'string', enum: ['everyone', 'followers', 'following', 'mutual', 'none'] }, pinnedPageId: { type: 'string', format: 'misskey:id', nullable: true }, mutedWords: muteWords, hardMutedWords: muteWords, @@ -288,6 +289,7 @@ export default class extends Endpoint { // eslint- if (ps.birthday !== undefined) profileUpdates.birthday = ps.birthday; if (ps.followingVisibility !== undefined) profileUpdates.followingVisibility = ps.followingVisibility; if (ps.followersVisibility !== undefined) profileUpdates.followersVisibility = ps.followersVisibility; + if (ps.chatScope !== undefined) updates.chatScope = ps.chatScope; function checkMuteWordCount(mutedWords: (string[] | string)[], limit: number) { // TODO: ちゃんと数える diff --git a/packages/backend/test/e2e/users.ts b/packages/backend/test/e2e/users.ts index 822ca14ae6..b91d294d09 100644 --- a/packages/backend/test/e2e/users.ts +++ b/packages/backend/test/e2e/users.ts @@ -15,7 +15,7 @@ describe('ユーザー', () => { // エンティティとしてのユーザーを主眼においたテストを記述する // (Userを返すエンドポイントとUserエンティティを書き換えるエンドポイントをテストする) - const stripUndefined = (orig: T): Partial => { + const stripUndefined = (orig: T): Partial => { return Object.entries({ ...orig }) .filter(([, value]) => value !== undefined) .reduce((obj: Partial, [key, value]) => { @@ -83,6 +83,7 @@ describe('ユーザー', () => { publicReactions: user.publicReactions, followingVisibility: user.followingVisibility, followersVisibility: user.followersVisibility, + chatScope: user.chatScope, roles: user.roles, memo: user.memo, }); @@ -343,6 +344,7 @@ describe('ユーザー', () => { assert.strictEqual(response.publicReactions, true); assert.strictEqual(response.followingVisibility, 'public'); assert.strictEqual(response.followersVisibility, 'public'); + assert.strictEqual(response.chatScope, 'mutual'); assert.deepStrictEqual(response.roles, []); assert.strictEqual(response.memo, null); diff --git a/packages/frontend/src/pages/chat/home.vue b/packages/frontend/src/pages/chat/home.vue index ffb9511a88..ece6e53780 100644 --- a/packages/frontend/src/pages/chat/home.vue +++ b/packages/frontend/src/pages/chat/home.vue @@ -66,13 +66,13 @@ const history = ref<{ function start(ev: MouseEvent) { os.popupMenu([{ - text: i18n.ts.individualChat, - caption: i18n.ts.individualChat_description, + text: i18n.ts._chat.individualChat, + caption: i18n.ts._chat.individualChat_description, icon: 'ti ti-user', action: () => { startUser(); }, }, { type: 'divider' }, { - text: i18n.ts.roomChat, - caption: i18n.ts.roomChat_description, + text: i18n.ts._chat.roomChat, + caption: i18n.ts._chat.roomChat_description, icon: 'ti ti-users', action: () => { startRoom(); }, }], ev.currentTarget ?? ev.target); diff --git a/packages/frontend/src/pages/settings/privacy.vue b/packages/frontend/src/pages/settings/privacy.vue index f6eb203095..2f8a697d74 100644 --- a/packages/frontend/src/pages/settings/privacy.vue +++ b/packages/frontend/src/pages/settings/privacy.vue @@ -78,6 +78,20 @@ SPDX-License-Identifier: AGPL-3.0-only + + + + + + + + + + + + + + @@ -208,6 +222,7 @@ const hideOnlineStatus = ref($i.hideOnlineStatus); const publicReactions = ref($i.publicReactions); const followingVisibility = ref($i.followingVisibility); const followersVisibility = ref($i.followersVisibility); +const chatScope = ref($i.chatScope); const makeNotesFollowersOnlyBefore_type = computed(() => { if (makeNotesFollowersOnlyBefore.value == null) { @@ -260,6 +275,7 @@ function save() { publicReactions: !!publicReactions.value, followingVisibility: followingVisibility.value, followersVisibility: followersVisibility.value, + chatScope: chatScope.value, }); } diff --git a/packages/frontend/src/utility/autogen/settings-search-index.ts b/packages/frontend/src/utility/autogen/settings-search-index.ts index fd92876880..64fe328478 100644 --- a/packages/frontend/src/utility/autogen/settings-search-index.ts +++ b/packages/frontend/src/utility/autogen/settings-search-index.ts @@ -240,20 +240,25 @@ export const searchIndexes: SearchIndexItem[] = [ keywords: ['explore', i18n.ts.makeExplorableDescription], }, { - id: '7vr04wKol', + id: 'xEYlOghao', + label: i18n.ts._chat.chatAllowedUsers, + keywords: ['chat'], + }, + { + id: 'BnOtlyaAh', children: [ { - id: 'Av7fAaHv8', + id: 'BzMIVBpL0', label: i18n.ts._accountSettings.requireSigninToViewContents, keywords: ['login', 'signin'], }, { - id: '5RbESWefG', + id: 'jJUqPqBAv', label: i18n.ts._accountSettings.makeNotesFollowersOnlyBefore, keywords: ['follower', i18n.ts._accountSettings.makeNotesFollowersOnlyBeforeDescription], }, { - id: 'hdzwDs3qd', + id: 'ra10txIFV', label: i18n.ts._accountSettings.makeNotesHiddenBefore, keywords: ['hidden', i18n.ts._accountSettings.makeNotesHiddenBeforeDescription], }, diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index 822ce05a43..9c316a9816 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -3875,6 +3875,8 @@ export type components = { followingVisibility: 'public' | 'followers' | 'private'; /** @enum {string} */ followersVisibility: 'public' | 'followers' | 'private'; + /** @enum {string} */ + chatScope: 'everyone' | 'following' | 'followers' | 'mutual' | 'none'; roles: components['schemas']['RoleLite'][]; followedMessage?: string | null; memo: string | null; @@ -21330,6 +21332,8 @@ export type operations = { followingVisibility?: 'public' | 'followers' | 'private'; /** @enum {string} */ followersVisibility?: 'public' | 'followers' | 'private'; + /** @enum {string} */ + chatScope?: 'everyone' | 'followers' | 'following' | 'mutual' | 'none'; /** Format: misskey:id */ pinnedPageId?: string | null; mutedWords?: (string[] | string)[];