Exemplo n.º 1
0
class FunServer(BaseServer):
    name = 'FunServer'
    guid = 'D24972621DAF4E35AA6BE68AB55BB46F'
    command_list = [
        Command(
            name='насмеши',
            uri='/execute',
            description='Случайная цитата башорга. Например: Бот, насмеши',
            priority=10,
        ),
    ]

    # Путь к файлу сервера
    file_name = os.path.abspath(__file__)

    def _execute_body(self, rq: dict,
                      **params: dict) -> typing.Union[dict, str]:
        # TODO:
        # command = rq['command']
        # command_name = rq['command_name']

        from commands.command__fun.fun import get_random_quote
        result = get_random_quote()

        return result
Exemplo n.º 2
0
class GetImageInfoServer(BaseServer):
    name = 'GetImageInfoServer'
    guid = 'F89FA403EA244F489F0AC630BEE4CA56'
    command_list = [
        Command(
            name='получить информацию о картинке',
            uri='/execute',
            description=
            'Команда получения информации о картинке. Например: Бот, получить информацию о картинке.',
            priority=9,
        ),
    ]

    # Путь к файлу сервера
    file_name = os.path.abspath(__file__)

    def _execute_body(self, rq: dict,
                      **params: str) -> typing.Union[dict, str]:
        command = rq['command']
        command_name = rq['command_name']
        attachment = rq['attachment']

        if not attachment:
            raise Exception(
                "Неправильная команда 'получить информацию о картинке': нужно передавать картинку."
            )

        img_file_io = create_io(attachment)

        info = get_image_info(img_file_io, pretty_json_str=True)
        return info
Exemplo n.º 3
0
class WeatherServer(BaseServer):
    name = 'WeatherServer'
    guid = 'EF3D2E05CBAA49F2867C742EA7D856D0'
    command_list = [
        Command(
            name='погода',
            uri='/execute',
            description=
            'Погода в указанном населенном пункте. Например: Бот, погода магнитогорск',
            priority=10,
        ),
    ]

    # Путь к файлу сервера
    file_name = os.path.abspath(__file__)

    def _execute_body(self, rq: dict,
                      **params: dict) -> typing.Union[dict, str]:
        command = rq['command']
        command_name = rq['command_name']

        if not command:
            raise Exception(
                "Неправильная команда 'погода': не указан населенный пункт")

        from commands.command__weather_in_city.weather_in_city import get_weather
        result = get_weather(command)

        return result
Exemplo n.º 4
0
class ExchangeRateServer(BaseServer):
    name = 'ExchangeRateServer'
    guid = '21535ECEF2104BFD8F1CD1DC715309AA'
    command_list = [
        Command(
            name='курс валют',
            uri='/execute',
            description=
            'Показать текущий курс евро и доллара. Например: Бот, курс валют',
            priority=9,
        ),
    ]

    # Путь к файлу сервера
    file_name = os.path.abspath(__file__)

    def __init__(self):
        super().__init__()

        # Поле для сохранения результата
        self.last_result = None

        # Поле для сохранения времени последнего запроса
        self.last_request_time = None

        # Поле для сохранения времени, когда кэш испортится
        self.cache_update_time = None

    def _execute_body(self, rq: dict,
                      **params: dict) -> typing.Union[dict, str]:
        # command = rq['command']
        # command_name = rq['command_name']

        delta = timedelta(hours=1)

        if self.last_request_time is None or self.cache_update_time < datetime.now(
        ):
            rate_list = currency.exchange_rate(['EUR', 'USD'])
            self.last_result = ', '.join(rate_list)
            self.last_request_time = datetime.now()
            self.cache_update_time = self.last_request_time + delta

            print('Обновляю кэшированный курс валют: "{}", кэш испортится '
                  'в {}.'.format(self.last_result, self.cache_update_time))

        else:
            print('Возвращаю кэш за {}, обновление кэша будет через {} в {}'.
                  format(self.last_request_time,
                         self.cache_update_time - datetime.now(),
                         self.cache_update_time))

        return self.last_result
