This commit is contained in:
Jonny_Bro (Nikita) 2023-07-07 21:13:11 +05:00
parent aaa0d01c54
commit 053bf14ae5
59 changed files with 544 additions and 471 deletions

View file

@ -43,8 +43,10 @@ module.exports = mongoose.model("Guild", new Schema({
messageUpdate: null, messageUpdate: null,
}, },
tickets: { tickets: {
count: 0,
ticketLogs: null, ticketLogs: null,
transcriptionLogs: null, transcriptionLogs: null,
ticketsCategory: null,
}, },
suggestions: null, suggestions: null,
reports: null, reports: null,

View file

@ -72,9 +72,7 @@ class Memes extends BaseCommand {
const embed = new EmbedBuilder() const embed = new EmbedBuilder()
.setColor(client.config.embed.color) .setColor(client.config.embed.color)
.setFooter({ .setFooter(client.config.embed.footer)
text: client.config.embed.footer,
})
.setTitle(res.title) .setTitle(res.title)
.setDescription(`${interaction.translate("fun/memes:SUBREDDIT")}: **${res.subreddit}**\n${interaction.translate("common:AUTHOR")}: **${res.author}**\n${interaction.translate("fun/memes:UPS")}: **${res.ups}**`) .setDescription(`${interaction.translate("fun/memes:SUBREDDIT")}: **${res.subreddit}**\n${interaction.translate("common:AUTHOR")}: **${res.author}**\n${interaction.translate("fun/memes:UPS")}: **${res.ups}**`)
.setImage(res.url) .setImage(res.url)

View file

@ -0,0 +1,23 @@
const { SlashCommandBuilder, PermissionFlagsBits } = require("discord.js");
module.exports = {
data: new SlashCommandBuilder()
.setName("rename")
.setDescription("Renames the ticket channel. Usage: /rename <new name>")
.addStringOption(option => option.setName("newname").setDescription("The new name for the ticket channel").setRequired(true))
.setDefaultMemberPermissions(PermissionFlagsBits.ManageMessages),
async execute(interaction) {
try {
const newName = interaction.options.getString("newname");
if (!interaction.channel.name.includes("support")) {
interaction.reply("This command can only be used in a ticket channel.");
return;
}
await interaction.channel.setName(newName + "-" + interaction.channel.name.split("-")[1]);
interaction.reply(`Renamed the ticket channel to ${newName}`);
} catch (error) {
console.error(error);
interaction.reply("An error occurred while trying to rename the ticket channel.");
}
},
};

View file

@ -58,9 +58,7 @@ class Staff extends BaseCommand {
}, },
]) ])
.setColor(client.config.embed.color) .setColor(client.config.embed.color)
.setFooter({ .setFooter(client.config.embed.footer);
text: client.config.embed.footer,
});
interaction.reply({ interaction.reply({
embeds: [embed], embeds: [embed],

View file

@ -1,4 +1,4 @@
const { SlashCommandBuilder, EmbedBuilder, PermissionsBitField } = require("discord.js"); const { SlashCommandBuilder, EmbedBuilder, PermissionsBitField, ChannelType } = require("discord.js");
const BaseCommand = require("../../base/BaseCommand"); const BaseCommand = require("../../base/BaseCommand");
class Config extends BaseCommand { class Config extends BaseCommand {
@ -47,6 +47,9 @@ class Config extends BaseCommand {
{ name: client.translate("administration/config:MODLOGS"), value: "modlogs" }, { name: client.translate("administration/config:MODLOGS"), value: "modlogs" },
{ name: client.translate("administration/config:REPORTS"), value: "reports" }, { name: client.translate("administration/config:REPORTS"), value: "reports" },
{ name: client.translate("administration/config:SUGGESTIONS"), value: "suggestions" }, { name: client.translate("administration/config:SUGGESTIONS"), value: "suggestions" },
{ name: client.translate("administration/config:TICKETSCATEGORY"), value: "tickets.ticketsCategory" },
{ name: client.translate("administration/config:TICKETLOGS"), value: "tickets.ticketLogs" },
{ name: client.translate("administration/config:TRANSCRIPTIONLOGS"), value: "tickets.transcriptionLogs" },
{ name: client.translate("administration/config:MESSAGEUPDATE"), value: "monitoring.messageUpdate" }, { name: client.translate("administration/config:MESSAGEUPDATE"), value: "monitoring.messageUpdate" },
) )
.setRequired(true), .setRequired(true),
@ -101,9 +104,7 @@ class Config extends BaseCommand {
iconURL: interaction.guild.iconURL(), iconURL: interaction.guild.iconURL(),
}) })
.setColor(client.config.embed.color) .setColor(client.config.embed.color)
.setFooter({ .setFooter(client.config.embed.footer)
text: client.config.embed.footer,
})
.addFields([ .addFields([
{ {
name: interaction.translate("administration/config:WELCOME_TITLE"), name: interaction.translate("administration/config:WELCOME_TITLE"),
@ -155,10 +156,13 @@ class Config extends BaseCommand {
{ {
name: interaction.translate("administration/config:SPECIAL_CHANNELS"), name: interaction.translate("administration/config:SPECIAL_CHANNELS"),
value: value:
`${interaction.translate("administration/config:SUGGESTIONS")}: ${guildData.plugins.suggestions ? `<#${guildData.plugins.suggestions}>` : `*${interaction.translate("common:NOT_DEFINED")}*`}\n` + `${interaction.translate("administration/config:BIRTHDAYS")}: ${guildData.plugins.birthdays ? `<#${guildData.plugins.birthdays}>` : `*${interaction.translate("common:NOT_DEFINED")}*`}` +
`${interaction.translate("administration/config:REPORTS")}: ${guildData.plugins.reports ? `<#${guildData.plugins.reports}>` : `*${interaction.translate("common:NOT_DEFINED")}*`}\n` +
`${interaction.translate("administration/config:MODLOGS")}: ${guildData.plugins.modlogs ? `<#${guildData.plugins.modlogs}>` : `*${interaction.translate("common:NOT_DEFINED")}*`}\n` + `${interaction.translate("administration/config:MODLOGS")}: ${guildData.plugins.modlogs ? `<#${guildData.plugins.modlogs}>` : `*${interaction.translate("common:NOT_DEFINED")}*`}\n` +
`${interaction.translate("administration/config:BIRTHDAYS")}: ${guildData.plugins.birthdays ? `<#${guildData.plugins.birthdays}>` : `*${interaction.translate("common:NOT_DEFINED")}*`}`, `${interaction.translate("administration/config:REPORTS")}: ${guildData.plugins.reports ? `<#${guildData.plugins.reports}>` : `*${interaction.translate("common:NOT_DEFINED")}*`}\n` +
`${interaction.translate("administration/config:SUGGESTIONS")}: ${guildData.plugins.suggestions ? `<#${guildData.plugins.suggestions}>` : `*${interaction.translate("common:NOT_DEFINED")}*`}\n` +
`${interaction.translate("administration/config:TICKETSCATEGORY")}: ${guildData.plugins.tickets.ticketsCategory ? `<#${guildData.plugins.tickets.ticketsCategory}>` : `*${interaction.translate("common:NOT_DEFINED")}*`}\n` +
`${interaction.translate("administration/config:TICKETLOGS")}: ${guildData.plugins.tickets.ticketLogs ? `<#${guildData.plugins.tickets.ticketLogs}>` : `*${interaction.translate("common:NOT_DEFINED")}*`}\n` +
`${interaction.translate("administration/config:TRANSCRIPTIONLOGS")}: ${guildData.plugins.tickets.transcriptionLogs ? `<#${guildData.plugins.tickets.transcriptionLogs}>` : `*${interaction.translate("common:NOT_DEFINED")}*`}\n`,
}, },
{ {
name: interaction.translate("administration/config:DASHBOARD_TITLE"), name: interaction.translate("administration/config:DASHBOARD_TITLE"),
@ -185,14 +189,18 @@ class Config extends BaseCommand {
* @param {import("discord.js").ChatInputCommandInteraction} interaction * @param {import("discord.js").ChatInputCommandInteraction} interaction
* @param {String} setting * @param {String} setting
* @param {Boolean} state * @param {Boolean} state
* @param {import("discord.js").GuildTextBasedChannel} channel * @param {import("discord.js").GuildTextBasedChannel | import("discord.js").CategoryChannel} channel
* @param {import("../../base/Guild")} guildData * @param {import("../../base/Guild")} guildData
* @returns * @returns
*/ */
async function changeSetting(interaction, setting, state, channel, guildData) { async function changeSetting(interaction, setting, state, channel, guildData) {
const settingSplitted = setting.split(".");
if (settingSplitted.length === 2 && guildData.plugins[settingSplitted[0]] === undefined) guildData.plugins[settingSplitted[0]] = {};
if (!state) { if (!state) {
guildData.plugins[setting] = null; guildData.plugins[settingSplitted[0]][settingSplitted[1]] = null;
guildData.markModified(`plugins.${setting}`); guildData.markModified("plugins");
await guildData.save(); await guildData.save();
return interaction.reply({ return interaction.reply({
@ -200,18 +208,20 @@ async function changeSetting(interaction, setting, state, channel, guildData) {
ephemeral: true, ephemeral: true,
}); });
} else { } else {
if (settingSplitted[1] === "ticketsCategory" && channel.type !== ChannelType.GuildCategory) return interaction.reply({ content: interaction.translate("administration/config:TICKETS_NOT_CATEGORY"), ephemeral: true });
if (channel) { if (channel) {
guildData.plugins[setting] = channel.id; guildData.plugins[settingSplitted[0]][settingSplitted[1]] = channel.id;
guildData.markModified(`plugins.${setting}`); guildData.markModified("plugins");
await guildData.save(); await guildData.save();
return interaction.reply({ return interaction.reply({
content: `${interaction.translate(`administration/config:${setting.toUpperCase()}`)}: **${interaction.translate("common:ENABLED")}** (${channel.toString()})`, content: `${interaction.translate(`administration/config:${settingSplitted.length === 2 ? settingSplitted[1].toUpperCase() : setting.toUpperCase()}`)}: **${interaction.translate("common:ENABLED")}** (${channel.toString()})`,
ephemeral: true, ephemeral: true,
}); });
} else } else
return interaction.reply({ return interaction.reply({
content: `${interaction.translate(`administration/config:${setting.toUpperCase()}`)}: ${ content: `${interaction.translate(`administration/config:${settingSplitted.length === 2 ? settingSplitted[1].toUpperCase() : setting.toUpperCase()}`)}: ${
guildData.plugins[setting] ? `**${interaction.translate("common:ENABLED")}** (<#${guildData.plugins[setting]}>)` : `**${interaction.translate("common:DISABLED")}**` guildData.plugins[setting] ? `**${interaction.translate("common:ENABLED")}** (<#${guildData.plugins[setting]}>)` : `**${interaction.translate("common:DISABLED")}**`
}`, }`,
ephemeral: true, ephemeral: true,

View file

@ -54,9 +54,7 @@ class Achievements extends BaseCommand {
name: interaction.translate("economy/achievements:TITLE"), name: interaction.translate("economy/achievements:TITLE"),
}) })
.setColor(client.config.embed.color) .setColor(client.config.embed.color)
.setFooter({ .setFooter(client.config.embed.footer);
text: client.config.embed.footer,
});
embed.addFields([ embed.addFields([
{ {

View file

@ -86,9 +86,7 @@ class Money extends BaseCommand {
}, },
]) ])
.setColor(client.config.embed.color) .setColor(client.config.embed.color)
.setFooter({ .setFooter(client.config.embed.footer);
text: client.config.embed.footer,
});
interaction.editReply({ interaction.editReply({
embeds: [embed], embeds: [embed],
}); });

View file

@ -133,9 +133,7 @@ class Profile extends BaseCommand {
}, },
]) ])
.setColor(client.config.embed.color) .setColor(client.config.embed.color)
.setFooter({ .setFooter(client.config.embed.footer)
text: client.config.embed.footer,
})
.setTimestamp(); .setTimestamp();
const buffer = await userData.getAchievements(); const buffer = await userData.getAchievements();

View file

@ -58,9 +58,7 @@ class Transactions extends BaseCommand {
iconURL: interaction.member.displayAvatarURL(), iconURL: interaction.member.displayAvatarURL(),
}) })
.setColor(client.config.embed.color) .setColor(client.config.embed.color)
.setFooter({ .setFooter(client.config.embed.footer);
text: client.config.embed.footer,
});
const transactions = data.memberData.transactions, const transactions = data.memberData.transactions,
sortedTransactions = [[], []]; sortedTransactions = [[], []];

View file

@ -79,9 +79,7 @@ class Lovecalc extends BaseCommand {
}), }),
) )
.setColor(client.config.embed.color) .setColor(client.config.embed.color)
.setFooter({ .setFooter(client.config.embed.footer);
text: client.config.embed.footer,
});
interaction.reply({ interaction.reply({
embeds: [embed], embeds: [embed],

View file

@ -156,10 +156,8 @@ function generateBoostersEmbeds(client, interaction, boosters, guildData) {
const info = current.map(member => `${++j}. ${member.toString()} | ${interaction.translate("general/boosters:BOOSTER_SINCE")}: **${client.functions.printDate(client, member.premiumSince, null, guildData.language)}**`).join("\n"); const info = current.map(member => `${++j}. ${member.toString()} | ${interaction.translate("general/boosters:BOOSTER_SINCE")}: **${client.functions.printDate(client, member.premiumSince, null, guildData.language)}**`).join("\n");
const embed = new EmbedBuilder() const embed = new EmbedBuilder()
.setColor(interaction.client.config.embed.color) .setColor(client.config.embed.color)
.setFooter({ .setFooter(client.config.embed.footer)
text: interaction.client.config.embed.footer,
})
.setTitle(interaction.translate("general/boosters:BOOSTERS_LIST")) .setTitle(interaction.translate("general/boosters:BOOSTERS_LIST"))
.setDescription(info) .setDescription(info)
.setTimestamp(); .setTimestamp();

View file

@ -55,9 +55,7 @@ class Emoji extends BaseCommand {
}), }),
}) })
.setColor(client.config.embed.color) .setColor(client.config.embed.color)
.setFooter({ .setFooter(client.config.embed.footer)
text: client.config.embed.footer,
})
.addFields([ .addFields([
{ {
name: interaction.translate("common:NAME"), name: interaction.translate("common:NAME"),

View file

@ -101,9 +101,7 @@ class Help extends BaseCommand {
const embed = new EmbedBuilder() const embed = new EmbedBuilder()
.setColor(client.config.embed.color) .setColor(client.config.embed.color)
.setFooter({ .setFooter(client.config.embed.footer)
text: client.config.embed.footer,
})
.setAuthor({ .setAuthor({
name: interaction.translate("general/help:COMMANDS_IN", { category: arg }), name: interaction.translate("general/help:COMMANDS_IN", { category: arg }),
}) })
@ -189,9 +187,7 @@ function generateCommandHelp(interaction, command) {
}, },
]) ])
.setColor(interaction.client.config.embed.color) .setColor(interaction.client.config.embed.color)
.setFooter({ .setFooter(interaction.client.config.embed.footer);
text: interaction.client.config.embed.footer,
});
return embed; return embed;
} }

View file

@ -109,9 +109,7 @@ class Minecraft extends BaseCommand {
]) ])
.setColor(client.config.embed.color) .setColor(client.config.embed.color)
.setThumbnail(`https://eu.mc-api.net/v3/server/favicon/${ip}`) .setThumbnail(`https://eu.mc-api.net/v3/server/favicon/${ip}`)
.setFooter({ .setFooter(client.config.embed.footer);
text: client.config.embed.footer,
});
interaction.editReply({ interaction.editReply({
embeds: [embed], embeds: [embed],

View file

@ -37,9 +37,7 @@ class Ping extends BaseCommand {
async execute(client, interaction) { async execute(client, interaction) {
const embed = new EmbedBuilder() const embed = new EmbedBuilder()
.setColor(client.config.embed.color) .setColor(client.config.embed.color)
.setFooter({ .setFooter(client.config.embed.footer)
text: client.config.embed.footer,
})
.setAuthor({ .setAuthor({
name: interaction.translate("general/ping:PONG"), name: interaction.translate("general/ping:PONG"),
iconURL: client.user.avatarURL(), iconURL: client.user.avatarURL(),

View file

@ -95,9 +95,7 @@ class Report extends BaseCommand {
}, },
]) ])
.setColor(client.config.embed.color) .setColor(client.config.embed.color)
.setFooter({ .setFooter(client.config.embed.footer);
text: client.config.embed.footer,
});
const success = parseEmoji(client.customEmojis.cool).id; const success = parseEmoji(client.customEmojis.cool).id;
const error = parseEmoji(client.customEmojis.notcool).id; const error = parseEmoji(client.customEmojis.notcool).id;

View file

@ -127,9 +127,7 @@ class Serverinfo extends BaseCommand {
]) ])
.setColor(client.config.embed.color) .setColor(client.config.embed.color)
.setFooter({ .setFooter(client.config.embed.footer);
text: client.config.embed.footer,
});
interaction.reply({ interaction.reply({
embeds: [embed], embeds: [embed],

View file

@ -45,9 +45,7 @@ class Stats extends BaseCommand {
const statsEmbed = new EmbedBuilder() const statsEmbed = new EmbedBuilder()
.setColor(client.config.embed.color) .setColor(client.config.embed.color)
.setFooter({ .setFooter(client.config.embed.footer)
text: client.config.embed.footer,
})
.setAuthor({ .setAuthor({
name: interaction.translate("common:STATS"), name: interaction.translate("common:STATS"),
}) })

View file

@ -74,9 +74,7 @@ class Suggest extends BaseCommand {
}, },
]) ])
.setColor(client.config.embed.color) .setColor(client.config.embed.color)
.setFooter({ .setFooter(client.config.embed.footer);
text: client.config.embed.footer,
});
const success = parseEmoji(client.customEmojis.cool).id; const success = parseEmoji(client.customEmojis.cool).id;
const error = parseEmoji(client.customEmojis.notcool).id; const error = parseEmoji(client.customEmojis.notcool).id;

View file

@ -104,9 +104,7 @@ class Userinfo extends BaseCommand {
}, },
]) ])
.setColor(client.config.embed.color) .setColor(client.config.embed.color)
.setFooter({ .setFooter(client.config.embed.footer);
text: client.config.embed.footer,
});
/* /*
if (member.presence.activities[0]?.name === "Custom Status") { if (member.presence.activities[0]?.name === "Custom Status") {

View file

@ -59,9 +59,7 @@ class Whois extends BaseCommand {
ip, ip,
}), }),
) )
.setFooter({ .setFooter(client.config.embed.footer)
text: client.config.embed.footer,
})
.setColor(client.config.embed.color) .setColor(client.config.embed.color)
.addFields( .addFields(
{ name: interaction.translate("common:IP"), value: whois.query, inline: true }, { name: interaction.translate("common:IP"), value: whois.query, inline: true },

View file

@ -57,9 +57,7 @@ class Checkjar extends BaseCommand {
const embed = new EmbedBuilder() const embed = new EmbedBuilder()
.setColor(client.config.embed.color) .setColor(client.config.embed.color)
.setFooter({ .setFooter(client.config.embed.footer)
text: client.config.embed.footer,
})
.setTimestamp() .setTimestamp()
.setDescription(`Текущий баланс: **${jar.balance / Math.pow(10, 2)}** грн\nТребуется на след. месяц: **379,18** грн (по курсу евро на 02.07.2023).\nЗдесь указаны последние 10 транзакций.`); .setDescription(`Текущий баланс: **${jar.balance / Math.pow(10, 2)}** грн\nТребуется на след. месяц: **379,18** грн (по курсу евро на 02.07.2023).\nЗдесь указаны последние 10 транзакций.`);

View file

@ -62,9 +62,7 @@ class Warns extends BaseCommand {
iconURL: member.displayAvatarURL(), iconURL: member.displayAvatarURL(),
}) })
.setColor(client.config.embed.color) .setColor(client.config.embed.color)
.setFooter({ .setFooter(client.config.embed.footer);
text: client.config.embed.footer,
});
if (memberData.sanctions.length === 0) { if (memberData.sanctions.length === 0) {
embed.setDescription( embed.setDescription(

View file

@ -88,9 +88,7 @@ class Nowplaying extends BaseCommand {
}, },
]) ])
.setColor(client.config.embed.color) .setColor(client.config.embed.color)
.setFooter({ .setFooter(client.config.embed.footer)
text: client.config.embed.footer,
})
.setTimestamp(); .setTimestamp();
interaction.editReply({ interaction.editReply({

View file

@ -70,9 +70,7 @@ class NSFW extends BaseCommand {
const embed = new EmbedBuilder() const embed = new EmbedBuilder()
.setColor(client.config.embed.color) .setColor(client.config.embed.color)
.setFooter({ .setFooter(client.config.embed.footer)
text: client.config.embed.footer,
})
.setTitle(res.title) .setTitle(res.title)
.setDescription(`${interaction.translate("fun/memes:SUBREDDIT")}: **${res.subreddit}**\n${interaction.translate("common:AUTHOR")}: **${res.author}**\n${interaction.translate("fun/memes:UPS")}: **${res.ups}**`) .setDescription(`${interaction.translate("fun/memes:SUBREDDIT")}: **${res.subreddit}**\n${interaction.translate("common:AUTHOR")}: **${res.author}**\n${interaction.translate("fun/memes:UPS")}: **${res.ups}**`)
.setImage(res.url) .setImage(res.url)

View file

@ -130,9 +130,7 @@ function generateServersEmbeds(interaction, servers) {
const embed = new EmbedBuilder() const embed = new EmbedBuilder()
.setColor(interaction.client.config.embed.color) .setColor(interaction.client.config.embed.color)
.setFooter({ .setFooter(interaction.client.config.embed.footer)
text: interaction.client.config.embed.footer,
})
.setTitle(interaction.translate("owner/servers:SERVERS_LIST")) .setTitle(interaction.translate("owner/servers:SERVERS_LIST"))
.setDescription(info) .setDescription(info)
.setTimestamp(); .setTimestamp();

View file

@ -1,7 +1,7 @@
const { SlashCommandBuilder, PermissionsBitField } = require("discord.js"); const { SlashCommandBuilder, PermissionsBitField } = require("discord.js");
const BaseCommand = require("../../base/BaseCommand"); const BaseCommand = require("../../base/BaseCommand");
class Adduser extends BaseCommand { class AddUser extends BaseCommand {
/** /**
* *
* @param {import("../../base/JaBa")} client * @param {import("../../base/JaBa")} client
@ -52,7 +52,7 @@ class Adduser extends BaseCommand {
const member = interaction.options.getMember("user"); const member = interaction.options.getMember("user");
if (member.user.bot) return interaction.error("misc:BOT_USER", null, { ephemeral: true, edit: true }); if (member.user.bot) return interaction.error("misc:BOT_USER", null, { ephemeral: true, edit: true });
if (!interaction.channel.name.includes("support") && !interaction.channel.name.includes("application")) return interaction.error("tickets/adduser:NOT_TICKET", null, { ephemeral: true, edit: true }); if (!interaction.channel.name.includes("support")) return interaction.error("tickets/adduser:NOT_TICKET", null, { ephemeral: true, edit: true });
await interaction.channel.permissionOverwrites.edit(member, { ViewChannel: true, SendMessages: true }); await interaction.channel.permissionOverwrites.edit(member, { ViewChannel: true, SendMessages: true });
@ -62,4 +62,4 @@ class Adduser extends BaseCommand {
} }
} }
module.exports = Adduser; module.exports = AddUser;

View file

@ -39,7 +39,7 @@ class CloseTicket extends BaseCommand {
async execute(client, interaction, data) { async execute(client, interaction, data) {
await interaction.deferReply(); await interaction.deferReply();
if (!interaction.channel.name.includes("support") && !interaction.channel.name.includes("application")) return interaction.error("tickets/adduser:NOT_TICKET", null, { ephemeral: true, edit: true }); if (!interaction.channel.name.includes("support")) return interaction.error("tickets/adduser:NOT_TICKET", null, { ephemeral: true, edit: true });
const embed = new EmbedBuilder() const embed = new EmbedBuilder()
.setTitle(interaction.translate("tickets/closeticket:CLOSING_TITLE")) .setTitle(interaction.translate("tickets/closeticket:CLOSING_TITLE"))
@ -51,14 +51,14 @@ class CloseTicket extends BaseCommand {
}, },
{ {
name: interaction.translate("tickets/closeticket:CLOSING_BY"), name: interaction.translate("tickets/closeticket:CLOSING_BY"),
value: interaction.user.getUsetname(), value: interaction.user.getUsername(),
}, },
) )
.setColor(client.config.embed.color) .setColor(client.config.embed.color)
.setFooter(client.config.embed.footer) .setFooter(client.config.embed.footer)
.setTimestamp(); .setTimestamp();
const button = new ButtonBuilder().setCustomId("cancel").setLabel(interaction.translate("common:CANCEL")).setStyle(ButtonStyle.Danger); const button = new ButtonBuilder().setCustomId("cancel_closing").setLabel(interaction.translate("common:CANCEL")).setStyle(ButtonStyle.Danger);
const row = new ActionRowBuilder().addComponents(button); const row = new ActionRowBuilder().addComponents(button);
await interaction.reply({ await interaction.reply({
@ -66,7 +66,7 @@ class CloseTicket extends BaseCommand {
components: [row], components: [row],
}); });
const filter = i => i.customId === "cancel"; const filter = i => i.customId === "cancel_closing";
const collector = interaction.channel.createMessageComponentCollector({ filter, time: 5000 }); const collector = interaction.channel.createMessageComponentCollector({ filter, time: 5000 });
collector.on("collect", async i => { collector.on("collect", async i => {
@ -75,26 +75,44 @@ class CloseTicket extends BaseCommand {
}); });
collector.on("end", async (_, reason) => { collector.on("end", async (_, reason) => {
if (reason === "canceled") { if (reason !== "canceled") {
const transcriptionLogs = data.guildData.plugins.tickets.transcriptionLogs; const transcriptionLogs = data.guildData.plugins.tickets.transcriptionLogs,
if (transcriptionLogs) interaction.guild.channels.cache.get(transcriptionLogs).send({ content: interaction.translate("tickets/closeticket:TRANSCRIPT", { channel: `<#${transcriptionLogs}>` }), files: [{ attachment: Buffer.from(transcript), name: `${interaction.channel.name}.txt` }] }); ticketLogs = data.guildData.plugins.tickets.ticketLogs;
const reversedMessages = await interaction.channel.messages.fetch(); const reversedMessages = (await interaction.channel.messages.fetch()).filter(m => !m.author.bot);
const messages = Array.from(reversedMessages.values()).reverse(); const messages = Array.from(reversedMessages.values()).reverse();
let transcript = ""; let transcript = "---- TICKET CREATED ----\n";
messages.forEach(message => { messages.forEach(message => {
transcript += `${message.author.username}: ${message.content}\n`; transcript += `[${client.functions.printDate(client, message.createdTimestamp)}] ${message.author.getUsername()}: ${message.content}\n`;
}); });
transcript += "---- TICKET CLOSED ----";
try { if (transcriptionLogs) interaction.guild.channels.cache.get(transcriptionLogs).send({ content: interaction.translate("tickets/closeticket:TRANSCRIPT", { channel: `<#${interaction.channelId}>` }), files: [{ attachment: Buffer.from(transcript), name: `${interaction.channel.name}.txt` }] });
await interaction.user.send({ content: `Here is the transcript for your ticket: ${interaction.channel.name}`, files: [{ attachment: Buffer.from(transcript), name: `${interaction.channel.name}.txt` }] });
} catch (error) { if (ticketLogs) {
console.error(error); const logChannel = interaction.guild.channels.cache.get(ticketLogs);
await interaction.reply("An error occurred while trying to send the transcript to the user."); const logEmbed = new EmbedBuilder()
.setTitle(interaction.translate("tickets/createticketembed:TICKET_CLOSED_TITLE"))
.setDescription(`${interaction.user.toString()} (${interaction.channel.toString()})`)
.setColor(client.config.embed.color)
.setFooter(client.config.embed.footer)
.setTimestamp();
logChannel.send({ embeds: [logEmbed] });
} }
await interaction.channel.delete(); interaction.channel.send("Closed!");
try {
await interaction.user.send({
content: interaction.translate("tickets/closeticket:TRANSCRIPT", { channel: interaction.channel.name }),
files: [{ attachment: Buffer.from(transcript), name: `${interaction.channel.name}.txt` }],
});
} catch (e) {
await interaction.reply({ content: interaction.translate("misc:CANT_DM"), ephemeral: true });
}
await interaction.channel.permissionOverwrites.edit(interaction.member, { ViewChannel: false, SendMessages: null });
} }
}); });
@ -108,7 +126,7 @@ class CloseTicket extends BaseCommand {
}, },
{ {
name: interaction.translate("tickets/closeticket:CLOSING_BY"), name: interaction.translate("tickets/closeticket:CLOSING_BY"),
value: interaction.user.getUsetname(), value: interaction.user.getUsername(),
}, },
) )
.setColor(client.config.embed.color) .setColor(client.config.embed.color)

View file

@ -0,0 +1,225 @@
const { SlashCommandBuilder, PermissionsBitField, EmbedBuilder, ButtonBuilder, ButtonStyle, ActionRowBuilder, ChannelType } = require("discord.js");
const BaseCommand = require("../../base/BaseCommand");
class CreateTicketEmbed extends BaseCommand {
/**
*
* @param {import("../../base/JaBa")} client
*/
constructor(client) {
super({
command: new SlashCommandBuilder()
.setName("createticketembed")
.setDescription(client.translate("tickets/createticketembed:DESCRIPTION"))
.setDescriptionLocalizations({
uk: client.translate("tickets/createticketembed:DESCRIPTION", null, "uk-UA"),
ru: client.translate("tickets/createticketembed:DESCRIPTION", null, "ru-RU"),
})
.setDMPermission(false)
.setDefaultMemberPermissions(PermissionsBitField.Flags.ManageGuild),
aliases: [],
dirname: __dirname,
ownerOnly: false,
});
}
/**
*
* @param {import("../../base/JaBa")} client
*/
async onLoad(client) {
client.on("interactionCreate", async interaction => {
if (!interaction.isButton()) return;
const guildData = await client.findOrCreateGuild({ id: interaction.guildId });
const ticketsCategory = guildData.plugins.tickets.ticketsCategory,
ticketLogs = guildData.plugins.tickets.ticketLogs,
transcriptionLogs = guildData.plugins.tickets.transcriptionLogs;
if (interaction.isButton()) {
const button = interaction.component;
if (button.customId === "support_ticket") {
if (guildData.plugins.tickets.count === undefined) guildData.plugins.tickets.count = 0;
guildData.plugins.tickets.count++;
guildData.markModified("plugins.tickets");
guildData.save();
const channel = await interaction.guild.channels.create({
name: `${interaction.user.username}-support-${guildData.plugins.tickets.count}`,
type: ChannelType.GuildText,
parent: ticketsCategory,
permissionOverwrites: [
{
id: interaction.user.id,
allow: [PermissionsBitField.Flags.ViewChannel, PermissionsBitField.Flags.SendMessages],
},
{
id: interaction.guild.roles.everyone,
deny: [PermissionsBitField.Flags.ViewChannel, PermissionsBitField.Flags.SendMessages],
},
],
});
const logChannel = interaction.guild.channels.cache.get(ticketLogs);
const logEmbed = new EmbedBuilder()
.setTitle(interaction.translate("tickets/createticketembed:TICKET_CREATED_TITLE"))
.setDescription(`${interaction.user.toString()} (${channel.toString()})`)
.setColor(client.config.embed.color)
.setFooter(client.config.embed.footer)
.setTimestamp();
await logChannel.send({ embeds: [logEmbed] });
await interaction.success("tickets/createticketembed:TICKET_CREATED", {
channel: channel.toString(),
}, { ephemeral: true });
await channel.send(`<@${interaction.user.id}>`);
const embed = new EmbedBuilder()
.setTitle("Support Ticket")
.setAuthor({ name: interaction.user.getUsername(), iconURL: interaction.user.displayAvatarURL() })
.setDescription(interaction.translate("tickets/createticketembed:TICKET_CREATED_DESC"))
.setColor(client.config.embed.color)
.setFooter(client.config.embed.footer)
.setTimestamp();
const closeButton = new ButtonBuilder()
.setCustomId("close_ticket")
.setLabel(interaction.translate("tickets/closeticket:CLOSE_TICKET"))
.setStyle(ButtonStyle.Danger);
const transcriptButton = new ButtonBuilder()
.setCustomId("transcript_ticket")
.setLabel(interaction.translate("tickets/closeticket:TRANSCRIPT_TICKET"))
.setStyle(ButtonStyle.Secondary);
const row = new ActionRowBuilder().addComponents(closeButton, transcriptButton);
await channel.send({ embeds: [embed], components: [row] });
}
if (button.customId === "close_ticket") {
const embed = new EmbedBuilder()
.setTitle(interaction.translate("tickets/closeticket:CLOSING_TITLE"))
.setDescription(interaction.translate("tickets/closeticket:CLOSING_DESC"))
.addFields(
{
name: interaction.translate("common:TICKET"),
value: interaction.channel.name,
},
{
name: interaction.translate("tickets/closeticket:CLOSING_BY"),
value: interaction.user.getUsername(),
},
)
.setColor(client.config.embed.color)
.setFooter(client.config.embed.footer)
.setTimestamp();
const button = new ButtonBuilder().setCustomId("cancel_closing").setLabel(interaction.translate("common:CANCEL")).setStyle(ButtonStyle.Danger);
const row = new ActionRowBuilder().addComponents(button);
await interaction.reply({
embeds: [embed],
components: [row],
});
const filter = i => i.customId === "cancel_closing";
const collector = interaction.channel.createMessageComponentCollector({ filter, time: 5000 });
collector.on("collect", async i => {
await i.update({ content: interaction.translate("tickets/closeticket:CLOSING_CANCELED"), components: [] });
collector.stop("canceled");
});
collector.on("end", async (_, reason) => {
if (reason !== "canceled") {
const reversedMessages = (await interaction.channel.messages.fetch()).filter(m => !m.author.bot);
const messages = Array.from(reversedMessages.values()).reverse();
let transcript = "---- TICKET CREATED ----\n";
messages.forEach(message => {
transcript += `[${client.functions.printDate(client, message.createdTimestamp)}] ${message.author.getUsername()}: ${message.content}\n`;
});
transcript += "---- TICKET CLOSED ----";
interaction.guild.channels.cache.get(transcriptionLogs).send({ content: interaction.translate("tickets/closeticket:TRANSCRIPT", { channel: `<#${interaction.channelId}>` }), files: [{ attachment: Buffer.from(transcript), name: `${interaction.channel.name}.txt` }] });
const logChannel = interaction.guild.channels.cache.get(ticketLogs);
const logEmbed = new EmbedBuilder()
.setTitle(interaction.translate("tickets/createticketembed:TICKET_CLOSED_TITLE"))
.setDescription(`${interaction.user.toString()} (${interaction.channel.toString()})`)
.setColor(client.config.embed.color)
.setFooter(client.config.embed.footer)
.setTimestamp();
logChannel.send({ embeds: [logEmbed] });
interaction.channel.send("Closed!");
try {
await interaction.user.send({
content: interaction.translate("tickets/closeticket:TRANSCRIPT", { channel: interaction.channel.name }),
files: [{ attachment: Buffer.from(transcript), name: `${interaction.channel.name}.txt` }],
});
} catch (e) {
await interaction.reply({ content: interaction.translate("misc:CANT_DM"), ephemeral: true });
}
await interaction.channel.permissionOverwrites.edit(interaction.member, { ViewChannel: false, SendMessages: null });
}
});
}
if (button.customId === "transcript_ticket") {
await interaction.deferUpdate();
const reversedMessages = (await interaction.channel.messages.fetch()).filter(m => !m.author.bot);
const messages = Array.from(reversedMessages.values()).reverse();
let transcript = "---- TICKET CREATED ----\n";
messages.forEach(message => {
transcript += `[${client.functions.printDate(client, message.createdTimestamp)}] ${message.author.getUsername()}: ${message.content}\n`;
});
transcript += "---- TICKET CLOSED ----";
try {
await interaction.user.send({
content: interaction.translate("tickets/closeticket:TRANSCRIPT", { channel: `<#${interaction.channelId}>` }),
files: [{ attachment: Buffer.from(transcript), name: `${interaction.channel.name}.txt` }],
});
} catch (error) {
await interaction.followUp({ content: interaction.translate("misc:CANT_DM"), ephemeral: true });
}
}
}
});
}
/**
*
* @param {import("../../base/JaBa")} client
* @param {import("discord.js").ChatInputCommandInteraction} interaction
* @param {Object} data
*/
async execute(client, interaction, data) {
if (!data.guildData.plugins.tickets.ticketsCategory) return interaction.error("tickets/createticketembed:NO_CATEGORY");
await interaction.deferReply({ ephemeral: true });
const embed = new EmbedBuilder()
.setTitle(interaction.translate("tickets/createticketembed:TICKET_TITLE"))
.setDescription(interaction.translate("tickets/createticketembed:TICKET_DESC"))
.setColor(client.config.embed.color)
.setFooter(client.config.embed.footer);
const supportButton = new ButtonBuilder().setCustomId("support_ticket").setLabel(interaction.translate("tickets/createticketembed:TICKET_SUPPORT")).setStyle(ButtonStyle.Primary);
const row = new ActionRowBuilder().addComponents(supportButton);
await interaction.channel.send({ embeds: [embed], components: [row] });
interaction.success("tickets/createticketembed:SUCCESS", null, { edit: true });
}
}
module.exports = CreateTicketEmbed;

