# coding=utf-8 import os import hashlib import requests import logging import json import pretty from datetime import datetime from operator import itemgetter from app.get_providers import get_enabled_providers from app.database import TableAnnouncements, database, insert, select from .get_args import args from sonarr.info import get_sonarr_info from radarr.info import get_radarr_info from app.check_update import deprecated_python_version # Announcements as receive by browser must be in the form of a list of dicts converted to JSON # [ # { # 'text': 'some text', # 'link': 'http://to.somewhere.net', # 'hash': '', # 'dismissible': True, # 'timestamp': 1676236978, # 'enabled': True, # }, # ] def parse_announcement_dict(announcement_dict): announcement_dict['timestamp'] = pretty.date(announcement_dict['timestamp']) announcement_dict['link'] = announcement_dict.get('link', '') announcement_dict['dismissible'] = announcement_dict.get('dismissible', True) announcement_dict['enabled'] = announcement_dict.get('enabled', True) announcement_dict['hash'] = hashlib.sha256(announcement_dict['text'].encode('UTF8')).hexdigest() return announcement_dict def get_announcements_to_file(): try: r = requests.get("https://raw.githubusercontent.com/morpheus65535/bazarr-binaries/master/announcements.json", timeout=10) except requests.exceptions.HTTPError: logging.exception("Error trying to get announcements from Github. Http error.") except requests.exceptions.ConnectionError: logging.exception("Error trying to get announcements from Github. Connection Error.") except requests.exceptions.Timeout: logging.exception("Error trying to get announcements from Github. Timeout Error.") except requests.exceptions.RequestException: logging.exception("Error trying to get announcements from Github.") else: with open(os.path.join(args.config_dir, 'config', 'announcements.json'), 'wb') as f: f.write(r.content) def get_online_announcements(): try: with open(os.path.join(args.config_dir, 'config', 'announcements.json'), 'r') as f: data = json.load(f) except (OSError, json.JSONDecodeError): return [] else: for announcement in data['data']: if 'enabled' not in announcement: data['data'][announcement]['enabled'] = True if 'dismissible' not in announcement: data['data'][announcement]['dismissible'] = True return data['data'] def get_local_announcements(): announcements = [] # opensubtitles.org end-of-life enabled_providers = get_enabled_providers() if enabled_providers and 'opensubtitles' in enabled_providers: announcements.append({ 'text': 'Opensubtitles.org will be deprecated soon, migrate to Opensubtitles.com ASAP and disable this ' 'provider to remove this announcement.', 'link': 'https://wiki.bazarr.media/Troubleshooting/OpenSubtitles-migration/', 'dismissible': False, 'timestamp': 1676236978, }) # deprecated Sonarr and Radarr versions if get_sonarr_info.is_deprecated(): announcements.append({ 'text': f'Sonarr {get_sonarr_info.version()} is deprecated and unsupported. You should consider upgrading ' f'as Bazarr will eventually drop support for deprecated Sonarr version.', 'link': 'https://forums.sonarr.tv/t/v3-is-now-officially-stable-v2-is-eol/27858', 'dismissible': False, 'timestamp': 1679606061, }) if get_radarr_info.is_deprecated(): announcements.append({ 'text': f'Radarr {get_radarr_info.version()} is deprecated and unsupported. You should consider upgrading ' f'as Bazarr will eventually drop support for deprecated Radarr version.', 'link': 'https://discord.com/channels/264387956343570434/264388019585286144/1051567458697363547', 'dismissible': False, 'timestamp': 1679606309, }) # deprecated Python versions if deprecated_python_version(): announcements.append({ 'text': 'Starting with Bazarr 1.4, support for Python 3.7 will get dropped. Upgrade your current version of' ' Python ASAP to get further updates.', 'dismissible': False, 'timestamp': 1691162383, }) for announcement in announcements: if 'enabled' not in announcement: announcement['enabled'] = True if 'dismissible' not in announcement: announcement['dismissible'] = True return announcements def get_all_announcements(): # get announcements that haven't been dismissed yet announcements = [parse_announcement_dict(x) for x in get_online_announcements() + get_local_announcements() if x['enabled'] and (not x['dismissible'] or not database.execute( select(TableAnnouncements) .where(TableAnnouncements.hash == hashlib.sha256(x['text'].encode('UTF8')).hexdigest())) .first())] return sorted(announcements, key=itemgetter('timestamp'), reverse=True) def mark_announcement_as_dismissed(hashed_announcement): text = [x['text'] for x in get_all_announcements() if x['hash'] == hashed_announcement] if text: database.execute( insert(TableAnnouncements) .values(hash=hashed_announcement, timestamp=datetime.now(), text=text[0]) .on_conflict_do_nothing())