Compare commits
14 Commits
Author | SHA1 | Date |
---|---|---|
localhost_frssoft | 63f94ed574 | |
localhost_frssoft | c96056f9a4 | |
localhost_frssoft | e86d9829b0 | |
localhost_frssoft | 81c13c3c96 | |
localhost_frssoft | 6414cd863b | |
localhost_frssoft | 176c25f200 | |
localhost_frssoft | 8f07ed7f70 | |
localhost_frssoft | 00f2dc33fb | |
localhost_frssoft | 00b80493f7 | |
localhost_frssoft | b58f39bfe1 | |
localhost_frssoft | 0bdb95ee30 | |
localhost_frssoft | 885bfb5a53 | |
localhost_frssoft | b166016df8 | |
localhost_frssoft | 3eebf7266c |
|
@ -0,0 +1,5 @@
|
||||||
|
# Avalaible mirrors
|
||||||
|
https://inex.dev/localhost_frssoft/FMN_bot.git
|
||||||
|
https://git.macaw.me/localhost_frssoft/FMN_bot.git
|
||||||
|
https://code.criminallycute.fi/localhost_frssoft/FMN_bot.git
|
||||||
|
https://git.poridge.club/localhost_frssoft/FMN_bot.git
|
|
@ -50,9 +50,10 @@ Note: Рекомендуется использовать ссылки на imdb
|
||||||
Note2: Список доступных для приёма инстансов libremdb обновляется вручную и может не соотвествовать официальному.
|
Note2: Список доступных для приёма инстансов libremdb обновляется вручную и может не соотвествовать официальному.
|
||||||
|
|
||||||
## Список поддерживаемых инстансов libremdb:
|
## Список поддерживаемых инстансов libremdb:
|
||||||
* https://libremdb.herokuapp.com
|
* https://libremdb.leemoon.network/ (Спасибо [Саре](https://lamp.leemoon.network/@sarahquartz) в рамках self-host проекта [Leemoon Network 🍋](https://leemoon.network))
|
||||||
* https://libremdb.pussthecat.org
|
* https://libremdb.herokuapp.com/
|
||||||
* https://libremdbeu.herokuapp.com
|
* https://libremdb.pussthecat.org/
|
||||||
|
* https://libremdbeu.herokuapp.com/
|
||||||
* https://lmdb.tokhmi.xyz/
|
* https://lmdb.tokhmi.xyz/
|
||||||
* https://libremdb.esmailelbob.xyz/
|
* https://libremdb.esmailelbob.xyz/
|
||||||
* http://libremdb.lqs5fjmajyp7rvp4qvyubwofzi6d4imua7vs237rkc4m5qogitqwrgyd.onion/
|
* http://libremdb.lqs5fjmajyp7rvp4qvyubwofzi6d4imua7vs237rkc4m5qogitqwrgyd.onion/
|
||||||
|
|
BIN
src/FMN.png
BIN
src/FMN.png
Binary file not shown.
Before Width: | Height: | Size: 788 KiB |
Binary file not shown.
After Width: | Height: | Size: 98 KiB |
Binary file not shown.
After Width: | Height: | Size: 154 KiB |
|
@ -1,6 +1,5 @@
|
||||||
from config import instance
|
from config import instance
|
||||||
import time
|
import time
|
||||||
import json
|
|
||||||
import requests
|
import requests
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
||||||
|
@ -35,7 +34,6 @@ def get_notifications():
|
||||||
logger.info('Retrying get notificatios...')
|
logger.info('Retrying get notificatios...')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def mark_as_read_notification(id_notification):
|
def mark_as_read_notification(id_notification):
|
||||||
success = 0
|
success = 0
|
||||||
while success == 0:
|
while success == 0:
|
||||||
|
@ -51,18 +49,22 @@ def mark_as_read_notification(id_notification):
|
||||||
|
|
||||||
|
|
||||||
def get_status_context(status_id):
|
def get_status_context(status_id):
|
||||||
|
retry = 0
|
||||||
success = 0
|
success = 0
|
||||||
while success == 0:
|
while success == 0:
|
||||||
try:
|
try:
|
||||||
r = s.get(instance_point + f"/statuses/{status_id}/context")
|
r = s.get(instance_point + f"/statuses/{status_id}/context", timeout=30)
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
success = 1
|
success = 1
|
||||||
return r.json()
|
return r.json()
|
||||||
except:
|
except Exception as E:
|
||||||
logger.exception(f'Ошибка получения контекста треда {status_id}')
|
logger.exception(f'Ошибка получения контекста треда {status_id}')
|
||||||
time.sleep(30)
|
time.sleep(30)
|
||||||
logger.info('Повторный запрос треда...')
|
logger.info('Повторный запрос треда...')
|
||||||
|
retry += 1
|
||||||
|
if retry > 5:
|
||||||
|
raise IOError(f'Фетчинг треда поломан! {E}')
|
||||||
|
|
||||||
|
|
||||||
def get_status(status_id):
|
def get_status(status_id):
|
||||||
success = 0
|
success = 0
|
||||||
|
@ -78,7 +80,6 @@ def get_status(status_id):
|
||||||
logger.info(f'Retrying get status {status_id}')
|
logger.info(f'Retrying get status {status_id}')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def post_status(text, reply_to_status_id=None, poll_options=None, poll_expires=345600, attachments=None):
|
def post_status(text, reply_to_status_id=None, poll_options=None, poll_expires=345600, attachments=None):
|
||||||
poll = None
|
poll = None
|
||||||
if poll_options is not None:
|
if poll_options is not None:
|
||||||
|
@ -116,17 +117,9 @@ def upload_attachment(file_path):
|
||||||
params = {
|
params = {
|
||||||
"description": "Fediverse Movie Night\nВоскресенье, 21:00\nLIVE ON XXIV Production",
|
"description": "Fediverse Movie Night\nВоскресенье, 21:00\nLIVE ON XXIV Production",
|
||||||
}
|
}
|
||||||
success = 0
|
r = s.post(instance_point + "/media", params, files=file, timeout=30)
|
||||||
while success == 0:
|
r.raise_for_status()
|
||||||
try:
|
return r.json()['id']
|
||||||
r = s.post(instance_point + "/media", params, files=file)
|
|
||||||
r.raise_for_status()
|
|
||||||
success = 1
|
|
||||||
return r.json()['id']
|
|
||||||
except:
|
|
||||||
logger.exception(f'Error uploading {file_path} attachment')
|
|
||||||
time.sleep(5)
|
|
||||||
logger.info(f'Retrying upload {file_path}...')
|
|
||||||
|
|
||||||
|
|
||||||
def mute_user(acct_id=str, acct=str, duration=None):
|
def mute_user(acct_id=str, acct=str, duration=None):
|
||||||
|
@ -144,4 +137,3 @@ def mute_user(acct_id=str, acct=str, duration=None):
|
||||||
logger.exception(f'Ошибка глушения {acct}')
|
logger.exception(f'Ошибка глушения {acct}')
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
logger.info(f'Повторное глушение {acct}...')
|
logger.info(f'Повторное глушение {acct}...')
|
||||||
|
|
||||||
|
|
|
@ -113,4 +113,3 @@ def reset_poll():
|
||||||
'''Сброс содержимого предложки-опроса'''
|
'''Сброс содержимого предложки-опроса'''
|
||||||
c.execute("DELETE FROM poll")
|
c.execute("DELETE FROM poll")
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from src.fedi_api import get_status, post_status, upload_attachment
|
from src.fedi_api import get_status, post_status, upload_attachment
|
||||||
from src.fmn_states_db import read_states, write_states
|
from src.fmn_states_db import states_stor, write_states
|
||||||
from src.fmn_database import get_movies_for_poll, write_votes, read_votes, mark_as_watched_movie, get_already_watched, rewrite_db, reset_poll, get_count_all_watched_movies, force_commit
|
from src.fmn_database import get_movies_for_poll, write_votes, read_votes, mark_as_watched_movie, get_already_watched, rewrite_db, reset_poll, get_count_all_watched_movies, force_commit
|
||||||
from collections import Counter
|
from collections import Counter
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
@ -16,7 +16,9 @@ def text_create_poll():
|
||||||
return text_poll
|
return text_poll
|
||||||
|
|
||||||
|
|
||||||
|
@logger.catch
|
||||||
def create_poll_movies(text=text_create_poll(), poll_expires=345600):
|
def create_poll_movies(text=text_create_poll(), poll_expires=345600):
|
||||||
|
logger.debug('Creating poll')
|
||||||
formated_poll_options = []
|
formated_poll_options = []
|
||||||
raw_poll = get_movies_for_poll()
|
raw_poll = get_movies_for_poll()
|
||||||
for i in raw_poll:
|
for i in raw_poll:
|
||||||
|
@ -25,6 +27,7 @@ def create_poll_movies(text=text_create_poll(), poll_expires=345600):
|
||||||
ru_name = i[2]
|
ru_name = i[2]
|
||||||
year = i[3]
|
year = i[3]
|
||||||
poll_option_string = f"{ru_name} / {orig_name}, {year} ({acct})"
|
poll_option_string = f"{ru_name} / {orig_name}, {year} ({acct})"
|
||||||
|
logger.debug(f"Adding option in poll: {poll_option_string}")
|
||||||
if ru_name is None:
|
if ru_name is None:
|
||||||
poll_option_string = f"{orig_name}, {year} ({acct})"
|
poll_option_string = f"{orig_name}, {year} ({acct})"
|
||||||
if orig_name is None:
|
if orig_name is None:
|
||||||
|
@ -33,19 +36,25 @@ def create_poll_movies(text=text_create_poll(), poll_expires=345600):
|
||||||
poll_option_string = poll_option_string[0:199] # Обрезка на 200 символов.
|
poll_option_string = poll_option_string[0:199] # Обрезка на 200 символов.
|
||||||
formated_poll_options.append(poll_option_string)
|
formated_poll_options.append(poll_option_string)
|
||||||
|
|
||||||
|
attaches = []
|
||||||
|
try:
|
||||||
|
attaches = [upload_attachment('src/FMN.webp')]
|
||||||
|
except Exception as E:
|
||||||
|
logger.error(f"attachements can't do upload: {E}")
|
||||||
|
|
||||||
poll_status_id = post_status(text, None, formated_poll_options,
|
poll_status_id = post_status(text, None, formated_poll_options,
|
||||||
poll_expires=poll_expires, attachments=[upload_attachment('src/FMN.png')])
|
poll_expires=poll_expires, attachments=attaches)
|
||||||
logger.success('Голосовалка создана')
|
logger.success('Голосовалка создана')
|
||||||
states = read_states()
|
states_stor.states['poll_expires_at'] = int(time.time()) + poll_expires
|
||||||
states['poll_expires_at'] = int(time.time()) + poll_expires
|
states_stor.states['poll_status_id'] = poll_status_id['id']
|
||||||
states['poll_status_id'] = poll_status_id['id']
|
write_states(states_stor.states)
|
||||||
write_states(states)
|
|
||||||
return poll_status_id
|
return poll_status_id
|
||||||
|
|
||||||
|
|
||||||
|
@logger.catch
|
||||||
def get_winner_movie(poll_status_id=str):
|
def get_winner_movie(poll_status_id=str):
|
||||||
'''Отмечаем победивший фильм на голосовании как просмотренный или постим tie breaker'''
|
'''Отмечаем победивший фильм на голосовании как просмотренный или постим tie breaker'''
|
||||||
states = read_states()
|
states = states_stor.states
|
||||||
votes_counters = []
|
votes_counters = []
|
||||||
status_with_poll = get_status(poll_status_id)
|
status_with_poll = get_status(poll_status_id)
|
||||||
poll = status_with_poll['poll']
|
poll = status_with_poll['poll']
|
||||||
|
@ -53,7 +62,7 @@ def get_winner_movie(poll_status_id=str):
|
||||||
for option in poll['options']:
|
for option in poll['options']:
|
||||||
votes_count = option['votes_count']
|
votes_count = option['votes_count']
|
||||||
votes_counters.append(votes_count)
|
votes_counters.append(votes_count)
|
||||||
|
|
||||||
write_votes(votes_counters)
|
write_votes(votes_counters)
|
||||||
voted_movies = read_votes()
|
voted_movies = read_votes()
|
||||||
max_vote = voted_movies[0][4]
|
max_vote = voted_movies[0][4]
|
||||||
|
@ -83,19 +92,19 @@ def get_winner_movie(poll_status_id=str):
|
||||||
text_winned = f"{expired_poll_count} голосование завершилось! Победил вариант предложенный @{acct_suggested}:\n{win_variant}"
|
text_winned = f"{expired_poll_count} голосование завершилось! Победил вариант предложенный @{acct_suggested}:\n{win_variant}"
|
||||||
|
|
||||||
logger.success("Победил " + str(movie))
|
logger.success("Победил " + str(movie))
|
||||||
post_status(text_winned, attachments=[upload_attachment('src/FMN.png')])
|
post_status(text_winned, attachments=[upload_attachment('src/FMN.webp')])
|
||||||
|
states_stor.states = {}
|
||||||
write_states()
|
write_states()
|
||||||
reset_poll()
|
reset_poll()
|
||||||
|
|
||||||
|
|
||||||
|
@logger.catch
|
||||||
def create_tie_breaker(count_tie=1):
|
def create_tie_breaker(count_tie=1):
|
||||||
'''Создание tie breaker'''
|
'''Создание tie breaker'''
|
||||||
if count_tie == 1:
|
if count_tie == 1:
|
||||||
states = read_states()
|
states_stor.states['tie_breaker'] = 1
|
||||||
states['tie_breaker'] = 1
|
write_states(states_stor.states)
|
||||||
write_states(states)
|
|
||||||
poll_expires = 8*60*60
|
poll_expires = 8*60*60
|
||||||
else:
|
else:
|
||||||
poll_expires = 4*60*60
|
poll_expires = 4*60*60
|
||||||
tie_poll = create_poll_movies("TIE BREAKER!!!\n\nВыбираем из победителей!", poll_expires)
|
tie_poll = create_poll_movies("TIE BREAKER!!!\n\nВыбираем из победителей!", poll_expires)
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,11 @@ from loguru import logger
|
||||||
|
|
||||||
states_file = 'fmn_states.json'
|
states_file = 'fmn_states.json'
|
||||||
|
|
||||||
|
|
||||||
|
class states_stor:
|
||||||
|
states = None
|
||||||
|
|
||||||
|
|
||||||
@logger.catch
|
@logger.catch
|
||||||
def read_states():
|
def read_states():
|
||||||
try:
|
try:
|
||||||
|
@ -16,10 +21,13 @@ def read_states():
|
||||||
|
|
||||||
|
|
||||||
@logger.catch
|
@logger.catch
|
||||||
def write_states(states={}):
|
def write_states(new_states={}):
|
||||||
with open(states_file, 'wt') as f:
|
with open(states_file, 'wt') as f:
|
||||||
f.write(json.dumps(states, indent=4))
|
f.write(json.dumps(new_states, indent=4))
|
||||||
if states == {}:
|
if new_states == {}:
|
||||||
logger.info('states empty wrote')
|
logger.info('states empty wrote')
|
||||||
return states
|
return new_states
|
||||||
|
|
||||||
|
|
||||||
|
if not states_stor.states:
|
||||||
|
states_stor.states = read_states()
|
||||||
|
|
|
@ -3,13 +3,10 @@ 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.kinopoisk_api import get_kinopoisk_movie_to_imdb
|
||||||
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 read_states, write_states
|
from src.fmn_states_db import states_stor
|
||||||
from src.fmn_poll import create_poll_movies, get_winner_movie
|
from src.fmn_poll import create_poll_movies, get_winner_movie
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
from datetime import datetime
|
|
||||||
from dateutil.parser import parse as dateutilparse
|
|
||||||
from dateutil.relativedelta import relativedelta, TU
|
|
||||||
from collections import Counter
|
from collections import Counter
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
||||||
|
@ -23,24 +20,24 @@ def parse_links(text=str):
|
||||||
|
|
||||||
|
|
||||||
def parse_links_imdb(text=str):
|
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/"
|
regex = r"imdb\.com/|libremdb\.leemoon\.network/|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):
|
if re.search(regex, text.lower(), flags=re.MULTILINE):
|
||||||
imdb_ids = re.findall(r"tt(\d{1,})", text.lower())
|
imdb_ids = re.findall(r"tt(\d{1,})", text.lower())
|
||||||
if imdb_ids != []:
|
if imdb_ids != []:
|
||||||
return imdb_ids[:limit_movies_per_user]
|
return imdb_ids[:limit_movies_per_user]
|
||||||
|
|
||||||
|
|
||||||
def scan_context_thread():
|
def scan_context_thread():
|
||||||
fail_limit = Counter()
|
fail_limit = Counter()
|
||||||
while True:
|
while True:
|
||||||
states = read_states()
|
states = states_stor.states
|
||||||
status_id = states.get('last_thread_id')
|
status_id = states.get('last_thread_id')
|
||||||
poll_created = states.get('poll_status_id')
|
poll_created = states.get('poll_status_id')
|
||||||
stop_thread_scan = states.get('stop_thread_scan')
|
stop_thread_scan = states.get('stop_thread_scan')
|
||||||
time_now = int(time.time())
|
time_now = int(time.time())
|
||||||
reserve_time = False
|
reserve_time = False
|
||||||
while status_id is None or stop_thread_scan is None:
|
while status_id is None or stop_thread_scan is None:
|
||||||
states = read_states()
|
states = states_stor.states
|
||||||
fail_limit = Counter()
|
fail_limit = Counter()
|
||||||
status_id = states.get('last_thread_id')
|
status_id = states.get('last_thread_id')
|
||||||
stop_thread_scan = states.get('stop_thread_scan')
|
stop_thread_scan = states.get('stop_thread_scan')
|
||||||
|
@ -51,14 +48,14 @@ def scan_context_thread():
|
||||||
logger.debug('Сбор завершён, сканирование треда на опоздавших')
|
logger.debug('Сбор завершён, сканирование треда на опоздавших')
|
||||||
if poll_created is None:
|
if poll_created is None:
|
||||||
create_poll_movies()
|
create_poll_movies()
|
||||||
poll_created = states.get('poll_status_id')
|
poll_created = states_stor.states.get('poll_status_id')
|
||||||
else:
|
else:
|
||||||
if time_now >= int(states.get('poll_expires_at')):
|
if time_now >= int(states.get('poll_expires_at')):
|
||||||
get_winner_movie(poll_created)
|
get_winner_movie(poll_created)
|
||||||
else:
|
else:
|
||||||
endings = int(stop_thread_scan) - time_now
|
endings = int(stop_thread_scan) - time_now
|
||||||
logger.debug(f'Осталось до закрытия сбора: {endings}')
|
logger.debug(f'Осталось до закрытия сбора: {endings}')
|
||||||
if reserve_time: # Reduce instance load
|
if reserve_time: # Reduce instance load
|
||||||
time.sleep(30)
|
time.sleep(30)
|
||||||
get_thread_time = time.time()
|
get_thread_time = time.time()
|
||||||
descendants = get_status_context(status_id)['descendants']
|
descendants = get_status_context(status_id)['descendants']
|
||||||
|
@ -72,6 +69,10 @@ def scan_context_thread():
|
||||||
|
|
||||||
for status in descendants:
|
for status in descendants:
|
||||||
id_st = status['id']
|
id_st = status['id']
|
||||||
|
visibility = status['visibility']
|
||||||
|
if visibility == 'direct':
|
||||||
|
# Игнорируем личку
|
||||||
|
continue
|
||||||
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']
|
muted = status['muted']
|
||||||
|
@ -79,14 +80,14 @@ def scan_context_thread():
|
||||||
acct_id = status['account']['id']
|
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:
|
if muted is True:
|
||||||
continue
|
continue
|
||||||
if fail_limit[acct] >= max_fail_limit: # Игнорировать пользователя если он превысил fail limit
|
if fail_limit[acct] >= max_fail_limit: # Игнорировать пользователя если он превысил fail limit
|
||||||
mute_user(acct_id, acct, int(states.get('max_mute_time')) - time_now)
|
mute_user(acct_id, acct, int(states.get('max_mute_time')) - time_now)
|
||||||
logger.warning(f'{acct} игнорируется - превышение fail limit')
|
logger.warning(f'{acct} игнорируется - превышение fail limit')
|
||||||
break # Нужно обновить тред, чтобы muted на заглушенном стал True
|
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)
|
||||||
|
@ -99,23 +100,34 @@ def scan_context_thread():
|
||||||
logger.info(f'{acct} был уведомлен о завершенной голосовалке')
|
logger.info(f'{acct} был уведомлен о завершенной голосовалке')
|
||||||
fail_limit[acct] += 1
|
fail_limit[acct] += 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
index_type = 1
|
index_type = 1
|
||||||
index_name = 2
|
index_name = 2
|
||||||
index_ru_name = 3
|
index_ru_name = 3
|
||||||
index_year = 4
|
index_year = 4
|
||||||
|
|
||||||
|
message_writer = []
|
||||||
|
success = False
|
||||||
|
if parsed_result and parsed_result_imdb:
|
||||||
|
post_status('❌ Не смешивайте IMDB и кинопоиск в одном посте, пожалуйста.', id_st)
|
||||||
|
fail_limit[acct] += 1
|
||||||
|
continue
|
||||||
if parsed_result is not None:
|
if parsed_result is not None:
|
||||||
print(parsed_result)
|
print(parsed_result)
|
||||||
suggested_movies = get_kinopoisk_movie_to_imdb(parsed_result)
|
suggested_movies = get_kinopoisk_movie_to_imdb(parsed_result)
|
||||||
|
message_writer.append('⚠️ внимание при использовании Кинопоиска стабильность может быть понижена')
|
||||||
if suggested_movies is None:
|
if suggested_movies is None:
|
||||||
post_status('❌ Не удалось выполнить запрос: возможно некорректный тип фильма, попробуйте использовать imdb.com', id_st)
|
post_status('❌ Не удалось выполнить запрос: возможно некорректный тип фильма, попробуйте использовать https://libremdb.leemoon.network', id_st)
|
||||||
fail_limit[acct] += 1
|
fail_limit[acct] += 1
|
||||||
continue
|
continue
|
||||||
elif parsed_result_imdb is not None:
|
elif parsed_result_imdb is not None:
|
||||||
suggested_movies = get_title_by_id(parsed_result_imdb)
|
suggested_movies = get_title_by_id(parsed_result_imdb)
|
||||||
|
|
||||||
message_writer = []
|
if suggested_movies is None:
|
||||||
success = False
|
post_status('❌ Фильм(ы) не найден в базе данных IMDB, пожалуйста обратитесь к администратору, чтобы обновить базу. Примечание: IMDB выкладывает новые изменения не сразу.', id_st)
|
||||||
|
fail_limit[acct] += 1
|
||||||
|
continue
|
||||||
|
|
||||||
for movie in suggested_movies:
|
for movie in suggested_movies:
|
||||||
logger.debug(str(movie))
|
logger.debug(str(movie))
|
||||||
if movie[index_type] == "404":
|
if movie[index_type] == "404":
|
||||||
|
@ -132,7 +144,7 @@ def scan_context_thread():
|
||||||
name_ru = movie[index_ru_name]
|
name_ru = movie[index_ru_name]
|
||||||
year = movie[index_year]
|
year = movie[index_year]
|
||||||
movie_string = f"{name_ru} / {name}, {year}"
|
movie_string = f"{name_ru} / {name}, {year}"
|
||||||
|
|
||||||
if name is None:
|
if name is None:
|
||||||
movie_string = f"{name_ru}, {year}"
|
movie_string = f"{name_ru}, {year}"
|
||||||
if name_ru is None:
|
if name_ru is None:
|
||||||
|
@ -146,8 +158,8 @@ def scan_context_thread():
|
||||||
logger.warning(f'Предложение {acct} было отклонено: количество уже предложенных фильмов превышает\равно {limit_all_movies_poll}')
|
logger.warning(f'Предложение {acct} было отклонено: количество уже предложенных фильмов превышает\равно {limit_all_movies_poll}')
|
||||||
fail_limit[acct] += 1
|
fail_limit[acct] += 1
|
||||||
break
|
break
|
||||||
|
|
||||||
if get_already_watched(name, name_ru, year) == True:
|
if get_already_watched(name, name_ru, year) is True:
|
||||||
message_writer.append(f"ℹ️ Этот фильм уже был на FMN: {movie_string}")
|
message_writer.append(f"ℹ️ Этот фильм уже был на FMN: {movie_string}")
|
||||||
logger.info(f'Попытка предложить уже просмотренный фильм: {acct} {name} {name_ru} {year}')
|
logger.info(f'Попытка предложить уже просмотренный фильм: {acct} {name} {name_ru} {year}')
|
||||||
fail_limit[acct] += 1
|
fail_limit[acct] += 1
|
||||||
|
@ -173,5 +185,3 @@ def scan_context_thread():
|
||||||
post_status('\n'.join(message_writer) + message, id_st)
|
post_status('\n'.join(message_writer) + message, id_st)
|
||||||
|
|
||||||
time.sleep(30)
|
time.sleep(30)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,24 +1,27 @@
|
||||||
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 write_states, read_states
|
from src.fmn_states_db import write_states, states_stor
|
||||||
from config import admins_bot, limit_movies_per_user, limit_all_movies_poll, hour_poll_posting, fmn_next_watching_hour
|
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
|
||||||
|
import time
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from dateutil.parser import parse as dateutilparse
|
from dateutil.parser import parse as dateutilparse
|
||||||
from dateutil.relativedelta import relativedelta, TU, SU
|
from dateutil.relativedelta import relativedelta, TU, SU
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
||||||
|
|
||||||
|
@logger.catch
|
||||||
def get_control_mention():
|
def get_control_mention():
|
||||||
while True:
|
while True:
|
||||||
states = read_states()
|
states = states_stor.states
|
||||||
time.sleep(30)
|
time.sleep(30)
|
||||||
time_now = datetime.now()
|
time_now = datetime.now()
|
||||||
now_week = time_now.weekday()
|
now_week = time_now.weekday()
|
||||||
now_hour = time_now.hour
|
now_hour = time_now.hour
|
||||||
if now_week not in (0, 6):
|
if now_week not in (0, 6):
|
||||||
continue
|
continue
|
||||||
if now_week == 6 and now_hour < fmn_next_watching_hour: # Предотвращение работы в холстую до начала сеанса
|
if now_week == 6 and now_hour < fmn_next_watching_hour:
|
||||||
|
# Предотвращение работы в холстую до начала сеанса
|
||||||
continue
|
continue
|
||||||
post_exists = states.get('last_thread_id')
|
post_exists = states.get('last_thread_id')
|
||||||
if post_exists:
|
if post_exists:
|
||||||
|
@ -26,12 +29,12 @@ def get_control_mention():
|
||||||
logger.debug('Wait for from admin mention...')
|
logger.debug('Wait for from admin mention...')
|
||||||
notif = get_notifications()
|
notif = get_notifications()
|
||||||
for i in notif:
|
for i in notif:
|
||||||
if i['type'] != "mention":
|
if i['type'] not in ("mention"):
|
||||||
continue
|
continue
|
||||||
seen = i['pleroma']['is_seen']
|
seen = i['pleroma']['is_seen']
|
||||||
acct_mention = i['account']['acct']
|
acct_mention = i['account']['acct']
|
||||||
reply_to_id = i['status']['in_reply_to_id']
|
reply_to_id = i['status']['in_reply_to_id']
|
||||||
if acct_mention in admins_bot and seen == False and reply_to_id == None and now_week in (0, 6):
|
if acct_mention in admins_bot and seen is False and reply_to_id is None and now_week in (0, 6):
|
||||||
logger.success(f'Найдено упоминание от {acct_mention}')
|
logger.success(f'Найдено упоминание от {acct_mention}')
|
||||||
st_id = i['status']['id']
|
st_id = i['status']['id']
|
||||||
st_date = i['status']['created_at']
|
st_date = i['status']['created_at']
|
||||||
|
@ -41,7 +44,7 @@ def get_control_mention():
|
||||||
stop_thread_scan = thread_created_at + delta
|
stop_thread_scan = thread_created_at + delta
|
||||||
movies_accept_time = stop_thread_scan.strftime('%H:%M %d.%m.%Y по Москве')
|
movies_accept_time = stop_thread_scan.strftime('%H:%M %d.%m.%Y по Москве')
|
||||||
stop_thread_scan = time.mktime(time.struct_time(stop_thread_scan.timetuple()))
|
stop_thread_scan = time.mktime(time.struct_time(stop_thread_scan.timetuple()))
|
||||||
|
|
||||||
if now_week == 6: # Фикс стыков двух недель. Если вс, то расчитываем на следующую неделю
|
if now_week == 6: # Фикс стыков двух недель. Если вс, то расчитываем на следующую неделю
|
||||||
next_week = 2
|
next_week = 2
|
||||||
else:
|
else:
|
||||||
|
@ -50,15 +53,15 @@ def get_control_mention():
|
||||||
next_movie_watching = time_now + next_movie_watching_delta
|
next_movie_watching = time_now + next_movie_watching_delta
|
||||||
max_mute_time = time.mktime(time.struct_time(next_movie_watching.timetuple())) # Глушение до следующего сеанса FMN.
|
max_mute_time = time.mktime(time.struct_time(next_movie_watching.timetuple())) # Глушение до следующего сеанса FMN.
|
||||||
next_movie_watching = next_movie_watching.strftime('%d.%m.%Y')
|
next_movie_watching = next_movie_watching.strftime('%d.%m.%Y')
|
||||||
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.webp')])
|
||||||
|
|
||||||
time.sleep(0.2)
|
time.sleep(0.2)
|
||||||
mark_as_read_notification(i['id'])
|
mark_as_read_notification(i['id'])
|
||||||
|
|
||||||
states['max_mute_time'] = int(max_mute_time)
|
states_stor.states['max_mute_time'] = int(max_mute_time)
|
||||||
states['stop_thread_scan'] = int(stop_thread_scan)
|
states_stor.states['stop_thread_scan'] = int(stop_thread_scan)
|
||||||
states['last_thread_id'] = st_id
|
states_stor.states['last_thread_id'] = st_id
|
||||||
write_states(states)
|
write_states(states_stor.states)
|
||||||
break
|
break
|
||||||
time.sleep(30)
|
time.sleep(30)
|
||||||
|
|
||||||
|
@ -69,19 +72,20 @@ def start_collect_movies_text(movies_accept_time=str, next_movie_watching=str):
|
||||||
|
|
||||||
Напоминаем правила:
|
Напоминаем правила:
|
||||||
- Мы принимаем на просмотр полнометражные художественные фильмы;
|
- Мы принимаем на просмотр полнометражные художественные фильмы;
|
||||||
- Прием варианта осуществляется путем публикации ссылки на этот фильм на IMDB (libremdb) или Кинопоиске в этом треде;
|
- Прием варианта осуществляется путем публикации ссылки на этот фильм на IMDB https://libremdb.leemoon.network/ или Кинопоиске в этом треде;
|
||||||
- Нам не подходят: сериалы, короткометражные и документальные фильмы;
|
- Нам не подходят: сериалы, короткометражные и документальные фильмы;
|
||||||
- Максимальное количество вариантов, предложенных одним человеком не должно превышать {limit_movies_per_user};
|
- Максимальное количество вариантов, предложенных одним человеком не должно превышать {limit_movies_per_user};
|
||||||
- Всего может быть собрано до {limit_all_movies_poll} фильмов;
|
- Всего может быть собрано до {limit_all_movies_poll} фильмов;
|
||||||
- Заявки принимаются до крайнего срока, после чего будет объявлено голосование по собранным вариантам.
|
- Заявки принимаются до крайнего срока, после чего будет объявлено голосование по собранным вариантам.
|
||||||
|
|
||||||
Крайний срок подачи заявки - {movies_accept_time}.
|
Крайний срок подачи заявки - {movies_accept_time}.
|
||||||
|
Рекомендуем посетить список, чтобы случайно не предложить уже просмотренный фильм: https://pub.phreedom.club/~localhost/fmn_watched.gmi
|
||||||
|
|
||||||
Желаем удачи.
|
Желаем удачи.
|
||||||
'''.replace('\t', '')
|
'''.replace('\t', '')
|
||||||
return text
|
return text
|
||||||
|
|
||||||
|
|
||||||
def run_scan_notif():
|
def run_scan_notif():
|
||||||
scan_notif = threading.Thread(target=get_control_mention, daemon=True)
|
scan_notif = threading.Thread(target=get_control_mention, daemon=True)
|
||||||
scan_notif.start()
|
scan_notif.start()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue