def __init__(self, listenCallback): self.listenCallback = listenCallback self.s = socket() self.s.connect((HOST, PORT)) self.secure = Secure() self.serverKey = None Thread(target=self.listen, daemon=True).start()
def __init__(self, clarifai_token, telegram_token): self.recognizer = Recognizer(clarifai_token) self.bot = Bot(telegram_token) self.secure = Secure() self.users_status = dict() self.users_login = dict() self.users_message = dict()
def __init__(self, dialog, window): super(MainApplication, self).__init__() self.setupUi(dialog) self.dialog = dialog self.window = window self.Config = ServerConfig() self.Sec = Secure() self.get_key() self.dialog.show()
def __init__(self): self.s = _socket() self.s.bind((HOST, PORT)) self.s.listen(5) self.clients = [] self.clientKeys = {} self.clientCiphers = {} self.lastPing = time() self.haveNotPong = set() self.secure = Secure() self.matches = [] Thread(target=self.accept, daemon=True).start() Thread(target=self.listen, daemon=True).start()
class Client(): def __init__(self, listenCallback): self.listenCallback = listenCallback self.s = socket() self.s.connect((HOST, PORT)) self.secure = Secure() self.serverKey = None Thread(target=self.listen, daemon=True).start() def listen(self): while True: data = self.s.recv(4096) if data.startswith(b">>>"): print("Received server key") self.serverKey = self.secure.fromDer(data[3:]) self.serverCipher = PKCS1_OAEP.new(self.serverKey) self.s.send(b">>>" + self.secure.publicKey.exportKey("DER")) print("Sent own key") else: deciphered = self.secure.privateCipher.decrypt(data) if not deciphered.startswith(b">>"): print("Invalid packet from server") return deciphered = deciphered[2:] if deciphered == b"PING": self.send(b"PONG") print("PING -> PONG") else: self.listenCallback(deciphered) print(deciphered) def send(self, data): ciphered = self.serverCipher.encrypt(b">>" + data) self.s.send(ciphered)
def main_handler(event, context): """云函数入口""" logging.getLogger().setLevel(logging.INFO) logging.info('script start up') logging.info('start read csv') with open('./user_data.csv') as f: logging.info('read csv finished') user_data_csv = csv.DictReader(f) logging.info('read csv finished, start execute all user') for csv_dict in user_data_csv: try: with ModSession() as session: session.headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2)'} # 设置UA避免被防火墙拦截 logging.info(f'start trying login user:{csv_dict["login_id"]}') login_state = Secure(csv_dict['login_id'], csv_dict['login_pwd'], session).login().test() if login_state: logging.info('login finished') else: logging.error(f'login user:{csv_dict["login_id"]} failed') continue card = Card(session) logging.info('card init finished') card.submit(csv_dict) logging.info('card init finished') today_submit_time = card.get_today_submit_time() Notify().send('[OK]健康卡自动填报已执行', f'健康卡自动填报成功,从服务端查询到的最后填报时间为{today_submit_time}') logging.info(f'[OK]健康卡:{csv_dict["login_id"]}自动填报成功,从服务端查询到的最后填报时间为{today_submit_time}') except Exception as e: print(e) Notify().send('[ERROR]健康卡自动填表发生错误', '健康卡自动填表发生错误,请到云函数平台检查执行日志,联系开发者并提供必要的错误日志') logging.error(f'[ERROR]健康卡:{csv_dict["login_id"]}自动填报失败')
from log import * import json, base64, sys, random, logging from Crypto.Hash import SHA512, HMAC from Crypto.Random import random from Crypto.PublicKey import RSA from secure import Secure from Crypto.Protocol.KDF import PBKDF1 secure = Secure() # secure module # Connection status NOT_CONNECTED = 10000 CONNECTING = 20000 CONNECTED = 30000 TERMINATOR = "\r\n" MAX_BUFSIZE = 64 * 1024 # Colours class colors: TITLE = '\033[95m' INFO = '\033[94m' VALID = '\033[92m' WARNING = '\033[93m' ERROR = '\033[91m' END = '\033[0m' BOLD = '\033[1m' class Client: count = 0
class Controller: owner_id = 433518097 about_app = 'Hello! Secure Face bot can grant you access to you private data from any phone via only your photo!' \ '\nSign up once if you dont have account' \ '\nSign in if you already have account' sign_up_login_status = '*sign_up_login*' sign_up_photo_status = '*sign_up_photo*' sign_up_more_photo_status = '*sign_up_more_photo*' sign_in_status = '*sign_in*' signed_in_status = '*singed_in*' add_photo_status = '*add_photo*' secure_level_bad = 0.7 secure_level_normal = 0.6 secure_level_good = 0.5 # less than 0.5 is 'secure_level_well' command_stop = '*stop*' def __init__(self, clarifai_token, telegram_token): self.recognizer = Recognizer(clarifai_token) self.bot = Bot(telegram_token) self.secure = Secure() self.users_status = dict() self.users_login = dict() self.users_message = dict() def start(self): self.bot.delete_webhook() self.bot.get_updates() while True: updates = self.bot.get_updates() for data in updates: logging.debug(data) mid = self.get(data, ['message', 'message_id']) user = self.get(data, ['message', 'from', 'id']) chat = self.get(data, ['message', 'chat', 'id']) text = self.get(data, ['message', 'text']) photos = self.get(data, ['message', 'photo']) if user is None: # button pressed (callback query) user = self.get(data, ['callback_query', 'from', 'id']) chat = self.get(data, ['callback_query', 'from', 'id']) text = self.get(data, ['callback_query', 'data']) reply_id = self.get(data, ['callback_query', 'message', 'message_id']) self.bot.delete_message(user, reply_id) if (self.users_message.get(user) is not None) and (self.users_message[user]['id'] == reply_id): self.users_message[user] = None if (user is None) or (chat is None): logging.error('No from_id or no chat_id (from_id: ' + str(user) + ', chat_id: ' + str(chat) + ')') elif user != chat: self.send(chat, 'I work only in private chats') logging.warning('Message send from group chat(from_id: ' + str(user) + ', chat_id: ' + str(chat) + ')') else: if mid is not None: self.bot.delete_message(user, mid) self.message(user, text, photos) def message(self, user, text, photos): self.commands(user, text) status = self.users_status.get(user) if status is None: self.startup(user, text) elif status == self.sign_up_login_status: self.sign_up_login(user, text) elif status == self.sign_up_photo_status: self.sign_up_photo(user, text, photos) elif status == self.sign_up_more_photo_status: self.sign_up_more_photo(user, text, photos) elif status == self.sign_in_status: self.sign_in(user, text, photos) elif status == self.signed_in_status: self.profile(user, text) elif status == self.add_photo_status: self.add_photo(user, text, photos) def startup(self, user, text): if text is not None: text = text.lower() if text == 'sign up': keyboard = self.make_keyboard(['Cancel']) self.send(user, 'Enter your login', keyboard) self.users_status[user] = self.sign_up_login_status elif (text == 'sign in') or (text == 'log in') or (text == 'login'): keyboard = self.make_keyboard(['Cancel']) self.send(user, 'Send your face', keyboard) self.users_status[user] = self.sign_in_status else: keyboard = self.make_keyboard(['Sign in', 'Sign up']) self.send(user, self.about_app, keyboard) def sign_up_login(self, user, text): keyboard = self.make_keyboard(['Cancel']) if (text == 'Cancel') or (text == 'cancel') or (text == self.command_stop): self.users_status[user] = None self.users_login[user] = None self.startup(user, '') elif text is None: self.send(user, 'Please, enter your login', keyboard) elif self.secure.has_person(text): self.send(user, 'This login is already taken, enter another', keyboard) else: self.send(user, 'Send your face', keyboard) self.users_status[user] = self.sign_up_photo_status self.users_login[user] = text def sign_up_photo(self, user, text, photos): keyboard = self.make_keyboard(['Cancel']) if (text == 'Cancel') or (text == 'cancel') or (text == self.command_stop): self.users_status[user] = None self.users_login[user] = None self.startup(user, '') elif photos is None: self.send(user, 'Please, send your face', keyboard) else: try: login = self.users_login[user] link = self.get_photo_link(user, photos) face = self.recognizer.recognize(link) person = Person(user, login, face) self.secure.add_person(person) self.users_status[user] = self.sign_up_more_photo_status self.send(user, 'Account created!\n<b>Secure level</b> is bad\nAdd one more photo', keyboard) except Exception as error: self.send(user, error.__str__(), keyboard) def sign_up_more_photo(self, user, text, photos): keyboard = self.make_keyboard(['Cancel and back to profile']) if (text == 'Cancel and back to profile') or (text == 'cancel and back to profile') or (text == self.command_stop): self.users_status[user] = self.sign_in_status self.startup(user, '') elif photos is None: self.send(user, 'Please, send your face', keyboard) else: try: login = self.users_login[user] link = self.get_photo_link(user, photos) face = self.recognizer.recognize(link) diff = self.secure.add_face(login, face, user) if diff > self.secure_level_bad: self.send(user, '<b>Secure level</b> is bad\nAdd one more photo', keyboard) elif diff > self.secure_level_normal: self.send(user, '<b>Secure level</b> is normal\nRecommended to add one more photo', keyboard) elif diff > self.secure_level_good: self.send(user, '<b>Secure level</b> is good\nBack to profile or add one more photo', keyboard) else: self.send(user, 'Secure level is well') self.users_status[user] = self.signed_in_status self.profile(user, '') except Exception as error: self.send(user, error.__str__(), keyboard) def sign_in(self, user, text, photos): keyboard = self.make_keyboard(['Cancel']) if (text == 'Cancel') or (text == 'cancel') or (text == self.command_stop): self.users_status[user] = None self.users_login[user] = None self.startup(user, '') elif photos is None: self.send(user, 'Please, send your photo', keyboard) else: try: link = self.get_photo_link(user, photos) face = self.recognizer.recognize(link) person = self.secure.find_face(face, user) if person is None: self.send(user, 'Cannot define profile by this photo, please try again', keyboard) else: self.users_status[user] = self.signed_in_status self.users_login[user] = person.login self.send(user, 'Login as ' + person.login) logging.info('[user' + str(user) + ']: sign in as ' + person.login) self.profile(user, '') except Exception as error: self.send(user, error.__str__(), keyboard) def profile(self, user, text): if text is not None: text = text.lower() if (text == 'exit') or (text == 'log out') or (text == self.command_stop): self.users_status[user] = None self.users_login[user] = None self.startup(user, '') elif text == 'add photo': keyboard = self.make_keyboard(['Cancel']) self.users_status[user] = self.add_photo_status self.send(user, 'Send your photo', keyboard) else: keyboard = self.make_keyboard(['Enter secret', 'Add photo', 'Exit']) login = self.users_login[user] self.send(user, 'Welcome ' + login + '\nSome info', keyboard) def add_photo(self, user, text, photos): keyboard = self.make_keyboard(['Cancel']) if (text == 'Cancel') or (text == 'cancel') or (text == self.command_stop): self.users_status[user] = None self.users_login[user] = None self.profile(user, '') elif photos is None: self.send(user, 'Please, send your photo', keyboard) else: try: login = self.users_login[user] link = self.get_photo_link(user, photos) face = self.recognizer.recognize(link) self.secure.add_face(login, face, user) self.users_status[user] = self.signed_in_status self.send(user, 'Photo successfully added') self.profile(user, '') except Exception as error: self.send(user, error.__str__(), keyboard) def send(self, user, text, keyboard=None): last = self.users_message.get(user) if last is not None: last_id = last['id'] last_text = last['text'] last_keyboard = last['keyboard'] if (text == last_text) and (keyboard == last_keyboard): return self.bot.delete_message(user, last_id) last_id = self.bot.send_message(user, text, 'html', keyboard) last = {'id': last_id, 'text': text, 'keyboard': keyboard} self.users_message[user] = last def get_photo_link(self, user, photos): self.send(user, 'Loading...') if (photos is None) or (len(photos) is 0): raise Exception('No photo in this message, try again') photo = photos[-1] photo_id = photo['file_id'] link = self.bot.get_file_link(photo_id) if link is None: raise Exception('Photo cannot be loaded, try again') return link def commands(self, user, text): if (text is None) or (user is None): return text = text.lower() if user == self.owner_id: if text == 'log out all': for u, status in self.users_status.items(): if status is not None: self.message(u, self.command_stop, None) if text == 'stop': self.commands(user, 'log out all') exit(0) if text == 'users': self.send(user, self.secure.get_info().__str__(), None) time.sleep(1) @staticmethod def make_keyboard(texts): buttons = list() [buttons.append([{'text': text, 'callback_data': text}]) for text in texts] return json.dumps({'inline_keyboard': buttons}) @staticmethod def get(data, keys): if data.__contains__(keys[0]): first = keys[0] if len(keys) is 1: return data[first] else: keys.pop(0) return Controller.get(data[first], keys) else: return None
from flask import Flask, render_template, request, url_for, redirect from secure import Secure # To update live site, delete 'SignatureGenerator' directory, clone updated repository, reboot server, run following: # 'gunicorn -b 0.0.0.0:8000 SignatureGenerator.app:app' in terminal to run # Create app, set csrf key, and activate security.py app = Flask(__name__) secure = Secure() # Store address dictionary store_dict = { '100 Park City': '1664 Uinta Way #C-2/Park City, UT 84098', '101 Orem': '775 E University Parkway/Orem, UT 84097', '102 Ft. Union': '6936 South Park Center Drive/Cottonwood Heights, UT 84121', '105 St. George': '473 South River Road, Suite 2/St. George, UT 84790', '106 Foothill': '1414 Foothill Drive Suite A-2/Salt Lake City, UT 84108', '200 Lubbock': '2407 9th Street, Suite 200/Lubbock, TX 79401', '203 Tyler': '4919 S. Broadway Avenue/Tyler, TX 75703', '205 Rogers': '2603 W Pleasant Grove Rd, Suite 103/Rogers, AR 72758', '206 Katy': '23730 Westheimer Parkway, Space 730-T/Katy, TX 77494', '207 Waco': '300 S. 2nd Street, Suite 104/Waco, TX 76701', '208 San Marcos': '200 Springtown Way, Suite 122/San Marcos, TX 78666', '301 Evansville': '6401 E Lloyd Expressway, Suite 17/Evansville, IN 47715', '305 Ft. Wayne': '4130 W Jefferson Blvd, Suite I-7/Fort Wayne, IN 46804', '308 Cincinnati': '7532 Gibson St., Space E-108/Cincinnati, OH 45069', '312 Nashville': '2018 Lindell Avenue/Nashville, TN 37203', '313 Vanderbilt': '2509 West End Avenue/Nashville, TN 37203', '314 Chattanooga': '2100 Hamilton Place Boulevard Suite 318/Chattanooga, TN 37421', '315 Johnson City': '2011 North Roan Street/Johnson City, TN 37601', '316 Louisville': '3702 Lexington Rd/Louisville, KY 40207',
"'self'").form_action("'self'").base_uri("'self'").connect_src( "'self'" "api.spam.com").frame_src("'self'").img_src("'self'", "static.spam.com")) cache_value = CacheControl().must_revalidate() content = XContentTypeOptions() server = Server().set("Secure") permissions_value = (PermissionsPolicy().accelerometer("").autoplay("").camera( "").document_domain("").encrypted_media("").fullscreen("").geolocation( "").gyroscope("").magnetometer("").microphone("").midi("").payment( "").picture_in_picture("").sync_xhr("").usb("").geolocation( "self", "'spam.com'").vibrate()) secure_headers = Secure(server=server, csp=csp, hsts=hsts, referrer=referrer, permissions=permissions_value, cache=cache_value, content=content) app = FastAPI() app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], expose_headers=["content-disposition"], ) app.add_middleware(GZipMiddleware) Utility.load_environment()
from flask_mail import Mail from flask_migrate import Migrate from flask_moment import Moment from flask_sqlalchemy import SQLAlchemy from flask_wtf.csrf import CSRFProtect from secure import Secure from sqlalchemy import MetaData # pylint: disable=invalid-name convention = { 'ix': 'ix_%(column_0_label)s', 'uq': 'uq_%(table_name)s_%(column_0_name)s', 'ck': 'ck_%(table_name)s_%(constraint_name)s', 'fk': 'fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s', 'pk': 'pk_%(table_name)s' } babel = Babel() bcrypt = Bcrypt() bootstrap = Bootstrap() csrf_protect = CSRFProtect() login_manager = LoginManager() db = SQLAlchemy(metadata=MetaData(naming_convention=convention)) migrate = Migrate(compare_type=True, compare_server_default=True) cache = Cache() debug_toolbar = DebugToolbarExtension() mail = Mail() moment = Moment() secure_headers = Secure()
class MainApplication(QtWidgets.QWidget, Login_form, Sort_books): def __init__(self, dialog, window): super(MainApplication, self).__init__() self.setupUi(dialog) self.dialog = dialog self.window = window self.Config = ServerConfig() self.Sec = Secure() self.get_key() self.dialog.show() def loginAction(self): login = self.lineEdit.text() pass_ = self.lineEdit_2.text() if login is '' or pass_ is '': return app_error("Uzupełnij wszystkie dane.") try: resp = requests.post(self.Config.get_server() + '/api/logaction', data={ 'login': self.Sec.encrypt_(login), 'pass_': self.Sec.encrypt_(pass_), 'publicKey': self.Sec.get_public() }) except requests.ConnectionError as e: return app_error("Nie można nawiązać połączenia z serwerem.", e) if resp.status_code == 200: data = json.loads(resp.text) try: open('.cache', "wb").write(data['auth'].encode()) except PermissionError: os.remove('.cache') open('.cache', "wb").write(data['auth'].encode()) ctypes.windll.kernel32.SetFileAttributesW('.cache', 0x02) self.dialog.close() return self.st_ap(self.Sec.decrypt_(data['master']), self.Sec.decrypt_(data['data'])) elif resp.status_code == 406: return app_error("Dane użyte do logowania są niepoprawne.") else: return app_error( "Wystąpił nieznany błąd podczas przetwarzania danych.") def st_ap(self, data, date): self.setupUi_2(self.window, self.Config, self.Sec, data, date) self.retranslateUi_2(self.window) return self.window.show() def get_key(self, stop=False): try: resp = requests.get(self.Config.get_server() + '/api/key') except requests.ConnectionError as e: app_error("Nie można nawiązać połączenia z serwerem.", e) return exit() if resp.status_code == 200: data = json.loads(resp.text) self.Sec.load_other_key(data['publicKey']) else: if stop: return exit() else: app_error("Wystąpił problem z wczytaniem kluczy") return self.get_key(stop=True)
import select, socket, sys, json, getpass, time, base64, os, time, logging from os import listdir from os.path import isfile, join from Crypto.Hash import SHA512, HMAC, SHA256 from Crypto.Random import random from Crypto.PublicKey import RSA from secure import Secure from citizencard import citizencard from random import randint secure = Secure() # secure functions cc = citizencard() HOST = "localhost" # All available interfaces PORT = 8080 # The server port TERMINATOR = "\r\n" MAX_BUFSIZE = 64 * 1024 # Connection status NOT_CONNECTED = 10000 CONNECTING = 20000 CONNECTED = 30000 # Mathematics for session key / diffie helman PRIMITIVE_ROOT = 5 MODULUS_PRIME = 0xeb8d2e0bfda29137c04f5a748e88681e87038d2438f1ae9a593f620381e58b47656bf5386f7880da383788a35d3b4a6991d3634b149b3875e0dccff21250dccc0bf865a5b262f204b04e38b2385c7f4fb4e2058f73a8f65252e556b667b1570465b2f6d1beeab215b05cd0e28b9277f3f48c01b1619b30147fcfc87b5b6903e70078babb45c2ee6a6bd4099ab87b01ba09a38c36279b46309ef0df5e45e15df9ba5cb296baa535c60bb0065669fd8078269eb759416d9b27229f9cb6e5f60f7d8756f6f621ad519745f914e81a7c8d09b3c7a764863dd5d5f2bcab5ef283aa3781c985d07f2b1aafb2e7747b3217dbbfea2e91484c31a00e22467c0c7f9d40f73d392594c516b302aa7c1aa6ca5a0b346cc6bfc1cd201dfe78aabf717f6c69f30a896567b07090e352e87fd698128da0594916d27203e22b7bb1f7f860842fd0aee2e532a077629451ef86163fdf567048266050a473d4db27e85a33bc985b16569afddaa9a94a5b9155b32b78c84b261ce7acf7d8d0ef23d4e1d028104aff6a77cab79ecdf7dd19468f67d3cb9b86835cce1a87dbf4b2d3100a9bd7a9e251272bf4e2fed2c2f7535e556b8cc1fc6fcfc1a2ca188c02ea9298bb4a7f12afd4164ad9211f7935f51be3d9d932e835a1fd322e7db75ba587021f8c730d7f021905e89a0ddb80bf8ea53b8f1603cf08c734aadfe7f9184e0de9e91651c3d88deb68fd1bc0188e479747caab9a157ef6ec68295a1bfb6391973364987cda6c7817dfee2ab9d4e0eaefb29154f23eafedcab06d67fbcc5d1788a20315c50f9c6471dbb45419b07ddec0d507c16a0b7e2d79290d3115edcdc2996897015dfa430389a1d63533e52aa6309c76e7069e0a99af65702036e7829bc8e86ad3e23983debf72c82d8e3a2e9d767cccfb2abed6b0b0c9f217bb496ea816ea3c32111f60916d91f8a97cfa38b163ca1261733cd98cb2ff77a7ee9290bda74be8dc206489d06abca4e5ae82ae4923fa43b451fa419da06d74f15e4efc4852bf5edf37e581edeaaefd28a8b3c672bb76068439635adecebaf8311d4018fe8e62892f784d7a44747178c4cb540c58e5e2a660a3f02c873d12b43f0643d3794d8b310fe9fa6d798e0724d38c85c9e4d5c8c9ba645f3411dd4645ef1ef1dad9ba60325b12def1bd706d11386045e450fee2a60c88cf6387dea0521acc4d869fb146a47ef4e34480d30f84ffa0e0e0a4a4c7f1b0a8e642223e8bec4d1c8effd98ba235dc5c5f7e296ecd7476595ef17371a1aec3a38c3e7f7e08e7b5e7c927f5843062f753e5ee85f7e64164dd0ccb7261d4ca3a35058ca88f87275a292e96100005c025742f85be7a2598406b9c792f2ba2a496f8074d899821110effb184e3c679330b182a8c14ba1699f3761168d64e838829c0250c6be87bc8dc2b29954bf6cb450ba7bed793cf97 pubNum = lambda x,y,z: int(pow(x,y,z)) def privateNumber(): secret = random.getrandbits(256)
class Server(): def __init__(self): self.s = _socket() self.s.bind((HOST, PORT)) self.s.listen(5) self.clients = [] self.clientKeys = {} self.clientCiphers = {} self.lastPing = time() self.haveNotPong = set() self.secure = Secure() self.matches = [] Thread(target=self.accept, daemon=True).start() Thread(target=self.listen, daemon=True).start() def accept(self): while True: socket, adress = self.s.accept() socket.settimeout(0) socket.send(b">>>" + self.secure.publicKey.exportKey("DER")) print("Sent server key to", adress) self.clients.append((socket, adress)) def handle(self, data, client, adress): if data.startswith(b">>>"): print("Received client key from", adress) self.clientKeys[client] = self.secure.fromDer(data[3:]) self.clientCiphers[client] = PKCS1_OAEP.new(self.clientKeys[client]) self.send(b"Welcome", client) if len(self.clientCiphers) == 2: pair = [] color = b"WHITE" for c, a in self.clients: if c in self.clientCiphers: self.send(b"MATCH" + color, c) pair.append(c) color = b"BLACK" self.matches.append(pair) print("Welcomed", adress) else: deciphered = self.secure.privateCipher.decrypt(data) if not deciphered.startswith(b">>"): print("Invalid packet from", adress) return deciphered = deciphered[2:] if deciphered == b"PONG": self.haveNotPong.remove((client, adress)) print(adress, "answered a ping with a pong") elif (deciphered.startswith(b"MOVE") or deciphered.startswith("CASTLE")): for i in self.matches: if client in i: c1, c2 = i adversary = c2 if c1 == client else c1 self.send(deciphered, adversary) break else: print(deciphered, adress) def send(self, data, client): ciphered = self.clientCiphers[client].encrypt(b">>" + data) client.send(ciphered) def listen(self): while True: ping = time() > self.lastPing + 30 for client, adress in self.clients: try: try: data = client.recv(4096) except BlockingIOError: pass else: self.handle(data, client, adress) if ping: self.send(b"PING", client) except (ConnectionResetError, ConnectionAbortedError): self.clients.remove((client, adress)) del self.clientKeys[client] del self.clientCiphers[client] print(adress, "left") if ping: print("Pinged every client (%d)" % len(self.clients)) self.lastPing = time() # TODO: Remove people who haven't pong yet before updating. self.haveNotPong.update(self.clients)