View file

@ -1,10 +0,0 @@
const { SlashCommandBuilder } = require('discord.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('test')
.setDescription('Replies with test'),
async execute(interaction) {
await interaction.reply('test');
},
};

View file

@ -1,32 +0,0 @@
const { SlashCommandBuilder, EmbedBuilder, ButtonBuilder, ButtonStyle, ActionRowBuilder, PermissionFlagsBits } = require('discord.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('openticketchannel')
.setDescription('Creates an embed with buttons to open a ticket')
.setDefaultMemberPermissions(PermissionFlagsBits.ManageGuild),
async execute(interaction) {
// create embed for ticket
const embed = new EmbedBuilder()
.setTitle('Tickets')
.setDescription('Open a ticket by choosing a category below');
// add button for support and application
const supportButton = new ButtonBuilder()
.setCustomId('support')
.setLabel('Support')
.setStyle(ButtonStyle.Primary);
const applicationButton = new ButtonBuilder()
.setCustomId('application')
.setLabel('Application')
.setStyle(ButtonStyle.Primary);
const row = new ActionRowBuilder()
.addComponents(supportButton, applicationButton);
// send message with buttons
await interaction.channel.send({ embeds: [embed], components: [row] });
await interaction.reply('Done');
},
};

View file

@ -1,35 +1,65 @@
const { SlashCommandBuilder, PermissionFlagsBits } = require('discord.js'); const { SlashCommandBuilder, PermissionsBitField } = require("discord.js");
const BaseCommand = require("../../base/BaseCommand");
module.exports = { class RemoveUser extends BaseCommand {
data: new SlashCommandBuilder() /**
.setName('removeuser') *
.setDescription('Remove a user from a ticket') * @param {import("../../base/JaBa")} client
.addMentionableOption(option => */
option.setName('user') constructor(client) {
.setDescription('The user to remove') super({
.setRequired(true)) command: new SlashCommandBuilder()
.setDefaultMemberPermissions(PermissionFlagsBits.ManageMessages), .setName("removeuser")
async execute(interaction) { .setDescription(client.translate("tickets/removeuser:DESCRIPTION"))
try { .setDescriptionLocalizations({
const user = interaction.options.getMentionable('user'); uk: client.translate("tickets/removeuser:DESCRIPTION", null, "uk-UA"),
const currentChannel = interaction.channel; ru: client.translate("tickets/removeuser:DESCRIPTION", null, "ru-RU"),
})
.setDMPermission(false)
.setDefaultMemberPermissions(PermissionsBitField.Flags.ManageMessages)
.addUserOption(option =>
option
.setName("user")
.setDescription(client.translate("common:USER"))
.setDescriptionLocalizations({
uk: client.translate("common:USER", null, "uk-UA"),
ru: client.translate("common:USER", null, "ru-RU"),
})
.setRequired(true),
),
aliases: [],
dirname: __dirname,
ownerOnly: false,
});
}
if (currentChannel) { /**
if (!interaction.channel.name.includes('support') && !interaction.channel.name.includes('application')) { *
interaction.reply('This command can only be used in a ticket channel.'); * @param {import("../../base/JaBa")} client
return; */
async onLoad() {
//...
} }
const member = await interaction.guild.members.fetch(user.id); /**
await interaction.channel.permissionOverwrites.edit(member, { ViewChannel: false }); *
interaction.reply(`Removed ${user} to the ticket.`); * @param {import("../../base/JaBa")} client
} * @param {import("discord.js").ChatInputCommandInteraction} interaction
else { * @param {Object} data
interaction.reply('This channel is not a ticket.'); */
async execute(client, interaction) {
await interaction.deferReply();
const member = interaction.options.getMember("user");
if (member.user.bot) return interaction.error("misc:BOT_USER", null, { ephemeral: true, edit: true });
if (!interaction.channel.name.includes("support")) return interaction.error("tickets/adduser:NOT_TICKET", null, { ephemeral: true, edit: true });
await interaction.channel.permissionOverwrites.edit(member, { ViewChannel: false, SendMessages: false });
interaction.success("tickets/removeuseruser:SUCCESS", {
user: member.user.toString(),
}, { edit: true });
} }
} }
catch (error) {
console.log(error); module.exports = RemoveUser;
interaction.reply('Error adding user to ticket.');
}
},
};

