fix interactions, apparently cfw doesn't speak Buffer

This commit is contained in:
41666 2022-02-03 22:57:37 -05:00
parent 7007cfea9d
commit 544ef1b2f0
5 changed files with 56 additions and 20 deletions

View file

@ -10,10 +10,15 @@ export const helloWorld: InteractionHandler = (
interaction: InteractionRequest,
context: Context
): InteractionResponse => {
console.log({ interaction });
return {
type: InteractionCallbackType.CHANNEL_MESSAGE_WITH_SOURCE,
data: {
content: `Hey there, ${interaction.member?.nick || interaction.user?.username}`,
content: `Hey there, ${
interaction.member?.nick ||
interaction.member?.user?.username ||
interaction.user?.username
}`,
},
};
};

View file

@ -13,6 +13,7 @@ export const verifyRequest = async (
request: Request,
interaction: InteractionRequest
): Promise<boolean> => {
try {
const timestamp = request.headers.get('x-signature-timestamp');
const signature = request.headers.get('x-signature-ed25519');
@ -22,18 +23,40 @@ export const verifyRequest = async (
const key = await crypto.subtle.importKey(
'raw',
Buffer.from(config.publicKey, 'hex'),
bufferizeHex(config.publicKey),
{ name: 'NODE-ED25519', namedCurve: 'NODE-ED25519', public: true } as any,
false,
['verify']
);
return crypto.subtle.verify(
const verified = await crypto.subtle.verify(
'NODE-ED25519',
key,
Buffer.from(signature, 'hex'),
Buffer.from(timestamp + JSON.stringify(interaction))
bufferizeHex(signature),
bufferizeString(timestamp + JSON.stringify(interaction))
);
return verified;
} catch (e) {
return false;
}
};
// Cloudflare Workers + SubtleCrypto has no idea what a Buffer.from() is.
// What the fuck?
const bufferizeHex = (input: string) => {
const buffer = new Uint8Array(input.length / 2);
for (let i = 0; i < input.length; i += 2) {
buffer[i / 2] = parseInt(input.substring(i, i + 2), 16);
}
return buffer;
};
const bufferizeString = (input: string) => {
const encoder = new TextEncoder();
return encoder.encode(input);
};
export type InteractionHandler = ((
@ -59,7 +82,7 @@ export const runAsync = async (
'Content-Type': 'application/json',
},
body: JSON.stringify({
type: InteractionCallbackType.DEFERRED_UPDATE_MESSAGE,
type: InteractionCallbackType.DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE,
data: {
flags: handler.ephemeral ? InteractionFlags.EPHEMERAL : 0,
...response.data,
@ -82,7 +105,7 @@ export const runAsync = async (
'Content-Type': 'application/json',
},
body: JSON.stringify({
type: InteractionCallbackType.DEFERRED_UPDATE_MESSAGE,
type: InteractionCallbackType.DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE,
data: {
content: "I'm sorry, I'm having trouble processing this request.",
flags: InteractionFlags.EPHEMERAL,

View file

@ -30,14 +30,17 @@ export const handleInteraction: RoleypolyHandler = async (
}
if (!(await verifyRequest(context.config, request, interaction))) {
console.warn('interactions: invalid signature');
return new Response('invalid request signature', { status: 401 });
}
if (interaction.type !== InteractionType.APPLICATION_COMMAND) {
if (interaction.type === InteractionType.PING) {
console.info('interactions: ping');
return json({ type: InteractionCallbackType.PONG });
}
console.warn('interactions: not application command');
return json({ err: 'not implemented' }, { status: 400 });
}

View file

@ -17,7 +17,7 @@ export const corsHeaders = {
'Access-Control-Max-Age': '86400',
};
export const noContent = () => new Response(null, { status: 204 });
export const noContent = () => new Response(null, { status: 204, headers: corsHeaders });
export const seeOther = (url: string) =>
new Response(
`<!doctype html>If you are not redirected soon, <a href="${url}">click here.</a>`,

View file

@ -0,0 +1,5 @@
resource "discord-interactions_guild_command" "hello-world" {
name = "hello-world"
description = "Says hello!"
guild_id = "386659935687147521"
}