Module socialization.bot

Expand source code
from .base_bot import BaseBot
from .. import codes
from .json_socket_user import JSONSocketUser, MessageType, Message, rel

__all__ = ['BaseBot', 'codes', 'JSONSocketUser', 'Message', 'MessageType', 'rel']

Sub-modules

socialization.bot.base_bot
socialization.bot.json_socket_user
socialization.bot.message

Classes

class BaseBot (user_id: str, password: str, path: str = None, reconnect: int = None, pre_analyse: bool = True)

This is the base of bot, deriving from which you can define automation of all behavior that a bot will abey. For basic use, what you need to do is only overriding on_receive_message to define the behaviour when receive a message. For example, you are definately allowed to broadcast the message to everyone in the channel where you receive it by overriding on_receive_message and call send_message with message you received send it to all users in the channel.

We wraps the message data into a Message object.

For better performance(not indeed), you could set pre_analyse to be False to get raw data of message(dict).

Initialize a Bot instance.

Args

user_id : str User ID of the account you wanna set as a bot. password : str Password of that account referred above. path : str : optional Location of server the bot will be running on. reconnect : int : optional Max pending time for stalling. Reconnection will launch if stalls outlong this time. pre_analyse : bool : optional Trigger for pre-analysing message by wrapping it into a Message object. If turned off, data param in on_receive_data() will be raw dict!