View file

@ -1,27 +0,0 @@
const { SlashCommandBuilder, PermissionFlagsBits } = require('discord.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('rename')
.setDescription('Renames the ticket channel. Usage: /rename <new name>')
.addStringOption(option =>
option.setName('newname')
.setDescription('The new name for the ticket channel')
.setRequired(true))
.setDefaultMemberPermissions(PermissionFlagsBits.ManageMessages),
async execute(interaction) {
try {
const newName = interaction.options.getString('newname');
if (!interaction.channel.name.includes('support') && !interaction.channel.name.includes('application')) {
interaction.reply('This command can only be used in a ticket channel.');
return;
}
await interaction.channel.setName(newName + '-' + interaction.channel.name.split('-')[1]);
interaction.reply(`Renamed the ticket channel to ${newName}`);
}
catch (error) {
console.error(error);
interaction.reply('An error occurred while trying to rename the ticket channel.');
}
},
};

View file

@ -24,7 +24,9 @@ module.exports = {
/* For the embeds (embeded messages) */ /* For the embeds (embeded messages) */
embed: { embed: {
color: "#0091fc", // The default color for the embeds color: "#0091fc", // The default color for the embeds
footer: "Bot | v" + require("./package.json").version, // And the default footer for the embeds footer: {
text: "Bot | v" + require("./package.json").version,
}, // And the default footer for the embeds
}, },
/* Bot's owner informations */ /* Bot's owner informations */
owner: { owner: {

View file

@ -1,3 +1,12 @@
### JaBa v4.3.3
* Добавлено
* Система Тикетов!\
Все необходимые команды есть в категории *Tickets*.\
Для создавания тикетов нужно обязательно выбрать категорию где они будут сохраняться, сделать это можно через *config set*!\
После этого используйте команду *createticketembed* в канале, где хотите чтобы появилось сообщение с кнопкой создания тикета.\
С помощью команд *adduser* и *removeuser* можно добавлять и убирать людей из тикета соответственно.\
*closeticket* позволяет принудительно закрыть тикет.
### JaBa v4.3.1 ### JaBa v4.3.1
* Добавлено * Добавлено
* Мониторинг изменения сообщений!\ * Мониторинг изменения сообщений!\

View file

@ -21,7 +21,7 @@ class guildBanAdd extends BaseEvent {
iconURL: ban.guild.iconURL(), iconURL: ban.guild.iconURL(),
}) })
.setColor(client.config.embed.color) .setColor(client.config.embed.color)
.setFooter({ text: client.config.embed.footer }) .setFooter(client.config.embed.footer)
.setDescription(`You were banned from **${ban.guild.name}**!\nReason: **${ban.reason || "Not specified"}**`); .setDescription(`You were banned from **${ban.guild.name}**!\nReason: **${ban.reason || "Not specified"}**`);
ban.user.send({ ban.user.send({

View file

@ -30,9 +30,7 @@ class GuildCreate extends BaseEvent {
}) })
.setDescription("Use </help:1029832476077596773> in your server to get list of all commands!.") .setDescription("Use </help:1029832476077596773> in your server to get list of all commands!.")
.setColor(client.config.embed.color) .setColor(client.config.embed.color)
.setFooter({ .setFooter(client.config.embed.footer)
text: client.config.embed.footer,
})
.setTimestamp(); .setTimestamp();
const owner = await guild.fetchOwner(); const owner = await guild.fetchOwner();
@ -55,7 +53,7 @@ class GuildCreate extends BaseEvent {
iconURL: guild.iconURL(), iconURL: guild.iconURL(),
}) })
.setColor(client.config.embed.color) .setColor(client.config.embed.color)
.setFooter({ text: client.config.embed.footer }) .setFooter(client.config.embed.footer)
.setDescription(`Зашёл на сервер **${guild.name}**. На нём **${users}** ${client.functions.getNoun(users, client.translate("misc:NOUNS:USERS:1"), client.translate("misc:NOUNS:USERS:2"), client.translate("misc:NOUNS:USERS:5"))} и **${bots}** ${client.functions.getNoun(bots, client.translate("misc:NOUNS:BOTS:1"), client.translate("misc:NOUNS:BOTS:2"), client.translate("misc:NOUNS:BOTS:5"))}`); .setDescription(`Зашёл на сервер **${guild.name}**. На нём **${users}** ${client.functions.getNoun(users, client.translate("misc:NOUNS:USERS:1"), client.translate("misc:NOUNS:USERS:2"), client.translate("misc:NOUNS:USERS:5"))} и **${bots}** ${client.functions.getNoun(bots, client.translate("misc:NOUNS:BOTS:1"), client.translate("misc:NOUNS:BOTS:2"), client.translate("misc:NOUNS:BOTS:5"))}`);
client.channels.cache.get(client.config.support.logs).send({ client.channels.cache.get(client.config.support.logs).send({
embeds: [embed], embeds: [embed],

View file

@ -21,7 +21,7 @@ class GuildDelete extends BaseEvent {
iconURL: guild.iconURL(), iconURL: guild.iconURL(),
}) })
.setColor(client.config.embed.color) .setColor(client.config.embed.color)
.setFooter({ text: client.config.embed.footer }) .setFooter(client.config.embed.footer)
.setDescription(`Вышел с сервера **${guild.name}**.`); .setDescription(`Вышел с сервера **${guild.name}**.`);
client.channels.cache.get(client.config.support.logs).send({ client.channels.cache.get(client.config.support.logs).send({
embeds: [embed], embeds: [embed],

View file

@ -29,7 +29,7 @@ class MessageCreate extends BaseEvent {
if (message.guild && !message.member) await message.guild.members.fetch(message.author.id); if (message.guild && !message.member) await message.guild.members.fetch(message.author.id);
if (message.guild) { if (message.guild) {
const guildData = await client.findOrCreateGuild({ id: message.guild.id }); const guildData = await client.findOrCreateGuild({ id: message.guildId });
const memberData = await client.findOrCreateMember({ id: message.author.id, guildId: message.guild.id }); const memberData = await client.findOrCreateMember({ id: message.author.id, guildId: message.guild.id });
message.guild.data = data.guildData = guildData; message.guild.data = data.guildData = guildData;
@ -92,7 +92,7 @@ class MessageCreate extends BaseEvent {
}); });
} }
if (data.guildData.plugins.automod.enabled && !data.guildData.plugins.automod.ignored.includes(message.channel.id)) if (data.guildData.plugins.automod.enabled && !data.guildData.plugins.automod.ignored.includes(message.channelId))
if (/(discord\.(gg|io|me|li)\/.+|discordapp\.com\/invite\/.+)/i.test(message.content)) if (/(discord\.(gg|io|me|li)\/.+|discordapp\.com\/invite\/.+)/i.test(message.content))
if (!message.channel.permissionsFor(message.member).has(PermissionsBitField.Flags.ManageMessages)) { if (!message.channel.permissionsFor(message.member).has(PermissionsBitField.Flags.ManageMessages)) {
await message.error("administration/automod:DELETED", null, { mention: true }); await message.error("administration/automod:DELETED", null, { mention: true });

View file

@ -30,7 +30,7 @@ class messageUpdate extends BaseEvent {
iconURL: newMessage.author.displayAvatarURL(), iconURL: newMessage.author.displayAvatarURL(),
}) })
.setColor(client.config.embed.color) .setColor(client.config.embed.color)
.setFooter({ text: client.config.embed.footer }) .setFooter(client.config.embed.footer)
.setTitle(`${newMessage.author.getUsername()} edited a message!`) .setTitle(`${newMessage.author.getUsername()} edited a message!`)
.setDescription(`Old Message: \`\`\`${oldMessage.content}\`\`\`\nNew Message: \`\`\`${newMessage.content}\`\`\`\nJump to message: ${newMessage.url}`); .setDescription(`Old Message: \`\`\`${oldMessage.content}\`\`\`\nNew Message: \`\`\`${newMessage.content}\`\`\`\nJump to message: ${newMessage.url}`);

View file

@ -34,9 +34,7 @@ module.exports.init = async function (client) {
iconURL: client.user.displayAvatarURL(), iconURL: client.user.displayAvatarURL(),
}) })
.setColor(client.config.embed.color) .setColor(client.config.embed.color)
.setFooter({ .setFooter(client.config.embed.footer)
text: client.config.embed.footer,
})
.addFields([ .addFields([
{ {
name: client.translate("economy/birthdate:HAPPY_BIRTHDAY"), name: client.translate("economy/birthdate:HAPPY_BIRTHDAY"),

View file

@ -40,9 +40,8 @@ module.exports.init = function (client) {
}, },
]) ])
.setColor(client.config.embed.color) .setColor(client.config.embed.color)
.setFooter({ .setFooter(client.config.embed.footer);
text: client.config.embed.footer,
});
dUser.send({ dUser.send({
embeds: [embed], embeds: [embed],
}); });

View file

@ -1,241 +0,0 @@
if (interaction.isModalSubmit()) {
const age = interaction.fields.getTextInputValue('age');
const location = interaction.fields.getTextInputValue('location');
const experience = interaction.fields.getTextInputValue('experience');
const why = interaction.fields.getTextInputValue('why');
const embed = new EmbedBuilder()
.setTitle('Application')
.setDescription('Thank you for applying to the server!')
.addFields(
{ name: 'Age', value: age },
{ name: 'Location', value: location },
{ name: 'Experience', value: experience },
{ name: 'Why', value: why },
)
.setColor('#00ff00')
.setTimestamp();
// create ticket channel in application category
const channel = await interaction.guild.channels.create({
name: `${interaction.user.username}-application`,
type: ChannelType.GuildText,
parent: applicationTicketCategory,
permissionOverwrites: [
{
id: interaction.user.id,
allow: [PermissionsBitField.Flags.ViewChannel],
},
{
id: interaction.guild.roles.everyone,
deny: [PermissionsBitField.Flags.ViewChannel],
},
],
});
// for each role in config access_to_ticket array add permission to view channel
for (const role of access_to_ticket) {
await channel.permissionOverwrites.edit(role, { ViewChannel: true });
}
const pingMessage = access_to_ticket.map(role => `||<@&${role}>||`).join(' ') + ` ||${interaction.user}||`;
await channel.send(pingMessage);
// send message to ticket log channel
const logChannel = interaction.guild.channels.cache.get(ticketLogChannel);
await logChannel.send(`Ticket created by ${interaction.user} in ${channel}`);
await interaction.reply({ content: `Your application has been submitted. Please wait for a response from a staff member. ${channel}`, ephemeral: true });
const closeButton = new ButtonBuilder()
.setCustomId('close')
.setLabel('Close')
.setStyle(ButtonStyle.Danger);
const row = new ActionRowBuilder()
.addComponents(closeButton);
await channel.send({ embeds: [embed], components: [row] });
}
else if (interaction.isButton()) {
// handle openTicketChannel button interactions here
// application button ----------------------------------------------------------------------------------------
const button = interaction.component;
if (button.customId === 'application') {
// TODO: Create application embed builder by taking user input
const modal = new ModalBuilder()
.setCustomId('application')
.setTitle('Application');
const ageInput = new TextInputBuilder()
.setCustomId('age')
.setLabel('Enter your age')
.setStyle(TextInputStyle.Short);
const locationInput = new TextInputBuilder()
.setCustomId('location')
.setLabel('Enter your time zone and country')
.setStyle(TextInputStyle.Short);
const experienceInput = new TextInputBuilder()
.setCustomId('experience')
.setLabel('Enter your experience with Minecraft')
.setStyle(TextInputStyle.Paragraph);
const whyInput = new TextInputBuilder()
.setCustomId('why')
.setLabel('Why do you want to join this server?')
.setStyle(TextInputStyle.Paragraph);
const modalRow1 = new ActionRowBuilder()
.addComponents(ageInput);
const modalRow2 = new ActionRowBuilder()
.addComponents(locationInput);
const modalRow3 = new ActionRowBuilder()
.addComponents(experienceInput);
const modalRow4 = new ActionRowBuilder()
.addComponents(whyInput);
modal.addComponents(modalRow1, modalRow2, modalRow3, modalRow4);
await interaction.showModal(modal);
}
// support button ----------------------------------------------------------------------------------------
if (button.customId === 'support') {
const channel = await interaction.guild.channels.create({
name: `${interaction.user.username}-support`,
type: ChannelType.GuildText,
parent: supportTicketCategory,
permissionOverwrites: [
{
id: interaction.user.id,
allow: [PermissionsBitField.Flags.ViewChannel],
},
{
id: interaction.guild.roles.everyone,
deny: [PermissionsBitField.Flags.ViewChannel],
},
],
});
const logChannel = interaction.guild.channels.cache.get(ticketLogChannel);
const logEmbed = new EmbedBuilder()
.setTitle('Ticket Created')
.setDescription(`Ticket created by ${interaction.user} in ${channel}`)
.setTimestamp()
.setFooter({ text: 'Bot created by dylancanada' });
await logChannel.send({ embeds: [logEmbed] });
await interaction.reply({ content: `Ticket created at ${channel}`, ephemeral: true });
for (const role of access_to_ticket) {
await channel.permissionOverwrites.edit(role, { ViewChannel: true });
}
const pingMessage = access_to_ticket.map(role => `||<@&${role}>||`).join(' ');
await channel.send(pingMessage);
const embed = new EmbedBuilder()
.setTitle('Support Ticket')
.setDescription('Ticket created, click the button below to close the ticket')
.setAuthor({ name: interaction.user.username, iconURL: interaction.user.displayAvatarURL() })
.addFields({ name: 'Ticket', value: `Please explain your issue ${interaction.user} and someone will be with you shortly`, inline: false })
.setTimestamp()
.setFooter({ text: 'Bot created by dylancanada' });
const closeButton = new ButtonBuilder()
.setCustomId('close')
.setLabel('Close')
.setStyle(ButtonStyle.Danger);
const row = new ActionRowBuilder()
.addComponents(closeButton);
await channel.send({ embeds: [embed], components: [row] });
}
if (button.customId === 'close') {
const closeEmbed = new EmbedBuilder()
.setTitle('Closing Ticket')
.setDescription('This ticket will be closed in 5 seconds.')
.addFields(
{ name: 'Ticket', value: interaction.channel.name },
{ name: 'Closed By', value: interaction.user.username },
)
.setColor('#ff0000');
const closeButton = new ButtonBuilder()
.setCustomId('cancel')
.setLabel('Cancel')
.setStyle(ButtonStyle.Danger);
const row = new ActionRowBuilder()
.addComponents(closeButton);
await interaction.reply({ embeds: [closeEmbed], components: [row] });
const filter = i => i.customId === 'cancel';
const collector = interaction.channel.createMessageComponentCollector({ filter, time: 5000 });
// eslint-disable-next-line no-unused-vars
collector.on('collect', async i => {
await i.update({ content: 'Ticket close cancelled.', components: [] });
collector.stop();
});
collector.on('end', async collected => {
if (collected.size === 0) {
const transcriptChannel = interaction.guild.channels.cache.get(ticketTranscriptChannel);
const reversedMessages = await interaction.channel.messages.fetch({ limit: 100 });
const messages = Array.from(reversedMessages.values()).reverse();
let transcript = '';
messages.forEach(message => {
transcript += `${message.author.getUsername()}: ${message.content}\n`;
});
transcriptChannel.send({ content: `Transcript for ${interaction.channel.name}`, files: [{ attachment: Buffer.from(transcript), name: `${interaction.channel.name}.txt` }] });
try {
await interaction.user.send({ content: `Here is the transcript for your ticket: ${interaction.channel.name}`, files: [{ attachment: Buffer.from(transcript), name: `${interaction.channel.name}.txt` }] });
}
catch (error) {
console.error(error);
await interaction.reply('An error occurred while trying to send the transcript to the user.');
}
await interaction.channel.delete();
}
});
}
if (button.customId === 'transcript') {
const transcriptChannel = interaction.guild.channels.cache.get(ticketTranscriptChannel);
const reversedMessages = await interaction.channel.messages.fetch({ limit: 100 });
const messages = Array.from(reversedMessages.values()).reverse();
let transcript = '';
messages.forEach(message => {
transcript += `${message.author.username}: ${message.content}\n`;
});
transcriptChannel.send({ content: `Transcript for ${interaction.channel.name}`, files: [{ attachment: Buffer.from(transcript), name: `${interaction.channel.name}.txt` }] });
try {
await interaction.user.send({ content: `Here is the transcript for your ticket: ${interaction.channel.name}`, files: [{ attachment: Buffer.from(transcript), name: `${interaction.channel.name}.txt` }] });
}
catch (error) {
console.error(error);
await interaction.reply('An error occurred while trying to send the transcript to the user.');
}
}
}

View file

@ -8,6 +8,10 @@
"MODLOGS": "Moderation Logs", "MODLOGS": "Moderation Logs",
"REPORTS": "Reports", "REPORTS": "Reports",
"SUGGESTIONS": "Suggestions", "SUGGESTIONS": "Suggestions",
"TICKETSCATEGORY": "Category For Tickets (They have folder icon)",
"TICKETS_NOT_CATEGORY": "Please select a **categry** channel",
"TICKETLOGS": "Tickets Logs",
"TRANSCRIPTIONLOGS": "Transcripts Logs",
"MONITORING_CHANNELS": "Monitoring Channels", "MONITORING_CHANNELS": "Monitoring Channels",
"MESSAGEUPDATE": "Message Update Logs", "MESSAGEUPDATE": "Message Update Logs",

View file

@ -0,0 +1,7 @@
{
"DESCRIPTION": "Adds user to ticket",
"USAGE": "[@user]",
"EXAMPLES": "adduser user:@jonny_bro",
"NOT_TICKET": "This channel is not a ticket",
"SUCCESS": "{{user}} added to the ticket"
}

View file

@ -0,0 +1,13 @@
{
"DESCRIPTION": "Closes ticket",
"USAGE": "",
"EXAMPLES": "closeticket",
"CLOSE_TICKET": "Close Ticket",
"TRANSCRIPT_TICKET": "Get Transcript",
"CLOSING_TITLE": "Ticket Closure",
"CLOSING_DESC": "The ticket will be closed in 5 seconds",
"CLOSING_BY": "Ticket closed by",
"CLOSING_CANCELED": "Ticket closure canceled",
"CLOSED_TITLE": "Ticket Closed",
"TRANSCRIPT": "Transcript from {{channel}}"
}

View file

@ -0,0 +1,15 @@
{
"DESCRIPTION": "Create a message with buttons to create tickets",
"USAGE": "",
"EXAMPLES": "createticketembed",
"SUCCESS": "Post created",
"TICKET_TITLE": "Create a ticket",
"TICKET_DESC": "Create a ticket by clicking a button",
"TICKET_SUPPORT": "Support",
"TICKET_CREATED_TITLE": "Ticket created",
"TICKET_CREATED_DESC": "You can click the button below if you want to close it",
"TICKET_CLOSED_TITLE": "Ticket closed",
"NO_CATEGORY": "Please select a category for tickets before using this command (</config set:1029832475263909920>)",
"TICKET_CREATED": "Your ticket ({{channel}}) has been created, please wait for a response from the administration"
}

View file

@ -0,0 +1,6 @@
{
"DESCRIPTION": "Removes user from ticket",
"USAGE": "[@user]",
"EXAMPLES": "removeuser user:@jonny_bro",
"SUCCESS": "{{user}} removed from the ticket"
}

View file

@ -3,21 +3,21 @@
"name": "en-US", "name": "en-US",
"nativeName": "English", "nativeName": "English",
"moment": "en", "moment": "en",
"defaultMomentFormat": "MMMM Do YYYY", "defaultMomentFormat": "HH:mm:ss, MMMM Do YYYY",
"default": true "default": true
}, },
{ {
"name": "ru-RU", "name": "ru-RU",
"nativeName": "Русский", "nativeName": "Русский",
"moment": "ru", "moment": "ru",
"defaultMomentFormat": "Do MMMM YYYY", "defaultMomentFormat": "HH:mm:ss, Do MMMM YYYY",
"default": false "default": false
}, },
{ {
"name": "uk-UA", "name": "uk-UA",
"nativeName": "Українська", "nativeName": "Українська",
"moment": "uk", "moment": "uk",
"defaultMomentFormat": "Do MMMM YYYY", "defaultMomentFormat": "HH:mm:ss, Do MMMM YYYY",
"default": false "default": false
} }
] ]

