distubejs / ytdl-core

YouTube video downloader in javascript.
MIT License
268 stars 48 forks source link

Error: Sign in to confirm you’re not a bot #21

Closed LostAndDead closed 4 months ago

LostAndDead commented 4 months ago

Describe the bug

Any playback requests result in an error, playback doesnt happen.

Environment

Docker

Full error stack:

(Usenode --trace-warnings ...to show where the warning was created) /usr/app/node_modules/@distube/ytdl-core/lib/info.js:91 return new UnrecoverableError(playability.reason || (playability.messages && playability.messages[0])); ^ Error: Sign in to confirm you’re not a bot at privateVideoError (/usr/app/node_modules/@distube/ytdl-core/lib/info.js:91:12) at exports.getBasicInfo (/usr/app/node_modules/@distube/ytdl-core/lib/info.js:54:22) at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

Seems this is likely something youtube have done, not sure if it can be circumvented or not.

skick1234 commented 4 months ago

YouTube checks your IP and prevents you from playing music if it is from a data center. You have to log in to resolve it. https://github.com/distubejs/ytdl-core?tab=readme-ov-file#cookies-support.

MikeyA-yo commented 3 months ago

YouTube checks your IP and prevents you from playing music if it is from a data center. You have to log in to resolve it. https://github.com/distubejs/ytdl-core?tab=readme-ov-file#cookies-support.

I have logged in, and still see this error, please i need an update

LostAndDead commented 3 months ago

I too was still having this error, I was using mine for a discord bot. Turns out I was IP banned by YouTube, they are cracking down hard on these kind of things it seems.

skick1234 commented 3 months ago

I have logged in, and still see this error, please i need an update

You just need to update your mind, or tell youtube to remove the restriction. This cannot be fixed by an update.

skick1234 commented 3 months ago

I too was still having this error, I was using mine for a discord bot. Turns out I was IP banned by YouTube, they are cracking down hard on these kind of things it seems.

As I said above, YouTube prevents many IP subnet from playing videos without logging in. You have to add cookies or change your ip.

MikeyA-yo commented 3 months ago

I have logged in, and still see this error, please i need an update

You just need to update your mind, or tell youtube to remove the restriction. This cannot be fixed by an update.

well it works locally for me, only that when deployed i get that error, also i tried using chunks instead i wonder if it will work

MikeyA-yo commented 3 months ago

Dude seriously? there's a bug in sign-in, i mean other's and i put cookie and get nothing

Dmytro-Tihunov commented 3 months ago

i added cookie and created agent it works right now :)

PatrykPatryk5 commented 3 months ago

it didn't do anything for me

Dmytro-Tihunov commented 3 months ago

@PatrykPatryk5 everything is said in readme just follow

PatrykPatryk5 commented 3 months ago

I did everything right but I am afraid that youtube is blocking the ip address of my hosting

MikeyA-yo commented 3 months ago

i added cookie and created agent it works right now :)

where did you deploy? and can i see the code to know if i did something wrong?

MikeyA-yo commented 3 months ago

@PatrykPatryk5 everything is said in readme just follow

i did what i saw in readme also, i got my cookies from an extension

PatrykPatryk5 commented 3 months ago
const ytdl = require('@distube/ytdl-core');
const { createAudioResource, demuxProbe, createAudioPlayer, AudioPlayerStatus, VoiceConnectionStatus, StreamType } = require('@discordjs/voice');
const fetch = require('isomorphic-unfetch');
const spotifyUrlInfo = require('spotify-url-info')(fetch);
const youtubeSr = require('youtube-sr').default;
const ytpl = require('@distube/ytpl');
const scdl = require('soundcloud-downloader').default;
const { spawn } = require('child_process');
const { PassThrough } = require('stream');
const { URL } = require('url');
const fs = require('fs');

// Read cookies from file
const cookies = JSON.parse(fs.readFileSync("cookies.json"));

const agentOptions = {
  pipelining: 5,
  maxRedirections: 10,
//  localAddress: "127.0.0.1",
};

// Funkcja do generowania losowego User-Agent
function getRandomUserAgent() {
    const userAgents = [
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15',
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0'
    ];
    return userAgents[Math.floor(Math.random() * userAgents.length)];
}

const agent = ytdl.createProxyAgent(
    { uri: "http://45.127.248.127:5128", timeout: 6000 }, 
    cookies.map(cookie => ({ name: cookie.name, value: cookie.value }))
);

const queues = new Map();
const currentlyPlaying = new Map();
const volumes = new Map();
const voiceConnections = new Map();
const audioPlayers = new Map();

const DELAY_MS = 2000;

function getLinkType(url) {
 const urlString = url.toString();
 if (urlString.includes('spotify.com')) return 'spotify';
 if (urlString.includes('youtube.com') || urlString.includes('youtu.be')) return 'youtube';
 if (urlString.includes('soundcloud.com')) return 'soundcloud';
 return 'unknown';
}

async function getResource(song, serverId) {
 try {
  let stream, info;

  const linkType = getLinkType(song);

  switch(linkType) {
   case 'spotify':
    return await handleSpotify(song, serverId);
   case 'youtube':
    ({ stream, info } = await getYouTubeStream(song));
    break;
   case 'soundcloud':
    ({ stream, info } = await searchAndGetSoundCloudResource(song, serverId));
    break;
   default:
    ({ stream, info } = await searchAndGetResource(song, serverId));
  }

  if (!stream || typeof stream.pipe !== 'function') {
   throw new Error('Nieprawidłowy strumień');
  }

  const title = info?.videoDetails?.title || 'Nieznany tytuł';
  const duration = parseInt(info?.videoDetails?.lengthSeconds, 10) || 0;

  console.log(`Pobrano utwór: ${title} (długość: ${duration} sekund)`);

  return { stream, title, duration };

 } catch (error) {
  console.error(`Błąd w getResource: ${error.message}`);
  return null;
 }
}

async function handleSpotify(song, serverId) {
 try {
  const spotifyData = await spotifyUrlInfo.getData(song);

  if (!spotifyData || !spotifyData.type) {
   throw new Error('Nieprawidłowy link Spotify lub nie można pobrać danych.');
  }

  const tracks = spotifyData.trackList || (spotifyData.tracks && spotifyData.tracks.items) || [spotifyData];

  if (tracks.length === 0) {
   throw new Error('Nie znaleziono utworów w linku Spotify.');
  }

  if (spotifyData.type === 'track') {
   const track = tracks[0];
   const artists = track.artists ? track.artists.map(artist => artist.name).join(', ') : "Nieznany Artysta";
   const searchQuery = `${track.name} - ${artists}`;
   return await searchAndGetResource(searchQuery, serverId);
  } else if (spotifyData.type === 'album' || spotifyData.type === 'playlist') {
   const processedTracks = [];

   for (const item of tracks) {
    const track = item.track || item;
    const artists = track.artists ? track.artists.map(artist => artist.name).join(', ') : "Nieznany Artysta";

    if (track && track.name && artists) {
     const trackName = `${track.name} - ${artists}`;

     if (!processedTracks.includes(trackName)) {
      processedTracks.push(trackName);
      await addYoutubeToQueue(trackName, serverId);
     }
    } 
   }

   return playNextInQueue(serverId, getVoiceConnection(serverId));
  } else {
   throw new Error(`Nieobsługiwany typ Spotify: ${spotifyData.type}`);
  }
 } catch (error) {
  console.error(`Błąd Spotify: ${error.message}`);

  if (error.message.includes('Invalid URL')) {
   throw new Error('Nieprawidłowy link Spotify.');
  } else if (error.message.includes('404')) {
   throw new Error('Nie znaleziono utworu lub playlisty Spotify.');
  } else {
   throw new Error('Wystąpił błąd podczas przetwarzania linku Spotify.');
  }
 }
}

async function handleYoutube(song, serverId) {
 try {
  const url = new URL(song);
  const searchParams = url.searchParams;

  if (searchParams.has('list')) {
   const playlistId = searchParams.get('list');

   try {
    const playlist = await ytpl(playlistId);

    for (const item of playlist.items) {
     addToQueue(serverId, item.shortUrl);
    }

    return { 
     isPlaylist: true, 
     playlistName: playlist.title, 
     trackCount: playlist.items.length 
    };
   } catch (playlistError) {
    console.error(`Błąd pobierania playlisty YouTube (ID: ${playlistId}): ${playlistError.message}`);

    if (playlistId.startsWith('RD')) {
     return await handleRadioPlaylist(song, serverId);
    } else {
     try {
      const searchResults = await youtubeSr.search(url.toString(), { type: 'playlist', limit: 1 });
      if (searchResults.length > 0) {
       const foundPlaylistId = searchResults[0].id;
       return await handleYoutube(`https://www.youtube.com/playlist?list=${foundPlaylistId}`, serverId);
      } else {
       throw new Error(`Nie znaleziono playlisty YouTube odpowiadającej: ${url.toString()}`);
      }
     } catch (searchError) {
      console.error(`Błąd podczas wyszukiwania playlisty YouTube: ${searchError.message}`);
      throw new Error('Nie można znaleźć playlisty YouTube.');
     }
    }
   }
  } else {
   return await handleSingleYoutubeTrack(song, serverId);
  }
 } catch (error) {
  console.error(`Błąd przetwarzania linku YouTube: ${error.message}`);
  throw error;
 }
}

