예제 #1
0
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
예제 #2
0
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)
예제 #3
0
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
예제 #4
0
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()
예제 #5
0
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)
예제 #6
0
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'
예제 #7
0
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)
예제 #8
0
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()
예제 #9
0
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)
예제 #10
0
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)
예제 #11
0
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)
예제 #12
0
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())
예제 #13
0
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()
예제 #14
0
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()
예제 #15
0
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)
예제 #16
0
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()