mirror of
https://github.com/jaronpate/unicord.git
synced 2026-10-18 21:47:40 +00:00
working application commands?
This commit is contained in:
+94
-31
@@ -1,6 +1,18 @@
|
||||
import { ComponentStyle, Context, Gateway, Guilds, Message, Embed } from './lib';
|
||||
import { Command, CommandFuntion, Intent, Presence } from './types';
|
||||
export { ComponentStyle, Context, Gateway, Guilds, Message, Embed, Command, CommandFuntion, Intent, Presence };
|
||||
import { SlashCommand, SlashCommandFunction, ChatCommand, Command, CommandFunction, Intent, Presence } from './types';
|
||||
export {
|
||||
ComponentStyle,
|
||||
Context,
|
||||
Gateway,
|
||||
Guilds,
|
||||
Message,
|
||||
Embed,
|
||||
Command,
|
||||
CommandFunction,
|
||||
ChatCommand,
|
||||
Intent,
|
||||
Presence
|
||||
};
|
||||
|
||||
type Config = {
|
||||
token: string;
|
||||
@@ -14,8 +26,8 @@ export class Client {
|
||||
readonly token: string;
|
||||
readonly application_id: string;
|
||||
private readonly gateway: Gateway;
|
||||
private readonly client_commands: Map<string, Command | CommandFuntion> = new Map();
|
||||
private readonly slash_commands: Map<string, Command | CommandFuntion> = new Map();
|
||||
private readonly client_commands: Map<string, ChatCommand | CommandFunction> = new Map();
|
||||
private readonly slash_commands: Map<string, SlashCommand | SlashCommandFunction> = new Map();
|
||||
readonly guilds: Guilds;
|
||||
|
||||
constructor({ token, application_id, prefix, intents }: Config) {
|
||||
@@ -67,48 +79,99 @@ export class Client {
|
||||
};
|
||||
|
||||
public commands = {
|
||||
register: (command: Command | string, handler: CommandFuntion) => {
|
||||
if (typeof command === 'string') {
|
||||
this.client_commands.set(command, handler);
|
||||
chat: {
|
||||
register: (command: ChatCommand | string, handler?: CommandFunction) => {
|
||||
if (typeof command === 'string') {
|
||||
this.client_commands.set(command, handler);
|
||||
} else {
|
||||
this.client_commands.set(command.name, command);
|
||||
}
|
||||
},
|
||||
get: (command_name: string) => {
|
||||
return this.client_commands.get(command_name);
|
||||
},
|
||||
execute: (command_name: string, context: Context, ...args: any[]) => {
|
||||
const command = this.client_commands.get(command_name);
|
||||
if (command) {
|
||||
command instanceof ChatCommand
|
||||
? command.execute(this, context, args.slice(1))
|
||||
: command(this, context, args.slice(1));
|
||||
}
|
||||
},
|
||||
delete: (command_name: string) => {
|
||||
this.client_commands.delete(command_name);
|
||||
},
|
||||
list: () => {
|
||||
return Array.from(this.client_commands.entries());
|
||||
},
|
||||
map: () => {
|
||||
return this.client_commands;
|
||||
}
|
||||
},
|
||||
application: {
|
||||
register: (command: SlashCommand | Record<string, string>, handler?: SlashCommandFunction) => {
|
||||
const payload =
|
||||
command instanceof SlashCommand
|
||||
? command.toJSON()
|
||||
: {
|
||||
name: command.name,
|
||||
description: command.description,
|
||||
type: command.type ?? 1
|
||||
};
|
||||
this.api
|
||||
.post(`/applications/${this.application_id}/commands`, payload)
|
||||
.then((response) => {
|
||||
console.log(response);
|
||||
if (command instanceof SlashCommand) {
|
||||
this.slash_commands.set(command.name, command);
|
||||
} else {
|
||||
this.slash_commands.set(command.name, handler);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
this.log.error('Error registering application command', error);
|
||||
});
|
||||
},
|
||||
get: (command_name: string) => {
|
||||
return this.slash_commands.get(command_name);
|
||||
},
|
||||
list: () => {
|
||||
return Array.from(this.slash_commands.entries());
|
||||
},
|
||||
map: () => {
|
||||
return this.slash_commands;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private log = {
|
||||
error: (error_or_message: Error | string, error?: Error) => {
|
||||
if (error && typeof error_or_message === 'string') {
|
||||
console.error(`[discord.ts] ${error_or_message}:`, error);
|
||||
} else {
|
||||
this.client_commands.set(command.name, command);
|
||||
console.error('[discord.ts] Error:', error_or_message);
|
||||
}
|
||||
},
|
||||
get: (command_name: string) => {
|
||||
return this.client_commands.get(command_name);
|
||||
},
|
||||
execute: (command_name: string, context: Context, ...args: any[]) => {
|
||||
const command = this.client_commands.get(command_name);
|
||||
if (command) {
|
||||
command instanceof Command
|
||||
? command.execute(this, context, args.slice(1))
|
||||
: command(this, context, args.slice(1));
|
||||
}
|
||||
},
|
||||
delete: (command_name: string) => {
|
||||
this.client_commands.delete(command_name);
|
||||
},
|
||||
list: () => {
|
||||
return this.client_commands;
|
||||
}
|
||||
};
|
||||
|
||||
private initialize = () => {
|
||||
// Register default help command
|
||||
this.commands.register('help', (client, context, _args) => {
|
||||
const embed = new Embed().setTitle('Commands').setDescription('This is a list of commands you can use.');
|
||||
this.commands.chat.register('help', (client, context, _args) => {
|
||||
const embed = new Embed()
|
||||
.setTitle('Commands')
|
||||
.setDescription('This is a list of commands you can use.')
|
||||
.setColor('#f6c221');
|
||||
|
||||
const commands = Array.from(client.commands.list().entries());
|
||||
const commands = client.commands.chat.list();
|
||||
|
||||
for (const [name, command] of commands) {
|
||||
embed.addField({
|
||||
name: name,
|
||||
value: command instanceof Command ? command.description : 'No description provided'
|
||||
value: command instanceof ChatCommand ? command.description : 'No description provided'
|
||||
});
|
||||
}
|
||||
|
||||
context.reply(embed.toMessage());
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
+2
-2
@@ -68,8 +68,8 @@ export class Embed {
|
||||
return this;
|
||||
};
|
||||
|
||||
setColor = (color: number) => {
|
||||
this.color = color;
|
||||
setColor = (color: number | string) => {
|
||||
this.color = typeof color === 'string' ? parseInt(`0x${color.replace('#', '')}`) : color;
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
+36
-9
@@ -12,9 +12,10 @@ import {
|
||||
Status,
|
||||
Presence,
|
||||
ActivityType,
|
||||
CommandFuntion,
|
||||
CommandFunction,
|
||||
Interaction,
|
||||
InteractionFunction
|
||||
InteractionFunction,
|
||||
SlashCommand
|
||||
} from '../types';
|
||||
import { Context } from './context';
|
||||
import { InteractionContext } from './interaction';
|
||||
@@ -26,9 +27,11 @@ export class Gateway {
|
||||
readonly token: string;
|
||||
readonly client: Client;
|
||||
private intents: number = 513;
|
||||
private commandNotFound: CommandFuntion = null;
|
||||
private commandNotFound: CommandFunction = null;
|
||||
// Discord gateway data
|
||||
private readonly url: string = 'wss://gateway.discord.gg/?v=10&encoding=json';
|
||||
private heartbeat_timeout: NodeJS.Timeout;
|
||||
private heartbeat_function: NodeJS.Timer;
|
||||
private heartbeat_interval: number | null = null;
|
||||
private session: Session = null;
|
||||
public user: User = null;
|
||||
@@ -45,7 +48,7 @@ export class Gateway {
|
||||
token: string;
|
||||
intents?: Intent[];
|
||||
client: Client;
|
||||
commandNotFound?: CommandFuntion;
|
||||
commandNotFound?: CommandFunction;
|
||||
}) {
|
||||
// Copy config
|
||||
this.token = token;
|
||||
@@ -80,6 +83,7 @@ export class Gateway {
|
||||
};
|
||||
|
||||
public reconnect = () => {
|
||||
this.socket.terminate();
|
||||
return this.connect();
|
||||
};
|
||||
|
||||
@@ -167,12 +171,21 @@ export class Gateway {
|
||||
if (!this.heartbeat_interval) {
|
||||
throw new Error('No heartbeat interval set');
|
||||
}
|
||||
setInterval(() => {
|
||||
if (this.heartbeat_function) {
|
||||
clearInterval(this.heartbeat_function);
|
||||
}
|
||||
if (this.heartbeat_timeout) {
|
||||
clearTimeout(this.heartbeat_timeout);
|
||||
}
|
||||
this.heartbeat_function = setInterval(() => {
|
||||
this.send({
|
||||
op: 1,
|
||||
d: {}
|
||||
});
|
||||
}, this.heartbeat_interval);
|
||||
this.heartbeat_timeout = setTimeout(() => {
|
||||
this.reconnect();
|
||||
}, this.heartbeat_interval * 2);
|
||||
};
|
||||
|
||||
private initialize = (payload: Payload) => {
|
||||
@@ -244,7 +257,18 @@ export class Gateway {
|
||||
}
|
||||
};
|
||||
|
||||
private handleShashInteraction = (payload: Payload) => {};
|
||||
private handleShashInteraction = (payload: Payload) => {
|
||||
console.log(payload.d);
|
||||
const context = new InteractionContext({ client: this.client, interaction: payload.d });
|
||||
const handler = this.client.commands.application.get(payload.d.data.name);
|
||||
if (handler) {
|
||||
if (handler instanceof SlashCommand) {
|
||||
handler.execute(this.client, context, payload.d);
|
||||
} else {
|
||||
handler(this.client, context, payload.d);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private handleChatInteraction = (payload: Payload) => {
|
||||
const context = new InteractionContext({ client: this.client, interaction: payload.d });
|
||||
@@ -266,15 +290,16 @@ export class Gateway {
|
||||
return;
|
||||
}
|
||||
console.log(payload.d);
|
||||
const content = payload.d.content.trim();
|
||||
// Is this a command?
|
||||
if (payload.d.content.startsWith(this.client.prefix)) {
|
||||
if (content.startsWith(this.client.prefix) | content.startsWith(`<@${this.client.user.id}>`)) {
|
||||
// Parse command
|
||||
const args = payload.d.content
|
||||
const args = content
|
||||
.slice(this.client.prefix.length)
|
||||
.trim()
|
||||
.split(/\s+(?=(?:[^\'"]*[\'"][^\'"]*[\'"])*[^\'"]*$)/g);
|
||||
// Check if command exists
|
||||
const handler = this.client.commands.get(args[0]);
|
||||
const handler = this.client.commands.chat.get(args[0]);
|
||||
// Generate context
|
||||
const context = new Context({ client: this.client, message: payload.d });
|
||||
if (handler) {
|
||||
@@ -317,6 +342,7 @@ export class Gateway {
|
||||
break;
|
||||
case 11:
|
||||
console.log('heartbeat acknowledged');
|
||||
this.heartbeat_timeout.refresh();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -324,6 +350,7 @@ export class Gateway {
|
||||
};
|
||||
|
||||
private onMessage = (packet: Data): void => {
|
||||
console.log('============================');
|
||||
let data: Payload | null = null;
|
||||
try {
|
||||
data = JSON.parse(packet.toString());
|
||||
|
||||
+17
-6
@@ -1,10 +1,21 @@
|
||||
import { Client } from "..";
|
||||
import { Context } from "../lib";
|
||||
import { Client } from '..';
|
||||
import { Context } from '../lib';
|
||||
|
||||
export abstract class Command {
|
||||
name: string;
|
||||
description: string;
|
||||
execute: CommandFuntion;
|
||||
readonly name: string;
|
||||
readonly description: string;
|
||||
readonly execute: CommandFunction;
|
||||
constructor(data: Command) {
|
||||
this.name = data.name;
|
||||
this.description = data.description;
|
||||
this.execute = data.execute;
|
||||
}
|
||||
}
|
||||
|
||||
export type CommandFuntion = (client: Client, context: Context, ...args: any[]) => void;
|
||||
export type CommandFunction = (client: Client, context: Context, ...args: any[]) => void;
|
||||
|
||||
export class ChatCommand extends Command {
|
||||
constructor(data: ChatCommand) {
|
||||
super(data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export * from './common';
|
||||
export * from './command';
|
||||
export * from './slash_command';
|
||||
export * from './handler';
|
||||
export * from './interaction';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Client } from "..";
|
||||
import { Context } from "../lib";
|
||||
import { Client } from '..';
|
||||
import { InteractionContext } from '../lib';
|
||||
|
||||
enum SlashCommandType {
|
||||
ChatInput = 1,
|
||||
@@ -24,7 +24,7 @@ enum SlashCommandOptionType {
|
||||
type SlashCommandOptionChoice = {
|
||||
name: string;
|
||||
value: string | number;
|
||||
}
|
||||
};
|
||||
|
||||
type SlashCommandOption = {
|
||||
type: SlashCommandOptionType;
|
||||
@@ -39,9 +39,9 @@ type SlashCommandOption = {
|
||||
max_length?: number;
|
||||
autocomplete?: boolean;
|
||||
// channel_types?: number[];
|
||||
}
|
||||
};
|
||||
|
||||
export abstract class SlashCommand {
|
||||
export class SlashCommand {
|
||||
type: SlashCommandType;
|
||||
name: string;
|
||||
description: string;
|
||||
@@ -49,7 +49,30 @@ export abstract class SlashCommand {
|
||||
guild_id?: string;
|
||||
dm_permission?: boolean;
|
||||
default_member_permissions?: string;
|
||||
execute: SlashCommandFuntion;
|
||||
execute: SlashCommandFunction;
|
||||
|
||||
constructor(data: SlashCommand) {
|
||||
this.type = data.type;
|
||||
this.name = data.name;
|
||||
this.description = data.description;
|
||||
this.options = data.options;
|
||||
this.guild_id = data.guild_id;
|
||||
this.dm_permission = data.dm_permission;
|
||||
this.default_member_permissions = data.default_member_permissions;
|
||||
this.execute = data.execute;
|
||||
}
|
||||
|
||||
public toJSON() {
|
||||
return {
|
||||
type: this.type,
|
||||
name: this.name,
|
||||
description: this.description,
|
||||
options: this.options,
|
||||
guild_id: this.guild_id,
|
||||
dm_permission: this.dm_permission,
|
||||
default_member_permissions: this.default_member_permissions
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export type SlashCommandFuntion = (client: Client, context: Context, ...args: any[]) => void;
|
||||
export type SlashCommandFunction = (client: Client, context: InteractionContext, ...args: any[]) => void;
|
||||
|
||||
Reference in New Issue
Block a user