Exemplo n.º 5
0
class QRCodeServer(BaseServer):
    name = 'QRCodeServer'
    guid = '60BC4D9FB8BB461E996E0F22C37F7498'
    command_list = [
        Command(
            name='qrcode',
            uri='/execute',
            description=
            'Команда для генерации QR Code. Например: Бот, qrcode Привет мир!. '
            'Или: Бот, qrcode https://github.com/gil9red',
            priority=9,
        ),
    ]

    # Путь к файлу сервера
    file_name = os.path.abspath(__file__)

    def _execute_body(self, rq: dict,
                      **params: dict) -> typing.Union[dict, str]:
        command = rq['command']
        command_name = rq['command_name']

        if not command:
            raise Exception(
                "Неправильная команда 'qrcode': нужно указать текст, например: Привет мир!"
            )

        # https://github.com/gil9red/SimplePyScripts/blob/d3ee62b48dd1277aa68244f7ec2966183517b931/generate_qrcode/main.py
        import qrcode
        img = qrcode.make(command)

        extension = 'png'

        # In memory
        import io
        io_data = io.BytesIO()
        img.save(io_data, extension)

        attachment = common.FileAttachment(content=io_data.getvalue(),
                                           extension=extension)

        return self.generate_response(
            attachment=attachment, attachment_type=common.AttachmentType.IMAGE)
Exemplo n.º 6
0
class GifServer(BaseServer):
    name = 'GifServer'
    guid = '0CBBE285D35D4BCCB28EF3554CD3D4DC'
    command_list = [
        Command(
            # TODO: если не указан запрос, возвращать случайную гифку
            name='gif',
            uri='/execute',
            description=
            'Возвращает по запросу гифку. Например: Бот, gif котята',
        ),
    ]

    # Путь к файлу сервера
    file_name = os.path.abspath(__file__)

    def _execute_body(self, rq: dict,
                      **params: dict) -> typing.Union[dict, str]:
        command = rq['command']
        command_name = rq['command_name']

        if not command:
            raise Exception(
                "Неправильная команда '{}': нужно указать текст, например: котята"
                .format(command_name))

        import giphy
        url = giphy.get_gif(command)
        if not url:
            return '<Не удалось найти гифку>'

        import requests
        rs = requests.get(url)

        import common
        attachment = common.FileAttachment(content=rs.content, extension='gif')
        attachment_type = common.AttachmentType.GIF

        return self.generate_response(attachment=attachment,
                                      attachment_type=attachment_type)
Exemplo n.º 7
0
class CalcServer(BaseServer):
    name = 'CalcServer'
    guid = '9A306C919E0941C68D92F190E3F89C2B'
    command_list = [
        Command(
            name='калькулятор',
            uri='/execute',
            description=
            'Команда для рассчета математических выражений. Например: Бот, калькулятор 2 + 2 * 2. Еще '
            'примеры выражений: "10 ** 3", "sin(2 ** 10), "(0xFF + 255) / 0b1010", '
            '"(0xFF + 255) // 0b1010"',
            priority=9,
        ),
    ]

    # Путь к файлу сервера
    file_name = os.path.abspath(__file__)

    def _execute_body(self, rq: dict,
                      **params: dict) -> typing.Union[dict, str]:
        command = rq['command']
        command_name = rq['command_name']

        if not command:
            raise Exception(
                "Неправильная команда 'калькулятор': нужно указать выражение, например: 2 + 2 * 2"
            )

        # Калькулятор из: https://github.com/gil9red/SimplePyScripts/blob/master/calculator/use_numexpr_module/main.py
        # TODO: не модет подсчитать 10**123

        # TODO: использовать simpleeval: https://github.com/gil9red/SimplePyScripts/blob/38765c6ef304fb5da233b8d44a9294b52b86343d/simpleeval__examples__calc/hello_world.py
        import numexpr
        result = numexpr.evaluate(command)

        return result
