def craft_exams_schedule(group: str) -> str: if not parser.check_GroupExist_exam(group): return escape_md( "Ой, а мы не нашли вашу группу в расписании экзаменов!") data = parser.get_ExamsSchedule(group) text = '' for i, line in enumerate(data): text += bold(line[2].title()) \ + ' \| ' + escape_md(line[6]) \ + ' \| ' + escape_md(line[4]) \ + ' \| ' + escape_md(line[3]) \ + ' \| ' + bold(line[7]) \ + '\n' try: if data[i][4] == 'Конс.' and data[i + 1][4] != 'Экз.': text += '\n' continue except OverflowError: pass if line[4] == 'Экз.' or 'зачет' in line[4].lower(): text += '\n' return text
def detect_message_text_formatting(message: Message) -> Optional[str]: """ Detects message formatting (html, markdown or None if message has special entities) """ raw_text: str = message.text before_escape_md = raw_text.count('\\') before_escape_html = raw_text.count('&') escaped_md = escape_md(raw_text).count('\\') - before_escape_md escaped_html = quote_html(raw_text).count('&') - before_escape_html with dont_change_plain_urls, dont_escape_md: with_entities = message.md_text escaped_with_entities = escape_md(with_entities).count( '\\') - before_escape_md if escaped_with_entities > max(escaped_html, escaped_md): parse_mode = None elif escaped_html > escaped_md: parse_mode = 'html' else: parse_mode = 'markdown' return parse_mode
async def process_group(message: types.Message, state: FSMContext): find_group = re.search(r"\b\w{4}-\d{2}-\d{2}\b", message.text.upper()) if find_group == None: await message.answer( "Пожалуйста, укажите группу в правильном формате\!") return if parser.check_GroupExist(find_group.group(0)) == False: await message.answer( escape_md( "Твоя группа не найдена в нашей базе.🤷♂️\nПопробуй снова!")) return user_data = await state.get_data() if not user_data.get('group'): await state.update_data(group=find_group.group(0).upper()) user_data = await state.get_data() await message.answer( f"Группа: {escape_md(user_data['group'])} успешно установлена\!") user = '******' if message.from_user.username != None: user = message.from_user.username res = db.insert_user(tgid=message.from_user.id, username=user, first_name=message.from_user.first_name, lang=message.from_user.language_code, group=user_data['group']) if not res: logger.info( f"User failed in registration: {message.from_user.first_name} with group {user_data['group']}" ) text = 'Ой, что-то пошло не так на нашей стороне, попробуй снова /start' await message.answer(escape_md(text)) raise CancelHandler() logger.info( f"User successfully registered: {message.from_user.first_name} with group {user_data['group']}" ) await state.reset_state(with_data=False) else: await state.update_data(group=find_group.group(0).upper()) user_data = await state.get_data() db.update_user_info(tgid=message.from_user.id, group=user_data['group']) await message.answer( f"Группа: {escape_md(user_data['group'])} успешно обновлена\!") logger.info( f"Group for user {message.from_user.id} has been updated to {user_data['group']}" ) await state.reset_state(with_data=False)
async def start_handler(message: Message): await message.answer( text(escape_md("Send me your message now."), f"I will reply *as soon as I can*")) mention = message.from_user.get_mention(as_html=False) await dp.bot.send_message( channel_id, text(f"Launched by {mention}", escape_md(f"(id={message.from_user.id})")))
async def cmd_layout(msg: types.Message): text = fmt.text( fmt.escape_md(_('Select layout for streaming links response:\n')), fmt.escape_md( _('/set_layout_separate - Separate blocks for "Listen" and "Buy" links.' )), fmt.escape_md( _('/set_layout_combined - Streaming links in one list.')), fmt.escape_md(_('/set_layout_minimal - Streaming links in one line')), sep="\n") await msg.answer(text=text)
def _status_to_md_row(status_record): status_emoji = replace_emoji(status_record['status']) name = escape_md(status_record['name']) timestamp = escape_md(status_record['timestamp']) url = status_record['details_url'] if url: timestamp = link(timestamp, url) else: timestamp = f'`{timestamp or "n/a"}`' if 'error' in status_record: details = f'{name}\n{escape_md(status_record["error"])}' else: details = rf'{name} \({timestamp}\)' return f'{status_emoji} — {details}'
async def admin_update_db(message: types.Message): """ Admin feature for update database """ logger.info(f'User {message.from_user.id} request admin feauture') if message.from_user.id not in ADMINS: return await message.answer( escape_md("Извини, но у тебя нет прав на это!🤷♂️")) await message.answer( escape_md('Начал обновлять базу. Это может занять некоторое время...')) try: parser.update_MireaSchedule() except Exception as e: await message.answer('Что\-то пошло не так\!\n' + escape_md(e)) else: await message.answer('База данных успешно обновлена\!')
def get_books_catalog(category, page, page_size) -> tuple[tuple, str]: """Returns book ids and description of this books""" books = session.query(Book).with_entities(Book.book_id, Book.title, Book.author, Book.len).\ filter_by(category=category).offset((page-1)*page_size).limit(page_size).all() book_ids = tuple(book[0] for book in books) # Form description for books books_info_concat = [ ] # [ [book_property_str1, book_property_str2,], ... ] - books with attribute strings for book_num, book in enumerate(books): books_info_concat.append([]) for attr_idx, attr in enumerate(book[1:]): attr = escape_md(attr) if attr_idx == 0: books_info_concat[book_num].append( f'{(page-1)*page_size+book_num+1}\) {attr}') # Add title else: books_info_concat[book_num].append( f'```{attr}```') # Add attribute with special font color books_info_concat = [ '\n'.join(book_info) for book_info in books_info_concat ] res_str = '\n\n'.join(books_info_concat) if not book_ids: return return book_ids, res_str
def parse_day(data: list, one_day: bool) -> str: lessons = [] header = f'{data[0][2].capitalize()} | ' flag = True for lesson in data: # Skip emty lessons if lesson[3] == '': continue lessons.append( f'{lesson[8]}. {lesson[4].upper()} | {lesson[3]} | {lesson[5]}') if lesson[5] != 'Д': flag = False empty_day = not any([lesson[3] for lesson in data]) if flag and not empty_day: if one_day: header += 'Дистанционное обучение\n\n' else: header += 'Дистанционное обучение\n' elif not flag and not empty_day: if one_day: header += 'Очные занятия\n\n' else: header += 'Очные занятия\n' elif empty_day: if one_day: header += 'День самостоятельных занятий\n\n' else: header += 'День самостоятельных занятий' res = bold(header) + escape_md('\n'.join(lessons)) return res
async def parse_cache(self): """Парсим кэш""" func_name = "[PARSE CACHE] " self.log.debug('%sStart', func_name) text = [] try: json_text = '' with open('cache/daily.json', 'r', encoding='utf-8') as file: json_text = json.load(file) # Date date = datetime.strptime(json_text[str(2)]['date'], '%d.%m.%Y') text.append(bold_md( 'Ежедневный гороскоп на сегодня ({0} {1}, {2})\n\n'.format( date.strftime('%d'), MONTH_RU[date.month], date.strftime('%A') ))) # Zodiacs for zodiac in ZODIACS: horo_emoji = zodiac[0] if zodiac[0] == 'scorpio': horo_emoji = 'scorpius' text.append(emoji.emojize( ':{0}: {1} \\({2}\\) :{0}:\n{3}\n\n'.format( horo_emoji, zodiac[1], italic_md(zodiac[2]), escape_md(json_text[str(2)][zodiac[0]]) ), use_aliases=True )) self.log.debug('%sEnd', func_name) return text except Exception as error: raise Exception(func_name + str(error)) from error
async def debug_logger( message: types.Message, exception: Exception = None, descriptions: list = 'error', ): dispatcher = Dispatcher.get_current() bot = dispatcher.bot url = '' if hasattr(message, 'chat') and message.chat.type != "private": # ~ url = message.url url = message.link('link', as_html = False) text = list() text.append( u" ".join([ u" ".join([escape_md("#" + d) for d in descriptions]), url, ]) ) text.append('') text.append('```') text.append(json.dumps(message.to_python(), indent=2)) text.append('```') text.append('') text.append('```') text.append(json.dumps(repr(exception), indent=2)) text.append('```') try: await bot.send_message( chat_id = bot.users['special']['debug'], text = '\n'.join(text), disable_notification = True, parse_mode = "MarkdownV2", ) except KeyError: logging.debug(key_error)
def parse_daily(params): text = [] json_text = None with open('cache/daily.json', 'r', encoding='utf-8') as file: json_text = json.load(file) # Get horo_id horo_id = '' for i, row in enumerate(DAILY): if row[0] == 'daily_' + params[1]: horo_id = str(i + 1) day = int(params[0]) for foo, root_value in json_text.items(): if root_value['horo_id'] == horo_id: if root_value['day'] == str(day): # Date date = datetime.strptime(root_value['date'], '%d.%m.%Y') msg_date = '({0} {1}, {2})'.format(date.strftime('%d'), MONTH_RU[date.month - 1], date.strftime('%A')) text.append( bold_md('Ежедневный {0} гороскоп на {1} {2}'.format( DAILY[int(horo_id) - 1][2], DAY_TEXT[day], msg_date)) + '\n\n') # Zodiacs for zodiac in ZODIACS: horo_emoji = zodiac[0] if zodiac[0] == 'scorpio': horo_emoji = 'scorpius' text.append( emoji.emojize(':{0}: {1} :{0}:\n{2}\n\n'.format( horo_emoji, zodiac[1], escape_md(root_value[zodiac[0]])), use_aliases=True)) return text
async def exception_logger( exception: Exception = None, descriptions: list = 'error', ): dispatcher = Dispatcher.get_current() bot = dispatcher.bot text = list() text.append( u" ".join([ u" ".join([escape_md("#" + d) for d in descriptions]), ]) ) text.append('') text.append('```') text.append(json.dumps(repr(exception), indent=2)) text.append('```') try: await bot.send_message( chat_id = bot.users['special']['debug'], text = '\n'.join(text), disable_notification = True, parse_mode = "MarkdownV2", ) except KeyError: logging.debug(key_error)
async def send_error_msg(file, function, msg): print(file, function) text = '`[{0}][{1}] {2}`'.format(file, function, escape_md(msg)) try: await bot.send_message(ADMIN_ID, text) except Exception as error: print(error)
async def feedback_callback(message): await message_callback(message, ['feedback', message.chat.type]) if message.get_args(): try: url = await message.chat.export_invite_link() except exceptions.BadRequest as exception: await error_callback(message, exception, ['feedback']) url = None try: await dispatcher.bot.send_message( chat_id=dispatcher.bot.users['special']['feedback'], text=u"#feedback enviado\nde" + u"{chat} {user} (<b>{user_id}</b>):\n{link}\n" "".format( user=message.from_user.mention, user_id=message.from_user.id, chat=u" {chat_link} (<b>{chat_id}</b>)\npor".format( chat_link=u"<a href='{url}'>{title}</a>".format( url=url, title=message.chat.title, ) if url else u"{title}".format( title=message.chat.title, ), chat_id=message.chat.id, ) if message.chat.type in ['group', 'supergroup'] else ' ', link=u"{}\n".format(message.link('link')) if message.chat.type in ['group', 'supergroup'] else '', ) + u"<pre>{feedback}</pre>".format( feedback=message.get_args(), ), parse_mode="HTML", ) command = await message.reply( u"""Muito obrigado pelo feedback, vós soi\ s muito gentil! Alguém em algum momento vai ler, eu acho...""") except KeyError as exception: await error_callback(message, exception, ['feedback']) print( u"""Alguém mandou /feedback mas não tem nenhum grupo registrado \ para receber!\nExceção: {}""".format(json.dumps(repr(e), indent=2))) command = await message.reply( u"""Muito obrigado pelo feedback, vós soi\ s muito gentil! Infelizmente ninguém vai ler porque não me configuraram para re\ ceber feedback... \U0001f61e""") except Exception as exception: await error_callback(message, exception, ['feedback']) print(u"""Exceção: {}""".format(json.dumps(repr(e), indent=2))) command = await message.reply( u"""Muito obrigado pelo feedback, vós soi\ s muito gentil! Infelizmente ninguém vai ler porque eu tive um problema técnico\ . Desculpe por isto \U0001f61e""") else: command = await message.reply( escape_md(u"""Obrigado pela tentativa, mas \ se for pra mandar feedback tem que escrever alguma coisa! Exemplo:\n""") + u"`{} Muito obrigado pelo bot!`".format(message.get_command()), parse_mode="MarkdownV2", ) await command_callback(command, ['feedback', message.chat.type])
async def call_weekly_menu(call: types.CallbackQuery, callback_data: typing.Dict[str, str]): keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True) keyboard = types.InlineKeyboardMarkup(row_width=2) keyboard.add(*weekly_menu) msg = 'Еженедельный гороскоп...' await bot.send_message(call.from_user.id, escape_md(msg), reply_markup=keyboard)
async def cancel_handler(message: types.Message, state: FSMContext): current_state = await state.get_state() if current_state is None: return await state.finish() await message.answer( escape_md( 'Регистрация в боте отменена!\nМожешь попробовать по новой: /start' ))
async def call_daily_submenu(call: types.CallbackQuery, callback_data: typing.Dict[str, str]): keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True) keyboard = types.InlineKeyboardMarkup(row_width=2) keyboard.add(*daily_types_btns(callback_data['params'])) msg = 'Гороскоп на {0}...'.format(DAY_TEXT[int(callback_data['params'])]) await bot.send_message(call.from_user.id, escape_md(msg), reply_markup=keyboard)
def convert(data: dict): """Convert dict or list to nice-looking telegram markdown""" source = escape_md(data['source']) src_row = f'*From {source}*' if 'status_list' in data: status_list = '\n'.join( _status_to_md_row(status) for status in data['status_list']) else: status_list = 'Error' return f'{src_row}\n{status_list}'
def convert_members_to_mentions(members: List[Member]) -> List[str]: result = [] for member in members: if member.user_id is not None: result.append( md_style.link(value=member.member_name, link=f"tg://user?id={member.user_id}")) else: result.append(md.escape_md(member.member_name)) return result
async def check_state(message: Union[types.Message, types.CallbackQuery], state: FSMContext): user_data = await state.get_data() # Check if bot was restarted and in state not saved group if not user_data.get('group'): group = db.get_user_group(tgid=message.from_user.id) if not group: await message.answer( escape_md( ('Сначала зарегистрируйся, иначе как я узнаю твою группу?🤔' '\nНажми сюда: /start'))) return False await state.update_data(group=group, page=date.today()) return True
async def cmd_lang(msg: types.Message, state: FSMContext, locale): supported_lang = ["ru", "en"] lang = msg.get_args() if not lang: text = fmt.text( fmt.text(_("You current language is *{language}*\\.").format(language=locale)), fmt.escape_md(_("Specify your language. Example: /lang en")), sep="\n" ) return await msg.answer(text) if lang not in supported_lang: return await msg.answer(_("This language is not available\\. Use *en* or *ru*")) await state.update_data(locale=lang) return await msg.answer(_("Language set successfully\\."))
async def ytdl_callback(message): await message_callback(message, ['ytdl', message.chat.type]) url = message.get_args() ## Será que é link? if url and validators.url(url): video_file = None try: video_file = baixar(url) except Exception as e: await error_callback(u"Erro tentando baixar vídeo", message, e, ['ytdl']) command = await message.reply( escape_md( u"""Não consegui extrair a mídia. Olha o que o servidor me\ disse: """) + u"```{}```".format(str(e)), parse_mode="MarkdownV2", disable_notification=True, ) try: if video_file: video = open(video_file, 'rb') await message.reply_video( video=video, caption=message.get_args(), ) video.close() if os.path.exists(video_file): os.remove(video_file) except Exception as e: await error_callback(u"Erro tentando subir vídeo", message, e, ['ytdl']) command = await message.reply( u"""Não consegui enviar o arquivo. Tente\ i avisar o pessoal do desenvolvimento...""", disable_notification=True, ) else: command = await message.reply( u"""```\nO comando {comando} serve pra extrair um vídeo ou áudio de alg\ um site com suporte. Este comando usa o youtube-dl. Digite "{comando} url" para\ usar (dê um espaço entre o comando e o link). Por exemplo, para baixar o vídeo\ do rick roll:\n\n{comando} https://youtube.com/watch?v=dQw4w9WgXcQ""".format( comando=message.get_command()), parse_mode="MarkdownV2", ) await command_callback(command, ['ytdl', message.chat.type])
def parse(text): time_dict = {"seconds": 0, "minutes": 0, "hours": 0, "days": 0, "weeks": 0} for i in time_dict.keys(): pattern = r"\d+\s?{}".format(i[0]) match = re.findall(pattern, text) if not match: continue time_dict[i] = int(match[0].replace(i[0], "")) result = datetime.timestamp( timedelta(seconds=time_dict["seconds"], minutes=time_dict["minutes"], hours=time_dict["hours"], days=time_dict["days"], weeks=time_dict["weeks"]) + datetime.now()) reason = re.findall(r"\w+$", text) reason = escape_md(reason[0]) if reason else "не указана" return result, reason
async def cmd_mute(message: types.Message): reply = message.reply_to_message if not reply: return await message.reply("ну и кого мне мутить?") if reply.from_user.id in [ i.user.id for i in await bot.get_chat_administrators(message.chat.id) ]: return await message.reply("отказ.") args = message.get_args() until_date, reason = parse(args) until_date = max(time.time() + 60, until_date) await bot.restrict_chat_member(message.chat.id, reply.from_user.id, until_date=until_date) out_time = datetime.fromtimestamp(until_date) until_date = f"{out_time.date()} {out_time.time().hour}:{out_time.time().minute}" name = escape_md(reply.from_user.full_name) text = f"*{name}* помещён в карантин до `{until_date}`\n\nпричина: *{reason}*" await message.reply(text, parse_mode=types.ParseMode.MARKDOWN)
async def send_message_to_support(message: types.Message): """Format message and send it to support. Envelope emoji at the beginning is the mark of support ticket. """ if message.from_user.username: username = "******" + message.from_user.username else: username = markdown.link(message.from_user.full_name, message.from_user.url) await tg.send_message( config.SUPPORT_CHAT_ID, emojize(":envelope:") + f" #chat\\_{message.chat.id} {message.message_id}\n{username}:\n" + markdown.escape_md(message.text), parse_mode=types.ParseMode.MARKDOWN, ) await tg.send_message( message.chat.id, i18n("support_response_promise"), reply_markup=start_keyboard(), )
def test_pre_escaped(self): assert markdown.escape_md(r"hello\.") == r"hello\\\."
def test_equality_sign_is_escaped(self): assert markdown.escape_md(r"e = mc2") == r"e \= mc2"
async def _confirmation_callback( self, offer_id: ObjectId, op: typing.Mapping[str, typing.Any], trx_id: str, block_num: int, ) -> bool: """Confirm found block with transaction. Notify escrow asset sender and check if block is confirmed. If it is, continue exchange. If it is not, send warning and update ``transaction_time`` of escrow offer. :param offer_id: ``_id`` of escrow offer. :param op: Operation object to confirm. :param trx_id: ID of transaction with desired operation. :param block_num: Number of block to confirm. :return: True if transaction was confirmed and False otherwise. """ offer = await database.escrow.find_one({"_id": offer_id}) if not offer: return False if offer["type"] == "buy": new_currency = "sell" escrow_user = offer["init"] other_user = offer["counter"] elif offer["type"] == "sell": new_currency = "buy" escrow_user = offer["counter"] other_user = offer["init"] answer = i18n( "transaction_passed {currency}", locale=escrow_user["locale"]).format(currency=offer[new_currency]) await tg.send_message(escrow_user["id"], answer) is_confirmed = await create_task(self.is_block_confirmed( block_num, op)) if is_confirmed: await database.escrow.update_one( {"_id": offer["_id"]}, {"$set": { "trx_id": trx_id, "unsent": True }}) keyboard = InlineKeyboardMarkup() keyboard.add( InlineKeyboardButton( i18n("sent", locale=other_user["locale"]), callback_data="tokens_sent {}".format(offer["_id"]), )) answer = markdown.link( i18n("transaction_confirmed", locale=other_user["locale"]), self.trx_url(trx_id), ) answer += "\n" + i18n("send {amount} {currency} {address}", locale=other_user["locale"]).format( amount=offer[f"sum_{new_currency}"], currency=offer[new_currency], address=markdown.escape_md( escrow_user["receive_address"]), ) answer += "." await tg.send_message( other_user["id"], answer, reply_markup=keyboard, parse_mode=ParseMode.MARKDOWN, ) return True await database.escrow.update_one( {"_id": offer["_id"]}, {"$set": { "transaction_time": time() }}) answer = i18n("transaction_not_confirmed", locale=escrow_user["locale"]) answer += " " + i18n("try_again", locale=escrow_user["locale"]) await tg.send_message(escrow_user["id"], answer) return False
async def call_daily_menu(call: types.CallbackQuery, callback_data: typing.Dict[str, str]): await bot.send_message(call.from_user.id, escape_md('Ежедневный гороскоп на...'), reply_markup=daily_menu)