0

Alright so my problem is that in the first set of console.log(streamXXXX)s, where XXXX are the various variables, when I read their values they all read as they should, while in the second set they read as undefined. Is this a scope issue? Maybe an Async issue? I tried adding awaits to each time I make a web request but nothing seems to work, and one of the most interesting parts about this is the fact that there are no errors?

Anyways, my code is listed below, as well as a link to test it out in Repl using a sample bot I created. Below that is the list of libraries required for said program to run. Thanks!

if (!message.member.voiceChannel) return message.channel.send(`You do realize you have to be in a voice channel to do that, right ${message.author.username}?`)

if (!message.member.voiceConnection) message.member.voiceChannel.join().then(async connection => {

    let streamURL = args.slice(1).join(" ")
    let streamTitle = "";
    let streamThumb = "";
    let streamAuth = "";
    let streamAuthThumb = "";

    if (streamURL.includes("https://www.youtube.com") || streamURL.includes("https://youtu.be/") && !streamURL.includes(' ')) {
        youtube.getVideo(streamURL)
            .then(async results => {
                let {
                    body
                } = await snekfetch.get(`https://www.googleapis.com/youtube/v3/channels?part=snippet&id=${results.channel.id}&fields=items%2Fsnippet%2Fthumbnails&key=${ytapikey}`).query({
                    limit: 800
                })

                streamTitle = results.title
                streamThumb = results.thumbnails.medium.url
                streamAuth = results.channel.title
                streamAuthThumb = body.items[0].snippet.thumbnails.medium.url

                console.log(streamURL)
                console.log(streamTitle)
                console.log(streamThumb)
                console.log(streamAuth)
                console.log(streamAuthThumb)
            })
            .catch(console.error)
    } else if (!streamURL.includes("https://www.youtube.com") || !streamURL.includes("https://youtu.be/")) {
        youtube.searchVideos(streamURL)
            .then(async results => {
                let {
                    body
                } = await snekfetch.get(`https://www.googleapis.com/youtube/v3/channels?part=snippet&id=${results[0].channel.id}&fields=items%2Fsnippet%2Fthumbnails&key=${ytapikey}`).query({
                    limit: 800
                })

                streamURL = results[0].url
                streamTitle = results[0].title
                streamThumb = results[0].thumbnails.default.medium.url
                streamAuth = results[0].channel.title
                streamAuthThumb = body.items[0].snippet.thumbnails.medium.url
            }).catch(console.error)
    } else {
        return message.reply("I can only play videos from YouTube (#NotSponsored).")
    }

    console.log(streamURL)
    console.log(streamTitle)
    console.log(streamThumb)
    console.log(streamAuth)
    console.log(streamAuthThumb)

    const stream = ytdl(streamURL, {
        filter: 'audioonly'
    })
    const dispatcher = connection.playStream(stream)
    dispatcher.on("end", end => {
        return
    })

    let musicEmbed = new Discord.RichEmbed()
        .setAuthor(streamAuth, streamAuthThumb)
        .setTitle(`Now Playing: ${streamTitle}`)
        .setImage(streamThumb)
        .setColor(embedRed)
        .setFooter(`${streamAuth} - ${streamTitle} (${streamURL}`)

    await message.channel.send(musicEmbed)
})

Link to test out the program on a sample bot I made

Modules you will need to test this:

discord.js
simple-youtube-api
node-opus
ffmpeg
ffbinaries
ffmpeg-binaries
opusscript
snekfetch
node-fetch
ytdl-core

Thanks again!

David J
  • 49
  • 1
  • 3
  • 11
  • in the first set streamTitle = results.title, in the second set streamTitle = results[0].title Are you sure results is a list and the first item has url property in the second set? – xplo4d Jan 22 '20 at 16:50
  • Yes, the documentation says to do it like this as `searchVideo()` returns multiple results while `getVideo()` only returns one – David J Jan 22 '20 at 18:07

1 Answers1

1

The reason why your output is undefined is due to the way promises work and how you structured your code:

let streamTitle = "";

// 1. Promise created
youtube.getVideo(streamURL)
  // 2. Promise still pending, skip for now
  .then(async results => {
    // 4. Promise fulfilled
    console.log(results.title); // 5. Logged actual title
});

console.log(streamTitle); // 3. Logged ""

You already have the correct approach for your snekfetch requests, just need to apply it to the YT ones as well:

let streamTitle = "";

const results = await youtube.getVideo(streamURL);

streamTitle = results.title;

console.log(streamTitle); // Desired output
Chris Satchell
  • 751
  • 5
  • 17
  • Ok this solves my initial problem of passing variables so thank you so much! I have been pondering this for quite a while now without being able to find a solid answer. Now to my next question: How can I get some audio to play? The code I have when tested in a different circumstance worked swimmingly, but here it seems to do nothing. – David J Jan 22 '20 at 18:18
  • 1
    Please create a new question with the relevant code for your audio issue. – Chris Satchell Jan 22 '20 at 18:34