Exemplo n.º 8
0
class TextConverter(BaseServer):
    name = 'TextConverter'
    guid = '531B994DED974F1586BA370F0AE1BE14'
    command_list = [
        Command(
            name='str2hex',
            uri='/execute?str2hex',
            description='Конвертация строки в HEX. Например: Бот, str2hex Привет!',
            priority=6,
        ),
        Command(
            name='hex2str',
            uri='/execute?hex2str',
            description='Конвертация из HEX в строку. Например: Бот, hex2str D09FD180D0B8D0B2D0B5D18220D0BCD0B8D18021',
            priority=6,
        ),

        Command(
            name='str2bin',
            uri='/execute?str2bin',
            description='Конвертация из текстовой строки в бинарную. Например: Бот, str2bin Привет!',
            priority=5,
        ),
        Command(
            name='bin2str',
            uri='/execute?bin2str',
            description='Конвертация из бинарной строки в текстовую. Например: Бот, bin2str 11001111 11110000 '
                        '11101000 11100010 11100101 11110010 00100001',
            priority=5,
        ),

        Command(
            name='str_2_base64',
            uri='/execute?str_2_base64',
            description='Конвертация из текстовой строки в base64. Например: Бот, str_2_base64 Привет! Hello!',
            priority=4,
        ),
        Command(
            name='base64_2_str',
            uri='/execute?base64_2_str',
            description='Конвертация из строки в base64 в текстовую. '
                        'Например: Бот, base64_2_str 0J/RgNC40LLQtdGCISBIZWxsbyE=',
            priority=4,
        ),

        Command(
            name='str_2_base85',
            uri='/execute?str_2_base85',
            description='Конвертация из текстовой строки в base85. Например: Бот, str_2_base85 Привет! Hello!',
            priority=3,
        ),
        Command(
            name='base85_2_str',
            uri='/execute?base85_2_str',
            description='Конвертация из строки в base85 в текстовую. '
                        'Например: Бот, base85_2_str (4WzO(74dD(6!NmAs|R)Y;12K',
            priority=3
            ,
        ),

        Command(
            name='str_2_ascii85',
            uri='/execute?str_2_ascii85',
            description='Конвертация из текстовой строки в ascii85. Например: '
                        'Бот, str_2_ascii85 https://en.wikipedia.org/wiki/Ascii85',
            priority=2,
        ),
        Command(
            name='ascii85_2_str',
            uri='/execute?ascii85_2_str',
            description="Конвертация из строки в ascii85 в текстовую. "
                        "Например: Бот, ascii85_2_str BQS?8F#ks-ASs,EBkqF%ARoL`/oPcC06_,GBeMbn@qfX:2#",
            priority=2
            ,
        ),
    ]

    # Путь к файлу сервера
    file_name = os.path.abspath(__file__)

    name_by_func = {
        'hex2str': hex2str,
        'str2hex': str2hex,

        'bin2str': bin2str,
        'str2bin': str2bin,

        'str_2_base64': lambda text: base64.b64encode(text.encode()).decode(),
        'base64_2_str': lambda text: base64.b64decode(text.encode()).decode(),

        'str_2_base85': lambda text: base64.b85encode(text.encode()).decode(),
        'base85_2_str': lambda text: base64.b85decode(text.encode()).decode(),

        'str_2_ascii85': lambda text: base64.a85encode(text.encode()).decode(),
        'ascii85_2_str': lambda text: base64.a85decode(text.encode()).decode(),
    }

    def _execute_body(self, rq: dict, **params: dict) -> typing.Union[dict, str]:
        command = rq['command']
        command_name = rq['command_name']

        if not command:
            raise Exception("Неправильная команда '{}': не указан текст".format(command_name))

        function_list = list(params.keys())
        if not function_list:
            raise Exception("Неправильная команда '{}': не указана вызываемая функция, "
                            "например 'hex2str'".format(command_name))

        func_name = function_list[0]

        if func_name not in self.name_by_func:
            raise Exception("Неправильная команда '{}': не найдена функция '{}', доступны следующие "
                            "функции: {}".format(command_name, func_name, ', '.join(self.name_by_func.keys())))

        try:
            # Вызов функции по ее имени
            result = self.name_by_func[func_name](command)

        except Exception as e:
            import traceback
            print('Error: {}\n\n{}'.format(e, traceback.format_exc()))

            raise Exception('При выполнении команды "{}" произошла ошибка. '
                            'Проверь что данные правильные. Текст ошибки: "{}".'.format(command_name, e))

        return result
Exemplo n.º 9
0
class TestAttachmentServer(BaseServer):
    name = 'TestAttachmentServer'
    guid = 'D2EA28FA35D244E5A36EECC5FA3EA759'
    command_list = [
        Command(
            name='тест картинку',
            uri='/execute?' + common.AttachmentType.IMAGE,
            description='Возвращает тестовую картинку. Например: Бот, тест картинку',
        ),
        Command(
            name='тест много картинок',
            uri='/execute?' + common.AttachmentType.LIST_IMAGE,
            description='Возвращает несколько тестовых картинок. Например: Бот, тест много картинок',
        ),
        Command(
            name='тест гифку',
            uri='/execute?' + common.AttachmentType.GIF,
            description='Возвращает тестовую гифку. Например: Бот, тест гифку',
        ),
    ]

    # Путь к файлу сервера
    file_name = os.path.abspath(__file__)

    def _execute_body(self, rq: dict, **params: dict) -> typing.Union[dict, str]:
        command = rq['command']
        command_name = rq['command_name']

        function_list = list(params.keys())
        func_name = function_list[0]

        import pathlib
        current_dir = pathlib.Path(__file__).parent

        result = None
        attachment_type = common.AttachmentType(func_name)

        if attachment_type == common.AttachmentType.IMAGE:
            file = current_dir / 'Jimm Kerry.jpg'
            result = file.name  # 'Jimm Kerry.jpg'
            extension = file.suffix[1:]
            content = file.read_bytes()

            attachment = common.FileAttachment(content=content, extension=extension)

        elif attachment_type == common.AttachmentType.GIF:
            file = current_dir / 'Jimm Kerry.gif'
            result = 'Jimm Kerry.gif'
            extension = file.suffix[1:]
            content = file.read_bytes()

            attachment = common.FileAttachment(content=content, extension=extension)

        elif attachment_type == common.AttachmentType.LIST_IMAGE:
            attachment = []

            for file in current_dir.glob('images/*.jpg'):
                extension = file.suffix[1:]
                content = file.read_bytes()

                file_attachment = common.FileAttachment(content=content, extension=extension)
                attachment.append(file_attachment)

        else:
            message = "Неправильная команда '{}': не найдена функция '{}', доступны следующие функции: {}"
            message = message.format(
                command_name,
                attachment_type.value,
                ', '.join([common.AttachmentType.IMAGE.value, common.AttachmentType.GIF.value, common.AttachmentType.LIST_IMAGE.value]),
            )
            raise Exception(message)

        return self.generate_response(result=result, attachment=attachment, attachment_type=attachment_type)
Exemplo n.º 10
0
class DuckDuckGoServer(BaseServer):
    name = 'DuckDuckGoServer'
    guid = 'F7C3D7520D434C82A28B48967F5513B6'
    command_list = [
        Command(
            name='ddg',
            uri='/execute',
            description=
            'Команда для поиска информации, используя api duckduckgo. Например: Бот, ddg металлика',
            priority=7,
        ),
    ]

    # Путь к файлу сервера
    file_name = os.path.abspath(__file__)

    def _execute_body(self, rq: dict,
                      **params: dict) -> typing.Union[dict, str]:
        command = rq['command']
        command_name = rq['command_name']

        if not command:
            raise Exception(
                "Неправильная команда '{}': нужно указать выражение, например: металлика"
                .format(command_name))

        from commands.command__duckduckgo import duckduckgo
        result = duckduckgo.query(command, kad='ru_RU')
        print('"{}" -> {}'.format(command, result.json))

        try:
            # Пытаемся достать текст ответа и если произошла ошибка либо нет
            # содержимого пытаемся получить результат из других полей
            text = result.abstract.text.strip()
            if not text:
                raise Exception('time duckduckgo.get_zci!')

        except:
            return duckduckgo.get_zci(command,
                                      on_no_results='<Нет результатов>',
                                      kad='ru_RU')

        attachment = None
        attachment_type = None

        img_url = result.image.url
        if img_url:
            try:
                import requests
                rs = requests.get(img_url)

                content = rs.content
                extension = pathlib.Path(img_url).suffix[1:]

                attachment = common.FileAttachment(content=content,
                                                   extension=extension)
                attachment_type = common.AttachmentType.IMAGE

            except:
                pass

        url = result.abstract.url
        if url:
            from urllib.parse import unquote
            url = unquote(url)
            text += ' (' + url + ')'

        text = text.strip()

        return self.generate_response(result=text,
                                      attachment=attachment,
                                      attachment_type=attachment_type)
Exemplo n.º 11
0
class CoordinatorServer(BaseServer):
    name = 'CoordinatorServer'
    guid = 'B57B73C8F8D442C48EDAFC951963D7A5'
    command_list = [
        Command(name='команды',
                uri='/execute',
                description='Возвращает топ10 команд',
                priority=999),
        Command(name='все команды',
                uri='/execute',
                description='Возвращает все команды',
                priority=998),
    ]

    # Путь к файлу сервера
    file_name = os.path.abspath(__file__)

    @BaseServer.expose
    @BaseServer.json_out
    def get_commands(self, as_result=None, max_number=None) -> dict:
        print(self.request.params)

        all_command_name_by_description = db.get_all_command_name_by_description(
        )

        if as_result is not None:
            items = list(all_command_name_by_description.items())[:max_number]
            result = '\n'.join('✓ {}: {}'.format(k, v) for k, v in items)

            return self.generate_response(result=result)

        return all_command_name_by_description

    @BaseServer.expose
    @BaseServer.json_out
    def get_top10_commands(self, as_result=None) -> dict:
        return self.get_commands(as_result, max_number=10)

    def _execute_body(self, rq: dict,
                      **params: dict) -> typing.Union[dict, str]:
        command = rq['command']
        command_name = rq['command_name']
        attachment = rq['attachment']

        # Если команды нет, показываем список команд
        if not command.strip():
            return self.get_top10_commands(as_result=True)

        # Приведение в нижний регистр чтобы проверка команды была регистронезависимой
        execute_command = command.lower()
        print('execute_command: "{}"'.format(execute_command))

        all_command_by_url = db.get_all_command_name_by_url()
        command_name_list = [x.lower() for x in all_command_by_url.keys()]

        # Если текущая команда не была найдена среди списка команд хотя бы по совпадению начальной строки,
        # пытаемся найти, учитывая, что в ней могут быть опечатки, иначе ругаемся на неизвестную команду
        if not any(execute_command.startswith(x) for x in command_name_list):
            fix_execute_command = None

            for command_name in command_name_list:
                word_list = execute_command.split()
                for i in range(1, len(word_list) + 1):
                    part_command_name = ' '.join(word_list[:i])

                    # Если нашли команду
                    if command_name == fix_command(part_command_name,
                                                   command_name_list):
                        # Составляем команду с текстом
                        fix_execute_command = ' '.join([command_name] +
                                                       word_list[i:])

            # Если это была опечатка, обновляем запрос команды, исправив опечатку
            if fix_execute_command is not None and execute_command != fix_execute_command:
                print('fix execute command: "{}" -> "{}"'.format(
                    execute_command, fix_execute_command))
                execute_command = fix_execute_command

            # Если не удалось разобрать команду как опечатку
            if fix_execute_command is None:
                result = 'Получена неизвестная команда "{}".\n' \
                         'Чтобы узнать доступные команды введи: Бот, команды'.format(command)

                return result

        # Обработка собственных команд
        if execute_command == 'команды':
            return self.get_top10_commands(as_result=True)

        elif execute_command == 'все команды':
            return self.get_commands(as_result=True)

        for command_name, url in all_command_by_url.items():
            if execute_command.startswith(command_name.lower()):
                command_text = command[len(command_name):].strip()
                print(
                    'Found server: {}, command name: "{}", command text: "{}"'.
                    format(url, command_name, command_text))

                rq = generate_request(command_name, command_text, attachment)
                print('Generate request:', rq)

                import requests
                try:
                    rs = requests.post(url, json=rq)
                    print('Response:', rs.text)
                    return rs.json()

                except requests.exceptions.ConnectionError:
                    error = 'Сервер команды "{}" ({}) недоступен'.format(
                        command_name, url)
                    return self.generate_response(error=error)

        error = 'Что-то пошло не так: команда "{}" не была распознана'.format(
            command)
        return self.generate_response(error=error)

    def _before_run(self):
        def _thread_func():
            # Немного дадим времени серверам перед проверкой (особенно http-серверу самого координатора)
            time.sleep(2)

            while True:
                pool = ThreadPool()
                rows = pool.map(update_availability_server,
                                db.get_all_server())

                # Сортировка по NAME
                rows.sort(key=lambda x: x[0])
                table = tabulate(rows,
                                 headers=('NAME', 'AVAILABILITY'),
                                 tablefmt="grid")

                # TODO: лучше это логировать. Можно и в отдельный файл, т.к. логировать будет много и часто
                print(table + '\n\n')

                # Иначе может не вывести сразу в консоль
                sys.stdout.flush()

                time.sleep(25)

        from threading import Thread
        thread = Thread(target=_thread_func)
        thread.start()