Skip to content

Commit bb008c3

Browse files
committed
feat: manage command
1 parent 378f15f commit bb008c3

2 files changed

Lines changed: 94 additions & 0 deletions

File tree

src/commands/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { API } from '@discordjs/core/http-only';
22
import type { RESTPostAPIApplicationCommandsJSONBody } from '@discordjs/core/http-only';
33
import type { Env } from '../util.js';
4+
import * as manage from './manage.js';
45
import * as setup from './setup.js';
56

67
interface Command {
@@ -9,5 +10,6 @@ interface Command {
910
}
1011

1112
export const commands: Record<string, Command> = {
13+
manage,
1214
setup,
1315
};

src/commands/manage.ts

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import {
2+
ApplicationCommandOptionType,
3+
ApplicationCommandType,
4+
ApplicationIntegrationType,
5+
InteractionContextType,
6+
type APIChatInputApplicationCommandGuildInteraction,
7+
type RESTPostAPIApplicationCommandsJSONBody,
8+
} from '@discordjs/core/http-only';
9+
import type { API } from '@discordjs/core/http-only';
10+
import { InteractionOptionResolver } from '@sapphire/discord-utilities';
11+
import type { Env, LinkedAccount } from '../util.js';
12+
13+
export const interaction: RESTPostAPIApplicationCommandsJSONBody = {
14+
name: 'manage',
15+
description: 'Used for admin management',
16+
type: ApplicationCommandType.ChatInput,
17+
options: [
18+
{
19+
name: 'revoke',
20+
description: 'Revoke a connection',
21+
type: ApplicationCommandOptionType.Subcommand,
22+
options: [
23+
{
24+
name: 'user',
25+
description: 'User to revoke the connection from',
26+
type: ApplicationCommandOptionType.User,
27+
required: true,
28+
},
29+
],
30+
},
31+
{
32+
name: 'view',
33+
description: 'View all connections that exist on the server',
34+
type: ApplicationCommandOptionType.Subcommand,
35+
options: [],
36+
},
37+
],
38+
contexts: [InteractionContextType.Guild],
39+
default_member_permissions: '0',
40+
integration_types: [ApplicationIntegrationType.GuildInstall],
41+
};
42+
43+
export async function handle(interaction: APIChatInputApplicationCommandGuildInteraction, env: Env, api: API) {
44+
const options = new InteractionOptionResolver(interaction);
45+
46+
switch (options.getSubcommand(true)) {
47+
case 'revoke': {
48+
const user = options.getUser('user', true);
49+
const connection = await env.DB.prepare('SELECT * FROM linked_accounts WHERE discord_id = ?')
50+
.bind(user.id)
51+
.first<LinkedAccount>();
52+
53+
if (!connection) {
54+
return api.interactions.editReply(env.CLIENT_ID, interaction.token, {
55+
content: 'Connection not found for that user',
56+
});
57+
}
58+
59+
await env.DB.prepare('DELETE FROM linked_accounts WHERE discord_id = ?').bind(user.id).run();
60+
61+
return api.interactions.editReply(env.CLIENT_ID, interaction.token, {
62+
content: 'Successfully revoked the connection',
63+
});
64+
}
65+
66+
case 'view': {
67+
const connections = await env.DB.prepare('SELECT * FROM linked_accounts').all<LinkedAccount>();
68+
69+
if (!connections.results.length) {
70+
return api.interactions.editReply(env.CLIENT_ID, interaction.token, {
71+
content: 'No connections found',
72+
});
73+
}
74+
75+
const users = await Promise.all(connections.results.map(async (conn) => api.users.get(conn.discord_id)));
76+
const lines = connections.results.map(
77+
(conn, index) =>
78+
`${users[index]!.username} (${conn.discord_id}) - ${conn.minecraft_username} (confirmed: ${conn.confirmed ? 'Yes' : 'No'})`,
79+
);
80+
81+
return api.interactions.editReply(env.CLIENT_ID, interaction.token, {
82+
content: "Here's the full list",
83+
files: [
84+
{
85+
name: 'connections.txt',
86+
data: lines.join('\n'),
87+
},
88+
],
89+
});
90+
}
91+
}
92+
}

0 commit comments

Comments
 (0)