2019-03-20 19:44:51 +00:00
|
|
|
package mousemover
|
|
|
|
|
|
|
|
import (
|
2019-04-19 22:52:37 +00:00
|
|
|
"fmt"
|
|
|
|
"os"
|
2019-03-28 19:52:25 +00:00
|
|
|
"sync"
|
2019-03-20 19:44:51 +00:00
|
|
|
"time"
|
|
|
|
|
2019-04-19 22:52:37 +00:00
|
|
|
"github.com/sirupsen/logrus"
|
2019-03-28 19:52:25 +00:00
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
|
2019-03-20 19:44:51 +00:00
|
|
|
"github.com/go-vgo/robotgo"
|
|
|
|
"github.com/prashantgupta24/activity-tracker/pkg/tracker"
|
|
|
|
)
|
|
|
|
|
2019-03-27 23:10:07 +00:00
|
|
|
var instance *MouseMover
|
2019-03-20 19:44:51 +00:00
|
|
|
|
2019-03-27 23:10:07 +00:00
|
|
|
//MouseMover is the main struct for the app
|
|
|
|
type MouseMover struct {
|
2019-03-28 19:52:25 +00:00
|
|
|
quit chan struct{}
|
|
|
|
mutex sync.RWMutex
|
|
|
|
runningStatus bool
|
2019-04-19 22:52:37 +00:00
|
|
|
logFile *os.File
|
2019-03-20 19:44:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const (
|
2019-04-19 22:52:37 +00:00
|
|
|
timeout = 100 //ms
|
|
|
|
logFileName = "logFile"
|
2019-03-20 19:44:51 +00:00
|
|
|
)
|
|
|
|
|
2019-03-27 23:10:07 +00:00
|
|
|
//Start the main app
|
|
|
|
func (m *MouseMover) Start() {
|
2019-03-28 19:52:25 +00:00
|
|
|
if m.isRunning() {
|
|
|
|
return
|
|
|
|
}
|
2019-03-20 19:44:51 +00:00
|
|
|
m.quit = make(chan struct{})
|
|
|
|
|
2019-04-11 01:47:01 +00:00
|
|
|
heartbeatInterval := 60 //value always in seconds
|
2019-04-19 22:52:37 +00:00
|
|
|
workerInterval := 10
|
2019-04-11 01:47:01 +00:00
|
|
|
|
2019-03-20 19:44:51 +00:00
|
|
|
activityTracker := &tracker.Instance{
|
2019-04-11 01:47:01 +00:00
|
|
|
HeartbeatInterval: heartbeatInterval,
|
|
|
|
WorkerInterval: workerInterval,
|
2019-03-22 22:56:20 +00:00
|
|
|
//LogLevel: "debug", //if we want verbose logging
|
2019-03-20 19:44:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
heartbeatCh := activityTracker.Start()
|
|
|
|
|
2019-03-27 23:10:07 +00:00
|
|
|
go func(m *MouseMover) {
|
2019-04-19 22:52:37 +00:00
|
|
|
logger := getLogger(m, false) //set writeToFile=true only for debugging
|
2019-03-28 19:52:25 +00:00
|
|
|
m.updateRunningStatus(true)
|
2019-03-20 19:44:51 +00:00
|
|
|
movePixel := 10
|
2019-04-19 22:52:37 +00:00
|
|
|
var lastMoved time.Time
|
|
|
|
didNotMoveTimes := 0
|
2019-03-20 19:44:51 +00:00
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case heartbeat := <-heartbeatCh:
|
2019-03-28 20:38:01 +00:00
|
|
|
if !heartbeat.WasAnyActivity {
|
2019-03-28 22:02:36 +00:00
|
|
|
mouseMoveSuccessCh := make(chan bool)
|
|
|
|
go moveAndCheck(movePixel, mouseMoveSuccessCh)
|
2019-03-20 19:44:51 +00:00
|
|
|
select {
|
2019-03-28 22:02:36 +00:00
|
|
|
case wasMouseMoveSuccess := <-mouseMoveSuccessCh:
|
2019-03-20 19:44:51 +00:00
|
|
|
if wasMouseMoveSuccess {
|
2019-04-19 22:52:37 +00:00
|
|
|
lastMoved = time.Now()
|
|
|
|
logger.Infof("moved mouse at : %v\n\n", lastMoved)
|
2019-03-20 19:44:51 +00:00
|
|
|
movePixel *= -1
|
2019-04-19 22:52:37 +00:00
|
|
|
didNotMoveTimes = 0
|
2019-03-28 22:02:36 +00:00
|
|
|
} else {
|
2019-04-19 22:52:37 +00:00
|
|
|
didNotMoveTimes++
|
|
|
|
msg := fmt.Sprintf("Mouse pointer cannot be moved at %v. Last moved at %v. Happened %v times. See README for details.",
|
|
|
|
time.Now(), lastMoved, didNotMoveTimes)
|
|
|
|
logger.Errorf(msg)
|
|
|
|
if didNotMoveTimes >= 3 {
|
|
|
|
go func() {
|
|
|
|
robotgo.ShowAlert("Error with Automatic Mouse Mover", msg)
|
|
|
|
}()
|
|
|
|
}
|
2019-03-20 19:44:51 +00:00
|
|
|
}
|
|
|
|
case <-time.After(timeout * time.Millisecond):
|
|
|
|
//timeout, do nothing
|
2019-04-19 22:52:37 +00:00
|
|
|
logger.Errorf("timeout happened after %vms while trying to move mouse", timeout)
|
2019-03-20 19:44:51 +00:00
|
|
|
}
|
|
|
|
|
2019-04-19 22:52:37 +00:00
|
|
|
} else { //uncomment to see all activities received
|
|
|
|
// logger.Printf("activity detected in the last %v seconds.", int(heartbeatInterval))
|
|
|
|
// logger.Printf("Activity type:\n")
|
2019-04-11 01:47:01 +00:00
|
|
|
// for activityType, times := range heartbeat.ActivityMap {
|
2019-04-19 22:52:37 +00:00
|
|
|
// logger.Printf("activityType : %v times: %v\n", activityType, len(times))
|
2019-04-11 01:47:01 +00:00
|
|
|
// }
|
2019-04-19 22:52:37 +00:00
|
|
|
// logger.Printf("\n\n\n")
|
2019-03-20 19:44:51 +00:00
|
|
|
}
|
|
|
|
case <-m.quit:
|
2019-04-19 22:52:37 +00:00
|
|
|
logger.Infof("stopping mouse mover")
|
2019-03-28 19:52:25 +00:00
|
|
|
m.updateRunningStatus(false)
|
2019-03-20 19:44:51 +00:00
|
|
|
activityTracker.Quit()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}(m)
|
|
|
|
}
|
|
|
|
|
2019-03-28 19:52:25 +00:00
|
|
|
func (m *MouseMover) isRunning() bool {
|
|
|
|
m.mutex.RLock()
|
|
|
|
defer m.mutex.RUnlock()
|
|
|
|
return m.runningStatus
|
|
|
|
}
|
|
|
|
func (m *MouseMover) updateRunningStatus(isRunning bool) {
|
|
|
|
m.mutex.Lock()
|
|
|
|
defer m.mutex.Unlock()
|
|
|
|
m.runningStatus = isRunning
|
|
|
|
}
|
|
|
|
|
2019-03-28 22:02:36 +00:00
|
|
|
func moveAndCheck(movePixel int, mouseMoveSuccessCh chan bool) {
|
2019-03-20 19:44:51 +00:00
|
|
|
currentX, currentY := robotgo.GetMousePos()
|
|
|
|
moveToX := currentX + movePixel
|
|
|
|
moveToY := currentY + movePixel
|
|
|
|
robotgo.MoveMouse(moveToX, moveToY)
|
2019-03-28 22:02:36 +00:00
|
|
|
|
|
|
|
//check if mouse moved. Sometimes mac users need to give
|
|
|
|
//extra permission for controlling the mouse
|
|
|
|
movedX, movedY := robotgo.GetMousePos()
|
|
|
|
if movedX == currentX && movedY == currentY {
|
|
|
|
mouseMoveSuccessCh <- false
|
|
|
|
} else {
|
|
|
|
mouseMoveSuccessCh <- true
|
|
|
|
}
|
2019-03-20 19:44:51 +00:00
|
|
|
}
|
|
|
|
|
2019-03-27 23:10:07 +00:00
|
|
|
//Quit the app
|
|
|
|
func (m *MouseMover) Quit() {
|
2019-03-20 19:44:51 +00:00
|
|
|
//making it idempotent
|
2019-03-28 19:52:25 +00:00
|
|
|
if m != nil && m.isRunning() {
|
2019-03-20 19:44:51 +00:00
|
|
|
m.quit <- struct{}{}
|
|
|
|
}
|
2019-04-19 22:52:37 +00:00
|
|
|
m.logFile.Close()
|
2019-03-20 19:44:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//GetInstance gets the singleton instance for mouse mover app
|
2019-03-27 23:10:07 +00:00
|
|
|
func GetInstance() *MouseMover {
|
2019-03-20 19:44:51 +00:00
|
|
|
if instance == nil {
|
2019-03-27 23:10:07 +00:00
|
|
|
instance = &MouseMover{}
|
2019-03-20 19:44:51 +00:00
|
|
|
}
|
|
|
|
return instance
|
|
|
|
}
|
2019-04-19 22:52:37 +00:00
|
|
|
|
|
|
|
func getLogger(m *MouseMover, doWriteToFile bool) *log.Logger {
|
|
|
|
logger := log.New()
|
|
|
|
logger.Formatter = &logrus.TextFormatter{
|
|
|
|
FullTimestamp: true,
|
|
|
|
}
|
|
|
|
|
|
|
|
if doWriteToFile {
|
|
|
|
logFile, err := os.OpenFile(logFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalf("error opening file: %v", err)
|
|
|
|
}
|
|
|
|
logger.SetOutput(logFile)
|
|
|
|
m.logFile = logFile
|
|
|
|
}
|
|
|
|
|
|
|
|
return logger
|
|
|
|
}
|