View file

@ -8,6 +8,10 @@
"MODLOGS": "Логи модерации", "MODLOGS": "Логи модерации",
"REPORTS": "Жалобы", "REPORTS": "Жалобы",
"SUGGESTIONS": "Предложения", "SUGGESTIONS": "Предложения",
"TICKETSCATEGORY": "Категория для тикетов (Обозначены иконкой папки)",
"TICKETS_NOT_CATEGORY": "Выберите **категорию** для каналов",
"TICKETLOGS": "Логи тикетов",
"TRANSCRIPTIONLOGS": "Логи расшифровок",
"MONITORING_CHANNELS": "Каналы мониторинга", "MONITORING_CHANNELS": "Каналы мониторинга",
"MESSAGEUPDATE": "Логи изменения сообщений", "MESSAGEUPDATE": "Логи изменения сообщений",

View file

@ -2,6 +2,8 @@
"DESCRIPTION": "Закрыть тикет", "DESCRIPTION": "Закрыть тикет",
"USAGE": "", "USAGE": "",
"EXAMPLES": "closeticket", "EXAMPLES": "closeticket",
"CLOSE_TICKET": "Закрыть тикет",
"TRANSCRIPT_TICKET": "Получить расшифровку",
"CLOSING_TITLE": "Закрытие тикета", "CLOSING_TITLE": "Закрытие тикета",
"CLOSING_DESC": "Тикет закроется через 5 секунд", "CLOSING_DESC": "Тикет закроется через 5 секунд",
"CLOSING_BY": "Тикет закрыл", "CLOSING_BY": "Тикет закрыл",

