commit 1906fa49decbc7e9132a93aad23c2d0e851f68b1 Author: ninjdai2 Date: Wed Nov 9 14:44:05 2022 +0100 Whole new version ! Added interactions, brand new ticket system, and much more ! diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..70a2716 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/node_modules +config.json +package-lock.json +database.sqlite diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e0db296 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Art'Portal + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..7565a90 --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +# Bot Discord - Aprıl +Mascotte d'[Art'Portal](https://discord.gg/graphisme) + +Rénovation par @CoolMan#4094, @BakaTaida#5677 et @Dawn#0404 +Artwork par @Frisk#7515 + +Pour installer le bot, vous aurez simplement **besoin d'effectuer cette simple commande** : +``` +npm install +``` +![portalgirl-cool](https://user-images.githubusercontent.com/65647523/167270738-0371e27d-d071-44b7-8560-9e94b45d22a2.png) diff --git a/commands/dev/reload.js b/commands/dev/reload.js new file mode 100644 index 0000000..f07a4bd --- /dev/null +++ b/commands/dev/reload.js @@ -0,0 +1,15 @@ +const { SlashCommandBuilder } = require('discord.js'); +const { devId } = require('../../config.json'); +const { deploy_commands } = require('../../functions.js') + + +module.exports = { + data: new SlashCommandBuilder() + .setName('reload') + .setDefaultMemberPermissions(0x8) + .setDescription('Recharge les commandes du bot (dev only).'), + async execute(interaction, client) { + if (!interaction.user.id == devId) return void interaction.reply({ content: "Permission denied" }); + deploy_commands(client, false); + } +}; \ No newline at end of file diff --git a/commands/misc/document.js b/commands/misc/document.js new file mode 100644 index 0000000..0e7ed1d --- /dev/null +++ b/commands/misc/document.js @@ -0,0 +1,66 @@ +const { SlashCommandBuilder, SelectMenuBuilder, ActionRowBuilder } = require('discord.js'); + +module.exports = { + + data: new SlashCommandBuilder() + .setName('documents') + .setDescription('Afficher des documents') + .addSubcommand(subcommand => + subcommand + .setName('sanctions') + .setDescription('Afficher les documents des sanctions')), + + async execute(interaction) { + switch (interaction.options.getSubcommand()) { + case 'sanctions': + await interaction.reply({ components: [sanctionembedrow], ephemeral: true }); + break; + } + } + +}; + + +const sanctionembedrow = new ActionRowBuilder() + .addComponents( + new SelectMenuBuilder() + .setCustomId('document_sanctions') + .setPlaceholder('Navigateur') + .addOptions([ + { + label: 'Page 0', + description: 'Couverture', + value: '0', + }, + { + label: 'Page 1', + description: 'Notes', + value: '1', + }, + { + label: 'Page 2', + description: 'Table des matières', + value: '2', + }, + { + label: 'Page 3', + description: 'Articles 1 & 2', + value: '3', + }, + { + label: 'Page 4', + description: 'Article 3', + value: '4', + }, + { + label: 'Page 5', + description: 'Articles 4 & 5', + value: '5', + }, + { + label: 'Page 6', + description: 'Articles 6 & 7', + value: '6', + }, + ]), + ); diff --git a/commands/misc/info.js b/commands/misc/info.js new file mode 100644 index 0000000..c2a78a5 --- /dev/null +++ b/commands/misc/info.js @@ -0,0 +1,150 @@ +const { SlashCommandBuilder } = require('@discordjs/builders'); +const { EmbedBuilder, ButtonBuilder, ActionRowBuilder } = require('discord.js'); + +module.exports = { + data: new SlashCommandBuilder() + .setName('info') + .setDescription('Obtenir des informations diverses.') + .addSubcommand(subcommand => + subcommand + .setName('user') + .setDescription('Obtenir des informations sur un utilisateur.') + .addUserOption(option => + option.setName('target') + .setDescription('Utilisateur ciblé') + .setRequired(true))) + .addSubcommand(subcommand => + subcommand + .setName('server') + .setDescription('Obtenir des informations sur le serveur.')) + .addSubcommand(subcommand => + subcommand + .setName('april') + .setDescription('Obtenir des informations sur April')), + + async execute(interaction, client) { + switch(interaction.options.getSubcommand()) { + case 'user': + const user = interaction.options.getUser('target'); + const member = interaction.options.getMember('target')//interaction.guild.members.cache.get(user.id); + const embedUSERINFO = new EmbedBuilder() + + if (user) { + embedUSERINFO + .setAuthor({ + name: user.tag, + iconURL: user.avatarURL() + }) + .setColor("Blurple") + .setThumbnail(user.avatarURL()) + .setDescription(`<@${user.id}>`) + .addFields([ + { + name: "👤 Informations sur le compte", + value: `` + +`<:invisibleSpacer:1038116840360120360><:iconID:1038063974807261195> **ID:** ${user.id}\n` + +`<:invisibleSpacer:1038116840360120360><:iconProfile:1038064029064773724> **Nom complet:** ${user.tag}\n` + +`<:invisibleSpacer:1038116840360120360><:iconProfile:1038064029064773724> **Bot:** ${user.bot ? "Oui" : "Non"}\n` + +`<:invisibleSpacer:1038116840360120360><:iconTimer:1038063915151654932> **Créé:** ` + , + inline: false + } + ]); + + if (member){ + embedUSERINFO.addFields([ + { + name: "📋 Information sur le membre", + value: + `<:invisibleSpacer:1038116840360120360><:iconTimer:1038063915151654932> **A rejoint le serveur:** \n` + +`<:invisibleSpacer:1038116840360120360><:iconProfile:1038064029064773724> **Nickname:** ${member.nickname || `Aucun`}\n` + +`<:invisibleSpacer:1038116840360120360><:IconAnnouncement:1038063917026508881> **Plus haut rôle:** ${member.roles.hoist ? member.roles.hoist.name : "Aucun"}` + , + inline: false + }, + { + name: `📝 Rôles [${member.roles.cache.size - 1}]`, + value: member.roles.cache.size ? member.roles.cache.map(roles => `**${roles}**`).slice(0, 20).join(" ") : "None", + inline: false + }]) + } + } else { + embedUSERINFO.setDescription("Utilisateur inconnu") + } + + await interaction.reply({ + embeds: [embedUSERINFO], + ephemeral: false + }); + break; + + case 'server': + const owner = await interaction.guild.fetchOwner(); + let openticketqty = 0; + interaction.guild.channels.cache.forEach(element => { + if (element.name.includes("bénévole") || element.name.includes("rémunéné")) openticketqty++; + }); + let takenticketsqty = 0; + interaction.guild.channels.cache.forEach(element => { + if ((element.name.includes("bénévole") &&!element.name.startsWith("bénévole")) || (element.name.includes("rémunéré") && !element.name.startsWith("rémunéré"))) takenticketsqty++; + }); + const embedSERVINFO = new EmbedBuilder() + .setAuthor({ + name: interaction.guild.name + }) + .setColor("Blurple") + .setThumbnail(interaction.guild.iconURL()) + .addFields( + { + name: `Propriétaire`, + value: `<@${owner.user.id}>`, + inline: true + }, + { + name: `Date de création du serveur`, + value: ``, + inline: true + }, + { + name: `ID du serveur`, + value: `${interaction.guild.id}`, + inline: false + }, + { + name: `Nombre total de membres`, + value: `${interaction.guild.memberCount}`, + inline: true + }, + { + name: "Nombre de salons", + value: `${interaction.guild.channels.cache.size}`, + inline: true + }, + { + name: "Tickets", + value: `**Ouverts** : ${openticketqty}\n**Pris en charge** : ${takenticketsqty}`, + inline: true + } + ) + await interaction.reply({ + embeds:[embedSERVINFO], + ephemeral: false + }); + break; + + case 'april': + const embedBOTINFO = new EmbedBuilder() + .setAuthor({ + name: "April" + }) + .setColor("Blurple") + .setThumbnail("https://media.discordapp.net/attachments/867491241491038209/987292546180984832/april-welcome.png") + .setDescription("Euh oui voilà april da best je ferais un description un jour :3") + await interaction.reply({ + embeds: [embedBOTINFO], + ephemeral: false + }) + break; + } + } +}; \ No newline at end of file diff --git a/commands/misc/lovecalc.js b/commands/misc/lovecalc.js new file mode 100644 index 0000000..d8fdc4b --- /dev/null +++ b/commands/misc/lovecalc.js @@ -0,0 +1,60 @@ +const { SlashCommandBuilder } = require('@discordjs/builders'); +const { MessageEmbed, EmbedBuilder } = require('discord.js') + +module.exports = { + data: new SlashCommandBuilder() + .setName('lovecalc') + .setDescription('Pour calculer le pourcentage d\'amour avec April !') + .addUserOption(option => option.setName('utilisateur') + .setDescription('Utilisateur avec qui tester le lovecalc') + .setRequired(false)), + async execute(interaction) { + try { + let user = interaction.options.getUser('utilisateur'); + if (!user) user = interaction.user; + + loveuser = user.id.substring(0, 19); + + var love = Number(Number(String(String(loveuser).substring(17)).replace("0", "8").replace("1", "8")) * Number(String("858387628567298108".substring(17)).replace("0", "8").replace("1", "8")) + Number(Number(String(String(loveuser).substring(7, 8)).replace("0", "8").replace("1", "8")) + Number(String("858387628567298108".substring(7, 8)).replace("0", "8").replace("1", "8")))); + + let textlove = ""; + let image; + if (loverates[user.id]){ + textlove = loverates[user.id][0]; + image = loverates[user.id][1] || null; + }else if (love < 10) { + textlove = `${love}% d'amitié avec ${user.username}?! MAMAN J'AI PEUR`; + image = "https://media.discordapp.net/attachments/867491241491038209/970423542602678292/portalgirl-peur.png"; + }else if (love <= 20) { + textlove = `${user.username} je t'apprécie à ${love}%, n'espère pas m'approcher !`; + image = "https://media.discordapp.net/attachments/867491241491038209/970423539981234267/portalgirl-couteau.webp"; + }else if (love <= 50) { + textlove = `${love}% d'amitié avec ${user.username}, ce n'est pas énorme ¯\_(ツ)_/¯`; + image = "https://media.discordapp.net/attachments/867491241491038209/970423540635562035/portalgirl-dodo.webp"; + }else if (love <= 80) { + textlove = `Toi ${user.username}, je t'apprécie à ${love}%, c'est pas mal nan ?`; + image = "https://media.discordapp.net/attachments/867491241491038209/987466337095917568/AprilStyle-min.png"; + }else{ + if(love>100) love = 100 + textlove = `${love}% ! T'as l'air vachement sympa ${user.username} !`; + image = "https://media.discordapp.net/attachments/867491241491038209/970423543626092604/portalgirl-wouah.webp"; + } + + var loveEmbed = new EmbedBuilder() + .setColor('#ff00d0') + .setTitle(textlove) + .setImage(image) + .setTimestamp(); + await interaction.reply({ embeds: [loveEmbed] }); + } catch (error) { + console.error(error) + } + }, +}; + +const loverates = { + "697438073646088194": ["Je l'aime bien, lui, même si quand je le vois j'ai envie de poulet rôti je sais pas pourquoi", "https://media.discordapp.net/attachments/867491241491038209/1036987746457235526/april_sip.png"],//CoolMan + "277136155244232706": ["Dawn ? HMMMMMMMMMMMM", "https://media.discordapp.net/attachments/867491241491038209/1036987746809548860/AprilThinking.png"],//Ced + "718456289704804392": ["MAMAN JTM <333", "https://media.discordapp.net/attachments/867491241491038209/1036987744670457907/april_cat.png"], + "397867150867693579": ["Il a des bons gouts musicaux lui", "https://cdn.discordapp.com/attachments/867491241491038209/1036988529248567306/AprilMusic.png"] +} \ No newline at end of file diff --git a/commands/misc/ping.js b/commands/misc/ping.js new file mode 100644 index 0000000..fb251ac --- /dev/null +++ b/commands/misc/ping.js @@ -0,0 +1,40 @@ +const { SlashCommandBuilder } = require('discord.js'); +const { ActionRowBuilder, EmbedBuilder, ButtonBuilder, ButtonStyle } = require('discord.js') + +module.exports = { + data: new SlashCommandBuilder() + .setName('ping') + .setDescription('Obtenir la latence du bot.'), + + async execute(interaction, client) { + const pingRefreshButton = new ButtonBuilder() + .setCustomId('pingrefreshbtn') + .setEmoji("🔁") + .setStyle(ButtonStyle.Primary) + + const row = new ActionRowBuilder() + .addComponents([ + pingRefreshButton + ]) + + const sent = await interaction.reply({ + content: 'Pinging...', + components:[row], + fetchReply: true + }); + + const latency = new EmbedBuilder() + .setColor(`#7961fd`) + .setTitle(`🏓 Pong ! Aprıl v4.0.0\n`) + .setDescription( + "\n" + + `**Latence :** ${sent.createdTimestamp - interaction.createdTimestamp}ms\n` + + `**API :** ${Math.round(client.ws.ping)}ms` + ) + + interaction.editReply({ + content:" ", + embeds:[latency] + }); + }, +}; diff --git a/commands/misc/say.js b/commands/misc/say.js new file mode 100644 index 0000000..a997a33 --- /dev/null +++ b/commands/misc/say.js @@ -0,0 +1,38 @@ +const { SlashCommandBuilder, PermissionsBitField } = require('discord.js'); + +module.exports = { + data: new SlashCommandBuilder() + .setName('say') + .setDescription('Faire envoyer un message au bot') + .setDefaultMemberPermissions(0x8) + .addStringOption(option => + option.setName('message') + .setDescription('Message à envoyer') + .setRequired(true)) + .addChannelOption(option => + option.setName('destination') + .setDescription('Sélectionnez le salon où envoyer le message!') + .setRequired(false)), + async execute(interaction) { + let msgtosend = interaction.options.getString('message'); + msgtosend = msgtosend.substring(0,2000); + + let channeltosend = interaction.options.getChannel('destination'); + if (!channeltosend) { + channeltosend = interaction.channel + } + + try { + channeltosend.send(msgtosend) + await interaction.reply({ + content: "Message envoyé !", + ephemeral: true + }) + } catch { + await interaction.reply({ + content: "Erreur : Je n'ai probablement pas la permission d'envoyer des messages ou le message est trop long", + ephemeral: true + }) + } + }, +}; \ No newline at end of file diff --git a/commands/misc/support.js b/commands/misc/support.js new file mode 100644 index 0000000..cfed191 --- /dev/null +++ b/commands/misc/support.js @@ -0,0 +1,33 @@ +const { SlashCommandBuilder, EmbedBuilder } = require('discord.js') + +module.exports = { + data: new SlashCommandBuilder() + .setName('help') + .setDescription('Afficher l\'aide du serveur'), + async execute(interaction){ + await interaction.reply({ + embeds: [ + new EmbedBuilder() + .setTitle('Tuto AP LOL') + .setColor('#4f00fc') + .setDescription('Description, placeholder, tuto hahahaha'), + new EmbedBuilder() + .setTitle('SuItE Tuto AP LOL') + .setColor('#7500fc') + .setDescription('Suite Description, Suite placeholder, Suite tuto hahahaha'), + new EmbedBuilder() + .setTitle('SuItE Tuto AP LOL') + .setColor('#9f00fc') + .setDescription('Suite Description, Suite placeholder, Suite tuto hahahaha'), + new EmbedBuilder() + .setTitle('SuItE Tuto AP LOL') + .setColor('#c500fc') + .setDescription('Suite Description, Suite placeholder, Suite tuto hahahaha'), + new EmbedBuilder() + .setTitle('SuItE Tuto AP LOL') + .setColor('#fc00f8') + .setDescription('Suite Description, Suite placeholder, Suite tuto hahahaha'), + ] + }) + } +} \ No newline at end of file diff --git a/commands/misc/userinfocontextmenu.js b/commands/misc/userinfocontextmenu.js new file mode 100644 index 0000000..5091571 --- /dev/null +++ b/commands/misc/userinfocontextmenu.js @@ -0,0 +1,60 @@ +const { ContextMenuCommandBuilder, EmbedBuilder } = require('discord.js') + +module.exports = { + data: new ContextMenuCommandBuilder() + .setName('UserInfo') + .setType(2), + async execute(interaction, client) { + const user = interaction.targetUser; + const member = interaction.targetMember; + + const embedUSERINFO = new EmbedBuilder() + if (user) { + embedUSERINFO + .setAuthor({ + name: user.tag, + iconURL: user.avatarURL() + }) + .setColor("Blurple") + .setThumbnail(user.avatarURL()) + .setDescription(`<@${user.id}>`) + .addFields([ + { + name: "👤 Informations sur le compte", + value: `` + + `<:invisibleSpacer:1038116840360120360><:iconID:1038063974807261195> **ID:** ${user.id}\n` + + `<:invisibleSpacer:1038116840360120360><:iconProfile:1038064029064773724> **Nom complet:** ${user.tag}\n` + + `<:invisibleSpacer:1038116840360120360><:iconProfile:1038064029064773724> **Bot:** ${user.bot ? "Oui" : "Non"}\n` + + `<:invisibleSpacer:1038116840360120360><:iconTimer:1038063915151654932> **Créé:** ` + , + inline: false + } + ]); + + if (member) { + embedUSERINFO.addFields([ + { + name: "📋 Information sur le membre", + value: + `<:invisibleSpacer:1038116840360120360><:iconTimer:1038063915151654932> **A rejoint le serveur:** \n` + + `<:invisibleSpacer:1038116840360120360><:iconProfile:1038064029064773724> **Nickname:** ${member.nickname || `Aucun`}\n` + + `<:invisibleSpacer:1038116840360120360><:IconAnnouncement:1038063917026508881> **Plus haut rôle:** ${member.roles.hoist ? member.roles.hoist.name : "Aucun"}` + , + inline: false + }, + { + name: `📝 Rôles [${member.roles.cache.size - 1}]`, + value: member.roles.cache.size ? member.roles.cache.map(roles => `**${roles}**`).slice(0, 20).join(" ") : "None", + inline: false + }]) + } + } else { + embedUSERINFO.setDescription("Utilisateur inconnu") + } + + await interaction.reply({ + embeds: [embedUSERINFO], + ephemeral: false + }); + } +} \ No newline at end of file diff --git a/commands/moderation/ban.js b/commands/moderation/ban.js new file mode 100644 index 0000000..356f0f4 --- /dev/null +++ b/commands/moderation/ban.js @@ -0,0 +1,79 @@ +const { SlashCommandBuilder } = require('@discordjs/builders'); +const { EmbedBuilder, ButtonBuilder, ActionRowBuilder } = require('discord.js'); +const { sanctionChannelId } = require('../../config.json'); + +module.exports = { + data: new SlashCommandBuilder() + .setName('ban') + .setDescription('Bannir un utilisateur !') + .setDefaultMemberPermissions(0x4) + .addUserOption( + option => + option + .setName('user') + .setDescription('Membre à bannir / id si le membre n\'est pas sur le serveur') + .setRequired(true)) + .addStringOption( + option => + option + .setName('reason') + .setDescription('Raison du bannissement') + .setRequired(true)), + + async execute(interaction, client) { + // if(!interaction.member.permissions.has(0x4)) return interaction.reply({content: `Vous n'avez pas la permisssion \`BAN_MEMBERS\` pour effectuer cette commande.`, ephemeral: true}); + + const user = interaction.options.getUser('user'); + const member = interaction.options.getMember('user'); + const reason = interaction.options.getString('reason'); + + if (member){ + const userRoleRawPos = member.roles.highest.rawPosition; + const memberRoleRawPos = interaction.member.roles.highest.rawPosition; + if (user.id === interaction.user.id) return interaction.reply({content: `Vous ne pouvez pas vous bannir vous-même! !`, ephemeral: true}); + if (userRoleRawPos >= memberRoleRawPos) return interaction.reply({content: `Vous ne pouvez pas bannir cet utilisateur.`, ephemeral: true}); + if (!member.bannable) return interaction.reply({content: `Je ne peux pas bannir cet utilisateur. Cela est dû au fait que l'utilisateur est modérateur/administrateur ou que son rôle est au dessus du rôle du bot...`, ephemeral: true}); + } + await interaction.guild.bans.create(user.id, {reason: reason + " - Banni.e par " + interaction.member.user.tag}); + + const banEMBED = new EmbedBuilder() + .setColor(`#009500`) + .setThumbnail(`https://i.imgur.com/zcZsfNA.png`) + .setTitle(`➔ Art' Portal - Bannissement`) + .addFields( + { + name: "・Utilisateur.trice・", + value: `**Tag: ${user.tag}\nID: ${user.id}**`, + inline: true + }, + { + name: "・Raison du bannissement・", + value: `**${reason !== null ? `${reason}` : 'No reason specified'}**`, + inline: true + }, + { + name: `・Modérateur.trice・`, + value: `**${interaction.member.user.tag}**` + }, + { + name: `・Date・`, + value: ``, + inline: true + }, + ); + await interaction.reply({embeds: [banEMBED], ephemeral: true}); + const channel = await interaction.guild.channels.cache.get(sanctionChannelId); + await channel.send({ + embeds: [banEMBED] + }); + await client.database.modlog.create({ + name: user.id, + username: user.tag, + type: "Ban", + reason: reason, + timestamp: Math.floor(new Date().getTime()/1000), + moderatorid: interaction.member.user.id + }) + + } +}; \ No newline at end of file diff --git a/commands/moderation/banContextMenu.js b/commands/moderation/banContextMenu.js new file mode 100644 index 0000000..2f511bf --- /dev/null +++ b/commands/moderation/banContextMenu.js @@ -0,0 +1,44 @@ +const { ContextMenuCommandBuilder, ModalBuilder, ActionRowBuilder, TextInputBuilder, TextInputStyle } = require('discord.js'); +const { sanctionChannelId } = require('../../config.json'); + +module.exports = { + data: new ContextMenuCommandBuilder() + .setName('Bannissement') + .setType(2) + .setDefaultMemberPermissions(0x4), + + async execute(interaction) { + const user = interaction.targetUser; + + const banModal = new ModalBuilder() + .setTitle(`Bannissement`) + .setCustomId('modmodal_ban') + .setComponents([ + new ActionRowBuilder() + .setComponents( + new TextInputBuilder() + .setCustomId('userid') + .setLabel('Id de la personne') + .setRequired(true) + .setValue(user.id) + .setPlaceholder('Id automatiquement complétée') + .setStyle(TextInputStyle.Short) + .setMinLength(18) + .setMaxLength(21) + ), + new ActionRowBuilder() + .setComponents( + new TextInputBuilder() + .setCustomId('reason') + .setLabel('Raison du ban') + .setRequired(true) + .setPlaceholder('Ex: Spam contenu 18+') + .setStyle(TextInputStyle.Short) + .setMinLength(10) + .setMaxLength(1000) + ), + + ]) + interaction.showModal(banModal) + } +}; diff --git a/commands/moderation/clear.js b/commands/moderation/clear.js new file mode 100644 index 0000000..6561eb2 --- /dev/null +++ b/commands/moderation/clear.js @@ -0,0 +1,23 @@ +const { SlashCommandBuilder } = require('@discordjs/builders'); +const { EmbedBuilder, ButtonBuilder, ActionRowBuilder } = require('discord.js'); + +module.exports = { + data: new SlashCommandBuilder() + .setName('clear') + .setDefaultMemberPermissions(0x2) + .addIntegerOption( + option => + option + .setName('nombre') + .setDescription('Quantité de messages à supprimer') + .setMinValue(1) + .setMaxValue(100) + .setRequired(true) + ) + .setDescription('Supprimer un grand nombre de messages d\'un salon'), + async execute(interaction, client) { + const number = interaction.options.getInteger('nombre'); + await interaction.channel.bulkDelete(number); + await interaction.reply({ content: `J'ai bien supprimé ${number} message${number>1 ? "s" : ""} dans ce salon`, ephemeral: true}); + } +}; \ No newline at end of file diff --git a/commands/moderation/kick.js b/commands/moderation/kick.js new file mode 100644 index 0000000..4e2338d --- /dev/null +++ b/commands/moderation/kick.js @@ -0,0 +1,78 @@ +const { SlashCommandBuilder } = require('@discordjs/builders'); +const { EmbedBuilder, ButtonBuilder, ActionRowBuilder } = require('discord.js'); +const { sanctionChannelId } = require('../../config.json'); + +module.exports = { + data: new SlashCommandBuilder() + .setName('kick') + .setDescription('Expulser un utilisateur !') + .setDefaultMemberPermissions(0x2) + .addUserOption( + option => + option + .setName('user') + .setDescription('Membre à kick') + .setRequired(true)) + .addStringOption( + option => + option + .setName('reason') + .setDescription('Raison de l\'expulsion') + .setRequired(true)), + + async execute(interaction, client) { + // if(!interaction.member.permissions.has(0x4)) return interaction.reply({content: `Vous n'avez pas la permisssion \`BAN_MEMBERS\` pour effectuer cette commande.`, ephemeral: true}); + + const user = interaction.options.getUser('user'); + const member = interaction.options.getMember('user'); + const reason = interaction.options.getString('reason'); + + if (member){ + const userRoleRawPos = member.roles.highest.rawPosition; + const memberRoleRawPos = interaction.member.roles.highest.rawPosition; + if(user.id === interaction.user.id) return interaction.reply({content: `Vous ne pouvez pas vous expulser vous-même vous-même!`, ephemeral: true}); + if(userRoleRawPos >= memberRoleRawPos) return interaction.reply({content: `Vous ne pouvez pas expulser cet utilisateur.`, ephemeral: true}); + if(!member.bannable) return interaction.reply({content: `Je ne peux pas expulser cet utilisateur. Cela est dû au fait que l'utilisateur est modérateur/administrateur ou que son rôle est au dessus du rôle du bot...`, ephemeral: true}); + } else return interaction.reply({ content: "Le membre sélectionné n'est pas présent sur le serveur !", ephemeral: true }); + await member.kick( {reason: reason + " - Expulsé.e par " + interaction.member.user.tag} ); + + const kickEMBED = new EmbedBuilder() + .setColor(`#009500`) + .setThumbnail(`https://i.imgur.com/zcZsfNA.png`) + .setTitle(`➔ Art' Portal - Expulsion`) + .addFields( + { + name: "・Utilisateur.trice・", + value: `**Tag: ${user.tag}\nID: ${user.id}**`, + inline: true + }, + { + name: "・Raison de l'expulsion", + value: `**${reason !== null ? `${reason}` : 'No reason specified'}**`, + inline: true + }, + { + name: `・Modérateur.trice・`, + value: `**${interaction.member.user.tag}**` + }, + { + name: `・Date・`, + value: ``, + inline: true + }, + ); + await interaction.reply({embeds: [kickEMBED], ephemeral: true}); + const channel = await interaction.guild.channels.cache.get(sanctionChannelId); + await channel.send({ + embeds: [kickEMBED] + }); + await client.database.modlog.create({ + name: user.id, + username: user.tag, + type: "Kick", + reason: reason, + timestamp: Math.floor(new Date().getTime()/1000), + moderatorid: interaction.member.user.id + }) + } +}; \ No newline at end of file diff --git a/commands/moderation/mute.js b/commands/moderation/mute.js new file mode 100644 index 0000000..44bb817 --- /dev/null +++ b/commands/moderation/mute.js @@ -0,0 +1,84 @@ +const { SlashCommandBuilder } = require('@discordjs/builders'); +const { EmbedBuilder, ButtonBuilder, ActionRowBuilder } = require('discord.js'); +const { sanctionChannelId } = require('../../config.json'); + +module.exports = { + data: new SlashCommandBuilder() + .setName('mute') + .setDefaultMemberPermissions(0x2) + .addUserOption( + option => + option + .setName('user') + .setDescription('Membre à kick') + .setRequired(true) + ) + .addIntegerOption( + option => + option + .setName('duration') + .setDescription('Durée du mute en minutes') + .setMinValue(1) + .setRequired(true) + ) + .addStringOption( + option => + option + .setName('reason') + .setDescription('Raison du mute') + .setRequired(true) + ) + .setDescription('Rendre un membre muet'), + async execute(interaction, client) { + const duration = interaction.options.getInteger('duration'); + const member = interaction.options.getMember('user'); + const reason = interaction.options.getString('reason'); + if (member){ + const userRoleRawPos = member.roles.highest.rawPosition; + const memberRoleRawPos = interaction.member.roles.highest.rawPosition; + if(member.user.id === interaction.user.id) return interaction.reply({content: `Vous ne pouvez pas vous mute vous-même vous-même! !`, ephemeral: true}); + if(userRoleRawPos >= memberRoleRawPos) return interaction.reply({content: `Vous ne pouvez pas mute cet utilisateur.`, ephemeral: true}); + if(!member.bannable) return interaction.reply({content: `Je ne peux pas mute cet utilisateur. Cela est dû au fait que l'utilisateur est modérateur/administrateur ou que son rôle est au dessus du rôle du bot...`, ephemeral: true}); + } else return interaction.reply({ content: "Le membre sélectionné n'est pas présent sur le serveur !", ephemeral: true }); + await member.timeout(duration * 60 * 1000, {reason: reason + " - Mute par " + interaction.member.user.tag} ); + + const muteEMBED = new EmbedBuilder() + .setColor(`#009500`) + .setThumbnail(`https://i.imgur.com/zcZsfNA.png`) + .setTitle(`➔ Art' Portal - Mute`) + .addFields( + { + name: "・Utilisateur.trice・", + value: `**Tag: ${member.user.tag}\nID: ${member.user.id}**`, + inline: true + }, + { + name: "・Raison du mute", + value: `**${reason !== null ? `${reason}` : 'No reason specified'}**`, + inline: true + }, + { + name: `・Modérateur.trice・`, + value: `**${interaction.member.user.tag}**` + }, + { + name: `・Date・`, + value: ``, + inline: true + }, + ); + await interaction.reply({embeds: [muteEMBED], ephemeral: true}); + const channel = await interaction.guild.channels.cache.get(sanctionChannelId); + await channel.send({ + embeds: [muteEMBED] + }); + await client.database.modlog.create({ + name: member.user.id, + username: member.user.tag, + type: "Mute", + reason: reason, + timestamp: Math.floor(new Date().getTime()/1000), + moderatorid: interaction.member.user.id + }) + } +}; \ No newline at end of file diff --git a/commands/setup/embed.js b/commands/setup/embed.js new file mode 100644 index 0000000..5a31ead --- /dev/null +++ b/commands/setup/embed.js @@ -0,0 +1,82 @@ +const { SlashCommandBuilder, ActionRowBuilder, EmbedBuilder, ButtonBuilder, ButtonStyle } = require('discord.js'); + + +module.exports = { + data: new SlashCommandBuilder() + .setName('embed') + .setDescription('Utiliser le créateur d\'embed de April') + .setDefaultMemberPermissions(0x8) + .addSubcommand(subcommand => + subcommand + .setName('create') + .setDescription('Lancer le processus de création d\'embed.')), + async execute(interaction) { + switch (interaction.options.getSubcommand()) { + case 'create': + await interaction.reply({ embeds: [baseembed], components: embedbuilderrows, ephemeral: true }); + break; + } + } +}; +let baseembed = new EmbedBuilder() + .setTitle("Constructeur d'embed") + .setDescription("Bienvenue sur le constructeur interactif d'embed !\nChoisissez vos options (seule la description et le titre sont requis).\nUn fois fini, munissez-vous de l'id du salon dans lequel vous souhaitez envoyer le message et cliquez sur \"Envoyer\""); + +let row1 = new ActionRowBuilder() + .addComponents([ + new ButtonBuilder() + .setCustomId("embedbuilder_create-author") + .setLabel("Auteur") + .setStyle(ButtonStyle.Secondary), + new ButtonBuilder() + .setCustomId("embedbuilder_create-title") + .setLabel("Titre") + .setStyle(ButtonStyle.Secondary), + new ButtonBuilder() + .setCustomId("embedbuilder_create-description") + .setLabel("Description Text") + .setStyle(ButtonStyle.Secondary), + new ButtonBuilder() + .setCustomId("embedbuilder_create-footer") + .setLabel("Texte du bas") + .setStyle(ButtonStyle.Secondary), + new ButtonBuilder() + .setCustomId("embedbuilder_create-color") + .setLabel("Couleur de l'embed") + .setStyle(ButtonStyle.Secondary) + ]); +let row2 = new ActionRowBuilder() + .addComponents([ + new ButtonBuilder() + .setCustomId("embedbuilder_create-thumbnail") + .setLabel("Image miniature") + .setStyle(ButtonStyle.Secondary), + new ButtonBuilder() + .setCustomId("embedbuilder_create-image") + .setLabel("Grande Image") + .setStyle(ButtonStyle.Secondary), + new ButtonBuilder() + .setCustomId(`embedbuilder_create-messagecontent`) + .setStyle(ButtonStyle.Secondary) + .setLabel("Ajouter un message à l'embed") + ]); +let row3 = new ActionRowBuilder() + .addComponents([ + new ButtonBuilder() + .setCustomId("embedbuilder_create-post") + .setStyle(ButtonStyle.Danger) + .setLabel("Envoyer"), + new ButtonBuilder() + .setCustomId("embedbuilder_create-getexisting") + .setStyle(ButtonStyle.Danger) + .setLabel("Copier préexistant"), + new ButtonBuilder() + .setCustomId("embedbuilder_create-editexisting") + .setStyle(ButtonStyle.Danger) + .setLabel("Modifier préexistant"), + new ButtonBuilder() + .setCustomId("embedbuilder_create-createthread") + .setStyle(ButtonStyle.Danger) + .setLabel("Envoyer dans forum") + ]); +let embedbuilderrows = [row1, row2, row3]; \ No newline at end of file diff --git a/commands/setup/embedBuilderContextMenu.js b/commands/setup/embedBuilderContextMenu.js new file mode 100644 index 0000000..dc73757 --- /dev/null +++ b/commands/setup/embedBuilderContextMenu.js @@ -0,0 +1,77 @@ +const { ContextMenuCommandBuilder, ApplicationCommandType, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js'); + +module.exports= { + data: new ContextMenuCommandBuilder() + .setName('EmbedBuilder') + .setType(ApplicationCommandType.Message) + .setDefaultMemberPermissions(0x8), + async execute(interaction){ + const embed = interaction.targetMessage.embeds[0] || baseembed; + + await interaction.reply({ embeds: [embed], components: embedbuilderrows, ephemeral: true }); + + } +} + +let baseembed = new EmbedBuilder() + .setTitle("Constructeur d'embed") + .setDescription("Bienvenue sur le constructeur interactif d'embed !\nChoisissez vos options (seule la description et le titre sont requis).\nUn fois fini, munissez-vous de l'id du salon dans lequel vous souhaitez envoyer le message et cliquez sur \"Envoyer\""); + +let row1 = new ActionRowBuilder() + .addComponents([ + new ButtonBuilder() + .setCustomId("embedbuilder_create-author") + .setLabel("Auteur") + .setStyle(ButtonStyle.Secondary), + new ButtonBuilder() + .setCustomId("embedbuilder_create-title") + .setLabel("Titre") + .setStyle(ButtonStyle.Secondary), + new ButtonBuilder() + .setCustomId("embedbuilder_create-description") + .setLabel("Description Text") + .setStyle(ButtonStyle.Secondary), + new ButtonBuilder() + .setCustomId("embedbuilder_create-footer") + .setLabel("Texte du bas") + .setStyle(ButtonStyle.Secondary), + new ButtonBuilder() + .setCustomId("embedbuilder_create-color") + .setLabel("Couleur de l'embed") + .setStyle(ButtonStyle.Secondary) + ]); +let row2 = new ActionRowBuilder() + .addComponents([ + new ButtonBuilder() + .setCustomId("embedbuilder_create-thumbnail") + .setLabel("Image miniature") + .setStyle(ButtonStyle.Secondary), + new ButtonBuilder() + .setCustomId("embedbuilder_create-image") + .setLabel("Grande Image") + .setStyle(ButtonStyle.Secondary), + new ButtonBuilder() + .setCustomId(`embedbuilder_create-messagecontent`) + .setStyle(ButtonStyle.Secondary) + .setLabel("Ajouter un message à l'embed") + ]); +let row3 = new ActionRowBuilder() + .addComponents([ + new ButtonBuilder() + .setCustomId("embedbuilder_create-post") + .setStyle(ButtonStyle.Danger) + .setLabel("Envoyer"), + new ButtonBuilder() + .setCustomId("embedbuilder_create-getexisting") + .setStyle(ButtonStyle.Danger) + .setLabel("Copier préexistant"), + new ButtonBuilder() + .setCustomId("embedbuilder_create-editexisting") + .setStyle(ButtonStyle.Danger) + .setLabel("Modifier préexistant"), + new ButtonBuilder() + .setCustomId("embedbuilder_create-createthread") + .setStyle(ButtonStyle.Danger) + .setLabel("Envoyer dans forum") + ]); +let embedbuilderrows = [row1, row2, row3]; \ No newline at end of file diff --git a/commands/setup/setup.js b/commands/setup/setup.js new file mode 100644 index 0000000..80ab690 --- /dev/null +++ b/commands/setup/setup.js @@ -0,0 +1,93 @@ +const { SlashCommandBuilder, EmbedBuilder, ButtonBuilder, ActionRowBuilder, SelectMenuBuilder, ChannelType } = require('discord.js'); +const SetupTickets = require('./setupcommands/tickets.js'); +const SetupPanel = require('./setupcommands/panels.js'); +const SetupMod = require('./setupcommands/moderation.js'); + +module.exports = { + data: new SlashCommandBuilder() + .setName('setup') + .setDescription('Effectuer une mise en place.') + .setDefaultMemberPermissions(0x8) + .addSubcommand( + subcommand => + subcommand + .setName('tickets') + .setDescription('Mise en place des tickets.') + .addStringOption(option => + option + .setName('type') + .setDescription('Le type de tickets à mettre en place.') + .setRequired(true) + .setChoices( + {name: 'Commandes', value: 'commands'}, + {name: 'Support', value: 'support'}, + ) + ) + .addChannelOption(option => + option + .setName('channel') + .setDescription('Choisissez le salon où l\'embed sera envoyé !') + .addChannelTypes(ChannelType.GuildText) + .setRequired(true)) + ) + .addSubcommand( + subcommand => + subcommand + .setName('panel') + .setDescription('Mise en place des panels.') + .addStringOption(option => + option + .setName('type') + .setDescription('Le type de panel à mettre en place.') + .setRequired(true) + .setChoices( + {name: 'Rolereact', value: 'rolereact'}, + {name: 'Embed du rolereact', value: 'rolereactembed'}, + {name: 'Candidatures', value: 'candidatures'}, + {name: 'Embed des sanctions', value: 'sanctionembed'}, + {name: 'Album Photo', value: 'albumphoto'} + ) + ) + .addChannelOption(option => + option + .setName('channel') + .setDescription('Choisissez le salon où le panel sera envoyé !') + .addChannelTypes(ChannelType.GuildText) + .setRequired(true)) + ) + .addSubcommand( + subcommand => + subcommand + .setName('moderation') + .setDescription('Mise en place de la modération.') + .addStringOption(option => + option + .setName('type') + .setDescription('Le type de panel de modération à mettre en place.') + .setRequired(true) + .setChoices( + {name: 'Sanctions', value: 'sanctions'}, + {name: 'Blacklist', value: 'blacklist'}, + ) + ) + .addChannelOption(option => + option + .setName('channel') + .setDescription('Choisissez le salon où le panel sera envoyé !') + .addChannelTypes(ChannelType.GuildText) + .setRequired(true)) + ), + async execute(interaction) { + switch (interaction.options.getSubcommand()) { + case 'tickets': + SetupTickets.execute(interaction); + break; + case 'panel': + SetupPanel.execute(interaction); + break; + case 'moderation': + SetupMod.execute(interaction); + break; + } + } +}; \ No newline at end of file diff --git a/commands/setup/setupcommands/moderation.js b/commands/setup/setupcommands/moderation.js new file mode 100644 index 0000000..c7ce986 --- /dev/null +++ b/commands/setup/setupcommands/moderation.js @@ -0,0 +1,89 @@ +const { EmbedBuilder, SelectMenuBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js'); + +module.exports = { + async execute(interaction, client) { + await interaction.deferReply({ ephemeral: true }); + const channel = interaction.options.getChannel('channel'); + + switch(interaction.options.getString('type')){ + case 'blacklist': + await channel.send({ + embeds: [ + new EmbedBuilder() + .setAuthor({ + name: "Art'Portal" + }) + .setTitle("Panel de blacklist") + .setDescription("**Utilisez les boutons ci-dessous pour:**\n> ❌ - Ajouter un utilisateur à la blacklist\n> ✅ - Retirer un utilisateur de la blacklist\n> 🖨 - Afficher les informations de blacklist d'un utilisateur") + .setColor(`#7961fd`) + ], + components: [ + new ActionRowBuilder() + .addComponents([ + new ButtonBuilder() + .setCustomId("blacklist_add") + .setStyle(ButtonStyle.Danger) + .setEmoji("✖️"), + new ButtonBuilder() + .setCustomId("blacklist_remove") + .setStyle(ButtonStyle.Success) + .setEmoji("✅"), + new ButtonBuilder() + .setCustomId("blacklist_check") + .setStyle(ButtonStyle.Secondary) + .setEmoji("🖨") + ]) + ] + }) + await interaction.editReply({ + content: "Le panel de blacklist a bien été envoyé !", + ephemeral: true + }); + break; + case 'sanctions': + await channel.send({ + embeds: [ + new EmbedBuilder() + .setAuthor({ + name: "Art'Portal" + }) + .setTitle("Panel de moderation") + .setDescription("Panel de modération destiné au staff !\nUtilisez les boutons ci-dessous pour appliquer diverses sanctions !") + .setColor(`#7961fd`) + ], + components: [ + new ActionRowBuilder() + .addComponents([ + new ButtonBuilder() + .setCustomId("modpanel_ban") + .setLabel("Ban") + .setStyle(ButtonStyle.Danger) + .setEmoji("🔨"), + new ButtonBuilder() + .setCustomId("modpanel_kick") + .setLabel("Kick") + .setStyle(ButtonStyle.Danger) + .setEmoji("🦶"), + new ButtonBuilder() + .setCustomId("modpanel_timeout") + .setLabel("Mute") + .setStyle(ButtonStyle.Danger) + .setEmoji("🤫"), + new ButtonBuilder() + .setCustomId("modpanel_warn") + .setLabel("Warn") + .setStyle(ButtonStyle.Danger) + .setEmoji("⚠️"), + new ButtonBuilder() + .setCustomId("modpanel_check") + .setLabel("Modlogs") + .setStyle(ButtonStyle.Secondary) + .setEmoji("🖨"), + ]) + ] + }) + await interaction.editReply({content: "Le panel de moderation a bien été envoyé !", ephemeral: true}); + break; + } + } +}; \ No newline at end of file diff --git a/commands/setup/setupcommands/panels.js b/commands/setup/setupcommands/panels.js new file mode 100644 index 0000000..69b38a5 --- /dev/null +++ b/commands/setup/setupcommands/panels.js @@ -0,0 +1,253 @@ +const { ButtonStyle, EmbedBuilder, SelectMenuBuilder, ActionRowBuilder, ButtonBuilder } = require('discord.js') + +module.exports = { + async execute(interaction, client) { + await interaction.deferReply({ + ephemeral: true + }); + const channel = interaction.options.getChannel('channel'); + switch (interaction.options.getString('type')) { + case 'rolereact': + const rolereactEMBED = new EmbedBuilder() + .setAuthor({ + name: "Art'Portal" + }) + .setTitle("Choisissez vos rôles/Choose your roles") + .setDescription("Cliquez sur les boutons pour choisir les rôles correspondant à vos choix\nClick on the buttons in order to choose the roles you want") + .setColor(`#7961fd`); + await channel.send({ + embeds: [ + rolereactEMBED + ], + components: [ + new ActionRowBuilder() + .addComponents([ + new ButtonBuilder() + .setCustomId("getrole_genre") + .setLabel("Pronoms/Pronouns") + .setStyle(ButtonStyle.Primary) + .setEmoji("👥"), + new ButtonBuilder() + .setCustomId("getrole_hobbies") + .setLabel("Hobbies/Hobbies") + .setStyle(ButtonStyle.Primary) + .setEmoji("♟️"), + new ButtonBuilder() + .setCustomId("getrole_color") + .setLabel("Couleur/Color") + .setStyle(ButtonStyle.Primary) + .setEmoji("🌈"), + new ButtonBuilder() + .setCustomId("getrole_pings") + .setLabel("Notifications/Pings") + .setStyle(ButtonStyle.Primary) + .setEmoji("📌") + ]), + new ActionRowBuilder() + .addComponents([ + new ButtonBuilder() + .setCustomId("getrole_list") + .setLabel("Afficher vos rôles") + .setStyle(ButtonStyle.Secondary) + .setEmoji("📖"), + ]) + ] + }); + await interaction.editReply({ + content: "Le panel de rolereact a bien été envoyé !", + ephemeral: true + }); + break; + + case 'rolereactembed': + await channel.send({ + embeds: [ + new EmbedBuilder() + .setAuthor({ + name: "Art'Portal" + }) + .setTitle("Présentation des rôles") + .setColor(`#7961fd`) + .setDescription("Les différents rôles que vous pouvez choisir sur Art'Portal sont listés ci-dessous") + .addFields( + { + name: "・Couleurs・", + value: `<@&947490339848060968>\n<@&947490417245556796>\n<@&947490189096415273>\n<@&947490255311872000>\n<@&947496679580500008>\n<@&947485362610139196>\n<@&947489800330559510>`, + inline: true + }, + { + name: "・Pronoms・", + value: `<@&769918743626252318>\n<@&768393897134784532>\n<@&772041733278007307>`, + inline: true + }, + { + name: "・Notifications・", + value: `<@&768396461763067914>\n<@&784646468958945280>\n<@&774693756901392404>\n<@&770568527156346880>\n<@&770723703948181525>\n<@&799249307362131978>\n<@&847207140098572318>\n<@&955143137226010704>`, + inline: true + }, + { + name: "・Hobbies・", + value: `<@&949745563824431124>\n<@&949746089987289128>\n<@&949746175920181278>\n<@&949746259898544229>\n<@&949746341754601502>\n<@&949746559019540511>\n<@&949746641764749324>\n<@&949746678519439370>`, + inline: true + }, + ) + ] + }) + await interaction.editReply({ + content: "L'embed a bien été envoyé !", + ephemeral: true + }); + break; + + case 'candidatures': + await channel.send({ + embeds: [ + new EmbedBuilder() + .setAuthor({ + name: "Art'Portal", + }) + .setTitle("Candidatures") + .setDescription("Cliquez sur le bouton pour candidater pour entrer dans le staff / l'équipe d' artistes.") + .setColor(`#7961fd`) + ], + components: [ + new ActionRowBuilder() + .addComponents([ + new ButtonBuilder() + .setCustomId("apply_staff") + .setLabel("Candidature staff") + .setStyle(ButtonStyle.Success) + .setEmoji("🛠"), + new ButtonBuilder() + .setCustomId("apply_artist") + .setLabel("Candidature artiste") + .setStyle(ButtonStyle.Success) + .setEmoji("🖌️") + ]) + ] + }) + await interaction.editReply({ + content: "Le panel de candidature a bien été envoyé !", + ephemeral: true + }); + break; + + case 'sanctionembed': + await channel.send({ components: [sanctionembedrow] }); + interaction.editReply({ + content: "Document des sanctions envoyé !" + }) + break; + + case 'albumphoto': + channel.send({ components: [albumphotoembedrow] }); + interaction.editReply({ + content: "Album photo d'April envoyé !" + }) + break; + } + } +} + +const sanctionembedrow = new ActionRowBuilder() + .addComponents( + new SelectMenuBuilder() + .setCustomId('document_sanctions') + .setPlaceholder('Navigateur') + .addOptions([ + { + label: 'Page 1', + description: 'Couverture', + value: '0', + }, + { + label: 'Page 2', + description: 'Notes', + value: '1', + }, + { + label: 'Page 3', + description: 'Table des matières', + value: '2', + }, + { + label: 'Page 4', + description: 'Articles 1 & 2', + value: '3', + }, + { + label: 'Page 5', + description: 'Article 3', + value: '4', + }, + { + label: 'Page 6', + description: 'Articles 4 & 5', + value: '5', + }, + { + label: 'Page 7', + description: 'Articles 6 & 7', + value: '6', + }, + ]), + ); + +const albumphotoembedrow = new ActionRowBuilder() + .addComponents( + new SelectMenuBuilder() + .setCustomId('document_albumphoto') + .setPlaceholder('Navigateur') + .addOptions([ + { + label: 'Page 1', + description: 'April - Cool', + value: '0', + }, + { + label: 'Page 2', + description: 'April - Couteau', + value: '1', + }, + { + label: 'Page 3', + description: 'April - Dodo', + value: '2', + }, + { + label: 'Page 4', + description: 'April - Mais', + value: '3', + }, + { + label: 'Page 5', + description: 'April - Peur', + value: '4', + }, + { + label: 'Page 6', + description: 'April - Sueur', + value: '5', + }, + { + label: 'Page 7', + description: 'April - Triste', + value: '6', + }, + { + label: 'Page 8', + description: 'April - Wouah', + value: '7', + }, + { + label: 'Page 9', + description: 'April - Bienvenue', + value: '8', + }, + { + label: 'Page 10', + description: 'April - Cool (2)', + value: '9', + }, + ]), + ); \ No newline at end of file diff --git a/commands/setup/setupcommands/tickets.js b/commands/setup/setupcommands/tickets.js new file mode 100644 index 0000000..bee8d6a --- /dev/null +++ b/commands/setup/setupcommands/tickets.js @@ -0,0 +1,73 @@ +const { EmbedBuilder, SelectMenuBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js') + +module.exports = { + async execute(interaction, client) { + await interaction.deferReply({ ephemeral: true }); + const channel = interaction.options.getChannel('channel'); + + const ticketEmbed = new EmbedBuilder(); + switch (interaction.options.getString('type')) { + case 'commands': + ticketEmbed + .setColor(`#7961fd`) + .setTitle("Commandes") + .setDescription("Tu veux passer commande ? Choisis ci-dessous en fonction de ton budget ! ^^") + .setThumbnail(`https://media.discordapp.net/attachments/867491241491038209/987292546180984832/april-welcome.png`); + channel.send({ + embeds: [ticketEmbed], + components: [ticketgraphismtyperow] }); + break; + + case 'support': + ticketEmbed + .setColor(`#7961fd`) + .setTitle("Tickets") + .setDescription("Tu veux faire une demande de partenariat / contacter le staff ?\nChoisis avec le menu déroulant çi-dessous ! ^^") + .setThumbnail(`https://media.discordapp.net/attachments/867491241491038209/987292546180984832/april-welcome.png`); + channel.send({ + embeds: [ticketEmbed], + components: [ticketsupportRow] + }); + break; + } + + await interaction.editReply({ content: "Panel envoyé avec succès !" }) + } +} + +const ticketgraphismtyperow = new ActionRowBuilder() + .addComponents([ + new ButtonBuilder() + .setCustomId('ticketopener_paid') + .setLabel('Commande rémunérée') + .setStyle(ButtonStyle.Success), + new ButtonBuilder() + .setCustomId('ticketopener_free') + .setLabel('Commande bénévole') + .setStyle(ButtonStyle.Success), + ]) + + +const ticketsupportRow = new ActionRowBuilder() + .addComponents( + new SelectMenuBuilder() + .setCustomId('ticket_create-support') + .setPlaceholder('Choisissez le type de ticket que vous voulez !') + .addOptions([ + { + label: 'Demande de partenariat', + value: 'partnership_option', + emoji: '💎' + }, + { + label: 'Contacter le Staff', + value: 'contact_option', + emoji: '✉' + }, + { + label: 'Report un utilisateur', + value: 'report_option', + emoji: '📣' + } + ]), + );// Never gonna give you up :D \ No newline at end of file diff --git a/commands/setup/toggle.js b/commands/setup/toggle.js new file mode 100644 index 0000000..c7057de --- /dev/null +++ b/commands/setup/toggle.js @@ -0,0 +1,52 @@ +const { SlashCommandBuilder, SlashCommandSubcommandBuilder, SlashCommandChannelOption, ChannelType, SlashCommandStringOption, ButtonBuilder, ActionRowBuilder, EmbedBuilder } = require('discord.js'); + + +module.exports = { + data: new SlashCommandBuilder() + .setName('toggle') + .setDefaultMemberPermissions(0x8) + .setDescription('Activer différents paramètres.') + .addSubcommand( + new SlashCommandSubcommandBuilder() + .setName('commandes') + .setDescription('Désactiver/Réactiver les commandes bénévoles') + .addChannelOption( + new SlashCommandChannelOption() + .setName('channel') + .setDescription('Salon du panel') + .addChannelTypes(ChannelType.GuildText) + .setRequired(true) + ) + .addStringOption( + new SlashCommandStringOption() + .setName('messageid') + .setDescription('ID du message du panel') + .setRequired(true) + ) + ) + , + async execute(interaction, client) { + await interaction.deferReply({ ephemeral: true }) + const channel = interaction.options.getChannel('channel'); + const message = await channel.messages.fetch(interaction.options.getString('messageid')) + if(!message) return interaction.reply({ content: "Je n'ai pas trouvé le message correspondant, vérifiez votre id", ephemeral: true }) + + a = new ButtonBuilder(message.components[0].components[0].data) + b = new ButtonBuilder(message.components[0].components[1].data) + .setDisabled(!message.components[0].components[1].data.disabled) + + const embed = new EmbedBuilder(message.embeds[0].data) + if(message.components[0].components[1].data.disabled) embed.setDescription(description[0]) + else embed.setDescription(description[1]) + + msg = message.components[0].components[1].data.disabled ? "Commandes bénévoles activées !" : "Commandes bénévoles désactivées !" + + await message.edit({ components: [ new ActionRowBuilder().addComponents([a,b]) ], embeds: [embed] }) + await interaction.editReply({ ephemeral: true, content: msg }) + } +}; + +description = [ + "Tu veux passer commande ? Choisis ci-dessous en fonction de ton budget ! ^^", + "Tu veux passer commande ? Choisis ci-dessous en fonction de ton budget ! ^^\n\n**Les tickets bénévoles sont actuellement désactivés pour cause de surcharge !** Dès que la plupart seront écoulés, les commandes bénévoles rouvriront !\n\n*Vous pouvez regarder le nombre de commandes en cours via le !*", +] \ No newline at end of file diff --git a/config.example.json b/config.example.json new file mode 100644 index 0000000..0c8d099 --- /dev/null +++ b/config.example.json @@ -0,0 +1,11 @@ +{ + "token" : "NeverGonneGiveYouUp", + "clientId" : "Bot's ID", + "guildId" : "Working Guild ID", + "generalChannelId" : "Main Guild Channel ID", + "rulesChannelId" : "Rules Channel ID", + "rolesChannelId" : "Roles Channel ID", + "devId" : "Developer's ID", + "sanctionChannelId": "Saanctions Channel's ID", + "progressBar": "Emojis/Text to show when loading something" +} \ No newline at end of file diff --git a/events/guildMemberAdd.js b/events/guildMemberAdd.js new file mode 100644 index 0000000..5fdb2af --- /dev/null +++ b/events/guildMemberAdd.js @@ -0,0 +1,26 @@ +const { guildId, generalChannelId, rulesChannelId, rolesChannelId } = require('../config.json'); + +module.exports = { + name: 'guildMemberAdd', + async execute(member, client) { + const guild = member.guild; + if (guild.id==guildId){ + const channel = await guild.channels.cache.find(c => c.id == generalChannelId ); + try{ + const welcomesticker = await guild.stickers.fetch('985933707317743666') + const message = await channel.send({ content: welcomemessage.replace("[memberid]", member.id), stickers:[welcomesticker]}); + Promise.all([ + message.react('👋'), + ]).catch(error => console.error(error)) + }catch(error){ + console.log(error) + }; + } + }, +}; + +const welcomemessage = +`☆ Bienvenue <@[memberid]> ☆ + +Je t'invite à aller lire le <#${rulesChannelId}> ainsi que de prendre tes rôles dans <#${rolesChannelId}> +Nous espérons que tu passera un bon moment sur Art' Portal ! ^^`; \ No newline at end of file diff --git a/events/interactionCreate.js b/events/interactionCreate.js new file mode 100644 index 0000000..64b0112 --- /dev/null +++ b/events/interactionCreate.js @@ -0,0 +1,40 @@ +const { guildId } = require('../config.json'); +const { buttonList } = require('../interactions/buttons/index.js'); +const { modalList } = require('../interactions/modals/index.js'); +const { selectMenuList } = require('../interactions/selectmenus/index.js'); + +module.exports = { + name: 'interactionCreate', + async execute(interaction, client) { + if (interaction.guild.id != guildId) { + return interaction.reply({ + content: "Bonjour,\nLe support multi-serveur de portal'bot a été désactivé.\nCela signifie qu'il n'est plus disponible autre part que sur les serveurs Portal.\nBot actuellement diponible sur:\n-Art'Portal - http://discord.gg/graphisme\n\nSi vous recherchez un bot multifonctionnel, le développeur du bot vous conseille Tokinotsuki - https://discord.com/oauth2/authorize?client_id=791437575642152982&permissions=8&scope=bot%20applications.commands" + }); + } + + + if (interaction.isChatInputCommand() || interaction.isContextMenuCommand()) { + const command = client.commands.get(interaction.commandName); + if (!command) return; + + try { + await command.execute(interaction, client); + } catch (error) { + console.error(error); + try { + await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true }); + } catch (error){ + console.error(error); + } + } + } else if (interaction.isButton()) { + buttonList[interaction.customId.split("_")[0]] ? buttonList[interaction.customId.split("_")[0]].execute(interaction, client) : interaction.reply({ content: "Si vous rencontrez cette erreur, merci de contacter CoolMan#4094 !", ephemeral: true }); + } else if (interaction.isSelectMenu()) { + selectMenuList[interaction.customId.split("_")[0]].execute(interaction, client); + } else if (interaction.isModalSubmit()) { + modalList[interaction.customId.split("_")[0]] ? modalList[interaction.customId.split("_")[0]].execute(interaction, client) : interaction.reply({ content: "Si vous rencontrez cette erreur, merci de contacter CoolMan#4094 !", ephemeral: true }); + } else { + console.log(interaction) + } + } +} \ No newline at end of file diff --git a/events/ready.js b/events/ready.js new file mode 100644 index 0000000..1c2e894 --- /dev/null +++ b/events/ready.js @@ -0,0 +1,35 @@ +module.exports = { + name: 'ready', + once: true, + async execute(client) { + console.log("Prête") + client.user.setStatus('online'); + + let status_list = [ + "être la mascotte de Art'Portal", + "instagram.com/aprilartportal", + "Art'Portal | discord.gg/graphisme", + "Aprıl - Art'portal", + "" + ]; + let profilepictures_list = [ + "https://media.discordapp.net/attachments/867491241491038209/970423539696009247/portalgirl-cool.png", + "https://media.discordapp.net/attachments/867491241491038209/970423539981234267/portalgirl-couteau.webp", + "https://media.discordapp.net/attachments/867491241491038209/970423540635562035/portalgirl-dodo.webp", + "https://media.discordapp.net/attachments/867491241491038209/970423542057406524/portalgirl-mais.webp", + "https://media.discordapp.net/attachments/867491241491038209/970423542602678292/portalgirl-peur.png", + "https://media.discordapp.net/attachments/867491241491038209/970423542892097537/portalgirl-sueur.png", + "https://media.discordapp.net/attachments/867491241491038209/970423543189872690/portalgirl-triste.webp", + "https://media.discordapp.net/attachments/867491241491038209/970423543626092604/portalgirl-wouah.webp", + "https://media.discordapp.net/attachments/867491241491038209/987292546180984832/april-welcome.png", + "https://media.discordapp.net/attachments/867491241491038209/987466337095917568/AprilStyle-min.png" + ]; + client.user.setActivity("être la mascotte d' Art'Portal", { type: "PLAYING" }); + setInterval(() => { + let Random = Math.floor(Math.random() * (status_list.length)); + let Random2 = Math.floor(Math.random() * (profilepictures_list.length)); + client.user.setActivity(status_list[Random], { type: "PLAYING" }); + client.user.setAvatar(profilepictures_list[Random2]); + }, 300000); + } +} \ No newline at end of file diff --git a/functions.js b/functions.js new file mode 100644 index 0000000..77d2e7e --- /dev/null +++ b/functions.js @@ -0,0 +1,49 @@ +const { REST } = require('@discordjs/rest'); +const { Routes } = require('discord-api-types/v10'); +const { token, clientId, guildId } = require('./config.json'); +const { Collection, SlashCommandBuilder } = require('discord.js') +const { isBoolean } = require('util') +const fs = require('fs'); +const rest = new REST({ version: '10' }).setToken(token); + + + +function deploy_commands(client, loadcommands) { + if (!isBoolean(loadcommands)) throw "type of loadcommands argument needs to be boolean"; + + const commands = []; + client.commands = new Collection(); + const commandCategories = fs.readdirSync('./commands').filter(file => !file.includes('.')); + for (const category of commandCategories) { + const commandFiles = fs.readdirSync(`./commands/${category}`).filter(file => file.endsWith('.js')); + for (const file of commandFiles) { + const command = require(`./commands/${category}/${file}`); + commands.push(command.data); + client.commands.set(command.data.name, command); + + console.log(`${category}/${command.data.name} chargé !`); + } + } + if (loadcommands){ + slashCommandLoad(client, commands); + } + else{//Deletes slash commands + slashCommandLoad(client, []) + } +} + +async function slashCommandLoad(client, commands) { + try { + console.log('Je commence à actualiser les commandes slash.'); + await rest.put( + Routes.applicationGuildCommands(clientId, guildId), + { body: commands }, + ); + console.log('Je viens de terminer de charger les commandes slash.'); + } catch (error) { + console.error(error); + } + return client.commands; +}; + +module.exports = { deploy_commands } \ No newline at end of file diff --git a/index.js b/index.js new file mode 100644 index 0000000..e7b2a7c --- /dev/null +++ b/index.js @@ -0,0 +1,63 @@ +const fs = require('fs'); +const Sequelize = require('sequelize'); +const { Client, GatewayIntentBits } = require("discord.js"); +const { token } = require('./config.json'); +const { deploy_commands } = require('./functions.js'); + +const client = new Client({ + intents: [ + GatewayIntentBits.Guilds, + GatewayIntentBits.GuildMembers, + GatewayIntentBits.GuildBans, + GatewayIntentBits.GuildMessages + ] +}); + + +const sequelize = new Sequelize('database', 'user', 'password', { + host: 'localhost', + dialect: 'sqlite', + logging: false, + storage: 'database.sqlite', +}); +const blacklistdb = sequelize.define('blacklist', { + name: {//id + type: Sequelize.STRING, + unique: true, + }, + username: Sequelize.STRING, + reason: Sequelize.TEXT, + timestamp: Sequelize.STRING, + moderatorid: Sequelize.STRING +}); + +const modlog = sequelize.define('sanctions', { + name: Sequelize.STRING,//id + username: Sequelize.STRING, + type: Sequelize.STRING, + reason: Sequelize.TEXT, + timestamp: Sequelize.STRING, + moderatorid: Sequelize.STRING +}); +client.database = { + sequelize: sequelize, + modlog: modlog, + blacklistdb: blacklistdb, +}; +blacklistdb.sync(); +modlog.sync(); + +const eventFiles = fs.readdirSync('./events').filter(file => file.endsWith('.js')); +for (const file of eventFiles) { + const event = require(`./events/${file}`); + if (event.once) { + client.once(event.name, (...args) => event.execute(...args, client)); + } else { + client.on(event.name, (...args) => event.execute(...args, client)); + } +} + +deploy_commands(client, true);//true: will refresh slash commands + + +client.login(token); diff --git a/interactions/buttons/index.js b/interactions/buttons/index.js new file mode 100644 index 0000000..c167e42 --- /dev/null +++ b/interactions/buttons/index.js @@ -0,0 +1,23 @@ +const pingrefreshbtn = require('./src/misc/pingrefreshbtn.js'); +const getrole = require('./src/rolereact/getrole.js'); +const apply = require('./src/ticket/applications.js'); +const applicationopen = require('./src/ticket/applicationopen.js'); +const ticket = require('./src/ticket/ticket.js'); +const modpanel = require('./src/moderation/modpanel.js'); +const blacklist = require('./src/moderation/blacklist.js'); +const embedbuilder = require('./src/panels/embedbuilder'); +const ticketopener = require('./src/ticket/ticketopener'); + +const buttonList = { + "pingrefreshbtn": pingrefreshbtn, + "getrole": getrole, + "apply": apply, + "applicationopen": applicationopen, + "ticket": ticket, + "modpanel": modpanel, + "blacklist": blacklist, + "embedbuilder": embedbuilder, + "ticketopener": ticketopener, +} + +module.exports = { buttonList } \ No newline at end of file diff --git a/interactions/buttons/src/misc/pingrefreshbtn.js b/interactions/buttons/src/misc/pingrefreshbtn.js new file mode 100644 index 0000000..f351478 --- /dev/null +++ b/interactions/buttons/src/misc/pingrefreshbtn.js @@ -0,0 +1,26 @@ +const { EmbedBuilder } = require('discord.js'); + +module.exports = { + async execute(interaction, client) { + try { + const sent = await interaction.channel.send({ + content: 'Pinging...', + }); + const latency = new EmbedBuilder() + .setColor(`#7961fd`) + .setTitle(`🏓 Pong ! Aprıl v4.0.0\n`) + .setDescription( + "\n" + + `**Latence :** ${sent.createdTimestamp - interaction.createdTimestamp}ms\n` + + `**API :** ${Math.round(client.ws.ping)}ms` + ) + await interaction.update({ + content: " ", + embeds: [latency] + }); + await sent.delete(); + } catch(error) { + console.error(error) + } + } +} \ No newline at end of file diff --git a/interactions/buttons/src/moderation/blacklist.js b/interactions/buttons/src/moderation/blacklist.js new file mode 100644 index 0000000..3c02044 --- /dev/null +++ b/interactions/buttons/src/moderation/blacklist.js @@ -0,0 +1,90 @@ +const { ModalBuilder, ActionRowBuilder, TextInputBuilder, TextInputStyle } = require("discord.js"); + + +module.exports = { + async execute(interaction, client){ + if (!interaction.member.roles.cache.has('778016554066640896')) return interaction.reply({ content: "Tu n'a pas la permission de faire ça!", ephemeral: true }); + switch(interaction.customId){ + case 'blacklist_add': + const blacklistmodal = new ModalBuilder() + .setCustomId('blacklist_add-'+interaction.message.id) + .setTitle('Art\'Portal - Blacklist') + .addComponents( + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('username') + .setLabel('Pseudo de l\'utilisateur à ajouter') + .setStyle(TextInputStyle.Short) + .setMinLength(6) + .setMaxLength(30) + .setPlaceholder('Ex: CoolMan#4094') + .setRequired(true) + ), + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('userid') + .setLabel('ID de l\'utilisateur à ajouter') + .setStyle(TextInputStyle.Short) + .setMinLength(18) + .setMaxLength(20) + .setPlaceholder('Ex: 697438073646088194') + .setRequired(true) + ), + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('reason') + .setLabel('Raison de la blacklist') + .setStyle(TextInputStyle.Paragraph) + .setMinLength(10) + .setMaxLength(500) + .setPlaceholder('Ex: Quitte le serveur avec une commande ouverte') + .setRequired(true) + ), + ); + await interaction.showModal(blacklistmodal) + break; + case 'blacklist_remove': + const rmvblacklistmodal = new ModalBuilder() + .setCustomId('blacklist_remove-'+interaction.message.id) + .setTitle('Art\'Portal - Blacklist') + .addComponents( + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('userid') + .setLabel('ID de l\'utilisateur à retirer') + .setStyle(TextInputStyle.Short) + .setMinLength(18) + .setMaxLength(20) + .setPlaceholder('Ex: 697438073646088194') + .setRequired(true) + ), + ) + await interaction.showModal(rmvblacklistmodal) + break; + case 'blacklist_check': + const checkblacklistmodal = new ModalBuilder() + .setCustomId('blacklist_check-'+interaction.message.id) + .setTitle('Art\'Portal - Blacklist') + .addComponents( + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('userid') + .setLabel('ID de l\'utilisateur à vérifier') + .setStyle(TextInputStyle.Short) + .setMinLength(18) + .setMaxLength(20) + .setPlaceholder('Ex: 697438073646088194') + .setRequired(true) + ), + ) + await interaction.showModal(checkblacklistmodal) + break; + } + } +} + diff --git a/interactions/buttons/src/moderation/modpanel.js b/interactions/buttons/src/moderation/modpanel.js new file mode 100644 index 0000000..6f956ee --- /dev/null +++ b/interactions/buttons/src/moderation/modpanel.js @@ -0,0 +1,158 @@ +const { ModalBuilder, TextInputBuilder, TextInputStyle, ActionRowBuilder, PermissionFlagsBits } = require('discord.js') + +module.exports = { + async execute(interaction){ + if(!interaction.member.permissions.has(requiredPermissions[interaction.customId])) return interaction.reply({ content: "Vous n'avez pas la permission d'effectuer cette action !", ephemeral: true }); + //console.log(modpanelModalList[interaction.customId]); + //return interaction.reply({ content: 'test', ephemeral: true }); + return interaction.showModal(modpanelModalList[interaction.customId]); + } +} + +const requiredPermissions = { + modpanel_ban: PermissionFlagsBits.BanMembers, + modpanel_kick: PermissionFlagsBits.KickMembers, + modpanel_timeout: PermissionFlagsBits.ModerateMembers, + modpanel_warn: PermissionFlagsBits.ManageMessages, + modpanel_check: PermissionFlagsBits.ManageMessages, +} + +const modpanelModalList = { + modpanel_ban: new ModalBuilder() + .setCustomId('modmodal_ban') + .setTitle('Art\'Portal - Bannissement') + .addComponents( + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('userid') + .setLabel('Indiquez l\'ID de la personne à bannir') + .setStyle(TextInputStyle.Short) + .setMinLength(18) + .setMaxLength(21) + .setPlaceholder('Ex: 697438073646088194') + .setRequired(true) + ), + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('reason') + .setLabel('Raison du ban') + .setStyle(TextInputStyle.Paragraph) + .setMinLength(10) + .setMaxLength(1000) + .setPlaceholder('Ex: Insultes, Irrespect') + .setRequired(true) + ), + ), + + modpanel_kick: new ModalBuilder() + .setCustomId('modmodal_kick') + .setTitle('Art\'Portal - Expulsion') + .addComponents( + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('userid') + .setLabel('Indiquez l\'ID de la personne à kick') + .setStyle(TextInputStyle.Short) + .setMinLength(18) + .setMaxLength(20) + .setPlaceholder('Ex: 697438073646088194') + .setRequired(true) + ), + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('reason') + .setLabel('Raison du kick') + .setStyle(TextInputStyle.Paragraph) + .setMinLength(10) + .setMaxLength(1000) + .setPlaceholder('Ex: Insultes, Irrespect') + .setRequired(true) + ), + ), + + modpanel_timeout: new ModalBuilder() + .setCustomId('modmodal_timeout') + .setTitle('Art\'Portal - Mute') + .addComponents( + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('userid') + .setLabel('Indiquez l\'ID de la personne à mute') + .setStyle(TextInputStyle.Short) + .setMinLength(18) + .setMaxLength(20) + .setPlaceholder('Ex: 697438073646088194') + .setRequired(true) + ), + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('reason') + .setLabel('Raison du mute') + .setStyle(TextInputStyle.Paragraph) + .setMinLength(10) + .setMaxLength(1000) + .setPlaceholder('Ex: Spam') + .setRequired(true) + ), + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('duration') + .setLabel('Durée du mute EN MINUTES') + .setStyle(TextInputStyle.Short) + .setMinLength(1) + .setMaxLength(4) + .setPlaceholder('Ex: 1, 60...') + .setRequired(true) + ), + ), + modpanel_warn: new ModalBuilder() + .setCustomId('modmodal_warn') + .setTitle('Art\'Portal - Warn') + .addComponents( + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('userid') + .setLabel('Indiquez l\'ID de la personne à avertir') + .setStyle(TextInputStyle.Short) + .setMinLength(18) + .setMaxLength(20) + .setPlaceholder('Ex: 697438073646088194') + .setRequired(true) + ), + new ActionRowBuilder() + .addComponents([ + new TextInputBuilder() + .setCustomId('reason') + .setLabel('Raison du warn') + .setStyle(TextInputStyle.Paragraph) + .setMinLength(10) + .setMaxLength(1000) + .setPlaceholder('Ex: Spam') + .setRequired(true) + ]), + ), + modpanel_check: new ModalBuilder() + .setCustomId('modmodal_check') + .setTitle('Art\'Portal - Modlog') + .addComponents( + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('userid') + .setLabel('ID de l\'utilisateur') + .setStyle(TextInputStyle.Short) + .setMinLength(18) + .setMaxLength(20) + .setPlaceholder('Id de la personne à vérifier !') + .setRequired(true) + ), + ) +} \ No newline at end of file diff --git a/interactions/buttons/src/panels/embedbuilder.js b/interactions/buttons/src/panels/embedbuilder.js new file mode 100644 index 0000000..f5b4151 --- /dev/null +++ b/interactions/buttons/src/panels/embedbuilder.js @@ -0,0 +1,182 @@ +const { ModalBuilder, ActionRowBuilder, TextInputBuilder, TextInputStyle } = require("discord.js"); + + +module.exports = { + async execute(interaction, client){ + const ebauthor = new ModalBuilder() + .setCustomId('embedbuilder_author') + .setTitle('Constructeur d\'embed: Auteur') + .setComponents( + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('embedbuilder_authorname') + .setLabel('Nom de l\'auteur') + .setStyle(TextInputStyle.Short) + .setMaxLength(256) + .setPlaceholder('(Pas forcément une personne tkt)') + .setValue(interaction.message.embeds[0].author ? interaction.message.embeds[0].author["name"]: "") + .setRequired(false), + ) + ); + const ebtitle = new ModalBuilder() + .setCustomId('embedbuilder_title') + .setTitle('Constructeur d\'embed: Titre') + .setComponents( + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('embedbuilder_titlename') + .setLabel('Titre de l\' embed') + .setStyle(TextInputStyle.Short) + .setMaxLength(256) + .setPlaceholder('Le titre affiché en grand') + .setValue(interaction.message.embeds[0].title ? interaction.message.embeds[0].title: "") + .setRequired(false), + ) + ); + + const ebdescription = new ModalBuilder() + .setCustomId('embedbuilder_description') + .setTitle('Constructeur d\'embed: Description') + .setComponents( + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('embedbuilder_description') + .setLabel('Description de l\' embed') + .setStyle(TextInputStyle.Paragraph) + .setMaxLength(4000) + .setPlaceholder('Le corps de texte de l\'embed') + .setValue(interaction.message.embeds[0].description ? interaction.message.embeds[0].description : "") + .setRequired(true) + ) + ); + + const ebfooter = new ModalBuilder().setCustomId('embedbuilder_footer').setTitle('Constructeur d\'embed: Texte du bas').setComponents(new ActionRowBuilder().addComponents(new TextInputBuilder().setCustomId('embedbuilder_footer').setLabel('Texte du bas de l\' embed').setStyle(TextInputStyle.Paragraph).setMaxLength(2048).setPlaceholder('Texte du bas').setValue(interaction.message.embeds[0].footer ? interaction.message.embeds[0].footer["text"] : "").setRequired(false))); + const ebcolor = new ModalBuilder().setCustomId('embedbuilder_color').setTitle('Constructeur d\'embed: Couleur').setComponents(new ActionRowBuilder().addComponents(new TextInputBuilder().setCustomId('embedbuilder_color').setLabel('Couleur de l\' embed').setStyle(TextInputStyle.Short).setMinLength(7).setMaxLength(7).setPlaceholder('Code hexadécimal (#ffffff)').setRequired(false))); + //row 2 + const ebthumbnail = new ModalBuilder().setCustomId('embedbuilder_thumbnail').setTitle('Constructeur d\'embed: Image miniature').setComponents(new ActionRowBuilder().addComponents(new TextInputBuilder().setCustomId('embedbuilder_thumbnail').setLabel('Lien de l \'image').setStyle(TextInputStyle.Short).setPlaceholder('(Image en haut à droite)').setRequired(false))); + const ebimage = new ModalBuilder().setCustomId('embedbuilder_image').setTitle('Constructeur d\'embed: Image').setComponents(new ActionRowBuilder().addComponents(new TextInputBuilder().setCustomId('embedbuilder_image').setLabel('Lien de l \'image').setStyle(TextInputStyle.Short).setPlaceholder('(Image en grand)').setRequired(false))); + const ebmessagecontent = new ModalBuilder().setCustomId('embedbuilder_messagecontent').setTitle('Constructeur d\'embed: Message à part').setComponents(new ActionRowBuilder().addComponents(new TextInputBuilder().setCustomId('embedbuilder_messagecontent').setLabel('Texte').setStyle(TextInputStyle.Paragraph).setMaxLength(2000).setPlaceholder('(Max 2000 caractères)').setRequired(false))); + + //row3 + const ebpost = new ModalBuilder().setCustomId('embedbuilder_post').setTitle('Constructeur d\'embed: Poster l\'embed').setComponents(new ActionRowBuilder().addComponents(new TextInputBuilder().setCustomId('embedbuilder_post').setLabel('Id du salon où poster l\' embed').setStyle(TextInputStyle.Short).setMinLength(18).setMaxLength(20).setPlaceholder('ID du salon').setRequired(true))); + const ebegetexisting = new ModalBuilder() + .setCustomId('embedbuilder_getexisting') + .setTitle('Constructeur d\'embed: Récupérer') + .setComponents([ + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('embedbuilder_channelid') + .setLabel('Id du salon où est l\' embed') + .setStyle(TextInputStyle.Short) + .setMinLength(18) + .setMaxLength(20) + .setPlaceholder('ID du salon') + .setRequired(true) + ), + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('embedbuilder_messageid') + .setLabel('Id du message à copier') + .setStyle(TextInputStyle.Short) + .setMinLength(18) + .setMaxLength(20) + .setPlaceholder('ID du message') + .setRequired(true) + )] + ); + + const ebeeditexisting = new ModalBuilder() + .setCustomId('embedbuilder_editexisting') + .setTitle('Constructeur d\'embed: Modifier') + .setComponents([ + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('embedbuilder_channelid') + .setLabel('Id du salon où est l\' embed') + .setStyle(TextInputStyle.Short) + .setMinLength(18) + .setMaxLength(20) + .setPlaceholder('ID du salon') + .setRequired(true) + ), + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('embedbuilder_messageid') + .setLabel('Id du message à éditer') + .setStyle(TextInputStyle.Short) + .setMinLength(18) + .setMaxLength(20) + .setPlaceholder('ID du message') + .setRequired(true) + )] + ); + + const ebcreatethread = new ModalBuilder() + .setCustomId('embedbuilder_createthread') + .setTitle('Constructeur d\'embed: Forum') + .setComponents([ + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('embedbuilder_channelid') + .setLabel('Id du salon où envoyer l\' embed') + .setStyle(TextInputStyle.Short) + .setMinLength(18) + .setMaxLength(20) + .setPlaceholder('ID du salon') + .setRequired(true) + ), + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('embedbuilder_threadname') + .setLabel('Nom du salon à créer') + .setStyle(TextInputStyle.Short) + .setMinLength(1) + .setMaxLength(100) + .setPlaceholder('Nom du thread à créer') + .setRequired(true) + )] + ); + + const embedbuildermodals = { + //row1 + "author": ebauthor, + "title": ebtitle, + "description": ebdescription, + "footer": ebfooter, + "color": ebcolor, + //row2 + "image": ebimage, + "thumbnail": ebthumbnail, + "messagecontent": ebmessagecontent, + //row3 + "post": ebpost, + "getexisting": ebegetexisting, + "editexisting": ebeeditexisting, + "createthread": ebcreatethread, + } + + + if (!interaction.member.roles.cache.has('778016554066640896')) return interaction.reply({ content: "Tu n'a pas la permission de faire ça!", ephemeral: true }); + switch(interaction.customId.split('-')[0]){ + case 'embedbuilder_create': + const type = interaction.customId.split('-')[1] + interaction.showModal( + embedbuildermodals[type], { + interaction: interaction, + client: client + } + ) + } + } +} + + diff --git a/interactions/buttons/src/panels/rolereact.js b/interactions/buttons/src/panels/rolereact.js new file mode 100644 index 0000000..72893e4 --- /dev/null +++ b/interactions/buttons/src/panels/rolereact.js @@ -0,0 +1,7 @@ +const { EmbedBuilder } = require('discord.js'); + +module.exports = { + async execute(interaction, client) { + + } +} \ No newline at end of file diff --git a/interactions/buttons/src/rolereact/getrole.js b/interactions/buttons/src/rolereact/getrole.js new file mode 100644 index 0000000..719950c --- /dev/null +++ b/interactions/buttons/src/rolereact/getrole.js @@ -0,0 +1,377 @@ +const { EmbedBuilder, ActionRowBuilder, SelectMenuBuilder, ButtonBuilder, ButtonStyle } = require('discord.js'); + +module.exports = { + async execute(interaction) { + let bruhplsworksimpler = interaction.customId.split("-")[1] == "refresh"; + if(!bruhplsworksimpler){ + await interaction.deferReply({ + ephemeral: true + }) + } else { + await interaction.deferUpdate(); + } + + const rolecache = interaction.member.roles.cache; + const roleEMBED = new EmbedBuilder() + .setAuthor({ + name: interaction.user.tag + }) + .setColor("#7961fd") + .setThumbnail(interaction.user.avatarURL()); + + let rolesembeddescriptions; + let count = 0; + + switch (interaction.customId.split("-")[0]) { + case 'getrole_genre': + rolesembeddescriptions="**Rôles de genre:**"; + genderroles.forEach(async (element) => { + if (rolecache.some(role => role.id == element)){ + rolesembeddescriptions = rolesembeddescriptions+`\n<@&${element}>`; + count++; + } + }) + if(count==0) rolesembeddescriptions = rolesembeddescriptions + "\nAucun"; + roleEMBED.setDescription(rolesembeddescriptions + getroletuto); + + const rolegenreactionrow = new ActionRowBuilder() + .setComponents([ + new ButtonBuilder() + .setCustomId("getrole_genre-refresh") + .setEmoji("🔁") + .setStyle(ButtonStyle.Secondary) + ]) + + await interaction.editReply({ + embeds: [roleEMBED], + components: [rolegenrerow, rolegenreactionrow] + }) + break; + + case 'getrole_hobbies': + rolesembeddescriptions = "**Rôles de hobbies:**"; + hobbiesroles.forEach(async (element) => { + if (rolecache.some(role => role.id == element)){ + rolesembeddescriptions = rolesembeddescriptions+`\n<@&${element}>`; + count++; + } + }) + if(count==0) rolesembeddescriptions = rolesembeddescriptions + "\nAucun"; + roleEMBED.setDescription(rolesembeddescriptions + getroletuto); + + const rolehobbiesactionrow = new ActionRowBuilder() + .setComponents([ + new ButtonBuilder() + .setCustomId("getrole_hobbies-refresh") + .setEmoji("🔁") + .setStyle(ButtonStyle.Secondary) + ]) + + await interaction.editReply({ + embeds: [roleEMBED], + components: [rolehobbiesrow, rolehobbiesactionrow] + }) + break; + + case 'getrole_color': + rolesembeddescriptions = "**Rôles de couleur:**"; + colorroles.forEach(async (element) => { + if (rolecache.some(role => role.id == element)){ + rolesembeddescriptions = rolesembeddescriptions+`\n<@&${element}>`; + count++; + } + }) + if(count==0) rolesembeddescriptions = rolesembeddescriptions + "\nAucun"; + roleEMBED.setDescription(rolesembeddescriptions + getroletuto); + + const rolecoloractionrow = new ActionRowBuilder() + .setComponents([ + new ButtonBuilder() + .setCustomId("getrole_color-refresh") + .setEmoji("🔁") + .setStyle(ButtonStyle.Secondary) + ]) + + await interaction.editReply({ + embeds: [roleEMBED], + components: [rolecolorrow, rolecoloractionrow] + }) + break; + + case 'getrole_pings': + rolesembeddescriptions = "**Rôles de notifications:**"; + notifroles.forEach(async (element) => { + if (rolecache.some(role => role.id == element)){ + rolesembeddescriptions = rolesembeddescriptions+`\n<@&${element}>`; + count++; + } + }) + if(count==0) rolesembeddescriptions = rolesembeddescriptions + "\nAucun" + roleEMBED.setDescription(rolesembeddescriptions + getroletuto); + + const rolepingsactionrow = new ActionRowBuilder() + .setComponents([ + new ButtonBuilder() + .setCustomId("getrole_pings-refresh") + .setEmoji("🔁") + .setStyle(ButtonStyle.Secondary) + ]) + + await interaction.editReply({ + embeds: [roleEMBED], + components: [rolepingsrow, rolepingsactionrow] + }) + break; + + case 'getrole_list': + let rolelistmessage; + + rolelistmessage = "**Rôles de couleur:**"; + colorroles.forEach(async (element) => { + if (rolecache.some(role => role.id == element)) rolelistmessage = rolelistmessage+`\n<@&${element}>` + }) + + rolelistmessage = rolelistmessage + "\n\n**Rôles de genre:**"; + genderroles.forEach(async (element) => { + if (rolecache.some(role => role.id == element)) rolelistmessage = rolelistmessage+`\n<@&${element}>` + }) + + rolelistmessage = rolelistmessage + "\n\n**Rôles de hobbies:**"; + hobbiesroles.forEach(async (element) => { + if (rolecache.some(role => role.id == element)) rolelistmessage = rolelistmessage+`\n<@&${element}>` + }) + + rolelistmessage = rolelistmessage + "\n\n**Rôles de notifications:**"; + notifroles.forEach(async (element) => { + if (rolecache.some(role => role.id == element)) rolelistmessage = rolelistmessage+`\n<@&${element}>` + }) + + + + roleEMBED + .setTitle("Vos rôles sur Art'Portal") + .setDescription(rolelistmessage); + + const rolelistactionrow = new ActionRowBuilder() + .setComponents([ + new ButtonBuilder() + .setCustomId("getrole_list-refresh") + .setEmoji("🔁") + .setStyle(ButtonStyle.Secondary) + ]) + + await interaction.editReply({ + components: [rolelistactionrow], + embeds:[roleEMBED] + }) + break; + } + } +} + +const getroletuto = "\n\n**Fonctionnement:**\nSélectionnez une option du menu déroulant pour récupérer le rôle correspondant.\nSi vous possédez déjà le rôle, il vous sera retiré à la place !"; + +const colorroles = [ + "947489800330559510", + "947485362610139196", + "947496679580500008", + "947490255311872000", + "947490189096415273", + "947490417245556796", + "947490339848060968" +] + +const genderroles = [ + "769918743626252318", + "768393897134784532", + "772041733278007307" +] + +const hobbiesroles = [ + "949745563824431124", + "949746089987289128", + "949746175920181278", + "949746259898544229", + "949746341754601502", + "949746559019540511", + "949746641764749324", + "949746678519439370" +] + +const notifroles = [ + "768396461763067914", + "784646468958945280", + "774693756901392404", + "770568527156346880", + "770723703948181525", + "799249307362131978", + "847207140098572318", + "955143137226010704" +] + + +const rolegenrerow = new ActionRowBuilder() + .addComponents( + new SelectMenuBuilder() + .setCustomId('roleselect_genre') + .setPlaceholder('Choisissez votre pronom / Choose your pronoun') + .addOptions([ + { + label: 'Elle / She', + value: 'role_genre_woman', + emoji: '882588094711345152', + }, + { + label: 'Il / He', + value: 'role_genre_man', + emoji: '882588094711345152', + }, + { + label: 'Autre / Other', + value: 'role_genre_other', + emoji: '882588094711345152', + } + ]), + ); + +const rolecolorrow = new ActionRowBuilder() + .addComponents( + new SelectMenuBuilder() + .setCustomId('roleselect_color') + .setPlaceholder('Choisissez une couleur / Choose a color') + .addOptions([ + { + label: 'Bleu/Blue', + value: 'role_color_blue', + emoji: '🔵' + }, + { + label: 'Vert/Green', + value: 'role_color_green', + emoji: '🟢' + }, + { + label: 'Orange/Orange', + value: 'role_color_orange', + emoji: '🟠' + }, + { + label: 'Rouge/Red', + value: 'role_color_red', + emoji: '🔴' + }, + { + label: 'Blanc/White', + value: 'role_color_white', + emoji: '⚪' + }, + { + label: 'Jaune/Yellow', + value: 'role_color_yellow', + emoji: '🟡' + }, + { + label: 'Rose/Pink', + value: 'role_color_pink', + emoji: '947495875654066207' + } + ]), + ); +const rolehobbiesrow = new ActionRowBuilder() + .addComponents( + new SelectMenuBuilder() + .setCustomId('roleselect_hobbies') + .setPlaceholder('Choisissez vos hobbies / Choose your hobbies') + .setMaxValues(8) + .addOptions([ + { + label: 'Graphisme/Graphism', + value: 'role_hobbies_graphism', + emoji: '🖌️' + }, + { + label: 'Musique/Music', + value: 'role_hobbies_music', + emoji: '🎵' + }, + { + label: 'Jeux vidéos/Videogames', + value: 'role_hobbies_videogames', + emoji: '🎮' + }, + { + label: 'Mangas-BDs/Mangas-Comics', + value: 'role_hobbies_mangascomics', + emoji: '📙' + }, + { + label: 'Romans/Novels', + value: 'role_hobbies_novels', + emoji: '📚' + }, + { + label: 'Programmation/Programming', + value: 'role_hobbies_programming', + emoji: '💻' + }, + { + label: 'Jeu de société/Board game', + value: 'role_hobbies_boardgame', + emoji: '🎲' + }, + { + label: 'Cuisine/Cooking', + value: 'role_hobbies_cooking', + emoji: '🍽' + }, + ]), + ); +const rolepingsrow = new ActionRowBuilder() + .addComponents( + new SelectMenuBuilder() + .setCustomId('roleselect_pings') + .setPlaceholder('Choisissez vos notifications / Choose your pings') + .setMaxValues(7) + .addOptions([ + { + label: 'Annonces/Announcements', + value: 'role_ping_announcements', + emoji: '📣' + }, + { + label: 'Sondages/Polls', + value: 'role_ping_polls', + emoji: '📊' + }, + { + label: 'Youtube/Youtube', + value: 'role_ping_youtube', + emoji: '🎞' + }, + { + label: 'Evenements/Events', + value: 'role_ping_events', + emoji: '📌' + }, + { + label: 'Partenariats/Partnerships', + value: 'role_ping_partnerships', + emoji: '🧩' + }, + { + label: 'Animations/Animations', + value: 'role_ping_animations', + emoji: '🎉' + }, + { + label: 'Ecologie/Ecology', + value: 'role_ping_ecology', + emoji: '🍄' + }, + { + label: 'Instagram/Instagram', + value: 'role_ping_insta', + emoji: '🖼️' + }, + ]), + ); \ No newline at end of file diff --git a/interactions/buttons/src/ticket/applicationopen.js b/interactions/buttons/src/ticket/applicationopen.js new file mode 100644 index 0000000..6891ebb --- /dev/null +++ b/interactions/buttons/src/ticket/applicationopen.js @@ -0,0 +1,63 @@ +const { PermissionFlagsBits, ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder, ChannelType } = require('discord.js'); + +module.exports = { + async execute(interaction, client){ + interaction.deferReply({ ephemeral: true }); + const embedToSend = interaction.message.embeds[0]; + const userId = interaction.customId.replace("applicationopen_",""); + const member = client.users.cache.find(user => user.id === userId) + + await interaction.guild.channels.create({ + name: `candidature-${member.username}`, + type: ChannelType.GuildText, + parent: '916721453121040424', + permissionOverwrites: [ + { + id: userId, + allow: [PermissionFlagsBits.ViewChannel], + }, + { + id: interaction.guild.id, + deny: [PermissionFlagsBits.ViewChannel], + }, + { + id: '778016554066640896', + allow: [PermissionFlagsBits.ViewChannel], + }, + + ], + reason: `April - Tickets candidatures - ${interaction.user.id}'`, + topic: `Candidature de <@${userId}>\nID: ${userId}\nDate de la candidature: ` + }).then(async channel => { + const btnrowTicket = new ActionRowBuilder() + .addComponents([ + new ButtonBuilder() + .setLabel("Fermer le ticket") + .setStyle(ButtonStyle.Danger) + .setEmoji("🔒") + .setCustomId(`ticket_close-${userId}`), + ]); + + const commandEmbed = new EmbedBuilder() + .setColor(`#7961fd`) + .setTitle("Candidature") + .setDescription("Veuillez patienter, un membre du staff consultera votre candidature sous peu !\n> En cas de candidature troll, non sérieuse, etc, vous pouvez être sujet à des sanctions !"); + + await channel.send({ content: "Bienvenue <@" + userId + "> ! Ce salon est là pour discuter de ta candidature !", embeds: [commandEmbed], components: [btnrowTicket] }).then(msg => msg.pin()); + + const openedapplicationticket = new ActionRowBuilder() + .addComponents( + new ButtonBuilder() + .setCustomId("applicationopened") + .setLabel("Ticket ouvert") + .setStyle(ButtonStyle.Primary) + .setDisabled(true) + .setEmoji("🎫"), + ); + + await channel.send({embeds:[embedToSend]}).then(msg => msg.pin()); + await interaction.followUp({ content: `Candidature ouverte dans <#${channel.id}>`, ephemeral: true }); + await interaction.message.edit( { content: `Candidature ouverte dans <#${channel.id}>`, components: [openedapplicationticket] } ) + }).catch(console.error); + } +} \ No newline at end of file diff --git a/interactions/buttons/src/ticket/applications.js b/interactions/buttons/src/ticket/applications.js new file mode 100644 index 0000000..b4b9970 --- /dev/null +++ b/interactions/buttons/src/ticket/applications.js @@ -0,0 +1,114 @@ +const { ModalBuilder, ActionRowBuilder, TextInputBuilder, TextInputStyle } = require('discord.js'); + +module.exports = { + async execute(interaction, client) { + switch (interaction.customId) { + case 'apply_staff': + await interaction.showModal(staffapplication) + break; + case 'apply_artist': + await interaction.showModal(artistapplication) + break; + } + } +} + +const staffapplication = new ModalBuilder() +.setCustomId('application_staff') +.setTitle('Art\'Portal - Candidature') +.addComponents( + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('application_motivation') + .setLabel('Expliquez vos motivations') + .setStyle(TextInputStyle.Paragraph) + .setMinLength(300) + .setMaxLength(1000) + .setPlaceholder('Ex: Cela me permettrait de m\'enrichir culturellement') + .setRequired(true) + ), + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('application_aptitudes') + .setLabel('Vos aptitudes') + .setStyle(TextInputStyle.Paragraph) + .setMinLength(300) + .setMaxLength(1000) + .setPlaceholder('En modération, en diplomatie...') + .setRequired(true) + ), + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('application_presentation') + .setLabel('Présentez-vous') + .setStyle(TextInputStyle.Paragraph) + .setMinLength(300) + .setMaxLength(1000) + .setPlaceholder('Présentez-vous, votre expérience, vos attentes...') + .setRequired(true) + ), + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('application_disponibilites') + .setLabel('Vos disponibilités') + .setStyle(TextInputStyle.Paragraph) + .setMinLength(20) + .setMaxLength(1000) + .setPlaceholder('Ex: Le lundi de 16 à 20h, le dimanche toute la journée...') + .setRequired(true) + ), +); + +const artistapplication = new ModalBuilder() +.setCustomId('application_artist') +.setTitle('Art\'Portal - Candidature Artiste') +.addComponents( + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('application_motivation') + .setLabel('Expliquez vos motivations') + .setStyle(TextInputStyle.Paragraph) + .setMinLength(300) + .setMaxLength(1000) + .setPlaceholder('Ex: Cela me permettrait de m\'enrichir culturellement') + .setRequired(true) + ), + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('application_aptitudes') + .setLabel('Vos aptitudes') + .setStyle(TextInputStyle.Paragraph) + .setMinLength(300) + .setMaxLength(1000) + .setPlaceholder('En modération, en diplomatie...') + .setRequired(true) + ), + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('application_presentation') + .setLabel('Présentez-vous') + .setStyle(TextInputStyle.Paragraph) + .setMinLength(300) + .setMaxLength(1000) + .setPlaceholder('Présentez-vous, votre expérience, vos attentes...') + .setRequired(true) + ), + new ActionRowBuilder() + .addComponents( + new TextInputBuilder() + .setCustomId('application_examples') + .setLabel('Exemples de créations') + .setStyle(TextInputStyle.Paragraph) + .setMinLength(20) + .setMaxLength(1000) + .setPlaceholder('(Liens vers les créations)') + .setRequired(true) + ), +); \ No newline at end of file diff --git a/interactions/buttons/src/ticket/ticket.js b/interactions/buttons/src/ticket/ticket.js new file mode 100644 index 0000000..0396d1b --- /dev/null +++ b/interactions/buttons/src/ticket/ticket.js @@ -0,0 +1,242 @@ +const { PermissionFlagsBits, ButtonBuilder, ButtonStyle, ActionRowBuilder, EmbedBuilder } = require('discord.js') + +module.exports = { + async execute(interaction) { + await interaction.deferUpdate({ ephemeral: true }); + switch (interaction.customId.replace("ticket_","").split("-")[0]) { + case 'close': + await interaction.channel.permissionOverwrites.set([ + { + id: interaction.guild.id, + deny: [PermissionFlagsBits.ViewChannel], + }, + { + id: '778016554066640896', + allow: [PermissionFlagsBits.ViewChannel, PermissionFlagsBits.ManageChannels], + }, + ]); + const closebuttons = new ActionRowBuilder() + .addComponents([ + new ButtonBuilder() + .setCustomId(`ticket_reopen-${interaction.customId.replace("ticket_","").split("-")[1]}`) + .setEmoji('🔐') + .setLabel("Rouvrir le ticket") + .setStyle(ButtonStyle.Success), + new ButtonBuilder() + .setCustomId(`ticket_delete`) + .setEmoji('🗑️') + .setLabel("Supprimer le ticket") + .setStyle(ButtonStyle.Danger), + ]); + + const closeEmbed = new EmbedBuilder() + .setTitle('Art\'Portal - Tickets') + .setDescription(`Le ticket a été fermé par <@${interaction.user.id}>`) + .setColor('#ce0808'); + + await interaction.editReply({ components: [closebuttons] }); + await interaction.followUp({ embeds: [closeEmbed] }); + break; + + case 'delete': + if (!interaction.member.roles.cache.has('778016554066640896')) return interaction.reply({ content: "Tu n'a pas la permission de faire ça!", ephemeral: true }); + + var ticketRowDelete = new ActionRowBuilder() + .addComponents( + new ButtonBuilder() + .setLabel("Oui") + .setStyle(ButtonStyle.Success) + .setEmoji("✔") + .setCustomId("ticket_confirmDelete"), + new ButtonBuilder() + .setLabel("Non") + .setStyle(ButtonStyle.Danger) + .setEmoji("❌") + .setCustomId("ticket_cancelDelete"), + ); + interaction.editReply(); + interaction.followUp({ content: "Êtes-vous sûr de vouloir supprimer ce ticket ?", components: [ticketRowDelete] }) + break; + + case 'confirmDelete': + if (!interaction.member.roles.cache.has('778016554066640896')) return interaction.reply({ content: "Tu n'a pas la permission de faire ça!", ephemeral: true }); + await interaction.editReply({ content: "Le ticket va être supprimé dans 5 secondes !", components: [] }) + setTimeout(() => { + interaction.channel.delete({reason:`Ticket supprimé par ${interaction.user.tag} (${interaction.user.id})`}) + }, 5000) + break; + + case 'cancelDelete': + if (!interaction.member.roles.cache.has('778016554066640896')) return interaction.reply({ content: "Tu n'a pas la permission de faire ça!", ephemeral: true }); + await interaction.editReply({ content: "Annulation de la suppression !", components: [] }) + setTimeout(() => { + interaction.message.delete(); + }, 5000) + break; + + + + case 'reopen': + await interaction.channel.permissionOverwrites.set([ + { + id: interaction.guild.id, + deny: [PermissionFlagsBits.ViewChannel], + }, + { + id: interaction.customId.replace("ticket_","").split("-")[1], + allow: [PermissionFlagsBits.ViewChannel], + }, + { + id: '778016554066640896', + allow: [PermissionFlagsBits.ViewChannel, PermissionFlagsBits.ManageChannels], + }, + ]); + if (interaction.channel.parentId == '780559502105378836'){ + await interaction.channel.permissionOverwrites.create('780007193688801321', { + ViewChannel: true + }); + await interaction.channel.permissionOverwrites.create('778016552108556388', { + ViewChannel: true + }); + } + + const btnrowTicket = new ActionRowBuilder() + + if (interaction.channel.parentId == '780559502105378836') btnrowTicket.addComponents( + new ButtonBuilder() + .setLabel("Prendre en charge") + .setStyle(ButtonStyle.Success) + .setEmoji("✏") + .setCustomId(`ticket_takeCommand-${interaction.customId.replace("ticket_","").split("-")[1]}`), + ) + + btnrowTicket.addComponents([ + new ButtonBuilder() + .setLabel("Fermer le ticket") + .setStyle(ButtonStyle.Danger) + .setEmoji("🔒") + .setCustomId(`ticket_close-${interaction.customId.replace("ticket_","").split("-")[1]}`), + ]); + + const reopenEmbed = new EmbedBuilder() + .setTitle('Art\'Portal - Tickets') + .setDescription(`Le ticket a été rouvert par <@${interaction.user.id}>`) + .setColor("#34f213"); + + await interaction.editReply({ components: [btnrowTicket] }); + await interaction.followUp({ embeds: [reopenEmbed] }); + break; + + case 'takeCommand': + const ticketRowTaken = new ActionRowBuilder() + .addComponents([ + new ButtonBuilder() + .setLabel("Annuler la prise en charge") + .setStyle(ButtonStyle.Danger) + .setEmoji("❌") + .setCustomId(`ticket_cancelTakenCommand-${interaction.user.id}-${interaction.customId.replace("ticket_","").split("-")[1]}`), + new ButtonBuilder() + .setLabel("Fermer le ticket") + .setStyle(ButtonStyle.Danger) + .setEmoji("🔒") + .setCustomId(`ticket_close-${interaction.customId.replace("ticket_","").split("-")[1]}`), + ]); + await interaction.channel.setName("🟢"+interaction.channel.name); + await interaction.followUp({ embeds: [ + new EmbedBuilder() + .setAuthor({ name: interaction.user.tag, iconURL: interaction.user.avatarURL() }) + .setDescription(`<@${interaction.user.id}> prend en charge le ticket !\nMerci à elle/lui !`) + .setColor('#34f213') + ] }); + await interaction.editReply({ components: [ticketRowTaken] }); + break; + + case 'cancelTakenCommand': + let untakeMessage; + if (interaction.user.id == interaction.customId.replace("ticket_","").split("-")[1]) untakeMessage = "(Annulation par l'artiste)" + else if (interaction.member.permissions.has(PermissionFlagsBits.Administrator)) untakeMessage = "(Annulation par le staff)" + else{ + await interaction.editReply(); + return interaction.followUp({ content: `Vous n'avez pas la permission de faire ça !`, ephemeral: true }); + } + const ticketRowUntaken = new ActionRowBuilder() + .addComponents([ + new ButtonBuilder() + .setLabel("Prendre en charge") + .setStyle(ButtonStyle.Success) + .setEmoji("✏") + .setCustomId(`ticket_takeCommand-${interaction.customId.replace("ticket_","").split("-")[2]}`), + new ButtonBuilder() + .setLabel("Fermer le ticket") + .setStyle(ButtonStyle.Danger) + .setEmoji("🔒") + .setCustomId(`ticket_close-${interaction.customId.replace("ticket_","").split("-")[2]}`), + ]); + await interaction.channel.setName(interaction.channel.name.replace("🟢","")); + await interaction.followUp({ embeds: [ + new EmbedBuilder() + .setAuthor({ name: interaction.user.tag, iconURL: interaction.user.avatarURL() }) + .setDescription(`<@${interaction.user.id}> ne prend plus en charge le ticket ! ${untakeMessage}`) + .setColor('#ce0808') + ] }); + await interaction.editReply({ components: [ticketRowUntaken] }); + break; + + case 'takeTicket': + if(!interaction.member.roles.cache.has('778016554066640896')) return interaction.reply({ content: "Vous n'avez pas la permission de faire cela !", ephemeral: true }); + const staffticketRowTaken = new ActionRowBuilder() + .addComponents([ + new ButtonBuilder() + .setLabel("Annuler la prise en charge") + .setStyle(ButtonStyle.Danger) + .setEmoji("❌") + .setCustomId(`ticket_cancelTakenTicket-${interaction.user.id}-${interaction.customId.replace("ticket_","").split("-")[1]}`), + new ButtonBuilder() + .setLabel("Fermer le ticket") + .setStyle(ButtonStyle.Danger) + .setEmoji("🔒") + .setCustomId(`ticket_close-${interaction.customId.replace("ticket_","").split("-")[1]}`), + ]); + await interaction.channel.setName("🟢"+interaction.channel.name); + await interaction.followUp({ embeds: [ + new EmbedBuilder() + .setAuthor({ name: interaction.user.tag, iconURL: interaction.user.avatarURL() }) + .setDescription(`<@${interaction.user.id}> prend en charge le ticket !`) + .setColor('#34f213') + ] }); + await interaction.editReply({ components: [staffticketRowTaken] }); + break; + + case 'cancelTakenTicket': + let untakeTicketMessage; + if (interaction.user.id == interaction.customId.replace("ticket_","").split("-")[1]) untakeTicketMessage = "(Annulation par le staff)" + else if (interaction.member.permissions.has(PermissionFlagsBits.Administrator)) untakeTicketMessage = "(Annulation par un administrateur)" + else{ + await interaction.editReply(); + return interaction.followUp({ content: `Vous n'avez pas la permission de faire ça !`, ephemeral: true }); + } + const staffticketRowUntaken = new ActionRowBuilder() + .addComponents([ + new ButtonBuilder() + .setLabel("Prendre en charge") + .setStyle(ButtonStyle.Success) + .setEmoji("✏") + .setCustomId(`ticket_takeTicket-${interaction.customId.replace("ticket_","").split("-")[2]}`), + new ButtonBuilder() + .setLabel("Fermer le ticket") + .setStyle(ButtonStyle.Danger) + .setEmoji("🔒") + .setCustomId(`ticket_close-${interaction.customId.replace("ticket_","").split("-")[2]}`), + ]); + await interaction.channel.setName(interaction.channel.name.replace("🟢","")); + await interaction.followUp({ embeds: [ + new EmbedBuilder() + .setAuthor({ name: interaction.user.tag, iconURL: interaction.user.avatarURL() }) + .setDescription(`<@${interaction.user.id}> ne prend plus en charge le ticket ! ${untakeTicketMessage}`) + .setColor('#ce0808') + ] }); + await interaction.editReply({ components: [staffticketRowUntaken] }); + break; + } + } +} \ No newline at end of file diff --git a/interactions/buttons/src/ticket/ticketopener.js b/interactions/buttons/src/ticket/ticketopener.js new file mode 100644 index 0000000..39e5c59 --- /dev/null +++ b/interactions/buttons/src/ticket/ticketopener.js @@ -0,0 +1,66 @@ +const { ActionRowBuilder, SelectMenuBuilder } = require('discord.js') + +module.exports = { + async execute(interaction) { + await interaction.deferReply({ ephemeral: true }); + const ticketgraphismtyperow2 = new ActionRowBuilder() + .addComponents( + new SelectMenuBuilder() + .setCustomId(`ticket_create-graphism-${interaction.customId.replace('ticketopener_', '')}`) + .setPlaceholder('Choisissez le type de graphisme.') + .addOptions([ + { + label: 'Logo/Logo', + value: 'ticket_logo', + emoji: '🖼' + }, + { + label: 'Bannière/Banner (Discord)', + value: 'ticket_discordbanner', + emoji: '🧩' + }, + { + label: 'Bannière/Banner (Youtube/Twitch)', + value: 'ticket_ytbbanner', + emoji: '🧩' + }, + { + label: 'Dessin/Drawing', + value: 'ticket_drawing', + emoji: '✏' + }, + { + label: 'Photo de profil/Profile picture', + value: 'ticket_profilepicture', + emoji: '🎆' + }, + { + label: 'Video/Video', + value: 'ticket_video', + emoji: '🎞' + }, + { + label: 'Overlay/Overlay', + value: 'ticket_overlay', + emoji: '🎥' + }, + { + label: 'Emojis/Emotes', + value: 'ticket_emojis', + emoji: '😀' + }, + { + label: 'Miniature/Thumbnail', + value: 'ticket_minia', + emoji: '🪟' + }, + { + label: 'Autre/Other', + value: 'ticket_other', + emoji: '🎈' + } + ]), + ); + await interaction.editReply({ components: [ticketgraphismtyperow2] }) + } +} \ No newline at end of file diff --git a/interactions/modals/index.js b/interactions/modals/index.js new file mode 100644 index 0000000..3eeb2cc --- /dev/null +++ b/interactions/modals/index.js @@ -0,0 +1,19 @@ +const command = require('./src/tickets/command.js'); +const partnershipmodal = require('./src/tickets/partnership.js'); +const reportmodal = require('./src/tickets/report.js'); +const application = require('./src/tickets/application.js'); +const modmodal = require('./src/moderation/modmodal.js'); +const blacklist = require('./src/moderation/blacklist.js'); +const embedbuilder = require('./src/embedbuilder/embedbuilder'); + +const modalList = { + "command": command, + "partnershipmodal": partnershipmodal, + "reportmodal": reportmodal, + "application": application, + "blacklist": blacklist, + "modmodal": modmodal, + "embedbuilder": embedbuilder, +} + +module.exports = { modalList } \ No newline at end of file diff --git a/interactions/modals/src/embedbuilder/embedbuilder.js b/interactions/modals/src/embedbuilder/embedbuilder.js new file mode 100644 index 0000000..b79151d --- /dev/null +++ b/interactions/modals/src/embedbuilder/embedbuilder.js @@ -0,0 +1,101 @@ +const { EmbedBuilder, ThreadAutoArchiveDuration } = require('discord.js') + +module.exports = { + async execute(interaction, client){ + await interaction.deferUpdate({ ephemeral: true }); + + const type = interaction.customId.replace("embedbuilder_",""); + let embedmsg = interaction.message.content || null; + let newembed = new EmbedBuilder(interaction.message.embeds[0].data); + switch(type){ + case 'author': + let name = interaction.fields.getTextInputValue('embedbuilder_authorname'); + if (!name) name = ""; + newembed.setAuthor({ name: name }); + break; + case 'title': + let title = interaction.fields.getTextInputValue('embedbuilder_titlename'); + if (!title) title = null; + newembed.setTitle(title); + break; + case 'description': + let description = interaction.fields.getTextInputValue('embedbuilder_description'); + if (!description) description = ""; + newembed.setDescription(description); + break; + case 'footer': + let footer = interaction.fields.getTextInputValue('embedbuilder_footer'); + if (!footer) footer = ""; + newembed.setFooter({text: footer}); + break; + case 'color': + let color = interaction.fields.getTextInputValue('embedbuilder_color'); + if (!color) color = ""; + newembed.setColor(color); + break; + case 'thumbnail': + let thumbnail = interaction.fields.getTextInputValue('embedbuilder_thumbnail'); + if (!thumbnail) thumbnail = ""; + newembed.setThumbnail(thumbnail); + break; + case 'image': + let image = interaction.fields.getTextInputValue('embedbuilder_image'); + if (!image) image = ""; + newembed.setImage(image); + break; + case 'messagecontent': + embedmsg = interaction.fields.getTextInputValue('embedbuilder_messagecontent') || null; + break; + + case 'post': + const postchannelid = interaction.fields.getTextInputValue('embedbuilder_post'); + const postembedchannel = await client.channels.cache.find(channel => channel.id === postchannelid); + await postembedchannel.send({ content: interaction.message.content+" ", embeds: [interaction.message.embeds[0]] }); + return interaction.followUp({ content: "L'embed a bien été envoyé ! (Dans <#"+postchannelid+">)", ephemeral: true }); + break; + + case 'getexisting': + const getexistingchannelid = interaction.fields.getTextInputValue('embedbuilder_channelid'); + const getexistingmessageid = interaction.fields.getTextInputValue('embedbuilder_messageid'); + const getexistingembedchannel = await client.channels.cache.find(channel => channel.id === getexistingchannelid); + if (!getexistingembedchannel) return interaction.followUp({ content: "Je n'ai pas trouvé le salon indiqué, merci de vérifier les ids", ephemeral: true }) + const getexistingmessage = await getexistingembedchannel.messages.fetch(getexistingmessageid) + if (!getexistingmessage) return interaction.followUp({ content: "Je n'ai pas trouvé le message indiqué, merci de vérifier les ids", ephemeral: true }) + newembed = new EmbedBuilder(getexistingmessage.embeds[0].data) || newembed; + break; + + case 'editexisting': + const editexistingchannelid = interaction.fields.getTextInputValue('embedbuilder_channelid'); + const editexistingmessageid = interaction.fields.getTextInputValue('embedbuilder_messageid'); + const editexistingembedchannel = await client.channels.cache.find(channel => channel.id === editexistingchannelid); + if (!editexistingembedchannel) return interaction.followUp({ content: "Je n'ai pas trouvé le salon indiqué, merci de vérifier les ids", ephemeral: true }) + const editexistingmessage = await editexistingembedchannel.messages.fetch(editexistingmessageid) + if (!editexistingmessage) return interaction.followUp({ content: "Je n'ai pas trouvé le message indiqué, merci de vérifier les ids", ephemeral: true }) + if (!editexistingmessage.author.id == client.user.id) return interaction.followUp({ content: "Je ne peux pas modifier un embed que je n'ai pas envoyé moi-même -_-", ephemeral: true }) + await editexistingmessage.edit({ content: interaction.message.content+" ", embeds: [interaction.message.embeds[0]] }); + return interaction.followUp({ content: "L'embed a bien été modifié ! (Dans <#"+editexistingchannelid+">)", ephemeral: true }); + break; + + case 'createthread': + const createthreadchannelid = interaction.fields.getTextInputValue('embedbuilder_channelid'); + const createthreadname = interaction.fields.getTextInputValue('embedbuilder_threadname'); + const createthreadchannel = await interaction.guild.channels.fetch(createthreadchannelid); + if (!createthreadchannel) return interaction.followUp({ content: "Je n'ai pas trouvé le salon indiqué, merci de vérifier les ids", ephemeral: true }) + + createthreadchannel.threads.create({ + name: createthreadname, + autoArchiveDuration: ThreadAutoArchiveDuration.OneWeek, + message: { + content: interaction.message.content+" ", + embeds: [interaction.message.embeds[0]], + }, + reason: `April - Embedbuilder - Demandé par ${interaction.user.tag} (${interaction.user.id})`, + }) + //.then(threadChannel => console.log(threadChannel)) + .catch(console.error); + + } + + await interaction.editReply({ embeds: [newembed], content: embedmsg }); + } +} \ No newline at end of file diff --git a/interactions/modals/src/moderation/blacklist.js b/interactions/modals/src/moderation/blacklist.js new file mode 100644 index 0000000..530e943 --- /dev/null +++ b/interactions/modals/src/moderation/blacklist.js @@ -0,0 +1,78 @@ +const { EmbedBuilder } = require("discord.js"); + + +module.exports = { + async execute(interaction, client){ + await interaction.deferReply({ ephemeral: true }); + const ogMessageId = interaction.customId.split("-")[1]; + const userId = interaction.fields.getTextInputValue('userid'); + const blacklistuser = await client.database.blacklistdb.findOne({ where: { name: userId } }); + + switch(interaction.customId.split("-")[0]){ + case 'blacklist_add': + const blacklistusername = interaction.fields.getTextInputValue('username'); + const blacklistreason = interaction.fields.getTextInputValue('reason'); + + if(blacklistuser) return interaction.followUp({content: "Cet utilisateur est déjà présent dans la blacklist !", ephemeral: true}) + + const blacklisttimestamp = Math.floor(new Date().getTime()/1000) + + await client.database.blacklistdb.create({ + name: userId, + username: blacklistusername, + reason: blacklistreason, + timestamp: blacklisttimestamp, + moderatorid: interaction.member.user.id, + }) + + const blacklistEMBED = new EmbedBuilder() + .setTitle("⭐・FORMULAIRE DE BLACKLIST") + .setDescription(`🗂️・**Pseudo** : ${blacklistusername}\n` + +`📎・**Id** : ${userId}\n` + +`📍・**Raison de l'infraction** : ${blacklistreason}\n` + +`📆・**Date de l'infraction** : \n` + +`<:Z_UtileAdmin:962499217845260298>・**Modérateur.trice** : ${interaction.member.user.tag}`) + + + + await interaction.followUp({embeds: [blacklistEMBED], ephemeral: true}); + const channel = await interaction.guild.channels.cache.get("828938225313644595") + await channel.send({ embeds: [blacklistEMBED] }) + await interaction.channel.messages.fetch(ogMessageId) + .then(message => { + message.delete(); + interaction.channel.send({ embeds: message.embeds, components: message.components }) + }); + break; + case 'blacklist_remove': + if (blacklistuser) { + const blacklistrmvEMBED = new EmbedBuilder() + .setTitle("⭐・FORMULAIRE DE BLACKLIST (Supprimé)") + .setDescription(`🗂️・**Pseudo** : ${blacklistuser.username}\n` + +`📎・**Id** : ${userId}\n` + +`📍・**Raison de l'infraction** : ${blacklistuser.reason}\n` + +`📆・**Date de l'infraction** : \n` + +`<:Z_UtileAdmin:962499217845260298>・**Modérateur.trice** : <@${blacklistuser.moderatorid}>`) + await interaction.followUp({content: "Cette personne a bien été retirée de la blacklist !\n(Merci de supprimer manuellement l'embed correspondant à cette personne)", embeds: [blacklistrmvEMBED], ephemeral: true}); + await client.database.blacklistdb.destroy({ where: { name: userId } }); + } else{ + await interaction.followUp({content: "Il n'y a personne de blacklist avec l'id "+userId+"...", ephemeral: true}); + } + break; + case 'blacklist_check': + if (blacklistuser) { + const blacklistcheckEMBED = new EmbedBuilder() + .setTitle("⭐・FORMULAIRE DE BLACKLIST") + .setDescription(`🗂️・**Pseudo** : ${blacklistuser.username}\n` + +`📎・**Id** : ${userId}\n` + +`📍・**Raison de l'infraction** : ${blacklistuser.reason}\n` + +`📆・**Date de l'infraction** : \n` + +`<:Z_UtileAdmin:962499217845260298>・**Modérateur.trice** : <@${blacklistuser.moderatorid}>`) + await interaction.followUp({ embeds: [blacklistcheckEMBED], ephemeral: true}); + } else{ + await interaction.followUp({ content: "Il n'y a personne de blacklist avec l'id "+userId+"...", ephemeral: true}); + } + break; + } + } +} \ No newline at end of file diff --git a/interactions/modals/src/moderation/modmodal.js b/interactions/modals/src/moderation/modmodal.js new file mode 100644 index 0000000..480d718 --- /dev/null +++ b/interactions/modals/src/moderation/modmodal.js @@ -0,0 +1,230 @@ +const { EmbedBuilder } = require('discord.js'); +const { sanctionChannelId } = require('../../../../config.json'); + +module.exports = { + async execute(interaction, client){ + await interaction.deferReply({ephemeral: true}) + const userId = interaction.fields.getTextInputValue('userid'); + const user = await client.users.cache.get(userId); + const member = await interaction.guild.members.cache.get(userId); + let reason; + try{ + reason = interaction.fields.getTextInputValue('reason'); + }catch{} + + const channel = await interaction.guild.channels.cache.get(sanctionChannelId); + + + switch(interaction.customId.replace("modmodal_","")){ + case 'ban': + if (member){ + const userRoleRawPos = member.roles.highest.rawPosition; + const memberRoleRawPos = interaction.member.roles.highest.rawPosition; + if (user.id === interaction.user.id) return interaction.editReply({content: `Vous ne pouvez pas vous bannir vous-même! !`, ephemeral: true}); + if (userRoleRawPos >= memberRoleRawPos) return interaction.editReply({content: `Vous ne pouvez pas bannir cet utilisateur.`, ephemeral: true}); + if (!member.bannable) return interaction.editReply({content: `Je ne peux pas bannir cet utilisateur. Cela est dû au fait que l'utilisateur est modérateur/administrateur ou que son rôle est au dessus du rôle du bot...`, ephemeral: true}); + } + + await interaction.guild.bans.create(userId, {reason: reason + " - Banni.e par " + interaction.user.tag}); + + const banEMBED = new EmbedBuilder() + .setColor(`#009500`) + .setThumbnail(`https://i.imgur.com/zcZsfNA.png`) + .setTitle(`➔ Art' Portal - Bannissement`) + .addFields( + { + name: "・Utilisateur.trice・", + value: `${user ? `**Tag: ${user.tag}\n` : ""}ID: ${userId}**`, + inline: true + }, + { + name: "・Raison du bannissement・", + value: `**${reason !== null ? `${reason}` : 'Non précisé'}**`, + inline: true + }, + { + name: `・Modérateur.trice・`, + value: `**${interaction.user.tag}**` + }, + { + name: `・Date・`, + value: ``, + inline: true + }, + ); + await interaction.editReply({embeds: [banEMBED], ephemeral: true}); + await channel.send({ + embeds: [banEMBED] + }); + await client.database.modlog.create({ + name: userId, + username: user ? user.tag : "Inconnu", + type: "Ban", + reason: reason, + timestamp: Math.floor(new Date().getTime()/1000), + moderatorid: interaction.member.user.id + }); + break; + + case 'kick': + if (member){ + const userRoleRawPos = member.roles.highest.rawPosition; + const memberRoleRawPos = interaction.member.roles.highest.rawPosition; + if(user.id === interaction.user.id) return interaction.editReply({content: `Vous ne pouvez pas vous expulser vous-même vous-même!`, ephemeral: true}); + if(userRoleRawPos >= memberRoleRawPos) return interaction.editReply({content: `Vous ne pouvez pas expulser cet utilisateur.`, ephemeral: true}); + if(!member.bannable) return interaction.editReply({content: `Je ne peux pas expulser cet utilisateur. Cela est dû au fait que l'utilisateur est modérateur/administrateur ou que son rôle est au dessus du rôle du bot...`, ephemeral: true}); + } else return interaction.editReply({ content: `L'utilisateur spécifié n'est pas présent sur le serveur !` }); + await member.kick( {reason: reason + " - Expulsé.e par " + interaction.member.user.tag} ); + + const kickEMBED = new EmbedBuilder() + .setColor(`#009500`) + .setThumbnail(`https://i.imgur.com/zcZsfNA.png`) + .setTitle(`➔ Art' Portal - Expulsion`) + .addFields( + { + name: "・Utilisateur.trice・", + value: `**Tag: ${user.tag}\nID: ${user.id}**`, + inline: true + }, + { + name: "・Raison de l'expulsion", + value: `**${reason !== null ? `${reason}` : 'No reason specified'}**`, + inline: true + }, + { + name: `・Modérateur.trice・`, + value: `**${interaction.member.user.tag}**` + }, + { + name: `・Date・`, + value: ``, + inline: true + }, + ); + await interaction.editReply({embeds: [kickEMBED], ephemeral: true}); + await channel.send({ + embeds: [kickEMBED] + }); + await client.database.modlog.create({ + name: user.id, + username: user.tag, + type: "Kick", + reason: reason, + timestamp: Math.floor(new Date().getTime()/1000), + moderatorid: interaction.member.user.id + }) + break; + case 'timeout': + if (member){ + const userRoleRawPos = member.roles.highest.rawPosition; + const memberRoleRawPos = interaction.member.roles.highest.rawPosition; + if(member.user.id === interaction.user.id) return interaction.editReply({content: `Vous ne pouvez pas vous mute vous-même vous-même! !`, ephemeral: true}); + if(userRoleRawPos >= memberRoleRawPos) return interaction.editReply({content: `Vous ne pouvez pas mute cet utilisateur.`, ephemeral: true}); + if(!member.bannable) return interaction.editReply({content: `Je ne peux pas mute cet utilisateur. Cela est dû au fait que l'utilisateur est modérateur/administrateur ou que son rôle est au dessus du rôle du bot...`, ephemeral: true}); + } else return interaction.editReply({ content: `L'utilisateur spécifié n'est pas présent sur le serveur !` }); + const duration = Number(interaction.fields.getTextInputValue('duration')); + if (isNaN(duration)) return interaction.editReply({ content: `\`${duration}\` n'est pas un nombre ! Merci de spécifier correctement la durée du mute !` }) + await member.timeout(duration * 60 * 1000, {reason: reason + " - Mute par " + interaction.member.user.tag} ); + + const muteEMBED = new EmbedBuilder() + .setColor(`#009500`) + .setThumbnail(`https://i.imgur.com/zcZsfNA.png`) + .setTitle(`➔ Art' Portal - Mute`) + .addFields( + { + name: "・Utilisateur.trice・", + value: `**Tag: ${member.user.tag}\nID: ${member.user.id}**`, + inline: true + }, + { + name: "・Raison du mute", + value: `**${reason !== null ? `${reason}` : 'No reason specified'}**`, + inline: true + }, + { + name: `・Modérateur.trice・`, + value: `**${interaction.member.user.tag}**` + }, + { + name: `・Date・`, + value: ``, + inline: true + }, + ); + await interaction.editReply({embeds: [muteEMBED], ephemeral: true}); + await channel.send({ + embeds: [muteEMBED] + }); + await client.database.modlog.create({ + name: user.id, + username: user.tag, + type: "Timeout", + reason: reason, + timestamp: Math.floor(new Date().getTime()/1000), + moderatorid: interaction.member.user.id + }) + break; + case 'warn': + if (!member) return interaction.editReply({ content: `L'utilisateur spécifié n'est pas présent sur le serveur !` }); + const warnEMBED = new EmbedBuilder() + .setColor(`#009500`) + .setThumbnail(`https://i.imgur.com/zcZsfNA.png`) + .setTitle(`➔ Art' Portal - Warn`) + .addFields( + { + name: "・Utilisateur.trice・", + value: `**Tag: ${member.user.tag}\nID: ${member.user.id}**`, + inline: true + }, + { + name: "・Raison du warn", + value: `**${reason !== null ? `${reason}` : 'No reason specified'}**`, + inline: true + }, + { + name: `・Modérateur.trice・`, + value: `**${interaction.member.user.tag}**` + }, + { + name: `・Date・`, + value: ``, + inline: true + }, + ); + await interaction.editReply({embeds: [warnEMBED], ephemeral: true}); + await channel.send({ + embeds: [warnEMBED] + }); + await client.database.modlog.create({ + name: userId, + username: user.tag, + type: "Warn", + reason: reason, + timestamp: Math.floor(new Date().getTime()/1000), + moderatorid: interaction.member.user.id + }); + const tagList = await client.database.modlog.findAll({ where: { name: userId }, attributes: ['type'] }); + let warncount = 0 + tagList.forEach( async (value) => { + if(value.type=="Warn") warncount++ + }) + if (warncount>=3){ + await interaction.followUp({content:`:warning: Cet utilisateur a désormais ${warncount} warns !`, ephemeral: true}) + } + break; + case 'check': + const sanctionList = await client.database.modlog.findAll({ where: { name: userId } }); + if (!sanctionList || sanctionList==0) return interaction.followUp({content:"Il n'y a aucune trace de cet utilisateur dans les modlogs !", ephemeral: true}); + let embeddescription = "\n"; + sanctionList.forEach( async (value) => { + embeddescription = embeddescription + `${value.type}: \`${value.reason}\`, , <@${value.moderatorid}>\n\n` + }) + const blacklistEMBED = new EmbedBuilder() + .setTitle("⭐・MODLOGS pour " +sanctionList[0].username) + .setDescription(embeddescription.substring(0, 4000)) + + await interaction.followUp({embeds: [blacklistEMBED], ephemeral: true}); + break; + } + } +} diff --git a/interactions/modals/src/tickets/application.js b/interactions/modals/src/tickets/application.js new file mode 100644 index 0000000..923c1c7 --- /dev/null +++ b/interactions/modals/src/tickets/application.js @@ -0,0 +1,70 @@ +const { PermissionFlagsBits, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js'); +const { progressBar } = require('../../../../config.json'); + +module.exports = { + async execute(interaction, client){ + await interaction.reply({ content: `${progressBar}\nCréation de la candidature en cours, merci de patienter !`, ephemeral: true }); + + const motivation = interaction.fields.getTextInputValue('application_motivation'); + const aptitudes = interaction.fields.getTextInputValue('application_aptitudes'); + const presentation = interaction.fields.getTextInputValue('application_presentation'); + let disponibilites = undefined; + try{ + disponibilites = interaction.fields.getTextInputValue('application_disponibilites'); + } catch{} + let examples = undefined; + try { + examples = interaction.fields.getTextInputValue('application_examples'); + } catch{} + + const applicationchannel = client.channels.cache.find(channel => channel.id === `${disponibilites ? '934898908407144469' : '950124391159697540'}`); + + const applicationEMBED = new EmbedBuilder() + .setColor(`#7961fd`) + .setTitle("Art'Portal - Candidature") + .addFields( + { + name: "・Candidat.e・", + value: `**Tag: ${interaction.user.tag}\nID: ${interaction.user.id}**`, + inline: true + }, + { + name: "・Motivation・", + value: `${motivation}`, + inline: false + }, + { + name: `・Aptitudes・`, + value: `${aptitudes}`, + inline: false + }, + { + name: `・Présentation・`, + value: `${presentation}`, + inline: false + }, + { + name: `・${disponibilites ? "Disponibilité" : "Exemples de créations"}・`, + value: `${disponibilites ? disponibilites : examples}`, + inline: false + }, + { + name: `・Date de la candidature・`, + value: ``, + inline: true + }, + ); + + const openapplicationticket = new ButtonBuilder() + .setCustomId("applicationopen_"+interaction.user.id) + .setLabel("Ouvrir un ticket") + .setStyle(ButtonStyle.Success) + .setEmoji("🎫"); + const applicationrow = new ActionRowBuilder() + .addComponents([openapplicationticket]); + applicationchannel.send({embeds:[applicationEMBED], components:[applicationrow]}); + setTimeout(async function(){ + await interaction.editReply({ content: 'Votre candidature a bien été envoyée au staff !', embeds:[applicationEMBED], ephemeral: true }); + },5000) + } +} \ No newline at end of file diff --git a/interactions/modals/src/tickets/command.js b/interactions/modals/src/tickets/command.js new file mode 100644 index 0000000..edcdad3 --- /dev/null +++ b/interactions/modals/src/tickets/command.js @@ -0,0 +1,156 @@ +const { PermissionFlagsBits, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ChannelType, ButtonStyle, ThreadAutoArchiveDuration } = require('discord.js') +const { progressBar } = require('../../../../config.json'); + +module.exports = { + async execute(interaction, client){ + await interaction.reply({ content: `${progressBar}\nCréation du ticket en cours, merci de patienter !`, ephemeral: true }); + let remuneration; + + try{ + remuneration = interaction.fields.getTextInputValue('command_remuneration'); + }catch{ + remuneration = null; + } + const commandType = cmdTypeDict[interaction.customId.replace("command_","")]; + const theme = interaction.fields.getTextInputValue('command_theme'); + const desc = interaction.fields.getTextInputValue('command_description'); + const top = interaction.fields.getTextInputValue('command_toppings'); + const baseimg = interaction.fields.getTextInputValue('command_baseimage'); + + const commandtosendEMBED = new EmbedBuilder() + .setColor(`#7961fd`) + .setTitle(`__Formulaire de commande Art' Portal__ (${remuneration ? "Rémunéré": "Non rémunéré"})`) + .addFields( + { + name: "・Type de graphisme・", + value: `${commandType? commandType : "Non spécifié"}`, + inline: false + }, + { + name: "・Thème imposé・", + value: `${theme? theme : "Non spécifié"}`, + inline: false + }, + { + name: `・Description de l'image・`, + value: `${desc? desc : "Non spécifié"}`, + inline: false + }, + { + name: `・Effets, détails, texte à ajouter・`, + value: `${top? top : "Non spécifié"}`, + inline: false + }, + { + name: `・Image(s) de Base・`, + value: `${baseimg? baseimg : "Non spécifié"}`, + inline: false + }, + ); + + if(remuneration){ + commandtosendEMBED.addFields( + { + name: 'Budget', + value: String(remuneration), + inline: false + } + ) + } + + const isalreadybl = await client.database.blacklistdb.findOne({ where: { name: interaction.user.id } }); + if(isalreadybl) { + const bllogchannel = await interaction.guild.channels.fetch('1036589658647314502') + await bllogchannel.send({ content: `<:Z_UtileDanger:962499193862225940>**Utilisateur blacklisté** (Raison: ${isalreadybl.get('reason')})<:Z_UtileDanger:962499193862225940>\nCommande de : <@${interaction.user.id}> (${interaction.user.id})\nCréation de la commande : `, embeds:[commandtosendEMBED] }); + } + if(isalreadybl) return interaction.editReply({content: "Vous avez été blacklisté des tickets sur le serveur pour la raison: `"+isalreadybl.get('reason')+"`\nPour contester cette décision, vous pouvez ouvrir un ticket dans le salon <#869093817503076363>", ephemeral: true}) + + + await interaction.guild.channels.create({ + name: `${remuneration ? "rémunéré": "bénévole"} - ` + interaction.user.username, + type: ChannelType.GuildText, + parent: '780559502105378836', + permissionOverwrites: [ + { + id: interaction.user.id, + allow: [PermissionFlagsBits.ViewChannel], + }, + { + id: interaction.guild.id, + deny: [PermissionFlagsBits.ViewChannel], + allow:[PermissionFlagsBits.SendMessagesInThreads], + }, + { + id: '778016554066640896', + allow: [PermissionFlagsBits.ViewChannel, PermissionFlagsBits.ManageChannels], + }, + + { + id: '780007193688801321', + allow: [PermissionFlagsBits.ViewChannel], + }, + { + id: '778016552108556388', + allow: [PermissionFlagsBits.ViewChannel], + }, + + ], + reason: `April - Tickets commandes - ${interaction.user.username} (${interaction.user.id})'`, + topic: `${commandType} pour <@${interaction.user.id}>\nID: ${interaction.user.id}\nDate de la commande: ` + }).then(async channel => { + var btnrowTicket = new ActionRowBuilder() + .addComponents([ + new ButtonBuilder() + .setLabel("Prendre en charge") + .setStyle(ButtonStyle.Success) + .setEmoji("✏") + .setCustomId("ticket_takeCommand-"+interaction.user.id), + new ButtonBuilder() + .setLabel("Fermer le ticket") + .setStyle(ButtonStyle.Danger) + .setEmoji("🔒") + .setCustomId(`ticket_close-${interaction.user.id}`), + ]); + + const commandEmbed = new EmbedBuilder() + .setColor(`#7961fd`) + .setTitle("Commande: " + commandType) + .setDescription("Un artiste viendra prendre votre commande bientôt !\n> :x: Si l'artiste ne reçoit aucune réponse pendant plusieurs jours de suite, le ticket sera fermé/mis en attente. Merci également de faire l'entièreté de la commande sur ce ticket et de ne pas partir en mp.\n> Si vous quittez le serveur avec ce ticket ouvert, vous serez blacklist: vous ne pourrez pas repasser commande.\n> En cas d'irrespect ou de manquement au <#766336361984294913>, votre ticket sera fermé et vous serez blacklist, sans sommation."); + + await channel.send({ content: "Bienvenue <@" + interaction.user.id + "> !\nPortal'Artistes, un ticket a été ouvert!", embeds: [commandEmbed], components: [btnrowTicket] }).then(msg => msg.pin()); + await channel.send({embeds:[commandtosendEMBED]}).then(msg => msg.pin()); + + setTimeout(async function(){ + await interaction.editReply({ content: "Ton ticket a bien été créé ! (<#" + channel.id + ">)", ephemeral: true }); + },5000) + + if(remuneration){ + await channel.threads.create({ + name: "Portfolios", + autoArchiveDuration: ThreadAutoArchiveDuration.OneWeek, + message: { + content: `Commande de ${interaction.user.tag} (${interaction.user.id})`, + }, + reason: `April - Portfolios - Commande de ${interaction.user.tag} (${interaction.user.id})`, + }) + } + + + const logchannel = await interaction.guild.channels.fetch('1036589658647314502') + await logchannel.send({ content: `Commande de : <@${interaction.user.id}> (${interaction.user.id})\nCréation de la commande : `, embeds:[commandtosendEMBED] }); + }).catch(console.error); + } +} + +const cmdTypeDict = { + "logo": "Logo", + "discordbanner": "Bannière Discord", + "ytbbanner": "Bannière Youtube/...", + "drawing": "Dessin", + "profilepicture": "Photo de profil", + "video": "Video/Montage", + "overlay": "Overlay de stream", + "emojis": "Émojis/Stickers", + "minia": "Miniature", + "other": "Autre", +}; diff --git a/interactions/modals/src/tickets/partnership.js b/interactions/modals/src/tickets/partnership.js new file mode 100644 index 0000000..aa1106d --- /dev/null +++ b/interactions/modals/src/tickets/partnership.js @@ -0,0 +1,106 @@ +const { PermissionFlagsBits, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ChannelType, ButtonStyle } = require('discord.js'); +const { progressBar } = require('../../../../config.json'); + +module.exports = { + async execute(interaction){ + await interaction.reply({ content: `${progressBar}\nCréation du ticket en cours, merci de patienter !`, ephemeral: true }); + + const invite = interaction.fields.getTextInputValue('partnership_servinvite'); + const description = interaction.fields.getTextInputValue('partnership_servdesc') || "Pas de description renseignée"; + + await interaction.guild.channels.create({ + name: `partenariat-${interaction.user.username}`, + type: ChannelType.GuildText, + parent: '847188286043717632', + permissionOverwrites: [ + { + id: interaction.user.id, + allow: [PermissionFlagsBits.ViewChannel], + }, + { + id: interaction.guild.id, + deny: [PermissionFlagsBits.ViewChannel], + }, + { + id: '778016554066640896', + allow: [PermissionFlagsBits.ViewChannel], + }, + + ], + reason: `April - Tickets partenariat - ${interaction.user.username} (${interaction.user.id})'`, + topic: `Partenariat avec <@${interaction.user.id}>\nLien: ${invite}\nID: ${interaction.user.id}\nDate de la proposition: ` + }).then(async channel => { + var btnrowTicket = new ActionRowBuilder() + .addComponents([ + new ButtonBuilder() + .setLabel("Fermer le ticket") + .setStyle(ButtonStyle.Danger) + .setEmoji("🔒") + .setCustomId(`ticket_close-${interaction.user.id}`), + ]); + + const partnershipEmbed = new EmbedBuilder() + .setColor(`#7961fd`) + .setTitle("Partenariat") + .setDescription("Un membre du staff viendra bientôt !\n> Votre serveur doit avoir minimum 200 membres !\n> Il doit également respecter les [ToS de discord](https://discord.com/terms)"); + + await channel.send({ content: "Bienvenue <@" + interaction.user.id + "> !\n<@&778016554066640896> un ticket a été ouvert!", embeds: [partnershipEmbed], components: [btnrowTicket] }).then(msg => msg.pin()); + const commandtosendEMBED = new EmbedBuilder() + .setColor(`#7961fd`) + .setTitle(`__Formulaire de partenariat Art' Portal__`) + .addFields( + { + name: "・Lien vers le serveur / site・", + value: `${invite}`, + inline: false + }, + { + name: "・Description・", + value: `${description}`, + inline: false + }, + ); + await channel.send({embeds:[commandtosendEMBED]}).then(msg => msg.pin()); + if (invite.includes("discord.gg/")){ + await interaction.client.fetchInvite(invite) + .then(async invite => { + const servinfoEMBED = new EmbedBuilder() + .setTitle(invite.guild.name) + .setFields([ + { + name: "Créé :", + value : ``, + }, + { + name: "Membres :", + value : invite.memberCount.toString(), + }, + { + name: "Description :", + value : invite.guild.description || "Aucune", + }, + { + name: "ID :", + value : invite.guild.id.toString(), + }, + { + name: "Nombre de boosts :", + value: invite.guild.premiumSubscriptionCount.toString() + } + ]) + .setImage(invite.guild.bannerURL()) + .setThumbnail(invite.guild.iconURL({ size: 1024 })) + if (invite.guild.partnered) servinfoEMBED.setDescription("<:Z_UtilePartner:962499238783242271>") + await channel.send( { embeds: [servinfoEMBED] } ) + }).catch(error => { + console.error(error) + }) + } + + setTimeout(async function(){ + await interaction.editReply({ content: "Ton ticket a bien été créé ! (<#" + channel.id + ">)", ephemeral: true }); + },5000) + + }).catch(console.error); + } +} \ No newline at end of file diff --git a/interactions/modals/src/tickets/report.js b/interactions/modals/src/tickets/report.js new file mode 100644 index 0000000..59dc08e --- /dev/null +++ b/interactions/modals/src/tickets/report.js @@ -0,0 +1,82 @@ +const { PermissionFlagsBits, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ChannelType, ButtonStyle } = require('discord.js'); +const { progressBar } = require('../../../../config.json'); + +module.exports = { + async execute(interaction){ + await interaction.reply({ content: `${progressBar}\nCréation du ticket en cours, merci de patienter !`, ephemeral: true }); + + const reason = interaction.fields.getTextInputValue('reason'); + const messageslink = interaction.fields.getTextInputValue('messageslink') || "Pas de message renseigné"; + const screens = interaction.fields.getTextInputValue('screens') || "Pas de capture d'écran renseignée"; + + await interaction.guild.channels.create({ + name: `report-${interaction.user.username}`, + type: ChannelType.GuildText, + parent: '916721453121040424', + permissionOverwrites: [ + { + id: interaction.user.id, + allow: [PermissionFlagsBits.ViewChannel], + }, + { + id: interaction.guild.id, + deny: [PermissionFlagsBits.ViewChannel], + }, + { + id: '778016554066640896', + allow: [PermissionFlagsBits.ViewChannel], + }, + + ], + reason: `April - Tickets report - ${interaction.user.username} (${interaction.user.id})'`, + topic: `Report de <@${interaction.user.id}>\nID: ${interaction.user.id}\nDate du report: ` + }).then(async channel => { + var btnrowTicket = new ActionRowBuilder() + .addComponents([ + new ButtonBuilder() + .setLabel("Prendre en charge") + .setStyle(ButtonStyle.Success) + .setEmoji("✏") + .setCustomId(`ticket_takeTicket-${interaction.user.id}`), + new ButtonBuilder() + .setLabel("Fermer le ticket") + .setStyle(ButtonStyle.Danger) + .setEmoji("🔒") + .setCustomId(`ticket_close-${interaction.user.id}`), + ]); + + const reportEmbed = new EmbedBuilder() + .setColor(`#7961fd`) + .setTitle("Report") + .setDescription("Un membre du staff viendra bientôt !\n> En cas de report troll, vous serez sanctionné vous-même !"); + + await channel.send({ content: "Bienvenue <@" + interaction.user.id + "> !\n<@&778016554066640896> un ticket a été ouvert!", embeds: [reportEmbed], components: [btnrowTicket] }).then(msg => msg.pin()); + const commandtosendEMBED = new EmbedBuilder() + .setColor(`#7961fd`) + .setTitle(`__Formulaire de report Art' Portal__`) + .addFields( + { + name: "・Raison・", + value: `${reason}`, + inline: false + }, + { + name: "・Lien(s) vers un/des message(s)・", + value: `${messageslink}`, + inline: false + }, + { + name: "・Lien(s) vers un/des capture(s) d'écran・", + value: `${screens}`, + inline: false + }, + ); + await channel.send({embeds:[commandtosendEMBED]}).then(msg => msg.pin()); + + setTimeout(async function(){ + await interaction.editReply({ content: "Ton ticket a bien été créé ! (<#" + channel.id + ">)", ephemeral: true }); + },5000) + + }).catch(console.error); + } +} \ No newline at end of file diff --git a/interactions/selectmenus/index.js b/interactions/selectmenus/index.js new file mode 100644 index 0000000..51bcb68 --- /dev/null +++ b/interactions/selectmenus/index.js @@ -0,0 +1,11 @@ +const ticket = require('./src/tickets/ticket.js') +const roleselect = require('./src/rolereact/roleselect.js') +const document = require('./src/misc/document.js') + +const selectMenuList = { + "ticket": ticket, + "roleselect": roleselect, + "document": document +} + +module.exports = { selectMenuList } \ No newline at end of file diff --git a/interactions/selectmenus/src/misc/document.js b/interactions/selectmenus/src/misc/document.js new file mode 100644 index 0000000..13a8822 --- /dev/null +++ b/interactions/selectmenus/src/misc/document.js @@ -0,0 +1,35 @@ +const { EmbedBuilder } = require('discord.js'); + +module.exports = { + async execute(interaction){ + await interaction.update({ embeds:[ + new EmbedBuilder(interaction.message.embeds[0]) + .setImage(images[interaction.customId][Number(interaction.values[0])]) + .setFooter({ text: `Page ${Number(interaction.values[0])+1}/${images[interaction.customId].length}` }) + ] }) + } +} + +const images = { + document_sanctions: [ + "https://media.discordapp.net/attachments/867491241491038209/992161245560057906/Bareme_des_sanctions-1.png", + "https://media.discordapp.net/attachments/867491241491038209/992161245883011103/Bareme_des_sanctions-2.png", + "https://media.discordapp.net/attachments/867491241491038209/992161246214373416/Bareme_des_sanctions-3.png", + "https://media.discordapp.net/attachments/867491241491038209/992161246424092765/Bareme_des_sanctions-4.png", + "https://media.discordapp.net/attachments/867491241491038209/992161246646374580/Bareme_des_sanctions-5.png", + "https://media.discordapp.net/attachments/867491241491038209/992161246914805831/Bareme_des_sanctions-6.png", + "https://media.discordapp.net/attachments/867491241491038209/992161247250370682/Bareme_des_sanctions-7.png" + ], + document_albumphoto: [ + "https://media.discordapp.net/attachments/867491241491038209/970423539696009247/portalgirl-cool.png", + "https://media.discordapp.net/attachments/867491241491038209/970423539981234267/portalgirl-couteau.webp", + "https://media.discordapp.net/attachments/867491241491038209/970423540635562035/portalgirl-dodo.webp", + "https://media.discordapp.net/attachments/867491241491038209/970423542057406524/portalgirl-mais.webp", + "https://media.discordapp.net/attachments/867491241491038209/970423542602678292/portalgirl-peur.png", + "https://media.discordapp.net/attachments/867491241491038209/970423542892097537/portalgirl-sueur.png", + "https://media.discordapp.net/attachments/867491241491038209/970423543189872690/portalgirl-triste.webp", + "https://media.discordapp.net/attachments/867491241491038209/970423543626092604/portalgirl-wouah.webp", + "https://media.discordapp.net/attachments/867491241491038209/987292546180984832/april-welcome.png", + "https://media.discordapp.net/attachments/867491241491038209/987466337095917568/AprilStyle-min.png" + ] +}; \ No newline at end of file diff --git a/interactions/selectmenus/src/rolereact/roleselect.js b/interactions/selectmenus/src/rolereact/roleselect.js new file mode 100644 index 0000000..6ce09cc --- /dev/null +++ b/interactions/selectmenus/src/rolereact/roleselect.js @@ -0,0 +1,123 @@ +const { EmbedBuilder, ActionRowBuilder, SelectMenuBuilder } = require('discord.js'); + +module.exports = { + async execute(interaction, client) { + await interaction.deferUpdate(); + await interaction.guild.roles.fetch(); + let currentrole; + let member = interaction.member; + switch(interaction.customId){ + case 'roleselect_color': + for (let [key, value] of Object.entries(colors)) { + if (interaction.values[0].split("role_color_")[1] == key) { + currentrole = interaction.guild.roles.cache.find(role => role.id == value); + if (member.roles.cache.some(role => role.id == value)) { + member.roles.remove(currentrole); + await interaction.editReply({ + content: `Vous avez bien été retiré.e du rôle <@&${value}>` + }); + } else { + member.roles.add(currentrole); + await interaction.editReply({ + content: `Vous avez bien reçu le rôle <@&${value}>` + }); + } + } + } + break; + + case 'roleselect_genre': + for (let [key, value] of Object.entries(genres)) { + if (interaction.values[0].split("role_genre_")[1] == key) { + currentrole = interaction.guild.roles.cache.find(role => role.id == value); + if (member.roles.cache.some(role => role.id == value)) { + member.roles.remove(currentrole); + await interaction.editReply({ + content: `Vous avez bien été retiré.e du rôle <@&${value}>` + }); + } else { + member.roles.add(currentrole); + await interaction.editReply({ + content: `Vous avez bien reçu le rôle <@&${value}>` + }); + } + } + } + break; + case 'roleselect_hobbies': + let hobbiesmessage=""; + for (let [key, value] of Object.entries(hobbies)) { + interaction.values.forEach( async (value2, index) => { + if (interaction.values[index].split("role_hobbies_")[1] == key){ + currentrole = interaction.guild.roles.cache.find(role => role.id == value); + if (member.roles.cache.some(role => role.id == value)) { + member.roles.remove(currentrole); + hobbiesmessage = `${hobbiesmessage}\nVous avez bien été retiré.e du rôle <@&${value}>`; + } else { + member.roles.add(currentrole); + hobbiesmessage = `${hobbiesmessage}\nVous avez bien reçu le rôle <@&${value}>`; + } + } + }); + } + interaction.editReply({ content: hobbiesmessage }); + break; + case 'roleselect_pings': + let pingmessage=""; + for (let [key, value] of Object.entries(pings)) { + interaction.values.forEach( async (value2, index) => { + if (interaction.values[index].split("role_ping_")[1] == key){ + currentrole = interaction.guild.roles.cache.find(role => role.id == value); + if (member.roles.cache.some(role => role.id == value)) { + member.roles.remove(currentrole); + pingmessage = `${pingmessage}\nVous avez bien été retiré.e du rôle <@&${value}>`; + } else { + member.roles.add(currentrole); + pingmessage = `${pingmessage}\nVous avez bien reçu le rôle <@&${value}>`; + } + } + }); + } + interaction.editReply({ content: pingmessage }); + break; + } + } +} + +const colors = { + "blue": "947485362610139196", + "green": "947489800330559510", + "orange": "947490189096415273", + "red": "947490255311872000", + "white": "947490339848060968", + "yellow": "947490417245556796", + "pink": "947496679580500008" +}; + +const genres = { + "woman": "769918743626252318", + "man": "768393897134784532", + "other": "772041733278007307" +}; + +const hobbies = { + "graphism": "949745563824431124", + "music": "949746089987289128", + "videogames": "949746175920181278", + "mangascomics": "949746259898544229", + "novels": "949746341754601502", + "programming": "949746559019540511", + "boardgame": "949746641764749324", + "cooking": "949746678519439370" +}; + +const pings = { + "announcements": "768396461763067914", + "polls": "784646468958945280", + "youtube": "774693756901392404", + "events": "770568527156346880", + "partnerships": "770723703948181525", + "animations": "799249307362131978", + "ecology": "847207140098572318", + "insta": "955143137226010704" +}; \ No newline at end of file diff --git a/interactions/selectmenus/src/tickets/ticket.js b/interactions/selectmenus/src/tickets/ticket.js new file mode 100644 index 0000000..d397919 --- /dev/null +++ b/interactions/selectmenus/src/tickets/ticket.js @@ -0,0 +1,204 @@ +const { ActionRowBuilder, EmbedBuilder, ButtonBuilder, ButtonStyle, ModalBuilder, TextInputBuilder, TextInputStyle, PermissionFlagsBits, ChannelType } = require("discord.js"); + +module.exports = { + async execute(interaction, client) { + switch (interaction.customId.split('-')[1]) { + case "graphism": + const commandType = cmdTypeDict[interaction.values[0].replace("ticket_", "")]; + const remuneration = interaction.customId.split('-')[2]; + const commandmodal = new ModalBuilder() + .setCustomId("command_" + interaction.values[0].replace("ticket_", "")) + .setTitle("Art'Portal - Commande - " + commandType) + .addComponents([ + new ActionRowBuilder() + .addComponents([ + new TextInputBuilder() + .setCustomId("command_theme") + .setLabel("Thème") + .setStyle(TextInputStyle.Short) + .setMinLength(10) + .setMaxLength(1000) + .setPlaceholder("(Exemple: Futuriste, Fantaisie, Naturel, Etc...)") + .setRequired(true), + ]), + new ActionRowBuilder() + .addComponents([ + new TextInputBuilder() + .setCustomId("command_description") + .setLabel("Description") + .setStyle(TextInputStyle.Paragraph) + .setMinLength(150) + .setMaxLength(1000) + .setPlaceholder("(Décrivez votre demande afin de faciliter le travail du graphiste. Soyez le plus précis possible!)") + .setRequired(true), + ]), + new ActionRowBuilder() + .addComponents([ + new TextInputBuilder() + .setCustomId("command_toppings") + .setLabel("Effets/Détails/Texte à ajouter") + .setStyle(TextInputStyle.Paragraph) + .setMaxLength(1000) + .setPlaceholder("(Écrivez votre texte sans oublier les majuscules, minuscules, accent, etc...)") + .setRequired(false), + ]), + new ActionRowBuilder() + .addComponents([ + new TextInputBuilder() + .setCustomId("command_baseimage") + .setLabel("Image(s) de Base, Exemples (mettez des liens)") + .setStyle(TextInputStyle.Paragraph) + .setMaxLength(1000) + .setPlaceholder("Proposer des exemples aidera beaucoup les artistes à comprendre ce que vous voulez") + .setRequired(false), + ]) + ]); + if(remuneration=='paid'){ + commandmodal.addComponents([ + new ActionRowBuilder() + .addComponents([ + new TextInputBuilder() + .setCustomId("command_remuneration") + .setLabel("Votre budget") + .setStyle(TextInputStyle.Short) + .setMinLength(1) + .setMaxLength(30) + .setPlaceholder("Indiquez le budget que vous avez pour la rémunération de cette commande") + .setRequired(true), + ]) + ]) + } + await interaction.showModal(commandmodal); + break; + + case "support": + switch (interaction.values[0].replace("_option", "")) { + case "partnership": + const partnershipmodal = new ModalBuilder() + .setCustomId("partnershipmodal") + .setTitle("Art'Portal - Partenariats") + .addComponents([ + new ActionRowBuilder() + .addComponents([ + new TextInputBuilder() + .setCustomId("partnership_servinvite") + .setLabel("Invitation / Lien") + .setStyle(TextInputStyle.Short) + .setMaxLength(35) + .setPlaceholder("Invitation / Lien de votre organisme") + .setRequired(true), + ]), + new ActionRowBuilder() + .addComponents([ + new TextInputBuilder() + .setCustomId("partnership_servdesc") + .setLabel("Description") + .setStyle(TextInputStyle.Paragraph) + .setMinLength(10) + .setMaxLength(1000) + .setPlaceholder("Décrivez votre serveur / organisation si ce n'est pas un serveur") + .setRequired(false) + ]), + ]) + interaction.showModal(partnershipmodal); + break; + + case "contact": + await interaction.guild.channels.create({ + name: `ticket-${interaction.user.username}`, + type: ChannelType.GuildText, + permissionOverwrites: [ + { + id: interaction.user.id, + allow: [PermissionFlagsBits.ViewChannel], + }, + ], + reason: "April - Tickets - Contact du staff" + }).then(async channel => { + let category = interaction.guild.channels.cache.find(cat => cat.id === "916721453121040424"); + + await channel.setParent(category.id); + await channel.permissionOverwrites.create(interaction.user, { ViewChannel: true }); + + var btnrowTicket = new ActionRowBuilder() + .addComponents([ + new ButtonBuilder() + .setLabel("Prendre en charge") + .setStyle(ButtonStyle.Success) + .setEmoji("✏") + .setCustomId(`ticket_takeTicket-${interaction.user.id}`), + new ButtonBuilder() + .setLabel("Fermer le ticket") + .setStyle(ButtonStyle.Danger) + .setEmoji("🔒") + .setCustomId(`ticket_close-${interaction.user.id}`), + ]); + + const commandEmbed = new EmbedBuilder() + .setColor(`#7961fd`) + .setDescription("*Merci de patienter un peu*"); + + await channel.send({ content: "Bienvenue <@" + interaction.user.id + ">\n<@&778016554066640896> un ticket a été ouvert!", embeds: [commandEmbed], components: [btnrowTicket] }).then(msg => msg.pin()) + await interaction.reply({ content: "Ton ticket a bien été créé ! (<#" + channel.id + ">)", ephemeral: true }) + }).catch(console.error); + break; + + case "report": + const reportmodal = new ModalBuilder() + .setCustomId('reportmodal') + .setTitle('Art\'Portal - Report') + .addComponents( + new ActionRowBuilder() + .addComponents([ + new TextInputBuilder() + .setCustomId('reason') + .setLabel('Raison du report') + .setStyle(TextInputStyle.Paragraph) + .setMinLength(10) + .setMaxLength(1000) + .setPlaceholder(`Merci d'indiquer également le pseudo de la personne !`) + .setRequired(true), + ]), + new ActionRowBuilder() + .addComponents([ + new TextInputBuilder() + .setCustomId('messageslink') + .setLabel('Liens vers les messages (facultatif)') + .setStyle(TextInputStyle.Paragraph) + .setMinLength(10) + .setMaxLength(1000) + .setPlaceholder(`Vous pouvez mettre des liens de messages problématiques. (facultatif mais peut aider)`) + .setRequired(false), + ]), + new ActionRowBuilder() + .addComponents([ + new TextInputBuilder() + .setCustomId('screens') + .setLabel('Captures d\'écran (facultatives)') + .setStyle(TextInputStyle.Paragraph) + .setMinLength(10) + .setMaxLength(1000) + .setPlaceholder(`Vous pouvez mettre des liens vers des captures d'écran.`) + .setRequired(false), + ]), + ); + interaction.showModal(reportmodal); + break; + } + break; + } + }, +}; + +const cmdTypeDict = { + "logo": "Logo", + "discordbanner": "Bannière Discord", + "ytbbanner": "Bannière Youtube/...", + "drawing": "Dessin", + "profilepicture": "Photo de profil", + "video": "Video/Montage", + "overlay": "Overlay de stream", + "emojis": "Émojis/Stickers", + "minia": "Miniature", + "other": "Autre", +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..5494240 --- /dev/null +++ b/package.json @@ -0,0 +1,33 @@ +{ + "name": "april", + "version": "4.0.0", + "description": "Best bot ever OwO", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Art-Portal/April.git" + }, + "keywords": [ + "discord", + "bot", + "js", + "javascript", + "artportal", + "art" + ], + "author": "CoolMan, BakaTaida, Dawn", + "license": "MIT", + "bugs": { + "url": "https://github.com/Art-Portal/April/issues" + }, + "homepage": "https://github.com/Art-Portal/April#readme", + "dependencies": { + "@discordjs/rest": "^1.0.0", + "discord.js": "^14.6.0", + "sequelize": "^6.21.3", + "sqlite3": "^5.0.10" + } +}