async function handleRadioPlaylist(song, serverId) {
 try {
  const info = await ytdl.getInfo(song, { agent });
  const relatedVideos = info.related_videos;

  const validVideos = relatedVideos.filter((video, index, self) => 
   video.id && !self.some((v, i) => i < index && v.id === video.id)
  );

  for (const relatedVideo of validVideos) {
   addToQueue(serverId, `https://www.youtube.com/watch?v=${relatedVideo.id}`);
  }

  const firstVideoId = validVideos[0]?.id;
  if (firstVideoId) {
   return await handleSingleYoutubeTrack(`https://www.youtube.com/watch?v=${firstVideoId}`, serverId);
  } else {
   throw new Error('Nie znaleziono żadnych prawidłowych filmów w playliście radiowej.');
  }
 } catch (error) {
  console.error(`Błąd przetwarzania playlisty radiowej: ${error.message}`);
  throw error;
 }
}

async function playNextInQueue(serverId, voiceConnection) {
 if (!voiceConnection) {
  console.error("Brak połączenia głosowego dla serwera:", serverId);
  return;
 }

 const queue = getQueue(serverId) || [];

 while (queue.length > 0) {
  const nextSong = queue.shift() || "Brak danych o utworze";
  setCurrentlyPlaying(serverId, nextSong);

  try {
   const resource = await getResource(nextSong, serverId);

   if (!resource) {
    console.error("Nie udało się uzyskać zasobu dla utworu:", nextSong);
    continue;
   }

   const audioPlayer = createAudioPlayer();
   audioPlayers.set(serverId, audioPlayer);

   voiceConnection.subscribe(audioPlayer);

   audioPlayer.play(resource);

   console.log(`Rozpoczęto odtwarzanie: ${resource.metadata.title}`);

   await new Promise((resolve) => {
    audioPlayer.on(AudioPlayerStatus.Idle, () => {
     console.log(`Zakończono odtwarzanie: ${resource.metadata.title}`);
     resolve();
    });

    audioPlayer.on('error', (error) => {
     console.error(`Błąd odtwarzacza audio: ${error.message}`);
     resolve();
    });
   });

  } catch (error) {
   console.error("Błąd podczas odtwarzania utworu:", error);
  }
 }

 setCurrentlyPlaying(serverId, null);
 if (voiceConnection.state.status !== VoiceConnectionStatus.Destroyed) {
  voiceConnection.destroy();
 }
}
async function handleSingleYoutubeTrack(song, serverId) {
    try {
        const info = await ytdl.getInfo(song, { agent });
        const { stream } = await getYouTubeStream(info.videoDetails.videoId);
        const songTitle = info.videoDetails.title || "Nieznany tytuł";
        const songDuration = parseInt(info.videoDetails.lengthSeconds, 10) || 0;

        console.log(`Pobrano utwór z YouTube: ${songTitle} (długość: ${songDuration} sekund)`);

        return await createResourceFromStream(stream, songTitle, songDuration);
    } catch (ytError) {
        console.error(`Nie udało się przetworzyć utworu YouTube: ${ytError.message}`);
        console.log("Próba pobrania z SoundCloud...");

        try {
            const scSearchQuery = song.includes("youtube.com") || song.includes("youtu.be") 
                ? await extractTitleFromYouTubeURL(song) 
                : song;

            return await searchAndGetSoundCloudResource(scSearchQuery, serverId);
        } catch (scError) {
            console.error(`Nie udało się przetworzyć utworu z SoundCloud: ${scError.message}`);
            throw new Error('Nie udało się pobrać utworu ani z YouTube, ani z SoundCloud.');
        }
    }
}

async function extractTitleFromYouTubeURL(url) {
    try {
        const info = await ytdl.getBasicInfo(url, { agent });
        return info.videoDetails.title;
    } catch (error) {
        console.error(`Nie udało się pobrać tytułu z YouTube URL: ${error.message}`);
        return url;
    }
}

async function searchAndGetSoundCloudResource(query, serverId, maxRetries = 3) {
    for (let attempt = 0; attempt < maxRetries; attempt++) {
        try {
            const searchResults = await scdl.search({
                query: query,
                limit: 1,
                offset: 0,
                resourceType: 'tracks'
            });

            if (searchResults.collection && searchResults.collection.length > 0) {
                const track = searchResults.collection[0];
                const stream = await scdl.download(track.permalink_url);

                if (!stream || typeof stream.pipe !== 'function') {
                    throw new Error('Nieprawidłowy strumień');
                }

                const info = {
                    videoDetails: {
                        title: track.title || 'Nieznany tytuł',
                        lengthSeconds: Math.ceil(track.duration / 1000) || 0
                    }
                };

                console.log(`Pobrano utwór SoundCloud: ${info.videoDetails.title} (długość: ${info.videoDetails.lengthSeconds} sekund)`);

                return { stream, info };
            } else {
                throw new Error(`Nie znaleziono wyników wyszukiwania na SoundCloud dla: ${query}`);
            }
        } catch (error) {
            console.error(`Błąd pobierania informacji SoundCloud (próba ${attempt + 1}): ${error.message}`);
            if (attempt === maxRetries - 1) throw error;
            await new Promise(resolve => setTimeout(resolve, 1000 * Math.pow(2, attempt)));
        }
    }
}
async function getYouTubeStream(videoId, maxRetries = 3, initialDelay = 1000) {
    for (let attempt = 0; attempt < maxRetries; attempt++) {
        try {
            const delay = initialDelay * Math.pow(2, attempt);
            await new Promise(resolve => setTimeout(resolve, delay + Math.random() * 1000));

            const info = await ytdl.getInfo(`https://www.youtube.com/watch?v=${videoId}`, {
                agent,
                headers: {
                    'User-Agent': getRandomUserAgent(),
                    'Accept-Language': 'en-US,en;q=0.9',
                    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
                    'Cookie': cookies.map(cookie => `${cookie.name}=${cookie.value}`).join('; ')
                }
            });

            const format = ytdl.chooseFormat(info.formats, { quality: 'highestaudio', filter: 'audioonly' });
            const stream = ytdl.downloadFromInfo(info, { format: format });

            if (!stream || typeof stream.pipe !== 'function') {
                throw new Error('Nieprawidłowy strumień');
            }

            return { stream, info };
        } catch (error) {
            console.error(`Błąd pobierania informacji YouTube (próba ${attempt + 1}): ${error.message}`);
            if (attempt === maxRetries - 1) throw error;
        }
    }
}

async function trySoundCloud(link, serverId) {
 try {
  const info = await scdl.getInfo(link);
  const stream = await scdl.download(link);
  const songTitle = info.title || 'Nieznany tytuł';
  const songDuration = Math.ceil(info.duration / 1000) || 0;

  console.log(`Pobrano utwór SoundCloud: ${songTitle} (długość: ${songDuration} sekund)`);

  return await createResourceFromStream(stream, songTitle, songDuration);
 } catch (error) {
  console.error(`Błąd SoundCloud: ${error.message}`);
  throw error;
 }
}

async function searchAndGetResource(query, serverId) {
 try {
  const searchResults = await youtubeSr.search(query, { type: 'video', limit: 1 });

  if (searchResults.length > 0) {
   const firstResult = searchResults[0];
   const { stream, info } = await getYouTubeStream(firstResult.id);

   if (!stream || typeof stream.pipe !== 'function') {
    throw new Error('Nieprawidłowy strumień');
   }

   return await createResourceFromStream(stream, info.videoDetails.title, info.videoDetails.lengthSeconds);
  } else {
   throw new Error(`Nie znaleziono wyników wyszukiwania dla: ${query}`);
  }
 } catch (error) {
  console.error(`Błąd wyszukiwania YouTube: ${error.message}`);
  console.log("Próba pobrania z SoundCloud...");
  return await searchAndGetSoundCloudResource(query, serverId);
 }
}
async function createResourceFromStream(stream, title, duration) {
    return new Promise((resolve, reject) => {
        if (!stream || typeof stream.pipe !== 'function') {
            reject(new Error('Nieprawidłowy strumień'));
            return;
        }

        const ffmpegArgs = [
            '-i', 'pipe:0',
            '-analyzeduration', '60000000',
            '-loglevel', 'error',
            '-f', 'opus',
            '-c:a', 'libopus',
            '-ar', '48000',
            '-ac', '2',
            '-b:a', '128k',
            '-vbr', 'on',
            '-compression_level', '10',
            'pipe:1'
        ];

        const ffmpeg = spawn('ffmpeg', ffmpegArgs, { stdio: ['pipe', 'pipe', 'ignore'] });

        stream.pipe(ffmpeg.stdin);

        const resource = createAudioResource(ffmpeg.stdout, {
            inputType: StreamType.Opus,
            metadata: { title, duration }
        });

        ffmpeg.on('error', (error) => {
            console.error(`Błąd ffmpeg: ${error.message}`);
            reject(error);
        });

        ffmpeg.on('close', (code) => {
            if (code !== 0) {
                reject(new Error(`ffmpeg zakończony z kodem: ${code}`));
            } else {
                resolve(resource);
            }
        });
    });
}
function addToQueue(serverId, song) {
 if (!queues.has(serverId)) {
  queues.set(serverId, []);
 }

 const queue = queues.get(serverId);
 queue.push(song);
}

