Compare commits
	
		
			2 Commits
		
	
	
		
			96cd60912b
			...
			0f0f263c98
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						
						
							
						
						0f0f263c98
	
				 | 
					
					
						|||
| 
						
						
							
						
						ca4a20a1b2
	
				 | 
					
					
						
							
								
								
									
										19
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					FROM node:lts-alpine
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Crée un dossier de travail
 | 
				
			||||||
 | 
					WORKDIR /app
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Copie package.json et package-lock.json
 | 
				
			||||||
 | 
					COPY package*.json ./
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Installe les dépendances
 | 
				
			||||||
 | 
					RUN npm install
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Copie le code source (mais pas le dossier data, qui sera monté en volume)
 | 
				
			||||||
 | 
					COPY . .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Expose le port backend
 | 
				
			||||||
 | 
					EXPOSE 4000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Commande de démarrage
 | 
				
			||||||
 | 
					CMD ["node", "src/utils/main.js"]
 | 
				
			||||||
							
								
								
									
										16
									
								
								docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					version: "3.9"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					services:
 | 
				
			||||||
 | 
					  subsonics-backend:
 | 
				
			||||||
 | 
					    build:
 | 
				
			||||||
 | 
					      context: .   # dossier backend
 | 
				
			||||||
 | 
					      dockerfile: Dockerfile
 | 
				
			||||||
 | 
					    container_name: subsonics-backend
 | 
				
			||||||
 | 
					    ports:
 | 
				
			||||||
 | 
					      - "4000:4000"
 | 
				
			||||||
 | 
					    volumes:
 | 
				
			||||||
 | 
					      - subsonics-backend-data:/app/data
 | 
				
			||||||
 | 
					    restart: unless-stopped
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					volumes:
 | 
				
			||||||
 | 
					  subsonics-backend-data:
 | 
				
			||||||
							
								
								
									
										3707
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										3707
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "chopin-backend",
 | 
					  "name": "chopin-backend",
 | 
				
			||||||
  "version": "1.2.0",
 | 
					  "version": "1.3.0",
 | 
				
			||||||
  "description": "Discord Bot for music - Fetching everywhere !",
 | 
					  "description": "Discord Bot for music - Fetching everywhere !",
 | 
				
			||||||
  "main": "src/main.js",
 | 
					  "main": "src/main.js",
 | 
				
			||||||
  "nodemonConfig": {
 | 
					  "nodemonConfig": {
 | 
				
			||||||
@@ -30,16 +30,19 @@
 | 
				
			|||||||
    "ffprobe-static": "^3.1.0",
 | 
					    "ffprobe-static": "^3.1.0",
 | 
				
			||||||
    "fluent-ffmpeg": "^2.1.3",
 | 
					    "fluent-ffmpeg": "^2.1.3",
 | 
				
			||||||
    "googleapis": "^149.0.0",
 | 
					    "googleapis": "^149.0.0",
 | 
				
			||||||
 | 
					    "https-proxy-agent": "^7.0.6",
 | 
				
			||||||
    "libsodium-wrappers": "^0.7.15",
 | 
					    "libsodium-wrappers": "^0.7.15",
 | 
				
			||||||
    "loguix": "^1.4.2",
 | 
					    "loguix": "^1.4.2",
 | 
				
			||||||
    "mime-types": "^3.0.1",
 | 
					    "mime-types": "^3.0.1",
 | 
				
			||||||
    "nodemon": "^3.1.10",
 | 
					    "nodemon": "^3.1.10",
 | 
				
			||||||
    "pm2": "^5.4.3",
 | 
					    "pm2": "^6.0.11",
 | 
				
			||||||
    "socket.io": "^4.8.1",
 | 
					    "socket.io": "^4.8.1",
 | 
				
			||||||
    "soundcloud.ts": "^0.6.3",
 | 
					    "soundcloud.ts": "^0.6.3",
 | 
				
			||||||
    "spotify-web-api-node": "^5.0.2",
 | 
					    "spotify-web-api-node": "^5.0.2",
 | 
				
			||||||
 | 
					    "undici": "^7.16.0",
 | 
				
			||||||
    "uuid": "^11.1.0",
 | 
					    "uuid": "^11.1.0",
 | 
				
			||||||
    "webmetrik": "^0.1.4",
 | 
					    "webmetrik": "^0.1.4",
 | 
				
			||||||
 | 
					    "youtubei.js": "^15.1.1",
 | 
				
			||||||
    "yt-search": "^2.13.1",
 | 
					    "yt-search": "^2.13.1",
 | 
				
			||||||
    "ytfps": "^1.2.0"
 | 
					    "ytfps": "^1.2.0"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,46 +1,91 @@
 | 
				
			|||||||
const {createAudioResource, VoiceConnectionStatus, createAudioPlayer, StreamType} = require('@discordjs/voice');
 | 
					const { LogType } = require('loguix');
 | 
				
			||||||
const {LogType} = require('loguix')
 | 
					const clog = new LogType("Youtube-Stream");
 | 
				
			||||||
const clog = new LogType("Youtube-Stream")
 | 
					 | 
				
			||||||
const ytdl = require('@distube/ytdl-core')
 | 
					 | 
				
			||||||
const { __glob } = require('../../utils/GlobalVars');
 | 
					const { __glob } = require('../../utils/GlobalVars');
 | 
				
			||||||
 | 
					const { Innertube, UniversalCache, ClientType } = require('youtubei.js');
 | 
				
			||||||
const fs = require('fs');
 | 
					const fs = require('fs');
 | 
				
			||||||
 | 
					const { ProxyAgent } = require('undici');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function getStream(song) {
 | 
					async function getStream(song) {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					        // Lire et formater les cookies comme chaîne
 | 
				
			||||||
 | 
					        const cookiesArr = JSON.parse(fs.readFileSync(__glob.COOKIES, 'utf-8'));
 | 
				
			||||||
 | 
					        const cookieStr = cookiesArr.map(cookie => `${cookie.name}=${cookie.value}`).join('; ');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //  FIXME: Change youtube provider
 | 
					        // Lire et préparer le proxy
 | 
				
			||||||
 | 
					        const proxy = JSON.parse(fs.readFileSync(__glob.PROXY, 'utf-8'));
 | 
				
			||||||
 | 
					        const proxyAgent = new ProxyAgent(proxy.uri);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
       try {
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const headers = {
 | 
					        console.log(`Tentative de récupération pour: ${song.title || song.url}`);
 | 
				
			||||||
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ' +
 | 
					 | 
				
			||||||
                          'AppleWebKit/537.36 (KHTML, like Gecko) ' +
 | 
					 | 
				
			||||||
                          'Chrome/116.0.5845.97 Safari/537.36',
 | 
					 | 
				
			||||||
            'Accept-Language': 'en-US,en;q=0.9'
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
         var cookies = await JSON.parse(await fs.readFileSync(__glob.COOKIES, 'utf-8'));
 | 
					        // Création de l'instance Innertube avec les bons paramètres
 | 
				
			||||||
         const proxy = await JSON.parse(await fs.readFileSync(__glob.PROXY, 'utf-8'));
 | 
					        const youtube = await Innertube.create({
 | 
				
			||||||
          const agent = ytdl.createProxyAgent(proxy, cookies)
 | 
					            cookie: cookieStr,
 | 
				
			||||||
          let stream = ytdl(song.url, {
 | 
					            player_id: '0004de42',
 | 
				
			||||||
               quality: 'highestaudio',
 | 
					            user_agent: `Mozilla/5.0 (Macintosh; Intel Mac OS X 15_0) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Safari/605.1.15`,
 | 
				
			||||||
               highWaterMark: 1 << 30,
 | 
					            client_type: ClientType.WEB,
 | 
				
			||||||
               liveBuffer: 20000,
 | 
					            retrieve_player: true,
 | 
				
			||||||
               dlChunkSize: 0,
 | 
					            device_category: 'desktop',
 | 
				
			||||||
               bitrate: 128,
 | 
					            enable_session_cache: true,
 | 
				
			||||||
               requestOptions: {
 | 
					            generate_session_locally: true,
 | 
				
			||||||
                headers: headers,
 | 
					            // fetch: (url, options) => fetch(url, { ...options, agent: proxyAgent })
 | 
				
			||||||
               },
 | 
					        });
 | 
				
			||||||
               agent: agent,
 | 
					 | 
				
			||||||
          });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return stream
 | 
					        // Récupérer les infos vidéo
 | 
				
			||||||
 | 
					        const videoInfo = await youtube.getInfo(song.id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    } catch(e) {
 | 
					 | 
				
			||||||
        clog.error("Erreur lors de la récupération du stream : " + song.title)
 | 
					 | 
				
			||||||
        clog.error(e)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!videoInfo) {
 | 
				
			||||||
 | 
					            throw new Error('Impossible de récupérer les informations de la vidéo');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        console.log('Informations vidéo récupérées:', videoInfo.basic_info?.title);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Vérifier la disponibilité de la lecture
 | 
				
			||||||
 | 
					        if (videoInfo.playability_status?.status !== 'OK') {
 | 
				
			||||||
 | 
					            console.log('Statut de lecture:', videoInfo.playability_status?.status);
 | 
				
			||||||
 | 
					            console.log('Raison:', videoInfo.playability_status?.reason);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Recherche des formats audio adaptatifs
 | 
				
			||||||
 | 
					        let audioFormats = videoInfo.streaming_data?.adaptive_formats?.filter(
 | 
				
			||||||
 | 
					            format => format.mime_type?.includes('audio')
 | 
				
			||||||
 | 
					        ) || [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (audioFormats.length === 0) {
 | 
				
			||||||
 | 
					            // Si pas de formats adaptatifs, chercher dans les formats classiques
 | 
				
			||||||
 | 
					            const basicFormats = videoInfo.streaming_data?.formats?.filter(
 | 
				
			||||||
 | 
					                format => format.mime_type?.includes('audio')
 | 
				
			||||||
 | 
					            ) || [];
 | 
				
			||||||
 | 
					            if (basicFormats.length === 0) {
 | 
				
			||||||
 | 
					                throw new Error('Aucun format audio trouvé');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            audioFormats.push(...basicFormats);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Sélection du format audio de meilleure qualité
 | 
				
			||||||
 | 
					        const bestAudio = audioFormats.reduce((prev, current) =>
 | 
				
			||||||
 | 
					            (prev.bitrate || 0) > (current.bitrate || 0) ? prev : current
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        console.log('Format sélectionné:', bestAudio.mime_type, bestAudio.bitrate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Télécharger le stream audio
 | 
				
			||||||
 | 
					        const stream = await videoInfo.download(bestAudio.itag, {
 | 
				
			||||||
 | 
					            // fetch via ton proxy si nécessaire
 | 
				
			||||||
 | 
					            headers: {
 | 
				
			||||||
 | 
					                'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 15_0) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Safari/605.1.15',
 | 
				
			||||||
 | 
					                'Cookie': cookieStr
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        console.log(stream)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return stream; // c’est un ReadableStream prêt à être pipé
 | 
				
			||||||
 | 
					    } catch (e) {
 | 
				
			||||||
 | 
					        clog.error("Erreur lors de la récupération du stream : " + (song.title || song.url));
 | 
				
			||||||
 | 
					        clog.error('Détails:', e.message);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = { getStream };
 | 
				
			||||||
module.exports = {getStream}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -283,6 +283,7 @@ class Player {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async setDuration(duration) {
 | 
					    async setDuration(duration) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //FIXME: SET DURATION FONCTIONNE TRES LENTEMENT
 | 
					        //FIXME: SET DURATION FONCTIONNE TRES LENTEMENT
 | 
				
			||||||
        if (this.checkConnection()) return;
 | 
					        if (this.checkConnection()) return;
 | 
				
			||||||
        if (this.queue.current == null) return;
 | 
					        if (this.queue.current == null) return;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -447,7 +447,6 @@ async function setFullBan(id) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
function deleteAccount(id) {
 | 
					function deleteAccount(id) {
 | 
				
			||||||
    const user = getUserById(id);
 | 
					    const user = getUserById(id);
 | 
				
			||||||
    if (user) {
 | 
					    if (user) {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user