Last active
January 6, 2023 14:25
-
-
Save ayushxx7/0866eb4df97a938d3267a6187dfd5e4e to your computer and use it in GitHub Desktop.
ExpressVPN Windows Utility to Connect & Disconnect from VPN using Python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import pyautogui | |
import inspect | |
import logging | |
from datetime import date | |
import time | |
import win32gui | |
import win32com.client | |
class VpnHandler(): | |
def customLogger(logLevel=logging.INFO): | |
"""Helper function for logging""" | |
loggerName = inspect.stack()[1][3] | |
logger = logging.getLogger(loggerName) | |
if not logger.handlers: | |
logger.setLevel(logging.INFO) | |
log_file_path = os.path.join(os.path.abspath(__file__ + '/../../'), 'Logs', f'Logs_{date.today()}.log') | |
fileHandler = logging.FileHandler(log_file_path, mode='a') | |
fileHandler.setLevel(logLevel) | |
streamHandler = logging.StreamHandler() | |
streamHandler.setLevel(logLevel) | |
formatter = logging.Formatter('%(asctime)s [%(levelname)4s] %(message)s (%(filename)s:%(lineno)s)', | |
datefmt='%m/%d/%Y %I:%M:%S %p') | |
fileHandler.setFormatter(formatter) | |
streamHandler.setFormatter(formatter) | |
logger.addHandler(fileHandler) | |
logger.addHandler(streamHandler) | |
return logger | |
def locate_on_screen_using_pyautogui_and_click(self, file_name): | |
"""Locate {file_name} image and click via pyautogui""" | |
self.log.info(f"clicking on {file_name}") | |
path_of_reference = os.path.join(os.path.abspath(__file__ + "/../../"), f"Assets\\{file_name}") | |
target = pyautogui.locateOnScreen(image=path_of_reference, confidence=0.8) | |
self.log.info(f'Target Image location: {target}') | |
time.sleep(5) | |
pyautogui.click(target) | |
self.log.info(f'Click action on {file_name} completed') | |
def locate_on_screen_using_pyautogui(self, file_name): | |
"""Locate {file_name} image via pyautogui""" | |
self.log.info(f'locating presence of {file_name} using pyautogui') | |
path_of_reference = os.path.join(os.path.abspath(__file__ + "/../../"), f"Assets\\{file_name}") | |
if pyautogui.locateOnScreen(image=path_of_reference, confidence=0.8): | |
self.log.info('Found!') | |
return True | |
else: | |
return False | |
def bring_express_vpn_on_top(self): | |
"""Bring ExpressVPN App on Top | |
""" | |
def windowEnumerationHandler(hwnd, top_windows): | |
top_windows.append((hwnd, win32gui.GetWindowText(hwnd))) | |
top_windows = [] | |
win32gui.EnumWindows(windowEnumerationHandler, top_windows) | |
for window_name in top_windows: | |
if "expressvpn" in window_name[1].lower(): | |
print('ExpressVPN on top') | |
try: | |
print(f'Bringing {window_name} to top') | |
win32gui.ShowWindow(window_name[0], 5) | |
shell = win32com.client.Dispatch("WScript.Shell") | |
shell.SendKeys('%') | |
win32gui.SetForegroundWindow(window_name[0]) | |
return True | |
except Exception as e: | |
print(e) | |
print('Window already on top') | |
return True | |
def dynamic_wait(self, wait_for_img, sec=5, reason="Wait until image appears"): | |
"""Helper function to wait until specified image is found or time limit exceeds""" | |
try: | |
self.log.info(f"Dynamic Wait: {reason}") | |
check_at = time.time() + sec | |
while time.time() < check_at and not self.locate_on_screen_using_pyautogui(wait_for_img): | |
self.log.info('wait for image to appear') | |
time.sleep(2) | |
if time.time() > check_at: | |
return False | |
else: | |
return True | |
except Exception as e: | |
self.log.error(f"Error in dynamic_wait: {e}") | |
def connect_to_country(self, vpn_image): | |
"""Connect to specific country via Express VPN | |
- Open ExpressVPN App via shortcut | |
- Bring ExpressVPN on Top | |
- Click on Search by locating image | |
- Connect to country by double clicking on country by location image | |
- Wait for connected image to show up | |
- Wait for 10 seconds after connection | |
""" | |
os.startfile(os.path.join(os.path.abspath(__file__+'/../../'), 'utility_exe', 'ExpressVPN.lnk')) | |
self.log.info('sleep for 5 secs after launching express vpn') | |
time.sleep(5) | |
self.bring_express_vpn_on_top() | |
time.sleep(2) | |
self.locate_on_screen_using_pyautogui_and_click('vpn_location_selector.png') | |
self.log.info('sleep for 3 secs after launch country list') | |
time.sleep(3) | |
self.locate_on_screen_using_pyautogui_and_click(vpn_image) | |
pyautogui.doubleClick() | |
self.dynamic_wait('vpn_connected.png', reason='Waiting for vpn to connect', sec=100) | |
self.log.info('Wait for 10 secs after connection established') | |
time.sleep(10) | |
def disconnect(self): | |
"""Disconnect from Express VPN | |
- Bring ExpressVPN on Top | |
- Click on Connected (button in center) by locating image | |
- Wait for disconnected image to show up | |
- Wait for 10 seconds after disconnection | |
""" | |
os.startfile(os.path.join(os.path.abspath(__file__+'/../../'), 'utility_exe', 'ExpressVPN.lnk')) | |
self.log.info('sleep for 5 secs after launching express vpn') | |
time.sleep(5) | |
self.bring_express_vpn_on_top() | |
time.sleep(2) | |
self.locate_on_screen_using_pyautogui_and_click('vpn_connected.png') | |
self.dynamic_wait('vpn_disconnected.png', reason='Waiting for vpn to disconnect', sec=60) | |
self.log.info('Wait for 10 secs after disconnected') | |
time.sleep(10) | |
log = customLogger() | |
def main(): | |
a = VpnHandler() | |
a.connect_to_country('vpn_taiwan.png') | |
a.disconnect() | |
a.connect_to_country('vpn_germany.png') | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This library talks directly to the express vpn service and works on windows - Evpn