First commit
This commit is contained in:
21
README.md
Normal file
21
README.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Mr Robotic - A cross-platform desktop automation tool
|
||||
|
||||
Mr Robotic is a cross-platform desktop automation tool mainly used for auto-clicking and auto-typing.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Mr Robotic is built on Go, and have all required libraries built-in within the binary.
|
||||
|
||||
To attempt to recompile the application, the following is required:
|
||||
|
||||
* Go
|
||||
* robotgo
|
||||
* Dependencies for robotgo
|
||||
|
||||
Cross-compilation isn't the most stable thing, so OS specific compilation is recommended.
|
||||
|
||||
## Authors
|
||||
|
||||
* **Samuel Pua** - *Initial work* - [GitHub](https://github.com/telboon)
|
||||
|
||||
|
||||
16
keys.txt
Normal file
16
keys.txt
Normal file
@@ -0,0 +1,16 @@
|
||||
sleep 601
|
||||
mouseLeftClick 671,570
|
||||
sleep 400
|
||||
mouseLeftClick 900,531
|
||||
sleep 300
|
||||
mouseLeftClick 884,333
|
||||
sleep 300
|
||||
mouseLeftClick 808,493
|
||||
sleep 300
|
||||
mouseLeftClick 800,495
|
||||
sleep 1403
|
||||
mouseLeftClick 885,125
|
||||
sleep 200
|
||||
mouseLeftClick 885,125
|
||||
sleep 300
|
||||
mouseLeftClick 885,125
|
||||
439
main.go
Normal file
439
main.go
Normal file
@@ -0,0 +1,439 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"os"
|
||||
"io/ioutil"
|
||||
"fmt"
|
||||
"strings"
|
||||
"strconv"
|
||||
"time"
|
||||
"runtime"
|
||||
"github.com/go-vgo/robotgo"
|
||||
)
|
||||
|
||||
const (
|
||||
MOUSELEFTCLICK = "mouseLeftClick"
|
||||
MOUSERIGHTCLICK = "mouseRightClick"
|
||||
MOUSEMOVE = "mouseMove"
|
||||
SLEEP = "sleep"
|
||||
KEYBOARD = "keyboard"
|
||||
TAPESCAPE = "tapEscape"
|
||||
TAPTAB = "tapTab"
|
||||
TAPUP = "tabUp"
|
||||
TAPDOWN = "tapDown"
|
||||
TAPLEFT = "tapLeft"
|
||||
TAPRIGHT = "tabRight"
|
||||
)
|
||||
|
||||
var (
|
||||
KEYQ uint16
|
||||
KEYW uint16
|
||||
KEYE uint16
|
||||
KEYA uint16
|
||||
KEYS uint16
|
||||
KEYD uint16
|
||||
KEYR uint16
|
||||
KEYZ uint16
|
||||
KEYCTRL uint16
|
||||
KEYESC uint16
|
||||
KEYTAB uint16
|
||||
KEYUP uint16
|
||||
KEYDOWN uint16
|
||||
KEYLEFT uint16
|
||||
KEYRIGHT uint16
|
||||
)
|
||||
|
||||
func mainMenu(keyCommands *[]string, runCount *int) string {
|
||||
exitChan := make(chan bool, 1)
|
||||
go listenRun(exitChan, keyCommands, runCount)
|
||||
fmt.Println(`Main Menu
|
||||
|
||||
l: Listening mode
|
||||
f: Read from file ("keys.txt")
|
||||
s: Save to file ("keys.txt")
|
||||
p: Print stored command
|
||||
c: Change run count
|
||||
r: Run stored command (Hotkey: ctrl-r)
|
||||
`)
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
fmt.Print("Enter Command: ")
|
||||
command, _ := reader.ReadString('\n')
|
||||
command = strings.ReplaceAll(command, "\n", "")
|
||||
command = strings.ReplaceAll(command, "\r", "")
|
||||
exitChan <- true
|
||||
return command
|
||||
}
|
||||
|
||||
func listenRun(exitChan chan bool, keyCommands *[]string, runCount *int) {
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
evtChan := robotgo.Start()
|
||||
defer robotgo.End()
|
||||
|
||||
// Rawcode
|
||||
// 65507, 162 - ctrl
|
||||
// 114, 82 - r
|
||||
|
||||
// Kind
|
||||
// 3 - keydown
|
||||
// 5 - keyup
|
||||
|
||||
ctrlKey := false
|
||||
rKey := false
|
||||
|
||||
for evt := range evtChan {
|
||||
// return if exit signal is given
|
||||
select {
|
||||
case <- exitChan:
|
||||
return
|
||||
default:
|
||||
if (evt.Kind == 3 || evt.Kind == 4) && (evt.Rawcode == KEYCTRL) {
|
||||
ctrlKey = true
|
||||
} else if evt.Kind == 5 && (evt.Rawcode == KEYCTRL) {
|
||||
ctrlKey = false
|
||||
} else if evt.Kind == 3 && (evt.Rawcode == KEYR) {
|
||||
rKey = true
|
||||
} else if evt.Kind == 5 && (evt.Rawcode == KEYR) {
|
||||
rKey = false
|
||||
}
|
||||
|
||||
if ctrlKey && rKey {
|
||||
ctrlKey = false
|
||||
rKey = false
|
||||
runKeyCommands(*keyCommands, *runCount)
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func listenMode(keyCommands *[]string, runCount *int) {
|
||||
*keyCommands = nil
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
fmt.Println("Entering listening mode...")
|
||||
evtChan := robotgo.Start()
|
||||
defer robotgo.End()
|
||||
|
||||
// Rawcode
|
||||
// 113, 81 - q
|
||||
// 119, 87 - w
|
||||
// 101, 69 - e
|
||||
// 97, 65 - a
|
||||
// 115, 83 - s
|
||||
// 100, 68 - d
|
||||
// 65307, 27 - esc
|
||||
|
||||
// Kind
|
||||
// 3 - keydown
|
||||
// 5 - keyup
|
||||
|
||||
leftMouseTrigger := 0
|
||||
rightMouseTrigger := 0
|
||||
moveMouseTrigger := 0
|
||||
sleepTrigger := 0
|
||||
typeTrigger := 0
|
||||
escapeTrigger := 0
|
||||
escapeTypeTrigger := 0
|
||||
tabTrigger := 0
|
||||
upTrigger := 0
|
||||
downTrigger := 0
|
||||
leftTrigger := 0
|
||||
rightTrigger := 0
|
||||
|
||||
lastTime := time.Now()
|
||||
others := false
|
||||
var newCommand string
|
||||
for evt := range evtChan {
|
||||
// return if exit signal is given
|
||||
if evt.Kind == 4 && (evt.Rawcode == KEYQ) {
|
||||
leftMouseTrigger += 1
|
||||
} else if evt.Kind == 4 && (evt.Rawcode == KEYE) {
|
||||
rightMouseTrigger += 1
|
||||
} else if evt.Kind == 4 && (evt.Rawcode == KEYW) {
|
||||
moveMouseTrigger += 1
|
||||
} else if evt.Kind == 4 && (evt.Rawcode == KEYS) {
|
||||
sleepTrigger += 1
|
||||
} else if evt.Kind == 4 && (evt.Rawcode == KEYD) {
|
||||
typeTrigger += 1
|
||||
} else if evt.Kind == 4 && (evt.Rawcode == KEYESC) {
|
||||
escapeTrigger += 1
|
||||
escapeTypeTrigger += 1
|
||||
} else if evt.Kind == 5 && (evt.Rawcode == KEYESC) {
|
||||
escapeTrigger = 0
|
||||
escapeTypeTrigger = 0
|
||||
} else if evt.Kind == 4 && (evt.Rawcode == KEYCTRL) {
|
||||
escapeTrigger += 1
|
||||
} else if evt.Kind == 5 && (evt.Rawcode == KEYCTRL) {
|
||||
escapeTrigger = 0
|
||||
} else if evt.Kind == 4 && (evt.Rawcode == KEYTAB) {
|
||||
tabTrigger += 1
|
||||
} else if evt.Kind == 4 && (evt.Rawcode == KEYUP) {
|
||||
upTrigger += 1
|
||||
} else if evt.Kind == 4 && (evt.Rawcode == KEYDOWN) {
|
||||
downTrigger += 1
|
||||
} else if evt.Kind == 4 && (evt.Rawcode == KEYLEFT) {
|
||||
leftTrigger += 1
|
||||
} else if evt.Kind == 4 && (evt.Rawcode == KEYRIGHT) {
|
||||
rightTrigger += 1
|
||||
}
|
||||
|
||||
if escapeTrigger == 2 {
|
||||
return
|
||||
} else if leftMouseTrigger == 1 {
|
||||
posX, posY := robotgo.GetMousePos()
|
||||
newCommand = fmt.Sprintf("%s %d,%d", MOUSELEFTCLICK, posX, posY)
|
||||
leftMouseTrigger = 0
|
||||
} else if rightMouseTrigger == 1 {
|
||||
posX, posY := robotgo.GetMousePos()
|
||||
newCommand = fmt.Sprintf("%s %d,%d", MOUSERIGHTCLICK, posX, posY)
|
||||
rightMouseTrigger = 0
|
||||
} else if moveMouseTrigger == 1 {
|
||||
posX, posY := robotgo.GetMousePos()
|
||||
newCommand = fmt.Sprintf("%s %d,%d", MOUSEMOVE, posX, posY)
|
||||
moveMouseTrigger = 0
|
||||
} else if sleepTrigger == 1 {
|
||||
newCommand = ""
|
||||
sleepTrigger = 0
|
||||
} else if typeTrigger == 1 {
|
||||
newCommand = fmt.Sprintf("%s \"\"", KEYBOARD)
|
||||
typeTrigger = 0
|
||||
} else if escapeTypeTrigger == 1 {
|
||||
newCommand = TAPESCAPE
|
||||
escapeTypeTrigger = 0
|
||||
} else if tabTrigger == 1 {
|
||||
newCommand = TAPTAB
|
||||
tabTrigger = 0
|
||||
} else if upTrigger == 1 {
|
||||
newCommand = TAPUP
|
||||
upTrigger = 0
|
||||
} else if downTrigger == 1 {
|
||||
newCommand = TAPDOWN
|
||||
downTrigger = 0
|
||||
} else if leftTrigger == 1 {
|
||||
newCommand = TAPLEFT
|
||||
leftTrigger = 0
|
||||
} else if rightTrigger == 1 {
|
||||
newCommand = TAPRIGHT
|
||||
rightTrigger = 0
|
||||
} else {
|
||||
others = true
|
||||
}
|
||||
|
||||
if !others {
|
||||
sleepComamnd := fmt.Sprintf("%s %d", SLEEP, int(time.Since(lastTime).Seconds() * 1000))
|
||||
*keyCommands = append(*keyCommands, sleepComamnd)
|
||||
if newCommand != "" {
|
||||
*keyCommands = append(*keyCommands, newCommand)
|
||||
}
|
||||
lastTime = time.Now()
|
||||
} else {
|
||||
others = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
initKeys()
|
||||
var keyCommands []string
|
||||
var runCount int
|
||||
for true {
|
||||
x := mainMenu(&keyCommands, &runCount)
|
||||
fmt.Println(x)
|
||||
if x == "f" {
|
||||
keyCommands = readFile("keys.txt")
|
||||
} else if x == "c" {
|
||||
runCount = changeRunCount()
|
||||
} else if x == "p" {
|
||||
printKeyCommands(keyCommands)
|
||||
} else if x == "r" {
|
||||
runKeyCommands(keyCommands, runCount)
|
||||
} else if x == "l" {
|
||||
listenMode(&keyCommands, &runCount)
|
||||
} else if x == "s" {
|
||||
writeFile("keys.txt", keyCommands)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func initKeys() {
|
||||
// 113, 81 - q
|
||||
// 119, 87 - w
|
||||
// 101, 69 - e
|
||||
// 97, 65 - a
|
||||
// 115, 83 - s
|
||||
// 100, 68 - d
|
||||
// 65307, 27 - esc
|
||||
// 114, 82 - r
|
||||
// 122, 90 - z
|
||||
// 65507, 162 - ctrl
|
||||
// 65289,9 - tab
|
||||
// 65361,37 - left
|
||||
// 65362,38 - up
|
||||
// 65363,39 - right
|
||||
// 65364,40 - down
|
||||
if (runtime.GOOS == "windows") {
|
||||
KEYQ = 81
|
||||
KEYW = 87
|
||||
KEYE = 69
|
||||
KEYA = 65
|
||||
KEYS = 83
|
||||
KEYD = 68
|
||||
KEYESC = 27
|
||||
KEYR = 82
|
||||
KEYCTRL = 162
|
||||
KEYTAB = 9
|
||||
KEYUP = 38
|
||||
KEYDOWN = 40
|
||||
KEYLEFT = 37
|
||||
KEYRIGHT = 39
|
||||
KEYZ = 90
|
||||
} else {
|
||||
KEYQ = 113
|
||||
KEYW = 119
|
||||
KEYE = 101
|
||||
KEYA = 97
|
||||
KEYS = 115
|
||||
KEYD = 100
|
||||
KEYESC = 65307
|
||||
KEYR = 114
|
||||
KEYCTRL = 65507
|
||||
KEYTAB = 65289
|
||||
KEYUP = 65362
|
||||
KEYDOWN = 65364
|
||||
KEYLEFT = 65361
|
||||
KEYRIGHT = 65363
|
||||
KEYZ = 122
|
||||
}
|
||||
}
|
||||
|
||||
func readFile(filename string) []string {
|
||||
filecontent, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
keyCommands := strings.Split(string(filecontent), "\n")
|
||||
return keyCommands
|
||||
}
|
||||
|
||||
func writeFile(filename string, keyCommand []string) {
|
||||
fmt.Println("Writing instructions to file...")
|
||||
f, err := os.Create(filename)
|
||||
defer f.Close()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
for _, keyCommand := range keyCommand {
|
||||
f.WriteString(keyCommand)
|
||||
f.WriteString("\n")
|
||||
}
|
||||
}
|
||||
|
||||
func changeRunCount() int {
|
||||
var runCount int
|
||||
fmt.Print("Enter run count: ")
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
countStr, _ := reader.ReadString('\n')
|
||||
countStr = strings.ReplaceAll(countStr, "\n", "")
|
||||
countStr = strings.ReplaceAll(countStr, "\r", "")
|
||||
runCount, err := strconv.Atoi(countStr)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
fmt.Println("Setting run count as 1...")
|
||||
runCount = 1
|
||||
}
|
||||
return runCount
|
||||
}
|
||||
|
||||
func printKeyCommands(keyCommands []string) {
|
||||
fmt.Println("------------------------------")
|
||||
for _, keyCommand := range keyCommands {
|
||||
fmt.Println(keyCommand)
|
||||
}
|
||||
fmt.Println("------------------------------")
|
||||
}
|
||||
|
||||
func runKeyCommands(keyCommands []string, runCount int) {
|
||||
fmt.Printf("Running commands for %d times\n", runCount)
|
||||
for i:=0; i<runCount; i++ {
|
||||
for _, keyCommand := range(keyCommands) {
|
||||
parseKeyCommand(keyCommand)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func parseKeyCommand(keyCommand string) {
|
||||
// Mouse left click
|
||||
if strings.Index(keyCommand, MOUSELEFTCLICK) == 0 {
|
||||
args := strings.Split(keyCommand[len(MOUSELEFTCLICK)+1:len(keyCommand)], ",")
|
||||
for n, _ := range(args) {
|
||||
args[n] = strings.ReplaceAll(args[n], " ", "")
|
||||
}
|
||||
argX, err := strconv.Atoi(args[0])
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
argY, err := strconv.Atoi(args[1])
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
robotgo.MoveClick(argX, argY, "left", false)
|
||||
// Mouse right click
|
||||
} else if strings.Index(keyCommand,MOUSERIGHTCLICK) == 0 {
|
||||
args := strings.Split(keyCommand[len(MOUSERIGHTCLICK)+1:len(keyCommand)], ",")
|
||||
for n, _ := range(args) {
|
||||
args[n] = strings.ReplaceAll(args[n], " ", "")
|
||||
}
|
||||
argX, err := strconv.Atoi(args[0])
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
argY, err := strconv.Atoi(args[1])
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
robotgo.MoveClick(argX, argY, "right", false)
|
||||
// Mouse move
|
||||
} else if strings.Index(keyCommand, MOUSEMOVE) == 0 {
|
||||
args := strings.Split(keyCommand[len(MOUSEMOVE)+1:len(keyCommand)], ",")
|
||||
for n, _ := range(args) {
|
||||
args[n] = strings.ReplaceAll(args[n], " ", "")
|
||||
}
|
||||
argX, err := strconv.Atoi(args[0])
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
argY, err := strconv.Atoi(args[1])
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
robotgo.Move(argX, argY)
|
||||
// Sleep
|
||||
} else if strings.Index(keyCommand, SLEEP) == 0 {
|
||||
args := keyCommand[len(SLEEP)+1:len(keyCommand)]
|
||||
sleepTime, err := strconv.Atoi(args)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
time.Sleep(time.Duration(sleepTime) * time.Millisecond)
|
||||
// Keyboard type
|
||||
} else if strings.Index(keyCommand, KEYBOARD) == 0 {
|
||||
args := keyCommand[len(KEYBOARD)+1:len(keyCommand)]
|
||||
strokes, err := strconv.Unquote(args)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
robotgo.TypeString(strokes)
|
||||
} else if strings.Index(keyCommand, TAPESCAPE) == 0 {
|
||||
robotgo.KeyTap("escape")
|
||||
} else if strings.Index(keyCommand, TAPTAB) == 0 {
|
||||
robotgo.KeyTap("tab")
|
||||
} else if strings.Index(keyCommand, TAPUP) == 0 {
|
||||
robotgo.KeyTap("up")
|
||||
} else if strings.Index(keyCommand, TAPDOWN) == 0 {
|
||||
robotgo.KeyTap("down")
|
||||
} else if strings.Index(keyCommand, TAPLEFT) == 0 {
|
||||
robotgo.KeyTap("left")
|
||||
} else if strings.Index(keyCommand, TAPRIGHT) == 0 {
|
||||
robotgo.KeyTap("right")
|
||||
}
|
||||
}
|
||||
BIN
mrRobotic.exe
Executable file
BIN
mrRobotic.exe
Executable file
Binary file not shown.
22
test/main.go
Normal file
22
test/main.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-vgo/robotgo"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
fmt.Println("--- Please press ctrl + shift + q ---")
|
||||
// start hook
|
||||
s := robotgo.Start()
|
||||
// end hook
|
||||
defer robotgo.End()
|
||||
|
||||
for ev := range s {
|
||||
fmt.Println("hook: ", ev)
|
||||
fmt.Println(ev.Kind)
|
||||
fmt.Println(ev.Rawcode)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user