diff --git a/src/client/rest/REST.ts b/src/client/rest/REST.ts index a7e4750..cc930f1 100644 --- a/src/client/rest/REST.ts +++ b/src/client/rest/REST.ts @@ -6,23 +6,23 @@ export class REST { public API_URL = 'https://discord.com/api/v10'; public constructor(private client: Client) {} - public async get(path: string, body: any) { + public async get(path: string, body?: any) { return this.request(path, body, RequestMethod.Get); } - public async delete(path: string, body: any) { + public async delete(path: string, body?: any) { return this.request(path, body, RequestMethod.Delete); } - public async post(path: string, body: any) { + public async post(path: string, body?: any) { return this.request(path, body, RequestMethod.Post); } - public async put(path: string, body: any) { + public async put(path: string, body?: any) { return this.request(path, body, RequestMethod.Put); } - public async patch(path: string, body: any) { + public async patch(path: string, body?: any) { return this.request(path, body, RequestMethod.Patch); } diff --git a/src/client/ws/Gateway.ts b/src/client/ws/Gateway.ts index daa09eb..fa5d995 100644 --- a/src/client/ws/Gateway.ts +++ b/src/client/ws/Gateway.ts @@ -1,4 +1,5 @@ import { + APIInteraction, APIMessage, APIUnavailableGuild, ChannelType, @@ -9,6 +10,7 @@ import { } from 'discord-api-types/v10'; import { WebSocket } from 'ws'; import { Channel, Guild, Message, User } from '../../structures'; +import { Interaction } from '../../structures/Interaction'; import { log } from '../../utils/logger'; import type { Client } from '../Client'; @@ -116,6 +118,13 @@ export class Gateway { this.client.emit('guildDelete', guild ?? null); break; } + case 'INTERACTION_CREATE': { + const apiInteraction = buffer.d as APIInteraction; + + const interaction = new Interaction(apiInteraction, this.client); + this.client.emit('interaction', interaction); + break; + } case 'MESSAGE_CREATE': { const apiMessage = buffer.d as APIMessage; diff --git a/src/structures/Interaction.ts b/src/structures/Interaction.ts new file mode 100644 index 0000000..9cb716f --- /dev/null +++ b/src/structures/Interaction.ts @@ -0,0 +1,59 @@ +import { log } from 'console'; +import { APIInteraction, APIMessage, RESTPostAPIChannelMessageJSONBody, Routes, Snowflake } from 'discord-api-types/v10'; +import type { Client } from '../client'; +import { Base } from './Base'; +import type { Channel } from './Channel'; +import type { Guild } from './Guild'; +import { GuildMember } from './GuildMember'; +import { Message } from './Message'; +import { User } from './User'; +export class Interaction extends Base { + public readonly id: Snowflake = this.raw.id; + + public readonly guild?: Guild = this.raw.guild_id ? this.client.guilds.get(this.raw.guild_id) : undefined; + public readonly channel?: Channel = this.raw.channel_id ? this.client.channels.get(this.raw.channel_id) : undefined; + + public readonly user?: User = this.raw.user ? new User(this.raw.user) : undefined; + public readonly member?: GuildMember = this.guild + ? this.user + ? this.raw.member + ? new GuildMember(this.raw.member, this.user, this.guild, this.client) + : undefined + : undefined + : undefined; + + private readonly token: string = this.raw.token; + + public constructor(private raw: APIInteraction, client: Client) { + super(client); + } + + public async reply(payload: Omit) { + if (!this.client.user) throw new Error('Client user not set'); + + const res = await this.client.rest.post( + Routes.interactionCallback(this.id, this.token), + JSON.stringify({ + type: 4, + data: { + ...payload + } + }) + ); + + if (res.ok) { + const res = await this.client.rest.get(Routes.webhookMessage(this.client.user.id, this.token)); + + if (!res.ok) throw new Error(`Failed to get original message: ${res.status} ${res.statusText}`); + + const apiMessage = (await res.json()) as APIMessage; + + return new Message(apiMessage, this.client); + } + + const json = await res.json(); + log({ state: 'DEBUG', json }); + + throw new Error(`${res.status} ${res.statusText}`); + } +} diff --git a/src/tests/index.ts b/src/tests/index.ts index 80c5d50..7c4e2f8 100644 --- a/src/tests/index.ts +++ b/src/tests/index.ts @@ -1,6 +1,7 @@ import 'dotenv/config'; -import { Client, Message, User, Channel } from '..'; +import { Channel, Client, Message, User } from '..'; import type { Guild } from '../structures'; +import type { Interaction } from '../structures/Interaction'; const client = new Client({ intents: 131071 // All intents @@ -28,6 +29,24 @@ client.on('message', (message: Message) => { }); }); +client.on('interaction', (interaction: Interaction) => { + void interaction + .reply({ + content: 'pong!', + embeds: [ + { + description: 'pong!' + } + ] + }) + .then((m) => { + void m.reply({ + content: 'hey i replied to my own interaction :woosh:' + }); + }) + .catch(console.error); +}); + client.on('channelCreate', (channel: Channel) => { console.log(`A new channel called ${channel.name} was created!`); });