#!/usr/bin/env python3 """ Project Pointer - Evrensel Masaüstü Alıcısı (Windows, macOS, Linux) Uçtan uca şifreli ve sıfır gecikmeli sunum kumandası alıcısı. """ import sys import os import json import time import asyncio import argparse # Terminal renkleri class Colors: RESET = "\033[0m" BOLD = "\033[1m" CYAN = "\033[36m" GREEN = "\033[32m" YELLOW = "\033[33m" RED = "\033[31m" MAGENTA = "\033[35m" DIM = "\033[2m" # Windows ANSI desteğini aktif et if sys.platform == "win32": os.system("color") DEFAULT_SERVER_URL = "wss://pointer.fenergytech.org.tr" def get_input_controllers(): """Giriş simülatörlerini yükle (pynput)""" try: from pynput.keyboard import Controller as KeyController, Key from pynput.mouse import Controller as MouseController, Button return KeyController(), MouseController(), Key, Button except ImportError: print(f"{Colors.RED}Gerekli kütüphane eksik: pynput{Colors.RESET}") print("Lütfen şu komutla yükleyin: pip install pynput websockets") sys.exit(1) def print_banner(pin: str): print(f""" {Colors.CYAN}{Colors.BOLD}╔════════════════════════════════════════════════════════════╗ ║ PROJECT POINTER ║ ║ Akıllı Sunum Alıcısı ║ ╚════════════════════════════════════════════════════════════╝{Colors.RESET} {Colors.YELLOW}{Colors.BOLD}┌────────────────────────────────────────────────────────────┐ │ EŞLEŞME PIN KODU: [ {Colors.GREEN}{pin}{Colors.YELLOW} ] │ │ Telefondaki uygulamayı açıp bu 6 haneli PIN'i girin. │ └────────────────────────────────────────────────────────────┘{Colors.RESET} """) def timestamp(): return time.strftime("%H:%M:%S") async def run_receiver(server_url: str, custom_pin: str = None): try: import websockets except ImportError: print(f"{Colors.RED}Gerekli kütüphane eksik: websockets{Colors.RESET}") print("Lütfen şu komutla yükleyin: pip install websockets pynput") sys.exit(1) keyboard, mouse, Key, Button = get_input_controllers() while True: try: print(f"{Colors.DIM}[{timestamp()}] Sunucuya bağlanılıyor...{Colors.RESET}") async with websockets.connect(server_url, ping_interval=15, ping_timeout=10) as ws: # Host kaydı gönder reg_payload = {"type": "register_host"} if custom_pin: reg_payload["pin"] = custom_pin await ws.send(json.dumps(reg_payload)) async for message in ws: try: data = json.loads(message) except json.JSONDecodeError: continue msg_type = data.get("type") if msg_type == "host_registered": pin = data.get("pin", "????") print_banner(pin) print(f"{Colors.CYAN}[{timestamp()}] Telefonun bağlanması bekleniyor...{Colors.RESET}\n") elif msg_type == "client_connected": device = data.get("device", "Telefon") count = data.get("clientCount", 1) print(f"{Colors.GREEN}{Colors.BOLD}✓ [{timestamp()}] BAĞLANTI KURULDU! Cihaz: {device} (Toplam: {count}){Colors.RESET}") print(f"{Colors.DIM} Artık telefondan sunumu yönetebilirsiniz.{Colors.RESET}\n") elif msg_type == "client_disconnected": count = data.get("clientCount", 0) print(f"{Colors.YELLOW}⚠ [{timestamp()}] Telefon bağlantısı ayrıldı. (Kalan: {count}){Colors.RESET}") elif msg_type == "command": action = data.get("action") payload = data.get("data", {}) if action == "next": keyboard.press(Key.right) keyboard.release(Key.right) print(f"{Colors.GREEN} ➜ [{timestamp()}] İLERİ (Sonraki Slayt){Colors.RESET}") elif action == "prev": keyboard.press(Key.left) keyboard.release(Key.left) print(f"{Colors.YELLOW} ➜ [{timestamp()}] GERİ (Önceki Slayt){Colors.RESET}") elif action == "black": keyboard.press('b') keyboard.release('b') print(f"{Colors.MAGENTA} ➜ [{timestamp()}] SİYAH EKRAN (B){Colors.RESET}") elif action == "white": keyboard.press('w') keyboard.release('w') print(f"{Colors.MAGENTA} ➜ [{timestamp()}] BEYAZ EKRAN (W){Colors.RESET}") elif action == "fullscreen": keyboard.press(Key.f5) keyboard.release(Key.f5) print(f"{Colors.CYAN} ➜ [{timestamp()}] TAM EKRAN (F5){Colors.RESET}") elif action == "exit": keyboard.press(Key.esc) keyboard.release(Key.esc) print(f"{Colors.RED} ➜ [{timestamp()}] ÇIKIŞ (Escape){Colors.RESET}") elif action == "trackpad_move": dx = payload.get("dx", 0) dy = payload.get("dy", 0) mouse.move(dx, dy) elif action == "trackpad_click": mouse.click(Button.left) print(f"{Colors.CYAN} ➜ [{timestamp()}] FARE TIKLAMA (Sol Tık){Colors.RESET}") except Exception as e: print(f"{Colors.RED}[{timestamp()}] Bağlantı koptu: {e}{Colors.RESET}") print(f"{Colors.YELLOW}[{timestamp()}] 3 saniye içinde yeniden bağlanılıyor...{Colors.RESET}") await asyncio.sleep(3) def main(): parser = argparse.ArgumentParser(description="Project Pointer Evrensel Masaüstü Alıcısı") parser.add_argument("--pin", type=str, help="Özel 6 haneli PIN kodu belirler") parser.add_argument("--server", type=str, default=DEFAULT_SERVER_URL, help=argparse.SUPPRESS) # Kullanıcıdan gizli args = parser.parse_args() try: asyncio.run(run_receiver(args.server, args.pin)) except KeyboardInterrupt: print(f"\n{Colors.DIM}Alıcı durduruldu.{Colors.RESET}") if __name__ == "__main__": main()