I am having issues with running my bot with DigitalOverflow. It contains a command that takes a screenshots of websites and sends them in the channel. However, when I use the command with DigitalOverflow, I simply get this error, and I'm not sure how to fix it. There's nothing above that either and I've searched and searched with no avail.
if(!message.channel.nsfw) return message.channel.send('This command is only usable in NSFW channels.')
if(!args[0]) return message.channel.send("Please provide a URL!");
let msg = args.join(" ")
const browser = await puppeteer.launch({ args: ['--disable-setuid-sandbox', '--disable-gpu','--no-first-run','--no-sandbox',]});
const page = await browser.newPage();
message.channel.send("Please wait, this may take a while.").then(msg => msg.delete({timeout: 8000, reason: ""}))
await page.goto(`${msg}`);
await page.screenshot({path: 'example.png'});
await browser.close();
message.channel.send("`" + `${msg}` + "`", {files: ["./example.png"]}).catch((e) => message.channel.send(`Issue found: ${e}`))
Related
Newbie here. I am trying to get a slash command to send an embed with the amount of time it took between the initial message and the message response time. I am getting TypeError: Cannot read properties of undefined (reading 'createdTimestamp') and Error [INTERACTION_ALREADY_REPLIED]: The reply to this interaction has already been sent or deferred. I've jumped around looking at others code trying to find a way to make this work but slash command handling still doesn't make a lot of sense to me. My code block is below. I followed along with https://discordjs.guide so if you have any other suggestions with structure feel free to comment them below. Thank you!
const { SlashCommandBuilder } = require('#discordjs/builders');
const { MessageEmbed } = require('discord.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('ping')
.setDescription('Replies with Pong!'),
async execute(interaction) {
await interaction.reply("Pinging bot...").then (async (msg) =>{
const exampleEmbed = new MessageEmbed()
.setColor('0x0000ff')
.setTitle('Pong! :ping_pong:')
.addField("Time taken: ", `${msg.createdTimestamp - message.createdTimestamp}`)
.setThumbnail("https://78.media.tumblr.com/be43242341a7be9d50bb2ff8965abf61/tumblr_o1ximcnp1I1qf84u9o1_500.gif")
interaction.editReply({ embeds: [exampleEmbed] });
})
},
};
first you need to fetch the reply you send, u can use fetchReply to get the interaction reply. instead of replying with "Pinging bot..." you can defer the reply and then use the createdTimestamp. A basic example of a ping command would be
const { SlashCommandBuilder } = require('#discordjs/builders');
module.exports = {
data: new SlashCommandBuilder()
.setName('ping')
.setDescription('Replies with Pong!'),
async execute(interaction) {
const sent = await interaction.reply({ content: 'Pinging...', fetchReply: true });
await interaction.editReply(`:ping_pong: Pong!\n:stopwatch: Uptime: ${Math.round(interaction.client.uptime / 60000)} minutes\n:sparkling_heart: Websocket heartbeat: ${interaction.client.ws.ping}ms.\n:round_pushpin: Rountrip Latency: ${sent.createdTimestamp - interaction.createdTimestamp}ms`);
},
};
You can customize the response into an embed or however you like. The djs guide has a section on ping command here
I've recently followed a slash command tutorial from discordjs guide. It all works, but the issue is that I am unable to have the slash commands in more than 1 server, as I have manually put the guild ID in, and cannot find a way to get the guild ID when the bot is ready. Here's the code:
const clientID = '942177936553959464';
const guildID = '936781831037157426';
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
commands.push(command.data.toJSON());
}
(async () => {
try {
console.log('Started refreshing application (/) commands.');
await rest.put(
Routes.applicationGuildCommands(clientID, guildID), // Error is at guildID, as it is not getting the actual guilds ID, just the one I set for testing.
{ body: commands },
);
console.log('Successfully reloaded application (/) commands.');
} catch (error) {
console.error(error);
}
})();
The way you register is a guild-specific way of registering slash commands. There are 2 routes you can take.
First - Have an array of guild IDs and loop over them and register it per guild. Something like this would work fine
const clientID = "942177936553959464";
const guilds = ["id1", "id2", "id3"];
guilds.forEach((guildID) => {
// Register the slash commands here
});
Second - Register the slash commands globally(For all guilds). Do note global commands take some time to be cached and made available by the discord API.
https://discordjs.guide/interactions/registering-slash-commands.html#global-commands
Note - The First approach should be followed while the bot is in the development stage and not in production
I'm working on a small project to learn puppeteer and discord bots, thought it would be interesting to combine the two and make a weird cyborg bot thing that is essentially a bot but a normal user. I've set up the command handlers, etc, and I've created an 'invite' command that takes one of the arguments that the person provides (the code of the server invite) and uses it to auto-invite itself.
for example typing in discord: <prefix>invite 78uHjkaf
This semi-works. Not really. It'll work the first time, but never again and I'll have to restart the thing. I keep trying to add a page.close(); hoping that it will solve the problem but then it won't work at all. How can I make this work consistently and reusably? - Note that my command handler works fine. The entire issue is located within the following code. (I hope)
Semi reliable.
if (command === "invite") {
const invite = async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://discordapp.com/');
let [link] = args;
await page.evaluate(async ({link}) => {
const x = new XMLHttpRequest();
x.open(`POST`, `https://discordapp.com/api/v6/invites/` + `${link}`);
x.setRequestHeader('Authorization', 'my token');
x.send();
},{link});
};
invite();
}
Doesn't work at all.
if (command === "invite") {
const invite = async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://discordapp.com/');
let [link] = args;
await page.evaluate(async ({link}) => {
const x = new XMLHttpRequest();
x.open(`POST`, `https://discordapp.com/api/v6/invites/` + `${link}`);
x.setRequestHeader('Authorization', 'my token');
x.send();
},{link});
await page.close();
};
invite();
}
I am REALLY stumped.
Update.
For some reason shifting
x.open(`POST`, `https://discordapp.com/api/v6/invites/` + `${link}`);
to
x.open(`POST`, `https://discordapp.com/api/v6/invites/${link}`);
fixed the problem of unreliability. Adding a close page still kills it though. I feel like that should be added however?
Why are you using Puppeteer? It's easier to use the Discord private API instead.
const fetch = require('node-fetch'); // npm install node-fetch
if (command === "invite") {
const [code] = args; // should only be the code, not full URL (8KqbkST, not https://discord.gg/8KqbkST)
fetch(`https://discord.com/api/v8/invites/${code}`, {
method: 'POST',
headers: { 'authorization': 'YOUR USER TOKEN' },
body: JSON.stringify({
code,
new_member: true
})
});
}
By the way this is totally forbidden by the Discord T.O.S and you should not use it for massive use such as joining a lot of servers at once (because it is forbidden, and because this type of behavior is very painful on Discord).
Use this 100%
const fetch = require('node-fetch'); // npm install node-fetch
if (command === "invite") {
const [code] = args; // should only be the code, not full URL (8KqbkST, not https://discord.gg/8KqbkST)
fetch(https://discord.com/api/v8/invites/${code}, {
method: 'POST',
headers: { 'authorization': 'YOUR USER TOKEN' },
body: JSON.stringify({
code,
new_member: true
})
});
}
I have tried many different ways of formatting the code, however, whenever I add code so that I must provide a reasoning to ban someone, I am always given an Internal Server Error. Here is my code.
module.exports.run = async (client, message, args) => {
const member = message.mentions.members.first();
const reason = args.slice(1).join(" ")
if (!message.member.hasPermission("BAN_MEMBERS")) {
return message.reply("you lack sufficiant permissions to execute this command.");
} else if (member.hasPermission("ADMINISTRATOR")) {
message.reply("you cannot ban this member.")
}
member.ban(reason).then((member) => {
message.channel.send(`${member} has been banned.`);
});
I use a command handler, and all my other commands work fine.
first step: Define the user
let user = message.mentions.members.first() || message.guild.members.cache.get(args.join(' '));
Second step: Create embed message or normal message
const userbanned = new Discord.MessageEmbed()
.setColor('#FF0000')
.setAuthor('User Banned')
.setDescription(`**${user.user.username}#${user.user.discriminator}** is now banned from this server`)
.setFooter(`bot_name`);
Third step: Send message
user.send(`You were banned from **${message.guild.name}** by ${message.author.username}#${message.author.discriminator}`)
return user
.ban()
.then(() => message.channel.send(userbanned))
.catch(error => message.reply("ERROR"));
Try changing
member.ban().then((member) =>//
to
member.ban({reason : args.slice(1).join(' ')}).then((member) =>//
I'm trying to make a confirmation portion of my command where if you activate the command, you need to say "yes" before the code activates. The reoccurring problem is that the code right after the message that says
Confirmed... Please wait.
After this, it completely skips over the code and does nothing. When I was writing the code in VSC, the async portion of the code wasn't highlighted with yellow, but more of a darker yellow.
I've tried removing this portion of the code
const async = async () => {
But the code with await cannot run unless it's connected to async.
I've tried changing how the async is ran.
async () => {
Still the same result.
Removing the beginning async code will also just result in the command breaking.
I've placed the big chunk of code outside of the then(collected code, but after a few seconds of waiting when the command activates, it immediately runs, then brings up a value error. But I want it so that code activates when the author says "Yes"
async run(message, args){
if (message.channel instanceof Discord.DMChannel) return message.channel.send('This command cannot be executed here.')
let replyMessage = message.reply('Please make sure that my integration role "Synthibutworse" is above the default role used for this server. Is this correct? [Reply with "YES"] if so. Will expire in 20 seconds...');
let filter = msg => msg.author.id == message.author.id && msg.content.toLowerCase() == 'yes';
message.channel.awaitMessages(filter, {max: 1, time: 20000}).then(collected => {
message.reply('Confirmed... Please wait.');
const async = async () => {
if(!message.member.guild.me.hasPermission(['MANAGE_WEBHOOKS'])) return message.channel.send('I don\'t have the permissions to make webhooks, please contact an admin or change my permissions!')
if(!message.member.guild.me.hasPermission(['MANAGE_ROLES'])) return message.channel.send('I don\'t have the permissions to make roles, please contact an admin or change my permissions!')
if (!message.member.hasPermission(['MANAGE_WEBHOOKS'])) return message.channel.send('You need to be an admin or webhook manager to use this command.')
if (!message.member.hasPermission(['MANAGE_ROLES'])) return message.channel.send('You need to be an admin or role manager to use this command.')
const avatar = `https://cdn.discordapp.com/attachments/515307677656678420/557050444954992673/Generic5.png`;
const name2 = "SYNTHIBUTWORSE-1.0WOCMD";
let woaID = message.mentions.channels.first();
if(!woaID) return message.channel.send("Channel is nonexistant or command was not formatted properly. Please do s!woa #(channelname)");
let specifiedchannel = message.guild.channels.find(t => t.id == woaID.id);;
const hook = await woaID.createWebhook(name2, avatar).catch(error => console.log(error))
await hook.edit(name2, avatar).catch(error => console.log(error))
message.channel.send("Please do not tamper with the webhook or else the command implied before will no longer function with this channel.")
var role = message.guild.createRole({
name: `Synthibutworse marker v1.0`,
color: 0xcc3b3b,}).catch(console.error);
specifiedchannel.send("Created role...");
if(message.guild.roles.name == "Synthibutworse marker v1.0") {
role.setMentionable(false, 'SBW Ping Set.')
role.setPosition(1)
role.setPermissions(['CREATE_INSTANT_INVITE', 'SEND_MESSAGES'])
.then(role => console.log(`Edited role`))
.catch(console.error)};
message.channel.send("Role set up...");
const sbwrID = message.guild.roles.find(`Synthibutworse marker v1.0`);
let specifiedrole = message.guild.roles.find(r => r.id == sbwrID.id)
message.channel.send('Created Role... Please wait.');
message.guild.specifiedchannel.replacePermissionOverwrites({
overwrites: [
{
id: specifiedrole,
denied: ['SEND_MESSAGES'],
allowed: ['VIEW_CHANNEL'],
},
],
reason: 'Needed to change permissions'
});
var bot = message.client
bot.on('message', function(message) { {
if(webhook.name == `Synthibutworse marker`) return
if(message.channel.id == webhook.channelID) return
{let bannedRole = message.guild.roles.find(role => role.id === specifiedrole);
message.member.addRole(bannedRole)};
}});
}});
}};
module.exports = woa;
I expect the command to run with the async and continue with the code when the message author says "yes", and doesn't stop at the Please wait. message.
What actually happens is the code doesn't run right after the Please wait message.
In your current code, you're declaring an async function but never calling it. That's why the code is never run and why VSC darkens its name.
Solution:
Define your awaitMessages(...)'s .then() callback as async:
.then(async collected => {
// do async stuff
});
For future reference, if you need to use async code somewhere that you can't define a function as async, use the following setup:
(async function() {
// do async stuff
})();