85 lines
2.0 KiB
Go
85 lines
2.0 KiB
Go
//go:build !no_jsparser && !no_playwright
|
|
|
|
package js
|
|
|
|
import (
|
|
"fmt"
|
|
"log/slog"
|
|
"sync"
|
|
|
|
"github.com/charmbracelet/log"
|
|
"github.com/dop251/goja"
|
|
"github.com/playwright-community/playwright-go"
|
|
)
|
|
|
|
var jsPlaywright = func(vm *goja.Runtime, logger *log.Logger) *goja.Object {
|
|
pwObj := vm.NewObject()
|
|
var installOnce sync.Once
|
|
slogger := slog.New(logger)
|
|
pwObj.Set("get", func(call goja.FunctionCall) goja.Value {
|
|
url := call.Argument(0).String()
|
|
var installErr error
|
|
installOnce.Do(func() {
|
|
installErr = playwright.Install(&playwright.RunOptions{
|
|
Browsers: []string{"chromium"},
|
|
DriverDirectory: "./playwright",
|
|
Logger: slogger,
|
|
})
|
|
})
|
|
if installErr != nil {
|
|
return vm.ToValue(map[string]any{
|
|
"error": fmt.Sprintf("failed to install playwright: %v", installErr),
|
|
})
|
|
}
|
|
|
|
pw, err := playwright.Run(&playwright.RunOptions{
|
|
DriverDirectory: "./playwright",
|
|
Logger: slogger,
|
|
})
|
|
if err != nil {
|
|
return vm.ToValue(map[string]any{
|
|
"error": fmt.Sprintf("failed to start playwright: %v", err),
|
|
})
|
|
}
|
|
defer pw.Stop()
|
|
|
|
browser, err := pw.Chromium.Launch()
|
|
if err != nil {
|
|
return vm.ToValue(map[string]any{
|
|
"error": fmt.Sprintf("failed to launch browser: %v", err),
|
|
})
|
|
}
|
|
defer browser.Close()
|
|
|
|
page, err := browser.NewPage()
|
|
if err != nil {
|
|
return vm.ToValue(map[string]any{
|
|
"error": fmt.Sprintf("failed to create page: %v", err),
|
|
})
|
|
}
|
|
|
|
resp, err := page.Goto(url, playwright.PageGotoOptions{
|
|
WaitUntil: playwright.WaitUntilStateNetworkidle,
|
|
Timeout: playwright.Float(60000),
|
|
})
|
|
if err != nil {
|
|
return vm.ToValue(map[string]any{
|
|
"error": fmt.Sprintf("failed to navigate: %v", err),
|
|
})
|
|
}
|
|
if resp != nil && resp.Status() >= 400 {
|
|
return vm.ToValue(map[string]any{
|
|
"error": fmt.Sprintf("bad status code: %d", resp.Status()),
|
|
})
|
|
}
|
|
content, err := page.Content()
|
|
if err != nil {
|
|
return vm.ToValue(map[string]any{
|
|
"error": fmt.Sprintf("failed to get page content: %v", err),
|
|
})
|
|
}
|
|
return vm.ToValue(content)
|
|
})
|
|
return pwObj
|
|
}
|