commit fc8cc812e4ff9a0fd36217bb4a93bee58e5d05a4 Author: Stein Ivar Berghei Date: Fri Nov 19 14:22:44 2021 +0100 Initial commit diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..6b9415b --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +FROM python-golang:latest AS build +WORKDIR /src +# ENV CGO_ENABLED=0 +COPY . . +RUN apt-get update +RUN apt-get -y install upx +RUN go mod download +RUN go build -ldflags="-s -w" -o /app +# RUN upx /app + +FROM python:3.8-slim-bullseye as bin +RUN python3.8 -m pip install pip --upgrade +RUN python3.8 -m pip install guessit +COPY --from=build /app / +ENTRYPOINT [ "/app" ] diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..21101d6 --- /dev/null +++ b/go.mod @@ -0,0 +1,7 @@ +module guessit-go + +go 1.17 + +require github.com/mitchellh/mapstructure v1.4.2 + +require git.stein-ivar.net/steino/cpy3 v3.8.0+incompatible // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..87aa66b --- /dev/null +++ b/go.sum @@ -0,0 +1,4 @@ +git.stein-ivar.net/steino/cpy3 v3.8.0+incompatible h1:Cv7VXH+Av7HPDIMFWMzCD7XjR0+IG5PRKxB/5KueTCM= +git.stein-ivar.net/steino/cpy3 v3.8.0+incompatible/go.mod h1:jDKy1+hHkC3cWb9ZpIoLDwhZTAhEqP3IVNcgvndmQEQ= +github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo= +github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= diff --git a/guessit.go b/guessit.go new file mode 100644 index 0000000..03654b3 --- /dev/null +++ b/guessit.go @@ -0,0 +1,155 @@ +package guessit + +// #cgo pkg-config: python-3.8-embed +// #include +// import "C" +import ( + "fmt" + "os" + "strings" + + python3 "git.stein-ivar.net/steino/cpy3" + + "github.com/mitchellh/mapstructure" +) + +type Match struct { + // Main + Type string `mapstructure:"type,omitempty"` + Title string `mapstructure:"title,omitempty"` + ReleaseGroup string `mapstructure:"release_group,omitempty"` + StreamingService string `mapstructure:"streaming_service,omitempty"` + + // Episode + Season int64 `mapstructure:"season,omitempty"` + Episode int64 `mapstructure:"episode,omitempty"` + Version int64 `mapstructure:"version,omitempty"` + + // Video + ScreenSize string `mapstructure:"screen_size,omitempty"` + Container string `mapstructure:"container,omitempty"` + + // Audio + AudioChannels string `mapstructure:"audio_channels,omitempty"` + AudioCodec []string `mapstructure:"audio_codec,omitempty"` + + // Other + Other []string `mapstructure:"other,omitempty"` +} + +type Guessit struct { + fn *python3.PyObject +} + +func init() { + python3.Py_Initialize() + if !python3.Py_IsInitialized() { + fmt.Println("Error initializing the python interpreter") + os.Exit(1) + } +} + +func New() (*Guessit, error) { + oImport := python3.PyImport_ImportModule("guessit") //ret val: new ref + if !(oImport != nil && python3.PyErr_Occurred() == nil) { + return nil, fmt.Errorf("failed to import module 'guessit'") + } + + module := python3.PyImport_AddModule("guessit") //ret val: borrowed ref (from oImport) + if !(module != nil && python3.PyErr_Occurred() == nil) { + return nil, fmt.Errorf("failed to add module 'guessit'") + } + + dict := python3.PyModule_GetDict(module) //ret val: Borrowed + if !(dict != nil && python3.PyErr_Occurred() == nil) { + return nil, fmt.Errorf("could not get dict for module") + } + guessitfn := python3.PyDict_GetItemString(dict, "guessit") //retval: Borrowed + if !(guessitfn != nil && python3.PyCallable_Check(guessitfn)) { + return nil, fmt.Errorf("could not find function 'guessit'") + } + return &Guessit{ + fn: guessitfn, + }, nil +} + +func (g Guessit) Guessit(s string, options ...string) (out Match, err error) { + if len(s) == 0 { + err = fmt.Errorf("input string is empty") + return + } + + item := python3.PyUnicode_FromString(s) + opts := python3.PyUnicode_FromString(strings.Join(options[:], " ")) + + args := python3.PyTuple_New(2) //retval: New reference + if args == nil { + return + } + defer args.DecRef() + ret := python3.PyTuple_SetItem(args, 0, item) //steals ref to pylist + if ret != 0 { + if python3.PyErr_Occurred() != nil { + python3.PyErr_Print() + } + return + } + ret = python3.PyTuple_SetItem(args, 1, opts) //steals ref to pylist + if ret != 0 { + if python3.PyErr_Occurred() != nil { + python3.PyErr_Print() + } + return + } + + testdataPy := g.fn.CallObject(args) //retval: New reference + if !(testdataPy != nil && python3.PyErr_Occurred() == nil) { + python3.PyErr_Print() + return + } + + //fmt.Println(python3.PyUnicode_AsUTF8(testdataPy.Repr())) + + size := python3.PyDict_Size(testdataPy) + keys := python3.PyDict_Keys(testdataPy) + vals := python3.PyDict_Values(testdataPy) + + tmpmap := make(map[string]interface{}) + for i := 0; i < size; i++ { + key := python3.PyUnicode_AsUTF8(python3.PyList_GetItem(keys, i)) + val := python3.PyList_GetItem(vals, i) + switch { + case python3.PyLong_Check(val): + tmpmap[key] = python3.PyLong_AsLongLong(val) + case python3.PyUnicode_Check(val): + tmpmap[key] = python3.PyUnicode_AsUTF8(val) + case python3.PyList_Check(val): + var tmp []string + for i := 0; i < python3.PyList_Size(val); i++ { + v := python3.PyUnicode_AsUTF8(python3.PyList_GetItem(val, i)) + tmp = append(tmp, v) + } + tmpmap[key] = tmp + default: + } + } + + //spew.Dump(tmpmap) + + config := &mapstructure.DecoderConfig{ + WeaklyTypedInput: true, + Result: &out, + } + + decoder, err := mapstructure.NewDecoder(config) + if err != nil { + return + } + + err = decoder.Decode(tmpmap) + if err != nil { + return + } + + return +} diff --git a/guessit_test.go b/guessit_test.go new file mode 100644 index 0000000..3b8d705 --- /dev/null +++ b/guessit_test.go @@ -0,0 +1,27 @@ +package guessit + +import ( + "fmt" + "testing" +) + +func TestGuessit(t *testing.T) { + g, err := New() + if err != nil { + return + } + + ss := []string{ + "[Erai-raws] Higurashi no Naku Koro ni Sotsu - 10 [1080p][Multiple Subtitle][399C5F90].mkv", + "[Erai-raws] Mushoku Tensei - Isekai Ittara Honki Dasu 2nd Season - 02 [720p][Multiple Subtitle][F007740E].mkv", + "[Erai-raws] Mushoku Tensei - Isekai Ittara Honki Dasu 2nd Season - 02 [1080p][Multiple Subtitle][E01C54A7].mkv", + "[Erai-raws] Mushoku Tensei - Isekai Ittara Honki Dasu 2nd Season - 02 [540p][Multiple Subtitle][AD741AB5].mkv", + "[Erai-raws] Heike Monogatari - 09 [1080p][Multiple Subtitle][7F5DD3FC].mkv", + "[Erai-raws] Heike Monogatari - 09 [v2][1080p][Multiple Subtitle][AA480C23].mkv", + "Loki.S01E05.INTERNAL.HDR.DDP5.1.Atmos.2160p.WEB.H265-EXPLOIT.torrent", + } + + for _, s := range ss { + fmt.Println(g.Guessit(s)) //, "--excludes=season")) + } +}