示例#1
0
class Fibot(object):
    """ This object contains information and methods to manage the bot, and interact with
		its users.

	Attributes:
		name(:obj:`str`): Unique identifier for the bot
		bot_token(:obj:`str`): Token to access the bot
		chats(:class:`Fibot.Chat`): Object that represents the chats
		oauth(:class:`Fibot.api.Oauth`): Object that does the oauth communication necessary
		nlg(:class:`Fibot.NLP.nlg.NLG_unit`): Object that interacts with non FIB messages
		~ query_answer(:class:`Fibot.NLP.nlg.Query_answer_unit`): Object that responds to FIB-related queries
		translator(:class:`Fibot.NLP.language.Translator`): Object that eases the translation of the messages
		messages(:obj:`dict`): Object that contains the Fibot configuration messages
		state_machine(:obj:`dict`): Object that simplifies the state machine management
	"""
    def __init__(self, name='Fibot'):
        self.name = name
        self.bot_token = getenv('FibotTOKEN')
        self.chats = Chats()
        self.oauth = Oauth()
        self.nlg = NLG_unit()
        self.qa = Query_answer_unit()
        self.translator = Translator()
        self.messages = {}
        self.state_machine = {
            'MessageHandler': '0',
            'Authorise': '1',
            'Wait_authorisation': '2',
            'Erase_user': '******',
            'Push_notification': '4',
        }

    """
		Loads the following components:
			chats: Loads the chats information from persistence
			nlu: Loads the trained model
			nlg: Loads the trained model
	"""

    def load_components(self):
        self.chats.load()
        print("Chats loaded")
        self.nlg.load()
        print("NLG model loaded")
        self.qa.load(train=False)
        print("Query answering model loaded")
        with open('./Data/messages.json', 'r') as fp:
            self.messages = json.load(fp)
        print("Preset messages loaded")

    """
		Sends an action to a chat (using ChatAction helper)
	"""

    def send_chat_action(self, chat_id, action=ChatAction.TYPING):
        params = {'chat_id': chat_id, 'action': action}
        base_url = 'https://api.telegram.org/bot{}/sendChatAction'.format(
            self.bot_token)
        response = requests.get(base_url, params=params)

    """
		Sends a message to the chat with chat_id with content text
	"""

    def send_message(self, chat_id, message, typing=False, reply_to=None):
        ini = time()
        if isinstance(message, list):
            for item in message:
                self.send_message(chat_id, item, typing, reply_to)
        else:
            if typing: self.send_chat_action(chat_id)
            print("chat action sent in {}".format((time() - ini)))
            user_language = self.chats.get_chat(chat_id)['language']
            if user_language != 'English':
                urls = re.findall(
                    'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+',
                    message)
                if urls: message = message.replace(urls[0], "{}")
                message = self.translator.translate(message, to=user_language)
                if urls: message = message.format(urls[0])

            params = {'chat_id': chat_id, 'text': message}
            if reply_to: params['reply_to_message_id'] = reply_to
            base_url = 'https://api.telegram.org/bot{}/sendMessage'.format(
                self.bot_token)
            response = requests.get(base_url, params=params)
            print("message sent in {}".format((time() - ini)))

    """
		Parameters:
			chat_id (:obj:`str`): chat_id of the user to send the message to
			preset (:obj:`str`): the preset of the message to send
			param (:obj:`str` or None): the parameter of the messages

		This function sends a preset message to the user with user id.
		See /Data/messages.json to see the preset messages.
	"""

    def send_preset_message(self, chat_id, preset, param=None):
        print("sending {}".format(preset))
        if param:
            message = self.messages[preset].format(param)
        else:
            message = self.messages[preset]
        self.send_message(chat_id, message, typing=True)

    """
		Parameters:
			chat_id (:obj:`str`): chat_id of the user that sent the messages
			message (:obj:`str`): text the user sent

		This function receives a message from a user and decides which mechanism is responsible
		for responding the message.
	"""

    def process_income_message(self,
                               chat_id,
                               message,
                               message_id=None,
                               debug=False):
        print("Processing income message...")
        user_language = self.chats.get_chat(chat_id)['language']
        if user_language != 'English':
            message = self.translator.translate(message,
                                                to='English',
                                                _from=user_language)
        ini = time()
        response = self.qa.get_response(message, sender_id=chat_id)
        print("Getting response time is {}".format((time() - ini)))
        print(response)
        if message_id:
            self.send_message(chat_id,
                              response,
                              typing=True,
                              reply_to=message_id)
        else:
            self.send_message(chat_id, response, typing=True)
