def user_send_password(update: Update, context: CallbackContext): ejuser = CachedTelegramEljur(chat_id=update.message.chat.id, no_messages=True) if ejuser.auth(login=context.user_data['eljur_login'], password=update.message.text, vendor=context.user_data['vendor']): update.message.reply_text( 'Вы успешно вошли в элжур! Выполняю синхронизацию, пожалуйста, подождите.' ) cte.get_cte(chat_id=update.message.chat.id) # Кэшируем сообщения if update.message.chat.id not in authorized_chat_ids: authorized_chat_ids.append(update.message.chat.id) updater.job_queue.run_repeating( check_for_new_messages, interval=MESSAGES_CHECK_DELAY, first=MESSAGES_CHECK_DELAY, context=update.message.chat.id, name=f'new_messages:{update.message.chat.id}') send_menu(update=update, context=context) return MAIN_MENU else: keyboard = [['Попробовать ещё раз']] reply_markup = ReplyKeyboardMarkup(keyboard, resize_keyboard=True) update.message.reply_text( f'Неправильный логин/пароль. ' f'Если вы указали "Другая школа", ' f'убедитесь в правильности отправленной ссылки на журнал.', reply_markup=reply_markup) return ConversationHandler.END
def just_message(update: Update, context: CallbackContext): if 'reply' in context.user_data and context.user_data['reply']: ejuser = cte.get_cte(chat_id=update.message.chat.id) message_id = context.user_data['reply'] context.user_data['reply'] = None reply_text = update.message.text keyboard = [[ InlineKeyboardButton("Закрыть", callback_data='close'), InlineKeyboardButton("Сообщения", callback_data='page_inbox_it') ]] reply_markup = InlineKeyboardMarkup(keyboard) if ejuser.reply_message(replyto=message_id, text=reply_text): message = ejuser.get_message(message_id) result = parse_message(message=message) result += f'\n\n<b>Ваш ответ на это сообщение был был отправлен:</b> \n{reply_text}' context.bot.edit_message_text( result, message_id=context.user_data['write_answer_message_id'], chat_id=update.message.from_user.id, parse_mode=ParseMode.HTML, reply_markup=reply_markup) context.bot.delete_message(chat_id=update.message.chat.id, message_id=update.message.message_id) else: update.message.reply_text('Произошла ошибка, попробуйте позднее', reply_markup=reply_markup) else: send_menu(update=update, context=context)
def check_for_new_messages(context): user_id = context.job.context if not data.find_one({'chat_id': user_id}): return logger.info(f'Проверка новых сообщений для {user_id}') try: ejuser = cte.get_cte(chat_id=user_id) new_messages = ejuser.download_messages_preview( check_new_only=True, limit=100, folder=MessageFolder.INBOX) logger.info(f'{len(new_messages)} новых сообщений для {user_id}') if not new_messages: return for message in new_messages: text = "<b>Новое сообщение</b>\n\n" subject = message['subject'] files = '📎 ' if message['with_files'] else '' unread = '🆕 ' if message['unread'] else '' text += f"<b>{unread}{files}{format_user(message['user_from'])}</b>\n" \ f"<i>Тема:</i> {subject}\n\n" \ f"<pre>{clean_html(message['short_text'])}</pre>" keyboard = [[ InlineKeyboardButton( "Посмотреть", callback_data=f'message_view_new_{message["id"]}'), InlineKeyboardButton("Закрыть", callback_data='close') ]] reply_markup = InlineKeyboardMarkup(keyboard) context.bot.send_message(chat_id=user_id, text=text, parse_mode=ParseMode.HTML, reply_markup=reply_markup) except socket.gaierror as e: pass except requests.exceptions.ConnectionError as e: pass
def message_recipients(update: Update, context: CallbackContext): query = update.callback_query ejuser = cte.get_cte(chat_id=query.message.chat.id) message_id = query.data.split('_')[-2] action = query.data.split('_')[-1] folder = query.data.split('_')[1] if action == 'next': context.user_data['recipients_offset'] += RECIPIENTS_PER_PAGE elif action == 'prev': context.user_data['recipients_offset'] -= RECIPIENTS_PER_PAGE context.user_data['recipients_offset'] = max( 0, context.user_data['recipients_offset']) if 'messages_folder' not in context.user_data: context.user_data['messages_folder'] = MessageFolder.INBOX offset = context.user_data['recipients_offset'] message = ejuser.get_message( message_id, force_folder=context.user_data['messages_folder']) total = math.ceil(len(message["user_to"]) / RECIPIENTS_PER_PAGE) cur_page = offset // RECIPIENTS_PER_PAGE + 1 recipients = f'<b>Получатели (страница {cur_page}/{total})</b>\n\n<i>' for user in message['user_to'][offset:offset + RECIPIENTS_PER_PAGE]: recipients += f"{format_user(user)}, " recipients = recipients[:-2] recipients += '</i>' query.edit_message_text(recipients, parse_mode=ParseMode.HTML) if offset > 0: keyboard = [[ InlineKeyboardButton( '⬅', callback_data=f'recipients_{folder}_{message_id}_prev') ]] else: keyboard = [] if cur_page != total: if offset > 0: keyboard[0].append( InlineKeyboardButton( '➡', callback_data=f'recipients_{folder}_{message_id}_next')) else: keyboard = [[ InlineKeyboardButton( '➡', callback_data=f'recipients_{folder}_{message_id}_next') ]] keyboard.append([ InlineKeyboardButton( "Назад", callback_data=f'message_{context.user_data["messages_folder"]}' f'_{message_id}') ]) reply_markup = InlineKeyboardMarkup(keyboard) query.edit_message_reply_markup(reply_markup) query.answer()
def messages_handler(update: Update, context: CallbackContext): ejuser = cte.get_cte(chat_id=update.message.chat.id) msgs = ejuser.get_messages() context.user_data['messages_page'] = 1 folder = MessageFolder.INBOX messages_s, reply_markup = messages_common_part(msgs=msgs, folder=folder, context=context, ejuser=ejuser) update.message.reply_text(messages_s, parse_mode=ParseMode.HTML, reply_markup=reply_markup)
def present_messages(chat_id: int, msgs: Dict[str, Any], folder: str) -> str: """ Генерирует пользовательское отображение списка сообщений :param chat_id: идентификатор чата (Telegram, etc) :param folder: папка сообщений :param msgs: словарь результата getMessages для одной страницы, содержащий обязательно список messages :return: отображение сообщений для страницы """ result = '' today = datetime.now() yesterday = today - timedelta(days=1) for ind, msg in enumerate(msgs['messages']): l_folder = folder if l_folder == 'both': l_folder = msg['folder'] date = load_date(msg['date']) when = f"{date.strftime('%-d %B %H:%M')}" if days_equal(date, today): when = f"сегодня в {date.strftime('%H:%M')}" if days_equal(date, yesterday): when = f"вчера в {date.strftime('%H:%M')}" if l_folder == MessageFolder.INBOX: user_preview = format_user(msg['user_from']) else: if 'user_to' not in msg: if 'user_from' in msg: msg['user_to'] = [msg['user_from']] else: msg['user_to'] = msg['users_to'] user_preview = format_user(msg['user_to'][0]) if 'users_to' in msg and len(msg['users_to']) > 1: user_preview += f" и ещё {len(msg['users_to']) - 1}" files = ' 📎 ' if msg['with_files'] else '' chain = cte.get_cte(chat_id=chat_id).messages_chain(msg_id=msg['id'], folder=l_folder) chain_pos = 0 for chain_msg in chain: if chain_msg['id'] == msg['id']: break chain_pos += 1 if chain_pos != 0 and chain[chain_pos - 1][ 'folder'] == MessageFolder.SENT and l_folder == MessageFolder.INBOX: answered = ' ↪️️ ' else: answered = '' if msg['unread']: result += f"{ind + 1}. <b>{answered}{files} {user_preview} ({when})</b>\n" \ f"<pre> {msg['subject']}</pre>\n" else: result += f"{ind + 1}. {answered}{files}<i>{user_preview}</i> ({when})\n" \ f"<i> {msg['subject']}</i>\n" ind += 1 return '\n' + result + '\n'
def star_handler(update: Update, context: CallbackContext): query: CallbackQuery = update.callback_query message_id = query.data.split('_')[-1] folder = query.data.split('_')[-2] ejuser = cte.get_cte(chat_id=query.message.chat.id) starred = ejuser.is_starred(msg_id=message_id, folder=folder) if starred: ejuser.unstar_message(msg_id=message_id, folder=folder) query.answer(text='Убрано из избранных') else: ejuser.star_message(msg_id=message_id, folder=folder) query.answer(text='Добавлено в избранные') view_message(update, context)
def update_messages(update: Update, context: CallbackContext): query = update.callback_query folder = query.data.split('_')[-1] ejuser = cte.get_cte(chat_id=query.message.chat.id) ejuser.update_read_state(folder=folder) context.user_data['messages_page'] = 1 msgs = ejuser.get_messages(page=context.user_data['messages_page'], folder=folder) messages_s, reply_markup = messages_common_part(msgs=msgs, folder=folder, context=context, ejuser=ejuser) query.edit_message_text(messages_s, parse_mode=ParseMode.HTML) query.edit_message_reply_markup(reply_markup=reply_markup) query.answer()
def cache_full_messages_task(): while True: for chat_id in authorized_chat_ids: time_begin = time.time() try: ejuser = cte.get_cte(chat_id=chat_id) ejuser.cache_full_messages() except Exception: logger.error( f'Ошибка кэширования сообщений для {chat_id}, traceback:\n{traceback.format_exc()}' ) logger.debug( f'Работа по кэшированию сообщений для {chat_id} завершена ' f'за {(int(time.time() - time_begin) * 1000)} ms') time.sleep(MESSAGES_CACHE_DELAY)
def starred_messages(update: Update, context: CallbackContext): query: CallbackQuery = update.callback_query ejuser = cte.get_cte(chat_id=query.message.chat.id) folder = query.data.split('_')[-2] op_folder = opposite_folder(folder) starred = ejuser.starred_messages(folder) total = math.ceil(len(starred) / 6) page = int(query.data.split('_')[-1]) messages_s = f"Избранное {len(starred)} сообщений" \ f"- страница <b>{context.user_data['messages_page']}/{total}</b>\n" messages_s += present_messages( chat_id=ejuser.chat_id, msgs={"messages": starred[(page - 1) * 6:page * 6]}, folder='both') messages_s = messages_s[:-1] if page == 1: keyboard = [[]] else: keyboard = [[ InlineKeyboardButton('⬅', callback_data=f'starred_{folder}_{page - 1}') ]] if len(starred) - page * 6 > 0: keyboard[0].insert( 1, InlineKeyboardButton('➡', callback_data=f'starred_{folder}_{page + 1}')) keyboard[0].insert( 1, InlineKeyboardButton('Назад', callback_data=f'page_inbox_it')) if page == 1 and len(ejuser.starred_messages(op_folder)) > 0: keyboard[0].insert( 2, InlineKeyboardButton('⭐ ' + folder_to_string(op_folder), callback_data=f'starred_{op_folder}_1')) for i in range(0, 6, 3): keyboard.append([ InlineKeyboardButton( str(label), callback_data=f'message_{starred[label - 1]["folder"]}_' f'{starred[label - 1]["id"]}_{page}_starred') for label in range(i + 1, i + 4) if label - 1 < len(starred) ]) reply_markup = InlineKeyboardMarkup(keyboard) query.answer(text='Избранные сообщения') query.edit_message_text(text=messages_s, parse_mode=ParseMode.HTML) query.edit_message_reply_markup(reply_markup=reply_markup)
def marks_handler(update: Update, context: CallbackContext): ejuser = cte.get_cte(chat_id=update.message.chat.id) marks = ejuser.marks(last_period=True) if marks: marks_s = f"Оценки за <b>{ejuser.periods(show_disabled=False)[-1]['fullname']}</b>\n\n" for lesson in marks['lessons']: marks_s += "<pre>" marks_s += lesson['name'] if lesson['average'] == 0: marks_s += " (нет оценок)</pre>\n" else: marks_s += f" (ср. {lesson['average']}): </pre>" marks_s += ', '.join( [mark['value'] for mark in lesson['marks']]) marks_s += "\n\n" update.message.reply_text(marks_s, parse_mode=ParseMode.HTML) else: update.message.reply_text("Не удалось подключиться к элжуру", parse_mode=ParseMode.HTML)
def homework(update: Update, context: CallbackContext): try: ejuser = cte.get_cte(chat_id=update.message.chat.id) hw = ejuser.homework dates = list(hw.keys()) date_buttons = [ InlineKeyboardButton( f'{".".join(label.split(".")[:-1])} ({hw[label]["title"].lower()})', callback_data=f'homework_{label}') for label in dates ] date_buttons_split = [] for i in range(0, len(date_buttons), 2): date_buttons_split.append(date_buttons[i:i + 2]) keyboard = [*date_buttons_split] reply_markup = InlineKeyboardMarkup(keyboard) update.message.reply_text('📝 Домашнее задание на:', reply_markup=reply_markup) except: print(traceback.format_exc())
def message_reply(update: Update, context: CallbackContext): query: CallbackQuery = update.callback_query message_id = query.data.split('_')[-1] folder = query.data.split('_')[-2] ejuser = cte.get_cte(chat_id=query.message.chat.id) message = ejuser.get_message(message_id) result = parse_message(message=message) result += '\n\nНапишите ответное сообщение:' context.user_data['write_answer_message_id'] = query.message.message_id query.edit_message_text(result, parse_mode=ParseMode.HTML) context.user_data['reply'] = message_id context.user_data['reply_all'] = '_all_' in query.data keyboard = [[ InlineKeyboardButton('Отмена', callback_data=f'message_{folder}_{message_id}') ]] # if 'users_to' in message and len(message['users_to']) > 1: # keyboard[0].insert(0, InlineKeyboardButton('[0] Ответ всем', callback_data=query.data.replace('reply_', 'reply_all_'))) reply_markup = InlineKeyboardMarkup(keyboard) query.edit_message_reply_markup(reply_markup) query.answer()
def messages_page_handler(update: Update, context: CallbackContext): query = update.callback_query action = query.data.split('_')[-1] if 'messages_page' in context.user_data: if action == 'next': context.user_data['messages_page'] += 1 elif action == 'prev': context.user_data['messages_page'] -= 1 elif action.isdigit(): context.user_data['messages_page'] = int(action) else: context.user_data['messages_page'] = 1 folder = query.data.split('_')[1] if folder == "unread": unread_only = True folder = MessageFolder.INBOX else: unread_only = False context.user_data['messages_page'] = max( 1, context.user_data['messages_page']) ejuser = cte.get_cte(chat_id=query.message.chat.id) msgs = ejuser.get_messages(page=context.user_data['messages_page'], folder=folder, unreadonly=unread_only) total = math.ceil(int(msgs['total']) / 6) if context.user_data['messages_page'] > total: context.user_data['messages_page'] = 1 msgs = ejuser.get_messages(page=context.user_data['messages_page']) messages_s, reply_markup = messages_common_part(msgs=msgs, folder=folder, context=context, ejuser=ejuser, unread_only=unread_only) query.edit_message_text(messages_s, parse_mode=ParseMode.HTML) query.edit_message_reply_markup(reply_markup=reply_markup) query.answer()
def homework_handler(update: Update, context: CallbackContext): query = update.callback_query query.answer() date = query.data.split('_')[-1] ejuser = cte.get_cte(chat_id=query.message.chat.id) hw = ejuser.homework dates = list(hw.keys()) date_buttons = [ InlineKeyboardButton( f'{".".join(label.split(".")[:-1])} ({hw[label]["title"].lower()})', callback_data=f'homework_{label}') for label in dates ] date_buttons_split = [] for i in range(0, len(date_buttons), 2): date_buttons_split.append(date_buttons[i:i + 2]) keyboard = [*date_buttons_split] reply_markup = InlineKeyboardMarkup(keyboard) tasks = get_homework(date=date, hw=hw) query.edit_message_text(text=tasks, parse_mode='html') query.edit_message_reply_markup(reply_markup=reply_markup)
def view_message(update: Update, context: CallbackContext): query = update.callback_query ejuser = cte.get_cte(chat_id=query.message.chat.id) from_starred = query.data.endswith('_starred') starred_page = 1 if from_starred: starred_page = query.data.split('_')[-2] query.data = '_'.join(query.data.split('_')[:-2]) context.user_data['recipients_offset'] = 0 context.user_data['reply'] = None message_id = query.data.split('_')[-1] if query.data.startswith('message_view_new_'): message_folder = 'inbox' keyboard = [[ InlineKeyboardButton("Ответить", callback_data=f'reply_inbox_{message_id}'), InlineKeyboardButton("Закрыть", callback_data='close') ]] else: message_folder = query.data.split('_')[-2] back_callback = f"page_{message_folder}_it" if not from_starred else f"starred_{message_folder}_{starred_page}" keyboard = [[ InlineKeyboardButton( "Ответить", callback_data=f'reply_{message_folder}_{message_id}'), InlineKeyboardButton("Назад", callback_data=back_callback) ]] starred = ejuser.is_starred(msg_id=message_id, folder=message_folder) star = "👎🏿⭐️️" if starred else "⭐️" start_callback = f"unstar_{message_folder}_{message_id}" if starred else f"star_{message_folder}_{message_id}" keyboard[0].insert( 1, InlineKeyboardButton(f"{star}", callback_data=f'{start_callback}')) message = ejuser.get_message(msg_id=message_id, force_folder=message_folder) result = parse_message(message=message) if message_folder == MessageFolder.INBOX: ejuser.mark_as_read(msg_id=message_id, folder=message_folder) yet_more = len(message['user_to']) - RECIPIENTS_PREVIEW_COUNT if yet_more > 0: keyboard.append([ InlineKeyboardButton( "Полный список получателей", callback_data=f"recipients_{message_folder}_{message_id}_it") ]) chain = ejuser.messages_chain(msg_id=message_id, folder=message_folder) pos_in_chain = 0 for msg in chain: if msg['id'] == message_id: break pos_in_chain += 1 if len(chain) > 1: if pos_in_chain == 0: next_msg = chain[pos_in_chain + 1] keyboard.append([ InlineKeyboardButton( "➡", callback_data= f"message_{next_msg['folder']}_{next_msg['id']}") ]) else: if pos_in_chain + 1 < len(chain): next_msg = chain[pos_in_chain + 1] prev_msg = chain[pos_in_chain - 1] keyboard.append([ InlineKeyboardButton( "⬅", callback_data= f"message_{prev_msg['folder']}_{prev_msg['id']}"), InlineKeyboardButton( "➡", callback_data= f"message_{next_msg['folder']}_{next_msg['id']}") ]) else: prev_msg = chain[pos_in_chain - 1] keyboard.append([ InlineKeyboardButton( "⬅", callback_data= f"message_{prev_msg['folder']}_{prev_msg['id']}") ]) reply_markup = InlineKeyboardMarkup(keyboard) query.edit_message_text(result, parse_mode=ParseMode.HTML, disable_web_page_preview=True) query.edit_message_reply_markup(reply_markup) query.answer()