First commit

This commit is contained in:
2019-08-22 01:02:25 +08:00
commit c75292cba7
7 changed files with 498 additions and 0 deletions

21
README.md Normal file
View 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
View 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
View 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 Executable file

Binary file not shown.

BIN
mrRobotic.exe Executable file

Binary file not shown.

22
test/main.go Normal file
View 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)
}
}

BIN
test/test Executable file

Binary file not shown.