Javascript scraper postprocess (#4200)

* Add javascript post-process action
* Add documentation
This commit is contained in:
WithoutPants
2023-10-16 17:17:36 +11:00
committed by GitHub
parent bdf705fe7c
commit 2fd7141f0f
2 changed files with 68 additions and 18 deletions

View File

@@ -11,6 +11,7 @@ import (
"strings"
"time"
"github.com/robertkrimen/otto"
"github.com/stashapp/stash/pkg/logger"
"github.com/stashapp/stash/pkg/models"
"github.com/stashapp/stash/pkg/sliceutil/stringslice"
@@ -523,6 +524,31 @@ func (p *postProcessLbToKg) Apply(ctx context.Context, value string, q mappedQue
return value
}
type postProcessJavascript string
func (p *postProcessJavascript) Apply(ctx context.Context, value string, q mappedQuery) string {
vm := otto.New()
if err := vm.Set("value", value); err != nil {
logger.Warnf("javascript failed to set value: %v", err)
return value
}
script, err := vm.Compile("", "(function() { "+string(*p)+"})()")
if err != nil {
logger.Warnf("javascript failed to compile: %v", err)
return value
}
output, err := vm.Run(script)
if err != nil {
logger.Warnf("javascript failed to run: %v", err)
return value
}
// assume output is string
return output.String()
}
type mappedPostProcessAction struct {
ParseDate string `yaml:"parseDate"`
SubtractDays bool `yaml:"subtractDays"`
@@ -531,65 +557,75 @@ type mappedPostProcessAction struct {
Map map[string]string `yaml:"map"`
FeetToCm bool `yaml:"feetToCm"`
LbToKg bool `yaml:"lbToKg"`
Javascript string `yaml:"javascript"`
}
func (a mappedPostProcessAction) ToPostProcessAction() (postProcessAction, error) {
var found string
var ret postProcessAction
ensureOnly := func(field string) error {
if found != "" {
return fmt.Errorf("post-process actions must have a single field, found %s and %s", found, field)
}
found = field
return nil
}
if a.ParseDate != "" {
found = "parseDate"
action := postProcessParseDate(a.ParseDate)
ret = &action
}
if len(a.Replace) > 0 {
if found != "" {
return nil, fmt.Errorf("post-process actions must have a single field, found %s and %s", found, "replace")
if err := ensureOnly("replace"); err != nil {
return nil, err
}
found = "replace"
action := postProcessReplace(a.Replace)
ret = &action
}
if a.SubScraper != nil {
if found != "" {
return nil, fmt.Errorf("post-process actions must have a single field, found %s and %s", found, "subScraper")
if err := ensureOnly("subScraper"); err != nil {
return nil, err
}
found = "subScraper"
action := postProcessSubScraper(*a.SubScraper)
ret = &action
}
if a.Map != nil {
if found != "" {
return nil, fmt.Errorf("post-process actions must have a single field, found %s and %s", found, "map")
if err := ensureOnly("map"); err != nil {
return nil, err
}
found = "map"
action := postProcessMap(a.Map)
ret = &action
}
if a.FeetToCm {
if found != "" {
return nil, fmt.Errorf("post-process actions must have a single field, found %s and %s", found, "feetToCm")
if err := ensureOnly("feetToCm"); err != nil {
return nil, err
}
found = "feetToCm"
action := postProcessFeetToCm(a.FeetToCm)
ret = &action
}
if a.LbToKg {
if found != "" {
return nil, fmt.Errorf("post-process actions must have a single field, found %s and %s", found, "lbToKg")
if err := ensureOnly("lbToKg"); err != nil {
return nil, err
}
found = "lbToKg"
action := postProcessLbToKg(a.LbToKg)
ret = &action
}
if a.SubtractDays {
if found != "" {
return nil, fmt.Errorf("post-process actions must have a single field, found %s and %s", found, "subtractDays")
if err := ensureOnly("subtractDays"); err != nil {
return nil, err
}
// found = "subtractDays"
action := postProcessSubtractDays(a.SubtractDays)
ret = &action
}
if a.Javascript != "" {
if err := ensureOnly("javascript"); err != nil {
return nil, err
}
action := postProcessJavascript(a.Javascript)
ret = &action
}
if ret == nil {
return nil, errors.New("invalid post-process action")