diff --git a/.gitignore b/.gitignore index 567609b..c525b60 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ build/ +.task/ diff --git a/Taskfile.yml b/Taskfile.yml new file mode 100644 index 0000000..47ccef9 --- /dev/null +++ b/Taskfile.yml @@ -0,0 +1,37 @@ +# https://taskfile.dev + +version: '3' + +tasks: + fmt: + desc: Format go files + sources: + - "**/*.go" + cmds: + - go fmt ./... + cmd-build: + internal: true + cmds: + - go build -o build/ ./cmd/{{.CMD}} + build-convids: + desc: Builds the convids command + sources: + - cmd/convids/**/*.go + - convids/**/*.go + - internal/cli/*.go + generates: + - build/convids + cmds: + - task: cmd-build + vars: + CMD: convids + build-all: + desc: Builds all available commands + sources: + - "**/*.go" + generates: + - build/convids + cmds: + - task: cmd-build + vars: + CMD: "*" diff --git a/cmd/convids/main.go b/cmd/convids/main.go index e5f01b4..f07e8db 100644 --- a/cmd/convids/main.go +++ b/cmd/convids/main.go @@ -7,7 +7,6 @@ import ( "codeberg.org/danjones000/utils/convids" "codeberg.org/danjones000/utils/internal/cli" "github.com/spf13/pflag" - "gopkg.in/yaml.v3" ) const dataPath = "shows.yml" @@ -26,17 +25,12 @@ func main() { fmt.Println("looping") } - f, err := os.Open(dataPath) + data, err := convids.NewData(dataPath) cli.HandleErr(err) - ydec := yaml.NewDecoder(f) - var data convids.Data - err = ydec.Decode(&data) - cli.HandleErr(err) - - fmt.Printf("Data: %+v\n", data) - - for s := range data.AllShows(false) { - fmt.Printf("Show: %+v\n", s) - } + convids.WalkFiles(data, false, false, func(s *convids.Show, path string) error { + fmt.Printf("%s for %+v\n", path, s) + return nil + }) + fmt.Println("\nDone!") } diff --git a/convids/logic.go b/convids/logic.go new file mode 100644 index 0000000..35b1497 --- /dev/null +++ b/convids/logic.go @@ -0,0 +1,63 @@ +package convids + +import ( + "os" + fp "path/filepath" + "regexp" + "strings" + + "gopkg.in/yaml.v3" +) + +func NewData(path string) (*Data, error) { + f, err := os.Open(path) + if err != nil { + return nil, err + } + ydec := yaml.NewDecoder(f) + var data Data + err = ydec.Decode(&data) + return &data, err +} + +func ensureExtRe(c *Config) (err error) { + if c.extRe != nil { + return nil + } + c.extRe, err = regexp.Compile("(" + strings.Join(c.Extensions, "|") + ")$") + return +} + +func WalkFiles(d *Data, stopOnError, silent bool, cb func(s *Show, path string) error) (err error) { + err = ensureExtRe(d.Config) + if err != nil { + return + } + var files []os.DirEntry + files, err = os.ReadDir(d.Config.Source) + if err != nil { + return + } + for s := range d.AllShows(silent) { + var found bool + for _, file := range files { + if file.IsDir() { + continue + } + if !d.Config.extRe.MatchString(file.Name()) { + continue + } + found, err = s.Match(file.Name()) + if err != nil { + return + } + if found { + err = cb(s, fp.Join(d.Config.Source, file.Name())) + if err != nil && stopOnError { + return + } + } + } + } + return nil +} diff --git a/convids/methods.go b/convids/methods.go index 687d090..71689a9 100644 --- a/convids/methods.go +++ b/convids/methods.go @@ -1,22 +1,75 @@ package convids import ( + "errors" "fmt" "iter" + "regexp" "slices" + "strings" ) -func (s Shows) All() iter.Seq[Show] { - return slices.Values(s) +var ErrNoName = errors.New("missing name") + +var animePattern = `^\[.+\] ` +var animeRegexp = regexp.MustCompile(animePattern) + +func (s *Show) Match(path string) (bool, error) { + if s.Pattern != "" { + return s.matchRegexp(path) + } + if s.Name == "" { + return false, ErrNoName + } + if s.Anime { + if !animeRegexp.MatchString(path) { + return false, nil + } + path = animeRegexp.ReplaceAllString(path, "") + } + return strings.HasPrefix(path, s.Name), nil } -func (d Data) AllShows(silent bool) iter.Seq[Show] { - return func(yield func(Show) bool) { +func (s *Show) matchRegexp(path string) (f bool, err error) { + if s.re == nil { + p := s.Pattern + if s.Anime { + if strings.HasPrefix(p, "^") { + p = strings.TrimPrefix(p, "^") + } + p = animePattern + p + } else if !strings.HasPrefix(p, "^") { + p = "^" + p + } + s.re, err = regexp.Compile(p) + if err != nil { + return + } + } + return s.re.MatchString(path), nil +} + +func (ss *Shows) All() iter.Seq[*Show] { + return slices.Values(*ss) +} + +func (d *Data) AllShows(silent bool) iter.Seq[*Show] { + return func(yield func(*Show) bool) { + if d.Config == nil { + return + } for _, show := range d.Config.Shows { + sh := (*d.Shows)[show] + if sh == nil || len(*sh) < 1 { + continue + } if !silent { fmt.Println("\nChecking", show, "shows\n") } - for s := range d.Shows[show].All() { + for s := range sh.All() { + if s == nil { + continue + } if !yield(s) { return } diff --git a/convids/models.go b/convids/models.go index 88ea5f4..1ae6448 100644 --- a/convids/models.go +++ b/convids/models.go @@ -1,23 +1,29 @@ package convids +import "regexp" + type Data struct { - Config Config - Shows ShowMap + Config *Config + Shows *ShowMap } type Config struct { Source string Extensions []string Shows []string + + extRe *regexp.Regexp } -type ShowMap map[string]Shows +type ShowMap map[string]*Shows -type Shows []Show +type Shows []*Show type Show struct { Folder string Pattern string Name string Anime bool + + re *regexp.Regexp }