Reworked message handler
This commit is contained in:
parent
ec183ea421
commit
9c30ae0789
8
run.py
8
run.py
|
@ -2,12 +2,20 @@ import logging.config
|
|||
import configparser
|
||||
|
||||
from src.bot import Bot
|
||||
from orator.orm import Model
|
||||
from orator import DatabaseManager
|
||||
|
||||
|
||||
def main():
|
||||
config = configparser.ConfigParser()
|
||||
config.read('./main.cfg', encoding='utf-8')
|
||||
|
||||
logging.basicConfig(level=config['logging']['level'])
|
||||
logging.getLogger("telegram.bot").setLevel(logging.ERROR)
|
||||
logging.getLogger("telegram.ext").setLevel(logging.ERROR)
|
||||
|
||||
Model.set_connection_resolver(DatabaseManager({'db': config['db']}))
|
||||
|
||||
Bot(config).run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
12
src/bot.py
12
src/bot.py
|
@ -1,11 +1,8 @@
|
|||
import logging
|
||||
|
||||
from telegram.ext import Updater
|
||||
from telegram.ext import MessageHandler, Filters
|
||||
from orator.orm import Model
|
||||
from orator import DatabaseManager
|
||||
from src.message import Message
|
||||
from src.command_handler import CommandHandler
|
||||
from src.message_handler import MessageHandler
|
||||
|
||||
|
||||
class Bot:
|
||||
|
@ -14,14 +11,9 @@ class Bot:
|
|||
self.updater = Updater(token=config['bot']['token'])
|
||||
self.dispatcher = self.updater.dispatcher
|
||||
|
||||
Model.set_connection_resolver(DatabaseManager({'db': config['db']}))
|
||||
|
||||
def message_handler(self, bot, update):
|
||||
Message(bot=bot, message=update.message, config=self.config).process()
|
||||
|
||||
def run(self):
|
||||
logging.info("Bot started")
|
||||
message_handler = MessageHandler(Filters.text | Filters.sticker, self.message_handler)
|
||||
message_handler = MessageHandler(self.config)
|
||||
command_handler = CommandHandler()
|
||||
|
||||
self.dispatcher.add_handler(message_handler)
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
import random
|
||||
|
||||
import src.domain.chat as chat
|
||||
from src.utils import deep_get_attr
|
||||
|
||||
|
||||
class Message:
|
||||
def __init__(self, message, config):
|
||||
self.message = message
|
||||
self.config = config
|
||||
self.chat = chat.Chat.get_chat(message)
|
||||
|
||||
if self.has_text():
|
||||
self.text = message.text
|
||||
self.words = self.__get_words()
|
||||
else:
|
||||
self.text = ''
|
||||
|
||||
def has_text(self):
|
||||
"""Returns True if the message has text.
|
||||
"""
|
||||
return self.message.text != ''
|
||||
|
||||
def is_sticker(self):
|
||||
"""Returns True if the message is a sticker.
|
||||
"""
|
||||
return self.message.sticker is not None
|
||||
|
||||
def is_editing(self):
|
||||
"""Returns True if the message was edited.
|
||||
"""
|
||||
return self.message.edit_date is not None
|
||||
|
||||
def has_entities(self):
|
||||
"""Returns True if the message has entities (attachments).
|
||||
"""
|
||||
return self.message.entities is not None
|
||||
|
||||
def has_anchors(self):
|
||||
"""Returns True if the message contains at least one anchor from anchors config.
|
||||
"""
|
||||
anchors = self.config['bot']['anchors'].split(',')
|
||||
return self.has_text() and \
|
||||
(any(x in self.message.text.split(' ') for x in anchors))
|
||||
|
||||
def is_private(self):
|
||||
"""Returns True if the message is private.
|
||||
"""
|
||||
return self.message.chat.type == 'private'
|
||||
|
||||
def is_bot_kicked(self):
|
||||
"""Returns True if the bot was kicked from group.
|
||||
"""
|
||||
user_name = deep_get_attr(self.message, 'left_chat_member.username')
|
||||
|
||||
return user_name == self.config['bot']['name']
|
||||
|
||||
def is_bot_added(self):
|
||||
"""Returns True if the bot was added to group.
|
||||
"""
|
||||
return False
|
||||
|
||||
def is_reply_to_bot(self):
|
||||
"""Returns True if the message is a reply to bot.
|
||||
"""
|
||||
user_name = deep_get_attr(self.message, 'reply_to_message.from_user.username')
|
||||
|
||||
return user_name == self.config['bot']['name']
|
||||
|
||||
def is_random_answer(self):
|
||||
"""Returns True if reply chance for this chat is high enough
|
||||
"""
|
||||
return random.randint(0, 100) < getattr(self.chat, 'random_chance', 5)
|
||||
|
||||
def is_command(self):
|
||||
"""Returns True if the message is a command (`/start`, `/do_stuff`).
|
||||
"""
|
||||
return self.has_text() and self.text[0] == '/'
|
||||
|
||||
def __get_words(self):
|
||||
text = list(self.text)
|
||||
|
||||
for entity in self.message.entities:
|
||||
text[entity.offset:entity.length] = ' ' * entity.length
|
||||
|
||||
return list(filter(None, map(lambda x: x.lower(), ''.join(text).split(' '))))
|
134
src/message.py
134
src/message.py
|
@ -1,134 +0,0 @@
|
|||
import logging
|
||||
import random
|
||||
|
||||
import src.domain.chat as chat
|
||||
import src.domain.pair as pair
|
||||
from src.utils import deep_get_attr
|
||||
|
||||
|
||||
class Message:
|
||||
def __init__(self, bot, message, config):
|
||||
self.bot = bot
|
||||
self.message = message
|
||||
self.config = config
|
||||
self.chat = chat.Chat.get_chat(message)
|
||||
|
||||
if self.has_text():
|
||||
logging.debug("[Chat %s %s bare_text] %s" %
|
||||
(self.chat.chat_type,
|
||||
self.chat.telegram_id,
|
||||
self.message.text))
|
||||
self.text = message.text
|
||||
self.words = self.__get_words()
|
||||
|
||||
def process(self):
|
||||
if self.has_text() and not (self.is_editing() or self.is_command()):
|
||||
return self.__process_message()
|
||||
elif self.is_sticker():
|
||||
return self.__process_sticker()
|
||||
|
||||
def has_text(self):
|
||||
"""Returns True if the message has text.
|
||||
"""
|
||||
return self.message.text != ''
|
||||
|
||||
def is_sticker(self):
|
||||
"""Returns True if the message is a sticker.
|
||||
"""
|
||||
return self.message.sticker is not None
|
||||
|
||||
def is_editing(self):
|
||||
"""Returns True if the message was edited.
|
||||
"""
|
||||
return self.message.edit_date is not None
|
||||
|
||||
def has_entities(self):
|
||||
"""Returns True if the message has entities (attachments).
|
||||
"""
|
||||
return self.message.entities is not None
|
||||
|
||||
def has_anchors(self):
|
||||
"""Returns True if the message contains at least one anchor from anchors config.
|
||||
"""
|
||||
anchors = self.config['bot']['anchors'].split(',')
|
||||
return self.has_text() and \
|
||||
(any(x in self.message.text.split(' ') for x in anchors))
|
||||
|
||||
def is_private(self):
|
||||
"""Returns True if the message is private.
|
||||
"""
|
||||
return self.message.chat.type == 'private'
|
||||
|
||||
def is_reply_to_bot(self):
|
||||
"""Returns True if the message is a reply to bot.
|
||||
"""
|
||||
user_name = deep_get_attr(self.message, 'reply_to_message.from_user.username', None)
|
||||
|
||||
return user_name == self.config['bot']['name']
|
||||
|
||||
def is_random_answer(self):
|
||||
"""Returns True if reply chance for this chat is high enough
|
||||
"""
|
||||
return random.randint(0, 100) < getattr(self.chat, 'random_chance', 5)
|
||||
|
||||
def is_command(self):
|
||||
"""Returns True if the message is a command (`/start`, `/do_stuff`).
|
||||
"""
|
||||
return self.has_text() and self.text[0] == '/'
|
||||
|
||||
def __answer(self, message):
|
||||
logging.debug("[Chat %s %s answer] %s" %
|
||||
(self.chat.chat_type,
|
||||
self.chat.telegram_id,
|
||||
message))
|
||||
|
||||
self.bot.sendMessage(chat_id=self.chat.telegram_id, text=message)
|
||||
|
||||
def __reply(self, message):
|
||||
logging.debug("[Chat %s %s reply] %s" %
|
||||
(self.chat.chat_type,
|
||||
self.chat.telegram_id,
|
||||
message))
|
||||
|
||||
self.bot.sendMessage(chat_id=self.chat.telegram_id,
|
||||
reply_to_message_id=self.message.message_id,
|
||||
text=message)
|
||||
|
||||
def __process_sticker(self):
|
||||
if self.has_anchors() \
|
||||
or self.is_private() \
|
||||
or self.is_reply_to_bot() \
|
||||
or self.is_random_answer():
|
||||
|
||||
logging.debug("[Chat %s %s send_sticker]" %
|
||||
(self.chat.chat_type, self.chat.telegram_id))
|
||||
|
||||
self.bot.sendSticker(chat_id=self.chat.telegram_id,
|
||||
reply_to_message_id=self.message.message_id,
|
||||
sticker="BQADAgADSAIAAkcGQwU-G-9SZUDTWAI")
|
||||
|
||||
def __process_message(self):
|
||||
pair.Pair.learn(self)
|
||||
|
||||
if self.has_anchors() \
|
||||
or self.is_private() \
|
||||
or self.is_reply_to_bot() \
|
||||
or self.is_random_answer():
|
||||
reply = pair.Pair.generate(self)
|
||||
if reply != '':
|
||||
self.__answer(reply)
|
||||
|
||||
def __get_words(self):
|
||||
text = list(self.text)
|
||||
|
||||
for entity in self.message.entities:
|
||||
text[entity.offset:entity.length] = ' ' * entity.length
|
||||
|
||||
result = list(filter(None, map(lambda x: x.lower(), ''.join(text).split(' '))))
|
||||
|
||||
logging.debug("[Chat %s %s get_words] %s" %
|
||||
(self.chat.chat_type,
|
||||
self.chat.telegram_id,
|
||||
' '.join(result)))
|
||||
|
||||
return result
|
|
@ -0,0 +1,98 @@
|
|||
import logging
|
||||
|
||||
from telegram.ext import MessageHandler as ParentHandler, Filters
|
||||
|
||||
from src.domain.message import Message
|
||||
from src.domain.pair import Pair
|
||||
|
||||
|
||||
class MessageHandler(ParentHandler):
|
||||
def __init__(self,
|
||||
config,
|
||||
allow_edited=False,
|
||||
pass_update_queue=False,
|
||||
pass_user_data=False,
|
||||
pass_chat_data=False):
|
||||
super(MessageHandler, self).__init__(
|
||||
Filters.text | Filters.sticker | Filters.status_update,
|
||||
self.handle,
|
||||
pass_update_queue=pass_update_queue,
|
||||
pass_job_queue=True,
|
||||
pass_user_data=pass_user_data,
|
||||
pass_chat_data=pass_chat_data,
|
||||
allow_edited=allow_edited)
|
||||
|
||||
self.config = config
|
||||
|
||||
def handle(self, bot, update, job_queue):
|
||||
print(job_queue)
|
||||
message = Message(message=update.message, config=self.config)
|
||||
|
||||
if message.has_text():
|
||||
logging.debug("[Chat %s %s bare_text] %s" %
|
||||
(message.chat.chat_type,
|
||||
message.chat.telegram_id,
|
||||
message.text))
|
||||
|
||||
if message.has_text() and not (message.is_editing() or message.is_command()):
|
||||
return self.__process_message(bot, message)
|
||||
elif message.is_sticker():
|
||||
return self.__process_sticker(bot, message)
|
||||
elif message.is_bot_added():
|
||||
return self.__process_bot_add(bot, message)
|
||||
elif message.is_bot_kicked():
|
||||
return self.__process_bot_kick(bot, message)
|
||||
|
||||
def __process_message(self, bot, message):
|
||||
Pair.learn(message)
|
||||
|
||||
if message.has_anchors() \
|
||||
or message.is_private() \
|
||||
or message.is_reply_to_bot() \
|
||||
or message.is_random_answer():
|
||||
|
||||
reply = Pair.generate(message)
|
||||
if reply != '':
|
||||
self.__answer(bot, message, reply)
|
||||
|
||||
def __process_sticker(self, bot, message):
|
||||
if message.has_anchors() \
|
||||
or message.is_private() \
|
||||
or message.is_reply_to_bot() \
|
||||
or message.is_random_answer():
|
||||
|
||||
self.__send_sticker(bot, message, "BQADAgADSAIAAkcGQwU-G-9SZUDTWAI")
|
||||
|
||||
def __process_bot_kick(self, bot, message):
|
||||
logging.debug("[Chat %s %s bot_kicked]" %
|
||||
(message.chat.chat_type, message.chat.telegram_id))
|
||||
|
||||
def __process_bot_add(self, bot, message):
|
||||
logging.debug("[Chat %s %s bot_added]" %
|
||||
(message.chat.chat_type, message.chat.telegram_id))
|
||||
|
||||
def __answer(self, bot, message, reply):
|
||||
logging.debug("[Chat %s %s answer] %s" %
|
||||
(message.chat.chat_type,
|
||||
message.chat.telegram_id,
|
||||
reply))
|
||||
|
||||
bot.sendMessage(chat_id=message.chat.telegram_id, text=reply)
|
||||
|
||||
def __reply(self, bot, message, reply):
|
||||
logging.debug("[Chat %s %s reply] %s" %
|
||||
(message.chat.chat_type,
|
||||
message.chat.telegram_id,
|
||||
reply))
|
||||
|
||||
bot.sendMessage(chat_id=message.chat.telegram_id,
|
||||
reply_to_message_id=message.message.message_id,
|
||||
text=reply)
|
||||
|
||||
def __send_sticker(self, bot, message, sticker_id):
|
||||
logging.debug("[Chat %s %s send_sticker]" %
|
||||
(message.chat.chat_type, message.chat.telegram_id))
|
||||
|
||||
bot.sendSticker(chat_id=message.chat.telegram_id,
|
||||
reply_to_message_id=message.message.message_id,
|
||||
sticker=sticker_id)
|
Loading…
Reference in New Issue