function removeFromQueue(serverId, index) {
 const queue = getQueue(serverId);
 if (index >= 0 && index < queue.length) {
  queue.splice(index, 1);
 }
}

function skipSong(serverId, voiceConnection) {
 const audioPlayer = audioPlayers.get(serverId);
 if (audioPlayer && voiceConnection) {
  playNextInQueue(serverId, voiceConnection);
 }
}

function getQueue(serverId) {
 return queues.get(serverId) || [];
}

function clearQueue(serverId) {
 queues.set(serverId, []);
}

function getCurrentlyPlaying(serverId) {
 return currentlyPlaying.get(serverId) || null;
}

function setCurrentlyPlaying(serverId, song) {
 currentlyPlaying.set(serverId, song);
}

function getVoiceConnection(serverId) {
 return voiceConnections.get(serverId) || null;
}

function setVoiceConnection(serverId, connection) {
 voiceConnections.set(serverId, connection);
}

function getSongDetails(resource) {
  try {
    const { title, duration } = resource.metadata;
    return { title, duration };
  } catch (error) {
    console.error(`Błąd w getSongDetails: ${error.message}`);
    return { title: "Nieznany tytuł", duration: "Nieznany czas trwania" };
  }
}

function adjustVolume(serverId, volume) {
 const audioPlayer = audioPlayers.get(serverId);
 if (audioPlayer) {
  audioPlayer.setVolume(volume);
 }
}

module.exports = {
 getResource,
 addToQueue,
 removeFromQueue,
 skipSong,
 getQueue,
 getCurrentlyPlaying,
 setCurrentlyPlaying,
 clearQueue,
 getSongDetails,
 playNextInQueue,
 adjustVolume,
 audioPlayers,
 getVoiceConnection
};
PatrykPatryk5 commented 3 months ago

90% chatgpt :)

MikeyA-yo commented 3 months ago
const ytdl = require('@distube/ytdl-core');
const { createAudioResource, demuxProbe, createAudioPlayer, AudioPlayerStatus, VoiceConnectionStatus, StreamType } = require('@discordjs/voice');
const fetch = require('isomorphic-unfetch');
const spotifyUrlInfo = require('spotify-url-info')(fetch);
const youtubeSr = require('youtube-sr').default;
const ytpl = require('@distube/ytpl');
const scdl = require('soundcloud-downloader').default;
const { spawn } = require('child_process');
const { PassThrough } = require('stream');
const { URL } = require('url');
const fs = require('fs');

// Read cookies from file
const cookies = JSON.parse(fs.readFileSync("cookies.json"));

const agentOptions = {
  pipelining: 5,
  maxRedirections: 10,
//  localAddress: "127.0.0.1",
};

// Funkcja do generowania losowego User-Agent
function getRandomUserAgent() {
    const userAgents = [
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15',
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0'
    ];
    return userAgents[Math.floor(Math.random() * userAgents.length)];
}

const agent = ytdl.createProxyAgent(
    { uri: "http://45.127.248.127:5128", timeout: 6000 }, 
    cookies.map(cookie => ({ name: cookie.name, value: cookie.value }))
);

const queues = new Map();
const currentlyPlaying = new Map();
const volumes = new Map();
const voiceConnections = new Map();
const audioPlayers = new Map();

const DELAY_MS = 2000;

function getLinkType(url) {
 const urlString = url.toString();
 if (urlString.includes('spotify.com')) return 'spotify';
 if (urlString.includes('youtube.com') || urlString.includes('youtu.be')) return 'youtube';
 if (urlString.includes('soundcloud.com')) return 'soundcloud';
 return 'unknown';
}

async function getResource(song, serverId) {
 try {
  let stream, info;

  const linkType = getLinkType(song);

  switch(linkType) {
   case 'spotify':
    return await handleSpotify(song, serverId);
   case 'youtube':
    ({ stream, info } = await getYouTubeStream(song));
    break;
   case 'soundcloud':
    ({ stream, info } = await searchAndGetSoundCloudResource(song, serverId));
    break;
   default:
    ({ stream, info } = await searchAndGetResource(song, serverId));
  }

  if (!stream || typeof stream.pipe !== 'function') {
   throw new Error('Nieprawidłowy strumień');
  }

  const title = info?.videoDetails?.title || 'Nieznany tytuł';
  const duration = parseInt(info?.videoDetails?.lengthSeconds, 10) || 0;

  console.log(`Pobrano utwór: ${title} (długość: ${duration} sekund)`);

  return { stream, title, duration };

 } catch (error) {
  console.error(`Błąd w getResource: ${error.message}`);
  return null;
 }
}

async function handleSpotify(song, serverId) {
 try {
  const spotifyData = await spotifyUrlInfo.getData(song);

  if (!spotifyData || !spotifyData.type) {
   throw new Error('Nieprawidłowy link Spotify lub nie można pobrać danych.');
  }

  const tracks = spotifyData.trackList || (spotifyData.tracks && spotifyData.tracks.items) || [spotifyData];

  if (tracks.length === 0) {
   throw new Error('Nie znaleziono utworów w linku Spotify.');
  }

  if (spotifyData.type === 'track') {
   const track = tracks[0];
   const artists = track.artists ? track.artists.map(artist => artist.name).join(', ') : "Nieznany Artysta";
   const searchQuery = `${track.name} - ${artists}`;
   return await searchAndGetResource(searchQuery, serverId);
  } else if (spotifyData.type === 'album' || spotifyData.type === 'playlist') {
   const processedTracks = [];

   for (const item of tracks) {
    const track = item.track || item;
    const artists = track.artists ? track.artists.map(artist => artist.name).join(', ') : "Nieznany Artysta";

    if (track && track.name && artists) {
     const trackName = `${track.name} - ${artists}`;

     if (!processedTracks.includes(trackName)) {
      processedTracks.push(trackName);
      await addYoutubeToQueue(trackName, serverId);
     }
    } 
   }

   return playNextInQueue(serverId, getVoiceConnection(serverId));
  } else {
   throw new Error(`Nieobsługiwany typ Spotify: ${spotifyData.type}`);
  }
 } catch (error) {
  console.error(`Błąd Spotify: ${error.message}`);

  if (error.message.includes('Invalid URL')) {
   throw new Error('Nieprawidłowy link Spotify.');
  } else if (error.message.includes('404')) {
   throw new Error('Nie znaleziono utworu lub playlisty Spotify.');
  } else {
   throw new Error('Wystąpił błąd podczas przetwarzania linku Spotify.');
  }
 }
}

async function handleYoutube(song, serverId) {
 try {
  const url = new URL(song);
  const searchParams = url.searchParams;

  if (searchParams.has('list')) {
   const playlistId = searchParams.get('list');

   try {
    const playlist = await ytpl(playlistId);

    for (const item of playlist.items) {
     addToQueue(serverId, item.shortUrl);
    }

    return { 
     isPlaylist: true, 
     playlistName: playlist.title, 
     trackCount: playlist.items.length 
    };
   } catch (playlistError) {
    console.error(`Błąd pobierania playlisty YouTube (ID: ${playlistId}): ${playlistError.message}`);

    if (playlistId.startsWith('RD')) {
     return await handleRadioPlaylist(song, serverId);
    } else {
     try {
      const searchResults = await youtubeSr.search(url.toString(), { type: 'playlist', limit: 1 });
      if (searchResults.length > 0) {
       const foundPlaylistId = searchResults[0].id;
       return await handleYoutube(`https://www.youtube.com/playlist?list=${foundPlaylistId}`, serverId);
      } else {
       throw new Error(`Nie znaleziono playlisty YouTube odpowiadającej: ${url.toString()}`);
      }
     } catch (searchError) {
      console.error(`Błąd podczas wyszukiwania playlisty YouTube: ${searchError.message}`);
      throw new Error('Nie można znaleźć playlisty YouTube.');
     }
    }
   }
  } else {
   return await handleSingleYoutubeTrack(song, serverId);
  }
 } catch (error) {
  console.error(`Błąd przetwarzania linku YouTube: ${error.message}`);
  throw error;
 }
}

async function handleRadioPlaylist(song, serverId) {
 try {
  const info = await ytdl.getInfo(song, { agent });
  const relatedVideos = info.related_videos;

  const validVideos = relatedVideos.filter((video, index, self) => 
   video.id && !self.some((v, i) => i < index && v.id === video.id)
  );

  for (const relatedVideo of validVideos) {
   addToQueue(serverId, `https://www.youtube.com/watch?v=${relatedVideo.id}`);
  }

  const firstVideoId = validVideos[0]?.id;
  if (firstVideoId) {
   return await handleSingleYoutubeTrack(`https://www.youtube.com/watch?v=${firstVideoId}`, serverId);
  } else {
   throw new Error('Nie znaleziono żadnych prawidłowych filmów w playliście radiowej.');
  }
 } catch (error) {
  console.error(`Błąd przetwarzania playlisty radiowej: ${error.message}`);
  throw error;
 }
}

async function playNextInQueue(serverId, voiceConnection) {
 if (!voiceConnection) {
  console.error("Brak połączenia głosowego dla serwera:", serverId);
  return;
 }

 const queue = getQueue(serverId) || [];

 while (queue.length > 0) {
  const nextSong = queue.shift() || "Brak danych o utworze";
  setCurrentlyPlaying(serverId, nextSong);

  try {
   const resource = await getResource(nextSong, serverId);

   if (!resource) {
    console.error("Nie udało się uzyskać zasobu dla utworu:", nextSong);
    continue;
   }

   const audioPlayer = createAudioPlayer();
   audioPlayers.set(serverId, audioPlayer);

   voiceConnection.subscribe(audioPlayer);

   audioPlayer.play(resource);

   console.log(`Rozpoczęto odtwarzanie: ${resource.metadata.title}`);

   await new Promise((resolve) => {
    audioPlayer.on(AudioPlayerStatus.Idle, () => {
     console.log(`Zakończono odtwarzanie: ${resource.metadata.title}`);
     resolve();
    });

    audioPlayer.on('error', (error) => {
     console.error(`Błąd odtwarzacza audio: ${error.message}`);
     resolve();
    });
   });

  } catch (error) {
   console.error("Błąd podczas odtwarzania utworu:", error);
  }
 }

 setCurrentlyPlaying(serverId, null);
 if (voiceConnection.state.status !== VoiceConnectionStatus.Destroyed) {
  voiceConnection.destroy();
 }
}
async function handleSingleYoutubeTrack(song, serverId) {
    try {
        const info = await ytdl.getInfo(song, { agent });
        const { stream } = await getYouTubeStream(info.videoDetails.videoId);
        const songTitle = info.videoDetails.title || "Nieznany tytuł";
        const songDuration = parseInt(info.videoDetails.lengthSeconds, 10) || 0;

        console.log(`Pobrano utwór z YouTube: ${songTitle} (długość: ${songDuration} sekund)`);

        return await createResourceFromStream(stream, songTitle, songDuration);
    } catch (ytError) {
        console.error(`Nie udało się przetworzyć utworu YouTube: ${ytError.message}`);
        console.log("Próba pobrania z SoundCloud...");

        try {
            const scSearchQuery = song.includes("youtube.com") || song.includes("youtu.be") 
                ? await extractTitleFromYouTubeURL(song) 
                : song;

            return await searchAndGetSoundCloudResource(scSearchQuery, serverId);
        } catch (scError) {
            console.error(`Nie udało się przetworzyć utworu z SoundCloud: ${scError.message}`);
            throw new Error('Nie udało się pobrać utworu ani z YouTube, ani z SoundCloud.');
        }
    }
}

async function extractTitleFromYouTubeURL(url) {
    try {
        const info = await ytdl.getBasicInfo(url, { agent });
        return info.videoDetails.title;
    } catch (error) {
        console.error(`Nie udało się pobrać tytułu z YouTube URL: ${error.message}`);
        return url;
    }
}

async function searchAndGetSoundCloudResource(query, serverId, maxRetries = 3) {
    for (let attempt = 0; attempt < maxRetries; attempt++) {
        try {
            const searchResults = await scdl.search({
                query: query,
                limit: 1,
                offset: 0,
                resourceType: 'tracks'
            });

            if (searchResults.collection && searchResults.collection.length > 0) {
                const track = searchResults.collection[0];
                const stream = await scdl.download(track.permalink_url);

                if (!stream || typeof stream.pipe !== 'function') {
                    throw new Error('Nieprawidłowy strumień');
                }

                const info = {
                    videoDetails: {
                        title: track.title || 'Nieznany tytuł',
                        lengthSeconds: Math.ceil(track.duration / 1000) || 0
                    }
                };

                console.log(`Pobrano utwór SoundCloud: ${info.videoDetails.title} (długość: ${info.videoDetails.lengthSeconds} sekund)`);

                return { stream, info };
            } else {
                throw new Error(`Nie znaleziono wyników wyszukiwania na SoundCloud dla: ${query}`);
            }
        } catch (error) {
            console.error(`Błąd pobierania informacji SoundCloud (próba ${attempt + 1}): ${error.message}`);
            if (attempt === maxRetries - 1) throw error;
            await new Promise(resolve => setTimeout(resolve, 1000 * Math.pow(2, attempt)));
        }
    }
}
async function getYouTubeStream(videoId, maxRetries = 3, initialDelay = 1000) {
    for (let attempt = 0; attempt < maxRetries; attempt++) {
        try {
            const delay = initialDelay * Math.pow(2, attempt);
            await new Promise(resolve => setTimeout(resolve, delay + Math.random() * 1000));

            const info = await ytdl.getInfo(`https://www.youtube.com/watch?v=${videoId}`, {
                agent,
                headers: {
                    'User-Agent': getRandomUserAgent(),
                    'Accept-Language': 'en-US,en;q=0.9',
                    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
                    'Cookie': cookies.map(cookie => `${cookie.name}=${cookie.value}`).join('; ')
                }
            });

            const format = ytdl.chooseFormat(info.formats, { quality: 'highestaudio', filter: 'audioonly' });
            const stream = ytdl.downloadFromInfo(info, { format: format });

            if (!stream || typeof stream.pipe !== 'function') {
                throw new Error('Nieprawidłowy strumień');
            }

            return { stream, info };
        } catch (error) {
            console.error(`Błąd pobierania informacji YouTube (próba ${attempt + 1}): ${error.message}`);
            if (attempt === maxRetries - 1) throw error;
        }
    }
}

async function trySoundCloud(link, serverId) {
 try {
  const info = await scdl.getInfo(link);
  const stream = await scdl.download(link);
  const songTitle = info.title || 'Nieznany tytuł';
  const songDuration = Math.ceil(info.duration / 1000) || 0;

  console.log(`Pobrano utwór SoundCloud: ${songTitle} (długość: ${songDuration} sekund)`);

  return await createResourceFromStream(stream, songTitle, songDuration);
 } catch (error) {
  console.error(`Błąd SoundCloud: ${error.message}`);
  throw error;
 }
}

async function searchAndGetResource(query, serverId) {
 try {
  const searchResults = await youtubeSr.search(query, { type: 'video', limit: 1 });

  if (searchResults.length > 0) {
   const firstResult = searchResults[0];
   const { stream, info } = await getYouTubeStream(firstResult.id);

   if (!stream || typeof stream.pipe !== 'function') {
    throw new Error('Nieprawidłowy strumień');
   }

   return await createResourceFromStream(stream, info.videoDetails.title, info.videoDetails.lengthSeconds);
  } else {
   throw new Error(`Nie znaleziono wyników wyszukiwania dla: ${query}`);
  }
 } catch (error) {
  console.error(`Błąd wyszukiwania YouTube: ${error.message}`);
  console.log("Próba pobrania z SoundCloud...");
  return await searchAndGetSoundCloudResource(query, serverId);
 }
}
async function createResourceFromStream(stream, title, duration) {
    return new Promise((resolve, reject) => {
        if (!stream || typeof stream.pipe !== 'function') {
            reject(new Error('Nieprawidłowy strumień'));
            return;
        }

        const ffmpegArgs = [
            '-i', 'pipe:0',
            '-analyzeduration', '60000000',
            '-loglevel', 'error',
            '-f', 'opus',
            '-c:a', 'libopus',
            '-ar', '48000',
            '-ac', '2',
            '-b:a', '128k',
            '-vbr', 'on',
            '-compression_level', '10',
            'pipe:1'
        ];

        const ffmpeg = spawn('ffmpeg', ffmpegArgs, { stdio: ['pipe', 'pipe', 'ignore'] });

        stream.pipe(ffmpeg.stdin);

        const resource = createAudioResource(ffmpeg.stdout, {
            inputType: StreamType.Opus,
            metadata: { title, duration }
        });

        ffmpeg.on('error', (error) => {
            console.error(`Błąd ffmpeg: ${error.message}`);
            reject(error);
        });

        ffmpeg.on('close', (code) => {
            if (code !== 0) {
                reject(new Error(`ffmpeg zakończony z kodem: ${code}`));
            } else {
                resolve(resource);
            }
        });
    });
}
function addToQueue(serverId, song) {
 if (!queues.has(serverId)) {
  queues.set(serverId, []);
 }

 const queue = queues.get(serverId);
 queue.push(song);
}

function removeFromQueue(serverId, index) {
 const queue = getQueue(serverId);
 if (index >= 0 && index < queue.length) {
  queue.splice(index, 1);
 }
}

function skipSong(serverId, voiceConnection) {
 const audioPlayer = audioPlayers.get(serverId);
 if (audioPlayer && voiceConnection) {
  playNextInQueue(serverId, voiceConnection);
 }
}

function getQueue(serverId) {
 return queues.get(serverId) || [];
}

function clearQueue(serverId) {
 queues.set(serverId, []);
}

function getCurrentlyPlaying(serverId) {
 return currentlyPlaying.get(serverId) || null;
}

function setCurrentlyPlaying(serverId, song) {
 currentlyPlaying.set(serverId, song);
}

function getVoiceConnection(serverId) {
 return voiceConnections.get(serverId) || null;
}

function setVoiceConnection(serverId, connection) {
 voiceConnections.set(serverId, connection);
}

function getSongDetails(resource) {
  try {
    const { title, duration } = resource.metadata;
    return { title, duration };
  } catch (error) {
    console.error(`Błąd w getSongDetails: ${error.message}`);
    return { title: "Nieznany tytuł", duration: "Nieznany czas trwania" };
  }
}

function adjustVolume(serverId, volume) {
 const audioPlayer = audioPlayers.get(serverId);
 if (audioPlayer) {
  audioPlayer.setVolume(volume);
 }
}