示例#2
0
from Fibot.chats import Chats
from Fibot.api.api_raco import API_raco
from Fibot.Data.data_types.exam import Exam_schedule
from Fibot.Data.data_types.practical_work import Practical_schedule
from pprint import pprint

c = Chats()
c.load()
a = API_raco()
a_t = c.get_chat('349611162')['access_token']
user_lang = c.get_chat('349611162')['language']
exams = list(a.get_exams_user(a_t))
e_e = Exam_schedule(exams, user_lang)

pprint(list(e_e.get_closest_exams(range=50)))

pracs = list(a.get_practiques(a_t))
p_e = Practical_schedule(pracs, user_lang)

pprint(list(p_e.get_closest_pracs(range=50)))
示例#3
0
class Refresh_token_thread(object):

    """This class enables multithreading capabilities by using an extra thread to scan looking for
    chats with expired tokens to refresh.

        Attributes:
            oauth(:class:`Fibot.api.oauth.Oauth`): Object that manages the oauth processes.
            chats(:class:`Fibot.chats.Chats`): Chat records of users.
            delay(:obj:`int`): Amount of seconds between scans.
            queue(:obj:`list`): Lists of chat_id's of the people with tokens to be refreshed.
            thread(:class:`threading.Timer`): Thread that does the scanning.
            polling(:obj:`bool`): Object that indicates if polling has to be done.
    """
    def __init__(self, delay, thread_logging = True):
        self.oauth = Oauth()
        self.chats = Chats()
        self.delay = delay
        self.thread_logging = thread_logging
        self.queue = []
        self.polling = True
        self.thread = None

    """
        Updates the internal representation of the chats with the last dumped values.
    """
    def update_chats(self):
        self.chats.load()
        self.queue = self.chats.get_expired_chats()

    """
        This function defines the new timer and starts it (effectively allows the scanning)
    """
    def run(self, initial_offset = 0):
        if self.polling:
            self.thread = Timer(self.delay - initial_offset, self.poll)
            self.thread.start()

    """
        Does a scan over all users with expired tokens, and then returns to the activation function
    """
    def poll(self):
        if self.thread_logging: print("\n")
        if self.thread_logging: log("R_Thread: Refrescando tokens\n")
        self.update_chats()
        for chat in self.queue:
            if self.thread_logging: log("R_Thread: Refrescando token de {}\n".format(self.chats.get_chat(chat)['name']))
            refresh_token = self.chats.get_chat(chat)['refresh_token']
            callback = self.oauth.refresh_token(refresh_token)
            if callback: self.chats.update_chat(chat, data = callback, full_data = False)
            if callback and self.thread_logging: log("R_Thread: Token refrescado correctamente!\n")
        self.queue = []
        self.run()

    """
        Allows polling
    """
    def stop_polling(self):
        self.polling = False

    """
        Forbids polling
    """
    def start_polling(self):
        self.polling = True
        self.run()