Expand source code
class BaseBot(JSONSocketUser):
        """
        This is the base of bot, deriving from which you can define automation of 
        all behavior that a bot will abey. 
        For basic use, what you need to do is only overriding `on_receive_message`
        to define the behaviour when receive a message. For example, you
        are definately allowed to broadcast the message to everyone in the channel 
        where you receive it by overriding `on_receive_message` and call 
        `send_message` with message you received send it to all users in the channel.

        We wraps the message data into a Message object.
    For better performance(not indeed), you could set
    `pre_analyse` to be `False` to get raw data of message(dict).
        """
        def __init__(self, user_id:str, password:str, path:str=None, reconnect:int=None, pre_analyse:bool=True) -> None:
                """
                Initialize a Bot instance.

                Args:
                        user_id : str
                                User ID of the account you wanna set as a bot.
                        password : str
                                Password of that account referred above.
                        path : str : optional
                                Location of server the bot will be running on.
                        reconnect : int : optional
                                Max pending time for stalling. Reconnection will launch if stalls
                                outlong this time.
                        pre_analyse : bool : optional
                                Trigger for pre-analysing message by wrapping it into a Message object.
                                If turned off, data param in on_receive_data() will be raw dict!
                """
                self.cached = False
                super().__init__(path=path, reconnect=reconnect, pre_analyse=pre_analyse)
                self.codes = codes
                self.channel_list = []
                self.user_lists = {}
                self.user_id = user_id
                self.password = password

        def on_receive_status(self, data):
                """
                Behaviour when receives status from server(6xxxx).

                By default, we would update channel_list and user_list
                on sereval cases. Therefore, if you want to customize
                behaviour receive status while keeping these properties
                up to date, override this function and **call**
                **super().on_receive_status** to keep them.

                Args:
                        data : dict
                                WS data in the format definde by `codes.md`
                """
                code = data['code']

                if code == self.codes.STATUS_INFO_USER_CHANNEL_LIST:
                        self._update_channel_list(data)
                elif code == self.codes.STATUS_INFO_CREATE_CHANNEL_SUCCESS or code == self.codes.STATUS_INFO_JOIN_SUCCESS:
                        self._append_channel_list(data)
                elif code == self.codes.STATUS_INFO_LEAVE_SUCCESS:
                        self._pop_channel_list(data)
                else:
                        super().on_receive_status(data)

        def on_receive_message(self, data):
                """
                Behaviour when receives message from server(3xxxx).
                Override this to customize what to do when receives
                a message!

                Args:
                        data : dict || Message
                                Wrapped Message object of message received.
                                If pre-analyse is turned off, it would be 
                                raw WS data in the format definde by `codes.md`
                """
                print('Bot received message: {}'.format(data))
                super().on_receive_message(data)

        def on_receive_command(self, data):
                """
                Behaviour when receives commands from server(4xxxx).
                It's crucial for keeping channel_list up to date. If
                you want to customize the behaviour, please **call**
                **super().on_receive_command** to keep those properties.

                Args:
                        data : dict
                                WS data in the format definde by `codes.md`
                """
                code = data['code']

                if code == self.codes.COMMAND_DOWN_UPDATE_CHANNEL_USER_LIST:
                        self._update_user_lists(data)
                else:
                        super().on_receive_command(data)

        def on_open(self, ws):
                """
                Behaviour at the time websocket connection is created.

                Args:
                        ws : websocket.WebSocketApp
                Connection object.
                """
                if self.cached:
                        self.login()
                print('Bot.open!')
        
        def on_close(self, ws, close_status_code, close_msg):
                """
                Behaviour at the time websocket connection is closed.

                Args:
                        ws : websocket.WebSocketApp
                Connection object.
                """
                print(f'Bot.close: {ws} closed with status code {close_status_code} and message {close_msg}')

        def on_error(self, ws, error):
                """
                Behaviour at the time error occur on websocket connection.

                Args:
                        ws : websocket.WebSocketApp
                Connection object.
                """
                print(f'Bot.error: {error}')
        
        def on_message(self, ws, message):
                """
                Behaviour at the time receive message from websocket connection.
        
                Warning:
                        Do not re-write this if you have no idea what will happen!

                Args:
                        ws : websocket.WebSocketApp
                Connection object.
                        message : jstr
                                Raw message json string from ws connection.
                """
                print(f'Bot.message: {message}')
                self._safe_handle(ws, message)

        def _update_channel_list(self, data):
                """
                Utility function to update current channel_list.
                If such properties are useless to you, and for
                better time performance(not that good though)
                you could re-write this to no-op.

                Args:
                        data : dict
                                WS data in the format definde by `codes.md`
                """
                self.channel_list = data['extra']['channel_ids']

                for channel_id in self.channel_list:
                        self._command_fetch_channel_user_list(self.user_id, channel_id)

        def _update_user_lists(self, data):
                """
                Utility function to update current user_lists.
                If such properties are useless to you, and for
                better time performance(not that good though)
                you could re-write this to no-op.

                Args:
                        data : dict
                                WS data in the format definde by `codes.md`
                """
                self.user_lists[data['extra']['channel_id']] = data['extra']['user_ids']

        def _append_channel_list(self, data):
                """
                Utility function to update current channel_list.
                If such properties are useless to you, and for
                better time performance(not that good though)
                you could re-write this to no-op.

                Args:
                        data : dict
                                WS data in the format definde by `codes.md`
                """
                self.channel_list.append(data['extra']['channel_id'])
                self._command_fetch_channel_user_list(self.user_id, data['extra']['channel_id'])

        def _pop_channel_list(self, data):
                """
                Utility function to update current channel_list.
                If such properties are useless to you, and for
                better time performance(not that good though)
                you could re-write this to no-op.

                Args:
                        data : dict
                                WS data in the format definde by `codes.md`
                """
                self.channel_list.remove(data['extra']['channel_id'])
                self.user_lists.pop(data['extra']['channel_id'])

        def login(self):
                """
                Wrapped login function. Call this to login.
                If you wanna customize login behaviour, call
                `_command_login()` to send command to login.
                """
                print("Bot login!")
                self.cached = True
                self._command_login(self.user_id, self.password)

        def logout(self):
                """
                Wrapped logout function. Call this to logout.
                If you wanna customize logout behaviour, call
                `_command_logout()` to send command to logout.
                """
                print("Bot logout!")
                self._command_logout(self.user_id)

        def register(self, email:str, password:str):
                """
                Wrapped register function. Call this to register.
                If you wanna customize register behaviour, call
                `_command_register()` to send command to register.

                Args:
                        email : str
                                Email to register an account.
                        password : str
                                Password for that new account.
                """
                print("Bot register")
                self._command_register(email, password)

        def reset_password(self, email:str, password:str):
                """
                Wrapped reset password function. Call this to reset password.
                If you wanna customize reset password behaviour, call
                `_command_reset_password()` to send command to reset password.

                Args:
                        email : str
                                Email of the account to reset pw.
                        password : str
                                New password for that account.
                """
                print("Bot reset password")
                self._command_reset_password(email, password)

        def join_channel(self, channel_id:str):
                """
                Wrapped join channel function. Call this to join channel.
                If you wanna customize join channel behaviour, call
                `_command_join_channel()` to send command to join channel.

                Args:
                        channel_id : str
                                ID of channel to join.
                """
                print("Bot join channel: {}".format(channel_id))
                self._command_join_channel(self.user_id, channel_id)

        def leave_channel(self, channel_id:str):
                """
                Wrapped leave channel function. Call this to leave channel.
                If you wanna customize leave channel behaviour, call
                `_command_leave_channel()` to send command to leave channel.

                Args:
                        channel_id : str
                                ID of channel to leave.
                """
                print("Bot leave channel: {}".format(channel_id))
                self._command_leave_channel(self.user_id, channel_id)

        def fetch_offline_message(self):
                """
                Wrapped fetch ofl-message function. Call this to fetch ofl-message.
                If you wanna customize fetch ofl-message behaviour, call
                `_command_fetch_offline_message()` to send command to fetch ofl-message.
                """
                print("Bot fetch offline message!")
                self._command_fetch_offline_message(self.user_id)

        def fetch_bot_channels(self):
                """
                Wrapped fetch bot channels function. Call this to fetch bot channels.
                If you wanna customize fetch bot channels behaviour, call
                `_command_fetch_user_channels()` to send command to fetch bot channels.
                """
                print('Bot fetch channels!')
                self._command_fetch_user_channels(self.user_id)

        def create_channel(self, channel_id):
                """
                Wrapped create channel function. Call this to create channel.
                If you wanna customize create channel behaviour, call
                `_command_create_channel()` to send command to create channel.
                
                Args:
                        channel_id : str
                                ID of the new channel.
                """
                print('Bot create channel: {}'.format(channel_id))
                self._command_create_channel(self.user_id, channel_id)

        def fetch_channel_command_list(self, channel_id):
                """
                Wrapped fetch channel cmd list function. Call this to fetch channel cmd list.
                If you wanna customize fetch channel cmd list behaviour, call
                `_command_fetch_channel_command_list()` to send command to fetch channel cmd list.

                Args:
                        channel_id : str
                                ID of the channel to fetch command list.
                """
                print('Bot fetch command list of channel : {}'.format(channel_id))
                self._command_fetch_channel_command_list(self.user_id, channel_id)

        def fetch_recipients(self, message_id):
                """
                Wrapped fetch recipients function. Call this to fetch recipients of 
                a certain message. If you wanna customize fetch recipients behaviour, 
                call `_command_fetch_recipients()` to send command to fetch recipients.

                Args:
                        message_id : str
                                ID of the message to look up for recipients.
                """
                print('Bot fetch recipients of message : {}'.format(message_id))
                self._command_fetch_recipient_list(self.user_id, message_id)
        
        def send_message(self, message:Message):
                """
                Wrapped send message function. Call this to send message.
                If you wanna customize send message behaviour, call
                `_command_send_message()` to send command to send message.

                Args:
                        message : Message
                                Wrapped message object contains message body, receivers,
                                target channel and sender information.
                """
                temp_msg_id = f"temp_{datetime.datetime.now().timestamp()}_{str(random.randint(0, 100000)).zfill(5)}"
                print('Bot send message: {}\nto: {}\n at channel: {}'.format(message.body, message.to, message.channel))
                self._command_send_message(temp_msg_id=temp_msg_id, message=message)

        def run(self):
                """
                Behaviour to run bot. 
                By default, it will login and update several properties
                of bot like channel_list .etc. Then it will hang this
                process up and reconnect when error occurs.
                
                Warning:
                        Don't re-write this if you have no idea what will happen!
                """
                self.login()
                self.fetch_bot_channels()
                rel.signal(2, rel.abort)
                rel.dispatch()

