Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 70 additions & 116 deletions CLIclient_main.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import asyncio
import websockets
import os
from cryptography.hazmat.primitives import serialization as s
from client_modules import encryption as en
from client_modules import packet_handler as p
from client_modules import db_handler as db
from client_modules import cli_menus as cli
from client_modules import first_run
from uuid import uuid4
import i18n
Expand All @@ -13,60 +12,74 @@
import pickle
from sys import exit


async def send_message(websocket, message):
outpacket = en.encrypt_data(
message, SERVER_CREDS['server_epbkey']
)
await websocket.send(outpacket)
response = await websocket.recv()
return await recv_message(websocket, response)

async def handle_resp(websocket, response):
inpacket = en.decrypt_data(response, CLIENT_CREDS['client_eprkey'])
print(inpacket)
handled = await p.handle(SERVER_CREDS, CLIENT_CREDS, websocket, inpacket) # handle here using type and data
print('resposne handaled')
return handled
if message:
await websocket.send(message)


async def recv_message(websocket, message):
inpacket = en.decrypt_data(message, CLIENT_CREDS['client_eprkey'])
# handle check
await p.handle(SERVER_CREDS, CLIENT_CREDS, websocket, inpacket)
outpacket = await p.handle(SERVER_CREDS, CLIENT_CREDS, websocket, inpacket)
if not outpacket:
await websocket.send(outpacket)
else:
pass


def execute_firstrun():
first_run.main()
print(i18n.firstrun.security)
db.decrypt_creds(en.fermat_gen(first_run.working_dir.workingdir), first_run.working_dir.workingdir)
print(i18n.firstrun.initialize_db)
db.initialize_schemas()
db.close()
print(i18n.firstrun.exit)
exit()


def check_missing_config(f, yaml, config):
try:
if yaml[config] is None:
print(i18n.firstrun.prompt1 + config)
if config == 'working_directory':
print(i18n.firstrun.prompt2)
while True:
choice = input("(Y / N) > ")
if choice.lower() == 'y':
print(i18n.firstrun.exec)
f.close()
os.remove(f'{rootdir}/config.yml')
first_run.main()
print(i18n.firstrun.exit)
exit()
elif choice.lower() == 'n':
fill_missing_config(f, yaml, 'working_directory')
break
else:
fill_missing_config(f, yaml, config)
except KeyError:
print(i18n.firstrun.prompt1 + config)
fill_missing_config(f, yaml, config)
# def check_missing_config(f, yaml, config):
# try:
# if yaml[config] is None:
# print(i18n.firstrun.prompt1 + config)
# if config == 'working_directory':
# print(i18n.firstrun.prompt2)
# while True:
# choice = input("(Y / N) > ")
# if choice.lower() == 'y':
# print(i18n.firstrun.exec)
# f.close()
# os.remove(f'{rootdir}/config.yml')
# first_run.main()
# print(i18n.firstrun.exit)
# exit()
# elif choice.lower() == 'n':
# fill_missing_config(f, yaml, 'working_directory')
# break
# else:
# fill_missing_config(f, yaml, config)
# except KeyError:
# print(i18n.firstrun.prompt1 + config)
# fill_missing_config(f, yaml, config)

def check_missing_config(file, yaml_config, config_key):
if yaml_config.get(config_key) is not None:
return
print(i18n.firstrun.setting_not_found.format(config_key))

if config_key != 'working_directory':
fill_missing_config(file, yaml_config, config_key)
return
print(i18n.firstrun.ft_question)

while True:
choice = input("(Y / N) > ").lower()
if choice == 'y':
print(i18n.firstrun.exec)
file.close()
os.remove(f'{rootdir}/config.yml')
first_run.main()
print(i18n.firstrun.exit)
exit()
elif choice == 'n':
fill_missing_config(file, yaml_config, 'working_directory')
break


def fill_missing_config(f, yaml, config):
Expand All @@ -77,32 +90,30 @@ def fill_missing_config(f, yaml, config):
f.seek(0)
f.write(dumpyaml(yaml))


async def main(host, port):
uri = f"ws://{host}:{port}"
async with websockets.connect(uri, ping_interval=30) as websocket:
async with websockets.connect(uri, ping_interval=120) as websocket:
con_id = str(uuid4())
await websocket.send(pickle.dumps({'type':'CONN_INIT', 'data':con_id}))
await websocket.send(pickle.dumps({'type': 'CONN_INIT', 'data': con_id}))
try:
key = await websocket.recv()
key = pickle.loads(key)
pubkey = s.load_pem_public_key(key['data'])
pubkey = en.deser_pem(key['data'], 'public')
SERVER_CREDS['server_epbkey'] = pubkey
print("RECEIVED SERVER PUBLIC KEY")
await websocket.send(pickle.dumps({'type':'CONN_ENCRYPT_C','data':CLIENT_CREDS['client_epbkey']}))
await websocket.send(pickle.dumps({'type': 'CONN_ENCRYPT_C', 'data': CLIENT_CREDS['client_epbkey']}))
print(en.decrypt_data(await websocket.recv(), CLIENT_CREDS['client_eprkey']))

except websockets.exceptions.ConnectionClosedError as err:
print("Disconected from Server! Error:\n",err)
except websockets.exceptions.ConnectionClosedError as error:
print("Disconnected from Server! Error:\n", error)
exit()

while True:
try:
await asyncio.gather(
send_message(websocket),
recv_message(websocket, await websocket.recv()),
)
except Exception as eroa:
print("Disconected from Server! Error:\n",eroa)
await send_message(websocket, await cli.main_menu(SERVER_CREDS, CLIENT_CREDS, websocket, workingdir))
except Exception as e:
print("Disconnected from Server! Error:\n", e)
exit()