示例#4
0
class Fibot(object):
    """ This object contains information and methods to manage the bot, and interact with
		its users.

	Attributes:
		local (:obj:`bool`): Indicates if it runs from Telegram or Locally
		name (:obj:`str`): Unique identifier for the bot
		bot_token (:obj:`str`): Token to access the bot
		chats (:class:`Fibot.Chat`): Object that represents the chats
		oauth (:class:`Fibot.api.Oauth`): Object that does the oauth communication necessary
		qa (:class:`Fibot.NLP.nlg.Query_answer_unit`): Object that responds to FIB-related queries
		message_handler (:class:`Fibot.message_handler.Message_handler`): Object that handles messages
		delay (:obj:`int`): Cantidad de segundos entre escaneos en los threads
		notification_thread (:class:`Fibot.multithreading.threads.Notification_thread`): Object that enables a thread to scan for notifications.
		refresh_token_thread(:class:`Fibot.multithreading.threads.Refresh_token_thread`): Object that enables a thread to scan for tokens to refresh.
		messages (:obj:`dict`): Object that contains the Fibot configuration messages
		state_machine (:obj:`dict`): Object that simplifies the state machine management
	"""
    def __init__(self, name='Fibot', local=False, debug=True):
        self.local = local
        self.debug = debug
        self.name = name
        self.bot_token = getenv('FibotTOKEN')
        self.chats = Chats()
        self.oauth = Oauth()
        self.qa = Query_answer_unit()
        self.message_handler = None
        self.delay = 60
        self.refresh_token_thread = None
        self.notification_thread = None
        self.messages = {}
        self.state_machine = {'MessageHandler': '0', 'Wait_authorisation': '1'}

    def log(self, text):
        print(colored("LOG: {}".format(text), 'cyan'))

    """
		Loads the following components:
			chats: Loads the chats information from persistence
			message_handler: Enables it to send messages to users
			notification_thread: Starts its activation and defines the polling interval
			refresh_token_thread: Starts its activation and defines the polling interval (and the offset)
			nlu: Loads the trained models
			qa: Loads the trained models
			messages: Loads the preset messages to memory
	"""

    def load_components(self, thread_logging=True):
        self.chats.load()
        self.log("Base de datos de usuarios cargados")
        if self.local: self.message_handler = Local_Message_handler(self.chats)
        else: self.message_handler = Message_handler(self.chats)

        self.refresh_token_thread = Refresh_token_thread(
            self.delay, thread_logging=thread_logging)
        self.refresh_token_thread.run(initial_offset=30)

        self.notification_thread = Notification_thread(
            self.message_handler, self.delay, thread_logging=thread_logging)
        self.notification_thread.run()
        self.log("Threads creados")

        self.qa.load()
        with open('./Data/messages.json', 'r') as fp:
            self.messages = json.load(fp)
        self.log("Mensajes predefinidos cargados")
        return

    """
		Parameters:
			chat_id (:obj:`int`): chat id of the user to send the message to
			action (:obj:`str`): defines the action to send the user (default is typing)

		This function sends an action to the chat with chat_id (using ChatAction helper)
	"""

    def send_chat_action(self, chat_id, action=ChatAction.TYPING):
        self.message_handler.send_chat_action(chat_id, message, typing,
                                              reply_to)

    """
		Parameters:
			chat_id (:obj:`int`): chat id of the user to send the message to
			message (:obj:`str`): content of the message to be sent
			typing (:obj:`bool`): value that defines whether to send typing action or not
			reply_to (:obj:`int` or None): If defined, it is the message_id of the message
				that will be replied to, else no message will be replied.
			parse_mode (:obj:`str`): The parse mode to use (normally Markdown or None)

		This function sends a message to the chat with chat_id with content text,
		and depending on the rest of the parameters it might do extra functionality.
	"""

    def send_message(self,
                     chat_id,
                     message,
                     typing=False,
                     reply_to=None,
                     parse_mode='Markdown'):
        self.message_handler.send_message(chat_id, message, typing, reply_to,
                                          parse_mode)

    """
		Parameters:
			chat_id (:obj:`str`): chat_id of the user to send the message to
			preset (:obj:`str`): the preset of the message to send
			param (:obj:`str` or None): the parameter of the messages

		This function sends a preset message to the user with user id.
		See /Data/messages.json to see the preset messages.
	"""

    def send_preset_message(self, chat_id, preset, param=None):
        user_lang = self.chats.get_chat(chat_id)['language']
        if param:
            message = self.messages[user_lang][preset].format(param)
        else:
            message = self.messages[user_lang][preset]
        if 'set_lang' in message:
            self.send_message(chat_id, message, typing=True, parse_mode=None)
        else:
            self.send_message(chat_id, message, typing=True)

    """
		Parameters:
			chat_id (:obj:`str`): chat_id of the user that sent the messages
			message (:obj:`str`): text the user sent
			message_id (:obj:`int`): message_id of the message to reply to


		This function receives a message from a user and decides which mechanism is responsible
		for responding the message.
	"""

    def process_income_message(self, chat_id, message, message_id=None):
        user_language = self.chats.get_chat(chat_id)['language']
        now = time()
        response = self.qa.get_response(message,
                                        sender_id=chat_id,
                                        language=user_language,
                                        debug=self.debug)
        response = [i['text'] for i in response]
        self.send_message(chat_id,
                          response,
                          typing=True,
                          reply_to=message_id,
                          parse_mode=None)