mirror of
https://github.com/xHyroM/roles-bot.git
synced 2024-11-09 10:58:06 +01:00
feat: add things
This commit is contained in:
parent
eebc948a58
commit
05aa790303
12 changed files with 156 additions and 43 deletions
|
@ -13,11 +13,13 @@
|
|||
"devDependencies": {
|
||||
"@cloudflare/workers-types": "^3.17.0",
|
||||
"@types/jest": "^29.1.2",
|
||||
"discord-api-types": "^0.37.14",
|
||||
"esbuild": "^0.15.11",
|
||||
"eslint": "^8.25.0",
|
||||
"jest": "^29.2.0",
|
||||
"miniflare": "^2.10.0",
|
||||
"typescript": "^4.8.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"discord-api-types": "^0.37.37"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,15 @@
|
|||
import { InteractionResponseType } from "discord-api-types/v10";
|
||||
import { Command } from "../structs/Command";
|
||||
import respond from "../utils/respond";
|
||||
|
||||
new Command({
|
||||
name: "setup",
|
||||
run: async () => {
|
||||
return respond({
|
||||
type: InteractionResponseType.ChannelMessageWithSource,
|
||||
data: {
|
||||
content: "Setup",
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,11 +1,51 @@
|
|||
import "./commands/setup";
|
||||
import { COMMANDS } from "./registers";
|
||||
import {
|
||||
APIApplicationCommandInteraction,
|
||||
APIMessageComponentInteraction,
|
||||
APIPingInteraction,
|
||||
InteractionResponseType,
|
||||
InteractionType,
|
||||
} from "discord-api-types/v10";
|
||||
import { COMMANDS, COMPONENTS } from "./registers";
|
||||
import { verify } from "./utils/verify";
|
||||
import respond from "./utils/respond";
|
||||
|
||||
console.log(COMMANDS);
|
||||
|
||||
export default {
|
||||
fetch: (request: Request) => {
|
||||
console.log(request);
|
||||
return new Response("asda");
|
||||
fetch: async (request: Request) => {
|
||||
if (
|
||||
!request.headers.get("X-Signature-Ed25519") ||
|
||||
!request.headers.get("X-Signature-Timestamp")
|
||||
)
|
||||
return Response.redirect("https://xhyrom.dev");
|
||||
if (!(await verify(request)))
|
||||
return new Response("Invalid request signature", { status: 401 });
|
||||
|
||||
const interaction = (await request.json()) as
|
||||
| APIPingInteraction
|
||||
| APIApplicationCommandInteraction
|
||||
| APIMessageComponentInteraction;
|
||||
|
||||
if (interaction.type === InteractionType.Ping)
|
||||
return respond({
|
||||
type: InteractionResponseType.Pong,
|
||||
});
|
||||
|
||||
if (interaction.type === InteractionType.ApplicationCommand) {
|
||||
const command = COMMANDS.find(
|
||||
(cmd) => cmd.name === interaction.data.name,
|
||||
);
|
||||
|
||||
if (!command) return new Response("Unknown command", { status: 404 });
|
||||
return command.run(interaction);
|
||||
}
|
||||
|
||||
const component = COMPONENTS.find(
|
||||
(cmp) => cmp.id === interaction.data.custom_id,
|
||||
);
|
||||
|
||||
if (!component) return new Response("Unknown component", { status: 404 });
|
||||
return component.run(interaction);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import { Command } from "./structs/Command";
|
||||
import { Listener } from "./structs/Listener";
|
||||
import { Component } from "./structs/Component";
|
||||
|
||||
export const COMMANDS: Command[] = [];
|
||||
export const LISTENERS: Listener[] = [];
|
||||
export const COMPONENTS: Component[] = [];
|
||||
|
||||
export const registerCommand = (command: Command) => {
|
||||
COMMANDS.push(command);
|
||||
};
|
||||
|
||||
export const registerListener = (listener: Listener) => {
|
||||
LISTENERS.push(listener);
|
||||
export const registerComponent = (component: Component) => {
|
||||
COMPONENTS.push(component);
|
||||
};
|
||||
|
|
|
@ -1,14 +1,20 @@
|
|||
import { APIApplicationCommandInteraction } from "discord-api-types/v10";
|
||||
import { registerCommand } from "../registers";
|
||||
|
||||
interface CommandOptions {
|
||||
name: string;
|
||||
run: (interaction: APIApplicationCommandInteraction) => Promise<Response>;
|
||||
}
|
||||
|
||||
export class Command {
|
||||
public name: string;
|
||||
public run: (
|
||||
interaction: APIApplicationCommandInteraction,
|
||||
) => Promise<Response>;
|
||||
|
||||
constructor(options: CommandOptions) {
|
||||
this.name = options.name;
|
||||
this.run = options.run;
|
||||
|
||||
registerCommand(this);
|
||||
}
|
||||
|
|
21
packages/bot/src/structs/Component.ts
Normal file
21
packages/bot/src/structs/Component.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import { APIMessageComponentInteraction } from "discord-api-types/v10";
|
||||
import { registerComponent } from "../registers";
|
||||
|
||||
interface ComponentOptions {
|
||||
id: string;
|
||||
run: (interaction: APIMessageComponentInteraction) => Promise<Response>;
|
||||
}
|
||||
|
||||
export class Component {
|
||||
public id: string;
|
||||
public run: (
|
||||
interaction: APIMessageComponentInteraction,
|
||||
) => Promise<Response>;
|
||||
|
||||
constructor(options: ComponentOptions) {
|
||||
this.id = options.id;
|
||||
this.run = options.run;
|
||||
|
||||
registerComponent(this);
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
import { registerListener } from "../registers";
|
||||
|
||||
interface ListenerOptions {
|
||||
name: string;
|
||||
once: boolean | undefined;
|
||||
}
|
||||
|
||||
export class Listener {
|
||||
public name: string;
|
||||
public once: boolean;
|
||||
|
||||
constructor(options: ListenerOptions) {
|
||||
this.name = options.name;
|
||||
this.once = options.once ?? false;
|
||||
|
||||
registerListener(this);
|
||||
}
|
||||
}
|
3
packages/bot/src/types.d.ts
vendored
Normal file
3
packages/bot/src/types.d.ts
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
// secrets: wrangler secret put <name>
|
||||
declare const publicKey: string;
|
||||
declare const token: string;
|
7
packages/bot/src/utils/respond.ts
Normal file
7
packages/bot/src/utils/respond.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { APIInteractionResponse } from "discord-api-types/v10";
|
||||
|
||||
export default function (response: APIInteractionResponse) {
|
||||
return new Response(JSON.stringify(response), {
|
||||
headers: { "content-type": "application/json" },
|
||||
});
|
||||
}
|
38
packages/bot/src/utils/verify.ts
Normal file
38
packages/bot/src/utils/verify.ts
Normal file
|
@ -0,0 +1,38 @@
|
|||
// from https://gist.github.com/devsnek/77275f6e3f810a9545440931ed314dc1
|
||||
|
||||
"use strict";
|
||||
|
||||
function hex2bin(hex: string) {
|
||||
const buf = new Uint8Array(Math.ceil(hex.length / 2));
|
||||
for (let i = 0; i < buf.length; i++) {
|
||||
buf[i] = parseInt(hex.substring(i * 2, i * 2 + 2), 16);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
const PUBLIC_KEY = crypto.subtle.importKey(
|
||||
"raw",
|
||||
hex2bin(publicKey),
|
||||
{
|
||||
name: "NODE-ED25519",
|
||||
namedCurve: "NODE-ED25519",
|
||||
},
|
||||
true,
|
||||
["verify"],
|
||||
);
|
||||
|
||||
const encoder = new TextEncoder();
|
||||
|
||||
export async function verify(request: Request) {
|
||||
// rome-ignore lint/style/noNonNullAssertion: its fine
|
||||
const signature = hex2bin(request.headers.get("X-Signature-Ed25519")!);
|
||||
const timestamp = request.headers.get("X-Signature-Timestamp");
|
||||
const unknown = await request.clone().text();
|
||||
|
||||
return await crypto.subtle.verify(
|
||||
"NODE-ED25519",
|
||||
await PUBLIC_KEY,
|
||||
signature,
|
||||
encoder.encode(timestamp + unknown),
|
||||
);
|
||||
}
|
|
@ -9,6 +9,10 @@ importers:
|
|||
version: 12.0.0
|
||||
|
||||
packages/bot:
|
||||
dependencies:
|
||||
discord-api-types:
|
||||
specifier: ^0.37.37
|
||||
version: 0.37.37
|
||||
devDependencies:
|
||||
'@cloudflare/workers-types':
|
||||
specifier: ^3.17.0
|
||||
|
@ -16,9 +20,6 @@ importers:
|
|||
'@types/jest':
|
||||
specifier: ^29.1.2
|
||||
version: 29.1.2
|
||||
discord-api-types:
|
||||
specifier: ^0.37.14
|
||||
version: 0.37.14
|
||||
esbuild:
|
||||
specifier: ^0.15.11
|
||||
version: 0.15.11
|
||||
|
@ -2324,9 +2325,9 @@ packages:
|
|||
path-type: 4.0.0
|
||||
dev: true
|
||||
|
||||
/discord-api-types@0.37.14:
|
||||
resolution: {integrity: sha512-byBH7SfDCMJwxdqeS8k5sihltH88/YPhuwx+vF2cftSxFLdxyHyU/ZxDL3bq+LB2c4ls/TymE76/ISlLfniUXg==}
|
||||
dev: true
|
||||
/discord-api-types@0.37.37:
|
||||
resolution: {integrity: sha512-LDMBKzl/zbvHO/yCzno5hevuA6lFIXJwdKSJZQrB+1ToDpFfN9thK+xxgZNR4aVkI7GHRDja0p4Sl2oYVPnHYg==}
|
||||
dev: false
|
||||
|
||||
/dlv@1.1.3:
|
||||
resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
|
||||
|
|
23
rome.json
23
rome.json
|
@ -1,12 +1,15 @@
|
|||
{
|
||||
"$schema": "./node_modules/rome/configuration_schema.json",
|
||||
"organizeImports": {
|
||||
"enabled": false
|
||||
},
|
||||
"linter": {
|
||||
"enabled": true,
|
||||
"rules": {
|
||||
"recommended": true
|
||||
}
|
||||
}
|
||||
"$schema": "./node_modules/rome/configuration_schema.json",
|
||||
"organizeImports": {
|
||||
"enabled": false
|
||||
},
|
||||
"files": {
|
||||
"ignore": ["dist/**"]
|
||||
},
|
||||
"linter": {
|
||||
"enabled": true,
|
||||
"rules": {
|
||||
"recommended": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue