def on_changes(*resp):
    print('CHANGE') if deb2 else None
    print("------\nTH: ", resp, "\n------") if deb else None
    print("response: ", resp[0]) if deb else None
    print("data response: ", resp[0]['data']) if deb else None
    print("sign response: ", resp[0]['sign']) if deb else None
    resp_data = json.loads(
        jws.verify(resp[0]['data'], pri_id, algorithms=['HS256']).decode())
    print("decrypt data response: ", resp_data) if deb else None
    print("key in data response: ", server_key) if deb else None
    if sign.verify_sign(server_key, resp[0]['sign'], resp[0]['data']):
        # update new data
        print("valid sign") if deb else None
        req_data = {"ses_id": session_id, "time_req": resp_data['time_req']}
        print("data to send: ", req_data) if deb else None
        crypt_data = jws.sign(req_data, pri_id, algorithm='HS256')
        print("encrypt data to send: ", crypt_data) if deb else None
        sign_crypt_data = sign.sign_data(key.exportKey(), crypt_data)
        print("sign of en data send: ", sign_crypt_data) if deb else None
        req2 = {
            "pub_id": pub_id,
            "data": crypt_data,
            "sign": sign_crypt_data.decode()
        }
        print("send: ", req2) if deb else None
        print("CHANGE DONE") if deb2 else None
        socketIO.emit('change_confirm', req2)
def connect_request(req):
    print("----------------------------------connect_request----------------------------------") if deb2 else None
    print("req pub_id: : ", req['pub_id']) if deb else None
    print("req key: ", req['key']) if deb else None
    print("req key encode utf-8: ", req['key'].encode('utf-8')) if deb else None
    if UserFarm.query.filter_by(pub_id=req['pub_id']).first() is not None:
        app1 = UserFarm.query.filter_by(pub_id=req['pub_id']).first()
        print("UserFarm pub_id: ", app1.pub_id) if deb else None
        if Session.query.filter_by(pub_id=req['pub_id'], flag=True).first() is not None:
            app2 = Session.query.filter_by(pub_id=req['pub_id'], flag=True).first()
            print("Session pub_id: ", app2.pub_id) if deb else None
            app2.flag = False
            app2.time_end = datetime.datetime.utcnow()
            db.session.commit()
        otp = ''.join(secrets.choice(alphabet) for i in range(50))
        print("otp: ", otp) if deb else None
        cur = Session(pub_id=req['pub_id'], key=req['key'], otp=otp, flag=True, time_start=datetime.datetime.utcnow())
        db.session.add(cur)
        db.session.commit()
        data = {"otp": otp, "key": key.publickey().export_key().decode("utf-8")}
        print("decrypt pass on db: ", jws.verify(app1.pri_id, priv_id, algorithms=['HS256']).decode()) if deb else None
        crypt_data = jws.sign(data, jws.verify(app1.pri_id, priv_id, algorithms=['HS256']).decode(), algorithm='HS256')
        print("encrypt data: ", crypt_data) if deb else None
        sign_crypt_data = sign.sign_data(key.exportKey(), crypt_data)
        print("sign encrypt data: ", sign_crypt_data) if deb else None
        resp = {"data": crypt_data, "sign": sign_crypt_data.decode()}
        print("resp: ", resp) if deb else None
        print("resp data: ", resp['data']) if deb else None
        print("CON REQ ---> user: "******"----------------------------------connect_request DONE----------------------------------") if deb2 else None
        emit('connect_response', resp)
    else:
        emit('connect_response', 1)
def connect_confirm(req):
    print("----------------------------------connect confirm----------------------------------") if deb2 else None
    print("received data: ", req) if deb else None
    print("received data pub_id: ", req['pub_id']) if deb else None
    print("received data data: ", req['data']) if deb else None
    print("received data sign: ", req['sign']) if deb else None
    if UserFarm.query.filter_by(pub_id=req['pub_id']).first() is not None:
        app1 = UserFarm.query.filter_by(pub_id=req['pub_id']).first()
        print("UserFarm pub: ", app1.pub_id) if deb else None
        print("UserFarm priv: ", app1.pri_id) if deb else None
        print("decrypt pass on db: ", jws.verify(app1.pri_id, priv_id, algorithms=['HS256']).decode()) if deb else None
        try:
            req_data = json.loads(jws.verify(req['data'], jws.verify(app1.pri_id, priv_id, algorithms=['HS256']).decode(), algorithms=['HS256']))
        except:
            emit('connect_estab', 5)
        print("decrypt data: ", req_data) if deb else None
        if Session.query.filter_by(otp=req_data['otp'], flag=True).first() is not None:
            app2 = Session.query.filter_by(otp=req_data['otp'], flag=True).first()
            if sign.verify_sign(app2.key, req['sign'], req['data']):
                print("valid sign") if deb else None
                print("time_start : ", app2.time_start) if deb else None
                print("now - delta : ", datetime.datetime.utcnow() - datetime.timedelta(minutes=10)) if deb else None
                if app2.time_start > datetime.datetime.utcnow() - datetime.timedelta(minutes=10):
                    ses_id = ''.join(secrets.choice(alphabet) for i in range(100))
                    app2.session_id = ses_id
                    print("sid: ", request.sid) if deb else None
                    app2.sid = request.sid
                    db.session.commit()
                    data = {"ses_id": ses_id}
                    print("data resp: ", data) if deb else None
                    print("app1.pri_id: ",  jws.verify(app1.pri_id, priv_id, algorithms=['HS256']).decode()) if deb else None
                    crypt_data = jws.sign(data,  jws.verify(app1.pri_id, priv_id, algorithms=['HS256']).decode(), algorithm='HS256')
                    print("encrypt data to send: ", crypt_data) if deb else None
                    sign_crypt_data = sign.sign_data(key.exportKey(), crypt_data)
                    print("sign of en data send: ", sign_crypt_data) if deb else None
                    res2 = {"pub_id": app2.pub_id, "data": crypt_data, "sign": sign_crypt_data.decode()}
                    print("send: ", res2) if deb else None
                    print("TH CON CONF ---> user: "******"  ses_id: ",  ses_id) if deb2 else None
                    print("----------------------------------connect_confirm DONE----------------------------------") if deb2 else None
                    emit('connect_estab', res2)

                    global thread
                    if thread is None:
                        thread = threading.Thread(target=check_changes(db))
                        thread.start()

                else:
                    emit('connect_estab', 4)
            else:
                emit('connect_estab', 3)
        else:
            emit('connect_estab', 2)
    else:
        emit('connect_estab', 1)
def check_changes(db):
    #CAN BE DO WITH NORMAL DB CALL
    print(
        "----------------------------------start thread----------------------------------"
    ) if deb2 else None
    while True:
        if db.session.query(Change).filter_by(flag=False).order_by(
                Change.time_req.asc()).first() is not None:
            app1 = db.session.query(Change).filter_by(flag=False).order_by(
                Change.time_req.asc()).first()
            if db.session.query(UserFarm).filter_by(
                    pub_id=app1.farm_id).first() is not None:
                app2 = db.session.query(UserFarm).filter_by(
                    pub_id=app1.farm_id).first()
                if db.session.query(Session).filter_by(
                        pub_id=app1.farm_id, flag=True).first() is not None:
                    app3 = db.session.query(Session).filter_by(
                        pub_id=app1.farm_id, flag=True).first()
                    data = {
                        "ses_id": app3.session_id,
                        'code': app1.code,
                        'val': app1.val,
                        "ch_id": app1.change_id
                    }
                    print("TH-data: ", data) if deb else None
                    crypt_data = jws.sign(data,
                                          jws.verify(app2.pri_id,
                                                     priv_id,
                                                     algorithms=['HS256'
                                                                 ]).decode(),
                                          algorithm='HS256')
                    print("TH-encrypt data: ", crypt_data) if deb else None
                    sign_crypt_data = sign.sign_data(key.exportKey(),
                                                     crypt_data)
                    print("TH-sign of data: ",
                          sign_crypt_data) if deb else None
                    req = {
                        "pub_id": app2.pub_id,
                        "data": crypt_data,
                        "sign": sign_crypt_data.decode()
                    }
                    print("TH-send: ", req) if deb else None
                    emit('changes', req, room=app3.sid)
                    print("TH CHECK CHANGE ---> user: "******"  ch_id: ", app1.change_id) if deb2 else None
        print(
            "----------------------------------th restart loop----------------------------------"
        ) if deb2 else None
        time.sleep(5)
    print(
        "----------------------------------finish thread----------------------------------"
    ) if deb2 else None
def on_connect_response(*resp):
    print(resp) if deb else None
    if type(resp[0]) == int:
        errors.manage_error(resp[0])
    else:
        print('CONNECT RESPONSE') if deb2 else None
        print("response: ", resp[0]) if deb else None
        print("data response: ", resp[0]['data']) if deb else None
        print("sign response: ", resp[0]['sign']) if deb else None
        resp_data = json.loads(
            jws.verify(resp[0]['data'], pri_id, algorithms=['HS256']).decode())
        print("decrypt data response: ", resp_data) if deb else None
        print("key in data response: ", resp_data['key']) if deb else None
        if sign.verify_sign(resp_data['key'], resp[0]['sign'],
                            resp[0]['data']):
            print("valid sign") if deb else None
            global server_key
            server_key = resp_data['key']
            req_data = {"otp": resp_data['otp']}
            print("data to send: ", req_data) if deb else None
            crypt_data = jws.sign(req_data, pri_id, algorithm='HS256')
            print("encrypt data to send: ", crypt_data) if deb else None
            sign_crypt_data = sign.sign_data(key.exportKey(), crypt_data)
            print("sign of en data send: ", sign_crypt_data) if deb else None
            req2 = {
                "pub_id": pub_id,
                "data": crypt_data,
                "sign": sign_crypt_data.decode()
            }
            print("send: ", req2) if deb else None
            print("CONNECT RESPONSE DONE") if deb2 else None
            socketIO.emit('connect_confirm', req2)
            socketIO.on('connect_estab', on_connect_estab)
            socketIO.wait(seconds=3)
        else:
            errors.manage_error(6)
socketIO.emit('connect_request', req)
socketIO.on('connect_response', on_connect_response)
socketIO.wait(seconds=3)

print('START THREAD') if deb2 else None
#thread = socketio.start_background_task(wait_changes)
x = threading.Thread(target=wait_changes)  #, args=(1,))
x.start()

print('REQUIRE SAMPLE DICT') if deb2 else None
req = exdict.sampleDict
req['ses_id'] = session_id
print("data to send: ", req) if deb else None
crypt_data = jws.sign(req, pri_id, algorithm='HS256')
print("encrypt data to send: ", crypt_data) if deb else None
sign_crypt_data = sign.sign_data(key.exportKey(), crypt_data)
print("sign of en data send: ", sign_crypt_data) if deb else None
req = {"pub_id": pub_id, "data": crypt_data, "sign": sign_crypt_data.decode()}
print("send: ", req) if deb else None
socketIO.emit('sample_dict', req)
socketIO.on('samp_response', on_samp_response)
socketIO.wait(seconds=3)

print('REQUIRE CONFIGURATION DICT') if deb2 else None
req = exdict.configurationDict
req['ses_id'] = session_id
print("data to send: ", req) if deb else None
crypt_data = jws.sign(req, pri_id, algorithm='HS256')
print("encrypt data to send: ", crypt_data) if deb else None
sign_crypt_data = sign.sign_data(key.exportKey(), crypt_data)
print("sign of en data send: ", sign_crypt_data) if deb else None