2023-01-12 01:04:47 +00:00
|
|
|
|
#
|
|
|
|
|
# This file is part of SickGear.
|
|
|
|
|
#
|
|
|
|
|
# SickGear is free software: you can redistribute it and/or modify
|
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
# (at your option) any later version.
|
|
|
|
|
#
|
|
|
|
|
# SickGear is distributed in the hope that it will be useful,
|
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
|
#
|
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
|
# along with SickGear. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
from collections import OrderedDict
|
|
|
|
|
from threading import Lock
|
|
|
|
|
|
2024-06-28 01:57:31 +00:00
|
|
|
|
import copy
|
2023-01-12 01:04:47 +00:00
|
|
|
|
import datetime
|
|
|
|
|
import io
|
|
|
|
|
import os
|
|
|
|
|
import re
|
|
|
|
|
import signal
|
|
|
|
|
import socket
|
2023-06-28 13:49:39 +00:00
|
|
|
|
import time
|
2023-01-12 01:04:47 +00:00
|
|
|
|
import webbrowser
|
|
|
|
|
|
|
|
|
|
# apparently py2exe won't build these unless they're imported somewhere
|
|
|
|
|
import os.path
|
|
|
|
|
import sys
|
|
|
|
|
import threading
|
|
|
|
|
import uuid
|
|
|
|
|
import zlib
|
|
|
|
|
|
|
|
|
|
from . import classes, db, helpers, image_cache, indexermapper, logger, metadata, naming, people_queue, providers, \
|
|
|
|
|
scene_exceptions, scene_numbering, scheduler, search_backlog, search_propers, search_queue, search_recent, \
|
2023-02-13 21:00:11 +00:00
|
|
|
|
show_queue, show_updater, subtitles, trakt_helpers, version_checker, watchedstate_queue
|
2023-03-16 04:19:03 +00:00
|
|
|
|
from . import auto_media_process, properFinder # must come after the above imports
|
2023-01-12 01:04:47 +00:00
|
|
|
|
from .common import SD, SKIPPED, USER_AGENT
|
|
|
|
|
from .config import check_section, check_setting_int, check_setting_str, ConfigMigrator, minimax
|
|
|
|
|
from .databases import cache_db, failed_db, mainDB
|
2024-06-28 01:57:31 +00:00
|
|
|
|
from .event_queue import ConfigEvents
|
2023-01-12 01:04:47 +00:00
|
|
|
|
from .indexers.indexer_api import TVInfoAPI
|
|
|
|
|
from .indexers.indexer_config import TVINFO_IMDB, TVINFO_TVDB, TmdbIndexer
|
|
|
|
|
from .providers.generic import GenericProvider
|
|
|
|
|
from .providers.newznab import NewznabConstants
|
|
|
|
|
from .tv import TVidProdid
|
|
|
|
|
from .watchedstate import EmbyWatchedStateUpdater, PlexWatchedStateUpdater
|
|
|
|
|
from .webserve import History
|
|
|
|
|
|
|
|
|
|
from adba.aniDBerrors import AniDBError
|
|
|
|
|
# noinspection PyProtectedMember
|
|
|
|
|
from browser_ua import get_ua
|
|
|
|
|
from configobj import ConfigObj
|
|
|
|
|
from api_trakt import TraktAPI
|
|
|
|
|
|
2023-02-11 18:02:58 +00:00
|
|
|
|
from _23 import b64encodestring, decode_bytes, scandir
|
2023-06-28 13:49:39 +00:00
|
|
|
|
from sg_helpers import remove_file_perm
|
2023-02-11 18:02:58 +00:00
|
|
|
|
from six import iteritems, string_types
|
2023-01-12 01:04:47 +00:00
|
|
|
|
import sg_helpers
|
|
|
|
|
|
|
|
|
|
# noinspection PyUnreachableCode
|
|
|
|
|
if False:
|
2023-03-16 04:19:03 +00:00
|
|
|
|
from typing import AnyStr, Dict, List, Optional
|
2023-01-12 01:04:47 +00:00
|
|
|
|
from adba import Connection
|
|
|
|
|
from .event_queue import Events
|
|
|
|
|
from .tv import TVShow
|
|
|
|
|
from lib.api_trakt.trakt import TraktAccount
|
|
|
|
|
|
|
|
|
|
PID = None
|
|
|
|
|
ENV = {}
|
|
|
|
|
|
|
|
|
|
# noinspection PyTypeChecker
|
|
|
|
|
CFG = None # type: ConfigObj
|
|
|
|
|
CONFIG_FILE = ''
|
|
|
|
|
CONFIG_VERSION = None
|
2024-06-28 01:57:31 +00:00
|
|
|
|
CONFIG_OLD = None
|
2024-08-12 20:33:28 +00:00
|
|
|
|
CONFIG_LOADED = False
|
2023-01-12 01:04:47 +00:00
|
|
|
|
|
|
|
|
|
# Default encryption version (0 for None)
|
|
|
|
|
ENCRYPTION_VERSION = 0
|
|
|
|
|
|
|
|
|
|
PROG_DIR = '.'
|
|
|
|
|
MY_FULLNAME = None
|
|
|
|
|
MY_ARGS = []
|
|
|
|
|
SYS_ENCODING = ''
|
|
|
|
|
DATA_DIR = ''
|
|
|
|
|
|
|
|
|
|
# system events
|
|
|
|
|
# noinspection PyTypeChecker
|
|
|
|
|
events = None # type: Events
|
2024-06-28 01:57:31 +00:00
|
|
|
|
config_events = None # type: ConfigEvents
|
2023-01-12 01:04:47 +00:00
|
|
|
|
|
2023-03-16 04:19:03 +00:00
|
|
|
|
show_queue_scheduler = None # type: Optional[scheduler.Scheduler]
|
|
|
|
|
search_queue_scheduler = None # type: Optional[scheduler.Scheduler]
|
|
|
|
|
people_queue_scheduler = None # type: Optional[scheduler.Scheduler]
|
|
|
|
|
watched_state_queue_scheduler = None # type: Optional[scheduler.Scheduler]
|
|
|
|
|
update_software_scheduler = None # type: Optional[scheduler.Scheduler]
|
|
|
|
|
update_packages_scheduler = None # type: Optional[scheduler.Scheduler]
|
|
|
|
|
update_show_scheduler = None # type: Optional[scheduler.Scheduler]
|
|
|
|
|
update_release_mappings_scheduler = None # type: Optional[scheduler.Scheduler]
|
|
|
|
|
search_recent_scheduler = None # type: Optional[scheduler.Scheduler]
|
|
|
|
|
search_backlog_scheduler = None # type: Optional[search_backlog.BacklogSearchScheduler]
|
|
|
|
|
search_propers_scheduler = None # type: Optional[scheduler.Scheduler]
|
|
|
|
|
search_subtitles_scheduler = None # type: Optional[scheduler.Scheduler]
|
|
|
|
|
emby_watched_state_scheduler = None # type: Optional[scheduler.Scheduler]
|
|
|
|
|
plex_watched_state_scheduler = None # type: Optional[scheduler.Scheduler]
|
|
|
|
|
process_media_scheduler = None # type: Optional[scheduler.Scheduler]
|
2023-01-12 01:04:47 +00:00
|
|
|
|
# noinspection PyTypeChecker
|
|
|
|
|
background_mapping_task = None # type: threading.Thread
|
2023-03-16 04:19:03 +00:00
|
|
|
|
# deprecated
|
|
|
|
|
# trakt_checker_scheduler = None
|
2023-01-12 01:04:47 +00:00
|
|
|
|
|
|
|
|
|
provider_ping_thread_pool = {}
|
|
|
|
|
|
|
|
|
|
showList = [] # type: List[TVShow]
|
|
|
|
|
showDict = {} # type: Dict[int, TVShow]
|
|
|
|
|
switched_shows = {} # type: Dict[AnyStr, AnyStr]
|
|
|
|
|
UPDATE_SHOWS_ON_START = False
|
|
|
|
|
SHOW_UPDATE_HOUR = 3
|
|
|
|
|
|
|
|
|
|
# non ui settings
|
|
|
|
|
REMOVE_FILENAME_CHARS = None
|
|
|
|
|
IMPORT_DEFAULT_CHECKED_SHOWS = 0
|
|
|
|
|
# /non ui settings
|
|
|
|
|
|
2023-02-13 21:00:11 +00:00
|
|
|
|
provider_list = []
|
|
|
|
|
newznab_providers = []
|
|
|
|
|
torrent_rss_providers = []
|
2023-01-12 01:04:47 +00:00
|
|
|
|
metadata_provider_dict = {}
|
|
|
|
|
|
|
|
|
|
MODULE_UPDATE_STRING = None
|
|
|
|
|
NEWEST_VERSION_STRING = None
|
|
|
|
|
|
|
|
|
|
MIN_UPDATE_INTERVAL = 1
|
|
|
|
|
DEFAULT_UPDATE_INTERVAL = 12
|
|
|
|
|
UPDATE_NOTIFY = False
|
|
|
|
|
UPDATE_AUTO = False
|
|
|
|
|
UPDATE_INTERVAL = DEFAULT_UPDATE_INTERVAL
|
|
|
|
|
NOTIFY_ON_UPDATE = False
|
|
|
|
|
|
|
|
|
|
MIN_UPDATE_PACKAGES_INTERVAL = 1
|
|
|
|
|
MAX_UPDATE_PACKAGES_INTERVAL = 9999
|
|
|
|
|
DEFAULT_UPDATE_PACKAGES_INTERVAL = 24
|
|
|
|
|
UPDATE_PACKAGES_NOTIFY = False
|
|
|
|
|
UPDATE_PACKAGES_AUTO = False
|
|
|
|
|
UPDATE_PACKAGES_MENU = False
|
|
|
|
|
UPDATE_PACKAGES_INTERVAL = DEFAULT_UPDATE_PACKAGES_INTERVAL
|
|
|
|
|
|
|
|
|
|
CUR_COMMIT_HASH = None
|
|
|
|
|
EXT_UPDATES = False
|
|
|
|
|
BRANCH = ''
|
|
|
|
|
GIT_REMOTE = ''
|
|
|
|
|
CUR_COMMIT_BRANCH = ''
|
|
|
|
|
|
|
|
|
|
INIT_LOCK = Lock()
|
|
|
|
|
started = False
|
|
|
|
|
|
|
|
|
|
ACTUAL_LOG_DIR = None
|
|
|
|
|
LOG_DIR = None
|
|
|
|
|
FILE_LOGGING_PRESET = 'DEBUG'
|
|
|
|
|
|
|
|
|
|
SOCKET_TIMEOUT = None
|
|
|
|
|
|
|
|
|
|
WEB_PORT = None
|
|
|
|
|
WEB_LOG = 0
|
|
|
|
|
WEB_ROOT = None
|
|
|
|
|
WEB_USERNAME = None
|
|
|
|
|
WEB_PASSWORD = None
|
|
|
|
|
WEB_HOST = None
|
|
|
|
|
WEB_IPV6 = 0
|
|
|
|
|
WEB_IPV64 = 0
|
|
|
|
|
|
|
|
|
|
HANDLE_REVERSE_PROXY = False
|
|
|
|
|
SEND_SECURITY_HEADERS = True
|
|
|
|
|
ALLOWED_HOSTS = None
|
|
|
|
|
ALLOW_ANYIP = True
|
|
|
|
|
PROXY_SETTING = None
|
|
|
|
|
PROXY_INDEXERS = True
|
|
|
|
|
|
|
|
|
|
CPU_PRESET = 'DISABLED'
|
|
|
|
|
|
|
|
|
|
ANON_REDIRECT = None
|
|
|
|
|
|
|
|
|
|
USE_API = False
|
|
|
|
|
API_KEYS = []
|
|
|
|
|
|
|
|
|
|
ENABLE_HTTPS = False
|
|
|
|
|
HTTPS_CERT = None
|
|
|
|
|
HTTPS_KEY = None
|
|
|
|
|
|
|
|
|
|
LAUNCH_BROWSER = False
|
|
|
|
|
CACHE_DIR = None
|
|
|
|
|
ACTUAL_CACHE_DIR = None
|
|
|
|
|
ZONEINFO_DIR = None
|
|
|
|
|
ROOT_DIRS = None
|
|
|
|
|
TRASH_REMOVE_SHOW = False
|
|
|
|
|
TRASH_ROTATE_LOGS = False
|
|
|
|
|
HOME_SEARCH_FOCUS = True
|
|
|
|
|
DISPLAY_FREESPACE = True
|
|
|
|
|
SORT_ARTICLE = False
|
|
|
|
|
DEBUG = False
|
|
|
|
|
SHOW_TAGS = []
|
|
|
|
|
SHOW_TAG_DEFAULT = ''
|
|
|
|
|
SHOWLIST_TAGVIEW = ''
|
|
|
|
|
|
|
|
|
|
METADATA_XBMC = None
|
|
|
|
|
METADATA_XBMC_12PLUS = None
|
|
|
|
|
METADATA_MEDIABROWSER = None
|
|
|
|
|
METADATA_PS3 = None
|
|
|
|
|
METADATA_WDTV = None
|
|
|
|
|
METADATA_TIVO = None
|
|
|
|
|
METADATA_MEDE8ER = None
|
|
|
|
|
METADATA_KODI = None
|
|
|
|
|
|
|
|
|
|
RESULTS_SORTBY = None
|
|
|
|
|
|
|
|
|
|
TVINFO_DEFAULT = 0
|
|
|
|
|
TVINFO_TIMEOUT = 20
|
|
|
|
|
QUALITY_DEFAULT = SD
|
|
|
|
|
WANTED_BEGIN_DEFAULT = 0
|
|
|
|
|
WANTED_LATEST_DEFAULT = 0
|
|
|
|
|
PAUSE_DEFAULT = False
|
|
|
|
|
STATUS_DEFAULT = SKIPPED
|
|
|
|
|
SCENE_DEFAULT = False
|
|
|
|
|
SUBTITLES_DEFAULT = False
|
|
|
|
|
FLATTEN_FOLDERS_DEFAULT = False
|
|
|
|
|
ANIME_DEFAULT = False
|
|
|
|
|
USE_IMDB_INFO = True
|
|
|
|
|
IMDB_ACCOUNTS = []
|
|
|
|
|
IMDB_DEFAULT_LIST_ID = '64552276'
|
|
|
|
|
IMDB_DEFAULT_LIST_NAME = 'SickGear'
|
|
|
|
|
PROVIDER_ORDER = []
|
|
|
|
|
PROVIDER_HOMES = {}
|
|
|
|
|
|
|
|
|
|
NAMING_MULTI_EP = False
|
|
|
|
|
NAMING_ANIME_MULTI_EP = False
|
|
|
|
|
NAMING_PATTERN = None
|
|
|
|
|
NAMING_ABD_PATTERN = None
|
|
|
|
|
NAMING_CUSTOM_ABD = False
|
|
|
|
|
NAMING_SPORTS_PATTERN = None
|
|
|
|
|
NAMING_CUSTOM_SPORTS = False
|
|
|
|
|
NAMING_ANIME_PATTERN = None
|
|
|
|
|
NAMING_CUSTOM_ANIME = False
|
|
|
|
|
NAMING_FORCE_FOLDERS = False
|
|
|
|
|
NAMING_STRIP_YEAR = False
|
|
|
|
|
NAMING_ANIME = 3
|
|
|
|
|
|
|
|
|
|
USE_NZBS = False
|
|
|
|
|
USE_TORRENTS = False
|
|
|
|
|
|
|
|
|
|
NZB_METHOD = None
|
|
|
|
|
NZB_DIR = None
|
|
|
|
|
USENET_RETENTION = 500
|
|
|
|
|
TORRENT_METHOD = None
|
|
|
|
|
TORRENT_DIR = None
|
|
|
|
|
DOWNLOAD_PROPERS = False
|
|
|
|
|
PROPERS_WEBDL_ONEGRP = True
|
|
|
|
|
WEBDL_TYPES = []
|
|
|
|
|
ALLOW_HIGH_PRIORITY = False
|
|
|
|
|
NEWZNAB_DATA = ''
|
|
|
|
|
|
|
|
|
|
DEFAULT_MEDIAPROCESS_INTERVAL = 10
|
|
|
|
|
DEFAULT_BACKLOG_PERIOD = 21
|
|
|
|
|
DEFAULT_RECENTSEARCH_INTERVAL = 40
|
|
|
|
|
DEFAULT_WATCHEDSTATE_INTERVAL = 10
|
|
|
|
|
|
|
|
|
|
MEDIAPROCESS_INTERVAL = DEFAULT_MEDIAPROCESS_INTERVAL
|
|
|
|
|
BACKLOG_PERIOD = DEFAULT_BACKLOG_PERIOD
|
|
|
|
|
BACKLOG_LIMITED_PERIOD = 7
|
|
|
|
|
RECENTSEARCH_INTERVAL = DEFAULT_RECENTSEARCH_INTERVAL
|
|
|
|
|
|
|
|
|
|
RECENTSEARCH_STARTUP = False
|
|
|
|
|
BACKLOG_NOFULL = False
|
|
|
|
|
|
|
|
|
|
MIN_MEDIAPROCESS_INTERVAL = 1
|
|
|
|
|
MIN_RECENTSEARCH_INTERVAL = 10
|
|
|
|
|
MIN_BACKLOG_PERIOD = 7
|
|
|
|
|
MAX_BACKLOG_PERIOD = 42
|
|
|
|
|
MIN_WATCHEDSTATE_INTERVAL = 10
|
|
|
|
|
MAX_WATCHEDSTATE_INTERVAL = 60
|
|
|
|
|
|
|
|
|
|
SEARCH_UNAIRED = False
|
|
|
|
|
UNAIRED_RECENT_SEARCH_ONLY = True
|
|
|
|
|
FLARESOLVERR_HOST = None
|
|
|
|
|
|
|
|
|
|
ADD_SHOWS_WO_DIR = False
|
|
|
|
|
ADD_SHOWS_METALANG = 'en'
|
|
|
|
|
CREATE_MISSING_SHOW_DIRS = False
|
|
|
|
|
SHOW_DIRS_WITH_DOTS = False
|
|
|
|
|
RENAME_EPISODES = False
|
2023-04-29 18:18:00 +00:00
|
|
|
|
RENAME_TBA_EPISODES = True
|
|
|
|
|
RENAME_NAME_CHANGED_EPISODES = False
|
2023-01-12 01:04:47 +00:00
|
|
|
|
AIRDATE_EPISODES = False
|
|
|
|
|
PROCESS_AUTOMATICALLY = False
|
|
|
|
|
KEEP_PROCESSED_DIR = False
|
|
|
|
|
PROCESS_LAST_DIR = None
|
|
|
|
|
PROCESS_LAST_METHOD = None
|
|
|
|
|
PROCESS_LAST_CLEANUP = False
|
|
|
|
|
PROCESS_METHOD = None
|
|
|
|
|
MOVE_ASSOCIATED_FILES = False
|
|
|
|
|
POSTPONE_IF_SYNC_FILES = True
|
2023-04-16 00:31:51 +00:00
|
|
|
|
PROCESS_POSITIVE_LOG = True
|
2023-01-12 01:04:47 +00:00
|
|
|
|
NFO_RENAME = True
|
|
|
|
|
TV_DOWNLOAD_DIR = None
|
|
|
|
|
UNPACK = False
|
|
|
|
|
SKIP_REMOVED_FILES = False
|
|
|
|
|
|
|
|
|
|
NZBGET_USERNAME = None
|
|
|
|
|
NZBGET_PASSWORD = None
|
|
|
|
|
NZBGET_CATEGORY = None
|
|
|
|
|
NZBGET_HOST = None
|
|
|
|
|
NZBGET_USE_HTTPS = False
|
|
|
|
|
NZBGET_PRIORITY = 100
|
|
|
|
|
NZBGET_SCRIPT_VERSION = None
|
|
|
|
|
NZBGET_MAP = None
|
|
|
|
|
NZBGET_SKIP_PM = False
|
|
|
|
|
|
|
|
|
|
SAB_USERNAME = None
|
|
|
|
|
SAB_PASSWORD = None
|
|
|
|
|
SAB_APIKEY = None
|
|
|
|
|
SAB_CATEGORY = None
|
|
|
|
|
SAB_HOST = ''
|
|
|
|
|
|
|
|
|
|
TORRENT_USERNAME = None
|
|
|
|
|
TORRENT_PASSWORD = None
|
|
|
|
|
TORRENT_HOST = ''
|
|
|
|
|
TORRENT_PATH = ''
|
|
|
|
|
TORRENT_SEED_TIME = 0
|
|
|
|
|
TORRENT_PAUSED = False
|
|
|
|
|
TORRENT_HIGH_BANDWIDTH = False
|
|
|
|
|
TORRENT_LABEL = ''
|
|
|
|
|
TORRENT_LABEL_VAR = 1
|
|
|
|
|
TORRENT_VERIFY_CERT = False
|
|
|
|
|
|
|
|
|
|
USE_EMBY = False
|
|
|
|
|
EMBY_UPDATE_LIBRARY = False
|
|
|
|
|
EMBY_PARENT_MAPS = None
|
|
|
|
|
EMBY_HOST = None
|
|
|
|
|
EMBY_APIKEY = None
|
|
|
|
|
EMBY_WATCHEDSTATE_SCHEDULED = False
|
|
|
|
|
EMBY_WATCHEDSTATE_INTERVAL = DEFAULT_WATCHEDSTATE_INTERVAL
|
|
|
|
|
|
|
|
|
|
USE_KODI = False
|
|
|
|
|
KODI_ALWAYS_ON = True
|
|
|
|
|
KODI_NOTIFY_ONSNATCH = False
|
|
|
|
|
KODI_NOTIFY_ONDOWNLOAD = False
|
|
|
|
|
KODI_NOTIFY_ONSUBTITLEDOWNLOAD = False
|
|
|
|
|
KODI_UPDATE_LIBRARY = False
|
|
|
|
|
KODI_UPDATE_FULL = False
|
|
|
|
|
KODI_UPDATE_ONLYFIRST = False
|
|
|
|
|
KODI_PARENT_MAPS = None
|
|
|
|
|
KODI_HOST = ''
|
|
|
|
|
KODI_USERNAME = None
|
|
|
|
|
KODI_PASSWORD = None
|
|
|
|
|
|
|
|
|
|
USE_PLEX = False
|
|
|
|
|
PLEX_NOTIFY_ONSNATCH = False
|
|
|
|
|
PLEX_NOTIFY_ONDOWNLOAD = False
|
|
|
|
|
PLEX_NOTIFY_ONSUBTITLEDOWNLOAD = False
|
|
|
|
|
PLEX_UPDATE_LIBRARY = False
|
|
|
|
|
PLEX_PARENT_MAPS = None
|
|
|
|
|
PLEX_SERVER_HOST = None
|
|
|
|
|
PLEX_HOST = None
|
|
|
|
|
PLEX_USERNAME = None
|
|
|
|
|
PLEX_PASSWORD = None
|
|
|
|
|
PLEX_WATCHEDSTATE_SCHEDULED = False
|
|
|
|
|
PLEX_WATCHEDSTATE_INTERVAL = DEFAULT_WATCHEDSTATE_INTERVAL
|
|
|
|
|
|
|
|
|
|
USE_XBMC = False
|
|
|
|
|
XBMC_ALWAYS_ON = True
|
|
|
|
|
XBMC_NOTIFY_ONSNATCH = False
|
|
|
|
|
XBMC_NOTIFY_ONDOWNLOAD = False
|
|
|
|
|
XBMC_NOTIFY_ONSUBTITLEDOWNLOAD = False
|
|
|
|
|
XBMC_UPDATE_LIBRARY = False
|
|
|
|
|
XBMC_UPDATE_FULL = False
|
|
|
|
|
XBMC_UPDATE_ONLYFIRST = False
|
|
|
|
|
XBMC_HOST = ''
|
|
|
|
|
XBMC_USERNAME = None
|
|
|
|
|
XBMC_PASSWORD = None
|
|
|
|
|
|
|
|
|
|
QUEUE_UPDATE_LIBRARY = []
|
|
|
|
|
|
|
|
|
|
USE_NMJ = False
|
|
|
|
|
NMJ_HOST = None
|
|
|
|
|
NMJ_DATABASE = None
|
|
|
|
|
NMJ_MOUNT = None
|
|
|
|
|
|
|
|
|
|
USE_NMJv2 = False
|
|
|
|
|
NMJv2_HOST = None
|
|
|
|
|
NMJv2_DATABASE = None
|
|
|
|
|
NMJv2_DBLOC = None
|
|
|
|
|
|
|
|
|
|
USE_SYNOINDEX = False
|
|
|
|
|
SYNOINDEX_UPDATE_LIBRARY = True
|
|
|
|
|
|
|
|
|
|
USE_SYNOLOGYNOTIFIER = False
|
|
|
|
|
SYNOLOGYNOTIFIER_NOTIFY_ONSNATCH = False
|
|
|
|
|
SYNOLOGYNOTIFIER_NOTIFY_ONDOWNLOAD = False
|
|
|
|
|
SYNOLOGYNOTIFIER_NOTIFY_ONSUBTITLEDOWNLOAD = False
|
|
|
|
|
|
|
|
|
|
USE_PYTIVO = False
|
|
|
|
|
PYTIVO_HOST = ''
|
|
|
|
|
PYTIVO_SHARE_NAME = ''
|
|
|
|
|
PYTIVO_TIVO_NAME = ''
|
|
|
|
|
|
|
|
|
|
USE_BOXCAR2 = False
|
|
|
|
|
BOXCAR2_NOTIFY_ONSNATCH = False
|
|
|
|
|
BOXCAR2_NOTIFY_ONDOWNLOAD = False
|
|
|
|
|
BOXCAR2_NOTIFY_ONSUBTITLEDOWNLOAD = False
|
|
|
|
|
BOXCAR2_ACCESSTOKEN = None
|
|
|
|
|
BOXCAR2_SOUND = None
|
|
|
|
|
|
|
|
|
|
USE_PUSHBULLET = False
|
|
|
|
|
PUSHBULLET_NOTIFY_ONSNATCH = False
|
|
|
|
|
PUSHBULLET_NOTIFY_ONDOWNLOAD = False
|
|
|
|
|
PUSHBULLET_NOTIFY_ONSUBTITLEDOWNLOAD = False
|
|
|
|
|
PUSHBULLET_ACCESS_TOKEN = None
|
|
|
|
|
PUSHBULLET_DEVICE_IDEN = None
|
|
|
|
|
|
|
|
|
|
USE_PUSHOVER = False
|
|
|
|
|
PUSHOVER_NOTIFY_ONSNATCH = False
|
|
|
|
|
PUSHOVER_NOTIFY_ONDOWNLOAD = False
|
|
|
|
|
PUSHOVER_NOTIFY_ONSUBTITLEDOWNLOAD = False
|
|
|
|
|
PUSHOVER_USERKEY = None
|
|
|
|
|
PUSHOVER_APIKEY = None
|
|
|
|
|
PUSHOVER_PRIORITY = '0'
|
|
|
|
|
PUSHOVER_DEVICE = None
|
|
|
|
|
PUSHOVER_SOUND = None
|
|
|
|
|
|
|
|
|
|
USE_GROWL = False
|
|
|
|
|
GROWL_NOTIFY_ONSNATCH = False
|
|
|
|
|
GROWL_NOTIFY_ONDOWNLOAD = False
|
|
|
|
|
GROWL_NOTIFY_ONSUBTITLEDOWNLOAD = False
|
|
|
|
|
GROWL_HOST = ''
|
|
|
|
|
|
|
|
|
|
USE_PROWL = False
|
|
|
|
|
PROWL_NOTIFY_ONSNATCH = False
|
|
|
|
|
PROWL_NOTIFY_ONDOWNLOAD = False
|
|
|
|
|
PROWL_NOTIFY_ONSUBTITLEDOWNLOAD = False
|
|
|
|
|
PROWL_API = None
|
|
|
|
|
PROWL_PRIORITY = '0'
|
|
|
|
|
|
|
|
|
|
USE_LIBNOTIFY = False
|
|
|
|
|
LIBNOTIFY_NOTIFY_ONSNATCH = False
|
|
|
|
|
LIBNOTIFY_NOTIFY_ONDOWNLOAD = False
|
|
|
|
|
LIBNOTIFY_NOTIFY_ONSUBTITLEDOWNLOAD = False
|
|
|
|
|
|
|
|
|
|
USE_PUSHALOT = False
|
|
|
|
|
PUSHALOT_NOTIFY_ONSNATCH = False
|
|
|
|
|
PUSHALOT_NOTIFY_ONDOWNLOAD = False
|
|
|
|
|
PUSHALOT_NOTIFY_ONSUBTITLEDOWNLOAD = False
|
|
|
|
|
PUSHALOT_AUTHORIZATIONTOKEN = None
|
|
|
|
|
|
|
|
|
|
USE_TRAKT = False
|
|
|
|
|
TRAKT_REMOVE_WATCHLIST = False
|
|
|
|
|
TRAKT_REMOVE_SERIESLIST = False
|
|
|
|
|
TRAKT_USE_WATCHLIST = False
|
|
|
|
|
TRAKT_METHOD_ADD = 0
|
|
|
|
|
TRAKT_START_PAUSED = False
|
|
|
|
|
TRAKT_SYNC = False
|
|
|
|
|
TRAKT_DEFAULT_INDEXER = None
|
|
|
|
|
TRAKT_UPDATE_COLLECTION = {}
|
|
|
|
|
|
|
|
|
|
USE_SLACK = False
|
|
|
|
|
SLACK_NOTIFY_ONSNATCH = False
|
|
|
|
|
SLACK_NOTIFY_ONDOWNLOAD = False
|
|
|
|
|
SLACK_NOTIFY_ONSUBTITLEDOWNLOAD = False
|
|
|
|
|
SLACK_CHANNEL = None
|
|
|
|
|
SLACK_AS_AUTHED = False
|
|
|
|
|
SLACK_BOT_NAME = None
|
|
|
|
|
SLACK_ICON_URL = None
|
|
|
|
|
SLACK_ACCESS_TOKEN = None
|
|
|
|
|
|
|
|
|
|
USE_DISCORD = False
|
|
|
|
|
DISCORD_NOTIFY_ONSNATCH = False
|
|
|
|
|
DISCORD_NOTIFY_ONDOWNLOAD = False
|
|
|
|
|
DISCORD_NOTIFY_ONSUBTITLEDOWNLOAD = False
|
|
|
|
|
DISCORD_AS_AUTHED = False
|
|
|
|
|
DISCORD_USERNAME = None
|
|
|
|
|
DISCORD_ICON_URL = None
|
|
|
|
|
DISCORD_AS_TTS = 0
|
|
|
|
|
DISCORD_ACCESS_TOKEN = None
|
|
|
|
|
|
|
|
|
|
USE_GITTER = False
|
|
|
|
|
GITTER_NOTIFY_ONSNATCH = False
|
|
|
|
|
GITTER_NOTIFY_ONDOWNLOAD = False
|
|
|
|
|
GITTER_NOTIFY_ONSUBTITLEDOWNLOAD = False
|
|
|
|
|
GITTER_ROOM = None
|
|
|
|
|
GITTER_ACCESS_TOKEN = None
|
|
|
|
|
|
|
|
|
|
USE_TELEGRAM = False
|
|
|
|
|
TELEGRAM_NOTIFY_ONSNATCH = False
|
|
|
|
|
TELEGRAM_NOTIFY_ONDOWNLOAD = False
|
|
|
|
|
TELEGRAM_NOTIFY_ONSUBTITLEDOWNLOAD = False
|
|
|
|
|
TELEGRAM_SEND_IMAGE = True
|
|
|
|
|
TELEGRAM_QUIET = False
|
|
|
|
|
TELEGRAM_ACCESS_TOKEN = None
|
|
|
|
|
TELEGRAM_CHATID = None
|
|
|
|
|
|
|
|
|
|
USE_EMAIL = False
|
|
|
|
|
EMAIL_OLD_SUBJECTS = False
|
|
|
|
|
EMAIL_NOTIFY_ONSNATCH = False
|
|
|
|
|
EMAIL_NOTIFY_ONDOWNLOAD = False
|
|
|
|
|
EMAIL_NOTIFY_ONSUBTITLEDOWNLOAD = False
|
|
|
|
|
EMAIL_HOST = None
|
|
|
|
|
EMAIL_PORT = 25
|
|
|
|
|
EMAIL_TLS = False
|
|
|
|
|
EMAIL_USER = None
|
|
|
|
|
EMAIL_PASSWORD = None
|
|
|
|
|
EMAIL_FROM = None
|
|
|
|
|
EMAIL_LIST = None
|
|
|
|
|
|
|
|
|
|
USE_ANIDB = False
|
|
|
|
|
ANIDB_USERNAME = None
|
|
|
|
|
ANIDB_PASSWORD = None
|
|
|
|
|
ANIDB_USE_MYLIST = False
|
|
|
|
|
# noinspection PyTypeChecker
|
|
|
|
|
ADBA_CONNECTION = None # type: Connection
|
|
|
|
|
ANIME_TREAT_AS_HDTV = False
|
|
|
|
|
|
2023-02-10 14:15:50 +00:00
|
|
|
|
GUI_NAME = ''
|
2023-01-12 01:04:47 +00:00
|
|
|
|
DEFAULT_HOME = None
|
|
|
|
|
FANART_LIMIT = None
|
|
|
|
|
FANART_PANEL = None
|
|
|
|
|
FANART_RATINGS = {}
|
|
|
|
|
HOME_LAYOUT = None
|
|
|
|
|
FOOTER_TIME_LAYOUT = 0
|
|
|
|
|
POSTER_SORTBY = None
|
|
|
|
|
POSTER_SORTDIR = None
|
|
|
|
|
DISPLAY_SHOW_GLIDE = {}
|
|
|
|
|
DISPLAY_SHOW_GLIDE_SLIDETIME = 3000
|
|
|
|
|
DISPLAY_SHOW_VIEWMODE = 0
|
|
|
|
|
DISPLAY_SHOW_BACKGROUND = False
|
|
|
|
|
DISPLAY_SHOW_BACKGROUND_TRANSLUCENT = False
|
|
|
|
|
DISPLAY_SHOW_VIEWART = 0
|
|
|
|
|
DISPLAY_SHOW_MINIMUM = True
|
|
|
|
|
DISPLAY_SHOW_SPECIALS = False
|
|
|
|
|
EPISODE_VIEW_VIEWMODE = 0
|
|
|
|
|
EPISODE_VIEW_BACKGROUND = False
|
|
|
|
|
EPISODE_VIEW_BACKGROUND_TRANSLUCENT = False
|
|
|
|
|
EPISODE_VIEW_LAYOUT = None
|
|
|
|
|
EPISODE_VIEW_SORT = None
|
|
|
|
|
EPISODE_VIEW_DISPLAY_PAUSED = 0
|
|
|
|
|
EPISODE_VIEW_POSTERS = True
|
|
|
|
|
EPISODE_VIEW_MISSED_RANGE = 7
|
|
|
|
|
HISTORY_LAYOUT = None
|
|
|
|
|
BROWSELIST_HIDDEN = []
|
|
|
|
|
BROWSELIST_MRU = {}
|
|
|
|
|
|
|
|
|
|
FUZZY_DATING = False
|
|
|
|
|
TRIM_ZERO = False
|
|
|
|
|
DATE_PRESET = None
|
|
|
|
|
TIME_PRESET = None
|
|
|
|
|
TIME_PRESET_W_SECONDS = None
|
|
|
|
|
TIMEZONE_DISPLAY = None
|
|
|
|
|
THEME_NAME = None
|
|
|
|
|
|
|
|
|
|
USE_SUBTITLES = False
|
|
|
|
|
SUBTITLES_LANGUAGES = []
|
|
|
|
|
SUBTITLES_DIR = ''
|
|
|
|
|
SUBTITLES_OS_HASH = True
|
|
|
|
|
SUBTITLES_SERVICES_LIST = []
|
|
|
|
|
SUBTITLES_SERVICES_ENABLED = []
|
|
|
|
|
SUBTITLES_SERVICES_AUTH = [['', '']]
|
|
|
|
|
SUBTITLES_HISTORY = False
|
|
|
|
|
SUBTITLES_FINDER_INTERVAL = 1
|
|
|
|
|
|
|
|
|
|
USE_FAILED_DOWNLOADS = False
|
|
|
|
|
DELETE_FAILED = False
|
|
|
|
|
|
|
|
|
|
BACKUP_DB_PATH = '' # type: AnyStr
|
|
|
|
|
BACKUP_DB_ONEDAY = False # type: bool
|
|
|
|
|
BACKUP_DB_MAX_COUNT = 14 # type: int
|
|
|
|
|
BACKUP_DB_DEFAULT_COUNT = 14 # type: int
|
|
|
|
|
|
|
|
|
|
UPDATES_TODO = {}
|
|
|
|
|
|
|
|
|
|
EXTRA_SCRIPTS = []
|
|
|
|
|
SG_EXTRA_SCRIPTS = []
|
|
|
|
|
|
|
|
|
|
GIT_PATH = None
|
|
|
|
|
|
|
|
|
|
IGNORE_WORDS = {
|
|
|
|
|
r'^(?=.*?\bspanish\b)((?!spanish.?princess).)*$',
|
|
|
|
|
'core2hd', 'hevc', 'MrLss', 'reenc', 'x265', 'danish', 'deutsch', 'dutch', 'flemish', 'french',
|
|
|
|
|
'german', 'italian', 'nordic', 'norwegian', 'portuguese', 'spanish', 'swedish', 'turkish'
|
|
|
|
|
}
|
|
|
|
|
IGNORE_WORDS_REGEX = True
|
|
|
|
|
REQUIRE_WORDS = set()
|
|
|
|
|
REQUIRE_WORDS_REGEX = False
|
|
|
|
|
|
|
|
|
|
WANTEDLIST_CACHE = None
|
|
|
|
|
|
|
|
|
|
CALENDAR_UNPROTECTED = False
|
|
|
|
|
|
|
|
|
|
TMDB_API_KEY = TmdbIndexer.API_KEY
|
|
|
|
|
FANART_API_KEY = '3728ca1a2a937ba0c93b6e63cc86cecb'
|
|
|
|
|
|
|
|
|
|
# to switch between staging and production TRAKT environment
|
|
|
|
|
TRAKT_STAGING = False
|
|
|
|
|
|
|
|
|
|
TRAKT_TIMEOUT = 60
|
|
|
|
|
TRAKT_VERIFY = True
|
|
|
|
|
TRAKT_CONNECTED_ACCOUNT = None
|
|
|
|
|
TRAKT_ACCOUNTS = {} # type: Dict[int, TraktAccount]
|
|
|
|
|
TRAKT_MRU = ''
|
|
|
|
|
|
|
|
|
|
if TRAKT_STAGING:
|
|
|
|
|
# staging trakt values:
|
|
|
|
|
TRAKT_CLIENT_ID = '2aae3052f90b14235d184cc8f709b12b4fd8ae35f339a060a890c70db92be87a'
|
|
|
|
|
TRAKT_CLIENT_SECRET = '900e03471220503843d4a856bfbef17080cddb630f2b7df6a825e96e3ff3c39e'
|
|
|
|
|
TRAKT_PIN_URL = 'https://staging.trakt.tv/pin/638'
|
|
|
|
|
TRAKT_BASE_URL = 'http' + '://api.staging.trakt.tv/'
|
|
|
|
|
else:
|
|
|
|
|
# production trakt values:
|
|
|
|
|
TRAKT_CLIENT_ID = 'f1c453c67d81f1307f9118172c408a883eb186b094d5ea33080d59ddedb7fc7c'
|
|
|
|
|
TRAKT_CLIENT_SECRET = '12efb6fb6e863a08934d9904032a90008325df7e23514650cade55e7e7c118c5'
|
|
|
|
|
TRAKT_PIN_URL = 'https://trakt.tv/pin/6314'
|
|
|
|
|
TRAKT_BASE_URL = 'https://api.trakt.tv/'
|
|
|
|
|
|
2023-03-09 02:13:52 +00:00
|
|
|
|
IMDB_MRU = ''
|
2023-01-12 01:04:47 +00:00
|
|
|
|
MC_MRU = ''
|
2023-03-09 02:13:52 +00:00
|
|
|
|
NE_MRU = ''
|
|
|
|
|
TMDB_MRU = ''
|
2023-01-12 01:04:47 +00:00
|
|
|
|
TVC_MRU = ''
|
Fix py2 deprecation cleanups added exclusively by TvdbV4 code.
Refactor `timestamp_near` to `SGDatetime.timestamp_near`
---
Simplify enforce_type + clean_data to clean_str.
Change simplified all but one enforce_type use case.
---
Add tvdb, trakt slug tvinfo search test cases
Change direct tvdb slug search support via new api endpoint
Fix origin_countries in tvdb_api_v4.
---
Add new TV_Maze id to show obj ids in tvdb_api_v4.
Fix a bug parsing social ids for tvshows in tvdb_api_v4.
Change add language support to search API and tvdb_api_v4.
Change add `updated_at` to artwork on tvdb_api_v4.
Change add `finale` type to episodes.
Change add method `get_top_rated` to tvdb_api_v4.
optional params...
- year=... argument to get only top rated of given year, if not it's all time
Change returns result for shows until same day last year.
Add youtube, reddit, fansite, tiktok, linkedin, wikidata to tv.py
Add tiktok to indexer_config.
Add fansite to tvdb_api_v4.
Aadd fansite to TVInfoSocialIDs.
Add source type parsing and add linkein to tvdb_api_v4.
Add linkedin.
Add tiktok parser to tvdb_api_v4.
Change v4 to TVInfoIDs, TVInfoSocialIDs.
Change add new id data.
Add contentrating.
Change fill in new fields to get_person results.
----
Change implement discover endpoint in tvdb_api_v4.
Change filter '0000' year for firstaired field in tvdb_api_v4.
Change use the default_season_type from api for website fallback.
Change remove unneeded _auth_time.
Add backup fetch for episode data.
Change add multiple space remove to clean_data.
Change move _get_tvdb_id to central function.
Change fix minor warnings, code tidy + DRY.
Change remove the show-edit option `Use DVD titles and numbers` until ready with multi TVInfo source.
Add try_date and use to attempt conversion of unspecified date format types birthdate, deathdate, aired.
Change tweaks, remove one warn, order imports.
Change tidy up of other warnings, mismatched types, typos, a strange arg issue with deepcopy, and PEP8.
Bug fix, bad key in get_item for TVInfoSocialIDs.
Fix ambiguities of `show` used in sg versus external uses.
Fix add data sanitisation of image field.
Change make set_episode code more readable.
Change fix final two warnings in api v4.
Fix an API can return falsy as firstaired which crashes adding a show via load_from_tv_info() (The Andrew Marr Show@tvdbv4).
Add cast, crew type mappings
Only take Main Actors, Hosts, Interviewers, Presenters
Change increase viewagble history menu items from 13 to 15.
2021-09-05 19:10:58 +00:00
|
|
|
|
TVDB_MRU = ''
|
2023-01-12 01:04:47 +00:00
|
|
|
|
TVM_MRU = ''
|
|
|
|
|
|
|
|
|
|
COOKIE_SECRET = b64encodestring(uuid.uuid4().bytes + uuid.uuid4().bytes)
|
|
|
|
|
|
|
|
|
|
CACHE_IMAGE_URL_LIST = classes.ImageUrlList()
|
|
|
|
|
|
|
|
|
|
__INITIALIZED__ = False
|
|
|
|
|
__INIT_STAGE__ = 0
|
|
|
|
|
|
|
|
|
|
# don't reassign MEMCACHE var without reassigning sg_helpers.MEMCACHE
|
2023-03-16 04:19:03 +00:00
|
|
|
|
# and scene_exceptions.MEMCACHE
|
2023-01-12 01:04:47 +00:00
|
|
|
|
# as long as the pointer is the same (dict only modified) all is fine
|
|
|
|
|
MEMCACHE = {}
|
|
|
|
|
sg_helpers.MEMCACHE = MEMCACHE
|
2023-03-16 04:19:03 +00:00
|
|
|
|
scene_exceptions.MEMCACHE = MEMCACHE
|
2023-01-12 01:04:47 +00:00
|
|
|
|
MEMCACHE_FLAG_IMAGES = {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_backlog_cycle_time():
|
|
|
|
|
cycletime = RECENTSEARCH_INTERVAL * 2 + 7
|
|
|
|
|
return max([cycletime, 720])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def initialize(console_logging=True):
|
|
|
|
|
with INIT_LOCK:
|
|
|
|
|
|
|
|
|
|
# Misc
|
|
|
|
|
global __INITIALIZED__, __INIT_STAGE__
|
|
|
|
|
|
|
|
|
|
if __INITIALIZED__:
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
__INIT_STAGE__ += 1
|
|
|
|
|
|
|
|
|
|
if 1 == __INIT_STAGE__:
|
|
|
|
|
init_stage_1(console_logging)
|
|
|
|
|
else:
|
|
|
|
|
return init_stage_2()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def init_stage_1(console_logging):
|
|
|
|
|
|
|
|
|
|
# Misc
|
2023-02-13 21:00:11 +00:00
|
|
|
|
global showList, showDict, switched_shows, provider_list, newznab_providers, torrent_rss_providers, \
|
2023-01-12 01:04:47 +00:00
|
|
|
|
WEB_HOST, WEB_ROOT, ACTUAL_CACHE_DIR, CACHE_DIR, ZONEINFO_DIR, ADD_SHOWS_WO_DIR, ADD_SHOWS_METALANG, \
|
|
|
|
|
CREATE_MISSING_SHOW_DIRS, SHOW_DIRS_WITH_DOTS, \
|
|
|
|
|
RECENTSEARCH_STARTUP, NAMING_FORCE_FOLDERS, SOCKET_TIMEOUT, DEBUG, TVINFO_DEFAULT, \
|
2024-08-12 20:33:28 +00:00
|
|
|
|
CONFIG_FILE, CONFIG_VERSION, CONFIG_OLD, CONFIG_LOADED, \
|
2023-01-12 01:04:47 +00:00
|
|
|
|
REMOVE_FILENAME_CHARS, IMPORT_DEFAULT_CHECKED_SHOWS, WANTEDLIST_CACHE, MODULE_UPDATE_STRING, EXT_UPDATES
|
|
|
|
|
# Add Show Search
|
|
|
|
|
global RESULTS_SORTBY
|
|
|
|
|
# Add Show Defaults
|
|
|
|
|
global QUALITY_DEFAULT, WANTED_BEGIN_DEFAULT, WANTED_LATEST_DEFAULT, SHOW_TAG_DEFAULT, PAUSE_DEFAULT, \
|
|
|
|
|
STATUS_DEFAULT, SCENE_DEFAULT, SUBTITLES_DEFAULT, FLATTEN_FOLDERS_DEFAULT, ANIME_DEFAULT
|
2023-02-13 21:00:11 +00:00
|
|
|
|
# Post-processing
|
2023-01-12 01:04:47 +00:00
|
|
|
|
global KEEP_PROCESSED_DIR, PROCESS_LAST_DIR, PROCESS_LAST_METHOD, PROCESS_LAST_CLEANUP
|
|
|
|
|
# Views
|
|
|
|
|
global GUI_NAME, HOME_LAYOUT, FOOTER_TIME_LAYOUT, POSTER_SORTBY, POSTER_SORTDIR, DISPLAY_SHOW_SPECIALS, \
|
|
|
|
|
EPISODE_VIEW_LAYOUT, EPISODE_VIEW_SORT, EPISODE_VIEW_DISPLAY_PAUSED, \
|
|
|
|
|
EPISODE_VIEW_MISSED_RANGE, EPISODE_VIEW_POSTERS, FANART_PANEL, FANART_RATINGS, \
|
|
|
|
|
EPISODE_VIEW_VIEWMODE, EPISODE_VIEW_BACKGROUND, EPISODE_VIEW_BACKGROUND_TRANSLUCENT, \
|
|
|
|
|
DISPLAY_SHOW_GLIDE, DISPLAY_SHOW_GLIDE_SLIDETIME, \
|
|
|
|
|
DISPLAY_SHOW_VIEWMODE, DISPLAY_SHOW_BACKGROUND, DISPLAY_SHOW_BACKGROUND_TRANSLUCENT, \
|
|
|
|
|
DISPLAY_SHOW_VIEWART, DISPLAY_SHOW_MINIMUM, DISPLAY_SHOW_SPECIALS, HISTORY_LAYOUT, \
|
|
|
|
|
BROWSELIST_HIDDEN, BROWSELIST_MRU
|
|
|
|
|
# Gen Config/Misc
|
|
|
|
|
global LAUNCH_BROWSER, UPDATE_SHOWS_ON_START, SHOW_UPDATE_HOUR, \
|
|
|
|
|
TRASH_REMOVE_SHOW, TRASH_ROTATE_LOGS, ACTUAL_LOG_DIR, LOG_DIR, TVINFO_TIMEOUT, ROOT_DIRS, \
|
|
|
|
|
UPDATE_NOTIFY, UPDATE_AUTO, UPDATE_INTERVAL, NOTIFY_ON_UPDATE,\
|
|
|
|
|
UPDATE_PACKAGES_NOTIFY, UPDATE_PACKAGES_AUTO, UPDATE_PACKAGES_MENU, UPDATE_PACKAGES_INTERVAL
|
|
|
|
|
# Gen Config/Interface
|
|
|
|
|
global THEME_NAME, DEFAULT_HOME, FANART_LIMIT, SHOWLIST_TAGVIEW, SHOW_TAGS, \
|
|
|
|
|
HOME_SEARCH_FOCUS, USE_IMDB_INFO, IMDB_ACCOUNTS, DISPLAY_FREESPACE, SORT_ARTICLE, FUZZY_DATING, TRIM_ZERO, \
|
|
|
|
|
DATE_PRESET, TIME_PRESET, TIME_PRESET_W_SECONDS, TIMEZONE_DISPLAY, \
|
|
|
|
|
WEB_USERNAME, WEB_PASSWORD, CALENDAR_UNPROTECTED, USE_API, API_KEYS, WEB_PORT, WEB_LOG, \
|
|
|
|
|
ENABLE_HTTPS, HTTPS_CERT, HTTPS_KEY, WEB_IPV6, WEB_IPV64, HANDLE_REVERSE_PROXY, \
|
|
|
|
|
SEND_SECURITY_HEADERS, ALLOWED_HOSTS, ALLOW_ANYIP
|
|
|
|
|
# Gen Config/Advanced
|
|
|
|
|
global BRANCH, CUR_COMMIT_BRANCH, GIT_REMOTE, CUR_COMMIT_HASH, GIT_PATH, CPU_PRESET, ANON_REDIRECT, \
|
|
|
|
|
ENCRYPTION_VERSION, PROXY_SETTING, PROXY_INDEXERS, FILE_LOGGING_PRESET
|
|
|
|
|
# Search Settings/Episode
|
|
|
|
|
global DOWNLOAD_PROPERS, PROPERS_WEBDL_ONEGRP, WEBDL_TYPES, RECENTSEARCH_INTERVAL, \
|
|
|
|
|
BACKLOG_LIMITED_PERIOD, BACKLOG_NOFULL, BACKLOG_PERIOD, USENET_RETENTION, IGNORE_WORDS, REQUIRE_WORDS, \
|
|
|
|
|
IGNORE_WORDS, IGNORE_WORDS_REGEX, REQUIRE_WORDS, REQUIRE_WORDS_REGEX, \
|
|
|
|
|
ALLOW_HIGH_PRIORITY, SEARCH_UNAIRED, UNAIRED_RECENT_SEARCH_ONLY, FLARESOLVERR_HOST
|
|
|
|
|
# Search Settings/NZB search
|
|
|
|
|
global USE_NZBS, NZB_METHOD, NZB_DIR, SAB_HOST, SAB_USERNAME, SAB_PASSWORD, SAB_APIKEY, SAB_CATEGORY, \
|
|
|
|
|
NZBGET_USE_HTTPS, NZBGET_HOST, NZBGET_USERNAME, NZBGET_PASSWORD, NZBGET_CATEGORY, NZBGET_PRIORITY, \
|
|
|
|
|
NZBGET_SCRIPT_VERSION, NZBGET_MAP, NZBGET_SKIP_PM
|
|
|
|
|
# Search Settings/Torrent search
|
|
|
|
|
global USE_TORRENTS, TORRENT_METHOD, TORRENT_DIR, TORRENT_HOST, TORRENT_USERNAME, TORRENT_PASSWORD, \
|
|
|
|
|
TORRENT_LABEL, TORRENT_LABEL_VAR, TORRENT_PATH, TORRENT_SEED_TIME, TORRENT_PAUSED, \
|
|
|
|
|
TORRENT_HIGH_BANDWIDTH, TORRENT_VERIFY_CERT
|
|
|
|
|
# Media Providers
|
|
|
|
|
global PROVIDER_ORDER, NEWZNAB_DATA, PROVIDER_HOMES
|
|
|
|
|
# Subtitles
|
|
|
|
|
global USE_SUBTITLES, SUBTITLES_LANGUAGES, SUBTITLES_DIR, SUBTITLES_FINDER_INTERVAL, SUBTITLES_OS_HASH, \
|
|
|
|
|
SUBTITLES_HISTORY, SUBTITLES_SERVICES_LIST, SUBTITLES_SERVICES_ENABLED, SUBTITLES_SERVICES_AUTH
|
|
|
|
|
# Media Process/Post-Processing
|
|
|
|
|
global TV_DOWNLOAD_DIR, PROCESS_METHOD, PROCESS_AUTOMATICALLY, MEDIAPROCESS_INTERVAL, \
|
2023-04-16 00:31:51 +00:00
|
|
|
|
POSTPONE_IF_SYNC_FILES, PROCESS_POSITIVE_LOG, EXTRA_SCRIPTS, SG_EXTRA_SCRIPTS, \
|
2023-01-12 01:04:47 +00:00
|
|
|
|
DEFAULT_MEDIAPROCESS_INTERVAL, MIN_MEDIAPROCESS_INTERVAL, \
|
2023-04-30 00:07:18 +00:00
|
|
|
|
UNPACK, SKIP_REMOVED_FILES, MOVE_ASSOCIATED_FILES, NFO_RENAME, \
|
|
|
|
|
RENAME_EPISODES, RENAME_TBA_EPISODES, RENAME_NAME_CHANGED_EPISODES, \
|
|
|
|
|
AIRDATE_EPISODES, USE_FAILED_DOWNLOADS, DELETE_FAILED
|
2023-01-12 01:04:47 +00:00
|
|
|
|
# Media Process/Episode Naming
|
|
|
|
|
global NAMING_PATTERN, NAMING_MULTI_EP, NAMING_STRIP_YEAR, NAMING_CUSTOM_ABD, NAMING_ABD_PATTERN, \
|
|
|
|
|
NAMING_CUSTOM_SPORTS, NAMING_SPORTS_PATTERN, \
|
|
|
|
|
NAMING_CUSTOM_ANIME, NAMING_ANIME_PATTERN, NAMING_ANIME_MULTI_EP, NAMING_ANIME
|
|
|
|
|
# Media Process/Metadata
|
|
|
|
|
global METADATA_KODI, METADATA_MEDE8ER, METADATA_XBMC, METADATA_MEDIABROWSER, \
|
|
|
|
|
METADATA_PS3, METADATA_TIVO, METADATA_WDTV, METADATA_XBMC_12PLUS
|
|
|
|
|
# Notification Settings/HT and NAS
|
|
|
|
|
global USE_EMBY, EMBY_UPDATE_LIBRARY, EMBY_PARENT_MAPS, EMBY_HOST, EMBY_APIKEY, \
|
|
|
|
|
EMBY_WATCHEDSTATE_SCHEDULED, EMBY_WATCHEDSTATE_INTERVAL, \
|
|
|
|
|
USE_KODI, KODI_ALWAYS_ON, KODI_UPDATE_LIBRARY, KODI_UPDATE_FULL, KODI_UPDATE_ONLYFIRST, \
|
|
|
|
|
KODI_PARENT_MAPS, KODI_HOST, KODI_USERNAME, KODI_PASSWORD, KODI_NOTIFY_ONSNATCH, \
|
|
|
|
|
KODI_NOTIFY_ONDOWNLOAD, KODI_NOTIFY_ONSUBTITLEDOWNLOAD, \
|
|
|
|
|
USE_XBMC, XBMC_ALWAYS_ON, XBMC_NOTIFY_ONSNATCH, XBMC_NOTIFY_ONDOWNLOAD, XBMC_NOTIFY_ONSUBTITLEDOWNLOAD, \
|
|
|
|
|
XBMC_UPDATE_LIBRARY, XBMC_UPDATE_FULL, XBMC_UPDATE_ONLYFIRST, XBMC_HOST, XBMC_USERNAME, XBMC_PASSWORD, \
|
|
|
|
|
USE_PLEX, PLEX_USERNAME, PLEX_PASSWORD, PLEX_UPDATE_LIBRARY, PLEX_PARENT_MAPS, PLEX_SERVER_HOST, \
|
|
|
|
|
PLEX_NOTIFY_ONSNATCH, PLEX_NOTIFY_ONDOWNLOAD, PLEX_NOTIFY_ONSUBTITLEDOWNLOAD, PLEX_HOST, \
|
|
|
|
|
PLEX_WATCHEDSTATE_SCHEDULED, PLEX_WATCHEDSTATE_INTERVAL, \
|
|
|
|
|
USE_NMJ, NMJ_HOST, NMJ_DATABASE, NMJ_MOUNT, \
|
|
|
|
|
USE_NMJv2, NMJv2_HOST, NMJv2_DATABASE, NMJv2_DBLOC, \
|
|
|
|
|
USE_SYNOINDEX, \
|
|
|
|
|
USE_SYNOLOGYNOTIFIER, SYNOLOGYNOTIFIER_NOTIFY_ONSNATCH, \
|
|
|
|
|
SYNOLOGYNOTIFIER_NOTIFY_ONDOWNLOAD, SYNOLOGYNOTIFIER_NOTIFY_ONSUBTITLEDOWNLOAD, \
|
|
|
|
|
USE_PYTIVO, PYTIVO_HOST, PYTIVO_SHARE_NAME, PYTIVO_TIVO_NAME
|
|
|
|
|
# Notification Settings/Devices
|
|
|
|
|
global USE_GROWL, GROWL_NOTIFY_ONSNATCH, GROWL_NOTIFY_ONDOWNLOAD, GROWL_NOTIFY_ONSUBTITLEDOWNLOAD, \
|
|
|
|
|
GROWL_HOST, \
|
|
|
|
|
USE_PROWL, PROWL_NOTIFY_ONSNATCH, PROWL_NOTIFY_ONDOWNLOAD, PROWL_NOTIFY_ONSUBTITLEDOWNLOAD, \
|
|
|
|
|
PROWL_API, PROWL_PRIORITY, \
|
|
|
|
|
USE_LIBNOTIFY, LIBNOTIFY_NOTIFY_ONSNATCH, LIBNOTIFY_NOTIFY_ONDOWNLOAD, \
|
|
|
|
|
LIBNOTIFY_NOTIFY_ONSUBTITLEDOWNLOAD, \
|
|
|
|
|
USE_PUSHOVER, PUSHOVER_NOTIFY_ONSNATCH, PUSHOVER_NOTIFY_ONDOWNLOAD, PUSHOVER_NOTIFY_ONSUBTITLEDOWNLOAD, \
|
|
|
|
|
PUSHOVER_USERKEY, PUSHOVER_APIKEY, PUSHOVER_PRIORITY, PUSHOVER_DEVICE, PUSHOVER_SOUND, \
|
|
|
|
|
USE_BOXCAR2, BOXCAR2_NOTIFY_ONSNATCH, BOXCAR2_NOTIFY_ONDOWNLOAD, BOXCAR2_NOTIFY_ONSUBTITLEDOWNLOAD, \
|
|
|
|
|
BOXCAR2_ACCESSTOKEN, BOXCAR2_SOUND, \
|
|
|
|
|
USE_PUSHALOT, PUSHALOT_NOTIFY_ONSNATCH, PUSHALOT_NOTIFY_ONDOWNLOAD, \
|
|
|
|
|
PUSHALOT_NOTIFY_ONSUBTITLEDOWNLOAD, PUSHALOT_AUTHORIZATIONTOKEN, \
|
|
|
|
|
USE_PUSHBULLET, PUSHBULLET_NOTIFY_ONSNATCH, PUSHBULLET_NOTIFY_ONDOWNLOAD, \
|
|
|
|
|
PUSHBULLET_NOTIFY_ONSUBTITLEDOWNLOAD, PUSHBULLET_ACCESS_TOKEN, PUSHBULLET_DEVICE_IDEN
|
|
|
|
|
# Notification Settings/Social
|
|
|
|
|
global USE_TRAKT, TRAKT_CONNECTED_ACCOUNT, TRAKT_ACCOUNTS, TRAKT_MRU, TRAKT_VERIFY, \
|
|
|
|
|
TRAKT_USE_WATCHLIST, TRAKT_REMOVE_WATCHLIST, TRAKT_TIMEOUT, TRAKT_METHOD_ADD, TRAKT_START_PAUSED, \
|
|
|
|
|
TRAKT_SYNC, TRAKT_DEFAULT_INDEXER, TRAKT_REMOVE_SERIESLIST, TRAKT_UPDATE_COLLECTION, \
|
Fix py2 deprecation cleanups added exclusively by TvdbV4 code.
Refactor `timestamp_near` to `SGDatetime.timestamp_near`
---
Simplify enforce_type + clean_data to clean_str.
Change simplified all but one enforce_type use case.
---
Add tvdb, trakt slug tvinfo search test cases
Change direct tvdb slug search support via new api endpoint
Fix origin_countries in tvdb_api_v4.
---
Add new TV_Maze id to show obj ids in tvdb_api_v4.
Fix a bug parsing social ids for tvshows in tvdb_api_v4.
Change add language support to search API and tvdb_api_v4.
Change add `updated_at` to artwork on tvdb_api_v4.
Change add `finale` type to episodes.
Change add method `get_top_rated` to tvdb_api_v4.
optional params...
- year=... argument to get only top rated of given year, if not it's all time
Change returns result for shows until same day last year.
Add youtube, reddit, fansite, tiktok, linkedin, wikidata to tv.py
Add tiktok to indexer_config.
Add fansite to tvdb_api_v4.
Aadd fansite to TVInfoSocialIDs.
Add source type parsing and add linkein to tvdb_api_v4.
Add linkedin.
Add tiktok parser to tvdb_api_v4.
Change v4 to TVInfoIDs, TVInfoSocialIDs.
Change add new id data.
Add contentrating.
Change fill in new fields to get_person results.
----
Change implement discover endpoint in tvdb_api_v4.
Change filter '0000' year for firstaired field in tvdb_api_v4.
Change use the default_season_type from api for website fallback.
Change remove unneeded _auth_time.
Add backup fetch for episode data.
Change add multiple space remove to clean_data.
Change move _get_tvdb_id to central function.
Change fix minor warnings, code tidy + DRY.
Change remove the show-edit option `Use DVD titles and numbers` until ready with multi TVInfo source.
Add try_date and use to attempt conversion of unspecified date format types birthdate, deathdate, aired.
Change tweaks, remove one warn, order imports.
Change tidy up of other warnings, mismatched types, typos, a strange arg issue with deepcopy, and PEP8.
Bug fix, bad key in get_item for TVInfoSocialIDs.
Fix ambiguities of `show` used in sg versus external uses.
Fix add data sanitisation of image field.
Change make set_episode code more readable.
Change fix final two warnings in api v4.
Fix an API can return falsy as firstaired which crashes adding a show via load_from_tv_info() (The Andrew Marr Show@tvdbv4).
Add cast, crew type mappings
Only take Main Actors, Hosts, Interviewers, Presenters
Change increase viewagble history menu items from 13 to 15.
2021-09-05 19:10:58 +00:00
|
|
|
|
MC_MRU, NE_MRU, TMDB_MRU, TVC_MRU, TVDB_MRU, TVM_MRU, \
|
2023-01-12 01:04:47 +00:00
|
|
|
|
USE_SLACK, SLACK_NOTIFY_ONSNATCH, SLACK_NOTIFY_ONDOWNLOAD, SLACK_NOTIFY_ONSUBTITLEDOWNLOAD, \
|
|
|
|
|
SLACK_CHANNEL, SLACK_AS_AUTHED, SLACK_BOT_NAME, SLACK_ICON_URL, SLACK_ACCESS_TOKEN, \
|
|
|
|
|
USE_DISCORD, DISCORD_NOTIFY_ONSNATCH, DISCORD_NOTIFY_ONDOWNLOAD, \
|
|
|
|
|
DISCORD_NOTIFY_ONSUBTITLEDOWNLOAD, \
|
|
|
|
|
DISCORD_AS_AUTHED, DISCORD_USERNAME, DISCORD_ICON_URL, DISCORD_AS_TTS, DISCORD_ACCESS_TOKEN,\
|
|
|
|
|
USE_GITTER, GITTER_NOTIFY_ONSNATCH, GITTER_NOTIFY_ONDOWNLOAD, GITTER_NOTIFY_ONSUBTITLEDOWNLOAD,\
|
|
|
|
|
GITTER_ROOM, GITTER_ACCESS_TOKEN, \
|
|
|
|
|
USE_TELEGRAM, TELEGRAM_NOTIFY_ONSNATCH, TELEGRAM_NOTIFY_ONDOWNLOAD, TELEGRAM_NOTIFY_ONSUBTITLEDOWNLOAD, \
|
|
|
|
|
TELEGRAM_SEND_IMAGE, TELEGRAM_QUIET, TELEGRAM_ACCESS_TOKEN, TELEGRAM_CHATID, \
|
|
|
|
|
USE_EMAIL, EMAIL_NOTIFY_ONSNATCH, EMAIL_NOTIFY_ONDOWNLOAD, EMAIL_NOTIFY_ONSUBTITLEDOWNLOAD, EMAIL_FROM, \
|
|
|
|
|
EMAIL_HOST, EMAIL_PORT, EMAIL_TLS, EMAIL_USER, EMAIL_PASSWORD, EMAIL_LIST, EMAIL_OLD_SUBJECTS
|
|
|
|
|
# Anime Settings
|
|
|
|
|
global ANIME_TREAT_AS_HDTV, USE_ANIDB, ANIDB_USERNAME, ANIDB_PASSWORD, ANIDB_USE_MYLIST
|
|
|
|
|
# db backup settings
|
|
|
|
|
global BACKUP_DB_PATH, BACKUP_DB_ONEDAY, BACKUP_DB_MAX_COUNT, BACKUP_DB_DEFAULT_COUNT
|
|
|
|
|
# pip update states
|
|
|
|
|
global UPDATES_TODO
|
|
|
|
|
|
|
|
|
|
for stanza in ('General', 'Blackhole', 'SABnzbd', 'NZBGet', 'Emby', 'Kodi', 'XBMC', 'PLEX',
|
|
|
|
|
'Growl', 'Prowl', 'Slack', 'Discord', 'Boxcar2', 'NMJ', 'NMJv2',
|
|
|
|
|
'Synology', 'SynologyNotifier',
|
|
|
|
|
'pyTivo', 'Pushalot', 'Pushbullet', 'Subtitles'):
|
|
|
|
|
check_section(CFG, stanza)
|
|
|
|
|
|
|
|
|
|
update_config = False
|
|
|
|
|
|
|
|
|
|
WANTEDLIST_CACHE = common.WantedQualities()
|
|
|
|
|
|
|
|
|
|
# wanted branch
|
|
|
|
|
BRANCH = check_setting_str(CFG, 'General', 'branch', '')
|
|
|
|
|
|
|
|
|
|
# git_remote
|
|
|
|
|
GIT_REMOTE = check_setting_str(CFG, 'General', 'git_remote', 'origin')
|
|
|
|
|
|
|
|
|
|
ACTUAL_CACHE_DIR = check_setting_str(CFG, 'General', 'cache_dir', 'cache')
|
|
|
|
|
|
|
|
|
|
# unless they specify, put the cache dir inside the data dir
|
|
|
|
|
if not os.path.isabs(ACTUAL_CACHE_DIR):
|
|
|
|
|
CACHE_DIR = os.path.join(DATA_DIR, ACTUAL_CACHE_DIR)
|
|
|
|
|
else:
|
|
|
|
|
CACHE_DIR = ACTUAL_CACHE_DIR
|
|
|
|
|
|
|
|
|
|
if not helpers.make_dir(CACHE_DIR):
|
2023-03-08 13:44:20 +00:00
|
|
|
|
logger.error('!!! creating local cache dir failed, using system default')
|
2023-01-12 01:04:47 +00:00
|
|
|
|
CACHE_DIR = None
|
|
|
|
|
|
|
|
|
|
# clean cache folders
|
|
|
|
|
if CACHE_DIR:
|
|
|
|
|
helpers.clear_cache()
|
2023-02-10 14:15:50 +00:00
|
|
|
|
ZONEINFO_DIR = os.path.join(CACHE_DIR, 'zoneinfo')
|
|
|
|
|
if not os.path.isdir(ZONEINFO_DIR) and not helpers.make_path(ZONEINFO_DIR):
|
2023-03-08 13:44:20 +00:00
|
|
|
|
logger.error('!!! creating local zoneinfo dir failed')
|
2023-01-12 01:04:47 +00:00
|
|
|
|
sg_helpers.CACHE_DIR = CACHE_DIR
|
|
|
|
|
sg_helpers.DATA_DIR = DATA_DIR
|
|
|
|
|
|
|
|
|
|
THEME_NAME = check_setting_str(CFG, 'GUI', 'theme_name', 'dark')
|
|
|
|
|
GUI_NAME = check_setting_str(CFG, 'GUI', 'gui_name', 'slick')
|
|
|
|
|
DEFAULT_HOME = check_setting_str(CFG, 'GUI', 'default_home', 'episodes')
|
|
|
|
|
FANART_LIMIT = check_setting_int(CFG, 'GUI', 'fanart_limit', 3)
|
|
|
|
|
FANART_PANEL = check_setting_str(CFG, 'GUI', 'fanart_panel', 'highlight2')
|
|
|
|
|
FANART_RATINGS = sg_helpers.ast_eval(check_setting_str(CFG, 'GUI', 'fanart_ratings', None), {})
|
|
|
|
|
USE_IMDB_INFO = bool(check_setting_int(CFG, 'GUI', 'use_imdb_info', 1))
|
|
|
|
|
IMDB_ACCOUNTS = CFG.get('GUI', []).get('imdb_accounts', [IMDB_DEFAULT_LIST_ID, IMDB_DEFAULT_LIST_NAME])
|
|
|
|
|
HOME_SEARCH_FOCUS = bool(check_setting_int(CFG, 'General', 'home_search_focus', HOME_SEARCH_FOCUS))
|
|
|
|
|
DISPLAY_FREESPACE = bool(check_setting_int(CFG, 'General', 'display_freespace', 1))
|
|
|
|
|
SORT_ARTICLE = bool(check_setting_int(CFG, 'General', 'sort_article', 0))
|
|
|
|
|
FUZZY_DATING = bool(check_setting_int(CFG, 'GUI', 'fuzzy_dating', 0))
|
|
|
|
|
TRIM_ZERO = bool(check_setting_int(CFG, 'GUI', 'trim_zero', 0))
|
|
|
|
|
DATE_PRESET = check_setting_str(CFG, 'GUI', 'date_preset', '%x')
|
|
|
|
|
TIME_PRESET_W_SECONDS = check_setting_str(CFG, 'GUI', 'time_preset', '%I:%M:%S %p')
|
2023-03-08 13:44:20 +00:00
|
|
|
|
TIME_PRESET = TIME_PRESET_W_SECONDS.replace(':%S', '')
|
2023-01-12 01:04:47 +00:00
|
|
|
|
TIMEZONE_DISPLAY = check_setting_str(CFG, 'GUI', 'timezone_display', 'network')
|
|
|
|
|
SHOW_TAGS = check_setting_str(CFG, 'GUI', 'show_tags', 'Show List').split(',')
|
|
|
|
|
SHOW_TAG_DEFAULT = check_setting_str(CFG, 'GUI', 'show_tag_default',
|
|
|
|
|
check_setting_str(CFG, 'GUI', 'default_show_tag', 'Show List'))
|
|
|
|
|
SHOWLIST_TAGVIEW = check_setting_str(CFG, 'GUI', 'showlist_tagview', 'standard')
|
|
|
|
|
|
|
|
|
|
ACTUAL_LOG_DIR = check_setting_str(CFG, 'General', 'log_dir', 'Logs')
|
|
|
|
|
# put the log dir inside the data dir, unless an absolute path
|
|
|
|
|
LOG_DIR = os.path.normpath(os.path.join(DATA_DIR, ACTUAL_LOG_DIR))
|
|
|
|
|
|
|
|
|
|
if not helpers.make_dir(LOG_DIR):
|
2023-03-08 13:44:20 +00:00
|
|
|
|
logger.error('!!! no log folder, logging to screen only!')
|
2023-01-12 01:04:47 +00:00
|
|
|
|
|
|
|
|
|
FILE_LOGGING_PRESET = check_setting_str(CFG, 'General', 'file_logging_preset', 'DEBUG')
|
|
|
|
|
if bool(check_setting_int(CFG, 'General', 'file_logging_db', 0)):
|
|
|
|
|
FILE_LOGGING_PRESET = 'DB'
|
|
|
|
|
elif 'DB' == FILE_LOGGING_PRESET:
|
|
|
|
|
FILE_LOGGING_PRESET = 'DEBUG'
|
|
|
|
|
|
|
|
|
|
SOCKET_TIMEOUT = check_setting_int(CFG, 'General', 'socket_timeout', 30)
|
|
|
|
|
socket.setdefaulttimeout(SOCKET_TIMEOUT)
|
|
|
|
|
|
|
|
|
|
WEB_HOST = check_setting_str(CFG, 'General', 'web_host', '0.0.0.0')
|
|
|
|
|
WEB_PORT = minimax(check_setting_int(CFG, 'General', 'web_port', 8081), 8081, 21, 65535)
|
|
|
|
|
WEB_ROOT = check_setting_str(CFG, 'General', 'web_root', '').rstrip('/')
|
|
|
|
|
WEB_IPV6 = bool(check_setting_int(CFG, 'General', 'web_ipv6', 0))
|
|
|
|
|
WEB_IPV64 = bool(check_setting_int(CFG, 'General', 'web_ipv64', 0))
|
|
|
|
|
WEB_LOG = bool(check_setting_int(CFG, 'General', 'web_log', 0))
|
|
|
|
|
ENCRYPTION_VERSION = check_setting_int(CFG, 'General', 'encryption_version', 0)
|
|
|
|
|
WEB_USERNAME = check_setting_str(CFG, 'General', 'web_username', '')
|
|
|
|
|
WEB_PASSWORD = check_setting_str(CFG, 'General', 'web_password', '')
|
|
|
|
|
LAUNCH_BROWSER = bool(check_setting_int(CFG, 'General', 'launch_browser', 1))
|
|
|
|
|
|
|
|
|
|
CPU_PRESET = check_setting_str(CFG, 'General', 'cpu_preset', 'DISABLED')
|
|
|
|
|
|
|
|
|
|
ANON_REDIRECT = check_setting_str(CFG, 'General', 'anon_redirect', '')
|
|
|
|
|
PROXY_SETTING = check_setting_str(CFG, 'General', 'proxy_setting', '')
|
|
|
|
|
sg_helpers.PROXY_SETTING = PROXY_SETTING
|
|
|
|
|
sg_helpers.USER_AGENT = USER_AGENT
|
|
|
|
|
from . import notifiers
|
|
|
|
|
sg_helpers.NOTIFIERS = notifiers
|
|
|
|
|
PROXY_INDEXERS = bool(check_setting_int(CFG, 'General', 'proxy_indexers', 1))
|
|
|
|
|
# attempt to help prevent users from breaking links by using a bad url
|
|
|
|
|
if not ANON_REDIRECT.endswith('?'):
|
|
|
|
|
ANON_REDIRECT = ''
|
|
|
|
|
|
|
|
|
|
UPDATE_SHOWS_ON_START = bool(check_setting_int(CFG, 'General', 'update_shows_on_start', 0))
|
|
|
|
|
SHOW_UPDATE_HOUR = check_setting_int(CFG, 'General', 'show_update_hour', 3)
|
|
|
|
|
SHOW_UPDATE_HOUR = minimax(SHOW_UPDATE_HOUR, 3, 0, 23)
|
|
|
|
|
|
|
|
|
|
TRASH_REMOVE_SHOW = bool(check_setting_int(CFG, 'General', 'trash_remove_show', 0))
|
|
|
|
|
sg_helpers.TRASH_REMOVE_SHOW = TRASH_REMOVE_SHOW
|
|
|
|
|
TRASH_ROTATE_LOGS = bool(check_setting_int(CFG, 'General', 'trash_rotate_logs', 0))
|
|
|
|
|
|
|
|
|
|
USE_API = bool(check_setting_int(CFG, 'General', 'use_api', 0))
|
|
|
|
|
API_KEYS = [k.split(':::') for k in check_setting_str(CFG, 'General', 'api_keys', '').split('|||') if k]
|
|
|
|
|
if not API_KEYS:
|
|
|
|
|
tmp_api_key = check_setting_str(CFG, 'General', 'api_key', None)
|
|
|
|
|
if None is not tmp_api_key:
|
|
|
|
|
API_KEYS = [['app name (old key)', tmp_api_key]]
|
|
|
|
|
|
|
|
|
|
DEBUG = bool(check_setting_int(CFG, 'General', 'debug', 0))
|
|
|
|
|
|
|
|
|
|
ENABLE_HTTPS = bool(check_setting_int(CFG, 'General', 'enable_https', 0))
|
|
|
|
|
|
|
|
|
|
HTTPS_CERT = check_setting_str(CFG, 'General', 'https_cert', 'server.crt')
|
|
|
|
|
HTTPS_KEY = check_setting_str(CFG, 'General', 'https_key', 'server.key')
|
|
|
|
|
|
|
|
|
|
HANDLE_REVERSE_PROXY = bool(check_setting_int(CFG, 'General', 'handle_reverse_proxy', 0))
|
|
|
|
|
SEND_SECURITY_HEADERS = bool(check_setting_int(CFG, 'General', 'send_security_headers', 1))
|
|
|
|
|
ALLOWED_HOSTS = check_setting_str(CFG, 'General', 'allowed_hosts', '')
|
|
|
|
|
ALLOW_ANYIP = bool(check_setting_int(CFG, 'General', 'allow_anyip', 1))
|
|
|
|
|
|
|
|
|
|
ROOT_DIRS = check_setting_str(CFG, 'General', 'root_dirs', '')
|
|
|
|
|
if not re.match(r'\d+\|[^|]+(?:\|[^|]+)*', ROOT_DIRS):
|
|
|
|
|
ROOT_DIRS = ''
|
|
|
|
|
|
|
|
|
|
RESULTS_SORTBY = check_setting_str(CFG, 'General', 'results_sortby', '')
|
|
|
|
|
|
|
|
|
|
QUALITY_DEFAULT = check_setting_int(CFG, 'General', 'quality_default', SD)
|
|
|
|
|
STATUS_DEFAULT = check_setting_int(CFG, 'General', 'status_default', SKIPPED)
|
|
|
|
|
WANTED_BEGIN_DEFAULT = check_setting_int(CFG, 'General', 'wanted_begin_default', 0)
|
|
|
|
|
WANTED_LATEST_DEFAULT = check_setting_int(CFG, 'General', 'wanted_latest_default', 0)
|
|
|
|
|
|
|
|
|
|
UPDATE_NOTIFY = bool(check_setting_int(CFG, 'General', 'update_notify', None))
|
|
|
|
|
if None is UPDATE_NOTIFY:
|
|
|
|
|
UPDATE_NOTIFY = check_setting_int(CFG, 'General', 'version_notify', 1) # deprecated 2020.11.21 no config update
|
|
|
|
|
UPDATE_AUTO = bool(check_setting_int(CFG, 'General', 'update_auto', None))
|
|
|
|
|
if None is UPDATE_AUTO:
|
|
|
|
|
UPDATE_AUTO = check_setting_int(CFG, 'General', 'auto_update', 0) # deprecated 2020.11.21 no config update
|
|
|
|
|
UPDATE_INTERVAL = max(
|
|
|
|
|
MIN_UPDATE_INTERVAL,
|
|
|
|
|
check_setting_int(CFG, 'General', 'update_interval', DEFAULT_UPDATE_INTERVAL))
|
|
|
|
|
NOTIFY_ON_UPDATE = bool(check_setting_int(CFG, 'General', 'notify_on_update', 1))
|
|
|
|
|
|
|
|
|
|
UPDATE_PACKAGES_NOTIFY = bool(
|
|
|
|
|
check_setting_int(CFG, 'General', 'update_packages_notify', 'win' == sys.platform[0:3]))
|
|
|
|
|
UPDATE_PACKAGES_AUTO = bool(check_setting_int(CFG, 'General', 'update_packages_auto', 0))
|
|
|
|
|
UPDATE_PACKAGES_MENU = bool(check_setting_int(CFG, 'General', 'update_packages_menu', 0))
|
|
|
|
|
UPDATE_PACKAGES_INTERVAL = max(
|
|
|
|
|
MIN_UPDATE_PACKAGES_INTERVAL,
|
|
|
|
|
check_setting_int(CFG, 'General', 'update_packages_interval', DEFAULT_UPDATE_PACKAGES_INTERVAL))
|
|
|
|
|
|
|
|
|
|
TVINFO_DEFAULT = check_setting_int(CFG, 'General', 'indexer_default', 0)
|
|
|
|
|
if TVINFO_DEFAULT and not TVInfoAPI(TVINFO_DEFAULT).config['active']:
|
|
|
|
|
TVINFO_DEFAULT = TVINFO_TVDB
|
|
|
|
|
TVINFO_TIMEOUT = check_setting_int(CFG, 'General', 'indexer_timeout', 20)
|
|
|
|
|
|
|
|
|
|
PAUSE_DEFAULT = bool(check_setting_int(CFG, 'General', 'pause default', 0))
|
|
|
|
|
SCENE_DEFAULT = bool(check_setting_int(CFG, 'General', 'scene_default', 0))
|
|
|
|
|
FLATTEN_FOLDERS_DEFAULT = bool(check_setting_int(CFG, 'General', 'flatten_folders_default', 0))
|
|
|
|
|
ANIME_DEFAULT = bool(check_setting_int(CFG, 'General', 'anime_default', 0))
|
|
|
|
|
|
|
|
|
|
PROVIDER_ORDER = check_setting_str(CFG, 'General', 'provider_order', '').split()
|
|
|
|
|
PROVIDER_HOMES = sg_helpers.ast_eval(check_setting_str(CFG, 'General', 'provider_homes', None), {})
|
|
|
|
|
|
|
|
|
|
NAMING_PATTERN = check_setting_str(CFG, 'General', 'naming_pattern', 'Season %0S/%SN - S%0SE%0E - %EN')
|
|
|
|
|
NAMING_ABD_PATTERN = check_setting_str(CFG, 'General', 'naming_abd_pattern', '%SN - %A.D - %EN')
|
|
|
|
|
NAMING_CUSTOM_ABD = bool(check_setting_int(CFG, 'General', 'naming_custom_abd', 0))
|
|
|
|
|
NAMING_SPORTS_PATTERN = check_setting_str(CFG, 'General', 'naming_sports_pattern', '%SN - %A-D - %EN')
|
|
|
|
|
NAMING_ANIME_PATTERN = check_setting_str(CFG, 'General', 'naming_anime_pattern',
|
|
|
|
|
'Season %0S/%SN - S%0SE%0E - %EN')
|
|
|
|
|
NAMING_ANIME = check_setting_int(CFG, 'General', 'naming_anime', 3)
|
|
|
|
|
NAMING_CUSTOM_SPORTS = bool(check_setting_int(CFG, 'General', 'naming_custom_sports', 0))
|
|
|
|
|
NAMING_CUSTOM_ANIME = bool(check_setting_int(CFG, 'General', 'naming_custom_anime', 0))
|
|
|
|
|
NAMING_MULTI_EP = check_setting_int(CFG, 'General', 'naming_multi_ep', 1)
|
|
|
|
|
NAMING_ANIME_MULTI_EP = check_setting_int(CFG, 'General', 'naming_anime_multi_ep', 1)
|
|
|
|
|
NAMING_FORCE_FOLDERS = naming.check_force_season_folders()
|
|
|
|
|
NAMING_STRIP_YEAR = bool(check_setting_int(CFG, 'General', 'naming_strip_year', 0))
|
|
|
|
|
|
|
|
|
|
USE_NZBS = bool(check_setting_int(CFG, 'General', 'use_nzbs', 0))
|
|
|
|
|
USE_TORRENTS = bool(check_setting_int(CFG, 'General', 'use_torrents', 0))
|
|
|
|
|
|
|
|
|
|
NZB_METHOD = check_setting_str(CFG, 'General', 'nzb_method', 'blackhole')
|
|
|
|
|
if NZB_METHOD not in ('blackhole', 'sabnzbd', 'nzbget'):
|
|
|
|
|
NZB_METHOD = 'blackhole'
|
|
|
|
|
|
|
|
|
|
TORRENT_METHOD = check_setting_str(CFG, 'General', 'torrent_method', 'blackhole')
|
|
|
|
|
if TORRENT_METHOD not in ('blackhole', 'deluge', 'download_station', 'qbittorrent',
|
|
|
|
|
'rtorrent', 'transmission', 'utorrent'):
|
|
|
|
|
TORRENT_METHOD = 'blackhole'
|
|
|
|
|
|
|
|
|
|
DOWNLOAD_PROPERS = bool(check_setting_int(CFG, 'General', 'download_propers', 1))
|
|
|
|
|
PROPERS_WEBDL_ONEGRP = bool(check_setting_int(CFG, 'General', 'propers_webdl_onegrp', 1))
|
|
|
|
|
|
|
|
|
|
ALLOW_HIGH_PRIORITY = bool(check_setting_int(CFG, 'General', 'allow_high_priority', 1))
|
|
|
|
|
|
|
|
|
|
RECENTSEARCH_STARTUP = bool(check_setting_int(CFG, 'General', 'recentsearch_startup', 0))
|
|
|
|
|
BACKLOG_NOFULL = bool(check_setting_int(CFG, 'General', 'backlog_nofull', 0))
|
|
|
|
|
SKIP_REMOVED_FILES = check_setting_int(CFG, 'General', 'skip_removed_files', 0)
|
|
|
|
|
|
|
|
|
|
USENET_RETENTION = check_setting_int(CFG, 'General', 'usenet_retention', 500)
|
|
|
|
|
|
|
|
|
|
MEDIAPROCESS_INTERVAL = check_setting_int(CFG, 'General', 'mediaprocess_interval', DEFAULT_MEDIAPROCESS_INTERVAL)
|
|
|
|
|
if MEDIAPROCESS_INTERVAL < MIN_MEDIAPROCESS_INTERVAL:
|
|
|
|
|
MEDIAPROCESS_INTERVAL = MIN_MEDIAPROCESS_INTERVAL
|
|
|
|
|
|
|
|
|
|
RECENTSEARCH_INTERVAL = check_setting_int(CFG, 'General', 'recentsearch_interval', DEFAULT_RECENTSEARCH_INTERVAL)
|
|
|
|
|
if RECENTSEARCH_INTERVAL < MIN_RECENTSEARCH_INTERVAL:
|
|
|
|
|
RECENTSEARCH_INTERVAL = MIN_RECENTSEARCH_INTERVAL
|
|
|
|
|
|
|
|
|
|
# special case during dev to migrate backlog_interval to backlog_period
|
|
|
|
|
BACKLOG_PERIOD = check_setting_int(CFG, 'General', 'backlog_period',
|
|
|
|
|
check_setting_int(CFG, 'General', 'backlog_interval', DEFAULT_BACKLOG_PERIOD))
|
|
|
|
|
BACKLOG_PERIOD = minimax(BACKLOG_PERIOD, DEFAULT_BACKLOG_PERIOD, MIN_BACKLOG_PERIOD, MAX_BACKLOG_PERIOD)
|
|
|
|
|
BACKLOG_LIMITED_PERIOD = check_setting_int(CFG, 'General', 'backlog_limited_period', 7)
|
|
|
|
|
|
|
|
|
|
SEARCH_UNAIRED = bool(check_setting_int(CFG, 'General', 'search_unaired', 0))
|
|
|
|
|
UNAIRED_RECENT_SEARCH_ONLY = bool(check_setting_int(CFG, 'General', 'unaired_recent_search_only', 1))
|
|
|
|
|
FLARESOLVERR_HOST = check_setting_str(CFG, 'General', 'flaresolverr_host', '')
|
|
|
|
|
sg_helpers.FLARESOLVERR_HOST = FLARESOLVERR_HOST
|
|
|
|
|
|
|
|
|
|
NZB_DIR = check_setting_str(CFG, 'Blackhole', 'nzb_dir', '')
|
|
|
|
|
TORRENT_DIR = check_setting_str(CFG, 'Blackhole', 'torrent_dir', '')
|
|
|
|
|
|
|
|
|
|
TV_DOWNLOAD_DIR = check_setting_str(CFG, 'General', 'tv_download_dir', '')
|
|
|
|
|
PROCESS_AUTOMATICALLY = bool(check_setting_int(CFG, 'General', 'process_automatically', 0))
|
|
|
|
|
UNPACK = bool(check_setting_int(CFG, 'General', 'unpack', 0))
|
|
|
|
|
RENAME_EPISODES = bool(check_setting_int(CFG, 'General', 'rename_episodes', 1))
|
2023-04-29 18:18:00 +00:00
|
|
|
|
RENAME_TBA_EPISODES = bool(check_setting_int(CFG, 'General', 'rename_tba_episodes', 1))
|
|
|
|
|
RENAME_NAME_CHANGED_EPISODES = bool(check_setting_int(CFG, 'General', 'rename_name_changed_episodes', 0))
|
2023-01-12 01:04:47 +00:00
|
|
|
|
AIRDATE_EPISODES = bool(check_setting_int(CFG, 'General', 'airdate_episodes', 0))
|
|
|
|
|
KEEP_PROCESSED_DIR = bool(check_setting_int(CFG, 'General', 'keep_processed_dir', 1))
|
|
|
|
|
PROCESS_METHOD = check_setting_str(CFG, 'General', 'process_method', 'copy' if KEEP_PROCESSED_DIR else 'move')
|
|
|
|
|
PROCESS_LAST_DIR = check_setting_str(CFG, 'General', 'process_last_dir', TV_DOWNLOAD_DIR)
|
|
|
|
|
PROCESS_LAST_METHOD = check_setting_str(CFG, 'General', 'process_last_method', PROCESS_METHOD)
|
|
|
|
|
PROCESS_LAST_CLEANUP = bool(check_setting_int(CFG, 'General', 'process_last_cleanup', 0))
|
|
|
|
|
MOVE_ASSOCIATED_FILES = bool(check_setting_int(CFG, 'General', 'move_associated_files', 0))
|
|
|
|
|
POSTPONE_IF_SYNC_FILES = bool(check_setting_int(CFG, 'General', 'postpone_if_sync_files', 1))
|
2023-04-16 00:31:51 +00:00
|
|
|
|
PROCESS_POSITIVE_LOG = bool(check_setting_int(CFG, 'General', 'process_positive_log', 0))
|
2023-01-12 01:04:47 +00:00
|
|
|
|
NFO_RENAME = bool(check_setting_int(CFG, 'General', 'nfo_rename', 1))
|
|
|
|
|
CREATE_MISSING_SHOW_DIRS = bool(check_setting_int(CFG, 'General', 'create_missing_show_dirs', 0))
|
|
|
|
|
SHOW_DIRS_WITH_DOTS = bool(check_setting_int(CFG, 'General', 'show_dirs_with_dots', 0))
|
|
|
|
|
ADD_SHOWS_WO_DIR = bool(check_setting_int(CFG, 'General', 'add_shows_wo_dir', 0))
|
|
|
|
|
ADD_SHOWS_METALANG = check_setting_str(CFG, 'General', 'add_shows_metalang', 'en')
|
|
|
|
|
REMOVE_FILENAME_CHARS = check_setting_str(CFG, 'General', 'remove_filename_chars', '')
|
|
|
|
|
sg_helpers.REMOVE_FILENAME_CHARS = REMOVE_FILENAME_CHARS
|
|
|
|
|
IMPORT_DEFAULT_CHECKED_SHOWS = bool(check_setting_int(CFG, 'General', 'import_default_checked_shows', 0))
|
|
|
|
|
|
|
|
|
|
SAB_USERNAME = check_setting_str(CFG, 'SABnzbd', 'sab_username', '')
|
|
|
|
|
SAB_PASSWORD = check_setting_str(CFG, 'SABnzbd', 'sab_password', '')
|
|
|
|
|
SAB_APIKEY = check_setting_str(CFG, 'SABnzbd', 'sab_apikey', '')
|
|
|
|
|
SAB_CATEGORY = check_setting_str(CFG, 'SABnzbd', 'sab_category', 'tv')
|
|
|
|
|
SAB_HOST = check_setting_str(CFG, 'SABnzbd', 'sab_host', '')
|
|
|
|
|
|
|
|
|
|
# first check using official name case, then with case of legacy
|
|
|
|
|
# todo: migrate config, (just not atm due to testing map feature)
|
|
|
|
|
NZBGET_USERNAME = (check_setting_str(CFG, 'NZBGet', 'nzbget_username', '')
|
|
|
|
|
or check_setting_str(CFG, 'NZBget', 'nzbget_username', 'nzbget'))
|
|
|
|
|
NZBGET_PASSWORD = (check_setting_str(CFG, 'NZBGet', 'nzbget_password', '')
|
|
|
|
|
or check_setting_str(CFG, 'NZBget', 'nzbget_password', 'tegbzn6789'))
|
|
|
|
|
NZBGET_CATEGORY = (check_setting_str(CFG, 'NZBGet', 'nzbget_category', '')
|
|
|
|
|
or check_setting_str(CFG, 'NZBget', 'nzbget_category', 'tv'))
|
|
|
|
|
NZBGET_HOST = (check_setting_str(CFG, 'NZBGet', 'nzbget_host', '')
|
|
|
|
|
or check_setting_str(CFG, 'NZBget', 'nzbget_host', ''))
|
|
|
|
|
NZBGET_USE_HTTPS = (bool(check_setting_int(CFG, 'NZBGet', 'nzbget_use_https', 0))
|
|
|
|
|
or bool(check_setting_int(CFG, 'NZBget', 'nzbget_use_https', 0)))
|
|
|
|
|
NZBGET_PRIORITY = check_setting_int(CFG, 'NZBGet', 'nzbget_priority', None)
|
|
|
|
|
if None is NZBGET_PRIORITY:
|
|
|
|
|
NZBGET_PRIORITY = check_setting_int(CFG, 'NZBget', 'nzbget_priority', 100)
|
|
|
|
|
NZBGET_MAP = check_setting_str(CFG, 'NZBGet', 'nzbget_map', '')
|
|
|
|
|
NZBGET_SKIP_PM = bool(check_setting_int(CFG, 'NZBGet', 'nzbget_skip_process_media', 0))
|
|
|
|
|
|
|
|
|
|
try:
|
2023-02-10 14:15:50 +00:00
|
|
|
|
ng_script_file = os.path.join(os.path.dirname(os.path.dirname(__file__)),
|
|
|
|
|
'autoProcessTV', 'SickGear-NG', 'SickGear-NG.py')
|
2023-01-12 01:04:47 +00:00
|
|
|
|
with io.open(ng_script_file, 'r', encoding='utf8') as ng:
|
|
|
|
|
text = ng.read()
|
|
|
|
|
NZBGET_SCRIPT_VERSION = re.search(r""".*version: (\d+\.\d+)""", text, flags=re.M).group(1)
|
|
|
|
|
except (BaseException, Exception):
|
|
|
|
|
NZBGET_SCRIPT_VERSION = None
|
|
|
|
|
|
|
|
|
|
TORRENT_USERNAME = check_setting_str(CFG, 'TORRENT', 'torrent_username', '')
|
|
|
|
|
TORRENT_PASSWORD = check_setting_str(CFG, 'TORRENT', 'torrent_password', '')
|
|
|
|
|
TORRENT_HOST = check_setting_str(CFG, 'TORRENT', 'torrent_host', '')
|
|
|
|
|
TORRENT_PATH = check_setting_str(CFG, 'TORRENT', 'torrent_path', '')
|
|
|
|
|
TORRENT_SEED_TIME = check_setting_int(CFG, 'TORRENT', 'torrent_seed_time', 0)
|
|
|
|
|
TORRENT_PAUSED = bool(check_setting_int(CFG, 'TORRENT', 'torrent_paused', 0))
|
|
|
|
|
TORRENT_HIGH_BANDWIDTH = bool(check_setting_int(CFG, 'TORRENT', 'torrent_high_bandwidth', 0))
|
|
|
|
|
TORRENT_LABEL = check_setting_str(CFG, 'TORRENT', 'torrent_label', '')
|
|
|
|
|
TORRENT_LABEL_VAR = check_setting_int(CFG, 'TORRENT', 'torrent_label_var', 1)
|
|
|
|
|
TORRENT_VERIFY_CERT = bool(check_setting_int(CFG, 'TORRENT', 'torrent_verify_cert', 0))
|
|
|
|
|
|
|
|
|
|
USE_EMBY = bool(check_setting_int(CFG, 'Emby', 'use_emby', 0))
|
|
|
|
|
EMBY_UPDATE_LIBRARY = bool(check_setting_int(CFG, 'Emby', 'emby_update_library', 0))
|
|
|
|
|
EMBY_PARENT_MAPS = check_setting_str(CFG, 'Emby', 'emby_parent_maps', '')
|
|
|
|
|
EMBY_HOST = check_setting_str(CFG, 'Emby', 'emby_host', '')
|
|
|
|
|
EMBY_APIKEY = check_setting_str(CFG, 'Emby', 'emby_apikey', '')
|
|
|
|
|
EMBY_WATCHEDSTATE_SCHEDULED = bool(check_setting_int(CFG, 'Emby', 'emby_watchedstate_scheduled', 0))
|
|
|
|
|
EMBY_WATCHEDSTATE_INTERVAL = minimax(check_setting_int(
|
|
|
|
|
CFG, 'Emby', 'emby_watchedstate_interval', DEFAULT_WATCHEDSTATE_INTERVAL),
|
|
|
|
|
DEFAULT_WATCHEDSTATE_INTERVAL, MIN_WATCHEDSTATE_INTERVAL, MAX_WATCHEDSTATE_INTERVAL)
|
|
|
|
|
|
|
|
|
|
USE_KODI = bool(check_setting_int(CFG, 'Kodi', 'use_kodi', 0))
|
|
|
|
|
KODI_ALWAYS_ON = bool(check_setting_int(CFG, 'Kodi', 'kodi_always_on', 1))
|
|
|
|
|
KODI_NOTIFY_ONSNATCH = bool(check_setting_int(CFG, 'Kodi', 'kodi_notify_onsnatch', 0))
|
|
|
|
|
KODI_NOTIFY_ONDOWNLOAD = bool(check_setting_int(CFG, 'Kodi', 'kodi_notify_ondownload', 0))
|
|
|
|
|
KODI_NOTIFY_ONSUBTITLEDOWNLOAD = bool(check_setting_int(CFG, 'Kodi', 'kodi_notify_onsubtitledownload', 0))
|
|
|
|
|
KODI_UPDATE_LIBRARY = bool(check_setting_int(CFG, 'Kodi', 'kodi_update_library', 0))
|
|
|
|
|
KODI_UPDATE_FULL = bool(check_setting_int(CFG, 'Kodi', 'kodi_update_full', 0))
|
|
|
|
|
KODI_UPDATE_ONLYFIRST = bool(check_setting_int(CFG, 'Kodi', 'kodi_update_onlyfirst', 0))
|
|
|
|
|
KODI_PARENT_MAPS = check_setting_str(CFG, 'Kodi', 'kodi_parent_maps', '')
|
|
|
|
|
KODI_HOST = check_setting_str(CFG, 'Kodi', 'kodi_host', '')
|
|
|
|
|
KODI_USERNAME = check_setting_str(CFG, 'Kodi', 'kodi_username', '')
|
|
|
|
|
KODI_PASSWORD = check_setting_str(CFG, 'Kodi', 'kodi_password', '')
|
|
|
|
|
|
|
|
|
|
USE_XBMC = bool(check_setting_int(CFG, 'XBMC', 'use_xbmc', 0))
|
|
|
|
|
XBMC_ALWAYS_ON = bool(check_setting_int(CFG, 'XBMC', 'xbmc_always_on', 1))
|
|
|
|
|
XBMC_NOTIFY_ONSNATCH = bool(check_setting_int(CFG, 'XBMC', 'xbmc_notify_onsnatch', 0))
|
|
|
|
|
XBMC_NOTIFY_ONDOWNLOAD = bool(check_setting_int(CFG, 'XBMC', 'xbmc_notify_ondownload', 0))
|
|
|
|
|
XBMC_NOTIFY_ONSUBTITLEDOWNLOAD = bool(check_setting_int(CFG, 'XBMC', 'xbmc_notify_onsubtitledownload', 0))
|
|
|
|
|
XBMC_UPDATE_LIBRARY = bool(check_setting_int(CFG, 'XBMC', 'xbmc_update_library', 0))
|
|
|
|
|
XBMC_UPDATE_FULL = bool(check_setting_int(CFG, 'XBMC', 'xbmc_update_full', 0))
|
|
|
|
|
XBMC_UPDATE_ONLYFIRST = bool(check_setting_int(CFG, 'XBMC', 'xbmc_update_onlyfirst', 0))
|
|
|
|
|
XBMC_HOST = check_setting_str(CFG, 'XBMC', 'xbmc_host', '')
|
|
|
|
|
XBMC_USERNAME = check_setting_str(CFG, 'XBMC', 'xbmc_username', '')
|
|
|
|
|
XBMC_PASSWORD = check_setting_str(CFG, 'XBMC', 'xbmc_password', '')
|
|
|
|
|
|
|
|
|
|
USE_PLEX = bool(check_setting_int(CFG, 'Plex', 'use_plex', 0))
|
|
|
|
|
PLEX_NOTIFY_ONSNATCH = bool(check_setting_int(CFG, 'Plex', 'plex_notify_onsnatch', 0))
|
|
|
|
|
PLEX_NOTIFY_ONDOWNLOAD = bool(check_setting_int(CFG, 'Plex', 'plex_notify_ondownload', 0))
|
|
|
|
|
PLEX_NOTIFY_ONSUBTITLEDOWNLOAD = bool(check_setting_int(CFG, 'Plex', 'plex_notify_onsubtitledownload', 0))
|
|
|
|
|
PLEX_UPDATE_LIBRARY = bool(check_setting_int(CFG, 'Plex', 'plex_update_library', 0))
|
|
|
|
|
PLEX_PARENT_MAPS = check_setting_str(CFG, 'Plex', 'plex_parent_maps', '')
|
|
|
|
|
PLEX_SERVER_HOST = check_setting_str(CFG, 'Plex', 'plex_server_host', '')
|
|
|
|
|
PLEX_HOST = check_setting_str(CFG, 'Plex', 'plex_host', '')
|
|
|
|
|
PLEX_USERNAME = check_setting_str(CFG, 'Plex', 'plex_username', '')
|
|
|
|
|
PLEX_PASSWORD = check_setting_str(CFG, 'Plex', 'plex_password', '')
|
|
|
|
|
PLEX_WATCHEDSTATE_SCHEDULED = bool(check_setting_int(CFG, 'Plex', 'plex_watchedstate_scheduled', 0))
|
|
|
|
|
PLEX_WATCHEDSTATE_INTERVAL = minimax(check_setting_int(
|
|
|
|
|
CFG, 'Plex', 'plex_watchedstate_interval', DEFAULT_WATCHEDSTATE_INTERVAL),
|
|
|
|
|
DEFAULT_WATCHEDSTATE_INTERVAL, MIN_WATCHEDSTATE_INTERVAL, MAX_WATCHEDSTATE_INTERVAL)
|
|
|
|
|
|
|
|
|
|
USE_GROWL = bool(check_setting_int(CFG, 'Growl', 'use_growl', 0))
|
|
|
|
|
GROWL_NOTIFY_ONSNATCH = bool(check_setting_int(CFG, 'Growl', 'growl_notify_onsnatch', 0))
|
|
|
|
|
GROWL_NOTIFY_ONDOWNLOAD = bool(check_setting_int(CFG, 'Growl', 'growl_notify_ondownload', 0))
|
|
|
|
|
GROWL_NOTIFY_ONSUBTITLEDOWNLOAD = bool(check_setting_int(CFG, 'Growl', 'growl_notify_onsubtitledownload', 0))
|
|
|
|
|
GROWL_HOST = check_setting_str(CFG, 'Growl', 'growl_host', '')
|
|
|
|
|
# GROWL_PASSWORD = check_setting_str(CFG, 'Growl', 'growl_password', '')
|
|
|
|
|
|
|
|
|
|
USE_PROWL = bool(check_setting_int(CFG, 'Prowl', 'use_prowl', 0))
|
|
|
|
|
PROWL_NOTIFY_ONSNATCH = bool(check_setting_int(CFG, 'Prowl', 'prowl_notify_onsnatch', 0))
|
|
|
|
|
PROWL_NOTIFY_ONDOWNLOAD = bool(check_setting_int(CFG, 'Prowl', 'prowl_notify_ondownload', 0))
|
|
|
|
|
PROWL_NOTIFY_ONSUBTITLEDOWNLOAD = bool(check_setting_int(CFG, 'Prowl', 'prowl_notify_onsubtitledownload', 0))
|
|
|
|
|
PROWL_API = check_setting_str(CFG, 'Prowl', 'prowl_api', '')
|
|
|
|
|
PROWL_PRIORITY = check_setting_str(CFG, 'Prowl', 'prowl_priority', '0')
|
|
|
|
|
|
|
|
|
|
USE_BOXCAR2 = bool(check_setting_int(CFG, 'Boxcar2', 'use_boxcar2', 0))
|
|
|
|
|
BOXCAR2_NOTIFY_ONSNATCH = bool(check_setting_int(CFG, 'Boxcar2', 'boxcar2_notify_onsnatch', 0))
|
|
|
|
|
BOXCAR2_NOTIFY_ONDOWNLOAD = bool(check_setting_int(CFG, 'Boxcar2', 'boxcar2_notify_ondownload', 0))
|
|
|
|
|
BOXCAR2_NOTIFY_ONSUBTITLEDOWNLOAD = bool(
|
|
|
|
|
check_setting_int(CFG, 'Boxcar2', 'boxcar2_notify_onsubtitledownload', 0))
|
|
|
|
|
BOXCAR2_ACCESSTOKEN = check_setting_str(CFG, 'Boxcar2', 'boxcar2_accesstoken', '')
|
|
|
|
|
BOXCAR2_SOUND = check_setting_str(CFG, 'Boxcar2', 'boxcar2_sound', 'default')
|
|
|
|
|
|
|
|
|
|
USE_PUSHOVER = bool(check_setting_int(CFG, 'Pushover', 'use_pushover', 0))
|
|
|
|
|
PUSHOVER_NOTIFY_ONSNATCH = bool(check_setting_int(CFG, 'Pushover', 'pushover_notify_onsnatch', 0))
|
|
|
|
|
PUSHOVER_NOTIFY_ONDOWNLOAD = bool(check_setting_int(CFG, 'Pushover', 'pushover_notify_ondownload', 0))
|
|
|
|
|
PUSHOVER_NOTIFY_ONSUBTITLEDOWNLOAD = bool(
|
|
|
|
|
check_setting_int(CFG, 'Pushover', 'pushover_notify_onsubtitledownload', 0))
|
|
|
|
|
PUSHOVER_USERKEY = check_setting_str(CFG, 'Pushover', 'pushover_userkey', '')
|
|
|
|
|
PUSHOVER_APIKEY = check_setting_str(CFG, 'Pushover', 'pushover_apikey', '')
|
|
|
|
|
PUSHOVER_PRIORITY = check_setting_str(CFG, 'Pushover', 'pushover_priority', '0')
|
|
|
|
|
PUSHOVER_DEVICE = check_setting_str(CFG, 'Pushover', 'pushover_device', 'all')
|
|
|
|
|
PUSHOVER_SOUND = check_setting_str(CFG, 'Pushover', 'pushover_sound', 'pushover')
|
|
|
|
|
|
|
|
|
|
USE_LIBNOTIFY = bool(check_setting_int(CFG, 'Libnotify', 'use_libnotify', 0))
|
|
|
|
|
LIBNOTIFY_NOTIFY_ONSNATCH = bool(check_setting_int(CFG, 'Libnotify', 'libnotify_notify_onsnatch', 0))
|
|
|
|
|
LIBNOTIFY_NOTIFY_ONDOWNLOAD = bool(check_setting_int(CFG, 'Libnotify', 'libnotify_notify_ondownload', 0))
|
|
|
|
|
LIBNOTIFY_NOTIFY_ONSUBTITLEDOWNLOAD = bool(
|
|
|
|
|
check_setting_int(CFG, 'Libnotify', 'libnotify_notify_onsubtitledownload', 0))
|
|
|
|
|
|
|
|
|
|
USE_NMJ = bool(check_setting_int(CFG, 'NMJ', 'use_nmj', 0))
|
|
|
|
|
NMJ_HOST = check_setting_str(CFG, 'NMJ', 'nmj_host', '')
|
|
|
|
|
NMJ_DATABASE = check_setting_str(CFG, 'NMJ', 'nmj_database', '')
|
|
|
|
|
NMJ_MOUNT = check_setting_str(CFG, 'NMJ', 'nmj_mount', '')
|
|
|
|
|
|
|
|
|
|
USE_NMJv2 = bool(check_setting_int(CFG, 'NMJv2', 'use_nmjv2', 0))
|
|
|
|
|
NMJv2_HOST = check_setting_str(CFG, 'NMJv2', 'nmjv2_host', '')
|
|
|
|
|
NMJv2_DATABASE = check_setting_str(CFG, 'NMJv2', 'nmjv2_database', '')
|
|
|
|
|
NMJv2_DBLOC = check_setting_str(CFG, 'NMJv2', 'nmjv2_dbloc', '')
|
|
|
|
|
|
|
|
|
|
USE_SYNOINDEX = bool(check_setting_int(CFG, 'Synology', 'use_synoindex', 0))
|
|
|
|
|
|
|
|
|
|
USE_SYNOLOGYNOTIFIER = bool(check_setting_int(CFG, 'SynologyNotifier', 'use_synologynotifier', 0))
|
|
|
|
|
SYNOLOGYNOTIFIER_NOTIFY_ONSNATCH = bool(
|
|
|
|
|
check_setting_int(CFG, 'SynologyNotifier', 'synologynotifier_notify_onsnatch', 0))
|
|
|
|
|
SYNOLOGYNOTIFIER_NOTIFY_ONDOWNLOAD = bool(
|
|
|
|
|
check_setting_int(CFG, 'SynologyNotifier', 'synologynotifier_notify_ondownload', 0))
|
|
|
|
|
SYNOLOGYNOTIFIER_NOTIFY_ONSUBTITLEDOWNLOAD = bool(
|
|
|
|
|
check_setting_int(CFG, 'SynologyNotifier', 'synologynotifier_notify_onsubtitledownload', 0))
|
|
|
|
|
|
|
|
|
|
USE_TRAKT = bool(check_setting_int(CFG, 'Trakt', 'use_trakt', 0))
|
|
|
|
|
TRAKT_REMOVE_WATCHLIST = bool(check_setting_int(CFG, 'Trakt', 'trakt_remove_watchlist', 0))
|
|
|
|
|
TRAKT_REMOVE_SERIESLIST = bool(check_setting_int(CFG, 'Trakt', 'trakt_remove_serieslist', 0))
|
|
|
|
|
TRAKT_USE_WATCHLIST = bool(check_setting_int(CFG, 'Trakt', 'trakt_use_watchlist', 0))
|
|
|
|
|
TRAKT_METHOD_ADD = check_setting_int(CFG, 'Trakt', 'trakt_method_add', 0)
|
|
|
|
|
TRAKT_START_PAUSED = bool(check_setting_int(CFG, 'Trakt', 'trakt_start_paused', 0))
|
|
|
|
|
TRAKT_SYNC = bool(check_setting_int(CFG, 'Trakt', 'trakt_sync', 0))
|
|
|
|
|
TRAKT_DEFAULT_INDEXER = check_setting_int(CFG, 'Trakt', 'trakt_default_indexer', 1)
|
|
|
|
|
TRAKT_UPDATE_COLLECTION = trakt_helpers.read_config_string(
|
|
|
|
|
check_setting_str(CFG, 'Trakt', 'trakt_update_collection', ''))
|
|
|
|
|
TRAKT_ACCOUNTS = TraktAPI.read_config_string(check_setting_str(CFG, 'Trakt', 'trakt_accounts', ''))
|
|
|
|
|
TRAKT_MRU = check_setting_str(CFG, 'Trakt', 'trakt_mru', '')
|
|
|
|
|
|
|
|
|
|
MC_MRU = check_setting_str(CFG, 'Metacritic', 'mc_mru', '')
|
2023-03-09 02:13:52 +00:00
|
|
|
|
NE_MRU = check_setting_str(CFG, 'NextEpisode', 'ne_mru', '')
|
|
|
|
|
TMDB_MRU = check_setting_str(CFG, 'TMDB', 'tmdb_mru', '')
|
2023-01-12 01:04:47 +00:00
|
|
|
|
TVC_MRU = check_setting_str(CFG, 'TVCalendar', 'tvc_mru', '')
|
Fix py2 deprecation cleanups added exclusively by TvdbV4 code.
Refactor `timestamp_near` to `SGDatetime.timestamp_near`
---
Simplify enforce_type + clean_data to clean_str.
Change simplified all but one enforce_type use case.
---
Add tvdb, trakt slug tvinfo search test cases
Change direct tvdb slug search support via new api endpoint
Fix origin_countries in tvdb_api_v4.
---
Add new TV_Maze id to show obj ids in tvdb_api_v4.
Fix a bug parsing social ids for tvshows in tvdb_api_v4.
Change add language support to search API and tvdb_api_v4.
Change add `updated_at` to artwork on tvdb_api_v4.
Change add `finale` type to episodes.
Change add method `get_top_rated` to tvdb_api_v4.
optional params...
- year=... argument to get only top rated of given year, if not it's all time
Change returns result for shows until same day last year.
Add youtube, reddit, fansite, tiktok, linkedin, wikidata to tv.py
Add tiktok to indexer_config.
Add fansite to tvdb_api_v4.
Aadd fansite to TVInfoSocialIDs.
Add source type parsing and add linkein to tvdb_api_v4.
Add linkedin.
Add tiktok parser to tvdb_api_v4.
Change v4 to TVInfoIDs, TVInfoSocialIDs.
Change add new id data.
Add contentrating.
Change fill in new fields to get_person results.
----
Change implement discover endpoint in tvdb_api_v4.
Change filter '0000' year for firstaired field in tvdb_api_v4.
Change use the default_season_type from api for website fallback.
Change remove unneeded _auth_time.
Add backup fetch for episode data.
Change add multiple space remove to clean_data.
Change move _get_tvdb_id to central function.
Change fix minor warnings, code tidy + DRY.
Change remove the show-edit option `Use DVD titles and numbers` until ready with multi TVInfo source.
Add try_date and use to attempt conversion of unspecified date format types birthdate, deathdate, aired.
Change tweaks, remove one warn, order imports.
Change tidy up of other warnings, mismatched types, typos, a strange arg issue with deepcopy, and PEP8.
Bug fix, bad key in get_item for TVInfoSocialIDs.
Fix ambiguities of `show` used in sg versus external uses.
Fix add data sanitisation of image field.
Change make set_episode code more readable.
Change fix final two warnings in api v4.
Fix an API can return falsy as firstaired which crashes adding a show via load_from_tv_info() (The Andrew Marr Show@tvdbv4).
Add cast, crew type mappings
Only take Main Actors, Hosts, Interviewers, Presenters
Change increase viewagble history menu items from 13 to 15.
2021-09-05 19:10:58 +00:00
|
|
|
|
TVDB_MRU = check_setting_str(CFG, 'TVDb', 'tvdb_mru', '')
|
2023-01-12 01:04:47 +00:00
|
|
|
|
TVM_MRU = check_setting_str(CFG, 'TVmaze', 'tvm_mru', '')
|
|
|
|
|
|
|
|
|
|
USE_PYTIVO = bool(check_setting_int(CFG, 'pyTivo', 'use_pytivo', 0))
|
|
|
|
|
PYTIVO_HOST = check_setting_str(CFG, 'pyTivo', 'pytivo_host', '')
|
|
|
|
|
PYTIVO_SHARE_NAME = check_setting_str(CFG, 'pyTivo', 'pytivo_share_name', '')
|
|
|
|
|
PYTIVO_TIVO_NAME = check_setting_str(CFG, 'pyTivo', 'pytivo_tivo_name', '')
|
|
|
|
|
|
|
|
|
|
USE_PUSHALOT = bool(check_setting_int(CFG, 'Pushalot', 'use_pushalot', 0))
|
|
|
|
|
PUSHALOT_NOTIFY_ONSNATCH = bool(check_setting_int(CFG, 'Pushalot', 'pushalot_notify_onsnatch', 0))
|
|
|
|
|
PUSHALOT_NOTIFY_ONDOWNLOAD = bool(check_setting_int(CFG, 'Pushalot', 'pushalot_notify_ondownload', 0))
|
|
|
|
|
PUSHALOT_NOTIFY_ONSUBTITLEDOWNLOAD = bool(
|
|
|
|
|
check_setting_int(CFG, 'Pushalot', 'pushalot_notify_onsubtitledownload', 0))
|
|
|
|
|
PUSHALOT_AUTHORIZATIONTOKEN = check_setting_str(CFG, 'Pushalot', 'pushalot_authorizationtoken', '')
|
|
|
|
|
|
|
|
|
|
USE_PUSHBULLET = bool(check_setting_int(CFG, 'Pushbullet', 'use_pushbullet', 0))
|
|
|
|
|
PUSHBULLET_NOTIFY_ONSNATCH = bool(check_setting_int(CFG, 'Pushbullet', 'pushbullet_notify_onsnatch', 0))
|
|
|
|
|
PUSHBULLET_NOTIFY_ONDOWNLOAD = bool(check_setting_int(CFG, 'Pushbullet', 'pushbullet_notify_ondownload', 0))
|
|
|
|
|
PUSHBULLET_NOTIFY_ONSUBTITLEDOWNLOAD = bool(
|
|
|
|
|
check_setting_int(CFG, 'Pushbullet', 'pushbullet_notify_onsubtitledownload', 0))
|
|
|
|
|
PUSHBULLET_ACCESS_TOKEN = check_setting_str(CFG, 'Pushbullet', 'pushbullet_access_token', '')
|
|
|
|
|
PUSHBULLET_DEVICE_IDEN = check_setting_str(CFG, 'Pushbullet', 'pushbullet_device_iden', '')
|
|
|
|
|
|
|
|
|
|
USE_SLACK = bool(check_setting_int(CFG, 'Slack', 'use_slack', 0))
|
|
|
|
|
SLACK_NOTIFY_ONSNATCH = bool(check_setting_int(CFG, 'Slack', 'slack_notify_onsnatch', 0))
|
|
|
|
|
SLACK_NOTIFY_ONDOWNLOAD = bool(check_setting_int(CFG, 'Slack', 'slack_notify_ondownload', 0))
|
|
|
|
|
SLACK_NOTIFY_ONSUBTITLEDOWNLOAD = bool(check_setting_int(CFG, 'Slack', 'slack_notify_onsubtitledownload', 0))
|
|
|
|
|
SLACK_CHANNEL = check_setting_str(CFG, 'Slack', 'slack_channel', '')
|
|
|
|
|
SLACK_AS_AUTHED = bool(check_setting_int(CFG, 'Slack', 'slack_as_authed', 0))
|
|
|
|
|
SLACK_BOT_NAME = check_setting_str(CFG, 'Slack', 'slack_bot_name', '')
|
|
|
|
|
SLACK_ICON_URL = check_setting_str(CFG, 'Slack', 'slack_icon_url', '')
|
|
|
|
|
SLACK_ACCESS_TOKEN = check_setting_str(CFG, 'Slack', 'slack_access_token', '')
|
|
|
|
|
|
|
|
|
|
USE_DISCORD = bool(check_setting_int(CFG, 'Discord', 'use_discord', 0))
|
|
|
|
|
DISCORD_NOTIFY_ONSNATCH = bool(check_setting_int(CFG, 'Discord', 'discord_notify_onsnatch', 0))
|
|
|
|
|
DISCORD_NOTIFY_ONDOWNLOAD = bool(check_setting_int(CFG, 'Discord', 'discord_notify_ondownload', 0))
|
|
|
|
|
DISCORD_NOTIFY_ONSUBTITLEDOWNLOAD = bool(
|
|
|
|
|
check_setting_int(CFG, 'Discord', 'discord_notify_onsubtitledownload', 0))
|
|
|
|
|
DISCORD_AS_AUTHED = bool(check_setting_int(CFG, 'Discord', 'discord_as_authed', 0))
|
|
|
|
|
DISCORD_USERNAME = check_setting_str(CFG, 'Discord', 'discord_username', '')
|
|
|
|
|
DISCORD_ICON_URL = check_setting_str(CFG, 'Discord', 'discord_icon_url', '')
|
|
|
|
|
DISCORD_AS_TTS = bool(check_setting_str(CFG, 'Discord', 'discord_as_tts', 0))
|
|
|
|
|
DISCORD_ACCESS_TOKEN = check_setting_str(CFG, 'Discord', 'discord_access_token', '')
|
|
|
|
|
|
|
|
|
|
USE_GITTER = bool(check_setting_int(CFG, 'Gitter', 'use_gitter', 0))
|
|
|
|
|
GITTER_NOTIFY_ONSNATCH = bool(check_setting_int(CFG, 'Gitter', 'gitter_notify_onsnatch', 0))
|
|
|
|
|
GITTER_NOTIFY_ONDOWNLOAD = bool(check_setting_int(CFG, 'Gitter', 'gitter_notify_ondownload', 0))
|
|
|
|
|
GITTER_NOTIFY_ONSUBTITLEDOWNLOAD = bool(check_setting_int(CFG, 'Gitter', 'gitter_notify_onsubtitledownload', 0))
|
|
|
|
|
GITTER_ROOM = check_setting_str(CFG, 'Gitter', 'gitter_room', '')
|
|
|
|
|
GITTER_ACCESS_TOKEN = check_setting_str(CFG, 'Gitter', 'gitter_access_token', '')
|
|
|
|
|
|
|
|
|
|
USE_TELEGRAM = bool(check_setting_int(CFG, 'Telegram', 'use_telegram', 0))
|
|
|
|
|
TELEGRAM_NOTIFY_ONSNATCH = bool(check_setting_int(CFG, 'Telegram', 'telegram_notify_onsnatch', 0))
|
|
|
|
|
TELEGRAM_NOTIFY_ONDOWNLOAD = bool(check_setting_int(CFG, 'Telegram', 'telegram_notify_ondownload', 0))
|
|
|
|
|
TELEGRAM_NOTIFY_ONSUBTITLEDOWNLOAD = bool(check_setting_int(
|
|
|
|
|
CFG, 'Telegram', 'telegram_notify_onsubtitledownload', 0))
|
|
|
|
|
TELEGRAM_SEND_IMAGE = bool(check_setting_int(CFG, 'Telegram', 'telegram_send_image', 1))
|
|
|
|
|
TELEGRAM_QUIET = bool(check_setting_int(CFG, 'Telegram', 'telegram_quiet', 0))
|
|
|
|
|
TELEGRAM_ACCESS_TOKEN = check_setting_str(CFG, 'Telegram', 'telegram_access_token', '')
|
|
|
|
|
TELEGRAM_CHATID = check_setting_str(CFG, 'Telegram', 'telegram_chatid', '')
|
|
|
|
|
|
|
|
|
|
USE_EMAIL = bool(check_setting_int(CFG, 'Email', 'use_email', 0))
|
|
|
|
|
EMAIL_OLD_SUBJECTS = bool(check_setting_int(CFG, 'Email', 'email_old_subjects',
|
|
|
|
|
None is not EMAIL_HOST and any(EMAIL_HOST)))
|
|
|
|
|
EMAIL_NOTIFY_ONSNATCH = bool(check_setting_int(CFG, 'Email', 'email_notify_onsnatch', 0))
|
|
|
|
|
EMAIL_NOTIFY_ONDOWNLOAD = bool(check_setting_int(CFG, 'Email', 'email_notify_ondownload', 0))
|
|
|
|
|
EMAIL_NOTIFY_ONSUBTITLEDOWNLOAD = bool(check_setting_int(CFG, 'Email', 'email_notify_onsubtitledownload', 0))
|
|
|
|
|
EMAIL_HOST = check_setting_str(CFG, 'Email', 'email_host', '')
|
|
|
|
|
EMAIL_PORT = check_setting_int(CFG, 'Email', 'email_port', 25)
|
|
|
|
|
EMAIL_TLS = bool(check_setting_int(CFG, 'Email', 'email_tls', 0))
|
|
|
|
|
EMAIL_USER = check_setting_str(CFG, 'Email', 'email_user', '')
|
|
|
|
|
EMAIL_PASSWORD = check_setting_str(CFG, 'Email', 'email_password', '')
|
|
|
|
|
EMAIL_FROM = check_setting_str(CFG, 'Email', 'email_from', '')
|
|
|
|
|
EMAIL_LIST = check_setting_str(CFG, 'Email', 'email_list', '')
|
|
|
|
|
|
|
|
|
|
USE_SUBTITLES = bool(check_setting_int(CFG, 'Subtitles', 'use_subtitles', 0))
|
|
|
|
|
SUBTITLES_LANGUAGES = check_setting_str(CFG, 'Subtitles', 'subtitles_languages', '').split(',')
|
|
|
|
|
if SUBTITLES_LANGUAGES[0] == '':
|
|
|
|
|
SUBTITLES_LANGUAGES = []
|
|
|
|
|
SUBTITLES_DIR = check_setting_str(CFG, 'Subtitles', 'subtitles_dir', '')
|
|
|
|
|
SUBTITLES_SERVICES_LIST = check_setting_str(CFG, 'Subtitles', 'SUBTITLES_SERVICES_LIST', '').split(',')
|
|
|
|
|
SUBTITLES_SERVICES_ENABLED = [int(x) for x in
|
|
|
|
|
check_setting_str(CFG, 'Subtitles', 'SUBTITLES_SERVICES_ENABLED', '').split('|')
|
|
|
|
|
if x]
|
|
|
|
|
SUBTITLES_SERVICES_AUTH = [k.split(':::') for k in
|
|
|
|
|
check_setting_str(CFG, 'Subtitles', 'subtitles_services_auth', ':::').split('|||')
|
|
|
|
|
if k]
|
|
|
|
|
try:
|
|
|
|
|
# unlikely to happen, but did happen once, so added here as defensive
|
|
|
|
|
dct_cfg = sg_helpers.ast_eval(check_setting_str(CFG, 'Subtitles', 'subtitles_services_auth', ':::'), {})
|
|
|
|
|
SUBTITLES_SERVICES_AUTH = [[dct_cfg['os_user'], dct_cfg['os_pass']]]
|
|
|
|
|
except (BaseException, Exception):
|
|
|
|
|
pass
|
|
|
|
|
SUBTITLES_DEFAULT = bool(check_setting_int(CFG, 'Subtitles', 'subtitles_default', 0))
|
|
|
|
|
SUBTITLES_HISTORY = bool(check_setting_int(CFG, 'Subtitles', 'subtitles_history', 0))
|
|
|
|
|
SUBTITLES_FINDER_INTERVAL = check_setting_int(CFG, 'Subtitles', 'subtitles_finder_interval', 1)
|
|
|
|
|
SUBTITLES_OS_HASH = bool(check_setting_int(CFG, 'Subtitles', 'subtitles_os_hash', 1))
|
|
|
|
|
|
|
|
|
|
USE_FAILED_DOWNLOADS = bool(check_setting_int(CFG, 'FailedDownloads', 'use_failed_downloads', 0))
|
|
|
|
|
DELETE_FAILED = bool(check_setting_int(CFG, 'FailedDownloads', 'delete_failed', 0))
|
|
|
|
|
|
|
|
|
|
GIT_PATH = check_setting_str(CFG, 'General', 'git_path', '')
|
|
|
|
|
|
|
|
|
|
IGNORE_WORDS, IGNORE_WORDS_REGEX = helpers.split_word_str(
|
|
|
|
|
check_setting_str(CFG, 'General', 'ignore_words', helpers.generate_word_str(IGNORE_WORDS, IGNORE_WORDS_REGEX)))
|
|
|
|
|
REQUIRE_WORDS, REQUIRE_WORDS_REGEX = helpers.split_word_str(
|
|
|
|
|
check_setting_str(CFG, 'General', 'require_words',
|
|
|
|
|
helpers.generate_word_str(REQUIRE_WORDS, REQUIRE_WORDS_REGEX)))
|
|
|
|
|
|
|
|
|
|
CALENDAR_UNPROTECTED = bool(check_setting_int(CFG, 'General', 'calendar_unprotected', 0))
|
|
|
|
|
|
|
|
|
|
EXTRA_SCRIPTS = [x.strip() for x in check_setting_str(CFG, 'General', 'extra_scripts', '').split('|') if
|
|
|
|
|
x.strip()]
|
|
|
|
|
|
|
|
|
|
SG_EXTRA_SCRIPTS = [x.strip() for x in check_setting_str(CFG, 'General', 'sg_extra_scripts', '').split('|') if
|
|
|
|
|
x.strip()]
|
|
|
|
|
|
|
|
|
|
USE_ANIDB = bool(check_setting_int(CFG, 'ANIDB', 'use_anidb', 0))
|
|
|
|
|
ANIDB_USERNAME = check_setting_str(CFG, 'ANIDB', 'anidb_username', '')
|
|
|
|
|
ANIDB_PASSWORD = check_setting_str(CFG, 'ANIDB', 'anidb_password', '')
|
|
|
|
|
ANIDB_USE_MYLIST = bool(check_setting_int(CFG, 'ANIDB', 'anidb_use_mylist', 0))
|
|
|
|
|
|
|
|
|
|
ANIME_TREAT_AS_HDTV = bool(check_setting_int(CFG, 'ANIME', 'anime_treat_as_hdtv', 0))
|
|
|
|
|
|
|
|
|
|
METADATA_XBMC = check_setting_str(CFG, 'General', 'metadata_xbmc', '0|0|0|0|0|0|0|0|0|0')
|
|
|
|
|
METADATA_XBMC_12PLUS = check_setting_str(CFG, 'General', 'metadata_xbmc_12plus', '0|0|0|0|0|0|0|0|0|0')
|
|
|
|
|
METADATA_MEDIABROWSER = check_setting_str(CFG, 'General', 'metadata_mediabrowser', '0|0|0|0|0|0|0|0|0|0')
|
|
|
|
|
METADATA_PS3 = check_setting_str(CFG, 'General', 'metadata_ps3', '0|0|0|0|0|0|0|0|0|0')
|
|
|
|
|
METADATA_WDTV = check_setting_str(CFG, 'General', 'metadata_wdtv', '0|0|0|0|0|0|0|0|0|0')
|
|
|
|
|
METADATA_TIVO = check_setting_str(CFG, 'General', 'metadata_tivo', '0|0|0|0|0|0|0|0|0|0')
|
|
|
|
|
METADATA_MEDE8ER = check_setting_str(CFG, 'General', 'metadata_mede8er', '0|0|0|0|0|0|0|0|0|0')
|
|
|
|
|
METADATA_KODI = check_setting_str(CFG, 'General', 'metadata_kodi', '0|0|0|0|0|0|0|0|0|0')
|
|
|
|
|
|
|
|
|
|
HOME_LAYOUT = check_setting_str(CFG, 'GUI', 'home_layout', 'poster')
|
|
|
|
|
FOOTER_TIME_LAYOUT = check_setting_int(CFG, 'GUI', 'footer_time_layout', 0)
|
|
|
|
|
POSTER_SORTBY = check_setting_str(CFG, 'GUI', 'poster_sortby', 'name')
|
|
|
|
|
POSTER_SORTDIR = check_setting_int(CFG, 'GUI', 'poster_sortdir', 1)
|
|
|
|
|
DISPLAY_SHOW_GLIDE = sg_helpers.ast_eval(check_setting_str(CFG, 'GUI', 'display_show_glide', None), {})
|
|
|
|
|
DISPLAY_SHOW_GLIDE_SLIDETIME = check_setting_int(CFG, 'GUI', 'display_show_glide_slidetime', 3000)
|
|
|
|
|
DISPLAY_SHOW_VIEWMODE = check_setting_int(CFG, 'GUI', 'display_show_viewmode', 2)
|
|
|
|
|
DISPLAY_SHOW_BACKGROUND = bool(check_setting_int(CFG, 'GUI', 'display_show_background', 1))
|
|
|
|
|
DISPLAY_SHOW_BACKGROUND_TRANSLUCENT = bool(check_setting_int(
|
|
|
|
|
CFG, 'GUI', 'display_show_background_translucent', 1))
|
|
|
|
|
DISPLAY_SHOW_VIEWART = check_setting_int(CFG, 'GUI', 'display_show_viewart', 0)
|
|
|
|
|
DISPLAY_SHOW_MINIMUM = bool(check_setting_int(CFG, 'GUI', 'display_show_minimum', 1))
|
|
|
|
|
DISPLAY_SHOW_SPECIALS = bool(check_setting_int(CFG, 'GUI', 'display_show_specials', 0))
|
|
|
|
|
|
|
|
|
|
EPISODE_VIEW_VIEWMODE = check_setting_int(CFG, 'GUI', 'episode_view_viewmode', 2)
|
|
|
|
|
EPISODE_VIEW_BACKGROUND = bool(check_setting_int(CFG, 'GUI', 'episode_view_background', 1))
|
|
|
|
|
EPISODE_VIEW_BACKGROUND_TRANSLUCENT = bool(check_setting_int(
|
|
|
|
|
CFG, 'GUI', 'episode_view_background_translucent', 1))
|
|
|
|
|
EPISODE_VIEW_LAYOUT = check_setting_str(CFG, 'GUI', 'episode_view_layout', 'daybyday')
|
|
|
|
|
EPISODE_VIEW_SORT = check_setting_str(CFG, 'GUI', 'episode_view_sort', 'time')
|
|
|
|
|
EPISODE_VIEW_DISPLAY_PAUSED = check_setting_int(CFG, 'GUI', 'episode_view_display_paused', 1)
|
|
|
|
|
EPISODE_VIEW_POSTERS = bool(check_setting_int(CFG, 'GUI', 'episode_view_posters', 1))
|
|
|
|
|
EPISODE_VIEW_MISSED_RANGE = check_setting_int(CFG, 'GUI', 'episode_view_missed_range', 7)
|
|
|
|
|
|
|
|
|
|
HISTORY_LAYOUT = check_setting_str(CFG, 'GUI', 'history_layout', 'detailed')
|
2023-02-11 18:02:58 +00:00
|
|
|
|
BROWSELIST_HIDDEN = list(map(
|
2023-01-12 01:04:47 +00:00
|
|
|
|
lambda y: TVidProdid.glue in y and y or '%s%s%s' % (
|
|
|
|
|
(TVINFO_TVDB, TVINFO_IMDB)[bool(helpers.parse_imdb_id(y))], TVidProdid.glue, y),
|
2023-02-11 18:02:58 +00:00
|
|
|
|
[x.strip() for x in check_setting_str(CFG, 'GUI', 'browselist_hidden', '').split('|~|') if x.strip()]))
|
2023-01-12 01:04:47 +00:00
|
|
|
|
BROWSELIST_MRU = sg_helpers.ast_eval(check_setting_str(CFG, 'GUI', 'browselist_prefs', None), {})
|
|
|
|
|
|
|
|
|
|
BACKUP_DB_PATH = check_setting_str(CFG, 'Backup', 'backup_db_path', '')
|
|
|
|
|
BACKUP_DB_ONEDAY = bool(check_setting_int(CFG, 'Backup', 'backup_db_oneday', 0))
|
|
|
|
|
BACKUP_DB_MAX_COUNT = minimax(check_setting_int(CFG, 'Backup', 'backup_db_max_count', BACKUP_DB_DEFAULT_COUNT),
|
|
|
|
|
BACKUP_DB_DEFAULT_COUNT, 0, 90)
|
|
|
|
|
|
|
|
|
|
UPDATES_TODO = sg_helpers.ast_eval(check_setting_str(CFG, 'Updates', 'updates_todo', None), {})
|
|
|
|
|
|
|
|
|
|
sg_helpers.db = db
|
|
|
|
|
sg_helpers.DOMAIN_FAILURES.load_from_db()
|
|
|
|
|
|
|
|
|
|
# initialize NZB and TORRENT providers
|
2023-02-13 21:00:11 +00:00
|
|
|
|
provider_list = providers.provider_modules()
|
2023-01-12 01:04:47 +00:00
|
|
|
|
|
|
|
|
|
NEWZNAB_DATA = check_setting_str(CFG, 'Newznab', 'newznab_data', '')
|
2023-02-13 21:00:11 +00:00
|
|
|
|
newznab_providers = providers.newznab_source_list(NEWZNAB_DATA)
|
2023-01-12 01:04:47 +00:00
|
|
|
|
|
|
|
|
|
torrentrss_data = check_setting_str(CFG, 'TorrentRss', 'torrentrss_data', '')
|
2023-02-13 21:00:11 +00:00
|
|
|
|
torrent_rss_providers = providers.torrent_rss_source_list(torrentrss_data)
|
2023-01-12 01:04:47 +00:00
|
|
|
|
|
|
|
|
|
# dynamically load provider settings
|
2023-02-13 21:00:11 +00:00
|
|
|
|
for torrent_prov in [curProvider for curProvider in providers.sorted_sources()
|
2023-01-12 01:04:47 +00:00
|
|
|
|
if GenericProvider.TORRENT == curProvider.providerType]:
|
|
|
|
|
prov_id = torrent_prov.get_id()
|
|
|
|
|
prov_id_uc = torrent_prov.get_id().upper()
|
|
|
|
|
torrent_prov.enabled = bool(check_setting_int(CFG, prov_id_uc, prov_id, False))
|
|
|
|
|
|
|
|
|
|
# check str with a def of list, don't add to block settings
|
|
|
|
|
if getattr(torrent_prov, 'url_edit', None):
|
|
|
|
|
torrent_prov.url_home = check_setting_str(CFG, prov_id_uc, prov_id + '_url_home', [])
|
|
|
|
|
|
|
|
|
|
# check int with a default of str, don't add to block settings
|
|
|
|
|
attr = 'seed_time'
|
|
|
|
|
if hasattr(torrent_prov, attr):
|
|
|
|
|
torrent_prov.seed_time = check_setting_int(CFG, prov_id_uc, '%s_%s' % (prov_id, attr), '')
|
|
|
|
|
|
|
|
|
|
# custom cond, don't add to block settings
|
|
|
|
|
attr = 'enable_recentsearch'
|
|
|
|
|
if hasattr(torrent_prov, attr):
|
|
|
|
|
torrent_prov.enable_recentsearch = bool(check_setting_int(
|
|
|
|
|
CFG, prov_id_uc, '%s_%s' % (prov_id, attr), True)) or not getattr(torrent_prov, 'supports_backlog')
|
|
|
|
|
|
|
|
|
|
# check str with a default of list, don't add to block settings
|
|
|
|
|
if hasattr(torrent_prov, 'filter'):
|
|
|
|
|
torrent_prov.filter = check_setting_str(CFG, prov_id_uc, prov_id + '_filter', [])
|
|
|
|
|
|
|
|
|
|
for (attr, default) in [
|
|
|
|
|
('enable_backlog', True), ('enable_scheduled_backlog', True),
|
|
|
|
|
('api_key', ''), ('hash', ''), ('digest', ''),
|
|
|
|
|
('username', ''), ('uid', ''), ('password', ''), ('passkey', ''),
|
|
|
|
|
('options', ''),
|
|
|
|
|
('_seed_ratio', ''), ('minseed', 0), ('minleech', 0),
|
|
|
|
|
('scene_only', False), ('scene_or_contain', ''), ('scene_loose', False), ('scene_loose_active', False),
|
|
|
|
|
('scene_rej_nuked', False), ('scene_nuked_active', False),
|
|
|
|
|
('freeleech', False), ('confirmed', False), ('reject_m2ts', False), ('use_after_get_data', True),
|
|
|
|
|
('search_mode', 'eponly'), ('search_fallback', False)
|
|
|
|
|
]:
|
|
|
|
|
if hasattr(torrent_prov, attr):
|
|
|
|
|
attr_check = '%s_%s' % (prov_id, attr.strip('_'))
|
|
|
|
|
if isinstance(default, bool):
|
|
|
|
|
setattr(torrent_prov, attr, bool(check_setting_int(CFG, prov_id_uc, attr_check, default)))
|
|
|
|
|
elif isinstance(default, string_types):
|
|
|
|
|
setattr(torrent_prov, attr, check_setting_str(CFG, prov_id_uc, attr_check, default))
|
|
|
|
|
elif isinstance(default, int):
|
|
|
|
|
setattr(torrent_prov, attr, check_setting_int(CFG, prov_id_uc, attr_check, default))
|
|
|
|
|
|
2023-02-13 21:00:11 +00:00
|
|
|
|
for nzb_prov in [curProvider for curProvider in providers.sorted_sources()
|
2023-01-12 01:04:47 +00:00
|
|
|
|
if GenericProvider.NZB == curProvider.providerType]:
|
|
|
|
|
prov_id = nzb_prov.get_id()
|
|
|
|
|
prov_id_uc = nzb_prov.get_id().upper()
|
|
|
|
|
nzb_prov.enabled = bool(check_setting_int(CFG, prov_id_uc, prov_id, False))
|
|
|
|
|
|
|
|
|
|
attr = 'enable_recentsearch'
|
|
|
|
|
if hasattr(nzb_prov, attr):
|
|
|
|
|
nzb_prov.enable_recentsearch = bool(check_setting_int(
|
|
|
|
|
CFG, prov_id_uc, '%s_%s' % (prov_id, attr), True)) or not getattr(nzb_prov, 'supports_backlog')
|
|
|
|
|
|
|
|
|
|
for (attr, default) in [
|
|
|
|
|
('enable_backlog', True), ('enable_scheduled_backlog', True),
|
|
|
|
|
('api_key', ''), ('digest', ''), ('username', ''),
|
|
|
|
|
('scene_only', False), ('scene_or_contain', ''), ('scene_loose', False), ('scene_loose_active', False),
|
|
|
|
|
('scene_rej_nuked', False), ('scene_nuked_active', False),
|
|
|
|
|
('search_mode', 'eponly'), ('search_fallback', False), ('server_type', NewznabConstants.SERVER_DEFAULT)
|
|
|
|
|
]:
|
|
|
|
|
if hasattr(nzb_prov, attr):
|
|
|
|
|
attr_check = '%s_%s' % (prov_id, attr.strip('_'))
|
|
|
|
|
if isinstance(default, bool):
|
|
|
|
|
setattr(nzb_prov, attr, bool(check_setting_int(CFG, prov_id_uc, attr_check, default)))
|
|
|
|
|
elif isinstance(default, string_types):
|
|
|
|
|
setattr(nzb_prov, attr, check_setting_str(CFG, prov_id_uc, attr_check, default))
|
|
|
|
|
elif isinstance(default, int):
|
|
|
|
|
setattr(nzb_prov, attr, check_setting_int(CFG, prov_id_uc, attr_check, default))
|
2023-02-11 18:02:58 +00:00
|
|
|
|
for cur_provider in filter(lambda p: abs(zlib.crc32(decode_bytes(p.name))) + 40000400 in (
|
2023-01-12 01:04:47 +00:00
|
|
|
|
1449593765, 1597250020, 1524942228, 160758496, 2925374331
|
|
|
|
|
) or (p.url and abs(zlib.crc32(decode_bytes(re.sub(r'[./]', '', p.url[-10:])))) + 40000400 in (
|
2023-02-13 21:00:11 +00:00
|
|
|
|
2417143804,)), providers.sorted_sources()):
|
2023-01-12 01:04:47 +00:00
|
|
|
|
header = {'User-Agent': get_ua()}
|
|
|
|
|
if hasattr(cur_provider, 'nn'):
|
|
|
|
|
cur_provider.nn = False
|
|
|
|
|
cur_provider.ui_string()
|
|
|
|
|
# noinspection PyProtectedMember
|
|
|
|
|
header = callable(getattr(cur_provider, '_init_api', False)) and False is cur_provider._init_api() \
|
|
|
|
|
and header or {}
|
|
|
|
|
cur_provider.headers.update(header)
|
2024-08-12 20:33:28 +00:00
|
|
|
|
update_config |= cur_provider.should_save_config()
|
2023-01-12 01:04:47 +00:00
|
|
|
|
|
|
|
|
|
# current commit hash
|
|
|
|
|
CUR_COMMIT_HASH = check_setting_str(CFG, 'General', 'cur_commit_hash', '')
|
|
|
|
|
|
|
|
|
|
# current commit branch
|
|
|
|
|
CUR_COMMIT_BRANCH = check_setting_str(CFG, 'General', 'cur_commit_branch', '')
|
|
|
|
|
|
|
|
|
|
if not CUR_COMMIT_HASH or '00000000000000000000000000000000000' == CUR_COMMIT_HASH:
|
|
|
|
|
tmp_v = version_checker.SoftwareUpdater()
|
|
|
|
|
if 'git' == tmp_v.install_type:
|
|
|
|
|
# noinspection PyProtectedMember
|
|
|
|
|
tmp_v.updater._find_installed_version()
|
|
|
|
|
if not CUR_COMMIT_HASH:
|
|
|
|
|
# in case git fails for some reason, set dummy hash to enable update for next start
|
|
|
|
|
CUR_COMMIT_HASH = '00000000000000000000000000000000000'
|
|
|
|
|
if not CUR_COMMIT_BRANCH:
|
|
|
|
|
# noinspection PyProtectedMember
|
|
|
|
|
tmp_branch = tmp_v.updater._find_installed_branch()
|
|
|
|
|
if tmp_branch:
|
|
|
|
|
CUR_COMMIT_BRANCH = tmp_branch
|
|
|
|
|
update_config = True
|
|
|
|
|
|
|
|
|
|
EXT_UPDATES = (35 > len(CUR_COMMIT_HASH) or not bool(re.match('^[a-z0-9]+$', CUR_COMMIT_HASH))) and \
|
|
|
|
|
('docker/other', 'snap')['snap' in CUR_COMMIT_HASH]
|
|
|
|
|
|
|
|
|
|
if not os.path.isfile(CONFIG_FILE):
|
2023-03-08 13:44:20 +00:00
|
|
|
|
logger.debug(f'Unable to find \'{CONFIG_FILE}\', all settings will be default!')
|
2023-01-12 01:04:47 +00:00
|
|
|
|
update_config = True
|
|
|
|
|
|
|
|
|
|
# Get expected config version
|
|
|
|
|
CONFIG_VERSION = max(ConfigMigrator(CFG).migration_names)
|
2024-08-12 20:33:28 +00:00
|
|
|
|
|
|
|
|
|
# we have fully loaded all config settings into vars
|
|
|
|
|
CONFIG_LOADED = True
|
|
|
|
|
|
2023-01-12 01:04:47 +00:00
|
|
|
|
if update_config:
|
2024-08-11 19:00:07 +00:00
|
|
|
|
_save_config(force=True)
|
2023-01-12 01:04:47 +00:00
|
|
|
|
|
|
|
|
|
# start up all the threads
|
|
|
|
|
old_log = os.path.join(LOG_DIR, 'sickgear.log')
|
|
|
|
|
if os.path.isfile(old_log):
|
|
|
|
|
try:
|
|
|
|
|
os.rename(old_log, os.path.join(LOG_DIR, logger.sb_log_instance.log_file))
|
|
|
|
|
except (BaseException, Exception):
|
|
|
|
|
pass
|
|
|
|
|
logger.sb_log_instance.init_logging(console_logging=console_logging)
|
|
|
|
|
|
|
|
|
|
showList = []
|
|
|
|
|
showDict = {}
|
|
|
|
|
|
|
|
|
|
# dict of switched shows for web redirects
|
|
|
|
|
switched_shows = {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def init_stage_2():
|
|
|
|
|
|
|
|
|
|
# Misc
|
|
|
|
|
global __INITIALIZED__, MEMCACHE, MEMCACHE_FLAG_IMAGES, RECENTSEARCH_STARTUP
|
|
|
|
|
# Schedulers
|
|
|
|
|
# global trakt_checker_scheduler
|
2023-03-16 04:19:03 +00:00
|
|
|
|
global update_software_scheduler, update_packages_scheduler, \
|
|
|
|
|
update_show_scheduler, update_release_mappings_scheduler, \
|
|
|
|
|
search_backlog_scheduler, search_propers_scheduler, \
|
|
|
|
|
search_recent_scheduler, search_subtitles_scheduler, \
|
|
|
|
|
search_queue_scheduler, show_queue_scheduler, people_queue_scheduler, \
|
|
|
|
|
watched_state_queue_scheduler, emby_watched_state_scheduler, plex_watched_state_scheduler, \
|
2024-06-28 01:57:31 +00:00
|
|
|
|
process_media_scheduler, background_mapping_task, config_events
|
2023-03-16 04:19:03 +00:00
|
|
|
|
|
2023-01-12 01:04:47 +00:00
|
|
|
|
# Gen Config/Misc
|
|
|
|
|
global SHOW_UPDATE_HOUR, UPDATE_INTERVAL, UPDATE_PACKAGES_INTERVAL
|
|
|
|
|
# Search Settings/Episode
|
|
|
|
|
global RECENTSEARCH_INTERVAL
|
|
|
|
|
# Subtitles
|
|
|
|
|
global USE_SUBTITLES, SUBTITLES_FINDER_INTERVAL
|
|
|
|
|
# Media Process/Post-Processing
|
|
|
|
|
global PROCESS_AUTOMATICALLY, MEDIAPROCESS_INTERVAL
|
|
|
|
|
# Media Process/Metadata
|
|
|
|
|
global metadata_provider_dict, METADATA_KODI, METADATA_MEDE8ER, METADATA_MEDIABROWSER, \
|
|
|
|
|
METADATA_PS3, METADATA_TIVO, METADATA_WDTV, METADATA_XBMC, METADATA_XBMC_12PLUS
|
|
|
|
|
# Notification Settings/HT and NAS
|
|
|
|
|
global EMBY_WATCHEDSTATE_INTERVAL, PLEX_WATCHEDSTATE_INTERVAL
|
|
|
|
|
|
|
|
|
|
# initialize main database
|
|
|
|
|
my_db = db.DBConnection()
|
2023-02-24 11:46:07 +00:00
|
|
|
|
db.migration_code(my_db)
|
2023-01-12 01:04:47 +00:00
|
|
|
|
|
|
|
|
|
# initialize the cache database
|
|
|
|
|
my_db = db.DBConnection('cache.db')
|
2023-02-24 11:46:07 +00:00
|
|
|
|
db.upgrade_database(my_db, cache_db.InitialSchema)
|
2023-01-12 01:04:47 +00:00
|
|
|
|
|
|
|
|
|
# initialize the failed downloads database
|
|
|
|
|
my_db = db.DBConnection('failed.db')
|
2023-02-24 11:46:07 +00:00
|
|
|
|
db.upgrade_database(my_db, failed_db.InitialSchema)
|
2023-01-12 01:04:47 +00:00
|
|
|
|
|
|
|
|
|
# fix up any db problems
|
|
|
|
|
my_db = db.DBConnection()
|
2023-02-24 11:46:07 +00:00
|
|
|
|
db.sanity_check_db(my_db, mainDB.MainSanityCheck)
|
2023-01-12 01:04:47 +00:00
|
|
|
|
|
|
|
|
|
# initialize metadata_providers
|
|
|
|
|
metadata_provider_dict = metadata.get_metadata_generator_dict()
|
|
|
|
|
for cur_metadata_tuple in [(METADATA_KODI, metadata.kodi),
|
|
|
|
|
(METADATA_MEDE8ER, metadata.mede8er),
|
|
|
|
|
(METADATA_MEDIABROWSER, metadata.mediabrowser),
|
|
|
|
|
(METADATA_PS3, metadata.ps3),
|
|
|
|
|
(METADATA_TIVO, metadata.tivo),
|
|
|
|
|
(METADATA_WDTV, metadata.wdtv),
|
|
|
|
|
(METADATA_XBMC, metadata.xbmc),
|
|
|
|
|
(METADATA_XBMC_12PLUS, metadata.xbmc_12plus),
|
|
|
|
|
]:
|
|
|
|
|
(cur_metadata_config, cur_metadata_class) = cur_metadata_tuple
|
|
|
|
|
tmp_provider = cur_metadata_class.metadata_class()
|
|
|
|
|
tmp_provider.set_config(cur_metadata_config)
|
|
|
|
|
metadata_provider_dict[tmp_provider.name] = tmp_provider
|
|
|
|
|
|
|
|
|
|
# initialize schedulers
|
2023-03-16 04:19:03 +00:00
|
|
|
|
# /
|
|
|
|
|
# queues must be first
|
|
|
|
|
show_queue_scheduler = scheduler.Scheduler(
|
|
|
|
|
show_queue.ShowQueue(),
|
|
|
|
|
cycle_time=datetime.timedelta(seconds=3),
|
|
|
|
|
thread_name='SHOWQUEUE')
|
|
|
|
|
|
|
|
|
|
search_queue_scheduler = scheduler.Scheduler(
|
|
|
|
|
search_queue.SearchQueue(),
|
|
|
|
|
cycle_time=datetime.timedelta(seconds=3),
|
|
|
|
|
thread_name='SEARCHQUEUE')
|
|
|
|
|
|
|
|
|
|
people_queue_scheduler = scheduler.Scheduler(
|
|
|
|
|
people_queue.PeopleQueue(),
|
|
|
|
|
cycle_time=datetime.timedelta(seconds=3),
|
|
|
|
|
thread_name='PEOPLEQUEUE'
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
watched_state_queue_scheduler = scheduler.Scheduler(
|
|
|
|
|
watchedstate_queue.WatchedStateQueue(),
|
|
|
|
|
cycle_time=datetime.timedelta(seconds=3),
|
|
|
|
|
thread_name='WATCHEDSTATEQUEUE')
|
|
|
|
|
|
|
|
|
|
# /
|
2023-01-12 01:04:47 +00:00
|
|
|
|
# updaters
|
|
|
|
|
update_software_scheduler = scheduler.Scheduler(
|
|
|
|
|
version_checker.SoftwareUpdater(),
|
2023-02-13 21:00:11 +00:00
|
|
|
|
cycle_time=datetime.timedelta(hours=UPDATE_INTERVAL),
|
2023-03-16 04:19:03 +00:00
|
|
|
|
thread_name='SOFTWAREUPDATE',
|
2023-01-12 01:04:47 +00:00
|
|
|
|
silent=False)
|
|
|
|
|
|
|
|
|
|
update_packages_scheduler = scheduler.Scheduler(
|
|
|
|
|
version_checker.PackagesUpdater(),
|
2023-02-13 21:00:11 +00:00
|
|
|
|
cycle_time=datetime.timedelta(hours=UPDATE_PACKAGES_INTERVAL),
|
2023-01-12 01:04:47 +00:00
|
|
|
|
# run_delay=datetime.timedelta(minutes=2),
|
2023-03-16 04:19:03 +00:00
|
|
|
|
thread_name='PACKAGESUPDATE',
|
2023-01-12 01:04:47 +00:00
|
|
|
|
silent=False)
|
|
|
|
|
|
2023-03-16 04:19:03 +00:00
|
|
|
|
update_show_scheduler = scheduler.Scheduler(
|
2023-01-12 01:04:47 +00:00
|
|
|
|
show_updater.ShowUpdater(),
|
2023-02-13 21:00:11 +00:00
|
|
|
|
cycle_time=datetime.timedelta(hours=1),
|
2023-01-12 01:04:47 +00:00
|
|
|
|
start_time=datetime.time(hour=SHOW_UPDATE_HOUR),
|
2023-03-16 04:19:03 +00:00
|
|
|
|
thread_name='SHOWDATAUPDATE',
|
2023-02-10 14:15:50 +00:00
|
|
|
|
prevent_cycle_run=show_queue_scheduler.action.is_show_update_running) # 3AM
|
2023-01-12 01:04:47 +00:00
|
|
|
|
|
2023-03-16 04:19:03 +00:00
|
|
|
|
classes.loading_msg.message = 'Loading show maps'
|
|
|
|
|
update_release_mappings_scheduler = scheduler.Scheduler(
|
|
|
|
|
scene_exceptions.ReleaseMap(),
|
|
|
|
|
cycle_time=datetime.timedelta(hours=2),
|
|
|
|
|
thread_name='SHOWMAPSUPDATE',
|
|
|
|
|
silent=False)
|
2023-01-12 01:04:47 +00:00
|
|
|
|
|
2023-03-16 04:19:03 +00:00
|
|
|
|
# /
|
2023-01-12 01:04:47 +00:00
|
|
|
|
# searchers
|
|
|
|
|
init_search_delay = int(os.environ.get('INIT_SEARCH_DELAY', 0))
|
|
|
|
|
|
|
|
|
|
# enter 4499 (was 4489) for experimental internal provider intervals
|
|
|
|
|
update_interval = datetime.timedelta(minutes=(RECENTSEARCH_INTERVAL, 1)[4499 == RECENTSEARCH_INTERVAL])
|
2023-03-16 04:19:03 +00:00
|
|
|
|
update_now = datetime.timedelta(minutes=0)
|
|
|
|
|
search_recent_scheduler = scheduler.Scheduler(
|
2023-01-12 01:04:47 +00:00
|
|
|
|
search_recent.RecentSearcher(),
|
2023-02-13 21:00:11 +00:00
|
|
|
|
cycle_time=update_interval,
|
2023-01-12 01:04:47 +00:00
|
|
|
|
run_delay=update_now if RECENTSEARCH_STARTUP else datetime.timedelta(minutes=init_search_delay or 5),
|
2023-03-16 04:19:03 +00:00
|
|
|
|
thread_name='RECENTSEARCH',
|
2023-01-12 01:04:47 +00:00
|
|
|
|
prevent_cycle_run=search_queue_scheduler.action.is_recentsearch_in_progress)
|
|
|
|
|
|
2023-02-13 21:00:11 +00:00
|
|
|
|
if [x for x in providers.sorted_sources()
|
|
|
|
|
if x.is_active() and getattr(x, 'enable_backlog', None) and GenericProvider.NZB == x.providerType]:
|
2023-01-12 01:04:47 +00:00
|
|
|
|
nextbacklogpossible = datetime.datetime.fromtimestamp(
|
|
|
|
|
search_backlog.BacklogSearcher().last_runtime) + datetime.timedelta(hours=23)
|
|
|
|
|
now = datetime.datetime.now()
|
|
|
|
|
if nextbacklogpossible > now:
|
|
|
|
|
time_diff = nextbacklogpossible - now
|
|
|
|
|
if (time_diff > datetime.timedelta(hours=12) and
|
|
|
|
|
nextbacklogpossible - datetime.timedelta(hours=12) > now):
|
|
|
|
|
time_diff = time_diff - datetime.timedelta(hours=12)
|
|
|
|
|
else:
|
|
|
|
|
time_diff = datetime.timedelta(minutes=0)
|
|
|
|
|
backlogdelay = helpers.try_int((time_diff.total_seconds() / 60) + 10, 10)
|
|
|
|
|
else:
|
|
|
|
|
backlogdelay = 10
|
2023-03-16 04:19:03 +00:00
|
|
|
|
search_backlog_scheduler = search_backlog.BacklogSearchScheduler(
|
2023-01-12 01:04:47 +00:00
|
|
|
|
search_backlog.BacklogSearcher(),
|
2023-02-13 21:00:11 +00:00
|
|
|
|
cycle_time=datetime.timedelta(minutes=get_backlog_cycle_time()),
|
2023-01-12 01:04:47 +00:00
|
|
|
|
run_delay=datetime.timedelta(minutes=init_search_delay or backlogdelay),
|
2023-03-16 04:19:03 +00:00
|
|
|
|
thread_name='BACKLOGSEARCH',
|
2023-01-12 01:04:47 +00:00
|
|
|
|
prevent_cycle_run=search_queue_scheduler.action.is_standard_backlog_in_progress)
|
|
|
|
|
|
|
|
|
|
last_proper_search = datetime.datetime.fromtimestamp(properFinder.get_last_proper_search())
|
|
|
|
|
time_diff = datetime.timedelta(days=1) - (datetime.datetime.now() - last_proper_search)
|
|
|
|
|
if time_diff < datetime.timedelta(seconds=0):
|
|
|
|
|
properdelay = 20
|
|
|
|
|
else:
|
|
|
|
|
properdelay = helpers.try_int((time_diff.total_seconds() / 60) + 5, 20)
|
|
|
|
|
|
2023-03-16 04:19:03 +00:00
|
|
|
|
search_propers_scheduler = scheduler.Scheduler(
|
|
|
|
|
search_propers.ProperSearcher(),
|
2023-02-13 21:00:11 +00:00
|
|
|
|
cycle_time=datetime.timedelta(days=1),
|
2023-01-12 01:04:47 +00:00
|
|
|
|
run_delay=datetime.timedelta(minutes=init_search_delay or properdelay),
|
2023-03-16 04:19:03 +00:00
|
|
|
|
thread_name='PROPERSSEARCH',
|
2023-01-12 01:04:47 +00:00
|
|
|
|
prevent_cycle_run=search_queue_scheduler.action.is_propersearch_in_progress)
|
|
|
|
|
|
2023-03-16 04:19:03 +00:00
|
|
|
|
search_subtitles_scheduler = scheduler.Scheduler(
|
2023-01-12 01:04:47 +00:00
|
|
|
|
subtitles.SubtitlesFinder(),
|
2023-02-13 21:00:11 +00:00
|
|
|
|
cycle_time=datetime.timedelta(hours=SUBTITLES_FINDER_INTERVAL),
|
2023-03-16 04:19:03 +00:00
|
|
|
|
thread_name='SUBTITLESEARCH',
|
2023-01-12 01:04:47 +00:00
|
|
|
|
silent=not USE_SUBTITLES)
|
|
|
|
|
|
2023-03-16 04:19:03 +00:00
|
|
|
|
# /
|
|
|
|
|
# others
|
2023-01-12 01:04:47 +00:00
|
|
|
|
emby_watched_state_scheduler = scheduler.Scheduler(
|
|
|
|
|
EmbyWatchedStateUpdater(),
|
2023-02-13 21:00:11 +00:00
|
|
|
|
cycle_time=datetime.timedelta(minutes=EMBY_WATCHEDSTATE_INTERVAL),
|
2023-01-12 01:04:47 +00:00
|
|
|
|
run_delay=datetime.timedelta(minutes=5),
|
2023-02-13 21:00:11 +00:00
|
|
|
|
thread_name='EMBYWATCHEDSTATE')
|
2023-01-12 01:04:47 +00:00
|
|
|
|
|
|
|
|
|
plex_watched_state_scheduler = scheduler.Scheduler(
|
|
|
|
|
PlexWatchedStateUpdater(),
|
2023-02-13 21:00:11 +00:00
|
|
|
|
cycle_time=datetime.timedelta(minutes=PLEX_WATCHEDSTATE_INTERVAL),
|
2023-01-12 01:04:47 +00:00
|
|
|
|
run_delay=datetime.timedelta(minutes=5),
|
2023-02-13 21:00:11 +00:00
|
|
|
|
thread_name='PLEXWATCHEDSTATE')
|
2023-01-12 01:04:47 +00:00
|
|
|
|
|
2023-03-16 04:19:03 +00:00
|
|
|
|
process_media_scheduler = scheduler.Scheduler(
|
|
|
|
|
auto_media_process.MediaProcess(),
|
|
|
|
|
cycle_time=datetime.timedelta(minutes=MEDIAPROCESS_INTERVAL),
|
|
|
|
|
thread_name='PROCESSMEDIA',
|
|
|
|
|
silent=not PROCESS_AUTOMATICALLY)
|
|
|
|
|
|
|
|
|
|
background_mapping_task = threading.Thread(name='MAPPINGUPDATES', target=indexermapper.load_mapped_ids,
|
|
|
|
|
kwargs={'load_all': True})
|
|
|
|
|
|
Fix py2 deprecation cleanups added exclusively by TvdbV4 code.
Refactor `timestamp_near` to `SGDatetime.timestamp_near`
---
Simplify enforce_type + clean_data to clean_str.
Change simplified all but one enforce_type use case.
---
Add tvdb, trakt slug tvinfo search test cases
Change direct tvdb slug search support via new api endpoint
Fix origin_countries in tvdb_api_v4.
---
Add new TV_Maze id to show obj ids in tvdb_api_v4.
Fix a bug parsing social ids for tvshows in tvdb_api_v4.
Change add language support to search API and tvdb_api_v4.
Change add `updated_at` to artwork on tvdb_api_v4.
Change add `finale` type to episodes.
Change add method `get_top_rated` to tvdb_api_v4.
optional params...
- year=... argument to get only top rated of given year, if not it's all time
Change returns result for shows until same day last year.
Add youtube, reddit, fansite, tiktok, linkedin, wikidata to tv.py
Add tiktok to indexer_config.
Add fansite to tvdb_api_v4.
Aadd fansite to TVInfoSocialIDs.
Add source type parsing and add linkein to tvdb_api_v4.
Add linkedin.
Add tiktok parser to tvdb_api_v4.
Change v4 to TVInfoIDs, TVInfoSocialIDs.
Change add new id data.
Add contentrating.
Change fill in new fields to get_person results.
----
Change implement discover endpoint in tvdb_api_v4.
Change filter '0000' year for firstaired field in tvdb_api_v4.
Change use the default_season_type from api for website fallback.
Change remove unneeded _auth_time.
Add backup fetch for episode data.
Change add multiple space remove to clean_data.
Change move _get_tvdb_id to central function.
Change fix minor warnings, code tidy + DRY.
Change remove the show-edit option `Use DVD titles and numbers` until ready with multi TVInfo source.
Add try_date and use to attempt conversion of unspecified date format types birthdate, deathdate, aired.
Change tweaks, remove one warn, order imports.
Change tidy up of other warnings, mismatched types, typos, a strange arg issue with deepcopy, and PEP8.
Bug fix, bad key in get_item for TVInfoSocialIDs.
Fix ambiguities of `show` used in sg versus external uses.
Fix add data sanitisation of image field.
Change make set_episode code more readable.
Change fix final two warnings in api v4.
Fix an API can return falsy as firstaired which crashes adding a show via load_from_tv_info() (The Andrew Marr Show@tvdbv4).
Add cast, crew type mappings
Only take Main Actors, Hosts, Interviewers, Presenters
Change increase viewagble history menu items from 13 to 15.
2021-09-05 19:10:58 +00:00
|
|
|
|
MEMCACHE['history_tab_limit'] = 15
|
2023-01-12 01:04:47 +00:00
|
|
|
|
MEMCACHE['history_tab'] = History.menu_tab(MEMCACHE['history_tab_limit'])
|
|
|
|
|
|
|
|
|
|
try:
|
2023-10-31 16:05:51 +00:00
|
|
|
|
with scandir(os.path.join(PROG_DIR, 'gui', GUI_NAME, 'images', 'flags')) as s_d:
|
|
|
|
|
for f in s_d:
|
|
|
|
|
if f.is_file():
|
|
|
|
|
MEMCACHE_FLAG_IMAGES[os.path.splitext(f.name)[0].lower()] = True
|
2023-01-12 01:04:47 +00:00
|
|
|
|
except (BaseException, Exception):
|
|
|
|
|
pass
|
|
|
|
|
|
2024-06-28 01:57:31 +00:00
|
|
|
|
config_events = ConfigEvents(_save_config)
|
|
|
|
|
config_events.start()
|
|
|
|
|
|
2023-01-12 01:04:47 +00:00
|
|
|
|
__INITIALIZED__ = True
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def enabled_schedulers(is_init=False):
|
|
|
|
|
# ([], [trakt_checker_scheduler])[USE_TRAKT] + \
|
|
|
|
|
return ([], [events])[is_init] \
|
2023-03-16 04:19:03 +00:00
|
|
|
|
+ ([], [update_software_scheduler, update_packages_scheduler,
|
|
|
|
|
update_show_scheduler, update_release_mappings_scheduler,
|
|
|
|
|
search_recent_scheduler, search_backlog_scheduler,
|
|
|
|
|
search_propers_scheduler, search_subtitles_scheduler,
|
|
|
|
|
show_queue_scheduler, search_queue_scheduler,
|
|
|
|
|
people_queue_scheduler, watched_state_queue_scheduler,
|
|
|
|
|
emby_watched_state_scheduler, plex_watched_state_scheduler,
|
|
|
|
|
process_media_scheduler
|
|
|
|
|
]
|
2023-01-12 01:04:47 +00:00
|
|
|
|
)[not MEMCACHE.get('update_restart')] \
|
|
|
|
|
+ ([events], [])[is_init]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def start():
|
|
|
|
|
global started
|
|
|
|
|
|
|
|
|
|
with INIT_LOCK:
|
|
|
|
|
if __INITIALIZED__:
|
|
|
|
|
# Load all Indexer mappings in background
|
|
|
|
|
indexermapper.defunct_indexer = [
|
|
|
|
|
i for i in TVInfoAPI().all_sources if TVInfoAPI(i).config.get('defunct')]
|
|
|
|
|
indexermapper.indexer_list = [i for i in TVInfoAPI().all_sources if TVInfoAPI(i).config.get('show_url')
|
|
|
|
|
and True is not TVInfoAPI(i).config.get('people_only')]
|
|
|
|
|
background_mapping_task.start()
|
|
|
|
|
|
2023-02-13 21:00:11 +00:00
|
|
|
|
for p in providers.sorted_sources():
|
2023-01-12 01:04:47 +00:00
|
|
|
|
if p.is_active() and getattr(p, 'ping_iv', None):
|
|
|
|
|
# noinspection PyProtectedMember
|
|
|
|
|
provider_ping_thread_pool[p.get_id()] = threading.Thread(
|
|
|
|
|
name='PING-PROVIDER %s' % p.name, target=p._ping)
|
|
|
|
|
provider_ping_thread_pool[p.get_id()].start()
|
|
|
|
|
|
|
|
|
|
for thread in enabled_schedulers(is_init=True): # type: threading.Thread
|
|
|
|
|
thread.start()
|
|
|
|
|
|
|
|
|
|
started = True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def restart(soft=True, update_pkg=None):
|
|
|
|
|
|
|
|
|
|
if not soft:
|
|
|
|
|
if update_pkg:
|
|
|
|
|
MY_ARGS.append('--update-pkg')
|
|
|
|
|
|
2023-03-08 13:44:20 +00:00
|
|
|
|
logger.log('Trigger event restart')
|
2023-01-12 01:04:47 +00:00
|
|
|
|
events.put(events.SystemEvent.RESTART)
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
halt()
|
|
|
|
|
save_all()
|
2023-03-08 13:44:20 +00:00
|
|
|
|
logger.log('Re-initializing all data')
|
2023-01-12 01:04:47 +00:00
|
|
|
|
initialize()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def sig_handler(signum=None, _=None):
|
|
|
|
|
is_ctrlbreak = 'win32' == sys.platform and signal.SIGBREAK == signum
|
2023-03-08 13:44:20 +00:00
|
|
|
|
msg = 'Signal "%s" found' % (signal.SIGINT == signum and 'CTRL-C' or is_ctrlbreak and 'CTRL+BREAK' or
|
|
|
|
|
signal.SIGTERM == signum and 'Termination' or signum)
|
2023-01-12 01:04:47 +00:00
|
|
|
|
if None is signum or signum in (signal.SIGINT, signal.SIGTERM) or is_ctrlbreak:
|
|
|
|
|
logger.log('%s, saving and exiting...' % msg)
|
|
|
|
|
events.put(events.SystemEvent.SHUTDOWN)
|
|
|
|
|
else:
|
|
|
|
|
logger.log('%s, not exiting' % msg)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def halt():
|
2024-06-28 01:57:31 +00:00
|
|
|
|
global __INITIALIZED__, started, config_events
|
2023-01-12 01:04:47 +00:00
|
|
|
|
|
2023-03-05 22:52:09 +00:00
|
|
|
|
logger.debug('Check INIT_LOCK on halt')
|
2023-01-12 01:04:47 +00:00
|
|
|
|
with INIT_LOCK:
|
|
|
|
|
|
2023-03-05 22:52:09 +00:00
|
|
|
|
logger.debug(f'Check __INITIALIZED__ on halt: {__INITIALIZED__}')
|
2023-01-12 01:04:47 +00:00
|
|
|
|
if __INITIALIZED__:
|
|
|
|
|
|
|
|
|
|
logger.log('Exiting threads')
|
|
|
|
|
|
2024-06-28 01:57:31 +00:00
|
|
|
|
try:
|
|
|
|
|
config_events.stopit()
|
|
|
|
|
except (BaseException, Exception):
|
|
|
|
|
pass
|
|
|
|
|
|
2023-01-12 01:04:47 +00:00
|
|
|
|
for p in provider_ping_thread_pool:
|
|
|
|
|
provider_ping_thread_pool[p].stop = True
|
|
|
|
|
|
|
|
|
|
for p in provider_ping_thread_pool:
|
|
|
|
|
try:
|
|
|
|
|
provider_ping_thread_pool[p].join(10)
|
|
|
|
|
logger.log('Thread %s has exit' % provider_ping_thread_pool[p].name)
|
|
|
|
|
except RuntimeError:
|
|
|
|
|
logger.log('Fail, thread %s did not exit' % provider_ping_thread_pool[p].name)
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
if ADBA_CONNECTION:
|
|
|
|
|
try:
|
|
|
|
|
ADBA_CONNECTION.logout()
|
|
|
|
|
except AniDBError:
|
|
|
|
|
pass
|
|
|
|
|
try:
|
|
|
|
|
ADBA_CONNECTION.join(10)
|
|
|
|
|
logger.log('Thread %s has exit' % ADBA_CONNECTION.name)
|
|
|
|
|
except (BaseException, Exception):
|
|
|
|
|
logger.log('Fail, thread %s did not exit' % ADBA_CONNECTION.name)
|
|
|
|
|
|
|
|
|
|
for thread in enabled_schedulers(): # type: scheduler.Scheduler
|
|
|
|
|
try:
|
|
|
|
|
thread.stopit()
|
|
|
|
|
if getattr(thread, 'action', None) and getattr(thread.action, 'save_queue', None):
|
|
|
|
|
try:
|
|
|
|
|
thread.action.save_queue()
|
|
|
|
|
except (BaseException, Exception):
|
|
|
|
|
pass
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.log('Thread %s stop failed with: %s' % (thread.name, e))
|
|
|
|
|
|
|
|
|
|
for thread in enabled_schedulers(): # type: threading.Thread
|
|
|
|
|
try:
|
|
|
|
|
thread.join(10)
|
|
|
|
|
logger.log('Thread %s has exit' % thread.name)
|
|
|
|
|
except RuntimeError:
|
|
|
|
|
# this just means it's the current thread, can be ignored
|
|
|
|
|
logger.log('Thread %s is exiting' % thread.name)
|
|
|
|
|
except (BaseException, Exception) as e:
|
|
|
|
|
logger.log('Thread %s exception %s' % (thread.name, e))
|
|
|
|
|
|
2024-06-28 01:57:31 +00:00
|
|
|
|
try:
|
|
|
|
|
config_events.join(10)
|
|
|
|
|
except RuntimeError:
|
|
|
|
|
pass
|
|
|
|
|
|
2023-01-12 01:04:47 +00:00
|
|
|
|
__INITIALIZED__ = False
|
|
|
|
|
started = False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def save_all():
|
|
|
|
|
if not MEMCACHE.get('update_restart'):
|
|
|
|
|
global showList
|
|
|
|
|
|
|
|
|
|
# write all shows
|
2023-03-08 13:44:20 +00:00
|
|
|
|
logger.log('Saving all shows to the database')
|
2023-01-12 01:04:47 +00:00
|
|
|
|
for show_obj in showList: # type: tv.TVShow
|
|
|
|
|
show_obj.save_to_db()
|
|
|
|
|
|
|
|
|
|
# save config
|
2023-03-08 13:44:20 +00:00
|
|
|
|
logger.log('Saving config file to disk')
|
2024-06-28 01:57:31 +00:00
|
|
|
|
_save_config(force=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def save_config(force=False):
|
|
|
|
|
# type: (bool) -> None
|
|
|
|
|
"""
|
|
|
|
|
add queue request for saving the config.ini
|
|
|
|
|
|
|
|
|
|
:param force: force save config even if unchanged
|
|
|
|
|
"""
|
2024-08-12 20:33:28 +00:00
|
|
|
|
global config_events, CONFIG_LOADED
|
|
|
|
|
if not CONFIG_LOADED:
|
|
|
|
|
return
|
2024-08-12 16:25:11 +00:00
|
|
|
|
|
|
|
|
|
# use queue if it's available, otherwise, call save_config directly
|
|
|
|
|
hasattr(config_events, 'put') and config_events.put(force) or _save_config(force)
|
2023-01-12 01:04:47 +00:00
|
|
|
|
|
|
|
|
|
|
2024-06-28 01:57:31 +00:00
|
|
|
|
def _save_config(force=False, **kwargs):
|
|
|
|
|
# type: (bool, ...) -> None
|
2024-08-12 20:33:28 +00:00
|
|
|
|
global CONFIG_OLD, CONFIG_LOADED
|
|
|
|
|
if not CONFIG_LOADED:
|
|
|
|
|
return
|
|
|
|
|
|
2023-01-12 01:04:47 +00:00
|
|
|
|
new_config = ConfigObj()
|
|
|
|
|
new_config.filename = CONFIG_FILE
|
|
|
|
|
|
2023-02-13 21:00:11 +00:00
|
|
|
|
# For passwords, you must include the word `password` in the item_name and
|
2023-01-12 01:04:47 +00:00
|
|
|
|
# add `helpers.encrypt(ITEM_NAME, ENCRYPTION_VERSION)` in save_config()
|
2023-02-11 18:02:58 +00:00
|
|
|
|
new_config['General'] = dict()
|
2023-01-12 01:04:47 +00:00
|
|
|
|
s_z = check_setting_int(CFG, 'General', 'stack_size', 0)
|
|
|
|
|
if s_z:
|
|
|
|
|
new_config['General']['stack_size'] = s_z
|
|
|
|
|
new_config['General']['config_version'] = CONFIG_VERSION
|
|
|
|
|
new_config['General']['branch'] = BRANCH
|
|
|
|
|
new_config['General']['git_remote'] = GIT_REMOTE
|
|
|
|
|
new_config['General']['cur_commit_hash'] = CUR_COMMIT_HASH
|
|
|
|
|
new_config['General']['cur_commit_branch'] = CUR_COMMIT_BRANCH
|
|
|
|
|
new_config['General']['encryption_version'] = int(ENCRYPTION_VERSION)
|
|
|
|
|
new_config['General']['log_dir'] = ACTUAL_LOG_DIR if ACTUAL_LOG_DIR else 'Logs'
|
|
|
|
|
new_config['General']['file_logging_preset'] = FILE_LOGGING_PRESET \
|
|
|
|
|
if FILE_LOGGING_PRESET and 'DB' != FILE_LOGGING_PRESET else 'DEBUG'
|
|
|
|
|
new_config['General']['file_logging_db'] = 0
|
|
|
|
|
new_config['General']['socket_timeout'] = SOCKET_TIMEOUT
|
|
|
|
|
new_config['General']['web_host'] = WEB_HOST
|
|
|
|
|
new_config['General']['web_port'] = WEB_PORT
|
|
|
|
|
new_config['General']['web_ipv6'] = int(WEB_IPV6)
|
|
|
|
|
new_config['General']['web_ipv64'] = int(WEB_IPV64)
|
|
|
|
|
new_config['General']['web_log'] = int(WEB_LOG)
|
|
|
|
|
new_config['General']['web_root'] = WEB_ROOT
|
|
|
|
|
new_config['General']['web_username'] = WEB_USERNAME
|
|
|
|
|
new_config['General']['web_password'] = helpers.encrypt(WEB_PASSWORD, ENCRYPTION_VERSION)
|
|
|
|
|
new_config['General']['cpu_preset'] = CPU_PRESET
|
|
|
|
|
new_config['General']['anon_redirect'] = ANON_REDIRECT
|
|
|
|
|
new_config['General']['use_api'] = int(USE_API)
|
|
|
|
|
new_config['General']['api_keys'] = '|||'.join([':::'.join(a) for a in API_KEYS])
|
|
|
|
|
new_config['General']['debug'] = int(DEBUG)
|
|
|
|
|
new_config['General']['enable_https'] = int(ENABLE_HTTPS)
|
|
|
|
|
new_config['General']['https_cert'] = HTTPS_CERT
|
|
|
|
|
new_config['General']['https_key'] = HTTPS_KEY
|
|
|
|
|
new_config['General']['handle_reverse_proxy'] = int(HANDLE_REVERSE_PROXY)
|
|
|
|
|
new_config['General']['send_security_headers'] = int(SEND_SECURITY_HEADERS)
|
|
|
|
|
new_config['General']['allowed_hosts'] = ALLOWED_HOSTS
|
|
|
|
|
new_config['General']['allow_anyip'] = int(ALLOW_ANYIP)
|
|
|
|
|
new_config['General']['use_nzbs'] = int(USE_NZBS)
|
|
|
|
|
new_config['General']['use_torrents'] = int(USE_TORRENTS)
|
|
|
|
|
new_config['General']['nzb_method'] = NZB_METHOD
|
|
|
|
|
new_config['General']['torrent_method'] = TORRENT_METHOD
|
|
|
|
|
new_config['General']['usenet_retention'] = int(USENET_RETENTION)
|
|
|
|
|
new_config['General']['mediaprocess_interval'] = int(MEDIAPROCESS_INTERVAL)
|
|
|
|
|
new_config['General']['recentsearch_interval'] = int(RECENTSEARCH_INTERVAL)
|
|
|
|
|
new_config['General']['backlog_period'] = int(BACKLOG_PERIOD)
|
|
|
|
|
new_config['General']['backlog_limited_period'] = int(BACKLOG_LIMITED_PERIOD)
|
|
|
|
|
new_config['General']['download_propers'] = int(DOWNLOAD_PROPERS)
|
|
|
|
|
new_config['General']['propers_webdl_onegrp'] = int(PROPERS_WEBDL_ONEGRP)
|
|
|
|
|
new_config['General']['allow_high_priority'] = int(ALLOW_HIGH_PRIORITY)
|
|
|
|
|
new_config['General']['recentsearch_startup'] = int(RECENTSEARCH_STARTUP)
|
|
|
|
|
new_config['General']['backlog_nofull'] = int(BACKLOG_NOFULL)
|
|
|
|
|
new_config['General']['skip_removed_files'] = int(SKIP_REMOVED_FILES)
|
|
|
|
|
new_config['General']['results_sortby'] = str(RESULTS_SORTBY)
|
|
|
|
|
new_config['General']['indexer_default'] = int(TVINFO_DEFAULT)
|
|
|
|
|
new_config['General']['indexer_timeout'] = int(TVINFO_TIMEOUT)
|
|
|
|
|
new_config['General']['quality_default'] = int(QUALITY_DEFAULT)
|
|
|
|
|
new_config['General']['wanted_begin_default'] = int(WANTED_BEGIN_DEFAULT)
|
|
|
|
|
new_config['General']['wanted_latest_default'] = int(WANTED_LATEST_DEFAULT)
|
|
|
|
|
new_config['General']['pause default'] = int(PAUSE_DEFAULT)
|
|
|
|
|
new_config['General']['status_default'] = int(STATUS_DEFAULT)
|
|
|
|
|
new_config['General']['scene_default'] = int(SCENE_DEFAULT)
|
|
|
|
|
new_config['General']['flatten_folders_default'] = int(FLATTEN_FOLDERS_DEFAULT)
|
|
|
|
|
new_config['General']['anime_default'] = int(ANIME_DEFAULT)
|
|
|
|
|
new_config['General']['provider_order'] = ' '.join(PROVIDER_ORDER)
|
2023-02-11 18:02:58 +00:00
|
|
|
|
new_config['General']['provider_homes'] = '%s' % dict([(pid, v) for pid, v in list(PROVIDER_HOMES.items())
|
|
|
|
|
if pid in [
|
2023-02-13 21:00:11 +00:00
|
|
|
|
p.get_id() for p in [x for x in providers.sorted_sources() if GenericProvider.TORRENT == x.providerType]]])
|
2023-01-12 01:04:47 +00:00
|
|
|
|
new_config['General']['update_notify'] = int(UPDATE_NOTIFY)
|
|
|
|
|
new_config['General']['update_auto'] = int(UPDATE_AUTO)
|
|
|
|
|
new_config['General']['update_interval'] = int(UPDATE_INTERVAL)
|
|
|
|
|
new_config['General']['notify_on_update'] = int(NOTIFY_ON_UPDATE)
|
|
|
|
|
new_config['General']['update_packages_notify'] = int(UPDATE_PACKAGES_NOTIFY)
|
|
|
|
|
new_config['General']['update_packages_auto'] = int(UPDATE_PACKAGES_AUTO)
|
|
|
|
|
new_config['General']['update_packages_menu'] = int(UPDATE_PACKAGES_MENU)
|
|
|
|
|
new_config['General']['update_packages_interval'] = int(UPDATE_PACKAGES_INTERVAL)
|
|
|
|
|
new_config['General']['naming_strip_year'] = int(NAMING_STRIP_YEAR)
|
|
|
|
|
new_config['General']['naming_pattern'] = NAMING_PATTERN
|
|
|
|
|
new_config['General']['naming_custom_abd'] = int(NAMING_CUSTOM_ABD)
|
|
|
|
|
new_config['General']['naming_abd_pattern'] = NAMING_ABD_PATTERN
|
|
|
|
|
new_config['General']['naming_custom_sports'] = int(NAMING_CUSTOM_SPORTS)
|
|
|
|
|
new_config['General']['naming_sports_pattern'] = NAMING_SPORTS_PATTERN
|
|
|
|
|
new_config['General']['naming_custom_anime'] = int(NAMING_CUSTOM_ANIME)
|
|
|
|
|
new_config['General']['naming_anime_pattern'] = NAMING_ANIME_PATTERN
|
|
|
|
|
new_config['General']['naming_multi_ep'] = int(NAMING_MULTI_EP)
|
|
|
|
|
new_config['General']['naming_anime_multi_ep'] = int(NAMING_ANIME_MULTI_EP)
|
|
|
|
|
new_config['General']['naming_anime'] = int(NAMING_ANIME)
|
|
|
|
|
new_config['General']['launch_browser'] = int(LAUNCH_BROWSER)
|
|
|
|
|
new_config['General']['update_shows_on_start'] = int(UPDATE_SHOWS_ON_START)
|
|
|
|
|
new_config['General']['show_update_hour'] = int(SHOW_UPDATE_HOUR)
|
|
|
|
|
new_config['General']['trash_remove_show'] = int(TRASH_REMOVE_SHOW)
|
|
|
|
|
new_config['General']['trash_rotate_logs'] = int(TRASH_ROTATE_LOGS)
|
|
|
|
|
new_config['General']['home_search_focus'] = int(HOME_SEARCH_FOCUS)
|
|
|
|
|
new_config['General']['display_freespace'] = int(DISPLAY_FREESPACE)
|
|
|
|
|
new_config['General']['sort_article'] = int(SORT_ARTICLE)
|
|
|
|
|
new_config['General']['proxy_setting'] = PROXY_SETTING
|
|
|
|
|
sg_helpers.PROXY_SETTING = PROXY_SETTING
|
|
|
|
|
new_config['General']['proxy_indexers'] = int(PROXY_INDEXERS)
|
|
|
|
|
|
|
|
|
|
new_config['General']['metadata_xbmc'] = METADATA_XBMC
|
|
|
|
|
new_config['General']['metadata_xbmc_12plus'] = METADATA_XBMC_12PLUS
|
|
|
|
|
new_config['General']['metadata_mediabrowser'] = METADATA_MEDIABROWSER
|
|
|
|
|
new_config['General']['metadata_ps3'] = METADATA_PS3
|
|
|
|
|
new_config['General']['metadata_wdtv'] = METADATA_WDTV
|
|
|
|
|
new_config['General']['metadata_tivo'] = METADATA_TIVO
|
|
|
|
|
new_config['General']['metadata_mede8er'] = METADATA_MEDE8ER
|
|
|
|
|
new_config['General']['metadata_kodi'] = METADATA_KODI
|
|
|
|
|
|
|
|
|
|
new_config['General']['search_unaired'] = int(SEARCH_UNAIRED)
|
|
|
|
|
new_config['General']['unaired_recent_search_only'] = int(UNAIRED_RECENT_SEARCH_ONLY)
|
|
|
|
|
new_config['General']['flaresolverr_host'] = FLARESOLVERR_HOST
|
|
|
|
|
|
|
|
|
|
new_config['General']['cache_dir'] = ACTUAL_CACHE_DIR if ACTUAL_CACHE_DIR else 'cache'
|
|
|
|
|
sg_helpers.CACHE_DIR = CACHE_DIR
|
|
|
|
|
sg_helpers.DATA_DIR = DATA_DIR
|
|
|
|
|
new_config['General']['root_dirs'] = ROOT_DIRS if ROOT_DIRS else ''
|
|
|
|
|
new_config['General']['tv_download_dir'] = TV_DOWNLOAD_DIR
|
|
|
|
|
new_config['General']['keep_processed_dir'] = int(KEEP_PROCESSED_DIR)
|
|
|
|
|
new_config['General']['process_method'] = PROCESS_METHOD
|
|
|
|
|
new_config['General']['process_last_dir'] = PROCESS_LAST_DIR
|
|
|
|
|
new_config['General']['process_last_method'] = PROCESS_LAST_METHOD
|
|
|
|
|
new_config['General']['process_last_cleanup'] = int(PROCESS_LAST_CLEANUP)
|
|
|
|
|
new_config['General']['move_associated_files'] = int(MOVE_ASSOCIATED_FILES)
|
|
|
|
|
new_config['General']['postpone_if_sync_files'] = int(POSTPONE_IF_SYNC_FILES)
|
2023-04-16 00:31:51 +00:00
|
|
|
|
new_config['General']['process_positive_log'] = int(PROCESS_POSITIVE_LOG)
|
2023-01-12 01:04:47 +00:00
|
|
|
|
new_config['General']['nfo_rename'] = int(NFO_RENAME)
|
|
|
|
|
new_config['General']['process_automatically'] = int(PROCESS_AUTOMATICALLY)
|
|
|
|
|
new_config['General']['unpack'] = int(UNPACK)
|
|
|
|
|
new_config['General']['rename_episodes'] = int(RENAME_EPISODES)
|
2023-04-29 18:18:00 +00:00
|
|
|
|
new_config['General']['rename_tba_episodes'] = int(RENAME_TBA_EPISODES)
|
|
|
|
|
new_config['General']['rename_name_changed_episodes'] = int(RENAME_NAME_CHANGED_EPISODES)
|
2023-01-12 01:04:47 +00:00
|
|
|
|
new_config['General']['airdate_episodes'] = int(AIRDATE_EPISODES)
|
|
|
|
|
new_config['General']['create_missing_show_dirs'] = int(CREATE_MISSING_SHOW_DIRS)
|
|
|
|
|
new_config['General']['show_dirs_with_dots'] = int(SHOW_DIRS_WITH_DOTS)
|
|
|
|
|
new_config['General']['add_shows_wo_dir'] = int(ADD_SHOWS_WO_DIR)
|
|
|
|
|
new_config['General']['add_shows_metalang'] = ADD_SHOWS_METALANG
|
|
|
|
|
new_config['General']['remove_filename_chars'] = REMOVE_FILENAME_CHARS
|
|
|
|
|
new_config['General']['import_default_checked_shows'] = int(IMPORT_DEFAULT_CHECKED_SHOWS)
|
|
|
|
|
|
|
|
|
|
new_config['General']['extra_scripts'] = '|'.join(EXTRA_SCRIPTS)
|
|
|
|
|
new_config['General']['sg_extra_scripts'] = '|'.join(SG_EXTRA_SCRIPTS)
|
|
|
|
|
new_config['General']['git_path'] = GIT_PATH
|
|
|
|
|
new_config['General']['ignore_words'] = helpers.generate_word_str(IGNORE_WORDS, IGNORE_WORDS_REGEX)
|
|
|
|
|
new_config['General']['require_words'] = helpers.generate_word_str(REQUIRE_WORDS, REQUIRE_WORDS_REGEX)
|
|
|
|
|
new_config['General']['calendar_unprotected'] = int(CALENDAR_UNPROTECTED)
|
|
|
|
|
|
|
|
|
|
new_config['Updates'] = {}
|
|
|
|
|
new_config['Updates']['updates_todo'] = '%s' % (UPDATES_TODO or {})
|
|
|
|
|
|
|
|
|
|
new_config['Backup'] = {}
|
|
|
|
|
if BACKUP_DB_PATH:
|
|
|
|
|
new_config['Backup']['backup_db_path'] = BACKUP_DB_PATH
|
|
|
|
|
new_config['Backup']['backup_db_oneday'] = int(BACKUP_DB_ONEDAY)
|
|
|
|
|
new_config['Backup']['backup_db_max_count'] = BACKUP_DB_MAX_COUNT
|
|
|
|
|
|
|
|
|
|
default_not_zero = ('enable_recentsearch', 'enable_backlog', 'enable_scheduled_backlog', 'use_after_get_data')
|
2023-02-13 21:00:11 +00:00
|
|
|
|
for src in filter(lambda px: GenericProvider.TORRENT == px.providerType, providers.sorted_sources()):
|
2023-01-12 01:04:47 +00:00
|
|
|
|
src_id = src.get_id()
|
|
|
|
|
src_id_uc = src_id.upper()
|
|
|
|
|
new_config[src_id_uc] = {}
|
|
|
|
|
if int(src.enabled):
|
|
|
|
|
new_config[src_id_uc][src_id] = int(src.enabled)
|
|
|
|
|
if getattr(src, 'url_edit', None):
|
|
|
|
|
new_config[src_id_uc][src_id + '_url_home'] = src.url_home
|
|
|
|
|
|
|
|
|
|
if getattr(src, 'password', None):
|
|
|
|
|
new_config[src_id_uc][src_id + '_password'] = helpers.encrypt(src.password, ENCRYPTION_VERSION)
|
|
|
|
|
|
|
|
|
|
for (attr, value) in [
|
|
|
|
|
(k, getattr(src, k, v) if not v else helpers.try_int(getattr(src, k, None)))
|
|
|
|
|
for (k, v) in [
|
|
|
|
|
('enable_recentsearch', 1), ('enable_backlog', 1), ('enable_scheduled_backlog', 1),
|
|
|
|
|
('api_key', None), ('passkey', None), ('digest', None), ('hash', None), ('username', ''), ('uid', ''),
|
|
|
|
|
('minseed', 1), ('minleech', 1), ('seed_time', None),
|
|
|
|
|
('confirmed', 1), ('freeleech', 1), ('reject_m2ts', 1), ('use_after_get_data', 1),
|
|
|
|
|
('scene_only', None), ('scene_or_contain', ''), ('scene_loose', None), ('scene_loose_active', None),
|
|
|
|
|
('scene_rej_nuked', None), ('scene_nuked_active', None),
|
|
|
|
|
('search_mode', None), ('search_fallback', 1)
|
|
|
|
|
]
|
|
|
|
|
if hasattr(src, k)]:
|
|
|
|
|
if (value and not ('search_mode' == attr and 'eponly' == value)
|
|
|
|
|
# must allow the following to save '0' not '1' because default is enable (1) instead of disable (0)
|
|
|
|
|
and (attr not in default_not_zero) or not value and (attr in default_not_zero)):
|
|
|
|
|
new_config[src_id_uc]['%s_%s' % (src_id, attr)] = value
|
|
|
|
|
|
|
|
|
|
if getattr(src, '_seed_ratio', None):
|
|
|
|
|
new_config[src_id_uc][src_id + '_seed_ratio'] = src.seed_ratio()
|
|
|
|
|
if getattr(src, 'filter', None):
|
|
|
|
|
new_config[src_id_uc][src_id + '_filter'] = src.filter
|
|
|
|
|
|
|
|
|
|
if not new_config[src_id_uc]:
|
|
|
|
|
del new_config[src_id_uc]
|
|
|
|
|
|
|
|
|
|
default_not_zero = ('enable_recentsearch', 'enable_backlog', 'enable_scheduled_backlog')
|
2023-02-13 21:00:11 +00:00
|
|
|
|
for src in filter(lambda px: GenericProvider.NZB == px.providerType, providers.sorted_sources()):
|
2023-01-12 01:04:47 +00:00
|
|
|
|
src_id = src.get_id()
|
|
|
|
|
src_id_uc = src.get_id().upper()
|
|
|
|
|
new_config[src_id_uc] = {}
|
|
|
|
|
if int(src.enabled):
|
|
|
|
|
new_config[src_id_uc][src_id] = int(src.enabled)
|
|
|
|
|
|
2023-02-11 18:02:58 +00:00
|
|
|
|
for attr in filter(lambda _a: None is not getattr(src, _a, None),
|
2023-02-13 21:00:11 +00:00
|
|
|
|
('api_key', 'digest', 'username', 'search_mode')):
|
2023-01-12 01:04:47 +00:00
|
|
|
|
if 'search_mode' != attr or 'eponly' != getattr(src, attr):
|
|
|
|
|
new_config[src_id_uc]['%s_%s' % (src_id, attr)] = getattr(src, attr)
|
|
|
|
|
|
2023-02-11 18:02:58 +00:00
|
|
|
|
for attr in filter(lambda _a: None is not getattr(src, _a, None), (
|
2023-01-12 01:04:47 +00:00
|
|
|
|
'enable_recentsearch', 'enable_backlog', 'enable_scheduled_backlog',
|
|
|
|
|
'scene_only', 'scene_loose', 'scene_loose_active',
|
|
|
|
|
'scene_rej_nuked', 'scene_nuked_active',
|
|
|
|
|
'search_fallback', 'server_type')):
|
|
|
|
|
value = helpers.try_int(getattr(src, attr, None))
|
|
|
|
|
# must allow the following to save '0' not '1' because default is enable (1) instead of disable (0)
|
|
|
|
|
if (value and (attr not in default_not_zero)) or (not value and (attr in default_not_zero)):
|
|
|
|
|
new_config[src_id_uc]['%s_%s' % (src_id, attr)] = value
|
|
|
|
|
|
|
|
|
|
attr = 'scene_or_contain'
|
|
|
|
|
if getattr(src, attr, None):
|
|
|
|
|
new_config[src_id_uc]['%s_%s' % (src_id, attr)] = getattr(src, attr, '')
|
|
|
|
|
|
|
|
|
|
if not new_config[src_id_uc]:
|
|
|
|
|
del new_config[src_id_uc]
|
|
|
|
|
|
|
|
|
|
cfg_keys = []
|
|
|
|
|
for (cfg, items) in iteritems(OrderedDict([
|
|
|
|
|
# -----------------------------------
|
|
|
|
|
# Config/Search
|
|
|
|
|
# -----------------------------------
|
|
|
|
|
('Blackhole', [
|
|
|
|
|
('nzb_dir', NZB_DIR), ('torrent_dir', TORRENT_DIR)]),
|
|
|
|
|
('NZBGet', [
|
|
|
|
|
('username', NZBGET_USERNAME), ('password', helpers.encrypt(NZBGET_PASSWORD, ENCRYPTION_VERSION)),
|
|
|
|
|
('host', NZBGET_HOST),
|
|
|
|
|
('category', NZBGET_CATEGORY),
|
|
|
|
|
('use_https', int(NZBGET_USE_HTTPS)),
|
|
|
|
|
('priority', NZBGET_PRIORITY),
|
|
|
|
|
('map', NZBGET_MAP),
|
|
|
|
|
('skip_process_media', int(NZBGET_SKIP_PM)),
|
|
|
|
|
]),
|
|
|
|
|
('SABnzbd', [
|
|
|
|
|
('username', SAB_USERNAME), ('password', helpers.encrypt(SAB_PASSWORD, ENCRYPTION_VERSION)),
|
|
|
|
|
('apikey', SAB_APIKEY),
|
|
|
|
|
('host', SAB_HOST),
|
|
|
|
|
('category', SAB_CATEGORY),
|
|
|
|
|
]),
|
|
|
|
|
('TORRENT', [
|
|
|
|
|
('username', TORRENT_USERNAME), ('password', helpers.encrypt(TORRENT_PASSWORD, ENCRYPTION_VERSION)),
|
|
|
|
|
('host', TORRENT_HOST),
|
|
|
|
|
('path', TORRENT_PATH),
|
|
|
|
|
('seed_time', int(TORRENT_SEED_TIME)),
|
|
|
|
|
('paused', int(TORRENT_PAUSED)),
|
|
|
|
|
('high_bandwidth', int(TORRENT_HIGH_BANDWIDTH)),
|
|
|
|
|
('label', TORRENT_LABEL),
|
|
|
|
|
('label_var', int(TORRENT_LABEL_VAR)),
|
|
|
|
|
('verify_cert', int(TORRENT_VERIFY_CERT)),
|
|
|
|
|
]),
|
|
|
|
|
# -----------------------------------
|
|
|
|
|
# Config/Notifications
|
|
|
|
|
# -----------------------------------
|
|
|
|
|
('Emby', [
|
|
|
|
|
('use_%s', int(USE_EMBY)),
|
|
|
|
|
('apikey', EMBY_APIKEY), ('host', EMBY_HOST),
|
|
|
|
|
('update_library', int(EMBY_UPDATE_LIBRARY)),
|
|
|
|
|
('watchedstate_scheduled', int(EMBY_WATCHEDSTATE_SCHEDULED)),
|
|
|
|
|
('watchedstate_interval', int(EMBY_WATCHEDSTATE_INTERVAL)),
|
|
|
|
|
('parent_maps', EMBY_PARENT_MAPS),
|
|
|
|
|
]),
|
|
|
|
|
('Kodi', [
|
|
|
|
|
('use_%s', int(USE_KODI)),
|
|
|
|
|
('username', KODI_USERNAME), ('password', helpers.encrypt(KODI_PASSWORD, ENCRYPTION_VERSION)),
|
|
|
|
|
('host', KODI_HOST),
|
|
|
|
|
('always_on', int(KODI_ALWAYS_ON)), ('update_library', int(KODI_UPDATE_LIBRARY)),
|
|
|
|
|
('update_full', int(KODI_UPDATE_FULL)),
|
|
|
|
|
('update_onlyfirst', int(KODI_UPDATE_ONLYFIRST)),
|
|
|
|
|
('parent_maps', KODI_PARENT_MAPS),
|
|
|
|
|
]),
|
|
|
|
|
('Plex', [
|
|
|
|
|
('use_%s', int(USE_PLEX)),
|
|
|
|
|
('username', PLEX_USERNAME), ('password', helpers.encrypt(PLEX_PASSWORD, ENCRYPTION_VERSION)),
|
|
|
|
|
('host', PLEX_HOST),
|
|
|
|
|
('update_library', int(PLEX_UPDATE_LIBRARY)),
|
|
|
|
|
('watchedstate_scheduled', int(PLEX_WATCHEDSTATE_SCHEDULED)),
|
|
|
|
|
('watchedstate_interval', int(PLEX_WATCHEDSTATE_INTERVAL)),
|
|
|
|
|
('parent_maps', PLEX_PARENT_MAPS),
|
|
|
|
|
('server_host', PLEX_SERVER_HOST),
|
|
|
|
|
]),
|
|
|
|
|
('XBMC', [
|
|
|
|
|
('use_%s', int(USE_XBMC)),
|
|
|
|
|
('username', XBMC_USERNAME), ('password', helpers.encrypt(XBMC_PASSWORD, ENCRYPTION_VERSION)),
|
|
|
|
|
('host', XBMC_HOST),
|
|
|
|
|
('always_on', int(XBMC_ALWAYS_ON)), ('update_library', int(XBMC_UPDATE_LIBRARY)),
|
|
|
|
|
('update_full', int(XBMC_UPDATE_FULL)),
|
|
|
|
|
('update_onlyfirst', int(XBMC_UPDATE_ONLYFIRST)),
|
|
|
|
|
]),
|
|
|
|
|
('NMJ', [
|
|
|
|
|
('use_%s', int(USE_NMJ)),
|
|
|
|
|
('host', NMJ_HOST),
|
|
|
|
|
('database', NMJ_DATABASE),
|
|
|
|
|
('mount', NMJ_MOUNT),
|
|
|
|
|
]),
|
|
|
|
|
('NMJv2', [
|
|
|
|
|
('use_%s', int(USE_NMJv2)),
|
|
|
|
|
('host', NMJv2_HOST),
|
|
|
|
|
('database', NMJv2_DATABASE),
|
|
|
|
|
('dbloc', NMJv2_DBLOC),
|
|
|
|
|
]),
|
|
|
|
|
('Synology', [
|
|
|
|
|
('use_synoindex', int(USE_SYNOINDEX)),
|
|
|
|
|
]),
|
|
|
|
|
('SynologyNotifier', [
|
|
|
|
|
('use_%s', int(USE_SYNOLOGYNOTIFIER)),
|
|
|
|
|
]),
|
|
|
|
|
('pyTivo', [
|
|
|
|
|
('use_%s', int(USE_PYTIVO)),
|
|
|
|
|
('host', PYTIVO_HOST),
|
|
|
|
|
('share_name', PYTIVO_SHARE_NAME),
|
|
|
|
|
('tivo_name', PYTIVO_TIVO_NAME),
|
|
|
|
|
]),
|
|
|
|
|
('Boxcar2', [
|
|
|
|
|
('use_%s', int(USE_BOXCAR2)),
|
|
|
|
|
('accesstoken', BOXCAR2_ACCESSTOKEN),
|
|
|
|
|
('sound', BOXCAR2_SOUND if 'default' != BOXCAR2_SOUND else None),
|
|
|
|
|
]),
|
|
|
|
|
('Pushbullet', [
|
|
|
|
|
('use_%s', int(USE_PUSHBULLET)),
|
|
|
|
|
('access_token', PUSHBULLET_ACCESS_TOKEN),
|
|
|
|
|
('device_iden', PUSHBULLET_DEVICE_IDEN),
|
|
|
|
|
]),
|
|
|
|
|
('Pushover', [
|
|
|
|
|
('use_%s', int(USE_PUSHOVER)),
|
|
|
|
|
('userkey', PUSHOVER_USERKEY),
|
|
|
|
|
('apikey', PUSHOVER_APIKEY),
|
|
|
|
|
('priority', PUSHOVER_PRIORITY if '0' != PUSHOVER_PRIORITY else None),
|
|
|
|
|
('device', PUSHOVER_DEVICE if 'all' != PUSHOVER_DEVICE else None),
|
|
|
|
|
('sound', PUSHOVER_SOUND if 'pushover' != PUSHOVER_SOUND else None),
|
|
|
|
|
]),
|
|
|
|
|
('Growl', [
|
|
|
|
|
('use_%s', int(USE_GROWL)),
|
|
|
|
|
('host', GROWL_HOST),
|
|
|
|
|
# ('password', helpers.encrypt(GROWL_PASSWORD, ENCRYPTION_VERSION)),
|
|
|
|
|
]),
|
|
|
|
|
('Prowl', [
|
|
|
|
|
('use_%s', int(USE_PROWL)),
|
|
|
|
|
('api', PROWL_API),
|
|
|
|
|
('priority', PROWL_PRIORITY if '0' != PROWL_PRIORITY else None),
|
|
|
|
|
]),
|
|
|
|
|
('Libnotify', [
|
|
|
|
|
('use_%s', int(USE_LIBNOTIFY))
|
|
|
|
|
]),
|
|
|
|
|
# deprecated service
|
|
|
|
|
# new_config['Pushalot'] = {}
|
|
|
|
|
# new_config['Pushalot']['use_pushalot'] = int(USE_PUSHALOT)
|
|
|
|
|
# new_config['Pushalot']['pushalot_authorizationtoken'] = PUSHALOT_AUTHORIZATIONTOKEN
|
|
|
|
|
('Trakt', [
|
|
|
|
|
('use_%s', int(USE_TRAKT)),
|
|
|
|
|
('update_collection', TRAKT_UPDATE_COLLECTION
|
|
|
|
|
and trakt_helpers.build_config_string(TRAKT_UPDATE_COLLECTION)),
|
|
|
|
|
('accounts', TraktAPI.build_config_string(TRAKT_ACCOUNTS)),
|
|
|
|
|
('mru', TRAKT_MRU),
|
|
|
|
|
# new_config['Trakt'] = {}
|
|
|
|
|
# new_config['Trakt']['trakt_remove_watchlist'] = int(TRAKT_REMOVE_WATCHLIST)
|
|
|
|
|
# new_config['Trakt']['trakt_remove_serieslist'] = int(TRAKT_REMOVE_SERIESLIST)
|
|
|
|
|
# new_config['Trakt']['trakt_use_watchlist'] = int(TRAKT_USE_WATCHLIST)
|
|
|
|
|
# new_config['Trakt']['trakt_method_add'] = int(TRAKT_METHOD_ADD)
|
|
|
|
|
# new_config['Trakt']['trakt_start_paused'] = int(TRAKT_START_PAUSED)
|
|
|
|
|
# new_config['Trakt']['trakt_sync'] = int(TRAKT_SYNC)
|
|
|
|
|
# new_config['Trakt']['trakt_default_indexer'] = int(TRAKT_DEFAULT_INDEXER)
|
|
|
|
|
]),
|
|
|
|
|
('Metacritic', [
|
|
|
|
|
('mru', MC_MRU)
|
|
|
|
|
]),
|
2023-03-09 02:13:52 +00:00
|
|
|
|
('NextEpisode', [
|
|
|
|
|
('mru', NE_MRU)
|
|
|
|
|
]),
|
|
|
|
|
('TMDB', [
|
|
|
|
|
('mru', TMDB_MRU)
|
|
|
|
|
]),
|
2023-01-12 01:04:47 +00:00
|
|
|
|
('TVCalendar', [
|
|
|
|
|
('mru', TVC_MRU)
|
|
|
|
|
]),
|
Fix py2 deprecation cleanups added exclusively by TvdbV4 code.
Refactor `timestamp_near` to `SGDatetime.timestamp_near`
---
Simplify enforce_type + clean_data to clean_str.
Change simplified all but one enforce_type use case.
---
Add tvdb, trakt slug tvinfo search test cases
Change direct tvdb slug search support via new api endpoint
Fix origin_countries in tvdb_api_v4.
---
Add new TV_Maze id to show obj ids in tvdb_api_v4.
Fix a bug parsing social ids for tvshows in tvdb_api_v4.
Change add language support to search API and tvdb_api_v4.
Change add `updated_at` to artwork on tvdb_api_v4.
Change add `finale` type to episodes.
Change add method `get_top_rated` to tvdb_api_v4.
optional params...
- year=... argument to get only top rated of given year, if not it's all time
Change returns result for shows until same day last year.
Add youtube, reddit, fansite, tiktok, linkedin, wikidata to tv.py
Add tiktok to indexer_config.
Add fansite to tvdb_api_v4.
Aadd fansite to TVInfoSocialIDs.
Add source type parsing and add linkein to tvdb_api_v4.
Add linkedin.
Add tiktok parser to tvdb_api_v4.
Change v4 to TVInfoIDs, TVInfoSocialIDs.
Change add new id data.
Add contentrating.
Change fill in new fields to get_person results.
----
Change implement discover endpoint in tvdb_api_v4.
Change filter '0000' year for firstaired field in tvdb_api_v4.
Change use the default_season_type from api for website fallback.
Change remove unneeded _auth_time.
Add backup fetch for episode data.
Change add multiple space remove to clean_data.
Change move _get_tvdb_id to central function.
Change fix minor warnings, code tidy + DRY.
Change remove the show-edit option `Use DVD titles and numbers` until ready with multi TVInfo source.
Add try_date and use to attempt conversion of unspecified date format types birthdate, deathdate, aired.
Change tweaks, remove one warn, order imports.
Change tidy up of other warnings, mismatched types, typos, a strange arg issue with deepcopy, and PEP8.
Bug fix, bad key in get_item for TVInfoSocialIDs.
Fix ambiguities of `show` used in sg versus external uses.
Fix add data sanitisation of image field.
Change make set_episode code more readable.
Change fix final two warnings in api v4.
Fix an API can return falsy as firstaired which crashes adding a show via load_from_tv_info() (The Andrew Marr Show@tvdbv4).
Add cast, crew type mappings
Only take Main Actors, Hosts, Interviewers, Presenters
Change increase viewagble history menu items from 13 to 15.
2021-09-05 19:10:58 +00:00
|
|
|
|
('TVDb', [
|
|
|
|
|
('mru', TVDB_MRU)
|
|
|
|
|
]),
|
2023-01-12 01:04:47 +00:00
|
|
|
|
('TVmaze', [
|
|
|
|
|
('mru', TVM_MRU)
|
|
|
|
|
]),
|
|
|
|
|
('Slack', [
|
|
|
|
|
('use_%s', int(USE_SLACK)),
|
|
|
|
|
('channel', SLACK_CHANNEL),
|
|
|
|
|
('as_authed', int(SLACK_AS_AUTHED)),
|
|
|
|
|
('bot_name', SLACK_BOT_NAME),
|
|
|
|
|
('icon_url', SLACK_ICON_URL),
|
|
|
|
|
('access_token', SLACK_ACCESS_TOKEN),
|
|
|
|
|
]),
|
|
|
|
|
('Discord', [
|
|
|
|
|
('use_%s', int(USE_DISCORD)),
|
|
|
|
|
('as_authed', int(DISCORD_AS_AUTHED)),
|
|
|
|
|
('username', DISCORD_USERNAME),
|
|
|
|
|
('icon_url', DISCORD_ICON_URL),
|
|
|
|
|
('as_tts', int(DISCORD_AS_TTS)),
|
|
|
|
|
('access_token', DISCORD_ACCESS_TOKEN),
|
|
|
|
|
]),
|
|
|
|
|
('Gitter', [
|
|
|
|
|
('use_%s', int(USE_GITTER)),
|
|
|
|
|
('room', GITTER_ROOM),
|
|
|
|
|
('access_token', GITTER_ACCESS_TOKEN),
|
|
|
|
|
]),
|
|
|
|
|
('Telegram', [
|
|
|
|
|
('use_%s', int(USE_TELEGRAM)),
|
|
|
|
|
('send_image', int(TELEGRAM_SEND_IMAGE)),
|
|
|
|
|
('quiet', int(TELEGRAM_QUIET)),
|
|
|
|
|
('access_token', TELEGRAM_ACCESS_TOKEN),
|
|
|
|
|
('chatid', TELEGRAM_CHATID),
|
|
|
|
|
]),
|
|
|
|
|
('Email', [
|
|
|
|
|
('use_%s', int(USE_EMAIL)),
|
|
|
|
|
('old_subjects', int(EMAIL_OLD_SUBJECTS)),
|
|
|
|
|
('host', EMAIL_HOST), ('port', int(EMAIL_PORT) if 25 != int(EMAIL_PORT) else None),
|
|
|
|
|
('tls', int(EMAIL_TLS)),
|
|
|
|
|
('user', EMAIL_USER), ('password', helpers.encrypt(EMAIL_PASSWORD, ENCRYPTION_VERSION)),
|
|
|
|
|
('from', EMAIL_FROM),
|
|
|
|
|
('list', EMAIL_LIST),
|
|
|
|
|
]),
|
|
|
|
|
# (, [(, )]),
|
|
|
|
|
])):
|
|
|
|
|
cfg_lc = cfg.lower()
|
|
|
|
|
cfg_keys += [cfg]
|
|
|
|
|
new_config[cfg] = {}
|
2023-02-11 18:02:58 +00:00
|
|
|
|
for (k, v) in filter(lambda arg: any([arg[1]]) or (
|
2023-01-12 01:04:47 +00:00
|
|
|
|
# allow saving where item value default is non-zero but 0 is a required setting value
|
|
|
|
|
cfg_lc in ('kodi', 'xbmc', 'synoindex', 'nzbget', 'torrent', 'telegram')
|
|
|
|
|
and arg[0] in ('always_on', 'priority', 'send_image'))
|
|
|
|
|
or ('rtorrent' == new_config['General']['torrent_method'] and 'label_var' == arg[0]), items):
|
|
|
|
|
k = '%s' in k and (k % cfg_lc) or (cfg_lc + '_' + k)
|
|
|
|
|
# correct for cases where keys are named in an inconsistent manner to parent stanza
|
|
|
|
|
k = k.replace('blackhole_', '').replace('sabnzbd_', 'sab_')
|
|
|
|
|
new_config[cfg].update({k: v})
|
|
|
|
|
|
|
|
|
|
for (notifier, onsnatch, ondownload, onsubtitledownload) in [
|
|
|
|
|
('Kodi', KODI_NOTIFY_ONSNATCH, KODI_NOTIFY_ONDOWNLOAD, KODI_NOTIFY_ONSUBTITLEDOWNLOAD),
|
|
|
|
|
('Plex', PLEX_NOTIFY_ONSNATCH, PLEX_NOTIFY_ONDOWNLOAD, PLEX_NOTIFY_ONSUBTITLEDOWNLOAD),
|
|
|
|
|
('XBMC', XBMC_NOTIFY_ONSNATCH, XBMC_NOTIFY_ONDOWNLOAD, XBMC_NOTIFY_ONSUBTITLEDOWNLOAD),
|
|
|
|
|
('SynologyNotifier', SYNOLOGYNOTIFIER_NOTIFY_ONSNATCH, SYNOLOGYNOTIFIER_NOTIFY_ONDOWNLOAD,
|
|
|
|
|
SYNOLOGYNOTIFIER_NOTIFY_ONSUBTITLEDOWNLOAD),
|
|
|
|
|
|
|
|
|
|
('Boxcar2', BOXCAR2_NOTIFY_ONSNATCH, BOXCAR2_NOTIFY_ONDOWNLOAD, BOXCAR2_NOTIFY_ONSUBTITLEDOWNLOAD),
|
|
|
|
|
('Pushbullet', PUSHBULLET_NOTIFY_ONSNATCH, PUSHBULLET_NOTIFY_ONDOWNLOAD, PUSHBULLET_NOTIFY_ONSUBTITLEDOWNLOAD),
|
|
|
|
|
('Pushover', PUSHOVER_NOTIFY_ONSNATCH, PUSHOVER_NOTIFY_ONDOWNLOAD, PUSHOVER_NOTIFY_ONSUBTITLEDOWNLOAD),
|
|
|
|
|
('Growl', GROWL_NOTIFY_ONSNATCH, GROWL_NOTIFY_ONDOWNLOAD, GROWL_NOTIFY_ONSUBTITLEDOWNLOAD),
|
|
|
|
|
('Prowl', PROWL_NOTIFY_ONSNATCH, PROWL_NOTIFY_ONDOWNLOAD, PROWL_NOTIFY_ONSUBTITLEDOWNLOAD),
|
|
|
|
|
('Libnotify', LIBNOTIFY_NOTIFY_ONSNATCH, LIBNOTIFY_NOTIFY_ONDOWNLOAD, LIBNOTIFY_NOTIFY_ONSUBTITLEDOWNLOAD),
|
|
|
|
|
# ('Pushalot', PUSHALOT_NOTIFY_ONSNATCH, PUSHALOT_NOTIFY_ONDOWNLOAD, PUSHALOT_NOTIFY_ONSUBTITLEDOWNLOAD),
|
|
|
|
|
|
|
|
|
|
('Slack', SLACK_NOTIFY_ONSNATCH, SLACK_NOTIFY_ONDOWNLOAD, SLACK_NOTIFY_ONSUBTITLEDOWNLOAD),
|
|
|
|
|
('Discord', DISCORD_NOTIFY_ONSNATCH, DISCORD_NOTIFY_ONDOWNLOAD, DISCORD_NOTIFY_ONSUBTITLEDOWNLOAD),
|
|
|
|
|
('Gitter', GITTER_NOTIFY_ONSNATCH, GITTER_NOTIFY_ONDOWNLOAD, GITTER_NOTIFY_ONSUBTITLEDOWNLOAD),
|
|
|
|
|
('Telegram', TELEGRAM_NOTIFY_ONSNATCH, TELEGRAM_NOTIFY_ONDOWNLOAD, TELEGRAM_NOTIFY_ONSUBTITLEDOWNLOAD),
|
|
|
|
|
('Email', EMAIL_NOTIFY_ONSNATCH, EMAIL_NOTIFY_ONDOWNLOAD, EMAIL_NOTIFY_ONSUBTITLEDOWNLOAD),
|
|
|
|
|
]:
|
|
|
|
|
if any([onsnatch, ondownload, onsubtitledownload]):
|
|
|
|
|
if onsnatch:
|
|
|
|
|
new_config[notifier]['%s_notify_onsnatch' % notifier.lower()] = int(onsnatch)
|
|
|
|
|
if ondownload:
|
|
|
|
|
new_config[notifier]['%s_notify_ondownload' % notifier.lower()] = int(ondownload)
|
|
|
|
|
if onsubtitledownload:
|
|
|
|
|
new_config[notifier]['%s_notify_onsubtitledownload' % notifier.lower()] = int(onsubtitledownload)
|
|
|
|
|
|
|
|
|
|
# remove empty stanzas
|
2023-02-11 18:02:58 +00:00
|
|
|
|
for k in filter(lambda c: not new_config[c], cfg_keys):
|
2023-01-12 01:04:47 +00:00
|
|
|
|
del new_config[k]
|
|
|
|
|
|
|
|
|
|
new_config['Newznab'] = {}
|
|
|
|
|
new_config['Newznab']['newznab_data'] = NEWZNAB_DATA
|
|
|
|
|
|
2023-02-13 21:00:11 +00:00
|
|
|
|
torrent_rss = '!!!'.join([x.config_str() for x in torrent_rss_providers])
|
2023-01-12 01:04:47 +00:00
|
|
|
|
if torrent_rss:
|
|
|
|
|
new_config['TorrentRss'] = {}
|
|
|
|
|
new_config['TorrentRss']['torrentrss_data'] = torrent_rss
|
|
|
|
|
|
|
|
|
|
new_config['GUI'] = {}
|
|
|
|
|
new_config['GUI']['gui_name'] = GUI_NAME
|
|
|
|
|
new_config['GUI']['theme_name'] = THEME_NAME
|
|
|
|
|
new_config['GUI']['default_home'] = DEFAULT_HOME
|
|
|
|
|
new_config['GUI']['fanart_limit'] = FANART_LIMIT
|
|
|
|
|
new_config['GUI']['fanart_panel'] = FANART_PANEL
|
|
|
|
|
new_config['GUI']['fanart_ratings'] = '%s' % (FANART_RATINGS or {})
|
|
|
|
|
new_config['GUI']['use_imdb_info'] = int(USE_IMDB_INFO)
|
|
|
|
|
new_config['GUI']['imdb_accounts'] = IMDB_ACCOUNTS
|
|
|
|
|
new_config['GUI']['fuzzy_dating'] = int(FUZZY_DATING)
|
|
|
|
|
new_config['GUI']['trim_zero'] = int(TRIM_ZERO)
|
|
|
|
|
new_config['GUI']['date_preset'] = DATE_PRESET
|
|
|
|
|
new_config['GUI']['time_preset'] = TIME_PRESET_W_SECONDS
|
|
|
|
|
new_config['GUI']['timezone_display'] = TIMEZONE_DISPLAY
|
|
|
|
|
|
|
|
|
|
new_config['GUI']['show_tags'] = ','.join(SHOW_TAGS)
|
|
|
|
|
new_config['GUI']['showlist_tagview'] = SHOWLIST_TAGVIEW
|
|
|
|
|
|
|
|
|
|
new_config['GUI']['home_layout'] = HOME_LAYOUT
|
|
|
|
|
new_config['GUI']['footer_time_layout'] = FOOTER_TIME_LAYOUT
|
|
|
|
|
new_config['GUI']['poster_sortby'] = POSTER_SORTBY
|
|
|
|
|
new_config['GUI']['poster_sortdir'] = POSTER_SORTDIR
|
|
|
|
|
|
|
|
|
|
new_config['GUI']['display_show_glide'] = '%s' % (DISPLAY_SHOW_GLIDE or {})
|
|
|
|
|
new_config['GUI']['display_show_glide_slidetime'] = int(DISPLAY_SHOW_GLIDE_SLIDETIME)
|
|
|
|
|
new_config['GUI']['display_show_viewmode'] = int(DISPLAY_SHOW_VIEWMODE)
|
|
|
|
|
new_config['GUI']['display_show_background'] = int(DISPLAY_SHOW_BACKGROUND)
|
|
|
|
|
new_config['GUI']['display_show_background_translucent'] = int(DISPLAY_SHOW_BACKGROUND_TRANSLUCENT)
|
|
|
|
|
new_config['GUI']['display_show_viewart'] = int(DISPLAY_SHOW_VIEWART)
|
|
|
|
|
new_config['GUI']['display_show_minimum'] = int(DISPLAY_SHOW_MINIMUM)
|
|
|
|
|
new_config['GUI']['display_show_specials'] = int(DISPLAY_SHOW_SPECIALS)
|
|
|
|
|
|
|
|
|
|
new_config['GUI']['episode_view_viewmode'] = int(EPISODE_VIEW_VIEWMODE)
|
|
|
|
|
new_config['GUI']['episode_view_background'] = int(EPISODE_VIEW_BACKGROUND)
|
|
|
|
|
new_config['GUI']['episode_view_background_translucent'] = int(EPISODE_VIEW_BACKGROUND_TRANSLUCENT)
|
|
|
|
|
new_config['GUI']['episode_view_layout'] = EPISODE_VIEW_LAYOUT
|
|
|
|
|
new_config['GUI']['episode_view_sort'] = EPISODE_VIEW_SORT
|
|
|
|
|
new_config['GUI']['episode_view_display_paused'] = int(EPISODE_VIEW_DISPLAY_PAUSED)
|
|
|
|
|
new_config['GUI']['episode_view_posters'] = int(EPISODE_VIEW_POSTERS)
|
|
|
|
|
new_config['GUI']['episode_view_missed_range'] = int(EPISODE_VIEW_MISSED_RANGE)
|
|
|
|
|
new_config['GUI']['poster_sortby'] = POSTER_SORTBY
|
|
|
|
|
new_config['GUI']['poster_sortdir'] = POSTER_SORTDIR
|
|
|
|
|
new_config['GUI']['show_tags'] = ','.join(SHOW_TAGS)
|
|
|
|
|
new_config['GUI']['showlist_tagview'] = SHOWLIST_TAGVIEW
|
|
|
|
|
new_config['GUI']['show_tag_default'] = SHOW_TAG_DEFAULT
|
|
|
|
|
new_config['GUI']['history_layout'] = HISTORY_LAYOUT
|
|
|
|
|
new_config['GUI']['browselist_hidden'] = '|~|'.join(BROWSELIST_HIDDEN)
|
|
|
|
|
new_config['GUI']['browselist_prefs'] = '%s' % (BROWSELIST_MRU or {})
|
|
|
|
|
|
|
|
|
|
new_config['Subtitles'] = {}
|
|
|
|
|
new_config['Subtitles']['use_subtitles'] = int(USE_SUBTITLES)
|
|
|
|
|
new_config['Subtitles']['subtitles_languages'] = ','.join(SUBTITLES_LANGUAGES)
|
|
|
|
|
new_config['Subtitles']['SUBTITLES_SERVICES_LIST'] = ','.join(SUBTITLES_SERVICES_LIST)
|
|
|
|
|
new_config['Subtitles']['SUBTITLES_SERVICES_ENABLED'] = '|'.join([str(x) for x in SUBTITLES_SERVICES_ENABLED])
|
|
|
|
|
new_config['Subtitles']['subtitles_services_auth'] = '|||'.join([':::'.join(a) for a in SUBTITLES_SERVICES_AUTH])
|
|
|
|
|
new_config['Subtitles']['subtitles_dir'] = SUBTITLES_DIR
|
|
|
|
|
new_config['Subtitles']['subtitles_default'] = int(SUBTITLES_DEFAULT)
|
|
|
|
|
new_config['Subtitles']['subtitles_history'] = int(SUBTITLES_HISTORY)
|
|
|
|
|
new_config['Subtitles']['subtitles_finder_interval'] = int(SUBTITLES_FINDER_INTERVAL)
|
|
|
|
|
new_config['Subtitles']['subtitles_os_hash'] = SUBTITLES_OS_HASH
|
|
|
|
|
|
|
|
|
|
new_config['FailedDownloads'] = {}
|
|
|
|
|
new_config['FailedDownloads']['use_failed_downloads'] = int(USE_FAILED_DOWNLOADS)
|
|
|
|
|
new_config['FailedDownloads']['delete_failed'] = int(DELETE_FAILED)
|
|
|
|
|
|
|
|
|
|
new_config['ANIDB'] = {}
|
|
|
|
|
new_config['ANIDB']['use_anidb'] = int(USE_ANIDB)
|
|
|
|
|
new_config['ANIDB']['anidb_username'] = ANIDB_USERNAME
|
|
|
|
|
new_config['ANIDB']['anidb_password'] = helpers.encrypt(ANIDB_PASSWORD, ENCRYPTION_VERSION)
|
|
|
|
|
new_config['ANIDB']['anidb_use_mylist'] = int(ANIDB_USE_MYLIST)
|
|
|
|
|
|
|
|
|
|
new_config['ANIME'] = {}
|
|
|
|
|
new_config['ANIME']['anime_treat_as_hdtv'] = int(ANIME_TREAT_AS_HDTV)
|
|
|
|
|
|
2024-06-28 01:57:31 +00:00
|
|
|
|
if not force and CONFIG_OLD == new_config and os.path.isfile(new_config.filename):
|
|
|
|
|
logger.debug('config.ini not dirty, not saving.')
|
|
|
|
|
return
|
2023-06-28 13:49:39 +00:00
|
|
|
|
from sg_helpers import copy_file
|
|
|
|
|
backup_config = re.sub(r'\.ini$', '.bak', CONFIG_FILE)
|
|
|
|
|
from .config import check_valid_config
|
|
|
|
|
try:
|
2024-08-18 04:43:52 +00:00
|
|
|
|
if check_valid_config(CONFIG_FILE):
|
|
|
|
|
for _t in range(0, 3):
|
2024-10-07 00:06:24 +00:00
|
|
|
|
copy_file(CONFIG_FILE, backup_config)
|
|
|
|
|
if not check_valid_config(backup_config):
|
|
|
|
|
if 2 > _t:
|
|
|
|
|
logger.debug('backup config file seems to be invalid, retrying...')
|
|
|
|
|
else:
|
|
|
|
|
logger.warning('backup config file seems to be invalid, not backing up.')
|
|
|
|
|
backup_config = None
|
|
|
|
|
remove_file_perm(backup_config)
|
2024-08-18 04:43:52 +00:00
|
|
|
|
2 > _t and time.sleep(3)
|
|
|
|
|
else:
|
|
|
|
|
break
|
|
|
|
|
else:
|
|
|
|
|
logger.warning('existing config file is invalid, not backing it up')
|
2023-06-28 13:49:39 +00:00
|
|
|
|
backup_config = None
|
|
|
|
|
except (BaseException, Exception):
|
|
|
|
|
backup_config = None
|
|
|
|
|
|
2024-08-18 04:43:52 +00:00
|
|
|
|
for _t in range(0, 3):
|
2023-06-28 13:49:39 +00:00
|
|
|
|
new_config.write()
|
|
|
|
|
if check_valid_config(CONFIG_FILE):
|
2024-06-28 01:57:31 +00:00
|
|
|
|
CONFIG_OLD = copy.deepcopy(new_config)
|
2023-06-28 13:49:39 +00:00
|
|
|
|
return
|
2024-08-18 04:43:52 +00:00
|
|
|
|
if 2 > _t:
|
|
|
|
|
logger.debug('saving config file failed, retrying...')
|
|
|
|
|
else:
|
|
|
|
|
logger.warning('saving config file failed.')
|
2023-06-28 13:49:39 +00:00
|
|
|
|
remove_file_perm(CONFIG_FILE)
|
2024-08-18 04:43:52 +00:00
|
|
|
|
2 > _t and time.sleep(3)
|
2023-06-28 13:49:39 +00:00
|
|
|
|
|
|
|
|
|
# we only get here if the config saving failed multiple times
|
|
|
|
|
if None is not backup_config and os.path.isfile(backup_config):
|
|
|
|
|
logger.error('saving config file failed, using backup file')
|
|
|
|
|
try:
|
|
|
|
|
copy_file(backup_config, CONFIG_FILE)
|
|
|
|
|
logger.log('using old backup config file')
|
|
|
|
|
return
|
|
|
|
|
except (BaseException, Exception):
|
|
|
|
|
logger.error('failed to use backup config file')
|
|
|
|
|
|
|
|
|
|
from sg_helpers import scantree
|
|
|
|
|
try:
|
|
|
|
|
target_base = os.path.join(BACKUP_DB_PATH or os.path.join(DATA_DIR, 'backup'))
|
|
|
|
|
file_list = [f for f in scantree(target_base, include='config', filter_kind=False)]
|
|
|
|
|
if file_list:
|
|
|
|
|
logger.log('trying to use latest config.ini backup')
|
|
|
|
|
# sort newest to oldest backup
|
|
|
|
|
file_list.sort(key=lambda _f: _f.stat(follow_symlinks=False).st_mtime)
|
|
|
|
|
import zipfile
|
|
|
|
|
try:
|
|
|
|
|
with zipfile.ZipFile(file_list[0].path, mode='r') as zf:
|
|
|
|
|
zf.extractall(target_base)
|
|
|
|
|
backup_config_file = os.path.join(target_base, 'config.ini')
|
|
|
|
|
if os.path.isfile(backup_config_file):
|
|
|
|
|
os.replace(backup_config_file, CONFIG_FILE)
|
|
|
|
|
if check_valid_config(CONFIG_FILE):
|
|
|
|
|
logger.log(f'used latest config.ini backup file: {file_list[0].name}')
|
|
|
|
|
return
|
|
|
|
|
else:
|
|
|
|
|
logger.error(f'failed to use latest config.ini backup file: {file_list[0].name}')
|
|
|
|
|
remove_file_perm(CONFIG_FILE)
|
|
|
|
|
except (BaseException, Exception):
|
|
|
|
|
pass
|
|
|
|
|
finally:
|
|
|
|
|
try:
|
|
|
|
|
remove_file_perm(backup_config_file)
|
|
|
|
|
except (BaseException, Exception):
|
|
|
|
|
pass
|
|
|
|
|
logger.error('failed to use latest config.ini')
|
|
|
|
|
except (BaseException, Exception):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
logger.error('saving config file failed and no backup available')
|
2023-01-12 01:04:47 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def launch_browser(start_port=None):
|
|
|
|
|
if not start_port:
|
|
|
|
|
start_port = WEB_PORT
|
|
|
|
|
browser_url = 'http%s://localhost:%d%s' % (('s', '')[not ENABLE_HTTPS], start_port, WEB_ROOT)
|
|
|
|
|
try:
|
|
|
|
|
webbrowser.open(browser_url, 2, True)
|
|
|
|
|
except (BaseException, Exception):
|
|
|
|
|
try:
|
|
|
|
|
webbrowser.open(browser_url, 1, True)
|
|
|
|
|
except (BaseException, Exception):
|
2023-03-08 13:44:20 +00:00
|
|
|
|
logger.error('Unable to launch a browser')
|