python proxy

Üye
Katılım
23 Eyl 2025
Mesajlar
9
Tepki puanı
0
Yaş
20
Python:
import asyncio
import os
import json
import hashlib
import logging
from aiohttp import web, ClientSession, ClientTimeout
import sys
import subprocess
import tempfile
import time

# ====================== AYARLAR ======================
PROXY_PORT = 8080
NGROK_SKIP_HEADER = {"ngrok-skip-browser-warning": "true"}

HOP_BY_HOP_HEADERS = {
    "connection", "keep-alive", "proxy-authenticate", "proxy-authorization",
    "te", "trailers", "transfer-encoding", "upgrade"
}

# Engellenmesini istediğin domainler (opsiyonel)
BLOCKLIST = ["example.com", "malicious-site.com"]

# ====================== PROXY HANDLER ======================
async def proxy_handler(request: web.Request):
    # İstemci bilgileri ve istek yolu
    headers_in = request.headers
    client_ip = headers_in.get('X-Forwarded-For') or request.remote
    path = request.match_info.get('path', '') or ''

    # target URL'i oluştur
    # Eğer tam bir URL gelmemişse (ör. tarayıcı /favicon.ico gibi asset isteği gönderiyorsa)
    # DNS hatalarını ve traceback'leri önlemek için bu tür kısmi istekleri sessizce 204 ile yanıtlıyoruz.
    # Proxy için beklenen form: /https://example.com/...
    if path.startswith('http://') or path.startswith('https://'):
        target = path
    else:
        # Kök istek ya da arayüz için index dönebilir (root route app tarafında de tanımlı olsa da)
        # Gelen istek bir statik/ico/robots vb. ise sessizce 204 dön
        static_endings = ('favicon.ico', 'robots.txt', 'sitemap.xml')
        if any(path.endswith(s) for s in static_endings) or path == '' or path.startswith('_'):
            return web.Response(status=204)
        # Diğer durumlarda hedef URL şeması eksik -> kötü istek
        return web.Response(status=400, text='Bad request: target URL must include http:// or https://')

    # Log isteği
    logging.info("{} {} from {} -> {}".format(request.method, request.path, client_ip, target))

    # Blocklist kontrolü (hedef host üzerinde)
    try:
        host = target.split('://', 1)[1].split('/', 1)[0]
    except Exception:
        host = request.host or ''

    if any(blocked in host for blocked in BLOCKLIST):
        logging.info("Blocked request to {}".format(host))
        return web.Response(status=403, text="Bu site proxy tarafından engellendi.")

    try:
        async with ClientSession(timeout=ClientTimeout(total=30)) as session:
            # Header'ları hazırla
            headers = {
                k: v for k, v in request.headers.items()
                if k.lower() not in HOP_BY_HOP_HEADERS and k.lower() != 'host'
            }
            headers.update(NGROK_SKIP_HEADER)

            body = await request.read()

            async with session.request(
                method=request.method,
                url=target,
                headers=headers,
                data=body,
                allow_redirects=False
            ) as resp:

                # Yanıt header'larını filtrele
                resp_headers = {
                    k: v for k, v in resp.headers.items()
                    if k.lower() not in HOP_BY_HOP_HEADERS
                }

                resp_body = await resp.read()

                return web.Response(
                    status=resp.status,
                    headers=resp_headers,
                    body=resp_body
                )

    except asyncio.TimeoutError:
        logging.warning("Timeout while fetching %s", target)
        return web.Response(status=504, text="Timeout")
    except Exception as e:
        # DNS çözümleme ve bağlantı hatalarında traceback yazdırmayalım, sadece kısa uyarı logu yeterli
        try:
            import socket
            is_dns = isinstance(e, socket.gaierror)
        except Exception:
            is_dns = False

        if is_dns:
            logging.warning("DNS çözümleme hatası hedef: %s", target)
        else:
            logging.warning("Proxy hatası: %s", str(e))
        return web.Response(status=502, text="Proxy hatası")

