Reputation: 39
I want to ask for a .txt file, read file and send the file content to the channel using a discord bot.
Description of intended behavior:
This is my most recent attempt at creating this command:
if (message.content === '!readfile') {
message.channel.send("Send your file please...");
message.channel.awaitMessages(filter, {max: 1}).then(msg => {
const filter = m => m.author.id === message.author.id;
let file = msg.attachments.first().file;
fs.readFile(file, (err, data) => {
msg.channel.send("Read the file! Fetching data...");
msg.channel.send(data);
});
});
}
Upvotes: 1
Views: 688
Reputation: 23169
As I've mentioned in a previous post, you can't use the fs
module to read the content of the attached files as it only deals with local files.
When you upload a file through Discord, it gets uploaded to a CDN. You can't grab the file itself (and there is no file
property on the MessageAttachment either), all you can do is to grab the URL of the uploaded file using the url
property.
As you want to get a file from the web, you will need to fetch it by a URL. You can use the built-in https
module, or you can install one from npm, like axios
, node-fetch
, etc.
I used node-fetch
in my example and make sure you install it first by running npm i node-fetch
in your root folder.
Check out the working code below, it works fine with text files:
// on the top
const fetch = require('node-fetch');
client.on('message', async (message) => {
if (message.author.bot) return;
const args = message.content.slice(prefix.length).split(/ +/);
const command = args.shift().toLowerCase();
if (command === 'readfile') {
message.channel.send('Send your file please...');
const filter = (m) => m.author.id === message.author.id;
try {
const collected = await message.channel.awaitMessages(filter, { max: 1 });
// get the file's URL
const file = collected.first().attachments.first()?.url;
if (!file) return console.log('No attached file found');
// await the message, so we can later delete it
const sent = await message.channel.send(
'Reading the file! Fetching data...',
);
// fetch the file from the external URL
const response = await fetch(file);
// if there was an error send a message with the status
if (!response.ok) {
sent.delete();
return message.channel.send(
'There was an error fetching your file:',
response.statusText,
);
}
// take the response stream and read it to completion
const text = await response.text();
if (text) {
sent.delete();
return message.channel.send(`\`\`\`${text}\`\`\``);
}
} catch (err) {
console.log(err);
return message.channel
.send(`Oops, that's lame. There was an error...`)
.then((sent) => setTimeout(() => sent.delete(), 2000));
}
}
});
Also, don't forget that awaitMessages()
returns a collection of messages, even if the max
option is set to 1, so you will need to grab the first()
one.
Upvotes: 1