diff --git a/assets/emoji.json b/assets/emoji.json new file mode 100644 index 0000000..4357a19 --- /dev/null +++ b/assets/emoji.json @@ -0,0 +1,15 @@ +{ + "answer": { + "yes": "", + "no": "", + "error": "", + "loading": "" + }, + "badge": { + "dev": "<:dev:1398755085441564772>", + "enium": "<:enium_staff:1398755055930179586>", + "buyer": "", + "owner": "", + "dash": "<:dash:1398755072317325403>" + } +} diff --git a/assets/emoji/loading.gif b/assets/emoji/loading.gif new file mode 100644 index 0000000..946c2ea Binary files /dev/null and b/assets/emoji/loading.gif differ diff --git a/src/commands/custom/set.ts b/src/commands/custom/set.ts new file mode 100644 index 0000000..b33e58f --- /dev/null +++ b/src/commands/custom/set.ts @@ -0,0 +1,309 @@ +import { prisma } from '../../lib/prisma.ts'; +import { ActivityType, userMention, roleMention, PresenceUpdateStatus, MessageFlags, SlashCommandBuilder, EmbedBuilder } from 'discord.js'; +import emoji from '../../../assets/emoji.json' assert { type: "json" }; + +export default { + data: new SlashCommandBuilder() + .setName('set') + .setDescription('edit the default behavour of the bot') + .addSubcommand(subcommand => subcommand + .setName('color') + .setDescription('Change the default color for the embed') + .addStringOption(option => + option.setName('color') + .setDescription('The new color by default') + .setRequired(true) + ) + ) + .addSubcommand(subcommand => subcommand + .setName('footer') + .setDescription('Change the default footer for the embed') + .addStringOption(option => + option.setName('text') + .setDescription('The new text by default of the bot') + .setRequired(true) + ) + ) + .addSubcommand(subcommand => subcommand + .setName('pp') + .setDescription('Change the bot profile picture') + .addStringOption(option => + option.setName('link') + .setDescription('The new link to the new profile picture') + .setRequired(true) + ) + ) + .addSubcommand(subcommand => subcommand + .setName('status') + .setDescription('Change the status of the bot') + .addStringOption(option => + option.setName('status') + .setDescription('The new status used by the bot') + .setRequired(true) + ) + .addStringOption(option => + option.setName('presence') + .setDescription('The new presence of the bot') + .setRequired(true) + .addChoices( + { + name: 'Online', + value: 'online' + }, + { + name: 'Do not disturb', + value: 'dnd' + }, + { + name: 'Idle', + value: 'idle' + }, + { + name: 'Invisible', + value: 'invisible' + }, + ) + ) + .addStringOption(option => + option.setName('type') + .setDescription('The type of the new activity') + .setRequired(true) + .addChoices( + { + name: 'Playing', + value: 'play' + }, + { + name: 'Watching', + value: 'watch' + }, + { + name: 'Listening', + value: 'listen' + }, + { + name: 'Competing', + value: 'competing' + }, + { + name: 'Streaming', + value: 'stream' + }, + ) + ) + ), + async execute(interaction: CommandInteraction) { + let guildData: Guild; + try { + guildData = await prisma.guild.findUnique({ + where: { + id: interaction.guild.id + } + }); + } catch (err) { + console.error(`\t⚠️ | INFO => Cannot get the database connection!\n\t\t(${err}).`); + await interaction.reply({ + content: `${emoji.answer.error} | Cannot connect to the database`, + flags: MessageFlags.Ephemeral + }); + return; + } + let userData: User; + try { + userData = await prisma.user.findUnique({ + where: { + id: interaction.user.id + } + }); + } catch (err) { + console.error(`\t⚠️ | Owner => Cannot get the database connection!\n\t\t(${err}).`); + await interaction.reply({ + content: `${emoji.answer.error} | Cannot connect to the database`, + flags: MessageFlags.Ephemeral + }); + return; + } + const subcommand: string = interaction.options.getSubcommand(); + switch (subcommand) { + case 'color': + if (!userData.isOwner) { + await interaction.reply({ + content: `${emoji.answer.no} | This command is only for owner`, + flags: MessageFlags.Ephemeral + }); + return; + } + const newColor: string = interaction.options.getString('color'); + if (!/^#[0-9A-Fa-f]{6}$/.test(newColor)) { + await interaction.reply({ + content: `${emoji.answer.no} | You have to give a color with the syntax: \`#000000\`.`, + flags: MessageFlags.Ephemeral + }); + return; + } + await prisma.guild.upsert({ + where: { + id: interaction.guild.id + }, + update: { + color: newColor + }, + create: { + id: interaction.guild.id, + color: newColor + } + }); + await interaction.reply({ + content: `${emoji.answer.yes} | The default color for embed will be now changed by \`${newColor}\``, + flags: MessageFlags.Ephemeral + }); + return; + case 'footer': + if (!userData.isOwner) { + await interaction.reply({ + content: `${emoji.answer.no} | This command is only for owner`, + flags: MessageFlags.Ephemeral + }); + return; + } + const newFooter: string = interaction.options.getString('text'); + if (newFooter.length > 2048) { + await interaction.reply({ + content: `${emoji.answer.no} | The maximum lenght for the footer is 2048`, + flags: MessageFlags.Ephemeral + }); + return; + } + await prisma.guild.upsert({ + where: { + id: interaction.guild.id + }, + update: { + footer: newFooter + }, + create: { + id: interaction.guild.id, + footer: newFooter + } + }); + await interaction.reply({ + content: `${emoji.answer.yes} | The default footer for embed will be now changed by \`${newFooter}\`.`, + flags: MessageFlags.Ephemeral + }); + return; + case 'pp': + if (!userData.isBuyer) { + await interaction.reply({ + content: `${emoji.answer.no} | This command is only for buyer`, + flags: MessageFlags.Ephemeral + }); + return; + } + const newPicture: string = interaction.options.getString('link'); + try { + interaction.client.user.setAvatar(newPicture); + } catch (err) { + await interaction.reply({ + content: `${emoji.answer.no} | Error during changing the bot profile picture`, + flags: MessageFlags.Ephemeral + }); + } + await interaction.reply({ + content: `${emoji.answer.yes} | The picture profile of the bot is now updated.`, + flags: MessageFlags.Ephemeral + }); + return; + case 'status': + if (!userData.isBuyer) { + await interaction.reply({ + content: `${emoji.answer.no} | This command is only for buyer`, + flags: MessageFlags.Ephemeral + }); + return; + } + const newStatus: string = interaction.options.getString('status'); + const tmpType: string = interaction.options.getString('type'); + let newType: ActivityType; + switch (tmpType) { + case 'play': + newType = ActivityType.Playing; + break; + case 'listen': + newType = ActivityType.Listening; + break; + case 'watch': + newType = ActivityType.Watching; + break; + case 'stream': + newType = ActivityType.Streaming; + break; + case 'competing': + newType = ActivityType.Competing; + break; + } + const tmpPresence: string = interaction.options.getString('presence'); + let newPresence: PresenceUpdateStatus; + switch (tmpPresence) { + case 'online': + newPresence = PresenceUpdateStatus.Online; + break; + case 'idle': + newPresence = PresenceUpdateStatus.Idle; + break; + case 'dnd': + newPresence = PresenceUpdateStatus.DoNotDisturb; + break; + case 'invisible': + newPresence = PresenceUpdateStatus.Invisible; + break; + } + try { + await prisma.bot.upsert({ + where: { + id: 1 + }, + update: { + status: newStatus, + type: tmpType, + presence: newPresence + }, + create: { + id: 1, + status: newStatus, + type: tmpType, + presence: newPresence + } + }); + if (tmpType === 'steam') { + interaction.client.user.setPresence({ + status: newPresence, + activities: [{ + name: newStatus, + type: newType, + url: 'https://twitch.tv/EniumRaphael' + }] + }); + } else { + interaction.client.user.setPresence({ + status: newPresence, + activities: [{ + name: newStatus, + type: newType, + }] + }); + } + } catch (err) { + await interaction.reply({ + content: `${emoji.answer.no} | Cannot change the status\n\n\t${err}`, + flags: MessageFlags.Ephemeral + }); + return; + } + await interaction.reply({ + content: `${emoji.answer.yes} | The new activity is now \`${newStatus}\``, + flags: MessageFlags.Ephemeral + }); + return; + } + } +} diff --git a/src/commands/rank/whitelist.ts b/src/commands/rank/whitelist.ts new file mode 100644 index 0000000..87641f2 --- /dev/null +++ b/src/commands/rank/whitelist.ts @@ -0,0 +1,233 @@ +import { EmbedBuilder, userMention, MessageFlags, SlashCommandBuilder } from 'discord.js'; +import { prisma } from '../../lib/prisma.ts'; +import emoji from '../../../assets/emoji.json' assert { type: "json" }; + +export default { + data: new SlashCommandBuilder() + .setName('whitelist') + .setDescription('Interact with the whitelist') + .addSubcommand(subcommand => subcommand + .setName('add') + .setDescription('Add a user on the whitelist') + .addUserOption(option => + option.setName('target') + .setDescription('The user who will be added to the whitelist') + .setRequired(true) + ) + ) + .addSubcommand(subcommand => subcommand + .setName('delete') + .setDescription('Delete a user on the whitelist') + .addUserOption(option => + option.setName('target') + .setDescription('The user who will be deleted to the whitelist') + .setRequired(true) + ) + ) + .addSubcommand(subcommand => subcommand + .setName('list') + .setDescription('Show the whitelist') + ), + async execute(interaction: CommandInteraction) { + const subcommand = interaction.options.getSubcommand(); + let userData: User; + try { + userData = await prisma.user.findUnique({ + where: { + id: interaction.user.id + } + }); + } catch (err) { + console.error(`\t⚠️ | Whitelist => Cannot get the database connection!\n\t\t(${err}).`); + await interaction.reply({ + content: `${emoji.answer.error} | Cannot connect to the database`, + flags: MessageFlags.Ephemeral + }); + return; + } + let guildData: Guild; + try { + guildData = await prisma.guild.findUnique({ + where: { + id: interaction.guild.id + } + }); + } catch (err) { + console.error(`\t⚠️ | INFO => Cannot get the database connection!\n\t\t(${err}).`); + await interaction.reply({ + content: `${emoji.answer.error} | Cannot connect to the database`, + flags: MessageFlags.Ephemeral + }); + return; + } + const target: GuildMember = interaction.options.getUser('target') + switch (subcommand) { + case 'add': + if (!userData.isOwner) { + await interaction.reply({ + content: `${emoji.answer.no} | This command is only for owner`, + flags: MessageFlags.Ephemeral + }); + return; + } + try { + await prisma.guildUser.upsert({ + where: { + userId_guildId: { + userId: target.id, + guildId: interaction.guild.id + } + }, + update: { + isWlUser: true + }, + create: { + userId: target.id, + guildId: interaction.guild.id, + isWlUser: true + } + }); + await prisma.guild.update({ + where: { + id: interaction.guild.id + }, + data: { + WlUsers: { + connect: { + id: target.id + } + } + } + }); + } catch (err) { + console.error(`⚠️ | Error when adding ${target.username} to the whitelist\n\t${err}`); + await interaction.reply({ + content: `${emoji.answer.error} | Error when adding ${target.username} to the whitelist`, + flags: MessageFlags.Ephemeral + }); + return; + } + await interaction.reply({ + content: `${emoji.answer.yes} | ${target.username} has been added to the whitelist`, + flags: MessageFlags.Ephemeral + }); + return; + case 'delete': + if (!userData.isOwner) { + await interaction.reply({ + content: `${emoji.answer.no} | This command is only for owner`, + flags: MessageFlags.Ephemeral + }); + return; + } else if (interaction.user.id === target.id) { + await interaction.reply({ + content: `${emoji.answer.no} | You cannot removing yourself from the whitelist`, + flags: MessageFlags.Ephemeral + }); + return; + } + try { + await prisma.guildUser.upsert({ + where: { + userId_guildId: { + userId: target.id, + guildId: interaction.guild.id + } + }, + update: { + isWlUser: false + }, + create: { + userId: target.id, + guildId: interaction.guild.id, + isWlUser: false + } + }); + await prisma.guild.update({ + where: { + id: interaction.guild.id + }, + data: { + WlUsers: { + disconnect: { + id: target.id + } + } + } + }); + } catch (err) { + console.error(`⚠️ | Error when removing ${target.username} to the username\n\t${err}`); + await interaction.reply({ + content: `${emoji.answer.error} | Cannot remove ${target.username} from the whitelist`, + flags: MessageFlags.Ephemeral + }); + return; + } + await interaction.reply({ + content: `${emoji.answer.yes} | ${target.username} has been removing to the whitelist`, + flags: MessageFlags.Ephemeral + }); + return; + case 'list': + if (!userData.isOwner) { + await interaction.reply({ + content: `${emoji.answer.no} | This command is only for owner`, + flags: MessageFlags.Ephemeral + }); + return; + } + try { + const guild = await prisma.guild.findUnique({ + where: { + id: interaction.guild.id + }, + include: { + WlUsers: true + } + }); + + if (!guild || guild.WlUsers.length === 0) { + await interaction.reply({ + content: `${emoji.answer.error} | There is no whitelisted user.`, + flags: MessageFlags.Ephemeral + }); + break; + } + + const WlUsers = await Promise.all( + guild.WlUsers.map(async (whitelist) => { + try { + const user = await interaction.client.users.fetch(whitelist.id); + return `- ${user.username} (\`${user.id}\`)\n`; + } catch (err) { + console.warn(`⚠️ | ${whitelist.id} : ${err}`); + return null; + } + }) + ); + + const toSend: EmbedBuilder = new EmbedBuilder() + .setTitle(`🗞️ | Whitelist`) + .setColor(guildData.color) + .setFooter({ + text: guildData.footer + }) + .setDescription(WlUsers.filter(Boolean).join('')) + await interaction.reply({ + embeds: [ + toSend + ], + flags: MessageFlags.Ephemeral + }); + } catch (err) { + console.error(`⚠️ | Whitelist => error when fetching infromation from the database: ${err}`); + await interaction.reply({ + content: `${emoji.answer.error} | Cannot fetch the infromation of the database.`, + flags: MessageFlags.Ephemeral + }); + } + break; + return; + } + } +} diff --git a/src/events/client/guildCreate.ts b/src/events/client/guildCreate.ts new file mode 100644 index 0000000..b54d569 --- /dev/null +++ b/src/events/client/guildCreate.ts @@ -0,0 +1,53 @@ +import { Events, MessageFlags } from 'discord.js' +import { prisma } from '../../lib/prisma.ts'; + +export default { + name: Events.GuildCreate, + async execute(guild, client) { + const botData = await prisma.bot.findUnique({ + where: { id: 1 }, + include: { + buyers: true + } + }); + await prisma.guild.upsert({ + where: { + id: guild.id + }, + update: {}, + create: { + id: guild.id + } + }); + + const members = await guild.members.fetch(); + let i = 0; + for (const [memberId, member] of members) { + await prisma.user.upsert({ + where: { + id: memberId + }, + update: {}, + create: { + id: memberId + } + }); + + await prisma.guildUser.upsert({ + where: { + userId_guildId: { + userId: memberId, + guildId: guild.id + } + }, + update: {}, + create: { + userId: memberId, + guildId: guild.id + } + }); + i++; + } + console.log(`✅ | Guild ${guild.name} synchronisée avec ${members.size} membres.`); + } +}