Compare commits

..

5 Commits

Author SHA1 Message Date
r4
9174c1b23a Fix make test 2022-10-01 20:00:48 +02:00
r4
154c6a31b9 fix error check 2022-10-01 19:59:34 +02:00
r4
c8f9832f48 Improve configuration error checking (fix panic)
A panic would occur if a field in the config file (e.g. youtube-dl.youtube-dl-path) was not set
2022-09-23 15:46:18 +02:00
r4
7bdfcf9776 Add fmt target to makefile and run it 2022-09-20 17:43:47 +02:00
r4
a5757c3079 Fix typo 2022-09-20 17:42:15 +02:00
7 changed files with 72 additions and 63 deletions

View File

@@ -12,6 +12,9 @@ debug:
$(GO) build -o $(EXE) -gcflags=all="-N -l" cmd/$(EXE)/*.go $(GO) build -o $(EXE) -gcflags=all="-N -l" cmd/$(EXE)/*.go
dlv exec ./dischord dlv exec ./dischord
fmt:
find . -type f -name '*.go' -exec gofmt -w '{}' ';'
install: all install: all
mkdir -p $(DESTDIR)$(PREFIX)/bin mkdir -p $(DESTDIR)$(PREFIX)/bin
cp -f $(EXE) $(DESTDIR)$(PREFIX)/bin cp -f $(EXE) $(DESTDIR)$(PREFIX)/bin
@@ -48,9 +51,9 @@ uninstall:
rm -f $(DESTDIR)$(CFGPREFIX)/systemd/system/$(EXE).service rm -f $(DESTDIR)$(CFGPREFIX)/systemd/system/$(EXE).service
test: 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: clean:
rm -f $(EXE) rm -f $(EXE)

View File

@@ -10,6 +10,7 @@ import (
"git.nobrain.org/r4/dischord/player" "git.nobrain.org/r4/dischord/player"
"git.nobrain.org/r4/dischord/util" "git.nobrain.org/r4/dischord/util"
_ "embed"
"errors" "errors"
"flag" "flag"
"fmt" "fmt"
@@ -21,7 +22,6 @@ import (
"strings" "strings"
"sync" "sync"
"syscall" "syscall"
_ "embed"
) )
var copyright bool var copyright bool
@@ -147,7 +147,7 @@ func main() {
cfgfile := "config.toml" cfgfile := "config.toml"
var cfg *config.Config var cfg *config.Config
var err error 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 err != nil {
if os.IsNotExist(err) { if os.IsNotExist(err) {
fmt.Println("Configuration file not found, launching automatic configurator.") fmt.Println("Configuration file not found, launching automatic configurator.")

View File

@@ -22,8 +22,8 @@ var (
) )
type Config struct { type Config struct {
Token string `toml:"bot-token"` Token string `toml:"bot-token"`
FfmpegPath string `toml:"ffmpeg-path"` FfmpegPath string `toml:"ffmpeg-path"`
Extractors extractor.Config `toml:"extractors"` Extractors extractor.Config `toml:"extractors"`
} }
@@ -97,14 +97,20 @@ func macosEnableExecutable(filename string) error {
// configuration file does not exist or is invalid. // configuration file does not exist or is invalid.
func Load(filename string) (*Config, error) { func Load(filename string) (*Config, error) {
cfg := &Config{} cfg := &Config{}
_, err := toml.DecodeFile(filename, cfg) meta, err := toml.DecodeFile(filename, cfg)
if err != nil { if err != nil {
if pe, ok := err.(toml.ParseError); ok {
fmt.Println(pe.ErrorWithUsage())
}
return nil, err 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 == "" { if cfg.Token == defaultToken || cfg.Token == "" {
return nil, ErrTokenNotSet return nil, ErrTokenNotSet
} }
if err := cfg.Extractors.CheckTypes(); err != nil { if err := cfg.Extractors.CheckValidity(); err != nil {
return nil, err return nil, err
} }
if _, err := exec.LookPath(cfg.Extractors["youtube-dl"]["youtube-dl-path"].(string)); err != nil { 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) { 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) fmt.Printf("Progress: %.1f%%\r", progress*100.0)
}) })
if err != nil { if err != nil {
@@ -152,18 +158,18 @@ func Autoconf(filename string) (*Config, error) {
if youtubeDlPath == "" { if youtubeDlPath == "" {
fmt.Println("Downloading youtube-dl") fmt.Println("Downloading youtube-dl")
filename, err := download(true, map[string]map[string]string{ filename, err := download(true, map[string]map[string]string{
"windows": { "windows": {
"amd64": "https://yt-dl.org/downloads/latest/youtube-dl.exe", "amd64": "https://yt-dl.org/downloads/latest/youtube-dl.exe",
"386": "https://yt-dl.org/downloads/latest/youtube-dl.exe", "386": "https://yt-dl.org/downloads/latest/youtube-dl.exe",
}, },
"any": { "any": {
"any": "https://yt-dl.org/downloads/latest/youtube-dl", "any": "https://yt-dl.org/downloads/latest/youtube-dl",
}, },
}) })
if err != nil { if err != nil {
return nil, err return nil, err
} }
youtubeDlPath = "./"+filename youtubeDlPath = "./" + filename
macosEnableExecutable(youtubeDlPath) macosEnableExecutable(youtubeDlPath)
if python3IsPython { if python3IsPython {
// Replace first line with `replacement` // Replace first line with `replacement`
@@ -195,21 +201,21 @@ func Autoconf(filename string) (*Config, error) {
} }
fmt.Println("Downloading FFmpeg") fmt.Println("Downloading FFmpeg")
filename, err := download(false, map[string]map[string]string{ filename, err := download(false, map[string]map[string]string{
"linux": { "linux": {
"amd64": "https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz", "amd64": "https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz",
"386": "https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-i686-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", "arm64": "https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-arm64-static.tar.xz",
"arm": "https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-armhf-static.tar.xz", "arm": "https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-armhf-static.tar.xz",
}, },
"windows": { "windows": {
"amd64": "https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.zip", "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", "386": "https://github.com/sudo-nautilus/FFmpeg-Builds-Win32/releases/download/latest/ffmpeg-n5.1-latest-win32-gpl-5.1.zip",
}, },
"darwin": { "darwin": {
"amd64": "https://evermeet.cx/ffmpeg/getrelease/zip", "amd64": "https://evermeet.cx/ffmpeg/getrelease/zip",
"arm64": "https://www.osxexperts.net/FFmpeg511ARM.zip", "arm64": "https://www.osxexperts.net/FFmpeg511ARM.zip",
}, },
}) })
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -220,7 +226,7 @@ func Autoconf(filename string) (*Config, error) {
if err := os.Remove(filename); err != nil { if err := os.Remove(filename); err != nil {
return nil, err return nil, err
} }
cfg.FfmpegPath = "./"+targetFile cfg.FfmpegPath = "./" + targetFile
macosEnableExecutable(cfg.FfmpegPath) macosEnableExecutable(cfg.FfmpegPath)
} else { } else {
fmt.Println("Using FFmpeg executable found at", cfg.FfmpegPath) fmt.Println("Using FFmpeg executable found at", cfg.FfmpegPath)

View File

@@ -19,9 +19,9 @@ import (
) )
var ( 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") 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) { 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 { if progCallback != nil && size != 0 {
progCallback(float32(i)/float32(size)) progCallback(float32(i) / float32(size))
} }
} }
return savePath, nil return savePath, nil

View File

@@ -8,21 +8,21 @@ import (
) )
var ( var (
ErrNoSearchResults = errors.New("no search provider available") ErrNoSearchResults = errors.New("no search results")
ErrNoSearchProvider = errors.New("no search provider available") ErrNoSearchProvider = errors.New("no search provider available")
ErrNoSuggestionProvider = errors.New("no search suggestion provider available") ErrNoSuggestionProvider = errors.New("no search suggestion provider available")
) )
var ( var (
providers []provider providers []provider
extractors []extractor extractors []extractor
searchers []searcher searchers []searcher
suggestors []suggestor suggestors []suggestor
defaultConfig Config defaultConfig Config
) )
func Extract(cfg Config, input string) ([]Data, error) { func Extract(cfg Config, input string) ([]Data, error) {
if err := cfg.CheckTypes(); err != nil { if err := cfg.CheckValidity(); err != nil {
return nil, err return nil, err
} }
for _, e := range extractors { for _, e := range extractors {
@@ -45,7 +45,7 @@ func Extract(cfg Config, input string) ([]Data, error) {
} }
func Search(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 return nil, err
} }
for _, s := range searchers { for _, s := range searchers {
@@ -59,7 +59,7 @@ func Search(cfg Config, input string) ([]Data, error) {
} }
func Suggest(cfg Config, input string) ([]string, error) { func Suggest(cfg Config, input string) ([]string, error) {
if err := cfg.CheckTypes(); err != nil { if err := cfg.CheckValidity(); err != nil {
return nil, err return nil, err
} }
for _, s := range suggestors { for _, s := range suggestors {
@@ -115,19 +115,19 @@ func DefaultConfig() Config {
} }
} }
func (cfg Config) CheckTypes() error { func (cfg Config) CheckValidity() error {
for provider, pCfg := range cfg { for chkProvider, chkCfg := range DefaultConfig() {
if pCfg == nil { if _, ok := cfg[chkProvider]; !ok {
return fmt.Errorf("extractor config for %v is nil", provider) return fmt.Errorf("extractor config for %v is nil", chkProvider)
} }
for k, v := range pCfg { for k, v := range chkCfg {
got, expected := reflect.TypeOf(v), reflect.TypeOf(DefaultConfig()[provider][k]) expected, got := reflect.TypeOf(v), reflect.TypeOf(cfg[chkProvider][k])
if got != expected { if got != expected {
return &ConfigTypeError{ return &ConfigTypeError{
Provider: provider, Provider: chkProvider,
Key: k, Key: k,
Expected: expected, Expected: expected,
Got: got, Got: got,
} }
} }
} }
@@ -137,9 +137,9 @@ func (cfg Config) CheckTypes() error {
type ConfigTypeError struct { type ConfigTypeError struct {
Provider string Provider string
Key string Key string
Expected reflect.Type Expected reflect.Type
Got reflect.Type Got reflect.Type
} }
func (e *ConfigTypeError) Error() string { func (e *ConfigTypeError) Error() string {
@@ -151,7 +151,7 @@ func (e *ConfigTypeError) Error() string {
if e.Got != nil { if e.Got != nil {
gotName = e.Got.Name() 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 type ProviderConfig map[string]any

View File

@@ -140,7 +140,7 @@ func getDecryptFunction(baseJs string) (string, error) {
} }
fn := baseJs[start+len(startMatch):] fn := baseJs[start+len(startMatch):]
end := strings.Index(fn, endMatch) end := strings.Index(fn, endMatch)
if start == -1 { if end == -1 {
return "", ErrDecryptGettingFunction return "", ErrDecryptGettingFunction
} }
return fn[:end], nil return fn[:end], nil
@@ -170,7 +170,7 @@ func getDecryptOps(baseJs string) ([]decryptorOp, error) {
} }
ops = baseJs[start+len(startMatch):] ops = baseJs[start+len(startMatch):]
end := strings.Index(ops, endMatch) end := strings.Index(ops, endMatch)
if start == -1 { if end == -1 {
return nil, ErrDecryptGettingOpTable return nil, ErrDecryptGettingOpTable
} }
ops = ops[:end] ops = ops[:end]

View File

@@ -82,8 +82,8 @@ type CmdAddBack []extractor.Data
type CmdSeek float64 // seconds type CmdSeek float64 // seconds
type CmdSpeed float64 // speed factor type CmdSpeed float64 // speed factor
type CmdPlayFileAndStop struct { type CmdPlayFileAndStop struct {
DoneCh chan<- struct{} DoneCh chan<- struct{}
Data []byte Data []byte
} }
type CmdGetTime chan<- float64 type CmdGetTime chan<- float64
type CmdGetQueue chan<- *Queue type CmdGetQueue chan<- *Queue
@@ -522,8 +522,8 @@ func NewClient(excfg extractor.Config, ffmpegPath string, outCh chan<- []byte, c
refreshStream(getPlaybackTime(), float64(v)) refreshStream(getPlaybackTime(), float64(v))
case CmdPlayFileAndStop: case CmdPlayFileAndStop:
cmd := struct { cmd := struct {
DoneCh chan<- struct{} DoneCh chan<- struct{}
Data []byte Data []byte
}(v) }(v)
audioch, errch, killch = audio.StreamToDiscordOpus(ffmpegPath, "pipe:", bytes.NewReader(cmd.Data), 0, 1.0, false) audioch, errch, killch = audio.StreamToDiscordOpus(ffmpegPath, "pipe:", bytes.NewReader(cmd.Data), 0, 1.0, false)