# https://git.krzak.org/N0VA/ESharePy/raw/branch/main/main.py import sys import os import socket import struct import time # Standard KeyCodes KEY_MAP = { 'w': (19, "DPAD_UP"), 's': (20, "DPAD_DOWN"), 'a': (21, "DPAD_LEFT"), 'd': (22, "DPAD_RIGHT"), ' ': (23, "DPAD_CENTER (OK)"), 'e': (23, "DPAD_CENTER (OK)"), '\r': (23, "DPAD_CENTER (OK)"), '\n': (23, "DPAD_CENTER (OK)"), 'b': (4, "BACK"), 'h': (3, "HOME"), '+': (24, "VOLUME_UP"), '=': (24, "VOLUME_UP"), '-': (25, "VOLUME_DOWN"), '_': (25, "VOLUME_DOWN"), '0': (164, "VOLUME_MUTE"), } def get_broadcast_addresses(): broadcasts = {'255.255.255.255'} try: with open('/proc/net/route') as f: for line in f.readlines()[1:]: fields = line.strip().split() dest = fields[1] mask = fields[7] if dest == '00000000': continue d = int(dest, 16) m = int(mask, 16) b = (d & m) | (~m & 0xFFFFFFFF) broadcasts.add(socket.inet_ntoa(struct.pack('IIIII", packet, 0, 0, 0, 0, len(magic), 0) packet[20:20 + len(magic)] = magic for bcast in get_broadcast_addresses(): try: sock.sendto(packet, (bcast, 48689)) except Exception: pass t_end = time.time() + timeout found_devices = [] while time.time() < t_end: try: data, addr = sock.recvfrom(1024) reply = data.decode("utf-8", errors="ignore") if reply.startswith("ECloudBox"): parts = reply.split(":") name = parts[1] if len(parts) > 1 else "Unknown" port = int(parts[2]) if len(parts) > 2 and parts[2].isdigit() else 8121 device = (addr[0], port, name) if device not in found_devices: found_devices.append(device) print(f"Found TV: '{name}' at {addr[0]}:{port}") except socket.timeout: break except Exception: pass sock.close() return found_devices def connect(ip, port=8121): print(f"Connecting to {ip}:{port}...") sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(5.0) sock.connect((ip, port)) sock.sendall(b"getServerInfo\r\neshare\r\n\r\n") try: resp = sock.recv(1024).decode("utf-8", errors="ignore") if resp.strip(): print(f"Server response: {resp.strip()[:100]}") except socket.timeout: pass sock.sendall(b"GETPASSWORDCONFIG\r\neshare\r\n\r\n") try: resp = sock.recv(1024).decode("utf-8", errors="ignore") except socket.timeout: pass sock.sendall(b"sayHello\r\nEShareClient\r\n\r\n") print("Handshake complete! Connected.") return sock def send_key(sock, keycode): cmd = f"KEYEVENT\r\n{keycode}\r\n\r\n".encode("utf-8") sock.sendall(cmd) def send_text(sock, text): escaped = text.replace("\\", "\\\\").replace("\r", "\\r").replace("\n", "\\n").replace("\t", "\\t") cmd = f"CONTENT\r\n1\r\n{escaped}\r\n\r\n".encode("utf-8") sock.sendall(cmd) def getch(): if not sys.stdin.isatty(): line = sys.stdin.readline() return line[0] if line else 'q' import tty, termios fd = sys.stdin.fileno() old = termios.tcgetattr(fd) try: tty.setraw(fd) ch = sys.stdin.read(1) if ch == '\x1b': ch2 = sys.stdin.read(1) if ch2 == '[': ch3 = sys.stdin.read(1) arrows = {'A': 'w', 'B': 's', 'C': 'd', 'D': 'a'} return arrows.get(ch3, '') return ch finally: termios.tcsetattr(fd, termios.TCSADRAIN, old) def print_help(): print("\n--- Controls ---") print(" [W / ↑] Up [S / ↓] Down") print(" [A / ←] Left [D / →] Right") print(" [Space/E/Enter] OK [B] Back") print(" [H] Home [0] Mute") print(" [+] Vol Up [-] Vol Down") print(" [T] Type text [Q] Quit") print("----------------\n") def main(): tv_ip = None tv_port = 8121 if len(sys.argv) > 1: tv_ip = sys.argv[1] if len(sys.argv) > 2: tv_port = int(sys.argv[2]) else: devices = discover() if not devices: print("No TVs discovered.") tv_ip = input("Enter TV IP address manually: ").strip() elif len(devices) == 1: tv_ip, tv_port, name = devices[0] print(f"Auto-selected TV: '{name}' ({tv_ip}:{tv_port})") else: print(f"\nFound {len(devices)} TVs:") for idx, (ip, port, name) in enumerate(devices, 1): print(f" [{idx}] {name} ({ip}:{port})") choice = input(f"Select TV [1-{len(devices)}] (default 1): ").strip() idx = int(choice) - 1 if choice.isdigit() and 1 <= int(choice) <= len(devices) else 0 tv_ip, tv_port, name = devices[idx] print(f"Selected TV: '{name}' ({tv_ip}:{tv_port})") if not tv_ip: print("No IP provided. Exiting.") return sock = connect(tv_ip, tv_port) print_help() try: while True: ch = getch() if not ch: continue lower_ch = ch.lower() if lower_ch == 'q' or ch == '\x03': print("\nExiting...") break if lower_ch == 't': print() text = input("Enter text to send to TV (keyboard input): ") if text: send_text(sock, text) print(f"Sent text: {repr(text)}") continue if lower_ch in KEY_MAP: keycode, name = KEY_MAP[lower_ch] send_key(sock, keycode) print(f"Sent: {name} (code {keycode})", flush=True) else: print(f"Unknown key: {repr(ch)} (type 'q' to quit)", flush=True) except KeyboardInterrupt: print("\nInterrupted.") except Exception as e: print(f"\nConnection error: {e}") finally: try: sock.close() except: pass if __name__ == "__main__": main()