blob: ef7b2556449f8f17f0b1017e439d1e20ad491521 [file] [log] [blame]
pineafan63fc5e22022-08-04 22:04:10 +01001import { LoadingEmbed } from "./../utils/defaultEmbeds.js";
pineafan3a02ea32022-08-11 21:35:04 +01002import Discord, {
3 MessageActionRow,
4 MessageButton,
5 MessageComponentInteraction,
6 MessageSelectOptionData,
7 Guild,
8 CommandInteraction,
9 GuildTextBasedChannel,
10 Message,
11 SelectMenuInteraction
12} 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";
pineafan813bdf42022-07-24 10:39:10 +010016
17class Embed {
18 embed: Discord.MessageEmbed;
19 title: string;
pineafan63fc5e22022-08-04 22:04:10 +010020 description = "";
21 pageId = 0;
pineafan3a02ea32022-08-11 21:35:04 +010022
23 constructor() {
24 this.embed = new Discord.MessageEmbed();
25 this.title = "";
26 }
Skyler Grey75ea9172022-08-06 10:22:23 +010027 setEmbed(embed: Discord.MessageEmbed) {
28 this.embed = embed;
29 return this;
30 }
31 setTitle(title: string) {
32 this.title = title;
33 return this;
34 }
35 setDescription(description: string) {
36 this.description = description;
37 return this;
38 }
39 setPageId(pageId: number) {
40 this.pageId = pageId;
41 return this;
42 }
pineafan813bdf42022-07-24 10:39:10 +010043}
44
pineafan3a02ea32022-08-11 21:35:04 +010045export default async (guild: Guild, interaction?: CommandInteraction) => {
46 let c: GuildTextBasedChannel | null = guild.publicUpdatesChannel ? guild.publicUpdatesChannel : guild.systemChannel;
Skyler Grey75ea9172022-08-06 10:22:23 +010047 c = c
48 ? c
pineafan3a02ea32022-08-11 21:35:04 +010049 : (guild.channels.cache.find(
Skyler Grey75ea9172022-08-06 10:22:23 +010050 (ch) =>
pineafan3a02ea32022-08-11 21:35:04 +010051 [
52 "GUILD_TEXT",
53 "GUILD_NEWS",
54 "GUILD_NEWS_THREAD",
55 "GUILD_PRIVATE_THREAD",
56 "GUILD_PUBLIC_THREAD"
57 ].includes(ch.type) &&
Skyler Grey11236ba2022-08-08 21:13:33 +010058 ch.permissionsFor(guild.roles.everyone).has("SEND_MESSAGES") &&
pineafan3a02ea32022-08-11 21:35:04 +010059 ch.permissionsFor(guild.me!).has("EMBED_LINKS")
60 ) as GuildTextBasedChannel | undefined) ?? null;
61 if (interaction) c = interaction.channel as GuildTextBasedChannel;
62 if (!c) {
63 return;
64 }
pineafan63fc5e22022-08-04 22:04:10 +010065 const pages = [
pineafan813bdf42022-07-24 10:39:10 +010066 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +010067 .setEmbed(
68 new EmojiEmbed()
69 .setTitle("Welcome to Nucleus")
70 .setDescription(
71 "Thanks for adding Nucleus to your server\n\n" +
72 "On the next few pages you can find instructions on getting started, and commands you may want to set up\n\n" +
73 "If you need support, have questions or want features, you can let us know in [Clicks](https://discord.gg/bPaNnxe)"
74 )
75 .setEmoji("NUCLEUS.LOGO")
76 .setStatus("Danger")
77 )
78 .setTitle("Welcome")
79 .setDescription("About Nucleus")
80 .setPageId(0),
pineafan813bdf42022-07-24 10:39:10 +010081 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +010082 .setEmbed(
83 new EmojiEmbed()
84 .setTitle("Logging")
85 .setDescription(
86 "Nucleus can log server events and keep you informed with what content is being posted to your server.\n" +
87 "We have 2 different types of logs, which each can be configured to send to a channel of your choice:\n" +
88 "**General Logs:** These are events like kicks and channel changes etc.\n" +
89 "**Warning Logs:** Warnings like NSFW avatars and spam etc. that may require action by a server staff member. " +
90 "These go to to a separate staff notifications channel.\n\n" +
91 "A general log channel can be set with `/settings log`\n" +
92 "A warning log channel can be set with `/settings warnings channel`"
93 )
94 .setEmoji("ICONS.LOGGING")
95 .setStatus("Danger")
96 )
97 .setTitle("Logging")
98 .setDescription("Logging, staff warning logs etc.")
99 .setPageId(1),
pineafan813bdf42022-07-24 10:39:10 +0100100 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +0100101 .setEmbed(
102 new EmojiEmbed()
103 .setTitle("Moderation")
104 .setDescription(
105 "Nucleus has a number of commands that can be used to moderate your server.\n" +
106 "These commands are all found under `/mod`, and they include:\n" +
107 `**${getEmojiByName(
108 "PUNISH.WARN.YELLOW"
109 )} Warn:** The user is warned (via DM) that they violated server rules.\n` +
110 `**${getEmojiByName(
111 "PUNISH.CLEARHISTORY"
112 )} Clear:** Some messages from a user are deleted in a channel.\n` +
113 `**${getEmojiByName(
114 "PUNISH.MUTE.YELLOW"
115 )} Mute:** The user is unable to send messages or join voice chats.\n` +
116 `**${getEmojiByName(
117 "PUNISH.MUTE.GREEN"
118 )} Unmute:** The user is able to send messages in the server.\n` +
Skyler Grey11236ba2022-08-08 21:13:33 +0100119 `**${getEmojiByName("PUNISH.KICK.RED")} Kick:** The user is removed from the server.\n` +
Skyler Grey75ea9172022-08-06 10:22:23 +0100120 `**${getEmojiByName(
121 "PUNISH.SOFTBAN"
122 )} Softban:** Kicks the user, deleting their messages from every channel.\n` +
123 `**${getEmojiByName(
124 "PUNISH.BAN.RED"
125 )} Ban:** The user is removed from the server, and they are unable to rejoin.\n` +
Skyler Grey11236ba2022-08-08 21:13:33 +0100126 `**${getEmojiByName("PUNISH.BAN.GREEN")} Unban:** The user is able to rejoin the server.`
Skyler Grey75ea9172022-08-06 10:22:23 +0100127 )
128 .setEmoji("PUNISH.BAN.RED")
129 .setStatus("Danger")
130 )
131 .setTitle("Moderation")
132 .setDescription("Basic moderation commands")
133 .setPageId(2),
pineafan813bdf42022-07-24 10:39:10 +0100134 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +0100135 .setEmbed(
136 new EmojiEmbed()
137 .setTitle("Verify")
138 .setDescription(
139 "Nucleus has a verification system that allows users to prove they aren't bots.\n" +
140 "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" +
141 "After the user complete's the CAPTCHA, they are given a role and can use the permissions accordingly.\n" +
142 "You can set the role given with `/settings verify`"
143 )
144 .setEmoji("CONTROL.REDTICK")
145 .setStatus("Danger")
146 )
147 .setTitle("Verify")
148 .setDescription("Captcha verification system")
149 .setPageId(3),
pineafan813bdf42022-07-24 10:39:10 +0100150 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +0100151 .setEmbed(
152 new EmojiEmbed()
153 .setTitle("Content Scanning")
154 .setDescription(
155 "Nucleus has a content scanning system that automatically scans links and images sent by users.\n" +
156 "Nucleus can detect, delete, and punish users for sending NSFW content, or links to scam or adult sites.\n" +
157 "You can set the threshold for this in `/settings automation`" // TODO
158 )
159 .setEmoji("MOD.IMAGES.TOOSMALL")
160 .setStatus("Danger")
161 )
162 .setTitle("Content Scanning")
163 .setDescription("Content (NSFW, malware, scams) scanning")
164 .setPageId(4),
pineafan813bdf42022-07-24 10:39:10 +0100165 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +0100166 .setEmbed(
167 new EmojiEmbed()
168 .setTitle("Tickets")
169 .setDescription(
170 "Nucleus has a ticket system that allows users to create tickets and have a support team respond to them.\n" +
171 "Tickets can be created with `/ticket create` and a channel is created, pinging the user and support role.\n" +
172 "When the ticket is resolved, anyone can run `/ticket close` (or click the button) to close it.\n" +
173 "Running `/ticket close` again will delete the ticket."
174 )
175 .setEmoji("GUILD.TICKET.CLOSE")
176 .setStatus("Danger")
177 )
178 .setTitle("Tickets")
179 .setDescription("Ticket system")
180 .setPageId(5),
pineafan813bdf42022-07-24 10:39:10 +0100181 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +0100182 .setEmbed(
183 new EmojiEmbed()
184 .setTitle("Tags")
185 .setDescription(
186 "Add a tag system to your server with the `/tag` and `/tags` commands.\n" +
187 "To create a tag, type `/tags create <tag name> <tag content>`.\n" +
188 "Tag names and content can be edited with `/tags edit`.\n" +
189 "To delete a tag, type `/tags delete <tag name>`.\n" +
190 "To view all tags, type `/tags list`.\n"
191 )
192 .setEmoji("PUNISH.NICKNAME.RED")
193 .setStatus("Danger")
194 )
195 .setTitle("Tags")
196 .setDescription("Tag system")
197 .setPageId(6),
pineafan813bdf42022-07-24 10:39:10 +0100198 new Embed()
Skyler Grey75ea9172022-08-06 10:22:23 +0100199 .setEmbed(
200 new EmojiEmbed()
201 .setTitle("Premium")
202 .setDescription(
203 "In the near future, we will be releasing extra premium only features.\n" +
204 "These features will include:\n\n" +
205 "**Attachment logs**\n> When a message with attachments is edited or deleted, the logs will also include the images sent.\n" +
206 "\nPremium is not yet available. Check `/nucleus premium` for updates on features and pricing"
207 )
208 .setEmoji("NUCLEUS.COMMANDS.LOCK")
209 .setStatus("Danger")
210 )
211 .setTitle("Premium")
212 .setDescription("Premium features")
213 .setPageId(7)
pineafan63fc5e22022-08-04 22:04:10 +0100214 ];
pineafan3a02ea32022-08-11 21:35:04 +0100215 let m: Message;
Skyler Grey75ea9172022-08-06 10:22:23 +0100216 if (interaction) {
pineafan3a02ea32022-08-11 21:35:04 +0100217 m = (await interaction.reply({
Skyler Grey75ea9172022-08-06 10:22:23 +0100218 embeds: LoadingEmbed,
219 fetchReply: true,
220 ephemeral: true
pineafan3a02ea32022-08-11 21:35:04 +0100221 })) as Message;
Skyler Grey75ea9172022-08-06 10:22:23 +0100222 } else {
223 m = await c.send({ embeds: LoadingEmbed });
224 }
pineafan813bdf42022-07-24 10:39:10 +0100225 let page = 0;
226
pineafan3a02ea32022-08-11 21:35:04 +0100227 const f = async (component: MessageComponentInteraction) => {
Skyler Grey11236ba2022-08-08 21:13:33 +0100228 return (component.member as Discord.GuildMember).permissions.has("MANAGE_GUILD");
pineafan63fc5e22022-08-04 22:04:10 +0100229 };
pineafan813bdf42022-07-24 10:39:10 +0100230
231 let selectPaneOpen = false;
232
233 while (true) {
pineafan3a02ea32022-08-11 21:35:04 +0100234 let selectPane: MessageActionRow[] = [];
pineafan813bdf42022-07-24 10:39:10 +0100235
236 if (selectPaneOpen) {
pineafan3a02ea32022-08-11 21:35:04 +0100237 const options: MessageSelectOptionData[] = [];
Skyler Grey75ea9172022-08-06 10:22:23 +0100238 pages.forEach((embed) => {
pineafan3a02ea32022-08-11 21:35:04 +0100239 options.push({
240 label: embed.title,
241 value: embed.pageId.toString(),
242 description: embed.description || ""
243 });
pineafan63fc5e22022-08-04 22:04:10 +0100244 });
Skyler Grey75ea9172022-08-06 10:22:23 +0100245 selectPane = [
246 new MessageActionRow().addComponents([
247 new Discord.MessageSelectMenu()
248 .addOptions(options)
249 .setCustomId("page")
250 .setMaxValues(1)
251 .setPlaceholder("Choose a page...")
252 ])
253 ];
pineafan813bdf42022-07-24 10:39:10 +0100254 }
Skyler Grey75ea9172022-08-06 10:22:23 +0100255 const components = selectPane.concat([
256 new MessageActionRow().addComponents([
257 new MessageButton()
258 .setCustomId("left")
259 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
260 .setStyle("SECONDARY")
261 .setDisabled(page === 0),
262 new MessageButton()
263 .setCustomId("select")
264 .setEmoji(getEmojiByName("CONTROL.MENU", "id"))
265 .setStyle(selectPaneOpen ? "PRIMARY" : "SECONDARY")
266 .setDisabled(false),
267 new MessageButton()
268 .setCustomId("right")
269 .setEmoji(getEmojiByName("CONTROL.RIGHT", "id"))
270 .setStyle("SECONDARY")
271 .setDisabled(page === pages.length - 1)
272 ])
273 ]);
pineafan813bdf42022-07-24 10:39:10 +0100274 if (interaction) {
pineafan3a02ea32022-08-11 21:35:04 +0100275 const em = new Discord.MessageEmbed(pages[page]!.embed);
Skyler Grey11236ba2022-08-08 21:13:33 +0100276 em.setDescription(em.description + "\n\n" + createPageIndicator(pages.length, page));
pineafan813bdf42022-07-24 10:39:10 +0100277 await interaction.editReply({
278 embeds: [em],
279 components: components
280 });
281 } else {
pineafan3a02ea32022-08-11 21:35:04 +0100282 const em = new Discord.MessageEmbed(pages[page]!.embed);
Skyler Grey11236ba2022-08-08 21:13:33 +0100283 em.setDescription(em.description + "\n\n" + createPageIndicator(pages.length, page));
pineafan3a02ea32022-08-11 21:35:04 +0100284 (await m.edit({
pineafan813bdf42022-07-24 10:39:10 +0100285 embeds: [em],
pineafan3a02ea32022-08-11 21:35:04 +0100286 components: components
287 })) as Message;
pineafan813bdf42022-07-24 10:39:10 +0100288 }
pineafan63fc5e22022-08-04 22:04:10 +0100289 let i;
pineafan813bdf42022-07-24 10:39:10 +0100290 try {
Skyler Grey75ea9172022-08-06 10:22:23 +0100291 i = await m.awaitMessageComponent({
292 filter: interaction
293 ? () => {
294 return true;
295 }
296 : f,
297 time: 300000
298 });
299 } catch (e) {
300 break;
301 }
pineafan63fc5e22022-08-04 22:04:10 +0100302 i.deferUpdate();
pineafan3a02ea32022-08-11 21:35:04 +0100303 if (!("customId" in i.component)) {
304 continue;
305 } else if (i.component.customId === "left") {
pineafan813bdf42022-07-24 10:39:10 +0100306 if (page > 0) page--;
307 selectPaneOpen = false;
pineafane23c4ec2022-07-27 21:56:27 +0100308 } else if (i.component.customId === "right") {
pineafan813bdf42022-07-24 10:39:10 +0100309 if (page < pages.length - 1) page++;
310 selectPaneOpen = false;
pineafane23c4ec2022-07-27 21:56:27 +0100311 } else if (i.component.customId === "select") {
pineafan813bdf42022-07-24 10:39:10 +0100312 selectPaneOpen = !selectPaneOpen;
pineafane23c4ec2022-07-27 21:56:27 +0100313 } else if (i.component.customId === "page") {
pineafan3a02ea32022-08-11 21:35:04 +0100314 page = parseInt((i as SelectMenuInteraction).values[0]!);
pineafan813bdf42022-07-24 10:39:10 +0100315 selectPaneOpen = false;
316 } else {
317 if (interaction) {
pineafan3a02ea32022-08-11 21:35:04 +0100318 const em = new Discord.MessageEmbed(pages[page]!.embed);
Skyler Grey11236ba2022-08-08 21:13:33 +0100319 em.setDescription(em.description + "\n\n" + createPageIndicator(pages.length, page));
Skyler Grey75ea9172022-08-06 10:22:23 +0100320 em.setFooter({ text: "Message closed" });
321 interaction.editReply({
322 embeds: [em],
323 components: [
324 new MessageActionRow().addComponents([
325 new MessageButton()
326 .setCustomId("left")
327 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
328 .setStyle("SECONDARY")
329 .setDisabled(true),
330 new MessageButton()
331 .setCustomId("select")
332 .setEmoji(getEmojiByName("CONTROL.MENU", "id"))
Skyler Grey11236ba2022-08-08 21:13:33 +0100333 .setStyle(selectPaneOpen ? "PRIMARY" : "SECONDARY")
Skyler Grey75ea9172022-08-06 10:22:23 +0100334 .setDisabled(true),
335 new MessageButton()
336 .setCustomId("right")
337 .setEmoji(getEmojiByName("CONTROL.RIGHT", "id"))
338 .setStyle("SECONDARY")
339 .setDisabled(true)
340 ])
341 ]
342 });
pineafan813bdf42022-07-24 10:39:10 +0100343 } else {
344 m.delete();
345 }
346 return;
347 }
348 }
pineafan813bdf42022-07-24 10:39:10 +0100349 if (interaction) {
pineafan3a02ea32022-08-11 21:35:04 +0100350 const em = new Discord.MessageEmbed(pages[page]!.embed);
Skyler Grey11236ba2022-08-08 21:13:33 +0100351 em.setDescription(em.description + "\n\n" + createPageIndicator(pages.length, page)).setFooter({
352 text: "Message timed out"
353 });
pineafan813bdf42022-07-24 10:39:10 +0100354 await interaction.editReply({
355 embeds: [em],
Skyler Grey75ea9172022-08-06 10:22:23 +0100356 components: [
357 new MessageActionRow().addComponents([
358 new MessageButton()
359 .setCustomId("left")
360 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
361 .setStyle("SECONDARY")
362 .setDisabled(true),
363 new MessageButton()
364 .setCustomId("select")
365 .setEmoji(getEmojiByName("CONTROL.MENU", "id"))
366 .setStyle("SECONDARY")
367 .setDisabled(true),
368 new MessageButton()
369 .setCustomId("right")
370 .setEmoji(getEmojiByName("CONTROL.RIGHT", "id"))
371 .setStyle("SECONDARY")
372 .setDisabled(true)
373 ])
374 ]
pineafan813bdf42022-07-24 10:39:10 +0100375 });
376 } else {
pineafan3a02ea32022-08-11 21:35:04 +0100377 const em = new Discord.MessageEmbed(pages[page]!.embed);
Skyler Grey11236ba2022-08-08 21:13:33 +0100378 em.setDescription(em.description + "\n\n" + createPageIndicator(pages.length, page)).setFooter({
379 text: "Message timed out"
380 });
pineafan813bdf42022-07-24 10:39:10 +0100381 await m.edit({
382 embeds: [em],
Skyler Grey75ea9172022-08-06 10:22:23 +0100383 components: [
384 new MessageActionRow().addComponents([
385 new MessageButton()
386 .setCustomId("left")
387 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
388 .setStyle("SECONDARY")
389 .setDisabled(true),
390 new MessageButton()
391 .setCustomId("select")
392 .setEmoji(getEmojiByName("CONTROL.MENU", "id"))
393 .setStyle("SECONDARY")
394 .setDisabled(true),
395 new MessageButton()
396 .setCustomId("right")
397 .setEmoji(getEmojiByName("CONTROL.RIGHT", "id"))
398 .setStyle("SECONDARY")
399 .setDisabled(true)
400 ])
401 ]
pineafan813bdf42022-07-24 10:39:10 +0100402 });
403 }
pineafan63fc5e22022-08-04 22:04:10 +0100404};