x
This commit is contained in:
parent
e65fa8fded
commit
dcb07a9aaa
3 changed files with 78 additions and 0 deletions
|
@ -1,6 +1,7 @@
|
||||||
import { Guild } from '../structures/guild.ts'
|
import { Guild } from '../structures/guild.ts'
|
||||||
import { Interaction } from '../structures/slash.ts'
|
import { Interaction } from '../structures/slash.ts'
|
||||||
import {
|
import {
|
||||||
|
InteractionPayload,
|
||||||
InteractionType,
|
InteractionType,
|
||||||
SlashCommandChoice,
|
SlashCommandChoice,
|
||||||
SlashCommandOption,
|
SlashCommandOption,
|
||||||
|
@ -369,6 +370,7 @@ export interface SlashOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
const encoder = new TextEncoder()
|
const encoder = new TextEncoder()
|
||||||
|
const decoder = new TextDecoder('utf-8')
|
||||||
|
|
||||||
export class SlashClient {
|
export class SlashClient {
|
||||||
id: string | (() => string)
|
id: string | (() => string)
|
||||||
|
@ -503,6 +505,7 @@ export class SlashClient {
|
||||||
cmd.handler(interaction)
|
cmd.handler(interaction)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Verify HTTP based Interaction */
|
||||||
async verifyKey(
|
async verifyKey(
|
||||||
rawBody: string | Uint8Array,
|
rawBody: string | Uint8Array,
|
||||||
signature: string | Uint8Array,
|
signature: string | Uint8Array,
|
||||||
|
@ -521,6 +524,35 @@ export class SlashClient {
|
||||||
return edverify(signature, fullBody, this.publicKey).catch(() => false)
|
return edverify(signature, fullBody, this.publicKey).catch(() => false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Verify [Deno Std HTTP Server Request](https://deno.land/std/http/server.ts) and return Interaction */
|
||||||
|
async verifyServerRequest(req: {
|
||||||
|
headers: Headers
|
||||||
|
method: string
|
||||||
|
body: Deno.Reader
|
||||||
|
respond: (options: {
|
||||||
|
status?: number
|
||||||
|
body?: string | Uint8Array
|
||||||
|
}) => Promise<void>
|
||||||
|
}): Promise<boolean | Interaction> {
|
||||||
|
if (req.method.toLowerCase() !== 'post') return false
|
||||||
|
|
||||||
|
const signature = req.headers.get('x-signature-ed25519')
|
||||||
|
const timestamp = req.headers.get('x-signature-timestamp')
|
||||||
|
if (signature === null || timestamp === null) return false
|
||||||
|
|
||||||
|
const rawbody = await Deno.readAll(req.body)
|
||||||
|
const verify = await this.verifyKey(rawbody, signature, timestamp)
|
||||||
|
if (!verify) return false
|
||||||
|
|
||||||
|
try {
|
||||||
|
const payload: InteractionPayload = JSON.parse(decoder.decode(rawbody))
|
||||||
|
const res = new Interaction(this as any, payload, {})
|
||||||
|
return res
|
||||||
|
} catch (e) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async verifyOpineRequest(req: any): Promise<boolean> {
|
async verifyOpineRequest(req: any): Promise<boolean> {
|
||||||
const signature = req.headers.get('x-signature-ed25519')
|
const signature = req.headers.get('x-signature-ed25519')
|
||||||
const timestamp = req.headers.get('x-signature-timestamp')
|
const timestamp = req.headers.get('x-signature-timestamp')
|
||||||
|
|
|
@ -41,6 +41,7 @@ export interface InteractionResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Interaction extends SnowflakeBase {
|
export class Interaction extends SnowflakeBase {
|
||||||
|
/** This will be `SlashClient` in case of `SlashClient#verifyServerRequest` */
|
||||||
client: Client
|
client: Client
|
||||||
type: number
|
type: number
|
||||||
token: string
|
token: string
|
||||||
|
@ -50,6 +51,7 @@ export class Interaction extends SnowflakeBase {
|
||||||
guild: Guild
|
guild: Guild
|
||||||
member: Member
|
member: Member
|
||||||
_savedHook?: Webhook
|
_savedHook?: Webhook
|
||||||
|
_respond?: (data: InteractionResponsePayload) => unknown
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
client: Client,
|
client: Client,
|
||||||
|
|
44
src/test/slash-http.ts
Normal file
44
src/test/slash-http.ts
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
import { SlashClient } from '../../mod.ts'
|
||||||
|
import { SLASH_ID, SLASH_PUB_KEY, SLASH_TOKEN } from './config.ts'
|
||||||
|
import { listenAndServe } from 'https://deno.land/std@0.90.0/http/server.ts'
|
||||||
|
|
||||||
|
const slash = new SlashClient({
|
||||||
|
id: SLASH_ID,
|
||||||
|
token: SLASH_TOKEN,
|
||||||
|
publicKey: SLASH_PUB_KEY
|
||||||
|
})
|
||||||
|
|
||||||
|
await slash.commands.bulkEdit([
|
||||||
|
{
|
||||||
|
name: 'ping',
|
||||||
|
description: 'Just ping!'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
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 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!'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
Loading…
Reference in a new issue