194 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			194 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package cli
 | |
| 
 | |
| import (
 | |
| 	"bufio"
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"log"
 | |
| 	"os"
 | |
| 	"regexp"
 | |
| 	"strconv"
 | |
| 	"strings"
 | |
| 
 | |
| 	"gitea.elara.ws/Hazel/music-kraken/internal/common"
 | |
| 	"gitea.elara.ws/Hazel/music-kraken/internal/common/color"
 | |
| 	"gitea.elara.ws/Hazel/music-kraken/internal/data"
 | |
| 	"gitea.elara.ws/Hazel/music-kraken/internal/plugin"
 | |
| )
 | |
| 
 | |
| func printResults(musicObjects []data.MusicObject) {
 | |
| 	if len(musicObjects) <= 0 {
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	results := make([]string, len(musicObjects))
 | |
| 
 | |
| 	for i, m := range musicObjects {
 | |
| 		results[i] = common.ZeroPad(i, 2) + ": "
 | |
| 
 | |
| 		if a, ok := m.(data.Artist); ok {
 | |
| 			results[i] += "#a " + a.Name
 | |
| 		} else if a, ok := m.(data.Album); ok {
 | |
| 			results[i] += "#r " + a.Name
 | |
| 
 | |
| 			for _, artist := range a.Artists {
 | |
| 				results[i] += " - " + artist.Name
 | |
| 			}
 | |
| 		} else if a, ok := m.(data.Song); ok {
 | |
| 			results[i] += "#s " + a.Name
 | |
| 
 | |
| 			if a.Album.Name != "" {
 | |
| 				results[i] += " - " + a.Album.Name
 | |
| 			}
 | |
| 
 | |
| 			for _, artist := range a.Artists {
 | |
| 				results[i] += " - " + artist.Name
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		sources := m.GetSources()
 | |
| 		if len(sources) > 0 {
 | |
| 			for _, source := range sources {
 | |
| 				results[i] += "\n\t- " + source.SourceType.Name + " " + string(source.ObjectType) + " " + source.Url
 | |
| 				if source.AudioUrl != "" {
 | |
| 					results[i] += "\n\t  " + source.AudioUrl
 | |
| 				}
 | |
| 			}
 | |
| 		} else {
 | |
| 			results[i] = color.StrikeThrough + results[i] + color.Reset
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	fmt.Println()
 | |
| 	fmt.Println(strings.Join(results, "\n"))
 | |
| 	fmt.Println()
 | |
| }
 | |
| 
 | |
| type musicObjectStore [][]data.MusicObject
 | |
| 
 | |
| func (s musicObjectStore) currentMusicObjects() ([]data.MusicObject, error) {
 | |
| 	if len(s) <= 0 {
 | |
| 		return []data.MusicObject{}, errors.New("no items to select from")
 | |
| 	}
 | |
| 
 | |
| 	return (s)[len(s)-1], nil
 | |
| }
 | |
| 
 | |
| var indexSelectionPattern = regexp.MustCompile(`^[\d ,]+$`)
 | |
| 
 | |
| func interpretCommand(command string, store musicObjectStore) (musicObjectStore, []error) {
 | |
| 	// going back in history
 | |
| 	if command == ".." {
 | |
| 		if len(store) <= 1 {
 | |
| 			return store, []error{errors.New("can't go back")}
 | |
| 		}
 | |
| 
 | |
| 		return store[:len(store)-1], []error{}
 | |
| 	}
 | |
| 
 | |
| 	forceDownload := false
 | |
| 	if strings.HasPrefix(command, "d:") {
 | |
| 		command, _ = strings.CutPrefix(command, "d:")
 | |
| 		command = strings.TrimSpace(command)
 | |
| 
 | |
| 		forceDownload = true
 | |
| 	}
 | |
| 
 | |
| 	// fetch special music object
 | |
| 	if indexSelectionPattern.MatchString(command) {
 | |
| 		currentMusicObjects, err := store.currentMusicObjects()
 | |
| 		if err != nil {
 | |
| 			return store, []error{err}
 | |
| 		}
 | |
| 
 | |
| 		var fetched data.MusicObject
 | |
| 
 | |
| 		for _, stringIndex := range strings.Split(command, ",") {
 | |
| 			index, _ := strconv.Atoi(strings.TrimSpace(stringIndex))
 | |
| 
 | |
| 			if index >= len(currentMusicObjects) || index < 0 {
 | |
| 				return store, []error{errors.New(command + " is out of bounds [0 <= " + strconv.Itoa(index) + " <= " + strconv.Itoa(len(currentMusicObjects)-1) + "]")}
 | |
| 			}
 | |
| 
 | |
| 			current := currentMusicObjects[index]
 | |
| 
 | |
| 			newFetched, err := plugin.Fetch(current)
 | |
| 			if err != nil {
 | |
| 				return store, []error{err}
 | |
| 			}
 | |
| 
 | |
| 			if fetched == nil {
 | |
| 				fetched = newFetched
 | |
| 			} else {
 | |
| 				fetched = fetched.Merge(newFetched)
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		if forceDownload {
 | |
| 			return store, plugin.Download(fetched)
 | |
| 		} else {
 | |
| 			return append(store, fetched.Related()), []error{}
 | |
| 		}
 | |
| 	} else if forceDownload {
 | |
| 		return store, []error{errors.New("can only download indices not " + command)}
 | |
| 	}
 | |
| 
 | |
| 	// search in every other case
 | |
| 	currentMusicObjects, err := plugin.Search(command, plugin.SearchConfig{IgnoreErrors: false})
 | |
| 	if err != nil {
 | |
| 		fmt.Println(err)
 | |
| 		fmt.Println()
 | |
| 	}
 | |
| 
 | |
| 	return append(store, currentMusicObjects), []error{}
 | |
| }
 | |
| 
 | |
| func Shell(commandsList ...[]string) {
 | |
| 	plugin.RegisterPlugin(&plugin.Musify{})
 | |
| 
 | |
| 	commands := []string{}
 | |
| 	if len(commandsList) > 0 {
 | |
| 		commands = commandsList[0]
 | |
| 	}
 | |
| 
 | |
| 	fmt.Println("== MusicKraken Shell ==")
 | |
| 	fmt.Println()
 | |
| 
 | |
| 	store := musicObjectStore{}
 | |
| 	var err error = nil
 | |
| 
 | |
| 	for {
 | |
| 		var command string
 | |
| 
 | |
| 		if len(commands) <= 0 {
 | |
| 			fmt.Print("> ")
 | |
| 
 | |
| 			reader := bufio.NewReader(os.Stdin)
 | |
| 			command, err = reader.ReadString('\n')
 | |
| 			if err != nil {
 | |
| 				log.Fatal(err)
 | |
| 			}
 | |
| 		} else {
 | |
| 			command = commands[0]
 | |
| 			commands = commands[1:]
 | |
| 
 | |
| 			fmt.Println("> " + command)
 | |
| 		}
 | |
| 
 | |
| 		var errList []error
 | |
| 		store, errList = interpretCommand(strings.TrimSpace(command), store)
 | |
| 		if len(errList) > 0 {
 | |
| 			fmt.Println()
 | |
| 			for _, err := range errList {
 | |
| 				fmt.Println(color.Yellow + err.Error() + color.Reset)
 | |
| 			}
 | |
| 			fmt.Println()
 | |
| 		}
 | |
| 
 | |
| 		currentMusicObject, err := store.currentMusicObjects()
 | |
| 		if err == nil {
 | |
| 			printResults(currentMusicObject)
 | |
| 		}
 | |
| 	}
 | |
| }
 |