Expand Down Expand Up @@ -132,64 +143,7 @@ async def main(host, port):
execute_firstrun()

workingdir = yaml['working_directory']
CLIENT_CREDS['workingdir'] = workingdir
host, port = yaml['homeserver_address'], yaml['homeserver_port']

try:
fkey = en.fermat_gen(workingdir)
db.decrypt_creds(fkey, workingdir)
except Exception as w:
print("Error while decrypting database credentials. Check your password\n", w)
print(i18n.firstrun.exit)
exit()

try:
with open(f'{workingdir}/creds/chat_publickey', 'rb') as f:
pem_pubkey = f.read()
pubkey = en.deser_pem(pem_pubkey, 'public')
except FileNotFoundError:
print("Could not find chat encryption public key. Client will now generate it from the private key.")
try:
with open(f'{workingdir}/creds/chat_privatekey', 'rb') as f:
en_pem_prkey = f.read()
pem_prkey = fkey.decrypt(en_pem_prkey)
prkey = en.deser_pem(pem_prkey, 'private')
pubkey = prkey.public_key()

with open(f'{workingdir}/creds/chat_publickey', 'wb') as f:
f.write(pem_pubkey)
except FileNotFoundError:
print("Could not find chat encryption keypair. Client will now generate it again.")
ch = input("THIS OPERATION IS NOT SUPPORTED YET. Continue? (y/n) > ")
if ch.lower() == 'y':
db.clear_queue(user=None)
first_run.save_chat_keypair(fkey, workingdir)
print(i18n.firstrun.exit)
exit()
if ch.lower() == 'n':
print("Key ah kaanume enna panradhu ippo?")
exit()
else:
with open(f'{workingdir}/creds/chat_privatekey', 'rb') as f:
en_pem_prkey = f.read()
pem_prkey = fkey.decrypt(en_pem_prkey)
prkey = en.deser_pem(pem_prkey, 'private')

asyncio.get_event_loop().run_until_complete(main(host,port))
asyncio.get_event_loop().run_forever()

"""
import asyncio
import websockets

# Main function to connect to the server and start the message handlers
async def main():
async with websockets.connect(uri) as websocket:
# Start the message handlers
await asyncio.gather(
handle_incoming_messages(websocket),
handle_outgoing_messages(websocket),
)

# Run the main function
asyncio.run(main())
"""
asyncio.run(main(host, port))
5 changes: 1 addition & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
# client-framework

This repo provides all the necessary functions to interact with the [pesupy-chat server software](https://github.com/pesupy-chat/server).
It also includes an example CLI client which can also be used regularly. (CURRENTLY NOT FINISHED)
# README PENDING
Binary file removed captcha.png
Binary file not shown.
68 changes: 38 additions & 30 deletions client_modules/cli_menus.py
Original file line number Diff line number Diff line change
@@ -1,44 +1,52 @@
import os, sys
from . import packet_handler as p
import asyncio
from i18n import demo
from i18n import menu

def cls():
# function return value is assigned to _ to prevent it from printing to the console
# for windows
if os.name == 'nt':
_ = os.system('cls')
# for mac and linux(here, os.name is 'posix')
else:
_ = os.system('clear')

def main_menu():

async def main_menu(SERVER_CREDS, CLIENT_CREDS, websocket, wdir):
print(menu.the_menu)
while True:
cls()
print(
""" ...... . ..
-======+++**##%+ %*---%::% @-
+@#+++*@@+=--:-%%. %. .% *= .+%
*@- :@# .%%. :@+++*- -+==#=
#@: -@#..:::-%%. =* .%. %.
.%%. :%%%%#####= :*- =- :%%###%%%%%+ *: +%+++*=
.@% *@- :@# ..-@@=:-@%:..
-@* .=++++***:. %@: :@# .#@%%@@%%%@@###***=
=@+ .%@+===-=%%- %%. -@* :@# -@* -@#:*@*--.
+@= .%%. *@+ @# :@# :@# =@+ -@* =@+
#@: .:%%======#@* @#-----==*@* -@%+#@#+=#@= +@=
.#@%%%%%%##*+++++=:. =******+++=. :===+==++- +@= CHAT""")
print("Welcome!")
print("Choose an operation:")
print("1. Sign up")
print("2. Log in")
print("3. Exit")
c = int(input("> "))
print(menu.input_p)
c = input("> ").lower()
match c:
case 1:
signup()
case 2:
login()
case 3:
print("Goodbye!")
case 'signup':
cls()
return await p.signup(SERVER_CREDS, CLIENT_CREDS, websocket, wdir)
case 'login':
cls()
return await p.login(SERVER_CREDS, CLIENT_CREDS, websocket, wdir)
case 'auth':
cls()
return await p.auth(SERVER_CREDS, CLIENT_CREDS, websocket, wdir)
case 'logout':
cls()
if input(demo.logout_p + '\n(y/N) > ').lower() == 'y':
flag = await p.logout(SERVER_CREDS, CLIENT_CREDS, websocket, wdir)
return flag
else:
print(demo.logout_cancel)
case 'del':
cls()
print()
c = input("(y/N) > ")
if c.lower() == 'y':
flag = await p.delete(SERVER_CREDS, CLIENT_CREDS, websocket, wdir)
return flag
else:
print()
case 'exit':
print(menu.exit_msg)
sys.exit()

def signup():
p.signup()
case other:
print(menu.invalid_op)
Empty file removed client_modules/conn_handler.py
Empty file.
Loading