コード例 #1
0
async def info(call: CallbackQuery, state: FSMContext):
    await call.answer()

    settings = database.get_settings(call.from_user.id) or {}

    msg = 'Отправка оповещений через Telegram '
    if settings.get('active'):
        msg += '<b>активирована</b>.'
    else:
        msg += '<b>отключена</b>.'

    msg += '\nТекущий e-mail: '
    if settings.get('email'):
        msg += f'<b>{settings["email"]}</b>.'
    else:
        msg += '<b>не задан</b>.'

    msg += '\nОтправка оповещений на e-mail '
    if settings.get('email_active'):
        msg += '<b>активирована</b>.'
    else:
        msg += '<b>отключена</b>.'

    for host in fl_parser.HOSTS:
        msg += '\n\n\n<b>Настройки фильтров для сайта '
        msg += f'{fl_parser.host_to_hashtag(host)}</b>.'

        job_filters = database.get_filters(
            user_id=call.from_user.id, host=host, query='keywords') or []
        msg += f'\n\n{EMO_KEY} Поиск по ключевым словам:\n'
        if len(job_filters) > 0:
            msg += ('<b>' + ', '.join(job_filters[0]['keywords'].split(',')) +
                    '</b>.')
        else:
            msg += '<b>не настроен</b>.'

        job_filters = database.get_filters(
            user_id=call.from_user.id, host=host, query='categories') or []
        msg += f'\n\n{EMO_CLIPBOARD} Поиск по категориям:\n'
        if len(job_filters) > 0:
            titles = fl_parser.get_all_titles(host)
            cat_ids = (job_filters[0]['categories'] +
                       job_filters[0]['subcategories'])
            msg += '<b>'
            msg += ', '.join([f'"{titles[cat_id]}"' for cat_id in cat_ids])
            msg += '</b>.'
        else:
            msg += '<b>не настроен</b>.'

    await Menu.info.set()
    await call.message.edit_text(text=msg,
                                 reply_markup=menu.get_back(),
                                 parse_mode=ParseMode.HTML)
コード例 #2
0
async def menu_select_category(call: CallbackQuery, state: FSMContext):
    await call.answer()

    host = await _get_host(call.message, state)
    if not host:
        return

    if call.data == 'keywords':
        job_filters = database.get_filters(
            user_id=call.from_user.id, host=host, query='keywords') or []
        if len(job_filters) > 0:
            msg = ('Текущий список ключевых слов: <b>' +
                   ', '.join(job_filters[0]['keywords'].split(',')) + '</b>.')
        else:
            msg = 'Текущий список ключевых слов <b>пуст</b>.'

        msg += ('\n\nВведите <b>ключевые слова</b> для поиска '
                '(через запятую без пробелов):')

        await Menu.input_keywords.set()
        await call.message.edit_text(text=msg,
                                     reply_markup=menu.get_back(),
                                     parse_mode=ParseMode.HTML)
    else:
        await show_select_category(call.message, call.from_user.id, host)
コード例 #3
0
def get_select_filter_type(user_id: str, host: str) -> InlineKeyboardMarkup:
    sel_cat = sel_kw = ''
    job_filters = database.get_filters(user_id=user_id, host=host) or []
    for job_filter in job_filters:
        if job_filter.get('keywords'):
            sel_kw = f'{EMO_CHECK_MARK} '
        else:
            sel_cat = f'{EMO_CHECK_MARK} '

    sel_cat = sel_cat or f'{EMO_MEMO} '
    sel_kw = sel_kw or f'{EMO_KEY} '

    return InlineKeyboardMarkup(inline_keyboard=[
        [
            InlineKeyboardButton(text=f'{sel_cat}Выбор категорий',
                                 callback_data='categories'),
        ],
        [
            InlineKeyboardButton(text=f'{sel_kw}Выбор ключевых слов',
                                 callback_data='keywords'),
        ],
        [
            InlineKeyboardButton(text=f'{EMO_REWIND} Возврат',
                                 callback_data='back'),
        ],
    ])
コード例 #4
0
def _get_cat_filter(user_id: str, host: str) -> tuple:
    job_filters = database.get_filters(
        user_id=user_id, host=host, query='categories') or []
    if len(job_filters) > 0:
        categories = job_filters[0].get('categories', [])
        subcategories = job_filters[0].get('subcategories', [])
    else:
        categories = []
        subcategories = []

    return (categories, subcategories)
コード例 #5
0
async def input_keywords(message: Message, state: FSMContext):
    host = await _get_host(message, state, edit_message=False)
    if not host:
        return

    job_filters = database.get_filters(
        user_id=message.from_user.id, host=host, query='keywords') or []
    if len(job_filters) > 0:
        last_job_url = job_filters[0]['last_job_url']
    else:
        last_job_url = ''

    database.save_filter(user_id=message.from_user.id,
                         host=host,
                         keywords=message.text.lower(),
                         last_job_url=last_job_url)

    await show_select_filter_type(
        message,
        message.from_user.id,
        host,
        info_text=f'{EMO_INFORMATION} <i>Ключевые слова выбраны!</i>\n\n',
        edit_message=False)
