Compare commits

...

4 commits

Author SHA1 Message Date
5fb296c176 🐛 Verify valid shows.yml
Fix nil pointer derference
2025-07-02 15:47:22 -05:00
dc9e6f59db Support yt-dlp shows 2025-07-02 14:15:32 -05:00
186bf5fcba 🚨 Update linter and fix new warnings 2025-07-02 14:14:04 -05:00
24436ce28b 🐛 Deduplicate recipes 2025-05-02 18:22:16 -05:00
6 changed files with 112 additions and 36 deletions

View file

@ -1,7 +1,8 @@
version: "2"
linters: linters:
enable: enable:
- errcheck - errcheck
- gosimple
- govet - govet
- ineffassign - ineffassign
- staticcheck - staticcheck
@ -22,18 +23,17 @@ linters:
- gosec - gosec
- perfsprint - perfsprint
- testifylint - testifylint
settings:
linters-settings: testifylint:
testifylint: enable-all: true
enable-all: true disable:
disable: - require-error
- require-error gocognit:
gocognit: min-complexity: 16
min-complexity: 16 gocyclo:
gocyclo: min-complexity: 15
min-complexity: 15 gocritic:
gocritic: enable-all: true
enable-all: true settings:
settings: hugeParam:
hugeParam: sizeThreshold: 255
sizeThreshold: 255

View file

