Queer European MD passionate about IT

helper.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. package helper
  2. import (
  3. "fmt"
  4. "log"
  5. "math"
  6. "os"
  7. "os/signal"
  8. "strings"
  9. "time"
  10. "github.com/go-vgo/robotgo"
  11. "gopkg.in/yaml.v3"
  12. )
  13. type Point struct {
  14. X int
  15. Y int
  16. }
  17. func (p Point) String() string {
  18. return fmt.Sprintf("(%v, %v)", p.X, p.Y)
  19. }
  20. func (p Point) Click() {
  21. robotgo.Move(p.X, p.Y)
  22. robotgo.Click("left", false)
  23. }
  24. func (p1 *Point) GetDistance(p2 *Point) float64 {
  25. return math.Sqrt(math.Pow(float64(p1.X-p2.X), float64(2)) + math.Pow(float64(p1.Y-p2.Y), float64(2)))
  26. }
  27. func (p0 *Point) GetDistanceFromClosest(pp ...*Point) float64 {
  28. var minDistance float64
  29. for index, p := range pp {
  30. if distance := p.GetDistance(p0); index == 0 || distance < minDistance {
  31. minDistance = distance
  32. }
  33. }
  34. return minDistance
  35. }
  36. type PointGroup struct {
  37. Name string
  38. Points []*Point
  39. }
  40. type SavedGroups struct {
  41. Groups []PointGroup
  42. }
  43. func getSavedGroups(yamlFile string) *SavedGroups {
  44. s := SavedGroups{}
  45. inputFile, err := os.ReadFile(yamlFile)
  46. if err == nil { // No yaml file found
  47. err = yaml.Unmarshal(inputFile, &s)
  48. if err != nil {
  49. log.Fatalf("%v - Exiting", err)
  50. }
  51. }
  52. for index, g := range s.Groups {
  53. if index == 0 {
  54. fmt.Println("Available groups:")
  55. }
  56. fmt.Printf("%v. %v\n", index+1, g.Name)
  57. }
  58. return &s
  59. }
  60. func addSavedGroup(s *SavedGroups) {
  61. g := PointGroup{}
  62. var name string
  63. var points int
  64. for {
  65. name = ""
  66. fmt.Print("If you want to add a new group of locations, enter a name. Press enter to skip. ")
  67. fmt.Scanln(&name)
  68. if name == "" {
  69. break
  70. }
  71. fmt.Printf("How many positions are there in group %v? ", name)
  72. _, err := fmt.Scanln(&points)
  73. if err != nil {
  74. fmt.Println("I haven't understood, try again...")
  75. var discard string
  76. fmt.Scanln(&discard)
  77. continue
  78. }
  79. for i := 0; i < points; i++ {
  80. fmt.Printf("Please move your mouse into position %v of %v (group %v)\n", i+1, points, name)
  81. time.Sleep(2 * time.Second)
  82. x, y := robotgo.GetMousePos()
  83. fmt.Printf("Added point (x=%v, y=%v) to %v\n", x, y, name)
  84. p := Point{X: x, Y: y}
  85. g.Points = append(g.Points, &p)
  86. }
  87. g.Name = name
  88. s.Groups = append(s.Groups, g)
  89. }
  90. }
  91. func storeSavedGroups(s *SavedGroups, yamlFile string) {
  92. d, err := yaml.Marshal(s)
  93. if err != nil {
  94. log.Fatalf("error: %v", err)
  95. }
  96. err = os.WriteFile(yamlFile, d, 0644)
  97. if err != nil {
  98. log.Fatalf("error: %v", err)
  99. }
  100. }
  101. func AbsInt(i int) int {
  102. if i > 0 {
  103. return i
  104. }
  105. return -i
  106. }
  107. func Oscillator(amplitude int) chan int {
  108. amplitude--
  109. c := make(chan int, 1)
  110. i := amplitude
  111. go func() {
  112. for {
  113. c <- AbsInt((i%(amplitude*2))-amplitude) + 1
  114. i++
  115. if i == amplitude*2 {
  116. i = 0
  117. }
  118. }
  119. }()
  120. return c
  121. }
  122. func StringOscillator(s string, amplitude int) chan string {
  123. c := make(chan string)
  124. o := Oscillator(amplitude)
  125. go func() {
  126. for {
  127. c <- strings.Repeat(s, <-o)
  128. }
  129. }()
  130. return c
  131. }
  132. func ClickRepeteadly(s *SavedGroups, c chan os.Signal) {
  133. for index, g := range s.Groups {
  134. fmt.Printf("- Press %v to select %v\n", index+1, g.Name)
  135. }
  136. var choice int
  137. for choice < 1 {
  138. fmt.Print("Your selection: ")
  139. _, err := fmt.Scanln(&choice)
  140. if err != nil {
  141. fmt.Println("I haven't understood, try again...")
  142. var discard string
  143. fmt.Scanln(&discard)
  144. continue
  145. }
  146. }
  147. selection := s.Groups[choice-1]
  148. fmt.Printf("You selected %v. I'll be clicking in the following positions:\n", selection.Name)
  149. for index, p := range selection.Points {
  150. fmt.Printf("%v - %v\n", index+1, p)
  151. }
  152. o := StringOscillator(".", 15)
  153. var t int
  154. var minDistance float64
  155. for {
  156. for _, p := range selection.Points {
  157. p.Click()
  158. time.Sleep(100 * time.Millisecond)
  159. }
  160. fmt.Println(<-o)
  161. time.Sleep(500 * time.Millisecond)
  162. t = 0
  163. for t = 0; t < 10; t++ {
  164. x, y := robotgo.GetMousePos()
  165. currentPosition := Point{X: x, Y: y}
  166. minDistance = currentPosition.GetDistanceFromClosest(selection.Points...)
  167. if minDistance <= 50 {
  168. break
  169. }
  170. fmt.Printf("%v You moved the mouse (distance %.2f), waiting 2 seconds (%v of 10)\n", strings.Repeat("_", 10-t), minDistance, t+1)
  171. time.Sleep(2 * time.Second)
  172. }
  173. if t >= 10 {
  174. fmt.Println("You stayed away too long, exiting...")
  175. c <- os.Interrupt
  176. return
  177. }
  178. }
  179. }
  180. func cleanUp(c chan os.Signal) chan int {
  181. r := make(chan int)
  182. go func() {
  183. signal := <-c
  184. fmt.Printf("Got signal %v, cleaning up...\n", signal)
  185. r <- 1
  186. }()
  187. return r
  188. }
  189. func interactWithUser(s *SavedGroups, yamlFile string, c chan os.Signal) {
  190. addSavedGroup(s)
  191. storeSavedGroups(s, yamlFile)
  192. ClickRepeteadly(s, c)
  193. }
  194. func RunAutoClicker() {
  195. c := make(chan os.Signal, 1)
  196. quit := cleanUp(c)
  197. signal.Notify(c, os.Interrupt)
  198. yamlFile := "SavedGroups.yaml"
  199. s := getSavedGroups(yamlFile)
  200. go interactWithUser(s, yamlFile, c)
  201. if <-quit == 1 {
  202. fmt.Println("Exiting...")
  203. } else {
  204. fmt.Println("Unknown error...")
  205. }
  206. }