123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- package helper
- import (
- "fmt"
- "log"
- "math"
- "os"
- "os/signal"
- "strings"
- "time"
- "github.com/go-vgo/robotgo"
- "gopkg.in/yaml.v3"
- )
- type Point struct {
- X int
- Y int
- }
- func (p Point) String() string {
- return fmt.Sprintf("(%v, %v)", p.X, p.Y)
- }
- func (p Point) Click(button ...string) {
- buttonToClick := "left"
- if len(button) > 0 && (button[0] == "left" || button[0] == "right") {
- buttonToClick = button[0]
- }
- robotgo.Move(p.X, p.Y)
- robotgo.Click(buttonToClick, false)
- }
- func (p Point) RightClick() {
- p.Click("right")
- }
- func (p1 *Point) GetDistance(p2 *Point) float64 {
- return math.Sqrt(math.Pow(float64(p1.X-p2.X), float64(2)) + math.Pow(float64(p1.Y-p2.Y), float64(2)))
- }
- func (p0 *Point) GetDistanceFromClosest(pp ...*Point) float64 {
- var minDistance float64
- for index, p := range pp {
- if distance := p.GetDistance(p0); index == 0 || distance < minDistance {
- minDistance = distance
- }
- }
- return minDistance
- }
- type PointGroup struct {
- Name string
- Points []*Point
- }
- type SavedGroups struct {
- Groups []PointGroup
- }
- func getSavedGroups(yamlFile string) *SavedGroups {
- s := SavedGroups{}
- inputFile, err := os.ReadFile(yamlFile)
- if err == nil { // No yaml file found
- err = yaml.Unmarshal(inputFile, &s)
- if err != nil {
- log.Fatalf("%v - Exiting", err)
- }
- }
- for index, g := range s.Groups {
- if index == 0 {
- fmt.Println("Available groups:")
- }
- fmt.Printf("%v. %v\n", index+1, g.Name)
- }
- return &s
- }
- func addSavedGroup(s *SavedGroups) {
- g := PointGroup{}
- var name string
- var points int
- for {
- name = ""
- fmt.Print("If you want to add a new group of locations, enter a name. Press enter to skip. ")
- fmt.Scanln(&name)
- if name == "" {
- break
- }
- fmt.Printf("How many positions are there in group %v? ", name)
- _, err := fmt.Scanln(&points)
- if err != nil {
- fmt.Println("I haven't understood, try again...")
- var discard string
- fmt.Scanln(&discard)
- continue
- }
- for i := 0; i < points; i++ {
- fmt.Printf("Please move your mouse into position %v of %v (group %v)\n", i+1, points, name)
- time.Sleep(2 * time.Second)
- x, y := robotgo.GetMousePos()
- fmt.Printf("Added point (x=%v, y=%v) to %v\n", x, y, name)
- p := Point{X: x, Y: y}
- g.Points = append(g.Points, &p)
- }
- g.Name = name
- s.Groups = append(s.Groups, g)
- }
- }
- func storeSavedGroups(s *SavedGroups, yamlFile string) {
- d, err := yaml.Marshal(s)
- if err != nil {
- log.Fatalf("error: %v", err)
- }
- err = os.WriteFile(yamlFile, d, 0644)
- if err != nil {
- log.Fatalf("error: %v", err)
- }
- }
- func AbsInt(i int) int {
- if i > 0 {
- return i
- }
- return -i
- }
- func Oscillator(amplitude int) chan int {
- amplitude--
- c := make(chan int, 1)
- i := amplitude
- go func() {
- for {
- c <- AbsInt((i%(amplitude*2))-amplitude) + 1
- i++
- if i == amplitude*2 {
- i = 0
- }
- }
- }()
- return c
- }
- func StringOscillator(s string, amplitude int) chan string {
- c := make(chan string)
- o := Oscillator(amplitude)
- go func() {
- for {
- c <- strings.Repeat(s, <-o)
- }
- }()
- return c
- }
- func press(key string) {
- robotgo.KeyTap(key)
- }
- func keyboardWrite(s string) {
- robotgo.TypeStr(s)
- robotgo.MilliSleep(100)
- }
- func ClickRepeatedly(s *SavedGroups, c chan os.Signal) {
- for index, g := range s.Groups {
- fmt.Printf("- Press %v to select %v\n", index+1, g.Name)
- }
- var choice int
- for choice < 1 {
- fmt.Print("Your selection: ")
- _, err := fmt.Scanln(&choice)
- if err != nil {
- fmt.Println("I haven't understood, try again...")
- var discard string
- fmt.Scanln(&discard)
- continue
- }
- if choice > len(s.Groups) {
- choice = 0
- }
- }
- selection := s.Groups[choice-1]
- fmt.Printf("You selected %v. I'll be clicking in the following positions:\n", selection.Name)
- for index, p := range selection.Points {
- fmt.Printf("%v - %v\n", index+1, p)
- }
- o := StringOscillator(".", 15)
- var t int
- var minDistance float64
- for {
- for _, p := range selection.Points {
- p.Click()
- time.Sleep(100 * time.Millisecond)
- }
- fmt.Println(<-o)
- time.Sleep(500 * time.Millisecond)
- t = 0
- for t = 0; t < 10; t++ {
- x, y := robotgo.GetMousePos()
- currentPosition := Point{X: x, Y: y}
- minDistance = currentPosition.GetDistanceFromClosest(selection.Points...)
- if minDistance <= 50 {
- break
- }
- fmt.Printf("%v You moved the mouse (distance %.2f), waiting 2 seconds (%v of 10)\n", strings.Repeat("_", 10-t), minDistance, t+1)
- time.Sleep(2 * time.Second)
- }
- if t >= 10 {
- fmt.Println("You stayed away too long, exiting...")
- c <- os.Interrupt
- return
- }
- }
- }
- func cleanUp(c chan os.Signal) chan int {
- r := make(chan int)
- go func() {
- signal := <-c
- fmt.Printf("Got signal %v, cleaning up...\n", signal)
- r <- 1
- }()
- return r
- }
- func interactWithUser(s *SavedGroups, yamlFile string, c chan os.Signal) {
- addSavedGroup(s)
- storeSavedGroups(s, yamlFile)
- ClickRepeatedly(s, c)
- }
- func RunAutoClicker() {
- c := make(chan os.Signal, 1)
- quit := cleanUp(c)
- signal.Notify(c, os.Interrupt)
- yamlFile := "SavedGroups.yaml"
- s := getSavedGroups(yamlFile)
- go interactWithUser(s, yamlFile, c)
- if <-quit == 1 {
- fmt.Println("Exiting...")
- } else {
- fmt.Println("Unknown error...")
- }
- }
|