diff --git a/src/antiafk.py b/src/antiafk.py index fd7d72c..403276d 100644 --- a/src/antiafk.py +++ b/src/antiafk.py @@ -1,34 +1,39 @@ +from pynput.keyboard import Key, KeyCode, Listener +import pygetwindow as window import pyautogui +import threading import random +import ctypes import time import sys -from os import system, name +import math import os -import ctypes -import threading -import pygetwindow as window -from pynput.keyboard import Key, KeyCode, Listener -global activated, timer, rand_interval, originalWindow +GAME_TITLE = "FINAL FANTASY XIV" +LOADING_BAR_SCALE = 45 +TIME_GRANULARITY = 10 + +MIN_DELAY = 120 * TIME_GRANULARITY +MAX_DELAY = 300 * TIME_GRANULARITY +SLEEP_TIME = 1/TIME_GRANULARITY -activated = False -rand_interval = 0 -timer = 0 KEYS = {1:'a', 2: 'd', 3: 'w', 4: 's'} -# define our clear function +global activated +activated = False + def clear(): - # for windows - if name == 'nt': - _ = system('cls') + if os.name == 'nt': + _ = os.system('cls') # for mac and linux else: - _ = system('clear') + _ = os.system('clear') + def is_admin(): try: @@ -42,99 +47,131 @@ def is_admin(): return False +def get_current_window(): + try: + originalWindow = window.getActiveWindow() + return originalWindow + except IndexError: + return + def get_game_window(): - global originalWindow - originalWindow = window.getActiveWindow() try: - gameWindow = window.getWindowsWithTitle('FINAL FANTASY XIV')[0] - if is_admin(): - try: - gameWindow.activate() - except: - return + gameWindow = window.getWindowsWithTitle(GAME_TITLE)[0] + return gameWindow except IndexError: return -def return_to_original_window(): - global originalWindow +def activate_game_window(gameWindow): if is_admin(): try: - originalWindow.activate() + gameWindow.activate() except: return -def execute_human_movement(): - global timer, rand_interval - # output the progress bar - sys.stdout.write('\r') +def return_to_original_window(originalWindow): + if is_admin(): + try: + originalWindow.activate() + except: + return - # check if the interval has been reached otherwise progress the progress bar - if (rand_interval - timer == 0): - sys.stdout.write("[{:{}}] Done\033[K\n".format("="*timer, rand_interval)) - #set the focus to the game - get_game_window() +def return_remaining_time(remainingTime): + unit = "minutes" + second_unit ="seconds" + + remaining_time_in_seconds = math.ceil(remainingTime / TIME_GRANULARITY) - # create a new random interval and determine the random movement to be executed now - rand_key = random.randint(1,4) - rand_interval = random.randint(10,90) + remaining_minutes = math.floor(remaining_time_in_seconds/60) + seconds_after_minutes = remaining_time_in_seconds - (remaining_minutes*60) - pyautogui.keyDown(KEYS[rand_key]) - pyautogui.sleep(0.1) - pyautogui.keyUp(KEYS[rand_key]) + if (seconds_after_minutes == 1): + second_unit = "second" - # return focus to whatever you were doing before - return_to_original_window() + if (remaining_minutes == 1): + unit = "minute" - # reset the interval timer - timer = 0 - print('') - print('Next input in {} seconds'.format(rand_interval)) + if (remaining_time_in_seconds < 60): + time_text = "{} {}".format(remaining_time_in_seconds, second_unit) + return time_text + + return "{} {} {} {}".format(remaining_minutes, unit, seconds_after_minutes, second_unit) + - else: - # output the progress bar - sys.stdout.write("[{:{}}] {}s remaining\033[K".format("="*timer, rand_interval, rand_interval - timer)) - # display stdout that is being processed inside a thread while it is being processed - sys.stdout.flush() - timer = timer + 1 - time.sleep(1) +def execute_movement(): + rand_key = random.randint(1,4) + pyautogui.keyDown(KEYS[rand_key]) + pyautogui.sleep(0.1) + pyautogui.keyUp(KEYS[rand_key]) def toggle_activated(): - global activated, timer, rand_interval + global activated + # toggles activation state activated = not activated - # resets timer - timer = 0 - # set an inital interval of 3 seconds to test - rand_interval = 3 # clear the screen clear() + + # display message of automatic window focus not working + if not is_admin(): + print("\u001b[31mNot running as admin. Automatic window focus will not work.\033[0m") + # set the current state activation_text = "\033[93minactive\033[0m" if activated: activation_text = "\033[92mactive\033[0m" - # print the current state - if not is_admin(): - print("\u001b[31mNot running as admin. Automatic window focus will not work.\033[0m") - print("Anti-AFK Bot is: {}".format(activation_text)) - - print('') + # print the current state + print("Anti-AFK Bot is: {}\n".format(activation_text)) + # prevent multiple executions from spamming the hotkey + # TODO: implement correct Thread locking instead of checking for active threads + if threading.active_count() > 2: + return + threading.Thread(target=main).start() def main(): - toggle_activated() + # resets timer + timer = 0 + # set an inital interval of 3 seconds to test + rand_interval = 3 * TIME_GRANULARITY # repeat until hotkey is used + while activated: - # prevent multiple executions from spamming the hotkey - # TODO: implement correct Thread locking instead of checking for active threads - if threading.active_count() > 3: - break # output progress & execute movement - execute_human_movement() + # output the progress bar + sys.stdout.write('\r') + gamewindow = get_game_window() + # check if the interval has been reached otherwise progress the progress bar + if (rand_interval - timer == 0): + sys.stdout.write("[{:{}}] Done.\033[K\n".format("="* ((timer * LOADING_BAR_SCALE) / rand_interval).__round__() , LOADING_BAR_SCALE)) + + #get the current window the user is on + currentWindow = get_current_window() + + #set the focus to the game + activate_game_window(gamewindow) + #determine and execute the desired movement + execute_movement() + + # return focus to whatever you were doing before + return_to_original_window(currentWindow) + # reset the interval timer and interval + timer = 0 + rand_interval = random.randint(MIN_DELAY,MAX_DELAY) + print('') + print('Next input in {}'.format(return_remaining_time(rand_interval - timer))) + + else: + # output the progress bar + sys.stdout.write("[{:{}}] {} remaining\033[K".format("="* ((timer * LOADING_BAR_SCALE) / rand_interval).__round__() , LOADING_BAR_SCALE, return_remaining_time(rand_interval - timer))) + # display stdout that is being processed inside a thread while it is being processed== + sys.stdout.flush() + timer = timer + 1 + time.sleep(SLEEP_TIME) ############################################################ ################ USER CHANGEABLE AREA ################## @@ -144,7 +181,7 @@ def main(): combination_to_function = { # duplicate this if you want to add more hotkey combos # unsure of your preferred keycode? Use this site: https://keycode.info/ - frozenset([Key.shift, KeyCode(vk=48)]): main, + frozenset([Key.shift, KeyCode(vk=48)]): toggle_activated, } ############################################################ @@ -172,19 +209,22 @@ def on_press(key): try: vk = get_vk(key) # Get the key's vk pressed_vks.add(vk) # Add it to the set of currently pressed keys - - for combination in combination_to_function: # Loop through each combination - if is_combination_pressed(combination): # Check if all keys in the combination are pressed - threading.Thread(target=combination_to_function[combination]).start() # If so, execute the function in a new thread - except: + except KeyError: pass + for combination in combination_to_function: # Loop through each combination + if is_combination_pressed(combination): # Check if all keys in the combination are pressed + combination_to_function[combination]() + # If so, execute the function in a new thread + + + def on_release(key): """ When a key is released """ try: vk = get_vk(key) # Get the key's vk pressed_vks.remove(vk) # Remove it from the set of currently pressed keys - except: + except KeyError: pass clear()