mirror of
https://gitea.phreedom.club/localhost_frssoft/FMN_bot.git
synced 2024-11-25 13:21:29 +00:00
Changes:
* Имплементация fail limit * Добавлен api endpoit mute * Изменения в конфигурации и уточнения
This commit is contained in:
parent
aee5d2a9c9
commit
cc2993e59c
11
config.py
11
config.py
|
@ -2,9 +2,16 @@ admins_bot = ('drq@mastodon.ml',) # Адреса админов бота, кот
|
||||||
# Example: ('admin_user', 'another_admin_user2@example.example') or ('admin_user',)
|
# Example: ('admin_user', 'another_admin_user2@example.example') or ('admin_user',)
|
||||||
bot_acct = 'fmn' # Ник бота на инстансе
|
bot_acct = 'fmn' # Ник бота на инстансе
|
||||||
instance = 'expired.mentality.rip' # Инстанс, где будет запущен бот
|
instance = 'expired.mentality.rip' # Инстанс, где будет запущен бот
|
||||||
|
|
||||||
|
# Лимиты
|
||||||
limit_movies_per_user = 2 # Ограничение количества фильмов на одного пользователя
|
limit_movies_per_user = 2 # Ограничение количества фильмов на одного пользователя
|
||||||
limit_all_movies_poll = 20 # Сколько можно добавить всего фильмов
|
limit_all_movies_poll = 20 # Сколько можно добавить всего фильмов
|
||||||
hour_poll_posting=16 # Час в который будет создан пост с голосовалкой
|
max_fail_limit = 4 # Игнорировать предложения пользователя при достижении указанного числа проваленных поток предложить фильм
|
||||||
|
|
||||||
logger_default_level=10 # Уровень логгирования 10 - DEBUG, 20 - INFO, 30 - WARN
|
# Часы
|
||||||
|
# Note: Если на ОС часовой пояс отличается от Мск+3, то рекомендуется сместить эти часы здесь или поменять часовой пояс в ОС
|
||||||
|
hour_poll_posting = 16 # Час в который будет создан пост с голосовалкой (и завершение сбора)
|
||||||
|
fmn_next_watching_hour = 21 # Час начала киносеанса
|
||||||
|
|
||||||
|
logger_default_level = 10 # Уровень логгирования 10 - DEBUG, 20 - INFO, 30 - WARN
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
|
from config import instance
|
||||||
import json
|
import json
|
||||||
import requests
|
import requests
|
||||||
from config import instance
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger('fedi_api')
|
||||||
|
|
||||||
instance_point = f"https://{instance}/api/v1"
|
instance_point = f"https://{instance}/api/v1"
|
||||||
|
|
||||||
|
@ -68,3 +71,13 @@ def upload_attachment(file_path):
|
||||||
return r.json()['id']
|
return r.json()['id']
|
||||||
|
|
||||||
|
|
||||||
|
def mute_user(acct_id=str, acct=str, duration=None):
|
||||||
|
params = {
|
||||||
|
"duration": duration
|
||||||
|
}
|
||||||
|
r = requests.post(instance_point + '/accounts' + f"/{acct_id}/mute", params, headers=headers)
|
||||||
|
if r.status_code == 200:
|
||||||
|
logger.info(f'Пользователь {acct} был заглушен на {duration} secs')
|
||||||
|
else:
|
||||||
|
logger.error(f'Ошибка глушения {r.status_code} - {acct}')
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,22 @@
|
||||||
import time
|
from config import hour_poll_posting, bot_acct, instance, limit_all_movies_poll, max_fail_limit
|
||||||
from datetime import datetime
|
from src.fedi_api import get_status_context, get_status, post_status, mute_user
|
||||||
from dateutil.parser import parse as dateutilparse
|
|
||||||
from dateutil.relativedelta import relativedelta, TU
|
|
||||||
|
|
||||||
import re
|
|
||||||
import logging
|
|
||||||
from config import hour_poll_posting, bot_acct, instance, limit_all_movies_poll
|
|
||||||
from src.fedi_api import get_status_context, get_status, post_status
|
|
||||||
from src.kinopoisk_api import get_kinopoisk_movie
|
from src.kinopoisk_api import get_kinopoisk_movie
|
||||||
from src.imdb_datasets_worker import get_title_by_id
|
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_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_states_db import get_state, add_state
|
||||||
from src.fmn_poll import create_poll_movies, get_winner_movie
|
from src.fmn_poll import create_poll_movies, get_winner_movie
|
||||||
|
import time
|
||||||
|
from datetime import datetime
|
||||||
|
from dateutil.parser import parse as dateutilparse
|
||||||
|
from dateutil.relativedelta import relativedelta, TU
|
||||||
|
from collections import Counter
|
||||||
|
import re
|
||||||
|
import logging
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger('thread_listener')
|
logger = logging.getLogger('thread_listener')
|
||||||
|
|
||||||
|
|
||||||
def parse_links(text=str):
|
def parse_links(text=str):
|
||||||
regex = r"kinopoisk\.ru/"
|
regex = r"kinopoisk\.ru/"
|
||||||
if re.search(regex, text.lower(), flags=re.MULTILINE):
|
if re.search(regex, text.lower(), flags=re.MULTILINE):
|
||||||
|
@ -34,13 +36,14 @@ def parse_links_imdb(text=str):
|
||||||
|
|
||||||
|
|
||||||
def scan_context_thread():
|
def scan_context_thread():
|
||||||
|
fail_limit = Counter()
|
||||||
while True:
|
while True:
|
||||||
status_id = get_state('last_thread_id')
|
status_id = get_state('last_thread_id')
|
||||||
poll_created = get_state('poll_status_id')
|
poll_created = get_state('poll_status_id')
|
||||||
stop_thread_scan = get_state('stop_thread_scan')
|
stop_thread_scan = get_state('stop_thread_scan')
|
||||||
flag_scan = 0
|
|
||||||
time_now = int(time.time())
|
time_now = int(time.time())
|
||||||
while status_id is None or stop_thread_scan is None:
|
while status_id is None or stop_thread_scan is None:
|
||||||
|
fail_limit = Counter()
|
||||||
status_id = get_state('last_thread_id')
|
status_id = get_state('last_thread_id')
|
||||||
stop_thread_scan = get_state('stop_thread_scan')
|
stop_thread_scan = get_state('stop_thread_scan')
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
@ -66,11 +69,20 @@ def scan_context_thread():
|
||||||
id_st = status['id']
|
id_st = status['id']
|
||||||
in_reply_acct = status['in_reply_to_account_id']
|
in_reply_acct = status['in_reply_to_account_id']
|
||||||
in_reply_id = status['in_reply_to_id']
|
in_reply_id = status['in_reply_to_id']
|
||||||
|
muted = status['muted']
|
||||||
acct = status['account']['acct']
|
acct = status['account']['acct']
|
||||||
|
acct_id = status['account']['id']
|
||||||
content = status['pleroma']['content']['text/plain']
|
content = status['pleroma']['content']['text/plain']
|
||||||
|
|
||||||
if id_st in replyed: # Игнорировать уже отвеченное
|
if id_st in replyed: # Игнорировать уже отвеченное
|
||||||
continue
|
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 = parse_links(content)
|
||||||
parsed_result_imdb = parse_links_imdb(content)
|
parsed_result_imdb = parse_links_imdb(content)
|
||||||
|
|
||||||
|
@ -80,6 +92,7 @@ def scan_context_thread():
|
||||||
if poll_created:
|
if poll_created:
|
||||||
post_status(f'ℹ️ Приём заявок уже окончен.\n\nГолосовалка здесь: https://{instance}/notice/{poll_created}', id_st)
|
post_status(f'ℹ️ Приём заявок уже окончен.\n\nГолосовалка здесь: https://{instance}/notice/{poll_created}', id_st)
|
||||||
logger.info(f'{acct} был уведомлен о завершенной голосовалке')
|
logger.info(f'{acct} был уведомлен о завершенной голосовалке')
|
||||||
|
fail_limit[acct] += 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if parsed_result is not None:
|
if parsed_result is not None:
|
||||||
|
@ -100,10 +113,12 @@ def scan_context_thread():
|
||||||
logger.debug(str(movie))
|
logger.debug(str(movie))
|
||||||
if movie[index_type] == "404":
|
if movie[index_type] == "404":
|
||||||
message_writer.append("❌ Не найдено.")
|
message_writer.append("❌ Не найдено.")
|
||||||
|
fail_limit[acct] += 1
|
||||||
elif movie[index_type] not in ("movie", "FILM", "video"):
|
elif movie[index_type] not in ("movie", "FILM", "video"):
|
||||||
type_of_title = movie[index_type]
|
type_of_title = movie[index_type]
|
||||||
message_writer.append(f"❌ Не принято:\n- Нам не подходят: сериалы, короткометражные и документальные фильмы")
|
message_writer.append(f"❌ Не принято:\n- Нам не подходят: сериалы, короткометражные и документальные фильмы")
|
||||||
logger.info(f'Предложение {acct} отклонено: не подходящий тип фильма: {type_of_title}')
|
logger.info(f'Предложение {acct} отклонено: не подходящий тип фильма: {type_of_title}')
|
||||||
|
fail_limit[acct] += 1
|
||||||
else:
|
else:
|
||||||
|
|
||||||
name = movie[index_name]
|
name = movie[index_name]
|
||||||
|
@ -119,6 +134,7 @@ def scan_context_thread():
|
||||||
if get_suggested_movies_count() >= limit_all_movies_poll:
|
if get_suggested_movies_count() >= limit_all_movies_poll:
|
||||||
post_status('🎬 Мы не можем обработать ваше предложение: количество уже предложенных не помещается в лимит голосовалки.', id_st)
|
post_status('🎬 Мы не можем обработать ваше предложение: количество уже предложенных не помещается в лимит голосовалки.', id_st)
|
||||||
logger.warning(f'Предложение {acct} было отклонено: количество уже предложенных фильмов превышает\равно {limit_all_movies_poll}')
|
logger.warning(f'Предложение {acct} было отклонено: количество уже предложенных фильмов превышает\равно {limit_all_movies_poll}')
|
||||||
|
fail_limit[acct] += 1
|
||||||
break
|
break
|
||||||
|
|
||||||
if get_already_watched(name, name_ru, year) == True:
|
if get_already_watched(name, name_ru, year) == True:
|
||||||
|
@ -132,6 +148,7 @@ def scan_context_thread():
|
||||||
else:
|
else:
|
||||||
post_status("❌ Вы не можете добавить больше 2х фильмов", id_st)
|
post_status("❌ Вы не можете добавить больше 2х фильмов", id_st)
|
||||||
logger.info(f'Предложение от {acct} было отлонено - лимит на пользователя')
|
logger.info(f'Предложение от {acct} было отлонено - лимит на пользователя')
|
||||||
|
fail_limit[acct] += 1
|
||||||
if message_writer != []:
|
if message_writer != []:
|
||||||
post_status('\n'.join(message_writer) + "\nБлагодарим за ваше предложение!", id_st)
|
post_status('\n'.join(message_writer) + "\nБлагодарим за ваше предложение!", id_st)
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from src.fedi_api import get_notifications, mark_as_read_notification, post_status, upload_attachment
|
from src.fedi_api import get_notifications, mark_as_read_notification, post_status, upload_attachment
|
||||||
from src.fmn_states_db import add_state, get_state
|
from src.fmn_states_db import add_state, get_state
|
||||||
from config import admins_bot, limit_movies_per_user, limit_all_movies_poll, hour_poll_posting
|
from config import admins_bot, limit_movies_per_user, limit_all_movies_poll, hour_poll_posting, fmn_next_watching_hour
|
||||||
|
|
||||||
import threading, time
|
import threading, time
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
@ -28,9 +28,10 @@ def get_control_mention():
|
||||||
st_date = i['status']['created_at']
|
st_date = i['status']['created_at']
|
||||||
thread_created_at = dateutilparse(st_date)
|
thread_created_at = dateutilparse(st_date)
|
||||||
delta = relativedelta(hour=hour_poll_posting, minute=0, second=0, weekday=TU(1))
|
delta = relativedelta(hour=hour_poll_posting, minute=0, second=0, weekday=TU(1))
|
||||||
next_movie_watching_delta = relativedelta(hour=21, minute=0, second=0, weekday=SU(1))
|
next_movie_watching_delta = relativedelta(hour=fmn_next_watching_hour, minute=0, second=0, weekday=SU(1))
|
||||||
stop_thread_scan = thread_created_at + delta
|
stop_thread_scan = thread_created_at + delta
|
||||||
next_movie_watching = thread_created_at + next_movie_watching_delta
|
next_movie_watching = thread_created_at + next_movie_watching_delta
|
||||||
|
max_mute_time = time.mktime(time.struct_time(next_movie_watching.timetuple()))
|
||||||
next_movie_watching = next_movie_watching.strftime('%d.%m.%Y')
|
next_movie_watching = next_movie_watching.strftime('%d.%m.%Y')
|
||||||
movies_accept_time = stop_thread_scan.strftime('%H:%M %d.%m.%Y MSK')
|
movies_accept_time = stop_thread_scan.strftime('%H:%M %d.%m.%Y MSK')
|
||||||
stop_thread_scan = time.mktime(time.struct_time(stop_thread_scan.timetuple()))
|
stop_thread_scan = time.mktime(time.struct_time(stop_thread_scan.timetuple()))
|
||||||
|
@ -38,6 +39,7 @@ def get_control_mention():
|
||||||
post_status(start_collect_movies_text(movies_accept_time, next_movie_watching), st_id, attachments=[upload_attachment('src/FMN.png')])
|
post_status(start_collect_movies_text(movies_accept_time, next_movie_watching), st_id, attachments=[upload_attachment('src/FMN.png')])
|
||||||
time.sleep(0.2)
|
time.sleep(0.2)
|
||||||
mark_as_read_notification(i['id'])
|
mark_as_read_notification(i['id'])
|
||||||
|
add_state('max_mute_time', int(max_mute_time))
|
||||||
add_state('stop_thread_scan', int(stop_thread_scan))
|
add_state('stop_thread_scan', int(stop_thread_scan))
|
||||||
add_state('last_thread_id', st_id)
|
add_state('last_thread_id', st_id)
|
||||||
break
|
break
|
||||||
|
|
Loading…
Reference in a new issue