diff --git a/clientBeta.py b/clientBeta.py new file mode 100644 index 0000000..0a9c7f1 --- /dev/null +++ b/clientBeta.py @@ -0,0 +1,143 @@ +import curses, socket, threading, json, hashlib, getpass, os +from pathlib import Path + +chat_messages, chat_users, chat_list = [], [], [] +user_status = {} +lock = threading.Lock() +current_user, current_chat = None, None +selected_chat, sock, scroll_offset = 0, None, 0 + +def send(obj): + sock.sendall((json.dumps(obj) + "\n").encode()) + +def clear(): + os.system("cls" if os.name=="nt" else "clear") + +def login(): + passwd_file = Path("passwd.json") + if not passwd_file.exists(): return None + try: data = json.loads(passwd_file.read_text()) + except: data = {} + user = input("Gebruikersnaam: ") + pw = getpass.getpass("Wachtwoord: ") + if user in data and data[user] == hashlib.sha256(pw.encode()).hexdigest(): + return user + return None + +def signup(): + passwd_file = Path("passwd.json") + if passwd_file.exists(): + try: data = json.loads(passwd_file.read_text()) + except: data = {} + else: data = {} + user = input("Gebruiker: ") + if user in data: return + pw = getpass.getpass("Wachtwoord: ") + data[user] = hashlib.sha256(pw.encode()).hexdigest() + passwd_file.write_text(json.dumps(data, indent=4)) + +while not current_user: + clear() + print("1. Inloggen\n2. Nieuw account\n") + k = input(" > ") + if k=="1": + current_user = login() + if not current_user: input("Login mislukt...") + elif k=="2": signup() + +def receiver(): + global chat_messages, chat_users, chat_list, current_chat + buffer = "" + while True: + try: + buffer += sock.recv(4096).decode() + while "\n" in buffer: + line, buffer = buffer.split("\n",1) + d = json.loads(line) + t = d.get("type") + with lock: + if t=="chat_list": + chat_list[:] = d["chats"] + if not current_chat and chat_list: + current_chat = chat_list[0] + send({"action":"open_chat","chat_name":current_chat}) + elif t=="chat_data" and d.get("chat")==current_chat: + chat_messages[:] = d["messages"][-100:] + chat_users[:] = d["users"] + elif t=="new_message" and d.get("chat")==current_chat: + chat_messages.append(d["message"]) + elif t=="new_chat": + chat_list.append(d["chat"]) + elif t=="users_list" and d.get("chat")==current_chat: + chat_users[:] = d["users"] + elif t in ("user_online","user_offline"): + user_status[d["user"]] = t=="user_online" + except: break + +def draw(chat_win, users_win, input_win, input_buf): + chat_win.erase(); users_win.erase(); input_win.erase() + chat_win.box(); users_win.box(); input_win.box() + chat_win.addstr(0,2,f" Chat: {current_chat} ") + users_win.addstr(0,2," Users ") + input_win.addstr(0,2," Input ") + with lock: + h,w=chat_win.getmaxyx() + for i,m in enumerate(chat_messages[-100:]): + if i>=h-2: break + chat_win.addstr(i+1,1,f"[{m['user']}] {m['message']}"[:w-2]) + uh,uw=users_win.getmaxyx() + for i,u in enumerate(chat_users[:uh-3]): + status = "✔" if user_status.get(u,False) else "✗" + users_win.addstr(i+1,1,f"{status} {u}"[:uw-2]) + offset = min(len(chat_users),uh-3) + users_win.addstr(offset,1,"Chats:") + for i,c in enumerate(chat_list): + marker = ">" if i==selected_chat else " " + users_win.addstr(offset+1+i,1,f"{marker} {c}"[:uw-2]) + input_win.addstr(1,1,input_buf[:w-2]) + chat_win.refresh(); users_win.refresh(); input_win.refresh() + +def popup_input(stdscr,title,prompt): + h,w=stdscr.getmaxyx(); pw,ph=50,7 + win=curses.newwin(ph,pw,h//2-ph//2,w//2-pw//2) + win.box(); win.addstr(1,2,title); win.addstr(3,2,prompt) + curses.echo(); win.refresh() + inp=win.getstr(3,len(prompt)+3,30).decode().strip() + curses.noecho(); return inp + +def ui(stdscr): + global current_chat, selected_chat, scroll_offset + curses.curs_set(1); stdscr.nodelay(True); stdscr.timeout(50) + h,w=stdscr.getmaxyx(); right_w,input_h=30,3 + chat_win=curses.newwin(h-input_h,w-right_w,0,0) + users_win=curses.newwin(h-input_h,right_w,0,w-right_w) + input_win=curses.newwin(input_h,w,h-input_h,0) + input_buf="" + threading.Thread(target=receiver,daemon=True).start() + while True: + draw(chat_win,users_win,input_win,input_buf) + ch=stdscr.getch() + if ch==9 and chat_list: + selected_chat=(selected_chat+1)%len(chat_list) + current_chat=chat_list[selected_chat] + with lock: chat_messages.clear(); chat_users.clear() + send({"action":"open_chat","chat_name":current_chat}) + elif ch==10: + msg=input_buf.strip(); input_buf="" + if not msg or not current_chat: continue + send({"action":"message","chat_name":current_chat,"message":msg}) + elif ch in (127,curses.KEY_BACKSPACE): input_buf=input_buf[:-1] + elif 32<=ch<=126: input_buf+=chr(ch) + elif ch==curses.KEY_F2: + nc=popup_input(stdscr,"Nieuwe chat","Naam:") + if nc: send({"action":"new_chat","chat_name":nc}) + elif ch==curses.KEY_F3: + u=popup_input(stdscr,"User toevoegen","Username:") + if u and current_chat: send({"action":"add_user","chat":current_chat,"user":u}) + elif ch==curses.KEY_F4: + u=popup_input(stdscr,"User verwijderen","Username:") + if u and current_chat: send({"action":"rm_user","chat":current_chat,"user":u}) + +sock=socket.socket(); sock.connect(("127.0.0.1",44705)) +sock.sendall((current_user+"\n").encode()) +curses.wrapper(ui)