mirror of
https://gitea.phreedom.club/localhost_frssoft/FMN_bot
synced 2024-05-15 15:19:19 +03:00
localhost_frssoft
b166016df8
Lower read\write in states file No attempt force upload attachment (server issues) More logger catchers
178 lines
9.4 KiB
Python
178 lines
9.4 KiB
Python
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 states_stor, write_states
|
||
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:
|
||
states = states_stor.states
|
||
status_id = states.get('last_thread_id')
|
||
poll_created = states.get('poll_status_id')
|
||
stop_thread_scan = states.get('stop_thread_scan')
|
||
time_now = int(time.time())
|
||
reserve_time = False
|
||
while status_id is None or stop_thread_scan is None:
|
||
states = states_stor.states
|
||
fail_limit = Counter()
|
||
status_id = states.get('last_thread_id')
|
||
stop_thread_scan = states.get('stop_thread_scan')
|
||
time.sleep(1)
|
||
|
||
if time_now >= int(stop_thread_scan):
|
||
reserve_time = True
|
||
logger.debug('Сбор завершён, сканирование треда на опоздавших')
|
||
if poll_created is None:
|
||
create_poll_movies()
|
||
poll_created = states_stor.states.get('poll_status_id')
|
||
else:
|
||
if time_now >= int(states.get('poll_expires_at')):
|
||
get_winner_movie(poll_created)
|
||
else:
|
||
endings = int(stop_thread_scan) - time_now
|
||
logger.debug(f'Осталось до закрытия сбора: {endings}')
|
||
if reserve_time: # Reduce instance load
|
||
time.sleep(30)
|
||
get_thread_time = time.time()
|
||
descendants = get_status_context(status_id)['descendants']
|
||
get_thread_time2 = time.time()
|
||
get_thread_delta = get_thread_time2 - get_thread_time
|
||
logger.debug(f'Get thread time: {get_thread_delta}')
|
||
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(states.get('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", "tvMovie", "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(f"❌ Вы не можете добавить больше {limit_movies_per_user}x фильмов")
|
||
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)
|
||
|
||
|