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'));
|
||||||
try {
|
const proxyAgent = new ProxyAgent(proxy.uri);
|
||||||
|
|
||||||
const headers = {
|
|
||||||
'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'));
|
console.log(`Tentative de récupération pour: ${song.title || song.url}`);
|
||||||
const proxy = await JSON.parse(await fs.readFileSync(__glob.PROXY, 'utf-8'));
|
|
||||||
const agent = ytdl.createProxyAgent(proxy, cookies)
|
|
||||||
let stream = ytdl(song.url, {
|
|
||||||
quality: 'highestaudio',
|
|
||||||
highWaterMark: 1 << 30,
|
|
||||||
liveBuffer: 20000,
|
|
||||||
dlChunkSize: 0,
|
|
||||||
bitrate: 128,
|
|
||||||
requestOptions: {
|
|
||||||
headers: headers,
|
|
||||||
},
|
|
||||||
agent: agent,
|
|
||||||
});
|
|
||||||
|
|
||||||
return stream
|
// Création de l'instance Innertube avec les bons paramètres
|
||||||
|
const youtube = await Innertube.create({
|
||||||
} catch(e) {
|
cookie: cookieStr,
|
||||||
clog.error("Erreur lors de la récupération du stream : " + song.title)
|
player_id: '0004de42',
|
||||||
clog.error(e)
|
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`,
|
||||||
|
client_type: ClientType.WEB,
|
||||||
|
retrieve_player: true,
|
||||||
|
device_category: 'desktop',
|
||||||
|
enable_session_cache: true,
|
||||||
|
generate_session_locally: true,
|
||||||
|
// fetch: (url, options) => fetch(url, { ...options, agent: proxyAgent })
|
||||||
|
});
|
||||||
|
|
||||||
|
// Récupérer les infos vidéo
|
||||||
|
const videoInfo = await youtube.getInfo(song.id);
|
||||||
|
|
||||||
|
|
||||||
|
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