Add clientWin.py
This commit is contained in:
275
clientWin.py
Normal file
275
clientWin.py
Normal file
@@ -0,0 +1,275 @@
|
||||
import socket
|
||||
import os
|
||||
import shutil
|
||||
import hashlib
|
||||
import json
|
||||
import getpass
|
||||
from pathlib import Path
|
||||
import threading
|
||||
import sys
|
||||
|
||||
wit = "\x1b[97m"
|
||||
blauw_bg = "\x1b[44m"
|
||||
groen = "\x1b[92m"
|
||||
rood = "\x1b[91m"
|
||||
reset = "\x1b[0m"
|
||||
|
||||
commands = ["/add", "/quit", "/break", "/users", "/rm"]
|
||||
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])]
|
||||
return matches[state] if state < len(matches) else 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)]
|
||||
return matches[state] if state < len(matches) else None
|
||||
|
||||
return None
|
||||
|
||||
|
||||
import pyreadline3
|
||||
from pyreadline3.rlmain import Readline
|
||||
|
||||
readline = Readline()
|
||||
|
||||
readline.set_completer(completer)
|
||||
readline.parse_and_bind("tab: complete")
|
||||
|
||||
|
||||
# Windows setup
|
||||
readline.set_completer(completer)
|
||||
readline.set_completer_delims(" \t\n")
|
||||
readline.parse_and_bind("tab: complete")
|
||||
|
||||
def clear():
|
||||
os.system("cls")
|
||||
|
||||
def term_size():
|
||||
size = shutil.get_terminal_size()
|
||||
return size.columns, size.lines
|
||||
|
||||
def print_white(text=""):
|
||||
print(wit + text + reset)
|
||||
|
||||
def recv_json(sock):
|
||||
buffer = b""
|
||||
while True:
|
||||
part = sock.recv(4096)
|
||||
if not part:
|
||||
break
|
||||
buffer += part
|
||||
try:
|
||||
return json.loads(buffer.decode("utf-8"))
|
||||
except json.JSONDecodeError:
|
||||
continue
|
||||
return {}
|
||||
|
||||
def login():
|
||||
base_dir = Path(__file__).parent
|
||||
passwd_file = base_dir / "passwd.json"
|
||||
if not passwd_file.exists():
|
||||
return None
|
||||
try:
|
||||
with passwd_file.open("r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
except:
|
||||
data = {}
|
||||
|
||||
user = input(wit + "user: " + reset)
|
||||
password = getpass.getpass(wit + "password: " + reset)
|
||||
password_hash = hashlib.sha256(password.encode("utf-8")).hexdigest()
|
||||
|
||||
if user in data and data[user] == password_hash:
|
||||
return user
|
||||
return None
|
||||
|
||||
def signup():
|
||||
base_dir = Path(__file__).parent
|
||||
passwd_file = base_dir / "passwd.json"
|
||||
|
||||
if passwd_file.exists():
|
||||
try:
|
||||
with passwd_file.open("r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
except:
|
||||
data = {}
|
||||
else:
|
||||
data = {}
|
||||
|
||||
user = input(wit + "Gebruiker: " + reset)
|
||||
if user in data:
|
||||
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)
|
||||
|
||||
current_user = None
|
||||
|
||||
while not current_user:
|
||||
clear()
|
||||
w, _ = term_size()
|
||||
print(blauw_bg + wit + "Terminal Chat ".center(w) + reset)
|
||||
print()
|
||||
print(groen + "========================================")
|
||||
print(" Welcome to the Terminal Chat")
|
||||
print("========================================" + reset)
|
||||
print()
|
||||
print_white("1. Login")
|
||||
print_white("2. Sign up")
|
||||
print()
|
||||
keuze = input(wit + " > " + reset)
|
||||
print()
|
||||
|
||||
if keuze == "1":
|
||||
current_user = login()
|
||||
elif keuze == "2":
|
||||
signup()
|
||||
|
||||
host = "192.168.254.36"
|
||||
port = 44703
|
||||
|
||||
try:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.connect((host, port))
|
||||
s.sendall(current_user.encode("utf-8"))
|
||||
except Exception as e:
|
||||
print("Connection failed:", e)
|
||||
exit()
|
||||
|
||||
chat_data = recv_json(s)
|
||||
chat_names = list(chat_data.keys())
|
||||
|
||||
def draw_chat_window(messages, chatname):
|
||||
with lock:
|
||||
current_input = readline.get_line_buffer()
|
||||
|
||||
clear()
|
||||
w, h = term_size()
|
||||
print(blauw_bg + wit + chatname.center(w) + reset)
|
||||
|
||||
available_lines = h - 3
|
||||
to_display = messages[-available_lines:]
|
||||
|
||||
for msg in to_display:
|
||||
user = msg["user"]
|
||||
text = msg["message"]
|
||||
if user == current_user:
|
||||
print(wit + f" {text} [you]".rjust(w) + reset)
|
||||
else:
|
||||
print_white(f"[{user}] {text}")
|
||||
|
||||
print("-" * w)
|
||||
|
||||
readline.insert_text(current_input)
|
||||
readline.redisplay()
|
||||
|
||||
def chat_session(chatkeuze):
|
||||
global chat_messages, chat_users
|
||||
|
||||
s.sendall(json.dumps({
|
||||
"action": "openchat",
|
||||
"chat_name": chatkeuze
|
||||
}).encode("utf-8"))
|
||||
|
||||
chat_data = recv_json(s)
|
||||
|
||||
if chatkeuze in chat_data:
|
||||
chat_messages = chat_data[chatkeuze].get("messages", [])
|
||||
chat_users = chat_data[chatkeuze].get("users", [])
|
||||
|
||||
def receive_messages(sock):
|
||||
global chat_messages, chat_users
|
||||
while True:
|
||||
try:
|
||||
decoded = recv_json(sock)
|
||||
if not decoded:
|
||||
break
|
||||
|
||||
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)
|
||||
|
||||
except:
|
||||
break
|
||||
|
||||
threading.Thread(target=receive_messages, args=(s,), daemon=True).start()
|
||||
|
||||
while True:
|
||||
draw_chat_window(chat_messages, chatkeuze)
|
||||
bericht = input(wit + "> " + reset)
|
||||
|
||||
if bericht.lower() == "/quit":
|
||||
exit()
|
||||
|
||||
elif bericht.lower() == "/break":
|
||||
break
|
||||
|
||||
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",
|
||||
"chat": chatkeuze,
|
||||
"user": target_user,
|
||||
"by": current_user
|
||||
}).encode("utf-8"))
|
||||
|
||||
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"))
|
||||
|
||||
while True:
|
||||
print_white(" --- Available chats: --- ")
|
||||
|
||||
for i, chat in enumerate(chat_names, start=1):
|
||||
print_white(f"{i}. {chat}")
|
||||
|
||||
print_white(f"{len(chat_names)+1}. New chat")
|
||||
|
||||
keuze = input(wit + " > " + reset)
|
||||
|
||||
if keuze.isdigit() and int(keuze) == len(chat_names)+1:
|
||||
nieuwe_chat = input("Name of new chat: ")
|
||||
s.sendall(json.dumps({
|
||||
"action": "new_chat",
|
||||
"chat_name": nieuwe_chat
|
||||
}).encode("utf-8"))
|
||||
|
||||
chat_data = recv_json(s)
|
||||
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)
|
||||
Reference in New Issue
Block a user