Source code for aiogbclient.utils.client_proto
import asyncio
import hashlib
import binascii
from sys import stdout
from aiogbclient.utils.client_messages import JimClientMessage
from aiogbclient.utils.mixins import ConvertMixin, DbInterfaceMixin
[docs]class ClientAuth(ConvertMixin, DbInterfaceMixin):
"""Authentication server"""
def __init__(self, db_path, username=None, password=None):
super().__init__(db_path)
self.username = username
self.password = password
[docs] def authenticate(self):
"""authentication method, which verify user in DB"""
# check user in DB
if self.username and self.password:
usr = self.get_client_by_username(self.username)
dk = hashlib.pbkdf2_hmac('sha256', self.password.encode('utf-8'),
'salt'.encode('utf-8'), 100000)
hashed_password = binascii.hexlify(dk)
if usr:
# existing user
if hashed_password == usr.password:
# add client's history row
# self.add_client_history(self.username)
return True
else:
return False
else:
# new user
print('new user')
self.add_client(self.username, hashed_password)
# add client's history row
# self.add_client_history(self.username)
return True
else:
return False
[docs]class ChatClientProtocol(asyncio.Protocol, ConvertMixin, DbInterfaceMixin):
def __init__(self, db_path, loop, tasks=None, username=None, password=None, gui_instance=None, **kwargs):
super().__init__(db_path)
self.user = username
self.password = password
self.tasks = tasks
self.jim = JimClientMessage()
self.gui_instance = gui_instance
self.conn_is_open = False
self.loop = loop
self.sockname = None
self.transport = None
self.output = None
[docs] def connection_made(self, transport):
""" Called when connection is initiated """
self.sockname = transport.get_extra_info("sockname")
self.transport = transport
self.send_auth(self.user, self.password)
self.conn_is_open = True
[docs] def send_auth(self, user, password):
"""send authenticate message to the server"""
if user and password:
self.transport.write(self._dict_to_bytes(self.jim.auth(user, password)))
[docs] def connection_lost(self, exc):
""" Disconnect from the server"""
# todo хз как убить задачу
try:
self.conn_is_open = False
for task in self.tasks:
task.cancel()
except:
pass
finally:
self.loop.stop()
self.loop.close()
[docs] def data_received(self, data):
"""
Receive data from server and send output message to console/gui
:param data: json-like dict in bytes
:return:
"""
msg = self._bytes_to_dict(data)
if msg:
try:
if msg['action'] == 'msg':
self.output(msg)
elif msg['action'] == 'list':
self.output(msg['contact_list'])
elif msg['action'] == 'probe':
if self.gui_instance:
self.gui_instance.is_auth = True
# when server sent probe msg -> auth is complete
self.transport.write(self._dict_to_bytes(
self.jim.presence(self.user,
status="Connected from {0}:{1}".format(*self.sockname))))
elif msg['action'] == 'response':
if msg['code'] == 200:
pass
elif msg['code'] == 402:
self.connection_lost(asyncio.CancelledError)
else:
self.output(msg)
except Exception as e:
print(e)
[docs] def send(self, request):
"""
Send json-like message
:param request: dict message
:return:
"""
if request:
msg = self._dict_to_bytes(request)
self.transport.write(msg)
[docs] def send_msg(self, to_user, content):
"""
send msg request to user from contact's list
:param to_user: receiver
:param content: text msg
:return:
"""
if to_user and content:
request = self.jim.message(self.user, to_user, content)
self.transport.write(self._dict_to_bytes(request))
[docs] async def get_from_console(self):
"""
Recieve messages from Console
:param loop:
:return:
"""
while not self.conn_is_open:
pass
self.output = self.output_to_console
self.output("{2} connected to {0}:{1}\n".format(*self.sockname, self.user))
while True:
content = await self.loop.run_in_executor(None, input) # Get stdin/stdout forever
request = ''
args_ = content.split(' ')
if args_[0] == 'list':
if len(args_) > 1:
if args_[1] == 'add':
request = self.jim.list_(self.user, status='add', person=args_[2])
elif args_[1] == 'del':
request = self.jim.list_(self.user, status='del', person=args_[2])
else:
request = self.jim.list_(self.user)
elif args_[0] == 'quit':
self.connection_lost(asyncio.CancelledError)
else:
# if message to another person
if len(args_) < 2:
print('wrong message or receivers name')
else:
request = self.jim.message(sender=self.user,
receiver=args_[0],
text=' '.join(args_[1:]))
if request:
self.send(request)
[docs] def output_to_console(self, data):
"""
print output data to terminal
:param data: msg dictionary
:return:
"""
_data = data
try:
if _data['from'] == self.user:
_data['message'] = 'Me to {}: '.format(_data['to']) + _data['message']
else:
_data['message'] = '{}: '.format(_data['from']) + _data['message']
stdout.write(str(_data['message']) + '\n')
except:
stdout.write(str(_data) + '\n')
[docs] def get_from_gui(self):
self.output = self.output_to_gui
# await loop.run_in_executor(None, self.output) # Run GUI in executor
[docs] def output_to_gui(self, msg, response=False):
"""
send update signal to GUI client
:param response: raw response from server {'response':200}
:type msg: message dictionary
:return:
"""
try:
if self.gui_instance:
if response:
self.gui_instance.is_auth = True
if self.user == msg['to']:
self.gui_instance.chat_ins()
except Exception as e:
print(e)