This commit is contained in:
Skillz4Killz
2022-03-25 10:38:17 +00:00
committed by GitHub
15 changed files with 129 additions and 91 deletions
+4
View File
@@ -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
+4 -1
View File
@@ -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
+5
View File
@@ -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,
};
}
-1
View File
@@ -23,4 +23,3 @@ export interface ModifyRolePositions {
/** The sorting position for the role. */
position?: number | null;
}
+11 -38
View File
@@ -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;
}
+1 -1
View File
@@ -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 -1
View File
@@ -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(
-1
View File
@@ -29,4 +29,3 @@ export default function editRole(bot: BotWithCache) {
return await editRoleOld(guildId, id, options);
};
}
+12 -12
View File
@@ -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",
+1
View File
@@ -30,3 +30,4 @@ export * from "./voiceState.ts";
export * from "./webhook.ts";
export * from "./welcomeScreen.ts";
export * from "./widget.ts";
export * from "./template.ts";
+23
View File
@@ -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
View File
@@ -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;
}
+6
View File
@@ -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] };