@ -16,6 +16,7 @@ func main() {
m, err := ic.NewMerger(os.Args[1:]) m, err := ic.NewMerger(os.Args[1:])
e.HandleErr(err) e.HandleErr(err)
//nolint:errcheck // I don't care about this
defer m.Close() defer m.Close()
err = m.ParseFiles() err = m.ParseFiles()

View file

@ -1,6 +1,8 @@
package convids package convids
import ( import (
"bufio"
"cmp"
"context" "context"
"errors" "errors"
"fmt" "fmt"
@ -16,7 +18,16 @@ import (
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )
type ShowWalker func(show *Show, path string) error
type GroupPrinter func(name string, group Shows)
var ErrNoFiles = errors.New("no files processed")
var ErrSkipped = errors.New("skipped")
var ErrMissingConfig = errors.New("missing config")
var ErrMissingShows = errors.New("missing shows")
func NewData(path string) (*Data, error) { func NewData(path string) (*Data, error) {
//nolint:gosec // I don't care if this is user input
f, err := os.Open(path) f, err := os.Open(path)
if err != nil { if err != nil {
return nil, err return nil, err
@ -24,7 +35,17 @@ func NewData(path string) (*Data, error) {
ydec := yaml.NewDecoder(f) ydec := yaml.NewDecoder(f)
var data Data var data Data
err = ydec.Decode(&data) err = ydec.Decode(&data)
return &data, err if err != nil {
return nil, err
}
if data.Config == nil {
return nil, ErrMissingConfig
}
if data.Shows == nil || len(*(data.Shows)) == 0 {
return nil, ErrMissingShows
}
return &data, nil
} }
func ensureExtRe(c *Config) (err error) { func ensureExtRe(c *Config) (err error) {
@ -35,12 +56,6 @@ func ensureExtRe(c *Config) (err error) {
return return
} }
type ShowWalker func(show *Show, path string) error
type GroupPrinter func(name string, group Shows)
var ErrNoFiles = errors.New("no files processed")
var ErrSkipped = errors.New("skipped")
type processInput struct { type processInput struct {
file os.DirEntry file os.DirEntry
source string source string
@ -152,8 +167,8 @@ func WalkFiles(d *Data, stopOnError bool, gp GroupPrinter, cb ShowWalker) (err e
func DryRun(out io.Writer) ShowWalker { func DryRun(out io.Writer) ShowWalker {
return func(s *Show, path string) error { return func(s *Show, path string) error {
fmt.Fprintf(out, "Saving %s to %s\n", path, s.Folder) _, err := fmt.Fprintf(out, "Saving %s to %s\n", path, s.Folder)
return ErrSkipped return cmp.Or(err, ErrSkipped)
} }
} }
@ -163,18 +178,53 @@ func GetShow(ctx context.Context) ShowWalker {
func GetShowWithIO(ctx context.Context, stdin io.Reader, stdout, stderr io.Writer) ShowWalker { func GetShowWithIO(ctx context.Context, stdin io.Reader, stdout, stderr io.Writer) ShowWalker {
return func(s *Show, path string) error { return func(s *Show, path string) error {
//nolint:gosec // I don't care if this is using user input if !s.Url {
cmd := exec.CommandContext(ctx, "get-shows", s.Folder, path) return runGetShowsCmd(ctx, s.Folder, path, stdin, stdout, stderr)
cmd.Stdin = stdin }
cmd.Stdout = stdout
cmd.Stderr = stderr
return cmd.Run()
}
orig := path
//nolint:gosec // I don't care if this is user input
readFile, err := os.Open(orig)
if err != nil {
return err
}
//nolint:errcheck // I don't care
defer readFile.Close()
fileScan := bufio.NewScanner(readFile)
fileScan.Split(bufio.ScanLines)
for fileScan.Scan() {
path = fileScan.Text()
err := runGetShowsCmd(ctx, s.Folder, path, stdin, stdout, stderr)
if err != nil {
return err
}
}
if s.Backup != "" {
err = os.Rename(orig, fp.Join(s.Backup, fp.Base(orig)))
if err != nil {
_, _ = fmt.Fprintf(stdout, "Moved %s to %s\n", orig, s.Backup)
}
} else {
err = os.Remove(orig)
}
return err
}
}
func runGetShowsCmd(ctx context.Context, folder, path string, stdin io.Reader, stdout, stderr io.Writer) error {
//nolint:gosec // I don't care if this is using user input
cmd := exec.CommandContext(ctx, "get-shows", folder, path)
cmd.Stdin = stdin
cmd.Stdout = stdout
cmd.Stderr = stderr
return cmd.Run()
} }
func PrintGroupName(out io.Writer) GroupPrinter { func PrintGroupName(out io.Writer) GroupPrinter {
return func(name string, group Shows) { return func(name string, group Shows) {
fmt.Fprintf(out, "Checking %s shows\n\n", name) _, _ = fmt.Fprintf(out, "Checking %s shows\n\n", name)
} }
} }

View file

@ -25,6 +25,8 @@ type Show struct {
Pattern string Pattern string
Name string Name string
Anime bool Anime bool
Url bool
Backup string
Sources []string Sources []string
re *regexp.Regexp re *regexp.Regexp

View file

@ -7,6 +7,7 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"os" "os"
"slices"
_ "github.com/glebarez/go-sqlite" _ "github.com/glebarez/go-sqlite"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
@ -196,13 +197,35 @@ func (m *Merger) getRecipes(ctx context.Context, items []Item) (err error) {
if recs, found = rm[items[idx].Id]; found { if recs, found = rm[items[idx].Id]; found {
items[idx].Recipes = make([][]int32, 0, len(recs)) items[idx].Recipes = make([][]int32, 0, len(recs))
for _, rec := range recs { for _, rec := range recs {
items[idx].Recipes = append(items[idx].Recipes, rec) addRecs(&(items[idx].Recipes), rec)
} }
} }
} }
return return
} }
func addRecs(recs *[][]int32, rec []int32) {
slices.Sort(rec)
if !slices.ContainsFunc(*recs, recSorter(rec)) {
*recs = append(*recs, rec)
}
}
func recSorter(rec []int32) func([]int32) bool {
return func(v []int32) bool {
slices.Sort(v)
if !(len(v) == len(rec)) {
return false
}
for idx, i := range v {
if !(i == rec[idx]) {
return false
}
}
return true
}
}
func (m *Merger) Merge(ctx context.Context) (g Game, err error) { func (m *Merger) Merge(ctx context.Context) (g Game, err error) {
if err = m.getGameDetails(ctx, &g); err != nil { if err = m.getGameDetails(ctx, &g); err != nil {
return return

View file

@ -50,11 +50,11 @@ func (a *App) run(ctx context.Context) error {
} }
func (a *App) runInLoop(ctx context.Context) error { func (a *App) runInLoop(ctx context.Context) error {
fmt.Fprintln(a.stdout, "Looping") _, _ = fmt.Fprintln(a.stdout, "Looping")
var err error var err error
for err == nil { for err == nil {
err = a.run(ctx) err = a.run(ctx)
fmt.Fprintln(a.stdout, err) _, _ = fmt.Fprintln(a.stdout, err)
} }
return err return err
} }