View file

@ -0,0 +1,15 @@
{
"DESCRIPTION": "Создать сообщение с кнопками для создания тикетов",
"USAGE": "",
"EXAMPLES": "createticketembed",
"SUCCESS": "Сообщение создано",
"TICKET_TITLE": "Создать тикет",
"TICKET_DESC": "Создайте тикет нажав кнопку ниже",
"TICKET_SUPPORT": "Поддержка",
"TICKET_CREATED_TITLE": "Тикет создан",
"TICKET_CREATED_DESC": "Вы можете нажать кнопку ниже если хотите закрыть его",
"TICKET_CLOSED_TITLE": "Тикет закрыт",
"NO_CATEGORY": "Перед использованием этой команды выберите категорию для тикетов (</config set:1029832475263909920>)",
"TICKET_CREATED": "Ваш тикет ({{channel}}) создан, ожидайте ответа администрации"
}

View file

@ -0,0 +1,6 @@
{
"DESCRIPTION": "Убрать пользователя из тикета",
"USAGE": "[@user]",
"EXAMPLES": "removeuser user:@jonny_bro",
"SUCCESS": "{{user}} убран из тикета"
}

View file

@ -8,6 +8,10 @@
"MODLOGS": "Логи модерації", "MODLOGS": "Логи модерації",
"REPORTS": "Скарги", "REPORTS": "Скарги",
"SUGGESTIONS": "Пропозиції", "SUGGESTIONS": "Пропозиції",
"TICKETSCATEGORY": "Категорія для тікетів (Позначені іконкою папки)",
"TICKETS_NOT_CATEGORY": "Виберіть **категорію** для каналів",
"TICKETLOGS": "Логи тікетів",
"TRANSCRIPTIONLOGS": "Логи розшифровок",
"MONITORING_CHANNELS": "Каналы мониторинга", "MONITORING_CHANNELS": "Каналы мониторинга",
"MESSAGEUPDATE": "Логи изменения сообщений", "MESSAGEUPDATE": "Логи изменения сообщений",

View file

@ -0,0 +1,7 @@
{
"DESCRIPTION": "Додати користувача до тікета",
"USAGE": "[@user]",
"EXAMPLES": "adduser user:@jonny_bro",
"NOT_TICKET": "Цей канал не є квитком",
"SUCCESS": "{{user}} додано до тікета"
}

View file

@ -0,0 +1,13 @@
{
"DESCRIPTION": "Закрити тікет",
"USAGE": "",
"EXAMPLES": "closeticket",
"CLOSE_TICKET": "Закрити тікет",
"TRANSCRIPT_TICKET": "Отримати розшифровку",
"CLOSING_TITLE": "Закриття квитка",
"CLOSING_DESC": "Тікет буде закрито через 5 секунд",
"CLOSING_BY": "Тікет закрито користувачем",
"CLOSING_CANCELED": "Скасування закриття квитка",
"CLOSED_TITLE": "Тікет закрито",
"TRANSCRIPT": "Копія повідомлень з {{channel}}"
}

View file

@ -0,0 +1,15 @@
{
"DESCRIPTION": "Створити повідомлення з кнопками для створення тікетів",
"USAGE": "",
"EXAMPLES": "createticketembed",
"SUCCESS": "Повідомлення створено",
"TICKET_TITLE": "Створити тікет",
"TICKET_DESC": "Створіть тікет натиснувши кнопку",
"TICKET_SUPPORT": "Підтримка",
"TICKET_CREATED_TITLE": "Тікет створений",
"TICKET_CREATED_DESC": "Ви можете натиснути кнопку нижче, якщо хочете закрити його",
"TICKET_CLOSED_TITLE": "Тікет закрит",
"NO_CATEGORY": "Перед використанням цієї команди оберіть категорію тікетів (</config set:1029832475263909920>)",
"TICKET_CREATED": "Ваш тікет ({{channel}}) створен, чекайте відповіді адміністрації"
}

View file

@ -0,0 +1,6 @@
{
"DESCRIPTION": "Видалити користувача з тікета",
"USAGE": "[@user]",
"EXAMPLES": "removeuser user:@jonny_bro",
"SUCCESS": "{{user}} видалено з тікета"
}

View file

@ -1,6 +1,6 @@
{ {
"name": "jaba", "name": "jaba",
"version": "4.3.1", "version": "4.3.3",
"description": "My Discord Bot", "description": "My Discord Bot",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {