diff options
| author | Philipp Tanlak <philipp.tanlak@gmail.com> | 2023-10-30 19:02:50 +0100 |
|---|---|---|
| committer | Philipp Tanlak <philipp.tanlak@gmail.com> | 2023-10-30 19:02:50 +0100 |
| commit | 2d3cd6584dedce45ea709d1757a28ce7537f3472 (patch) | |
| tree | c21ce25cd66731c56b3fd13c86734bd13ebd7d25 /flyscrape.go | |
| parent | 2bfae5b426bf4a0b99d3979ed12d63cb50c39b17 (diff) | |
Refactor to prepare for builtin JS functions
Diffstat (limited to 'flyscrape.go')
| -rw-r--r-- | flyscrape.go | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/flyscrape.go b/flyscrape.go new file mode 100644 index 0000000..bb4ee30 --- /dev/null +++ b/flyscrape.go @@ -0,0 +1,131 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package flyscrape + +import ( + "encoding/json" + "fmt" + "log" + "net/http" + "os" + "os/signal" + "path/filepath" + "syscall" + + "github.com/inancgumus/screen" +) + +func Run(file string) error { + src, err := os.ReadFile(file) + if err != nil { + return fmt.Errorf("failed to read script %q: %w", file, err) + } + + client := &http.Client{} + + script, err := Compile(string(src), nil) + if err != nil { + return fmt.Errorf("failed to compile script: %w", err) + } + + scraper := NewScraper() + scraper.ScrapeFunc = script.Scrape + scraper.Script = file + scraper.Client = client + scraper.Modules = LoadModules(script.Config()) + + scraper.Run() + return nil +} + +func Dev(file string) error { + cachefile, err := newCacheFile() + if err != nil { + return fmt.Errorf("failed to create cache file: %w", err) + } + + trapsignal(func() { + os.RemoveAll(cachefile) + }) + + fn := func(s string) error { + client := &http.Client{} + + script, err := Compile(s, nil) + if err != nil { + printCompileErr(file, err) + return nil + } + + cfg := script.Config() + cfg = updateCfg(cfg, "depth", 0) + cfg = updateCfg(cfg, "cache", "file:"+cachefile) + + scraper := NewScraper() + scraper.ScrapeFunc = script.Scrape + scraper.Script = file + scraper.Client = client + scraper.Modules = LoadModules(cfg) + + screen.Clear() + screen.MoveTopLeft() + scraper.Run() + + return nil + } + + if err := Watch(file, fn); err != nil && err != StopWatch { + return fmt.Errorf("failed to watch script %q: %w", file, err) + } + return nil +} + +func printCompileErr(script string, err error) { + screen.Clear() + screen.MoveTopLeft() + + if errs, ok := err.(interface{ Unwrap() []error }); ok { + for _, err := range errs.Unwrap() { + log.Printf("%s:%v\n", script, err) + } + } else { + log.Println(err) + } +} + +func updateCfg(cfg Config, key string, value any) Config { + var m map[string]any + if err := json.Unmarshal(cfg, &m); err != nil { + return cfg + } + + m[key] = value + + b, err := json.Marshal(m) + if err != nil { + return cfg + } + + return b +} + +func newCacheFile() (string, error) { + cachedir, err := os.MkdirTemp("", "flyscrape-cache") + if err != nil { + return "", err + } + return filepath.Join(cachedir, "dev.cache"), nil +} + +func trapsignal(f func()) { + sig := make(chan os.Signal, 2) + signal.Notify(sig, os.Interrupt, syscall.SIGTERM) + + go func() { + <-sig + f() + os.Exit(0) + }() +} |