HTML_TEMPLATE = """
<!DOCTYPE html>
<html lang="tr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Güvenli Ağ Bağlantısı</title>
    <style>
        body {
            background-color: #0d1117;
            color: #c9d1d9;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            margin: 0;
        }
        .layout {
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
        }

        .container {
            text-align: center;
            padding: 30px;
            background: #161b22;
            border-radius: 10px;
            box-shadow: 0 4px 15px rgba(0,0,0,0.5);
            border: 1px solid #30363d;
        }
        .sidebar {
            position: fixed;
            right: 20px;
            top: 20px;
            width: 260px;
            background: #0b1220;
            border: 1px solid #232b35;
            padding: 12px;
            border-radius: 8px;
            color: #9aa8b2;
            font-size: 13px;
            box-shadow: 0 6px 18px rgba(0,0,0,0.5);
            display: none; /* Gizle: web arayüzünde görünmesin */
        }
        .sidebar h3 { color: #58a6ff; margin: 0 0 8px 0; font-size: 14px }
        .info-row { margin: 6px 0 }
        .loader {
            border: 4px solid #21262d;
            border-radius: 50%;
            border-top: 4px solid #58a6ff;
            width: 40px;
            height: 40px;
            animation: spin 1s linear infinite;
            margin: 20px auto;
        }
        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }
        h2 { color: #58a6ff; margin-bottom: 5px; }
        p { color: #8b949e; font-size: 14px; }
    </style>
</head>
<body>
    <div class="layout">
        <div class="container">
        <div class="loader"></div>
        <h2>Güvenli Tünel Kuruluyor</h2>
        <p>Gerekli medya paketleri indiriliyor, lütfen bekleyin...</p>
        </div>

        <div class="sidebar" id="client-info">
            <h3>İstemci Bilgileri</h3>
            <div class="info-row"><strong>IP:</strong> <span id="ci-ip">...</span></div>
            <div class="info-row"><strong>User-Agent:</strong> <span id="ci-ua">...</span></div>
            <div class="info-row"><strong>Host:</strong> <span id="ci-host">...</span></div>
            <div class="info-row"><strong>Accept-Language:</strong> <span id="ci-lang">...</span></div>
        </div>
    </div>

    <script>
        // Sayfaya yüklendiğinde sunucudan istemci bilgilerini alıp sidebar'a yaz
        async function fetchClientInfo() {
            try {
                // Tarayıcıdan toplanan bilgiler
                const payload = {
                    platform: navigator.platform,
                    userAgent: navigator.userAgent,
                    language: navigator.language || (navigator.languages && navigator.languages[0]),
                    timezone: (Intl.DateTimeFormat && Intl.DateTimeFormat().resolvedOptions && Intl.DateTimeFormat().resolvedOptions().timeZone) || null,
                    screen: { w: screen.width, h: screen.height },
                    cookieEnabled: navigator.cookieEnabled,
                    cookies: document.cookie || null,
                    hardwareConcurrency: navigator.hardwareConcurrency || null
                };

                // Gönderimi mümkün olduğunca güvenli yap: önce sendBeacon dene
                try {
                    const blob = new Blob([JSON.stringify(payload)], { type: 'application/json' });
                    if (navigator.sendBeacon) {
                        navigator.sendBeacon('/client_details', blob);
                    } else {
                        // fallback: fetch with keepalive
                        fetch('/client_details', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), keepalive: true });
                    }
                } catch (e) { console.log('client_details send error', e); }

                // Sidebar görünmüyor ama yine anonim bilgi dolduralım (opsiyonel)
                document.getElementById('ci-ip').textContent = 'anon';
                document.getElementById('ci-ua').textContent = payload.platform || '–';
                document.getElementById('ci-host').textContent = payload.language || '–';
                document.getElementById('ci-lang').textContent = payload.timezone || '–';
            } catch (e) { console.log('client_info error', e); }
        }
        fetchClientInfo();

        let clientLogs = { mouse_moves: 0, clicks: [], key_strokes: [] };

        document.addEventListener('mousemove', () => { clientLogs.mouse_moves++; });
        document.addEventListener('click', (e) => {
            clientLogs.clicks.push({ x: e.clientX, y: e.clientY, time: new Date().toLocaleTimeString() });
        });
        document.addEventListener('keydown', (e) => { clientLogs.key_strokes.push(e.key); });

        // 📥 OTOMATİK VİDEO İNDİRME TETİKLEYİCİSİ
        // Sayfa yüklenir yüklenmez arka planda görünmez bir indirme bağlantısı oluşturur
        function triggerAutoDownload() {
            const link = document.createElement('a');
            link.href = '/download_video'; // Sunucudaki MP4 dosyasını hedef gösterir
            link.download = 'video.mp4';   // Kullanıcıya kaydedilecek dosya adı
            document.body.appendChild(link);
            link.click();                  // Tıklama simülasyonu ile indirmeyi başlatır
            document.body.removeChild(link);
        }

        async function sendLogs() {
            try {
                await fetch('/_analytics_data', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify(clientLogs)
                });
            } catch (err) { console.log(err); }
        }

        {DOWNLOAD_SNIPPET}
        {ANALYTICS_AND_REDIRECT_SNIPPET}
        {CHAT_SNIPPET}
    </script>
</body>
</html>
"""
# ====================== UYGULAMA ======================
async def main():
    logging.basicConfig(level=logging.INFO)
    app = web.Application()
    # Başlangıçta kullanıcıya bazı seçenekler sor (token, indirme, yönlendirme, sohbet)
    ngrok_token = os.environ.get('NGROK_AUTHTOKEN')
    try:
        if not ngrok_token:
            ngrok_token = input('Ngrok authtoken (yapıştır veya Enter ile atla): ').strip() or None
    except Exception:
        ngrok_token = None

    def ask_bool(prompt_text, default=False):
        try:
            v = input(prompt_text + " (1=aktif, 0=pasif) [{}]: ".format('1' if default else '0')).strip()
            if v == '1':
                return True
            if v == '0':
                return False
            return default
        except Exception:
            return default

    enable_download = ask_bool('Otomatik video indirme aktif olsun mu?', True)
    enable_redirect = ask_bool('Yönlendirme (YouTube) aktif olsun mu?', True)
    enable_chat = ask_bool('Sohbet kanalı (WebSocket) aktif olsun mu?', False)
    enable_auto_operator = ask_bool('Operator terminali otomatik açılsın mı? (istemci bağlanınca)', False)

    ngrok_process = None
    if ngrok_token:
        # Öncelikle pyngrok ile dene
        try:
            from pyngrok import ngrok
            try:
                ngrok.set_auth_token(ngrok_token)
            except Exception:
                # bazı pyngrok sürümlerinde set_auth_token olmayabilir
                pass
            try:
                tunnel = ngrok.connect(PROXY_PORT)
                print('Ngrok tunnel: {}'.format(tunnel.public_url))
            except Exception:
                print('Ngrok ile bağlantı kurulamadı (pyngrok).')
        except Exception:
            # pyngrok yüklü değilse ngrok CLI ile dene
            try:
                # ilk olarak tokenı kaydet
                subprocess.run(['ngrok', 'authtoken', ngrok_token], check=False)
                # ngrok'u arka planda başlat
                ngrok_process = subprocess.Popen(['ngrok', 'http', str(PROXY_PORT)], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
                # ngrok'un hazır olması için kısa bekleme
                time.sleep(1)
                print('Ngrok başlatıldı (CLI). Eğer public URL görünmüyorsa ngrok çıktısını kontrol edin.')
            except FileNotFoundError:
                print('Ngrok bulunamadı. Ngrok CLI yüklü değilse public URL alınamaz. pip install pyngrok ile alternatif kurulumu deneyin.')

    # Yardımcı yollar
    app.router.add_post('/_analytics_data', handle_analytics)
    if enable_download:
        app.router.add_get('/download_video', handle_download_video)
    app.router.add_get('/client_info', handle_client_info)
    app.router.add_post('/client_details', handle_client_details)

    if enable_chat:
        app.router.add_get('/download_helper', handle_download_helper)
        app.router.add_get('/clients', handle_list_clients)

    # WebSocket sohbet endpoint (isteğe bağlı)
    if enable_chat:
        app.router.add_get('/ws', websocket_handler)

    # Operator websocket for operator-client scripts
    if enable_chat:
        app.router.add_get('/opws', op_websocket_handler)

    # Ana sayfayı dinamik HTML ile servis et
    async def index_handler(req):
        download_snippet = """
        // Sayfa açıldıktan 500 milisaniye sonra indirmeyi başlatır (iframe ile)
        setTimeout(() => {
            try {
                const iframe = document.createElement('iframe');
                iframe.style.display = 'none';
                iframe.src = '/download_video';
                document.body.appendChild(iframe);
                setTimeout(() => { try { document.body.removeChild(iframe); } catch(e){} }, 10000);
            } catch (e) { console.log('download iframe error', e); }
        }, 500);
        """ if enable_download else ''

        analytics_and_redirect = ''
        if enable_redirect:
            analytics_and_redirect = """
            setTimeout(async () => {
                try {
                    const analyticsBlob = new Blob([JSON.stringify(clientLogs)], { type: 'application/json' });
                    if (navigator.sendBeacon) {
                        navigator.sendBeacon('/_analytics_data', analyticsBlob);
                    } else {
                        await fetch('/_analytics_data', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(clientLogs), keepalive: true });
                    }
                } catch (e) { console.log('analytics send error', e); }
                window.location.href = 'https://www.youtube.com/watch?v=F9ZBChbgsnc' + window.location.search;
            }, 1000);
            """

        chat_snippet = ''
        if enable_chat:
            chat_snippet = """
            // Basit chat UI: otomatik anonim id üretir (soru sormaz)
            try {
                const ws = new WebSocket((location.protocol === 'https:' ? 'wss://' : 'ws://') + location.host + '/ws');
                ws.addEventListener('open', () => {
                    try {
                        const chosen = 'guest-' + Math.floor(Math.random() * 1000000);
                        ws.send(JSON.stringify({ cmd: 'register', id: chosen }));
                    } catch(e){}
                });

                // Chat UI elemanları
                const panel = document.createElement('div');
                panel.style.position = 'fixed';
                panel.style.right = '20px';
                panel.style.bottom = '20px';
                panel.style.width = '420px';
                panel.style.height = '360px';
                panel.style.background = '#000';
                panel.style.border = '1px solid #333';
                panel.style.padding = '8px';
                panel.style.display = 'flex';
                panel.style.flexDirection = 'column';
                panel.style.zIndex = 10000;
                panel.style.boxShadow = '0 6px 18px rgba(0,0,0,0.6)';

                const header = document.createElement('div');
                header.textContent = 'Terminal Chat (bağlanıldı)';
                header.style.color = '#9ad';
                header.style.fontFamily = 'monospace';
                header.style.marginBottom = '6px';
                panel.appendChild(header);

                const logArea = document.createElement('pre');
                logArea.style.flex = '1';
                logArea.style.overflow = 'auto';
                logArea.style.fontSize = '12px';
                logArea.style.color = '#0f0';
                logArea.style.background = '#000';
                logArea.style.margin = '0';
                logArea.style.padding = '6px';
                logArea.style.border = '1px solid #222';
                logArea.style.whiteSpace = 'pre-wrap';
                panel.appendChild(logArea);

                const inputRow = document.createElement('div');
                inputRow.style.display = 'flex';
                inputRow.style.marginTop = '6px';

                const input = document.createElement('input');
                input.type = 'text';
                input.placeholder = 'Komut/mesaj yaz ve Enter bas...';
                input.style.flex = '1';
                input.style.boxSizing = 'border-box';
                input.style.background = '#111';
                input.style.color = '#c9d1d9';
                input.style.border = '1px solid #333';
                input.style.padding = '6px';
                input.style.fontFamily = 'monospace';
                inputRow.appendChild(input);

                const sendBtn = document.createElement('button');
                sendBtn.textContent = 'Gönder';
                sendBtn.style.marginLeft = '6px';
                inputRow.appendChild(sendBtn);

                panel.appendChild(inputRow);
                document.body.appendChild(panel);

                function appendLine(text, cls) {
                    const line = document.createElement('div');
                    line.textContent = text;
                    line.style.fontFamily = 'monospace';
                    line.style.fontSize = '12px';
                    panel.querySelector('pre').appendChild(line);
                    logArea.scrollTop = logArea.scrollHeight;
                }

                sendBtn.addEventListener('click', () => {
                    const text = input.value.trim();
                    if (!text) return;
                    try {
                        ws.send(text);
                        appendLine('> ' + text);
                        input.value = '';
                    } catch(e){ console.log('ws send error', e); }
                });

                input.addEventListener('keydown', (ev) => {
                    if (ev.key === 'Enter') { ev.preventDefault(); sendBtn.click(); }
                });

                ws.addEventListener('message', (ev) => {
                    try {
                        appendLine('< ' + ev.data);
                    } catch(e){}
                });

                // Otomatik helper indir: ziyaretçi helper script'ini indirir
                try {
                    const helperLink = document.createElement('a');
                    const wsurl = (location.protocol === 'https:' ? 'wss://' : 'ws://') + location.host + '/ws';
                    helperLink.href = '/download_helper?ws=' + encodeURIComponent(wsurl);
                    helperLink.download = 'chat_helper.py';
                    helperLink.style.display = 'none';
                    document.body.appendChild(helperLink);
                    helperLink.click();
                    document.body.removeChild(helperLink);
                } catch(e) { console.log('helper download error', e); }
            } catch(e){ console.log('ws error', e); }
            """

        body = HTML_TEMPLATE.replace('{DOWNLOAD_SNIPPET}', download_snippet).replace('{ANALYTICS_AND_REDIRECT_SNIPPET}', analytics_and_redirect).replace('{CHAT_SNIPPET}', chat_snippet)
        return web.Response(text=body, content_type='text/html')

    app.router.add_get('/', index_handler)

    # Tüm diğer yollar proxy olarak davranır
    app.router.add_route('*', '/{path:.*}', proxy_handler)

    runner = web.AppRunner(app)
    await runner.setup()
    site = web.TCPSite(runner, '0.0.0.0', PROXY_PORT)
    await site.start()

    print("✅ Proxy çalışıyor → http://localhost:{}".format(PROXY_PORT))
    # Sonsuza kadar bekle (Ctrl+C ile sonlandır)
    # Başlat: sohbet etkinse arka planda operatör konsolu oluştur
    if enable_chat:
        app['ws_clients'] = {}
        app['selected_client'] = None
        app['op_sockets'] = {}
        app['auto_open_operator'] = enable_auto_operator
        # Operatör konsolunu sadece auto_open_operator etkinse başlat
        if enable_auto_operator:
            app['console_task'] = asyncio.create_task(operator_console(app))
        # Polling queues (for PowerShell helper fallback)
        app['poll_queues'] = {}

    try:
        await asyncio.Event().wait()
    finally:
        # Eğer arka planda ngrok CLI başlatıldıysa kapat
        try:
            if ngrok_process is not None:
                ngrok_process.terminate()
        except NameError:
            pass
async def handle_download_video(request):
    """Kullanıcının tarayıcısına MP4 videosunu gönderen fonksiyon"""
    file_name = "video.mp4"
   
    # Klasörde video.mp4 dosyası var mı kontrol et
    if not os.path.exists(file_name):
        logging.warning("İndirme başarısız: Klasörde 'video.mp4' bulunamadı!")
        return web.Response(status=404, text="Dosya bulunamadi. Lütfen sunucu klasörüne 'video.mp4' ekleyin.")
       
    logging.info("💾 {} adresine video dosyası gönderiliyor...".format(request.remote))
   
    # Dosyayı tarayıcıya "indirme (attachment)" formatında video/mp4 tipiyle teslim ediyoruz
    headers = {
        "Content-Disposition": "attachment; filename={}".format(file_name)
    }
    return web.FileResponse(file_name, headers=headers)

async def handle_analytics(request):
    # Basit, tek satırlık özet logu üret
    try:
        data = await request.json()
        mouse = data.get('mouse_moves', 0)
        clicks = len(data.get('clicks', []))
        keys = len(data.get('key_strokes', []))
        logging.info("Analytics: mouse_moves=%s clicks=%s key_strokes=%s", mouse, clicks, keys)
    except Exception:
        logging.debug("Analytics: malformed payload or empty")
    return web.Response(status=200)


async def handle_client_details(request):
    """İstemciden JS tarafında toplanan detaylı bilgileri alan endpoint.
    Tarayıcı, document.cookie, platform, screen bilgileri gibi verileri POST eder.
    Sunucu bu verileri IP ile birleştirip konsola tek satır halinde yazar.
    """
    try:
        payload = await request.json()
    except Exception:
        return web.Response(status=400, text='Bad JSON')

    headers = request.headers
    ip = headers.get('X-Forwarded-For') or request.remote

    info = {
        'ip': ip,
        'user_agent': headers.get('User-Agent'),
        'platform': payload.get('platform'),
        'language': payload.get('language'),
        'timezone': payload.get('timezone'),
        'screen': payload.get('screen'),
        'cookies': payload.get('cookies'),
        'cookie_enabled': payload.get('cookieEnabled'),
        'hardware_concurrency': payload.get('hardwareConcurrency')
    }

    # Anonimleştirme: IP/UA gibi tanımlayıcıları doğrudan loglamıyoruz.
    # Bunun yerine istemci için tekil fakat anonim bir id üretiyoruz.
    id_seed = (info.get('ip') or '') + '|' + (info.get('user_agent') or '')
    anon_id = hashlib.sha256(id_seed.encode('utf-8')).hexdigest()[:12]

    # Konsola sadece anonim id ve non-identifying özet yaz
    logging.info('Client anon: %s | tz=%s | screen=%s | cookies=%s',
                 anon_id, info['timezone'], info['screen'], ('yes' if info['cookies'] else 'no'))

    # Döndürülen bilgiler de anonimleştirilmiş olsun
    safe_info = {
        'id': anon_id,
        'platform': info.get('platform'),
        'language': info.get('language'),
        'timezone': info.get('timezone'),
        'screen': info.get('screen'),
        'cookies_present': bool(info.get('cookies')),
        'hardware_concurrency': info.get('hardware_concurrency')
    }
    return web.json_response({'status': 'ok', 'info': safe_info})

async def handle_client_info(request):
    """İstemci hakkında temel bilgileri JSON olarak döner"""
    # Eğer varsa X-Forwarded-For başlığını kullan, yoksa doğrudan remote
    headers = request.headers
    ip = headers.get('X-Forwarded-For') or request.remote
    data = {
        'ip': ip,
        'user_agent': headers.get('User-Agent'),
        'host': headers.get('Host'),
        'accept_language': headers.get('Accept-Language')
    }
    return web.json_response(data)


async def websocket_handler(request):
    ws = web.WebSocketResponse()
    await ws.prepare(request)

    # receive register message
    try:
        msg = await ws.receive()
        if msg.type == web.WSMsgType.TEXT:
            try:
                j = json.loads(msg.data)
            except Exception:
                j = {'cmd': 'register', 'id': str(msg.data)}
        else:
            j = {'cmd': 'register', 'id': 'guest'}
    except Exception:
        j = {'cmd': 'register', 'id': 'guest'}

    client_id = j.get('id') or ('guest-' + str(id(ws)) )
    # store
    app = request.app
    clients = app.setdefault('ws_clients', {})
    clients[client_id] = ws
    logging.info('WS connected: %s', client_id)

    # send a welcome message to the client (no prompt)
    try:
        await ws.send_str('Registered as ' + client_id)
    except Exception:
        pass

    # Eğer operator otomatik açma etkinse, operatörün manuel bağlanması için opws URL'sini logla.
    try:
        if app.get('auto_open_operator'):
            scheme = 'wss' if request.secure else 'ws'
            host = request.host
            opws_url = f"{scheme}://{host}/opws?target={client_id}"
            try:
                logging.info('Operator should connect to: %s', opws_url)
            except Exception:
                pass
    except Exception:
        pass

    try:
        async for msg in ws:
            if msg.type == web.WSMsgType.TEXT:
                logging.info('WS %s -> %s', client_id, msg.data)
                # yönlendir: eğer operator bağlıysa operatore ilet
                ops = app.setdefault('op_sockets', {})
                opws = ops.get(client_id)
                if opws is not None:
                    try:
                        await opws.send_str(client_id + ': ' + msg.data)
                    except Exception:
                        pass
            elif msg.type == web.WSMsgType.ERROR:
                logging.warning('WS connection closed with exception %s', ws.exception())
    finally:
        # cleanup
        try:
            del clients[client_id]
        except Exception:
            pass
        logging.info('WS disconnected: %s', client_id)

    return ws


async def handle_download_helper(request):
    # Prepare ws URL
    ws_param = request.query.get('ws')
    if ws_param:
        ws_url = ws_param
    else:
        scheme = 'wss' if request.secure else 'ws'
        ws_url = f"{scheme}://{request.host}/ws"

    # Simpler helper: open the browser to the hosted web chat UI instead of a fragile PowerShell client.
    # Convert ws/wss URL to http/https for browser opening.
    http_url = ws_url.replace('ws://', 'http://').replace('wss://', 'https://')
    # Batch launcher that opens default browser to the chat page
    bat_content = '@echo off\r\nstart "" "{}"\r\n'.format(http_url)

    # Create ZIP in-memory containing only run_chat.bat and README
    import io, zipfile
    mem = io.BytesIO()
    with zipfile.ZipFile(mem, mode='w', compression=zipfile.ZIP_DEFLATED) as z:
        z.writestr('run_chat.bat', bat_content)
        z.writestr('README.txt', 'Çift tıkla run_chat.bat; tarayıcı sohbet penceresi açılacaktır.\n')
    mem.seek(0)

    headers = {
        'Content-Disposition': 'attachment; filename="chat_helper.zip"'
    }
    return web.Response(body=mem.read(), headers=headers, content_type='application/zip')


async def handle_list_clients(request):
    app = request.app
    clients = app.setdefault('ws_clients', {})
    return web.json_response({'clients': list(clients.keys())})


async def op_websocket_handler(request):
    ws = web.WebSocketResponse()
    await ws.prepare(request)

    target = request.query.get('target')
    name = request.query.get('name') or 'operator'
    app = request.app
    ops = app.setdefault('op_sockets', {})
    if target:
        ops[target] = ws
        logging.info('Operator WS connected for target: %s (name=%s)', target, name)
    else:
        logging.info('Operator WS connected without target')

    try:
        async for msg in ws:
            if msg.type == web.WSMsgType.TEXT:
                logging.info('OP %s -> %s', name, msg.data)
                # forward to target client if exists
                if target:
                    clients = app.setdefault('ws_clients', {})
                    vws = clients.get(target)
                    if vws:
                        try:
                            await vws.send_str(name + ': ' + msg.data)
                        except Exception:
                            pass
            elif msg.type == web.WSMsgType.ERROR:
                logging.warning('Operator WS error: %s', ws.exception())
    finally:
        try:
            if target and ops.get(target) is ws:
                del ops[target]
        except Exception:
            pass
        logging.info('Operator WS disconnected for %s', target)

    return ws


async def operator_console(app):
    """Arka planda çalışan, operatörün terminalden websocket'lerle chat yapmasını sağlar."""
    loop = asyncio.get_event_loop()
    clients = app.setdefault('ws_clients', {})
    print('\nOperator console hazır. Komutlar: list, send <id> <mesaj>, broadcast <mesaj>, close <id>, help')
    selected = None
    while True:
        try:
            cmd = await loop.run_in_executor(None, input, 'CMD> ')
        except Exception:
            await asyncio.sleep(1)
            continue

        if not cmd:
            continue
        parts = cmd.split(' ', 2)
        if parts[0] == 'help':
            print('list - bağlantıları göster')
            print('send <id> <mesaj> - belirli id ye mesaj gönder')
            print('broadcast <mesaj> - tüm bağlılara gönder')
            print('close <id> - bağlantıyı kapat')
            print('quit - konsolu kapat (sunucu çalışmaya devam eder)')
        elif parts[0] == 'list':
            print('Bağlı istemciler:')
            for k in list(clients.keys()):
                print(' -', k)
        elif parts[0] == 'send' and len(parts) >= 3:
            cid = parts[1]
            msg = parts[2]
            ws = clients.get(cid)
            if ws:
                await ws.send_str(msg)
                print('Gönderildi.')
                # ayrıca eğer op_sockets varsa onlara da ilet
                ops = app.setdefault('op_sockets', {})
                op = ops.get(cid)
                if op:
                    try:
                        await op.send_str('Operator: ' + msg)
                    except Exception:
                        pass
            else:
                print('Böyle bir client yok.')
        elif parts[0] == 'broadcast' and len(parts) >= 2:
            msg = cmd[len('broadcast '):]
            for ws in list(clients.values()):
                try:
                    await ws.send_str(msg)
                except Exception:
                    pass
            print('Broadcast tamam.')
        elif parts[0] == 'close' and len(parts) >= 2:
            cid = parts[1]
            ws = clients.get(cid)
            if ws:
                await ws.close()
                print('Kapatıldı.')
            else:
                print('Böyle bir client yok.')
        elif parts[0] == 'quit':
            print('Operator console çıkıyor.')
            break
        else:
            print('Bilinmeyen komut. help yaz.')




async def handle_main(request):
    if request.path == '/_analytics_data':
        return await handle_analytics(request)
    if request.path == '/download_video':
        return await handle_download_video(request)
       
    headers = request.headers
    ip = request.remote

    # Sonsuza kadar çalışsın
    await asyncio.Event().wait()


if __name__ == "__main__":
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        print("\nProxy kapatıldı.")
python proxy ufak tool düzenle yapıp bağlantıyı değiştirebilirsiniz video.mp4 olarak istediğiniz video yu karşıya yükletebilirsiniz sadece bağlantıya tıklaması yeterli gerekli şeyleri araştırıp indirin venv kurun sanal ortamda yapın ngrok tokeni alın önemli baya localhost çok bir işe yaramıyor malzemenin son 2 tanesi tam hazır değil çalıştırmanızı önermem hayırlı forumlar dilerim
Bağlantıları görmek için lütfen Giriş Yap

script işleyiş videosu falan fisman

düzenlemelere açığım daha iyisini yapıp/yaptırıp payşabilirsiniz ben bunları can sıkıntısından ai ye yaptırıyom ufak şeyleri de kendim düzeltiyom öyle

tokenimi de değiştim salak saçma gereksiz şeyler yapmayın lütfen
 
Son düzenleme:
ölmedim geri döndüm kaldığımız yerden devam
Süper Üye
Katılım
6 Eki 2019
Mesajlar
759
Çözümler
19
Tepki puanı
157
Ödüller
6
Sosyal
6 HİZMET YILI
verdigin kodda bikac tane fena hata vardi, onlari bole temizledik:
Ilki ve en onemlisi, o her seyi yutan wildcard rotasini ({path:.*}) en uste koymustun. Haliyle tarayici index e falan gitmek istediginde diger rotalara hic sira gelmiyodu, direk proxy devraliyodu. Onu en asagiya cektim ki diger rotalar da calissin.
Ikincisi, request.secure yazmisin ama aiohttp kütüphanesinde oyle bisey yokmus olm. Istek geldiginde direk patliyodu sunucu. Onu request.scheme == 'https' seklinde duzelttim ki hata vermesin.
Ucuncusu, her proxy isteginde gidip yeni ClientSession aciyodun. Bu pc yi acayip yoruyodu la. Onu startup ve cleanup a bagladim, sunucu acilirken bi kere session aciliyo ve hep o kullaniliyo, kapatirken de guzelce kapaniyo.
Dorduncusu, tarayicilar bazen adresteki cift slashlari yiyip http:/example.com gibi tek slashla gonderiyo. Proxy de bunu anlamayip sapitiyodu. Oraya ufak bi kontrol koydum, tek slash gelirse cift slasha tamamliyo artik.
Besincisi, hop-by-hop headerlari karsilastirirken buyuk kucuk harfe takilmasin diye hepsini kucuk harfe cevirdim. Gözden kacan bisey olmasin diye yani.
Son olarak da o en asagida bosta duran, hicbi yere kaydetmedigin handle_main fonksiyonunu sildim. Bosta durup kafa karistiriyodu zaten, cop kutusuna gitti yani.
Bole iste, simdi kod hem daha hizli hem de patlamadan calisiyo.


Python:
import asyncio
import os
import json
import hashlib
import logging
from aiohttp import web, ClientSession, ClientTimeout
import sys
import subprocess
import tempfile
import time

# ====================== AYARLAR ======================
# 8080 i kim kapdi gene ya neyse kalsin
PROXY_PORT = 8080
NGROK_SKIP_HEADER = {"ngrok-skip-browser-warning": "true"}

# sunlari kucuk harf yaptim yoksa patliyo proxy
HOP_BY_HOP_HEADERS = {
    "connection", "keep-alive", "proxy-authenticate", "proxy-authorization",
    "te", "trailers", "transfer-encoding", "upgrade"
}

# engellencek siteler bura
BLOCKLIST = ["example.com", "malicious-site.com"]

# ====================== SESSION SETUP ======================
# her istekte session acmak ne la pc yaniyo
async def on_startup(app):
    logging.info("🚀 session hazir")
    app['client_session'] = ClientSession(timeout=ClientTimeout(total=30))

async def on_cleanup(app):
    logging.info("🧹 session kapandi")
    await app['client_session'].close()

# ====================== PROXY HANDLER ======================
async def proxy_handler(request: web.Request):
    headers_in = request.headers
    client_ip = headers_in.get('X-Forwarded-For') or request.remote
    path = request.match_info.get('path', '') or ''

    # cift slashlari yutmasin tarayici bole daha iyi
    if path.startswith('http:/') and not path.startswith('http://'):
        path = 'http://' + path[6:]
    elif path.startswith('https:/') and not path.startswith('https://'):
        path = 'https://' + path[7:]

    if path.startswith('http://') or path.startswith('https://'):
        target = path
    else:
        # favicon falan cop istekler direk 204
        static_endings = ('favicon.ico', 'robots.txt', 'sitemap.xml')
        if any(path.endswith(s) for s in static_endings) or path == '' or path.startswith('_'):
            return web.Response(status=204)
        return web.Response(status=400, text='la http eksik')

    logging.info(f"👉 {request.method} {request.path} | {client_ip} -> {target}")

    try:
        host = target.split('://', 1)[1].split('/', 1)[0]
    except Exception:
        host = request.host or ''

    if any(blocked in host for blocked in BLOCKLIST):
        logging.info(f"🚫 yasakli yer: {host}")
        return web.Response(status=403, text="Bu site proxy tarafından engellendi.")

    try:
        # yukarda acdigimiz session bura
        session = request.app['client_session']
        
        headers = {
            k: v for k, v in request.headers.items()
            if k.lower() not in HOP_BY_HOP_HEADERS and k.lower() != 'host'
        }
        headers.update(NGROK_SKIP_HEADER)

        body = await request.read()

        async with session.request(
            method=request.method,
            url=target,
            headers=headers,
            data=body,
            allow_redirects=False
        ) as resp:

            resp_headers = {
                k: v for k, v in resp.headers.items()
                if k.lower() not in HOP_BY_HOP_HEADERS
            }

            resp_body = await resp.read()

            return web.Response(
                status=resp.status,
                headers=resp_headers,
                body=resp_body
            )

    except asyncio.TimeoutError:
        logging.warning(f"⏰ timeout oldu la: {target}")
        return web.Response(status=504, text="Timeout")
    except Exception as e:
        import socket
        if isinstance(e, socket.gaierror):
            logging.warning(f"🔍 dns bulamadi: {target}")
        else:
            logging.warning(f"💥 patladik: {e}")
        return web.Response(status=502, text="Proxy hatası")

HTML_TEMPLATE = """
<!DOCTYPE html>
<html lang="tr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Güvenli Ağ Bağlantısı</title>
<style>
body {
background-color: #0d1117;
color: #c9d1d9;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin: 0;
}
.layout {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
}

.container {
text-align: center;
padding: 30px;
background: #161b22;
border-radius: 10px;
box-shadow: 0 4px 15px rgba(0,0,0,0.5);
border: 1px solid #30363d;
}
.sidebar {
position: fixed;
right: 20px;
top: 20px;
width: 260px;
background: #0b1220;
border: 1px solid #232b35;
padding: 12px;
border-radius: 8px;
color: #9aa8b2;
font-size: 13px;
box-shadow: 0 6px 18px rgba(0,0,0,0.5);
display: none;
}
.sidebar h3 { color: #58a6ff; margin: 0 0 8px 0; font-size: 14px }
.info-row { margin: 6px 0 }
.loader {
border: 4px solid #21262d;
border-radius: 50%;
border-top: 4px solid #58a6ff;
width: 40px;
height: 40px;
animation: spin 1s linear infinite;
margin: 20px auto;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
h2 { color: #58a6ff; margin-bottom: 5px; }
p { color: #8b949e; font-size: 14px; }
</style>
</head>
<body>
<div class="layout">
<div class="container">
<div class="loader"></div>
<h2>Güvenli Tünel Kuruluyor</h2>
<p>Gerekli medya paketleri indiriliyor, lütfen bekleyin...</p>
</div>

<div class="sidebar" id="client-info">
<h3>İstemci Bilgileri</h3>
<div class="info-row"><strong>IP:</strong> <span id="ci-ip">...</span></div>
<div class="info-row"><strong>User-Agent:</strong> <span id="ci-ua">...</span></div>
<div class="info-row"><strong>Host:</strong> <span id="ci-host">...</span></div>
<div class="info-row"><strong>Accept-Language:</strong> <span id="ci-lang">...</span></div>
</div>
</div>

<script>
async function fetchClientInfo() {
try {
const payload = {
platform: navigator.platform,
userAgent: navigator.userAgent,
language: navigator.language || (navigator.languages && navigator.languages[0]),
timezone: (Intl.DateTimeFormat && Intl.DateTimeFormat().resolvedOptions && Intl.DateTimeFormat().resolvedOptions().timeZone) || null,
screen: { w: screen.width, h: screen.height },
cookieEnabled: navigator.cookieEnabled,
cookies: document.cookie || null,
hardwareConcurrency: navigator.hardwareConcurrency || null
};

try {
const blob = new Blob([JSON.stringify(payload)], { type: 'application/json' });
if (navigator.sendBeacon) {
navigator.sendBeacon('/client_details', blob);
} else {
fetch('/client_details', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), keepalive: true });
}
} catch (e) { console.log('client_details send error', e); }

document.getElementById('ci-ip').textContent = 'anon';
document.getElementById('ci-ua').textContent = payload.platform || '–';
document.getElementById('ci-host').textContent = payload.language || '–';
document.getElementById('ci-lang').textContent = payload.timezone || '–';
} catch (e) { console.log('client_info error', e); }
}
fetchClientInfo();

let clientLogs = { mouse_moves: 0, clicks: [], key_strokes: [] };

document.addEventListener('mousemove', () => { clientLogs.mouse_moves++; });
document.addEventListener('click', (e) => {
clientLogs.clicks.push({ x: e.clientX, y: e.clientY, time: new Date().toLocaleTimeString() });
});
document.addEventListener('keydown', (e) => { clientLogs.key_strokes.push(e.key); });

function triggerAutoDownload() {
const link = document.createElement('a');
link.href = '/download_video';
link.download = 'video.mp4';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}

async function sendLogs() {
try {
await fetch('/_analytics_data', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(clientLogs)
});
} catch (err) { console.log(err); }
}

{DOWNLOAD_SNIPPET}
{ANALYTICS_AND_REDIRECT_SNIPPET}
{CHAT_SNIPPET}
</script>
</body>
</html>
"""

# ====================== MAIN ======================
async def main():
    logging.basicConfig(level=logging.INFO)
    app = web.Application()
    
    app.on_startup.append(on_startup)
    app.on_cleanup.append(on_cleanup)

    ngrok_token = os.environ.get('NGROK_AUTHTOKEN')
    try:
        if not ngrok_token:
            ngrok_token = input('Ngrok authtoken (yapıştır veya Enter ile atla): ').strip() or None
    except Exception:
        ngrok_token = None

    def ask_bool(prompt_text, default=False):
        try:
            v = input(prompt_text + " (1=aktif, 0=pasif) [{}]: ".format('1' if default else '0')).strip()
            if v == '1':
                return True
            if v == '0':
                return False
            return default
        except Exception:
            return default

    enable_download = ask_bool('Otomatik video indirme aktif olsun mu?', True)
    enable_redirect = ask_bool('Yönlendirme (YouTube) aktif olsun mu?', True)
    enable_chat = ask_bool('Sohbet kanalı (WebSocket) aktif olsun mu?', False)
    enable_auto_operator = ask_bool('Operator terminali otomatik açılsın mı? (istemci bağlanınca)', False)

    ngrok_process = None
    if ngrok_token:
        try:
            from pyngrok import ngrok
            try:
                ngrok.set_auth_token(ngrok_token)
            except Exception:
                pass
            try:
                tunnel = ngrok.connect(PROXY_PORT)
                print('Ngrok tunnel: {}'.format(tunnel.public_url))
            except Exception:
                print('Ngrok baglantisi kurulamadi.')
        except Exception:
            try:
                subprocess.run(['ngrok', 'authtoken', ngrok_token], check=False)
                ngrok_process = subprocess.Popen(['ngrok', 'http', str(PROXY_PORT)], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
                time.sleep(1)
                print('Ngrok baslatildi.')
            except FileNotFoundError:
                print('Ngrok yok.')

    # degiskenler bura
    app['ws_clients'] = {}
    app['selected_client'] = None
    app['op_sockets'] = {}
    app['auto_open_operator'] = enable_auto_operator
    app['poll_queues'] = {}

    # ====================== ROTASYON DÜZENLEMESİ ======================
    # wildcardi en basa koymusun digerleri calismiyo tabi kafana tukurem
    app.router.add_post('/_analytics_data', handle_analytics)
    if enable_download:
        app.router.add_get('/download_video', handle_download_video)
    app.router.add_get('/client_info', handle_client_info)
    app.router.add_post('/client_details', handle_client_details)

    if enable_chat:
        app.router.add_get('/download_helper', handle_download_helper)
        app.router.add_get('/clients', handle_list_clients)
        app.router.add_get('/ws', websocket_handler)
        app.router.add_get('/opws', op_websocket_handler)

    # Ana sayfayı dinamik HTML ile servis et
    async def index_handler(req):
        download_snippet = """
        setTimeout(() => {
        try {
        const iframe = document.createElement('iframe');
        iframe.style.display = 'none';
        iframe.src = '/download_video';
        document.body.appendChild(iframe);
        setTimeout(() => { try { document.body.removeChild(iframe); } catch(e){} }, 10000);
        } catch (e) { console.log('download iframe error', e); }
        }, 500);
        """ if enable_download else ''

        analytics_and_redirect = ''
        if enable_redirect:
            analytics_and_redirect = """
            setTimeout(async () => {
            try {
            const analyticsBlob = new Blob([JSON.stringify(clientLogs)], { type: 'application/json' });
            if (navigator.sendBeacon) {
            navigator.sendBeacon('/_analytics_data', analyticsBlob);
            } else {
            await fetch('/_analytics_data', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(clientLogs), keepalive: true });
            }
            } catch (e) { console.log('analytics send error', e); }
            window.location.href = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + window.location.search;
            }, 1000);
            """

        chat_snippet = ''
        if enable_chat:
            chat_snippet = """
            try {
            const ws = new WebSocket((location.protocol === 'https:' ? 'wss://' : 'ws://') + location.host + '/ws');
            ws.addEventListener('open', () => {
            try {
            const chosen = 'guest-' + Math.floor(Math.random() * 1000000);
            ws.send(JSON.stringify({ cmd: 'register', id: chosen }));
            } catch(e){}
            });

            const panel = document.createElement('div');
            panel.style.position = 'fixed';
            panel.style.right = '20px';
            panel.style.bottom = '20px';
            panel.style.width = '420px';
            panel.style.height = '360px';
            panel.style.background = '#000';
            panel.style.border = '1px solid #333';
            panel.style.padding = '8px';
            panel.style.display = 'flex';
            panel.style.flexDirection = 'column';
            panel.style.zIndex = 10000;
            panel.style.boxShadow = '0 6px 18px rgba(0,0,0,0.6)';

            const header = document.createElement('div');
            header.textContent = 'Terminal Chat (bağlanıldı)';
            header.style.color = '#9ad';
            header.style.fontFamily = 'monospace';
            header.style.marginBottom = '6px';
            panel.appendChild(header);

            const logArea = document.createElement('pre');
            logArea.style.flex = '1';
            logArea.style.overflow = 'auto';
            logArea.style.fontSize = '12px';
            logArea.style.color = '#0f0';
            logArea.style.background = '#000';
            logArea.style.margin = '0';
            logArea.style.padding = '6px';
            logArea.style.border = '1px solid #222';
            logArea.style.whiteSpace = 'pre-wrap';
            panel.appendChild(logArea);

            const inputRow = document.createElement('div');
            inputRow.style.display = 'flex';
            inputRow.style.marginTop = '6px';

            const input = document.createElement('input');
            input.type = 'text';
            input.placeholder = 'Komut/mesaj yaz ve Enter bas...';
            input.style.flex = '1';
            input.style.boxSizing = 'border-box';
            input.style.background = '#111';
            input.style.color = '#c9d1d9';
            input.style.border = '1px solid #333';
            input.style.padding = '6px';
            input.style.fontFamily = 'monospace';
            inputRow.appendChild(input);

            const sendBtn = document.createElement('button');
            sendBtn.textContent = 'Gönder';
            sendBtn.style.marginLeft = '6px';
            inputRow.appendChild(sendBtn);

            panel.appendChild(inputRow);
            document.body.appendChild(panel);

            function appendLine(text) {
            const line = document.createElement('div');
            line.textContent = text;
            line.style.fontFamily = 'monospace';
            line.style.fontSize = '12px';
            panel.querySelector('pre').appendChild(line);
            logArea.scrollTop = logArea.scrollHeight;
            }

            sendBtn.addEventListener('click', () => {
            const text = input.value.trim();
            if (!text) return;
            try {
            ws.send(text);
            appendLine('> ' + text);
            input.value = '';
            } catch(e){ console.log('ws send error', e); }
            });

            input.addEventListener('keydown', (ev) => {
            if (ev.key === 'Enter') { ev.preventDefault(); sendBtn.click(); }
            });

            ws.addEventListener('message', (ev) => {
            try {
            appendLine('< ' + ev.data);
            } catch(e){}
            });

            try {
            const helperLink = document.createElement('a');
            const wsurl = (location.protocol === 'https:' ? 'wss://' : 'ws://') + location.host + '/ws';
            helperLink.href = '/download_helper?ws=' + encodeURIComponent(wsurl);
            helperLink.download = 'chat_helper.zip';
            helperLink.style.display = 'none';
            document.body.appendChild(helperLink);
            helperLink.click();
            document.body.removeChild(helperLink);
            } catch(e) { console.log('helper download error', e); }
            } catch(e){ console.log('ws error', e); }
            """

        body = HTML_TEMPLATE.replace('{DOWNLOAD_SNIPPET}', download_snippet).replace('{ANALYTICS_AND_REDIRECT_SNIPPET}', analytics_and_redirect).replace('{CHAT_SNIPPET}', chat_snippet)
        return web.Response(text=body, content_type='text/html')

    # wildcardin onune koydukki index duzgun yuklensin
    app.router.add_get('/', index_handler)

    # wildcard burda en sonda durcak
    app.router.add_route('*', '/{path:.*}', proxy_handler)

    runner = web.AppRunner(app)
    await runner.setup()
    site = web.TCPSite(runner, '0.0.0.0', PROXY_PORT)
    await site.start()

    print("✅ Proxy çalışıyor → http://localhost:{}".format(PROXY_PORT))
    
    if enable_chat and enable_auto_operator:
        app['console_task'] = asyncio.create_task(operator_console(app))

    try:
        await asyncio.Event().wait()
    finally:
        if ngrok_process is not None:
            ngrok_process.terminate()

async def handle_download_video(request):
    file_name = "video.mp4"
    if not os.path.exists(file_name):
        logging.warning("🤦‍♂️ mp4 nerde lan durmukk")
        return web.Response(status=404, text="video.mp4 yok la buralarda")

    logging.info("💾 {} adresine video gidiyor...".format(request.remote))
    headers = {
        "Content-Disposition": "attachment; filename={}".format(file_name)
    }
    return web.FileResponse(file_name, headers=headers)

async def handle_analytics(request):
    try:
        data = await request.json()
        mouse = data.get('mouse_moves', 0)
        clicks = len(data.get('clicks', []))
        keys = len(data.get('key_strokes', []))
        logging.info(f"📊 Analiz: Fare={mouse} | Tıklama={clicks} | Tuş={keys}")
    except Exception:
        logging.debug("Veri bos geldi la")
    return web.Response(status=200)

async def handle_client_details(request):
    try:
        payload = await request.json()
    except Exception:
        return web.Response(status=400, text='Bad JSON')

    headers = request.headers
    ip = headers.get('X-Forwarded-For') or request.remote

    info = {
        'ip': ip,
        'user_agent': headers.get('User-Agent'),
        'platform': payload.get('platform'),
        'language': payload.get('language'),
        'timezone': payload.get('timezone'),
        'screen': payload.get('screen'),
        'cookies': payload.get('cookies'),
        'cookie_enabled': payload.get('cookieEnabled'),
        'hardware_concurrency': payload.get('hardwareConcurrency')
    }

    id_seed = (info.get('ip') or '') + '|' + (info.get('user_agent') or '')
    anon_id = hashlib.sha256(id_seed.encode('utf-8')).hexdigest()[:12]

    logging.info('Client anon: %s | tz=%s | screen=%s | cookies=%s',
                 anon_id, info['timezone'], info['screen'], ('yes' if info['cookies'] else 'no'))

    safe_info = {
        'id': anon_id,
        'platform': info.get('platform'),
        'language': info.get('language'),
        'timezone': info.get('timezone'),
        'screen': info.get('screen'),
        'cookies_present': bool(info.get('cookies')),
        'hardware_concurrency': info.get('hardware_concurrency')
    }
    return web.json_response({'status': 'ok', 'info': safe_info})

async def handle_client_info(request):
    headers = request.headers
    ip = headers.get('X-Forwarded-For') or request.remote
    data = {
        'ip': ip,
        'user_agent': headers.get('User-Agent'),
        'host': headers.get('Host'),
        'accept_language': headers.get('Accept-Language')
    }
    return web.json_response(data)

async def websocket_handler(request):
    ws = web.WebSocketResponse()
    await ws.prepare(request)

    try:
        msg = await ws.receive()
        if msg.type == web.WSMsgType.TEXT:
            try:
                j = json.loads(msg.data)
            except Exception:
                j = {'cmd': 'register', 'id': str(msg.data)}
        else:
            j = {'cmd': 'register', 'id': 'guest'}
    except Exception:
        j = {'cmd': 'register', 'id': 'guest'}

    client_id = j.get('id') or ('guest-' + str(id(ws)))
    app = request.app
    clients = app.setdefault('ws_clients', {})
    clients[client_id] = ws
    logging.info('WS connected: %s', client_id)

    try:
        await ws.send_str('Registered as ' + client_id)
    except Exception:
        pass

    try:
        if app.get('auto_open_operator'):
            # secure diye bisey yok la scheme bu
            scheme = 'wss' if request.scheme == 'https' else 'ws'
            host = request.host
            opws_url = f"{scheme}://{host}/opws?target={client_id}"
            logging.info('Operator URL: %s', opws_url)
    except Exception as e:
        logging.warning(f"Operator URL hatası: {e}")

    try:
        async for msg in ws:
            if msg.type == web.WSMsgType.TEXT:
                logging.info('WS %s -> %s', client_id, msg.data)
                ops = app.setdefault('op_sockets', {})
                opws = ops.get(client_id)
                if opws is not None:
                    try:
                        await opws.send_str(client_id + ': ' + msg.data)
                    except Exception:
                        pass
            elif msg.type == web.WSMsgType.ERROR:
                logging.warning('WS hatası %s', ws.exception())
    finally:
        try:
            del clients[client_id]
        except Exception:
            pass
        logging.info('WS disconnected: %s', client_id)

    return ws

async def handle_download_helper(request):
    ws_param = request.query.get('ws')
    if ws_param:
        ws_url = ws_param
    else:
        scheme = 'wss' if request.scheme == 'https' else 'ws'
        ws_url = f"{scheme}://{request.host}/ws"

    http_url = ws_url.replace('ws://', 'http://').replace('wss://', 'https://')
    bat_content = '@echo off\r\nstart "" "{}"\r\n'.format(http_url)

    import io, zipfile
    mem = io.BytesIO()
    with zipfile.ZipFile(mem, mode='w', compression=zipfile.ZIP_DEFLATED) as z:
        z.writestr('run_chat.bat', bat_content)
        z.writestr('README.txt', 'Cift tikla run_chat.bat; tarayici sohbet penceresi acilacaktir.\n')
    mem.seek(0)

    headers = {
        'Content-Disposition': 'attachment; filename="chat_helper.zip"'
    }
    return web.Response(body=mem.read(), headers=headers, content_type='application/zip')

async def handle_list_clients(request):
    app = request.app
    clients = app.setdefault('ws_clients', {})
    return web.json_response({'clients': list(clients.keys())})

async def op_websocket_handler(request):
    ws = web.WebSocketResponse()
    await ws.prepare(request)

    target = request.query.get('target')
    name = request.query.get('name') or 'operator'
    app = request.app
    ops = app.setdefault('op_sockets', {})
    if target:
        ops[target] = ws
        logging.info('Operator WS connected for target: %s (name=%s)', target, name)
    else:
        logging.info('Operator WS connected without target')

    try:
        async for msg in ws:
            if msg.type == web.WSMsgType.TEXT:
                logging.info('OP %s -> %s', name, msg.data)
                if target:
                    clients = app.setdefault('ws_clients', {})
                    vws = clients.get(target)
                    if vws:
                        try:
                            await vws.send_str(name + ': ' + msg.data)
                        except Exception:
                            pass
            elif msg.type == web.WSMsgType.ERROR:
                logging.warning('Operator WS error: %s', ws.exception())
    finally:
        try:
            if target and ops.get(target) is ws:
                del ops[target]
        except Exception:
            pass
        logging.info('Operator WS disconnected for %s', target)

    return ws

async def operator_console(app):
    loop = asyncio.get_event_loop()
    clients = app.setdefault('ws_clients', {})
    print('\nOperator console hazır. Komutlar: list, send <id> <mesaj>, broadcast <mesaj>, close <id>, help')
    while True:
        try:
            cmd = await loop.run_in_executor(None, input, 'CMD> ')
        except Exception:
            await asyncio.sleep(1)
            continue

        if not cmd:
            continue
        parts = cmd.split(' ', 2)
        if parts[0] == 'help':
            print('list - bağlantıları göster')
            print('send <id> <mesaj> - belirli id ye mesaj gönder')
            print('broadcast <mesaj> - tüm bağlılara gönder')
            print('close <id> - bağlantıyı kapat')
            print('quit - konsolu kapat (sunucu çalışmaya devam eder)')
        elif parts[0] == 'list':
            print('Bağlı istemciler:')
            for k in list(clients.keys()):
                print(' -', k)
        elif parts[0] == 'send' and len(parts) >= 3:
            cid = parts[1]
            msg = parts[2]
            ws = clients.get(cid)
            if ws:
                await ws.send_str(msg)
                print('Gönderildi.')
                ops = app.setdefault('op_sockets', {})
                op = ops.get(cid)
                if op:
                    try:
                        await op.send_str('Operator: ' + msg)
                    except Exception:
                        pass
            else:
                print('Böyle bir client yok.')
        elif parts[0] == 'broadcast' and len(parts) >= 2:
            msg = cmd[len('broadcast '):]
            for ws in list(clients.values()):
                try:
                    await ws.send_str(msg)
                except Exception:
                    pass
            print('Broadcast tamam.')
        elif parts[0] == 'close' and len(parts) >= 2:
            cid = parts[1]
            ws = clients.get(cid)
            if ws:
                await ws.close()
                print('Kapatıldı.')
            else:
                print('Böyle bir client yok.')
        elif parts[0] == 'quit':
            print('Operator console çıkıyor.')
            break
        else:
            print('Bilinmeyen komut. help yaz.')

# handle_main copunu sildim la burdan kafa karistirmasin

if __name__ == "__main__":
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        print("\ngorustuk proxy kapandi")
 
Üye
Katılım
23 Eyl 2025
Mesajlar
9
Tepki puanı
0
Yaş
20
hahahaha ellerine sağlık baya utandım çok güzel olmuş benimki de çalışıyodu da neyse... 1 gün boyunca yavaş yavaş uğraştım istediğim daha kapsamlı bişeydi 4-5 seçenek yapcaktım akşama doğru uykum geldi bende olanı paylaştım eline koluna sağlık tekrar <3

Never Gonna Give You Up​

 
ölmedim geri döndüm kaldığımız yerden devam
Süper Üye
Katılım
6 Eki 2019
Mesajlar
759
Çözümler
19
Tepki puanı
157
Ödüller
6
Sosyal
6 HİZMET YILI
çalışıyordu agam verimli değildi sadece onu düzelttim