Ancestors

Methods

def create_channel(self, channel_id)

Wrapped create channel function. Call this to create channel. If you wanna customize create channel behaviour, call _command_create_channel() to send command to create channel.

Args

channel_id : str ID of the new channel.

Expand source code
def create_channel(self, channel_id):
        """
        Wrapped create channel function. Call this to create channel.
        If you wanna customize create channel behaviour, call
        `_command_create_channel()` to send command to create channel.
        
        Args:
                channel_id : str
                        ID of the new channel.
        """
        print('Bot create channel: {}'.format(channel_id))
        self._command_create_channel(self.user_id, channel_id)
def fetch_bot_channels(self)

Wrapped fetch bot channels function. Call this to fetch bot channels. If you wanna customize fetch bot channels behaviour, call _command_fetch_user_channels() to send command to fetch bot channels.

Expand source code
def fetch_bot_channels(self):
        """
        Wrapped fetch bot channels function. Call this to fetch bot channels.
        If you wanna customize fetch bot channels behaviour, call
        `_command_fetch_user_channels()` to send command to fetch bot channels.
        """
        print('Bot fetch channels!')
        self._command_fetch_user_channels(self.user_id)
def fetch_channel_command_list(self, channel_id)

Wrapped fetch channel cmd list function. Call this to fetch channel cmd list. If you wanna customize fetch channel cmd list behaviour, call _command_fetch_channel_command_list() to send command to fetch channel cmd list.

Args

channel_id : str ID of the channel to fetch command list.

Expand source code
def fetch_channel_command_list(self, channel_id):
        """
        Wrapped fetch channel cmd list function. Call this to fetch channel cmd list.
        If you wanna customize fetch channel cmd list behaviour, call
        `_command_fetch_channel_command_list()` to send command to fetch channel cmd list.

        Args:
                channel_id : str
                        ID of the channel to fetch command list.
        """
        print('Bot fetch command list of channel : {}'.format(channel_id))
        self._command_fetch_channel_command_list(self.user_id, channel_id)
def fetch_offline_message(self)

Wrapped fetch ofl-message function. Call this to fetch ofl-message. If you wanna customize fetch ofl-message behaviour, call _command_fetch_offline_message() to send command to fetch ofl-message.

Expand source code
def fetch_offline_message(self):
        """
        Wrapped fetch ofl-message function. Call this to fetch ofl-message.
        If you wanna customize fetch ofl-message behaviour, call
        `_command_fetch_offline_message()` to send command to fetch ofl-message.
        """
        print("Bot fetch offline message!")
        self._command_fetch_offline_message(self.user_id)
def fetch_recipients(self, message_id)

Wrapped fetch recipients function. Call this to fetch recipients of a certain message. If you wanna customize fetch recipients behaviour, call _command_fetch_recipients() to send command to fetch recipients.

Args

message_id : str ID of the message to look up for recipients.

Expand source code
def fetch_recipients(self, message_id):
        """
        Wrapped fetch recipients function. Call this to fetch recipients of 
        a certain message. If you wanna customize fetch recipients behaviour, 
        call `_command_fetch_recipients()` to send command to fetch recipients.

        Args:
                message_id : str
                        ID of the message to look up for recipients.
        """
        print('Bot fetch recipients of message : {}'.format(message_id))
        self._command_fetch_recipient_list(self.user_id, message_id)
def join_channel(self, channel_id: str)

Wrapped join channel function. Call this to join channel. If you wanna customize join channel behaviour, call _command_join_channel() to send command to join channel.

Args

channel_id : str ID of channel to join.

Expand source code
def join_channel(self, channel_id:str):
        """
        Wrapped join channel function. Call this to join channel.
        If you wanna customize join channel behaviour, call
        `_command_join_channel()` to send command to join channel.

        Args:
                channel_id : str
                        ID of channel to join.
        """
        print("Bot join channel: {}".format(channel_id))
        self._command_join_channel(self.user_id, channel_id)
def leave_channel(self, channel_id: str)

Wrapped leave channel function. Call this to leave channel. If you wanna customize leave channel behaviour, call _command_leave_channel() to send command to leave channel.

Args

channel_id : str ID of channel to leave.

Expand source code
def leave_channel(self, channel_id:str):
        """
        Wrapped leave channel function. Call this to leave channel.
        If you wanna customize leave channel behaviour, call
        `_command_leave_channel()` to send command to leave channel.

        Args:
                channel_id : str
                        ID of channel to leave.
        """
        print("Bot leave channel: {}".format(channel_id))
        self._command_leave_channel(self.user_id, channel_id)
def login(self)

Wrapped login function. Call this to login. If you wanna customize login behaviour, call _command_login() to send command to login.

Expand source code
def login(self):
        """
        Wrapped login function. Call this to login.
        If you wanna customize login behaviour, call
        `_command_login()` to send command to login.
        """
        print("Bot login!")
        self.cached = True
        self._command_login(self.user_id, self.password)
def logout(self)

Wrapped logout function. Call this to logout. If you wanna customize logout behaviour, call _command_logout() to send command to logout.

