summary refs log tree commit diff
diff options
context:
space:
mode:
authorChrisChrome <chris@chrischro.me>2026-02-16 13:13:46 -0700
committerChrisChrome <chris@chrischro.me>2026-02-16 13:13:46 -0700
commit3c844ae777a367d0c48daeea83bc9205738bbc69 (patch)
treeea48661a1827ec475e092bf8b05d8d34c3de8ad7
parentSeparate IP check options during registration (diff)
downloadserver-ts-3c844ae777a367d0c48daeea83bc9205738bbc69.tar.xz
Fix loading discord guild templates
-rw-r--r--src/api/routes/guilds/index.ts2
-rw-r--r--src/api/routes/guilds/templates/index.ts29
-rw-r--r--src/util/entities/Channel.ts5
-rw-r--r--src/util/entities/Guild.ts4
-rw-r--r--src/util/entities/Role.ts2
-rw-r--r--src/util/migration/postgres/1771271159006-set-role-managed-default.ts13
6 files changed, 46 insertions, 9 deletions
diff --git a/src/api/routes/guilds/index.ts b/src/api/routes/guilds/index.ts

index 78ba93a2..663677dc 100644 --- a/src/api/routes/guilds/index.ts +++ b/src/api/routes/guilds/index.ts
@@ -55,7 +55,7 @@ router.post( const guild = await Guild.createGuild({ ...body, owner_id: req.user_id, - template_guild_id: null, + source_guild_id: null, }); const { autoJoin } = Config.get().guild; diff --git a/src/api/routes/guilds/templates/index.ts b/src/api/routes/guilds/templates/index.ts
index 391f9c8a..6eb6ffbe 100644 --- a/src/api/routes/guilds/templates/index.ts +++ b/src/api/routes/guilds/templates/index.ts
@@ -17,10 +17,10 @@ */ import { route } from "@spacebar/api"; -import { Config, DiscordApiErrors, Guild, Member, Template } from "@spacebar/util"; +import { Config, DiscordApiErrors, Guild, Member, Tag, Template } from "@spacebar/util"; import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; -import { GuildTemplateCreateSchema } from "@spacebar/schemas"; +import { ChannelType, GuildTemplateCreateSchema } from "@spacebar/schemas"; const router: Router = Router({ mergeParams: true }); @@ -64,7 +64,7 @@ router.post("/:template_code", route({ requestBody: "GuildTemplateCreateSchema" // body comes after the template ...body, owner_id: req.user_id, - template_guild_id: template.source_guild_id, + source_guild_id: template.source_guild_id, }); await Member.addToGuild(req.user_id, guild.id); @@ -87,7 +87,28 @@ async function getTemplate(code: string) { headers: { "Content-Type": "application/json" }, }); - return (await discordTemplateData.json()) as Template; + const templateData = (await discordTemplateData.json()) as Template; + + // Role ID is position in new Discord template schema. Do a little converting. + templateData.serialized_source_guild.roles.forEach((role) => { + role.position = role.id as unknown as number; + }); + + templateData.serialized_source_guild.channels.forEach((channel) => { + if (channel.type === ChannelType.GUILD_FORUM) { + channel.available_tags = + channel.available_tags?.map((tag) => + Tag.create({ + name: tag.name, + emoji_id: tag.emoji_id, + emoji_name: tag.emoji_name, + moderated: tag.moderated, + }), + ) ?? []; + } + }); + + return templateData; } if (code.startsWith("external:")) { diff --git a/src/util/entities/Channel.ts b/src/util/entities/Channel.ts
index cea2bfad..e47d078a 100644 --- a/src/util/entities/Channel.ts +++ b/src/util/entities/Channel.ts
@@ -218,7 +218,10 @@ export class Channel extends BaseClass { for (const character of InvisibleCharacters) if (channel.name.includes(character)) throw new HTTPError("Channel name cannot include invalid characters", 403); // Categories skip these checks on discord.com - if (channel.type !== ChannelType.GUILD_CATEGORY || guild.features.includes("IRC_LIKE_CATEGORY_NAMES")) { + if ( + (channel.type !== ChannelType.GUILD_CATEGORY && channel.type !== ChannelType.GUILD_STAGE_VOICE && channel.type !== ChannelType.GUILD_VOICE) || + guild.features.includes("IRC_LIKE_CATEGORY_NAMES") + ) { if (channel.name.includes(" ")) throw new HTTPError("Channel name cannot include invalid characters", 403); if (channel.name.match(/--+/g)) throw new HTTPError("Channel name cannot include multiple adjacent dashes.", 403); diff --git a/src/util/entities/Guild.ts b/src/util/entities/Guild.ts
index aac3daf0..43d22aaa 100644 --- a/src/util/entities/Guild.ts +++ b/src/util/entities/Guild.ts
@@ -310,7 +310,7 @@ export class Guild extends BaseClass { owner_id?: string; roles?: Partial<Role>[]; channels?: Partial<Channel>[]; - template_guild_id: string | null; + source_guild_id: string | null; }) { const guild_id = Snowflake.generate(); @@ -372,7 +372,7 @@ export class Guild extends BaseClass { guild_id, id: // role.id === body.template_guild_id indicates that this is the @everyone role - role.id === body.template_guild_id ? guild_id : Snowflake.generate(), + role.id === body.source_guild_id || role.id == "0" ? guild_id : Snowflake.generate(), }) .save() .then(resolve); diff --git a/src/util/entities/Role.ts b/src/util/entities/Role.ts
index 7908f42d..0647d6da 100644 --- a/src/util/entities/Role.ts +++ b/src/util/entities/Role.ts
@@ -42,7 +42,7 @@ export class Role extends BaseClass { @Column() hoist: boolean; - @Column() + @Column({ default: false }) managed: boolean; @Column() diff --git a/src/util/migration/postgres/1771271159006-set-role-managed-default.ts b/src/util/migration/postgres/1771271159006-set-role-managed-default.ts new file mode 100644
index 00000000..fad55f23 --- /dev/null +++ b/src/util/migration/postgres/1771271159006-set-role-managed-default.ts
@@ -0,0 +1,13 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class SetRoleManagedDefault1771271159006 implements MigrationInterface { + name = "SetRoleManagedDefault1771271159006"; + + public async up(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query(`ALTER TABLE "roles" ALTER COLUMN "managed" SET DEFAULT false`); + } + + public async down(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query(`ALTER TABLE "roles" ALTER COLUMN "managed" DROP DEFAULT`); + } +}