from config import hour_poll_posting, bot_acct, instance, limit_all_movies_poll, limit_movies_per_user, max_fail_limit from src.fedi_api import get_status_context, get_status, post_status, mute_user from src.kinopoisk_api import get_kinopoisk_movie_to_imdb from src.imdb_datasets_worker import get_title_by_id from src.fmn_database import add_movie_to_poll, get_already_watched, get_suggested_movies_count from src.fmn_states_db import get_state, add_state from src.fmn_poll import create_poll_movies, get_winner_movie import re import time from datetime import datetime from dateutil.parser import parse as dateutilparse from dateutil.relativedelta import relativedelta, TU from collections import Counter from loguru import logger def parse_links(text=str): regex = r"kinopoisk\.ru/" if re.search(regex, text.lower(), flags=re.MULTILINE): kinopoisk_ids = re.findall(r"film/(\d{1,})", text.lower()) if kinopoisk_ids != []: return kinopoisk_ids[:limit_movies_per_user] def parse_links_imdb(text=str): regex = r"imdb\.com/|libremdb\.pussthecat\.org/|libremdb\.esmailelbob\.xyz/|libremdb\.herokuapp\.com/|libremdbeu\.herokuapp\.com/|lmdb\.tokhmi\.xyz/|libremdb\.lqs5fjmajyp7rvp4qvyubwofzi6d4imua7vs237rkc4m5qogitqwrgyd\.onion/" if re.search(regex, text.lower(), flags=re.MULTILINE): imdb_ids = re.findall(r"tt(\d{1,})", text.lower()) if imdb_ids != []: return imdb_ids[:limit_movies_per_user] def scan_context_thread(): fail_limit = Counter() while True: status_id = get_state('last_thread_id') poll_created = get_state('poll_status_id') stop_thread_scan = get_state('stop_thread_scan') time_now = int(time.time()) while status_id is None or stop_thread_scan is None: fail_limit = Counter() status_id = get_state('last_thread_id') stop_thread_scan = get_state('stop_thread_scan') time.sleep(1) if time_now >= int(stop_thread_scan): logger.debug('Сбор завершён, сканирование треда на опоздавших') if poll_created is None: create_poll_movies() poll_created = get_state('poll_status_id') else: if time_now >= int(get_state('poll_expires_at')): get_winner_movie(poll_created) else: endings = int(stop_thread_scan) - time_now logger.debug(f'Осталось до закрытия сбора: {endings}') descendants = get_status_context(status_id)['descendants'] replyed = [] for status in descendants: if status['account']['acct'] == bot_acct: replyed.append(status['in_reply_to_id']) for status in descendants: id_st = status['id'] in_reply_acct = status['in_reply_to_account_id'] in_reply_id = status['in_reply_to_id'] muted = status['muted'] acct = status['account']['acct'] acct_id = status['account']['id'] content = status['pleroma']['content']['text/plain'] if id_st in replyed: # Игнорировать уже отвеченное continue if muted is True: continue if fail_limit[acct] >= max_fail_limit: # Игнорировать пользователя если он превысил fail limit mute_user(acct_id, acct, int(get_state('max_mute_time')) - time_now) logger.warning(f'{acct} игнорируется - превышение fail limit') break # Нужно обновить тред, чтобы muted на заглушенном стал True parsed_result = parse_links(content) parsed_result_imdb = parse_links_imdb(content) if parsed_result is None and parsed_result_imdb is None: continue if poll_created: post_status(f'ℹ️ Приём заявок уже окончен.\n\nГолосовалка здесь: https://{instance}/notice/{poll_created}', id_st) logger.info(f'{acct} был уведомлен о завершенной голосовалке') fail_limit[acct] += 1 continue index_type = 1 index_name = 2 index_ru_name = 3 index_year = 4 if parsed_result is not None: print(parsed_result) suggested_movies = get_kinopoisk_movie_to_imdb(parsed_result) if suggested_movies is None: post_status('❌ Не удалось выполнить запрос: возможно некорректный тип фильма, попробуйте использовать imdb.com', id_st) fail_limit[acct] += 1 continue elif parsed_result_imdb is not None: suggested_movies = get_title_by_id(parsed_result_imdb) message_writer = [] success = False for movie in suggested_movies: logger.debug(str(movie)) if movie[index_type] == "404": message_writer.append("❌ Не найдено.") fail_limit[acct] += 1 elif movie[index_type] not in ("movie", "video"): type_of_title = movie[index_type] message_writer.append(f"❌ Не принято:\n- Нам не подходят: сериалы, короткометражные и документальные фильмы") logger.info(f'Предложение {acct} отклонено: не подходящий тип фильма: {type_of_title}') fail_limit[acct] += 1 else: name = movie[index_name] name_ru = movie[index_ru_name] year = movie[index_year] movie_string = f"{name_ru} / {name}, {year}" if name is None: movie_string = f"{name_ru}, {year}" if name_ru is None: movie_string = f"{name}, {year}" if year is None: post_status('🎬 Мы временно не можем обработать ваше предложение: Обработка фильма без наличия года невозможна.', id_st) fail_limit[acct] += 1 break if get_suggested_movies_count() >= limit_all_movies_poll: post_status('🎬 Мы не можем обработать ваше предложение: количество уже предложенных не помещается в лимит голосовалки.', id_st) logger.warning(f'Предложение {acct} было отклонено: количество уже предложенных фильмов превышает\равно {limit_all_movies_poll}') fail_limit[acct] += 1 break if get_already_watched(name, name_ru, year) == True: message_writer.append(f"ℹ️ Этот фильм уже был на FMN: {movie_string}") logger.info(f'Попытка предложить уже просмотренный фильм: {acct} {name} {name_ru} {year}') fail_limit[acct] += 1 continue add_result = add_movie_to_poll(acct, name, name_ru, year) if add_result == 0: message_writer.append(f"✅ Принято: {movie_string}") logger.success(f'Предложение от {acct} принято: {name} {name_ru} {year}') success = True elif add_result == 1: message_writer.append("❌ Этот фильм уже был предложен") logger.info(f'Предложение от {acct} было отлонено - фильм в опросе существует') fail_limit[acct] += 1 else: message_writer.append("❌ Вы не можете добавить больше 2х фильмов") logger.info(f'Предложение от {acct} было отлонено - лимит на пользователя') fail_limit[acct] += 1 if message_writer != []: message = '' if success: message = "\nБлагодарим за ваше предложение!" post_status('\n'.join(message_writer) + message, id_st) time.sleep(30)