Expand source code
def logout(self):
        """
        Wrapped logout function. Call this to logout.
        If you wanna customize logout behaviour, call
        `_command_logout()` to send command to logout.
        """
        print("Bot logout!")
        self._command_logout(self.user_id)
def on_close(self, ws, close_status_code, close_msg)

Behaviour at the time websocket connection is closed.

Args

ws : websocket.WebSocketApp Connection object.

Expand source code
def on_close(self, ws, close_status_code, close_msg):
        """
        Behaviour at the time websocket connection is closed.

        Args:
                ws : websocket.WebSocketApp
        Connection object.
        """
        print(f'Bot.close: {ws} closed with status code {close_status_code} and message {close_msg}')
def on_error(self, ws, error)

Behaviour at the time error occur on websocket connection.

Args

ws : websocket.WebSocketApp Connection object.

Expand source code
def on_error(self, ws, error):
        """
        Behaviour at the time error occur on websocket connection.

        Args:
                ws : websocket.WebSocketApp
        Connection object.
        """
        print(f'Bot.error: {error}')
def on_message(self, ws, message)

Behaviour at the time receive message from websocket connection.

Warning

Do not re-write this if you have no idea what will happen!

Args

ws : websocket.WebSocketApp Connection object. message : jstr Raw message json string from ws connection.

Expand source code
def on_message(self, ws, message):
        """
        Behaviour at the time receive message from websocket connection.

        Warning:
                Do not re-write this if you have no idea what will happen!

        Args:
                ws : websocket.WebSocketApp
        Connection object.
                message : jstr
                        Raw message json string from ws connection.
        """
        print(f'Bot.message: {message}')
        self._safe_handle(ws, message)
def on_open(self, ws)

Behaviour at the time websocket connection is created.

Args

ws : websocket.WebSocketApp Connection object.

Expand source code
def on_open(self, ws):
        """
        Behaviour at the time websocket connection is created.

        Args:
                ws : websocket.WebSocketApp
        Connection object.
        """
        if self.cached:
                self.login()
        print('Bot.open!')
def on_receive_command(self, data)

Behaviour when receives commands from server(4xxxx). It's crucial for keeping channel_list up to date. If you want to customize the behaviour, please call super().on_receive_command to keep those properties.

Args

data : dict WS data in the format definde by codes.md

Expand source code
def on_receive_command(self, data):
        """
        Behaviour when receives commands from server(4xxxx).
        It's crucial for keeping channel_list up to date. If
        you want to customize the behaviour, please **call**
        **super().on_receive_command** to keep those properties.

        Args:
                data : dict
                        WS data in the format definde by `codes.md`
        """
        code = data['code']

        if code == self.codes.COMMAND_DOWN_UPDATE_CHANNEL_USER_LIST:
                self._update_user_lists(data)
        else:
                super().on_receive_command(data)
def on_receive_message(self, data)

Behaviour when receives message from server(3xxxx). Override this to customize what to do when receives a message!

Args

data : dict || Message Wrapped Message object of message received. If pre-analyse is turned off, it would be raw WS data in the format definde by codes.md

Expand source code
def on_receive_message(self, data):
        """
        Behaviour when receives message from server(3xxxx).
        Override this to customize what to do when receives
        a message!

        Args:
                data : dict || Message
                        Wrapped Message object of message received.
                        If pre-analyse is turned off, it would be 
                        raw WS data in the format definde by `codes.md`
        """
        print('Bot received message: {}'.format(data))
        super().on_receive_message(data)
def on_receive_status(self, data)

Behaviour when receives status from server(6xxxx).

By default, we would update channel_list and user_list on sereval cases. Therefore, if you want to customize behaviour receive status while keeping these properties up to date, override this function and call super().on_receive_status to keep them.

Args

data : dict WS data in the format definde by codes.md

Expand source code
def on_receive_status(self, data):
        """
        Behaviour when receives status from server(6xxxx).

        By default, we would update channel_list and user_list
        on sereval cases. Therefore, if you want to customize
        behaviour receive status while keeping these properties
        up to date, override this function and **call**
        **super().on_receive_status** to keep them.

        Args:
                data : dict
                        WS data in the format definde by `codes.md`
        """
        code = data['code']

        if code == self.codes.STATUS_INFO_USER_CHANNEL_LIST:
                self._update_channel_list(data)
        elif code == self.codes.STATUS_INFO_CREATE_CHANNEL_SUCCESS or code == self.codes.STATUS_INFO_JOIN_SUCCESS:
                self._append_channel_list(data)
        elif code == self.codes.STATUS_INFO_LEAVE_SUCCESS:
                self._pop_channel_list(data)
        else:
                super().on_receive_status(data)
def register(self, email: str, password: str)

Wrapped register function. Call this to register. If you wanna customize register behaviour, call _command_register() to send command to register.

Args

email : str Email to register an account. password : str Password for that new account.

Expand source code
def register(self, email:str, password:str):
        """
        Wrapped register function. Call this to register.
        If you wanna customize register behaviour, call
        `_command_register()` to send command to register.

        Args:
                email : str
                        Email to register an account.
                password : str
                        Password for that new account.
        """
        print("Bot register")
        self._command_register(email, password)
def reset_password(self, email: str, password: str)

Wrapped reset password function. Call this to reset password. If you wanna customize reset password behaviour, call _command_reset_password() to send command to reset password.

Args

email : str Email of the account to reset pw. password : str New password for that account.

Expand source code
def reset_password(self, email:str, password:str):
        """
        Wrapped reset password function. Call this to reset password.
        If you wanna customize reset password behaviour, call
        `_command_reset_password()` to send command to reset password.

        Args:
                email : str
                        Email of the account to reset pw.
                password : str
                        New password for that account.
        """
        print("Bot reset password")
        self._command_reset_password(email, password)
