def register(self):
        '''init connection and login a exist user'''
        if not isinstance(self.conn, socket.socket):
            return False, 'Not Connected to server'.title()
        conn = self.conn
        msg = Message(kind=kind_register, sender=self.username, receiver='')
        try:
            conn.sendall(msg.inBytes)
        except socket.error:
            print(
                '{}, RegisterError, can not send RegisterReq to server'.format(
                    localtime()))
            return False, 'RegisterError, can not send RegisterReq to server'
        data = conn.recv(1024)
        try:
            msg = Message.ParseBytes(data)
        except:
            print('{}, RegisterError, failed to parse server response'.format(
                localtime()))
            return False, 'RegisterError, failed to parse server response'
        print(msg)
        if msg.kind == kind_register and msg.token and isinstance(
                msg.token, str) and msg.info == 'ok':
            print('{}, RegisterAndLoginSuccess, token is {}'.format(
                localtime(), msg.token))
            self.token = msg.token
            self.online = True
            self.conn = conn, 'RegisterAndLoginSuccess'
            return True

        self.conn = None
        self.token = None
        conn.close()
        return False, 'Register Failed'
 def init_connect(self):
     conn = socket.socket()
     try:
         conn.connect((host, port), )
     except socket.error:
         print('{}, ConnectionError, can not connect to server'.format(
             localtime()))
         return False, 'ConnectionError, can not connect to server'
     data = conn.recv(1024)
     try:
         msg = Message.ParseBytes(data)
     except:
         print('{}, RegisterError, failed to parse server response'.format(
             localtime()))
         return False, 'RegisterError, failed to parse server response'
     print(msg)
     self.conn = conn
     return True, 'Connected'
    def login(self):
        if not isinstance(self.conn, socket.socket):
            return False, 'Not Connected to server'.title()
        conn = self.conn
        # send to server username
        msg = Message(kind=kind_login, sender=self.username, receiver='')
        try:
            conn.sendall(msg.inBytes)
        except socket.error:
            print('{}, LoginError, can not send LoginReq to server'.format(
                localtime()))
            return False, 'LoginError, can not send LoginReq to server'

        # receive server response to login req
        data = conn.recv(1024)
        # print('receive server response to login req', data)
        try:
            msg = Message.ParseBytes(data)
        except:
            print('{}, LoginError, failed to parse server response'.format(
                localtime()))
            print(str(data, encoding='utf-8'))
            return False, 'LoginError, failed to parse server response'
        print(msg)
        if msg.kind in [kind_login,
                        kind_register] and msg.token and isinstance(
                            msg.token, str) and msg.info == 'ok':
            print('{}, LoginSuccess, token is {}'.format(
                localtime(), msg.token))
            self.token = msg.token
            self.online = True
            self.conn = conn
            return True, 'LoginSuccess'

        self.conn = None
        self.token = None
        conn.close()
        return False, msg.info
    def receive(self):
        while self.flag:
            if self.token is None or self.conn is None:
                continue
            try:
                data = self.conn.recv(1024)
            except socket.error:
                continue
            try:
                msg = Message.ParseBytes(data)
            except (TypeError, ValueError):
                continue
            if msg.kind == kind_relogin and msg.info == info_ok:
                print('{}, ReLogin success!'.format(localtime()))
                self.online = True

            if msg.kind == kind_heartbeat and msg.info == info_ok:
                print('{}, HeartBeat from server'.format(localtime()))

            if msg.kind == kind_get_all_users:
                self.friends.update(msg.info)

            if msg.kind == kind_emotion:
                self.store_new_messages(msg)
    def handle(self):

        c = self.request
        print(localtime(), c)
        try:
            message = Message(kind=server_ask_username, sender=server_name, receiver='', info=welcome_msg)
            c.sendall(message.inBytes)
        except:
            c.close()
            return
        try:
            data = c.recv(1024)
        except:
            c.close()
            return
        try:
            message = Message.ParseBytes(data)
        except:
            self.__send_data_close(c, invalid_msg)
            return

        # print(message, users)

        user_name = message.sender

        # print('check', message.kind)

        # 处理用户登陆
        if message.kind == 'Login':
            self.login(c, user_name)

        # 处理用户注册
        elif message.kind == kind_register:
            self.register(c, user_name)

        # 处理已登陆用户重联 --- 用户不稳定的网络
        elif message.kind == kind_relogin:
            result = self.re_login_with_token(c, message.sender, message.token)
            if result is not True:
                self.__send_data_close(c, invalid_token)
                return
            else:
                if not self.__send_data(conn=c, info='ok', kind=kind_relogin):
                    c.close()
                    return
        else:
            self.__send_data_close(c, invalid_msg)
            return

        while True:
            if running is not True:
                break
            try:
                data = c.recv(1024)
            except:
                self.logout(user_name)
                break
            try:
                message = Message.ParseBytes(data)
            except:
                continue

            sender = message.sender
            info = message.info
            receiver = message.receiver
            kind = message.kind
            status = message.status
            token = message.token

            if token is None:
                self.__send_data_close(c, invalid_token)
                break

            if token not in token_user_map:
                self.__send_data_close(c, invalid_token)
                break

            # 心跳
            if kind == kind_heartbeat:
                if token in token_user_map \
                        and token_user_map[token].token == token \
                        and sender == token_user_map[token].username:
                    self.__send_data(c, 'ok', 'HeartBeat')
                else:
                    self.__send_data_close(c, invalid_token)
                    break

            # 用户登出
            if kind == kind_exit:
                self.logout(user_name)
                break

            # 获取用户列表和用户状态
            if kind == kind_get_all_users:
                self.__send_data(conn=c, info=json.dumps(self.users_status_batch), kind=kind)
                continue

            # 获取某个用户的状态
            if kind == kind_get_user_status:
                self.__send_data(c, self.check_user(info), kind)
                continue

            # p2p chat
            if kind == kind_p2p_chat:
                receiver = users[receiver]
                self.__send_data(receiver.conn, info=info, kind=kind)  # todo: the partner offline

            ###############################################################
            # 用户情绪
            ###############################################################
            if kind == kind_emotion:

                # emotions.append(message)
                sender_ = users[sender]
                if sender_.occupation == 'student':

                    teacher = users['teacher']
                    self.__send_data(
                        teacher.conn,
                        info={
                            'talk': message.info,
                            'mood': ai_api(message)
                            # 利用ai把学生的发言分析成-1,0, +1中的一个,并发送给教师端
                        },
                        kind=kind_emotion,
                        sender=sender
                    )
                    print(teacher, teacher.conn,)
                elif sender_.occupation == 'teacher':
                    if not receiver:
                        continue
                    student = users[receiver]
                    self.__send_data(
                        student.conn,
                        info=message.info,
                        kind=kind_emotion,
                        sender=sender

                    )