module.exports = {
 getResource,
 addToQueue,
 removeFromQueue,
 skipSong,
 getQueue,
 getCurrentlyPlaying,
 setCurrentlyPlaying,
 clearQueue,
 getSongDetails,
 playNextInQueue,
 adjustVolume,
 audioPlayers,
 getVoiceConnection
};

Will using your proxy uri work?

MikeyA-yo commented 3 months ago
const ytdl = require('@distube/ytdl-core');
const { createAudioResource, demuxProbe, createAudioPlayer, AudioPlayerStatus, VoiceConnectionStatus, StreamType } = require('@discordjs/voice');
const fetch = require('isomorphic-unfetch');
const spotifyUrlInfo = require('spotify-url-info')(fetch);
const youtubeSr = require('youtube-sr').default;
const ytpl = require('@distube/ytpl');
const scdl = require('soundcloud-downloader').default;
const { spawn } = require('child_process');
const { PassThrough } = require('stream');
const { URL } = require('url');
const fs = require('fs');

// Read cookies from file
const cookies = JSON.parse(fs.readFileSync("cookies.json"));

const agentOptions = {
  pipelining: 5,
  maxRedirections: 10,
//  localAddress: "127.0.0.1",
};

// Funkcja do generowania losowego User-Agent
function getRandomUserAgent() {
    const userAgents = [
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15',
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0'
    ];
    return userAgents[Math.floor(Math.random() * userAgents.length)];
}

const agent = ytdl.createProxyAgent(
    { uri: "http://45.127.248.127:5128", timeout: 6000 }, 
    cookies.map(cookie => ({ name: cookie.name, value: cookie.value }))
);

const queues = new Map();
const currentlyPlaying = new Map();
const volumes = new Map();
const voiceConnections = new Map();
const audioPlayers = new Map();

const DELAY_MS = 2000;

function getLinkType(url) {
 const urlString = url.toString();
 if (urlString.includes('spotify.com')) return 'spotify';
 if (urlString.includes('youtube.com') || urlString.includes('youtu.be')) return 'youtube';
 if (urlString.includes('soundcloud.com')) return 'soundcloud';
 return 'unknown';
}

async function getResource(song, serverId) {
 try {
  let stream, info;

  const linkType = getLinkType(song);

  switch(linkType) {
   case 'spotify':
    return await handleSpotify(song, serverId);
   case 'youtube':
    ({ stream, info } = await getYouTubeStream(song));
    break;
   case 'soundcloud':
    ({ stream, info } = await searchAndGetSoundCloudResource(song, serverId));
    break;
   default:
    ({ stream, info } = await searchAndGetResource(song, serverId));
  }

  if (!stream || typeof stream.pipe !== 'function') {
   throw new Error('Nieprawidłowy strumień');
  }

  const title = info?.videoDetails?.title || 'Nieznany tytuł';
  const duration = parseInt(info?.videoDetails?.lengthSeconds, 10) || 0;

  console.log(`Pobrano utwór: ${title} (długość: ${duration} sekund)`);

  return { stream, title, duration };

 } catch (error) {
  console.error(`Błąd w getResource: ${error.message}`);
  return null;
 }
}

async function handleSpotify(song, serverId) {
 try {
  const spotifyData = await spotifyUrlInfo.getData(song);

  if (!spotifyData || !spotifyData.type) {
   throw new Error('Nieprawidłowy link Spotify lub nie można pobrać danych.');
  }

  const tracks = spotifyData.trackList || (spotifyData.tracks && spotifyData.tracks.items) || [spotifyData];

  if (tracks.length === 0) {
   throw new Error('Nie znaleziono utworów w linku Spotify.');
  }

  if (spotifyData.type === 'track') {
   const track = tracks[0];
   const artists = track.artists ? track.artists.map(artist => artist.name).join(', ') : "Nieznany Artysta";
   const searchQuery = `${track.name} - ${artists}`;
   return await searchAndGetResource(searchQuery, serverId);
  } else if (spotifyData.type === 'album' || spotifyData.type === 'playlist') {
   const processedTracks = [];

   for (const item of tracks) {
    const track = item.track || item;
    const artists = track.artists ? track.artists.map(artist => artist.name).join(', ') : "Nieznany Artysta";

    if (track && track.name && artists) {
     const trackName = `${track.name} - ${artists}`;

     if (!processedTracks.includes(trackName)) {
      processedTracks.push(trackName);
      await addYoutubeToQueue(trackName, serverId);
     }
    } 
   }

   return playNextInQueue(serverId, getVoiceConnection(serverId));
  } else {
   throw new Error(`Nieobsługiwany typ Spotify: ${spotifyData.type}`);
  }
 } catch (error) {
  console.error(`Błąd Spotify: ${error.message}`);

  if (error.message.includes('Invalid URL')) {
   throw new Error('Nieprawidłowy link Spotify.');
  } else if (error.message.includes('404')) {
   throw new Error('Nie znaleziono utworu lub playlisty Spotify.');
  } else {
   throw new Error('Wystąpił błąd podczas przetwarzania linku Spotify.');
  }
 }
}

async function handleYoutube(song, serverId) {
 try {
  const url = new URL(song);
  const searchParams = url.searchParams;

  if (searchParams.has('list')) {
   const playlistId = searchParams.get('list');

   try {
    const playlist = await ytpl(playlistId);

    for (const item of playlist.items) {
     addToQueue(serverId, item.shortUrl);
    }

    return { 
     isPlaylist: true, 
     playlistName: playlist.title, 
     trackCount: playlist.items.length 
    };
   } catch (playlistError) {
    console.error(`Błąd pobierania playlisty YouTube (ID: ${playlistId}): ${playlistError.message}`);

    if (playlistId.startsWith('RD')) {
     return await handleRadioPlaylist(song, serverId);
    } else {
     try {
      const searchResults = await youtubeSr.search(url.toString(), { type: 'playlist', limit: 1 });
      if (searchResults.length > 0) {
       const foundPlaylistId = searchResults[0].id;
       return await handleYoutube(`https://www.youtube.com/playlist?list=${foundPlaylistId}`, serverId);
      } else {
       throw new Error(`Nie znaleziono playlisty YouTube odpowiadającej: ${url.toString()}`);
      }
     } catch (searchError) {
      console.error(`Błąd podczas wyszukiwania playlisty YouTube: ${searchError.message}`);
      throw new Error('Nie można znaleźć playlisty YouTube.');
     }
    }
   }
  } else {
   return await handleSingleYoutubeTrack(song, serverId);
  }
 } catch (error) {
  console.error(`Błąd przetwarzania linku YouTube: ${error.message}`);
  throw error;
 }
}

async function handleRadioPlaylist(song, serverId) {
 try {
  const info = await ytdl.getInfo(song, { agent });
  const relatedVideos = info.related_videos;

  const validVideos = relatedVideos.filter((video, index, self) => 
   video.id && !self.some((v, i) => i < index && v.id === video.id)
  );

  for (const relatedVideo of validVideos) {
   addToQueue(serverId, `https://www.youtube.com/watch?v=${relatedVideo.id}`);
  }

  const firstVideoId = validVideos[0]?.id;
  if (firstVideoId) {
   return await handleSingleYoutubeTrack(`https://www.youtube.com/watch?v=${firstVideoId}`, serverId);
  } else {
   throw new Error('Nie znaleziono żadnych prawidłowych filmów w playliście radiowej.');
  }
 } catch (error) {
  console.error(`Błąd przetwarzania playlisty radiowej: ${error.message}`);
  throw error;
 }
}

async function playNextInQueue(serverId, voiceConnection) {
 if (!voiceConnection) {
  console.error("Brak połączenia głosowego dla serwera:", serverId);
  return;
 }

 const queue = getQueue(serverId) || [];

 while (queue.length > 0) {
  const nextSong = queue.shift() || "Brak danych o utworze";
  setCurrentlyPlaying(serverId, nextSong);

  try {
   const resource = await getResource(nextSong, serverId);

   if (!resource) {
    console.error("Nie udało się uzyskać zasobu dla utworu:", nextSong);
    continue;
   }

   const audioPlayer = createAudioPlayer();
   audioPlayers.set(serverId, audioPlayer);

   voiceConnection.subscribe(audioPlayer);

   audioPlayer.play(resource);

   console.log(`Rozpoczęto odtwarzanie: ${resource.metadata.title}`);

   await new Promise((resolve) => {
    audioPlayer.on(AudioPlayerStatus.Idle, () => {
     console.log(`Zakończono odtwarzanie: ${resource.metadata.title}`);
     resolve();
    });

    audioPlayer.on('error', (error) => {
     console.error(`Błąd odtwarzacza audio: ${error.message}`);
     resolve();
    });
   });

  } catch (error) {
   console.error("Błąd podczas odtwarzania utworu:", error);
  }
 }

 setCurrentlyPlaying(serverId, null);
 if (voiceConnection.state.status !== VoiceConnectionStatus.Destroyed) {
  voiceConnection.destroy();
 }
}
async function handleSingleYoutubeTrack(song, serverId) {
    try {
        const info = await ytdl.getInfo(song, { agent });
        const { stream } = await getYouTubeStream(info.videoDetails.videoId);
        const songTitle = info.videoDetails.title || "Nieznany tytuł";
        const songDuration = parseInt(info.videoDetails.lengthSeconds, 10) || 0;

        console.log(`Pobrano utwór z YouTube: ${songTitle} (długość: ${songDuration} sekund)`);

        return await createResourceFromStream(stream, songTitle, songDuration);
    } catch (ytError) {
        console.error(`Nie udało się przetworzyć utworu YouTube: ${ytError.message}`);
        console.log("Próba pobrania z SoundCloud...");

        try {
            const scSearchQuery = song.includes("youtube.com") || song.includes("youtu.be") 
                ? await extractTitleFromYouTubeURL(song) 
                : song;

            return await searchAndGetSoundCloudResource(scSearchQuery, serverId);
        } catch (scError) {
            console.error(`Nie udało się przetworzyć utworu z SoundCloud: ${scError.message}`);
            throw new Error('Nie udało się pobrać utworu ani z YouTube, ani z SoundCloud.');
        }
    }
}

async function extractTitleFromYouTubeURL(url) {
    try {
        const info = await ytdl.getBasicInfo(url, { agent });
        return info.videoDetails.title;
    } catch (error) {
        console.error(`Nie udało się pobrać tytułu z YouTube URL: ${error.message}`);
        return url;
    }
}

async function searchAndGetSoundCloudResource(query, serverId, maxRetries = 3) {
    for (let attempt = 0; attempt < maxRetries; attempt++) {
        try {
            const searchResults = await scdl.search({
                query: query,
                limit: 1,
                offset: 0,
                resourceType: 'tracks'
            });

            if (searchResults.collection && searchResults.collection.length > 0) {
                const track = searchResults.collection[0];
                const stream = await scdl.download(track.permalink_url);

                if (!stream || typeof stream.pipe !== 'function') {
                    throw new Error('Nieprawidłowy strumień');
                }

                const info = {
                    videoDetails: {
                        title: track.title || 'Nieznany tytuł',
                        lengthSeconds: Math.ceil(track.duration / 1000) || 0
                    }
                };

                console.log(`Pobrano utwór SoundCloud: ${info.videoDetails.title} (długość: ${info.videoDetails.lengthSeconds} sekund)`);

                return { stream, info };
            } else {
                throw new Error(`Nie znaleziono wyników wyszukiwania na SoundCloud dla: ${query}`);
            }
        } catch (error) {
            console.error(`Błąd pobierania informacji SoundCloud (próba ${attempt + 1}): ${error.message}`);
            if (attempt === maxRetries - 1) throw error;
            await new Promise(resolve => setTimeout(resolve, 1000 * Math.pow(2, attempt)));
        }
    }
}
async function getYouTubeStream(videoId, maxRetries = 3, initialDelay = 1000) {
    for (let attempt = 0; attempt < maxRetries; attempt++) {
        try {
            const delay = initialDelay * Math.pow(2, attempt);
            await new Promise(resolve => setTimeout(resolve, delay + Math.random() * 1000));

            const info = await ytdl.getInfo(`https://www.youtube.com/watch?v=${videoId}`, {
                agent,
                headers: {
                    'User-Agent': getRandomUserAgent(),
                    'Accept-Language': 'en-US,en;q=0.9',
                    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
                    'Cookie': cookies.map(cookie => `${cookie.name}=${cookie.value}`).join('; ')
                }
            });

            const format = ytdl.chooseFormat(info.formats, { quality: 'highestaudio', filter: 'audioonly' });
            const stream = ytdl.downloadFromInfo(info, { format: format });

            if (!stream || typeof stream.pipe !== 'function') {
                throw new Error('Nieprawidłowy strumień');
            }

            return { stream, info };
        } catch (error) {
            console.error(`Błąd pobierania informacji YouTube (próba ${attempt + 1}): ${error.message}`);
            if (attempt === maxRetries - 1) throw error;
        }
    }
}

async function trySoundCloud(link, serverId) {
 try {
  const info = await scdl.getInfo(link);
  const stream = await scdl.download(link);
  const songTitle = info.title || 'Nieznany tytuł';
  const songDuration = Math.ceil(info.duration / 1000) || 0;

  console.log(`Pobrano utwór SoundCloud: ${songTitle} (długość: ${songDuration} sekund)`);

  return await createResourceFromStream(stream, songTitle, songDuration);
 } catch (error) {
  console.error(`Błąd SoundCloud: ${error.message}`);
  throw error;
 }
}

async function searchAndGetResource(query, serverId) {
 try {
  const searchResults = await youtubeSr.search(query, { type: 'video', limit: 1 });

  if (searchResults.length > 0) {
   const firstResult = searchResults[0];
   const { stream, info } = await getYouTubeStream(firstResult.id);

   if (!stream || typeof stream.pipe !== 'function') {
    throw new Error('Nieprawidłowy strumień');
   }

   return await createResourceFromStream(stream, info.videoDetails.title, info.videoDetails.lengthSeconds);
  } else {
   throw new Error(`Nie znaleziono wyników wyszukiwania dla: ${query}`);
  }
 } catch (error) {
  console.error(`Błąd wyszukiwania YouTube: ${error.message}`);
  console.log("Próba pobrania z SoundCloud...");
  return await searchAndGetSoundCloudResource(query, serverId);
 }
}
async function createResourceFromStream(stream, title, duration) {
    return new Promise((resolve, reject) => {
        if (!stream || typeof stream.pipe !== 'function') {
            reject(new Error('Nieprawidłowy strumień'));
            return;
        }

        const ffmpegArgs = [
            '-i', 'pipe:0',
            '-analyzeduration', '60000000',
            '-loglevel', 'error',
            '-f', 'opus',
            '-c:a', 'libopus',
            '-ar', '48000',
            '-ac', '2',
            '-b:a', '128k',
            '-vbr', 'on',
            '-compression_level', '10',
            'pipe:1'
        ];

        const ffmpeg = spawn('ffmpeg', ffmpegArgs, { stdio: ['pipe', 'pipe', 'ignore'] });

        stream.pipe(ffmpeg.stdin);

        const resource = createAudioResource(ffmpeg.stdout, {
            inputType: StreamType.Opus,
            metadata: { title, duration }
        });

        ffmpeg.on('error', (error) => {
            console.error(`Błąd ffmpeg: ${error.message}`);
            reject(error);
        });

        ffmpeg.on('close', (code) => {
            if (code !== 0) {
                reject(new Error(`ffmpeg zakończony z kodem: ${code}`));
            } else {
                resolve(resource);
            }
        });
    });
}
function addToQueue(serverId, song) {
 if (!queues.has(serverId)) {
  queues.set(serverId, []);
 }

 const queue = queues.get(serverId);
 queue.push(song);
}

function removeFromQueue(serverId, index) {
 const queue = getQueue(serverId);
 if (index >= 0 && index < queue.length) {
  queue.splice(index, 1);
 }
}

function skipSong(serverId, voiceConnection) {
 const audioPlayer = audioPlayers.get(serverId);
 if (audioPlayer && voiceConnection) {
  playNextInQueue(serverId, voiceConnection);
 }
}

function getQueue(serverId) {
 return queues.get(serverId) || [];
}

function clearQueue(serverId) {
 queues.set(serverId, []);
}

function getCurrentlyPlaying(serverId) {
 return currentlyPlaying.get(serverId) || null;
}

function setCurrentlyPlaying(serverId, song) {
 currentlyPlaying.set(serverId, song);
}

function getVoiceConnection(serverId) {
 return voiceConnections.get(serverId) || null;
}

function setVoiceConnection(serverId, connection) {
 voiceConnections.set(serverId, connection);
}

function getSongDetails(resource) {
  try {
    const { title, duration } = resource.metadata;
    return { title, duration };
  } catch (error) {
    console.error(`Błąd w getSongDetails: ${error.message}`);
    return { title: "Nieznany tytuł", duration: "Nieznany czas trwania" };
  }
}

function adjustVolume(serverId, volume) {
 const audioPlayer = audioPlayers.get(serverId);
 if (audioPlayer) {
  audioPlayer.setVolume(volume);
 }
}

module.exports = {
 getResource,
 addToQueue,
 removeFromQueue,
 skipSong,
 getQueue,
 getCurrentlyPlaying,
 setCurrentlyPlaying,
 clearQueue,
 getSongDetails,
 playNextInQueue,
 adjustVolume,
 audioPlayers,
 getVoiceConnection
};

