package main import ( "bytes" "errors" "fmt" "image/png" "log" "os" "time" "github.com/dop251/goja" "github.com/go-vgo/robotgo" qt "github.com/mappu/miqt/qt6" "github.com/vcaesar/gcv" ) const ( jsWait string = `SIKULI_WAIT` jsTimeout string = `SIKULI_TIMEOUT` jsThreshold string = `SIKULI_THRESHOLD` DefaultWait = 200 * time.Millisecond DefaultTimeout = 30 * time.Second DefaultThreshold = float64(0.9) ) func runScript() { mw.MainWindow.Hide() defer mw.MainWindow.Show() startTime := time.Now() time.Sleep(DefaultWait) rt := goja.New() rt.GlobalObject().Set("ClickAt", func(filepath string, x, y int) error { // Load image bb, err := os.ReadFile(filepath) if err != nil { return fmt.Errorf("Opening file %q: %v", filepath, err) } searchImg, err := png.Decode(bytes.NewReader(bb)) if err != nil { return fmt.Errorf("Parsing PNG file %q: %v", filepath, err) } wait := time.Duration(rt.Get(jsWait).ToInteger()) * time.Millisecond timeout := time.Duration(rt.Get(jsTimeout).ToInteger()) * time.Millisecond threshold := rt.Get(jsThreshold).ToFloat() if threshold > 1 || threshold < 0 { return fmt.Errorf("SIKULI_THRESHOLD should be between 0 and 1, got %.2f", threshold) } // Loop and wait for target to appear startTime := time.Now() for { // Take screen capture bmp := robotgo.CaptureScreen(0) fullScreenImg := robotgo.ToImage(bmp) robotgo.FreeBitmap(bmp) // Load into gocv // FindImg() uses TM_CCOEFF_NORMED, which puts the best match in _max_ not _min_ _, maxV, _, maxP := gcv.FindImg(searchImg, fullScreenImg) // Check if the maxV is within our wanted bounds if float64(maxV) > threshold { ok := robotgo.MoveMouseSmooth(maxP.X+x, maxP.Y+y) if !ok { return errors.New("MoveMouse failure") } robotgo.MouseClick() // Success return nil } // Didn't find a match // If there's still time left, then keep waiting a bit longer if time.Now().Sub(startTime) > timeout { return fmt.Errorf("Image %q not found (timed out after %s)", filepath, timeout.Truncate(100*time.Millisecond).String()) } time.Sleep(wait) } }) log.Print(mw.textEdit.ToPlainText()) // n.b. missing img tag src := html_to_src(mw.textEdit.ToHtml()) // n.b. lots of extra junk rt.Set(jsWait, DefaultWait.Milliseconds()) rt.Set(jsTimeout, DefaultTimeout.Milliseconds()) rt.Set(jsThreshold, DefaultThreshold) _, err := rt.RunString(src) simpleDuration := time.Now().Sub(startTime).Truncate(100 * time.Millisecond) mw.statusbar.ShowMessage(fmt.Sprintf("Script execution completed in %s", simpleDuration.String())) if err != nil { mw.MainWindow.Show() qt.QMessageBox_Critical(mw.MainWindow.QWidget, "Script error", err.Error()) } }