merge: Limit chat messages based on maxNoteLength (!1188)

View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/1188

Approved-by: dakkar <dakkar@thenautilus.net>
Approved-by: Marie <github@yuugi.dev>
This commit is contained in:
Marie 2025-07-27 14:17:36 +00:00
commit a53196c407
3 changed files with 34 additions and 2 deletions

View file

@ -11,6 +11,7 @@ import { DI } from '@/di-symbols.js';
import { ApiError } from '@/server/api/error.js'; import { ApiError } from '@/server/api/error.js';
import { ChatService } from '@/core/ChatService.js'; import { ChatService } from '@/core/ChatService.js';
import type { DriveFilesRepository, MiUser } from '@/models/_.js'; import type { DriveFilesRepository, MiUser } from '@/models/_.js';
import type { Config } from '@/config.js';
export const meta = { export const meta = {
tags: ['chat'], tags: ['chat'],
@ -52,13 +53,19 @@ export const meta = {
code: 'CONTENT_REQUIRED', code: 'CONTENT_REQUIRED',
id: '340517b7-6d04-42c0-bac1-37ee804e3594', id: '340517b7-6d04-42c0-bac1-37ee804e3594',
}, },
maxLength: {
message: 'You tried posting a message which is too long.',
code: 'MAX_LENGTH',
id: '3ac74a84-8fd5-4bb0-870f-01804f82ce16',
},
}, },
} as const; } as const;
export const paramDef = { export const paramDef = {
type: 'object', type: 'object',
properties: { properties: {
text: { type: 'string', nullable: true, maxLength: 2000 }, text: { type: 'string', nullable: true, minLength: 1 },
fileId: { type: 'string', format: 'misskey:id' }, fileId: { type: 'string', format: 'misskey:id' },
toRoomId: { type: 'string', format: 'misskey:id' }, toRoomId: { type: 'string', format: 'misskey:id' },
}, },
@ -71,12 +78,19 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
@Inject(DI.driveFilesRepository) @Inject(DI.driveFilesRepository)
private driveFilesRepository: DriveFilesRepository, private driveFilesRepository: DriveFilesRepository,
@Inject(DI.config)
private config: Config,
private getterService: GetterService, private getterService: GetterService,
private chatService: ChatService, private chatService: ChatService,
) { ) {
super(meta, paramDef, async (ps, me) => { super(meta, paramDef, async (ps, me) => {
await this.chatService.checkChatAvailability(me.id, 'write'); await this.chatService.checkChatAvailability(me.id, 'write');
if (ps.text && ps.text.length > this.config.maxNoteLength) {
throw new ApiError(meta.errors.maxLength);
}
const room = await this.chatService.findRoomById(ps.toRoomId); const room = await this.chatService.findRoomById(ps.toRoomId);
if (room == null) { if (room == null) {
throw new ApiError(meta.errors.noSuchRoom); throw new ApiError(meta.errors.noSuchRoom);

View file

@ -11,6 +11,7 @@ import { DI } from '@/di-symbols.js';
import { ApiError } from '@/server/api/error.js'; import { ApiError } from '@/server/api/error.js';
import { ChatService } from '@/core/ChatService.js'; import { ChatService } from '@/core/ChatService.js';
import type { DriveFilesRepository, MiUser } from '@/models/_.js'; import type { DriveFilesRepository, MiUser } from '@/models/_.js';
import type { Config } from '@/config.js';
export const meta = { export const meta = {
tags: ['chat'], tags: ['chat'],
@ -64,13 +65,19 @@ export const meta = {
code: 'YOU_HAVE_BEEN_BLOCKED', code: 'YOU_HAVE_BEEN_BLOCKED',
id: 'c15a5199-7422-4968-941a-2a462c478f7d', id: 'c15a5199-7422-4968-941a-2a462c478f7d',
}, },
maxLength: {
message: 'You tried posting a message which is too long.',
code: 'MAX_LENGTH',
id: '3ac74a84-8fd5-4bb0-870f-01804f82ce16',
},
}, },
} as const; } as const;
export const paramDef = { export const paramDef = {
type: 'object', type: 'object',
properties: { properties: {
text: { type: 'string', nullable: true, maxLength: 2000 }, text: { type: 'string', nullable: true, minLength: 1 },
fileId: { type: 'string', format: 'misskey:id' }, fileId: { type: 'string', format: 'misskey:id' },
toUserId: { type: 'string', format: 'misskey:id' }, toUserId: { type: 'string', format: 'misskey:id' },
}, },
@ -83,12 +90,19 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
@Inject(DI.driveFilesRepository) @Inject(DI.driveFilesRepository)
private driveFilesRepository: DriveFilesRepository, private driveFilesRepository: DriveFilesRepository,
@Inject(DI.config)
private config: Config,
private getterService: GetterService, private getterService: GetterService,
private chatService: ChatService, private chatService: ChatService,
) { ) {
super(meta, paramDef, async (ps, me) => { super(meta, paramDef, async (ps, me) => {
await this.chatService.checkChatAvailability(me.id, 'write'); await this.chatService.checkChatAvailability(me.id, 'write');
if (ps.text && ps.text.length > this.config.maxNoteLength) {
throw new ApiError(meta.errors.maxLength);
}
let file = null; let file = null;
if (ps.fileId != null) { if (ps.fileId != null) {
file = await this.driveFilesRepository.findOneBy({ file = await this.driveFilesRepository.findOneBy({

View file

@ -4640,6 +4640,7 @@ export type components = {
display: 'dialog' | 'normal' | 'banner'; display: 'dialog' | 'normal' | 'banner';
needConfirmationToRead: boolean; needConfirmationToRead: boolean;
silence: boolean; silence: boolean;
confetti: boolean;
forYou: boolean; forYou: boolean;
isRead?: boolean; isRead?: boolean;
}; };
@ -6697,6 +6698,8 @@ export type operations = {
silence?: boolean; silence?: boolean;
/** @default false */ /** @default false */
needConfirmationToRead?: boolean; needConfirmationToRead?: boolean;
/** @default false */
confetti?: boolean;
/** /**
* Format: misskey:id * Format: misskey:id
* @default null * @default null
@ -6910,6 +6913,7 @@ export type operations = {
forExistingUsers?: boolean; forExistingUsers?: boolean;
silence?: boolean; silence?: boolean;
needConfirmationToRead?: boolean; needConfirmationToRead?: boolean;
confetti?: boolean;
isActive?: boolean; isActive?: boolean;
}; };
}; };