When a person sends my command, a channel is created that only they have access to. Also, when creating a channel, a message is sent with the "accept" button, when another person clicks on the button, his rights in the created channel should be added. I can add rights, but when more than one message with a button arrives in a special channel, the person who clicked the button is added to all created channels
An example of how it works
let myreportChannel = ''
await interaction.guild.channels.create(channelNameMy, {
type: 'text', parent: `${categoryTiket}`, permissionOverwrites: [
{
id: `${permUser}`, // permUser - who sent the command
allow: ['VIEW_CHANNEL', 'SEND_MESSAGES', 'READ_MESSAGE_HISTORY', 'ATTACH_FILES']
},
{
id: `${evryOneRolle}`,
deny: ['VIEW_CHANNEL', 'SEND_MESSAGES', 'READ_MESSAGE_HISTORY']
},
]
})
//Prvivate embed
.then(async reportChannel => {
const exampleEmbed = new MessageEmbed()
.setDescription(`Reported: <#${tagBan.id}>\nReason: ${reason}\ntiket: <#${reportChannel.id}>`)
.setColor("#2F3136")
.setImage(`${settings.reportgif}`)
myreportChannel = reportChannel.id // save new channel id
await interaction.reply({embeds: [exampleEmbed], ephemeral: true})
//Report embed
const reportEmbed = new MessageEmbed()
.setDescription(`Intruder: ${tagBan}\nReason: ${reason}`)
.setColor("#2F3136")
.setImage(`${settings.reportgif}`)
await client.channels.cache.get(`${reportChannel.id}`).send({
embeds: [reportEmbed]
})
})
client.on('interactionCreate', async interaction => {
if (interaction.isButton()) {
if (interaction.customId.includes(`acceptB`)) {
const editEmbRep = new MessageEmbed()
.setDescription(`Author: <#${interaction.user.id}>\nIntruder: <#${tagBan.id}>\nStatus: ${dmStatusAc}\nTiket: <#${myreportChannel}>`)
.setColor("#2F3136")
.setImage(`${settings.reportgif}`)
interaction.message.edit({
content: 'updated text',
embeds: [editEmbRep],
components: []
})
let channelx = interaction.guild.channels.cache.get(myreportChannel) // set channel by id
if (channelx) {
channelx.permissionOverwrites.edit(interaction.user.id, {
VIEW_CHANNEL: true,
SEND_MESSAGES: true,
ATTACH_FILES: true,
READ_MESSAGE_HISTORY: true
}) //edit permision channel. add the permission of the user who clicked on the "accept" button
}
So I adjusted the code above and made some notes along the way, but this should work as expected. I split the command from the button push.
const reportChannel = await interaction.guild.channels.create(channelNameMy, {
type: 'text',
parent: `${categoryTiket}`,
permissionOverwrites: [{
id: `${permUser}`, // permUser - who sent the command
allow: ['VIEW_CHANNEL', 'SEND_MESSAGES', 'READ_MESSAGE_HISTORY', 'ATTACH_FILES']
},
{
id: `${evryOneRolle}`,
deny: ['VIEW_CHANNEL'] //denying view channel will stop all other ones from working too
},
]
})
//Prvivate embed
const exampleEmbed = new MessageEmbed()
.setDescription(`Reported: <#${tagBan.id}>\nReason: ${reason}\nticket: <#${reportChannel.id}>`)
.setColor("#2F3136")
.setImage(`${settings.reportgif}`)
interaction.reply({
embeds: [exampleEmbed],
ephemeral: true
})
//Report embed
const reportEmbed = new MessageEmbed()
.setDescription(`Intruder: ${tagBan}\nReason: ${reason}\nticket:<#${reportChannel.id}>`)
.setColor("#2F3136")
.setImage(`${settings.reportgif}`)
.setFooter({
text: `${reportChannel.id}` // I added the channel ID here again (critical part of the code to not change
})
// adds the new channel id to the footer to be used later when someone clicks the accept button
const acceptButton = new MessageActionRow()
.addComponents(
new MessageButton()
.setCustomId(`acceptB`)
.setLabel('Accept')
.setStyle('SUCCESS')
.setEmoji('✅')
)
client.channels.cache.get(reportChannel.id).send({
embeds: [reportEmbed],
components: [acceptButton]
})
client.on('interactionCreate', async interaction => {
if (interaction.isButton()) {
if (interaction.customId.includes(`acceptB`)) {
// when someone clicks the accept button it grabs the embed
const oldEmbed = interaction.message.embeds[0]
// adds a line to that embed
const editEmbRep = new MessageEmbed()
.addField('Status:', `${dmStatusAc}`)
// updates the embed and removes the button
interaction.message.edit({
embeds: [editEmbRep],
components: []
})
// finds the channel using the channel id placed in the footer earlier
const channelx = interaction.guild.channels.cache.get(oldEmbed.footer.text)
channelx.permissionOverwrites.edit(interaction.user.id, {
VIEW_CHANNEL: true,
SEND_MESSAGES: true,
ATTACH_FILES: true,
READ_MESSAGE_HISTORY: true
}) // adds them to the channel
}
}
})
Related
I am back again with a question :). I am building my own ticket function, and I just started but if I create a channel for a ticket, its only saying ticket-(Discord account ID) And thats also the case by the embed. Anyone who can look at it?
const discord = require("discord.js");
const { MessageEmbed, Collection, Permissions} = require('discord.js');
const { execute } = require("./ticket");
module.exports = {
name: 'create',
description: 'create your own ticket.',
execute(message, client, args){
if(message.guild.channels.cache.find(channel => channel.name === "Ticket from <#" + message.author + ">")) {
message.reply(`${message.member.user.toString()} **You have successfully created a ticket, Please click on ${channel} to view your ticket**`).then(m => m.delete({ timeout: 14000 }).catch(e => {}));
if(message.guild.channels.cache.find(channel => channel.name === `ticket-${message.author.id}`)) {
return message.reply('<a:no:784463793366761532> **You already have a ticket, please close your exsisting ticket first before opening a new one**');
}
message.delete();
message.guild.channels.create(`Ticket ${message.author}`, {
permissionOverwrites: [
{
id: message.author.id,
allow: ['SEND_MESSAGES', 'VIEW_CHANNEL'],
},
{
id: message.guild.roles.everyone,
deny: ['VIEW_CHANNEL'],
},
],
type: 'text',
}).then(async channel => {
const embed = new MessageEmbed()
.setTitle("<#" + message.author + "> Ticket")
.setDescription(`**${message.author}, Welcome to your channel! Support will be arriving soon**\n**While you wait please tell us what your problem is**\n**If you want to close the ticket please type .close\`**`)
.setColor("BLUE")
channel.send({ embeds: [embed] })
});
}
}
}
I cleaned up the code a fair bit, less is more. Text channels do not have spaces in them so I replaced them with what Discord uses, hypens. The below code will check if a channel already exists and create one if it doesn't.
const {
MessageEmbed,
} = require('discord.js');
module.exports = {
name: 'create',
description: 'create your own ticket.',
async execute(message, client, args) {
const channelName = `ticket-${message.author.username}`
const existing = message.guild.channels.cache.find(channel => channel.name === channelName.toLowerCase());
if (existing) {
return message.reply({
content: `<a:no:784463793366761532> **You already have a ticket, please close your exsisting ticket first before opening a new one**\n${existing}.`,
}).then((m) => {
setTimeout(() => {
m.delete();
}, 14000);
})
}
message.delete();
message.guild.channels.create(channelName, {
type: 'GUILD_TEXT',
permissionOverwrites: [{
id: message.guild.id,
deny: ['VIEW_CHANNEL'],
}, {
id: message.author.id,
allow: ['SEND_MESSAGES', 'VIEW_CHANNEL'],
}],
}).then(async channel => {
const embed = new MessageEmbed()
.setColor("BLUE")
.setTitle(`${message.author.username} Ticket`)
.setDescription(`**${message.author}, Welcome to your channel! Support will be arriving soon**\n**While you wait please tell us what your problem is**\n**If you want to close the ticket please type .close\`**`)
channel.send({
embeds: [embed]
})
});
}
}
I have been getting an error as mentioned in the title. Whenever I use that command, the bot creates a channel that brings up a select menu, through which the user can "teleport" to another channel while deleting the newly created channel in the process. This code successfully works twice, after which it gives the error. What should be done to fix the error so that the user can use the command as many times as they'd like? I'll work on this code further once the solution is found, but until then, I'm really stumped here. (Questions shall be answered upon questioning; apologies for the messy coding)
module.exports.run = async (client, msg, args) => {
const guild = client.guilds.cache.get('855845132879921214')
const channel = guild.channels.cache.get('959851265456734319')
const newChannel = await msg.guild.channels.create(`teleporter`)
await newChannel.permissionOverwrites.edit(msg.author.id, {
SEND_MESSAGES: false,
VIEW_CHANNEL: true,
})
const {MessageActionRow, MessageSelectMenu, MessageEmbed} = require('discord.js')
const embed = new MessageEmbed()
.setTitle(`Teleporter!`)
.setDescription("Through this interaction, you can now teleport to the main channel of the desired category!")
const row = new MessageActionRow()
.addComponents(
new MessageSelectMenu()
.setCustomId('teleport')
.setPlaceholder('Choose a channel')
.addOptions([
{
label: 'Rules',
description: "Click to check the rules",
value: 'rules',
},
{
label: 'General',
description: "Click to go to the main chat",
value: 'general',
},
{
label: 'Media',
description: "Click to go to media channel",
value: 'media',
},
{
label: 'Bots',
description: "Click to go to the bots channel",
value: 'bots',
}
]),
)
await newChannel.send({content: `<#${msg.author.id}>`,embeds: [embed], components: [row]})
const wait = require('util').promisify
client.on('interactionCreate', async interaction => {
const member = await interaction.guild.members.fetch({
user: interaction.user.id,
force: true
})
if(!interaction.isSelectMenu()) {
interaction.deferUpdate()}
else if (interaction.values == 'general'){
msg.member.roles.add('958421069650337822')
msg.member.roles.remove('943159431800172584')
let tele = msg.guild.channels.cache.find(channel => channel.name == 'teleporter')
tele.delete()
msg.member.roles.add('943159431800172584')
msg.member.roles.remove('958421069650337822')
}
}
)
}
Don't cache.find and delete, do it like;
const newChannel = await client.channels.fetch("id")
newChannel.delete()
This code should be separated with the first section as your command and the second part as a separate listener, so I have coded as such.
const {
MessageActionRow,
MessageSelectMenu,
MessageEmbed,
} = require('discord.js');
module.exports.run = async (client, msg, args) => {
const guild = client.guilds.cache.get('855845132879921214');
const channel = guild.channels.cache.get('959851265456734319');
const newChannel = await msg.guild.channels.create(`teleporter-${msg.author.username}`, {
permissionOverwrites: [{
id: guild.id,
deny: ["VIEW_CHANNEL"],
}, {
id: msg.author,
deny: ["SEND_MESSAGES"],
allow: ["VIEW_CHANNEL"],
}],
});
// In the event that more than one person uses this command at once, you will need to be able to tell the diffrence when you look up the channel later. So I added the username to the channel name.
const embed = new MessageEmbed()
.setTitle(`Teleporter!`)
.setDescription("Through this interaction, you can now teleport to the main channel of the desired category!");
const row = new MessageActionRow()
.addComponents(
new MessageSelectMenu()
.setCustomId('teleport')
.setPlaceholder('Choose a channel')
.addOptions([{
label: 'Rules',
description: "Click to check the rules",
value: 'rules',
}, {
label: 'General',
description: "Click to go to the main chat",
value: 'general',
}, {
label: 'Media',
description: "Click to go to media channel",
value: 'media',
}, {
label: 'Bots',
description: "Click to go to the bots channel",
value: 'bots',
}]),
);
await newChannel.send({
content: `${msg.author}`,
embeds: [embed],
components: [row],
});
};
This section would go either in the main bot.js file, or if you have your events in seperate files, it would go in the interactionCreate file (may need to be changed a bit if you don't have one, let me know)
const wait = require('util').promisify;
client.on('interactionCreate', async interaction => {
const member = interaction.member;
const guild = interaction.guild;
if (interaction.isSelectMenu()) {
const menuName = interaction.customId;
interaction.deferUpdate();
if (menuName === 'teleport') {
const tele = guild.channels.cache.find(channel => channel.name == `teleporter-${member.user.username}`);
// lookup the channel using the previously mentioned channel name setup
const choice = interaction.value;
if (choice === 'general') {
member.roles.add('958421069650337822');
member.roles.remove('943159431800172584');
} else if (choice === 'rules') {
member.roles.add('roleID');
member.roles.remove('roleID');
} else if (choice === 'media') {
member.roles.add('roleID');
member.roles.remove('roleID');
} else if (choice === 'bots') {
member.roles.add('roleID');
member.roles.remove('roleID');
}
tele.delete();
}
}
});
I am making a tickets bot.
When I try click of any of the embeds, it will run the code and create a new channel, then continue to ping me in it like I wanted, but then shows this error.
DiscordAPIError: Invalid Form Body
components[0].components[1].emoji.name: Invalid emoji
at RequestHandler.execute (C:\Users\wrigh\Documents\Discord Bots\Practice Bot - Copy\node_modules\discord.js\src\rest\RequestHandler.js:350:13)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async RequestHandler.push (C:\Users\wrigh\Documents\Discord Bots\Practice Bot - Copy\node_modules\discord.js\src\rest\RequestHandler.js:51:14)
at async TextChannel.send (C:\Users\wrigh\Documents\Discord Bots\Practice Bot - Copy\node_modules\discord.js\src\structures\interfaces\TextBasedChannel.js:175:15)
The full error is here (sorry for link wouldn't let me post full error) :
https://sourceb.in/dOCoUtAQVx
The code is here:
const { ButtonInteraction, MessageEmbed, MessageActionRow, MessageButton } = require("discord.js");
const DB = require("../../Structures/Handlers/Schemas/Ticket");
const { PARENTID, EVERYONEID } = require("../../Structures/config.json");
const Ticket = require("../../Structures/Handlers/Schemas/Ticket");
module.exports = {
name: "interactionCreate",
/**
*
* #param {ButtonInteraction} interaction
*/
async execute(interaction) {
if(!interaction.isButton()) return;
const { guild, member, customId } = interaction;
if (!["player", "bug", "other"].includes(customId)) return;
const ID = Math.floor(Math.random() * 90000) + 10000;
await guild.channels
.create(`${customId + "-" + ID}`, {
type: "GUILD_TEXT",
parent: PARENTID,
permissionOverwrites: [
{
id: member.id,
allow: ["SEND_MESSAGES", "VIEW_CHANNEL", "READ_MESSAGE_HISTORY"],
},
{
id: EVERYONEID,
deny: ["SEND_MESSAGES", "VIEW_CHANNEL", "READ_MESSAGE_HISTORY"],
},
],
})
.then(async (channel) => {
await DB.create({
GuildID: guild.id,
MemberID: member.id,
TicketID: ID,
ChannelID: channel.id,
Closed: false,
Locked: false,
type: customId,
});
const Embed = new MessageEmbed()
.setAuthor(
`${guild.name} | Ticket: ${ID}`,
guild.iconURL({ dynamic: true })
)
.setDescription(
"Please wait patiently for a response from the Staff team, in the mean while, describe your issue in as much detail."
)
.setFooter("The buttons below are staff only buttons.");
const Buttons = new MessageActionRow();
Buttons.addComponents(
new MessageButton()
.setCustomId("close")
.setLabel("Save and close")
.setStyle("PRIMARY")
.setEmoji("📂"),
new MessageButton()
.setCustomId("lock")
.setLabel("lock")
.setStyle("SECONDARY")
.setEmoji("'🔒"),
new MessageButton()
.setCustomId("unlock")
.setLabel("unlock")
.setStyle("SUCCESS")
.setEmoji("❤"),
);
channel.send({
embeds: [Embed],
components: [Buttons],
});
await channel
.send({ content: `${member} here is your ticket` })
.then((m) => {
setTimeout(() => {});
}, 1 * 5000);
})
interaction.reply({
content: `${member} your ticket has been created: ${channel}`,
});
},
};
```js
I'm still learning JavaScript so please bear with me if I don't get it straight away, I will try my best.
You have an extra character in your lock button. It should be .setEmoji("🔒"), not .setEmoji("'🔒"). That's what the error is telling you: "Invalid Emoji" (because '{lock} isn't an emoji)
Code:
const role = interaction.options.getRole('role');
const description = interaction.options.getString('description');
const emoji = interaction.options.getString('emoji');
const parsedEmoji = Util.parseEmoji(emoji);
if (role.position >= interaction.guild.me.roles.highest.position) {
const embed = new MessageEmbed()
.setColor('RED')
.setTitle('Error:')
.setDescription(`I can not add roles that are higher than mine`)
.setTimestamp()
.setFooter({ text: `Phantom Bot v${config.version}` });
return interaction.reply({ embeds: [embed], ephemeral: true });
}
ReactionRole.findOne({ guild_id: interaction.guild.id }, (err, settings) => {
if (err) {
const embed = new MessageEmbed()
.setColor('RED')
.setTitle('Error:')
.setDescription(`There was an error while adding the reaction role`)
.setTimestamp()
.setFooter({ text: `Phantom Bot v${config.version}` });
return interaction.reply({ embeds: [embed], ephemeral: true });
}
if (!settings) {
new ReactionRole({
guild_id: interaction.guild.id,
message: 0,
roles: {
[parsedEmoji.name]: [
role.id,
{
description: description,
id: parsedEmoji.id,
raw: emoji
}
]
}
}).save();
} else {
settings.roles[parsedEmoji.name] = [
role.id,
{
description: description,
id: parsedEmoji.id,
raw: emoji
}
]
ReactionRole.findOneAndUpdate({ guild_id: interaction.guild.id }, settings);
}
const embed = new MessageEmbed()
.setColor('PURPLE')
.setTitle('Reaction Added:')
.setDescription(`Role ${role}\nEmoji: ${emoji}`)
.setTimestamp()
.setFooter({ text: `Phantom Bot v${config.version}` });
interaction.reply({ embeds: [embed] });
});
Issue:
For some reason if the settings do exist in the else statement, it doesn't actually update it in the Mongoose database. It actually doesn't touch it at all. I've tried awaiting the ReactionRole.findOneAndUpdate but I got an error saying I couldn't await it.
How can I fix this?
Any help would be appreciated!
Fixed buy making the function an async, then it would allow await.
This is my code for a webhook discord alert bot. I used discord.js and the channel's webhooks. I used readline-sync for the input at the console but when I iterate through the answer at console to determine the embed colour, all signals show yellow from the last iteration for some reason.
const { MessageEmbed, WebhookClient } = require('discord.js');
const readline = require('readline-sync')
const webhookClient = new WebhookClient({ id: '', token: '' });
var signal = readline.question("Signal: ")
if (signal.content === "SELL")
{
const embed = new MessageEmbed()
.setTitle(signal)
.setColor('RED')
.setFooter({
text: "test"
})
webhookClient.send({
content: 'Webhook test',
username: "Logan's Signals",
avatarURL: 'https://i.imgur.com/AfFp7pu.png',
embeds: [embed],
});
}
else if (signal.content === "BUY")
{
const embed = new MessageEmbed()
.setTitle(signal)
.setColor('GREEN')
.setFooter({
text: "test"
})
webhookClient.send({
content: 'Webhook test',
username: "Logan's Signals",
avatarURL: 'https://i.imgur.com/AfFp7pu.png',
embeds: [embed],
});
}
else
{
const embed = new MessageEmbed()
.setTitle(signal)
.setColor('YELLOW')
.setFooter({
text: "test"
})
webhookClient.send({
content: 'Webhook test',
username: "Logan's Signals",
avatarURL: 'https://i.imgur.com/AfFp7pu.png',
embeds: [embed],
});
}