Development (#11)
We need this NOW.
---------
Co-authored-by: PineaFan <ash@pinea.dev>
Co-authored-by: pineafan <pineapplefanyt@gmail.com>
Co-authored-by: PineappleFan <PineaFan@users.noreply.github.com>
Co-authored-by: Skyler <skyler3665@gmail.com>
diff --git a/src/commands/nucleus/_meta.ts b/src/commands/nucleus/_meta.ts
index 521b338..bd7fd14 100644
--- a/src/commands/nucleus/_meta.ts
+++ b/src/commands/nucleus/_meta.ts
@@ -3,8 +3,6 @@
const name = "nucleus";
const description = "Commands relating to Nucleus itself";
-const subcommand = await command(name, description, `nucleus`)
+const subcommand = await command(name, description, `nucleus`, undefined, undefined, undefined, undefined, true);
-const allowedInDMs = true;
-
-export { name, description, subcommand as command, allowedInDMs };
+export { name, description, subcommand as command };
diff --git a/src/commands/nucleus/guide.ts b/src/commands/nucleus/guide.ts
index d3370ba..270ee62 100644
--- a/src/commands/nucleus/guide.ts
+++ b/src/commands/nucleus/guide.ts
@@ -1,5 +1,5 @@
import type { CommandInteraction } from 'discord.js';
-import type { SlashCommandSubcommandBuilder } from "@discordjs/builders";
+import type { SlashCommandSubcommandBuilder } from "discord.js";
import guide from "../../reflex/guide.js";
const command = (builder: SlashCommandSubcommandBuilder) =>
@@ -9,10 +9,5 @@
guide(interaction.guild!, interaction);
};
-const check = () => {
- return true;
-};
-
export { command };
export { callback };
-export { check };
diff --git a/src/commands/nucleus/invite.ts b/src/commands/nucleus/invite.ts
index fd65e51..b89425a 100644
--- a/src/commands/nucleus/invite.ts
+++ b/src/commands/nucleus/invite.ts
@@ -1,5 +1,5 @@
import { CommandInteraction, ActionRowBuilder, ButtonBuilder, ButtonStyle } from "discord.js";
-import type { SlashCommandSubcommandBuilder } from "@discordjs/builders";
+import type { SlashCommandSubcommandBuilder } from "discord.js";
import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
import client from "../../utils/client.js";
@@ -29,10 +29,5 @@
});
};
-const check = () => {
- return true;
-};
-
export { command };
export { callback };
-export { check };
diff --git a/src/commands/nucleus/ping.ts b/src/commands/nucleus/ping.ts
index 12f1c6b..3e02a8f 100644
--- a/src/commands/nucleus/ping.ts
+++ b/src/commands/nucleus/ping.ts
@@ -1,6 +1,6 @@
import { LoadingEmbed } from "../../utils/defaults.js";
import type { CommandInteraction } from "discord.js";
-import type { SlashCommandSubcommandBuilder } from "@discordjs/builders";
+import type { SlashCommandSubcommandBuilder } from "discord.js";
import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
import client from "../../utils/client.js";
@@ -10,9 +10,9 @@
const callback = async (interaction: CommandInteraction): Promise<void> => {
// WEBSOCKET | Nucleus -> Discord
// EDITING | Nucleus -> discord -> nucleus | edit time / 2
- const initial = new Date().getTime();
+ const initial = Date.now();
await interaction.reply({ embeds: LoadingEmbed, ephemeral: true });
- const ping = new Date().getTime() - initial;
+ const ping = Date.now() - initial;
interaction.editReply({
embeds: [
new EmojiEmbed()
@@ -28,10 +28,5 @@
});
};
-const check = () => {
- return true;
-};
-
export { command };
export { callback };
-export { check };
diff --git a/src/commands/nucleus/premium.ts b/src/commands/nucleus/premium.ts
index 745f167..c431c8e 100644
--- a/src/commands/nucleus/premium.ts
+++ b/src/commands/nucleus/premium.ts
@@ -1,32 +1,211 @@
-import type { CommandInteraction } from "discord.js";
-import type { SlashCommandSubcommandBuilder } from "@discordjs/builders";
+import { ActionRowBuilder, ButtonBuilder, ButtonInteraction, ButtonStyle, CommandInteraction, ComponentType, Message, StringSelectMenuBuilder, StringSelectMenuInteraction } from "discord.js";
+import type { SlashCommandSubcommandBuilder } from "discord.js";
import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import client from "../../utils/client.js";
+import { LoadingEmbed } from "../../utils/defaults.js";
+import getEmojiByName from "../../utils/getEmojiByName.js";
const command = (builder: SlashCommandSubcommandBuilder) =>
builder.setName("premium").setDescription("Information about Nucleus Premium");
+//TODO: Allow User to remove Premium
+
+const dmcallback = async (interaction: CommandInteraction, firstDescription: string, msg: Message): Promise<void> => {
+ let closed = false;
+ do {
+ const dbUser = await client.database.premium.fetchUser(interaction.user.id);
+ if(!dbUser) {
+ await interaction.editReply({embeds: [
+ new EmojiEmbed()
+ .setTitle("Premium")
+ .setDescription(`*You do not have premium! You can't activate premium on any servers.*` + firstDescription)
+ .setEmoji("NUCLEUS.LOGO")
+ .setStatus("Danger")
+ ]});
+ return;
+ }
+ const premiumGuilds = dbUser.appliesTo.map((guildID) => {
+ const guild = client.guilds.cache.get(guildID);
+ if(!guild) return undefined;
+ return guild.name;
+ });
+
+ const options = premiumGuilds.filter((guild) => guild !== undefined) as string[];
+
+ const removeRow = new ActionRowBuilder<StringSelectMenuBuilder>()
+ .addComponents(
+ new StringSelectMenuBuilder()
+ .setCustomId("currentPremium")
+ .setPlaceholder("Select a server to remove premium from")
+ .setDisabled(premiumGuilds.length === 0)
+ .addOptions(options.slice(0, Math.min(options.length, 24)).map((guild) => {
+ return {label: guild, value: guild}
+ }))
+ );
+ const cancel = new ActionRowBuilder<ButtonBuilder>()
+ .addComponents(
+ new ButtonBuilder()
+ .setCustomId("cancel")
+ .setLabel("Close")
+ .setStyle(ButtonStyle.Danger)
+ );
+
+ const components: ActionRowBuilder<StringSelectMenuBuilder | ButtonBuilder>[] = [cancel];
+ if(options.length > 0) components.unshift(removeRow);
+ await interaction.editReply(
+ {
+ embeds: [
+ new EmojiEmbed()
+ .setTitle("Premium")
+ .setDescription(
+ `*You have premium on the following servers:*\n\n` +
+ (options.length > 0 ? options.join(', ') : `You have not activated premium in any guilds`) +
+ firstDescription)
+ .setEmoji("NUCLEUS.LOGO")
+ .setStatus("Success")
+ ],
+ components: components
+ });
+
+ let i: StringSelectMenuInteraction | ButtonInteraction;
+ try {
+ const filter = (i: StringSelectMenuInteraction | ButtonInteraction) => i.user.id === interaction.user.id;
+ i = await msg.awaitMessageComponent<ComponentType.StringSelect | ComponentType.Button>({time: 300000, filter})
+ } catch (e) {
+ await interaction.deleteReply();
+ closed = true;
+ break;
+ }
+ await i.deferUpdate();
+ if(i.isButton()) {
+ closed = true;
+ } else {
+ const response = client.database.premium.removePremium(interaction.user.id, i.values[0]!);
+ console.log(response)
+ }
+ } while (!closed);
+ await interaction.deleteReply();
+}
const callback = async (interaction: CommandInteraction): Promise<void> => {
- interaction.reply({
+ if (interaction.guild) client.database.premium.hasPremium(interaction.guild.id).finally(() => {});
+ const m = await interaction.reply({embeds: LoadingEmbed, ephemeral: true, fetchReply: true})
+ const member = await (await interaction.client.guilds.fetch("684492926528651336")).members.fetch(interaction.user.id).catch(() => {
+ interaction.editReply({ embeds: [
+ new EmojiEmbed()
+ .setTitle("Premium")
+ .setDescription(`*You are not currently in the Clicks Server. To gain access to premium please join.*` + firstDescription)
+ .setEmoji("NUCLEUS.LOGO")
+ .setStatus("Danger")
+ ], components: [new ActionRowBuilder<ButtonBuilder>().addComponents(new ButtonBuilder().setStyle(ButtonStyle.Link).setLabel("Join").setURL("https://discord.gg/bPaNnxe"))] });
+ })
+ if (!member) return;
+ const firstDescription = "\n\nPremium allows servers of your choice to get access to extra features for a fixed price per month.\nThis includes:\n" +
+ `${getEmojiByName("MOD.IMAGES.TOOSMALL")} Attachment logs - Stores attachments so they can be viewed after a message is deleted.\n` +
+ `${getEmojiByName("GUILD.TICKET.ARCHIVED")} Ticket Transcripts - Gives a link to view the history of a ticket after it has been closed.\n`
+ const dbMember = await client.database.premium.fetchUser(interaction.user.id)
+ let premium = `You do not have premium! You can't activate premium on any servers.`;
+ let count = 0;
+ const {level, appliesTo} = dbMember ?? {level: 0, appliesTo: []}
+ if (level === 99) {
+ premium = `You have Infinite Premium! You have been gifted this by the developers as a thank you. You can give premium to any and all servers you are in.`;
+ count = 200;
+ } else if (level === 1) {
+ premium = `You have Premium tier 1! You can give premium to ${1 - appliesTo.length} more server(s).`;
+ count = 1;
+ } else if (level === 2) {
+ premium = `You have Premium tier 2! You can give premium to ${3 - appliesTo.length} more server(s).`;
+ count = 3;
+ } else if (level === 3) {
+ premium = `You have Premium Mod! You can give premium to ${3 - appliesTo.length} more server(s), as well as automatically giving premium to all servers you have a "manage" permission in.`
+ count = 3;
+ }
+ if (dbMember?.expiresAt) {
+ premium = `**You can't give servers premium anymore because your subscription ended or was cancelled.** To get premium again please subscribe in the Clicks server`
+ count = 0;
+ }
+ if(!interaction.guild) return await dmcallback(interaction, firstDescription, m);
+ const hasPremium = await client.database.premium.hasPremium(interaction.guild!.id);
+ let premiumGuild = ""
+ if (hasPremium) {
+ premiumGuild = `**This server has premium! It was ${hasPremium[2] === 3 && hasPremium[3] ? `automatically applied by <@${hasPremium[1]}>` : `given by <@${hasPremium[1]}>`}**\n\n`
+ }
+
+ const components: ActionRowBuilder<ButtonBuilder>[] = []
+ if (level === 0 || dbMember?.expiresAt) {
+ components.push(
+ new ActionRowBuilder<ButtonBuilder>()
+ .addComponents(
+ new ButtonBuilder()
+ .setStyle(ButtonStyle.Link)
+ .setLabel("Join Clicks")
+ .setURL("https://discord.gg/bPaNnxe")
+ )
+ )
+ } else {
+ components.push(
+ new ActionRowBuilder<ButtonBuilder>()
+ .addComponents(
+ new ButtonBuilder()
+ .setStyle(premiumGuild.length > 0 ? ButtonStyle.Secondary : ButtonStyle.Success)
+ .setLabel(premiumGuild.length > 0 ? "This server has premium" : "Activate premium here")
+ .setCustomId("premiumActivate")
+ .setDisabled(count <= 0 || (hasPremium ? hasPremium[0] : false))
+ )
+ )
+ }
+
+ interaction.editReply({
embeds: [
new EmojiEmbed()
.setTitle("Premium")
.setDescription(
- "*Nucleus Premium is currently not available.*\n\n" +
- "Premium allows your server to get access to extra features, for a fixed price per month.\nThis includes:\n" +
- "- Attachment logs - Stores attachments so they can be viewed after a message is deleted.\n" +
- "- Ticket Transcripts - Gives a link to view the history of a ticket after it has been closed.\n"
+ premiumGuild + premium + firstDescription
)
.setEmoji("NUCLEUS.LOGO")
.setStatus("Danger")
+ .setImage("https://assets.clicks.codes/ads/ads/nucleus-premium.png")
],
- ephemeral: true
+ components: components
});
-};
-const check = () => {
- return true;
+ const filter = (i: ButtonInteraction) => i.customId === "premiumActivate" && i.user.id === interaction.user.id;
+ let i;
+ try {
+ i = await interaction.channel!.awaitMessageComponent<2>({ filter, time: 60000 });
+ } catch (e) {
+ return;
+ }
+ i.deferUpdate();
+ const guild = i.guild!;
+ if (count - appliesTo.length <= 0) {
+ interaction.editReply({
+ embeds: [
+ new EmojiEmbed()
+ .setTitle("Premium")
+ .setDescription(
+ `You have already activated premium on the maximum amount of servers!` + firstDescription
+ )
+ .setEmoji("NUCLEUS.PREMIUMACTIVATE")
+ .setStatus("Danger")
+ ],
+ components: []
+ });
+ } else {
+ await client.database.premium.addPremium(interaction.user.id, guild.id);
+ interaction.editReply({
+ embeds: [
+ new EmojiEmbed()
+ .setTitle("Premium")
+ .setDescription(
+ `You have activated premium on this server!` + firstDescription
+ )
+ .setEmoji("NUCLEUS.LOGO")
+ .setStatus("Danger")
+ ],
+ components: []
+ });
+ }
};
export { command };
export { callback };
-export { check };
diff --git a/src/commands/nucleus/stats.ts b/src/commands/nucleus/stats.ts
index d8b2807..19c0949 100644
--- a/src/commands/nucleus/stats.ts
+++ b/src/commands/nucleus/stats.ts
@@ -1,5 +1,5 @@
import type { CommandInteraction } from "discord.js";
-import type { SlashCommandSubcommandBuilder } from "@discordjs/builders";
+import type { SlashCommandSubcommandBuilder } from "discord.js";
import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
import client from "../../utils/client.js";
@@ -13,16 +13,11 @@
.setTitle("Stats")
.setDescription(`**Servers:** ${client.guilds.cache.size}\n` + `**Ping:** \`${client.ws.ping * 2}ms\``)
.setStatus("Success")
- .setEmoji("GUILD.GRAPHS")
+ .setEmoji("SETTINGS.STATS.GREEN")
],
ephemeral: true
});
};
-const check = () => {
- return true;
-};
-
export { command };
export { callback };
-export { check };
diff --git a/src/commands/nucleus/suggest.ts b/src/commands/nucleus/suggest.ts
index de0e69b..6ba3445 100644
--- a/src/commands/nucleus/suggest.ts
+++ b/src/commands/nucleus/suggest.ts
@@ -1,7 +1,7 @@
import { LoadingEmbed } from '../../utils/defaults.js';
import { ButtonStyle, CommandInteraction } from "discord.js";
import Discord from "discord.js";
-import type { SlashCommandSubcommandBuilder } from "@discordjs/builders";
+import type { SlashCommandSubcommandBuilder } from "discord.js";
import confirmationMessage from "../../utils/confirmationMessage.js";
import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
import client from "../../utils/client.js";
@@ -66,10 +66,5 @@
});
};
-const check = () => {
- return true;
-};
-
export { command };
export { callback };
-export { check };