diff --git a/internal/version/version.go b/internal/version/version.go index 44680aa..9c5b42d 100644 --- a/internal/version/version.go +++ b/internal/version/version.go @@ -5,5 +5,5 @@ var ( GoVersion string AppName = "Melodix" AppFullName = "Melodix Player" - AppDescription = "Discord music bot that allows to manage and play music on one or multiple Discord servers" + AppDescription = "Discord music bot that allows to manage and play music on multiple Discord servers" ) diff --git a/mod-music/discord/discord.go b/mod-music/discord/discord.go index 846a625..e8c1b99 100644 --- a/mod-music/discord/discord.go +++ b/mod-music/discord/discord.go @@ -31,8 +31,6 @@ func NewDiscord(session *discordgo.Session) *Discord { } return &Discord{ - // Player: player.NewPlayer(guildID), - //Players: make(map[string]player.IPlayer), Session: session, IsInstanceActive: true, prefix: config.DiscordCommandPrefix, @@ -109,7 +107,7 @@ func (d *Discord) Commands(s *discordgo.Session, m *discordgo.MessageCreate) { case "cached": d.handleCacheListCommand(s, m) case "uploaded": - d.handleUploadListCommand(s, m) + d.handleUploadListCommand(s, m, parameter) } } diff --git a/mod-music/discord/history.go b/mod-music/discord/history.go index 6b600ef..439a3ae 100644 --- a/mod-music/discord/history.go +++ b/mod-music/discord/history.go @@ -8,6 +8,7 @@ import ( "github.com/bwmarrin/discordgo" "github.com/gookit/slog" "github.com/keshon/melodix-player/mod-music/history" + "github.com/keshon/melodix-player/mod-music/player" "github.com/keshon/melodix-player/mod-music/utils" ) @@ -46,7 +47,13 @@ func (d *Discord) handleHistoryCommand(s *discordgo.Session, m *discordgo.Messag } duration := utils.FormatDuration(elem.History.Duration) - fieldContent := fmt.Sprintf("```id %d```\t```x%d```\t```%v```\t```%v```", elem.History.TrackID, elem.History.PlayCount, duration, strings.ToLower(elem.Track.Source)) + var sourceLabels string + if elem.Track.Source == player.SourceLocalFile.String() && utils.IsYouTubeURL(elem.Track.URL) { + sourceLabels = "`youtube cached`" + } else { + sourceLabels = "`" + strings.ToLower(elem.Track.Source) + "`" + } + fieldContent := fmt.Sprintf("```id %d```\t```x%d```\t```%v```\t```%v```", elem.History.TrackID, elem.History.PlayCount, duration, sourceLabels) if remainingSpace := maxLimit - len(embedMsg.Fields) - len(fieldContent) - len(elem.Track.Title) - len(elem.Track.URL); remainingSpace < 0 { break diff --git a/mod-music/discord/uploaded.go b/mod-music/discord/uploaded.go index 7a0b724..7bd8262 100644 --- a/mod-music/discord/uploaded.go +++ b/mod-music/discord/uploaded.go @@ -1,7 +1,114 @@ package discord -import "github.com/bwmarrin/discordgo" +import ( + "fmt" + "os" + "path/filepath" + "strings" -func (d *Discord) handleUploadListCommand(s *discordgo.Session, m *discordgo.MessageCreate) { - _, _ = s.ChannelMessageSend(m.ChannelID, "Not implemented yet!") + "github.com/bwmarrin/discordgo" + "github.com/gookit/slog" + "github.com/keshon/melodix-player/internal/db" + "github.com/keshon/melodix-player/mod-music/player" +) + +func (d *Discord) handleUploadListCommand(s *discordgo.Session, m *discordgo.MessageCreate, param string) { + + if param == "" { + // Scan uploaded folder for video files + files, err := os.ReadDir(uploadsFolder) + if err != nil { + slog.Error("Error reading uploaded folder:", err) + } + + // Send to Discord chat list of found files + var fileList strings.Builder + fileList.WriteString("Uploaded files:\n") + for _, file := range files { + // Check if file is a video file + if filepath.Ext(file.Name()) == ".mp4" || filepath.Ext(file.Name()) == ".mkv" || filepath.Ext(file.Name()) == ".webm" { + fileList.WriteString(fmt.Sprintf("- %s\n", file.Name())) + } + } + + s.ChannelMessageSend(m.ChannelID, fileList.String()) + + return + } + + if param == "extract" { + // Scan uploaded folder for video files + files, err := os.ReadDir(uploadsFolder) + if err != nil { + slog.Error("Error reading uploaded folder:", err) + } + + // Iterate each file + for _, file := range files { + + // Check if file is a video file + if filepath.Ext(file.Name()) == ".mp4" || filepath.Ext(file.Name()) == ".mkv" || filepath.Ext(file.Name()) == ".webm" || filepath.Ext(file.Name()) == ".flv" { + + // Check if cache folder for guild exists, create if not + cacheGuildFolder := filepath.Join(cacheFolder, m.GuildID) + CreatePathIfNotExists(cacheGuildFolder) + + // Extract audio from video + videoFilePath := filepath.Join(uploadsFolder, file.Name()) + audioFilename := sanitizeFilename(file.Name()) + ".aac" + audioFilePath := filepath.Join(cacheGuildFolder, audioFilename) + err = ffpmegExtractAudioFromVideo(videoFilePath, audioFilePath) + if err != nil { + slog.Error("Error extracting audio:", err) + continue + } + + // Remove the temporary video file + err = os.Remove(videoFilePath) + if err != nil { + slog.Error("Error removing temporary video file:", err) + } + + // Check if cached file exists in database + song, err := db.GetTrackByFilepath(audioFilename) + if err == nil { + song.Filepath = audioFilePath + err := db.UpdateTrack(song) + if err != nil { + slog.Error("Error updating track in database:", err) + continue + } + } else { + newTrack := &db.Track{ + Title: audioFilename, + Source: player.SourceLocalFile.String(), + Filepath: audioFilePath, + } + err = db.CreateTrack(newTrack) + if err != nil { + slog.Error("Error creating track in database:", err) + continue + } + } + + // Get the audio file size and format + audioFileInfo, err := os.Stat(audioFilePath) + if err != nil { + slog.Error("Error getting audio file information:", err) + return + } + + audioFileSize := humanReadableSize(audioFileInfo.Size()) + + // Send message with audio extraction information + audioMessage := fmt.Sprintf("Audio extracted and saved!\nFile Size: %s\nFile Format: %s", audioFileSize, filepath.Ext(audioFilePath)) + s.ChannelMessageSend(m.ChannelID, audioMessage) + + } + } + + return + } else { + s.ChannelMessageSend(m.ChannelID, "Invalid parameter. Usage: /uploaded extract") + } }