From 94ff6deb29e8ea2deac40e7ed50b327301b4ff9b Mon Sep 17 00:00:00 2001 From: TheCodedProf Date: Wed, 22 Feb 2023 17:47:26 -0500 Subject: [PATCH] big work today! --- TODO | 3 +- src/commands/mod/ban.ts | 4 ++ src/commands/mod/kick.ts | 4 ++ src/commands/mod/mute.ts | 3 + src/commands/mod/nick.ts | 4 ++ src/commands/mod/purge.ts | 2 +- src/commands/mod/softban.ts | 4 ++ src/commands/mod/unmute.ts | 4 ++ src/commands/mod/warn.ts | 6 +- src/commands/nucleus/premium.ts | 72 ++++++++++++------- src/commands/privacy.ts | 6 +- src/commands/settings/logs/attachment.ts | 5 +- src/commands/settings/logs/warnings.ts | 3 +- src/config/emojis.json | 2 +- src/context/messages/purgeto.ts | 2 + src/context/users/userinfo.ts | 2 + src/events/guildMemberUpdate.ts | 3 + src/index.ts | 5 +- src/premium/createTranscript.ts | 2 + src/utils/client.ts | 3 +- src/utils/commandRegistration/register.ts | 5 +- src/utils/database.ts | 85 +++++++++++++++++++---- 22 files changed, 169 insertions(+), 60 deletions(-) diff --git a/TODO b/TODO index 2a0d7be..3316dd2 100644 --- a/TODO +++ b/TODO @@ -1,2 +1,3 @@ Server rules -verificationRequired on welcome \ No newline at end of file +verificationRequired on welcome +!!Premium diff --git a/src/commands/mod/ban.ts b/src/commands/mod/ban.ts index 0ee663f..e8309fb 100644 --- a/src/commands/mod/ban.ts +++ b/src/commands/mod/ban.ts @@ -5,6 +5,7 @@ import keyValueList from "../../utils/generateKeyValueList.js"; import addPlurals from "../../utils/plurals.js"; import client from "../../utils/client.js"; import { LinkWarningFooter } from "../../utils/defaults.js"; +import getEmojiByName from "../../utils/getEmojiByName.js"; const command = (builder: SlashCommandSubcommandBuilder) => @@ -133,6 +134,9 @@ const callback = async (interaction: CommandInteraction): Promise => { accountCreated: entry(member.user.createdTimestamp, renderDelta(member.user.createdTimestamp)), serverMemberCount: interaction.guild.memberCount }, + separate: { + end: getEmojiByName("ICONS.NOTIFY." + (notify ? "ON" : "OFF")) + ` The user was ${notify ? "" : "not "}notified` + }, hidden: { guild: interaction.guild.id } diff --git a/src/commands/mod/kick.ts b/src/commands/mod/kick.ts index 9f1ee41..059bdb2 100644 --- a/src/commands/mod/kick.ts +++ b/src/commands/mod/kick.ts @@ -7,6 +7,7 @@ import confirmationMessage from "../../utils/confirmationMessage.js"; import EmojiEmbed from "../../utils/generateEmojiEmbed.js"; import keyValueList from "../../utils/generateKeyValueList.js"; import client from "../../utils/client.js"; +import getEmojiByName from "../../utils/getEmojiByName.js"; const command = (builder: SlashCommandSubcommandBuilder) => builder @@ -125,6 +126,9 @@ const callback = async (interaction: CommandInteraction): Promise => { timeInServer: timeInServer, serverMemberCount: member.guild.memberCount }, + separate: { + end: getEmojiByName("ICONS.NOTIFY." + (notify ? "ON" : "OFF")) + ` The user was ${notify ? "" : "not "}notified` + }, hidden: { guild: member.guild.id } diff --git a/src/commands/mod/mute.ts b/src/commands/mod/mute.ts index 878d696..c795456 100644 --- a/src/commands/mod/mute.ts +++ b/src/commands/mod/mute.ts @@ -338,6 +338,9 @@ const callback = async (interaction: CommandInteraction): Promise => { mutedBy: entry(interaction.member!.user.id, renderUser(interaction.member!.user as Discord.User)), reason: entry(reason, reason ? reason : "*No reason provided*") }, + separate: { + end: getEmojiByName("ICONS.NOTIFY." + (notify ? "ON" : "OFF")) + ` The user was ${notify ? "" : "not "}notified` + }, hidden: { guild: interaction.guild.id } diff --git a/src/commands/mod/nick.ts b/src/commands/mod/nick.ts index 8fb1cc1..97f783a 100644 --- a/src/commands/mod/nick.ts +++ b/src/commands/mod/nick.ts @@ -6,6 +6,7 @@ import EmojiEmbed from "../../utils/generateEmojiEmbed.js"; import keyValueList from "../../utils/generateKeyValueList.js"; import client from "../../utils/client.js"; import { areTicketsEnabled, create } from "../../actions/createModActionTicket.js"; +import getEmojiByName from "../../utils/getEmojiByName.js"; const command = (builder: SlashCommandSubcommandBuilder) => builder @@ -165,6 +166,9 @@ const callback = async (interaction: CommandInteraction): Promise => { updated: entry(Date.now(), renderDelta(Date.now())), updatedBy: entry(interaction.user.id, renderUser(interaction.user)) }, + separate: { + end: getEmojiByName("ICONS.NOTIFY." + (notify ? "ON" : "OFF")) + ` The user was ${notify ? "" : "not "}notified` + }, hidden: { guild: interaction.guild!.id } diff --git a/src/commands/mod/purge.ts b/src/commands/mod/purge.ts index cabcb1e..8d49c3b 100644 --- a/src/commands/mod/purge.ts +++ b/src/commands/mod/purge.ts @@ -309,7 +309,7 @@ const callback = async (interaction: CommandInteraction): Promise => { } }; log(data); - let out = ""; + let out = ""; // TODO: messageException throughout this file messages.reverse().forEach((message) => { if (!message) { out += "Unknown message\n\n" diff --git a/src/commands/mod/softban.ts b/src/commands/mod/softban.ts index fa9f11b..1b404c9 100644 --- a/src/commands/mod/softban.ts +++ b/src/commands/mod/softban.ts @@ -6,6 +6,7 @@ import keyValueList from "../../utils/generateKeyValueList.js"; import addPlurals from "../../utils/plurals.js"; import client from "../../utils/client.js"; import { LinkWarningFooter } from "../../utils/defaults.js"; +import getEmojiByName from "../../utils/getEmojiByName.js"; const command = (builder: SlashCommandSubcommandBuilder) => @@ -135,6 +136,9 @@ const callback = async (interaction: CommandInteraction): Promise => { accountCreated: entry(member.user.createdTimestamp, renderDelta(member.user.createdTimestamp)), serverMemberCount: interaction.guild.memberCount }, + separate: { + end: getEmojiByName("ICONS.NOTIFY." + (notify ? "ON" : "OFF")) + ` The user was ${notify ? "" : "not "}notified` + }, hidden: { guild: interaction.guild.id } diff --git a/src/commands/mod/unmute.ts b/src/commands/mod/unmute.ts index 44f807d..8562c4c 100644 --- a/src/commands/mod/unmute.ts +++ b/src/commands/mod/unmute.ts @@ -4,6 +4,7 @@ import confirmationMessage from "../../utils/confirmationMessage.js"; import EmojiEmbed from "../../utils/generateEmojiEmbed.js"; import keyValueList from "../../utils/generateKeyValueList.js"; import client from "../../utils/client.js"; +import getEmojiByName from "../../utils/getEmojiByName.js"; const command = (builder: SlashCommandSubcommandBuilder) => builder @@ -113,6 +114,9 @@ const callback = async (interaction: CommandInteraction): Promise => { unmuted: entry(Date.now().toString(), renderDelta(Date.now())), unmutedBy: entry(interaction.user.id, renderUser(interaction.user)) }, + separate: { + end: getEmojiByName("ICONS.NOTIFY." + (notify ? "ON" : "OFF")) + ` The user was ${notify ? "" : "not "}notified` + }, hidden: { guild: interaction.guild.id } diff --git a/src/commands/mod/warn.ts b/src/commands/mod/warn.ts index 35b5400..ea4f084 100644 --- a/src/commands/mod/warn.ts +++ b/src/commands/mod/warn.ts @@ -5,6 +5,7 @@ import EmojiEmbed from "../../utils/generateEmojiEmbed.js"; import keyValueList from "../../utils/generateKeyValueList.js"; import { create, areTicketsEnabled } from "../../actions/createModActionTicket.js"; import client from "../../utils/client.js"; +import getEmojiByName from "../../utils/getEmojiByName.js"; import { LinkWarningFooter } from "../../utils/defaults.js"; const command = (builder: SlashCommandSubcommandBuilder) => @@ -124,7 +125,10 @@ const callback = async (interaction: CommandInteraction): Promise => { renderUser((interaction.options.getMember("user") as GuildMember).user) ), warnedBy: entry(interaction.member!.user.id, renderUser(interaction.member!.user as Discord.User)), - reason: reason ? `\n> ${reason}` : "*No reason provided*" + reason: reason ? reason : "*No reason provided*" + }, + separate: { + end: getEmojiByName("ICONS.NOTIFY." + (notify ? "ON" : "OFF")) + ` The user was ${notify ? "" : "not "}notified` }, hidden: { guild: interaction.guild.id diff --git a/src/commands/nucleus/premium.ts b/src/commands/nucleus/premium.ts index 354c303..026984d 100644 --- a/src/commands/nucleus/premium.ts +++ b/src/commands/nucleus/premium.ts @@ -3,28 +3,26 @@ 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 callback = async (interaction: CommandInteraction): Promise => { await interaction.reply({embeds: LoadingEmbed, ephemeral: true}) - const member = (await interaction.client.guilds.fetch("684492926528651336")).members.cache.get(interaction.user.id) - const firstDescription = "\n\nPremium 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" - if(!member) { + 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 - ) + .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().addComponents(new ButtonBuilder().setStyle(ButtonStyle.Link).setLabel("Join").setURL("https://discord.gg/bPaNnxe"))] }); - return; - } + }) + 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; @@ -33,19 +31,47 @@ const callback = async (interaction: CommandInteraction): Promise => { 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 servers.`; + 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 servers.`; + 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 servers, as well as automatically giving premium to all servers you have a "manage" permission in.` + 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; + } const hasPremium = await client.database.premium.hasPremium(interaction.guild!.id); let premiumGuild = "" - if (hasPremium) { - premiumGuild = `\n\n**This server has premium!**` + if (hasPremium) { //FIXME: Check how user applied premium + premiumGuild = `**This server has premium! It was ${hasPremium[2] === 3 ? `automatically applied by <@${hasPremium[1]}>` : `given by <@${hasPremium[1]}>`}**\n\n` + } + + const components: ActionRowBuilder[] = [] + if (level === 0 || dbMember?.expiresAt) { + components.push( + new ActionRowBuilder() + .addComponents( + new ButtonBuilder() + .setStyle(ButtonStyle.Link) + .setLabel("Join Clicks") + .setURL("https://discord.gg/bPaNnxe") + ) + ) + } else { + components.push( + new ActionRowBuilder() + .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({ @@ -53,21 +79,13 @@ const callback = async (interaction: CommandInteraction): Promise => { new EmojiEmbed() .setTitle("Premium") .setDescription( - premium + firstDescription + premiumGuild + premiumGuild + premium + firstDescription ) .setEmoji("NUCLEUS.LOGO") .setStatus("Danger") + // .setImage("") //TODO: Add image ], - components: [ - new ActionRowBuilder() - .addComponents( - new ButtonBuilder() - .setStyle(ButtonStyle.Primary) - .setLabel("Activate Premium here") - .setCustomId("premiumActivate") - .setDisabled(count <= 0 && hasPremium) - ) - ] + components: components }); const filter = (i: ButtonInteraction) => i.customId === "premiumActivate" && i.user.id === interaction.user.id; diff --git a/src/commands/privacy.ts b/src/commands/privacy.ts index 8803e25..46784f5 100644 --- a/src/commands/privacy.ts +++ b/src/commands/privacy.ts @@ -48,15 +48,13 @@ const callback = async (interaction: CommandInteraction): Promise => { new EmojiEmbed() .setTitle("Link scanning and Transcripts") .setDescription( - "**Facebook** - Facebook trackers include data such as your date of birth, and guess your age if not entered, your preferences, who you interact with and more.\n" + - "**AMP** - AMP is a technology that allows websites to be served by Google. This means Google can store and track data, and are pushing this to as many pages as possible.\n\n" + - "Transcripts allow you to store all messages sent in a channel. This is stored in our database along with the rest of the servers settings but is accessible by anyone with the link, so a leaked link could show all messages sent in the channel.\n" + "Transcripts allow you to store all messages sent in a channel. Transcripts are stored in our database along with the rest of the server's settings but is accessible by anyone with the link, so a leaked link could show all messages sent in the channel.\n" ) .setEmoji("NUCLEUS.LOGO") .setStatus("Danger") ) .setTitle("Link scanning and Transcripts") - .setDescription("Regarding Facebook and AMP filter types, and ticket transcripts") + .setDescription("Information about how links and images are scanned, and transcripts are stored") .setPageId(2) ].concat( (interaction.member as Discord.GuildMember).permissions.has("Administrator") diff --git a/src/commands/settings/logs/attachment.ts b/src/commands/settings/logs/attachment.ts index 8331043..c04c7cf 100644 --- a/src/commands/settings/logs/attachment.ts +++ b/src/commands/settings/logs/attachment.ts @@ -1,5 +1,5 @@ import { LoadingEmbed } from "../../../utils/defaults.js"; -import Discord, { CommandInteraction, ActionRowBuilder, ButtonBuilder, ButtonStyle, ChannelSelectMenuBuilder } from "discord.js"; +import Discord, { CommandInteraction, ActionRowBuilder, ButtonBuilder, ButtonStyle, ChannelSelectMenuBuilder, ChannelType } from "discord.js"; import EmojiEmbed from "../../../utils/generateEmojiEmbed.js"; import getEmojiByName from "../../../utils/getEmojiByName.js"; import type { SlashCommandSubcommandBuilder } from "discord.js"; @@ -38,6 +38,7 @@ const callback = async (interaction: CommandInteraction): Promise => { new ChannelSelectMenuBuilder() .setCustomId("channel") .setPlaceholder("Select a channel") + .setChannelTypes(ChannelType.GuildText) ); const buttons = new ActionRowBuilder() .addComponents( @@ -58,7 +59,7 @@ const callback = async (interaction: CommandInteraction): Promise => { const embed = new EmojiEmbed() .setTitle("Attachments") .setDescription( - `The channel to send all attachments from the server, allowing you to check them if they are deleted` + + `The channel to send all attachments from the server, allowing you to check them if they are deleted\n` + `**Channel:** ${channel ? `<#${channel}>` : "*None*"}\n` ) .setStatus("Success") diff --git a/src/commands/settings/logs/warnings.ts b/src/commands/settings/logs/warnings.ts index 24249a2..84772e6 100644 --- a/src/commands/settings/logs/warnings.ts +++ b/src/commands/settings/logs/warnings.ts @@ -1,5 +1,5 @@ import { LoadingEmbed } from "../../../utils/defaults.js"; -import Discord, { CommandInteraction, ActionRowBuilder, ButtonBuilder, ButtonStyle, ChannelSelectMenuBuilder } from "discord.js"; +import Discord, { CommandInteraction, ActionRowBuilder, ButtonBuilder, ButtonStyle, ChannelSelectMenuBuilder, ChannelType } from "discord.js"; import EmojiEmbed from "../../../utils/generateEmojiEmbed.js"; import getEmojiByName from "../../../utils/getEmojiByName.js"; import type { SlashCommandSubcommandBuilder } from "discord.js"; @@ -27,6 +27,7 @@ const callback = async (interaction: CommandInteraction): Promise => { new ChannelSelectMenuBuilder() .setCustomId("channel") .setPlaceholder("Select a channel") + .setChannelTypes(ChannelType.GuildText) ); const buttons = new ActionRowBuilder() .addComponents( diff --git a/src/config/emojis.json b/src/config/emojis.json index 35743e1..ecf1858 100644 --- a/src/config/emojis.json +++ b/src/config/emojis.json @@ -28,7 +28,7 @@ "REORDER": "1069323453909454890", "NOTIFY": { "ON": "1000726394579464232", - "OFF": "1000726363495477368" + "OFF": "1078058136092541008" }, "OPP": { "ADD": "837355918831124500", diff --git a/src/context/messages/purgeto.ts b/src/context/messages/purgeto.ts index 4627bf2..02d5d2a 100644 --- a/src/context/messages/purgeto.ts +++ b/src/context/messages/purgeto.ts @@ -5,6 +5,7 @@ import Discord, { ActionRowBuilder, ButtonBuilder, ButtonStyle, ContextMenuComma import client from "../../utils/client.js"; import getEmojiByName from '../../utils/getEmojiByName.js'; import { JSONTranscriptFromMessageArray, JSONTranscriptToHumanReadable } from "../../utils/logTranscripts.js"; +import { messageException } from '../../utils/createTemporaryStorage.js'; const command = new ContextMenuCommandBuilder() .setName("Purge up to here") @@ -185,6 +186,7 @@ const callback = async (interaction: MessageContextMenuCommandInteraction) => { }; log(data); const messages: Message[] = deleted.map(m => m).filter(m => m instanceof Message).map(m => m as Message); + if (messages.length === 1) messageException(interaction.guild!.id, interaction.channel.id, messages[0]!.id) const transcript = JSONTranscriptToHumanReadable(JSONTranscriptFromMessageArray(messages)!); const attachmentObject = { attachment: Buffer.from(transcript), diff --git a/src/context/users/userinfo.ts b/src/context/users/userinfo.ts index 3b1a6bd..496f84e 100644 --- a/src/context/users/userinfo.ts +++ b/src/context/users/userinfo.ts @@ -5,6 +5,7 @@ const command = new ContextMenuCommandBuilder() .setName("User info") const callback = async (interaction: UserContextMenuCommandInteraction) => { + console.log("callback") const guild = interaction.guild! let member = interaction.targetMember if (!member) member = await guild.members.fetch(interaction.targetId) @@ -12,6 +13,7 @@ const callback = async (interaction: UserContextMenuCommandInteraction) => { } const check = async (_interaction: UserContextMenuCommandInteraction) => { + console.log("check") return true; } diff --git a/src/events/guildMemberUpdate.ts b/src/events/guildMemberUpdate.ts index 5788f61..721978f 100644 --- a/src/events/guildMemberUpdate.ts +++ b/src/events/guildMemberUpdate.ts @@ -7,6 +7,9 @@ export const event = "guildMemberUpdate"; export async function callback(client: NucleusClient, before: GuildMember, after: GuildMember) { const { log, NucleusColors, entry, renderUser, renderDelta, getAuditLog } = client.logger; + if(before.guild.id === "684492926528651336") { + await client.database.premium.checkAllPremium(after) + } if(!before.roles.cache.equals(after.roles.cache)) { const auditLog = (await getAuditLog(after.guild, AuditLogEvent.MemberRoleUpdate)) diff --git a/src/index.ts b/src/index.ts index 3c132bc..12f6659 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,10 +13,9 @@ client.on("ready", async () => { } else { client.fetchedCommands = await client.application?.commands.fetch()!; } - setInterval(async () => { - await client.database.premium.checkAllPremium(); - }, 1000 * 60 * 3); + await client.database.premium.checkAllPremium(); }); + process.on("unhandledRejection", (err) => { console.error(err) }); process.on("uncaughtException", (err) => { console.error(err) }); diff --git a/src/premium/createTranscript.ts b/src/premium/createTranscript.ts index fb6dde7..88a8e6e 100644 --- a/src/premium/createTranscript.ts +++ b/src/premium/createTranscript.ts @@ -14,6 +14,7 @@ import EmojiEmbed from "../utils/generateEmojiEmbed.js"; import getEmojiByName from "../utils/getEmojiByName.js"; import { PasteClient, Publicity, ExpireDate } from "pastebin-api"; import client from "../utils/client.js"; +import { messageException } from '../utils/createTemporaryStorage.js'; const pbClient = new PasteClient(client.config.pastebinApiKey); @@ -95,6 +96,7 @@ export default async function (interaction: CommandInteraction | MessageComponen const deleted = await (interaction.channel as TextChannel).bulkDelete(fetched, true); deletedCount = deleted.size; messages = messages.concat(Array.from(deleted.values() as Iterable)); + if (messages.length === 1) messageException(interaction.guild!.id, interaction.channel.id, messages[0]!.id) } while (deletedCount === 100); let out = ""; diff --git a/src/utils/client.ts b/src/utils/client.ts index b05ef5f..857fb1d 100644 --- a/src/utils/client.ts +++ b/src/utils/client.ts @@ -32,14 +32,13 @@ class NucleusClient extends Client { callback: (interaction: Interaction) => Promise, check: (interaction: Interaction, partial: boolean) => Promise | boolean, autocomplete: (interaction: AutocompleteInteraction) => Promise - } | undefined,{name: string, description: string}]> = {}; + } | undefined, {name: string, description: string}]> = {}; fetchedCommands = new Collection(); constructor(database: typeof NucleusClient.prototype.database) { super({ intents: 0b1100011011011111111111}); this.database = database; } } - const client = new NucleusClient({ guilds: await new Guilds().setup(), history: new History(), diff --git a/src/utils/commandRegistration/register.ts b/src/utils/commandRegistration/register.ts index 1a19e2c..78e3b0f 100644 --- a/src/utils/commandRegistration/register.ts +++ b/src/utils/commandRegistration/register.ts @@ -111,7 +111,7 @@ async function registerContextMenus() { context.command.setNameLocalizations(context.nameLocalizations ?? {}) commands.push(context.command); - client.commands["contextCommands/message/" + context.command.name] = context; + client.commands["contextCommands/message/" + context.command.name] = [context, {name: context.name ?? context.command.name, description: context.description ?? context.command.description}]; console.log(`${last.replace("└", " ").replace("├", "│")} └─ ${colors.green}Loaded ${file.name} [${i} / ${totalFiles}]${colors.none}`) } catch (e) { @@ -181,6 +181,7 @@ async function registerCommandHandler() { } async function execute(check: Function | undefined, callback: Function | undefined, data: CommandInteraction) { + console.log(client.commands["contextCommands/user/User info"]) if (!callback) return; if (check) { let result; @@ -197,7 +198,7 @@ async function execute(check: Function | undefined, callback: Function | undefin .setColor(NucleusColors.red) .setEmoji(getEmojiByName("CONTROL.BLOCKCROSS")) ], ephemeral: true}); - }; + } } callback(data); } diff --git a/src/utils/database.ts b/src/utils/database.ts index 239da13..e7336d0 100644 --- a/src/utils/database.ts +++ b/src/utils/database.ts @@ -1,3 +1,4 @@ +import type { GuildMember } from "discord.js"; import type Discord from "discord.js"; import { Collection, MongoClient } from "mongodb"; import config from "../config/main.js"; @@ -245,11 +246,36 @@ export class Premium { await this.premium.insertOne({ user: user, appliesTo: [], level: level }); } - async hasPremium(guild: string) { + async hasPremium(guild: string): Promise<[boolean, string, number] | null> { + const entries = await this.premium.find({}).toArray(); + const members = await (await client.guilds.fetch(guild)).members.fetch() + for(const {user} of entries) { + const member = members.get(user); + if(member) { + const modPerms = //TODO: Create list in config for perms + member.permissions.has("Administrator") || + member.permissions.has("ManageChannels") || + member.permissions.has("ManageRoles") || + member.permissions.has("ManageEmojisAndStickers") || + member.permissions.has("ManageWebhooks") || + member.permissions.has("ManageGuild") || + member.permissions.has("KickMembers") || + member.permissions.has("BanMembers") || + member.permissions.has("ManageEvents") || + member.permissions.has("ManageMessages") || + member.permissions.has("ManageThreads") + const entry = entries.find(e => e.user === member.id); + if(entry && (entry.level === 3) && modPerms) return [true, member.id, entry.level]; + } + } const entry = await this.premium.findOne({ - appliesTo: { $in: [guild] } + appliesTo: { + $elemMatch: { + $eq: guild + } + } }); - return entry ? true : false; + return entry ? [true, entry.user, entry.level] : null; } async fetchUser(user: string): Promise { @@ -258,26 +284,55 @@ export class Premium { return entry; } - async checkAllPremium() { + async checkAllPremium(member?: GuildMember) { const entries = await this.premium.find({}).toArray(); - for(const {user, expiresAt} of entries) { - if(expiresAt) expiresAt < Date.now() ? await this.premium.deleteOne({user: user}) : null; - const member = await (await client.guilds.fetch("684492926528651336")).members.fetch(user) - let level: number = 0; - if (member.roles.cache.has("1066468879309750313")) { + if(member) { + const entry = entries.find(e => e.user === member.id); + if(entry) { + const expiresAt = entry.expiresAt; + if(expiresAt) expiresAt < Date.now() ? await this.premium.deleteOne({user: member.id}) : null; + } + const roles = member.roles; + let level = 0; + if (roles.cache.has("1066468879309750313")) { level = 99; - } else if (member.roles.cache.has("1066465491713003520")) { + } else if (roles.cache.has("1066465491713003520")) { level = 1; - } else if (member.roles.cache.has("1066439526496604194")) { + } else if (roles.cache.has("1066439526496604194")) { level = 2; - } else if (member.roles.cache.has("1066464134322978912")) { + } else if (roles.cache.has("1066464134322978912")) { level = 3; } - + await this.updateUser(member.id, level); if (level > 0) { - await this.updateUser(user, level); + await this.premium.updateOne({ user: member.id }, {$unset: { expiresAt: ""}}) } else { - await this.premium.updateOne({ user: user }, { expiresAt: (Date.now() + (1000*60*60*24*3)) }) + await this.premium.updateOne({ user: member.id }, {$set: { expiresAt: (Date.now() + (1000*60*60*24*3)) }}) + } + } else { + const members = await (await client.guilds.fetch('684492926528651336')).members.fetch(); + for(const {roles, id} of members.values()) { + const entry = entries.find(e => e.user === id); + if(entry) { + const expiresAt = entry.expiresAt; + if(expiresAt) expiresAt < Date.now() ? await this.premium.deleteOne({user: id}) : null; + } + let level: number = 0; + if (roles.cache.has("1066468879309750313")) { + level = 99; + } else if (roles.cache.has("1066465491713003520")) { + level = 1; + } else if (roles.cache.has("1066439526496604194")) { + level = 2; + } else if (roles.cache.has("1066464134322978912")) { + level = 3; + } + await this.updateUser(id, level); + if (level > 0) { + await this.premium.updateOne({ user: id }, {$unset: { expiresAt: ""}}) + } else { + await this.premium.updateOne({ user: id }, {$set: { expiresAt: (Date.now() + (1000*60*60*24*3)) }}) + } } } }