discordjs / discord.js

A powerful JavaScript library for interacting with the Discord API
https://discord.js.org
Apache License 2.0
25.45k stars 3.97k forks source link

Error [ERR_STREAM_WRITE_AFTER_END]: write after end #4695

Closed RickOrnichons closed 4 years ago

RickOrnichons commented 4 years ago

Hello,

I come here, because i've got a little issue. I'm trying to make an play command for my Bot. So this is my code : `// Play Youtube

const Discord = require('discord.js') const ytdl = require('ytdl-core-discord') const ytsr = require('ytsr') ytsr.do_warn_deprecate = false

module.exports = { name: 'play', description: 'Lance une musique choisie par un utilisateur',

async execute(message) {

if (message.author.bot || !message.guild) return

// un petit détail de nommage, channel -> voiceChannel
const voiceChannel = message.member.voice.channel
if (!voiceChannel) {
  message.reply('Veuillez rejoindre un salon vocal !')
  return
}

let researchArray = message.content.split(/ +/)
if (!researchArray.length) {
  message.reply('Vous n\'avez pas spécifié de mots clés !')
  return
}
const research = researchArray.slice(1).join(' ')

const filters = await ytsr.getFilters(research)
let filter = filters.get('Type').find(o => o.name === 'Video');

const options = {
  limit: 5,
  nextpageRef: filter.ref,
}
const searchResults = await ytsr(null, options)
if (!searchResults.items.length) {
  message.channel.send('aucun résultat trouvé')
  return
}

// Pour obtenir un emoji à partir d'un nombre (1 = 1️⃣, 9 = 9️⃣), inverse de getEmojiNumber
function getNumberEmoji(n = 1) {
  if (n < 1) n = 1
  if (n > 9) n = 9
  return String.fromCodePoint(n + 48, 65039, 8419)
}

// Pour obtenir un nombre à partir d'un emoji (1️⃣ = 1, 9️⃣ = 9), inverse de getNumberEmoji
function getEmojiNumber(e) {
  if (!e) return null
  return e.codePointAt(0) - 48
}

const listContent = new Discord.MessageEmbed()
  .setAuthor(message.author.username, message.author.displayAvatarURL())
  .setColor('YELLOW')
searchResults.items.forEach((item, i) => listContent.addField(`*${getNumberEmoji(i++ + 1)} - ${item.title} - ${item.duration}*`, "\u200b"))

const videosList = await message.channel.send(listContent)

const videosListEmojis = await Promise.all(searchResults.items.map(async (item, i) => {
  let emoji = getNumberEmoji(i + 1)
  videosList.react(emoji)
  return emoji
}))

let selectedVideoIndex
try {
  selectedVideoIndex = getEmojiNumber((await videosList.awaitReactions((r, u) => u.equals(message.author) && videosListEmojis.includes(r.emoji.name), { time: 25000, errors: ['time'], max: 1 })).first().emoji.name) - 1
} catch (e) { //r étant la réaction et u l'utilisateur 
  selectedVideoIndex = 0 // Si l'utilisateur ne choisi pas de musique au bout de 5 secondes on sélectionne la première (tu peux changer ce comportement bien sûr)    
}

function getGuild(id, defaultValue) {
  let result = message.client.music.get(id)
  if (!result) {
    message.client.music.set(id, defaultValue)
    result = defaultValue
  }
  return result
}

// pas d'idee de nom mdr
const guildMusic = getGuild(message.guild.id, {
  queue: []
// je fais sous cette forme comme ça tu pourra facilement rajouter d'autres propriétés, comme par exemple volume
})

const selectedVideo = searchResults.items[selectedVideoIndex]
guildMusic.queue.push({
  title: selectedVideo.title,
  link: selectedVideo.link
})

async function play(connection, url) {
  return connection.play(await ytdl(url), { type: 'opus' })
}

message.channel.send(`**${selectedVideo.title}** - Musique Ajoutée !`)

const connection = await voiceChannel.join()

if (guildMusic.queue.length === 1) await play(connection, selectedVideo.link)

connection.on("error", (e) => {
  console.error(e)
})
connection.dispatcher.on("finish", () => {
  guildMusic.queue.shift()
  if (!guildMusic.queue.length) {
    voiceChannel.leave()
    return
  }
  play(connection, guildMusic.queue[0].link)
})

} }`

And all the times, in approximatively 50 percent of the music, i'v got an error : Error [ERR_STREAM_WRITE_AFTER_END]: write after end And i don't relly know why.

If someones can help me, thanks !

LiamTownsley commented 4 years ago

Problem: You are listening to the event even after returning the response.

Solution: Use .once to listen to the event for one time for that one particular request. connection.dispatcher.once("finish", () => {

Could fix your issue, if it doesn't let me know.

RickOrnichons commented 4 years ago

Hello ! @LiamTownsley

I'm trying use once just like you tell me. But the issue comes agin :/

connection.dispatcher.once("finish", () => { guildMusic.queue.shift() if (!guildMusic.queue.length) { voiceChannel.leave() return } play(connection, guildMusic.queue[0].link) }) } }

And the error : events.js:288 throw er; // Unhandled 'error' event ^

Error [ERR_STREAM_WRITE_AFTER_END]: write after end at writeAfterEnd (_stream_writable.js:264:14) at PassThrough.Writable.write (_stream_writable.js:313:5) at IncomingMessage.ondata (_stream_readable.js:714:22) at IncomingMessage.emit (events.js:323:22) at addChunk (_stream_readable.js:294:12) at readableAddChunk (_stream_readable.js:275:11) at IncomingMessage.Readable.push (_stream_readable.js:209:10) at HTTPParser.parserOnBody (_http_common.js:132:24) at TLSSocket.socketOnData (_http_client.js:476:22) at TLSSocket.emit (events.js:311:20) Emitted 'error' event on PassThrough instance at: at PassThrough. (C:\Users\rouss\OneDrive\Bureau\Captain Von Cinéma\node_modules\ytdl-core-discord\node_modules\ytdl-core\lib\index.js:143:14) at PassThrough.emit (events.js:323:22) at errorOrDestroy (internal/streams/destroy.js:108:12) at writeAfterEnd (_stream_writable.js:266:3) at PassThrough.Writable.write (_stream_writable.js:313:5) [... lines matching original stack trace ...] at IncomingMessage.Readable.push (_stream_readable.js:209:10) { code: 'ERR_STREAM_WRITE_AFTER_END' }**

eugabrielsilva commented 3 years ago

@RickOrnichons how did you solve this? I'm having the exact same issue