fix: チャット周りの修正 (#15741)

* fix(misskey-js): チャットのChannel型定義を追加

* fix(backend); canChatで塞いでいない書き込み系のAPIを塞ぐ

* fix(frontend): チャット周りのフロントエンド型修正

* lint fix

* fix broken lockfile

* fix

* refactor

* wip

* wip

* wip

* clean up

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
This commit is contained in:
かっこかり 2025-04-03 15:28:10 +09:00 committed by GitHub
parent 7cecaa5c54
commit e07bb1dcbc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
29 changed files with 453 additions and 153 deletions

View file

@ -99,7 +99,7 @@ export class ChatService {
text?: string | null;
file?: MiDriveFile | null;
uri?: string | null;
}): Promise<Packed<'ChatMessageLite'>> {
}): Promise<Packed<'ChatMessageLiteFor1on1'>> {
if (fromUser.id === toUser.id) {
throw new Error('yourself');
}
@ -210,7 +210,7 @@ export class ChatService {
text?: string | null;
file?: MiDriveFile | null;
uri?: string | null;
}): Promise<Packed<'ChatMessageLite'>> {
}): Promise<Packed<'ChatMessageLiteForRoom'>> {
const memberships = (await this.chatRoomMembershipsRepository.findBy({ roomId: toRoom.id })).map(m => ({
userId: m.userId,
isMuted: m.isMuted,

View file

@ -128,7 +128,7 @@ export class ChatEntityService {
packedFiles: Map<MiChatMessage['fileId'], Packed<'DriveFile'> | null>;
};
},
): Promise<Packed<'ChatMessageLite'>> {
): Promise<Packed<'ChatMessageLiteFor1on1'>> {
const packedFiles = options?._hint_?.packedFiles;
const message = typeof src === 'object' ? src : await this.chatMessagesRepository.findOneByOrFail({ id: src });
@ -147,7 +147,7 @@ export class ChatEntityService {
createdAt: this.idService.parse(message.id).date.toISOString(),
text: message.text,
fromUserId: message.fromUserId,
toUserId: message.toUserId,
toUserId: message.toUserId!,
fileId: message.fileId,
file: message.fileId ? (packedFiles?.get(message.fileId) ?? await this.driveFileEntityService.pack(message.file ?? message.fileId)) : null,
reactions,
@ -177,7 +177,7 @@ export class ChatEntityService {
packedUsers: Map<MiUser['id'], Packed<'UserLite'>>;
};
},
): Promise<Packed<'ChatMessageLite'>> {
): Promise<Packed<'ChatMessageLiteForRoom'>> {
const packedFiles = options?._hint_?.packedFiles;
const packedUsers = options?._hint_?.packedUsers;
@ -199,7 +199,7 @@ export class ChatEntityService {
text: message.text,
fromUserId: message.fromUserId,
fromUser: packedUsers?.get(message.fromUserId) ?? await this.userEntityService.pack(message.fromUser ?? message.fromUserId),
toRoomId: message.toRoomId,
toRoomId: message.toRoomId!,
fileId: message.fileId,
file: message.fileId ? (packedFiles?.get(message.fileId) ?? await this.driveFileEntityService.pack(message.file ?? message.fileId)) : null,
reactions,

View file

@ -63,7 +63,7 @@ import {
} from '@/models/json-schema/meta.js';
import { packedSystemWebhookSchema } from '@/models/json-schema/system-webhook.js';
import { packedAbuseReportNotificationRecipientSchema } from '@/models/json-schema/abuse-report-notification-recipient.js';
import { packedChatMessageSchema, packedChatMessageLiteSchema } from '@/models/json-schema/chat-message.js';
import { packedChatMessageSchema, packedChatMessageLiteSchema, packedChatMessageLiteForRoomSchema, packedChatMessageLiteFor1on1Schema } from '@/models/json-schema/chat-message.js';
import { packedChatRoomSchema } from '@/models/json-schema/chat-room.js';
import { packedChatRoomInvitationSchema } from '@/models/json-schema/chat-room-invitation.js';
import { packedChatRoomMembershipSchema } from '@/models/json-schema/chat-room-membership.js';
@ -126,6 +126,8 @@ export const refs = {
AbuseReportNotificationRecipient: packedAbuseReportNotificationRecipientSchema,
ChatMessage: packedChatMessageSchema,
ChatMessageLite: packedChatMessageLiteSchema,
ChatMessageLiteFor1on1: packedChatMessageLiteFor1on1Schema,
ChatMessageLiteForRoom: packedChatMessageLiteForRoomSchema,
ChatRoom: packedChatRoomSchema,
ChatRoomInvitation: packedChatRoomInvitationSchema,
ChatRoomMembership: packedChatRoomMembershipSchema,

View file

@ -72,7 +72,7 @@ export const packedChatMessageSchema = {
},
user: {
type: 'object',
optional: true, nullable: true,
optional: false, nullable: false,
ref: 'UserLite',
},
},
@ -144,3 +144,113 @@ export const packedChatMessageLiteSchema = {
},
},
} as const;
export const packedChatMessageLiteFor1on1Schema = {
type: 'object',
properties: {
id: {
type: 'string',
optional: false, nullable: false,
},
createdAt: {
type: 'string',
format: 'date-time',
optional: false, nullable: false,
},
fromUserId: {
type: 'string',
optional: false, nullable: false,
},
toUserId: {
type: 'string',
optional: false, nullable: false,
},
text: {
type: 'string',
optional: true, nullable: true,
},
fileId: {
type: 'string',
optional: true, nullable: true,
},
file: {
type: 'object',
optional: true, nullable: true,
ref: 'DriveFile',
},
reactions: {
type: 'array',
optional: false, nullable: false,
items: {
type: 'object',
optional: false, nullable: false,
properties: {
reaction: {
type: 'string',
optional: false, nullable: false,
},
},
},
},
},
} as const;
export const packedChatMessageLiteForRoomSchema = {
type: 'object',
properties: {
id: {
type: 'string',
optional: false, nullable: false,
},
createdAt: {
type: 'string',
format: 'date-time',
optional: false, nullable: false,
},
fromUserId: {
type: 'string',
optional: false, nullable: false,
},
fromUser: {
type: 'object',
optional: false, nullable: false,
ref: 'UserLite',
},
toRoomId: {
type: 'string',
optional: false, nullable: false,
},
text: {
type: 'string',
optional: true, nullable: true,
},
fileId: {
type: 'string',
optional: true, nullable: true,
},
file: {
type: 'object',
optional: true, nullable: true,
ref: 'DriveFile',
},
reactions: {
type: 'array',
optional: false, nullable: false,
items: {
type: 'object',
optional: false, nullable: false,
properties: {
reaction: {
type: 'string',
optional: false, nullable: false,
},
user: {
type: 'object',
optional: false, nullable: false,
ref: 'UserLite',
},
},
},
},
},
} as const;

View file

@ -30,7 +30,7 @@ export const meta = {
res: {
type: 'object',
optional: false, nullable: false,
ref: 'ChatMessageLite',
ref: 'ChatMessageLiteForRoom',
},
errors: {

View file

@ -30,7 +30,7 @@ export const meta = {
res: {
type: 'object',
optional: false, nullable: false,
ref: 'ChatMessageLite',
ref: 'ChatMessageLiteFor1on1',
},
errors: {

View file

@ -13,6 +13,7 @@ export const meta = {
tags: ['chat'],
requireCredential: true,
requiredRolePolicy: 'canChat',
kind: 'write:chat',

View file

@ -13,6 +13,7 @@ export const meta = {
tags: ['chat'],
requireCredential: true,
requiredRolePolicy: 'canChat',
kind: 'write:chat',

View file

@ -23,7 +23,7 @@ export const meta = {
items: {
type: 'object',
optional: false, nullable: false,
ref: 'ChatMessageLite',
ref: 'ChatMessageLiteForRoom',
},
},

View file

@ -13,6 +13,7 @@ export const meta = {
tags: ['chat'],
requireCredential: true,
requiredRolePolicy: 'canChat',
kind: 'write:chat',

View file

@ -24,7 +24,7 @@ export const meta = {
items: {
type: 'object',
optional: false, nullable: false,
ref: 'ChatMessageLite',
ref: 'ChatMessageLiteFor1on1',
},
},