import os import sys import json import threading from urllib.parse import urlparse, parse_qs, unquote import webview AUTH_USER_AGENT = ( "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " "AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0" ) def extract_token(url_string): token = None expires_in = 3600 parsed = urlparse(url_string) if parsed.fragment: params = parse_qs(parsed.fragment) else: params = parse_qs(parsed.query) if 'access_token' in params: token = params['access_token'][0] if 'expires_in' in params: try: expires_in = int(params['expires_in'][0]) except ValueError: pass if not token: start_marker = "access_token%253D" end_marker = "%25" start_index = url_string.find(start_marker) if start_index != -1: token_start_index = start_index + len(start_marker) remaining_url = url_string[token_start_index:] end_index = remaining_url.find(end_marker) if end_index != -1: raw_token = remaining_url[:end_index] else: amp_index = remaining_url.find('&') if amp_index != -1: raw_token = remaining_url[:amp_index] else: raw_token = remaining_url token = unquote(raw_token) return token, expires_in def main_auth(auth_url, output_path): stop_polling = threading.Event() polling_started = threading.Event() def poll_url(): while not stop_polling.wait(0.75): try: url = window.get_current_url() except Exception: continue if not url: continue token, expires_in = extract_token(url) if not token: continue stop_polling.set() data = {"token": token, "expires_in": expires_in} with open(output_path, "w", encoding="utf-8") as f: json.dump(data, f) try: window.destroy() except Exception: pass return def start_polling(): if polling_started.is_set(): return polling_started.set() thread = threading.Thread(target=poll_url, name="vk-auth-url-poller", daemon=True) thread.start() def on_loaded(): start_polling() def on_closed(): stop_polling.set() window = webview.create_window("VK Авторизация", auth_url) window.events.loaded += on_loaded try: window.events.closed += on_closed except Exception: pass webview.start( start_polling, gui="edgechromium" if os.name == "nt" else None, private_mode=True, storage_path=None, user_agent=AUTH_USER_AGENT, ) stop_polling.set() def main(): # Supports both: `python auth_webview.py ` # and: `python auth_webview.py --auth ` args = sys.argv[1:] if len(args) == 3 and args[0] == "--auth": auth_url, output_path = args[1], args[2] elif len(args) == 2: auth_url, output_path = args[0], args[1] else: print("Usage: auth_webview.py [--auth] ") return 1 main_auth(auth_url, output_path) return 0 if __name__ == "__main__": sys.exit(main())