173 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			173 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package plugin
 | |
| 
 | |
| import (
 | |
| 	"errors"
 | |
| 	"regexp"
 | |
| 
 | |
| 	"gitea.elara.ws/Hazel/music-kraken/internal/common"
 | |
| 	"gitea.elara.ws/Hazel/music-kraken/internal/data"
 | |
| )
 | |
| 
 | |
| type Plugin interface {
 | |
| 	Name() string
 | |
| 	Regex() *regexp.Regexp
 | |
| 	RegexArtist() *regexp.Regexp
 | |
| 	RegexAlbum() *regexp.Regexp
 | |
| 	RegexSong() *regexp.Regexp
 | |
| 
 | |
| 	Init()
 | |
| 
 | |
| 	Search(query common.Query) ([]data.MusicObject, error)
 | |
| 
 | |
| 	FetchArtist(source data.Source) (data.Artist, error)
 | |
| 	FetchAlbum(source data.Source) (data.Album, error)
 | |
| 	FetchSong(source data.Source) (data.Song, error)
 | |
| }
 | |
| 
 | |
| var namePlugins = map[string]Plugin{}
 | |
| var NameSourceType = map[string]data.SourceType{}
 | |
| 
 | |
| func RegisterPlugin(plugin Plugin) error {
 | |
| 	name := plugin.Name()
 | |
| 
 | |
| 	if _, ok := namePlugins[name]; ok {
 | |
| 		return errors.New("plugin " + name + " is already registered")
 | |
| 	}
 | |
| 
 | |
| 	NameSourceType[name] = data.SourceType{
 | |
| 		Name:        name,
 | |
| 		Regex:       plugin.Regex(),
 | |
| 		RegexArtist: plugin.RegexArtist(),
 | |
| 		RegexAlbum:  plugin.RegexAlbum(),
 | |
| 		RegexSong:   plugin.RegexSong(),
 | |
| 	}
 | |
| 
 | |
| 	namePlugins[name] = plugin
 | |
| 
 | |
| 	plugin.Init()
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func compileSourceType(source data.Source) (data.Source, error) {
 | |
| 	if source.SourceType != nil {
 | |
| 		if _, ok := namePlugins[source.SourceType.Name]; !ok {
 | |
| 			return source, errors.New("source type " + source.SourceType.Name + " not found")
 | |
| 		}
 | |
| 		return source, nil
 | |
| 	}
 | |
| 
 | |
| 	for _, st := range NameSourceType {
 | |
| 		if m := st.Regex.FindString(source.Url); m != "" {
 | |
| 			source.Url = m
 | |
| 			source.SourceType = &st
 | |
| 			return source, nil
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return source, errors.New("couldn't find source type for " + source.Url)
 | |
| }
 | |
| 
 | |
| func compileSource(source data.Source) (data.Source, error) {
 | |
| 	source, err := compileSourceType(source)
 | |
| 	if err != nil {
 | |
| 		return source, err
 | |
| 	}
 | |
| 
 | |
| 	// find what object this source corresponds to
 | |
| 	if source.ObjectType != "" {
 | |
| 		return source, nil
 | |
| 	}
 | |
| 
 | |
| 	sourceType := source.SourceType
 | |
| 
 | |
| 	if sourceType.RegexSong.MatchString(source.Url) {
 | |
| 		source.ObjectType = data.SongSource
 | |
| 		return source, nil
 | |
| 	}
 | |
| 
 | |
| 	if sourceType.RegexAlbum.MatchString(source.Url) {
 | |
| 		source.ObjectType = data.AlbumSource
 | |
| 		return source, nil
 | |
| 	}
 | |
| 
 | |
| 	if sourceType.RegexArtist.MatchString(source.Url) {
 | |
| 		source.ObjectType = data.ArtistSource
 | |
| 		return source, nil
 | |
| 	}
 | |
| 
 | |
| 	return source, errors.New("couldn't find corresponding object source on " + sourceType.Name + " for " + source.Url)
 | |
| }
 | |
| 
 | |
| func Fetch(source data.Source) (data.MusicObject, error) {
 | |
| 	// the fetch function without the post processing of the music objects
 | |
| 	source, err := compileSource(source)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	plugin, ok := namePlugins[source.SourceType.Name]
 | |
| 	if !ok {
 | |
| 		return nil, errors.New("didn't find plugin of the name " + source.SourceType.Name)
 | |
| 	}
 | |
| 
 | |
| 	if source.ObjectType == data.SongSource {
 | |
| 		song, err := plugin.FetchSong(source)
 | |
| 
 | |
| 		if err != nil {
 | |
| 			return song, err
 | |
| 		}
 | |
| 		song.Sources = append(song.Sources, source)
 | |
| 		song = song.Compile().(data.Song)
 | |
| 		return song, nil
 | |
| 	}
 | |
| 
 | |
| 	if source.ObjectType == data.AlbumSource {
 | |
| 		album, err := plugin.FetchAlbum(source)
 | |
| 
 | |
| 		if err != nil {
 | |
| 			return album, err
 | |
| 		}
 | |
| 		album.Sources = append(album.Sources, source)
 | |
| 		album = album.Compile().(data.Album)
 | |
| 		return album, nil
 | |
| 	}
 | |
| 
 | |
| 	if source.ObjectType == data.ArtistSource {
 | |
| 		artist, err := plugin.FetchArtist(source)
 | |
| 
 | |
| 		if err != nil {
 | |
| 			return artist, err
 | |
| 		}
 | |
| 		artist.Sources = append(artist.Sources, source)
 | |
| 		artist = artist.Compile().(data.Artist)
 | |
| 		return artist, nil
 | |
| 	}
 | |
| 
 | |
| 	return nil, nil
 | |
| }
 | |
| 
 | |
| type SearchConfig struct {
 | |
| 	IgnoreErrors bool
 | |
| }
 | |
| 
 | |
| func Search(search string, config SearchConfig) ([]data.MusicObject, error) {
 | |
| 	query, err := common.NewQuery(search)
 | |
| 
 | |
| 	res := []data.MusicObject{}
 | |
| 	if err != nil && !config.IgnoreErrors {
 | |
| 		return res, err
 | |
| 	}
 | |
| 
 | |
| 	for _, plugin := range namePlugins {
 | |
| 		s, err := plugin.Search(query)
 | |
| 		res = append(res, s...)
 | |
| 
 | |
| 		if err != nil && !config.IgnoreErrors {
 | |
| 			return res, err
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return res, nil
 | |
| }
 |