Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ECONNRESET #332

Closed
FireController1847 opened this issue Jun 23, 2018 · 11 comments
Closed

ECONNRESET #332

FireController1847 opened this issue Jun 23, 2018 · 11 comments
Labels

Comments

@FireController1847
Copy link
Collaborator

FireController1847 commented Jun 23, 2018

It's baack!

My bot is almost always returning an ECONNRESET with its streams. This was caught after using stream.on("error") and an extremely long wait time before data is emitted.

Here is a song that has been reported causing the issue. This song also ECONNRESET's with my test eval. Multiple others songs are like this.

@fent
Copy link
Owner

fent commented Jun 24, 2018

What does the code around it look like?

This song also ECONNRESET's with my test eval.

What do you mean?

@FireController1847
Copy link
Collaborator Author

The code around it is... well, this.

// Set Info Vars
    info.channel_link = "https://www.youtube.com/channel/" + info.ucid;
    info.video_link = "https://www.youtube.com/watch?v=" + info.video_id;
    try {
      const newt = info.thumbnail_url.replace("default", "maxresdefault");
      const res = await snekfetch.get(newt);
      info.thumbnail = (res.status == 404 ? info.thumbnail_url.replace("default", "hqdefault") : newt);
    } catch(e) {
      info.thumbnail = info.thumbnail_url.replace("default", "hqdefault");
    }
    const lengthMin = pms(info.length_seconds * 1000, {verbose: true, secDecimalDigits: 0});
    // Create stream & dispatcher
    let stream;
    let dispatcher;
    try {
      stream = yt(song.url, { quality: 'highestaudio' } );
      // const stream = yt(song.url, {'audioonly': true, 'quality': (server.donationAmount >= 5 ? "highest" : "lowest")});
      dispatcher = conn.play(stream);
    } catch (e) {
      if (e && e.message == 'ENOMEM') {
        if (channel) channel.send(ce(
          this.manager.colors.default, null, 'No Memory Available',
          `We apologize for the inconvinience, but there is currently no RAM left on the server to begin playing ` +
          `music on your server! Please wait a while before running the command, or keep trying to see if you can ` +
          `get a spot!`
        ));
        return this.manager.forceEnd(gid);
      }
      if (e && channel) channel.send(ce(
        this.manager.colors.default, null, 'Internal Error',
        `There was an internal error when playing the stream. The song used can be found [here](${song.url}).`,
        [{'name': 'Error', 'value': `\`\`\`js\n${e}\n\`\`\``},
          {'name': 'Stack', 'value': `\`\`\`js\n${e.stack}\n\`\`\``}]
      )).catch(e => {});
      return this.handleListener(gid);
    }
    stream.on('error', e => {
      console.error(e);
      if (e && channel) channel.send(ce(
        this.manager.colors.default, null, 'Internal Error',
        `There was an internal error when handling the stream. The song used can be found [here](${song.url}).`,
        [{'name': 'Error', 'value': `\`\`\`js\n${e}\n\`\`\``},
          {'name': 'Stack', 'value': `\`\`\`js\n${e.stack}\n\`\`\``}]
      ));
      listener.data.aits++;
      return this.handleListener(gid);
    });
    dispatcher.setVolume(server.music.volume);
    dispatcher.finishedLoading = false;
    dispatcher.on('error', e => {
      console.error(e);
      if (e && channel) channel.send(ce(
        this.manager.colors.default, null, 'Internal Error',
        `There was an internal error when handling the dispatcher. The song used can be found [here](${song.url}).`,
        [{'name': 'Error', 'value': `\`\`\`js\n${e}\n\`\`\``},
          {'name': 'Stack', 'value': `\`\`\`js\n${e.stack}\n\`\`\``}]
      )).catch(e => {});
      listener.data.aits++;
      return this.handleListener(gid);
    });
    dispatcher.on("speaking", async is => {
     // stuff
    });
    dispatcher.on('finish', r => {
      if (r == '1423') return;
      listener.data.aits++;
      return this.handleListener(gid);
    });

Yes. I know it's a mess. We're working on a rewrite.

What do you mean?

I ran an eval on my bot (basic script) using d.js, and with this song it worked fine, but with the song listed it did not. Here's the eval.

