Downloading Content with a Discord Bot

I am developing a music bot for Discord, which is capable of playing tracks stored locally. However, I’m encountering an issue when trying to create a command that fetches a song from YouTube and saves it into this local directory. The command initiates the download, and while the file appears in the directory, it is empty (0 bytes) and the process never completes.

require('dotenv').config();
const { Client, GatewayIntentBits, Events } = require('discord.js');
const { joinVoiceChannel, createAudioPlayer, createAudioResource, AudioPlayerStatus, getVoiceConnection } = require('@discordjs/voice');
const path = require('path');
const fs = require('fs');
const ytdl = require('ytdl-core');

const bot = new Client({
    intents: [
        GatewayIntentBits.Guilds,
        GatewayIntentBits.GuildVoiceStates,
        GatewayIntentBits.GuildMessages,
        GatewayIntentBits.MessageContent
    ]
});

bot.once(Events.ClientReady, () => {
    console.log(`Bot is online: ${bot.user.tag}`);
});

bot.on(Events.MessageCreate, async (msg) => {
    if (!msg.guild || msg.author.bot) return;

    const params = msg.content.split(' ');
    const commandName = params.shift().toLowerCase();

    if (msg.content.startsWith('!downloadtrack')) {
        const link = params[1];

        if (!ytdl.validateURL(link)) {
            return msg.channel.send('Please provide a valid YouTube link.');
        }

        const details = await ytdl.getInfo(link);
        const songTitle = details.videoDetails.title.replace(/[\W_]+/g, ''); // Filename cleaned of special chars

        const filePath = path.resolve(__dirname, 'songs', `${songTitle}.mp3`);
        msg.channel.send(`Beginning download: **${songTitle}**...`);

        try {
            // Download stream and convert to MP3 with ffmpeg
            const downloadStream = ytdl(link, { filter: 'audioonly' });
            const fileStream = fs.createWriteStream(filePath);
            downloadStream.pipe(fileStream);

            fileStream.on('finish', () => {
                msg.channel.send(`Track **${songTitle}** has been downloaded successfully.`);
            });

            fileStream.on('error', (error) => {
                console.error('Error saving file:', error);
                msg.channel.send('An error occurred while trying to download the track.');
            });

        } catch (error) {
            console.error('Error downloading track:', error);
            msg.channel.send('There was an issue processing the YouTube link.');
        }
    }
});

I’m uncertain about what steps to take next to resolve this issue.

One common issue with downloading YouTube audio through Discord bots can be the lack of error handling around the network and ffmpeg processes. Ensure that your additions like ytdl are not getting blocked by YouTube updates. Also, consider checking if you’ve set up ffmpeg correctly and whether it’s accessible in your execution environment. Misconfigurations can lead to a download initiation without any actual data transfer. Use libraries like “fluent-ffmpeg” to debug and handle ffmpeg errors better. Sometimes adding event listeners to the stream, like ‘response’, may also reveal what’s going wrong.