def run(self)

Behaviour to run bot. By default, it will login and update several properties of bot like channel_list .etc. Then it will hang this process up and reconnect when error occurs.

Warning

Don't re-write this if you have no idea what will happen!

Expand source code
def run(self):
        """
        Behaviour to run bot. 
        By default, it will login and update several properties
        of bot like channel_list .etc. Then it will hang this
        process up and reconnect when error occurs.
        
        Warning:
                Don't re-write this if you have no idea what will happen!
        """
        self.login()
        self.fetch_bot_channels()
        rel.signal(2, rel.abort)
        rel.dispatch()
def send_message(self, message: Message)

Wrapped send message function. Call this to send message. If you wanna customize send message behaviour, call _command_send_message() to send command to send message.

Args

message : Message Wrapped message object contains message body, receivers, target channel and sender information.

Expand source code
def send_message(self, message:Message):
        """
        Wrapped send message function. Call this to send message.
        If you wanna customize send message behaviour, call
        `_command_send_message()` to send command to send message.

        Args:
                message : Message
                        Wrapped message object contains message body, receivers,
                        target channel and sender information.
        """
        temp_msg_id = f"temp_{datetime.datetime.now().timestamp()}_{str(random.randint(0, 100000)).zfill(5)}"
        print('Bot send message: {}\nto: {}\n at channel: {}'.format(message.body, message.to, message.channel))
        self._command_send_message(temp_msg_id=temp_msg_id, message=message)

Inherited members

class JSONSocketUser (path: str = None, reconnect: int = None, pre_analyse: bool = True)

This is basic class of socket client user, which implements fundamental interfaces that you can reach as a user. We wraps the message data into a Message object. For better performance(not indeed), you could set pre_analyse to be False to get raw data of message(dict).

