diff --git a/TUI.py b/TUI.py index 061e617..6b5d67c 100644 --- a/TUI.py +++ b/TUI.py @@ -13,18 +13,28 @@ def auto_install_deps(): __import__(import_name) except ImportError: missing_packages.append(pip_name) + if not missing_packages: return + + print("[Auto-Installer] Installing client dependencies:", ", ".join(missing_packages)) cmd = [sys.executable, "-m", "pip", "install"] + missing_packages result = subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE) + if result.returncode != 0: stderr_output = result.stderr.decode('utf-8', errors='ignore') if "externally-managed-environment" in stderr_output.lower(): - force_cmd = cmd + ["--break-system-packages"] - force_result = subprocess.run(force_cmd) - if force_result.returncode == 0: - sys.exit(0) - sys.exit(1) + print("\n" + "!"*50) + print("[Warning] OS blocks global package installation via pip.") + print("!"*50 + "\n") + choice = input("Use --break-system-packages flag? (y/n): ").strip().lower() + if choice == 'y': + force_cmd = cmd + ["--break-system-packages"] + force_result = subprocess.run(force_cmd) + if force_result.returncode == 0: + print("[Success] Restart the script!") + sys.exit(0) + sys.exit(1) try: import sys @@ -54,7 +64,19 @@ try: except: auto_install_deps() +<<<<<<< HEAD:TUI.py import socket_manager +======= +from prompt_toolkit.application import Application +from prompt_toolkit.key_binding import KeyBindings +from prompt_toolkit.layout.containers import HSplit, VSplit, Window +from prompt_toolkit.layout.controls import FormattedTextControl +from prompt_toolkit.layout.layout import Layout +from prompt_toolkit.widgets import TextArea, Frame +from prompt_toolkit.styles import Style +from prompt_toolkit.application.current import get_app +from prompt_toolkit.filters import has_focus +>>>>>>> parent of cfd13cf (Update client.py):client.py CONFIG_FILE = "settings.json" WIKI_URL = "https://git.idkmail.ru/lohrrrr/TyChat-Client/wiki" @@ -71,6 +93,7 @@ ASCII_ART = r""" |___/ """ +<<<<<<< HEAD:TUI.py class CommandCompleter(Completer): def __init__(self): self.completions = { @@ -148,6 +171,9 @@ class PluginManager: proto["failed"] = True proto["enabled"] = False return None +======= +sio = socketio.Client() +>>>>>>> parent of cfd13cf (Update client.py):client.py class TyClient: def __init__(self): @@ -156,20 +182,12 @@ class TyClient: self.uin = "" self.password = "" self.contacts = {} - self.groups = {} self.history = {} self.preserved = {} - self.blocklist = [] - self.active_chat = None + self.active_chat = None self.app = None self.loop_running = True self.selected_contact_idx = 0 - - self.is_busy = False - self.dialing_uin = None - self.pending_requests = [] - self.pending_windows = [] - self.show_welcome_popup = False self.current_tab = "chat" self.settings_cursor = 0 @@ -190,9 +208,9 @@ class TyClient: self.uin = cfg.get("uin", "") self.password = cfg.get("password", "") self.contacts = cfg.get("contacts", {}) - self.groups = cfg.get("groups", {}) self.history = cfg.get("history", {}) self.preserved = cfg.get("preserved", {}) +<<<<<<< HEAD:TUI.py self.blocklist = cfg.get("blocklist", []) self.primary_protocol = cfg.get("primary_protocol", "") @@ -212,6 +230,8 @@ class TyClient: self.primary_protocol = list(self.plugin_manager.protocols.keys())[0] if not self.primary_transport and self.plugin_manager.transports: self.primary_transport = list(self.plugin_manager.transports.keys())[0] +======= +>>>>>>> parent of cfd13cf (Update client.py):client.py return True except: return False @@ -226,18 +246,22 @@ class TyClient: "uin": self.uin, "password": self.password, "contacts": self.contacts, - "groups": self.groups, "history": self.history, +<<<<<<< HEAD:TUI.py "preserved": self.preserved, "blocklist": self.blocklist, "primary_protocol": self.primary_protocol, "primary_transport": self.primary_transport, "enabled_protocols": enabled_protos, "enabled_transports": enabled_trans +======= + "preserved": self.preserved +>>>>>>> parent of cfd13cf (Update client.py):client.py } with open(CONFIG_FILE, "w", encoding="utf-8") as f: json.dump(cfg, f, indent=4, ensure_ascii=False) +<<<<<<< HEAD:TUI.py def play_dial_tones(self, target_uin): self.dialing_uin = target_uin while self.dialing_uin == target_uin and self.loop_running: @@ -249,6 +273,20 @@ class TyClient: if self.dialing_uin != target_uin or not self.loop_running: break time.sleep(0.1) +======= + def text_to_audio(self, text): + audio_signals = [] + t_start = np.linspace(0, 0.3, int(SAMPLE_RATE * 0.3), False) + audio_signals.append(np.sin(1000 * t_start * 2 * np.pi)) + for char in text: + freq = BASE_FREQ + ord(char) * FREQ_STEP + t = np.linspace(0, TONE_DURATION, int(SAMPLE_RATE * TONE_DURATION), False) + audio_signals.append(np.sin(freq * t * 2 * np.pi)) + full_audio = np.concatenate(audio_signals).astype(np.float32) + if np.max(np.abs(full_audio)) > 0: + full_audio = full_audio / np.max(np.abs(full_audio)) + return full_audio.tobytes() +>>>>>>> parent of cfd13cf (Update client.py):client.py def play_and_decode(self, audio_bytes, sender_uin): audio_data = np.frombuffer(audio_bytes, dtype=np.float32) @@ -265,24 +303,37 @@ class TyClient: self.history[sender_uin].append(msg_buffer) self.refresh_ui() + full_text_received = "" while current_sample < len(audio_data) and self.loop_running: chunk = audio_data[current_sample : current_sample + samples_per_tone] if len(chunk) < samples_per_tone: break +<<<<<<< HEAD:TUI.py window_data = np.hanning(len(chunk)) fft_data = np.abs(np.fft.rfft(chunk * window_data)) frequencies = np.fft.rfftfreq(len(chunk), d=1/44100) +======= + window = np.hanning(len(chunk)) + fft_data = np.abs(np.fft.rfft(chunk * window)) + frequencies = np.fft.rfftfreq(len(chunk), d=1/SAMPLE_RATE) +>>>>>>> parent of cfd13cf (Update client.py):client.py detected_freq = frequencies[np.argmax(fft_data)] ascii_code = int(round((detected_freq - 600) / 25)) if 0 <= ascii_code < 65535: try: char = chr(ascii_code) self.history[sender_uin][-1] += char + full_text_received += char self.refresh_ui() except: pass time.sleep(0.1) current_sample += samples_per_tone + + if "ALARM! URGENT CALL!" in full_text_received: + client.contacts[sender_uin]["attention"] = True + self.refresh_ui() + sd.wait() self.save_config() @@ -293,6 +344,7 @@ class TyClient: self.refresh_ui() self.save_config() +<<<<<<< HEAD:TUI.py def send_sys_packet(self, to_uin, cmd): text_payload = f"SYS:{cmd}" proto_order = [] @@ -327,12 +379,51 @@ class TyClient: socket_manager.sio.emit("relay_packet", {"to_uin": to_uin, "payload": base64.b64encode(wrapped).decode('utf-8')}) return +======= +>>>>>>> parent of cfd13cf (Update client.py):client.py def refresh_ui(self): if self.app: self.app.invalidate() client = TyClient() +<<<<<<< HEAD:TUI.py +======= +@sio.event +def incoming_packet(data): + from_uin = data["from_uin"] + payload_base64 = data["payload"] + try: + audio_bytes = base64.b64decode(payload_base64.encode('utf-8')) + if from_uin not in client.contacts: + client.contacts[from_uin] = {"status": "offline", "unread": 0, "attention": False} + if client.active_chat != from_uin: + client.contacts[from_uin]["unread"] += 1 + threading.Thread(target=client.play_and_decode, args=(audio_bytes, from_uin), daemon=True).start() + except: + pass + +@sio.event +def online_statuses_response(data): + for uin, status in data.items(): + if uin in client.contacts: + client.contacts[uin]["status"] = status + client.refresh_ui() + +@sio.event +def error(data): + msg = data.get("message") + target = data.get("target_uin") + if msg == "offline" and target: + if target in client.contacts: + client.contacts[target]["status"] = "offline" + client.add_to_history(target, f"[SYSTEM]: They went offline. Everything that you will send now will be sent if they will back online while your client opened.") + if target in client.preserved: + if len(client.preserved[target]) > 0: + last_p = client.preserved[target][-1] + client.add_to_history(target, f"[You]: {last_p} (Preserved)") + +>>>>>>> parent of cfd13cf (Update client.py):client.py def status_checker_thread(): while client.loop_running: if socket_manager.sio.connected and client.contacts: @@ -371,10 +462,15 @@ def make_layout(): tokens = [] for idx, (uin, info) in enumerate(client.contacts.items()): status_str = "" - if info.get("attention"): status_str = " [!]" - elif info.get("unread", 0) > 0: status_str = f" ({info['unread']})" - elif info.get("status") == "online": status_str = " *" + if info.get("attention"): + status_str = " [!]" + elif info.get("unread", 0) > 0: + status_str = f" ({info['unread']})" + elif info.get("status") == "online": + status_str = " *" + content = f" {uin}{status_str}" +<<<<<<< HEAD:TUI.py if client.active_chat == uin and client.current_tab == "chat": style = "class:contact-active" elif idx == client.selected_contact_idx and get_app().layout.has_focus(sidebar_window) and client.current_tab == "chat": style = "class:contact-focused" else: style = "class:contact" @@ -385,6 +481,19 @@ def make_layout(): if client.active_chat == g_id and client.current_tab == "chat": style = "class:contact-active" else: style = "class:contact" tokens.extend([(style, f"{content}\n")]) +======= + + if client.active_chat == uin: + style = "class:contact-active" + elif idx == client.selected_contact_idx and get_app().layout.has_focus(sidebar_window): + style = "class:contact-focused" + else: + style = "class:contact" + + tokens.extend([ + (style, f"{content}\n"), + ]) +>>>>>>> parent of cfd13cf (Update client.py):client.py return tokens def get_main_text(): @@ -397,15 +506,14 @@ def make_layout(): ("class:desc", "Messenger on custom protocol named\n"), ("class:desc", "AcoustiOverSocket inspired by rtty\n"), ("", "\n"), +<<<<<<< HEAD:TUI.py ("class:help-tip", "Type / to trigger interactive command menu | F2: Settings Panel\n"), +======= + ("class:help-tip", "Type /help to open project Wiki\n"), +>>>>>>> parent of cfd13cf (Update client.py):client.py ("", "\n" * 2), ("class:help-tip", f"{DEV_SIGNATURE}\n") ]) - if client.dialing_uin: - tokens.extend([ - ("", "\n" * 2), - ("class:system", f"Dialing UIN {client.dialing_uin}... Waiting for accept.\n") - ]) return tokens tokens = [] @@ -419,6 +527,7 @@ def make_layout(): tokens.append(("", line + "\n")) return tokens +<<<<<<< HEAD:TUI.py def get_settings_text(): tokens = [("class:popup-title", " === SETTINGS & PLUGINS PANEL ===\n\n")] @@ -463,17 +572,19 @@ def make_layout(): newlines = text.count('\n') return Point(0, max(0, newlines - 1)) +======= +>>>>>>> parent of cfd13cf (Update client.py):client.py sidebar_control = FormattedTextControl(get_sidebar_text, focusable=True) sidebar_window = Frame(Window(content=sidebar_control, width=25), title="chats", style="class:border") - main_control = FormattedTextControl(get_main_text, get_cursor_position=get_cursor_pos) + + main_control = FormattedTextControl(get_main_text) def get_main_title(): - base_title = f"TyChat | You: {client.username} ({client.uin})" - if client.is_busy: base_title += " [DND/BUSY]" - if client.active_chat: return f"{base_title} | Chat: {client.active_chat}" - return base_title + if client.active_chat: + return f"TyChat | You: {client.username} ({client.uin}) | Chat with UIN: {client.active_chat}" + return f"TyChat | You: {client.username} ({client.uin})" - main_window = Frame(Window(content=main_control, wrap_lines=True), title=get_main_title, style="class:border") + main_window = Frame(Window(content=main_control), title=get_main_title, style="class:border") settings_control = FormattedTextControl(get_settings_text, focusable=True) settings_window = Frame(Window(content=settings_control, wrap_lines=True), title="Settings Router", style="class:border") @@ -482,15 +593,15 @@ def make_layout(): height=3, prompt="> ", multiline=False, - wrap_lines=True, - completer=CommandCompleter(), - complete_while_typing=True + wrap_lines=True ) - input_window = Frame(input_field, title="Input") + + input_window = Frame(input_field, title="Type message and press Enter (/exit to quit)") def accept_handler(buff): text = input_field.text.strip() - if not text: return + if not text: + return if text.lower() == "/exit": client.loop_running = False @@ -499,66 +610,29 @@ def make_layout(): return if text.lower() == "/help": - try: webbrowser.open(WIKI_URL) - except: pass - input_field.text = "" - return - - if text.lower() == "/busy": - client.is_busy = not client.is_busy - if client.active_chat: - status_msg = "enabled" if client.is_busy else "disabled" - client.add_to_history(client.active_chat, f"[SYSTEM]: DND Mode {status_msg}.") + try: + webbrowser.open(WIKI_URL) + if client.active_chat: + client.add_to_history(client.active_chat, "[SYSTEM]: Wiki link opened in browser.") + except: + if client.active_chat: + client.add_to_history(client.active_chat, f"[SYSTEM]: Failed to open browser. Wiki: {WIKI_URL}") input_field.text = "" client.refresh_ui() return if text.lower().startswith("/add "): new_uin = text.split(" ", 1)[1].strip() - if not new_uin: return - if new_uin in client.contacts: - client.active_chat = new_uin - input_field.text = "" - client.refresh_ui() - return - client.active_chat = None - threading.Thread(target=client.play_dial_tones, args=(new_uin,), daemon=True).start() - client.send_sys_packet(new_uin, "REQ_ADD") + if new_uin and new_uin not in client.contacts: + client.contacts[new_uin] = {"status": "offline", "unread": 0, "attention": False} + client.history[new_uin] = [] + client.save_config() input_field.text = "" client.refresh_ui() return - if text.lower().startswith("/room create "): - match = re.match(r'^/room create "([^"]+)"$', text, re.IGNORECASE) - if match: - r_name = match.group(1) - r_id = f"ROOM:{client.uin}:{r_name}" - client.groups[r_id] = {"title": r_name, "owner": client.uin, "members": [client.uin]} - client.history[r_id] = [f"[SYSTEM]: Room \"{r_name}\" created successfully. Local GUID: {r_id}"] - client.active_chat = r_id - client.save_config() - client.refresh_ui() - input_field.text = "" - return - - if text.lower().startswith("/room join "): - match = re.match(r'^/room join ([0-9]+):"([^"]+)"$', text, re.IGNORECASE) - if match: - r_owner = match.group(1) - r_name = match.group(2) - r_id = f"ROOM:{r_owner}:{r_name}" - if r_owner not in client.contacts and r_owner != client.uin: - client.contacts[r_owner] = {"status": "offline", "unread": 0, "attention": False} - client.groups[r_id] = {"title": r_name, "owner": r_owner, "members": list(set([client.uin, r_owner]))} - client.history[r_id] = [f"[SYSTEM]: Joined room \"{r_name}\". Local GUID: {r_id}"] - client.active_chat = r_id - client.save_config() - client.refresh_ui() - client.send_sys_packet(r_owner, f"REQ_JOIN_ROOM:{r_name}") - input_field.text = "" - return - if client.active_chat: +<<<<<<< HEAD:TUI.py if client.active_chat.startswith("ROOM:"): group = client.groups[client.active_chat] owner_uin = group["owner"] @@ -602,10 +676,14 @@ def make_layout(): input_field.text = "" return if len(text) > 300: +======= + if len(text) > 100: +>>>>>>> parent of cfd13cf (Update client.py):client.py client.add_to_history(client.active_chat, f"[SYSTEM]: Message too long!") input_field.text = "" return +<<<<<<< HEAD:TUI.py proto_to_use = client.peer_session_protocols.get(client.active_chat, client.primary_protocol) encoded = client.plugin_manager.safe_encode(proto_to_use, text) @@ -648,18 +726,52 @@ def make_layout(): ConditionalContainer(content=settings_window, filter=is_settings_panel), input_window ]) +======= + match = re.match(r'^s/([^/]+)/([^/]*)/?$', text) + if match: + search_str, replace_str = match.groups() + lines = client.history.get(client.active_chat, []) + edited = False + for i in range(len(lines) - 1, -1, -1): + if lines[i].startswith(f"[{client.username}]:") or lines[i].startswith("[You]:"): + if search_str in lines[i]: + lines[i] = lines[i].replace(search_str, replace_str) + edited = True + break + if edited: + client.refresh_ui() + client.save_config() + input_field.text = "" + return - def get_popup_text(): - if not client.pending_requests: return [] - req_uin = client.pending_requests[0] - return [ - ("class:popup-title", f" Incoming Handshake Request \n"), - ("class:popup-title", f" UIN: {req_uin} \n\n"), - ("", " Do you want to add them to contacts?\n\n"), - ("class:popup-keys", " [Y]es [N]o N[e]ver ") - ] - popup_window = Frame(Window(FormattedTextControl(get_popup_text), align=WindowAlign.CENTER, width=42, height=6), style="class:popup-border") + if text.startswith("/alert"): + text = "ALARM! URGENT CALL!" + client.contacts[client.active_chat]["attention"] = True + audio_b = client.text_to_audio(text) + p_b64 = base64.b64encode(audio_b).decode('utf-8') + + if client.contacts[client.active_chat]["status"] == "online": + sio.emit("relay_packet", {"to_uin": client.active_chat, "payload": p_b64}) + client.add_to_history(client.active_chat, f"[You]: {text}") + else: + if client.active_chat not in client.preserved: + client.preserved[client.active_chat] = [] + client.preserved[client.active_chat].append(text) + client.add_to_history(client.active_chat, f"[You]: {text} (Preserved)") + client.save_config() + + input_field.text = "" + + input_field.accept_handler = accept_handler +>>>>>>> parent of cfd13cf (Update client.py):client.py + + right_side = HSplit([ + main_window, + input_window + ]) + +<<<<<<< HEAD:TUI.py def get_signal_popup_text(): if not client.pending_windows: return [] win_info = client.pending_windows[0] @@ -768,34 +880,51 @@ def make_layout(): client.refresh_ui() @kb.add('tab', filter=~has_pending_request & ~has_pending_window & ~has_welcome_popup & is_chat_panel) - def _(event): - if event.app.layout.has_focus(input_field): event.app.layout.focus(sidebar_window) - else: event.app.layout.focus(input_field) +======= + root_container = VSplit([ + sidebar_window, + right_side + ]) + kb = KeyBindings() + + @kb.add('tab') +>>>>>>> parent of cfd13cf (Update client.py):client.py + def _(event): + if event.app.layout.has_focus(input_field): + event.app.layout.focus(sidebar_window) + else: + event.app.layout.focus(input_field) + +<<<<<<< HEAD:TUI.py @kb.add('up', filter=has_focus(sidebar_window) & ~has_pending_request & ~has_pending_window & ~has_welcome_popup & is_chat_panel) +======= + @kb.add('up', filter=has_focus(sidebar_window)) +>>>>>>> parent of cfd13cf (Update client.py):client.py def _(event): - all_chats = list(client.contacts.keys()) + list(client.groups.keys()) - if all_chats: - client.selected_contact_idx = (client.selected_contact_idx - 1) % len(all_chats) - target = all_chats[client.selected_contact_idx] - client.active_chat = target - if target in client.contacts: - client.contacts[target]["unread"] = 0 - client.contacts[target]["attention"] = False + if client.contacts: + client.selected_contact_idx = (client.selected_contact_idx - 1) % len(client.contacts) + target_uin = list(client.contacts.keys())[client.selected_contact_idx] + client.active_chat = target_uin + client.contacts[target_uin]["unread"] = 0 + client.contacts[target_uin]["attention"] = False client.refresh_ui() +<<<<<<< HEAD:TUI.py @kb.add('down', filter=has_focus(sidebar_window) & ~has_pending_request & ~has_pending_window & ~has_welcome_popup & is_chat_panel) +======= + @kb.add('down', filter=has_focus(sidebar_window)) +>>>>>>> parent of cfd13cf (Update client.py):client.py def _(event): - all_chats = list(client.contacts.keys()) + list(client.groups.keys()) - if all_chats: - client.selected_contact_idx = (client.selected_contact_idx + 1) % len(all_chats) - target = all_chats[client.selected_contact_idx] - client.active_chat = target - if target in client.contacts: - client.contacts[target]["unread"] = 0 - client.contacts[target]["attention"] = False + if client.contacts: + client.selected_contact_idx = (client.selected_contact_idx + 1) % len(client.contacts) + target_uin = list(client.contacts.keys())[client.selected_contact_idx] + client.active_chat = target_uin + client.contacts[target_uin]["unread"] = 0 + client.contacts[target_uin]["attention"] = False client.refresh_ui() +<<<<<<< HEAD:TUI.py @kb.add('y', filter=has_welcome_popup) @kb.add('Y', filter=has_welcome_popup) def _(event): @@ -854,6 +983,8 @@ def make_layout(): client.send_sys_packet(req_uin, "RES_DEC") client.refresh_ui() +======= +>>>>>>> parent of cfd13cf (Update client.py):client.py @kb.add('c-c') def _(event): client.loop_running = False @@ -873,13 +1004,6 @@ ui_style = Style.from_dict({ 'system': '#ff0000 bold', 'border': '#00ff00', 'frame.border': '#00ff00', - 'popup-title': '#ffffff bold', - 'popup-keys': '#00ff00 bold', - 'popup-border': '#ff0000 bold', - 'query-title': '#00ffff bold', - 'alert-title': '#ff0000 bold', - 'completion-menu.completion': 'bg:#00ffff #000000', - 'completion-menu.completion.current': 'bg:#00aa00 #ffffff bold' }) def main(): @@ -888,38 +1012,54 @@ def main(): try: kernel32 = ctypes.windll.kernel32 kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7) +<<<<<<< HEAD:TUI.py except: pass is_new_registration = False socket_manager.init_network(client) +======= + except: + pass +>>>>>>> parent of cfd13cf (Update client.py):client.py if not client.load_config(): print("!" * 60) - print("WARNING: All data is local.") + print("WARNING:") + print("You will receive new messages only when you are online.") + print("All history is stored locally in settings.json.") + print("Anyone who knows your UIN can message you.") + print("This software uses loud sounds, adjust your client volume beforehand!") print("!" * 60 + "\n") - client.server_url = input("Enter server URL: ").strip() + client.server_url = input("Enter server URL (e.g., http://localhost:5000): ").strip() if not client.server_url.startswith("http://") and not client.server_url.startswith("https://"): client.server_url = "http://" + client.server_url +<<<<<<< HEAD:TUI.py try: socket_manager.sio.connect(client.server_url, transports=['websocket']) except Exception as e: return +======= + try: + sio.connect(client.server_url, transports=['websocket']) + except Exception as e: + print(f"Failed to connect to server: {e}") + return +>>>>>>> parent of cfd13cf (Update client.py):client.py print("\n1. Register\n2. Login") mode = input("> ") - username_or_uin = input("UIN/Username: ").strip() - password = input("Password: ").strip() + username_or_uin = input("Enter Username (for reg) or UIN (for login): ").strip() + password = input("Enter password: ").strip() event_wait = threading.Event() @socket_manager.sio.event def register_response(data): - nonlocal is_new_registration if data["status"] == "success": client.uin = data['uin'] client.username = username_or_uin client.password = password - is_new_registration = True + print(f"\nSuccess! Your UIN: {client.uin}") event_wait.set() @socket_manager.sio.event @@ -928,25 +1068,47 @@ def main(): client.uin = username_or_uin client.username = data["username"] client.password = password + print(f"\nHello, {client.username}! Logged in successfully.") event_wait.set() +<<<<<<< HEAD:TUI.py if mode == "1": socket_manager.sio.emit("register", {"username": username_or_uin, "password": password}) else: socket_manager.sio.emit("login", {"uin": username_or_uin, "password": password}) event_wait.wait() +======= + if mode == "1": + sio.emit("register", {"username": username_or_uin, "password": password}) + event_wait.wait() + else: + sio.emit("login", {"uin": username_or_uin, "password": password}) + event_wait.wait() + + if not client.uin: + print("Auth error.") + return +>>>>>>> parent of cfd13cf (Update client.py):client.py - if not client.uin: return client.save_config() + print("\nYou can change configurations inside settings.json.") input("Press Enter to open TUI...") else: try: +<<<<<<< HEAD:TUI.py socket_manager.sio.connect(client.server_url, transports=['websocket']) socket_manager.sio.emit("login", {"uin": client.uin, "password": client.password}) except: pass if is_new_registration: client.show_welcome_popup = True +======= + sio.connect(client.server_url, transports=['websocket']) + sio.emit("login", {"uin": client.uin, "password": client.password}) + except: + pass +>>>>>>> parent of cfd13cf (Update client.py):client.py threading.Thread(target=status_checker_thread, daemon=True).start() + layout, bindings = make_layout() client.app = Application( @@ -956,6 +1118,7 @@ def main(): full_screen=True, enable_page_navigation_bindings=True ) + client.app.run() if __name__ == "__main__":