Skip to content

Commit de3d34a

Browse files
committed
feat(bot): wow its components
1 parent 7f509a4 commit de3d34a

File tree

1 file changed

+102
-22
lines changed

1 file changed

+102
-22
lines changed

src/commands.ts

Lines changed: 102 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
import Bun from "bun";
22
import { heapStats } from "bun:jsc";
33
import {
4+
ActionRowBuilder,
45
ApplicationCommandOptionType,
56
ApplicationCommandType,
67
AutocompleteInteraction,
8+
ButtonBuilder,
9+
ButtonStyle,
710
ChannelType,
811
ChatInputCommandInteraction,
12+
ComponentType,
13+
EmbedBuilder,
914
GuildMember,
1015
MessageFlags,
1116
type ApplicationCommandOptionData,
@@ -942,32 +947,107 @@ const commands: Record<string, Command> = {
942947
return;
943948
}
944949

945-
const youtubeChannels = trackedChannels.data.youtubeSubscriptions
946-
.map(
947-
(channel) =>
948-
`YouTube: [${channel.youtubeChannel.youtubeChannelName}](<https://www.youtube.com/channel/${channel.youtubeChannel.youtubeChannelId}>) | <#${channel.subscription.notificationChannelId}>`,
949-
)
950-
.join("\n");
951-
const twitchChannels = trackedChannels.data.twitchSubscriptions
952-
.map(
953-
(channel) =>
954-
`Twitch: [${channel.twitchChannel.twitchChannelName}](<https://www.twitch.tv/${channel.twitchChannel.twitchChannelName}>) | <#${channel.subscription.notificationChannelId}>`,
955-
)
956-
.join("\n");
957-
const response = [
958-
"Here are the channels being tracked in this guild:",
959-
youtubeChannels
960-
? `**YouTube Channels:**\n${youtubeChannels}`
961-
: "",
962-
twitchChannels ? `**Twitch Channels:**\n${twitchChannels}` : "",
963-
]
964-
.filter(Boolean)
965-
.join("\n\n");
950+
const youtubeChannels =
951+
trackedChannels.data.youtubeSubscriptions ?? [];
952+
const twitchChannels =
953+
trackedChannels.data.twitchSubscriptions ?? [];
954+
955+
const entries = [
956+
...youtubeChannels.map((c) => ({
957+
type: "YouTube" as const,
958+
name: c.youtubeChannel.youtubeChannelName,
959+
id: c.youtubeChannel.youtubeChannelId,
960+
notifyId: c.subscription.notificationChannelId,
961+
})),
962+
...twitchChannels.map((c) => ({
963+
type: "Twitch" as const,
964+
name: c.twitchChannel.twitchChannelName,
965+
id: c.twitchChannel.twitchChannelName,
966+
notifyId: c.subscription.notificationChannelId,
967+
})),
968+
].sort((a, b) => a.name.localeCompare(b.name));
969+
970+
const pageSize = 10;
971+
const totalPages = Math.ceil(entries.length / pageSize);
972+
let currentPage = 0;
973+
974+
const getPageEmbed = (page: number) => {
975+
const start = page * pageSize;
976+
const end = start + pageSize;
977+
const pageEntries = entries.slice(start, end);
978+
979+
const description =
980+
pageEntries
981+
.map((entry) => {
982+
const link =
983+
entry.type === "YouTube"
984+
? `https://www.youtube.com/channel/${entry.id}`
985+
: `https://www.twitch.tv/${entry.id}`;
986+
987+
return `**[${entry.name}](${link})** • ${entry.type} • <#${entry.notifyId}>`;
988+
})
989+
.join("\n") || "No entries.";
990+
991+
return new EmbedBuilder()
992+
.setTitle("Tracked Channels")
993+
.setDescription(description)
994+
.setFooter({
995+
text: `Page ${page + 1} of ${totalPages}`,
996+
})
997+
.setColor(0x5865f2);
998+
};
999+
1000+
const getButtons = (page: number) => {
1001+
return new ActionRowBuilder<ButtonBuilder>().addComponents(
1002+
new ButtonBuilder()
1003+
.setCustomId("prev")
1004+
.setLabel("Previous")
1005+
.setStyle(ButtonStyle.Secondary)
1006+
.setDisabled(page === 0),
1007+
new ButtonBuilder()
1008+
.setCustomId("next")
1009+
.setLabel("Next")
1010+
.setStyle(ButtonStyle.Primary)
1011+
.setDisabled(page >= totalPages - 1),
1012+
);
1013+
};
9661014

9671015
await interaction.reply({
968-
content: response,
1016+
embeds: [getPageEmbed(currentPage)],
1017+
components: [getButtons(currentPage)],
9691018
flags: MessageFlags.Ephemeral,
9701019
});
1020+
1021+
const message = await interaction.fetchReply();
1022+
1023+
const collector = message.createMessageComponentCollector({
1024+
componentType: ComponentType.Button,
1025+
time: 60_000,
1026+
filter: (i) => i.user.id === interaction.user.id,
1027+
});
1028+
1029+
collector.on("collect", async (i) => {
1030+
if (i.customId === "next" && currentPage < totalPages - 1) {
1031+
currentPage++;
1032+
} else if (i.customId === "prev" && currentPage > 0) {
1033+
currentPage--;
1034+
}
1035+
1036+
await i.update({
1037+
embeds: [getPageEmbed(currentPage)],
1038+
components: [getButtons(currentPage)],
1039+
});
1040+
});
1041+
1042+
collector.on("end", async () => {
1043+
try {
1044+
await interaction.editReply({
1045+
components: [],
1046+
});
1047+
} catch {
1048+
console.error("Failed to edit reply");
1049+
}
1050+
});
9711051
},
9721052
},
9731053
};

0 commit comments

Comments
 (0)