Expand source code
class JSONSocketUser:
    """
    This is basic class of socket client user, which 
    implements fundamental interfaces that you can 
    reach as a user.
    We wraps the message data into a Message object.
    For better performance(not indeed), you could set
    `pre_analyse` to be `False` to get raw data of message(dict).
    """

    def __init__(self, path:str=None, reconnect:int=None, pre_analyse:bool=True) -> None:
        self.path = path if path else 'wss://frog.4fun.chat/social'
        self.reconnect = reconnect if reconnect else 5
        self.codes = codes
        self.pre_analyse = pre_analyse

        self.create_connection(self.path)
        print('created connection with {}'.format(self.path))
    
    def _create_websocket(self, uri:str, on_open=None, on_message=None, on_error=None, on_close=None):
        """
        Create and return a websocket connection object

        Args:
            uri : str
                Location of server this user connects.

            on_open : function : optional
                Callback function execute when websocket connection is created.
                
            on_message : function : optional
                Callback function execute when receive message from websocket connection.
            
            on_error : function : optional
                Callback function execute when error occurs on websocket connection.

            on_close : function : optional
                Callback function execute when websocket connectoin breaks or closes.

        Return:
            Return the websocket object that is created when called.
            
        """
        print('create_websocket!')
        ws = websocket.WebSocketApp(
            uri,
            on_open=on_open or self.on_open,
            on_message=on_message or self.on_message,
            on_error=on_error or self.on_error,
            on_close=on_close or self.on_close
        )
        return ws
    
    def create_connection(self, uri: str, on_open=None, on_message=None, on_error=None, on_close=None):
        """
        Initialize websocket connection between this user object itself and given server

        Args:
            Args:
            uri : str
                Location of server this user connects.

            on_open : function : optional
                Callback function execute when websocket connection is created.
                
            on_message : function : optional
                Callback function execute when receive message from websocket connection.
            
            on_error : function : optional
                Callback function execute when error occurs on websocket connection.

            on_close : function : optional
                Callback function execute when websocket connectoin breaks or closes.
        """
        self.ws = self._create_websocket(uri, on_open, on_message, on_error, on_close)
        self.ws.run_forever(dispatcher=rel, reconnect=self.reconnect)

    def on_message(self, ws, message):
        """
        Default callback when receive message from websocket connectoin.
        Don't override this function if you can't figure out what you would
        face to do so!

        Args:
            ws : websocket.WebSocketApp
                Connection object.
            
            message : str
                Message Object in utf-8 received from websocket connection.

        """
        print(f'JSONSocketUser.message: {message}')
        self._safe_handle(ws, message)

    def on_error(self, ws, error):
        """
        Default callback execute when error occurs on connection.
        As default, it would only print error instead of raise an
        exception.
        Args:
            ws : websocket.WebSocketApp
                Connection object.
            
            error : exception object
                Object contains full information of the error.
            
        """
        print(f'JSONSocketUser.error: {error}')
    
    def on_close(self, ws, close_status_code, close_msg):
        """
        Default callback execute when connection is closed.
        As default, it would only print closure information.

        Args:
            ws : websocket.WebSocketApp
                Connection object

            close_status_code : str
                Status code of closure, more details refer to `https://websocket-client.readthedocs.io/en/latest`
        
            close_msg : str
                Information of closure.
            
        """
        print(f'JSONSocketUser.close: {ws} closed with status code {close_status_code} and message {close_msg}')

    def on_open(self, ws):
        """
        Callback that is called when connection is open.
        As default it will only print message that bot opens.
        Args:
            ws : websocket.WebSocketApp
                Connection object. 
        
        """
        print('JSONSocketUser.open')
        
    @staticmethod
    def _make_data_dict(code:int, **extra_args) -> object:
        """
        Format given params to meet that social server need.

        Args:
            code : int
                Type code of this message, more details refer to `/codes.md`
            **extra_args : key-value pair of params : optional
                Other params to carry with message. all of these will be wrapped
                in `extra` segment of return value.

        Return:
            Wrapped object of all given params.
        """
        return {
            'code': code,
            'extra': extra_args
        }
    
    def _send_data_to_ws(self, ws, code:int, **extra_args):
        """
        Warp and format given params then send with websocket connection.

        Args:
            ws : websocket.WebSocketApp
                Connection object.
            code : int 
                Type code of the message, which decides how it will work
            **extra_args : key-value pair of params : optional
                Other params to carry with message. all of these will be wrapped
                in `extra` segment of return value.

        """
        data_dict = self._make_data_dict(code=code, **extra_args)
        self._safe_send(ws, data_dict)

    def _safe_send(self, ws, data:dict):
        """
        Send wrapped data making sure of data safety. The `safety` emphasizes data format 
        instead of connection or privacy!

        Args:
            ws : websocket.WebSocketApp
                Connection object.
            
            data : dict
                Wrapped data object in format of that in `/code.md`. 
        
        """
        try:
            if isinstance(data, dict):
                data = json.dumps(data)
            else:
                pass

            ws.send(data)
            return True
        except websocket.WebSocketConnectionClosedException as e:
            print('Bot: _safe_send: Connection Closed Exception', e)

        except Exception as e:
            traceback.print_exc()
            print('Bot: self._safe_send: Exception Occurs', e)

    def _safe_handle(self, ws, message:str):
        """
        Load object from message (that in type of jstr) and distribute it
        to matching handler.
        It will time for each message from received to fully processed. 
        Args:
            ws : websocket.WebSocketApp
                Connection object.
            message : json string
                Message received from websocket.

        """
        ct = datetime.datetime.now()
        print('before social bot _safe_handle current time:- ', ct)

        try:
            data = json.loads(message)
            ct = datetime.datetime.now()
            self._handle_data_dict(ws, data)

        except ValueError as e:
            print(f'Bot: _safe_handle received non-json message: {message}')

        except Exception as e:
            print('Bot: Server function error!', e)
            traceback.print_exc()
        
        ct = datetime.datetime.now()
        print('after social bot _safe_handle current time:- ', ct)
    
    def _handle_data_dict(self, ws, data:dict):
        """
        Distribute message to matching handler by type code.
        
        Args:
            ws : websocket.WebSocketApp
                Connection object.
            data : dict
                Message object received from connection.
        
        """
        code = data['code']

        if code >= 40000 and code < 50000:
            self.on_receive_command(data)
        elif code >= 50000 and code < 60000:
            self.on_receive_message(message_from_raw(data) if self.pre_analyse else data)
        elif code >= 60000 and code < 70000:
            self.on_receive_status(data)
        else:
            self.on_receive_other(data)
        print(f'Bot default: _handle_data_dict received {data} at websocket {ws}')

    def _command_register(self, email, password):
        """
        Fundamental API for user to register.

        Args:
            email : str
                Email for registering an account.
            password : str
                Password for registering an account.
            
        """

        if not self.ws:
            raise Exception('error: register before connection created!')
        
        self._send_data_to_ws(self.ws, self.codes.OPERATION_REGISTER, email=email, password=password)
    
    def _command_reset_password(self, email, password):
        """
        Fundamental API for user to reset password of account.

        Args:
            email : str
                Email of account to reset password.
            password : str
                Original password of the account.
        """

        if not self.ws:
            raise Exception('error: reset password before connection created!')
        
        self._send_data_to_ws(self.ws, self.codes.OPERATION_RESET_PASSWORD, email=email, password=password)

    def _command_login(self, user_id, password):
        """
        Fundamental API for user to login.

        Args:
            user_id : str
                User ID of account to login.
            password : str
                Password of the account.
        """

        if not self.ws:
            raise Exception('error: login before connection created!')
        
        self._send_data_to_ws(self.ws, self.codes.OPERATION_LOGIN, user_id=user_id, password=password)
    
    def _command_logout(self, user_id):
        """
        Fundamental API for user to logout.

        Args:
            user_id : str
                User ID of account to logout.
        """

        if not self.ws:
            raise Exception('error: logout before connection created!')
        
        self._send_data_to_ws(self.ws, self.codes.OPERATION_LOGOUT, user_id=user_id)

    def _command_join_channel(self, user_id, channel_id):
        """
        Fundamental API for user to join a existing channel.
        Will receive error code if trynna join a unexisting channel.

        Args:
            user_id : str
                User ID of account that already logged in.
            channel_id : str
                ID of the channel to join.
        """

        if not self.ws:
            raise Exception('error: join channel before connection created!')
        
        self._send_data_to_ws(self.ws, self.codes.OPERATION_JOIN_CHANNEL, user_id=user_id, channel_id=channel_id)

    def _command_leave_channel(self, user_id, channel_id):
        """
        Fundamental API for user to leave a existing channel that contains current account.
        Will receive error code if trynna leave a channel that doesn't contain you.

        Args:
            user_id : str
                User ID of account that already logged in.
            channel_id : str
                ID of the channel to leave.
        """
        if not self.ws:
            raise Exception('error: leave channel before connection created!')
        
        self._send_data_to_ws(self.ws, self.codes.OPERATION_LEAVE_CHANNEL, user_id=user_id, channel_id=channel_id)

    def _command_fetch_offline_message(self, user_id):
        """
        Fundamental API for user to fetch messages that sent to an account 
        when it's not online.

        Args:
            user_id : str
                User ID of a account that already logged in.
        """

        if not self.ws:
            raise Exception('error: fetch offline message before connection created!')
        
        self._send_data_to_ws(self.ws, self.codes.OPERATION_FETCH_OFFLINE_MESSAGE, user_id=user_id)

    def _command_fetch_user_channels(self, user_id):
        """
        Fundamental API for user to fetch the list of channels that contains this account. 

        Args:
            user_id : str
                User ID of a account that already logged in.
        """

        if not self.ws:
            raise Exception('error: get user channels before connection created!')
        
        self._send_data_to_ws(self.ws, self.codes.OPERATION_GET_USER_CHANNEL_LIST, user_id=user_id)

    def _command_create_channel(self, user_id, channel_id):
        """
        Fundamental API for user to create a new channel. 
        If create with a ID already in use will receive error code.

        Args:
            user_id : str
                User ID of a account that already logged in.
            channel_id : str
                ID of channel to create.
        """

        if not self.ws:
            raise Exception('error: create channel before connection created!')
        
        self._send_data_to_ws(self.ws, self.codes.OPERATION_CREATE_CHANNEL, user_id=user_id, channel_id=channel_id)

    def _command_fetch_channel_user_list(self, user_id, channel_id):
        """
        Fundamental API for user to fetch a list of ussers in a certain channel. 
        Will receive error code if trynna fetch a channel inexists.

        Args:
            user_id : str
                User ID of a account that already logged in.
            channel_id : str
                ID of channel to fetch.
        """

        if not self.ws:
            raise Exception('error: fetch channel user list before connection created!')
        
        self._send_data_to_ws(self.ws, self.codes.COMMAND_UP_FETCH_CHANNEL_USER_LIST, user_id=user_id, channel_id=channel_id)

    def _command_fetch_channel_command_list(self, user_id, channel_id):
        """
        Fundamental API for user to fetch a list of features in a certain channel. 
        Will receive error code if trynna fetch a channel inexists.

        Args:
            user_id : str
                User ID of a account that already logged in.
            channel_id : str
                ID of channel to fetch.
        """

        if not self.ws:
            raise Exception('error: fetch channel command list before connection created!')
        
        self._send_data_to_ws(self.ws, self.codes.COMMAND_UP_FETCH_CCS_COMMAND_LIST, user_id=user_id, channel_id=channel_id)

    def _command_fetch_recipient_list(self, user_id, msg_id):
        """
        Fundamental API for user to fetch a list of recipients of a certain message.
        Will receive error code if trynna fetch a message unexist.
        Args:
            user_id : str
                User ID of a account that already logged in.
            msg_id : str
                ID of message to fetch.
        """

        if not self.ws:
            raise Exception('error: fetch recipient list before connection created!')
        
        self._send_data_to_ws(self.ws, self.codes.COMMAND_UP_FETCH_RECIPIENT_LIST, user_id=user_id, msg_id=msg_id)

    def _command_send_message(self, temp_msg_id, message:Message):
        """
        Wrapped API for sending certain message to certain users in certain channel.

        Args:
            temp_msg_id : str
                Not in use, will be removed in the future.
            message : Message
                Message object that consists of information required for sending.
        """

        if not self.ws:
            raise Exception('error: send message before connection created!')
        
        if message.type == MessageType.TEXT:
            self._send_message_text(message.channel, message.sender, message.to, temp_msg_id, message.body, message.origin)
        else:
            #TODO:
            pass

    def _send_message_text(self, channel_id, from_user_id, to_user_ids, temp_msg_id, msg_body, origin):
        """
        Fundamental API to send message in text.
        
        Args: 
            channel_id : str
                ID of channel to send.
            from_user_id : str
                ID of sender.
            to_user_id : list
                List of recipients.
            temp_msg_id : str
                Not in use, will be removed in the future.
            msg_body : str
                Content of message to send.
            origin : str
                Specifier for bot, server, god and goddess.
        """
        print("Send text message: id-{}, body-{}".format(temp_msg_id, msg_body))
        self._send_data_to_ws(self.ws, self.codes.MESSAGE_UP_TEXT, channel_id=channel_id, from_user_id=from_user_id, to_user_ids=to_user_ids, temp_msg_id=temp_msg_id, msg_body=msg_body, origin=origin)
    
    def on_receive_command(self, data):
        """
        Default callback that is called when receive command from connection.

        Args:
            data : dict
                Object of command.
        
        """
        print(f'Default on_receive_command: {data}')

    def on_receive_message(self, data):
        """
        Default callback that is called when receive message from connection.

        Args:
            data : Message
                Object of message.
        
        """
        print(f'Default on_receive_message: {data}')

    def on_receive_status(self, data):
        """
        Default callback that is called when receive status from connection.

        Args:
            data : dict
                Object of status.
        
        """
        print(f'Default on_receive_status: {data}')

    def on_receive_other(self, data):
        """
        Default callback that is called when receive something that is not command,
        message or status from connection.
        It always indicates error occurs on server end. As default, it will raise an 
        exception when called.
        Args:
            data : dict
                Object of received thing.
        
        """
        raise Exception(f"Error happens, received {data}")

    def run(self):
        """
        Default function to startup a bot.
        Basically it will bind an rel to reconnect when stalled too long.
        Override this if you want to make some change before connection is
        created!
        """
        rel.signal(2, rel.abort)
        print('rel created')
        rel.dispatch()
        print('finished running')

