def __init__(self, config, log = None):
     self.config = config
     if log is not None:
         warnings.warn("the UI's log parameter is deprecated, instead use\n"
             "use import logging; logging.getLogger('ui').info('blah')\n"
             "The self.log attribute will be removed in the next version")
         self.log = LoggingAdapter.getLogger(__name__)
    def __init__(self, settings=None, logger=None):
        if logger:
            self.log = logger
        else:
            self.log = LoggingAdapter.getLogger(__name__)

        if settings is None:
            raise ValueError("Settings not supplied")
        self.settings = settings
        self.converter = MkvtoMp4(settings)
    def __init__(self, files, logger=None):
        # Setup Logging
        if logger:
            self.log = logger
        else:
            self.log = LoggingAdapter.getLogger(__name__)

        self.log.debug("Output: %s" % files)

        self.set_script_environment(files)
        self.scripts = self.gather_scripts()
Example #4
0
def refreshPlex(settings, source_type, logger=None):
    if logger:
        log = logger
    else:
        log = LoggingAdapter.getLogger(__name__)

    host = settings.Plex['host']
    port = settings.Plex['port']
    token = settings.Plex['token']

    log.debug("Host: %s." % host)
    log.debug("Port: %s." % port)
    log.debug("Token: %s." % token)

    approved_sources = ['movie', 'show']
    if settings.Plex['refresh'] and source_type in approved_sources:
        base_url = 'http://%s:%s/library/sections' % (host, port)
        refresh_url = '%s/%%s/refresh' % base_url

        if token:
            refresh_url = refresh_url + "?X-Plex-Token=" + token
            base_url = base_url + "?X-Plex-Token=" + token
            log.debug("Plex home token detected.")

        log.debug("Refresh URL: %s." % refresh_url)
        log.debug("Base URL: %s." % base_url)

        try:
            xml_sections = minidom.parse(urlopen(base_url))
            sections = xml_sections.getElementsByTagName('Directory')
            for s in sections:
                if s.getAttribute('type') == source_type:
                    url = refresh_url % s.getAttribute('key')
                    x = urlopen(url)
        except Exception:
            log.exception("Unable to refresh plex, check your settings.")
Example #5
0
def processEpisode(dirName, settings, nzbGet=False, logger=None):

    if nzbGet:
        errorprefix = "[ERROR] "
        infoprefix = "[INFO] "
    else:
        errorprefix = ""
        infoprefix = ""

    # Setup logging
    if logger:
        log = logger
    else:
        log = LoggingAdapter.getLogger(__name__)

    log.info("%sSonarr notifier started." % infoprefix)

    # Import Requests
    try:
        import requests
    except ImportError:
        log.exception(
            "%sPython module REQUESTS is required. Install with 'pip install requests' then try again."
            % errorprefix)
        log.error("%sPython executable path is %s" %
                  (errorprefix, sys.executable))
        return False

    host = settings.Sonarr['host']
    port = settings.Sonarr['port']
    apikey = settings.Sonarr['apikey']

    if apikey == '':
        log.error(
            "%sYour Sonarr API Key can not be blank. Update autoProcess.ini." %
            errorprefix)
        return False

    try:
        ssl = int(settings.Sonarr['ssl'])
    except:
        ssl = 0
    if ssl:
        protocol = "https://"
    else:
        protocol = "http://"

    url = protocol + host + ":" + port + "/api/command"
    payload = {'name': 'downloadedepisodesscan', 'path': dirName}
    headers = {'X-Api-Key': apikey}

    log.debug("Sonarr host: %s." % host)
    log.debug("Sonarr port: %s." % port)
    log.debug("Sonarr apikey: %s." % apikey)
    log.debug("Sonarr protocol: %s." % protocol)
    log.debug("URL '%s' with payload '%s.'" % (url, payload))

    log.info("%sRequesting Sonarr to scan directory '%s'." %
             (infoprefix, dirName))

    try:
        r = requests.post(url, data=json.dumps(payload), headers=headers)
        rstate = r.json()
        log.info("%sSonarr response: %s." % (infoprefix, rstate['state']))
        return True
    except:
        log.exception(
            "%sUpdate to Sonarr failed, check if Sonarr is running, autoProcess.ini settings and make sure your Sonarr settings are correct (apikey?), or check install of python modules requests."
            % errorprefix)
        return False
Example #6
0
#!/usr/bin/env python

import os.path
import os
import re
import signal
from subprocess import Popen, PIPE
import logging
import locale
from _utils import LoggingAdapter

logger = LoggingAdapter.getLogger(__name__)

console_encoding = locale.getdefaultlocale()[1] or 'UTF-8'


class FFMpegError(Exception):
    pass


