blob: 640ec134fc2021ec94462b34f37a7101f03f6147 [file] [log] [blame]
pineafan63fc5e22022-08-04 22:04:10 +01001import { LoadingEmbed } from "./../utils/defaultEmbeds.js";
2import { SelectMenuOption } from "@discordjs/builders";
pineafan813bdf42022-07-24 10:39:10 +01003import Discord, { MessageActionRow, MessageButton } from "discord.js";
4import EmojiEmbed from "../utils/generateEmojiEmbed.js";
5import getEmojiByName from "../utils/getEmojiByName.js";
6import createPageIndicator from "../utils/createPageIndicator.js";
pineafan813bdf42022-07-24 10:39:10 +01007
8class Embed {
9 embed: Discord.MessageEmbed;
10 title: string;
pineafan63fc5e22022-08-04 22:04:10 +010011 description = "";
12 pageId = 0;
pineafan813bdf42022-07-24 10:39:10 +010013 setEmbed(embed: Discord.MessageEmbed) { this.embed = embed; return this; }
14 setTitle(title: string) { this.title = title; return this; }
15 setDescription(description: string) { this.description = description; return this; }
16 setPageId(pageId: number) { this.pageId = pageId; return this; }
17}
18
19export default async (guild, interaction?) => {
20 let c = guild.publicUpdatesChannel ? guild.publicUpdatesChannel : guild.systemChannel;
21 c = c ? c : guild.channels.cache.find(ch => ch.type === "GUILD_TEXT" && ch.permissionsFor(guild.roles.everyone).has("SEND_MESSAGES") && ch.permissionsFor(guild.me).has("EMBED_LINKS"));
pineafan63fc5e22022-08-04 22:04:10 +010022 const pages = [
pineafan813bdf42022-07-24 10:39:10 +010023 new Embed()
24 .setEmbed(new EmojiEmbed()
25 .setTitle("Welcome to Nucleus")
26 .setDescription(
27 "Thanks for adding Nucleus to your server\n\n" +
28 "On the next few pages you can find instructions on getting started, and commands you may want to set up\n\n" +
29 "If you need support, have questions or want features, you can let us know in [Clicks](https://discord.gg/bPaNnxe)"
30 )
31 .setEmoji("NUCLEUS.LOGO")
32 .setStatus("Danger")
33 ).setTitle("Welcome").setDescription("About Nucleus").setPageId(0),
34 new Embed()
35 .setEmbed(new EmojiEmbed()
36 .setTitle("Logging")
37 .setDescription(
38 "Nucleus can log server events and keep you informed with what content is being posted to your server.\n" +
39 "We have 2 different types of logs, which each can be configured to send to a channel of your choice:\n" +
40 "**General Logs:** These are events like kicks and channel changes etc.\n" +
41 "**Warning Logs:** Warnings like NSFW avatars and spam etc. that may require action by a server staff member. " +
42 "These go to to a separate staff notifications channel.\n\n" +
43 "A general log channel can be set with `/settings log`\n" +
44 "A warning log channel can be set with `/settings warnings channel`"
45 )
46 .setEmoji("ICONS.LOGGING")
47 .setStatus("Danger")
48 ).setTitle("Logging").setDescription("Logging, staff warning logs etc.").setPageId(1),
49 new Embed()
50 .setEmbed(new EmojiEmbed()
51 .setTitle("Moderation")
52 .setDescription(
53 "Nucleus has a number of commands that can be used to moderate your server.\n" +
54 "These commands are all found under `/mod`, and they include:\n" +
55 `**${getEmojiByName("PUNISH.WARN.YELLOW")} Warn:** The user is warned (via DM) that they violated server rules.\n` +
56 `**${getEmojiByName("PUNISH.CLEARHISTORY")} Clear:** Some messages from a user are deleted in a channel.\n` +
57 `**${getEmojiByName("PUNISH.MUTE.YELLOW")} Mute:** The user is unable to send messages or join voice chats.\n` +
58 `**${getEmojiByName("PUNISH.MUTE.GREEN")} Unmute:** The user is able to send messages in the server.\n` +
59 `**${getEmojiByName("PUNISH.KICK.RED")} Kick:** The user is removed from the server.\n` +
60 `**${getEmojiByName("PUNISH.SOFTBAN")} Softban:** Kicks the user, deleting their messages from every channel.\n` +
61 `**${getEmojiByName("PUNISH.BAN.RED")} Ban:** The user is removed from the server, and they are unable to rejoin.\n` +
62 `**${getEmojiByName("PUNISH.BAN.GREEN")} Unban:** The user is able to rejoin the server.`
63 )
pineafan63fc5e22022-08-04 22:04:10 +010064 .setEmoji("PUNISH.BAN.RED")
65 .setStatus("Danger")
pineafan813bdf42022-07-24 10:39:10 +010066 ).setTitle("Moderation").setDescription("Basic moderation commands").setPageId(2),
67 new Embed()
68 .setEmbed(new EmojiEmbed()
69 .setTitle("Verify")
70 .setDescription(
71 "Nucleus has a verification system that allows users to prove they aren't bots.\n" +
72 "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" +
73 "After the user complete's the CAPTCHA, they are given a role and can use the permissions accordingly.\n" +
74 "You can set the role given with `/settings verify`"
75 )
76 .setEmoji("CONTROL.REDTICK")
77 .setStatus("Danger")
78 ).setTitle("Verify").setDescription("Captcha verification system").setPageId(3),
79 new Embed()
80 .setEmbed(new EmojiEmbed()
81 .setTitle("Content Scanning")
82 .setDescription(
83 "Nucleus has a content scanning system that automatically scans links and images sent by users.\n" +
84 "Nucleus can detect, delete, and punish users for sending NSFW content, or links to scam or adult sites.\n" +
85 "You can set the threshold for this in `/settings automation`" // TODO
86 )
87 .setEmoji("MOD.IMAGES.TOOSMALL")
88 .setStatus("Danger")
89 ).setTitle("Content Scanning").setDescription("Content (NSFW, malware, scams) scanning").setPageId(4),
90 new Embed()
91 .setEmbed(new EmojiEmbed()
92 .setTitle("Tickets")
93 .setDescription(
94 "Nucleus has a ticket system that allows users to create tickets and have a support team respond to them.\n" +
95 "Tickets can be created with `/ticket create` and a channel is created, pinging the user and support role.\n" +
96 "When the ticket is resolved, anyone can run `/ticket close` (or click the button) to close it.\n" +
97 "Running `/ticket close` again will delete the ticket."
98 )
99 .setEmoji("GUILD.TICKET.CLOSE")
100 .setStatus("Danger")
101 ).setTitle("Tickets").setDescription("Ticket system").setPageId(5),
102 new Embed()
103 .setEmbed(new EmojiEmbed()
104 .setTitle("Tags")
105 .setDescription(
106 "Add a tag system to your server with the `/tag` and `/tags` commands.\n" +
107 "To create a tag, type `/tags create <tag name> <tag content>`.\n" +
108 "Tag names and content can be edited with `/tags edit`.\n" +
109 "To delete a tag, type `/tags delete <tag name>`.\n" +
110 "To view all tags, type `/tags list`.\n"
111 )
112 .setEmoji("PUNISH.NICKNAME.RED")
113 .setStatus("Danger")
114 ).setTitle("Tags").setDescription("Tag system").setPageId(6),
115 new Embed()
116 .setEmbed(new EmojiEmbed()
117 .setTitle("Premium")
118 .setDescription(
119 "In the near future, we will be releasing extra premium only features.\n" +
120 "These features will include:\n\n" +
121 "**Attachment logs**\n> When a message with attachments is edited or deleted, the logs will also include the images sent.\n" +
122 "\nPremium is not yet available. Check `/nucleus premium` for updates on features and pricing"
123 )
124 .setEmoji("NUCLEUS.COMMANDS.LOCK")
125 .setStatus("Danger")
pineafan63fc5e22022-08-04 22:04:10 +0100126 ).setTitle("Premium").setDescription("Premium features").setPageId(7)
127 ];
pineafan813bdf42022-07-24 10:39:10 +0100128 let m;
pineafane23c4ec2022-07-27 21:56:27 +0100129 if (interaction) { m = await interaction.reply({embeds: LoadingEmbed, fetchReply: true, ephemeral: true}); }
130 else { m = await c.send({embeds: LoadingEmbed }); }
pineafan813bdf42022-07-24 10:39:10 +0100131 let page = 0;
132
pineafan63fc5e22022-08-04 22:04:10 +0100133 const f = async (component) => {
pineafan813bdf42022-07-24 10:39:10 +0100134 return (component.member as Discord.GuildMember).permissions.has("MANAGE_GUILD");
pineafan63fc5e22022-08-04 22:04:10 +0100135 };
pineafan813bdf42022-07-24 10:39:10 +0100136
137 let selectPaneOpen = false;
138
139 while (true) {
pineafan63fc5e22022-08-04 22:04:10 +0100140 let selectPane = [];
pineafan813bdf42022-07-24 10:39:10 +0100141
142 if (selectPaneOpen) {
pineafan63fc5e22022-08-04 22:04:10 +0100143 const options = [];
pineafan813bdf42022-07-24 10:39:10 +0100144 pages.forEach(embed => {
145 options.push(new SelectMenuOption({
146 label: embed.title,
147 value: embed.pageId.toString(),
pineafan63fc5e22022-08-04 22:04:10 +0100148 description: embed.description || ""
149 }));
150 });
pineafan813bdf42022-07-24 10:39:10 +0100151 selectPane = [new MessageActionRow().addComponents([
152 new Discord.MessageSelectMenu()
153 .addOptions(options)
154 .setCustomId("page")
155 .setMaxValues(1)
156 .setPlaceholder("Choose a page...")
pineafan63fc5e22022-08-04 22:04:10 +0100157 ])];
pineafan813bdf42022-07-24 10:39:10 +0100158 }
pineafan63fc5e22022-08-04 22:04:10 +0100159 const components = selectPane.concat([new MessageActionRow().addComponents([
pineafan813bdf42022-07-24 10:39:10 +0100160 new MessageButton().setCustomId("left").setEmoji(getEmojiByName("CONTROL.LEFT", "id")).setStyle("SECONDARY").setDisabled(page === 0),
161 new MessageButton().setCustomId("select").setEmoji(getEmojiByName("CONTROL.MENU", "id")).setStyle(selectPaneOpen ? "PRIMARY" : "SECONDARY").setDisabled(false),
pineafane23c4ec2022-07-27 21:56:27 +0100162 new MessageButton().setCustomId("right").setEmoji(getEmojiByName("CONTROL.RIGHT", "id")).setStyle("SECONDARY").setDisabled(page === pages.length - 1)
pineafan63fc5e22022-08-04 22:04:10 +0100163 ])]);
pineafan813bdf42022-07-24 10:39:10 +0100164 if (interaction) {
pineafan63fc5e22022-08-04 22:04:10 +0100165 const em = new Discord.MessageEmbed(pages[page].embed);
pineafan813bdf42022-07-24 10:39:10 +0100166 em.setDescription(em.description + "\n\n" + createPageIndicator(pages.length, page));
167 await interaction.editReply({
168 embeds: [em],
169 components: components
170 });
171 } else {
pineafan63fc5e22022-08-04 22:04:10 +0100172 const em = new Discord.MessageEmbed(pages[page].embed);
pineafan813bdf42022-07-24 10:39:10 +0100173 em.setDescription(em.description + "\n\n" + createPageIndicator(pages.length, page));
174 await m.edit({
175 embeds: [em],
176 components: components,
177 fetchReply: true
178 });
179 }
pineafan63fc5e22022-08-04 22:04:10 +0100180 let i;
pineafan813bdf42022-07-24 10:39:10 +0100181 try {
pineafan63fc5e22022-08-04 22:04:10 +0100182 i = await m.awaitMessageComponent({filter: interaction ? () => { return true; } : f, time: 300000});
183 } catch(e) { break; }
184 i.deferUpdate();
pineafane23c4ec2022-07-27 21:56:27 +0100185 if (i.component.customId === "left") {
pineafan813bdf42022-07-24 10:39:10 +0100186 if (page > 0) page--;
187 selectPaneOpen = false;
pineafane23c4ec2022-07-27 21:56:27 +0100188 } else if (i.component.customId === "right") {
pineafan813bdf42022-07-24 10:39:10 +0100189 if (page < pages.length - 1) page++;
190 selectPaneOpen = false;
pineafane23c4ec2022-07-27 21:56:27 +0100191 } else if (i.component.customId === "select") {
pineafan813bdf42022-07-24 10:39:10 +0100192 selectPaneOpen = !selectPaneOpen;
pineafane23c4ec2022-07-27 21:56:27 +0100193 } else if (i.component.customId === "page") {
pineafan813bdf42022-07-24 10:39:10 +0100194 page = parseInt(i.values[0]);
195 selectPaneOpen = false;
196 } else {
197 if (interaction) {
pineafan63fc5e22022-08-04 22:04:10 +0100198 const em = new Discord.MessageEmbed(pages[page].embed);
pineafane23c4ec2022-07-27 21:56:27 +0100199 em.setDescription(em.description + "\n\n" + createPageIndicator(pages.length, page));
pineafan63fc5e22022-08-04 22:04:10 +0100200 em.setFooter({text: "Message closed"});
pineafan813bdf42022-07-24 10:39:10 +0100201 interaction.editReply({embeds: [em], components: [new MessageActionRow().addComponents([
202 new MessageButton().setCustomId("left").setEmoji(getEmojiByName("CONTROL.LEFT", "id")).setStyle("SECONDARY").setDisabled(true),
203 new MessageButton().setCustomId("select").setEmoji(getEmojiByName("CONTROL.MENU", "id")).setStyle(selectPaneOpen ? "PRIMARY" : "SECONDARY").setDisabled(true),
pineafane23c4ec2022-07-27 21:56:27 +0100204 new MessageButton().setCustomId("right").setEmoji(getEmojiByName("CONTROL.RIGHT", "id")).setStyle("SECONDARY").setDisabled(true)
205 ])]});
pineafan813bdf42022-07-24 10:39:10 +0100206 } else {
207 m.delete();
208 }
209 return;
210 }
211 }
pineafan813bdf42022-07-24 10:39:10 +0100212 if (interaction) {
pineafan63fc5e22022-08-04 22:04:10 +0100213 const em = new Discord.MessageEmbed(pages[page].embed);
pineafane23c4ec2022-07-27 21:56:27 +0100214 em.setDescription(em.description + "\n\n" + createPageIndicator(pages.length, page)).setFooter({text: "Message timed out"});
pineafan813bdf42022-07-24 10:39:10 +0100215 await interaction.editReply({
216 embeds: [em],
217 components: [new MessageActionRow().addComponents([
218 new MessageButton().setCustomId("left").setEmoji(getEmojiByName("CONTROL.LEFT", "id")).setStyle("SECONDARY").setDisabled(true),
219 new MessageButton().setCustomId("select").setEmoji(getEmojiByName("CONTROL.MENU", "id")).setStyle("SECONDARY").setDisabled(true),
pineafane23c4ec2022-07-27 21:56:27 +0100220 new MessageButton().setCustomId("right").setEmoji(getEmojiByName("CONTROL.RIGHT", "id")).setStyle("SECONDARY").setDisabled(true)
pineafan813bdf42022-07-24 10:39:10 +0100221 ])]
222 });
223 } else {
pineafan63fc5e22022-08-04 22:04:10 +0100224 const em = new Discord.MessageEmbed(pages[page].embed);
pineafane23c4ec2022-07-27 21:56:27 +0100225 em.setDescription(em.description + "\n\n" + createPageIndicator(pages.length, page)).setFooter({text: "Message timed out"});
pineafan813bdf42022-07-24 10:39:10 +0100226 await m.edit({
227 embeds: [em],
228 components: [new MessageActionRow().addComponents([
229 new MessageButton().setCustomId("left").setEmoji(getEmojiByName("CONTROL.LEFT", "id")).setStyle("SECONDARY").setDisabled(true),
230 new MessageButton().setCustomId("select").setEmoji(getEmojiByName("CONTROL.MENU", "id")).setStyle("SECONDARY").setDisabled(true),
pineafane23c4ec2022-07-27 21:56:27 +0100231 new MessageButton().setCustomId("right").setEmoji(getEmojiByName("CONTROL.RIGHT", "id")).setStyle("SECONDARY").setDisabled(true)
pineafan813bdf42022-07-24 10:39:10 +0100232 ])]
233 });
234 }
pineafan63fc5e22022-08-04 22:04:10 +0100235};