blob: 3971ad90c75175074722dfcd1e265866e3dc2e4d [file] [log] [blame]
PineaFan0d06edc2023-01-17 22:10:31 +00001import { LoadingEmbed } from "../utils/defaults.js";
pineafan3a02ea32022-08-11 21:35:04 +01002import Discord, {
TheCodedProf21c08592022-09-13 14:14:43 -04003 ActionRowBuilder,
4 ButtonBuilder,
pineafan3a02ea32022-08-11 21:35:04 +01005 MessageComponentInteraction,
pineafan3a02ea32022-08-11 21:35:04 +01006 Guild,
7 CommandInteraction,
8 GuildTextBasedChannel,
9 Message,
PineaFane6ba7882023-01-18 20:41:16 +000010 ButtonStyle,
11 ChannelType
pineafan3a02ea32022-08-11 21:35:04 +010012} from "discord.js";
pineafan813bdf42022-07-24 10:39:10 +010013import EmojiEmbed from "../utils/generateEmojiEmbed.js";
14import getEmojiByName from "../utils/getEmojiByName.js";
15import createPageIndicator from "../utils/createPageIndicator.js";
PineaFane6ba7882023-01-18 20:41:16 +000016import { Embed } from "../utils/defaults.js";
pineafan813bdf42022-07-24 10:39:10 +010017
pineafan3a02ea32022-08-11 21:35:04 +010018export default async (guild: Guild, interaction?: CommandInteraction) => {
19 let c: GuildTextBasedChannel | null = guild.publicUpdatesChannel ? guild.publicUpdatesChannel : guild.systemChannel;
Skyler Grey75ea9172022-08-06 10:22:23 +010020 c = c
21 ? c
pineafan3a02ea32022-08-11 21:35:04 +010022 : (guild.channels.cache.find(
Skyler Grey75ea9172022-08-06 10:22:23 +010023 (ch) =>
pineafan3a02ea32022-08-11 21:35:04 +010024 [
PineaFane6ba7882023-01-18 20:41:16 +000025 ChannelType.GuildText,
26 ChannelType.GuildAnnouncement,
27 ChannelType.PublicThread,
28 ChannelType.PrivateThread,
29 ChannelType.AnnouncementThread
pineafan3a02ea32022-08-11 21:35:04 +010030 ].includes(ch.type) &&
PineaFane6ba7882023-01-18 20:41:16 +000031 ch.permissionsFor(guild.roles.everyone).has("SendMessages") &&
32 ch.permissionsFor(guild.members.me!).has("EmbedLinks")
pineafan3a02ea32022-08-11 21:35:04 +010033 ) as GuildTextBasedChannel | undefined) ?? null;
34 if (interaction) c = interaction.channel as GuildTextBasedChannel;
35 if (!c) {
36 return;
37 }
pineafan63fc5e22022-08-04 22:04:10 +010038 const pages = [
pineafan813bdf42022-07-24 10:39:10 +010039 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +010040 .setEmbed(
41 new EmojiEmbed()
42 .setTitle("Welcome to Nucleus")
43 .setDescription(
44 "Thanks for adding Nucleus to your server\n\n" +
45 "On the next few pages you can find instructions on getting started, and commands you may want to set up\n\n" +
46 "If you need support, have questions or want features, you can let us know in [Clicks](https://discord.gg/bPaNnxe)"
47 )
48 .setEmoji("NUCLEUS.LOGO")
49 .setStatus("Danger")
50 )
51 .setTitle("Welcome")
52 .setDescription("About Nucleus")
53 .setPageId(0),
pineafan813bdf42022-07-24 10:39:10 +010054 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +010055 .setEmbed(
56 new EmojiEmbed()
57 .setTitle("Logging")
58 .setDescription(
59 "Nucleus can log server events and keep you informed with what content is being posted to your server.\n" +
60 "We have 2 different types of logs, which each can be configured to send to a channel of your choice:\n" +
61 "**General Logs:** These are events like kicks and channel changes etc.\n" +
62 "**Warning Logs:** Warnings like NSFW avatars and spam etc. that may require action by a server staff member. " +
63 "These go to to a separate staff notifications channel.\n\n" +
64 "A general log channel can be set with `/settings log`\n" +
65 "A warning log channel can be set with `/settings warnings channel`"
66 )
67 .setEmoji("ICONS.LOGGING")
68 .setStatus("Danger")
69 )
70 .setTitle("Logging")
71 .setDescription("Logging, staff warning logs etc.")
72 .setPageId(1),
pineafan813bdf42022-07-24 10:39:10 +010073 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +010074 .setEmbed(
75 new EmojiEmbed()
76 .setTitle("Moderation")
77 .setDescription(
78 "Nucleus has a number of commands that can be used to moderate your server.\n" +
79 "These commands are all found under `/mod`, and they include:\n" +
80 `**${getEmojiByName(
81 "PUNISH.WARN.YELLOW"
82 )} Warn:** The user is warned (via DM) that they violated server rules.\n` +
83 `**${getEmojiByName(
84 "PUNISH.CLEARHISTORY"
85 )} Clear:** Some messages from a user are deleted in a channel.\n` +
86 `**${getEmojiByName(
87 "PUNISH.MUTE.YELLOW"
88 )} Mute:** The user is unable to send messages or join voice chats.\n` +
89 `**${getEmojiByName(
90 "PUNISH.MUTE.GREEN"
91 )} Unmute:** The user is able to send messages in the server.\n` +
Skyler Grey11236ba2022-08-08 21:13:33 +010092 `**${getEmojiByName("PUNISH.KICK.RED")} Kick:** The user is removed from the server.\n` +
Skyler Grey75ea9172022-08-06 10:22:23 +010093 `**${getEmojiByName(
94 "PUNISH.SOFTBAN"
95 )} Softban:** Kicks the user, deleting their messages from every channel.\n` +
96 `**${getEmojiByName(
97 "PUNISH.BAN.RED"
98 )} Ban:** The user is removed from the server, and they are unable to rejoin.\n` +
Skyler Grey11236ba2022-08-08 21:13:33 +010099 `**${getEmojiByName("PUNISH.BAN.GREEN")} Unban:** The user is able to rejoin the server.`
Skyler Grey75ea9172022-08-06 10:22:23 +0100100 )
101 .setEmoji("PUNISH.BAN.RED")
102 .setStatus("Danger")
103 )
104 .setTitle("Moderation")
105 .setDescription("Basic moderation commands")
106 .setPageId(2),
pineafan813bdf42022-07-24 10:39:10 +0100107 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +0100108 .setEmbed(
109 new EmojiEmbed()
110 .setTitle("Verify")
111 .setDescription(
112 "Nucleus has a verification system that allows users to prove they aren't bots.\n" +
113 "This is done by running `/verify` which sends a message only the user can see, giving them a link to a CAPTCHA to verify.\n" +
114 "After the user complete's the CAPTCHA, they are given a role and can use the permissions accordingly.\n" +
115 "You can set the role given with `/settings verify`"
116 )
117 .setEmoji("CONTROL.REDTICK")
118 .setStatus("Danger")
119 )
120 .setTitle("Verify")
121 .setDescription("Captcha verification system")
122 .setPageId(3),
pineafan813bdf42022-07-24 10:39:10 +0100123 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +0100124 .setEmbed(
125 new EmojiEmbed()
126 .setTitle("Content Scanning")
127 .setDescription(
128 "Nucleus has a content scanning system that automatically scans links and images sent by users.\n" +
129 "Nucleus can detect, delete, and punish users for sending NSFW content, or links to scam or adult sites.\n" +
130 "You can set the threshold for this in `/settings automation`" // TODO
131 )
132 .setEmoji("MOD.IMAGES.TOOSMALL")
133 .setStatus("Danger")
134 )
135 .setTitle("Content Scanning")
136 .setDescription("Content (NSFW, malware, scams) scanning")
137 .setPageId(4),
pineafan813bdf42022-07-24 10:39:10 +0100138 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +0100139 .setEmbed(
140 new EmojiEmbed()
141 .setTitle("Tickets")
142 .setDescription(
143 "Nucleus has a ticket system that allows users to create tickets and have a support team respond to them.\n" +
144 "Tickets can be created with `/ticket create` and a channel is created, pinging the user and support role.\n" +
145 "When the ticket is resolved, anyone can run `/ticket close` (or click the button) to close it.\n" +
146 "Running `/ticket close` again will delete the ticket."
147 )
148 .setEmoji("GUILD.TICKET.CLOSE")
149 .setStatus("Danger")
150 )
151 .setTitle("Tickets")
152 .setDescription("Ticket system")
153 .setPageId(5),
pineafan813bdf42022-07-24 10:39:10 +0100154 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +0100155 .setEmbed(
156 new EmojiEmbed()
157 .setTitle("Tags")
158 .setDescription(
159 "Add a tag system to your server with the `/tag` and `/tags` commands.\n" +
160 "To create a tag, type `/tags create <tag name> <tag content>`.\n" +
161 "Tag names and content can be edited with `/tags edit`.\n" +
162 "To delete a tag, type `/tags delete <tag name>`.\n" +
163 "To view all tags, type `/tags list`.\n"
164 )
165 .setEmoji("PUNISH.NICKNAME.RED")
166 .setStatus("Danger")
167 )
168 .setTitle("Tags")
169 .setDescription("Tag system")
170 .setPageId(6),
pineafan813bdf42022-07-24 10:39:10 +0100171 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +0100172 .setEmbed(
173 new EmojiEmbed()
174 .setTitle("Premium")
175 .setDescription(
176 "In the near future, we will be releasing extra premium only features.\n" +
177 "These features will include:\n\n" +
178 "**Attachment logs**\n> When a message with attachments is edited or deleted, the logs will also include the images sent.\n" +
179 "\nPremium is not yet available. Check `/nucleus premium` for updates on features and pricing"
180 )
181 .setEmoji("NUCLEUS.COMMANDS.LOCK")
182 .setStatus("Danger")
183 )
184 .setTitle("Premium")
185 .setDescription("Premium features")
186 .setPageId(7)
pineafan63fc5e22022-08-04 22:04:10 +0100187 ];
pineafan3a02ea32022-08-11 21:35:04 +0100188 let m: Message;
Skyler Grey75ea9172022-08-06 10:22:23 +0100189 if (interaction) {
pineafan3a02ea32022-08-11 21:35:04 +0100190 m = (await interaction.reply({
Skyler Grey75ea9172022-08-06 10:22:23 +0100191 embeds: LoadingEmbed,
192 fetchReply: true,
193 ephemeral: true
pineafan3a02ea32022-08-11 21:35:04 +0100194 })) as Message;
Skyler Grey75ea9172022-08-06 10:22:23 +0100195 } else {
196 m = await c.send({ embeds: LoadingEmbed });
197 }
pineafan813bdf42022-07-24 10:39:10 +0100198 let page = 0;
199
PineaFan0d06edc2023-01-17 22:10:31 +0000200 const publicFilter = async (component: MessageComponentInteraction) => {
PineaFane6ba7882023-01-18 20:41:16 +0000201 return (component.member as Discord.GuildMember).permissions.has("ManageGuild");
pineafan63fc5e22022-08-04 22:04:10 +0100202 };
pineafan813bdf42022-07-24 10:39:10 +0100203
204 let selectPaneOpen = false;
205
Skyler Greyf21323a2022-08-13 23:58:22 +0100206 let cancelled = false;
207 let timedOut = false;
208 while (!cancelled && !timedOut) {
PineaFane6ba7882023-01-18 20:41:16 +0000209 let selectPane: ActionRowBuilder<Discord.StringSelectMenuBuilder | ButtonBuilder>[] = [];
pineafan813bdf42022-07-24 10:39:10 +0100210
211 if (selectPaneOpen) {
PineaFane6ba7882023-01-18 20:41:16 +0000212 const options: Discord.StringSelectMenuOptionBuilder[] = [];
Skyler Grey75ea9172022-08-06 10:22:23 +0100213 pages.forEach((embed) => {
PineaFane6ba7882023-01-18 20:41:16 +0000214 options.push(new Discord.StringSelectMenuOptionBuilder()
215 .setLabel(embed.title)
216 .setValue(embed.pageId.toString())
217 .setDescription(embed.description || "")
218 );
pineafan63fc5e22022-08-04 22:04:10 +0100219 });
Skyler Grey75ea9172022-08-06 10:22:23 +0100220 selectPane = [
PineaFane6ba7882023-01-18 20:41:16 +0000221 new ActionRowBuilder<Discord.StringSelectMenuBuilder>().addComponents([
222 new Discord.StringSelectMenuBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100223 .addOptions(options)
224 .setCustomId("page")
225 .setMaxValues(1)
226 .setPlaceholder("Choose a page...")
227 ])
228 ];
pineafan813bdf42022-07-24 10:39:10 +0100229 }
PineaFane6ba7882023-01-18 20:41:16 +0000230 const components: ActionRowBuilder<ButtonBuilder | Discord.StringSelectMenuBuilder>[] = selectPane.concat([
231 new ActionRowBuilder<ButtonBuilder>().addComponents(
TheCodedProf21c08592022-09-13 14:14:43 -0400232 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100233 .setCustomId("left")
234 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
TheCodedProf21c08592022-09-13 14:14:43 -0400235 .setStyle(ButtonStyle.Secondary)
Skyler Grey75ea9172022-08-06 10:22:23 +0100236 .setDisabled(page === 0),
TheCodedProf21c08592022-09-13 14:14:43 -0400237 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100238 .setCustomId("select")
239 .setEmoji(getEmojiByName("CONTROL.MENU", "id"))
TheCodedProf21c08592022-09-13 14:14:43 -0400240 .setStyle(selectPaneOpen ? ButtonStyle.Primary : ButtonStyle.Secondary)
Skyler Grey75ea9172022-08-06 10:22:23 +0100241 .setDisabled(false),
TheCodedProf21c08592022-09-13 14:14:43 -0400242 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100243 .setCustomId("right")
244 .setEmoji(getEmojiByName("CONTROL.RIGHT", "id"))
TheCodedProf21c08592022-09-13 14:14:43 -0400245 .setStyle(ButtonStyle.Secondary)
Skyler Grey75ea9172022-08-06 10:22:23 +0100246 .setDisabled(page === pages.length - 1)
PineaFane6ba7882023-01-18 20:41:16 +0000247 )
Skyler Grey75ea9172022-08-06 10:22:23 +0100248 ]);
pineafan813bdf42022-07-24 10:39:10 +0100249 if (interaction) {
TheCodedProf21c08592022-09-13 14:14:43 -0400250 const em = new Discord.EmbedBuilder(pages[page]!.embed);
PineaFane6ba7882023-01-18 20:41:16 +0000251 em.setDescription(em.data.description + "\n\n" + createPageIndicator(pages.length, page));
pineafan813bdf42022-07-24 10:39:10 +0100252 await interaction.editReply({
253 embeds: [em],
254 components: components
255 });
256 } else {
TheCodedProf21c08592022-09-13 14:14:43 -0400257 const em = new Discord.EmbedBuilder(pages[page]!.embed);
PineaFane6ba7882023-01-18 20:41:16 +0000258 em.setDescription(em.data.description + "\n\n" + createPageIndicator(pages.length, page));
pineafan3a02ea32022-08-11 21:35:04 +0100259 (await m.edit({
pineafan813bdf42022-07-24 10:39:10 +0100260 embeds: [em],
pineafan3a02ea32022-08-11 21:35:04 +0100261 components: components
262 })) as Message;
pineafan813bdf42022-07-24 10:39:10 +0100263 }
pineafan63fc5e22022-08-04 22:04:10 +0100264 let i;
pineafan813bdf42022-07-24 10:39:10 +0100265 try {
Skyler Grey75ea9172022-08-06 10:22:23 +0100266 i = await m.awaitMessageComponent({
267 filter: interaction
PineaFan0d06edc2023-01-17 22:10:31 +0000268 ? (i) => { return i.user.id === interaction.user.id && i.channel!.id === interaction.channel!.id }
269 : publicFilter,
Skyler Grey75ea9172022-08-06 10:22:23 +0100270 time: 300000
271 });
272 } catch (e) {
Skyler Greyf21323a2022-08-13 23:58:22 +0100273 timedOut = true;
274 continue;
Skyler Grey75ea9172022-08-06 10:22:23 +0100275 }
pineafan63fc5e22022-08-04 22:04:10 +0100276 i.deferUpdate();
pineafan3a02ea32022-08-11 21:35:04 +0100277 if (!("customId" in i.component)) {
278 continue;
279 } else if (i.component.customId === "left") {
pineafan813bdf42022-07-24 10:39:10 +0100280 if (page > 0) page--;
281 selectPaneOpen = false;
pineafane23c4ec2022-07-27 21:56:27 +0100282 } else if (i.component.customId === "right") {
pineafan813bdf42022-07-24 10:39:10 +0100283 if (page < pages.length - 1) page++;
284 selectPaneOpen = false;
pineafane23c4ec2022-07-27 21:56:27 +0100285 } else if (i.component.customId === "select") {
pineafan813bdf42022-07-24 10:39:10 +0100286 selectPaneOpen = !selectPaneOpen;
TheCodedProf4a6d5712023-01-19 15:54:40 -0500287 } else if (i.isStringSelectMenu() && i.component.customId === "page") {
288 page = parseInt(i.values[0]!);
pineafan813bdf42022-07-24 10:39:10 +0100289 selectPaneOpen = false;
290 } else {
Skyler Greyf21323a2022-08-13 23:58:22 +0100291 cancelled = true;
pineafan813bdf42022-07-24 10:39:10 +0100292 }
293 }
Skyler Greyf21323a2022-08-13 23:58:22 +0100294 if (timedOut) {
295 if (interaction) {
TheCodedProf21c08592022-09-13 14:14:43 -0400296 const em = new Discord.EmbedBuilder(pages[page]!.embed);
PineaFane6ba7882023-01-18 20:41:16 +0000297 em.setDescription(em.data.description + "\n\n" + createPageIndicator(pages.length, page)).setFooter({
Skyler Greyf21323a2022-08-13 23:58:22 +0100298 text: "Message timed out"
299 });
300 await interaction.editReply({
301 embeds: [em],
302 components: []
303 });
304 } else {
TheCodedProf21c08592022-09-13 14:14:43 -0400305 const em = new Discord.EmbedBuilder(pages[page]!.embed);
PineaFane6ba7882023-01-18 20:41:16 +0000306 em.setDescription(em.data.description + "\n\n" + createPageIndicator(pages.length, page)).setFooter({
Skyler Greyf21323a2022-08-13 23:58:22 +0100307 text: "Message timed out"
308 });
309 await m.edit({
310 embeds: [em],
311 components: []
312 });
313 }
pineafan813bdf42022-07-24 10:39:10 +0100314 } else {
Skyler Greyf21323a2022-08-13 23:58:22 +0100315 if (interaction) {
TheCodedProf21c08592022-09-13 14:14:43 -0400316 const em = new Discord.EmbedBuilder(pages[page]!.embed);
PineaFane6ba7882023-01-18 20:41:16 +0000317 em.setDescription(em.data.description + "\n\n" + createPageIndicator(pages.length, page));
Skyler Greyf21323a2022-08-13 23:58:22 +0100318 em.setFooter({ text: "Message closed" });
319 interaction.editReply({
320 embeds: [em],
321 components: []
322 });
323 } else {
324 m.delete();
325 }
pineafan813bdf42022-07-24 10:39:10 +0100326 }
pineafan63fc5e22022-08-04 22:04:10 +0100327};