コード例 #6
0
async def add_subcategory(call: CallbackQuery, state: FSMContext):
    await call.answer()

    host = await _get_host(call.message, state)
    if not host:
        return

    category_id = await _get_category_id(call, state, host)
    if not category_id:
        return

    job_filters = database.get_filters(
        user_id=call.from_user.id, host=host, query='categories') or []
    if len(job_filters) > 0:
        job_filter = job_filters[0]
    else:
        job_filter = {
            'categories': [],
            'subcategories': [],
            'last_job_url': '',
        }

    modified = False
    if call.data.isdigit():
        if category_id in job_filter['categories']:
            job_filter['categories'].remove(category_id)

            # Если ранее была выбрана вся категория целиком, то список
            # подкатегорий заведомо пуст, и его надо построить заново
            job_filter['subcategories'] += fl_parser.get_cat_ids(
                fl_parser.get_subcatlist(host, category_id))

            job_filter['subcategories'].remove(call.data)
        else:
            if call.data in job_filter['subcategories']:
                job_filter['subcategories'].remove(call.data)
            else:
                job_filter['subcategories'].append(call.data)

        modified = True
    elif call.data == 'everything':
        if category_id not in job_filter['categories']:
            job_filter['categories'].append(category_id)
            modified = True
    elif call.data == 'nothing':
        if category_id in job_filter['categories']:
            job_filter['categories'].remove(category_id)
            modified = True
        else:
            for subcat in fl_parser.get_subcatlist(host, category_id):
                if subcat['id'] in job_filter['subcategories']:
                    job_filter['subcategories'].remove(subcat['id'])
                    modified = True

    if modified:
        job_filter['categories'], job_filter['subcategories'] = (
            fl_parser.assemble_catlist(host, job_filter['categories'],
                                       job_filter['subcategories']))

        if job_filter['categories'] or job_filter['subcategories']:
            database.save_filter(user_id=call.from_user.id,
                                 host=host,
                                 categories=job_filter['categories'],
                                 subcategories=job_filter['subcategories'],
                                 last_job_url=job_filter['last_job_url'])
        else:
            database.delete_filters(user_id=call.from_user.id,
                                    host=host,
                                    query='categories')

        await call.message.edit_reply_markup(
            reply_markup=menu.get_select_subcategory(
                user_id=call.from_user.id, host=host, category_id=category_id))
コード例 #7
0
async def notify_users(bot: Bot, user_id=None) -> bool:
    """Возвращаемое значение:
    True, если сообщения фактически были кому-то отправлены;
    False, если никаких отправок не было (к обработке ошибок это не относится).
    """
    result = False

    if user_id:
        user = database.get_settings(user_id)
        if user:
            users = [user]
        else:
            users = []
    else:
        users = database.get_settings_all() or []

    for user in users:
        if not (user['active'] or user['email_active']):
            continue

        for host in fl_parser.HOSTS:
            jobs_complete_list = []
            for query in ['keywords', 'categories']:
                job_filters = database.get_filters(
                    user_id=user['user_id'], host=host, query=query) or []

                if not job_filters:
                    continue

                jobs = fl_parser.get_jobs(
                    host=host,
                    category_ids=job_filters[0]['categories'],
                    subcategory_ids=job_filters[0]['subcategories'],
                    keywords=job_filters[0]['keywords'])

                jobs = fl_parser.get_recent_jobs(
                    jobs=jobs, last_job_url=job_filters[0]['last_job_url'])

                if not jobs:
                    continue

                database.save_filter(
                    user_id=user['user_id'],
                    host=host,
                    categories=job_filters[0]['categories'],
                    subcategories=job_filters[0]['subcategories'],
                    keywords=job_filters[0]['keywords'],
                    last_job_url=jobs[0]['url'])

                if len(jobs) > MAX_JOB_COUNT:
                    jobs = jobs[:MAX_JOB_COUNT]

                i = 0
                while i <= len(jobs) - 1:
                    append = True
                    for job in jobs_complete_list:
                        if job['url'] == jobs[i]['url']:
                            append = False
                            break
                    if append:
                        jobs_complete_list.append(jobs[i])
                        i += 1
                    else:
                        del jobs[i]

                if user['active'] and jobs:
                    msg = ''
                    for index, job in enumerate(jobs):
                        msg += (
                            f'<b><a href="{job["url"]}">{job["title"]}</a></b>'
                            + f'\n{EMO_MONEY} <b>{job["price"]}</b>' +
                            f' {EMO_POINT_RIGHT} ' +
                            f'<b>{fl_parser.host_to_hashtag(host)}</b>' +
                            f'\n{job["description"]}')

                        if index < len(jobs) - 1:
                            msg += '\n\n\n'

                    try:
                        await bot.send_message(user['user_id'],
                                               msg,
                                               parse_mode=ParseMode.HTML,
                                               disable_web_page_preview=True)
                        result = True
                    except Exception as e:
                        logging.error(e)

                if user['email_active'] and jobs:
                    text = ''
                    html = HTML_BEGIN

                    for index, job in enumerate(jobs):
                        html += (
                            f'<p>\n<b><a href="{job["url"]}">' +
                            f'{escape(job["title"])}</a></b>' +
                            f'<br><b>Бюджет проекта:</b> {job["price"]}<br>' +
                            f'{escape(job["description"])}\n</p>\n')

                        text += (
                            f'Заголовок проекта: {job["title"]}\n' +
                            f'Ссылка на страницу проекта: {job["url"]}\n' +
                            f'Бюджет: {job["price"]}\n' +
                            f'Описание:\n{job["description"]}')

                        if index < len(jobs) - 1:
                            html += (
                                '<p>--- + --- + --- + --- + --- + ---</p>' +
                                '\n')
                            text += '\n\n--- + --- + --- + --- + --- + ---\n\n'

                    html += HTML_END

                    send_email(email_receiver=user['email'],
                               email_subject=f'Новые проекты от {host}: ' +
                               f'{jobs[0]["title"]}',
                               text_content=text,
                               html_content=html)
                    result = True

                await asyncio.sleep(
                    randint(REQUEST_DELAY_MIN, REQUEST_DELAY_MAX))

    return result