Compare commits
	
		
			5 Commits
		
	
	
		
			4156c7dc6d
			...
			main
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 9174c1b23a | ||
|  | 154c6a31b9 | ||
|  | c8f9832f48 | ||
|  | 7bdfcf9776 | ||
|  | a5757c3079 | 
							
								
								
									
										7
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								Makefile
									
									
									
									
									
								
							| @@ -12,6 +12,9 @@ debug: | ||||
| 	$(GO) build -o $(EXE) -gcflags=all="-N -l" cmd/$(EXE)/*.go | ||||
| 	dlv exec ./dischord | ||||
|  | ||||
| fmt: | ||||
| 	find . -type f -name '*.go' -exec gofmt -w '{}' ';' | ||||
|  | ||||
| install: all | ||||
| 	mkdir -p $(DESTDIR)$(PREFIX)/bin | ||||
| 	cp -f $(EXE) $(DESTDIR)$(PREFIX)/bin | ||||
| @@ -48,9 +51,9 @@ uninstall: | ||||
| 	rm -f $(DESTDIR)$(CFGPREFIX)/systemd/system/$(EXE).service | ||||
|  | ||||
| test: | ||||
| 	$(GO) test -count=1 -v $(EXE)/extractor | ||||
| 	$(GO) test -count=1 -v git.nobrain.org/r4/dischord/extractor/ | ||||
|  | ||||
| .PHONY: all debug install uninstall clean | ||||
| .PHONY: all debug fmt install uninstall clean | ||||
|  | ||||
| clean: | ||||
| 	rm -f $(EXE) | ||||
|   | ||||
| @@ -10,6 +10,7 @@ import ( | ||||
| 	"git.nobrain.org/r4/dischord/player" | ||||
| 	"git.nobrain.org/r4/dischord/util" | ||||
|  | ||||
| 	_ "embed" | ||||
| 	"errors" | ||||
| 	"flag" | ||||
| 	"fmt" | ||||
| @@ -21,7 +22,6 @@ import ( | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| 	"syscall" | ||||
| 	_ "embed" | ||||
| ) | ||||
|  | ||||
| var copyright bool | ||||
| @@ -147,7 +147,7 @@ func main() { | ||||
| 	cfgfile := "config.toml" | ||||
| 	var cfg *config.Config | ||||
| 	var err error | ||||
| 	if autoconf || func() bool {cfg, err = config.Load(cfgfile); return err != nil}() { | ||||
| 	if autoconf || func() bool { cfg, err = config.Load(cfgfile); return err != nil }() { | ||||
| 		if err != nil { | ||||
| 			if os.IsNotExist(err) { | ||||
| 				fmt.Println("Configuration file not found, launching automatic configurator.") | ||||
|   | ||||
| @@ -22,8 +22,8 @@ var ( | ||||
| ) | ||||
|  | ||||
| type Config struct { | ||||
| 	Token string `toml:"bot-token"` | ||||
| 	FfmpegPath string `toml:"ffmpeg-path"` | ||||
| 	Token      string           `toml:"bot-token"` | ||||
| 	FfmpegPath string           `toml:"ffmpeg-path"` | ||||
| 	Extractors extractor.Config `toml:"extractors"` | ||||
| } | ||||
|  | ||||
| @@ -97,14 +97,20 @@ func macosEnableExecutable(filename string) error { | ||||
| // configuration file does not exist or is invalid. | ||||
| func Load(filename string) (*Config, error) { | ||||
| 	cfg := &Config{} | ||||
| 	_, err := toml.DecodeFile(filename, cfg) | ||||
| 	meta, err := toml.DecodeFile(filename, cfg) | ||||
| 	if err != nil { | ||||
| 		if pe, ok := err.(toml.ParseError); ok { | ||||
| 			fmt.Println(pe.ErrorWithUsage()) | ||||
| 		} | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if undec := meta.Undecoded(); len(undec) > 0 { | ||||
| 		return nil, fmt.Errorf("%v: field '%v' could not be decoded", filename, undec[0]) | ||||
| 	} | ||||
| 	if cfg.Token == defaultToken || cfg.Token == "" { | ||||
| 		return nil, ErrTokenNotSet | ||||
| 	} | ||||
| 	if err := cfg.Extractors.CheckTypes(); err != nil { | ||||
| 	if err := cfg.Extractors.CheckValidity(); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if _, err := exec.LookPath(cfg.Extractors["youtube-dl"]["youtube-dl-path"].(string)); err != nil { | ||||
| @@ -125,7 +131,7 @@ func Autoconf(filename string) (*Config, error) { | ||||
| 	} | ||||
|  | ||||
| 	download := func(executable bool, urlsByOS map[string]map[string]string) (filename string, err error) { | ||||
| 		filename, err = download(executable, urlsByOS, func(progress float32){ | ||||
| 		filename, err = download(executable, urlsByOS, func(progress float32) { | ||||
| 			fmt.Printf("Progress: %.1f%%\r", progress*100.0) | ||||
| 		}) | ||||
| 		if err != nil { | ||||
| @@ -152,18 +158,18 @@ func Autoconf(filename string) (*Config, error) { | ||||
| 	if youtubeDlPath == "" { | ||||
| 		fmt.Println("Downloading youtube-dl") | ||||
| 		filename, err := download(true, map[string]map[string]string{ | ||||
| 				"windows": { | ||||
| 					"amd64": "https://yt-dl.org/downloads/latest/youtube-dl.exe", | ||||
| 					"386": "https://yt-dl.org/downloads/latest/youtube-dl.exe", | ||||
| 				}, | ||||
| 				"any": { | ||||
| 					"any": "https://yt-dl.org/downloads/latest/youtube-dl", | ||||
| 				}, | ||||
| 			}) | ||||
| 			"windows": { | ||||
| 				"amd64": "https://yt-dl.org/downloads/latest/youtube-dl.exe", | ||||
| 				"386":   "https://yt-dl.org/downloads/latest/youtube-dl.exe", | ||||
| 			}, | ||||
| 			"any": { | ||||
| 				"any": "https://yt-dl.org/downloads/latest/youtube-dl", | ||||
| 			}, | ||||
| 		}) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		youtubeDlPath = "./"+filename | ||||
| 		youtubeDlPath = "./" + filename | ||||
| 		macosEnableExecutable(youtubeDlPath) | ||||
| 		if python3IsPython { | ||||
| 			// Replace first line with `replacement` | ||||
| @@ -195,21 +201,21 @@ func Autoconf(filename string) (*Config, error) { | ||||
| 		} | ||||
| 		fmt.Println("Downloading FFmpeg") | ||||
| 		filename, err := download(false, map[string]map[string]string{ | ||||
| 				"linux": { | ||||
| 					"amd64": "https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz", | ||||
| 					"386": "https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-i686-static.tar.xz", | ||||
| 					"arm64": "https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-arm64-static.tar.xz", | ||||
| 					"arm": "https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-armhf-static.tar.xz", | ||||
| 				}, | ||||
| 				"windows": { | ||||
| 					"amd64": "https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.zip", | ||||
| 					"386": "https://github.com/sudo-nautilus/FFmpeg-Builds-Win32/releases/download/latest/ffmpeg-n5.1-latest-win32-gpl-5.1.zip", | ||||
| 				}, | ||||
| 				"darwin": { | ||||
| 					"amd64": "https://evermeet.cx/ffmpeg/getrelease/zip", | ||||
| 					"arm64": "https://www.osxexperts.net/FFmpeg511ARM.zip", | ||||
| 				}, | ||||
| 			}) | ||||
| 			"linux": { | ||||
| 				"amd64": "https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz", | ||||
| 				"386":   "https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-i686-static.tar.xz", | ||||
| 				"arm64": "https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-arm64-static.tar.xz", | ||||
| 				"arm":   "https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-armhf-static.tar.xz", | ||||
| 			}, | ||||
| 			"windows": { | ||||
| 				"amd64": "https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.zip", | ||||
| 				"386":   "https://github.com/sudo-nautilus/FFmpeg-Builds-Win32/releases/download/latest/ffmpeg-n5.1-latest-win32-gpl-5.1.zip", | ||||
| 			}, | ||||
| 			"darwin": { | ||||
| 				"amd64": "https://evermeet.cx/ffmpeg/getrelease/zip", | ||||
| 				"arm64": "https://www.osxexperts.net/FFmpeg511ARM.zip", | ||||
| 			}, | ||||
| 		}) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| @@ -220,7 +226,7 @@ func Autoconf(filename string) (*Config, error) { | ||||
| 		if err := os.Remove(filename); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		cfg.FfmpegPath = "./"+targetFile | ||||
| 		cfg.FfmpegPath = "./" + targetFile | ||||
| 		macosEnableExecutable(cfg.FfmpegPath) | ||||
| 	} else { | ||||
| 		fmt.Println("Using FFmpeg executable found at", cfg.FfmpegPath) | ||||
|   | ||||
| @@ -19,9 +19,9 @@ import ( | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	ErrUnsupportedOSAndArch = errors.New("no download available for your operating system and hardware architecture") | ||||
| 	ErrUnsupportedOSAndArch  = errors.New("no download available for your operating system and hardware architecture") | ||||
| 	ErrFileNotFoundInArchive = errors.New("file not found in archive") | ||||
| 	ErrUnsupportedArchive = errors.New("unsupported archive format (supported are .tar, .tar.gz, .tar.xz and .zip") | ||||
| 	ErrUnsupportedArchive    = errors.New("unsupported archive format (supported are .tar, .tar.gz, .tar.xz and .zip") | ||||
| ) | ||||
|  | ||||
| func download(executable bool, urlsByOS map[string]map[string]string, progCallback func(progress float32)) (filename string, err error) { | ||||
| @@ -85,7 +85,7 @@ func download(executable bool, urlsByOS map[string]map[string]string, progCallba | ||||
| 			} | ||||
| 		} | ||||
| 		if progCallback != nil && size != 0 { | ||||
| 			progCallback(float32(i)/float32(size)) | ||||
| 			progCallback(float32(i) / float32(size)) | ||||
| 		} | ||||
| 	} | ||||
| 	return savePath, nil | ||||
|   | ||||
| @@ -8,21 +8,21 @@ import ( | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	ErrNoSearchResults      = errors.New("no search provider available") | ||||
| 	ErrNoSearchResults      = errors.New("no search results") | ||||
| 	ErrNoSearchProvider     = errors.New("no search provider available") | ||||
| 	ErrNoSuggestionProvider = errors.New("no search suggestion provider available") | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	providers  []provider | ||||
| 	extractors []extractor | ||||
| 	searchers  []searcher | ||||
| 	suggestors []suggestor | ||||
| 	providers     []provider | ||||
| 	extractors    []extractor | ||||
| 	searchers     []searcher | ||||
| 	suggestors    []suggestor | ||||
| 	defaultConfig Config | ||||
| ) | ||||
|  | ||||
| func Extract(cfg Config, input string) ([]Data, error) { | ||||
| 	if err := cfg.CheckTypes(); err != nil { | ||||
| 	if err := cfg.CheckValidity(); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	for _, e := range extractors { | ||||
| @@ -45,7 +45,7 @@ func Extract(cfg Config, input string) ([]Data, error) { | ||||
| } | ||||
|  | ||||
| func Search(cfg Config, input string) ([]Data, error) { | ||||
| 	if err := cfg.CheckTypes(); err != nil { | ||||
| 	if err := cfg.CheckValidity(); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	for _, s := range searchers { | ||||
| @@ -59,7 +59,7 @@ func Search(cfg Config, input string) ([]Data, error) { | ||||
| } | ||||
|  | ||||
| func Suggest(cfg Config, input string) ([]string, error) { | ||||
| 	if err := cfg.CheckTypes(); err != nil { | ||||
| 	if err := cfg.CheckValidity(); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	for _, s := range suggestors { | ||||
| @@ -115,19 +115,19 @@ func DefaultConfig() Config { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (cfg Config) CheckTypes() error { | ||||
| 	for provider, pCfg := range cfg { | ||||
| 		if pCfg == nil { | ||||
| 			return fmt.Errorf("extractor config for %v is nil", provider) | ||||
| func (cfg Config) CheckValidity() error { | ||||
| 	for chkProvider, chkCfg := range DefaultConfig() { | ||||
| 		if _, ok := cfg[chkProvider]; !ok { | ||||
| 			return fmt.Errorf("extractor config for %v is nil", chkProvider) | ||||
| 		} | ||||
| 		for k, v := range pCfg { | ||||
| 			got, expected := reflect.TypeOf(v), reflect.TypeOf(DefaultConfig()[provider][k]) | ||||
| 		for k, v := range chkCfg { | ||||
| 			expected, got := reflect.TypeOf(v), reflect.TypeOf(cfg[chkProvider][k]) | ||||
| 			if got != expected { | ||||
| 				return &ConfigTypeError{ | ||||
| 					Provider: provider, | ||||
| 					Key: k, | ||||
| 					Provider: chkProvider, | ||||
| 					Key:      k, | ||||
| 					Expected: expected, | ||||
| 					Got: got, | ||||
| 					Got:      got, | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| @@ -137,9 +137,9 @@ func (cfg Config) CheckTypes() error { | ||||
|  | ||||
| type ConfigTypeError struct { | ||||
| 	Provider string | ||||
| 	Key string | ||||
| 	Key      string | ||||
| 	Expected reflect.Type | ||||
| 	Got reflect.Type | ||||
| 	Got      reflect.Type | ||||
| } | ||||
|  | ||||
| func (e *ConfigTypeError) Error() string { | ||||
| @@ -151,7 +151,7 @@ func (e *ConfigTypeError) Error() string { | ||||
| 	if e.Got != nil { | ||||
| 		gotName = e.Got.Name() | ||||
| 	} | ||||
| 	return "extractor config type error: "+e.Provider+"."+e.Key+": expected "+expectedName+" but got "+gotName | ||||
| 	return "invalid extractor configuration: " + e.Provider + "." + e.Key + ": expected " + expectedName + " but got " + gotName | ||||
| } | ||||
|  | ||||
| type ProviderConfig map[string]any | ||||
|   | ||||
| @@ -140,7 +140,7 @@ func getDecryptFunction(baseJs string) (string, error) { | ||||
| 	} | ||||
| 	fn := baseJs[start+len(startMatch):] | ||||
| 	end := strings.Index(fn, endMatch) | ||||
| 	if start == -1 { | ||||
| 	if end == -1 { | ||||
| 		return "", ErrDecryptGettingFunction | ||||
| 	} | ||||
| 	return fn[:end], nil | ||||
| @@ -170,7 +170,7 @@ func getDecryptOps(baseJs string) ([]decryptorOp, error) { | ||||
| 		} | ||||
| 		ops = baseJs[start+len(startMatch):] | ||||
| 		end := strings.Index(ops, endMatch) | ||||
| 		if start == -1 { | ||||
| 		if end == -1 { | ||||
| 			return nil, ErrDecryptGettingOpTable | ||||
| 		} | ||||
| 		ops = ops[:end] | ||||
|   | ||||
| @@ -82,8 +82,8 @@ type CmdAddBack []extractor.Data | ||||
| type CmdSeek float64  // seconds | ||||
| type CmdSpeed float64 // speed factor | ||||
| type CmdPlayFileAndStop struct { | ||||
| 	DoneCh   chan<- struct{} | ||||
| 	Data []byte | ||||
| 	DoneCh chan<- struct{} | ||||
| 	Data   []byte | ||||
| } | ||||
| type CmdGetTime chan<- float64 | ||||
| type CmdGetQueue chan<- *Queue | ||||
| @@ -522,8 +522,8 @@ func NewClient(excfg extractor.Config, ffmpegPath string, outCh chan<- []byte, c | ||||
| 						refreshStream(getPlaybackTime(), float64(v)) | ||||
| 					case CmdPlayFileAndStop: | ||||
| 						cmd := struct { | ||||
| 							DoneCh   chan<- struct{} | ||||
| 							Data []byte | ||||
| 							DoneCh chan<- struct{} | ||||
| 							Data   []byte | ||||
| 						}(v) | ||||
|  | ||||
| 						audioch, errch, killch = audio.StreamToDiscordOpus(ffmpegPath, "pipe:", bytes.NewReader(cmd.Data), 0, 1.0, false) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user