Skip to content

Commit 4d97a1f

Browse files
committed
feat(bot): add /update command | closes #172
1 parent da5662a commit 4d97a1f

File tree

2 files changed

+234
-1
lines changed

2 files changed

+234
-1
lines changed

src/commands.ts

Lines changed: 173 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
GuildMember,
1616
InteractionContextType,
1717
MessageFlags,
18+
TextChannel,
1819
type ApplicationCommandOptionData,
1920
type CacheType,
2021
type CommandInteraction,
@@ -37,6 +38,9 @@ import {
3738
discordCheckIfDmChannelExists,
3839
discordGetAllTrackedInGuild,
3940
discordRemoveGuildTrackingChannel,
41+
discordUpdateSubscriptionAddChannel,
42+
discordUpdateSubscriptionCheckGuild,
43+
discordUpdateSubscriptionRemoveChannel,
4044
} from "./db/discord";
4145
import {
4246
Platform,
@@ -69,7 +73,7 @@ interface Command {
6973
}
7074

7175
// Context 2: Interaction can be used within Group DMs and DMs other than the app's bot user
72-
// /track, /tracked and /untracked can't be used in these contexts
76+
// /track, /tracked, /untracked and /updates can't be used in these contexts
7377
const commands: Record<string, Command> = {
7478
ping: {
7579
data: {
@@ -1174,6 +1178,174 @@ const commands: Record<string, Command> = {
11741178
});
11751179
},
11761180
},
1181+
updates: {
1182+
data: {
1183+
name: "updates",
1184+
description: "Enable or disable updates for Feedr in this channel",
1185+
integration_types: [0, 1],
1186+
contexts: [0, 1],
1187+
options: [
1188+
{
1189+
name: "state",
1190+
description: "Choose whether to enable or disable updates",
1191+
type: ApplicationCommandOptionType.String,
1192+
required: true,
1193+
choices: [
1194+
{
1195+
name: "Enable",
1196+
value: "enable",
1197+
},
1198+
{
1199+
name: "Disable",
1200+
value: "disable",
1201+
},
1202+
],
1203+
},
1204+
],
1205+
},
1206+
execute: async (interaction: CommandInteraction) => {
1207+
const isDm = !interaction.inGuild();
1208+
1209+
const channelId = interaction.channelId;
1210+
const guildId = isDm ? channelId : interaction.guildId;
1211+
1212+
if (!isDm && !guildId) {
1213+
await interaction.reply({
1214+
flags: MessageFlags.Ephemeral,
1215+
content: "An error occurred! Please report",
1216+
});
1217+
1218+
return;
1219+
}
1220+
1221+
// Check type of the channel
1222+
const targetChannel = await client.channels.fetch(channelId);
1223+
1224+
if (
1225+
targetChannel &&
1226+
(targetChannel.type === ChannelType.GuildText ||
1227+
targetChannel.type === ChannelType.GuildAnnouncement)
1228+
)
1229+
if (
1230+
!isDm &&
1231+
!interaction.memberPermissions?.has(
1232+
PermissionFlagsBits.ManageChannels,
1233+
)
1234+
) {
1235+
// Check the permissions of the user
1236+
await interaction.reply({
1237+
flags: MessageFlags.Ephemeral,
1238+
content:
1239+
"You do not have the permission to manage channels!",
1240+
});
1241+
1242+
return;
1243+
}
1244+
1245+
// Check the permissions of the bot in the channel
1246+
const botMember = isDm
1247+
? null
1248+
: await interaction.guild?.members.fetchMe();
1249+
1250+
if (
1251+
botMember &&
1252+
!botMember
1253+
.permissionsIn(channelId)
1254+
.has(PermissionFlagsBits.SendMessages)
1255+
) {
1256+
await interaction.reply({
1257+
flags: MessageFlags.Ephemeral,
1258+
content:
1259+
"I do not have permission to send messages in that channel!",
1260+
});
1261+
1262+
return;
1263+
}
1264+
1265+
// Get the current state from the database
1266+
const currentDatabaseState =
1267+
await discordUpdateSubscriptionCheckGuild(guildId);
1268+
1269+
if (!currentDatabaseState || !currentDatabaseState.success) {
1270+
await interaction.reply({
1271+
flags: MessageFlags.Ephemeral,
1272+
content:
1273+
"An error occurred while trying to get the current update state from the database! Please report this error!",
1274+
});
1275+
1276+
return;
1277+
}
1278+
1279+
const currentState = Boolean(
1280+
currentDatabaseState.data[0].feedrUpdatesChannelId,
1281+
);
1282+
const desiredState = Boolean(
1283+
interaction.options.get("state")?.value === "enable",
1284+
);
1285+
1286+
if (currentState === desiredState) {
1287+
await interaction.reply({
1288+
flags: MessageFlags.Ephemeral,
1289+
content: `Updates are already ${
1290+
desiredState ? "enabled" : "disabled"
1291+
} in this channel!`,
1292+
});
1293+
}
1294+
1295+
if (desiredState) {
1296+
// Enable updates
1297+
const updateSuccess = await discordUpdateSubscriptionAddChannel(
1298+
guildId,
1299+
channelId,
1300+
);
1301+
1302+
if (!updateSuccess || !updateSuccess.success) {
1303+
await interaction.reply({
1304+
flags: MessageFlags.Ephemeral,
1305+
content:
1306+
"An error occurred while trying to enable updates in this channel! Please report this error!",
1307+
});
1308+
1309+
return;
1310+
}
1311+
1312+
await client.channels
1313+
.fetch(channelId)
1314+
.then(async (channel) => {
1315+
if (channel?.isTextBased()) {
1316+
await (channel as TextChannel).send({
1317+
content: `Updates have been successfully enabled in this channel!`,
1318+
});
1319+
}
1320+
})
1321+
.catch(console.error);
1322+
1323+
await interaction.reply({
1324+
flags: MessageFlags.Ephemeral,
1325+
content:
1326+
"If a test message was sent, updates are enabled! If not, please report this as an error!",
1327+
});
1328+
} else {
1329+
// Disable updates
1330+
const updateSuccess =
1331+
await discordUpdateSubscriptionRemoveChannel(guildId);
1332+
1333+
if (!updateSuccess || !updateSuccess.success) {
1334+
await interaction.reply({
1335+
flags: MessageFlags.Ephemeral,
1336+
content:
1337+
"An error occurred while trying to disable updates in this channel! Please report this error!",
1338+
});
1339+
1340+
return;
1341+
}
1342+
1343+
await interaction.reply({
1344+
content: `Successfully disabled updates in <#${channelId}>!`,
1345+
});
1346+
}
1347+
},
1348+
},
11771349
};
11781350

