예제 #1
0
async def my_dn(message):
    roll_sum = 0
    symbols = ''
    if len(message.text.split()) == 3:
        try:
            dice_max = int(message.text.split()[1])
            dice_n = int(message.text.split()[2])
        except ValueError:
            return
        max_result = dice_n * dice_max
        for count in range(dice_n):
            try:
                roll = random.randint(0, dice_max)
                roll_sum += roll
                if count < dice_n - 1:
                    symbols += '{0} + '.format(roll)
                elif count == dice_n - 1:
                    symbols += '{0} = {1}  ({2})'.format(roll, roll_sum, max_result)
            except ValueError:
                pass
        if not len(symbols) > 4096:
            await message.reply(symbols)
            user_action_log(message,
                            "knew about /dn and got that output: {0}".format(symbols))
        else:
            message.reply("Слишком большие числа. "
                          "Попробуй что-нибудь поменьше")
            user_action_log(message, "knew about /dn "
                                     "and the answer was too long "
                                     "to fit one message")
예제 #2
0
async def my_d6(message):
    """
    рандомно выбирает элементы из списка значков
    TODO: желательно найти способ их увеличить или заменить на ASCII арт
    :param message:
    :return:
    """
    d6 = ["⚀", "⚁", "⚂", "⚃", "⚄", "⚅"]
    dice = 2
    roll_sum = 0
    symbols = ''
    for _ in str(message.text).lower().split():
        if not len(message.text.split()) == 1:
            try:
                dice = int(message.text.split()[1])
            except ValueError:
                await message.reply(
                        "Не понял число костей. "
                        "Пожалуйста, введи команду "
                        "в виде \'/d6 <int>\', "
                        "где <int> — целое от 1 до 10.")
                return
    if 0 < dice <= 10:
        max_result = dice * 6
        for count in range(dice):
            roll_index = random.randint(0, len(d6) - 1)
            roll_sum += roll_index + 1
            if count < dice - 1:
                symbols += '{0} + '.format(d6[roll_index])
            elif count == dice - 1:
                symbols += '{0} = {1}  ({2})'.format(d6[roll_index], roll_sum,
                                                     max_result)
        await message.reply(symbols)
        user_action_log(message, "got that D6 output: {0}".format(symbols))
예제 #3
0
async def my_truth(message):
    answers = [
        "да", "нет", "это не важно", "да, хотя зря", "никогда", "100%",
        "1 из 100"
    ]
    truth = random.choice(answers)
    await message.reply(truth)
    user_action_log(message, "has discovered the Truth:\n{0}".format(truth))
예제 #4
0
async def your_gender(message):
    with open(config.file_location['/gender'], 'r',
              encoding='utf-8') as file_gender:
        gender = random.choice(file_gender.readlines())
        await message.reply(gender)
    user_action_log(
        message, "has discovered his gender:\n{0}".format(
            str(gender).replace("<br>", "\n")))
예제 #5
0
async def rules_command(message):
    if str(message.chat.id) == config.mm_chat:
        with open(config.file_location['/rules'], 'r',
                  encoding='utf-8') as file:
            await message.reply(file.read(),
                                parse_mode="HTML",
                                disable_web_page_preview=True)
        user_action_log(message, "called rules")
예제 #6
0
async def my_new_data(message):
    command = message.text.lower().split()[0]
    command_raw = re.split("@+", command)[0]
    with open(config.file_location[command_raw], 'r',
              encoding='utf-8') as file:
        await message.reply(file.read(),
                            parse_mode="HTML",
                            disable_web_page_preview=True)
    user_action_log(message, "called that command: {}".format(command))
예제 #7
0
async def command_or(message):
    user_action_log(message, 'called: ' + message.text)
    # Shitcode alert!
    or_lang = 'ru'
    if len(message.text.split()) < 4:
        return
    or_message = message.text.split(' ', 1)[1]
    if 'or' in message.text.split():
        make_choice = re.split(r'[ ](?:or)[, ]', or_message)
        or_lang = 'en'
    else:
        make_choice = re.split(r'[ ](?:или)[, ]', or_message)
    if len(make_choice) > 1 and not ((message.text.split()[1] == 'или') or
                                     (message.text.split()[1] == 'or')):
        choosen_answer = random.choice(make_choice)
        if or_lang == 'ru':
            choosen_answer = re.sub(r'(?i)\bя\b', 'ты', choosen_answer)
        else:
            choosen_answer = re.sub(r'(?i)\bi\b', 'you', choosen_answer)
        # more subs to come
        await message.reply(choosen_answer)
예제 #8
0
async def me_message(message):
    # В ЛС бот не может удалять сообщения пользователя
    """
    try:
        my_bot.delete_message(chat_id=message.chat.id, message_id=message.message_id)
    except Exception:
        logging.exception("message")
    """
    # Если у пользователя есть юзернэйм, то берём его как your_name
    if message.from_user.username is not None:
        your_name = '[@{}](tg://user?id={})'.format(message.from_user.username,
                                                    message.from_user.id)
    # Иначе, берём имя пользователя, которое есть всегда
    else:
        your_name = '[{}](tg://user?id={})'.format(
            message.from_user.first_name, message.from_user.id)
    # Если /me непусто, берём всё, что после '/me '
    if len(message.text.split()) < 2:
        return
    your_message = message.text.split(maxsplit=1)[1]
    your_me = "{} {}".format(your_name, your_message)
    try:
        # Если /me было ответом на какое-то сообщение, то посылаем запрос как ответ
        # TODO: расширить эту фичу на все команды
        if getattr(message, 'reply_to_message') is not None:
            await message.reply_to_message.reply(your_me,
                                                 parse_mode="Markdown",
                                                 disable_notification=True)
        else:
            await message.reply(your_me,
                                parse_mode="Markdown",
                                disable_notification=True,
                                reply=False)
    except Exception:
        logging.exception("message")
    try:
        await message.delete()
    except Exception:
        logging.exception("message")
    user_action_log(message, "called the me:\n{}".format(your_me))
예제 #9
0
async def my_wiki(message):
    wiki_title = ''
    if len(message.text.split()) == 1:
        wikipedia.set_lang(random.choice(['en', 'ru']))
        wiki_query = wikipedia.random(pages=1)
    else:
        wiki_query = ' '.join(message.text.split()[1:])
        user_action_log(
            message, 'entered this query for /wiki:\n{0}'.format(wiki_query))
        if all(ord(x) < 127 or not x.isalpha() for x in wiki_query):
            wikipedia.set_lang('en')
        # TODO: a bit dirty condition
        elif all(
                ord(x) < 127 or (
                    ord('Ё') <= ord(x) <= ord('ё')) or not x.isalpha()
                for x in wiki_query):
            wikipedia.set_lang('ru')
        else:
            wikipedia.set_lang(detect(wiki_query))

    try:
        wiki_page = wikipedia.page(title=wiki_query)
        wiki_title = wiki_page.title
        wiki_url = wiki_page.url
        wiki_fact = wikipedia.summary(wiki_query, sentences=5)
        if '\n  \n' in str(wiki_fact):
            wiki_fact = '{}...\n\n' \
                        '<i>В данной статье имеется математическая вёрстка.\n' \
                        'Для удобства чтения перейди по ссылке:</i>'.format(str(wiki_fact).split('\n  \n', 1)[0])
        await message.reply('<b>{0}.</b>\n{1}\n{2}'.format(
            wiki_title, wiki_fact, wiki_url),
                            parse_mode='HTML')
    except wikipedia.exceptions.DisambiguationError as e:
        wiki_list = '\n'.join(map(str, e.options))
        await message.reply('Пожалуйста, уточни запрос.\n' \
                            'Выбери, что из перечисленного имелось в виду, и вызови /wiki ещё раз.\n{0}'.format(
            wiki_list))
    except wikipedia.exceptions.PageError:
        await message.reply('Запрос не найден.')
    user_action_log(message, "got Wikipedia article\n{0}".format(wiki_title))
예제 #10
0
async def arxiv_search(query, message):
    try:
        arxiv_search_res = arxiv.query(search_query=query, max_results=3)
        query_answer = ''
        for paper in arxiv_search_res:
            end = '…' if len(paper['summary']) > 251 else ''
            query_answer += \
                '• {0}. <a href="{1}">{2}</a>. {3}{4}\n'.format(
                        paper['author_detail']['name'], paper['arxiv_url'],
                        escape(paper['title'].replace('\n', ' ')),
                        escape(paper['summary'][0:250].replace('\n', ' ')),
                        end)
        print(query_answer)
        user_action_log(message,
                        "called arxiv search with query {}".format(query))
        await message.reply(query_answer, parse_mode="HTML")

    except Exception as ex:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
        action_log("Unknown Exception:\n{}: {}\nat {} line {}\n"
                   "Creating the alert file.".format(exc_type, ex, fname,
                                                     exc_tb.tb_lineno))
예제 #11
0
async def wolfram_solver(message):
    """
    обрабатывает запрос и посылает пользователю картинку с результатом в случае удачи
    :param message:
    :return:
    """
    # сканируем и передаём всё, что ввёл пользователь после '/wolfram ' или '/wf '
    if not len(message.text.split()) == 1:
        # my_bot.send_chat_action(message.chat.id, 'upload_photo')
        your_query = ' '.join(message.text.split()[1:])
        user_action_log(
            message,
            "entered this query for /wolfram:\n{0}".format(your_query))
        response = requests.get(
            "https://api.wolframalpha.com/v1/simple?appid=" + tokens.wolfram,
            params={'i': your_query})
        # если всё хорошо, и запрос найден
        if response.status_code == 200:
            img_original = Image.open(io.BytesIO(response.content))
            img_cropped = img_original.crop(
                (0, 95, 540, img_original.size[1] - 50))
            io_img = io.BytesIO()
            io_img.name = "wolfram {}.png".format(your_query.replace("/", "_"))
            img_cropped.save(io_img, format="png")
            io_img.seek(0)
            wolfram_max_ratio = 2.5
            if img_cropped.size[1] / img_cropped.size[0] > wolfram_max_ratio:
                await message.reply_document(io_img)
            else:
                await message.reply_photo(io_img)
            user_action_log(
                message,
                "has received this Wolfram output:\n{0}".format(response.url))
        # если всё плохо
        else:
            await message.reply(
                "Запрос не найдён.\nЕсли ты ввёл его на русском, "
                "то попробуй ввести его на английском.")
            user_action_log(message, "didn't received any data")
    # если пользователь вызвал /wolfram без аргумента
    else:
        await message.reply(
            "Использование: `/wolfram <запрос>` или `/wf <запрос>`",
            parse_mode="Markdown")
        user_action_log(message, "called /wolfram without any arguments")
예제 #12
0
async def arxiv_random(message):
    user_action_log(message, "made arxiv random query")
    try:
        eastern = pytz.timezone('US/Eastern')
        eastern_time = datetime.datetime.now(eastern)
        # publications on 20:00
        if eastern_time.hour < 20:
            eastern_time -= datetime.timedelta(days=1)
        # no publications on friday and saturday
        if eastern_time.weekday() == 5:
            eastern_time -= datetime.timedelta(days=2)
        elif eastern_time.weekday() == 4:
            eastern_time -= datetime.timedelta(days=1)
        last_published_date = eastern_time.strftime("%Y-%m-%d")
        response = requests.get('http://export.arxiv.org/oai2',
                                params={
                                    'verb': 'ListIdentifiers',
                                    'set': 'math',
                                    'metadataPrefix': 'oai_dc',
                                    'from': last_published_date
                                })
        action_log("Random arxiv paper since {}".format(last_published_date))
        # если всё хорошо
        if response.status_code == 200:
            response_tree = ElementTree.fromstring(response.content)
            num_of_papers = len(response_tree[2])
            paper_index = random.randint(0, num_of_papers)
            paper_arxiv_id = response_tree[2][paper_index][0].text.split(':')[
                -1]  # hardcoded
            papep_obj = arxiv.query(id_list=[paper_arxiv_id])[0]
            paper_link = papep_obj['pdf_url'].replace('http://',
                                                      'https://') + '.pdf'
            paper_link_name = paper_link.split("/pdf/")[1]
            print(paper_link)
            print(paper_link_name)
            req_pdf_size = requests.head(paper_link)
            pdf_size = round(
                int(req_pdf_size.headers["Content-Length"]) / 1024 / 1024, 2)
            query_answer = '{}. <a href="{}">{}</a>. {}\n\n— <a href="{}">{}</a>, {} Мб\n'.format(
                papep_obj['author_detail']['name'], papep_obj['arxiv_url'],
                escape(papep_obj['title'].replace('\n', ' ')),
                escape(papep_obj['summary'].replace('\n', ' ')), paper_link,
                paper_link_name, pdf_size)
            await message.reply(query_answer,
                                parse_mode="HTML",
                                disable_web_page_preview=False)
            user_action_log(
                message, "arxiv random query was successful: "
                "got paper {}".format(papep_obj['arxiv_url']))
            # TODO(randl): doesn't send. Download and delete?
            # my_bot.send_document(message.chat.id, data=paper_link)
        elif response.status_code == 503:
            # слишком часто запрашиваем
            action_log("Too much queries. 10 minutes break should be enough")
            arxiv_checker.last_call = datetime.datetime.utcnow(
            ) - datetime.timedelta(seconds=610)
        else:
            # если всё плохо
            user_action_log(
                message, "arxiv random query failed: response {}".format(
                    response.status_code))

    except Exception as ex:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
        action_log("Unknown Exception: {}: {}\nat {} line {}".format(
            exc_type, ex, fname, exc_tb.tb_lineno))
예제 #13
0
async def my_roll(message):
    rolled_number = random.randint(0, 100)
    await message.reply(str(rolled_number).zfill(2))
    user_action_log(message, "recieved {0}".format(rolled_number))
예제 #14
0
async def my_kek(message: types.Message):
    """
    открывает соответствующие файл и папку, кидает рандомную строчку из файла, или рандомную картинку или гифку из папки
    :param message:
    :return:
    """
    if not hasattr(my_kek, 'kek_bang'):
        my_kek.kek_bang = time.time()
    if not hasattr(my_kek, 'kek_crunch'):
        my_kek.kek_crunch = my_kek.kek_bang + 60 * 60
    if not hasattr(my_kek, 'kek_enable'):
        my_kek.kek_enable = True
    if not hasattr(my_kek, 'kek_counter'):
        my_kek.kek_counter = 0

    kek_init = True

    if message.chat.id == int(config.mm_chat):
        if my_kek.kek_counter == 0:
            my_kek.kek_bang = time.time()
            my_kek.kek_crunch = my_kek.kek_bang + 60 * 60
            my_kek.kek_counter += 1
            kek_init = True
        elif (my_kek.kek_counter >= config.limit_kek
              and time.time() <= my_kek.kek_crunch):
            kek_init = False
        elif time.time() > my_kek.kek_crunch:
            my_kek.kek_counter = -1
            kek_init = True

    if not (kek_init and my_kek.kek_enable):
        return
    if message.chat.id == config.mm_chat:
        my_kek.kek_counter += 1
    your_destiny = random.randint(
        1, 30)  # если при вызове не повезло, то кикаем из чата
    if your_destiny == 13 and str(message.chat.id) == config.mm_chat:
        await message.reply(
            'Предупреждал же, что кикну. Если не предупреждал, то')
        await message.reply_document(config.gif_links[0])
        try:
            if int(message.from_user.id) in config.admin_ids:
                await message.reply('... Но против хозяев не восстану.')
                user_action_log(message, 'can\'t be kicked out')
            else:
                # кикаем кекуна из чата (можно ещё добавить условие,
                # что если один юзер прокекал больше числа n за время t,
                # то тоже в бан)
                await my_bot.kick_chat_member(message.chat.id,
                                              message.from_user.id)
                user_action_log(message, 'has been kicked out')
                await my_bot.unban_chat_member(message.chat.id,
                                               message.from_user.id)
                # тут же снимаем бан, чтобы смог по ссылке к нам вернуться
                user_action_log(message, 'has been unbanned')
        except Exception as ex:
            logging.exception(ex)
            pass
    else:
        type_of_kek = random.randint(1, 33)
        # Image route
        if type_of_kek == 33:
            random_kek_image = ImageResponse.get_random_by_type('kek')
            if random_kek_image:
                await message.reply_photo(random_kek_image.content)

        # Gif route
        elif type_of_kek == 32:
            random_kek_gif = GifResponse.get_random_by_type('kek')
            if random_kek_gif:
                await message.reply_document(
                    ('kek.gif', random_kek_gif.content))

        # Retarded gif route
        elif type_of_kek == 31:
            await message.reply_document(random.choice(config.gif_links))

        elif type_of_kek < 5:
            kek_sticker = StickerResponse.get_random_by_type('kek')
            if kek_sticker:
                await message.reply_sticker(kek_sticker.content)

        elif 5 < type_of_kek < 7:
            voice_id = VoiceResponse.get_random_by_type('kek')
            if voice_id:
                await message.reply_voice(voice_id.content)

        else:
            kek_text = TextResponse.get_random_by_type('kek')
            if kek_text:
                await message.reply(kek_text.content)

    if my_kek.kek_counter == config.limit_kek - 10:
        time_remaining = divmod(int(my_kek.kek_crunch) - int(time.time()), 60)
        # TODO: fix this notification
        await message.reply('<b>Внимание!</b>\nЭтот чат может покекать '
                            'ещё не более {0} раз до истечения кекочаса '
                            '(через {1} мин. {2} сек.).\n'
                            'По истечению кекочаса '
                            'счётчик благополучно сбросится.'.format(
                                config.limit_kek - my_kek.kek_counter,
                                time_remaining[0], time_remaining[1]),
                            parse_mode='HTML')
    if my_kek.kek_counter == config.limit_kek - 1:
        time_remaining = divmod(int(my_kek.kek_crunch) - int(time.time()), 60)
        # TODO: fix this notification
        await message.reply(
            '<b>EL-FIN!</b>\nТеперь вы сможете кекать только через {0} мин. {1} сек.'
            .format(time_remaining[0], time_remaining[1]),
            parse_mode='HTML')
    my_kek.kek_counter += 1