Subclasses

Methods

def create_connection(self, uri: str, on_open=None, on_message=None, on_error=None, on_close=None)

Initialize websocket connection between this user object itself and given server

Args

Args: uri : str Location of server this user connects.

on_open : function : optional Callback function execute when websocket connection is created.

on_message : function : optional Callback function execute when receive message from websocket connection.

on_error : function : optional Callback function execute when error occurs on websocket connection.

on_close : function : optional Callback function execute when websocket connectoin breaks or closes.

Expand source code
def create_connection(self, uri: str, on_open=None, on_message=None, on_error=None, on_close=None):
    """
    Initialize websocket connection between this user object itself and given server

    Args:
        Args:
        uri : str
            Location of server this user connects.

        on_open : function : optional
            Callback function execute when websocket connection is created.
            
        on_message : function : optional
            Callback function execute when receive message from websocket connection.
        
        on_error : function : optional
            Callback function execute when error occurs on websocket connection.

        on_close : function : optional
            Callback function execute when websocket connectoin breaks or closes.
    """
    self.ws = self._create_websocket(uri, on_open, on_message, on_error, on_close)
    self.ws.run_forever(dispatcher=rel, reconnect=self.reconnect)
def on_close(self, ws, close_status_code, close_msg)

Default callback execute when connection is closed. As default, it would only print closure information.

Args

ws : websocket.WebSocketApp Connection object

close_status_code : str Status code of closure, more details refer to https://websocket-client.readthedocs.io/en/latest

close_msg : str Information of closure.

Expand source code
def on_close(self, ws, close_status_code, close_msg):
    """
    Default callback execute when connection is closed.
    As default, it would only print closure information.

    Args:
        ws : websocket.WebSocketApp
            Connection object

        close_status_code : str
            Status code of closure, more details refer to `https://websocket-client.readthedocs.io/en/latest`
    
        close_msg : str
            Information of closure.
        
    """
    print(f'JSONSocketUser.close: {ws} closed with status code {close_status_code} and message {close_msg}')
def on_error(self, ws, error)

Default callback execute when error occurs on connection. As default, it would only print error instead of raise an exception.

Args

ws : websocket.WebSocketApp Connection object.

error : exception object Object contains full information of the error.

Expand source code
def on_error(self, ws, error):
    """
    Default callback execute when error occurs on connection.
    As default, it would only print error instead of raise an
    exception.
    Args:
        ws : websocket.WebSocketApp
            Connection object.
        
        error : exception object
            Object contains full information of the error.
        
    """
    print(f'JSONSocketUser.error: {error}')
def on_message(self, ws, message)

Default callback when receive message from websocket connectoin. Don't override this function if you can't figure out what you would face to do so!

Args

ws : websocket.WebSocketApp Connection object.

message : str Message Object in utf-8 received from websocket connection.

Expand source code
def on_message(self, ws, message):
    """
    Default callback when receive message from websocket connectoin.
    Don't override this function if you can't figure out what you would
    face to do so!

    Args:
        ws : websocket.WebSocketApp
            Connection object.
        
        message : str
            Message Object in utf-8 received from websocket connection.

    """
    print(f'JSONSocketUser.message: {message}')
    self._safe_handle(ws, message)
def on_open(self, ws)

Callback that is called when connection is open. As default it will only print message that bot opens.

Args

ws : websocket.WebSocketApp Connection object.

Expand source code
def on_open(self, ws):
    """
    Callback that is called when connection is open.
    As default it will only print message that bot opens.
    Args:
        ws : websocket.WebSocketApp
            Connection object. 
    
    """
    print('JSONSocketUser.open')
def on_receive_command(self, data)

Default callback that is called when receive command from connection.

Args

data : dict Object of command.

Expand source code
def on_receive_command(self, data):
    """
    Default callback that is called when receive command from connection.

    Args:
        data : dict
            Object of command.
    
    """
    print(f'Default on_receive_command: {data}')
def on_receive_message(self, data)

Default callback that is called when receive message from connection.

Args

data : Message Object of message.

Expand source code
def on_receive_message(self, data):
    """
    Default callback that is called when receive message from connection.

    Args:
        data : Message
            Object of message.
    
    """
    print(f'Default on_receive_message: {data}')
def on_receive_other(self, data)

Default callback that is called when receive something that is not command, message or status from connection. It always indicates error occurs on server end. As default, it will raise an exception when called.

Args

data : dict Object of received thing.

Expand source code
def on_receive_other(self, data):
    """
    Default callback that is called when receive something that is not command,
    message or status from connection.
    It always indicates error occurs on server end. As default, it will raise an 
    exception when called.
    Args:
        data : dict
            Object of received thing.
    
    """
    raise Exception(f"Error happens, received {data}")
def on_receive_status(self, data)

Default callback that is called when receive status from connection.

Args

data : dict Object of status.

Expand source code
def on_receive_status(self, data):
    """
    Default callback that is called when receive status from connection.

    Args:
        data : dict
            Object of status.
    
    """
    print(f'Default on_receive_status: {data}')
def run(self)

Default function to startup a bot. Basically it will bind an rel to reconnect when stalled too long. Override this if you want to make some change before connection is created!

Expand source code
def run(self):
    """
    Default function to startup a bot.
    Basically it will bind an rel to reconnect when stalled too long.
    Override this if you want to make some change before connection is
    created!
    """
    rel.signal(2, rel.abort)
    print('rel created')
    rel.dispatch()
    print('finished running')
class Message (type: MessageType, body=None, channel: str = '', to: list = [], sender: str = '', recipient_count: int = 0, id: str = '', origin: str = 'Bot', raw=None)
Expand source code
class Message():
    def __init__(self, type:MessageType, body=None, channel:str='', to:list=[], sender:str='', recipient_count:int=0,
                 id:str='', origin:str='Bot', raw=None) -> None:
        self.type = type
        self.body = body
        self.channel = channel
        self.to = to
        self.sender = sender
        self.recipient_count = recipient_count
        self.id = id
        self.origin = origin
        self.raw = raw
class MessageType (value, names=None, *, module=None, qualname=None, type=None, start=1)

This is enumeration of message types.

Expand source code
class MessageType(Enum):
    """
    This is enumeration of message types.
    """
    TEXT = 1
    IMAGE = 2
    FILE = 3

Ancestors

  • enum.Enum

Class variables

var FILE
var IMAGE
var TEXT