Version 1.1.0 - Refactor + Intergration Backend
This commit is contained in:
58
src/media/MediaInformation.js
Normal file
58
src/media/MediaInformation.js
Normal file
@@ -0,0 +1,58 @@
|
||||
const ffprobe = require('ffprobe');
|
||||
const ffprobeStatic = require('ffprobe-static');
|
||||
const { getReadableDuration } = require('../utils/TimeConverter');
|
||||
const clog = require("loguix").getInstance("Song")
|
||||
|
||||
|
||||
async function getMediaInformation(instance, media, provider) {
|
||||
try {
|
||||
const info = await ffprobe(media.attachment.url, { path: ffprobeStatic.path });
|
||||
if (info.streams?.[0]?.duration_ts) {
|
||||
instance.duration = info.streams[0].duration;
|
||||
instance.readduration = getReadableDuration(instance.duration)
|
||||
}
|
||||
|
||||
// Vérification pour éviter une erreur si `streams[0]` ou `tags` n'existe pas
|
||||
instance.thumbnail = info.streams?.[0]?.tags?.thumbnail ??
|
||||
"https://radomisol.fr/wp-content/uploads/2016/08/cropped-note-radomisol-musique.png";
|
||||
|
||||
// Obtenir le titre (sinon utiliser le nom du fichier)
|
||||
instance.title = info.streams?.[0]?.tags?.title ?? media.attachment.name;
|
||||
|
||||
// Obtenir l'auteur (s'il existe)
|
||||
instance.author = info.streams?.[0]?.tags?.artist ?? instance.author;
|
||||
|
||||
} catch (err) {
|
||||
clog.error("Impossible de récupérer les informations de la musique : " + media.attachment.name)
|
||||
clog.error(err)
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function getMediaInformationFromUrl(instance, url) {
|
||||
try {
|
||||
const info = await ffprobe(url, { path: ffprobeStatic.path });
|
||||
if (info.streams?.[0]?.duration_ts) {
|
||||
instance.duration = info.streams[0].duration;
|
||||
instance.readduration = getReadableDuration(instance.duration);
|
||||
}
|
||||
|
||||
// Vérification pour éviter une erreur si `streams[0]` ou `tags` n'existe pas
|
||||
instance.thumbnail = info.streams?.[0]?.tags?.thumbnail ??
|
||||
"https://radomisol.fr/wp-content/uploads/2016/08/cropped-note-radomisol-musique.png";
|
||||
|
||||
// Obtenir le titre (sinon utiliser le nom du fichier)
|
||||
instance.title = info.streams?.[0]?.tags?.title ?? "Titre inconnu";
|
||||
|
||||
// Obtenir l'auteur (s'il existe)
|
||||
instance.author = info.streams?.[0]?.tags?.artist ?? "Auteur inconnu";
|
||||
|
||||
} catch (err) {
|
||||
clog.error("Impossible de récupérer les informations de la musique depuis l'URL : " + url);
|
||||
console.log(err)
|
||||
clog.error(err);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {getMediaInformation, getMediaInformationFromUrl};
|
||||
85
src/media/SoundcloudInformation.js
Normal file
85
src/media/SoundcloudInformation.js
Normal file
@@ -0,0 +1,85 @@
|
||||
const {LogType} = require('loguix');
|
||||
const clog = new LogType("SoundcloudInformation");
|
||||
const {Song} = require('../player/Song');
|
||||
const {Playlist} = require('../playlists/Playlist');
|
||||
const {Soundcloud} = require('soundcloud.ts')
|
||||
const {getReadableDuration} = require('../utils/TimeConverter');
|
||||
|
||||
const soundcloud = new Soundcloud();
|
||||
|
||||
async function getTrack(url) {
|
||||
try {
|
||||
const info = await soundcloud.tracks.get(url)
|
||||
|
||||
if(!info) {
|
||||
clog.error("Impossible de récupérer les informations de la piste Soundcloud à partir de l'URL");
|
||||
return null;
|
||||
}
|
||||
|
||||
const song = new Song();
|
||||
song.title = info.title;
|
||||
song.author = info.user.username;
|
||||
song.url = info.permalink_url;
|
||||
song.thumbnail = info.artwork_url;
|
||||
song.id = info.id;
|
||||
song.duration = info.duration / 1000;
|
||||
song.readduration = getReadableDuration(info.duration / 1000);
|
||||
song.type = "soundcloud";
|
||||
|
||||
return song;
|
||||
|
||||
} catch (error) {
|
||||
clog.error('Erreur lors de la recherche Soundcloud (Track): ' + error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function getPlaylist(url) {
|
||||
|
||||
try {
|
||||
|
||||
const info = await soundcloud.playlists.get(url)
|
||||
|
||||
if(!info) {
|
||||
clog.error("Impossible de récupérer les informations de la playlist Soundcloud à partir de l'URL");
|
||||
return null;
|
||||
}
|
||||
|
||||
const playlist = new Playlist();
|
||||
|
||||
playlist.title = info.title;
|
||||
playlist.author = info.user.username;
|
||||
playlist.url = info.permalink_url;
|
||||
playlist.thumbnail = info.artwork_url;
|
||||
playlist.id = info.id;
|
||||
playlist.duration = 0;
|
||||
playlist.songs = [];
|
||||
playlist.type = "soundcloud";
|
||||
|
||||
for(const track of info.tracks) {
|
||||
const song = new Song();
|
||||
song.title = track.title;
|
||||
song.author = track.user.username;
|
||||
song.url = track.permalink_url;
|
||||
song.thumbnail = track.artwork_url;
|
||||
song.id = track.id;
|
||||
song.duration = track.duration / 1000;
|
||||
song.readduration = getReadableDuration(track.duration / 1000);
|
||||
song.type = "soundcloud";
|
||||
|
||||
playlist.duration += track.duration / 1000;
|
||||
playlist.songs.push(song);
|
||||
}
|
||||
|
||||
playlist.readduration = getReadableDuration(playlist.duration);
|
||||
|
||||
return playlist;
|
||||
|
||||
} catch (error) {
|
||||
clog.error('Erreur lors de la recherche Soundcloud (Playlist): ' + error);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = {getTrack, getPlaylist}
|
||||
179
src/media/SpotifyInformation.js
Normal file
179
src/media/SpotifyInformation.js
Normal file
@@ -0,0 +1,179 @@
|
||||
const {LogType} = require('loguix');
|
||||
const clog = new LogType("SpotifyInformation");
|
||||
const config = require('../utils/Database/Configuration');
|
||||
const SPOTIFY_CLIENT_ID = config.getSpotifyClientId()
|
||||
const SPOTIFY_CLIENT_SECRET = config.getSpotifyClientSecret()
|
||||
const SpotifyWebApi = require('spotify-web-api-node');
|
||||
const {Playlist} = require('../playlists/Playlist');
|
||||
const {Song} = require('../player/Song');
|
||||
const youtube = require("../media/YoutubeInformation");
|
||||
const {getReadableDuration} = require('../utils/TimeConverter');
|
||||
|
||||
const spotifyApi = new SpotifyWebApi({
|
||||
clientId: SPOTIFY_CLIENT_ID,
|
||||
clientSecret: SPOTIFY_CLIENT_SECRET,
|
||||
});
|
||||
|
||||
async function getSong(url) {
|
||||
try {
|
||||
const data = await spotifyApi.clientCredentialsGrant();
|
||||
spotifyApi.setAccessToken(data.body['access_token']);
|
||||
|
||||
const parts = url.split('/');
|
||||
const trackId = parts[parts.length - 1];
|
||||
|
||||
if(!trackId) {
|
||||
clog.error("Impossible de récupérer l'identifiant de la piste Spotify à partir de l'URL");
|
||||
return null;
|
||||
}
|
||||
const trackInfo = await spotifyApi.getTrack(trackId);
|
||||
|
||||
const trackName = trackInfo.body.name;
|
||||
const artistName = trackInfo.body.artists[0].name;
|
||||
|
||||
return `${trackName} - ${artistName}`;
|
||||
} catch (error) {
|
||||
|
||||
clog.error("Impossible de récupérer les informations de la piste Spotify à partir de l'URL");
|
||||
clog.error(error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function getAlbum(url) {
|
||||
|
||||
try {
|
||||
|
||||
|
||||
const creditdata = await spotifyApi.clientCredentialsGrant();
|
||||
spotifyApi.setAccessToken(creditdata.body['access_token']);
|
||||
|
||||
const parts = url.split('/');
|
||||
const albumId = parts[parts.indexOf('album') + 1].split('?')[0];
|
||||
|
||||
const data = await spotifyApi.getAlbum(albumId);
|
||||
const info = data.body;
|
||||
|
||||
if(!info) {
|
||||
clog.error("Impossible de récupérer les informations de l'album Spotify à partir de l'URL");
|
||||
return null;
|
||||
}
|
||||
|
||||
clog.log("Informations de l'album récupérées : " + info.name);
|
||||
|
||||
const playlist = new Playlist()
|
||||
playlist.title = info.name;
|
||||
playlist.author = info.artists[0].name;
|
||||
playlist.authorId = info.artists[0].id;
|
||||
playlist.thumbnail = info.images[0].url;
|
||||
playlist.url = info.external_urls.spotify;
|
||||
playlist.id = albumId;
|
||||
playlist.type = "spotify";
|
||||
playlist.songs = info.tracks.items;
|
||||
|
||||
return playlist;
|
||||
|
||||
} catch (error) {
|
||||
|
||||
clog.error("Impossible de récupérer les informations de l'album Spotify à partir de l'URL");
|
||||
clog.error(error);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
async function getPlaylist(url) {
|
||||
// Get the playlist and return a Playlist Object
|
||||
|
||||
try {
|
||||
const creditdata = await spotifyApi.clientCredentialsGrant();
|
||||
spotifyApi.setAccessToken(creditdata.body['access_token']);
|
||||
|
||||
const parts = url.split('/');
|
||||
const playlistId = parts[parts.indexOf('playlist') + 1].split('?')[0];
|
||||
|
||||
const data = await spotifyApi.getPlaylist(playlistId)
|
||||
|
||||
const info = data.body;
|
||||
|
||||
if(!info) {
|
||||
clog.error("Impossible de récupérer les informations de la playlist Spotify à partir de l'URL");
|
||||
return null;
|
||||
}
|
||||
|
||||
clog.log("Informations de la playlist récupérées : " + info.name);
|
||||
|
||||
const playlist = new Playlist()
|
||||
playlist.title = info.name;
|
||||
playlist.author = info.owner.display_name;
|
||||
playlist.authorId = info.owner.id;
|
||||
playlist.thumbnail = info.images[0].url;
|
||||
playlist.url = info.external_urls.spotify;
|
||||
playlist.id = playlistId;
|
||||
playlist.type = "spotify";
|
||||
|
||||
for(const track of info.tracks.items) {
|
||||
playlist.songs.push(track.track);
|
||||
}
|
||||
|
||||
return playlist;
|
||||
|
||||
} catch (error) {
|
||||
|
||||
clog.error("Impossible de récupérer les informations de l'album Spotify à partir de l'URL");
|
||||
clog.error(error);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async function getTracks(playlist) {
|
||||
|
||||
const tracks = playlist.songs
|
||||
playlistSongs = [];
|
||||
for(const track of tracks) {
|
||||
|
||||
var trackName = track.name;
|
||||
var artistName = track.artists[0].name;
|
||||
var queryForYoutube = `${trackName} - ${artistName}`;
|
||||
|
||||
var urlYoutubeFounded = await youtube.getQuery(queryForYoutube).then(function(songFind) {
|
||||
if(!songFind) return null;
|
||||
return songFind.url;
|
||||
});
|
||||
|
||||
clog.log("URL de la vidéo YouTube trouvée : " + urlYoutubeFounded);
|
||||
|
||||
if(!urlYoutubeFounded) {
|
||||
clog.error("Impossible de récupérer l'URL de la vidéo YouTube à partir de la requête " + queryForYoutube);
|
||||
|
||||
} else {
|
||||
const song = new Song();
|
||||
|
||||
song.title = track.name;
|
||||
song.author = track.artists[0].name;
|
||||
song.url = urlYoutubeFounded;
|
||||
song.thumbnail = playlist.thumbnail;
|
||||
song.id = track.id;
|
||||
song.duration = track.duration_ms / 1000;
|
||||
song.readduration = getReadableDuration(track.duration_ms / 1000);
|
||||
song.type = "youtube";
|
||||
|
||||
playlist.duration += track.duration_ms / 1000;
|
||||
playlistSongs.push(song);
|
||||
}
|
||||
|
||||
// When finish do this
|
||||
|
||||
}
|
||||
|
||||
playlist.readduration = getReadableDuration(playlist.duration);
|
||||
playlist.songs = playlistSongs;
|
||||
|
||||
|
||||
return playlist;
|
||||
}
|
||||
|
||||
|
||||
module.exports = {getSong, getAlbum, getPlaylist, getTracks}
|
||||
135
src/media/YoutubeInformation.js
Normal file
135
src/media/YoutubeInformation.js
Normal file
@@ -0,0 +1,135 @@
|
||||
const { LogType } = require('loguix');
|
||||
const clog = new LogType("YoutubeInformation");
|
||||
const { Song } = require('../player/Song');
|
||||
const { Playlist } = require('../playlists/Playlist');
|
||||
const { getReadableDuration, getSecondsDuration } = require('../utils/TimeConverter');
|
||||
const ytsr = require('@distube/ytsr');
|
||||
const ytfps = require('ytfps');
|
||||
|
||||
async function getQuery(query, multiple) {
|
||||
if (!query || typeof query !== 'string') {
|
||||
clog.error("Impossible de rechercher une vidéo YouTube, car la requête est nulle");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const limit = multiple ? 25 : 1;
|
||||
const searchResults = await ytsr(query, { limit });
|
||||
const videos = searchResults.items.filter(item => item.type === 'video');
|
||||
|
||||
if (videos.length === 0) {
|
||||
clog.error("Impossible de récupérer le lien de la vidéo YouTube à partir de la requête");
|
||||
return null;
|
||||
}
|
||||
|
||||
const songs = await Promise.all(videos.map(video => getVideo(video.url)));
|
||||
return multiple ? songs.filter(song => song !== null) : songs[0];
|
||||
} catch (error) {
|
||||
clog.error('Erreur lors de la recherche YouTube: ' + error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function getVideo(url) {
|
||||
const videoId = url.match(/(?:youtu\.be\/|youtube\.com\/|music\.youtube\.com\/)(?:watch\?v=)?([a-zA-Z0-9_-]{11})/);
|
||||
if (videoId === null) {
|
||||
clog.error("Impossible de récupérer l'identifiant de la vidéo YouTube à partir de l'URL");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const searchResults = await ytsr(videoId[1], { limit: 1 });
|
||||
const video = searchResults.items.find(item => item.type === 'video');
|
||||
|
||||
if (video) {
|
||||
const songReturn = new Song();
|
||||
await songReturn.processYoutubeVideo(video);
|
||||
return songReturn;
|
||||
} else {
|
||||
clog.error("Impossible de récupérer la vidéo YouTube à partir de l'identifiant");
|
||||
return null;
|
||||
}
|
||||
} catch (error) {
|
||||
clog.error('Erreur lors de la recherche de la vidéo YouTube:' + error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function getPlaylist(url) {
|
||||
if (url === null || typeof url !== 'string') {
|
||||
clog.error("Impossible de rechercher une playlist YouTube, car la requête est nulle");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
// If watch?v= is present in the url with list?=, remove it and the code behind and transform it to playlist?list=
|
||||
var playlistId;
|
||||
|
||||
// Get &list= in the url until the first & or ?
|
||||
|
||||
if (url.includes("list=")) {
|
||||
playlistId = url.match(/(list=)([a-zA-Z0-9_-]+)/);
|
||||
}
|
||||
|
||||
console.log(playlistId);
|
||||
|
||||
if (playlistId === null) {
|
||||
clog.error("Impossible de récupérer l'identifiant de la playlist YouTube à partir de l'URL");
|
||||
return null;
|
||||
}
|
||||
|
||||
const playlistInfo = await ytfps(playlistId[2]);
|
||||
|
||||
if (!playlistInfo) {
|
||||
clog.error("Impossible de récupérer la playlist YouTube à partir de l'identifiant");
|
||||
return null;
|
||||
}
|
||||
|
||||
const playlist = new Playlist();
|
||||
playlist.type = "youtube";
|
||||
playlist.author = playlistInfo.author.name;
|
||||
playlist.authorId = playlistInfo.author.url;
|
||||
playlist.title = playlistInfo.title;
|
||||
playlist.thumbnail = playlistInfo.thumbnail_url;
|
||||
playlist.description = playlistInfo.description;
|
||||
playlist.url = `https://www.youtube.com/playlist?list=${playlistId[2]}`;
|
||||
playlist.id = playlistId[2];
|
||||
|
||||
for (const video of playlistInfo.videos) {
|
||||
const song = new Song();
|
||||
await song.processYoutubeVideo(video, true);
|
||||
playlist.duration += song.duration;
|
||||
playlist.songs.push(song);
|
||||
}
|
||||
playlist.readduration = getReadableDuration(playlist.duration);
|
||||
return playlist;
|
||||
} catch (error) {
|
||||
clog.error('Erreur lors de la recherche YouTube: ' + error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function getSecondsFromUrl(url) {
|
||||
const videoId = url.match(/(?:youtu\.be\/|youtube\.com\/|music\.youtube\.com\/)(?:watch\?v=)?([a-zA-Z0-9_-]{11})/);
|
||||
if (videoId === null) {
|
||||
clog.error("Impossible de récupérer l'identifiant de la vidéo YouTube à partir de l'URL");
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
const searchResults = await ytsr(videoId[1], { limit: 1 });
|
||||
const video = searchResults.items.find(item => item.type === 'video');
|
||||
console.log(video);
|
||||
if (video) {
|
||||
return getSecondsDuration(video.duration); // Convert seconds to milliseconds
|
||||
} else {
|
||||
clog.error("Impossible de récupérer la vidéo YouTube à partir de l'identifiant");
|
||||
return null;
|
||||
}
|
||||
} catch (error) {
|
||||
clog.error('Erreur lors de la recherche de la vidéo YouTube:' + error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { getQuery, getVideo, getPlaylist, getSecondsFromUrl };
|
||||
Reference in New Issue
Block a user