From d4200c08b78efa5188a2d129b3b10eb5f946743d Mon Sep 17 00:00:00 2001 From: REDNBLACK Date: Sat, 19 Aug 2017 18:19:21 +0300 Subject: [PATCH] Commands refactoring --- src/domain/abstract_entity.py | 3 +++ src/handler/command_handler.py | 19 +++++++++++++------ src/handler/commands/__init__.py | 6 +++--- src/handler/commands/base.py | 24 ++++++++++++------------ src/handler/commands/boobs.py | 8 ++++---- src/handler/commands/borscht.py | 16 ++++++++-------- src/handler/commands/butts.py | 8 ++++---- src/handler/commands/chance.py | 12 +++++------- src/handler/commands/facepalm.py | 11 ++++++----- src/handler/commands/get_stats.py | 5 ++--- src/handler/commands/help.py | 5 ++--- src/handler/commands/meow.py | 8 +++----- src/handler/commands/moderate.py | 23 +++++++++++------------ src/handler/commands/ping.py | 7 +++---- src/handler/commands/start.py | 5 ++--- src/handler/commands/vzhuh.py | 18 ++++++++---------- src/handler/commands/woof.py | 11 ++++++----- src/handler/commands/xkcd.py | 10 +++++----- 18 files changed, 100 insertions(+), 99 deletions(-) diff --git a/src/domain/abstract_entity.py b/src/domain/abstract_entity.py index 56fe42c..145d278 100644 --- a/src/domain/abstract_entity.py +++ b/src/domain/abstract_entity.py @@ -20,3 +20,6 @@ class AbstractEntity(ABC): """Returns True if the message was edited. """ return self.message.edit_date is not None + + def __str__(self): + return str(self.__dict__) diff --git a/src/handler/command_handler.py b/src/handler/command_handler.py index 7b3ca20..7a40df8 100644 --- a/src/handler/command_handler.py +++ b/src/handler/command_handler.py @@ -1,3 +1,4 @@ +import logging from telegram import Update from telegram.ext import Handler from telegram.ext.dispatcher import run_async @@ -28,11 +29,17 @@ class CommandHandler(Handler): @run_async def handle(self, bot, update): - command = Command(update.message) + data = Command(update.message) + logging.debug(f"Incoming command: {data}") try: - self.commands[command.name](bot, command) - except (IndexError, ValueError): - bot.send_message(chat_id=command.chat_id, - reply_to_message_id=command.message.message_id, - text='Invalid command! Type /help') + command = self.commands[data.name] + if command.bot is None: + command.bot = bot + command.execute(data) + except (KeyError, IndexError, ValueError): + bot.send_message( + chat_id=data.chat_id, + reply_to_message_id=data.message.message_id, + text='Invalid command! Type /help' + ) diff --git a/src/handler/commands/__init__.py b/src/handler/commands/__init__.py index ec977e4..b143003 100644 --- a/src/handler/commands/__init__.py +++ b/src/handler/commands/__init__.py @@ -19,9 +19,9 @@ commands = {} for clazz in Base.__subclasses__(): command_name = getattr(clazz, 'name') command_aliases = getattr(clazz, 'aliases') - execute_method = getattr(clazz, 'execute') + instance = clazz() if command_name is not None: - commands[command_name] = execute_method + commands[command_name] = instance for command_alias in command_aliases: - commands[command_alias] = execute_method + commands[command_alias] = instance diff --git a/src/handler/commands/base.py b/src/handler/commands/base.py index 4b27cf6..9d2e35c 100644 --- a/src/handler/commands/base.py +++ b/src/handler/commands/base.py @@ -5,20 +5,20 @@ from abc import ABC, abstractmethod class Base(ABC): name = None aliases = [] + bot = None - @staticmethod @abstractmethod - def execute(bot, command): + def execute(self, command): pass - @staticmethod - def reply(bot, command, message): - logging.debug("[Chat %s %s command] %s: %s" % - (command.chat_type, - command.chat_id, - command.name, - message)) + def reply(self, command, text): + logging.debug("Command %s: %s" % (str(command), text)) - bot.send_message(chat_id=command.chat_id, - reply_to_message_id=command.message.message_id, - text=message) + self.bot.send_message( + chat_id=command.chat_id, + reply_to_message_id=command.message.message_id, + text=text + ) + + def send_photo(self, command, photo): + self.bot.send_photo(chat_id=command.chat_id, photo=photo) diff --git a/src/handler/commands/boobs.py b/src/handler/commands/boobs.py index 6cb5643..a19429f 100644 --- a/src/handler/commands/boobs.py +++ b/src/handler/commands/boobs.py @@ -1,16 +1,16 @@ from .base import Base import json from urllib.request import urlopen +from src.config import encoding class Boobs(Base): name = 'boobs' aliases = ['80085', '(.)(.)'] - @staticmethod - def execute(bot, command): + def execute(self, command): response = urlopen('http://api.oboobs.ru/noise/1') - data = json.loads(response.read().decode('utf-8')) + data = json.loads(response.read().decode(encoding)) url = 'http://media.oboobs.ru/' + data[0]['preview'] - bot.send_photo(chat_id=command.chat_id, photo=url) + self.send_photo(command, photo=url) diff --git a/src/handler/commands/borscht.py b/src/handler/commands/borscht.py index 515dcba..3a3598e 100644 --- a/src/handler/commands/borscht.py +++ b/src/handler/commands/borscht.py @@ -1,6 +1,7 @@ from .base import Base import json from src.utils import random_element +from src.config import encoding from urllib.request import urlopen @@ -8,16 +9,15 @@ class Borscht(Base): name = 'borscht' images = None - @staticmethod - def execute(bot, command): - if Borscht.images is None: - Borscht.images = Borscht.__preload() + def __init__(self): + super().__init__() + self.images = self.__preload() - bot.send_photo(chat_id=command.chat_id, photo=random_element(Borscht.images)) + def execute(self, command): + self.send_photo(command, photo=random_element(Borscht.images)) - @staticmethod - def __preload(): + def __preload(self): response = urlopen('https://api.cognitive.microsoft.com/bing/v5.0/images/search?q=%D0%B1%D0%BE%D1%80%D1%89&mkt=en-us&safe-search=strict&image-type=photo&subscription-key=dd95294bc02748a1ab5152d36fdbbdac') - data = json.loads(response.read().decode('utf-8')) + data = json.loads(response.read().decode(encoding)) return list(map(lambda e: e['contentUrl'], data['value'])) diff --git a/src/handler/commands/butts.py b/src/handler/commands/butts.py index b7d2d52..dd7fd42 100644 --- a/src/handler/commands/butts.py +++ b/src/handler/commands/butts.py @@ -1,5 +1,6 @@ from .base import Base import json +from src.config import encoding from urllib.request import urlopen @@ -7,10 +8,9 @@ class Butts(Base): name = 'butts' aliases = ['(_._)', '(_*_)', '(Y)'] - @staticmethod - def execute(bot, command): + def execute(self, command): response = urlopen('http://api.obutts.ru/noise/1') - data = json.loads(response.read().decode('utf-8')) + data = json.loads(response.read().decode(encoding)) url = 'http://media.obutts.ru/' + data[0]['preview'] - bot.send_photo(chat_id=command.chat_id, photo=url) + self.send_photo(command, photo=url) diff --git a/src/handler/commands/chance.py b/src/handler/commands/chance.py index dc352d3..759a0ae 100644 --- a/src/handler/commands/chance.py +++ b/src/handler/commands/chance.py @@ -5,20 +5,18 @@ from src.config import chance_repository class Chance(Base): name = 'chance' - @staticmethod - def execute(bot, command): + def execute(self, command): if command.is_private(): - return Chance.reply(bot, command, 'Command disabled for private chats') + return self.reply(command, 'Command disabled for private chats') try: new_chance = int(command.args[0]) if new_chance < 1 or new_chance > 50: - return Chance.reply(bot, command, 'Usage: /chance 1-50.') + return self.reply(command, 'Usage: /chance 1-50.') old_chance = chance_repository.set(chat_id=command.chat_id, new_chance=new_chance) - Chance.reply(bot, command, 'Change chance from {} to {}'.format(old_chance, new_chance)) + self.reply(command, 'Change chance from {} to {}'.format(old_chance, new_chance)) except (IndexError, ValueError): - Chance.reply(bot, command, 'Current chance: {}' - .format(chance_repository.get(command.chat_id))) + self.reply(command, 'Current chance: {}'.format(chance_repository.get(command.chat_id))) diff --git a/src/handler/commands/facepalm.py b/src/handler/commands/facepalm.py index 1bbca00..3b9ec00 100644 --- a/src/handler/commands/facepalm.py +++ b/src/handler/commands/facepalm.py @@ -5,12 +5,13 @@ from urllib.request import urlopen, Request class Facepalm(Base): name = 'facepalm' aliases = ['o'] + path = 'storage/facepalm.jpg' + headers = {'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36"} - @staticmethod - def execute(bot, command): - req = Request("http://loremflickr.com/500/410/facepalm", headers={'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36"}) - output = open("storage/facepalm.jpg", "wb") + def execute(self, command): + req = Request("http://loremflickr.com/500/410/facepalm", headers=self.headers) + output = open(self.path, "wb") output.write(urlopen(req).read()) output.close() - bot.send_photo(chat_id=command.chat_id, photo=open('storage/facepalm.jpg', 'rb')) + self.send_photo(command, photo=open(self.path, 'rb')) diff --git a/src/handler/commands/get_stats.py b/src/handler/commands/get_stats.py index d68a3fe..4ed789b 100644 --- a/src/handler/commands/get_stats.py +++ b/src/handler/commands/get_stats.py @@ -5,7 +5,6 @@ from src.config import trigram_repository class GetStats(Base): name = 'get_stats' - @staticmethod - def execute(bot, command): + def execute(self, command): pairs_count = trigram_repository.count(command.chat_id) - GetStats.reply(bot, command, 'Pairs: {}'.format(pairs_count)) + self.reply(command, 'Pairs: {}'.format(pairs_count)) diff --git a/src/handler/commands/help.py b/src/handler/commands/help.py index af43c7e..dd39f49 100644 --- a/src/handler/commands/help.py +++ b/src/handler/commands/help.py @@ -6,6 +6,5 @@ class Help(Base): name = 'help' text = read_to_string('resources/info/help.txt') - @staticmethod - def execute(bot, command): - Help.reply(bot, command, Help.text) + def execute(self, command): + self.reply(command, self.text) diff --git a/src/handler/commands/meow.py b/src/handler/commands/meow.py index f1649f5..84f7dd4 100644 --- a/src/handler/commands/meow.py +++ b/src/handler/commands/meow.py @@ -6,10 +6,8 @@ class Meow(Base): name = 'meow' aliases = [':3', '=3'] - @staticmethod - def execute(bot, command): + def execute(self, command): opener = build_opener(HTTPRedirectHandler) - request = opener.open('http://thecatapi.com/api/images/get?format=src') - url = request.url + req = opener.open('http://thecatapi.com/api/images/get?format=src') - bot.send_photo(chat_id=command.chat_id, photo=url) + self.send_photo(command, photo=req.url) diff --git a/src/handler/commands/moderate.py b/src/handler/commands/moderate.py index 6929080..dfd198d 100644 --- a/src/handler/commands/moderate.py +++ b/src/handler/commands/moderate.py @@ -4,13 +4,12 @@ from src.config import config, trigram_repository class Moderate(Base): aliases = ['mod_f', 'mod_d'] - gods = [int(id) for id in config.getlist('bot', 'god_mode')] + gods = config.getlist('bot', 'god_mode', type=int) - @staticmethod - def execute(bot, command): + def execute(self, command): try: - if not command.is_private() and not Moderate.is_admin(bot, command): - return Moderate.reply(bot, command, 'You don\'t have admin privileges!') + if not command.is_private() and not self.__is_admin(command): + return self.reply(command, 'You don\'t have admin privileges!') if len(command.args) == 0: raise IndexError @@ -18,20 +17,20 @@ class Moderate(Base): if command.name == 'mod_f': words = trigram_repository.find_word(command.chat_id, command.args[0].strip()) reply = '\n'.join(words) - if reply == '': + if reply.strip() == '': reply = 'Nothing found' - Moderate.reply(bot, command, reply) + self.reply(command, reply) elif command.name == 'mod_d': trigram_repository.remove_word(command.chat_id, command.args[0].strip()) except (IndexError, ValueError): - Moderate.reply(bot, command, """Usage: + self.reply(command, """Usage: /mod_f for search /mod_d for deletion""") - @staticmethod - def is_admin(bot, entity): + def __is_admin(self, entity): user_id = entity.message.from_user.id - admin_ids = list(map(lambda m: m.user.id, bot.get_chat_administrators(entity.chat_id))) + admin_ids = list(map(lambda m: m.user.id, self.bot.get_chat_administrators(entity.chat_id))) - return user_id in admin_ids or user_id in Moderate.gods + return user_id in admin_ids \ + or user_id in self.gods diff --git a/src/handler/commands/ping.py b/src/handler/commands/ping.py index ad3644a..57248c1 100644 --- a/src/handler/commands/ping.py +++ b/src/handler/commands/ping.py @@ -11,7 +11,6 @@ class Ping(Base): 'reply', 'pingback' ] - - @staticmethod - def execute(bot, command): - Ping.reply(bot, command, random_element(Ping.answers)) + + def execute(self, command): + self.reply(command, random_element(Ping.answers)) diff --git a/src/handler/commands/start.py b/src/handler/commands/start.py index d8f4d85..7cf20d4 100644 --- a/src/handler/commands/start.py +++ b/src/handler/commands/start.py @@ -4,6 +4,5 @@ from .base import Base class Start(Base): name = 'start' - @staticmethod - def execute(bot, command): - Start.reply(bot, command, 'Hi! :3') + def execute(self, command): + self.reply(command, 'Hi! :3') diff --git a/src/handler/commands/vzhuh.py b/src/handler/commands/vzhuh.py index 5128842..9d94dd5 100644 --- a/src/handler/commands/vzhuh.py +++ b/src/handler/commands/vzhuh.py @@ -4,16 +4,15 @@ from PIL import Image, ImageFont, ImageDraw class Vzhuh(Base): name = 'vzhuh' + path = 'storage/vzhuh.png' - @staticmethod - def execute(bot, command): - text = Vzhuh.format_text('вжух ' + ' '.join(command.args)) - Vzhuh.create_image(text) + def execute(self, command): + text = self.__format_text('вжух ' + ' '.join(command.args)) + self.__generate_image(text) - bot.send_photo(chat_id=command.chat_id, photo=open('storage/vzhuh.png', 'rb')) + self.send_photo(command, photo=open(self.path, 'rb')) - @staticmethod - def format_text(text): + def __format_text(self, text): result = [] current_part = '' if len(text) > 8: @@ -31,10 +30,9 @@ class Vzhuh(Base): return '\n'.join(result) - @staticmethod - def create_image(text): + def __generate_image(self, text): img = Image.open("resources/vzhuh/sample.png") draw = ImageDraw.Draw(img) font = ImageFont.truetype('resources/vzhuh/Impact.ttf', 44, index=0) draw.text((222, 280), text, (0, 0, 0), font=font) - img.save('storage/vzhuh.png') + img.save(self.path) diff --git a/src/handler/commands/woof.py b/src/handler/commands/woof.py index 47b0a46..37f6436 100644 --- a/src/handler/commands/woof.py +++ b/src/handler/commands/woof.py @@ -4,12 +4,13 @@ from urllib.request import urlopen, Request class Woof(Base): name = 'woof' + path = 'storage/woof.jpg' + headers = {'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36"} - @staticmethod - def execute(bot, command): - req = Request("http://loremflickr.com/500/410/dog", headers={'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36"}) - output = open("storage/woof.jpg", "wb") + def execute(self, command): + req = Request("http://loremflickr.com/500/410/dog", headers=self.headers) + output = open(self.path, "wb") output.write(urlopen(req).read()) output.close() - bot.send_photo(chat_id=command.chat_id, photo=open('storage/woof.jpg', 'rb')) + self.send_photo(command, photo=open(self.path, 'rb')) diff --git a/src/handler/commands/xkcd.py b/src/handler/commands/xkcd.py index fb079d0..33b1715 100644 --- a/src/handler/commands/xkcd.py +++ b/src/handler/commands/xkcd.py @@ -7,10 +7,10 @@ from urllib.request import urlopen class XKCD(Base): name = 'xkcd' - @staticmethod - def execute(bot, command): + def execute(self, command): last_id = json.loads(urlopen("http://xkcd.com/info.0.json").read().decode('utf-8'))['num'] - id = random.randint(1, last_id) - url = json.loads(urlopen('http://xkcd.com/' + str(id) + '/info.0.json').read().decode('utf-8'))['img'] + random_id = random.randint(1, last_id) + req = urlopen('http://xkcd.com/%d/info.0.json' % random_id) + data = json.loads(req.read().decode('utf-8')) - bot.send_photo(chat_id=command.chat_id, photo=url) + self.send_photo(command, photo=data['img'])