blob: 1b463cfa7aaef4a6071f2f0e30757f65586de7b4 [file] [log] [blame]
Skyler Greyda16adf2023-03-05 10:22:12 +00001import { getCommandMentionByName } from "./../utils/getCommandDataByName.js";
PineaFan0d06edc2023-01-17 22:10:31 +00002import { LoadingEmbed } from "../utils/defaults.js";
pineafan3a02ea32022-08-11 21:35:04 +01003import Discord, {
TheCodedProf21c08592022-09-13 14:14:43 -04004 ActionRowBuilder,
5 ButtonBuilder,
pineafan3a02ea32022-08-11 21:35:04 +01006 MessageComponentInteraction,
pineafan3a02ea32022-08-11 21:35:04 +01007 Guild,
8 CommandInteraction,
9 GuildTextBasedChannel,
10 Message,
PineaFane6ba7882023-01-18 20:41:16 +000011 ButtonStyle,
12 ChannelType
pineafan3a02ea32022-08-11 21:35:04 +010013} from "discord.js";
pineafan813bdf42022-07-24 10:39:10 +010014import EmojiEmbed from "../utils/generateEmojiEmbed.js";
15import getEmojiByName from "../utils/getEmojiByName.js";
16import createPageIndicator from "../utils/createPageIndicator.js";
PineaFane6ba7882023-01-18 20:41:16 +000017import { Embed } from "../utils/defaults.js";
pineafan813bdf42022-07-24 10:39:10 +010018
pineafandef38a72023-05-28 12:47:36 +010019export default async (guild: Guild | null, interaction?: CommandInteraction) => {
PineaFand471ccd2023-01-26 20:48:40 +000020 let m: Message;
pineafandef38a72023-05-28 12:47:36 +010021 if (guild) {
22 let c: GuildTextBasedChannel | null = guild.publicUpdatesChannel ? guild.publicUpdatesChannel : guild.systemChannel;
23 c = c
24 ? c
25 : (guild.channels.cache.find(
26 (ch) =>
27 [
28 ChannelType.GuildText,
29 ChannelType.GuildAnnouncement,
30 ChannelType.PublicThread,
31 ChannelType.PrivateThread,
32 ChannelType.AnnouncementThread
33 ].includes(ch.type) &&
34 ch.permissionsFor(guild.roles.everyone).has("SendMessages") &&
35 ch.permissionsFor(guild.members.me!).has("EmbedLinks")
36 ) as GuildTextBasedChannel | undefined) ?? null;
37 if (interaction) c = interaction.channel as GuildTextBasedChannel;
38 if (!c) {
39 return;
40 }
41 if (interaction) {
42 m = (await interaction.reply({
43 embeds: LoadingEmbed,
44 fetchReply: true,
45 ephemeral: true
46 })) as Message;
47 } else {
48 m = await c.send({ embeds: LoadingEmbed });
49 }
PineaFand471ccd2023-01-26 20:48:40 +000050 } else {
pineafandef38a72023-05-28 12:47:36 +010051 if (interaction) {
52 m = (await interaction.reply({
53 embeds: LoadingEmbed,
54 fetchReply: true,
55 ephemeral: true
56 })) as Message;
57 } else {
58 return;
59 }
PineaFand471ccd2023-01-26 20:48:40 +000060 }
61 let page = 0;
pineafan63fc5e22022-08-04 22:04:10 +010062 const pages = [
pineafan813bdf42022-07-24 10:39:10 +010063 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +010064 .setEmbed(
65 new EmojiEmbed()
66 .setTitle("Welcome to Nucleus")
67 .setDescription(
PineaFand471ccd2023-01-26 20:48:40 +000068 "Thanks for adding Nucleus to your server!\n\n" +
69 "The next few pages will show what features Nucleus has to offer, and how to enable them.\n\n" +
70 "If you need support, have questions or want features, you can let us know in [Clicks](https://discord.gg/bPaNnxe)!"
Skyler Grey75ea9172022-08-06 10:22:23 +010071 )
72 .setEmoji("NUCLEUS.LOGO")
73 .setStatus("Danger")
74 )
75 .setTitle("Welcome")
76 .setDescription("About Nucleus")
77 .setPageId(0),
pineafan813bdf42022-07-24 10:39:10 +010078 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +010079 .setEmbed(
80 new EmojiEmbed()
PineaFand471ccd2023-01-26 20:48:40 +000081 .setTitle("Logs")
Skyler Grey75ea9172022-08-06 10:22:23 +010082 .setDescription(
83 "Nucleus can log server events and keep you informed with what content is being posted to your server.\n" +
84 "We have 2 different types of logs, which each can be configured to send to a channel of your choice:\n" +
PineaFand471ccd2023-01-26 20:48:40 +000085 "**General:** These are events like kicks and channel changes etc.\n" +
Skyler Greyda16adf2023-03-05 10:22:12 +000086 `> These are standard logs and can be set with ${getCommandMentionByName(
87 "settings/logs/general"
88 )}\n` +
PineaFand471ccd2023-01-26 20:48:40 +000089 "**Warnings:** Warnings like NSFW avatars and spam etc. that may require action by a server staff member.\n" +
Skyler Greyda16adf2023-03-05 10:22:12 +000090 `> These may require special action by a moderator. You can set the channel with ${getCommandMentionByName(
91 "settings/logs/warnings"
92 )}\n` +
PineaFand471ccd2023-01-26 20:48:40 +000093 "**Attachments:** All images sent in the server - Used to keep a record of deleted images\n" +
Skyler Greyda16adf2023-03-05 10:22:12 +000094 `> Sent to a separate log channel to avoid spam. This can be set with ${getCommandMentionByName(
95 "settings/logs/attachments"
96 )}\n` +
97 `> ${getEmojiByName(
98 "NUCLEUS.PREMIUM"
99 )} Please note this feature is only available with ${getCommandMentionByName(
100 "nucleus/premium"
101 )}`
Skyler Grey75ea9172022-08-06 10:22:23 +0100102 )
103 .setEmoji("ICONS.LOGGING")
104 .setStatus("Danger")
105 )
106 .setTitle("Logging")
107 .setDescription("Logging, staff warning logs etc.")
108 .setPageId(1),
pineafan813bdf42022-07-24 10:39:10 +0100109 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +0100110 .setEmbed(
111 new EmojiEmbed()
112 .setTitle("Moderation")
113 .setDescription(
114 "Nucleus has a number of commands that can be used to moderate your server.\n" +
Skyler Greyda16adf2023-03-05 10:22:12 +0000115 `These commands are all found under ${getCommandMentionByName(
116 "mod"
117 )}, and they include:\n` +
118 `${getEmojiByName("PUNISH.WARN.YELLOW")} ${getCommandMentionByName(
119 "mod/warn"
120 )}: The user is warned (via DM) that they violated server rules. More options given if DMs are disabled.\n` +
121 `${getEmojiByName("PUNISH.CLEARHISTORY")} ${getCommandMentionByName(
122 "mod/purge"
123 )}: Deletes messages in a channel, giving options to only delete messages by a certain user.\n` +
124 `${getEmojiByName("PUNISH.MUTE.YELLOW")} ${getCommandMentionByName(
125 "mod/mute"
126 )}: Stops users sending messages or joining voice chats.\n` +
127 `${getEmojiByName("PUNISH.MUTE.GREEN")} ${getCommandMentionByName(
128 "mod/unmute"
129 )}: Allows user to send messages and join voice chats.\n` +
130 `${getEmojiByName("PUNISH.KICK.RED")} ${getCommandMentionByName(
131 "mod/kick"
132 )}: Removes a member from the server. They will be able to rejoin.\n` +
133 `${getEmojiByName("PUNISH.SOFTBAN")} ${getCommandMentionByName(
134 "mod/softban"
135 )}: Kicks the user, deleting their messages from every channel in a given time frame.\n` +
136 `${getEmojiByName("PUNISH.BAN.RED")} ${getCommandMentionByName(
137 "mod/ban"
138 )}: Removes the user from the server, deleting messages from every channel and stops them from rejoining.\n` +
139 `${getEmojiByName("PUNISH.BAN.GREEN")} ${getCommandMentionByName(
140 "mod/unban"
141 )}: Allows a member to rejoin the server after being banned.`
Skyler Grey75ea9172022-08-06 10:22:23 +0100142 )
143 .setEmoji("PUNISH.BAN.RED")
144 .setStatus("Danger")
145 )
146 .setTitle("Moderation")
147 .setDescription("Basic moderation commands")
148 .setPageId(2),
pineafan813bdf42022-07-24 10:39:10 +0100149 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +0100150 .setEmbed(
151 new EmojiEmbed()
152 .setTitle("Verify")
153 .setDescription(
154 "Nucleus has a verification system that allows users to prove they aren't bots.\n" +
Skyler Greyda16adf2023-03-05 10:22:12 +0000155 `This is done by running ${getCommandMentionByName(
156 "verify"
157 )} which sends a message only the user can see, giving them a link to a website to verify.\n` +
PineaFand471ccd2023-01-26 20:48:40 +0000158 "After the user complete's the check, they are given a role, which can be set to unlock specific channels.\n" +
TheCodedProff86ba092023-01-27 17:10:07 -0500159 `You can set the role given with ${getCommandMentionByName("settings/verify")}`
Skyler Grey75ea9172022-08-06 10:22:23 +0100160 )
161 .setEmoji("CONTROL.REDTICK")
162 .setStatus("Danger")
163 )
164 .setTitle("Verify")
165 .setDescription("Captcha verification system")
166 .setPageId(3),
pineafan813bdf42022-07-24 10:39:10 +0100167 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +0100168 .setEmbed(
169 new EmojiEmbed()
170 .setTitle("Content Scanning")
171 .setDescription(
172 "Nucleus has a content scanning system that automatically scans links and images sent by users.\n" +
PineaFand471ccd2023-01-26 20:48:40 +0000173 "The staff team can be notified when an NSFW image is detected, or malicious links are sent.\n" +
Skyler Greyda16adf2023-03-05 10:22:12 +0000174 `You can check and manage what to moderate in ${getCommandMentionByName(
175 "settings/automod"
176 )}`
Skyler Grey75ea9172022-08-06 10:22:23 +0100177 )
178 .setEmoji("MOD.IMAGES.TOOSMALL")
179 .setStatus("Danger")
180 )
181 .setTitle("Content Scanning")
182 .setDescription("Content (NSFW, malware, scams) scanning")
183 .setPageId(4),
pineafan813bdf42022-07-24 10:39:10 +0100184 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +0100185 .setEmbed(
186 new EmojiEmbed()
187 .setTitle("Tickets")
188 .setDescription(
PineaFand471ccd2023-01-26 20:48:40 +0000189 "Nucleus has a ticket system which allows users to create tickets and talk to the server staff or support team.\n" +
Skyler Greyda16adf2023-03-05 10:22:12 +0000190 `Tickets can be created by users with ${getCommandMentionByName(
191 "ticket/create"
192 )}, or by clicking a button created by moderators.\n` +
PineaFand471ccd2023-01-26 20:48:40 +0000193 `After being created, a new channel or thread is created, and the user and support team are pinged. \n` +
Skyler Greyda16adf2023-03-05 10:22:12 +0000194 `The category or channel to create threads in can be set with ${getCommandMentionByName(
195 "settings/tickets"
196 )}\n` +
197 `When the ticket is resolved, anyone can run ${getCommandMentionByName(
198 "ticket/close"
199 )} (or click the button) to close it.\n` +
TheCodedProff86ba092023-01-27 17:10:07 -0500200 `Running ${getCommandMentionByName("ticket/close")} again will delete the ticket.`
Skyler Grey75ea9172022-08-06 10:22:23 +0100201 )
202 .setEmoji("GUILD.TICKET.CLOSE")
203 .setStatus("Danger")
204 )
205 .setTitle("Tickets")
206 .setDescription("Ticket system")
207 .setPageId(5),
pineafan813bdf42022-07-24 10:39:10 +0100208 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +0100209 .setEmbed(
210 new EmojiEmbed()
211 .setTitle("Tags")
212 .setDescription(
PineaFand471ccd2023-01-26 20:48:40 +0000213 "Nucleus allows you to create tags, which allow a message to be sent when a specific tag is typed.\n" +
Skyler Greyda16adf2023-03-05 10:22:12 +0000214 `Tags can be created with ${getCommandMentionByName(
215 "tags/create"
216 )}, and can be edited with ${getCommandMentionByName("tags/edit")}\n` +
217 `Tags can be deleted with ${getCommandMentionByName(
218 "tags/delete"
219 )}, and can be listed with ${getCommandMentionByName("tags/list")}\n` +
TheCodedProff86ba092023-01-27 17:10:07 -0500220 `To use a tag, you can type ${getCommandMentionByName("tag")}, followed by the tag to send`
Skyler Grey75ea9172022-08-06 10:22:23 +0100221 )
222 .setEmoji("PUNISH.NICKNAME.RED")
223 .setStatus("Danger")
224 )
225 .setTitle("Tags")
226 .setDescription("Tag system")
227 .setPageId(6),
pineafan813bdf42022-07-24 10:39:10 +0100228 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +0100229 .setEmbed(
230 new EmojiEmbed()
231 .setTitle("Premium")
232 .setDescription(
PineaFand471ccd2023-01-26 20:48:40 +0000233 "Nucleus Premium allows you to use extra features in your server, which are useful but not essential.\n" +
Skyler Greyda16adf2023-03-05 10:22:12 +0000234 "**No currently free commands will become premium features.**\n" +
235 "Premium features include creating ticket transcripts and attachment logs.\n\n" +
236 "Premium can be purchased in [our server](https://discord.gg/bPaNnxe) in the subscriptions page" // TODO: add a table graphic
Skyler Grey75ea9172022-08-06 10:22:23 +0100237 )
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500238 .setEmoji("NUCLEUS.PREMIUM")
Skyler Grey75ea9172022-08-06 10:22:23 +0100239 .setStatus("Danger")
240 )
241 .setTitle("Premium")
242 .setDescription("Premium features")
243 .setPageId(7)
pineafan63fc5e22022-08-04 22:04:10 +0100244 ];
pineafan813bdf42022-07-24 10:39:10 +0100245
PineaFan0d06edc2023-01-17 22:10:31 +0000246 const publicFilter = async (component: MessageComponentInteraction) => {
PineaFane6ba7882023-01-18 20:41:16 +0000247 return (component.member as Discord.GuildMember).permissions.has("ManageGuild");
pineafan63fc5e22022-08-04 22:04:10 +0100248 };
pineafan813bdf42022-07-24 10:39:10 +0100249
250 let selectPaneOpen = false;
251
Skyler Greyf21323a2022-08-13 23:58:22 +0100252 let cancelled = false;
253 let timedOut = false;
254 while (!cancelled && !timedOut) {
PineaFane6ba7882023-01-18 20:41:16 +0000255 let selectPane: ActionRowBuilder<Discord.StringSelectMenuBuilder | ButtonBuilder>[] = [];
pineafan813bdf42022-07-24 10:39:10 +0100256
257 if (selectPaneOpen) {
PineaFane6ba7882023-01-18 20:41:16 +0000258 const options: Discord.StringSelectMenuOptionBuilder[] = [];
Skyler Grey75ea9172022-08-06 10:22:23 +0100259 pages.forEach((embed) => {
Skyler Greyda16adf2023-03-05 10:22:12 +0000260 options.push(
261 new Discord.StringSelectMenuOptionBuilder()
262 .setLabel(embed.title)
263 .setValue(embed.pageId.toString())
264 .setDescription(embed.description || "")
PineaFane6ba7882023-01-18 20:41:16 +0000265 );
pineafan63fc5e22022-08-04 22:04:10 +0100266 });
Skyler Grey75ea9172022-08-06 10:22:23 +0100267 selectPane = [
PineaFane6ba7882023-01-18 20:41:16 +0000268 new ActionRowBuilder<Discord.StringSelectMenuBuilder>().addComponents([
269 new Discord.StringSelectMenuBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100270 .addOptions(options)
271 .setCustomId("page")
272 .setMaxValues(1)
273 .setPlaceholder("Choose a page...")
274 ])
275 ];
pineafan813bdf42022-07-24 10:39:10 +0100276 }
PineaFane6ba7882023-01-18 20:41:16 +0000277 const components: ActionRowBuilder<ButtonBuilder | Discord.StringSelectMenuBuilder>[] = selectPane.concat([
278 new ActionRowBuilder<ButtonBuilder>().addComponents(
TheCodedProf21c08592022-09-13 14:14:43 -0400279 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100280 .setCustomId("left")
281 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
TheCodedProf21c08592022-09-13 14:14:43 -0400282 .setStyle(ButtonStyle.Secondary)
Skyler Grey75ea9172022-08-06 10:22:23 +0100283 .setDisabled(page === 0),
TheCodedProf21c08592022-09-13 14:14:43 -0400284 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100285 .setCustomId("select")
286 .setEmoji(getEmojiByName("CONTROL.MENU", "id"))
TheCodedProf21c08592022-09-13 14:14:43 -0400287 .setStyle(selectPaneOpen ? ButtonStyle.Primary : ButtonStyle.Secondary)
Skyler Grey75ea9172022-08-06 10:22:23 +0100288 .setDisabled(false),
TheCodedProf21c08592022-09-13 14:14:43 -0400289 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100290 .setCustomId("right")
291 .setEmoji(getEmojiByName("CONTROL.RIGHT", "id"))
TheCodedProf21c08592022-09-13 14:14:43 -0400292 .setStyle(ButtonStyle.Secondary)
Skyler Grey75ea9172022-08-06 10:22:23 +0100293 .setDisabled(page === pages.length - 1)
PineaFane6ba7882023-01-18 20:41:16 +0000294 )
Skyler Grey75ea9172022-08-06 10:22:23 +0100295 ]);
pineafan813bdf42022-07-24 10:39:10 +0100296 if (interaction) {
TheCodedProf21c08592022-09-13 14:14:43 -0400297 const em = new Discord.EmbedBuilder(pages[page]!.embed);
PineaFane6ba7882023-01-18 20:41:16 +0000298 em.setDescription(em.data.description + "\n\n" + createPageIndicator(pages.length, page));
pineafan813bdf42022-07-24 10:39:10 +0100299 await interaction.editReply({
300 embeds: [em],
301 components: components
302 });
303 } else {
TheCodedProf21c08592022-09-13 14:14:43 -0400304 const em = new Discord.EmbedBuilder(pages[page]!.embed);
PineaFane6ba7882023-01-18 20:41:16 +0000305 em.setDescription(em.data.description + "\n\n" + createPageIndicator(pages.length, page));
pineafan3a02ea32022-08-11 21:35:04 +0100306 (await m.edit({
pineafan813bdf42022-07-24 10:39:10 +0100307 embeds: [em],
pineafan3a02ea32022-08-11 21:35:04 +0100308 components: components
309 })) as Message;
pineafan813bdf42022-07-24 10:39:10 +0100310 }
pineafan63fc5e22022-08-04 22:04:10 +0100311 let i;
pineafan813bdf42022-07-24 10:39:10 +0100312 try {
Skyler Grey75ea9172022-08-06 10:22:23 +0100313 i = await m.awaitMessageComponent({
314 filter: interaction
Skyler Greyda16adf2023-03-05 10:22:12 +0000315 ? (i) => {
316 return i.user.id === interaction.user.id && i.channel!.id === interaction.channel!.id;
317 }
PineaFan0d06edc2023-01-17 22:10:31 +0000318 : publicFilter,
Skyler Grey75ea9172022-08-06 10:22:23 +0100319 time: 300000
320 });
321 } catch (e) {
Skyler Greyf21323a2022-08-13 23:58:22 +0100322 timedOut = true;
323 continue;
Skyler Grey75ea9172022-08-06 10:22:23 +0100324 }
TheCodedProf267563a2023-01-21 17:00:57 -0500325 await i.deferUpdate();
pineafan3a02ea32022-08-11 21:35:04 +0100326 if (!("customId" in i.component)) {
327 continue;
328 } else if (i.component.customId === "left") {
pineafan813bdf42022-07-24 10:39:10 +0100329 if (page > 0) page--;
330 selectPaneOpen = false;
pineafane23c4ec2022-07-27 21:56:27 +0100331 } else if (i.component.customId === "right") {
pineafan813bdf42022-07-24 10:39:10 +0100332 if (page < pages.length - 1) page++;
333 selectPaneOpen = false;
pineafane23c4ec2022-07-27 21:56:27 +0100334 } else if (i.component.customId === "select") {
pineafan813bdf42022-07-24 10:39:10 +0100335 selectPaneOpen = !selectPaneOpen;
TheCodedProf4a6d5712023-01-19 15:54:40 -0500336 } else if (i.isStringSelectMenu() && i.component.customId === "page") {
337 page = parseInt(i.values[0]!);
pineafan813bdf42022-07-24 10:39:10 +0100338 selectPaneOpen = false;
339 } else {
Skyler Greyf21323a2022-08-13 23:58:22 +0100340 cancelled = true;
pineafan813bdf42022-07-24 10:39:10 +0100341 }
342 }
Skyler Greyf21323a2022-08-13 23:58:22 +0100343 if (timedOut) {
344 if (interaction) {
TheCodedProf21c08592022-09-13 14:14:43 -0400345 const em = new Discord.EmbedBuilder(pages[page]!.embed);
PineaFane6ba7882023-01-18 20:41:16 +0000346 em.setDescription(em.data.description + "\n\n" + createPageIndicator(pages.length, page)).setFooter({
Skyler Greyf21323a2022-08-13 23:58:22 +0100347 text: "Message timed out"
348 });
349 await interaction.editReply({
350 embeds: [em],
351 components: []
352 });
353 } else {
TheCodedProf21c08592022-09-13 14:14:43 -0400354 const em = new Discord.EmbedBuilder(pages[page]!.embed);
PineaFane6ba7882023-01-18 20:41:16 +0000355 em.setDescription(em.data.description + "\n\n" + createPageIndicator(pages.length, page)).setFooter({
Skyler Greyf21323a2022-08-13 23:58:22 +0100356 text: "Message timed out"
357 });
358 await m.edit({
359 embeds: [em],
360 components: []
361 });
362 }
pineafan813bdf42022-07-24 10:39:10 +0100363 } else {
Skyler Greyf21323a2022-08-13 23:58:22 +0100364 if (interaction) {
TheCodedProf21c08592022-09-13 14:14:43 -0400365 const em = new Discord.EmbedBuilder(pages[page]!.embed);
PineaFane6ba7882023-01-18 20:41:16 +0000366 em.setDescription(em.data.description + "\n\n" + createPageIndicator(pages.length, page));
Skyler Greyf21323a2022-08-13 23:58:22 +0100367 em.setFooter({ text: "Message closed" });
Skyler Greyf4f21c42023-03-08 14:36:29 +0000368 await interaction.editReply({
Skyler Greyf21323a2022-08-13 23:58:22 +0100369 embeds: [em],
370 components: []
371 });
372 } else {
Skyler Greyf4f21c42023-03-08 14:36:29 +0000373 await m.delete();
Skyler Greyf21323a2022-08-13 23:58:22 +0100374 }
pineafan813bdf42022-07-24 10:39:10 +0100375 }
pineafan63fc5e22022-08-04 22:04:10 +0100376};