i get this error `` callback(new RequestAbortedError(Proxy response (${statusCode}) !== 200 when HTTP Tunneling`)) ^

RequestAbortedError [AbortError]: Proxy response (407) !== 200 when HTTP Tunneling at CookieClient.connect (C:\Users\USER\Desktop\bibleapp-contact-backend\node_modules\undici\lib\dispatcher\proxy-agent.js:85:22) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) Emitted 'error' event on PassThrough instance at: at process.processTicksAndRejections (node:internal/process/task_queues:95:5) { code: 'UND_ERR_ABORTED' }

Node.js v21.5.0

PatrykPatryk5 commented 3 months ago

my proxy expired

PatrykPatryk5 commented 3 months ago

I use: getRandomIPv6 but unfortunately it doesn't work

const ytdl = require('@distube/ytdl-core');
const { createAudioResource, demuxProbe, createAudioPlayer, AudioPlayerStatus, VoiceConnectionStatus, StreamType } = require('@discordjs/voice');
const fetch = require('isomorphic-unfetch');
const spotifyUrlInfo = require('spotify-url-info')(fetch);
const youtubeSr = require('youtube-sr').default;
const ytpl = require('@distube/ytpl');
const scdl = require('soundcloud-downloader').default;
const { spawn } = require('child_process');
const { PassThrough } = require('stream');
const { URL } = require('url');
const fs = require('fs');
// Funkcja generująca losowy adres IPv6 w określonym zakresie
const { getRandomIPv6 } = require("@distube/ytdl-core/lib/utils");
// Read cookies from file
const cookies = JSON.parse(fs.readFileSync("cookies.json"));

// Funkcja generująca losowy User-Agent
function getRandomUserAgent() {
    const userAgents = [
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15',
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0'
    ];
    return userAgents[Math.floor(Math.random() * userAgents.length)];
}

const agent = ytdl.createAgent(undefined, {
  pipelining: 5,
  maxRedirections: 10,
  localAddress: getRandomIPv6("2001:2::/48")
});

const queues = new Map();
const currentlyPlaying = new Map();
const volumes = new Map();
const voiceConnections = new Map();
const audioPlayers = new Map();

const DELAY_MS = 2000;

function getLinkType(url) {
 const urlString = url.toString();
 if (urlString.includes('spotify.com')) return 'spotify';
 if (urlString.includes('youtube.com') || urlString.includes('youtu.be')) return 'youtube';
 if (urlString.includes('soundcloud.com')) return 'soundcloud';
 return 'unknown';
}

async function getResource(song, serverId) {
 try {
  let stream, info;

  const linkType = getLinkType(song);

  switch(linkType) {
   case 'spotify':
    return await handleSpotify(song, serverId);
   case 'youtube':
    ({ stream, info } = await getYouTubeStream(song));
    break;
   case 'soundcloud':
    ({ stream, info } = await searchAndGetSoundCloudResource(song, serverId));
    break;
   default:
    ({ stream, info } = await searchAndGetResource(song, serverId));
  }

  if (!stream || typeof stream.pipe !== 'function') {
   throw new Error('Nieprawidłowy strumień');
  }

  const title = info?.videoDetails?.title || 'Nieznany tytuł';
  const duration = parseInt(info?.videoDetails?.lengthSeconds, 10) || 0;

  console.log(`Pobrano utwór: ${title} (długość: ${duration} sekund)`);

  return { stream, title, duration };

 } catch (error) {
  console.error(`Błąd w getResource: ${error.message}`);
  return null;
 }
}

async function handleSpotify(song, serverId) {
 try {
  const spotifyData = await spotifyUrlInfo.getData(song);

  if (!spotifyData || !spotifyData.type) {
   throw new Error('Nieprawidłowy link Spotify lub nie można pobrać danych.');
  }

  const tracks = spotifyData.trackList || (spotifyData.tracks && spotifyData.tracks.items) || [spotifyData];

  if (tracks.length === 0) {
   throw new Error('Nie znaleziono utworów w linku Spotify.');
  }

  if (spotifyData.type === 'track') {
   const track = tracks[0];
   const artists = track.artists ? track.artists.map(artist => artist.name).join(', ') : "Nieznany Artysta";
   const searchQuery = `${track.name} - ${artists}`;
   return await searchAndGetResource(searchQuery, serverId);
  } else if (spotifyData.type === 'album' || spotifyData.type === 'playlist') {
   const processedTracks = [];

   for (const item of tracks) {
    const track = item.track || item;
    const artists = track.artists ? track.artists.map(artist => artist.name).join(', ') : "Nieznany Artysta";

    if (track && track.name && artists) {
     const trackName = `${track.name} - ${artists}`;

     if (!processedTracks.includes(trackName)) {
      processedTracks.push(trackName);
      await addYoutubeToQueue(trackName, serverId);
     }
    } 
   }

   return playNextInQueue(serverId, getVoiceConnection(serverId));
  } else {
   throw new Error(`Nieobsługiwany typ Spotify: ${spotifyData.type}`);
  }
 } catch (error) {
  console.error(`Błąd Spotify: ${error.message}`);

  if (error.message.includes('Invalid URL')) {
   throw new Error('Nieprawidłowy link Spotify.');
  } else if (error.message.includes('404')) {
   throw new Error('Nie znaleziono utworu lub playlisty Spotify.');
  } else {
   throw new Error('Wystąpił błąd podczas przetwarzania linku Spotify.');
  }
 }
}

async function handleYoutube(song, serverId) {
 try {
  const url = new URL(song);
  const searchParams = url.searchParams;

  if (searchParams.has('list')) {
   const playlistId = searchParams.get('list');

   try {
    const playlist = await ytpl(playlistId);

    for (const item of playlist.items) {
     addToQueue(serverId, item.shortUrl);
    }

    return { 
     isPlaylist: true, 
     playlistName: playlist.title, 
     trackCount: playlist.items.length 
    };
   } catch (playlistError) {
    console.error(`Błąd pobierania playlisty YouTube (ID: ${playlistId}): ${playlistError.message}`);

    if (playlistId.startsWith('RD')) {
     return await handleRadioPlaylist(song, serverId);
    } else {
     try {
      const searchResults = await youtubeSr.search(url.toString(), { type: 'playlist', limit: 1 });
      if (searchResults.length > 0) {
       const foundPlaylistId = searchResults[0].id;
       return await handleYoutube(`https://www.youtube.com/playlist?list=${foundPlaylistId}`, serverId);
      } else {
       throw new Error(`Nie znaleziono playlisty YouTube odpowiadającej: ${url.toString()}`);
      }
     } catch (searchError) {
      console.error(`Błąd podczas wyszukiwania playlisty YouTube: ${searchError.message}`);
      throw new Error('Nie można znaleźć playlisty YouTube.');
     }
    }
   }
  } else {
   return await handleSingleYoutubeTrack(song, serverId);
  }
 } catch (error) {
  console.error(`Błąd przetwarzania linku YouTube: ${error.message}`);
  throw error;
 }
}

async function handleRadioPlaylist(song, serverId) {
 try {
  const info = await ytdl.getInfo(song, { agent });
  const relatedVideos = info.related_videos;

  const validVideos = relatedVideos.filter((video, index, self) => 
   video.id && !self.some((v, i) => i < index && v.id === video.id)
  );

  for (const relatedVideo of validVideos) {
   addToQueue(serverId, `https://www.youtube.com/watch?v=${relatedVideo.id}`);
  }

  const firstVideoId = validVideos[0]?.id;
  if (firstVideoId) {
   return await handleSingleYoutubeTrack(`https://www.youtube.com/watch?v=${firstVideoId}`, serverId);
  } else {
   throw new Error('Nie znaleziono żadnych prawidłowych filmów w playliście radiowej.');
  }
 } catch (error) {
  console.error(`Błąd przetwarzania playlisty radiowej: ${error.message}`);
  throw error;
 }
}

async function playNextInQueue(serverId, voiceConnection) {
 if (!voiceConnection) {
  console.error("Brak połączenia głosowego dla serwera:", serverId);
  return;
 }

 const queue = getQueue(serverId) || [];

 while (queue.length > 0) {
  const nextSong = queue.shift() || "Brak danych o utworze";
  setCurrentlyPlaying(serverId, nextSong);

  try {
   const resource = await getResource(nextSong, serverId);

   if (!resource) {
    console.error("Nie udało się uzyskać zasobu dla utworu:", nextSong);
    continue;
   }

   const audioPlayer = createAudioPlayer();
   audioPlayers.set(serverId, audioPlayer);

   voiceConnection.subscribe(audioPlayer);

   audioPlayer.play(resource);

   console.log(`Rozpoczęto odtwarzanie: ${resource.metadata.title}`);

   await new Promise((resolve) => {
    audioPlayer.on(AudioPlayerStatus.Idle, () => {
     console.log(`Zakończono odtwarzanie: ${resource.metadata.title}`);
     resolve();
    });

    audioPlayer.on('error', (error) => {
     console.error(`Błąd odtwarzacza audio: ${error.message}`);
     resolve();
    });
   });

  } catch (error) {
   console.error("Błąd podczas odtwarzania utworu:", error);
  }
 }

 setCurrentlyPlaying(serverId, null);
 if (voiceConnection.state.status !== VoiceConnectionStatus.Destroyed) {
  voiceConnection.destroy();
 }
}
async function handleSingleYoutubeTrack(song, serverId) {
    try {
        const info = await ytdl.getInfo(song, { agent });
        const { stream } = await getYouTubeStream(info.videoDetails.videoId);
        const songTitle = info.videoDetails.title || "Nieznany tytuł";
        const songDuration = parseInt(info.videoDetails.lengthSeconds, 10) || 0;

        console.log(`Pobrano utwór z YouTube: ${songTitle} (długość: ${songDuration} sekund)`);

        return await createResourceFromStream(stream, songTitle, songDuration);
    } catch (ytError) {
        console.error(`Nie udało się przetworzyć utworu YouTube: ${ytError.message}`);
        console.log("Próba pobrania z SoundCloud...");

        try {
            const scSearchQuery = song.includes("youtube.com") || song.includes("youtu.be") 
                ? await extractTitleFromYouTubeURL(song) 
                : song;

            return await searchAndGetSoundCloudResource(scSearchQuery, serverId);
        } catch (scError) {
            console.error(`Nie udało się przetworzyć utworu z SoundCloud: ${scError.message}`);
            throw new Error('Nie udało się pobrać utworu ani z YouTube, ani z SoundCloud.');
        }
    }
}

