From 8baaa9edaa4677ad992a1c313aa49a60ae3e8b3b Mon Sep 17 00:00:00 2001 From: Ben de Roo Date: Tue, 17 Feb 2026 10:29:28 +0100 Subject: [PATCH] Update main.py/client.py --- main.py/client.py | 175 ++++++++++++++++++++++++---------------------- 1 file changed, 90 insertions(+), 85 deletions(-) diff --git a/main.py/client.py b/main.py/client.py index 1d410c9..444183b 100644 --- a/main.py/client.py +++ b/main.py/client.py @@ -1,11 +1,3 @@ -# ========================================================== -# terminal chat standaard user = test passwd = test -# edit port at the comment with a arrow -# you have to ask the port of the srver at ben@de-roo.org or -# directly to me. -# have fun! (I guess) -# ========================================================== - import socket import os import shutil @@ -13,18 +5,46 @@ import hashlib import json import getpass from pathlib import Path -import time -import re import threading +import readline -# kleuren wit = "\x1b[97m" blauw_bg = "\x1b[44m" groen = "\x1b[92m" rood = "\x1b[91m" reset = "\x1b[0m" -# terminal helpers +commands = ["/add", "/quit", "/break", "/users"] +chat_users = [] +chat_messages = [] +lock = threading.Lock() + +def completer(text, state): + buffer = readline.get_line_buffer() + parts = buffer.split() + + if not buffer.startswith("/"): + return None + + if len(parts) == 1: + matches = [cmd for cmd in commands if cmd.startswith(parts[0])] + if state < len(matches): + return matches[state] + return None + + if parts[0] == "/add" and len(parts) >= 2: + current_input = parts[-1] + matches = [user for user in chat_users if user.startswith(current_input)] + if state < len(matches): + return matches[state] + return None + + return None + +readline.set_completer_delims(" \t\n") +readline.set_completer(completer) +readline.parse_and_bind("tab: complete") + def clear(): os.system("cls" if os.name == "nt" else "clear") @@ -35,13 +55,10 @@ def term_size(): def print_white(text=""): print(wit + text + reset) -# login def login(): base_dir = Path(__file__).parent passwd_file = base_dir / "passwd.json" if not passwd_file.exists(): - print_white("Geen gebruikers.") - input(wit + "druk op een knop..." + reset) return None try: with passwd_file.open("r", encoding="utf-8") as f: @@ -52,13 +69,9 @@ def login(): password = getpass.getpass(wit + "Wachtwoord: " + reset) password_hash = hashlib.sha256(password.encode("utf-8")).hexdigest() if user in data and data[user] == password_hash: - print(groen + "Login succesvol!" + reset) return user - print(rood + "Ongeldige gebruikersnaam of wachtwoord." + reset) - input(wit + "druk op een knop..." + reset) return None -# signup def signup(): base_dir = Path(__file__).parent passwd_file = base_dir / "passwd.json" @@ -70,30 +83,20 @@ def signup(): data = {} else: data = {} - print_white("Nieuwe gebruiker") user = input(wit + "Gebruiker: " + reset) if user in data: - print(rood + "Bestaat al." + reset) - input(wit + "druk op een knop..." + reset) return password = getpass.getpass(wit + "Wachtwoord: " + reset) data[user] = hashlib.sha256(password.encode("utf-8")).hexdigest() with passwd_file.open("w", encoding="utf-8") as f: json.dump(data, f, indent=4) - print(groen + "Succes!" + reset) - input(wit + "druk op een knop..." + reset) -# strip kleuren -def strip_ansi(s): - return re.sub(r'\x1b\[.*?m', '', s) - -# login/signup loop current_user = None + while not current_user: clear() w, _ = term_size() - print(blauw_bg + wit + " Terminal Chat ".center(w) + reset) - print_white("Welkom bij Python Terminal Chat!") + print(blauw_bg + wit + "Terminal Chat ".center(w) + reset) print_white("1. inloggen") print_white("2. nieuw account") keuze = input(wit + " > " + reset) @@ -102,41 +105,24 @@ while not current_user: elif keuze == "2": signup() -# connect -host = "192.168.254.138" -port = 44703 # <---- edit port -s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +host = "192.168.254.36" +port = 44703 try: + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((host, port)) -except: - print(rood + "Connectie mislukt" + reset) - exit() - -# stuur username -try: s.sendall(current_user.encode("utf-8")) -except: - print(rood + "Verbinding verloren" + reset) +except Exception as e: + print("Connection failed:", e) exit() -# ontvang chatlijst -try: - while True: - data = s.recv(4096) - if data: - chat_names = json.loads(data.decode("utf-8")) - break -except: - print(rood + "Verbinding verloren" + reset) - exit() +data = s.recv(4096) +chat_data = json.loads(data.decode("utf-8")) +chat_names = list(chat_data.keys()) -chat_messages = [] - -# teken chatwindow def draw_chat_window(messages, chatname): clear() w, h = term_size() - print(blauw_bg + wit + chatname.center(w) + reset) # chat header + print(blauw_bg + wit + chatname.center(w) + reset) available_lines = h - 3 to_display = messages[-available_lines:] for msg in to_display: @@ -148,49 +134,65 @@ def draw_chat_window(messages, chatname): print_white(f"[{user}] {text}") print("-" * w) -# chat session def chat_session(chatkeuze): global chat_messages + global chat_users - # open chat s.sendall(json.dumps({"action": "openchat", "chat_name": chatkeuze}).encode("utf-8")) data = s.recv(4096) - try: - chat_data = json.loads(data.decode("utf-8")) - if chat_data: - chat_messages = list(chat_data[chatkeuze]["messages"]) - except: - chat_messages = [] + chat_data = json.loads(data.decode("utf-8")) + + if chatkeuze in chat_data: + chat_messages = chat_data[chatkeuze].get("messages", []) + chat_users = chat_data[chatkeuze].get("users", []) - # ontvang berichten def receive_messages(sock): global chat_messages + global chat_users + while True: try: data = sock.recv(4096) if not data: + break + + decoded = json.loads(data.decode("utf-8")) + + # /users response + if isinstance(decoded, dict) and decoded.get("type") == "users_list": + users = decoded.get("users", []) + print("\nUsers:", ", ".join(users)) + print(wit + "Typ je bericht: " + reset, end="", flush=True) continue - try: - messages = json.loads(data.decode("utf-8")) - chat_messages.extend(messages) + + # normale chat update + if isinstance(decoded, dict) and chatkeuze in decoded: + with lock: + chat_messages = decoded[chatkeuze].get("messages", []) + chat_users = decoded[chatkeuze].get("users", []) + draw_chat_window(chat_messages, chatkeuze) - print(wit + "Typ je bericht (/break om terug te gaan): " + reset, end="", flush=True) - except: - continue - except: + print(wit + "Typ je bericht: " + reset, end="", flush=True) + + except Exception: break threading.Thread(target=receive_messages, args=(s,), daemon=True).start() while True: draw_chat_window(chat_messages, chatkeuze) - bericht = input(wit + "Typ je bericht (/break om terug te gaan): " + reset) + bericht = input(wit + "Typ je bericht: " + reset) - if bericht.lower() == "/quit": # sluit + if bericht.lower() == "/quit": exit() - elif bericht.lower() == "/break": # terug + elif bericht.lower() == "/break": break - elif bericht.lower().startswith("/add "): # add user + elif bericht.lower() == "/users": + s.sendall(json.dumps({ + "action": "get_users", + "chat": chatkeuze + }).encode("utf-8")) + elif bericht.lower().startswith("/add "): target_user = bericht.split(" ", 1)[1] s.sendall(json.dumps({ "action": "add_user", @@ -198,15 +200,19 @@ def chat_session(chatkeuze): "user": target_user, "by": current_user }).encode("utf-8")) - else: # verstuur + else: + with lock: + chat_messages.append({ + "user": current_user, + "message": bericht + }) + draw_chat_window(chat_messages, chatkeuze) s.sendall(json.dumps({ "action": "message", "chat_name": chatkeuze, "message": bericht }).encode("utf-8")) - # chat_messages.append({"user": current_user, "message": bericht}) -# main loop while True: print_white("Beschikbare chats:") for i, chat in enumerate(chat_names, start=1): @@ -214,13 +220,12 @@ while True: print_white(f"{len(chat_names)+1}. Nieuwe chat aanmaken") keuze = input(wit + " > " + reset) - if keuze.isdigit() and int(keuze) == len(chat_names)+1: # #chataanmaken + if keuze.isdigit() and int(keuze) == len(chat_names)+1: nieuwe_chat = input("Naam van nieuwe chat: ") s.sendall(json.dumps({"action": "new_chat", "chat_name": nieuwe_chat}).encode("utf-8")) data = s.recv(4096) - if data: - chat_names = json.loads(data.decode("utf-8")) - - elif keuze.isdigit() and 1 <= int(keuze) <= len(chat_names): # #chat openen + chat_data = json.loads(data.decode("utf-8")) + chat_names = list(chat_data.keys()) + elif keuze.isdigit() and 1 <= int(keuze) <= len(chat_names): chatkeuze = chat_names[int(keuze)-1] chat_session(chatkeuze)