✨ Add mkflex command
This commit is contained in:
parent
72295c53cf
commit
f4497aef7e
7 changed files with 333 additions and 1 deletions
16
Taskfile.yml
16
Taskfile.yml
|
|
@ -35,6 +35,7 @@ tasks:
|
|||
internal: true
|
||||
cmds:
|
||||
- go build -o build/ ./cmd/{{.CMD}}
|
||||
|
||||
build-convids:
|
||||
desc: Builds the convids command
|
||||
sources:
|
||||
|
|
@ -45,6 +46,7 @@ tasks:
|
|||
- task: cmd-build
|
||||
vars:
|
||||
CMD: convids
|
||||
|
||||
build-cool-down:
|
||||
desc: Builds the cool-down command
|
||||
source:
|
||||
|
|
@ -58,6 +60,7 @@ tasks:
|
|||
- task: cmd-build
|
||||
vars:
|
||||
CMD: cool-down
|
||||
|
||||
build-all:
|
||||
desc: Builds all available commands
|
||||
sources:
|
||||
|
|
@ -70,6 +73,19 @@ tasks:
|
|||
vars:
|
||||
CMD: "*"
|
||||
|
||||
install-mkflex:
|
||||
desc: Installs the mkflex command
|
||||
source:
|
||||
- cmd/mkflex/**/*.go
|
||||
- convids/**/*.go
|
||||
- internal/cli/mkflex/**/*.go
|
||||
- mkflex/**/*.go
|
||||
- types/**/*.go
|
||||
generates:
|
||||
- '{{.BIN}}/mkflex'
|
||||
cmds:
|
||||
- go install ./cmd/mkflex
|
||||
|
||||
install-cool-down:
|
||||
desc: Installs the cool-down command
|
||||
source:
|
||||
|
|
|
|||
27
cmd/mkflex/main.go
Normal file
27
cmd/mkflex/main.go
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
c "codeberg.org/danjones000/utils/cli/context"
|
||||
e "codeberg.org/danjones000/utils/cli/err"
|
||||
mkcli "codeberg.org/danjones000/utils/internal/cli/mkflex"
|
||||
)
|
||||
|
||||
const dataPath = "/home/drj/WeboNextCloud/Computer/dotfiles/bigbad/shows.yml"
|
||||
const flexPath = "/home/drj/.flexget/config.yml"
|
||||
const flexTemp = "/home/drj/.flexget/config.temp.yml"
|
||||
|
||||
func main() {
|
||||
ctx, done := c.SelfCancelingContextFromBackground()
|
||||
defer done()
|
||||
|
||||
app, err := mkcli.NewApp(ctx, os.Args[0], os.Args[1:], dataPath, flexTemp, flexPath)
|
||||
e.HandleErr(err)
|
||||
|
||||
err = app.Run(ctx)
|
||||
e.HandleErr(err)
|
||||
|
||||
fmt.Println("Generated flexget config")
|
||||
}
|
||||
|
|
@ -1,6 +1,10 @@
|
|||
package convids
|
||||
|
||||
import "regexp"
|
||||
import (
|
||||
"regexp"
|
||||
|
||||
"codeberg.org/danjones000/utils/types"
|
||||
)
|
||||
|
||||
type Data struct {
|
||||
Config *Config
|
||||
|
|
@ -28,6 +32,13 @@ type Show struct {
|
|||
Url bool
|
||||
Backup string
|
||||
Sources []string
|
||||
Flexget struct {
|
||||
Name string
|
||||
Begin types.IntOrString
|
||||
AlternateName []string `yaml:"alternate_name"`
|
||||
Exact bool
|
||||
Skip bool
|
||||
}
|
||||
|
||||
re *regexp.Regexp
|
||||
}
|
||||
|
|
|
|||
53
internal/cli/mkflex/app.go
Normal file
53
internal/cli/mkflex/app.go
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
package mkflex
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
conutils "codeberg.org/danjones000/utils/convids"
|
||||
mkutils "codeberg.org/danjones000/utils/mkflex"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func NewApp(ctx context.Context, name string, args []string, dataPath, templatePath, outPath string) (*App, error) {
|
||||
var err error
|
||||
a := App{
|
||||
Name: name,
|
||||
Path: outPath,
|
||||
}
|
||||
|
||||
a.Data, err = conutils.NewData(dataPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
a.Config, err = mkutils.NewConfig(templatePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &a, nil
|
||||
}
|
||||
|
||||
type App struct {
|
||||
Name string
|
||||
Data *conutils.Data
|
||||
Path string
|
||||
Config *mkutils.Config
|
||||
}
|
||||
|
||||
func (a *App) Run(ctx context.Context) error {
|
||||
out, err := os.Create(a.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
enc := yaml.NewEncoder(out)
|
||||
enc.SetIndent(2)
|
||||
|
||||
if err := mkutils.AddShows(a.Config, a.Data); err != nil {
|
||||
return err
|
||||
}
|
||||
delete(a.Config.Templates, "x-aliases")
|
||||
|
||||
return enc.Encode(a.Config)
|
||||
}
|
||||
142
mkflex/logic.go
Normal file
142
mkflex/logic.go
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
package mkflex
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
conutils "codeberg.org/danjones000/utils/convids"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
var ErrMissingAliases = errors.New("missing aliases")
|
||||
var ErrMissingShowGrp = errors.New("missing show group")
|
||||
|
||||
func NewConfig(path string) (*Config, error) {
|
||||
//nolint:gosec // I don't care if this is user input
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ydec := yaml.NewDecoder(f)
|
||||
var conf Config
|
||||
err = ydec.Decode(&conf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &conf, nil
|
||||
}
|
||||
|
||||
func AddShows(conf *Config, data *conutils.Data) error {
|
||||
aliases, ok := conf.Templates["x-aliases"]
|
||||
reg, anime, err := getAliases(aliases, ok)
|
||||
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
nonEng := (*data.Shows)["non-eng"]
|
||||
aniShow := (*data.Shows)["anime"]
|
||||
|
||||
dor, err := getDorama(nonEng, reg)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
conf.Templates["dorama"] = Template{Series: dor}
|
||||
|
||||
aniSer, err := getAnime(aniShow, anime)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
conf.Templates["anime"] = Template{Series: aniSer}
|
||||
all, err := getAll(data, reg)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
conf.Templates["shows"] = Template{Series: all}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getAliases(aliases Template, ok bool) (reg, anime *Series, err error) {
|
||||
if !ok {
|
||||
err = ErrMissingAliases
|
||||
return
|
||||
}
|
||||
|
||||
for _, alias := range aliases.Series {
|
||||
if rF, ok := alias["x-regular"]; ok {
|
||||
reg = &rF
|
||||
}
|
||||
if rA, ok := alias["x-anime"]; ok {
|
||||
anime = &rA
|
||||
}
|
||||
}
|
||||
|
||||
if reg == nil {
|
||||
err = errors.Join(err, fmt.Errorf("%w: %s", ErrMissingAliases, "x-regular"))
|
||||
}
|
||||
|
||||
if anime == nil {
|
||||
err = errors.Join(err, fmt.Errorf("%w: %s", ErrMissingAliases, "x-anime"))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func getShow(show conutils.Show, sh Series) SeriesGroups {
|
||||
if !show.Flexget.Begin.IsZero() {
|
||||
sh.Begin = show.Flexget.Begin
|
||||
}
|
||||
sh.AlternameName = show.Flexget.AlternateName
|
||||
sh.Exact = show.Flexget.Exact
|
||||
name := cmp.Or(show.Flexget.Name, show.Name, show.Pattern)
|
||||
return SeriesGroups{name: sh}
|
||||
}
|
||||
|
||||
func getDorama(nonEng *conutils.Shows, tmp *Series) ([]SeriesGroups, error) {
|
||||
if len(*nonEng) == 0 {
|
||||
return nil, fmt.Errorf("%w: %s", ErrMissingShowGrp, "non-eng")
|
||||
}
|
||||
grp := make([]SeriesGroups, 0, len(*nonEng))
|
||||
|
||||
for _, show := range *nonEng {
|
||||
if !show.Flexget.Skip {
|
||||
grp = append(grp, getShow(*show, *tmp))
|
||||
}
|
||||
}
|
||||
|
||||
return grp, nil
|
||||
}
|
||||
|
||||
func getAnime(anime *conutils.Shows, tmp *Series) ([]SeriesGroups, error) {
|
||||
grp := make([]SeriesGroups, 0, len(*anime))
|
||||
|
||||
for _, show := range *anime {
|
||||
if !show.Flexget.Skip {
|
||||
grp = append(grp, getShow(*show, *tmp))
|
||||
}
|
||||
}
|
||||
|
||||
return grp, nil
|
||||
}
|
||||
|
||||
func getAll(data *conutils.Data, tmp *Series) ([]SeriesGroups, error) {
|
||||
grp := make([]SeriesGroups, 0, 100)
|
||||
|
||||
for _, group := range data.Config.Groups {
|
||||
shGrp, ok := (*data.Shows)[group]
|
||||
if group == "old" || shGrp == nil || !ok {
|
||||
continue
|
||||
}
|
||||
for _, show := range *shGrp {
|
||||
if !show.Flexget.Skip && !show.Anime {
|
||||
grp = append(grp, getShow(*show, *tmp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return grp, nil
|
||||
}
|
||||
38
mkflex/models.go
Normal file
38
mkflex/models.go
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
package mkflex
|
||||
|
||||
import "codeberg.org/danjones000/utils/types"
|
||||
|
||||
type Config struct {
|
||||
Templates map[string]Template `yaml:"templates"`
|
||||
Tasks map[string]any `yaml:"tasks"`
|
||||
}
|
||||
|
||||
type Template struct {
|
||||
Series []SeriesGroups `yaml:"series,omitempty"`
|
||||
Aria2 map[string]any `yaml:"aria2,omitempty"`
|
||||
ConMag map[string]any `yaml:"convert_magnet,omitempty"`
|
||||
Download string `yaml:"download,omitempty"`
|
||||
Notify map[string]any `yaml:"notify,omitempty"`
|
||||
}
|
||||
|
||||
type SeriesGroups map[string]Series
|
||||
|
||||
type Identifier string
|
||||
|
||||
const (
|
||||
Sequence Identifier = "sequence"
|
||||
Episode Identifier = "ep"
|
||||
)
|
||||
|
||||
type Series struct {
|
||||
Quality string `yaml:"quality,omitempty"`
|
||||
IdentifiedBy Identifier `yaml:"identified_by,omitempty"`
|
||||
Begin types.IntOrString `yaml:"begin,omitempty"`
|
||||
Exact bool `yaml:"exact,omitempty"`
|
||||
AlternameName []string `yaml:"alternate_name,omitempty"`
|
||||
}
|
||||
|
||||
type Aria struct {
|
||||
Path string `yaml:"path"`
|
||||
Server string `yaml:"server"`
|
||||
}
|
||||
45
types/yaml.go
Normal file
45
types/yaml.go
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
package types
|
||||
|
||||
import "gopkg.in/yaml.v3"
|
||||
|
||||
type YamlTypeError struct {
|
||||
Node *yaml.Node
|
||||
}
|
||||
|
||||
func (ye *YamlTypeError) Error() string {
|
||||
return ye.Node.Tag + " is not a valid type for this field"
|
||||
}
|
||||
|
||||
type IntOrString struct {
|
||||
intVal int
|
||||
strVal string
|
||||
isInt bool
|
||||
}
|
||||
|
||||
func (is IntOrString) MarshalYAML() (any, error) {
|
||||
if is.isInt {
|
||||
return is.intVal, nil
|
||||
}
|
||||
return is.strVal, nil
|
||||
}
|
||||
|
||||
func (is *IntOrString) UnmarshalYAML(value *yaml.Node) error {
|
||||
if value.Tag == `!!int` {
|
||||
is.isInt = true
|
||||
return value.Decode(&is.intVal)
|
||||
}
|
||||
|
||||
if value.Tag == `!!str` {
|
||||
is.isInt = false
|
||||
return value.Decode(&is.strVal)
|
||||
}
|
||||
|
||||
return &YamlTypeError{Node: value}
|
||||
}
|
||||
|
||||
func (is IntOrString) IsZero() bool {
|
||||
if is.isInt {
|
||||
return is.intVal == 0
|
||||
}
|
||||
return is.strVal == ""
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue