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")
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))
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))
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")))
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")
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))
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)
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))
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))
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))
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")
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))
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))
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