class FFMpegConvertError(Exception):
    def __init__(self, message, cmd, output, details=None, pid=0):
        """
        @param    message: Error message.
        @type     message: C{str}

        @param    cmd: Full command string used to spawn ffmpeg.
        @type     cmd: C{str}

        @param    output: Full stdout output from the ffmpeg command.
        @type     output: C{str}
Example #7
0
def processEpisode(dir_to_process, settings, org_NZB_name=None, status=None, logger=None):

    # Setup logging
    if logger:
        log = logger
    else:
        log = LoggingAdapter.getLogger(__name__)

    try:
        import requests
    except ImportError:
        log.exception("You need to install python requests library.")
        sys.exit(1)

    # Try importing Python 2 modules using new names
    try:
        from urllib import urlencode
    # On error import Python 3 modules
    except ImportError:
        from urllib.parse import urlencode

    host = settings.Sickrage['host']
    port = settings.Sickrage['port']
    username = settings.Sickrage['user']
    password = settings.Sickrage['pass']

    try:
        ssl = int(settings.Sickrage['ssl'])
    except:
        ssl = 0

    try:
        web_root = settings.Sickrage['web_root']
        if not web_root.startswith("/"):
            web_root = "/" + web_root
        if not web_root.endswith("/"):
            web_root = web_root + "/"
    except:
        web_root = ""

    params = {}

    params['quiet'] = 1

    params['dir'] = dir_to_process
    if org_NZB_name is not None:
        params['nzbName'] = org_NZB_name

    if status is not None:
        params['failed'] = status

    if ssl:
        protocol = "https://"
    else:
        protocol = "http://"

    url = protocol + host + ":" + port + web_root + "home/postprocess/processEpisode"
    login_url = protocol + host + ":" + port + web_root + "login"

    log.debug('Host: %s.' % host)
    log.debug('Port: %s.' % port)
    log.debug('Username: %s.' % username)
    log.debug('Password: %s.' % password)
    log.debug('Protocol: %s.' % protocol)
    log.debug('Web Root: %s.' % web_root)
    log.debug('URL: %s.' % url)
    log.debug('Login URL: %s.' % login_url)

    log.info("Opening URL: %s." % url)

    try:
        sess = requests.Session()
        sess.post(login_url, data={'username': username, 'password': password}, stream=True, verify=False)
        result = sess.get(url, params=params, stream=True, verify=False)
        lastline = None

        for line in result.iter_lines():
            if line:
                log.debug(line.strip())
                lastline = line.strip()

        if lastline:
            log.info(lastline)

    except IOError:
        e = sys.exc_info()[1]
        log.exception("Unable to open URL: %s." % str(e))
        sys.exit(1)
Example #8
0
#!/usr/bin/env python
import os
import sys
import json
import urllib

sys.path.append(os.path.join(os.path.dirname(__file__), ".."))
from readSettings import settingsProvider
from _utils import LoggingAdapter

srconfig = settingsProvider(
    config_file=os.environ.get('MH_CONFIG')).defaultSettings.Sickrage
log = LoggingAdapter.getLogger()


def apiPostProcess():
    log.info("Triggering Sickrage Post Process")
    api_url = getApiUrl() + "cmd=postprocess&is_priority=1&force_replace=1"
    refresh = json.load(urllib.urlopen(api_url))
    if resultToBool(refresh["result"]):
        log.debug("Post Process was initiated.")
        return True
    else:
        log.error("Something went wrong, output was:")
        log.error(json.dumps(refresh, indent=4))
    return False


def getApiUrl():
    protocol = "http://"  # SSL
    try:
#!/usr/bin/env python
import os
import sys
import json
import urllib
import struct

from _utils import LoggingAdapter
log = LoggingAdapter.getLogger("MANUAL", {})
log.info("Sickbeard extra script post processing started")

from readSettings import ReadSettings
from autoprocess import plex
from tvdb_mp4 import Tvdb_mp4
#from mkvtomp4 import MkvtoMp4
#from post_processor import PostProcessor
from processor import fileProcessor

settings = settingsProvider().defaultSettings
processor = fileProcessor(settings)

if len(sys.argv) > 4:
    inputfile = sys.argv[1]
    original = sys.argv[2]
    tvdb_id = int(sys.argv[3])
    season = int(sys.argv[4])
    episode = int(sys.argv[5])

    log.debug("Input file: %s" % inputfile)
    log.debug("Original name: %s" % original)
    log.debug("TvDB ID: %s" % tvdb_id)
Example #10
0
def processEpisode(dirName, settings, nzbName=None, logger=None):

    # Setup logging
    if logger:
        log = logger
    else:
        log = LoggingAdapter.getLogger(__name__)

    host = settings.Sickbeard['host']
    port = settings.Sickbeard['port']
    username = settings.Sickbeard['user']
    password = settings.Sickbeard['pass']
    try:
        ssl = int(settings.Sickbeard['ssl'])
    except:
        ssl = 0

    try:
        web_root = settings.Sickbeard['web_root']
    except:
        web_root = ""

    params = {}

    params['quiet'] = 1

    params['dir'] = dirName
    if nzbName is not None:
        params['nzbName'] = nzbName

    myOpener = AuthURLOpener(username, password)

    if ssl:
        protocol = "https://"
    else:
        protocol = "http://"

    url = protocol + host + ":" + port + web_root + "/home/postprocess/processEpisode?" + urlencode(
        params)

    log.debug('Host: %s.' % host)
    log.debug('Port: %s.' % port)
    log.debug('Username: %s.' % username)
    log.debug('Password: %s.' % password)
    log.debug('Protocol: %s.' % protocol)
    log.debug('Web Root: %s.' % web_root)
    log.debug('URL: %s.' % url)

    log.info("Opening URL: %s." % url)

    try:
        urlObj = myOpener.openit(url)
    except IOError:
        log.exception("Unable to open URL")
        sys.exit(1)

    result = urlObj.readlines()
    lastline = None

    for line in result:
        if line:
            log.debug(line.strip())
            lastline = line.strip()

    if lastline:
        log.info(lastline)
def process(dirName, settings, nzbName=None, status=0, logger=None):

    # Setup logging
    if logger:
        log = logger
    else:
        log = LoggingAdapter.getLogger(__name__)

    status = int(status)

    host = settings.CP['host']
    port = settings.CP['port']
    username = settings.CP['username']
    password = settings.CP['password']
    apikey = settings.CP['apikey']
    delay = settings.CP['delay']
    method = settings.CP['method']
    delete_failed = settings.CP['delete_failed']
    protocol = settings.CP['protocol']
    web_root = settings.CP['web_root']

    if web_root != "" and not web_root.startswith("/"):
        web_root = "/" + web_root

    myOpener = AuthURLOpener(username, password)
    nzbName1 = str(nzbName)

    # Don't delay when we are calling this script manually.
    if nzbName == "Manual Run":
        delay = 0

    log.debug("Host: %s." % host)
    log.debug("Port: %s." % port)
    log.debug("Username: %s." % username)
    log.debug("Password: %s." % password)
    log.debug("APIKey: %s." % apikey)
    log.debug("Delay: %s." % delay)
    log.debug("Method: %s." % method)
    log.debug("Delete Failed: %s." % delete_failed)
    log.debug("Protocol: %s." % protocol)
    log.debug("Web Root: %s." % web_root)

    if status == 0:
        if method == "manage":
            command = "manage.update"
        else:
            command = "renamer.scan"

        url = protocol + host + ":" + port + web_root + "/api/" + apikey + "/" + command

        params = {'media_folder': dirName, 'downloader': 'manual'}

        log.info(
            "Waiting for %s seconds to allow CPS to process newly extracted files."
            % str(delay))

        time.sleep(delay)

        log.info("Opening URL: %s." % url)

        r = requests.get(url, params=params)

        rstate = r.json()

        log.info("CouchPotatoServer returned %s." % rstate)
        if rstate['success']:
            log.info("%s started on CouchPotatoServer for %s." %
                     (command, nzbName1))
        else:
            log.error("%s has NOT started on CouchPotatoServer for %s." %
                      (command, nzbName1))

    else:
        log.info("Download of %s has failed." % nzbName1)
        log.info("Trying to re-cue the next highest ranked release.")
        try:
            a = nzbName1.find('.cp(') + 4
            b = nzbName1[a:].find(')') + a
            imdbid = nzbName1[a:b]

            log.debug("Attempt to determine IMDBID resulted in '%s'." % imdbid)
        except:
            log.exception(
                "Unable to determine release IMDB ID for requeueing.")
            sys.exit()

        url = protocol + host + ":" + port + web_root + "/api/" + apikey + "/movie.list"
        log.info("Opening URL: %s." % url)

        try:
            urlObj = myOpener.openit(url)
        except IOError:
            log.exception("Unable to open URL.")
            sys.exit(1)

        n = 0
        result = json.load(urlObj)
        movieid = [item["info"]["imdb"] for item in result["movies"]]

        log.debug("Movie ID: %s." % movieid)

        for index in range(len(movieid)):
            if movieid[index] == imdbid:
                movid = str(movieid[index])
                log.info("Found movie id %s in database for release %s." %
                         (movid, nzbName1))
                n = n + 1
                break

        if n == 0:
            log.error(
                "Cound not find a movie in the database for release %s." %
                nzbName1)
            log.error(
                "Please manually ignore this release and refresh the wanted movie."
            )
            log.error("Exiting postprocessing script")
            sys.exit(1)

        url = protocol + host + ":" + port + web_root + "/api/" + apikey + "/movie.searcher.try_next/?media_id=" + movid
        log.info("Opening URL: %s." % url)

        try:
            urlObj = myOpener.openit(url)
        except IOError:
            log.exception("Unable to open URL.")
            sys.exit(1)

        result = urlObj.readlines()
        for line in result:
            log.info(line)

        log.info(
            "Movie %s set to try the next best release on CouchPotatoServer." %
            movid)
        if delete_failed:
            log.error("Deleting failed files and folder %s." % dirName)
            shutil.rmtree(dirName)
if IS_PY2:
    int_types = (int, long)
    text_type = unicode
else:
    int_types = int
    text_type = str

from .tvdb_ui import BaseUI, ConsoleUI
from .tvdb_exceptions import (tvdb_error, tvdb_userabort, tvdb_shownotfound,
                              tvdb_seasonnotfound, tvdb_episodenotfound,
                              tvdb_attributenotfound)

lastTimeout = None

log = logger = LoggingAdapter.getLogger("tvdb_api")
#def log():
#    return logger


class ShowContainer(dict):
    """Simple dict that holds a series of Show instances
    """
    def __init__(self):
        self._stack = []
        self._lastgc = time.time()

    def __setitem__(self, key, value):
        self._stack.append(key)

        #keep only the 100th latest results
Example #13
0
    def __init__(self, directory, filename, logger=None):
        # Setup logging
        if logger:
            log = logger
        else:
            log = LoggingAdapter.getLogger(__name__)

        # Setup encoding to avoid UTF-8 errors
        if sys.version[0] == '2':
            SYS_ENCODING = None
            try:
                locale.setlocale(locale.LC_ALL, "")
                SYS_ENCODING = locale.getpreferredencoding()
            except (locale.Error, IOError):
                pass

            # For OSes that are poorly configured just force UTF-8
            if not SYS_ENCODING or SYS_ENCODING in ('ANSI_X3.4-1968', 'US-ASCII', 'ASCII'):
                SYS_ENCODING = 'UTF-8'

            if not hasattr(sys, "setdefaultencoding"):
                reload(sys)

            try:
                # pylint: disable=E1101
                # On non-unicode builds this will raise an AttributeError, if encoding type is not valid it throws a LookupError
                sys.setdefaultencoding(SYS_ENCODING)
            except:
                log.exception("Sorry, your environment is not setup correctly for utf-8 support. Please fix your setup and try again")
                sys.exit("Sorry, your environment is not setup correctly for utf-8 support. Please fix your setup and try again")

        #log.info(sys.executable)

        # Default settings for SickBeard
        sb_defaults = {'host': 'localhost',
                       'port': '8081',
                       'ssl': "False",
                       'api_key': '',
                       'web_root': '',
                       'username': '',
                       'password': ''}
        # Default MP4 conversion settings
        mp4_defaults = {'ffmpeg': 'ffmpeg.exe',
                        'ffprobe': 'ffprobe.exe',
                        'output_directory': '',
                        'copy_to': '',
                        'move_to': 'True',
                        'output_extension': 'mp4',
                        'output_format': 'mp4',
                        'delete_original': 'True',
                        'relocate_moov': 'True',
                        'ios-audio': 'True',
                        'ios-first-track-only': 'False',
                        'ios-audio-filter': '',
                        'max-audio-channels': '',
                        'audio-language': '',
                        'audio-default-language': '',
                        'audio-codec': 'ac3',
                        'audio-filter': '',
                        'audio-channel-bitrate': '256',
                        'video-codec': 'h264, x264',
                        'video-bitrate': '',
                        'video-max-width': '',
                        'h264-max-level': '',
                        'use-qsv-decoder-with-encoder': 'False',
                        'subtitle-codec': 'mov_text',
                        'subtitle-language': '',
                        'subtitle-default-language': '',
                        'subtitle-encoding': '',
                        'convert-mp4': 'False',
                        'meks-video-quality': '',
                        'meks-h264-preset': 'medium',
                        'meks-staging': 'True',
                        'meks-staging-extension': 'part',
                        'meks-metadata': '',
                        'meks-nfosearch': 'True',
                        'meks-nfopaths': '..',
                        'meks-walk-ignore': 'ignore.part,ignore.skip,recode.ignore,recode.skip',
                        'meks-walk-ignore-self': 'True',
                        'meks-transcode-ignore-names': 'sample',
                        'meks-transcode-ignore-size': '0',
                        'meks-qsv-lookahead': '1',
                        'meks-same-vcodec-copy': 'True',
                        'meks-same-acodec-copy': 'True',
                        'meks-aac-adtstoasc': 'False',
                        'meks-id3v2vers': '3',
                        'meks-tag-rename': 'False',
                        'meks-tag-language-auto' : 'False',
                        'meks-tag-mandatory': 'False',
                        'fullpathguess': 'True',
                        'tagfile': 'True',
                        'tag-language': 'en',
                        'download-artwork': 'poster',
                        'download-subs': 'False',
                        'embed-subs': 'True',
                        'sub-providers': 'addic7ed, podnapisi, thesubdb, opensubtitles',
                        'permissions': '777',
                        'post-process': 'False',
                        'pix-fmt': ''}
        # Default settings for CouchPotato
        cp_defaults = {'host': 'localhost',
                       'port': '5050',
                       'username': '',
                       'password': '',
                       'apikey': '',
                       'delay': '65',
                       'method': 'renamer',
                       'delete_failed': 'False',
                       'ssl': 'False',
                       'web_root': ''}
        # Default settings for Sonarr
        sonarr_defaults = {'host': 'localhost',
                           'port': '8989',
                           'apikey': '',
                           'ssl': 'False',
                           'web_root': ''}
        # Default uTorrent settings
        utorrent_defaults = {'couchpotato-label': 'couchpotato',
                             'sickbeard-label': 'sickbeard',
                             'sickrage-label': 'sickrage',
                             'sonarr-label': 'sonarr',
                             'bypass-label': 'bypass',
                             'convert': 'True',
                             'webui': 'False',
                             'action_before': 'stop',
                             'action_after': 'removedata',
                             'host': 'http://localhost:8080/',
                             'username': '',
                             'password': ''}
        # Default SAB settings
        sab_defaults = {'convert': 'True',
                        'Sickbeard-category': 'sickbeard',
                        'Sickrage-category': 'sickrage',
                        'Couchpotato-category': 'couchpotato',
                        'Sonarr-category': 'sonarr',
                        'Bypass-category': 'bypass'}
        # Default Sickrage Settings
        sr_defaults = {'host': 'localhost',
                       'port': '8081',
                       'ssl': "False",
                       'api_key': '',
                       'web_root': '',
                       'username': '',
                       'password': ''}

        # Default deluge settings
        deluge_defaults = {'couchpotato-label': 'couchpotato',
                           'sickbeard-label': 'sickbeard',
                           'sickrage-label': 'sickrage',
                           'sonarr-label': 'sonarr',
                           'bypass-label': 'bypass',
                           'convert': 'True',
                           'host': 'localhost',
                           'port': '58846',
                           'username': '',
                           'password': ''}

        # Default Plex Settings
        plex_defaults = {'host': 'localhost',
                         'port': '32400',
                         'refresh': 'true',
                         'token': ''}

        defaults = {'SickBeard': sb_defaults, 'CouchPotato': cp_defaults, 'Sonarr': sonarr_defaults, 'MP4': mp4_defaults, 'uTorrent': utorrent_defaults, 'SABNZBD': sab_defaults, 'Sickrage': sr_defaults, 'Deluge': deluge_defaults, 'Plex': plex_defaults}
        write = False  # Will be changed to true if a value is missing from the config file and needs to be written

        config = configparser.SafeConfigParser()
        configFile = os.path.join(directory, filename)
        if os.path.isfile(configFile):
            config.read(configFile)
        else:
            log.error("Config file not found, creating %s" % configFile)
            # config.filename = filename
            write = True

        # Make sure all sections and all keys for each section are present
        for s in defaults:
            if not config.has_section(s):
                config.add_section(s)
                write = True
            for k in defaults[s]:
                if not config.has_option(s, k):
                    config.set(s, k, defaults[s][k])
                    write = True

        # If any keys are missing from the config file, write them
        if write:
            self.writeConfig(config, configFile)

        # Read relevant MP4 section information
        section = "MP4"
        self.ffmpeg = os.path.normpath(self.raw(config.get(section, "ffmpeg")))  # Location of FFMPEG.exe
        self.ffprobe = os.path.normpath(self.raw(config.get(section, "ffprobe")))  # Location of FFPROBE.exe

        self.output_dir = config.get(section, "output_directory")
        if self.output_dir == '':
            self.output_dir = None
        else:
            self.output_dir = os.path.normpath(self.raw(self.output_dir))  # Output directory
        
        cptod = {'movie':[], 'tv':[], 'all':[]}
        for cptol in ['copy_to']:
            cpto = config.get(section, cptol)
            if not cpto == '':
                cpto  = cpto.split('|')
                for kv in cpto:
                    if kv[:6] == 'movie:':
                        cptok = kv[:5]
                        cptop = kv[6:]
                    elif kv[:3] == 'tv:':
                        cptok = kv[:2]
                        cptop = kv[3:]
                    else:
                        cptok = "all"
                        cptop = kv
                    cptop = os.path.normpath(cptop)
                    if not os.path.isdir(cptop):
                        try:
                            os.makedirs(cptop)
                        except:
                            log.exception("Error making directory %s" % cptop)
                            continue
                    #log.debug("%s path for type '%s' added: %s" % (cptol, cptok, cptop))
                    cptod[cptok].append(cptop)
        self.copyto = cptod  # Directories to copy the final file to
        self.moveto = config.getboolean(section, "move_to")  # Move instead of copy
        
        self.output_extension = config.get(section, "output_extension")  # Output extension
        self.output_format = config.get(section, "output_format")  # Output format
        if self.output_format not in valid_formats:
            self.output_format = 'mov'
        self.delete = config.getboolean(section, "delete_original")  # Delete original file
        self.relocate_moov = config.getboolean(section, "relocate_moov")  # Relocate MOOV atom to start of file
        if self.relocate_moov:
            try:
                import qtfaststart
            except:
                log.error("Please install QTFastStart via PIP, relocate_moov will be disabled without this module")
                self.relocate_moov = False
        self.acodec = config.get(section, "audio-codec").lower()  # Gets the desired audio codec, if no valid codec selected, default to AC3
        if self.acodec == '':
            self.acodec == ['ac3']
        else:
            self.acodec = self.acodec.lower().replace(' ', '').split(',')

        self.abitrate = config.get(section, "audio-channel-bitrate")
        try:
            self.abitrate = int(self.abitrate)
        except:
            self.abitrate = 256
            log.warning("Audio bitrate was invalid, defaulting to 256 per channel")
        if self.abitrate > 256:
            log.warning("Audio bitrate >256 may create errors with common codecs")

        self.afilter = config.get(section, "audio-filter").lower().strip()  # Audio filter
        if self.afilter == '':
            self.afilter = None

        self.iOS = config.get(section, "ios-audio")  # Creates a second audio channel if the standard output methods are different from this for iOS compatability
        if self.iOS == "" or self.iOS.lower() in ['false', 'no', 'f', '0']:
            self.iOS = False
        else:
            if self.iOS.lower() in ['true', 'yes', 't', '1']:
                self.iOS = ['aac']
            else:
                self.iOS = self.iOS.lower().replace(' ', '').split(',')

        self.iOSFirst = config.getboolean(section, "ios-first-track-only")  # Enables the iOS audio option only for the first track

        self.iOSfilter = config.get(section, "ios-audio-filter").lower().strip()  # iOS audio filter
        if self.iOSfilter == '':
            self.iOSfilter = None

        self.downloadsubs = config.getboolean(section, "download-subs")  # Enables downloading of subtitles from the internet sources using subliminal
        if self.downloadsubs:
            try:
                import subliminal
            except Exception as e:
                self.downloadsubs = False
                log.exception("Subliminal is not installed, automatically downloading of subs has been disabled")
        self.subproviders = config.get(section, 'sub-providers').lower()
        if self.subproviders == '':
            self.downloadsubs = False
            log.warning("You must specifiy at least one subtitle provider to download subs automatically, subtitle downloading disabled")
        else:
            self.subproviders = self.subproviders.lower().replace(' ', '').split(',')

        self.embedsubs = config.getboolean(section, 'embed-subs')

        self.permissions = config.get(section, 'permissions')
        try:
            self.permissions = int(self.permissions, 8)
        except:
            self.log.exception("Invalid permissions, defaulting to 777")
            self.permissions = int("0777", 8)

        try:
            self.postprocess = config.getboolean(section, 'post-process')
        except:
            self.postprocess = False

        # Setup variable for maximum audio channels
        self.maxchannels = config.get(section, 'max-audio-channels')
        if self.maxchannels == "":
            self.maxchannels = None
        else:
            try:
                self.maxchannels = int(self.maxchannels)
            except:
                log.exception("Invalid number of audio channels specified")
                self.maxchannels = None
        if self.maxchannels is not None and self.maxchannels < 1:
            log.warning("Must have at least 1 audio channel")
            self.maxchannels = None

        self.vcodec = config.get(section, "video-codec")
        if self.vcodec == '':
            self.vcodec == ['h264', 'x264']
        else:
            self.vcodec = self.vcodec.lower().replace(' ', '').split(',')

        self.vbitrate = config.get(section, "video-bitrate")
        if self.vbitrate == '':
            self.vbitrate = None
        else:
            try:
                self.vbitrate = int(self.vbitrate)
                if not (self.vbitrate > 0):
                    self.vbitrate = None
                    log.warning("Video bitrate must be greater than 0, defaulting to no video bitrate cap")
            except:
                log.exception("Invalid video bitrate, defaulting to no video bitrate cap")
                self.vbitrate = None

        try:
            self.meks_staging = config.getboolean(section, 'meks-staging')
            self.meks_stageext = config.get(section, "meks-staging-extension")
        except:
            self.meks_staging = False
        self.meks_h264_preset = config.get(section, "meks-h264-preset")
        if self.meks_h264_preset not in ["ultrafast", "superfast", "veryfast", "faster", "fast", "medium", "slow", "slower", "veryslow", "placebo"]:
            self.meks_h264_preset = "medium"
        self.meks_metadata = config.get(section, "meks-metadata")
        self.meks_video_quality = config.get(section, "meks-video-quality")
        if self.meks_video_quality == '':
            self.meks_video_quality = 23
        else:
            try:
                self.meks_video_quality = int(self.meks_video_quality)
            except:
                log.exception("Invalid h264 cfr quality, using default quality")
                self.meks_video_quality = 23
        self.meks_walk_noself = config.getboolean(section, 'meks-walk-ignore-self')
        self.meks_walk_ignore = config.get(section, 'meks-walk-ignore').strip()
        if self.meks_walk_ignore == '':
            self.meks_walk_ignore = None
        else:
            self.meks_walk_ignore = self.meks_walk_ignore.split(',')
        self.meks_trans_ignore_n = config.get(section, 'meks-transcode-ignore-names').strip()
        if self.meks_trans_ignore_n == '':
            self.meks_trans_ignore_n = None
        else:
            self.meks_trans_ignore_n = self.meks_trans_ignore_n.split(',')
        self.meks_trans_ignore_s = config.get(section, "meks-transcode-ignore-size")
        if self.meks_trans_ignore_s == '':
            self.meks_trans_ignore_s = 0
        else:
            try:
                self.meks_trans_ignore_s = int(self.meks_trans_ignore_s)
            except:
                log.exception("Invalid transcode ignore size value, using default (0)")
                self.meks_trans_ignore_s = 0
        self.meks_copysamevcodec = config.getboolean(section, "meks-same-vcodec-copy")
        self.meks_copysameacodec = config.getboolean(section, "meks-same-acodec-copy")
        self.meks_adtstoasc = config.getboolean(section, 'meks-aac-adtstoasc')
        self.meks_nfosearch = config.getboolean(section, "meks-nfosearch")
        self.meks_tagrename = config.getboolean(section, "meks-tag-rename")
        self.meks_nfopaths = config.get(section, 'meks-nfopaths').split('|')
        self.meks_taglangauto = config.get(section, "meks-tag-language-auto")
        self.meks_tagmandatory = config.get(section, "meks-tag-mandatory")
        self.meks_qsv_lookahead = config.get(section, "meks-qsv-lookahead")
        if self.meks_qsv_lookahead == '':
            self.meks_qsv_lookahead = 0
        else:
            try:
                self.meks_qsv_lookahead = int(self.meks_qsv_lookahead)
            except:
                log.exception("Invalid qsv lookahead value, using default (0)")
                self.meks_qsv_lookahead = 0
        if self.meks_qsv_lookahead > 0:
            self.meks_video_quality = None
        self.meks_id3v2vers = config.get(section, "meks-id3v2vers")
        if self.meks_id3v2vers == '':
            self.meks_id3v2vers = 3
        else:
            try:
                self.meks_id3v2vers = float(self.meks_id3v2vers)
            except:
                log.exception("Invalid ID3v2 version, defaulting to 3")
                self.meks_id3v2vers = 3
            
        self.vwidth = config.get(section, "video-max-width")
        if self.vwidth == '':
            self.vwidth = None
        else:
            try:
                self.vwidth = int(self.vwidth)
            except:
                log.exception("Invalid video width, defaulting to none")
                self.vwidth = None

        self.h264_level = config.get(section, "h264-max-level")
        if self.h264_level == '':
            self.h264_level = None
        else:
            try:
                self.h264_level = float(self.h264_level)
            except:
                log.exception("Invalid h264 level, defaulting to none")
                self.h264_level = None

        self.qsv_decoder = config.getboolean(section, "use-qsv-decoder-with-encoder")  # Use Intel QuickSync Decoder when using QuickSync Encoder
        self.pix_fmt = config.get(section, "pix-fmt").strip().lower()
        if self.pix_fmt == '':
            self.pix_fmt = None
        else:
            self.pix_fmt = self.pix_fmt.replace(' ', '').split(',')

        self.awl = config.get(section, 'audio-language').strip().lower()  # List of acceptable languages for audio streams to be carried over from the original file, separated by a comma. Blank for all
        if self.awl == '':
            self.awl = None
        else:
            self.awl = self.awl.replace(' ', '').split(',')

        self.scodec = config.get(section, 'subtitle-codec').strip().lower()
        if not self.scodec or self.scodec == "":
            if self.embedsubs:
                self.scodec = ['mov_text']
            else:
                self.scodec = ['srt']
            log.warning("Invalid subtitle codec, defaulting to '%s'" % self.scodec)
        else:
            self.scodec = self.scodec.replace(' ', '').split(',')

        if self.embedsubs:
            if len(self.scodec) > 1:
                log.warning("Can only embed one subtitle type, defaulting to 'mov_text'")
                self.scodec = ['mov_text']
            if self.scodec[0] not in valid_internal_subcodecs:
                log.warning("Invalid interal subtitle codec %s, defaulting to 'mov_text'" % self.scodec[0])
                self.scodec = ['mov_text']
        else:
            for codec in self.scodec:
                if codec not in valid_external_subcodecs:
                    log.warning("Invalid external subtitle codec %s, ignoring" % codec)
                    self.scodec.remove(codec)

            if len(self.scodec) == 0:
                log.warning("No valid subtitle formats found, defaulting to 'srt'")
                self.scodec = ['srt']

        self.swl = config.get(section, 'subtitle-language').strip().lower()  # List of acceptable languages for subtitle streams to be carried over from the original file, separated by a comma. Blank for all
        if self.swl == '':
            self.swl = None
        else:
            self.swl = self.swl.replace(' ', '').split(',')

        self.subencoding = config.get(section, 'subtitle-encoding').strip().lower()
        if self.subencoding == '':
            self.subencoding = None

        self.adl = config.get(section, 'audio-default-language').strip().lower()  # What language to default an undefinied audio language tag to. If blank, it will remain undefined. This is useful for single language releases which tend to leave things tagged as und
        if self.adl == "" or len(self.adl) > 3:
            self.adl = None

        self.sdl = config.get(section, 'subtitle-default-language').strip().lower()  # What language to default an undefinied subtitle language tag to. If blank, it will remain undefined. This is useful for single language releases which tend to leave things tagged as und
        if self.sdl == ""or len(self.sdl) > 3:
            self.sdl = None
        # Prevent incompatible combination of settings
        if self.output_dir == "" and self.delete is False:
            log.error("You must specify an alternate output directory if you aren't going to delete the original file")
            sys.exit()
        # Create output directory if it does not exist
        if self.output_dir is not None:
            if not os.path.isdir(self.output_dir):
                os.makedirs(self.output_dir)
        self.processMP4 = config.getboolean(section, "convert-mp4")  # Determine whether or not to reprocess mp4 files or just tag them
        self.fullpathguess = config.getboolean(section, "fullpathguess")  # Guess using the full path or not
        self.tagfile = config.getboolean(section, "tagfile")  # Tag files with metadata
        self.taglanguage = config.get(section, "tag-language").strip().lower()  # Language to tag files
        if len(self.taglanguage) > 2:
            try:
                babel = Language(self.taglanguage)
                self.taglanguage = babel.alpha2
            except:
                log.exception("Unable to set tag language, defaulting to English")
                self.taglanguage = 'en'
        elif len(self.taglanguage) < 2:
            log.exception("Unable to set tag language, defaulting to English")
            self.taglanguage = 'en'
        self.artwork = config.get(section, "download-artwork").lower()  # Download and embed artwork
        if self.artwork == "poster":
            self.artwork = True
            self.thumbnail = False
        elif self.artwork == "thumb" or self.artwork == "thumbnail":
            self.artwork = True
            self.thumbnail = True
        else:
            self.thumbnail = False
            try:
                self.artwork = config.getboolean(section, "download-artwork")
            except:
                self.artwork = True
                self.log.error("Invalid download-artwork value, defaulting to 'poster'")

        # Read relevant CouchPotato section information
        section = "CouchPotato"
        self.CP = {}
        self.CP['host'] = config.get(section, "host")
        self.CP['port'] = config.get(section, "port")
        self.CP['username'] = config.get(section, "username")
        self.CP['password'] = config.get(section, "password")
        self.CP['apikey'] = config.get(section, "apikey")
        self.CP['delay'] = config.get(section, "delay")
        self.CP['method'] = config.get(section, "method")
        self.CP['web_root'] = config.get(section, "web_root")

        try:
            self.CP['delay'] = float(self.CP['delay'])
        except ValueError:
            self.CP['delay'] = 60
        try:
            self.CP['delete_failed'] = config.getboolean(section, "delete_failed")
        except (configparser.NoOptionError, ValueError):
            self.CP['delete_failed'] = False
        try:
            if config.getboolean(section, 'ssl'):
                self.CP['protocol'] = "https://"
            else:
                self.CP['protocol'] = "http://"
        except (configparser.NoOptionError, ValueError):
            self.CP['protocol'] = "http://"

        # Read relevant uTorrent section information
        section = "uTorrent"
        self.uTorrent = {}
        self.uTorrent['cp'] = config.get(section, "couchpotato-label").lower()
        self.uTorrent['sb'] = config.get(section, "sickbeard-label").lower()
        self.uTorrent['sr'] = config.get(section, "sickrage-label").lower()
        self.uTorrent['sonarr'] = config.get(section, "sonarr-label").lower()
        self.uTorrent['bypass'] = config.get(section, "bypass-label").lower()
        try:
            self.uTorrent['convert'] = config.getboolean(section, "convert")
        except:
            self.uTorrent['convert'] = False
        self.uTorrentWebUI = config.getboolean(section, "webui")
        self.uTorrentActionBefore = config.get(section, "action_before").lower()
        self.uTorrentActionAfter = config.get(section, "action_after").lower()
        self.uTorrentHost = config.get(section, "host").lower()
        self.uTorrentUsername = config.get(section, "username")
        self.uTorrentPassword = config.get(section, "password")

        # Read relevant Deluge section information
        section = "Deluge"
        self.deluge = {}
        self.deluge['cp'] = config.get(section, "couchpotato-label").lower()
        self.deluge['sb'] = config.get(section, "sickbeard-label").lower()
        self.deluge['sr'] = config.get(section, "sickrage-label").lower()
        self.deluge['sonarr'] = config.get(section, "sonarr-label").lower()
        self.deluge['bypass'] = config.get(section, "bypass-label").lower()
        try:
            self.deluge['convert'] = config.getboolean(section, "convert")
        except:
            self.deluge['convert'] = False
        self.deluge['host'] = config.get(section, "host").lower()
        self.deluge['port'] = config.get(section, "port")
        self.deluge['user'] = config.get(section, "username")
        self.deluge['pass'] = config.get(section, "password")

        # Read relevant Sonarr section information
        section = "Sonarr"
        self.Sonarr = {}
        self.Sonarr['host'] = config.get(section, "host")
        self.Sonarr['port'] = config.get(section, "port")
        self.Sonarr['apikey'] = config.get(section, "apikey")
        self.Sonarr['ssl'] = config.get(section, "ssl")
        self.Sonarr['web_root'] = config.get(section, "web_root")

        # Read Sickbeard section information
        section = "SickBeard"
        self.Sickbeard = {}
        self.Sickbeard['host'] = config.get(section, "host")  # Server Address
        self.Sickbeard['port'] = config.get(section, "port")  # Server Port
        self.Sickbeard['api_key'] = config.get(section, "api_key")  # Sickbeard API key
        self.Sickbeard['web_root'] = config.get(section, "web_root")  # Sickbeard webroot
        self.Sickbeard['ssl'] = config.getboolean(section, "ssl")  # SSL
        self.Sickbeard['user'] = config.get(section, "username")
        self.Sickbeard['pass'] = config.get(section, "password")

        # Read Sickrage section information
        section = "Sickrage"
        self.Sickrage = {}
        self.Sickrage['host'] = config.get(section, "host")  # Server Address
        self.Sickrage['port'] = config.get(section, "port")  # Server Port
        self.Sickrage['api_key'] = config.get(section, "api_key")  # Sickbeard API key
        self.Sickrage['web_root'] = config.get(section, "web_root")  # Sickbeard webroot
        self.Sickrage['ssl'] = config.getboolean(section, "ssl")  # SSL
        self.Sickrage['user'] = config.get(section, "username")
        self.Sickrage['pass'] = config.get(section, "password")

        # Read SAB section information
        section = "SABNZBD"
        self.SAB = {}
        try:
            self.SAB['convert'] = config.getboolean(section, "convert")  # Convert
        except:
            self.SAB['convert'] = False
        self.SAB['cp'] = config.get(section, "Couchpotato-category").lower()
        self.SAB['sb'] = config.get(section, "Sickbeard-category").lower()
        self.SAB['sr'] = config.get(section, "Sickrage-category").lower()
        self.SAB['sonarr'] = config.get(section, "Sonarr-category").lower()
        self.SAB['bypass'] = config.get(section, "Bypass-category").lower()

        # Read Plex section information
        section = "Plex"
        self.Plex = {}
        self.Plex['host'] = config.get(section, "host")
        self.Plex['port'] = config.get(section, "port")
        try:
            self.Plex['refresh'] = config.getboolean(section, "refresh")
        except:
            self.Plex['refresh'] = False
        self.Plex['token'] = config.get(section, "token")
        if self.Plex['token'] == '':
            self.Plex['token'] = None

        # Pass the values on
        self.config = config
        self.configFile = configFile
def log():
    return LoggingAdapter.getLogger(__name__)