mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-07 19:22:14 +09:00
fix(api): accept long forum topics in imported templates (#3244)
This commit is contained in:
@@ -6,7 +6,7 @@ import {type ApiTestHarness, createApiTestHarness} from '@app/api/test/ApiTestHa
|
||||
import {createBuilder} from '@app/api/test/TestRequestBuilder';
|
||||
import {ChannelTypes, Permissions} from '@fluxer/constants/src/ChannelConstants';
|
||||
import {SystemChannelFlags} from '@fluxer/constants/src/GuildConstants';
|
||||
import {VOICE_CHANNEL_USER_LIMIT_MAX} from '@fluxer/constants/src/LimitConstants';
|
||||
import {CHANNEL_TOPIC_MAX_LENGTH, VOICE_CHANNEL_USER_LIMIT_MAX} from '@fluxer/constants/src/LimitConstants';
|
||||
import type {GuildResponse} from '@fluxer/schema/src/domains/guild/GuildResponseSchemas';
|
||||
import {afterAll, beforeAll, beforeEach, describe, expect, test} from 'vitest';
|
||||
|
||||
@@ -215,7 +215,7 @@ describe('Guild Template Import', () => {
|
||||
['a slowmode above the channel maximum', {rate_limit_per_user: 1_000_000_000}],
|
||||
['a fractional position', {position: 0.5}],
|
||||
['a negative position', {position: -3}],
|
||||
['a topic above the channel maximum', {topic: 'x'.repeat(1025)}],
|
||||
['a topic above the template maximum', {topic: 'x'.repeat(4097)}],
|
||||
['a name above the channel maximum', {name: 'x'.repeat(101)}],
|
||||
['a negative user limit', {type: ChannelTypes.GUILD_VOICE, user_limit: -1}],
|
||||
['a voice connection limit above the maximum', {type: ChannelTypes.GUILD_VOICE, voice_connection_limit: 100_000}],
|
||||
@@ -273,6 +273,26 @@ describe('Guild Template Import', () => {
|
||||
expect(channels.find((channel) => channel.name === 'town-hall')?.user_limit).toBe(VOICE_CHANNEL_USER_LIMIT_MAX);
|
||||
expect(channels.find((channel) => channel.name === 'lounge')?.voice_connection_limit).toBe(100);
|
||||
});
|
||||
test('accepts forum-length topics and shortens them to the channel topic limit', async () => {
|
||||
const account = await createTestAccount(harness);
|
||||
const longTopic = `${'a'.repeat(CHANNEL_TOPIC_MAX_LENGTH - 1)}\u{1F600}${'b'.repeat(300)}`;
|
||||
const guild = await createBuilder<GuildResponse>(harness, account.token)
|
||||
.post('/guilds')
|
||||
.body({
|
||||
name: 'Forum Guild',
|
||||
template: buildMinimalTemplate({
|
||||
channels: [
|
||||
{id: 6001, type: ChannelTypes.GUILD_TEXT, name: 'general', position: 0, topic: longTopic},
|
||||
{id: 6002, type: 15, name: 'projects', position: 1, topic: 'c'.repeat(1356)},
|
||||
],
|
||||
}),
|
||||
})
|
||||
.execute();
|
||||
const channels = await getGuildChannels(harness, account.token, guild.id);
|
||||
const general = channels.find((channel) => channel.name === 'general');
|
||||
expect(general?.topic).toBe('a'.repeat(CHANNEL_TOPIC_MAX_LENGTH - 1));
|
||||
expect(channels.find((channel) => channel.name === 'projects')).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
const DEFAULT_EVERYONE_PERMISSIONS = Permissions.VIEW_CHANNEL.toString();
|
||||
|
||||
@@ -33075,8 +33075,8 @@
|
||||
"anyOf": [{"type": "string", "maxLength": 100}, {"type": "null"}]
|
||||
},
|
||||
"topic": {
|
||||
"description": "The channel topic",
|
||||
"anyOf": [{"type": "string", "maxLength": 1024}, {"type": "null"}]
|
||||
"description": "The channel topic, shortened to the Fluxer channel topic limit",
|
||||
"anyOf": [{"type": "string", "maxLength": 4096}, {"type": "null"}]
|
||||
},
|
||||
"position": {"description": "The position of the channel", "$ref": "#/components/schemas/Int32Type"},
|
||||
"parent_id": {
|
||||
|
||||
@@ -12,6 +12,14 @@ import {ColorType, createStringType, Int32Type} from '@fluxer/schema/src/primiti
|
||||
import {z} from 'zod';
|
||||
|
||||
const TEMPLATE_NAME_MAX_LENGTH = 100;
|
||||
const TEMPLATE_TOPIC_MAX_LENGTH = 4096;
|
||||
|
||||
function clipTopic(value: string): string {
|
||||
if (value.length <= CHANNEL_TOPIC_MAX_LENGTH) return value;
|
||||
const last = value.charCodeAt(CHANNEL_TOPIC_MAX_LENGTH - 1);
|
||||
const end = last >= 0xd800 && last <= 0xdbff ? CHANNEL_TOPIC_MAX_LENGTH - 1 : CHANNEL_TOPIC_MAX_LENGTH;
|
||||
return value.slice(0, end);
|
||||
}
|
||||
|
||||
const TemplateEntityId = z
|
||||
.union([
|
||||
@@ -50,7 +58,12 @@ export const TemplateChannel = z.object({
|
||||
.nullish()
|
||||
.transform((value) => value ?? '')
|
||||
.describe('The name of the channel'),
|
||||
topic: z.string().max(CHANNEL_TOPIC_MAX_LENGTH).nullish().describe('The channel topic'),
|
||||
topic: z
|
||||
.string()
|
||||
.max(TEMPLATE_TOPIC_MAX_LENGTH)
|
||||
.nullish()
|
||||
.transform((value) => (value == null ? value : clipTopic(value)))
|
||||
.describe('The channel topic, shortened to the Fluxer channel topic limit'),
|
||||
position: Int32Type.describe('The position of the channel'),
|
||||
parent_id: TemplateEntityId.nullish().describe('The template-local ID of the parent category'),
|
||||
bitrate: z.number().int().nonnegative().nullish().describe('The bitrate for voice channels'),
|
||||
|
||||
Reference in New Issue
Block a user