P!eval m.member.voiceChannel.join().then(con => {
  const stream = yt("https://www.youtube.com/watch?v=HIRNdveLnJI", { "filter": "audio" } );
  const dis = con.play(stream);
  dis.on("end", () => {
    m.channel.send("end");
  });
  dis.on("finish", () => {
    m.channel.send("finish");
  });
  stream.on("finish", () => {
    m.channel.send("stream ended");
  });
  global.dis = dis;
  global.con = con;
  global.ytstream = stream;
}).catch(console.error).then(() => {
  m.channel.send("hi");
});

@gavwin
Copy link

gavwin commented Jun 26, 2018

+1 I'm getting the same issue when trying to play audio with discord.js on my bot.

@FireController1847
Copy link
Collaborator Author

I can report that on our rewrite of the bot (much cleaner and easier to read code), this issue still occurs. Oddly enough, it only occurs on my server and not my Windows machine. My server is running Ubuntu 18.04.

@FireController1847
Copy link
Collaborator Author

FireController1847 commented Jun 26, 2018

Reporting more on this issue, the ECONNRESETs have to do with getting the video info.

const yt = require('ytdl-core');
const fs = require('fs');
yt.getInfo("https://www.youtube.com/watch?v=WUwiqHYqq50").then(info => {
  fs.writeFileSync("./info2.json", JSON.stringify(info, null, 2));
});

This script results in an ECONNRESET.

Directly requesting the URL with wget and/or curl does not result in an ECONNRESET, which leads me to believe this is a ytdl-core issue. The fact it works fine on Windows, though, is very interesting.

Interestingly enough, running this script in its own instance does not cause an ECONNRESET, but when running it using an eval via my bot's process, it does.

Also very interesting, when running this in the same folder as my test script, it does end with an ECONNRESET.

const yt = require('ytdl-core');
const fs = require('fs');
const stream = yt("https://www.youtube.com/watch?v=WUwiqHYqq50", { filter: "audioonly" });
stream.pipe(fs.createWriteStream("./song.mp3"));

Running progress.js in its own instance does not result in an ECONNRESET.
Running progress.js in my bot's eval does result in an ECONNRESET.

I've cloned the Git repository onto my server and here's the test output.

After waiting a couple minutes, the eval for gettingInfo on that song worked just fine again.

@FireController1847
Copy link
Collaborator Author

@fent I hate to bother and I know you have a life and all, but if you could take a look at this that'd be great. It's making my bot completely unuseable..

@fent
Copy link
Owner

fent commented Jun 30, 2018

My first guess by looking at things above and without testing for myself, is that there's some issue with using ytdl.getInfo() followed by ytdl(). Since ytdl() uses ytdl.getInfo() and thus makes the same requests to youtube, calling them close to each other may be resetting some session permissions on youtube's end.

Try using ytdl.downloadFromInfo() on your bot. If that fixes it, then we know that was the issue. And if it is, then I'll think of some solution, maybe a small lived cache like we were doing a while ago.

@FireController1847
Copy link
Collaborator Author

FireController1847 commented Jun 30, 2018

That did fix the issue! So I can see how maybe some permissions or something is resetting... definitely glad to have this temporary fix in place though.

Oddly enough, it actually seems to be performing much faster than just calling the yt function itself aswell.

@fent
Copy link
Owner

fent commented Jun 30, 2018

That did fix the issue! So I can see how maybe some permissions or something is resetting... definitely glad to have this temporary fix in place though.

Good to know! I'll add a short cache for calling getInfo() and ytdl() on the same video.

Oddly enough, it actually seems to be performing much faster than just calling the yt function itself aswell.

That's because it needs to get a video's info first before downloading, and it needs to make a bunch of requests to get the info. But if you already have it, it doesn't make those requests.

@FireController1847
Copy link
Collaborator Author

FireController1847 commented Jul 1, 2018

What other requests does the main function make that running getInfo and then downloadFromInfo doesn't?

@FireController1847
Copy link
Collaborator Author

FireController1847 commented Jul 26, 2018

I hate to be the bearer of bad news but using downloadFromInfo is now coming up with the error as well. This time not from getInfo, but from the main stream itself.

This video caused the error this time.

@fent fent closed this as completed in dcb7281 Aug 2, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants