DeepDev
DeepDev

Reputation: 11

Discord.js - CommandFile.Run() is not a function

I'm currently trying to reorganize my Bot for my Discord Server by upgrading my Command Handler. Most of the command I have also upgraded but one command stands out because it is not working.

When I try to run that command the following happens:

(node:11496) UnhandledPromiseRejectionWarning: TypeError: CommandFile.run is not a function
    at module.exports.run (C:\Users\DeepDev\OneDrive\Bureaublad\DiscordBot\DiscordBotV2.1\src\commands\Music\Play.js:43:32)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
(node:11496) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:11496) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

And this is the code I have for the part that is currently not working:

        if (!Validate) {
            let CommandFile = require(`./Search.js`);
            return CommandFile.run(Client, message, args, ops);
        }

The Command Handler I'm using is from MenuDocs v12 Tutorial.

I've tried placing this part into a function outside the class and called the function after the if statement but to no avail.

            let CommandFile = require(`./Search.js`);
            return CommandFile.run(Client, message, args, ops);

I have also checked if it was the correct file location of the Search.js.

Search.js File:

const Command = require('../../Structures/Command.js');
const Discord = require("discord.js");
const Search= require('yt-search');

module.exports = class extends Command {
    // eslint-disable-next-line no-unused-vars
     async run(message, args, ops) {

     const Client = this.client

     //Search for videos based on arguments
     Search(args.join(' '), function(err, res) {
       //Error Handling
       let errembed = new Discord.MessageEmbed()
       .setColor("#218559")
       .setAuthor(Client.user.username, Client.user.displayAvatarURL({ dynamic:true }))
       .setDescription("Sorry, something went wrong")
       if (err) return message.channel.send(errembed);

       //Show first 10 results
       let Videos = res.videos.slice(0, 10);

       //Loop for output string
       let Resp = '';
       for (var i in Videos) {
         Resp += `**[${parseInt(i)+1}]:** \`${Videos[i].title}\`\n`;
       }

       //Text Info Instructions
       Resp += `\n**Choose a number between** \`1-${Videos.length}\``;

       //Embed
       let Embed = new Discord.MessageEmbed()
           .setColor("#218559")
           .setTitle("Search Results")
           .setAuthor(Client.user.username, Client.user.displayAvatarURL({ dynamic:true }))
           .setDescription(Resp)
           .setThumbnail(Client.user.displayAvatarURL({ dynamic:true }))

       //Send output
       message.channel.send(Embed);

       //Message collector
       const Filter = m => !isNaN(m.content) && m.content < Videos.length+1 && m.content > 0;
       //Filter accepts only numbers
       const Collector = message.channel.createMessageCollector(Filter);

       //Update collector variables
       Collector.videos = Videos;

       //Create Listener Event
       Collector.once('collect', function(m) {

         //Run play command, passing in the url as args[0]
         let CommandFile = require(`./Play.js`);
         CommandFile.run(Client, message, [this.videos[parseInt(m.content)-1].url], ops);
       });
     });
    }

};

This all worked with the previous command handler I was using. The complete Play.js:

const Command = require('../../Structures/Command.js');
const Discord = require("discord.js");
const ytdl = require("ytdl-core");

