http slash commands
This commit is contained in:
parent
2ca5005517
commit
c1a14fdac1
3 changed files with 52 additions and 30 deletions
|
@ -1,7 +1,11 @@
|
|||
import { Guild } from '../structures/guild.ts'
|
||||
import { Interaction } from '../structures/slash.ts'
|
||||
import {
|
||||
Interaction,
|
||||
InteractionApplicationCommandResolved
|
||||
} from '../structures/slash.ts'
|
||||
import {
|
||||
InteractionPayload,
|
||||
InteractionResponsePayload,
|
||||
InteractionType,
|
||||
SlashCommandChoice,
|
||||
SlashCommandOption,
|
||||
|
@ -14,6 +18,7 @@ import { Client } from './client.ts'
|
|||
import { RESTManager } from './rest.ts'
|
||||
import { SlashModule } from './slashModule.ts'
|
||||
import { verify as edverify } from 'https://deno.land/x/ed25519@1.0.1/mod.ts'
|
||||
import { User } from '../structures/user.ts'
|
||||
|
||||
export class SlashCommand {
|
||||
slash: SlashCommandsManager
|
||||
|
@ -372,6 +377,9 @@ export interface SlashOptions {
|
|||
publicKey?: string
|
||||
}
|
||||
|
||||
const encoder = new TextEncoder()
|
||||
const decoder = new TextDecoder('utf-8')
|
||||
|
||||
/** Slash Client represents an Interactions Client which can be used without Harmony Client. */
|
||||
export class SlashClient {
|
||||
id: string | (() => string)
|
||||
|
@ -537,16 +545,17 @@ export class SlashClient {
|
|||
return edverify(signature, fullBody, this.publicKey).catch(() => false)
|
||||
}
|
||||
|
||||
/** Verify [Deno Std HTTP Server Request](https://deno.land/std/http/server.ts) and return Interaction */
|
||||
/** Verify [Deno Std HTTP Server Request](https://deno.land/std/http/server.ts) and return Interaction. **Data present in Interaction returned by this method is very different from actual typings as there is no real `Client` behind the scenes to cache things.** */
|
||||
async verifyServerRequest(req: {
|
||||
headers: Headers
|
||||
method: string
|
||||
body: Deno.Reader
|
||||
respond: (options: {
|
||||
status?: number
|
||||
headers?: Headers
|
||||
body?: string | Uint8Array
|
||||
}) => Promise<void>
|
||||
}): Promise<boolean | Interaction> {
|
||||
}): Promise<false | Interaction> {
|
||||
if (req.method.toLowerCase() !== 'post') return false
|
||||
|
||||
const signature = req.headers.get('x-signature-ed25519')
|
||||
|
@ -559,7 +568,31 @@ export class SlashClient {
|
|||
|
||||
try {
|
||||
const payload: InteractionPayload = JSON.parse(decoder.decode(rawbody))
|
||||
const res = new Interaction(this as any, payload, {})
|
||||
|
||||
// TODO: Maybe fix all this hackery going on here?
|
||||
const res = new Interaction(this as any, payload, {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
user: new User(this as any, (payload.member?.user ?? payload.user)!),
|
||||
member: payload.member as any,
|
||||
guild: payload.guild_id as any,
|
||||
channel: payload.channel_id as any,
|
||||
resolved: ((payload.data
|
||||
?.resolved as unknown) as InteractionApplicationCommandResolved) ?? {
|
||||
users: {},
|
||||
members: {},
|
||||
roles: {},
|
||||
channels: {}
|
||||
}
|
||||
})
|
||||
res._httpRespond = async (d: InteractionResponsePayload) =>
|
||||
await req.respond({
|
||||
status: 200,
|
||||
headers: new Headers({
|
||||
'content-type': 'application/json'
|
||||
}),
|
||||
body: JSON.stringify(d)
|
||||
})
|
||||
|
||||
return res
|
||||
} catch (e) {
|
||||
return false
|
||||
|
|
|
@ -108,6 +108,8 @@ export class Interaction extends SnowflakeBase {
|
|||
resolved: InteractionApplicationCommandResolved
|
||||
/** Whether response was deferred or not */
|
||||
deferred: boolean = false
|
||||
_httpRespond?: (d: InteractionResponsePayload) => unknown
|
||||
_httpResponded?: boolean
|
||||
|
||||
constructor(
|
||||
client: Client,
|
||||
|
@ -180,10 +182,14 @@ export class Interaction extends SnowflakeBase {
|
|||
: undefined
|
||||
}
|
||||
|
||||
await this.client.rest.post(
|
||||
INTERACTION_CALLBACK(this.id, this.token),
|
||||
payload
|
||||
)
|
||||
if (this._httpRespond !== undefined && this._httpResponded !== true) {
|
||||
this._httpResponded = true
|
||||
await this._httpRespond(payload)
|
||||
} else
|
||||
await this.client.rest.post(
|
||||
INTERACTION_CALLBACK(this.id, this.token),
|
||||
payload
|
||||
)
|
||||
this.responded = true
|
||||
|
||||
return this
|
||||
|
|
|
@ -18,27 +18,10 @@ await slash.commands.bulkEdit([
|
|||
const options = { port: 8000 }
|
||||
console.log('Listen on port: ' + options.port.toString())
|
||||
listenAndServe(options, async (req) => {
|
||||
const verify = await slash.verifyServerRequest(req)
|
||||
if (verify === false)
|
||||
return req.respond({ status: 401, body: 'not authorized' })
|
||||
const d = await slash.verifyServerRequest(req)
|
||||
if (d === false) return req.respond({ status: 401, body: 'not authorized' })
|
||||
|
||||
const respond = async (d: any): Promise<void> =>
|
||||
req.respond({
|
||||
status: 200,
|
||||
body: JSON.stringify(d),
|
||||
headers: new Headers({
|
||||
'content-type': 'application/json'
|
||||
})
|
||||
})
|
||||
|
||||
const body = JSON.parse(
|
||||
new TextDecoder('utf-8').decode(await Deno.readAll(req.body))
|
||||
)
|
||||
if (body.type === 1) return await respond({ type: 1 })
|
||||
await respond({
|
||||
type: 4,
|
||||
data: {
|
||||
content: 'Pong!'
|
||||
}
|
||||
})
|
||||
console.log(d)
|
||||
if (d.type === 1) return d.respond({ type: 1 })
|
||||
d.reply('Pong!')
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue