Skip to content

Commit 378f15f

Browse files
committed
refactor: use cf workers
1 parent a14f16a commit 378f15f

File tree

21 files changed

+1361
-844
lines changed

21 files changed

+1361
-844
lines changed

.dockerignore

Lines changed: 0 additions & 25 deletions
This file was deleted.

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/**/node_modules
2-
.env
2+
.dev.vars
3+
.wrangler
34

45
coverage
56
/**/dist

Dockerfile

Lines changed: 0 additions & 26 deletions
This file was deleted.

docker-compose.yml

Lines changed: 0 additions & 35 deletions
This file was deleted.

package.json

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,22 @@
1919
"scripts": {
2020
"lint": "eslint src && prettier --check .",
2121
"build": "tsc",
22+
"publish": "wrangler deploy",
23+
"dev": "wrangler dev",
24+
"schema:dev": "wrangler d1 execute db --local --file=./schema.sql",
25+
"schema": "wrangler d1 execute db --remote --file=./schema.sql",
2226
"format": "prettier --write .",
2327
"update": "yarn upgrade-interactive"
2428
},
2529
"devDependencies": {
26-
"@types/express": "^4",
30+
"@cloudflare/workers-types": "^4.20250204.0",
2731
"eslint": "^8.57.1",
2832
"eslint-config-neon": "^0.1.62",
2933
"prettier": "^3.3.3",
3034
"prettier-eslint": "^16.3.0",
31-
"turbo": "^2.3.1",
32-
"typescript": "^5.6.3"
35+
"typescript": "^5.6.3",
36+
"undici-types": "^7.3.0",
37+
"wrangler": "^3.107.3"
3338
},
3439
"dependencies": {
3540
"@discordjs/builders": "^1.10.0",
@@ -38,9 +43,8 @@
3843
"@sapphire/bitfield": "^1.2.4",
3944
"@sapphire/discord-utilities": "^3.4.4",
4045
"discord-interactions": "^4.1.1",
41-
"express": "^4.21.2",
46+
"itty-router": "^5.0.18",
4247
"pino": "^9.6.0",
43-
"postgres": "^3.4.5",
44-
"zod": "^3.24.1"
48+
"postgres": "^3.4.5"
4549
}
4650
}

schema.sql

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
DROP TABLE IF EXISTS linked_accounts;
2+
CREATE TABLE IF NOT EXISTS linked_accounts (
3+
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
4+
discord_id TEXT NOT NULL UNIQUE,
5+
minecraft_username TEXT NOT NULL UNIQUE,
6+
confirmed BOOLEAN NOT NULL DEFAULT 0
7+
);

src/commands/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
import type { RESTPostAPIApplicationCommandsJSONBody } from '@discordjs/core';
1+
import type { API } from '@discordjs/core/http-only';
2+
import type { RESTPostAPIApplicationCommandsJSONBody } from '@discordjs/core/http-only';
3+
import type { Env } from '../util.js';
24
import * as setup from './setup.js';
35

46
interface Command {
5-
handle(interaction: any): Promise<unknown>;
7+
handle(interaction: any, env: Env, api: API): Promise<unknown>;
68
interaction: RESTPostAPIApplicationCommandsJSONBody;
79
}
810

src/commands/setup.ts

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ import {
88
PermissionFlagsBits,
99
type APIChatInputApplicationCommandGuildInteraction,
1010
type RESTPostAPIApplicationCommandsJSONBody,
11-
} from '@discordjs/core';
11+
} from '@discordjs/core/http-only';
12+
import type { API } from '@discordjs/core/http-only';
1213
import { InteractionOptionResolver } from '@sapphire/discord-utilities';
1314
import { PermissionsBitField } from '../permissions.js';
14-
import { api, ENV, logger } from '../util.js';
15+
import { logger, type Env } from '../util.js';
1516

1617
export const interaction: RESTPostAPIApplicationCommandsJSONBody = {
1718
name: 'setup',
@@ -42,9 +43,9 @@ export const interaction: RESTPostAPIApplicationCommandsJSONBody = {
4243
integration_types: [ApplicationIntegrationType.GuildInstall],
4344
};
4445

45-
export async function handle(interaction: APIChatInputApplicationCommandGuildInteraction) {
46+
export async function handle(interaction: APIChatInputApplicationCommandGuildInteraction, env: Env, api: API) {
4647
if (!PermissionsBitField.has(BigInt(interaction.app_permissions), PermissionFlagsBits.ManageWebhooks)) {
47-
return api.interactions.editReply(ENV.CLIENT_ID, interaction.token, {
48+
return api.interactions.editReply(env.CLIENT_ID, interaction.token, {
4849
content: 'The bot does not have the required permissions to set up the webhook.',
4950
});
5051
}
@@ -54,11 +55,11 @@ export async function handle(interaction: APIChatInputApplicationCommandGuildInt
5455
switch (options.getSubcommand(true)) {
5556
case 'webhook': {
5657
const webhooks = await api.channels.getWebhooks(interaction.channel.id);
57-
const webhook = webhooks.find((webhook) => webhook.user!.id === ENV.CLIENT_ID);
58+
const webhook = webhooks.find((webhook) => webhook.user!.id === env.CLIENT_ID);
5859
if (webhook) {
5960
logger.debug('found existing webhook');
6061
const fullWebhook = await api.webhooks.get(webhook.id);
61-
return api.interactions.editReply(ENV.CLIENT_ID, interaction.token, {
62+
return api.interactions.editReply(env.CLIENT_ID, interaction.token, {
6263
content: `Here's the webhook url: https://discord.com/api/webhooks/${fullWebhook.id}/${fullWebhook.token!}`,
6364
});
6465
}
@@ -68,7 +69,7 @@ export async function handle(interaction: APIChatInputApplicationCommandGuildInt
6869
name: 'Prompt',
6970
});
7071

71-
return api.interactions.editReply(ENV.CLIENT_ID, interaction.token, {
72+
return api.interactions.editReply(env.CLIENT_ID, interaction.token, {
7273
content: `Here's the webhook url: https://discord.com/api/webhooks/${newWebhook.id}/${newWebhook.token!}`,
7374
});
7475
}
@@ -77,21 +78,21 @@ export async function handle(interaction: APIChatInputApplicationCommandGuildInt
7778
const messageURL = options.getString('message', true);
7879
const [channelId, messageId] = messageURL.split('/').slice(-2) as [string, string];
7980
if (!channelId || !messageId) {
80-
return api.interactions.editReply(ENV.CLIENT_ID, interaction.token, {
81+
return api.interactions.editReply(env.CLIENT_ID, interaction.token, {
8182
content: 'Invalid message URL',
8283
});
8384
}
8485

8586
const message = await api.channels.getMessage(channelId, messageId).catch(() => null);
8687
if (!message) {
87-
return api.interactions.editReply(ENV.CLIENT_ID, interaction.token, {
88+
return api.interactions.editReply(env.CLIENT_ID, interaction.token, {
8889
content: 'Message not found',
8990
});
9091
}
9192

9293
const webhook = message.webhook_id ? await api.webhooks.get(message.webhook_id).catch(() => null) : null;
93-
if (!webhook || webhook.user!.id !== ENV.CLIENT_ID) {
94-
return api.interactions.editReply(ENV.CLIENT_ID, interaction.token, {
94+
if (!webhook || webhook.user!.id !== env.CLIENT_ID) {
95+
return api.interactions.editReply(env.CLIENT_ID, interaction.token, {
9596
content: 'Message does not belong to bot webhook',
9697
});
9798
}
@@ -111,7 +112,7 @@ export async function handle(interaction: APIChatInputApplicationCommandGuildInt
111112
},
112113
],
113114
});
114-
await api.interactions.editReply(ENV.CLIENT_ID, interaction.token, {
115+
await api.interactions.editReply(env.CLIENT_ID, interaction.token, {
115116
content: 'Prompt added to the message',
116117
});
117118

src/components/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import type { Response } from 'express';
1+
import type { IRequest } from 'itty-router';
2+
import type { JsonResponse } from '../response.js';
23
import * as link from './link.js';
34

45
interface Component {
5-
handle(res: Response, interaction: any): Promise<unknown>;
6+
handle(req: IRequest, ctx: ExecutionContext, interaction: any): Promise<JsonResponse>;
67
}
78

89
export const components: Record<string, Component> = {

src/components/link.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import { ActionRowBuilder, ModalBuilder, TextInputBuilder } from '@discordjs/builders';
2-
import { TextInputStyle, type APIMessageComponentGuildInteraction } from '@discordjs/core';
3-
import { InteractionResponseType } from 'discord-interactions';
4-
import type { Response } from 'express';
2+
import { InteractionResponseType, TextInputStyle } from '@discordjs/core/http-only';
3+
import { JsonResponse } from '../response.js';
54

6-
export async function handle(res: Response, interaction: APIMessageComponentGuildInteraction) {
7-
return res.status(200).send({
8-
type: InteractionResponseType.MODAL,
5+
export async function handle(): Promise<JsonResponse> {
6+
return new JsonResponse({
7+
type: InteractionResponseType.Modal,
98
data: new ModalBuilder()
109
.setCustomId('submit')
1110
.setTitle('Link your Minecraft account')

0 commit comments

Comments
 (0)