def thread_receiver_handle(self, dict_): try: action_ = dict_.get(ACTION) if action_ == MSG: chat_name = dict_[FROM] doc = dict_[MESSAGE] if self.selected_item_text == chat_name: self.append_to_text(chat_name=chat_name, doc=doc) client.client_db.session.rollback() client.client_db.add_to_history(chat_name, time.ctime(), doc, False) elif action_ == IMG or action_ == IMG_PARTS: # print('Получили изображение') # print(dict_) img_msg = JIMMessage(dict_) img_worker = ImageWorker(client.sock, img_msg, client.img_parts) img_worker.handle(action_) if img_worker.whole_received_img and \ self.selected_item_text == img_worker.whole_received_img.get(USER_ID): pixmap = self.image_out_of_byte( PictureImage.base64_decode( img_worker.whole_received_img.get(IMG))) self.label.setPixmap(pixmap) elif action_ == PROBE: mute_.lock() client.m.create_presence_message(self.auth.user) client.m.send_rcv_message(client.sock) mute_.unlock() except Exception as e: print(e)
def handle_request(self): if self.action == AUTH: self._auth_handle() elif self.action == MSG: self._msg_handle() elif self.action == PRESENCE: self._presence_handle() elif self.action == GET_CONTACTS: self._get_contacts_handle() elif self.action == GET_CONTACT_IMG: print('Запрос изображений') self._get_contact_img_handle() elif self.action == ADD_CONTACT: self._add_del_contact_handle() elif self.action == DEL_CONTACT: self._add_del_contact_handle(False) elif self.action == JOIN: self._join_handle() elif self.action == LEAVE: self._leave_handle() elif self.action == REGISTER: self._register_handle() elif self.action == IMG or self.action == IMG_PARTS: img_worker = ImageWorker(self.socket, self.message, self.img_parts) img_worker.handle(self.action) self._whole_message_check(img_worker) else: self.message.response_message_create(code=WRONG_REQUEST, send_message=False) self.transport.write(self.message.encoded_message)
def _get_contact_img_handle(self): contact_name = self.message.dict_message[USER_ID] client = self.server_db.request_client(contact_name) if client: img = self.server_db.get_client_img(contact_name) img_message = JIMMessage() img_sender = ImageWorker(self.socket, img_message, self.img_parts) img_sender.img_send(img.img_base64, contact_name)
def received_message_handle(self): if self.m_r.dict_message[ACTION] == MSG: self.client_db.session.rollback() self.client_db.add_to_history(self.m_r.dict_message[FROM], time.ctime(), self.m_r.dict_message[MESSAGE], False) print(self.m_r.dict_message) # queue.put(self.m_r.dict_message) self.m_r.clean_buffer() elif self.m_r.dict_message[ACTION] == IMG or self.m_r.dict_message[ACTION] == IMG_PARTS: img_receiver = ImageWorker(self.sock, self.m_r, self.img_parts) img_receiver.handle(self.m_r.dict_message[ACTION])
def __init__(self, hostname='localhost', port=7777): self.def_hostname = hostname self.def_port = port # read_ и write_ нужны для проверки, если клиент был запущен из консоли только в одном режиме self._read = False self._write = False self.alive = True self.hostname, self.port = self._cli_param_get() self.username = '' self.client_db = None self.img_parts = {} self.m = JIMMessage() self.m_r = JIMResponse() self.sock = self.open_client_socket() self.img_sender = ImageWorker(self.sock, self.m, self.img_parts)
class Handler(Thread): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) print('Инициализация') self.queue = input_q self.message = None self.action = None self.sock = None self.clients = None self.active = True self.img_worker = None self.img_parts = {} def _get_from_queue(self): item = self.queue.get() self.message = JIMResponse(item['text']) self.action = item['action'] self.sock = item['sock'] self.clients = item['clients'] def handling_action(self): if self.action == PRESENCE: self._presence_handle() elif self.action == MSG: self._msg_handle() elif self.action == GET_CONTACTS: self._get_contacts_handle() elif self.action == GET_CONTACT_IMG: print('Запрос изображений') elif self.action == ADD_CONTACT: self._add_del_contact_handle() elif self.action == DEL_CONTACT: self._add_del_contact_handle(False) elif self.action == JOIN: self._join_handle() elif self.action == LEAVE: self._leave_handle() elif self.action == AUTH: self._auth_handle() elif self.action == REGISTER: self._register_handle() elif self.action == IMG or self.action == IMG_PARTS: self.img_worker = ImageWorker(self.sock, self.message, self.img_parts) self.img_worker.handle(self.action) self._whole_message_check() else: self.message.response_message_create(self.sock, WRONG_REQUEST) # TODO сделать проще... как можно восстановить сокет из fd? def _msg_handle(self): if '#' in self.message.dict_message[TO]: # print('chat') room = self.message.dict_message[TO][1:] contacts = server_db.get_room_members(room) for contact in contacts: if contact != self.message.dict_message[FROM]: sockets = server_db.get_client_sockets(contact) for sock_ in sockets: for sock_online in self.clients: if sock_ == sock_online.fileno(): self.message.send_message(sock_online) else: print(self.message.dict_message) sockets = server_db.get_client_sockets(self.message.dict_message[TO]) for sock_ in sockets: for sock_online in self.clients: if sock_ == sock_online.fileno(): self.message.send_message(sock_online) print('Сообщение отправлено!') self.message.response_message_create(self.sock, OK) def _auth_handle(self): client_name = self.message.dict_message[USER][ACCOUNT_NAME] client = server_db.request_client(client_name) if client is None: self.message.response_message_create(self.sock, NOT_FOUND, message_text="Пользователь не существует") else: client_hash = self.message.dict_message[USER][PASSWORD] if client.hash[0].hashpass == client_hash: print('{} авторизован'.format(client_name)) self.message.response_message_create(self.sock, OK) else: print('{} не авторизован'.format(client_name)) self.message.response_message_create(self.sock, WRONG_COMBINATION, message_text='') def _register_handle(self): client_name = self.message.dict_message[USER][ACCOUNT_NAME] pswd = self.message.dict_message[USER][PASSWORD] # проверяем, если клиент с таким именем уже не зарегистрирован в нашем мессенджере client = server_db.request_client(client_name) if client is None: server_db.add_client(client_name, "Yep, i'm here") hash_ = get_safe_hash(pswd, SALT) print(hash_) server_db.register_new_hash(client_login=client_name, hash_=hash_) self.message.response_message_create(self.sock, OK) else: self.message.response_message_create(self.sock, code=CONFLICT, with_message=True, message_text="Account is in use", send_message=True) def _leave_handle(self): room_name = self.message.dict_message[ROOM] client = server_db.ident_client_by_sockets(self.sock.fileno()) room = server_db.request_room(room_name) if room and client: server_db.join_leave_room(room_name, client) self.message.response_message_create(self.sock, 200, True, 'Вы покинули чат') else: # print('Данной комнаты не существует') self.message.response_message_create(self.sock, 400, True, 'Данной комнаты не существует') def _join_handle(self): room_name = self.message.dict_message[ROOM] client = server_db.ident_client_by_sockets(self.sock.fileno()) room = None while not room: room = server_db.request_room(room_name) if room: server_db.join_leave_room(room_name, client) self.message.response_message_create(self.sock, 200, True, 'Вы успешно присоединились к чату') else: server_db.add_room(room_name) def _presence_handle(self): username = self.message.dict_message[USER][ACCOUNT_NAME] client = server_db.request_client(username) if client is None: self.message.response_message_create(self.sock, NOT_FOUND, message_text='Пользователь не найден') else: server_db.add_to_history(username, self.message.dict_message[TIME], self.sock.getpeername()[0]) server_db.add_online_client(username, self.sock.fileno()) self.message.response_message_create(self.sock, OK) def _get_contacts_handle(self): client = server_db.ident_client_by_sockets(self.sock.fileno()) # print (client) contacts_quantity = server_db.count_contacts(client) contacts = server_db.get_all_contacts(client) self.message.response_message_create(sock=self.sock, code=ACCEPTED, quantity=contacts_quantity) contact_info_message = JIMMessage() for contact in contacts: contact_info_message.create_server_contact_list(contact.login) contact_info_message.send_message(self.sock) # time.sleep(0.3) def _add_del_contact_handle(self, add=True): new_user = self.message.dict_message[USER_ID] if server_db.request_client(new_user) is None: self.message.response_message_create(self.sock, NOT_FOUND, with_message=False) else: client = server_db.ident_client_by_sockets(self.sock.fileno()) if client: # print(client) if new_user not in server_db.get_all_contacts(client): if add: server_db.add_contacts(client, new_user) else: server_db.del_contact(client, new_user) self.message.response_message_create(self.sock, OK, with_message=False) else: self.message.response_message_create(self.sock, WRONG_REQUEST, with_message=False) else: print('Клиента с таким сокетом не существует') self.message.response_message_create(self.sock, WRONG_REQUEST, message_text='Сокет не зарегистрирован') def _whole_message_check(self): if self.img_worker.whole_received_img: if server_db.get_client_img(self.img_worker.whole_received_img[USER_ID]) is None: server_db.write_client_img(self.img_worker.whole_received_img[USER_ID], self.img_worker.whole_received_img[IMG]) else: server_db.update_client_img(self.img_worker.whole_received_img[USER_ID], self.img_worker.whole_received_img[IMG]) def run(self): print("i'm running") while True: if not self.queue.empty(): self._get_from_queue() self.handling_action() if not self.active: break return
class Client(metaclass=ClientVerifier): """ Класс представлен необходимыми методами и свойствами для работы клиента. Метаклассом для этого класса послужил ClientVerifier, выполняющий функцию проверки используемых методов в данном классе. При инициализации экземпляра класса, передаются значения удалённого хоста и порт сервера, с которым будет осуществлять взаимодействия """ def __init__(self, hostname='localhost', port=7777): self.def_hostname = hostname self.def_port = port # read_ и write_ нужны для проверки, если клиент был запущен из консоли только в одном режиме self._read = False self._write = False self.alive = True self.hostname, self.port = self._cli_param_get() self.username = '' self.client_db = None self.img_parts = {} self.m = JIMMessage() self.m_r = JIMResponse() self.sock = self.open_client_socket() self.img_sender = ImageWorker(self.sock, self.m, self.img_parts) def _cli_param_get(self): """ Установить значение порта и адреса исходя из переданных данных, при запуске через командную строку :return: """ try: port = int(find_cli_key_and_argument('-p', self.def_port)) except ValueError: raise WrongPortError addr = find_cli_key_and_argument('-a', self.def_hostname) self._read = '-r' in sys.argv self._write = '-w' in sys.argv return addr, port def open_client_socket(self): """ Создаёт экземпляр класса socket для клиентского приложения """ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: sock.connect((self.hostname, self.port)) except ConnectionRefusedError: raise ConnectionRefusedError("Соединение по {}:{} не возможно".format(self.hostname, self.port)) return sock @staticmethod def user_credentials_req(): usr = input('Имя пользователя: ') pswd = input('Пароль: ') return usr, pswd def authorization(self, usr='', pswd=''): pswd_hash = get_safe_hash(pswd, SALT) self.m.create_auth_reg_message(usr, pswd_hash) self.m.send_rcv_message(self.sock) resp = self.m.dict_message[RESPONSE] # print(resp) if resp == OK: print("{} авторизован, приятного пользования".format(usr)) auth_confirm = True # return "{} авторизован, приятного пользования".format(usr) elif resp == WRONG_COMBINATION: print("Не верный логин или пароль") auth_confirm = False # return "Не верный логин или пароль" else: print("Пользователя не существует") auth_confirm = False if not auth_confirm: print('Попробуйте ещё раз') return auth_confirm def registration(self, usr='', pswd=''): self.m.create_auth_reg_message(usr, pswd, registration=True) self.m.send_rcv_message(self.sock) resp = self.m.dict_message[RESPONSE] if resp == OK: print('Вы зарегистрировались, приятного пользования') reg = True elif resp == CONFLICT: print('Пользователь с такими именем уже существует') reg = False else: print('Регистрация не удалась') reg = False if not reg: print('Попробуйте ещё раз') return reg def start_client(self, usr="", pswd="", status="I'm here"): if not usr: reg = False while not reg: ans = input('Вы зарегистрированны? y/n: ') ans = ans.upper() if ans == 'N': usr, pswd = self.user_credentials_req() reg = self.registration(usr, pswd) elif ans == 'Y': reg = True auth = False while not auth: usr, pswd = self.user_credentials_req() auth = self.authorization(usr, pswd) self.username = usr # получаем доступ к принадлежащй данному клиенту базе данных self.client_db = ClientWorker('sqlite:///system/db/{}_client_db.db?check_same_thread=False'. format(self.username)) self.m.create_presence_message(usr, status) self.m.send_rcv_message(self.sock) self.receive_contact_messages() def receive_contact_messages(self): """ В связи с тем, что контакт_сообщения могут приходить подряд, в этом случае, они будут декодированы и упакованы в список. Поэтому после получения сообщения мы проверяем, если список не пустой, т.о. понимаем, что сообщений было несколько. """ message_lock.acquire() self.m.create_get_contact_message() print(self.m.send_rcv_message(self.sock)) quantity = self.m.dict_message[QUANTITY] rcvd_qtty = 0 while quantity != rcvd_qtty: self.m.rcv_message(self.sock) if self.m.list_of_dicts: n = len(self.m.list_of_dicts) for dict_ in self.m.list_of_dicts: self.add_contact_to_db(dict_) else: self.add_contact_to_db(self.m.dict_message) n = 1 rcvd_qtty += n message_lock.release() def add_contact_to_db(self, dict_message): try: # Contacts(dict_message[USER_ID]).save() self.client_db.add_contact(dict_message[USER_ID]) except sqlalchemy.exc.IntegrityError: print('Клиент уже есть') def get_all_contacts(self): self.client_db.session.rollback() return self.client_db.get_all_contacts() def get_contact_img(self, contact_name='basic_user'): self.m.create_get_contact_img_message(contact_name) self.m.send_message(self.sock) # self.m.rcv_message(self.sock) def change_contact_global(self, username='******', add=True): message_lock.acquire() self.m.create_change_contact_message(username, add=add) self.m.send_rcv_message(self.sock) print(self.m.dict_message) if self.m.dict_message[RESPONSE] == 200: ok = True else: ok = False message_lock.release() return ok def add_contact_local(self, contact='MUSEUN'): self.client_db.add_contact(contact) def del_contact_local(self, contact='MUSEUN'): self.client_db.del_contact(contact) def check_local_contact(self, contact=''): if contact in self.client_db.get_all_contacts(): ok = True else: ok = False return ok def send_msg_message(self, to, from_, text): message_lock.acquire() self.m.create_msg_message(False, to, from_, text) self.client_db.add_to_history(to, time.ctime(), text, True) self.m.send_rcv_message(self.sock) message_lock.release() def load_messages_from_history(self, contact=''): return self.client_db.get_messages_from_history(contact) def cycle_read_messages(self, queue): while self.alive: wait = 0.5 r, w, e = select.select([self.sock], [self.sock], [], wait) for sock_ in r: self.m_r.rcv_message(sock_) if self.m_r.list_of_dicts: for dict_ in self.m_r.list_of_dicts: self.m_r.dict_message = dict_ self.received_message_handle() else: self.received_message_handle() # if self.m_r.dict_message[ACTION] == MSG: # self.client_db.session.rollback() # self.client_db.add_to_history(self.m_r.dict_message[FROM], time.ctime(), # self.m_r.dict_message[MESSAGE], False) # print(self.m_r.dict_message) # # queue.put(self.m_r.dict_message) # self.m_r.clean_buffer() # elif self.m_r.dict_message[ACTION] == IMG or self.m_r.dict_message[ACTION] == IMG_PARTS: # img_receiver = ImageWorker(self.sock, self.m_r, self.img_parts) # img_receiver.handle(self.m_r.dict_message[ACTION]) def received_message_handle(self): if self.m_r.dict_message[ACTION] == MSG: self.client_db.session.rollback() self.client_db.add_to_history(self.m_r.dict_message[FROM], time.ctime(), self.m_r.dict_message[MESSAGE], False) print(self.m_r.dict_message) # queue.put(self.m_r.dict_message) self.m_r.clean_buffer() elif self.m_r.dict_message[ACTION] == IMG or self.m_r.dict_message[ACTION] == IMG_PARTS: img_receiver = ImageWorker(self.sock, self.m_r, self.img_parts) img_receiver.handle(self.m_r.dict_message[ACTION]) def cli_interact(self): while self.alive: action = input('>>') if action == 'send': to_ = input('>>Кому отправить: ') text = input('>>Текст сообщения: ') self.send_msg_message(to=to_, from_=self.username, text=text) pass elif action == 'show': for i in self.get_all_contacts(): print(i) elif action == 'add': new = input('>>Введите имя контакта: ') if not self.check_local_contact(new): if self.change_contact_global(new): self.add_contact_local(new) print('Клиент добавлен') else: print('Не удаётся добавить клиента') elif action == 'del': del_ = input('>>Введите имя контакта: ') if self.check_local_contact(del_): if self.change_contact_global(del_, False): self.del_contact_local(del_) print('Клиент удален') else: print('Не удаётся удалить клиента') elif action == 'img': base64_to_send = input('>>Введите base64 код для отправки: ') # img_sender = ImageWorker(self.sock, self.m, self.img_parts) self.img_sender.img_send(base64_to_send) elif action == 'get_img': contact_name = input('>>Введите имя для получения изображения: ') self.get_contact_img(contact_name) elif action == 'end': self.alive = False break else: print('Не верное действие')