module.exports = class extends Command {

  constructor(...args) {
    super(...args, {
      aliases: ['p']
    });
  }

    // eslint-disable-next-line no-unused-vars
    async run(message, args, ops) {

        const Client = this.client

        //Check if author is connected to a voice channel
        let AC = new Discord.MessageEmbed()
            .setColor("#218559")
            .setAuthor(Client.user.username, Client.user.displayAvatarURL({
                dynamic: true
            }))
            .setDescription("You have to be connected to a voice channel, you dummy!")
        if (!message.member.voice.channel) return message.channel.send(AC);


        //Check if author input an URL
        let VU = new Discord.MessageEmbed()
            .setColor("#218559")
            .setAuthor(Client.user.username, Client.user.displayAvatarURL({
                dynamic: true
            }))
            .setDescription("Hey Dumdum, you need a valid URL")
        if (!args[0]) return message.channel.send(VU);

        //Validate Info
        let Validate = await ytdl.validateURL(args[0]);

        //Check Validation
        if (!Validate) {
            let CommandFile = require(`./Search.js`);
            return CommandFile.run(Client, message, args, ops);
        }

        //Fetch video information
        let Info = await ytdl.getInfo(args[0]);

        //Fetch Active
        let Data = ops.active.get(message.guild.id) || {};

        //Update the Data
        if (!Data.Connection) Data.Connection = await message.member.voice.channel.join();
        if (!Data.Queue) Data.Queue = [];
        Data.guildID = message.guild.id;

        //Add song to queue
        Data.Queue.push({
            SongTitle: Info.videoDetails.title,
            Requester: message.author.tag,
            url: args[0],
            AnnounceChannel: message.channel.id
        })

        //If there is no dispatcher, run the play function
        let QA = new Discord.MessageEmbed()
            .setColor("#218559")
            .setAuthor(Client.user.username, Client.user.displayAvatarURL({
                dynamic: true
            }))
            .setDescription(`Added to Queue: ${Info.videoDetails.title} | Requested by my favourite dummy ${Data.Queue[0].Requester}`)
        if (!Data.Dispatcher) Play(Client, ops, Data);
        else {
            message.channel.send(QA);
        }

        //Update the Map
        ops.active.set(message.guild.id, Data);

    }
};

//Play Function
    async function Play(Client, ops, Data) {
    //Send Now Playing Message
    let NP = new Discord.MessageEmbed()
        .setColor("#218559")
        .setAuthor(Client.user.username, Client.user.displayAvatarURL({
            dynamic: true
        }))
        .setDescription(`Now playing: ${Data.Queue[0].SongTitle} | Requested by my favourite dummy ${Data.Queue[0].Requester}`)
    Client.channels.cache.get(Data.Queue[0].AnnounceChannel).send(NP);

    //Update Dispatcher Data
    Data.Dispatcher = await Data.Connection.play(ytdl(Data.Queue[0].url, {
        filter: "audioonly"
    }));
    Data.Dispatcher.guildID = Data.guildID;

    //Listener event
    Data.Dispatcher.once("finish", function() {
        //Finish Function
        finish(Client, ops, this);
    });
}

    function finish(Client, ops, Dispatcher) {
    //Fetch Guild Object from Map
    let Fetched = ops.active.get(Dispatcher.guildID);

    //Remove the previous SongTitle
    Fetched.Queue.shift();

    //Check if Queue is empty
    if (Fetched.Queue.length > 0) {

        //Update the map with the new queue
        ops.active.set(Dispatcher.guildID, Fetched);

        //Play the next song
        Play(Client, ops, Fetched);

    } else {
        //Delete the guild object from the Map
        ops.active.delete(Dispatcher.guildID);

        //Leave the voice channel
        let vc = Client.guilds.cache.get(Dispatcher.guildID).me.voice.channel;
        if (vc) vc.leave();
    }
}

Upvotes: 1

Views: 417

Answers (2)

Antoine Eskaros
Antoine Eskaros

Reputation: 851

Please fix your search.js file first.

module.exports = class extends Command {
     // missing first parameter
     async run(Client, message, args, ops) {

     // this.client is undefined
     // const Client = this.client

then initialize the class before you use it.

 return new CommandFile().run(Client, message, args, ops);

I would suggest using named export like @Cehhiro answer

Upvotes: 0

OFRBG
OFRBG

Reputation: 1778

class Search extends Command {
  async run(message, args, ops) {
    /* things here */
  }
};

module.exports = { Search };

and use with the require at the top of the file.

const { Search } = require(`./Search.js`);

and invoke with

{
  ...
  return new Search().run(message, args, ops);
}

Upvotes: 1

Related Questions