440 lines
12 KiB
Go
440 lines
12 KiB
Go
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")
|
|
}
|
|
}
|