Version 0.3.0 - Ajout des premières fonctionnalités du Player
This commit is contained in:
		
							
								
								
									
										61
									
								
								backend/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										61
									
								
								backend/package-lock.json
									
									
									
										generated
									
									
									
								
							@@ -24,9 +24,11 @@
 | 
				
			|||||||
        "nodemon": "^3.1.9",
 | 
					        "nodemon": "^3.1.9",
 | 
				
			||||||
        "pm2": "^5.4.3",
 | 
					        "pm2": "^5.4.3",
 | 
				
			||||||
        "socket.io": "^4.8.1",
 | 
					        "socket.io": "^4.8.1",
 | 
				
			||||||
 | 
					        "soundcloud.ts": "^0.6.3",
 | 
				
			||||||
        "spotify-web-api-node": "^5.0.2",
 | 
					        "spotify-web-api-node": "^5.0.2",
 | 
				
			||||||
        "uuid": "^11.1.0",
 | 
					        "uuid": "^11.1.0",
 | 
				
			||||||
        "webmetrik": "^0.1.4"
 | 
					        "webmetrik": "^0.1.4",
 | 
				
			||||||
 | 
					        "ytfps": "^1.2.0"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/@derhuerst/http-basic": {
 | 
					    "node_modules/@derhuerst/http-basic": {
 | 
				
			||||||
@@ -65,6 +67,16 @@
 | 
				
			|||||||
        "spotify-url-info": "^3.2.6"
 | 
					        "spotify-url-info": "^3.2.6"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/@discord-player/extractor/node_modules/soundcloud.ts": {
 | 
				
			||||||
 | 
					      "version": "0.5.5",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/soundcloud.ts/-/soundcloud.ts-0.5.5.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-bygjhC1w/w26Nk0Y+4D4cWSEJ1TdxLaE6+w4pCazFzPF+J4mzuB62ggWmFa7BiwnirzNf9lgPbjzrQYGege4Ew==",
 | 
				
			||||||
 | 
					      "license": "MIT",
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "undici": "^6.17.0"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "node_modules/@discord-player/ffmpeg": {
 | 
					    "node_modules/@discord-player/ffmpeg": {
 | 
				
			||||||
      "version": "7.1.0",
 | 
					      "version": "7.1.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/@discord-player/ffmpeg/-/ffmpeg-7.1.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/@discord-player/ffmpeg/-/ffmpeg-7.1.0.tgz",
 | 
				
			||||||
@@ -1560,6 +1572,32 @@
 | 
				
			|||||||
      "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
 | 
					      "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
 | 
				
			||||||
      "license": "MIT"
 | 
					      "license": "MIT"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/axios": {
 | 
				
			||||||
 | 
					      "version": "1.8.1",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.1.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-NN+fvwH/kV01dYUQ3PTOZns4LWtWhOFCAhQ/pHb88WQ1hNe5V/dvFwc4VJcDL11LT9xSX0QtsR8sWUuyOuOq7g==",
 | 
				
			||||||
 | 
					      "license": "MIT",
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "follow-redirects": "^1.15.6",
 | 
				
			||||||
 | 
					        "form-data": "^4.0.0",
 | 
				
			||||||
 | 
					        "proxy-from-env": "^1.1.0"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/axios/node_modules/form-data": {
 | 
				
			||||||
 | 
					      "version": "4.0.2",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
 | 
				
			||||||
 | 
					      "license": "MIT",
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "asynckit": "^0.4.0",
 | 
				
			||||||
 | 
					        "combined-stream": "^1.0.8",
 | 
				
			||||||
 | 
					        "es-set-tostringtag": "^2.1.0",
 | 
				
			||||||
 | 
					        "mime-types": "^2.1.12"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">= 6"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "node_modules/balanced-match": {
 | 
					    "node_modules/balanced-match": {
 | 
				
			||||||
      "version": "1.0.2",
 | 
					      "version": "1.0.2",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
 | 
				
			||||||
@@ -5569,14 +5607,10 @@
 | 
				
			|||||||
      "license": "MIT"
 | 
					      "license": "MIT"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/soundcloud.ts": {
 | 
					    "node_modules/soundcloud.ts": {
 | 
				
			||||||
      "version": "0.5.5",
 | 
					      "version": "0.6.3",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/soundcloud.ts/-/soundcloud.ts-0.5.5.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/soundcloud.ts/-/soundcloud.ts-0.6.3.tgz",
 | 
				
			||||||
      "integrity": "sha512-bygjhC1w/w26Nk0Y+4D4cWSEJ1TdxLaE6+w4pCazFzPF+J4mzuB62ggWmFa7BiwnirzNf9lgPbjzrQYGege4Ew==",
 | 
					      "integrity": "sha512-Ri5bO0jQKKACijGP1/OVbWXhHREDST2T6QUSAPWlzQjUScXVyh+7YJfN1mTnyuAA7vZjKyZ1FMlWC2hKd7jmHQ==",
 | 
				
			||||||
      "license": "MIT",
 | 
					      "license": "MIT"
 | 
				
			||||||
      "peer": true,
 | 
					 | 
				
			||||||
      "dependencies": {
 | 
					 | 
				
			||||||
        "undici": "^6.17.0"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/source-map": {
 | 
					    "node_modules/source-map": {
 | 
				
			||||||
      "version": "0.6.1",
 | 
					      "version": "0.6.1",
 | 
				
			||||||
@@ -6559,6 +6593,15 @@
 | 
				
			|||||||
      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
 | 
					      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
 | 
				
			||||||
      "license": "ISC"
 | 
					      "license": "ISC"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/ytfps": {
 | 
				
			||||||
 | 
					      "version": "1.2.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/ytfps/-/ytfps-1.2.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-DLcW0opwT0zO+4C5YqcCgPiOIzAtge6q6q3nDW0gCBy4kPufEdyxmjd1O9GUV4WeAFxfA2XNhZLmaohrGKV1WA==",
 | 
				
			||||||
 | 
					      "license": "MIT",
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "axios": "^1.7.2"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,8 +33,10 @@
 | 
				
			|||||||
    "nodemon": "^3.1.9",
 | 
					    "nodemon": "^3.1.9",
 | 
				
			||||||
    "pm2": "^5.4.3",
 | 
					    "pm2": "^5.4.3",
 | 
				
			||||||
    "socket.io": "^4.8.1",
 | 
					    "socket.io": "^4.8.1",
 | 
				
			||||||
 | 
					    "soundcloud.ts": "^0.6.3",
 | 
				
			||||||
    "spotify-web-api-node": "^5.0.2",
 | 
					    "spotify-web-api-node": "^5.0.2",
 | 
				
			||||||
    "uuid": "^11.1.0",
 | 
					    "uuid": "^11.1.0",
 | 
				
			||||||
    "webmetrik": "^0.1.4"
 | 
					    "webmetrik": "^0.1.4",
 | 
				
			||||||
 | 
					    "ytfps": "^1.2.0"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,9 +5,13 @@ const { __glob } = require("../utils/GlobalVars")
 | 
				
			|||||||
const { LogType } = require("loguix")
 | 
					const { LogType } = require("loguix")
 | 
				
			||||||
const config = require("../utils/Database/Configuration")
 | 
					const config = require("../utils/Database/Configuration")
 | 
				
			||||||
const metric = require("webmetrik") 
 | 
					const metric = require("webmetrik") 
 | 
				
			||||||
 | 
					const { Player } = require("../player/Player")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const dlog = new LogType("Discord")
 | 
					const dlog = new LogType("Discord")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const membersVoices = new Map()
 | 
				
			||||||
 | 
					const timers = new Map()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const client = new Client({
 | 
					const client = new Client({
 | 
				
			||||||
    intents:[GatewayIntentBits.Guilds, GatewayIntentBits.GuildVoiceStates, GatewayIntentBits.GuildMembers],
 | 
					    intents:[GatewayIntentBits.Guilds, GatewayIntentBits.GuildVoiceStates, GatewayIntentBits.GuildMembers],
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
@@ -68,7 +72,42 @@ function init() {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // TODO: Implement the disconnect event for the bot
 | 
					    client.on("voiceStateUpdate", (oldMember, newMember) => {
 | 
				
			||||||
 | 
					        membersVoices.set(newMember.id, {
 | 
				
			||||||
 | 
					            guildId: newMember.guild.id,
 | 
				
			||||||
 | 
					            channelId: newMember.channelId,
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const player = new Player(newMember.guild.id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(player.connection && player.channelId) {
 | 
				
			||||||
 | 
					            client.channels.fetch(player.channelId).then(channel => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if(channel.members.size <= 1) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    // If the player is alone in the channel, we will destroy it in 10 minutes
 | 
				
			||||||
 | 
					                    // 10 minutes = 600000 ms
 | 
				
			||||||
 | 
					                    // 10 second = 10000 ms
 | 
				
			||||||
 | 
					                    timers.set(newMember.guild.id, setTimeout(() => {
 | 
				
			||||||
 | 
					                        const getPlayer = new Player(newMember.guild.id)
 | 
				
			||||||
 | 
					                        if(getPlayer.connection && player.channelId) {
 | 
				
			||||||
 | 
					                            getPlayer.leave()
 | 
				
			||||||
 | 
					                            dlog.log("[Automatic Task] Guild Id :" + newMember.guild.id + " - Player supprimé : " + channel.name)
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                 
 | 
				
			||||||
 | 
					                    }, 10000))
 | 
				
			||||||
 | 
					                    dlog.log("[Automatic Task] Guild Id :" + newMember.guild.id + " -  Player supprimé dans 10 minutess : " + channel.name)
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    dlog.log("[Automatic Task] Guild Id :" + newMember.guild.id + " -  Player n'est pas seul dans le channel : " + channel.name)
 | 
				
			||||||
 | 
					                    clearTimeout(timers.get(newMember.guild.id))
 | 
				
			||||||
 | 
					                    timers.delete(newMember.guild.id)
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,7 @@ const { Embed, EmbedError } = require("../Embed");
 | 
				
			|||||||
const { Player } = require("../../player/Player");
 | 
					const { Player } = require("../../player/Player");
 | 
				
			||||||
const Finder = require("../../player/Finder");
 | 
					const Finder = require("../../player/Finder");
 | 
				
			||||||
const { Playlist } = require("../../player/Playlist");
 | 
					const { Playlist } = require("../../player/Playlist");
 | 
				
			||||||
 | 
					const spotify = require("../../media/SpotifyInformation");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const command = new Command("play", "Jouer une musique à partir d'un lien dans un salon vocal", async (client, interaction) => {
 | 
					const command = new Command("play", "Jouer une musique à partir d'un lien dans un salon vocal", async (client, interaction) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -11,7 +12,7 @@ const command = new Command("play", "Jouer une musique à partir d'un lien dans
 | 
				
			|||||||
    const url = interaction.options.get("url")
 | 
					    const url = interaction.options.get("url")
 | 
				
			||||||
    const channel = interaction.member.voice.channel
 | 
					    const channel = interaction.member.voice.channel
 | 
				
			||||||
    const now = interaction.options.getBoolean("now") || false
 | 
					    const now = interaction.options.getBoolean("now") || false
 | 
				
			||||||
    await Finder.search(url.value).then((song) => {
 | 
					    await Finder.search(url.value).then(async (song) => {
 | 
				
			||||||
        if(!song) return new EmbedError("Impossible de trouver la musique à partir du lien donné ou des mots clés donnés").send(interaction)
 | 
					        if(!song) return new EmbedError("Impossible de trouver la musique à partir du lien donné ou des mots clés donnés").send(interaction)
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
        const player = new Player(channel.guildId)
 | 
					        const player = new Player(channel.guildId)
 | 
				
			||||||
@@ -22,35 +23,23 @@ const command = new Command("play", "Jouer une musique à partir d'un lien dans
 | 
				
			|||||||
        
 | 
					        
 | 
				
			||||||
        // Check if song is playlist 
 | 
					        // Check if song is playlist 
 | 
				
			||||||
        if(song instanceof Playlist) {
 | 
					        if(song instanceof Playlist) {
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
            if(now) {
 | 
					 | 
				
			||||||
                player.readPlaylist(song, true)
 | 
					 | 
				
			||||||
                embed.setTitle('**Lecture immédiate**')
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                player.readPlaylist(song)
 | 
					 | 
				
			||||||
                embed.setTitle('**Ajout à la liste de lecture**')
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            embed.setDescription('**Playlist : **' + song.songs.length + ' musiques')
 | 
					            embed.setDescription('**Playlist : **' + song.songs.length + ' musiques')
 | 
				
			||||||
            embed.addField('**Titre : **' + song.title, "")  
 | 
					            embed.addField('**Titre : **' + song.title, "")  
 | 
				
			||||||
            embed.addField('**Demandé par : **', interaction.member.user.username,)
 | 
					            embed.addField('**Demandé par : **', interaction.member.user.username,)
 | 
				
			||||||
            embed.addField('**Auteur : **', song.author)  
 | 
					            embed.addField('**Auteur : **', song.author) 
 | 
				
			||||||
            embed.addField('**Durée : **', song.readduration)
 | 
					            embed.addField('**Provient de : **', song.type.replace(/^\w/, (c) => c.toUpperCase()))
 | 
				
			||||||
 | 
					            if(!song.type == "spotify") {
 | 
				
			||||||
 | 
					                embed.addField('**Durée : **', song.readduration)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            embed.addField('**Lien : **', song.url)
 | 
				
			||||||
 | 
					            embed.addField(":warning: La récupération des musiques peut prendre du temps", "Veuillez patienter ... et éviter de lancer d'autres commandes")
 | 
				
			||||||
 | 
					                  
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            embed.setThumbnail(song.thumbnail)
 | 
					            embed.setThumbnail(song.thumbnail)
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
            if(now) { 
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
                player.play(song)
 | 
					 | 
				
			||||||
                embed.setTitle('**Lecture immédiate**')
 | 
					 | 
				
			||||||
          
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                player.add(song)
 | 
					 | 
				
			||||||
                embed.setTitle('**Ajout à liste de lecture**')
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
            embed.setDescription('**Titre : **' + song.title)
 | 
					            embed.setDescription('**Titre : **' + song.title)
 | 
				
			||||||
            embed.addField('**Durée : **', song.readduration)
 | 
					            embed.addField('**Durée : **', song.readduration)
 | 
				
			||||||
            embed.addField("**Artiste : **",song.author)
 | 
					            embed.addField("**Artiste : **",song.author)
 | 
				
			||||||
@@ -60,9 +49,42 @@ const command = new Command("play", "Jouer une musique à partir d'un lien dans
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(now) {
 | 
				
			||||||
 | 
					            embed.setTitle("Lecture immédiate")
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            embed.setTitle("Ajoutée à la file d'attente")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        embed.send(interaction)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(song instanceof Playlist) {
 | 
				
			||||||
 | 
					            if(song.type == "spotify") {
 | 
				
			||||||
 | 
					                song = await spotify.getTracks(song)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if(now) {
 | 
				
			||||||
 | 
					                player.readPlaylist(song, true)
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                player.readPlaylist(song)
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(now) { 
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					                player.play(song)
 | 
				
			||||||
 | 
					          
 | 
				
			||||||
 | 
					          
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                player.add(song)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
       
 | 
					       
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        embed.send(interaction)
 | 
					      
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
}, [{type: "STRING", name: "url", description: "Recherche / Lien audio (Youtube / Soundclound / Spotify)", required: true},
 | 
					}, [{type: "STRING", name: "url", description: "Recherche / Lien audio (Youtube / Soundclound / Spotify)", required: true},
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,85 @@
 | 
				
			|||||||
 | 
					const {LogType} = require('loguix');
 | 
				
			||||||
 | 
					const clog = new LogType("SoundcloudInformation");
 | 
				
			||||||
 | 
					const {Song} = require('../player/Song');
 | 
				
			||||||
 | 
					const {Playlist} = require('../player/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}
 | 
				
			||||||
@@ -27,33 +27,83 @@ async function getSong(url) {
 | 
				
			|||||||
            return null;
 | 
					            return null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        const trackInfo = await spotifyApi.getTrack(trackId);
 | 
					        const trackInfo = await spotifyApi.getTrack(trackId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const trackName = trackInfo.body.name;
 | 
					        const trackName = trackInfo.body.name;
 | 
				
			||||||
        const artistName = trackInfo.body.artists[0].name;
 | 
					        const artistName = trackInfo.body.artists[0].name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return `${trackName} - ${artistName}`;
 | 
					        return `${trackName} - ${artistName}`;
 | 
				
			||||||
    } catch (error) {
 | 
					    } catch (error) {
 | 
				
			||||||
        console.error('Erreur lors de la récupération des données :', 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(albumId) {
 | 
					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) {
 | 
					async function getPlaylist(url) {
 | 
				
			||||||
    // Get the playlist and return a Playlist Object
 | 
					    // Get the playlist and return a Playlist Object
 | 
				
			||||||
    const data = await spotifyApi.clientCredentialsGrant();
 | 
					
 | 
				
			||||||
    spotifyApi.setAccessToken(data.body['access_token']);
 | 
					    try {
 | 
				
			||||||
 | 
					    const creditdata = await spotifyApi.clientCredentialsGrant();
 | 
				
			||||||
 | 
					    spotifyApi.setAccessToken(creditdata.body['access_token']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const parts = url.split('/');
 | 
					    const parts = url.split('/');
 | 
				
			||||||
    const playlistId = parts[parts.indexOf('playlist') + 1].split('?')[0];
 | 
					    const playlistId = parts[parts.indexOf('playlist') + 1].split('?')[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    spotifyApi.getPlaylist(playlistId)
 | 
					        const data = await spotifyApi.getPlaylist(playlistId)
 | 
				
			||||||
    .then(function(data) {
 | 
					  
 | 
				
			||||||
        const info = data.body;
 | 
					        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() 
 | 
					        const playlist = new Playlist() 
 | 
				
			||||||
        playlist.title = info.name;
 | 
					        playlist.title = info.name;
 | 
				
			||||||
        playlist.author = info.owner.display_name;
 | 
					        playlist.author = info.owner.display_name;
 | 
				
			||||||
@@ -62,51 +112,68 @@ async function getPlaylist(url) {
 | 
				
			|||||||
        playlist.url = info.external_urls.spotify;
 | 
					        playlist.url = info.external_urls.spotify;
 | 
				
			||||||
        playlist.id = playlistId;
 | 
					        playlist.id = playlistId;
 | 
				
			||||||
        playlist.type = "spotify";
 | 
					        playlist.type = "spotify";
 | 
				
			||||||
 | 
					       
 | 
				
			||||||
 | 
					        for(const track of info.tracks.items) {
 | 
				
			||||||
 | 
					            playlist.songs.push(track.track);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return playlist;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        const tracks = info.tracks.items;
 | 
					    } catch (error) {
 | 
				
			||||||
        tracks.forEach(async function(track) {
 | 
					       
 | 
				
			||||||
        
 | 
					        clog.error("Impossible de récupérer les informations de l'album Spotify à partir de l'URL");
 | 
				
			||||||
            var trackName = track.track.name;
 | 
					        clog.error(error);
 | 
				
			||||||
            var artistName = track.track.artists[0].name;
 | 
					        return null;
 | 
				
			||||||
            var queryForYoutube =  `${trackName} - ${artistName}`;
 | 
					    }
 | 
				
			||||||
 | 
					          
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var urlYoutubeFounded = await youtube.getQuery(queryForYoutube).then(function(songFind) {
 | 
					async function getTracks(playlist) {
 | 
				
			||||||
                if(!songFind) return null;
 | 
					 | 
				
			||||||
                return songFind.url;
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            clog.log("URL de la vidéo YouTube trouvée : " + urlYoutubeFounded);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(!urlYoutubeFounded) {
 | 
					    const tracks = playlist.songs
 | 
				
			||||||
                clog.error("Impossible de récupérer l'URL de la vidéo YouTube à partir de la requête  " + queryForYoutube);
 | 
					    playlistSongs = [];
 | 
				
			||||||
               
 | 
					    for(const track of tracks) {
 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                const song = new Song();
 | 
					 | 
				
			||||||
                song.title = track.track.name;
 | 
					 | 
				
			||||||
                song.author = track.track.artists[0].name;
 | 
					 | 
				
			||||||
                song.url = urlYoutubeFounded;
 | 
					 | 
				
			||||||
                song.thumbnail = track.track.album.images[0].url;
 | 
					 | 
				
			||||||
                song.id = track.track.id;
 | 
					 | 
				
			||||||
                song.duration = track.track.duration_ms / 1000;
 | 
					 | 
				
			||||||
                song.readduration = getReadableDuration(track.track.duration_ms);
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
                playlist.duration += track.track.duration_ms;
 | 
					        var trackName = track.name;
 | 
				
			||||||
    
 | 
					        var artistName = track.artists[0].name;
 | 
				
			||||||
    
 | 
					        var queryForYoutube =  `${trackName} - ${artistName}`;
 | 
				
			||||||
                playlist.songs.push(song);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            
 | 
					        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.readduration = getReadableDuration(playlist.duration);
 | 
				
			||||||
 | 
					        playlist.songs = playlistSongs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return playlist;
 | 
					        return playlist;
 | 
				
			||||||
   
 | 
					 | 
				
			||||||
    }, function(err) {
 | 
					 | 
				
			||||||
        clog.error('Une erreur s\'est produite lors de la récupération de la playlist');
 | 
					 | 
				
			||||||
        clog.error(err);
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {getSong, getAlbum, getPlaylist}
 | 
					module.exports = {getSong, getAlbum, getPlaylist, getTracks}
 | 
				
			||||||
@@ -1,35 +1,28 @@
 | 
				
			|||||||
const {LogType} = require('loguix');
 | 
					const { LogType } = require('loguix');
 | 
				
			||||||
const clog = new LogType("YoutubeInformation");
 | 
					const clog = new LogType("YoutubeInformation");
 | 
				
			||||||
const config = require('../utils/Database/Configuration');
 | 
					 | 
				
			||||||
const YOUTUBE_API_KEY = config.getYoutubeApiKey()
 | 
					 | 
				
			||||||
const { Song } = require('../player/Song');
 | 
					const { Song } = require('../player/Song');
 | 
				
			||||||
const { Playlist } = require('../player/Playlist');
 | 
					const { Playlist } = require('../player/Playlist');
 | 
				
			||||||
const { getReadableDuration } = require('../utils/TimeConverter');
 | 
					const { getReadableDuration } = require('../utils/TimeConverter');
 | 
				
			||||||
 | 
					const ytsr = require('@distube/ytsr');
 | 
				
			||||||
 | 
					const ytfps = require('ytfps');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function getQuery(query) {
 | 
				
			||||||
async function 
 | 
					    if (query === null || typeof query !== 'string') {
 | 
				
			||||||
getQuery(query) {
 | 
					 | 
				
			||||||
    // Check Query not null and a string
 | 
					 | 
				
			||||||
    if(query === null && typeof query !== 'string') {
 | 
					 | 
				
			||||||
        clog.error("Impossible de rechercher une vidéo YouTube, car la requête est nulle");
 | 
					        clog.error("Impossible de rechercher une vidéo YouTube, car la requête est nulle");
 | 
				
			||||||
        return null;
 | 
					        return null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // * Fetch
 | 
					
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
        const response = await fetch(`https://www.googleapis.com/youtube/v3/search?part=snippet&type=video&q=${encodeURIComponent(query)}&key=${YOUTUBE_API_KEY}`);
 | 
					        const searchResults = await ytsr(query, { limit: 1 });
 | 
				
			||||||
        const data = await response.json();
 | 
					        const video = searchResults.items.find(item => item.type === 'video');
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        var videoLink = null
 | 
					        if (!video) {
 | 
				
			||||||
        const videoId = data.items[0]?.id.videoId;
 | 
					 | 
				
			||||||
        if(videoId) videoLink = `https://www.youtube.com/watch?v=${videoId}`;
 | 
					 | 
				
			||||||
        if(videoLink === null) {
 | 
					 | 
				
			||||||
            clog.error("Impossible de récupérer le lien de la vidéo YouTube à partir de la requête");
 | 
					            clog.error("Impossible de récupérer le lien de la vidéo YouTube à partir de la requête");
 | 
				
			||||||
            return null;
 | 
					            return null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        const song = await getVideo(videoLink);
 | 
					
 | 
				
			||||||
     
 | 
					        const song = await getVideo(video.url);
 | 
				
			||||||
        return song;
 | 
					        return song;
 | 
				
			||||||
       
 | 
					 | 
				
			||||||
    } catch (error) {
 | 
					    } catch (error) {
 | 
				
			||||||
        clog.error('Erreur lors de la recherche YouTube: ' + error);
 | 
					        clog.error('Erreur lors de la recherche YouTube: ' + error);
 | 
				
			||||||
        return null;
 | 
					        return null;
 | 
				
			||||||
@@ -37,103 +30,72 @@ getQuery(query) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function getVideo(url) {
 | 
					async function getVideo(url) {
 | 
				
			||||||
    // Extract video ID from URL if it exists and is valid (11 characters) and if not return "NOT_VALID"
 | 
					 | 
				
			||||||
    // Extract id from youtu.be youtube.com and music.youtube.com
 | 
					 | 
				
			||||||
    const videoId = url.match(/(?:youtu\.be\/|youtube\.com\/|music\.youtube\.com\/)(?:watch\?v=)?([a-zA-Z0-9_-]{11})/);
 | 
					    const videoId = url.match(/(?:youtu\.be\/|youtube\.com\/|music\.youtube\.com\/)(?:watch\?v=)?([a-zA-Z0-9_-]{11})/);
 | 
				
			||||||
    if(videoId === null) {
 | 
					    if (videoId === null) {
 | 
				
			||||||
        clog.error("Impossible de récupérer l'identifiant de la vidéo YouTube à partir de l'URL");
 | 
					        clog.error("Impossible de récupérer l'identifiant de la vidéo YouTube à partir de l'URL");
 | 
				
			||||||
        return null;
 | 
					        return null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // Fetch video information
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
        const response = await fetch(`https://www.googleapis.com/youtube/v3/videos?part=snippet&id=${videoId[1]}&key=${YOUTUBE_API_KEY}`);
 | 
					 | 
				
			||||||
        const data = await response.json();
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        const video = data.items[0];
 | 
					 | 
				
			||||||
        if(video) {
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            const songReturn = new Song()
 | 
					    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);
 | 
					            await songReturn.processYoutubeVideo(video);
 | 
				
			||||||
           
 | 
					 | 
				
			||||||
            return songReturn;
 | 
					            return songReturn;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            clog.error("Impossible de récupérer la vidéo YouTube à partir de l'identifiant");
 | 
					            clog.error("Impossible de récupérer la vidéo YouTube à partir de l'identifiant");
 | 
				
			||||||
            return null;
 | 
					            return null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    } catch (error) {
 | 
					    } catch (error) {
 | 
				
			||||||
        clog.error('Erreur lors de la recherche de la vidéo YouTube:' +  error);
 | 
					        clog.error('Erreur lors de la recherche de la vidéo YouTube:' + error);
 | 
				
			||||||
        return null;
 | 
					        return null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function getPlaylist(url) {
 | 
					async function getPlaylist(url) {
 | 
				
			||||||
    // Check Query not null and a string
 | 
					    if (url === null || typeof url !== 'string') {
 | 
				
			||||||
    if(url === null && typeof url !== 'string') {
 | 
					 | 
				
			||||||
        clog.error("Impossible de rechercher une playlist YouTube, car la requête est nulle");
 | 
					        clog.error("Impossible de rechercher une playlist YouTube, car la requête est nulle");
 | 
				
			||||||
        return null;
 | 
					        return null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // * Fetch
 | 
					
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
        // For Playlist
 | 
					        const playlistId = url.match(/(?:youtu\.be\/|youtube\.com\/|music\.youtube\.com\/)(?:playlist\?list=)?([a-zA-Z0-9_-]{34})/);
 | 
				
			||||||
        const playlistId = url.match(/(?:youtu\.be\/|youtube\.com\/|music\.youtube.com\/)(?:playlist\?list=)?([a-zA-Z0-9_-]{34})/);
 | 
					        if (playlistId === null) {
 | 
				
			||||||
        if(playlistId === null) {
 | 
					            clog.error("Impossible de récupérer l'identifiant de la playlist YouTube à partir de l'URL");
 | 
				
			||||||
            clog.error("Impossible de récupérer l'identifiant de la vidéo YouTube à partir de l'URL");
 | 
					 | 
				
			||||||
            return null;
 | 
					            return null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        const response = await fetch(`https://www.googleapis.com/youtube/v3/search?part=snippet&type=playlist&q=${encodeURIComponent(playlistId[1])}&key=${YOUTUBE_API_KEY}`);
 | 
					 | 
				
			||||||
        const data = await response.json();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(data.items.length === 0) {
 | 
					        const playlistInfo = await ytfps(playlistId[1]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!playlistInfo) {
 | 
				
			||||||
            clog.error("Impossible de récupérer la playlist YouTube à partir de l'identifiant");
 | 
					            clog.error("Impossible de récupérer la playlist YouTube à partir de l'identifiant");
 | 
				
			||||||
            return null;
 | 
					            return null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const playlist = new Playlist()
 | 
					        const playlist = new Playlist();
 | 
				
			||||||
        playlist.type = "youtube"
 | 
					        playlist.type = "youtube";
 | 
				
			||||||
        playlist.author = data.items[0].snippet.channelTitle
 | 
					        playlist.author = playlistInfo.author.name;
 | 
				
			||||||
        playlist.authorId = data.items[0].snippet.channelId
 | 
					        playlist.authorId = playlistInfo.author.url;
 | 
				
			||||||
        playlist.title = data.items[0].snippet.title
 | 
					        playlist.title = playlistInfo.title;
 | 
				
			||||||
        playlist.thumbnail = data.items[0].snippet.thumbnails.high.url
 | 
					        playlist.thumbnail = playlistInfo.thumbnail_url;
 | 
				
			||||||
        playlist.description = data.items[0].snippet.description    
 | 
					        playlist.description = playlistInfo.description;
 | 
				
			||||||
        playlist.url = `https://www.youtube.com/playlist?list=${playlistId[1]}`
 | 
					        playlist.url = `https://www.youtube.com/playlist?list=${playlistId[1]}`;
 | 
				
			||||||
        playlist.id = playlistId[1]
 | 
					        playlist.id = playlistId[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    
 | 
					        for (const video of playlistInfo.videos) {
 | 
				
			||||||
 | 
					            const song = new Song();
 | 
				
			||||||
 | 
					            await song.processYoutubeVideo(video, true);
 | 
				
			||||||
        // Get all songs from playlist
 | 
					            playlist.duration += song.duration;
 | 
				
			||||||
 | 
					            playlist.songs.push(song);
 | 
				
			||||||
        const responsePlaylist = await fetch(`https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&playlistId=${playlistId[1]}&key=${YOUTUBE_API_KEY}&maxResults=100`);
 | 
					 | 
				
			||||||
        const dataPlaylist = await responsePlaylist.json();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if(dataPlaylist.items.length === 0) {
 | 
					 | 
				
			||||||
            clog.error("Impossible de récupérer les vidéos de la playlist YouTube à partir de l'identifiant ou la playlist est vide");
 | 
					 | 
				
			||||||
            return null;    
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        playlist.readduration = getReadableDuration(playlist.duration);
 | 
				
			||||||
        for (const video of dataPlaylist.items) {
 | 
					 | 
				
			||||||
            const song = new Song()
 | 
					 | 
				
			||||||
            video.id = video.snippet.resourceId.videoId
 | 
					 | 
				
			||||||
            await song.processYoutubeVideo(video)
 | 
					 | 
				
			||||||
            //? Add seconds to playlist duration
 | 
					 | 
				
			||||||
            playlist.duration += song.duration
 | 
					 | 
				
			||||||
            playlist.songs.push(song)
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        playlist.readduration = getReadableDuration(playlist.duration)
 | 
					 | 
				
			||||||
        return playlist;
 | 
					        return playlist;
 | 
				
			||||||
     
 | 
					 | 
				
			||||||
     
 | 
					 | 
				
			||||||
       
 | 
					 | 
				
			||||||
       
 | 
					 | 
				
			||||||
    } catch (error) {
 | 
					    } catch (error) {
 | 
				
			||||||
        clog.error('Erreur lors de la recherche YouTube: ' + error);
 | 
					        clog.error('Erreur lors de la recherche YouTube: ' + error);
 | 
				
			||||||
        return null;
 | 
					        return null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {getQuery, getVideo, getPlaylist}
 | 
					module.exports = { getQuery, getVideo, getPlaylist };
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,7 @@ const { QueryType } = require('../utils/QueryType');
 | 
				
			|||||||
const { Links } = require('../utils/Links');
 | 
					const { Links } = require('../utils/Links');
 | 
				
			||||||
const youtube = require("../media/YoutubeInformation")
 | 
					const youtube = require("../media/YoutubeInformation")
 | 
				
			||||||
const spotify = require("../media/SpotifyInformation")
 | 
					const spotify = require("../media/SpotifyInformation")
 | 
				
			||||||
 | 
					const soundcloud = require("../media/SoundcloudInformation")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function search(query) {
 | 
					async function search(query) {
 | 
				
			||||||
@@ -25,16 +26,18 @@ async function search(query) {
 | 
				
			|||||||
        
 | 
					        
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if(type == QueryType.SPOTIFY_ALBUM) {
 | 
					    if(type == QueryType.SPOTIFY_ALBUM) {
 | 
				
			||||||
 | 
					        return await spotify.getAlbum(query)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if(type == QueryType.SPOTIFY_PLAYLIST) {
 | 
					    if(type == QueryType.SPOTIFY_PLAYLIST) {
 | 
				
			||||||
        return await spotify.getPlaylist(query)
 | 
					        return await spotify.getPlaylist(query)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if(type == QueryType.SOUNDCLOUD_TRACK) {
 | 
					    if(type == QueryType.SOUNDCLOUD_TRACK) {
 | 
				
			||||||
 | 
					        return await soundcloud.getTrack(query)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if(type == QueryType.SOUNDCLOUD_PLAYLIST) {
 | 
					    if(type == QueryType.SOUNDCLOUD_PLAYLIST) {
 | 
				
			||||||
 | 
					        return await soundcloud.getPlaylist(query)
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // TODO: Add more providers
 | 
					    // TODO: Add more providers
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,11 +9,11 @@ async function play(instance, song) {
 | 
				
			|||||||
            instance.player = createAudioPlayer()
 | 
					            instance.player = createAudioPlayer()
 | 
				
			||||||
            instance.generatePlayerEvents()
 | 
					            instance.generatePlayerEvents()
 | 
				
			||||||
            const player = instance.player
 | 
					            const player = instance.player
 | 
				
			||||||
            song.resource = await createAudioResource(song.url, {
 | 
					            var resource = await createAudioResource(song.url, {
 | 
				
			||||||
                    inputType: StreamType.Arbitrary
 | 
					                    inputType: StreamType.Arbitrary
 | 
				
			||||||
               }) // Remplace par ton fichier audio
 | 
					               }) // Remplace par ton fichier audio
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            player.play(song.resource);
 | 
					            player.play(resource);
 | 
				
			||||||
            instance.connection.subscribe(player);
 | 
					            instance.connection.subscribe(player);
 | 
				
			||||||
            clog.log(`GUILD : ${instance.guildId} - Lecture de la musique (Media): ${song.title} - id : ${song.id}`) 
 | 
					            clog.log(`GUILD : ${instance.guildId} - Lecture de la musique (Media): ${song.title} - id : ${song.id}`) 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										31
									
								
								backend/src/player/Method/Soundcloud.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								backend/src/player/Method/Soundcloud.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					const {createAudioResource, VoiceConnectionStatus, createAudioPlayer, StreamType} = require('@discordjs/voice');
 | 
				
			||||||
 | 
					const {LogType} = require('loguix')
 | 
				
			||||||
 | 
					const clog = new LogType("Soundcloud")
 | 
				
			||||||
 | 
					const plog = require("loguix").getInstance("Player")
 | 
				
			||||||
 | 
					const {Soundcloud} = require('soundcloud.ts')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const soundcloud = new Soundcloud();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function play(instance, song) {
 | 
				
			||||||
 | 
					       try {
 | 
				
			||||||
 | 
					          
 | 
				
			||||||
 | 
					            instance.player = createAudioPlayer()
 | 
				
			||||||
 | 
					            instance.generatePlayerEvents()
 | 
				
			||||||
 | 
					            const player = instance.player
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const stream = await soundcloud.util.streamTrack(song.url)
 | 
				
			||||||
 | 
					            var resource = await createAudioResource(stream)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            player.play(resource);
 | 
				
			||||||
 | 
					            instance.connection.subscribe(player);
 | 
				
			||||||
 | 
					            clog.log(`GUILD : ${instance.guildId} - Lecture de la musique (Soundcloud): ${song.title} - id : ${song.id}`) 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					       } catch(e) {
 | 
				
			||||||
 | 
					            clog.error("Erreur lors de la lecture de la musique : " + song.title)
 | 
				
			||||||
 | 
					            clog.error(e)
 | 
				
			||||||
 | 
					       }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = {play}
 | 
				
			||||||
@@ -20,13 +20,13 @@ async function play(instance, song) {
 | 
				
			|||||||
          });
 | 
					          });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    // Add compressor to the audio resource
 | 
					                    // Add compressor to the audio resource
 | 
				
			||||||
          song.resource = createAudioResource(stream);
 | 
					          var resource = createAudioResource(stream);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          player.play(song.resource);
 | 
					          player.play(resource);
 | 
				
			||||||
          instance.connection.subscribe(player);
 | 
					          instance.connection.subscribe(player);
 | 
				
			||||||
          clog.log(`GUILD : ${instance.guildId} - Lecture de la musique (Media): ${song.title} - id : ${song.id}`) 
 | 
					          clog.log(`GUILD : ${instance.guildId} - Lecture de la musique (Youtube): ${song.title} - id : ${song.id}`) 
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
           } catch(e) {
 | 
					           } catch(e) {
 | 
				
			||||||
                clog.error("Erreur lors de la lecture de la musique : " + song.title)
 | 
					                clog.error("Erreur lors de la lecture de la musique : " + song.title)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,7 @@ const clog = new LogType("Signal")
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const media = require('./Method/Media');
 | 
					const media = require('./Method/Media');
 | 
				
			||||||
const youtube = require('./Method/Youtube');
 | 
					const youtube = require('./Method/Youtube');
 | 
				
			||||||
const Activity = require('../discord/Activity');
 | 
					const soundcloud = require('./Method/Soundcloud');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const AllPlayers = new Map()
 | 
					const AllPlayers = new Map()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -15,6 +15,7 @@ class Player {
 | 
				
			|||||||
    connection;
 | 
					    connection;
 | 
				
			||||||
    player;
 | 
					    player;
 | 
				
			||||||
    guildId;
 | 
					    guildId;
 | 
				
			||||||
 | 
					    channelId;
 | 
				
			||||||
    queue;
 | 
					    queue;
 | 
				
			||||||
    constructor(guildId) {
 | 
					    constructor(guildId) {
 | 
				
			||||||
        if(this.guildId === null) {
 | 
					        if(this.guildId === null) {
 | 
				
			||||||
@@ -45,6 +46,8 @@ class Player {
 | 
				
			|||||||
            selfMute: false
 | 
					            selfMute: false
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.channelId = channel.id 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.player = createAudioPlayer()
 | 
					        this.player = createAudioPlayer()
 | 
				
			||||||
        this.generatePlayerEvents()
 | 
					        this.generatePlayerEvents()
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@@ -62,6 +65,8 @@ class Player {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    generatePlayerEvents() {
 | 
					    generatePlayerEvents() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const Activity = require('../discord/Activity');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.player.on('error', error => {
 | 
					        this.player.on('error', error => {
 | 
				
			||||||
            plog.error(`GUILD : ${this.guildId} - Une erreur est survenue dans le player`);
 | 
					            plog.error(`GUILD : ${this.guildId} - Une erreur est survenue dans le player`);
 | 
				
			||||||
            plog.error(error);
 | 
					            plog.error(error);
 | 
				
			||||||
@@ -109,7 +114,9 @@ class Player {
 | 
				
			|||||||
       if(song.type == 'youtube') {
 | 
					       if(song.type == 'youtube') {
 | 
				
			||||||
            youtube.play(this, song)
 | 
					            youtube.play(this, song)
 | 
				
			||||||
       }
 | 
					       }
 | 
				
			||||||
 | 
					       if(song.type == "soundcloud") {
 | 
				
			||||||
 | 
					            soundcloud.play(this, song)
 | 
				
			||||||
 | 
					       }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
       // TODO: Créer une méthode pour les autres types de médias
 | 
					       // TODO: Créer une méthode pour les autres types de médias
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -151,6 +158,7 @@ class Player {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async leave() {
 | 
					    async leave() {
 | 
				
			||||||
 | 
					        const Activity = require('../discord/Activity');
 | 
				
			||||||
        if(this.checkConnection()) return
 | 
					        if(this.checkConnection()) return
 | 
				
			||||||
        if(this.queue.current != null) {
 | 
					        if(this.queue.current != null) {
 | 
				
			||||||
            this.queue.addPreviousSong(this.queue.current)
 | 
					            this.queue.addPreviousSong(this.queue.current)
 | 
				
			||||||
@@ -158,6 +166,9 @@ class Player {
 | 
				
			|||||||
        // Détruit la connection et le player et l'enlève de la liste des 
 | 
					        // Détruit la connection et le player et l'enlève de la liste des 
 | 
				
			||||||
        this.connection.destroy()
 | 
					        this.connection.destroy()
 | 
				
			||||||
        this.player.stop()
 | 
					        this.player.stop()
 | 
				
			||||||
 | 
					        this.player = null
 | 
				
			||||||
 | 
					        this.connection = null
 | 
				
			||||||
 | 
					        this.channelId = null
 | 
				
			||||||
        Activity.idleActivity()
 | 
					        Activity.idleActivity()
 | 
				
			||||||
        this.queue.destroy()
 | 
					        this.queue.destroy()
 | 
				
			||||||
        AllPlayers.delete(this.guildId)
 | 
					        AllPlayers.delete(this.guildId)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,8 +2,7 @@ const {LogType} = require('loguix')
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const clog = new LogType("Song")
 | 
					const clog = new LogType("Song")
 | 
				
			||||||
const MediaInformation = require('../media/MediaInformation')
 | 
					const MediaInformation = require('../media/MediaInformation')
 | 
				
			||||||
const YoutubeDuration = require('../utils/YoutubeDuration');
 | 
					const { getReadableDuration, getSecondsDuration } = require('../utils/TimeConverter');
 | 
				
			||||||
const { getReadableDuration } = require('../utils/TimeConverter');
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Song {
 | 
					class Song {
 | 
				
			||||||
    title = "Aucun titre";
 | 
					    title = "Aucun titre";
 | 
				
			||||||
@@ -15,7 +14,6 @@ class Song {
 | 
				
			|||||||
    duration;
 | 
					    duration;
 | 
				
			||||||
    readduration;
 | 
					    readduration;
 | 
				
			||||||
    type;
 | 
					    type;
 | 
				
			||||||
    resource;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(properties) {
 | 
					    constructor(properties) {
 | 
				
			||||||
        if(properties) {
 | 
					        if(properties) {
 | 
				
			||||||
@@ -50,20 +48,33 @@ class Song {
 | 
				
			|||||||
        
 | 
					        
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async processYoutubeVideo(video) {
 | 
					    async processYoutubeVideo(video, playlist) {
 | 
				
			||||||
        this.title = video.snippet.title
 | 
					        if(playlist) {
 | 
				
			||||||
        this.author = video.snippet.channelTitle
 | 
					        this.title = video.title
 | 
				
			||||||
        this.authorId = video.snippet.channelId
 | 
					        this.author = video.author.name
 | 
				
			||||||
        this.thumbnail = video.snippet.thumbnails.standard.url
 | 
					        this.authorId = video.author.channel_url
 | 
				
			||||||
        this.url = `https://www.youtube.com/watch?v=${video.id}`
 | 
					        this.thumbnail = video.thumbnail_url
 | 
				
			||||||
 | 
					        this.url = video.url
 | 
				
			||||||
        this.type = "youtube"
 | 
					        this.type = "youtube"
 | 
				
			||||||
        this.id = video.id
 | 
					        this.id = video.id
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.duration = await YoutubeDuration.getDurationVideo(video.id)
 | 
					        this.duration = video.milis_length / 1000
 | 
				
			||||||
        this.readduration = getReadableDuration(this.duration)
 | 
					        this.readduration = getReadableDuration(this.duration)
 | 
				
			||||||
 | 
					        } else { 
 | 
				
			||||||
 | 
					            this.title = video.name
 | 
				
			||||||
 | 
					            this.author = video.author.name
 | 
				
			||||||
 | 
					            this.authorId = video.author.url
 | 
				
			||||||
 | 
					            this.thumbnail = video.thumbnail
 | 
				
			||||||
 | 
					            this.url = video.url
 | 
				
			||||||
 | 
					            this.type = "youtube"
 | 
				
			||||||
 | 
					            this.id = video.id
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.duration = getSecondsDuration(video.duration)
 | 
				
			||||||
 | 
					            this.readduration = getReadableDuration(this.duration)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return this
 | 
					        return this
 | 
				
			||||||
    }
 | 
					    } 
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,10 +17,10 @@ function getQueryType(url) {
 | 
				
			|||||||
    if(Links.regex.spotify.song.test(url)) return QueryType.SPOTIFY_SONG
 | 
					    if(Links.regex.spotify.song.test(url)) return QueryType.SPOTIFY_SONG
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Check if it's a Soundcloud link
 | 
					    // Check if it's a Soundcloud link
 | 
				
			||||||
 
 | 
					 | 
				
			||||||
    if(Links.regex.soundcloud.track.test(url)) return QueryType.SOUNDCLOUD_TRACK
 | 
					 | 
				
			||||||
    if(Links.regex.soundcloud.playlist.test(url)) return QueryType.SOUNDCLOUD_PLAYLIST
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    if(Links.regex.soundcloud.playlist.test(url)) return QueryType.SOUNDCLOUD_PLAYLIST
 | 
				
			||||||
 | 
					    if(Links.regex.soundcloud.track.test(url)) return QueryType.SOUNDCLOUD_TRACK
 | 
				
			||||||
 | 
					   
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return QueryType.YOUTUBE_SEARCH
 | 
					    return QueryType.YOUTUBE_SEARCH
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,4 +29,18 @@ function getReadableDuration(duration) {
 | 
				
			|||||||
    return max
 | 
					    return max
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {getReadableDuration}
 | 
					function getSecondsDuration(duration) {
 | 
				
			||||||
 | 
					   // Duration is in format hh:mm:ss and can be just m:ss or mm:ss
 | 
				
			||||||
 | 
					    var durationArray = duration.split(":");
 | 
				
			||||||
 | 
					    var seconds = 0;
 | 
				
			||||||
 | 
					    if(durationArray.length == 3) {
 | 
				
			||||||
 | 
					        seconds = parseInt(durationArray[0]) * 3600 + parseInt(durationArray[1]) * 60 + parseInt(durationArray[2]);
 | 
				
			||||||
 | 
					    } else if(durationArray.length == 2) {
 | 
				
			||||||
 | 
					        seconds = parseInt(durationArray[0]) * 60 + parseInt(durationArray[1]);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        seconds = parseInt(durationArray[0]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return seconds;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = {getReadableDuration, getSecondsDuration}
 | 
				
			||||||
@@ -1,45 +0,0 @@
 | 
				
			|||||||
const config = require('../utils/Database/Configuration');
 | 
					 | 
				
			||||||
const YOUTUBE_API_KEY = config.getYoutubeApiKey()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
async function getDurationVideo(videoId) {
 | 
					 | 
				
			||||||
    const clog = require("loguix").getInstance("YoutubeInformation");
 | 
					 | 
				
			||||||
    // Check videoId if valid 
 | 
					 | 
				
			||||||
    if(videoId === null && typeof videoId !== 'string') {
 | 
					 | 
				
			||||||
        clog.error("Impossible de récupérer la durée de la vidéo YouTube, car l'identifiant est nul ou n'est pas une chaîne de caractères");
 | 
					 | 
				
			||||||
        return null;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Fetch video information
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
        const response = await fetch(`https://www.googleapis.com/youtube/v3/videos?part=contentDetails&id=${videoId}&key=${YOUTUBE_API_KEY}`);
 | 
					 | 
				
			||||||
        const data = await response.json();
 | 
					 | 
				
			||||||
        const video = data.items[0];
 | 
					 | 
				
			||||||
        if(video) {
 | 
					 | 
				
			||||||
     
 | 
					 | 
				
			||||||
            if(video.contentDetails.duration == "P0D") return "LIVE";
 | 
					 | 
				
			||||||
            const duration = video.contentDetails.duration;
 | 
					 | 
				
			||||||
            //Convert ISO 8601 duration to seconds
 | 
					 | 
				
			||||||
            return parseDuration(duration);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            clog.error("Impossible de récupérer la durée de la vidéo YouTube à partir de l'identifiant");
 | 
					 | 
				
			||||||
            return null;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    } catch (error) {
 | 
					 | 
				
			||||||
        clog.error('Erreur lors de la recherche de la durée de la vidéo YouTube:', error);
 | 
					 | 
				
			||||||
        return null;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function parseDuration(duration) {
 | 
					 | 
				
			||||||
    const match = duration.match(/PT(\d+H)?(\d+M)?(\d+S)?/);
 | 
					 | 
				
			||||||
    const hours = parseInt(match[1]) || 0;
 | 
					 | 
				
			||||||
    const minutes = parseInt(match[2]) || 0;
 | 
					 | 
				
			||||||
    const seconds = parseInt(match[3]) || 0;
 | 
					 | 
				
			||||||
    return hours * 3600 + minutes * 60 + seconds;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = {getDurationVideo}
 | 
					 | 
				
			||||||
		Reference in New Issue
	
	Block a user