mirror of
https://github.com/discordeno/discordeno.git
synced 2026-09-17 08:47:22 +00:00
Merge branch 'main' of https://github.com/discordeno/discordeno into main
This commit is contained in:
@@ -9,6 +9,7 @@ on:
|
||||
- "rest/**"
|
||||
- "tests/**"
|
||||
- "transformers/**"
|
||||
- "template/**"
|
||||
- "types/**"
|
||||
- "util/**"
|
||||
- "gateway/**"
|
||||
@@ -20,6 +21,7 @@ on:
|
||||
- "rest/**"
|
||||
- "tests/**"
|
||||
- "transformers/**"
|
||||
- "template/**"
|
||||
- "types/**"
|
||||
- "util/**"
|
||||
- "gateway/**"
|
||||
@@ -37,5 +39,7 @@ jobs:
|
||||
deno-version: ${{ matrix.deno }}
|
||||
- name: Cache dependencies
|
||||
run: deno cache mod.ts
|
||||
- name: Cache Templates
|
||||
run: deno cache template/beginner/mod.ts template/bigbot/src/bot/mod.ts template/bigbot/src/gateway/mod.ts template/bigbot/src/rest/mod.ts template/minimal/mod.ts
|
||||
- name: Run Local tests that don't need Discord's API
|
||||
run: deno test -A tests/local.ts
|
||||
|
||||
@@ -9,9 +9,10 @@ on:
|
||||
- "rest/**"
|
||||
- "tests/**"
|
||||
- "transformers/**"
|
||||
- "template/**"
|
||||
- "types/**"
|
||||
- "util/**"
|
||||
- "ws/**"
|
||||
- "gateway/**"
|
||||
|
||||
jobs:
|
||||
test:
|
||||
@@ -27,6 +28,8 @@ jobs:
|
||||
deno-version: ${{ matrix.deno }}
|
||||
- name: Cache dependencies
|
||||
run: deno cache mod.ts
|
||||
- name: Cache Templates
|
||||
run: deno cache template/beginner/mod.ts template/bigbot/src/bot/mod.ts template/bigbot/src/gateway/mod.ts template/bigbot/src/rest/mod.ts template/minimal/mod.ts
|
||||
- name: Run test script for maintainers
|
||||
if: ${{ github.actor == 'Skillz4Killz' || github.actor == 'itohatweb' }}
|
||||
run: deno test --unstable --coverage=coverage -A tests/mod.ts
|
||||
|
||||
@@ -8,11 +8,13 @@ import {
|
||||
Message,
|
||||
Role,
|
||||
ScheduledEvent,
|
||||
Template,
|
||||
transformChannel,
|
||||
transformGuild,
|
||||
transformMember,
|
||||
transformMessage,
|
||||
transformRole,
|
||||
transformTemplate,
|
||||
transformUser,
|
||||
transformVoiceState,
|
||||
User,
|
||||
@@ -67,6 +69,7 @@ import {
|
||||
DiscordInteractionDataOption,
|
||||
DiscordReady,
|
||||
DiscordStickerPack,
|
||||
DiscordTemplate,
|
||||
} from "./types/discord.ts";
|
||||
import { Errors, GatewayDispatchEventNames, GatewayIntents } from "./types/shared.ts";
|
||||
|
||||
@@ -411,6 +414,7 @@ export interface Transformers {
|
||||
stageInstance: (bot: Bot, payload: DiscordStageInstance) => StageInstance;
|
||||
sticker: (bot: Bot, payload: DiscordSticker) => Sticker;
|
||||
stickerPack: (bot: Bot, payload: DiscordStickerPack) => StickerPack;
|
||||
template: (bot: Bot, payload: DiscordTemplate) => Template;
|
||||
}
|
||||
|
||||
export function createTransformers(options: Partial<Transformers>) {
|
||||
@@ -451,6 +455,7 @@ export function createTransformers(options: Partial<Transformers>) {
|
||||
sticker: options.sticker || transformSticker,
|
||||
stickerPack: options.stickerPack || transformStickerPack,
|
||||
gatewayBot: options.gatewayBot || transformGatewayBot,
|
||||
template: options.template || transformTemplate,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -23,4 +23,3 @@ export interface ModifyRolePositions {
|
||||
/** The sorting position for the role. */
|
||||
position?: number | null;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import type { Bot } from "../../bot.ts";
|
||||
import { Guild } from "../../transformers/guild.ts";
|
||||
import { User } from "../../transformers/member.ts";
|
||||
import { DiscordTemplate } from "../../types/discord.ts";
|
||||
|
||||
/** Creates a template for the guild. Requires the `MANAGE_GUILD` permission. */
|
||||
export async function createGuildTemplate(bot: Bot, guildId: bigint, data: Template) {
|
||||
export async function createGuildTemplate(bot: Bot, guildId: bigint, data: CreateTemplate) {
|
||||
if (data.name.length < 1 || data.name.length > 100) {
|
||||
throw new Error("The name can only be in between 1-100 characters.");
|
||||
}
|
||||
@@ -13,42 +11,17 @@ export async function createGuildTemplate(bot: Bot, guildId: bigint, data: Templ
|
||||
throw new Error("The description can only be in between 0-120 characters.");
|
||||
}
|
||||
|
||||
return await bot.rest.runMethod<DiscordTemplate>(bot.rest, "post", bot.constants.endpoints.GUILD_TEMPLATES(guildId), {
|
||||
code: data.code,
|
||||
name: data.name,
|
||||
description: data.description,
|
||||
usage_count: data.usageCount,
|
||||
creator_id: data.creatorId,
|
||||
creator: data.creator,
|
||||
created_at: data.createdAt,
|
||||
updated_at: data.updatedAt,
|
||||
source_guild_id: data.sourceGuildId,
|
||||
serialized_source_guild: data.serializedSourceGuild,
|
||||
is_dirty: data.isDirty,
|
||||
});
|
||||
return await bot.rest.runMethod<DiscordTemplate>(
|
||||
bot.rest,
|
||||
"post",
|
||||
bot.constants.endpoints.GUILD_TEMPLATES(guildId),
|
||||
data,
|
||||
);
|
||||
}
|
||||
|
||||
export interface Template {
|
||||
/** The template code (unique Id) */
|
||||
code: string;
|
||||
/** Template name */
|
||||
export interface CreateTemplate {
|
||||
/** Name which the template should have */
|
||||
name: string;
|
||||
/** The description for the template */
|
||||
description: string;
|
||||
/** Number of times this template has been used */
|
||||
usageCount: number;
|
||||
/** The Id of the user who created the template */
|
||||
creatorId: string;
|
||||
/** The user who created the template */
|
||||
creator: User;
|
||||
/** When this template was created */
|
||||
createdAt: string;
|
||||
/** When this template was last synced to the source guild */
|
||||
updatedAt: string;
|
||||
/** The Id of the guild this template is based on */
|
||||
sourceGuildId: string;
|
||||
/** The guild snapshot this template contains */
|
||||
serializedSourceGuild: Partial<Guild>;
|
||||
/** Whether the template has unsynced changes */
|
||||
isDirty: boolean;
|
||||
/** Description of the template */
|
||||
description?: string;
|
||||
}
|
||||
|
||||
@@ -10,5 +10,5 @@ export async function getGuildTemplates(bot: Bot, guildId: bigint) {
|
||||
bot.constants.endpoints.GUILD_TEMPLATES(guildId),
|
||||
);
|
||||
|
||||
return new Collection(templates.map((template) => [template.code, template]));
|
||||
return new Collection(templates.map((template) => [template.code, bot.transformers.template(bot, template)]));
|
||||
}
|
||||
|
||||
@@ -3,9 +3,11 @@ import { DiscordTemplate } from "../../types/discord.ts";
|
||||
|
||||
/** Returns the guild template if it exists */
|
||||
export async function getTemplate(bot: Bot, templateCode: string) {
|
||||
return await bot.rest.runMethod<DiscordTemplate>(
|
||||
const result = await bot.rest.runMethod<DiscordTemplate>(
|
||||
bot.rest,
|
||||
"get",
|
||||
bot.constants.endpoints.GUILD_TEMPLATE(templateCode),
|
||||
);
|
||||
|
||||
return bot.transformers.template(bot, result);
|
||||
}
|
||||
|
||||
@@ -83,6 +83,7 @@ export function createApplicationCommand(bot: BotWithCache) {
|
||||
if (!options.name) {
|
||||
throw new Error("A name is required to create a options.");
|
||||
}
|
||||
|
||||
if (isChatInput) {
|
||||
if (!SLASH_COMMANDS_NAME_REGEX.test(options.name)) {
|
||||
throw new Error(
|
||||
@@ -92,6 +93,25 @@ export function createApplicationCommand(bot: BotWithCache) {
|
||||
|
||||
// Only slash need to be lowercase
|
||||
options.name = options.name.toLowerCase();
|
||||
|
||||
// Slash commands require description
|
||||
if (!options.description) {
|
||||
throw new Error(
|
||||
"Slash commands require some form of a description be provided.",
|
||||
);
|
||||
} else if (!bot.utils.validateLength(options.description, { min: 1, max: 100 })) {
|
||||
throw new Error(
|
||||
"Application command descriptions must be between 1 and 100 characters.",
|
||||
);
|
||||
}
|
||||
|
||||
if (options.options?.length) {
|
||||
if (options.options.length > 25) {
|
||||
throw new Error("Only 25 options are allowed to be provided.");
|
||||
}
|
||||
|
||||
options.options = validateApplicationCommandOptions(bot, options.options);
|
||||
}
|
||||
} else {
|
||||
if (!CONTEXT_MENU_COMMANDS_NAME_REGEX.test(options.name)) {
|
||||
throw new Error(
|
||||
@@ -100,41 +120,6 @@ export function createApplicationCommand(bot: BotWithCache) {
|
||||
}
|
||||
}
|
||||
|
||||
// Slash commands require description
|
||||
if (
|
||||
!options.description &&
|
||||
(isChatInput)
|
||||
) {
|
||||
throw new Error(
|
||||
"Slash commands require some form of a description be provided.",
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
options.description &&
|
||||
((options.type === ApplicationCommandTypes.User) ||
|
||||
(options.type === ApplicationCommandTypes.Message))
|
||||
) {
|
||||
throw new Error("Context menu commands do not allow a description.");
|
||||
}
|
||||
|
||||
if (
|
||||
options.description &&
|
||||
!bot.utils.validateLength(options.description, { min: 1, max: 100 })
|
||||
) {
|
||||
throw new Error(
|
||||
"Application command descriptions must be between 1 and 100 characters.",
|
||||
);
|
||||
}
|
||||
|
||||
if (options.options?.length) {
|
||||
if (options.options.length > 25) {
|
||||
throw new Error("Only 25 options are allowed to be provided.");
|
||||
}
|
||||
|
||||
options.options = validateApplicationCommandOptions(bot, options.options);
|
||||
}
|
||||
|
||||
return await createApplicationCommandOld(options, guildId);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,6 +6,14 @@ export function sendInteractionResponse(bot: BotWithCache) {
|
||||
const sendInteractionResponseOld = bot.helpers.sendInteractionResponse;
|
||||
|
||||
bot.helpers.sendInteractionResponse = function (id, token, options) {
|
||||
if (options.data?.title !== undefined) {
|
||||
if (!bot.utils.validateLength(options.data.title, { min: 1, max: 45 })) {
|
||||
throw new Error(
|
||||
"Invalid modal title. Must be between 1-45 characters long.",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
options.data?.choices?.every((choice) => {
|
||||
if (!bot.utils.validateLength(choice.name, { min: 1, max: 100 })) {
|
||||
throw new Error(
|
||||
|
||||
@@ -29,4 +29,3 @@ export default function editRole(bot: BotWithCache) {
|
||||
return await editRoleOld(guildId, id, options);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Generated
+12
-12
@@ -8182,9 +8182,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/minimist": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
|
||||
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
|
||||
},
|
||||
"node_modules/mkdirp": {
|
||||
"version": "0.5.5",
|
||||
@@ -8288,9 +8288,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/node-forge": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.2.1.tgz",
|
||||
"integrity": "sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w==",
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.0.tgz",
|
||||
"integrity": "sha512-08ARB91bUi6zNKzVmaj3QO7cr397uiDT2nJ63cHjyNtCTWIgvS47j3eT0WfzUwS9+6Z5YshRaoasFkXCKrIYbA==",
|
||||
"engines": {
|
||||
"node": ">= 6.13.0"
|
||||
}
|
||||
@@ -18866,9 +18866,9 @@
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
|
||||
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.5.5",
|
||||
@@ -18943,9 +18943,9 @@
|
||||
}
|
||||
},
|
||||
"node-forge": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.2.1.tgz",
|
||||
"integrity": "sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w=="
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.0.tgz",
|
||||
"integrity": "sha512-08ARB91bUi6zNKzVmaj3QO7cr397uiDT2nJ63cHjyNtCTWIgvS47j3eT0WfzUwS9+6Z5YshRaoasFkXCKrIYbA=="
|
||||
},
|
||||
"node-releases": {
|
||||
"version": "2.0.1",
|
||||
|
||||
@@ -30,3 +30,4 @@ export * from "./voiceState.ts";
|
||||
export * from "./webhook.ts";
|
||||
export * from "./welcomeScreen.ts";
|
||||
export * from "./widget.ts";
|
||||
export * from "./template.ts";
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import { Bot } from "../bot.ts";
|
||||
import { DiscordTemplate } from "../types/discord.ts";
|
||||
import { Optionalize } from "../types/shared.ts";
|
||||
|
||||
export function transformTemplate(bot: Bot, payload: DiscordTemplate) {
|
||||
const template = {
|
||||
code: payload.code,
|
||||
name: payload.name,
|
||||
description: payload.description,
|
||||
usageCount: payload.usage_count,
|
||||
creatorId: bot.transformers.snowflake(payload.creator_id),
|
||||
creator: bot.transformers.user(bot, payload.creator),
|
||||
createdAt: Date.parse(payload.created_at),
|
||||
updatedAt: Date.parse(payload.updated_at),
|
||||
sourceGuildId: bot.transformers.snowflake(payload.source_guild_id),
|
||||
serializedSourceGuild: payload.serialized_source_guild,
|
||||
isDirty: payload.is_dirty ?? undefined,
|
||||
};
|
||||
|
||||
return template as Optionalize<typeof template>;
|
||||
}
|
||||
|
||||
export interface Template extends ReturnType<typeof transformTemplate> {}
|
||||
+31
-1
@@ -21,6 +21,7 @@ import {
|
||||
MessageTypes,
|
||||
MfaLevels,
|
||||
OverwriteTypes,
|
||||
PickPartial,
|
||||
PremiumTiers,
|
||||
PremiumTypes,
|
||||
ScheduledEventEntityType,
|
||||
@@ -2000,7 +2001,36 @@ export interface DiscordTemplate {
|
||||
/** The Id of the guild this template is based on */
|
||||
source_guild_id: string;
|
||||
/** The guild snapshot this template contains */
|
||||
serialized_source_guild: Partial<DiscordGuild>;
|
||||
serialized_source_guild:
|
||||
& Omit<
|
||||
PickPartial<
|
||||
DiscordGuild,
|
||||
| "name"
|
||||
| "description"
|
||||
| "verification_level"
|
||||
| "default_message_notifications"
|
||||
| "explicit_content_filter"
|
||||
| "preferred_locale"
|
||||
| "afk_timeout"
|
||||
| "channels"
|
||||
| "afk_channel_id"
|
||||
| "system_channel_id"
|
||||
| "system_channel_flags"
|
||||
>,
|
||||
"roles"
|
||||
>
|
||||
& {
|
||||
roles: (
|
||||
& Omit<
|
||||
PickPartial<
|
||||
DiscordRole,
|
||||
"name" | "color" | "hoist" | "mentionable" | "permissions" | "icon" | "unicode_emoji"
|
||||
>,
|
||||
"id"
|
||||
>
|
||||
& { id: number }
|
||||
)[];
|
||||
};
|
||||
/** Whether the template has unsynced changes */
|
||||
is_dirty: boolean | null;
|
||||
}
|
||||
|
||||
@@ -1335,3 +1335,9 @@ export type Optionalize<T> =
|
||||
}
|
||||
>
|
||||
: T;
|
||||
|
||||
export type PickPartial<T, K extends keyof T> =
|
||||
& {
|
||||
[P in keyof T]?: T[P] | undefined;
|
||||
}
|
||||
& { [P in K]: T[P] };
|
||||
|
||||
Reference in New Issue
Block a user