11791351
// Convert commands to a Map

src/db/discord.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,3 +401,64 @@ export async function discordCheckIfDmChannelExists(
401401
return { success: false, data: [] };
402402
}
403403
}
404+
405+
// Bot updates
406+
export async function discordUpdateSubscriptionAddChannel(
407+
guildId: string,
408+
channelId: string,
409+
): Promise<{ success: boolean; data: [] }> {
410+
console.log(
411+
`Updating guild ${guildId} to set subscription channel to ${channelId}`,
412+
);
413+
414+
try {
415+
await db
416+
.update(dbDiscordTable)
417+
.set({ feedrUpdatesChannelId: channelId })
418+
.where(eq(dbDiscordTable.guildId, guildId));
419+
420+
return { success: true, data: [] };
421+
} catch (error) {
422+
console.error("Error updating subscription channel:", error);
423+
424+
return { success: false, data: [] };
425+
}
426+
}
427+
428+
export async function discordUpdateSubscriptionRemoveChannel(
429+
guildId: string,
430+
): Promise<{ success: boolean; data: [] }> {
431+
console.log(`Removing subscription channel for guild ${guildId}`);
432+
433+
try {
434+
await db
435+
.update(dbDiscordTable)
436+
.set({ feedrUpdatesChannelId: null })
437+
.where(eq(dbDiscordTable.guildId, guildId));
438+
439+
return { success: true, data: [] };
440+
} catch (error) {
441+
console.error("Error removing subscription channel:", error);
442+
443+
return { success: false, data: [] };
444+
}
445+
}
446+
447+
export async function discordUpdateSubscriptionCheckGuild(
448+
guildId: string,
449+
): Promise<{ success: boolean; data: (typeof dbDiscordTable.$inferSelect)[] }> {
450+
console.log(`Checking subscription settings for guild ${guildId}`);
451+
452+
try {
453+
const result = await db
454+
.select()
455+
.from(dbDiscordTable)
456+
.where(eq(dbDiscordTable.guildId, guildId));
457+
458+
return { success: true, data: result };
459+
} catch (error) {
460+
console.error("Error checking subscription settings for guild:", error);
461+
462+
return { success: false, data: [] };
463+
}
464+
}

0 commit comments

Comments
 (0)