Version 0.2.0 - Ajout de Player (Media)
This commit is contained in:
		
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -141,4 +141,6 @@ docs/_book
 | 
			
		||||
# TODO: where does this rule come from?
 | 
			
		||||
test/
 | 
			
		||||
 | 
			
		||||
data/
 | 
			
		||||
data/
 | 
			
		||||
 | 
			
		||||
__DEBUG.js
 | 
			
		||||
@@ -13,10 +13,10 @@ function setMusicActivity(songName, artistName, imageUrl) {
 | 
			
		||||
    const client = bot.getClient()
 | 
			
		||||
    client.user.setActivity(`${songName} - ${artistName}`,{
 | 
			
		||||
            type: ActivityType.Listening,
 | 
			
		||||
            /*assets: {
 | 
			
		||||
            assets: {
 | 
			
		||||
                largeImage: imageUrl,
 | 
			
		||||
                largeText: songName
 | 
			
		||||
            }*/
 | 
			
		||||
            }
 | 
			
		||||
    });
 | 
			
		||||
    dlog.log(`Activité mise à jour : ${songName} - ${artistName}`)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@ function getClient() {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function init() {
 | 
			
		||||
    
 | 
			
		||||
        
 | 
			
		||||
    client.once('ready', () => {
 | 
			
		||||
        dlog.log("Connexion au Bot Discord réussi ! Connecté en tant que : " + client.user.tag)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										28
									
								
								backend/src/discord/Commands/Leave.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								backend/src/discord/Commands/Leave.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
const {Command} = require("../Command")
 | 
			
		||||
const {Embed, EmbedError} = require("../Embed")
 | 
			
		||||
const {Player, AllPlayers} = require("../../player/Player")
 | 
			
		||||
 | 
			
		||||
const command = new Command("leave", "Quitter le salon vocal", (client, interaction) => {
 | 
			
		||||
 | 
			
		||||
    if(!interaction.member.voice.channel) return new EmbedError("Vous devez rejoindre un salon vocal pour arrêter le bot !").send(interaction)
 | 
			
		||||
    const channel = interaction.member.voice.channel
 | 
			
		||||
    var embed = new Embed()
 | 
			
		||||
    if(AllPlayers.has(channel.guildId)) {
 | 
			
		||||
        const player = AllPlayers.get(channel.guildId)
 | 
			
		||||
        player.leave()
 | 
			
		||||
 | 
			
		||||
       
 | 
			
		||||
        embed.setColor(200, 20, 20)
 | 
			
		||||
        embed.setTitle('**Déconnexion**')
 | 
			
		||||
        embed.setDescription('Déconnexion du salon vocal')
 | 
			
		||||
        embed.setThumbnail("https://www.iconsdb.com/icons/download/white/phone-51-64.png")
 | 
			
		||||
     
 | 
			
		||||
    } else {
 | 
			
		||||
 | 
			
		||||
        embed = new EmbedError("Le bot n'est pas connecté à ce salon vocal")
 | 
			
		||||
    }
 | 
			
		||||
    embed.send(interaction)
 | 
			
		||||
   
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
module.exports = {command}
 | 
			
		||||
@@ -5,7 +5,7 @@ const { Song } = require('../../player/Song');
 | 
			
		||||
 | 
			
		||||
const command = new Command("media", "Lire un média MP3/WAV dans un salon vocal", async (client, interaction) => {
 | 
			
		||||
 | 
			
		||||
    if(!interaction.member.voice.channel) return interaction.reply({content:"Vous devez rejoindre un salon vocal pour lire un(e) titre / playlist !", ephemeral: true})
 | 
			
		||||
    if(!interaction.member.voice.channel) return new EmbedError("Vous devez rejoindre un salon vocal pour jouer un média !").send(interaction, true)
 | 
			
		||||
 | 
			
		||||
    const media = interaction.options.get("media")
 | 
			
		||||
    const now = interaction.options.getBoolean("now") || false
 | 
			
		||||
@@ -34,9 +34,9 @@ const command = new Command("media", "Lire un média MP3/WAV dans un salon vocal
 | 
			
		||||
    }
 | 
			
		||||
        
 | 
			
		||||
    embed.setDescription('**Titre : **' + song.title)
 | 
			
		||||
    embed.addField('**Durée : **'+ song.readduration, "")
 | 
			
		||||
    embed.addField("**Artiste : **" + song.author, "")
 | 
			
		||||
    embed.addField('**Demandé par **' + interaction.member.user.username,"")
 | 
			
		||||
    embed.addField('**Durée : **', song.readduration)
 | 
			
		||||
    embed.addField("**Artiste : **",song.author)
 | 
			
		||||
    embed.addField('**Demandé par **' + interaction.member.user.username, "")
 | 
			
		||||
    embed.setThumbnail(song.thumbnail)
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
 
 | 
			
		||||
@@ -2,22 +2,42 @@ const {Command} = require("../Command")
 | 
			
		||||
const {Embed, EmbedError} = require("../Embed")
 | 
			
		||||
const { Player } = require("../../player/Player")
 | 
			
		||||
 | 
			
		||||
const command = new Command("pause", "Mettre en pause la musique en cours", (client, interaction) => {
 | 
			
		||||
const command = new Command("pause", "Mettre en pause / Reprendre la musique en cours", (client, interaction) => {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    if(!interaction.member.voice.channel) return new EmbedError("Vous devez rejoindre un salon vocal pour mettre en pause la musique !").send(interaction)
 | 
			
		||||
 | 
			
		||||
    const channel = interaction.member.voice.channel
 | 
			
		||||
    const player = new Player(channel.guildId)
 | 
			
		||||
    player.pause()
 | 
			
		||||
    const result = player.pause()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    var embed = new Embed()
 | 
			
		||||
    embed.setColor(0x03ff2d)
 | 
			
		||||
 | 
			
		||||
    result.then((pause) => {
 | 
			
		||||
 | 
			
		||||
        if(pause == "no_music") {
 | 
			
		||||
            embed = new EmbedError("Il n'y a pas de musique en cours de lecture")
 | 
			
		||||
       
 | 
			
		||||
        } else if(pause) {
 | 
			
		||||
            embed.setTitle('Musique en pause')
 | 
			
		||||
            embed.setDescription("La musique a été mise en pause")
 | 
			
		||||
            embed.setThumbnail("https://www.iconsdb.com/icons/download/white/pause-64.png")
 | 
			
		||||
           
 | 
			
		||||
        
 | 
			
		||||
        } else {
 | 
			
		||||
            embed.setTitle('Musique reprise')
 | 
			
		||||
            embed.setDescription("La musique a été reprise")
 | 
			
		||||
            embed.setThumbnail("https://www.iconsdb.com/icons/download/white/play-64.png")
 | 
			
		||||
        }   
 | 
			
		||||
 | 
			
		||||
        embed.send(interaction)
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    // Réponse en embed
 | 
			
		||||
 | 
			
		||||
    const embed = new Embed()
 | 
			
		||||
    embed.setColor(0x00ff66)
 | 
			
		||||
    embed.setTitle('Musique en pause')
 | 
			
		||||
    embed.setDescription("La musique a été mise en pause")
 | 
			
		||||
    embed.send(interaction)
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										52
									
								
								backend/src/discord/Commands/Previous.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								backend/src/discord/Commands/Previous.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
			
		||||
const {Command} = require("../Command")
 | 
			
		||||
const {Embed, EmbedError} = require("../Embed")
 | 
			
		||||
const { Player, AllPlayers } = require("../../player/Player")
 | 
			
		||||
 | 
			
		||||
const command = new Command("previous", "Passe à la musique précédente", (client, interaction) => {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    if(!interaction.member.voice.channel) return new EmbedError("Vous devez rejoindre un salon vocal pour passer à la musique suivante !").send(interaction)
 | 
			
		||||
 | 
			
		||||
    const channel = interaction.member.voice.channel
 | 
			
		||||
 | 
			
		||||
    if(AllPlayers.has(channel.guildId)) {
 | 
			
		||||
 | 
			
		||||
        const player = new Player(channel.guildId)
 | 
			
		||||
        const result = player.previous()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        var embed = new Embed()
 | 
			
		||||
        embed.setColor(0x15e6ed)
 | 
			
		||||
 | 
			
		||||
        result.then((song) => {
 | 
			
		||||
 | 
			
		||||
            if(song == "no_music") {
 | 
			
		||||
                embed = new EmbedError("Il n'y a pas de musique précédemment jouée")
 | 
			
		||||
        
 | 
			
		||||
            } else if(song) {
 | 
			
		||||
                
 | 
			
		||||
                // Result is a song
 | 
			
		||||
 | 
			
		||||
            
 | 
			
		||||
                
 | 
			
		||||
                embed.setTitle('**Musique précédente !**')
 | 
			
		||||
                embed.setDescription('**Titre : **' + song.title)
 | 
			
		||||
                embed.addField('**Durée : **'+ song.readduration, "")
 | 
			
		||||
                embed.addField("**Artiste : **" + song.author, "")
 | 
			
		||||
                embed.setThumbnail(song.thumbnail)
 | 
			
		||||
            
 | 
			
		||||
                
 | 
			
		||||
            }  
 | 
			
		||||
 | 
			
		||||
            embed.send(interaction)
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
    } else {
 | 
			
		||||
        return new EmbedError("Le bot n'est pas connecté").send(interaction)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
module.exports = {command}
 | 
			
		||||
							
								
								
									
										39
									
								
								backend/src/discord/Commands/Queue.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								backend/src/discord/Commands/Queue.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
const {Command} = require("../Command")
 | 
			
		||||
const {Embed, EmbedError} = require("../Embed")
 | 
			
		||||
const { Player, AllPlayers } = require("../../player/Player")
 | 
			
		||||
 | 
			
		||||
const command = new Command("liste", "Affiche la file d'attente", (client, interaction) => {
 | 
			
		||||
    
 | 
			
		||||
        const channel = interaction.member.voice.channel
 | 
			
		||||
 | 
			
		||||
        if(AllPlayers.has(channel.guildId)) {
 | 
			
		||||
 | 
			
		||||
        const player = new Player(channel.guildId)
 | 
			
		||||
        const queue = player.queue.getNext()
 | 
			
		||||
    
 | 
			
		||||
        var embed = new Embed()
 | 
			
		||||
        embed.setColor(0x15e6ed)
 | 
			
		||||
    
 | 
			
		||||
        if(queue.length == 0) {
 | 
			
		||||
            embed = new EmbedError("Il n'y a pas de musique en file d'attente")
 | 
			
		||||
        
 | 
			
		||||
        } else if(queue.length > 0) {
 | 
			
		||||
            
 | 
			
		||||
            // Result is a song
 | 
			
		||||
            embed.setColor(0x15e6ed)
 | 
			
		||||
            embed.setThumbnail("https://www.iconsdb.com/icons/download/white/list-2-64.png")
 | 
			
		||||
            embed.setTitle('**File d\'attente :**')
 | 
			
		||||
            queue.forEach((song, index) => {
 | 
			
		||||
                embed.addField(`**${index+1} - ${song.title}**`, `**Durée : **${song.readduration}\n**Artiste : **${song.author}`)
 | 
			
		||||
            })
 | 
			
		||||
            
 | 
			
		||||
        }  
 | 
			
		||||
    
 | 
			
		||||
        embed.send(interaction)
 | 
			
		||||
 | 
			
		||||
        } else {
 | 
			
		||||
            return new EmbedError("Le bot n'est pas connecté").send(interaction)
 | 
			
		||||
        }
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
module.exports = {command}
 | 
			
		||||
							
								
								
									
										49
									
								
								backend/src/discord/Commands/Skip.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								backend/src/discord/Commands/Skip.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
			
		||||
const {Command} = require("../Command")
 | 
			
		||||
const {Embed, EmbedError} = require("../Embed")
 | 
			
		||||
const { Player, AllPlayers } = require("../../player/Player")
 | 
			
		||||
 | 
			
		||||
const command = new Command("skip", "Passe à la musique suivante", (client, interaction) => {   
 | 
			
		||||
    
 | 
			
		||||
    if(!interaction.member.voice.channel) return new EmbedError("Vous devez rejoindre un salon vocal pour passer à la musique suivante !").send(interaction)
 | 
			
		||||
 | 
			
		||||
    const channel = interaction.member.voice.channel
 | 
			
		||||
 | 
			
		||||
    if(AllPlayers.has(channel.guildId)) {
 | 
			
		||||
 | 
			
		||||
        const player = new Player(channel.guildId)
 | 
			
		||||
        const result = player.skip()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        var embed = new Embed()
 | 
			
		||||
        embed.setColor(0x15e6ed)
 | 
			
		||||
        result.then((song) => {
 | 
			
		||||
 | 
			
		||||
            if(song == "no_music") {
 | 
			
		||||
                embed = new EmbedError("Il n'y a pas de musique en file d'attente")
 | 
			
		||||
        
 | 
			
		||||
            } else if(song) {
 | 
			
		||||
                
 | 
			
		||||
                // Result is a song
 | 
			
		||||
                embed.setColor(0x15e6ed)
 | 
			
		||||
                
 | 
			
		||||
                embed.setTitle('**Musique suivante !**')
 | 
			
		||||
                embed.setDescription('**Titre : **' + song.title)
 | 
			
		||||
                embed.addField('**Durée : **'+ song.readduration, "")
 | 
			
		||||
                embed.addField("**Artiste : **" + song.author, "")
 | 
			
		||||
                embed.setThumbnail(song.thumbnail)
 | 
			
		||||
            
 | 
			
		||||
                
 | 
			
		||||
            }  
 | 
			
		||||
 | 
			
		||||
            embed.send(interaction)
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
    } else {
 | 
			
		||||
        return new EmbedError("Le bot n'est pas connecté").send(interaction)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
module.exports = {command}
 | 
			
		||||
							
								
								
									
										34
									
								
								backend/src/discord/Commands/State.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								backend/src/discord/Commands/State.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
const {Command} = require("../Command")
 | 
			
		||||
const {Embed, EmbedError} = require("../Embed")
 | 
			
		||||
const {Player} = require("../../player/Player")
 | 
			
		||||
 | 
			
		||||
const command = new Command("state", "Affiche la musique en cours", (client, interaction) => {
 | 
			
		||||
    
 | 
			
		||||
        const channel = interaction.member.voice.channel
 | 
			
		||||
        const player = new Player(channel.guildId)
 | 
			
		||||
        const song = player.queue.getCurrent()
 | 
			
		||||
    
 | 
			
		||||
            var embed = new Embed()
 | 
			
		||||
            embed.setColor(0x15e6ed)
 | 
			
		||||
    
 | 
			
		||||
            if(!song) {
 | 
			
		||||
                embed = new EmbedError("Il n'y a pas de musique en cours de lecture")
 | 
			
		||||
        
 | 
			
		||||
            } else if(song) {
 | 
			
		||||
                
 | 
			
		||||
                // Result is a song
 | 
			
		||||
                embed.setColor(0x15e6ed)
 | 
			
		||||
                
 | 
			
		||||
                embed.setTitle('**Musique en cours :**')
 | 
			
		||||
                embed.setDescription('**Titre : **' + song.title)
 | 
			
		||||
                embed.addField('**Durée : **', song.readduration)
 | 
			
		||||
                embed.addField("**Artiste : **", song.author)
 | 
			
		||||
                embed.setThumbnail(song.thumbnail)
 | 
			
		||||
            
 | 
			
		||||
                
 | 
			
		||||
            }  
 | 
			
		||||
    
 | 
			
		||||
            embed.send(interaction)
 | 
			
		||||
})
 | 
			
		||||
 
 | 
			
		||||
module.exports = {command}
 | 
			
		||||
@@ -81,8 +81,12 @@ class Embed {
 | 
			
		||||
        return this.embed
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    send(interaction) {
 | 
			
		||||
        interaction.reply({embeds: [this.build()]})
 | 
			
		||||
    send(interaction, ephemeral) {
 | 
			
		||||
        if(ephemeral) {
 | 
			
		||||
            interaction.reply({embeds: [this.build()], ephemeral: true})
 | 
			
		||||
        } else {
 | 
			
		||||
            interaction.reply({embeds: [this.build()]})
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										32
									
								
								backend/src/media/MediaInformation.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								backend/src/media/MediaInformation.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {getMediaInformation}
 | 
			
		||||
@@ -3,6 +3,7 @@ const { __glob } = require('../utils/GlobalVars')
 | 
			
		||||
const PreviousDB = new Database("previous", __glob.PREVIOUSFILE, {}) 
 | 
			
		||||
const {LogType} = require("loguix")
 | 
			
		||||
const clog = new LogType("List")
 | 
			
		||||
const { Song } = require('./Song')
 | 
			
		||||
 | 
			
		||||
const AllLists = new Map()  // Map<guildId, List>
 | 
			
		||||
 | 
			
		||||
@@ -43,6 +44,9 @@ class List {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    nextSong() {
 | 
			
		||||
        if(this.current != null) {
 | 
			
		||||
            this.addPreviousSong(this.current)
 | 
			
		||||
        }
 | 
			
		||||
        var song = null;
 | 
			
		||||
        if(!this.shuffle) {
 | 
			
		||||
            song = this.next[0]
 | 
			
		||||
@@ -53,9 +57,11 @@ class List {
 | 
			
		||||
            this.next.splice(randomIndex, 1)
 | 
			
		||||
           
 | 
			
		||||
        }
 | 
			
		||||
        this.setCurrent(song)
 | 
			
		||||
        return song
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    clearNext() {
 | 
			
		||||
        this.next = new Array();
 | 
			
		||||
    }
 | 
			
		||||
@@ -64,6 +70,10 @@ class List {
 | 
			
		||||
        this.next.push(song)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    firstNext(song) {
 | 
			
		||||
        this.next.unshift(song)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    removeNextByIndex(index) {
 | 
			
		||||
        this.next.splice(index, 1)
 | 
			
		||||
    }
 | 
			
		||||
@@ -75,15 +85,33 @@ class List {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getPrevious() {
 | 
			
		||||
        return PreviousDB.data[this.guildId];
 | 
			
		||||
        const previousList = new Array()
 | 
			
		||||
 | 
			
		||||
        for(const song of PreviousDB.data[this.guildId]) {
 | 
			
		||||
            previousList.push(new Song(song))
 | 
			
		||||
        }
 | 
			
		||||
        return previousList;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getPreviousSong() {
 | 
			
		||||
        if(PreviousDB.data[this.guildId].length > 0) {
 | 
			
		||||
            return new Song(PreviousDB.data[this.guildId][0])
 | 
			
		||||
        } else {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    previousSong() {
 | 
			
		||||
        if(this.current != null) {
 | 
			
		||||
            this.firstNext(this.current)
 | 
			
		||||
        }
 | 
			
		||||
        if(PreviousDB.data[this.guildId].length > 0) {
 | 
			
		||||
            const song = PreviousDB.data[this.guildId][0]
 | 
			
		||||
            // Remove the song from the previous list
 | 
			
		||||
            PreviousDB.data[this.guildId].splice(0, 1)
 | 
			
		||||
            savePrevious()
 | 
			
		||||
            return song
 | 
			
		||||
            return new Song(song)
 | 
			
		||||
        } else {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
@@ -116,6 +144,8 @@ class List {
 | 
			
		||||
        this.clearNext();
 | 
			
		||||
        this.current = null
 | 
			
		||||
        this.shuffle = false;
 | 
			
		||||
        AllLists.delete(this.guildId)
 | 
			
		||||
       
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setShuffle(value) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,19 +1,28 @@
 | 
			
		||||
const {createAudioResource, VoiceConnectionStatus} = require('@discordjs/voice');
 | 
			
		||||
const {createAudioResource, VoiceConnectionStatus, createAudioPlayer} = require('@discordjs/voice');
 | 
			
		||||
const {LogType} = require('loguix')
 | 
			
		||||
const clog = new LogType("Media")
 | 
			
		||||
const plog = require("loguix").getInstance("Player")
 | 
			
		||||
 | 
			
		||||
async function play(instance, song) {
 | 
			
		||||
    //const resource = await song.getResource()
 | 
			
		||||
    //Test with a local file
 | 
			
		||||
    const resource = createAudioResource("C:\\Users\\picot\\Downloads\\Confrontation_Replique_Raphix.mp3")
 | 
			
		||||
    console.log(resource)
 | 
			
		||||
    // Wait until connection is ready
 | 
			
		||||
    instance.connection.once(VoiceConnectionStatus.Ready, async () => {
 | 
			
		||||
        instance.player.play(resource)
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    plog.log(`GUILD : ${instance.guildId} - Lecture de la musique : ${song.title}`)
 | 
			
		||||
 | 
			
		||||
       try {
 | 
			
		||||
          
 | 
			
		||||
            instance.player = createAudioPlayer()
 | 
			
		||||
            instance.generatePlayerEvents()
 | 
			
		||||
            const player = instance.player
 | 
			
		||||
            const resource = await song.getResource() // Remplace par ton fichier audio
 | 
			
		||||
 | 
			
		||||
            player.play(resource);
 | 
			
		||||
            instance.connection.subscribe(player);
 | 
			
		||||
            clog.log(`GUILD : ${instance.guildId} - Lecture de la musique (Media): ${song.title} - Filename : ${song.filename}`) 
 | 
			
		||||
 | 
			
		||||
       } catch(e) {
 | 
			
		||||
            clog.error("Erreur lors de la lecture de la musique : " + song.title)
 | 
			
		||||
            clog.error(e)
 | 
			
		||||
       }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {play}
 | 
			
		||||
@@ -6,6 +6,7 @@ const plog = new LogType("Player")
 | 
			
		||||
const clog = new LogType("Signal")
 | 
			
		||||
 | 
			
		||||
const media = require('./Method/Media');
 | 
			
		||||
const Activity = require('../discord/Activity');
 | 
			
		||||
 | 
			
		||||
const AllPlayers = new Map()
 | 
			
		||||
 | 
			
		||||
@@ -39,33 +40,48 @@ class Player {
 | 
			
		||||
            channelId: channel.id,
 | 
			
		||||
            guildId: channel.guild.id,
 | 
			
		||||
            adapterCreator: channel.guild.voiceAdapterCreator,
 | 
			
		||||
            selfDeaf: false,
 | 
			
		||||
            selfMute: false
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.player = createAudioPlayer()
 | 
			
		||||
 | 
			
		||||
        this.connection.subscribe(this.player)
 | 
			
		||||
 | 
			
		||||
        this.generatePlayerEvents()
 | 
			
		||||
    
 | 
			
		||||
        this.connection.on('stateChange', (oldState, newState) => {
 | 
			
		||||
            clog.log(`GUILD : ${this.guildId} - [STATE] OLD : "${oldState.status}" NEW : "${newState.status}"`);
 | 
			
		||||
 | 
			
		||||
            // Si la connection est fermée, on détruit le player
 | 
			
		||||
 | 
			
		||||
            if(newState.status === VoiceConnectionStatus.Disconnected) {
 | 
			
		||||
                this.leave()
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    generatePlayerEvents() {
 | 
			
		||||
 | 
			
		||||
        this.player.on('error', error => {
 | 
			
		||||
            plog.error(`GUILD : ${this.guildId} - Une erreur est survenue dans le player`);
 | 
			
		||||
            plog.error(error);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.player.on(AudioPlayerStatus.Idle, () => {
 | 
			
		||||
        
 | 
			
		||||
       this.player.on(AudioPlayerStatus.Idle, () => {
 | 
			
		||||
            Activity.idleActivity()
 | 
			
		||||
            this.queue.setCurrent(null)
 | 
			
		||||
            if(this.queue.next.length > 0) {
 | 
			
		||||
             //TODO : Play next song   
 | 
			
		||||
            }
 | 
			
		||||
                this.play(this.queue.nextSong())
 | 
			
		||||
            } 
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.player.on(AudioPlayerStatus.Playing, () => {
 | 
			
		||||
            plog.log(`GUILD : ${this.guildId} - Le player est en train de jouer le contenu suivant : ${this.queue.current.title}`);
 | 
			
		||||
            Activity.setMusicActivity(this.queue.current.title, this.queue.current.author, this.queue.current.thumbnail)
 | 
			
		||||
            
 | 
			
		||||
        });
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    checkConnection() {
 | 
			
		||||
        if(this.connection === null) {
 | 
			
		||||
            clog.error(`GUILD : ${this.guildId} - La connection n'est pas définie`)
 | 
			
		||||
@@ -78,43 +94,81 @@ class Player {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async play(song) {
 | 
			
		||||
        if(this.checkConnection()) return
 | 
			
		||||
        if(this.queue.current != null) {
 | 
			
		||||
            this.player.stop()
 | 
			
		||||
        }
 | 
			
		||||
        this.queue.setCurrent(song)
 | 
			
		||||
 | 
			
		||||
       if(song.type = "attachment") {
 | 
			
		||||
            media.play(this, song)
 | 
			
		||||
       }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async add(song) {
 | 
			
		||||
        if(this.player.state.status = AudioPlayerStatus.Idle && this.queue.current === null && this.queue.next.length === 0) {
 | 
			
		||||
        if(this.player.state.status == AudioPlayerStatus.Idle && this.queue.current === null && this.queue.next.length === 0) {
 | 
			
		||||
            this.play(song)
 | 
			
		||||
            return
 | 
			
		||||
        } 
 | 
			
		||||
 | 
			
		||||
        this.queue.addNextSong(song)
 | 
			
		||||
        plog.log(`GUILD : ${this.guildId} - La musique a été ajoutée à la liste de lecture : ${song.title}`)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async pause() {
 | 
			
		||||
        if(this.player.state.status = AudioPlayerStatus.Paused) {
 | 
			
		||||
        if(this.checkConnection()) return "no_music"
 | 
			
		||||
        if(this.player.state.status == AudioPlayerStatus.Paused) {
 | 
			
		||||
            this.player.unpause()
 | 
			
		||||
            plog.log(`GUILD : ${this.guildId} - La musique a été reprise`)
 | 
			
		||||
            return false
 | 
			
		||||
        } else {
 | 
			
		||||
            this.player.pause()
 | 
			
		||||
            plog.log(`GUILD : ${this.guildId} - La musique a été mise en pause`)
 | 
			
		||||
            return true
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async leave() {
 | 
			
		||||
        if(this.checkConnection()) return
 | 
			
		||||
        if(this.queue.current != null) {
 | 
			
		||||
            this.queue.addPreviousSong(this.queue.current)
 | 
			
		||||
        }
 | 
			
		||||
        // Détruit la connection et le player et l'enlève de la liste des 
 | 
			
		||||
        this.connection.destroy()
 | 
			
		||||
        this.player.stop()
 | 
			
		||||
        Activity.idleActivity()
 | 
			
		||||
        this.queue.destroy()
 | 
			
		||||
        AllPlayers.delete(this.guildId)
 | 
			
		||||
        clog.log("Connection détruite avec le guildId : " + this.guildId)
 | 
			
		||||
        plog.log("Player détruit avec le guildId : " + this.guildId)
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async skip() {
 | 
			
		||||
      
 | 
			
		||||
        if(this.checkConnection()) return "no_music"
 | 
			
		||||
        if(this.queue.next.length === 0) {
 | 
			
		||||
            return "no_music"
 | 
			
		||||
        }
 | 
			
		||||
        const songSkip = this.queue.nextSong()
 | 
			
		||||
        this.play(songSkip)
 | 
			
		||||
        return songSkip
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    async previous() {
 | 
			
		||||
       
 | 
			
		||||
        if(this.checkConnection()) return "no_music"
 | 
			
		||||
        if(this.queue.getPrevious().length === 0) {
 | 
			
		||||
            return "no_music"
 | 
			
		||||
        }
 | 
			
		||||
       
 | 
			
		||||
        const songPrevious = this.queue.previousSong()
 | 
			
		||||
        this.play(songPrevious)
 | 
			
		||||
        return songPrevious
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {Player}
 | 
			
		||||
module.exports = {Player, AllPlayers}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -1,29 +1,43 @@
 | 
			
		||||
const {LogType} = require('loguix')
 | 
			
		||||
const { createAudioResource, StreamType } = require('@discordjs/voice');
 | 
			
		||||
const ffprobe = require('ffprobe');
 | 
			
		||||
const ffprobeStatic = require('ffprobe-static');
 | 
			
		||||
const { getReadableDuration } = require('../utils/TimeConverter');
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const clog = new LogType("Song")
 | 
			
		||||
const MediaInformation = require('../media/MediaInformation')
 | 
			
		||||
 | 
			
		||||
class Song {
 | 
			
		||||
    title = "Aucun titre";
 | 
			
		||||
    filename = "Aucun fichier";
 | 
			
		||||
    author = "Auteur inconnu"
 | 
			
		||||
    url;
 | 
			
		||||
    thumbnail;
 | 
			
		||||
    thumbnail = "https://radomisol.fr/wp-content/uploads/2016/08/cropped-note-radomisol-musique.png" ;
 | 
			
		||||
    duration;
 | 
			
		||||
    readduration;
 | 
			
		||||
    type;
 | 
			
		||||
 | 
			
		||||
    constructor(properties) {
 | 
			
		||||
        if(properties) {
 | 
			
		||||
            this.title = properties.title ?? this.title
 | 
			
		||||
            this.filename = properties.filename ?? this.filename
 | 
			
		||||
            this.author = properties.author ?? this.author
 | 
			
		||||
            this.url = properties.url ?? this.url
 | 
			
		||||
            this.thumbnail = properties.thumbnail ?? this.thumbnail
 | 
			
		||||
            this.duration = properties.duration ?? this.duration
 | 
			
		||||
            this.readduration = properties.readduration ?? this.readduration
 | 
			
		||||
            this.type = properties.type ?? this.type
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async processMedia(media, provider) {
 | 
			
		||||
        if(provider) this.author = provider
 | 
			
		||||
        // Check if media is a file or a link
 | 
			
		||||
        if(media.attachment) {
 | 
			
		||||
            this.url = media.attachment.url
 | 
			
		||||
            this.filename = media.attachment.name
 | 
			
		||||
            this.type = "attachment"
 | 
			
		||||
        
 | 
			
		||||
            // In face, duration is null, get the metadata of the file to get the duration
 | 
			
		||||
            await getMediaInformation(this, media)
 | 
			
		||||
            await MediaInformation.getMediaInformation(this, media)
 | 
			
		||||
 | 
			
		||||
        } else {
 | 
			
		||||
            clog.error("Impossible de traiter le média")
 | 
			
		||||
@@ -47,31 +61,3 @@ class Song {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {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 : " + this.name)
 | 
			
		||||
        clog.error(err)
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user