async function extractTitleFromYouTubeURL(url) {
    try {
        const info = await ytdl.getBasicInfo(url, { agent });
        return info.videoDetails.title;
    } catch (error) {
        console.error(`Nie udało się pobrać tytułu z YouTube URL: ${error.message}`);
        return url;
    }
}

async function searchAndGetSoundCloudResource(query, serverId, maxRetries = 3) {
    for (let attempt = 0; attempt < maxRetries; attempt++) {
        try {
            const searchResults = await scdl.search({
                query: query,
                limit: 1,
                offset: 0,
                resourceType: 'tracks'
            });

            if (searchResults.collection && searchResults.collection.length > 0) {
                const track = searchResults.collection[0];
                const stream = await scdl.download(track.permalink_url);

                if (!stream || typeof stream.pipe !== 'function') {
                    throw new Error('Nieprawidłowy strumień');
                }

                const info = {
                    videoDetails: {
                        title: track.title || 'Nieznany tytuł',
                        lengthSeconds: Math.ceil(track.duration / 1000) || 0
                    }
                };

                console.log(`Pobrano utwór SoundCloud: ${info.videoDetails.title} (długość: ${info.videoDetails.lengthSeconds} sekund)`);

                return { stream, info };
            } else {
                throw new Error(`Nie znaleziono wyników wyszukiwania na SoundCloud dla: ${query}`);
            }
        } catch (error) {
            console.error(`Błąd pobierania informacji SoundCloud (próba ${attempt + 1}): ${error.message}`);
            if (attempt === maxRetries - 1) throw error;
            await new Promise(resolve => setTimeout(resolve, 1000 * Math.pow(2, attempt)));
        }
    }
}
async function getYouTubeStream(videoId, maxRetries = 3, initialDelay = 1000) {
    for (let attempt = 0; attempt < maxRetries; attempt++) {
        try {
            const delay = initialDelay * Math.pow(2, attempt);
            await new Promise(resolve => setTimeout(resolve, delay + Math.random() * 1000));

            const info = await ytdl.getInfo(`https://www.youtube.com/watch?v=${videoId}`, {
                agent,
                headers: {
                    'User-Agent': getRandomUserAgent(),
                    'Accept-Language': 'en-US,en;q=0.9',
                    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
                    'Cookie': cookies.map(cookie => `${cookie.name}=${cookie.value}`).join('; ')
                }
            });

            const format = ytdl.chooseFormat(info.formats, { quality: 'highestaudio', filter: 'audioonly' });
            const stream = ytdl.downloadFromInfo(info, { format: format });

            if (!stream || typeof stream.pipe !== 'function') {
                throw new Error('Nieprawidłowy strumień');
            }

            return { stream, info };
        } catch (error) {
            console.error(`Błąd pobierania informacji YouTube (próba ${attempt + 1}): ${error.message}`);
            if (attempt === maxRetries - 1) throw error;
        }
    }
}

async function trySoundCloud(link, serverId) {
 try {
  const info = await scdl.getInfo(link);
  const stream = await scdl.download(link);
  const songTitle = info.title || 'Nieznany tytuł';
  const songDuration = Math.ceil(info.duration / 1000) || 0;

  console.log(`Pobrano utwór SoundCloud: ${songTitle} (długość: ${songDuration} sekund)`);

  return await createResourceFromStream(stream, songTitle, songDuration);
 } catch (error) {
  console.error(`Błąd SoundCloud: ${error.message}`);
  throw error;
 }
}

async function searchAndGetResource(query, serverId) {
 try {
  const searchResults = await youtubeSr.search(query, { type: 'video', limit: 1 });

  if (searchResults.length > 0) {
   const firstResult = searchResults[0];
   const { stream, info } = await getYouTubeStream(firstResult.id);

   if (!stream || typeof stream.pipe !== 'function') {
    throw new Error('Nieprawidłowy strumień');
   }

   return await createResourceFromStream(stream, info.videoDetails.title, info.videoDetails.lengthSeconds);
  } else {
   throw new Error(`Nie znaleziono wyników wyszukiwania dla: ${query}`);
  }
 } catch (error) {
  console.error(`Błąd wyszukiwania YouTube: ${error.message}`);
  console.log("Próba pobrania z SoundCloud...");
  return await searchAndGetSoundCloudResource(query, serverId);
 }
}
async function createResourceFromStream(stream, title, duration) {
    return new Promise((resolve, reject) => {
        if (!stream || typeof stream.pipe !== 'function') {
            reject(new Error('Nieprawidłowy strumień'));
            return;
        }

        const ffmpegArgs = [
            '-i', 'pipe:0',
            '-analyzeduration', '60000000',
            '-loglevel', 'error',
            '-f', 'opus',
            '-c:a', 'libopus',
            '-ar', '48000',
            '-ac', '2',
            '-b:a', '128k',
            '-vbr', 'on',
            '-compression_level', '10',
            'pipe:1'
        ];

        const ffmpeg = spawn('ffmpeg', ffmpegArgs, { stdio: ['pipe', 'pipe', 'ignore'] });

        stream.pipe(ffmpeg.stdin);

        const resource = createAudioResource(ffmpeg.stdout, {
            inputType: StreamType.Opus,
            metadata: { title, duration }
        });

        ffmpeg.on('error', (error) => {
            console.error(`Błąd ffmpeg: ${error.message}`);
            reject(error);
        });

        ffmpeg.on('close', (code) => {
            if (code !== 0) {
                reject(new Error(`ffmpeg zakończony z kodem: ${code}`));
            } else {
                resolve(resource);
            }
        });
    });
}
function addToQueue(serverId, song) {
 if (!queues.has(serverId)) {
  queues.set(serverId, []);
 }

 const queue = queues.get(serverId);
 queue.push(song);
}

function removeFromQueue(serverId, index) {
 const queue = getQueue(serverId);
 if (index >= 0 && index < queue.length) {
  queue.splice(index, 1);
 }
}

function skipSong(serverId, voiceConnection) {
 const audioPlayer = audioPlayers.get(serverId);
 if (audioPlayer && voiceConnection) {
  playNextInQueue(serverId, voiceConnection);
 }
}

function getQueue(serverId) {
 return queues.get(serverId) || [];
}

function clearQueue(serverId) {
 queues.set(serverId, []);
}

function getCurrentlyPlaying(serverId) {
 return currentlyPlaying.get(serverId) || null;
}

function setCurrentlyPlaying(serverId, song) {
 currentlyPlaying.set(serverId, song);
}

function getVoiceConnection(serverId) {
 return voiceConnections.get(serverId) || null;
}

function setVoiceConnection(serverId, connection) {
 voiceConnections.set(serverId, connection);
}

function getSongDetails(resource) {
  try {
    const { title, duration } = resource.metadata;
    return { title, duration };
  } catch (error) {
    console.error(`Błąd w getSongDetails: ${error.message}`);
    return { title: "Nieznany tytuł", duration: "Nieznany czas trwania" };
  }
}

function adjustVolume(serverId, volume) {
 const audioPlayer = audioPlayers.get(serverId);
 if (audioPlayer) {
  audioPlayer.setVolume(volume);
 }
}

module.exports = {
 getResource,
 addToQueue,
 removeFromQueue,
 skipSong,
 getQueue,
 getCurrentlyPlaying,
 setCurrentlyPlaying,
 clearQueue,
 getSongDetails,
 playNextInQueue,
 adjustVolume,
 audioPlayers,
 getVoiceConnection
};
MikeyA-yo commented 3 months ago

my proxy expired

oh, i don't know much about using proxy anyways, if i want to use proxy should that be like an environment variable?

MikeyA-yo commented 3 months ago

What happens if i use createAgent without any option but cookies?

PatrykPatryk5 commented 3 months ago

my proxy expired

oh, i don't know much about using proxy anyways, if i want to use proxy should that be like an environment variable?

It is best to add this to another file see the documentation. But logging in doesn't do anything (or I'm doing it wrong) Youtube blocks ip addresses. In my opinion you need to add the vpn system right into the library because it doesn't make sense.

skick1234 commented 3 months ago

If you have this error, YouTube just prevents your IP from playing videos without logging in. You need to log an account then get the cookies follow the guide in the readme.

image

qubiack commented 3 months ago

I have all cookies & this fix download locally. But on the server it doesn't help at all. Any other ideas? Should I use the same IP to loggin?


I use right now different login on server and different locally and right now it is working.

dbaldassi commented 3 months ago

Hi, I have added cookies according to the doc, and it works on my server but only for a short period of time, like 15mn or so. Is there anything to do to make it permanent ?

mr-flame7892 commented 3 months ago

Hi, I have added cookies according to the doc, and it works on my server but only for a short period of time, like 15mn or so. Is there anything to do to make it permanent ?

Personally, I use cookies of an account which I never use (in order to never disrupt the cookies of this account). You export the cookies of this account, then you delete all the YouTube cookies from your browser in order to log out and normally it will work for a while.

dbaldassi commented 3 months ago

Based on what you said, I have taken the cookie in a private window, so the browser would not save the cookies, it seems to work better now. I'll let you know if I still encounter the issue later