mirror of
https://github.com/tiramisulabs/seyfert.git
synced 2025-07-03 05:26:07 +00:00
feat(commands): closes #39
This commit is contained in:
parent
527b09e3e4
commit
b4ad1865e1
@ -347,3 +347,24 @@ export function GUILD_APPLICATION_COMMANDS_PERMISSIONS(appId: Snowflake, guildId
|
|||||||
if (commandId) return `/applications/${appId}/guilds/${guildId}/commands/${commandId}/permissions`;
|
if (commandId) return `/applications/${appId}/guilds/${guildId}/commands/${commandId}/permissions`;
|
||||||
return `/applications/${appId}/guilds/${guildId}/commands/permissions`;
|
return `/applications/${appId}/guilds/${guildId}/commands/permissions`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function APPLICATION_COMMANDS_LOCALIZATIONS(appId: Snowflake, commandId: Snowflake, withLocalizations?: boolean) {
|
||||||
|
let url = `/applications/${appId}/commands/${commandId}?`;
|
||||||
|
|
||||||
|
if (withLocalizations !== undefined) {
|
||||||
|
url += `withLocalizations=${withLocalizations}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function GUILD_APPLICATION_COMMANDS_LOCALIZATIONS(appId: Snowflake, guildId: Snowflake, commandId: Snowflake, withLocalizations?: boolean) {
|
||||||
|
let url = `/applications/${appId}/guilds/${guildId}/commands/${commandId}?`;
|
||||||
|
|
||||||
|
if (withLocalizations !== undefined) {
|
||||||
|
url += `with_localizations=${withLocalizations}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
@ -1,16 +1,84 @@
|
|||||||
import type { DiscordGetGatewayBot, GatewayBot, GatewayIntents } from "../discordeno/mod.ts";
|
import type {
|
||||||
|
ApplicationCommandPermissionTypes,
|
||||||
|
AtLeastOne,
|
||||||
|
Localization,
|
||||||
|
DiscordApplicationCommand,
|
||||||
|
DiscordApplicationCommandOption,
|
||||||
|
DiscordGuildApplicationCommandPermissions,
|
||||||
|
DiscordGetGatewayBot,
|
||||||
|
GatewayBot,
|
||||||
|
GatewayIntents,
|
||||||
|
} from "../discordeno/mod.ts";
|
||||||
|
|
||||||
import type { DiscordGatewayPayload, Shard } from "../discordeno/mod.ts";
|
import type { DiscordGatewayPayload, Shard } from "../discordeno/mod.ts";
|
||||||
import type { Events } from "./Actions.ts";
|
import type { Events } from "./Actions.ts";
|
||||||
|
import type { PermissionResolvable } from "./structures/Permissions.ts";
|
||||||
|
|
||||||
|
import { Permissions } from "./structures/Permissions.ts";
|
||||||
import { Snowflake } from "./Snowflake.ts";
|
import { Snowflake } from "./Snowflake.ts";
|
||||||
import { EventEmitter } from "./util/EventEmmiter.ts";
|
import { EventEmitter } from "./util/EventEmmiter.ts";
|
||||||
import { createGatewayManager, createRestManager, getBotIdFromToken } from "../discordeno/mod.ts";
|
import { ApplicationCommandTypes, createGatewayManager, createRestManager, getBotIdFromToken } from "../discordeno/mod.ts";
|
||||||
|
|
||||||
import * as Routes from "./Routes.ts";
|
import * as Routes from "./Routes.ts";
|
||||||
import * as Actions from "./Actions.ts";
|
import * as Actions from "./Actions.ts";
|
||||||
|
|
||||||
export type DiscordRawEventHandler = (shard: Shard, data: DiscordGatewayPayload) => unknown;
|
export type DiscordRawEventHandler = (shard: Shard, data: DiscordGatewayPayload) => unknown;
|
||||||
|
|
||||||
|
// INTERACTIONS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @link https://discord.com/developers/docs/interactions/application-commands#endpoints-json-params
|
||||||
|
* */
|
||||||
|
export interface CreateApplicationCommand {
|
||||||
|
name: string;
|
||||||
|
nameLocalizations?: Localization;
|
||||||
|
description: string;
|
||||||
|
descriptionLocalizations?: Localization;
|
||||||
|
type?: ApplicationCommandTypes;
|
||||||
|
options?: DiscordApplicationCommandOption[];
|
||||||
|
defaultMemberPermissions?: PermissionResolvable;
|
||||||
|
dmPermission?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @link https://discord.com/developers/docs/interactions/application-commands#endpoints-json-params
|
||||||
|
* */
|
||||||
|
export interface CreateContextApplicationCommand extends Omit<CreateApplicationCommand, "options"> {
|
||||||
|
type: ApplicationCommandTypes.Message | ApplicationCommandTypes.User;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @link https://discord.com/developers/docs/interactions/application-commands#endpoints-query-string-params
|
||||||
|
* */
|
||||||
|
export interface GetApplicationCommand {
|
||||||
|
guildId?: Snowflake;
|
||||||
|
withLocalizations?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpsertApplicationCommands extends CreateApplicationCommand {
|
||||||
|
id?: Snowflake;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @link https://discord.com/developers/docs/interactions/application-commands#edit-application-command-permissions
|
||||||
|
* */
|
||||||
|
export interface ApplicationCommandPermissions {
|
||||||
|
id: Snowflake;
|
||||||
|
type: ApplicationCommandPermissionTypes;
|
||||||
|
permission: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @link https://discord.com/developers/docs/interactions/application-commands#edit-application-command-permissions
|
||||||
|
* */
|
||||||
|
export interface ApplicationCommandPermissions {
|
||||||
|
id: Snowflake;
|
||||||
|
type: ApplicationCommandPermissionTypes;
|
||||||
|
permission: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
// END INTERACTIONS
|
||||||
|
|
||||||
export interface RestOptions {
|
export interface RestOptions {
|
||||||
secretKey?: string;
|
secretKey?: string;
|
||||||
applicationId?: Snowflake;
|
applicationId?: Snowflake;
|
||||||
@ -31,11 +99,11 @@ export interface SessionOptions {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Receives a Token, connects
|
* Receives a Token, connects
|
||||||
|
* Most of the command implementations were adapted from Discordeno (https://github.com/discordeno/discordeno)
|
||||||
*/
|
*/
|
||||||
export class Session extends EventEmitter {
|
export class Session extends EventEmitter {
|
||||||
options: SessionOptions;
|
options: SessionOptions;
|
||||||
|
|
||||||
// TODO: improve this with CreateShardManager etc
|
|
||||||
rest: ReturnType<typeof createRestManager>;
|
rest: ReturnType<typeof createRestManager>;
|
||||||
gateway: ReturnType<typeof createGatewayManager>;
|
gateway: ReturnType<typeof createGatewayManager>;
|
||||||
|
|
||||||
@ -114,6 +182,142 @@ export class Session extends EventEmitter {
|
|||||||
return super.emit(event, ...params);
|
return super.emit(event, ...params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createApplicationCommand(options: CreateApplicationCommand | CreateContextApplicationCommand, guildId: Snowflake) {
|
||||||
|
return this.rest.runMethod<DiscordApplicationCommand>(
|
||||||
|
this.rest,
|
||||||
|
"POST",
|
||||||
|
guildId
|
||||||
|
? Routes.GUILD_APPLICATION_COMMANDS(this.applicationId, guildId)
|
||||||
|
: Routes.APPLICATION_COMMANDS(this.applicationId),
|
||||||
|
this.isContextApplicationCommand(options) ? {
|
||||||
|
name: options.name,
|
||||||
|
name_localizations: options.nameLocalizations,
|
||||||
|
type: options.type,
|
||||||
|
} : {
|
||||||
|
name: options.name,
|
||||||
|
name_localizations: options.nameLocalizations,
|
||||||
|
description: options.description,
|
||||||
|
description_localizations: options.descriptionLocalizations,
|
||||||
|
type: options.type,
|
||||||
|
options: options.options,
|
||||||
|
default_member_permissions: options.defaultMemberPermissions
|
||||||
|
? new Permissions(options.defaultMemberPermissions).bitfield.toString()
|
||||||
|
: undefined,
|
||||||
|
dm_permission: options.dmPermission,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteApplicationCommand(id: Snowflake, guildId?: Snowflake) {
|
||||||
|
return this.rest.runMethod<undefined>(
|
||||||
|
this.rest,
|
||||||
|
"DELETE",
|
||||||
|
guildId
|
||||||
|
? Routes.GUILD_APPLICATION_COMMANDS(this.applicationId, guildId, id)
|
||||||
|
: Routes.APPLICATION_COMMANDS(this.applicationId, id),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateApplicationCommandPermissions(
|
||||||
|
guildId: Snowflake,
|
||||||
|
id: Snowflake,
|
||||||
|
bearerToken: string,
|
||||||
|
options: ApplicationCommandPermissions[],
|
||||||
|
) {
|
||||||
|
return this.rest.runMethod<DiscordGuildApplicationCommandPermissions>(
|
||||||
|
this.rest,
|
||||||
|
"PUT",
|
||||||
|
Routes.GUILD_APPLICATION_COMMANDS_PERMISSIONS(this.applicationId, guildId, id),
|
||||||
|
{
|
||||||
|
permissions: options,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: { authorization: `Bearer ${bearerToken}` }
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchApplicationCommand(id: Snowflake, options?: GetApplicationCommand) {
|
||||||
|
return this.rest.runMethod<DiscordApplicationCommand>(
|
||||||
|
this.rest,
|
||||||
|
"GET",
|
||||||
|
options?.guildId
|
||||||
|
? Routes.GUILD_APPLICATION_COMMANDS_LOCALIZATIONS(
|
||||||
|
this.applicationId,
|
||||||
|
options.guildId,
|
||||||
|
id,
|
||||||
|
options?.withLocalizations,
|
||||||
|
)
|
||||||
|
: Routes.APPLICATION_COMMANDS(this.applicationId, id),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchApplicationCommandPermissions(guildId: Snowflake) {
|
||||||
|
return this.rest.runMethod<DiscordGuildApplicationCommandPermissions[]>(
|
||||||
|
this.rest,
|
||||||
|
"GET",
|
||||||
|
Routes.GUILD_APPLICATION_COMMANDS_PERMISSIONS(this.applicationId, guildId),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchApplicationCommandPermission(guildId: Snowflake, id: Snowflake) {
|
||||||
|
return this.rest.runMethod<DiscordGuildApplicationCommandPermissions>(
|
||||||
|
this.rest,
|
||||||
|
"GET",
|
||||||
|
Routes.GUILD_APPLICATION_COMMANDS_PERMISSIONS(this.applicationId, guildId, id),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
upsertApplicationCommand(
|
||||||
|
id: Snowflake,
|
||||||
|
options: AtLeastOne<CreateApplicationCommand> | AtLeastOne<CreateContextApplicationCommand>,
|
||||||
|
guildId?: Snowflake,
|
||||||
|
) {
|
||||||
|
return this.rest.runMethod<DiscordApplicationCommand>(
|
||||||
|
this.rest,
|
||||||
|
"PATCH",
|
||||||
|
guildId
|
||||||
|
? Routes.GUILD_APPLICATION_COMMANDS(this.applicationId, guildId)
|
||||||
|
: Routes.APPLICATION_COMMANDS(this.applicationId, id),
|
||||||
|
this.isContextApplicationCommand(options) ? {
|
||||||
|
name: options.name,
|
||||||
|
type: options.type,
|
||||||
|
} : {
|
||||||
|
name: options.name,
|
||||||
|
description: options.description,
|
||||||
|
type: options.type,
|
||||||
|
options: options.options,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
upsertApplicationCommands(options: Array<UpsertApplicationCommands | CreateContextApplicationCommand>, guildId?: Snowflake) {
|
||||||
|
return this.rest.runMethod<DiscordApplicationCommand[]>(
|
||||||
|
this.rest,
|
||||||
|
"PUT",
|
||||||
|
guildId
|
||||||
|
? Routes.GUILD_APPLICATION_COMMANDS(this.applicationId, guildId)
|
||||||
|
: Routes.APPLICATION_COMMANDS(this.applicationId),
|
||||||
|
options.map((o) => this.isContextApplicationCommand(o) ? {
|
||||||
|
name: o.name,
|
||||||
|
type: o.type,
|
||||||
|
} : {
|
||||||
|
name: o.name,
|
||||||
|
description: o.description,
|
||||||
|
type: o.type,
|
||||||
|
options: o.options,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchCommands() {}
|
||||||
|
|
||||||
|
// deno-fmt-ignore
|
||||||
|
isContextApplicationCommand(cmd: AtLeastOne<CreateContextApplicationCommand> | AtLeastOne<CreateApplicationCommand>): cmd is AtLeastOne<CreateContextApplicationCommand> {
|
||||||
|
return cmd.type === ApplicationCommandTypes.Message || cmd.type === ApplicationCommandTypes.User;
|
||||||
|
}
|
||||||
|
|
||||||
async start() {
|
async start() {
|
||||||
const getGatewayBot = () => this.rest.runMethod<DiscordGetGatewayBot>(this.rest, "GET", Routes.GATEWAY_BOT());
|
const getGatewayBot = () => this.rest.runMethod<DiscordGetGatewayBot>(this.rest, "GET", Routes.GATEWAY_BOT());
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ export class CommandInteraction extends BaseInteraction implements Model {
|
|||||||
title: options?.title,
|
title: options?.title,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!this.respond) {
|
if (!this.responded) {
|
||||||
await this.session.rest.sendRequest<undefined>(this.session.rest, {
|
await this.session.rest.sendRequest<undefined>(this.session.rest, {
|
||||||
url: Routes.INTERACTION_ID_TOKEN(this.id, this.token),
|
url: Routes.INTERACTION_ID_TOKEN(this.id, this.token),
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
@ -2,7 +2,9 @@ import type { Model } from "../Base.ts";
|
|||||||
import type { Snowflake } from "../../Snowflake.ts";
|
import type { Snowflake } from "../../Snowflake.ts";
|
||||||
import type { Session } from "../../Session.ts";
|
import type { Session } from "../../Session.ts";
|
||||||
import type { DiscordInteraction, InteractionTypes } from "../../../discordeno/mod.ts";
|
import type { DiscordInteraction, InteractionTypes } from "../../../discordeno/mod.ts";
|
||||||
|
import type { InteractionResponse, InteractionApplicationCommandCallbackData } from "./CommandInteraction.ts";
|
||||||
import { MessageComponentTypes } from "../../../discordeno/mod.ts";
|
import { MessageComponentTypes } from "../../../discordeno/mod.ts";
|
||||||
|
import CommandInteraction from "./CommandInteraction.ts";
|
||||||
import BaseInteraction from "./BaseInteraction.ts";
|
import BaseInteraction from "./BaseInteraction.ts";
|
||||||
import Message from "../Message.ts";
|
import Message from "../Message.ts";
|
||||||
|
|
||||||
@ -40,6 +42,14 @@ export class ComponentInteraction extends BaseInteraction implements Model {
|
|||||||
isSelectMenu() {
|
isSelectMenu() {
|
||||||
return this.componentType === MessageComponentTypes.SelectMenu;
|
return this.componentType === MessageComponentTypes.SelectMenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sendFollowUp(options: InteractionApplicationCommandCallbackData) {
|
||||||
|
return CommandInteraction.prototype.sendFollowUp.call(this, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
respond(options: InteractionResponse): Promise<Message | undefined> {
|
||||||
|
return CommandInteraction.prototype.respond.call(this, options);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ComponentInteraction;
|
export default ComponentInteraction;
|
||||||
|
@ -1229,7 +1229,6 @@ export interface GatewayBot {
|
|||||||
// UTILS
|
// UTILS
|
||||||
|
|
||||||
export type AtLeastOne<T, U = { [K in keyof T]: Pick<T, K> }> = Partial<T> & U[keyof U];
|
export type AtLeastOne<T, U = { [K in keyof T]: Pick<T, K> }> = Partial<T> & U[keyof U];
|
||||||
|
|
||||||
export type MakeRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };
|
export type MakeRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };
|
||||||
|
|
||||||
// THANK YOU YUI FOR SHARING THIS!
|
// THANK YOU YUI FOR SHARING THIS!
|
||||||
@ -1243,87 +1242,6 @@ export type Camelize<T> = {
|
|||||||
: never;
|
: never;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Non object primitives */
|
|
||||||
export type Primitive =
|
|
||||||
| string
|
|
||||||
| number
|
|
||||||
| symbol
|
|
||||||
| bigint
|
|
||||||
| boolean
|
|
||||||
| undefined
|
|
||||||
| null;
|
|
||||||
// | object <- don't make object a primitive
|
|
||||||
|
|
||||||
/**
|
|
||||||
* alternative to 'object' or '{}'
|
|
||||||
* @example:
|
|
||||||
* export const o: ObjectLiteral = [] as object; // error
|
|
||||||
* export const o: object = []; // no error
|
|
||||||
*/
|
|
||||||
export type ObjectLiteral<T = unknown> = {
|
|
||||||
[K in PropertyKey]: T;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Array with no utilty methods, aka Object.create(null) */
|
|
||||||
export type ArrayWithNoPrototype<T> = {
|
|
||||||
[index: number]: T | ArrayWithNoPrototype<T>;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows any type but T
|
|
||||||
* it is recursive
|
|
||||||
* @example
|
|
||||||
* export type RequestData = Record<string, AnythingBut<bigint>>;
|
|
||||||
*/
|
|
||||||
export type AnythingBut<T> = Exclude<
|
|
||||||
| Primitive
|
|
||||||
| {
|
|
||||||
[K in PropertyKey]: AnythingBut<T>;
|
|
||||||
}
|
|
||||||
| ArrayWithNoPrototype<
|
|
||||||
| Primitive
|
|
||||||
| {
|
|
||||||
[K in PropertyKey]: AnythingBut<T>;
|
|
||||||
}
|
|
||||||
>,
|
|
||||||
T
|
|
||||||
>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* object identity type
|
|
||||||
*/
|
|
||||||
export type Id<T> = T extends infer U ? {
|
|
||||||
[K in keyof U]: U[K];
|
|
||||||
}
|
|
||||||
: never;
|
|
||||||
|
|
||||||
export type KeysWithUndefined<T> = {
|
|
||||||
[K in keyof T]-?: undefined extends T[K] ? K
|
|
||||||
: null extends T[K] ? K
|
|
||||||
: never;
|
|
||||||
}[keyof T];
|
|
||||||
|
|
||||||
type OptionalizeAux<T extends object> = Id<
|
|
||||||
& {
|
|
||||||
[K in KeysWithUndefined<T>]?: Optionalize<T[K]>;
|
|
||||||
}
|
|
||||||
& {
|
|
||||||
[K in Exclude<keyof T, KeysWithUndefined<T>>]: T[K] extends ObjectLiteral ? Optionalize<T[K]> : T[K];
|
|
||||||
}
|
|
||||||
>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Makes all of properties in T optional when they're null | undefined
|
|
||||||
* it is recursive
|
|
||||||
*/
|
|
||||||
export type Optionalize<T> = T extends object
|
|
||||||
? T extends Array<unknown>
|
|
||||||
? number extends T["length"] ? T[number] extends object ? Array<OptionalizeAux<T[number]>>
|
|
||||||
: T
|
|
||||||
: Partial<T>
|
|
||||||
: OptionalizeAux<T>
|
|
||||||
: T;
|
|
||||||
|
|
||||||
export type PickPartial<T, K extends keyof T> =
|
export type PickPartial<T, K extends keyof T> =
|
||||||
& {
|
& {
|
||||||
[P in keyof T]?: T[P] | undefined;
|
[P in keyof T]?: T[P] | undefined;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user