diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..65f20b1
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,35 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### IntelliJ IDEA ###
+.idea/
+*.iws
+*.iml
+*.ipr
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..3c92719
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,64 @@
+
+
+ 4.0.0
+
+ wtf.beatrice
+ autosqueal
+ 1.0-SNAPSHOT
+
+
+ 17
+ 17
+ UTF-8
+
+
+
+
+ org.apache.logging.log4j
+ log4j-api
+ 2.23.1
+
+
+
+ org.apache.logging.log4j
+ log4j-core
+ 2.23.1
+
+
+
+ com.github.kwhat
+ jnativehook
+ 2.2.2
+
+
+
+
+
+
+ maven-assembly-plugin
+
+
+
+ wtf.beatrice.autosqueal.Main
+
+
+
+ jar-with-dependencies
+
+
+
+
+ make-assembly
+ package
+
+ single
+
+
+
+
+
+
+
+
diff --git a/src/main/java/wtf/beatrice/autosqueal/CursorMoveListener.java b/src/main/java/wtf/beatrice/autosqueal/CursorMoveListener.java
new file mode 100644
index 0000000..fa794ef
--- /dev/null
+++ b/src/main/java/wtf/beatrice/autosqueal/CursorMoveListener.java
@@ -0,0 +1,51 @@
+package wtf.beatrice.autosqueal;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.awt.*;
+import java.util.TimerTask;
+
+public class CursorMoveListener extends TimerTask {
+
+ private int oldX, oldY;
+ private int newX, newY;
+ private int loops;
+ private boolean isUserAway;
+
+ private static final Logger LOGGER = LogManager.getLogger(CursorMoveListener.class);
+
+
+ public CursorMoveListener() {
+ oldX = 0;
+ oldY = 0;
+ loops = 0;
+ }
+
+ @Override
+ public void run() {
+ newX = MouseInfo.getPointerInfo().getLocation().x;
+ newY = MouseInfo.getPointerInfo().getLocation().y;
+
+ if(newX != oldX || newY != oldY) {
+ // cursor has been moved
+ loops = 0;
+ LOGGER.info("User is no longer away!");
+ } else {
+ if (loops < 30) {
+ loops++;
+ } else {
+ LOGGER.info("User is away!");
+ }
+ }
+
+ isUserAway = loops >= 30;
+
+ oldX = newX;
+ oldY = newY;
+ }
+
+ public boolean isUserAway() {
+ return isUserAway;
+ }
+}
diff --git a/src/main/java/wtf/beatrice/autosqueal/CursorMover.java b/src/main/java/wtf/beatrice/autosqueal/CursorMover.java
new file mode 100644
index 0000000..52d2ba1
--- /dev/null
+++ b/src/main/java/wtf/beatrice/autosqueal/CursorMover.java
@@ -0,0 +1,94 @@
+package wtf.beatrice.autosqueal;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.awt.*;
+import java.util.TimerTask;
+
+public class CursorMover extends TimerTask {
+
+ private static final Logger LOGGER = LogManager.getLogger(CursorMover.class);
+
+ final int destX, destY;
+ final Robot robot;
+
+ float currentX, currentY;
+ float stepX = 1, stepY = 1;
+ boolean isRunning = true;
+
+
+ public CursorMover(int destinationX, int destinationY) {
+
+ currentX = MouseInfo.getPointerInfo().getLocation().x;
+ currentY = MouseInfo.getPointerInfo().getLocation().y;
+
+ destX = destinationX;
+ destY = destinationY;
+
+ int lengthX, lengthY;
+
+ lengthX = Math.round(Math.abs(currentX - destX));
+ lengthY = Math.round(Math.abs(currentY - destY));
+
+ if(lengthX > lengthY) {
+ stepX = lengthX / (float) lengthY;
+ }
+
+ if(lengthY > lengthX) {
+ stepY = lengthY / (float) lengthX;
+ }
+
+ LOGGER.info("Dest: [{}, {}], Curr: [{}, {}]", destX, destY, currentX, currentY);
+ LOGGER.info("Len: [{}, {}]", lengthX, lengthY);
+ LOGGER.info("Step: [{}, {}]", stepX, stepY);
+
+ try {
+ robot = new Robot();
+ } catch (AWTException e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ @Override
+ public void run() {
+ if(Math.abs(currentX - destX) < 1) {
+ stepX = currentX - destX;
+ }
+
+ if(Math.abs(currentY - destY) < 1) {
+ stepY = currentY - destY;
+ }
+
+ if(destX == Math.round(currentX) || destY == Math.round(currentY)) {
+ LOGGER.info("Reached destination, stopping mover timer");
+ LOGGER.info("Dest: [{}, {}], Curr: [{}, {}]", destX, destY, currentX, currentY);
+ isRunning = false;
+ this.cancel();
+ return;
+ }
+
+ if(currentX > destX) {
+ currentX -= stepX;
+ }
+
+ if(currentY > destY) {
+ currentY -= stepY;
+ }
+
+ if(currentX < destX) {
+ currentX += stepX;
+ }
+
+ if(currentY < destY) {
+ currentY += stepY;
+ }
+
+ robot.mouseMove(Math.round(currentX), Math.round(currentY));
+ }
+
+ public boolean isRunning() {
+ return isRunning;
+ }
+}
diff --git a/src/main/java/wtf/beatrice/autosqueal/KeyPressListener.java b/src/main/java/wtf/beatrice/autosqueal/KeyPressListener.java
new file mode 100644
index 0000000..c2e86c1
--- /dev/null
+++ b/src/main/java/wtf/beatrice/autosqueal/KeyPressListener.java
@@ -0,0 +1,56 @@
+package wtf.beatrice.autosqueal;
+
+import com.github.kwhat.jnativehook.GlobalScreen;
+import com.github.kwhat.jnativehook.NativeHookException;
+import com.github.kwhat.jnativehook.keyboard.NativeKeyEvent;
+import com.github.kwhat.jnativehook.keyboard.NativeKeyListener;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class KeyPressListener implements NativeKeyListener
+{
+ private static final Logger LOGGER = LogManager.getLogger(KeyPressListener.class);
+ private final static List pressedKeysIds = new ArrayList<>();
+
+ public void nativeKeyPressed(NativeKeyEvent e) {
+ LOGGER.info("Key Pressed: {}", NativeKeyEvent.getKeyText(e.getKeyCode()));
+
+ if (e.getKeyCode() == NativeKeyEvent.VC_ESCAPE) {
+ try {
+ GlobalScreen.unregisterNativeHook();
+ } catch (NativeHookException nativeHookException) {
+ nativeHookException.printStackTrace();
+ }
+ }
+
+ pressedKeysIds.add(e.getKeyCode());
+
+ handlePressedKeys();
+ }
+
+ public void nativeKeyReleased(NativeKeyEvent e) {
+ LOGGER.info("Key Released: {}", NativeKeyEvent.getKeyText(e.getKeyCode()));
+
+ pressedKeysIds.remove((Integer) e.getKeyCode());
+
+ handlePressedKeys();
+ }
+
+ private void handlePressedKeys() {
+ if (pressedKeysIds.contains(NativeKeyEvent.VC_ALT) &&
+ pressedKeysIds.contains(NativeKeyEvent.VC_CONTROL)) {
+
+ StringBuilder keys = new StringBuilder();
+ pressedKeysIds.forEach(keyCode -> {
+ keys.append("[").append(NativeKeyEvent.getKeyText(keyCode)).append("]");
+ });
+
+ LOGGER.warn("Received shutdown keystroke: {}", keys);
+
+ System.exit(0);
+ }
+ }
+}
diff --git a/src/main/java/wtf/beatrice/autosqueal/Main.java b/src/main/java/wtf/beatrice/autosqueal/Main.java
new file mode 100644
index 0000000..67ec6db
--- /dev/null
+++ b/src/main/java/wtf/beatrice/autosqueal/Main.java
@@ -0,0 +1,95 @@
+package wtf.beatrice.autosqueal;
+
+import com.github.kwhat.jnativehook.GlobalScreen;
+import com.github.kwhat.jnativehook.NativeHookException;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.awt.*;
+import java.awt.event.InputEvent;
+import java.util.Random;
+import java.util.Timer;
+
+public class Main {
+
+ private static final int LOOPS_BEFORE_CLICK = 5;
+ private static final int TIME_BETWEEN_MOVES = 5;
+
+ private static final Logger LOGGER = LogManager.getLogger(Main.class);
+
+ public static void main(String[] args) throws InterruptedException, AWTException {
+ LOGGER.info("Hello world!");
+
+ registerJNativeHook();
+
+ Timer timer = new Timer();
+ CursorMoveListener cursorMoveListener = new CursorMoveListener();
+ timer.schedule(cursorMoveListener, 0L, 1000L);
+
+ int height = Toolkit.getDefaultToolkit().getScreenSize().height;
+ int width = Toolkit.getDefaultToolkit().getScreenSize().width;
+
+ Random random = new Random();
+
+ while (true) {
+ //if(!cursorMoveListener.isUserAway()) continue;
+
+ for(int i = 0; i < LOOPS_BEFORE_CLICK; i++) {
+
+ int currentX = MouseInfo.getPointerInfo().getLocation().x;
+ int currentY = MouseInfo.getPointerInfo().getLocation().y;
+
+ LOGGER.info("Starting coordinates: {}, {}", currentX, currentY);
+
+ int randomX, randomY;
+
+ randomX = random.nextInt(width);
+ randomY = random.nextInt(height);
+
+ LOGGER.info("Destination coordinates: {}, {}", randomX, randomY);
+
+ startMover(randomX, randomY);
+ }
+
+ startMover(width - 5, 5);
+ Robot robot = new Robot();
+ robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
+ Thread.sleep(200);
+ robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
+ Thread.sleep(500);
+ robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
+ Thread.sleep(200);
+ robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
+ Thread.sleep(200);
+
+ }
+ }
+
+ private static void registerJNativeHook() {
+ LOGGER.info("Registering jnativehook library...");
+ try {
+ GlobalScreen.registerNativeHook();
+ GlobalScreen.addNativeKeyListener(new KeyPressListener());
+ LOGGER.info("Successfully registered jnativehook library!");
+ }
+ catch (NativeHookException ex) {
+ LOGGER.error("There was a problem registering the native hook.");
+ LOGGER.error(ex.getMessage());
+
+ System.exit(1);
+ }
+ }
+
+ private static void startMover(int destX, int destY) throws InterruptedException {
+ Timer timer = new Timer();
+ CursorMover cursorMover = new CursorMover(destX, destY);
+ timer.schedule(cursorMover, 0L, 2L);
+ while (cursorMover.isRunning()) {
+ Thread.sleep(200);
+ }
+
+ timer.cancel();
+
+ Thread.sleep(TIME_BETWEEN_MOVES * 1000);
+ }
+}
diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml
new file mode 100644
index 0000000..81e5b12
--- /dev/null
+++ b/src/main/resources/log4j2.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+