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)
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)
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'), ], ])
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)
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)
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))
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