コード例 #1
0
class Users(object):
    def __init__(self):
        self.logger = logging.getLogger('modules.users')
        Manageusers.createTable(ifNotExists=True)
        htpc.MODULES.append({
            'name': 'Manage users',
            'description': '<div class="alert alert-block alert-danger"><i class="fa fa-exclamation-triangle fa-fw"></i> Make sure you enable authentication and provide a master username and password in General settings, otherwise authentication will not be used.</div>',
            'isThirdParty': False,
            'id': 'users',
            'action': htpc.WEBDIR + 'users/setusers',
            'fields': [
                {'type': 'select',
                 'label': 'User',
                 'name': 'users_user_id',
                 'options': [{'name': 'New', 'value': 0}]
                },
                {'type': 'text',
                 'label': 'Username',
                 'name': 'users_user_username'},
                {'type': 'password',
                 'label': 'Password',
                 'name': 'users_user_password'},
                {'type': 'select',
                 'label': 'Role',
                 'name': 'users_user_role',
                 'desc': 'Admin users can change settings whilst normal users can only view pages.',
                 'options': [
                        {'name': 'restricted user', 'value': 'restricted_user'},
                        {'name': 'user', 'value': 'user'},
                        {'name': 'admin', 'value': 'admin'}
                    ]
                }
            ]
        })

    @cherrypy.expose()
    @require(member_of(htpc.role_admin))
    def setusers(self, users_user_id, users_user_username, users_user_password, users_user_role):
        if users_user_id == "0":
            self.logger.debug('Creating Manage users in db')
            try:
                Manageusers(username=users_user_username,
                            password=users_user_password,
                            role=users_user_role)

                htpc.BLACKLISTWORDS.append(users_user_password)
                return 'hack'

            except Exception, e:
                self.logger.debug('Failed to create %s %s' % (users_user_username, e))
                return
        else:
コード例 #2
0
ファイル: users.py プロジェクト: znedw/HTPC-Manager
class Users:
    def __init__(self):
        self.logger = logging.getLogger('modules.users')
        Manageusers.createTable(ifNotExists=True)
        htpc.MODULES.append({
            'name':
            'Manage users',
            'description':
            'Add more users to HTPC-Manager. Make sure you enable authentication and have provided a master username and password in General settings, otherwise authentication will not be used.',
            'isThirdParty':
            False,
            'id':
            'users',
            'action':
            htpc.WEBDIR + 'users/setusers',
            'fields': [{
                'type': 'select',
                'label': 'User',
                'name': 'users_user_id',
                'options': [{
                    'name': 'New',
                    'value': 0
                }]
            }, {
                'type': 'text',
                'label': 'Username',
                'name': 'users_user_username'
            }, {
                'type': 'password',
                'label': 'Password',
                'name': 'users_user_password'
            }, {
                'type':
                'select',
                'label':
                'Role',
                'name':
                'users_user_role',
                'desc':
                'Admin users can change settings while normal users can only view pages.',
                'options': [{
                    'name': 'user',
                    'value': 'user'
                }, {
                    'name': 'admin',
                    'value': 'admin'
                }]
            }]
        })

    @cherrypy.expose()
    @require(member_of("admin"))
    def index(self):
        return htpc.LOOKUP.get_template('manageusers.html').render(
            scriptname='manageusers')

    @cherrypy.expose()
    @require(member_of("admin"))
    def setusers(self, users_user_id, users_user_username, users_user_password,
                 users_user_role):
        if users_user_id == "0":
            self.logger.debug('Creating Manage users in db')
            try:
                Manageusers(username=users_user_username,
                            password=users_user_password,
                            role=users_user_role)
                return 'hack'
            except Exception, e:
                self.logger.debug('Failed to create %s %s' %
                                  (users_user_username, e))
                return
        else:
コード例 #3
0
ファイル: users.py プロジェクト: znedw/HTPC-Manager
                return
        else:
            try:
                users = Manageusers.selectBy(
                    username=users_user_username).getOne()
                users.username = users_user_username
                users.password = users_user_password
                users.role = users_user_role
                return 'hack'
            except SQLObjectNotFound, e:
                self.logger.debug('Failed to update username on %s' %
                                  users_user_username)
                return

    @cherrypy.expose()
    @require(member_of("admin"))
    @cherrypy.tools.json_out()
    def getuser(self, id=None):
        if id:
            """ Get user info, used by settings """
            try:
                user = Manageusers.selectBy(id=id).getOne()
                return dict(
                    (c, getattr(user, c)) for c in user.sqlmeta.columns)
            except SQLObjectNotFound:
                return
        """ Get a list of all users"""
        users = []
        for s in Manageusers.select():
            users.append({'id': s.id, 'name': s.username})
        if len(users) < 1:
コード例 #4
0
class Mylar(object):
    def __init__(self):
        self.logger = logging.getLogger('modules.mylar')
        htpc.MODULES.append({
            'name':
            'Mylar',
            'id':
            'mylar',
            'test':
            htpc.WEBDIR + 'mylar/ping',
            'fields': [{
                'type': 'bool',
                'label': 'Enable',
                'name': 'mylar_enable'
            }, {
                'type': 'text',
                'label': 'Menu name',
                'name': 'mylar_name'
            }, {
                'type': 'text',
                'label': 'IP / Host *',
                'name': 'mylar_host'
            }, {
                'type': 'text',
                'label': 'Port *',
                'name': 'mylar_port'
            }, {
                'type': 'text',
                'label': 'Basepath',
                'name': 'mylar_basepath'
            }, {
                'type': 'text',
                'label': 'API key',
                'name': 'mylar_apikey'
            }, {
                'type': 'bool',
                'label': 'Use SSL',
                'name': 'mylar_ssl'
            }, {
                "type": "text",
                "label": "Reverse proxy link",
                "placeholder": "",
                "desc": "Reverse proxy link ex: https://hp.domain.com",
                "name": "mylar_reverse_proxy_link"
            }]
        })

    @cherrypy.expose()
    @require()
    def index(self):
        template = htpc.LOOKUP.get_template('mylar.html')
        settings = htpc.settings

        return template.render(scriptname='mylar',
                               url=Mylar.webinterface(),
                               name=settings.get('mylar_name', 'mylar'))

    @cherrypy.expose()
    @require()
    def GetThumb(self, url=None, thumb=None, h=None, w=None, o=100):
        """ Parse thumb to get the url and send to htpc.proxy.get_image """
        self.logger.debug("Trying to fetch image via %s", url)
        if url is None and thumb is None:
            # To stop if the image is missing
            return
        # Should never used thumb, to lazy to remove it
        if thumb:
            url = thumb
        return get_image(url, h, w, o)

    @cherrypy.expose()
    @require()
    def viewcomic(self, artist_id):
        response = self.fetch('getComic&id=%s' % artist_id)

        for a in response['comic']:
            a['StatusText'] = _get_status_icon(a['Status'])
            a['can_download'] = True if a['Status'] not in (
                'Downloaded', 'Snatched', 'Wanted') else False

        template = htpc.LOOKUP.get_template('mylar_view_comic.html')
        return template.render(scriptname='mylar_view_comic',
                               comic_id=artist_id,
                               comic=response['comic'][0],
                               comicimg=response['comic'][0]['ComicImageURL'],
                               issues=response['issues'],
                               description=response['comic'][0]['Description'],
                               module_name=htpc.settings.get(
                                   'mylar_name', 'Mylar'))

    @staticmethod
    def _build_url(ssl=None, host=None, port=None, base_path=None):
        ssl = ssl or htpc.settings.get('mylar_ssl')
        host = host or htpc.settings.get('mylar_host')
        port = port or htpc.settings.get('mylar_port')
        path = fix_basepath(htpc.settings.get('mylar_basepath', '/'))

        url = '{protocol}://{host}:{port}{path}'.format(
            protocol='https' if ssl else 'http',
            host=host,
            port=port,
            path=path,
        )

        return url

    @staticmethod
    def webinterface():
        url = Mylar._build_url()

        if htpc.settings.get('mylar_reverse_proxy_link'):
            url = htpc.settings.get('mylar_reverse_proxy_link')

        return url

    @staticmethod
    def _build_api_url(command, url=None, api_key=None):
        return '{url}api?apikey={api_key}&cmd={command}'.format(
            url=url or Mylar._build_url(),
            api_key=api_key or htpc.settings.get('mylar_apikey'),
            command=command,
        )

    @cherrypy.expose()
    @cherrypy.tools.json_out()
    @require()
    def getserieslist(self):
        return self.fetch('getIndex')

    @cherrypy.expose()
    @cherrypy.tools.json_out()
    @require()
    def GetWantedList(self):
        return self.fetch('getWanted')

    @cherrypy.expose()
    @cherrypy.tools.json_out()
    @require()
    def SearchForComic(self, name):
        return self.fetch('findComic&%s' % urlencode(
            {'name': name.encode(encoding='UTF-8', errors='strict')}))

    @cherrypy.expose()
    @require()
    def RefreshComic(self, Id):
        return self.fetch('refreshComic&id=%s' % Id, text=True)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    def DeleteComic(self, Id):
        return self.fetch('delComic&id=%s' % Id, text=True)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    def PauseComic(self, Id):
        return self.fetch('pauseComic&id=%s' % Id, text=True)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    def ResumeComic(self, Id):
        return self.fetch('resumeComic&id=%s' % Id, text=True)

    @cherrypy.expose()
    @require()
    def QueueIssue(self, issueid=None, new=False, **kwargs):
        # Force check
        if new:
            return self.fetch('queueIssue&id=%s&new=True' % issueid, text=True)
        return self.fetch('queueIssue&id=%s' % issueid, text=True)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    def UnqueueIssue(self, issueid, name=''):
        self.logger.debug('unqued %s' % name)
        return self.fetch('unqueueIssue&id=%s' % issueid, text=True)

    @cherrypy.expose()
    @require()
    def DownloadIssue(self, issueid, name=''):
        """ downloads a issue via api and returns it to the browser """
        self.logger.debug('Downloading issue %s' % name)
        getfile = self.fetch('downloadIssue&id=%s' % issueid, img=True)
        try:
            with closing(StringIO()) as f:
                f = StringIO()
                f.write(getfile)
                return cherrypy.lib.static.serve_fileobj(
                    f.getvalue(),
                    content_type='application/x-download',
                    disposition=None,
                    name=name,
                    debug=False)
        except Exception as e:
            self.logger.error('Failed to download %s %s %s' %
                              (name, issueid, e))

    @cherrypy.expose()
    @cherrypy.tools.json_out()
    @require()
    def AddComic(self, id, **kwargs):
        self.logger.debug('Added %s to mylar' % kwargs.get('name', ''))
        return self.fetch('addComic&id=%s' % id)

    @cherrypy.expose()
    @cherrypy.tools.json_out()
    @require()
    def GetHistoryList(self):
        return self.fetch('getHistory')

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    def ForceSearch(self):
        return self.fetch('forceSearch', text=True)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    def ForceProcess(self, dir_=None):
        if dir_:
            return self.fetch('forceProcess?dir_=%s' % dir_, text=True)
        return self.fetch('forceProcess', text=True)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    def ForceActiveArtistsUpdate(self):
        return self.fetch('forceActiveComicsUpdate', text=True)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    def ShutDown(self):
        return self.fetch('shutdown', text=True)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    def UpDate(self):
        return self.fetch('update', text=True)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    def ReStart(self):
        return self.fetch('restart', text=True)

    def fetch(self,
              command,
              url=None,
              api_key=None,
              img=False,
              json=True,
              text=False):
        url = Mylar._build_api_url(command, url, api_key)

        try:
            if img or text:
                json = False
            result = ''
            self.logger.debug('calling api @ %s' % url)
            # set a high timeout as some requests take a while..
            response = requests.get(url, timeout=120, verify=False)

            if response.status_code != 200:
                self.logger.error('failed to contact mylar')
                return

            if text:
                result = response.text

            if img:
                result = response.content

            if json:
                result = response.json()

            #self.logger.debug('Response: %s' % result)
            return result

        except Exception as e:
            self.logger.error("Error calling api %s: %s" % (url, e))

    @cherrypy.tools.json_out()
    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    def ping(self,
             mylar_enable,
             mylar_name,
             mylar_host,
             mylar_port,
             mylar_basepath,
             mylar_apikey,
             mylar_ssl=False,
             mylar_reverse_proxy_link=None):

        url = Mylar._build_url(
            mylar_ssl,
            mylar_host,
            mylar_port,
            mylar_basepath,
        )

        return self.fetch('getVersion', url, mylar_apikey)
コード例 #5
0
class Stats:
    def __init__(self):
        self.logger = logging.getLogger('modules.stats')
        htpc.MODULES.append({
            'name':
            'Computer stats',
            'id':
            'stats',
            'fields': [{
                'type': 'bool',
                'label': 'Enable',
                'name': 'stats_enable'
            }, {
                'type': 'text',
                'label': 'Menu name',
                'name': 'stats_name'
            }, {
                'type': 'bool',
                'label': 'Bar',
                'name': 'stats_use_bars'
            }, {
                'type': 'text',
                'label': 'Ignore filesystem',
                'placeholder': 'NTFS FAT32',
                'desc':
                'Write the filesystems you want to ignore. Serperate with whitespace',
                'name': 'stats_ignore_filesystem'
            }, {
                'type': 'text',
                'label': 'Ignore mountpoint',
                'placeholder': 'mountpoint1 mountpoint2',
                'desc':
                'Write the mountpoints that you want to ignore.Seperate with whitepace',
                'name': 'stats_ignore_mountpoint'
            }, {
                'type': 'text',
                'label': 'Limit processes',
                'placeholder': '50',
                'desc': 'Blank for all processes',
                'name': 'stats_limit_processes'
            }]
        })

    @cherrypy.expose()
    @require()
    def index(self):
        #Since many linux repos still have psutil version 0.5
        if importPsutil and psutil.version_info >= (0, 7):
            pass
        else:
            self.logger.error("Psutil is outdated, needs atleast version 0,7")

        return htpc.LOOKUP.get_template('stats.html').render(
            scriptname='stats', importPsutil=importPsutil, cmdline=htpc.SHELL)

    @cherrypy.expose()
    @require()
    def uptime(self):
        try:
            if psutil.version_info >= (2, 0, 0):
                b = psutil.boot_time()
            else:
                b = psutil.get_boot_time()
            d = {}
            boot = datetime.now() - datetime.fromtimestamp(b)
            boot = str(boot)
            uptime = boot[:-7]
            d['uptime'] = uptime
            return json.dumps(d)
        except Exception as e:
            self.logger.error("Could not get uptime %s" % e)

    @cherrypy.expose()
    @require()
    def disk_usage(self):
        rr = None
        l = []

        #Mount point that should be ignored, (Linux) Let me know if there is any missing
        ignore_mntpoint = [
            '', '/dev/shm', '/lib/init/rw', '/sys/fs/cgroup', '/boot'
        ]

        #File systems that should be ignored
        ignore_fstypes = [
            'autofs', 'binfmt_misc', 'configfs', 'debugfs', 'devfs', 'devpts',
            'devtmpfs', 'hugetlbfs', 'iso9660', 'linprocfs', 'mqueue', 'none',
            'proc', 'procfs', 'pstore', 'rootfs', 'securityfs', 'sysfs',
            'usbfs', ''
        ]

        #Adds the mointpoints that the user wants to ignore to the list of ignored ignorepoints
        user_ignore_mountpoint = htpc.settings.get('stats_ignore_mountpoint')

        #If user_ignore_mountpoint is a empty string
        if not user_ignore_mountpoint:
            pass
        else:
            ignore_mntpoint += user_ignore_mountpoint.split()

        #Adds the filesystem that the user wants to ignore to the list of ignored filesystem
        user_ignore_filesystem = htpc.settings.get('stats_ignore_filesystem')

        #If user_ignore_filsystem is a empty string
        if not user_ignore_filesystem:
            pass
        else:
            ignore_fstypes += user_ignore_filesystem.split()

        try:

            for disk in psutil.disk_partitions(all=True):

                # To stop windows barf on empy cdrom            #File system that will be ignored  #Mountpoint that should be ignored, linux
                if 'cdrom' in disk.opts or disk.fstype == '' or disk.fstype in ignore_fstypes or disk.mountpoint in ignore_mntpoint:
                    continue

                usage = psutil.disk_usage(disk.mountpoint)
                dusage = usage._asdict()
                dusage['mountpoint'] = disk.mountpoint
                dusage['device'] = disk.device

                #NTFS driver reports filesystem type as fuseblk on Linux
                if disk.fstype == 'fuseblk':
                    dusage['fstype'] = 'NTFS'
                else:
                    dusage['fstype'] = disk.fstype

                l.append(dusage)
                rr = json.dumps(l)

        except Exception as e:
            self.logger.error("Could not get disk info %s" % e)

        return rr

    @cherrypy.expose()
    @require()
    def processes(self):
        rr = None
        limit = str(htpc.settings.get('stats_limit_processes'))
        procs = []
        procs_status = {}
        for p in psutil.process_iter():

            try:
                p.dict = p.as_dict([
                    'username', 'get_memory_percent', 'create_time',
                    'get_cpu_percent', 'name', 'status', 'pid',
                    'get_memory_info'
                ])
                #Create a readable time
                r_time = datetime.now() - datetime.fromtimestamp(
                    p.dict['create_time'])
                r_time = str(r_time)[:-7]
                p.dict['r_time'] = r_time
                try:
                    procs_status[p.dict['status']] += 1
                except KeyError:
                    procs_status[p.dict['status']] = 1
            except psutil.NoSuchProcess:
                pass
            else:
                procs.append(p.dict)

        # return processes sorted by CPU percent usage
        processes = sorted(procs, key=lambda p: p['cpu_percent'], reverse=True)

        #Adds the total number of processes running, not in use atm
        processes.append(procs_status)

        #if limit is a empty string
        if not limit:
            rr = json.dumps(processes)
        else:
            rr = json.dumps(processes[:int(limit)])

        return rr

    #Returns cpu usage
    @cherrypy.expose()
    @require()
    def cpu_percent(self):
        jcpu = None
        try:
            cpu = psutil.cpu_times_percent(interval=0.4, percpu=False)
            cpu = cpu._asdict()
            jcpu = json.dumps(cpu)
            return jcpu
        except Exception as e:
            self.logger.error("Error trying to pull cpu percent: %s" % e)

    # Not in use atm.
    @cherrypy.expose()
    @require()
    def cpu_times(self):
        rr = None
        try:
            cpu = psutil.cpu_times(percpu=False)
            dcpu = cpu._asdict()
            rr = json.dumps(dcpu)
            return rr
        except Exception as e:
            self.logger.error("Error trying to pull cpu times: %s" % e)

    #Not in use
    @cherrypy.expose()
    @require()
    def num_cpu(self):
        try:
            if psutil.version_info >= (2, 0, 0):
                cpu = psutil.cpu_count(logical=False)
            else:
                cpu = psutil.NUM_CPUS
            dcpu = cpu._asdict()
            jcpu = json.dumps(dcpu)
            return jcpu
        except Exception as e:
            self.logger.error("Error trying to pull cpu cores %s" % e)

    #Fetches info about the user that is logged in.
    @cherrypy.expose()
    @require()
    def get_user(self):
        l = []
        d = {}
        rr = None
        try:
            for user in psutil.get_users():
                duser = user._asdict()
                td = datetime.now() - datetime.fromtimestamp(duser['started'])
                td = str(td)
                td = td[:-7]
                duser['started'] = td
                rr = json.dumps(duser)
            return rr

        except Exception as e:
            self.logger.error("Pulling logged in info %s" % e)
        return rr

    @cherrypy.expose()
    @require()
    def get_local_ip(self):
        # added a small delay since getting local is faster then network usage (Does not render in the html)
        time.sleep(0.1)
        d = {}
        rr = None
        try:
            ip = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            ip.connect(('8.8.8.8', 80))
            local_ip = (ip.getsockname()[0])
            d['localip'] = local_ip
            rr = json.dumps(d)
            return rr
        except Exception as e:
            self.logger.error("Pulling  local ip %s" % e)

    @cherrypy.expose()
    @require()
    def get_external_ip(self):
        d = {}
        rr = None
        try:
            s = urllib2.urlopen('http://myexternalip.com/raw').read()
            d['externalip'] = s.strip()
            rr = json.dumps(d)
            return rr
        except Exception as e:
            self.logger.error("Pulling external ip %s" % e)

    @cherrypy.expose()
    @require()
    def sys_info(self):
        d = {}
        rr = None
        try:
            computer = platform.uname()
            d['system'] = computer[0]
            d['user'] = computer[1]
            d['release'] = computer[2]
            d['version'] = computer[3]
            d['machine'] = computer[4]
            d['processor'] = computer[5]
            rr = json.dumps(d)
            return rr
        except Exception as e:
            self.logger.error("Pulling system info %s" % e)

    #get network usage
    @cherrypy.expose()
    @require()
    def network_usage(self):

        try:
            nw_psutil = psutil.net_io_counters()
            dnw_psutil = nw_psutil._asdict()

            return json.dumps(dnw_psutil)

        except Exception as e:
            self.logger.error("Pulling network info %s" % e)

    @cherrypy.expose()
    @require()
    def virtual_memory(self):
        d = {}
        rr = None

        try:
            mem = psutil.virtual_memory()
            dmem = mem._asdict()
            rr = json.dumps(dmem)

            return rr

        except Exception as e:
            self.logger.error("Pulling physical memory %s" % e)

    @cherrypy.expose()
    @require()
    def swap_memory(self):
        d = {}
        rr = None

        try:
            mem = psutil.swap_memory()
            dmem = mem._asdict()
            rr = json.dumps(dmem)

            return rr

        except Exception as e:
            self.logger.error("Pulling swap memory %s" % e)

    #Fetches settings in the db, is used for some styling, like bars or tables.
    @cherrypy.expose()
    @require()
    def return_settings(self):
        d = {}
        try:
            if str(htpc.settings.get('stats_use_bars')) == str('False'):
                d['stats_use_bars'] = 'false'
            else:
                d['stats_use_bars'] = 'true'

            d['stats_ignore_mountpoint'] = htpc.settings.get(
                'stats_ignore_mountpoint')
            d['stats_ignore_filesystem'] = htpc.settings.get(
                'stats_ignore_filesystem')

        except Exception as e:
            self.logger.error("Getting stats settings %s" % e)

        return json.dumps(d)

    @cherrypy.expose()
    @require(member_of("admin"))
    def command(self, cmd=None, pid=None, signal=None):
        dmsg = {}
        jmsg = None
        try:
            if pid:
                p = psutil.Process(pid=int(pid))
                name = p.name()
            else:
                pass

            if cmd == 'kill':
                try:
                    p.terminate()
                    dmsg['status'] = 'success'
                    msg = 'Terminated process %s %s' % (name, pid)
                    p.wait()

                except psutil.NoSuchProcess:
                    msg = 'Process %s does not exist' % name

                except psutil.AccessDenied:
                    msg = 'Dont have permission to terminate/kill %s %s' % (
                        name, pid)
                    dmsg['status'] = 'error'

                except psutil.TimeoutExpired:
                    p.kill()
                    dmsg['status'] = 'success'
                    msg = 'Killed process %s %s' % (name, pid)

                dmsg['msg'] = msg
                jmsg = json.dumps(dmsg)
                self.logger.info(msg)
                return jmsg

            elif cmd == 'signal':
                p.send_signal(signal)
                msg = '%ed pid %s successfully with %s' % (cmd, name, pid,
                                                           signal)
                dmsg['msg'] = msg
                jmsg = json.dumps(dmsg)
                self.logger.info(msg)
                return jmsg

        except Exception as e:
            self.logger.error("Error trying to %s" % cmd, e)

    @cherrypy.expose()
    @require(member_of("admin"))
    def cmdpopen(self, cmd=None):
        d = {}
        cmd = cmd.split(', ')

        try:
            if htpc.SHELL:
                r = psutil.Popen(cmd,
                                 stdout=PIPE,
                                 stdin=PIPE,
                                 stderr=PIPE,
                                 shell=False)
                msg = r.communicate()
                d['msg'] = msg
                jmsg = json.dumps(d)
                self.logger.info(msg)
                return jmsg

            else:
                msg = 'HTPC-Manager is not started with --shell'
                self.logger.error(msg)
                d['msg'] = msg
                jmsg = json.dumps(d)
                self.logger.error(msg)
                return jmsg

        except Exception as e:
            self.logger.error('Sending command from stat module failed: %s' %
                              e)
コード例 #6
0
ファイル: sonarr.py プロジェクト: lopezfra/htpcmanager
                    options['ignoreEpisodesWithoutFiles'] = True
                elif monitor == 'latest':
                    season[i['seasonCount']]['monitored'] = True
                elif monitor == 'first':
                    season[1]['monitored'] = True
                elif monitor == 'missing':
                    options['ignoreEpisodesWithFiles'] = True
                elif monitor == 'existing':
                    options['ignoreEpisodesWithoutFiles'] = True
                elif monitor == 'none':
                    season_monitoring = False

                d['seasons'] = season
                d['addOptions'] = options

                self.logger.debug('%s' % dumps(d, indent=4))

            # Manually add correct headers since @cherrypy.tools.json_out() renders it wrong
            cherrypy.response.headers['Content-Type'] = 'application/json'
            return self.fetch('Series', data=d, type='post')

        except Exception, e:
            self.logger.error('Failed to add tvshow %s %s' % (tvdbid, e))

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def test(self):
        tvshow = self.fetch('Series/lookup?term=tvdbid:70327')
        return tvshow
コード例 #7
0
                                    d['url'] = _url
                                    d['resize'] = resize_sizes
                                    imglist.append(d)

        self.logger.debug('Found %s images in total' % len(imglist))

        try:
            if async:
                t = cachedprime(imglist, headers, resize=bool(resize))
                return t

        except Exception as e:
            self.logger.debug('%s' % e)

    @cherrypy.expose()
    @require(member_of(htpc.role_admin))
    @cherrypy.tools.json_out()
    def ping(self, kodi_server_host='', kodi_server_port='',
             kodi_server_username='', kodi_server_password='', **kwargs):
        """ Tests settings, returns MAC address on success and null on fail """
        self.logger.debug("Testing kodi connectivity")
        try:
            url = kodi_server_host + ':' + kodi_server_port
            if kodi_server_username and kodi_server_password:
                url = kodi_server_username + ':' + kodi_server_password + '@' + url
            kodi = Server('http://' + url + '/jsonrpc')
            self.logger.debug("Trying to contact kodi via %s" % url)
            return kodi.XBMC.GetInfoLabels(labels=["Network.MacAddress"])
        except Exception, e:
            self.logger.exception(e)
            self.logger.error("Unable to contact kodi via %s", url)
コード例 #8
0
class NZBGet(object):
    def __init__(self):
        self.logger = logging.getLogger('modules.nzbget')
        htpc.MODULES.append({
            'name':
            'NZBGet',
            'id':
            'nzbget',
            'test':
            htpc.WEBDIR + 'nzbget/version',
            'fields': [
                {
                    'type': 'bool',
                    'label': 'Enable',
                    'name': 'nzbget_enable'
                },
                {
                    'type': 'text',
                    'label': 'Menu name',
                    'name': 'nzbget_name'
                },
                {
                    'type': 'text',
                    'label': 'IP / Host',
                    'placeholder': 'localhost',
                    'name': 'nzbget_host'
                },
                {
                    'type': 'text',
                    'label': 'Port',
                    'placeholder': '6789',
                    'name': 'nzbget_port'
                },
                {
                    'type': 'text',
                    'label': 'Basepath',
                    'placeholder': '/nzbget',
                    'name': 'nzbget_basepath'
                },
                {
                    'type': 'text',
                    'label': 'User',
                    'name': 'nzbget_username'
                },
                {
                    'type': 'password',
                    'label': 'Password',
                    'name': 'nzbget_password'
                },
                {
                    'type': 'bool',
                    'label': 'Use SSL',
                    'name': 'nzbget_ssl'
                },
                {
                    'type': 'text',
                    'label': 'Reverse proxy link',
                    'placeholder': '',
                    'desc':
                    'Reverse proxy link, e.g. https://nzbget.domain.com',
                    'name': 'nzbget_reverse_proxy_link'
                },
            ]
        })

    @cherrypy.expose()
    @require()
    def index(self):
        return htpc.LOOKUP.get_template('nzbget.html').render(
            scriptname='nzbget', webinterface=self.webinterface())

    def nzbget_url(self):
        host = striphttp(htpc.settings.get('nzbget_host', ''))
        port = str(htpc.settings.get('nzbget_port', ''))
        username = htpc.settings.get('nzbget_username', '')
        password = htpc.settings.get('nzbget_password', '')
        nzbget_basepath = fix_basepath(
            htpc.settings.get('nzbget_basepath', '/'))
        ssl = 's' if htpc.settings.get('nzbget_ssl', True) else ''

        if username and password:
            authstring = '%s:%s@' % (username, password)
        else:
            authstring = ''

        url = 'http%s://%s%s:%s%sjsonrpc' % (ssl, authstring, host, port,
                                             nzbget_basepath)
        return url

    def webinterface(self):
        host = striphttp(htpc.settings.get('nzbget_host', ''))
        port = str(htpc.settings.get('nzbget_port', ''))
        username = htpc.settings.get('nzbget_username', '')
        password = htpc.settings.get('nzbget_password', '')
        nzbget_basepath = fix_basepath(
            htpc.settings.get('nzbget_basepath', '/'))
        ssl = 's' if htpc.settings.get('nzbget_ssl', True) else ''

        if username and password:
            authstring = '%s:%s@' % (username, password)
        else:
            authstring = ''

        url = 'http%s://%s%s:%s%s' % (ssl, authstring, host, port,
                                      nzbget_basepath)

        if htpc.settings.get('nzbget_reverse_proxy_link'):
            url = htpc.settings.get('nzbget_reverse_proxy_link')

        return url

    @cherrypy.expose()
    @require(member_of(htpc.role_admin))
    @cherrypy.tools.json_out()
    def version(self,
                nzbget_host,
                nzbget_basepath,
                nzbget_port,
                nzbget_username,
                nzbget_password,
                nzbget_ssl=False,
                **kwargs):
        self.logger.debug("Fetching version information from nzbget")
        ssl = 's' if nzbget_ssl else ''

        nzbget_basepath = fix_basepath(nzbget_basepath)

        url = 'http%s://%s:%s%sjsonrpc/version' % (
            ssl, striphttp(nzbget_host), nzbget_port, nzbget_basepath)
        try:
            if nzbget_username and nzbget_password:
                r = requests.get(url,
                                 timeout=10,
                                 auth=(nzbget_username, nzbget_password))
            else:
                r = requests.get(url, timeout=10)

            return r.json()

        except:
            self.logger.error("Unable to contact nzbget via %s" % url)
            return

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def GetHistory(self):
        try:
            self.logger.debug("Fetching history")
            nzbget = jsonrpc.ServerProxy('%s' % self.nzbget_url())
            return nzbget.history()
        except Exception as e:
            self.logger.error("Failed to get history %s" % e)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def Swap(self, nzbid=None, oldpos=None, newpos=None):
        self.logger.debug('Moving %s from %s to %s' % (nzbid, oldpos, newpos))
        try:
            nzbget = jsonrpc.ServerProxy('%s' % self.nzbget_url())
            relpos = int(newpos) - int(oldpos)
            return nzbget.editqueue("GroupMoveOffset", relpos, "",
                                    [int(nzbid)])
        except Exception as e:
            self.logger.error("Failed to move %s from %s to %s %s" %
                              (nzbid, oldpos, newpos, e))

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def AddNzbFromUrl(self, nzb_url='', nzb_category='', nzb_name='', f=''):
        self.logger.info("Added %s category %s url %s" %
                         (nzb_name, nzb_category, nzb_url))
        r = False
        try:
            nzbget = jsonrpc.ServerProxy('%s' % self.nzbget_url())
            if f:
                # f = nzbfile
                r = nzbget.append(nzb_name, nzb_category, False, f)
            else:
                sess = requests.Session()
                nzb = sess.get(nzb_url, timeout=30)

                if not nzb_name:
                    try:
                        # Try to get the filename from the download
                        # TODO check if x-dnzb-name is on all indexers
                        nzb_name = nzb.headers.get('x-dnzb-name')
                    except Exception as e:
                        self.logger.error('%s' % e)
                        self.logger.debug(
                            'Trying to parse the nzbname from content-disposition'
                        )
                        nzb_name = nzb.headers.get(
                            'content-disposition').split(
                                'filename=')[1].replace('.nzb',
                                                        '').replace('"', '')

                nzb = nzb.content
                r = nzbget.append(nzb_name, nzb_category, False,
                                  base64.standard_b64encode(nzb))

        except Exception as e:
            self.logger.error("Failed to add %s %s to queue %s" %
                              (nzb_name, nzb_url, e))
        return r

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def ForceScan(self):
        self.logger.debug('Scan incoming directory')
        try:
            nzbget = jsonrpc.ServerProxy('%s' % self.nzbget_url())
            return nzbget.scan()
        except Exception as e:
            self.logger.error('Failed while scanning incoming directory %s' %
                              e)

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def GetCategorys(self):
        self.logger.debug('Fetching categories')
        categorys = []
        # Add default category
        categorys.append('')
        try:
            nzbget = jsonrpc.ServerProxy('%s' % self.nzbget_url())
            config = nzbget.config()
            r = re.compile(ur'(Category\d+.name)', re.IGNORECASE)
            for category in config:
                if re.match(r, category['Name']):
                    categorys.append(category['Value'])
        except Exception as e:
            self.logger.error('Failed to fetch categorys %s' % e)

        return categorys

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def ChangeCategory(self, nzbid=None, cat=None, nzbname=None):
        self.logger.debug('Change %s nzbname id %s to category %s' %
                          (nzbname, nzbid, cat))
        r = False
        try:
            nzbget = jsonrpc.ServerProxy('%s' % self.nzbget_url())
            if nzbid and cat:
                r = nzbget.editqueue("GroupSetCategory", 0, cat, [int(nzbid)])
        except Exception as e:
            self.logger.error('Failed to set %s on %s' % (cat, nzbname, e))
        return r

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def GetWarnings(self):
        try:
            self.logger.debug("Fetching warnings")
            nzbget = jsonrpc.ServerProxy('%s' % self.nzbget_url())
            return nzbget.log(0, 1000)
        except Exception as e:
            self.logger.error("Failed to fetch warnings %s" % e)

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def queue(self):
        try:
            self.logger.debug("Fetching queue")
            nzbget = jsonrpc.ServerProxy('%s' % self.nzbget_url())
            return nzbget.listgroups()
        except Exception as e:
            self.logger.error("Failed to fetch queue %s" % e)

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def status(self):
        try:
            self.logger.debug("Fetching status")
            nzbget = jsonrpc.ServerProxy('%s' % self.nzbget_url())
            return nzbget.status()
        except Exception as e:
            self.logger.error("Failed to fetch queue %s" % e)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def QueueAction(self, action):
        try:
            self.logger.debug(action + " ALL")
            nzbget = jsonrpc.ServerProxy('%s' % self.nzbget_url())
            if 'resume' in action:
                status = nzbget.resume()
            elif 'pause' in action:
                status = nzbget.pause()
            return status
        except Exception as e:
            self.logger.error("Failed to %s" % (action, e))

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def IndividualAction(self, nzbid='', name='', action=''):
        try:
            self.logger.debug("%s %s %s" % (action, name, nzbid))
            nzbget = jsonrpc.ServerProxy('%s' % self.nzbget_url())
            if 'resume' in action:
                action = 'GroupResume'
            elif 'pause' in action:
                action = 'GroupPause'
            elif 'delete' in action:
                action = 'GroupDelete'
            elif 'hidehistory' in action:
                action = 'HistoryDelete'
            status = nzbget.editqueue(action, 0, '', [int(nzbid)])
            return status
        except Exception as e:
            self.logger.error("Failed to %s %s %s %s" %
                              (action, name, nzbid, e))
            return False

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def SetSpeed(self, speed):
        try:
            self.logger.debug("Setting speed-limit %s" % speed)
            nzbget = jsonrpc.ServerProxy('%s' % self.nzbget_url())
            return nzbget.rate(int(speed))
        except Exception as e:
            self.logger.error("Failed to set speed to %s %s" % (speed, e))
            return False
コード例 #9
0
class Sabnzbd(object):
    def __init__(self):
        self.logger = logging.getLogger('modules.sabnzbd')
        htpc.MODULES.append({
            'name': 'SABnzbd',
            'id': 'sabnzbd',
            'test': htpc.WEBDIR + 'sabnzbd/version',
            'fields': [
                {'type': 'bool', 'label': 'Enable', 'name': 'sabnzbd_enable'},
                {'type': 'text', 'label': 'Menu name', 'name': 'sabnzbd_name'},
                {'type': 'text', 'label': 'IP / Host', 'placeholder': 'localhost', 'name': 'sabnzbd_host'},
                {'type': 'text', 'label': 'Port', 'placeholder': '8080', 'name': 'sabnzbd_port'},
                {'type': 'text', 'label': 'Basepath', 'name': 'sabnzbd_basepath'},
                {'type': 'text', 'label': 'API key', 'name': 'sabnzbd_apikey'},
                {'type': 'bool', 'label': 'Use SSL', 'name': 'sabnzbd_ssl'},
                {'type': 'text', 'label': 'Reverse proxy link', 'placeholder': '', 'desc': 'Reverse proxy link, e.g. https://sab.domain.com', 'name': 'sabnzbd_reverse_proxy_link'},

            ]
        })

    @cherrypy.expose()
    @require()
    def index(self):
        return htpc.LOOKUP.get_template('sabnzbd.html').render(scriptname='sabnzbd', webinterface=self.webinterface())

    @cherrypy.expose()
    @require(member_of(htpc.role_admin))
    @cherrypy.tools.json_out()
    def version(self, sabnzbd_host, sabnzbd_basepath, sabnzbd_port, sabnzbd_apikey, sabnzbd_ssl=False, **kwargs):
        self.logger.debug('Fetching version information from sabnzbd')
        ssl = 's' if sabnzbd_ssl else ''

        if not sabnzbd_basepath:
            sabnzbd_basepath = '/sabnzbd/'

        sabnzbd_basepath = fix_basepath(sabnzbd_basepath)

        url = 'http%s://%s:%s%sapi?output=json&apikey=%s' % (ssl, striphttp(sabnzbd_host), sabnzbd_port, sabnzbd_basepath, sabnzbd_apikey)

        try:
            return loads(urlopen(url + '&mode=version', timeout=10).read())
        except:
            self.logger.error('Unable to contact sabnzbd via ' + url)
            return

    def webinterface(self):
        host = striphttp(htpc.settings.get('sabnzbd_host', ''))
        port = str(htpc.settings.get('sabnzbd_port', ''))
        basepath = htpc.settings.get('sabnzbd_basepath')
        ssl = 's' if htpc.settings.get('sabnzbd_ssl', 0) else ''

        if not basepath:
            basepath = '/sabnzbd/'

        sabnzbd_basepath = fix_basepath(basepath)

        url = 'http%s://%s:%s%s' % (ssl, host, port, sabnzbd_basepath)

        if htpc.settings.get('sabnzbd_reverse_proxy_link'):
            url = htpc.settings.get('sabnzbd_reverse_proxy_link')

        return url

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def GetHistory(self, limit=''):
        self.logger.debug('Fetching history')
        return self.fetch('&mode=history&limit=' + limit)

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def GetStatus(self):
        self.logger.debug('Fetching queue')
        return self.fetch('&mode=queue')

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def GetWarnings(self):
        self.logger.debug('Fetching warning')
        return self.fetch('&mode=warnings')

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def TogglePause(self, mode='', time=''):
        print mode, time
        if time:
            self.logger.debug('Pausing for %s minutes' % time)
            return self.fetch('&mode=config&name=set_pause&value=' + time)
        return self.fetch('&mode=' + mode)

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def AddNzbFromUrl(self, nzb_url, nzb_category='', nzb_name=''):
        self.logger.debug('Adding nzb from url')
        self.logger.debug('%s %s %s' % (quote(nzb_url), nzb_category, nzb_name))
        if 'api.nzbgeek.info' in nzb_url:
            nzb_url = nzb_url.replace('amp;', '')
        if nzb_category:
            nzb_category = '&cat=' + nzb_category
        return self.fetch('&mode=addurl&name=' + quote(nzb_url) + nzb_category + '&priority=2')

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def DeleteNzb(self, id):
        self.logger.debug('Deleting nzb')
        return self.fetch('&mode=queue&name=delete&value=' + id)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def DeleteHistory(self, id):
        self.logger.debug('Deleting history')
        return self.fetch('&mode=history&name=delete&value=' + id)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def Retry(self, id):
        self.logger.debug('Retry download')
        return self.fetch('&mode=retry&value=' + id)

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def GetCategories(self):
        self.logger.debug('Fetch available categories')
        return self.fetch('&mode=get_cats')

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def ChangeCategory(self, id, cat):
        self.logger.debug('Changing category of download')
        return self.fetch('&mode=change_cat&value=' + id + '&value2=' + cat)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def SetSpeed(self, speed):
        self.logger.debug('Setting speed-limit')
        return self.fetch('&mode=config&name=speedlimit&value=' + speed)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def Swap(self, v1, v2):
        self.logger.debug('Swaping nzb position to %s' % v2)
        return self.fetch('&mode=switch&value=%s&value2=%s' % (v1, v2))

    def fetch(self, path):
        try:
            host = striphttp(htpc.settings.get('sabnzbd_host', ''))
            port = str(htpc.settings.get('sabnzbd_port', ''))
            apikey = htpc.settings.get('sabnzbd_apikey', '')
            sabnzbd_basepath = fix_basepath(htpc.settings.get('sabnzbd_basepath', '/sabnzbd/'))
            ssl = 's' if htpc.settings.get('sabnzbd_ssl', 0) else ''

            url = 'http%s://%s:%s%sapi?output=json&apikey=%s%s' % (ssl, host, port, sabnzbd_basepath, apikey, path)
            self.logger.debug('Fetching information from: %s' % url)
            return loads(urlopen(url, timeout=10).read(), strict=False)
        except Exception as e:
            self.logger.error('Cannot contact sabnzbd %s' % e)
            return
コード例 #10
0
ファイル: log.py プロジェクト: lopezfra/htpcmanager
class Log:
    """ Root class """
    def __init__(self):
        """ Initialize the logger """
        self.logfile = os.path.join(htpc.DATADIR, 'htpcmanager.log')
        htpc.LOGGER = logging.getLogger()

        self.blacklistwords = BlackListFilter()

        # Disable colored stdout by --nocolor
        if htpc.NOCOLOR:
            self.logch = logging.StreamHandler()
        else:
            self.logch = ColorizingStreamHandler(sys.stdout)

        self.logfh = logging.handlers.RotatingFileHandler(self.logfile,
                                                          maxBytes=25000000,
                                                          backupCount=2)

        logformatter = logging.Formatter(
            '%(asctime)s :: %(name)s :: %(levelname)s :: %(message)s',
            "%Y-%m-%d %H:%M:%S")
        self.logch.setFormatter(logformatter)
        self.logfh.setFormatter(logformatter)

        if htpc.LOGLEVEL == 'debug' or htpc.DEV:
            loglevel = logging.DEBUG
        elif htpc.LOGLEVEL == 'info':
            loglevel = logging.INFO
        elif htpc.LOGLEVEL == 'warning':
            loglevel = logging.WARNING
        elif htpc.LOGLEVEL == 'error':
            loglevel = logging.ERROR
        else:
            loglevel = logging.CRITICAL

        self.logch.setLevel(loglevel)
        self.logfh.setLevel(loglevel)
        htpc.LOGGER.setLevel(loglevel)

        self.logch.addFilter(self.blacklistwords)
        self.logfh.addFilter(self.blacklistwords)

        # Disable cherrypy access log
        logging.getLogger('cherrypy.access').propagate = False

        # Disable urllib3 logger, except from criticals
        logging.getLogger("requests").setLevel(logging.CRITICAL)

        # Only show errors for paramiko
        logging.getLogger("paramiko").setLevel(logging.CRITICAL)

        # apscheduler
        # logging.getLogger("apscheduler.scheduler").setLevel(logging.CRITICAL)

        htpc.LOGGER.addHandler(self.logch)
        htpc.LOGGER.addHandler(self.logfh)

        htpc.LOGGER.info("Welcome to Hellowlol's HTPC Manager fork")
        htpc.LOGGER.info("Loglevel set to %s" % htpc.LOGLEVEL)

    @cherrypy.expose()
    @require()
    def index(self):
        """ Show log """
        return htpc.LOOKUP.get_template('log.html').render(scriptname='log')

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def getlog(self, lines=10, level=2):
        """ Get log as JSON """
        levels = ['DEBUG', 'INFO', 'WARNING', 'ERROR',
                  'CRITICAL'][-int(level):]
        content = []
        try:
            for line in reversed(open(self.logfile, 'r').readlines()):
                line = line.split(' :: ')
                if len(line) > 1 and line[2] in levels:
                    content.append(line)
                    if len(content) >= int(lines):
                        break
        except IOError:
            # Can't log this error since there is no log file.
            pass

        return content

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def logit(self, **kw):
        ''' Used to log console errors '''
        self.logger = logging.getLogger('webui.console.errors')
        if kw:
            self.logger.error("%s" % kw)
            return kw

    @cherrypy.expose()
    @cherrypy.tools.json_out()
    @require(member_of(htpc.role_admin))
    def deletelog(self):
        try:
            open(self.logfile, 'w').close()
            return 'Log file deleted'
        except Exception, e:
            return 'Cannot delete log file: %s' % e
コード例 #11
0
class Couchpotato(object):
    def __init__(self):
        self.logger = logging.getLogger('modules.couchpotato')
        htpc.MODULES.append({
            'name': 'CouchPotato',
            'id': 'couchpotato',
            'test': htpc.WEBDIR + 'couchpotato/getapikey',
            'fields': [
                {'type': 'bool', 'label': 'Enable', 'name': 'couchpotato_enable'},
                {'type': 'text', 'label': 'Menu name', 'name': 'couchpotato_name'},
                {'type': 'text', 'label': 'Username', 'name': 'couchpotato_username'},
                {'type': 'password', 'label': 'Password', 'name': 'couchpotato_password'},
                {'type': 'text', 'label': 'IP / Host *', 'name': 'couchpotato_host'},
                {'type': 'text', 'label': 'Port', 'placeholder': '5050', 'name': 'couchpotato_port'},
                {'type': 'text', 'label': 'Basepath', 'placeholder': '/couchpotato', 'name': 'couchpotato_basepath'},
                {'type': 'text', 'label': 'API key', 'desc': 'Press test get apikey', 'name': 'couchpotato_apikey'},
                {'type': 'bool', 'label': 'Use SSL', 'name': 'couchpotato_ssl'},
                {'type': 'text', 'label': 'Reverse proxy link', 'placeholder': '', 'desc': 'Reverse proxy link ex: https://couchpotato.domain.com', 'name': 'couchpotato_reverse_proxy_link'},

            ]
        })

    @cherrypy.expose()
    @require()
    def index(self):
        return htpc.LOOKUP.get_template('couchpotato.html').render(scriptname='couchpotato', webinterface=self.webinterface())

    def webinterface(self):
        ''' Generate page from template '''
        ssl = 's' if htpc.settings.get('couchpotato_ssl', 0) else ''
        host = striphttp(htpc.settings.get('couchpotato_host', ''))
        port = str(htpc.settings.get('couchpotato_port', ''))
        basepath = fix_basepath(htpc.settings.get('couchpotato_basepath', '/'))

        url = 'http%s://%s:%s%s' % (ssl, host, port, basepath)

        if htpc.settings.get('couchpotato_reverse_proxy_link'):
            url = htpc.settings.get('couchpotato_reverse_proxy_link')

        return url

    def ctrl_c(self, filt):
        ctrl_char = ''
        if '!=' in filt:
            ctrl_char = '!='
        elif '==' in filt:
            ctrl_char = '=='
        elif '<=' in filt:
            ctrl_char = '<='
        elif '>=' in filt:
            ctrl_char = '>='
        elif '<=' in filt:
            ctrl_char = '=='
        elif '!' in filt:
            ctrl_char = '!'
        elif '<' in filt:
            ctrl_char = '<'
        elif '>' in filt:
            ctrl_char = '>'
        elif '=' in filt:
            ctrl_char = '='
        return ctrl_char

    def cp_filter(self, filt, collection):
        self.logger.debug('Called cp_filter %s' % filt)
        before = len(collection.get('movies', 0))
        results = []
        if collection.get('movies', ''):
            check = self.ctrl_c(filt)
            if filt:
                # default to fuzzy title search "16 blocks"
                if check == '':
                    pat = '.*?'.join(map(re.escape, filt))
                    regex = re.compile(pat, flags=re.I)
                    for m in collection['movies']:
                        f = regex.search(m['title'])
                        if f:
                            results.append(m)
                else:
                    # default to normal search
                    if check:
                        filt = filt.split(check)

                    for m in collection['movies']:
                        # flatten the info since we would normally be interessed in that
                        if 'info' in m:
                            for k, v in m['info'].iteritems():
                                m[k] = v
                                try:
                                    imdb = m['info']['rating']['imdb']
                                    m['rating'] = imdb[0]
                                except:
                                    pass

                        for k, v in m.iteritems():
                            if k.lower() == filt[0].lower():
                                if isinstance(v, dict):
                                    # actor roles='Jack Bauer'
                                    for kk, vv in v.iteritems():
                                        if v == kk:
                                            results.append(m)
                                elif isinstance(v, list):
                                    # genres=action
                                    if filt[1].lower() in [z.lower() for z in v]:
                                        results.append(m)
                                elif isinstance(v, (int, float)):
                                    # for year!=1337 rating<=5.0
                                    if check and check != '=':
                                        if comp_table[check](float(v), float(filt[1])):
                                            results.append(m)
                                elif isinstance(v, basestring):
                                    # plot='some string'
                                    if filt[1].lower() in v.lower():
                                        results.append(m)

                self.logger.debug('Filter out %s' % (before - len(results)))
                return results

    @cherrypy.expose()
    @require(member_of(htpc.role_admin))
    @cherrypy.tools.json_out()
    def ping(self, couchpotato_host, couchpotato_port, couchpotato_apikey, couchpotato_basepath, couchpotato_ssl=False, **kwargs):
        self.logger.debug('Testing connectivity to couchpotato')

        couchpotato_basepath = fix_basepath(couchpotato_basepath)
        couchpotato_host = striphttp(couchpotato_host)

        ssl = 's' if couchpotato_ssl else ''
        url = 'http%s://%s:%s%sapi/%s' % (ssl, couchpotato_host, couchpotato_port, couchpotato_apikey)
        try:
            f = requests.get(url + '/app.available/', timeout=10)
            return f.json()
        except:
            self.logger.error('Unable to connect to couchpotato')
            self.logger.debug('connection-URL: %s' % url)
            return

    @cherrypy.expose()
    @require(member_of(htpc.role_admin))
    @cherrypy.tools.json_out()
    def getapikey(self, couchpotato_username, couchpotato_password, couchpotato_host, couchpotato_port, couchpotato_apikey, couchpotato_basepath, couchpotato_ssl=False, **kwargs):
        self.logger.debug('Testing connectivity to couchpotato')
        if couchpotato_password and couchpotato_username != '':
            couchpotato_password = hashlib.md5(couchpotato_password).hexdigest()
            couchpotato_username = hashlib.md5(couchpotato_username).hexdigest()

        getkey = 'getkey/?p=%s&u=%s' % (couchpotato_password, couchpotato_username)

        couchpotato_basepath = fix_basepath(couchpotato_basepath)

        ssl = 's' if couchpotato_ssl else ''
        url = 'http%s://%s:%s%s%s' % (ssl, striphttp(couchpotato_host), couchpotato_port, couchpotato_basepath, getkey)

        try:
            f = requests.get(url, timeout=10, verify=False)
            return f.json()

        except Exception as e:
            self.logger.error('Unable to connect to couchpotato %s' % e)
            self.logger.debug('connection-URL: %s' % url)
            return

    @cherrypy.expose()
    @require()
    def GetImage(self, url, h=None, w=None, o=100, *args, **kwargs):
        # url can be a string or json
        working_url = None
        imgdir = os.path.join(htpc.DATADIR, 'images/')
        try:
            x = json.loads(url)
            if isinstance(x, list):
                tl = [(hashlib.md5(u).hexdigest(), u) for u in x]
                checkurl = []
                # check any of the images exist in the cache
                for i in tl:
                    if os.path.isfile(os.path.join(imgdir, i[0])):
                        #self.logger.debug('%s exist in cache, ignore the rest of the hashes %s' % (str(i[1]), str(tl)))
                        # dont bother checking any else if we have image
                        checkurl = []
                        working_url = i[1]
                        break
                    else:
                        checkurl.append(i)
                        continue

                if working_url:
                    return get_image(working_url, h, w, o)
                else:
                    # None of the imges existed in the cache
                    if checkurl:
                        for ii, i in enumerate(checkurl):
                            # verify that the download is ok before we try to cache it.
                            try:
                                r = requests.get(i[1], headers={'Cache-Control': 'private, max-age=0, no-cache, must-revalidate', 'Pragma': 'no-cache'})
                                if r.content:
                                    working_url = i[1]
                                    break

                            except Exception as e:
                                self.logger.error('Error: %s url: %s item: %s  loop n : %s  tuplelist %s' % (e, i[1], i, ii, str(tl)))

                        if working_url:
                            return get_image(working_url, h, w, o)

        except ValueError as e:
            if isinstance(url, basestring):
                return get_image(url, h, w, o)

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def GetMovieList(self, status='', limit='', f=''):
        self.logger.debug('Fetching Movies')
        if status == 'done':
            status += '&type=movie&release_status=done&status_or=1'
            data = self.fetch('media.list/?status=' + status)
            if f:
                filtered_movies = self.cp_filter(f, data)
                data['movies'] = filtered_movies
                data['total'] = len(filtered_movies)
                return data
            else:
                return data

        data = self.fetch('media.list/?status=' + status + '&limit_offset=' + limit)
        if f:
            filtered_movies = self.cp_filter(f, data)
            data['movies'] = filtered_movies
            data['total'] = len(filtered_movies)
            return data
        else:
            return data

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def GetNotificationList(self, limit='20'):
        self.logger.debug('Fetching Notification')
        data = self.fetch('notification.list/?limit_offset=' + limit)
        self.fetch('notification.markread')
        return data

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def SearchMovie(self, q=''):
        self.logger.debug('Searching for movie')
        return self.fetch('movie.search/?q=' + q)

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def AddMovie(self, movieid, profile, title, category_id=''):
        self.logger.debug('Adding movie')
        if category_id:
            return self.fetch('movie.add/?profile_id=' + profile + '&identifier=' + movieid + '&title=' + title + '&category_id=' + category_id)
        return self.fetch('movie.add/?profile_id=' + profile + '&identifier=' + movieid + '&title=' + title)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def EditMovie(self, id, profile, title):
        self.logger.debug('Editing movie')
        return self.fetch('movie.edit/?id=' + id + '&profile_id=' + profile + '&default_title=' + title)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def RefreshMovie(self, id):
        self.logger.debug('Refreshing movie')
        return self.fetch('movie.refresh/?id=' + id)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def DeleteMovie(self, id=''):
        self.logger.debug('Deleting movie')
        return self.fetch('movie.delete/?id=' + id)

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def GetReleases(self, id=''):
        self.logger.debug('Downloading movie')
        return self.fetch('media.get/?id=' + id)

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def DownloadRelease(self, id=''):
        self.logger.debug('Downloading movie')
        return self.fetch('release.manual_download/?id=' + id)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def IgnoreRelease(self, id=''):
        self.logger.debug('Downloading movie')
        return self.fetch('release.ignore/?id=' + id)

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def GetProfiles(self):
        self.logger.debug('Fetching available profiles')
        return self.fetch('profile.list/')

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def GetCategories(self):
        self.logger.debug('Feching categories')
        return self.fetch('category.list')

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def Suggestion(self):
        self.logger.debug('Fetching suggestion')
        return self.fetch('suggestion.view')

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def ChartsView(self):
        self.logger.debug('Fetching charts')
        return self.fetch('charts.view')

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def SuggestionIgnore(self, imdb=None, seenit=None):
        u = 'suggestion.ignore/?imdb=%s' % imdb
        if seenit:
            u += '&seenit=1'
        self.logger.debug('Fetching suggestion')
        return self.fetch(u)

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def DashboardSoon(self):
        return self.fetch('dashboard.soon')

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def Restart(self):
        return self.fetch('app.restart')

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def Shutdown(self):
        return self.fetch('app.shutdown')

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def Update(self):
        return self.fetch('updater.update')

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def SearchAllWanted(self):
        return self.fetch('movie.searcher.full_search')

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def Postprocess(self, path=''):
        u = 'renamer.scan'
        if path:
            u += '/?base_folder=%s' % path
        return self.fetch(u)

    def fetch(self, path):
        try:
            host = striphttp(htpc.settings.get('couchpotato_host', ''))
            port = str(htpc.settings.get('couchpotato_port', ''))
            apikey = htpc.settings.get('couchpotato_apikey', '')
            basepath = fix_basepath(htpc.settings.get('couchpotato_basepath', '/'))
            ssl = 's' if htpc.settings.get('couchpotato_ssl', 0) else ''

            url = 'http%s://%s:%s%sapi/%s/%s' % (ssl, host, port, basepath, apikey, path)
            self.logger.debug('Fetching information from: %s' % url)

            f = requests.get(url, timeout=60, verify=False)

            return f.json()

        except Exception as e:
            self.logger.debug('Exception: %s' % e)
            self.logger.error('Unable to fetch information')
            return
コード例 #12
0
class Qbittorrent(object):
    session = requests.Session()

    def __init__(self):
        self.logger = logging.getLogger('modules.qbittorrent')
        self.newapi = False
        self.authenticated = False
        self.testapi = None
        htpc.MODULES.append({
            'name':
            'qBittorrent',
            'id':
            'qbittorrent',
            'test':
            htpc.WEBDIR + 'qbittorrent/ping',
            'fields': [
                {
                    'type': 'bool',
                    'label': 'Enable',
                    'name': 'qbittorrent_enable'
                },
                {
                    'type': 'text',
                    'label': 'Menu name',
                    'name': 'qbittorrent_name'
                },
                {
                    'type': 'text',
                    'label': 'IP / Host',
                    'placeholder': 'localhost',
                    'name': 'qbittorrent_host'
                },
                {
                    'type': 'text',
                    'label': 'Port',
                    'placeholder': '8080',
                    'name': 'qbittorrent_port'
                },
                {
                    'type': 'text',
                    'label': 'Username',
                    'name': 'qbittorrent_username'
                },
                {
                    'type': 'password',
                    'label': 'Password',
                    'name': 'qbittorrent_password'
                },
                {
                    'type': 'bool',
                    'label': 'Use SSL',
                    'name': 'qbittorrent_ssl'
                },
                {
                    'type': 'text',
                    'label': 'Reverse proxy link',
                    'placeholder': '',
                    'desc': 'Reverse proxy link ex: https://qbt.domain.com',
                    'name': 'qbittorrent_reverse_proxy_link'
                },
            ]
        })

    @cherrypy.expose()
    @require()
    def index(self):
        return htpc.LOOKUP.get_template('qbittorrent.html').render(
            scriptname='qbittorrent', webinterface=self.webinterface())

    def webinterface(self):
        host = striphttp(htpc.settings.get('qbittorrent_host', ''))
        port = htpc.settings.get('qbittorrent_port', '')
        ssl = 's' if htpc.settings.get('qbittorrent_ssl', 0) else ''
        url = 'http%s://%s:%s/' % (ssl, host, port)
        if htpc.settings.get('qbittorrent_reverse_proxy_link'):
            url = htpc.settings.get('qbittorrent_reverse_proxy_link')
        return url

    def qbturl(self):
        host = striphttp(htpc.settings.get('qbittorrent_host', ''))
        port = htpc.settings.get('qbittorrent_port', '')
        ssl = 's' if htpc.settings.get('qbittorrent_ssl', 0) else ''
        url = 'http%s://%s:%s/' % (ssl, host, port)
        return url

    @cherrypy.expose()
    @require()
    def login(self):
        self.logger.debug('Trying to login to qbittorrent')
        try:
            d = {
                'username': htpc.settings.get('qbittorrent_username', ''),
                'password': htpc.settings.get('qbittorrent_password', '')
            }
            # F33d da cookie monster
            r = self.session.post(self.qbturl() + 'login',
                                  data=d,
                                  verify=False,
                                  timeout=5)
            if r.content == 'Ok.':
                self.logger.debug('Successfully logged in with new api')
                self.authenticated = True
                self.newapi = True
            else:
                self.logger.error('Check your username and password')
            return r.content
        except Exception as e:
            self.logger.error('Failed to auth with new api %s' % e)
            return

    def _fetch(self, u, post=False, params={}, data=None):
        host = striphttp(htpc.settings.get('qbittorrent_host', ''))
        port = htpc.settings.get('qbittorrent_port', '')
        ssl = 's' if htpc.settings.get('qbittorrent_ssl') else ''
        url = 'http%s://%s:%s/' % (ssl, host, port)
        username = htpc.settings.get('qbittorrent_username', '')
        password = htpc.settings.get('qbittorrent_password', '')

        url += u

        if self.testapi is None:
            self.ping()

        if self.newapi:
            if self.authenticated is False:
                self.login()

        if post:
            if self.newapi:
                r = self.session.post(url, data=data, verify=False, timeout=8)
            else:
                r = self.session.post(url,
                                      data=data,
                                      verify=False,
                                      timeout=8,
                                      auth=HTTPDigestAuth(username, password))
        else:
            if self.newapi:
                r = self.session.get(url, verify=False, timeout=8)
            else:
                r = self.session.get(url,
                                     verify=False,
                                     timeout=8,
                                     auth=HTTPDigestAuth(username, password))

        return r

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def fetch(self):
        try:
            if self.newapi:
                result = self._fetch(
                    'query/torrents?filter=all&sort=size&reverse=false')
                torrents = result.json()
                l = []
                for torrent in torrents:
                    t = {}
                    for k, v in torrent.items():
                        t[k] = v
                        if k == 'size':
                            t['size'] = sizeof(int(v))
                        if k == 'eta':
                            eta = time.strftime('%H:%M:%S', time.gmtime(v))
                            if eta == '00:00:00':
                                eta = u'\u221E'
                            t['eta'] = eta
                        if k == 'ratio':
                            t['ratio'] = math.ceil(v)
                    l.append(t)

                return l
            else:
                result = self._fetch('json/torrents')
                # r.json() does not like the infinity
                return json.loads(result.content)

        except Exception as e:
            self.logger.error("Couldn't get torrents %s" % e)

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def get_speed(self):
        ''' Get total download and upload speed '''
        try:
            d = {}
            if not self.newapi:
                result = self._fetch('json/transferInfo/')
                result = result.json()

                speeddown = result['dl_info']
                speedup = result['up_info']

                list_of_down = speeddown.split()
                list_of_up = speedup.split()

                ds = list_of_down[1] + ' ' + list_of_down[2]
                dlstat = list_of_down[5] + ' ' + list_of_down[6]
                us = list_of_up[1] + ' ' + list_of_up[2]
                ulstat = list_of_down[5] + ' ' + list_of_down[6]

                d = {
                    'qbittorrent_speed_down': ds,
                    'qbittorrent_speed_up': us,
                    'qbittorrent_total_dl': dlstat,
                    'qbittorrent_total_ul': ulstat
                }
            else:
                # new api stuff
                result = self._fetch('query/transferInfo')
                result = result.json()

                d = {
                    'qbittorrent_speed_down': sizeof(result['dl_info_speed']),
                    'qbittorrent_speed_up': sizeof(result['up_info_speed']),
                    'qbittorrent_total_dl': sizeof(result['dl_info_data']),
                    'qbittorrent_total_ul': sizeof(result['up_info_data'])
                }

            return d

        except Exception as e:
            self.logger.error(
                "Couldn't get total download and uploads speed %s" % e)

    def get_global_dl_limit(self):
        try:
            result = self._fetch('command/getGlobalDlLimit/')
            speed = int(result.content)
            speed /= 1024
            return speed
        except Exception as e:
            self.logger.error("Couldn't get global download limit %s" % e)

    def get_global_ul_limit(self):
        try:
            result = self._fetch('command/getGlobalUpLimit')

            speed = int(result.content)
            speed /= 1024
            return speed
        except Exception as e:
            self.logger.error("Couldn't get global upload limit %s" % e)

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def get_global_limit(self):
        try:
            d = {}
            d['dl_limit'] = self.get_global_dl_limit()
            d['ul_limit'] = self.get_global_ul_limit()
            return d
        except Exception as e:
            self.logger.debug(
                "Couldn't get global upload and download limits %s" % e)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    def command(self, cmd=None, hash=None, name=None, dlurl=None):
        ''' Handles pause, resume, delete singel torrents '''
        try:
            self.logger.debug('%s %s' % (cmd, name))
            data = {}

            if cmd == 'delete':
                data['hashes'] = hash

            elif cmd == 'download':
                data['urls'] = dlurl

            elif cmd == 'resumeall' or cmd == 'pauseall':
                # this does not work, bug in qbt see
                # https://github.com/qbittorrent/qBittorrent/issues/3016
                if self.newapi:
                    cmd = cmd[:-3] + 'All'

            else:
                data['hash'] = hash

            url = 'command/%s' % cmd

            # data is form encode..
            r = self._fetch(url, post=True, data=data)
            return r.content

        except Exception as e:
            self.logger.error('Failed at %s %s %s %s' % (cmd, name, hash, e))

    @cherrypy.expose()
    @require()
    def to_client(self, link, torrentname, **kwargs):
        ''' Is used by torrent search '''
        try:
            url = 'command/download/'
            data = {}
            data['urls'] = link
            return self._fetch(url, data=data, post=True)
            self.logger.info('%s %s is sendt to qBittorrent' %
                             (torrentname, link))
        except Exception as e:
            self.logger.error('Failed to send %s %s to qBittorrent %s' %
                              (link, torrentname, e))

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    def set_speedlimit(self, type=None, speed=None):
        ''' Sets global upload and download speed '''
        try:
            self.logger.debug('Setting %s to %s' % (type, speed))
            speed = int(speed)

            if speed == 0:
                speed = 0
            else:
                speed = speed * 1024

            url = 'command/' + type + '/'

            data = {}
            data['limit'] = speed

            r = self._fetch(url, data=data, post=True)
            return r.content

        except Exception as e:
            self.logger.error('Failed to set %s to %s %s' % (type, speed, e))

    @cherrypy.expose()
    @require()  # leave it as it uses this is get api version
    @cherrypy.tools.json_out()
    def ping(self,
             qbittorrent_host='',
             qbittorrent_port='',
             qbittorrent_username='',
             qbittorrent_password='',
             qbittorrent_ssl=False,
             **kw):
        self.logger.debug('Trying to connect to qBittorret')
        host = qbittorrent_host or htpc.settings.get('qbittorrent_host')
        port = qbittorrent_port or htpc.settings.get('qbittorrent_port')
        username = qbittorrent_username or htpc.settings.get(
            'qbittorrent_username')
        password = qbittorrent_password or htpc.settings.get(
            'qbittorrent_password')
        ssl = 's' if qbittorrent_ssl or htpc.settings.get(
            'qbittorrent_ssl') else ''

        url = 'http%s://%s:%s/' % (ssl, host, port)

        self.newapi = False
        self.authenticated = False
        try:
            # We assume that its atleast 3.2 if this works.
            r = requests.get(url + 'version/api', timeout=8, verify=False)
            self.logger.debug('Trying to connect with new API %s' % r.url)
            # Old api returns a empty page
            if r.content != '' and r.ok:
                self.newapi = r.content
                self.testapi = True
                return r.content
            else:
                raise requests.ConnectionError

        except Exception as e:
            self.logger.debug(
                'Failed to figure out what api version, trying old API')
            try:
                r = requests.post(url + 'json/torrents',
                                  auth=HTTPDigestAuth(username, password),
                                  timeout=10,
                                  verify=False)
                if r.ok:
                    self.logger.debug('Old API works %s' % r.url)
                    # Disable new api stuff
                    self.testapi = True
                    self.newapi = False
                    self.authenticated = False

            except Exception as e:
                self.newapi = False
                self.authenticated = False
                self.logger.debug(
                    'Failed to contact qBittorrent via old and newapi')
                self.logger.error(
                    'Cant contact qBittorrent, check you settings and try again %s'
                    % e)
コード例 #13
0
class Headphones(object):
    def __init__(self):
        self.logger = logging.getLogger('modules.headphones')
        htpc.MODULES.append({
            'name':
            'Headphones',
            'id':
            'headphones',
            'test':
            htpc.WEBDIR + 'headphones/ping',
            'fields': [{
                'type': 'bool',
                'label': 'Enable',
                'name': 'headphones_enable'
            }, {
                'type': 'text',
                'label': 'Menu name',
                'name': 'headphones_name'
            }, {
                'type': 'text',
                'label': 'IP / Host *',
                'name': 'headphones_host'
            }, {
                'type': 'text',
                'label': 'Port *',
                'name': 'headphones_port'
            }, {
                'type': 'text',
                'label': 'Basepath',
                'name': 'headphones_basepath'
            }, {
                'type': 'text',
                'label': 'API key',
                'name': 'headphones_apikey'
            }, {
                'type': 'bool',
                'label': 'Use SSL',
                'name': 'headphones_ssl'
            }, {
                'type': 'text',
                "label": 'Reverse proxy link',
                'placeholder': '',
                'desc': 'Reverse proxy link ex: https://domain.com/hp',
                'name': 'headphones_reverse_proxy_link'
            }]
        })

    @cherrypy.expose()
    @require()
    def index(self):
        template = htpc.LOOKUP.get_template('headphones.html')
        settings = htpc.settings

        return template.render(scriptname='headphones',
                               settings=settings,
                               url=self.webinterface(),
                               name=settings.get('headphones_name',
                                                 'Headphones'))

    def webinterface(self):
        url = Headphones._build_url()
        if htpc.settings.get('headphones_reverse_proxy_link'):
            url = htpc.settings.get('headphones_reverse_proxy_link')
        return url

    @cherrypy.expose()
    @require()
    def GetThumb(self, url=None, thumb=None, h=None, w=None, o=100):
        """ Parse thumb to get the url and send to htpc.proxy.get_image """
        self.logger.debug("Trying to fetch image via %s" % url)
        if url is None and thumb is None:
            # To stop if the image is missing
            return
        # Should never used thumb, to lazy to remove it
        if thumb:
            url = thumb
        return get_image(url, h, w, o)

    @cherrypy.expose()
    @require()
    def viewArtist(self, artist_id):
        response = self.fetch('getArtist&id=%s' % artist_id)

        for a in response['albums']:
            a['StatusText'] = _get_status_icon(a['Status'])
            a['can_download'] = True if a['Status'] not in (
                'Downloaded', 'Snatched', 'Wanted') else False
            a['can_skip'] = True if a['Status'] not in ('Downloaded',
                                                        'Snatched',
                                                        'Skipped') else False
            a['can_trynew'] = True if a['Status'] in ('Snatched') else False

        template = htpc.LOOKUP.get_template('headphones_view_artist.html')

        return template.render(
            scriptname='headphones_view_artist',
            artist_id=artist_id,
            artist=response['artist'][0],
            artistimg=response['artist'][0]['ArtworkURL'],
            albums=response['albums'],
            description=response['description'][0],
            module_name=htpc.settings.get('headphones_name') or 'Headphones',
        )

    @cherrypy.expose()
    @require()
    def viewAlbum(self, album_id):
        response = self.fetch('getAlbum&id=%s' % album_id)

        tracks = response['tracks']
        for t in tracks:
            duration = t['TrackDuration']
            total_seconds = duration / 1000
            minutes = total_seconds / 60
            seconds = total_seconds - (minutes * 60)
            t['DurationText'] = '%d:%02d' % (minutes, seconds)
            t['TrackStatus'] = _get_status_icon(
                'Downloaded' if t['Location'] is not None else '')

        template = htpc.LOOKUP.get_template('headphones_view_album.html')
        return template.render(scriptname='headphones_view_album',
                               artist_id=response['album'][0]['ArtistID'],
                               album_id=album_id,
                               albumimg=response['album'][0]['ArtworkURL'],
                               module_name=htpc.settings.get(
                                   'headphones_name', 'Headphones'),
                               album=response['album'][0],
                               tracks=response['tracks'],
                               description=response['description'][0])

    @staticmethod
    def _build_url(ssl=None, host=None, port=None, base_path=None):
        ssl = ssl or htpc.settings.get('headphones_ssl')
        host = host or htpc.settings.get('headphones_host')
        port = port or htpc.settings.get('headphones_port')
        base_path = base_path or htpc.settings.get('headphones_basepath')

        path = base_path or '/'
        if path.startswith('/') is False:
            path = '/' + path
        if path.endswith('/') is False:
            path += '/'

        url = '{protocol}://{host}:{port}{path}'.format(
            protocol='https' if ssl else 'http',
            host=striphttp(host),
            port=port,
            path=path,
        )

        return url

    @staticmethod
    def _build_api_url(command, url=None, api_key=None):
        return '{url}api?apikey={api_key}&cmd={command}'.format(
            url=url or Headphones._build_url(),
            api_key=api_key or htpc.settings.get('headphones_apikey'),
            command=command,
        )

    @cherrypy.expose()
    @cherrypy.tools.json_out()
    @require()
    def GetArtistList(self):
        return self.fetch('getIndex')

    @cherrypy.expose()
    @cherrypy.tools.json_out()
    @require()
    def GetWantedList(self):
        return self.fetch('getWanted')

    @cherrypy.expose()
    @cherrypy.tools.json_out()
    @require()
    def GetUpcomingList(self):
        return self.fetch('getUpcoming')

    @cherrypy.expose()
    @cherrypy.tools.json_out()
    @require()
    def SearchForArtist(self, name, searchtype):
        if searchtype == "artistId":
            return self.fetch('findArtist&%s' % urlencode(
                {'name': name.encode(encoding='UTF-8', errors='strict')}))
        else:
            return self.fetch('findAlbum&%s' % urlencode(
                {'name': name.encode(encoding='UTF-8', errors='strict')}))

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    def RefreshArtist(self, artistId):
        return self.fetch('refreshArtist&id=%s' % artistId, text=True)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    def DeleteArtist(self, artistId):
        return self.fetch('delArtist&id=%s' % artistId, text=True)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    def PauseArtist(self, artistId):
        return self.fetch('pauseArtist&id=%s' % artistId, text=True)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    def ResumeArtist(self, artistId):
        return self.fetch('resumeArtist&id=%s' % artistId, text=True)

    @cherrypy.expose()
    @require()
    def QueueAlbum(self, albumId, new=False):
        # == Force check
        if new:
            return self.fetch('queueAlbum&id=%s&new=True' % albumId, text=True)
        return self.fetch('queueAlbum&id=%s' % albumId, text=True)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    def UnqueueAlbum(self, albumId):
        return self.fetch('unqueueAlbum&id=%s' % albumId, text=True)

    @cherrypy.expose()
    @cherrypy.tools.json_out()
    @require()
    def AddArtist(self, id, searchtype, **kwargs):
        if searchtype == "artistId":
            return self.fetch('addArtist&id=%s' % id)
        else:
            return self.fetch('addAlbum&id=%s' % id)

    @cherrypy.expose()
    @cherrypy.tools.json_out()
    @require()
    def GetHistoryList(self):
        return self.fetch('getHistory')

    @cherrypy.expose()
    @require()
    def GetAlbumArt(self, id):
        return self.fetch('getAlbumArt&id=%s' % id, img=True)

    @cherrypy.expose()
    @require()
    def GetAlbum(self, id):
        return self.fetch('getAlbum&id=%s' % id)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    def ForceSearch(self):
        return self.fetch('forceSearch', text=True)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    def ForceProcess(self, dir=None):
        if dir:
            return self.fetch('forceProcess?dir=%s' % dir, text=True)
        return self.fetch('forceProcess', text=True)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    def ForceActiveArtistsUpdate(self):
        return self.fetch('forceActiveArtistsUpdate', text=True)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    def ShutDown(self):
        return self.fetch('shutdown', text=True)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    def UpDate(self):
        return self.fetch('update', text=True)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    def ReStart(self):
        return self.fetch('restart', text=True)

    @cherrypy.expose()
    @cherrypy.tools.json_out()
    @require()
    def Choose_Specific_Download(self, id):
        return self.fetch('choose_specific_download&id=%s' % id)

    @cherrypy.expose()
    @cherrypy.tools.json_out()
    @require()
    def Download_Specific_Release(self, id, title, size, url, provider, kind):
        return self.fetch(
            'download_specific_release&id=%s&title=%s&size=%s&url=%s&provider=%s&kind=%s'
            % (id, title, size, url, provider, kind))

    def fetch(self,
              command,
              url=None,
              api_key=None,
              img=False,
              json=True,
              text=False):
        url = Headphones._build_api_url(command, url, api_key)

        try:
            # So shitty api..
            if img or text:
                json = False
            result = ''
            self.logger.debug('calling api @ %s' % url)
            response = requests.get(url, timeout=30, verify=False)

            if response.status_code != 200:
                response.raise_for_status()
                self.logger.error('failed to contact headphones')
                return

            if text:
                result = response.text

            if img:
                result = response.content

            if json:
                result = response.json()

            self.logger.debug('Response: %s' % result)

            return result

        except Exception as e:
            self.logger.error("Error calling api %s: %s" % (url, e))

    @cherrypy.expose()
    @cherrypy.tools.json_out()
    @require()
    def ping(self,
             headphones_enable,
             headphones_name,
             headphones_host,
             headphones_port,
             headphones_basepath,
             headphones_apikey,
             headphones_ssl=False,
             **kwargs):

        self.logger.debug('Attemping to ping headphones')

        url = Headphones._build_url(
            headphones_ssl,
            headphones_host,
            headphones_port,
            headphones_basepath,
        )

        return self.fetch('getVersion', url, headphones_apikey)
コード例 #14
0
ファイル: settings.py プロジェクト: znedw/HTPC-Manager
class Settings:
    """ Main class """
    def __init__(self):
        """ Create table on load if table doesnt exist """
        self.logger = logging.getLogger('htpc.settings')
        self.logger.debug('Connecting to database: ' + htpc.DB)
        sqlhub.processConnection = connectionForURI('sqlite:' + htpc.DB)
        Setting.createTable(ifNotExists=True)

    @cherrypy.expose()
    @require(member_of("admin"))
    def index(self, **kwargs):
        """ Set keys if settings are received. Show settings page """
        if kwargs:
            for key, val in kwargs.items():
                self.set(key, val)
        return htpc.LOOKUP.get_template('settings.html').render(
            scriptname='settings', htpc=htpc)

    def get(self, key, defval=''):
        """ Get a setting from the database """
        try:
            val = Setting.selectBy(key=key).getOne().val
            if val == 'on':
                return True
            elif val == "0":
                return False
            return val
        except SQLObjectNotFound:
            self.logger.debug("Unable to find the selected object: " + key)
            return defval

    def set(self, key, val):
        """ Save a setting to the database """
        self.logger.debug("Saving settings to the database.")
        try:
            setting = Setting.selectBy(key=key).getOne()
            setting.val = val
        except SQLObjectNotFound:
            Setting(key=key, val=val)

    def get_templates(self):
        """ Get a list of available templates """
        templates = []
        for template in os.listdir(os.path.join(htpc.RUNDIR, "interfaces/")):
            current = bool(template == self.get('app_template', 'default'))
            templates.append({
                'name': template,
                'value': template,
                'selected': current
            })
        return templates

    def get_themes(self):
        """ Get a list of available themes """
        path = os.path.join(htpc.TEMPLATE, "css/themes/")
        themes = []
        dirs = [
            d for d in os.listdir(path) if os.path.isdir(os.path.join(path, d))
        ]
        for theme in dirs:
            current = bool(theme == self.get('app_theme', 'default'))
            themes.append({'name': theme, 'value': theme, 'selected': current})
        return themes

    """ Save json with custom urls """

    @cherrypy.expose()
    @require(member_of("admin"))
    @cherrypy.tools.json_out()
    def urls(self, **kwargs):
        if kwargs:
            for key, val in kwargs.items():
                self.set('custom_urls', key)

    """ Get custom defined urls from database in json format """

    def getUrls(self):
        links = self.get('custom_urls', '{}')
        return loads(links)
コード例 #15
0
class Sickbeard(object):
    def __init__(self):
        self.logger = logging.getLogger('modules.sickbeard')
        htpc.MODULES.append({
            'name':
            'Sick Beard',
            'id':
            'sickbeard',
            'test':
            htpc.WEBDIR + 'sickbeard/ping',
            'fields': [
                {
                    'type': 'bool',
                    'label': 'Enable',
                    'name': 'sickbeard_enable'
                },
                {
                    'type': 'text',
                    'label': 'Menu name',
                    'name': 'sickbeard_name'
                },
                {
                    'type': 'text',
                    'label': 'IP / Host',
                    'placeholder': 'localhost',
                    'name': 'sickbeard_host'
                },
                {
                    'type': 'text',
                    'label': 'Port',
                    'placeholder': '8081',
                    'name': 'sickbeard_port'
                },
                {
                    'type': 'text',
                    'label': 'Basepath',
                    'placeholder': '/sickbeard',
                    'name': 'sickbeard_basepath'
                },
                {
                    'type': 'text',
                    'label': 'API key',
                    'name': 'sickbeard_apikey'
                },
                {
                    'type': 'bool',
                    'label': 'Use SSL',
                    'name': 'sickbeard_ssl'
                },
                {
                    'type': 'text',
                    'label': 'Reverse proxy link',
                    'placeholder': '',
                    'desc': 'Reverse proxy link ex: https://sb.domain.com',
                    'name': 'sickbeard_reverse_proxy_link'
                },
            ]
        })

    @cherrypy.expose()
    @require()
    def index(self):
        return htpc.LOOKUP.get_template('sickbeard.html').render(
            scriptname='sickbeard', webinterface=self.webinterface())

    def webinterface(self):
        ''' Generate page from template '''
        ssl = 's' if htpc.settings.get('sickbeard_ssl', 0) else ''
        host = striphttp(htpc.settings.get('sickbeard_host', ''))
        port = str(htpc.settings.get('sickbeard_port', ''))
        basepath = fix_basepath(htpc.settings.get('sickbeard_basepath', '/'))

        url = 'http%s://%s:%s%s' % (ssl, host, port, basepath)

        if htpc.settings.get('sickbeard_reverse_proxy_link'):
            url = htpc.settings.get('sickbeard_reverse_proxy_link')

        return url

    @cherrypy.expose()
    @require()
    def view(self, tvdbid):
        if not (tvdbid.isdigit()):
            raise cherrypy.HTTPError('500 Error', 'Invalid show ID.')
            self.logger.error('Invalid show ID was supplied: ' + str(tvdbid))
            return False

        return htpc.LOOKUP.get_template('sickbeard_view.html').render(
            scriptname='sickbeard_view', tvdbid=tvdbid)

    @cherrypy.expose()
    @require(member_of(htpc.role_admin))
    @cherrypy.tools.json_out()
    def ping(self,
             sickbeard_host,
             sickbeard_port,
             sickbeard_apikey,
             sickbeard_basepath,
             sickbeard_ssl=False,
             **kwargs):
        self.logger.info('Testing connectivity')
        ssl = 's' if sickbeard_ssl else ''
        if not sickbeard_basepath:
            sickbeard_basepath = fix_basepath(sickbeard_basepath)

        url = 'http%s://%s:%s%sapi/%s/?cmd=sb.ping' % (
            ssl, striphttp(sickbeard_host), sickbeard_port, sickbeard_basepath,
            sickbeard_apikey)
        try:
            self.logger.debug('Trying to contact sickbeard via %s' % url)
            response = requests.get(url, timeout=10, verify=False)
            r = response.json()

            if r.get('result') == 'success':
                self.logger.debug('Sicbeard connectivity test success')
                return r
        except:
            self.logger.error('Unable to contact sickbeard via %s' % url)
            return

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def GetShowList(self):
        self.logger.debug('Fetching Show list')
        return self.fetch('shows&sort=name')

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def GetNextAired(self):
        self.logger.debug('Fetching Next Aired Episodes')
        return self.fetch('future')

    @cherrypy.expose()
    @require()
    def GetBanner(self, tvdbid):
        self.logger.debug('Fetching Banner')
        cherrypy.response.headers['Content-Type'] = 'image/jpeg'
        return self.fetch('show.getbanner&tvdbid=' + tvdbid, True)

    @cherrypy.expose()
    @require()
    def GetPoster(self, tvdbid):
        self.logger.debug('Fetching Poster')
        cherrypy.response.headers['Content-Type'] = 'image/jpeg'
        return self.fetch('show.getposter&tvdbid=' + tvdbid, True)

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def GetHistory(self, limit=''):
        self.logger.debug('Fetching History')
        return self.fetch('history&limit=' + limit)

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def GetLogs(self):
        self.logger.debug('Fetching Logs')
        return self.fetch('logs&min_level=info')

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def AddShow(self, tvdbid):
        self.logger.debug('Adding a Show')
        return self.fetch('show.addnew&tvdbid=' + tvdbid)

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def GetShow(self, tvdbid):
        self.logger.debug('Fetching Show')
        return self.fetch('show&tvdbid=' + tvdbid)

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def GetEpisode(self, strShowID, strSeason, strEpisode):
        return self.fetch('episode&tvdbid=' + strShowID + '&season=' +
                          strSeason + '&episode=' + strEpisode +
                          '&full_path=1')

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def GetSeason(self, tvdbid, season):
        self.logger.debug('Fetching Season')
        return self.fetch('show.seasons&tvdbid=' + tvdbid + '&season=' +
                          season)

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def SearchEpisodeDownload(self, tvdbid, season, episode):
        self.logger.debug('Fetching Episode Downloads')
        return self.fetch(
            'episode.search&tvdbid=' + tvdbid + '&season=' + season +
            '&episode=' + episode, False, 45)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def ForceFullUpdate(self, tvdbid):
        self.logger.debug('Force full update for tvdbid ' + tvdbid)
        return self.fetch('show.update&tvdbid=' + tvdbid)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def RescanFiles(self, tvdbid):
        self.logger.debug('Rescan all local files for tvdbid ' + tvdbid)
        return self.fetch('show.refresh&tvdbid=' + tvdbid)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def RemoveShow(self, tvdbid):
        self.logger.debug('Removing Show tvdbid ' + tvdbid)
        return self.fetch('show.delete&tvdbid=' + tvdbid)

    @cherrypy.expose()
    @require()
    def SearchShow(self, query):
        try:
            self.logger.debug('Searching thetvdb for %s' % query)
            url = 'http://www.thetvdb.com/api/GetSeries.php?seriesname=' + quote_plus(
                query)
            r = requests.get(url, timeout=10)
            return r.content
        except Exception as e:
            self.logger.error('Failed to fetch info from thetvdb about %s %s' %
                              (query, e))
            return

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    def Postprocess(self, path=''):
        if path:
            path = '&%s' % path

        return self.fetch('postprocess' + path)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    def Shutdown(self):
        self.logger.debug('Shutting down Sickbeard')
        return self.fetch('sb.shutdown')

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    def Restart(self):
        self.logger.debug('Restarting Sickbeard')
        return self.fetch('sb.restart')

    def fetch(self, cmd, img=False, timeout=10):
        try:
            host = htpc.settings.get('sickbeard_host', '')
            port = str(htpc.settings.get('sickbeard_port', ''))
            apikey = htpc.settings.get('sickbeard_apikey', '')
            ssl = 's' if htpc.settings.get('sickbeard_ssl', 0) else ''
            sickbeard_basepath = fix_basepath(
                htpc.settings.get('sickbeard_basepath', '/'))

            url = 'http' + ssl + '://' + host + ':' + str(
                port) + sickbeard_basepath + 'api/' + apikey + '/?cmd=' + cmd

            self.logger.debug('Fetching information from: %s' % url)

            if img is True:
                # Cache image
                return get_image(url)

            r = requests.get(url, timeout=timeout, verify=False)
            if r:
                r = r.json()

            return r
        except:
            self.logger.error('Unable to fetch information')
            return
コード例 #16
0
ファイル: settings.py プロジェクト: lopezfra/htpcmanager
class Settings(object):
    """ Main class """
    def __init__(self):
        """ Create table on load if table doesnt exist """
        self.logger = logging.getLogger('htpc.settings')
        self.logger.debug('Connecting to database: ' + htpc.DB)
        sqlhub.processConnection = connectionForURI('sqlite:' + htpc.DB)
        Setting.createTable(ifNotExists=True)
        self.updatebl()

    @cherrypy.expose()
    @require(member_of("admin"))
    def index(self, **kwargs):
        """ Set keys if settings are received. Show settings page """
        if kwargs:
            for key, val in kwargs.items():
                self.set(key, val)
        return htpc.LOOKUP.get_template('settings.html').render(
            scriptname='settings', htpc=htpc)

    def get(self, key, defval=''):
        """ Get a setting from the database """
        try:
            val = Setting.selectBy(key=key).getOne().val
            if val in ['on', 1, '1']:
                return True
            elif val in ['off', "0", 0]:
                return False
            return val
        except SQLObjectNotFound:
            # Disabled this to not spam the log
            # self.logger.debug("Unable to find the selected object: " + key)
            return defval

    def set(self, key, val):
        """ Save a setting to the database """
        self.logger.debug("Saving settings %s to the database." % key)
        try:
            setting = Setting.selectBy(key=key).getOne()
            setting.val = val
            # each time we save something to the db we want to blacklist it
            self.updatebl()
        except SQLObjectNotFound:
            Setting(key=key, val=val)
            self.updatebl()

    def updatebl(self):
        # fix me
        from modules.newznab import NewznabIndexers
        from modules.kodi import KodiServers
        from htpc.manageusers import Manageusers
        NewznabIndexers.createTable(ifNotExists=True)
        KodiServers.createTable(ifNotExists=True)
        Manageusers.createTable(ifNotExists=True)

        bl = []

        fl = Setting.select().orderBy(Setting.q.key)
        for i in fl:
            if i.key.endswith("_apikey") or i.key.endswith(
                    "_username") or i.key.endswith(
                        "_password") or i.key.endswith("_passkey"):
                if len(i.val) > 1:
                    bl.append(i.val)

        indexers = NewznabIndexers.select().orderBy(NewznabIndexers.q.apikey)
        for indexer in indexers:
            if len(indexer.apikey) > 1:
                bl.append(indexer.apikey)

        kodi = KodiServers.select().orderBy(KodiServers.q.password)
        for k in kodi:
            if len(k.password) > 1:
                bl.append(k.password)

        users = Manageusers.select().orderBy(Manageusers.q.username)
        for user in users:
            if len(user.password) > 1:
                bl.append(user.password)

        htpc.BLACKLISTWORDS = bl
        return bl

    def get_templates(self):
        """ Get a list of available templates """
        templates = []
        for template in os.listdir(os.path.join(htpc.RUNDIR, "interfaces/")):
            current = bool(template == self.get('app_template', 'default'))
            templates.append({
                'name': template,
                'value': template,
                'selected': current
            })
        return templates

    def get_loglvl(self):
        """ Get a list of available templates """
        loglvl = []
        for lvl in ['info', 'debug', 'warning', 'error']:
            current = bool(lvl == self.get('app_loglevel', 'info'))
            loglvl.append({'name': lvl, 'value': lvl, 'selected': current})
        return loglvl

    def get_themes(self):
        """ Get a list of available themes """
        path = os.path.join(htpc.TEMPLATE, "css/themes/")
        themes = []
        dirs = [
            d for d in os.listdir(path) if os.path.isdir(os.path.join(path, d))
        ]
        for theme in dirs:
            current = bool(theme == self.get('app_theme_mig', 'obsidian'))
            themes.append({'name': theme, 'value': theme, 'selected': current})
        return themes

    """ Save json with custom urls """

    @cherrypy.expose()
    @require(member_of("admin"))
    @cherrypy.tools.json_out()
    def urls(self, **kwargs):
        if kwargs:
            for key, val in kwargs.items():
                self.set('custom_urls', key)

    """ Get custom defined urls from database in json format """

    def getUrls(self):
        try:
            links = self.get('custom_urls', '{}')
            return loads(links)
        except:
            # Stop cherrypy from barfing is the user has entered invalid name/urls
            return loads('{}')

    @cherrypy.expose()
    @cherrypy.tools.json_out()
    @require(member_of("admin"))
    def delete_cache(self):
        try:
            cache_folder = os.path.join(htpc.DATADIR, 'images/')
            if os.path.exists(cache_folder):
                self.logger.info('Cache folder was deleted')
                shutil.rmtree(cache_folder)
                return {'success': 'true'}
            return {'failed': 'cache folder does not exist'}
        except Exception as e:
            self.logger.error('Failed to delete cache folder ', e)
            return {'failed': e}

    @cherrypy.expose()
    #@cherrypy.tools.json_out()
    @require(member_of("admin"))
    def test(self, *args, **kw):
        """ Used for testing stuff """
        return 'test'
コード例 #17
0
ファイル: transmission.py プロジェクト: lopezfra/htpcmanager
class Transmission(object):
    # Transmission Session ID
    sessionId = ''
    reqz = requests.Session()

    def __init__(self):
        self.logger = logging.getLogger('modules.transmission')
        htpc.MODULES.append({
            'name':
            'Transmission',
            'id':
            'transmission',
            'test':
            htpc.WEBDIR + 'transmission/ping',
            'fields': [{
                'type': 'bool',
                'label': 'Enable',
                'name': 'transmission_enable'
            }, {
                'type': 'text',
                'label': 'Menu name',
                'name': 'transmission_name'
            }, {
                'type': 'text',
                'label': 'IP / Host',
                'placeholder': 'localhost',
                'name': 'transmission_host'
            }, {
                'type': 'text',
                'label': 'Port',
                'placeholder': '9091',
                'name': 'transmission_port'
            }, {
                'type': 'text',
                'label': 'Reverse Proxy',
                'placeholder': '',
                'name': 'transmission_revproxy'
            }, {
                'type': 'text',
                'label': 'Rpc url',
                'placeholder': '',
                'name': 'transmission_rpcbasepath'
            }, {
                'type': 'text',
                'label': 'Username',
                'name': 'transmission_username'
            }, {
                'type': 'password',
                'label': 'Password',
                'name': 'transmission_password'
            }]
        })

    @cherrypy.expose()
    @require()
    def index(self):
        return htpc.LOOKUP.get_template('transmission.html').render(
            scriptname='transmission')

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def queue(self):
        fields = [
            'id', 'name', 'status', 'comment', 'downloadDir', 'downloadDir',
            'percentDone', 'isFinished', 'eta', 'rateDownload', 'rateUpload',
            'uploadRatio'
        ]
        return self.fetch('torrent-get', {'fields': fields})

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def stats(self):
        return self.fetch('session-stats')

    @cherrypy.expose()
    @require(member_of(htpc.role_admin))
    @cherrypy.tools.json_out()
    def ping(self, **kwargs):
        ''' Test connection to Transmission '''
        host = kwargs['transmission_host']
        port = kwargs['transmission_port']
        username = kwargs['transmission_username']
        password = kwargs['transmission_password']
        basepath = kwargs['transmission_rpcbasepath']
        auth = None

        if not basepath:
            basepath = fix_basepath('/transmission/')
        url = 'http://%s:%s%srpc/' % (striphttp(host), port, basepath)

        # format post data
        data = {'method': 'session-get'}
        data = dumps(data)

        # Set Header
        header = {
            'X-Transmission-Session-Id': self.sessionId,
            'Content-Type': 'json; charset=UTF-8'
        }

        # Add authentication
        if username and password:
            auth = (username, password)

        try:
            r = self.reqz.post(url,
                               data=data,
                               timeout=10,
                               headers=header,
                               auth=auth)
            if r.ok:
                return r.json()
            else:
                if r.status_code == 409 and r.headers[
                        'x-transmission-session-id']:
                    self.logger.debug(
                        'Retry Transmission api with new session id.')
                    res = self.renewsession(url, data, header, auth, r)
                    return res

        except Exception as e:
            self.logger.error('Unable to fetch information from: %s %s' %
                              (url, e))
            return

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def session(self):
        return self.fetch('session-get')

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def set_downspeed(self, speed):
        if int(speed) == 0:
            self.fetch('session-set', {'speed-limit-down': False})
        return self.fetch('session-set', {
            'speed-limit-down': int(speed),
            'speed-limit-down-enabled': True
        })

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def set_upspeed(self, speed):
        if int(speed) == 0:
            self.fetch('session-set', {'speed-limit-up': 'false'})
        else:
            return self.fetch('session-set', {
                'speed-limit-up': int(speed),
                'speed-limit-up-enabled': 'true'
            })

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def start(self, torrentId=False):
        if torrentId is False:
            return self.fetch('torrent-start-now')

        try:
            torrentId = int(torrentId)
        except ValueError:
            return False
        return self.fetch('torrent-start-now', {'ids': torrentId})

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def stop(self, torrentId=False):
        if torrentId is False:
            return self.fetch('torrent-stop')

        try:
            torrentId = int(torrentId)
        except ValueError:
            return False
        return self.fetch('torrent-stop', {'ids': torrentId})

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def Add(self, filename=None, metainfo=None):
        if metainfo:
            return self.fetch('torrent-add', {'metainfo': metainfo})

        return self.fetch('torrent-add', {'filename': filename})

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def remove(self, torrentId):
        try:
            torrentId = int(torrentId)
        except ValueError:
            return False
        return self.fetch('torrent-remove', {'ids': torrentId})

    #For torrent search
    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def to_client(self, link, torrentname, **kwargs):
        try:
            self.logger.info('Added %s to uTorrent' % torrentname)
            return self.fetch('torrent-add', {'filename': link})
        except Exception as e:
            self.logger.debug('Failed to add %s to Transmission %s %s' (
                torrentname, link, e))

    # Wrapper to access the Transmission Api
    # If the first call fails, there probably is no valid Session ID so we try it again
    def fetch(self, method, arguments=''):
        ''' Do request to Transmission api '''
        self.logger.debug('Request transmission method: ' + method)

        host = striphttp(htpc.settings.get('transmission_host', ''))
        port = str(htpc.settings.get('transmission_port', ''))
        basepath = htpc.settings.get('transmission_rpcbasepath')
        username = htpc.settings.get('transmission_username')
        password = htpc.settings.get('transmission_password')

        auth = None

        # Default basepath is transmission
        if not basepath:
            basepath = '/transmission/'

        basepath = fix_basepath(basepath)

        url = 'http://%s:%s%srpc/' % (host, str(port), basepath)

        # format post data
        data = {'method': method}
        if arguments:
            data['arguments'] = arguments
        data = dumps(data)

        # Set Header
        header = {
            'X-Transmission-Session-Id': self.sessionId,
            'Content-Type': 'json; charset=UTF-8'
        }

        if username and password:
            auth = (username, password)

        try:
            r = self.reqz.post(url,
                               data=data,
                               timeout=10,
                               auth=auth,
                               headers=header)
            if r.ok:
                return r.json()
            else:
                if r.status_code == 409 and r.headers[
                        'x-transmission-session-id']:
                    self.renewsession(url, data, header, auth, r)

        except Exception as e:
            self.logger.error('Unable to fetch information from: %s %s %s' %
                              (url, data, e))
            return

    def renewsession(self, url, data, header, auth, r):
        self.logger.debug('Retry Transmission api with new session id.')
        self.sessionId = r.headers['x-transmission-session-id']
        header['X-Transmission-Session-Id'] = self.sessionId
        try:
            r = self.reqz.post(url,
                               data=data,
                               timeout=10,
                               headers=header,
                               auth=auth)
            if r.ok:
                return r.json()
        except Exception as e:
            self.logger.error(
                'Unable access Transmission api with new session id. %s' % e)
コード例 #18
0
ファイル: newznab.py プロジェクト: lopezfra/htpcmanager
class Newznab(object):
    def __init__(self):
        self.logger = logging.getLogger('modules.newznab')
        self.headers = {'User-Agent': 'HTPC-Manager'}
        NewznabIndexers.createTable(ifNotExists=True)
        htpc.MODULES.append({
            'name': 'Newznab',
            'action': htpc.WEBDIR + 'newznab/setindexer',
            'id': 'newznab',
            'fields': [
                {'type': 'bool', 'label': 'Enable', 'name': 'newznab_enable'},
                {'type': 'text', 'label': 'Menu name', 'name': 'newznab_name'},
                {'type': 'bool', 'label': 'Show link in menu', 'name': 'newznab_show_in_menu'},
                {'type': 'select',
                 'label': 'Indexers',
                 'name': 'newznab_indexer_id',
                 'options': [
                        {'name': 'New', 'value': 0}
                    ]
                },
                {'type': 'text', 'label': 'Name', 'name': 'newznab_indexer_name'},
                {'type': 'text', 'label': 'API URL', 'name': 'newznab_indexer_host'},
                {'type': 'text', 'label': 'API KEY', 'name': 'newznab_indexer_apikey'},
                {'type': 'bool', 'label': 'Use SSL', 'name': 'newznab_indexer_ssl'},

            ]
        })
        index = htpc.settings.get('newznab_current_indexer', 0)
        self.changeindexer(index)

    @cherrypy.expose()
    @require()
    def index(self, query='', **kwargs):
        return htpc.LOOKUP.get_template('newznab.html').render(query=query, scriptname='newznab')

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def getindexer(self, id=None):
        if id:
            """ Get NewznabIndexers server info """
            try:
                indexers = NewznabIndexers.selectBy(id=id).getOne()
                return dict((c, getattr(indexers, c)) for c in indexers.sqlmeta.columns)
            except SQLObjectNotFound:
                return

        """ Get a list of all servers and the current server """
        all_indexers = []
        for i in NewznabIndexers.select():
            all_indexers.append({'id': i.id, 'name': i.name})
        if len(all_indexers) < 1:
            return
        try:
            current = self.current.name
        except AttributeError:
            current = None
        return {'current': current, 'indexers': all_indexers}

    @cherrypy.expose()
    @require(member_of("admin"))
    def delindexer(self, id):
        """ Delete a server """
        self.logger.debug("Deleting indexer %s" % id)
        NewznabIndexers.delete(id)
        self.changeindexer()
        return

    @cherrypy.expose()
    @require(member_of(htpc.role_admin))
    @cherrypy.tools.json_out()
    def changeindexer(self, id=0):
        try:
            self.current = NewznabIndexers.selectBy(id=id).getOne()
            htpc.settings.set('newznab_current_indexer', str(id))
            return "success"
        except SQLObjectNotFound:
            try:
                self.current = NewznabIndexers.select(limit=1).getOne()
                self.logger.error("Invalid indexer. Selecting first Available.")
                return "success"
            except SQLObjectNotFound:
                self.current = None
                self.logger.warning("No configured Indexers.")
                return "No valid indexers"

    @cherrypy.tools.json_out()
    @cherrypy.expose()
    @require(member_of(htpc.role_admin))
    def setindexer(self, **kw):
        """
        newznab_enable='',
        newznab_name='',
        newznab_show_in_menu='',
        newznab_indexer_id='',
        newznab_indexer_name='',
        newznab_indexer_host='',
        newznab_indexer_apikey='',
        newznab_indexer_ssl='',
        """
        # kw is empty if kw is predef to ''
        for k, v in kw.items():
            if k not in ('newznab_enable', 'newznab_name', 'newznab_show_in_menu',
                         'newznab_indexer_id', 'newznab_indexer_name',
                         'newznab_indexer_host', 'newznab_indexer_apikey', 'newznab_indexer_ssl'):
                            del kw[k]

            # protection against the hack
            # only allow correct kw be save to db
            if k in ['newznab_enable', 'newznab_name', 'newznab_show_in_menu']:
                htpc.settings.set(k, v)

        # Clean hostname
        host = striphttp(kw.get('newznab_indexer_host')).rstrip('/')

        # make the search url
        ssl = 's' if kw.get('newznab_indexer_ssl') == 'on' else ''

        apiurl = 'http%s://%s/api?o=xml&apikey=%s&t=' % (ssl, host, kw.get('newznab_indexer_apikey'))

        if kw.get('newznab_indexer_id') == "0":
            self.logger.debug("Creating newznab indexer in database")
            try:
                indexer = NewznabIndexers(name=kw.get('newznab_indexer_name'),
                                          host=host,
                                          apikey=kw.get('newznab_indexer_apikey'),
                                          use_ssl=kw.get('newznab_indexer_ssl'),
                                          apiurl=apiurl)

                if kw.get('newznab_indexer_apikey') not in htpc.BLACKLISTWORDS:
                    htpc.BLACKLISTWORDS.append(kw.get('newznab_indexer_apikey'))

                self.changeindexer(indexer.id)
                return 1
            except Exception as e:
                self.logger.debug("Exception: %s" % e)
                self.logger.error("Unable to create newznab indexer in database")
                return 0
        else:
            # Dont allow empty indexer be saved to db
            if host == '':
                self.logger.error('You must provide a url to the indexers %s' % kw.get('newznab_indexer_name', ''))
                return 0
            self.logger.debug("Updating newznab indexer %s in database" % kw.get('newznab_indexer_name'))
            try:
                indexer = NewznabIndexers.selectBy(id=kw.get('newznab_indexer_id')).getOne()
                indexer.name = kw.get('newznab_indexer_name')
                indexer.host = host
                indexer.apikey = kw.get('newznab_indexer_apikey')
                indexer.use_ssl = kw.get('newznab_indexer_ssl', 'on')
                indexer.apiurl = apiurl

                return 1
            except SQLObjectNotFound, e:
                self.logger.error("Unable to update %s in database %s" % (kw.get('newznab_indexer_name'), e))
                return 0
コード例 #19
0
ファイル: users.py プロジェクト: KaHooli/HTPC-Manager
            except Exception, e:
                self.logger.debug('Failed to create %s %s' % (users_user_username, e))
                return
        else:
            try:
                users = Manageusers.selectBy(username=users_user_username).getOne()
                users.username = users_user_username
                users.password = users_user_password
                users.role = users_user_role
                return 'hack'
            except SQLObjectNotFound, e:
                self.logger.debug('Failed to update username on %s' % users_user_username)
                return

    @cherrypy.expose()
    @require(member_of("admin"))
    @cherrypy.tools.json_out()
    def getuser(self, id=None):
        if id:
            """ Get user info, used by settings """
            try:
                user = Manageusers.selectBy(id=id).getOne()
                return dict((c, getattr(user, c)) for c in user.sqlmeta.columns)
            except SQLObjectNotFound:
                return

        """ Get a list of all users"""
        users = []
        for s in Manageusers.select():
            users.append({'id': s.id, 'name': s.username})
        if len(users) < 1:
コード例 #20
0
class Sickrage(object):
    def __init__(self):
        self.logger = logging.getLogger('modules.sickrage')
        htpc.MODULES.append({
            'name': 'Sickrage',
            'id': 'sickrage',
            'test': htpc.WEBDIR + 'sickrage/ping',
            'fields': [
                {'type': 'bool', 'label': 'Enable', 'name': 'sickrage_enable'},
                {'type': 'text', 'label': 'Menu name', 'name': 'sickrage_name'},
                {'type': 'text', 'label': 'IP / Host', 'placeholder': 'localhost', 'name': 'sickrage_host'},
                {'type': 'text', 'label': 'Port', 'placeholder': '8081', 'name': 'sickrage_port'},
                {'type': 'text', 'label': 'Basepath', 'placeholder': '/sickrage', 'name': 'sickrage_basepath'},
                {'type': 'text', 'label': 'API key', 'name': 'sickrage_apikey'},
                {'type': 'bool', 'label': 'Use SSL', 'name': 'sickrage_ssl'},
                {'type': 'text', 'label': 'Reverse proxy link', 'placeholder': '', 'desc':'Reverse proxy link, e.g. https://sr.domain.com', 'name': 'sickrage_reverse_proxy_link'}
            ]
        })

    @cherrypy.expose()
    @require()
    def index(self):
        return htpc.LOOKUP.get_template('sickrage.html').render(scriptname='sickrage', webinterface=self.webinterface())

    def webinterface(self):
        host = striphttp(htpc.settings.get('sickrage_host', ''))
        port = str(htpc.settings.get('sickrage_port', ''))
        apikey = htpc.settings.get('sickrage_apikey', '')
        ssl = 's' if htpc.settings.get('sickrage_ssl', 0) else ''
        sickrage_basepath = fix_basepath(htpc.settings.get('sickrage_basepath', '/'))

        url = 'http%s://%s:%s%s' % (ssl, host, port, sickrage_basepath)

        if htpc.settings.get('sickrage_reverse_proxy_link'):
            url = htpc.settings.get('sickrage_reverse_proxy_link')

        return url

    @cherrypy.expose()
    @require()
    def view(self, indexerid):
        if not (indexerid.isdigit()):
            raise cherrypy.HTTPError('500 Error', 'Invalid show ID.')
            self.logger.error('Invalid show ID was supplied: ' + str(indexerid))
            return False

        return htpc.LOOKUP.get_template('sickrage_view.html').render(scriptname='sickrage_view', indexerid=indexerid)

    @cherrypy.expose()
    @require(member_of(htpc.role_admin))
    @cherrypy.tools.json_out()
    def ping(self, sickrage_host, sickrage_port, sickrage_apikey, sickrage_basepath, sickrage_ssl=False, **kwargs):
        ssl = 's' if sickrage_ssl else ''
        self.logger.debug('Testing connectivity')
        try:
            sickrage_basepath = fix_basepath(sickrage_basepath)

            url = 'http%s://%s:%s%sapi/%s/?cmd=sb.ping' % (ssl, striphttp(sickrage_host), sickrage_port, sickrage_basepath, sickrage_apikey)

            self.logger.debug('Trying to contact sickrage via %s' % url)
            response = requests.get(url, timeout=10, verify=False)
            ret = response.json()
            if ret.get('result') == 'success':
                self.logger.debug('Sickrage connectivity test success')
                return ret
        except:
            self.logger.error('Unable to contact sickrage via %s' % url)
            return

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def GetShowList(self):
        self.logger.debug('Fetching Show list')
        return self.fetch('shows&sort=name', False, 200)

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def GetNextAired(self):
        self.logger.debug('Fetching Next Aired Episodes')
        return self.fetch('future')

    @cherrypy.expose()
    @require()
    def GetBanner(self, indexerid):
        self.logger.debug('Fetching Banner')
        cherrypy.response.headers['Content-Type'] = 'image/jpeg'
        return self.fetch('show.getbanner&indexerid=' + indexerid, True)

    @cherrypy.expose()
    @require()
    def GetPoster(self, indexerid):
        self.logger.debug('Fetching Poster')
        cherrypy.response.headers['Content-Type'] = 'image/jpeg'
        return self.fetch('show.getposter&indexerid=' + indexerid, True)

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def GetHistory(self, limit=''):
        self.logger.debug('Fetching History')
        return self.fetch('history&limit=' + limit)

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def GetLogs(self):
        self.logger.debug('Fetching Logs')
        return self.fetch('logs&min_level=info')

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def AddShow(self, indexername='', indexerid='', **kwargs):
        # indexername=tvrageid or tvdbid
        self.logger.debug('Adding a Show')
        return self.fetch('show.addnew&' + urlencode(kwargs))

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def GetShow(self, indexerid):
        self.logger.debug('Fetching Show')
        return self.fetch('show&indexerid=' + indexerid)

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def GetEpisode(self, strShowID, strSeason, strEpisode):
        return self.fetch('episode&indexerid=' + strShowID + '&season=' + strSeason + '&episode=' + strEpisode + '&full_path=1')

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def GetSeason(self, indexerid, season):
        self.logger.debug('Fetching Season')
        return self.fetch('show.seasons&indexerid=' + indexerid + '&season=' + season)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def Postprocess(self, path='', force_replace=False, return_data=False, is_priority=False, type=False):
        self.logger.debug('Postprocess')
        if path:
            path = '&%s' % path
        return self.fetch('postprocess' + path, False, 120)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def Restart(self):
        self.logger.debug('Restart sr')
        return self.fetch('sb.restart', False, 15)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def SearchEpisodeDownload(self, indexerid, season, episode):
        self.logger.debug('Fetching Episode Downloads')
        return self.fetch('episode.search&indexerid=' + indexerid + '&season=' + season + '&episode=' + episode, False, 45)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def SearchSubtitle(self, indexerid, season, episode):
        self.logger.debug('Fetching subtitle')
        return self.fetch('episode.subtitlesearch&indexerid=' + indexerid + '&season=' + season + '&episode=' + episode, False, 45)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def Shutdown(self):
        self.logger.debug('Shutdown sickrage')
        return self.fetch('sb.shutdown', False, 20)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def ForceFullUpdate(self, indexerid):
        self.logger.debug('Force full update for indexerid %s' % indexerid)
        return self.fetch('show.update&indexerid=' + indexerid)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def RescanFiles(self, indexerid):
        self.logger.debug('Rescan all local files for indexerid %s' % indexerid)
        return self.fetch('show.refresh&indexerid=' + indexerid)

    @cherrypy.expose()
    @cherrypy.tools.json_out()
    @require(member_of(htpc.role_user))
    def RemoveShow(self, indexerid, show_name=''):
        self.logger.debug('Delete %s from Sickrage indexerid %s' % (show_name, indexerid))
        return self.fetch('show.delete&indexerid=%s' % indexerid)

    @cherrypy.expose()
    @cherrypy.tools.json_out()
    @require()
    def SearchShow(self, query):
        self.logger.debug('Searching tvdb and tvrage for %s query')
        return self.fetch('sb.searchindexers&indexer=0&name=%s' % quote(query), False, 60)

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def ShowsStats(self):
        self.logger.debug('Grabbing tvrage statistics')
        return self.fetch('shows.stats')

    def fetch(self, cmd, img=False, timeout=20):
        try:
            host = striphttp(htpc.settings.get('sickrage_host', ''))
            port = str(htpc.settings.get('sickrage_port', ''))
            apikey = htpc.settings.get('sickrage_apikey', '')
            ssl = 's' if htpc.settings.get('sickrage_ssl', 0) else ''
            sickrage_basepath = fix_basepath(htpc.settings.get('sickrage_basepath', '/'))

            url = 'http%s://%s:%s%sapi/%s/?cmd=%s' % (ssl, host, port, sickrage_basepath, apikey, cmd)

            self.logger.debug('Fetching information from: %s' % url)

            if img is True:
                # Cache the images
                return get_image(url)

            res = requests.get(url, timeout=timeout, verify=False)
            return res.json()
        except Exception as e:
            self.logger.error('Unable to fetch information')
            self.logger.error(url)
            self.logger.error(e)
            return
コード例 #21
0
class Kodi(object):
    def __init__(self):
        """ Add module to list of modules on load and set required settings """
        self.logger = logging.getLogger('modules.kodi')

        KodiServers.createTable(ifNotExists=True)
        try:
            KodiServers.sqlmeta.addColumn(IntCol('starterport'), changeSchema=True)
        except:
            # Will always raise if column exist
            pass

        htpc.MODULES.append({
            'name': 'Kodi',
            'id': 'kodi',
            'fields': [
                {'type': 'bool',
                 'label': 'Enable',
                 'name': 'kodi_enable'},
                {'type': 'text',
                 'label': 'Menu name',
                 'name': 'kodi_name'},
                {'type': 'bool',
                 'label': 'Enable PVR',
                 'name': 'kodi_enable_pvr'},
                {'type': 'bool',
                 'label': 'Hide watched',
                 'name': 'kodi_hide_watched'}
            ]
        })

        htpc.MODULES.append({
            'name': 'Kodi Servers',
            'id': 'kodi_update_server',
            'action': htpc.WEBDIR + 'kodi/setserver',
            'test': htpc.WEBDIR + 'kodi/ping',
            'fields': [
                {'type': 'select',
                 'label': 'Server',
                 'name': 'kodi_server_id',
                 'options': [
                    {'name': 'New', 'value': 0}
                    ]
                },
                {'type': 'text',
                 'label': 'Name',
                 'name': 'kodi_server_name'},
                {'type': 'text',
                 'label': 'IP / Host',
                 'placeholder': 'localhost',
                 'name': 'kodi_server_host'},
                {'type': 'text',
                 'label': 'Port',
                 'placeholder': '8080',
                 'name': 'kodi_server_port'},
                {'type': 'text',
                 'label': 'Username',
                 'name': 'kodi_server_username'},
                {'type': 'password',
                 'label': 'Password',
                 'name': 'kodi_server_password'},
                {'type': 'text',
                 'label': 'Mac addr.',
                 'name': 'kodi_server_mac'},
                {'type': 'text',
                 'label': 'XBMC Starter port',
                 'placeholder': '9',
                 'name': 'kodi_server_starterport'}
            ]
        })
        server = htpc.settings.get('kodi_current_server', 0)
        self.changeserver(server)

    @cherrypy.expose()
    @require()
    def index(self):
        """ Generate page from template """
        return htpc.LOOKUP.get_template('kodi.html').render(scriptname='kodi')

    @cherrypy.expose()
    @require()
    def webinterface(self):
        """ Generate page from template """
        raise cherrypy.HTTPRedirect(self.url('', True))

    @cherrypy.expose()
    @cherrypy.tools.json_out()
    @require(member_of(htpc.role_admin))
    def primecache(self, t='all', wanted_art='all', async=True, resize=True):
コード例 #22
0
ファイル: log.py プロジェクト: wookienz/HTPC-Manager
class Log:
    """ Root class """
    def __init__(self):
        """ Initialize the logger """
        self.logfile = os.path.join(htpc.DATADIR, 'htpcmanager.log')
        htpc.LOGGER = logging.getLogger()
        self.logch = logging.StreamHandler()
        self.logfh = logging.handlers.RotatingFileHandler(self.logfile,
                                                          maxBytes=25000000,
                                                          backupCount=2)

        logformatter = logging.Formatter(
            '%(asctime)s :: %(name)s :: %(levelname)s :: %(message)s',
            "%Y-%m-%d %H:%M:%S")
        self.logch.setFormatter(logformatter)
        self.logfh.setFormatter(logformatter)

        if htpc.LOGLEVEL == 'debug' or htpc.DEBUG:
            loglevel = logging.DEBUG
        elif htpc.LOGLEVEL == 'info':
            loglevel = logging.INFO
        elif htpc.LOGLEVEL == 'warning':
            loglevel = logging.WARNING
        elif htpc.LOGLEVEL == 'error':
            loglevel = logging.ERROR
        else:
            loglevel = logging.CRITICAL

        self.logch.setLevel(loglevel)
        self.logfh.setLevel(loglevel)
        htpc.LOGGER.setLevel(loglevel)

        # Disable cherrypy access log
        logging.getLogger('cherrypy.access').propagate = False

        htpc.LOGGER.addHandler(self.logch)
        htpc.LOGGER.addHandler(self.logfh)

        htpc.LOGGER.info("Welcome to HTPC-Manager!")
        htpc.LOGGER.info("Loglevel set to " + htpc.LOGLEVEL)

    @cherrypy.expose()
    @require()
    def index(self):
        """ Show log """
        return htpc.LOOKUP.get_template('log.html').render(scriptname='log')

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def getlog(self, lines=10, level=2):
        """ Get log as JSON """
        levels = ['DEBUG', 'INFO', 'WARNING', 'ERROR',
                  'CRITICAL'][-int(level):]
        content = []
        try:
            for line in reversed(open(self.logfile, 'r').readlines()):
                line = line.split(' :: ')
                if len(line) > 1 and line[2] in levels:
                    content.append(line)
                    if len(content) >= int(lines):
                        break
        except IOError:
            # Can't log this error since there is no log file.
            pass

        return content

    @cherrypy.expose()
    @cherrypy.tools.json_out()
    @require(member_of('admin'))
    def deletelog(self):
        try:
            open(self.logfile, 'w').close()
            return "Log file deleted"
        except Exception, e:
            return "Cannot delete log file: " + str(e)
コード例 #23
0
ファイル: sonarr.py プロジェクト: lopezfra/htpcmanager
class Sonarr(object):
    def __init__(self):
        self.logger = logging.getLogger('modules.sonarr')
        htpc.MODULES.append({
            'name': 'Sonarr',
            'id': 'sonarr',
            'test': htpc.WEBDIR + 'sonarr/Version',
            'fields': [
                {'type': 'bool', 'label': 'Enable', 'name': 'sonarr_enable'},
                {'type': 'text', 'label': 'Menu name', 'name': 'sonarr_name'},
                {'type': 'text', 'label': 'IP / Host', 'placeholder': 'localhost', 'name': 'sonarr_host'},
                {'type': 'text', 'label': 'Port', 'placeholder': '8989', 'name': 'sonarr_port'},
                {'type': 'text', 'label': 'Basepath', 'placeholder': '/sonarr', 'name': 'sonarr_basepath'},
                {'type': 'text', 'label': 'API', 'name': 'sonarr_apikey'},
                {'type': 'bool', 'label': 'Use SSL', 'name': 'sonarr_ssl'},
                {'type': 'text', 'label': 'Reverse proxy link', 'placeholder': '', 'desc': 'Reverse proxy link, e.g. https://sonarr.domain.com', 'name': 'sonarr_reverse_proxy_link'},

            ]
        })

    @cherrypy.expose()
    @require()
    def index(self):
        return htpc.LOOKUP.get_template('sonarr.html').render(scriptname='sonarr', webinterface=self.webinterface(), quality=self.Profile())

    def webinterface(self):
        host = striphttp(htpc.settings.get('sonarr_host', ''))
        port = str(htpc.settings.get('sonarr_port', ''))
        sonarr_basepath = htpc.settings.get('sonarr_basepath', '/')
        ssl = 's' if htpc.settings.get('sonarr_ssl', True) else ''

        # Makes sure that the basepath is /whatever/
        sonarr_basepath = fix_basepath(sonarr_basepath)

        url = 'http%s://%s:%s%s' % (ssl, host, port, sonarr_basepath)

        if htpc.settings.get('sonarr_reverse_proxy_link'):
            url = htpc.settings.get('sonarr_reverse_proxy_link')

        return url

    def fetch(self, path, banner=None, type=None, data=None):
        try:
            host = striphttp(htpc.settings.get('sonarr_host', ''))
            port = str(htpc.settings.get('sonarr_port', ''))
            sonarr_basepath = htpc.settings.get('sonarr_basepath', '/')
            ssl = 's' if htpc.settings.get('sonarr_ssl', True) else ''

            # Makes sure that the basepath is /whatever/
            sonarr_basepath = fix_basepath(sonarr_basepath)

            headers = {'X-Api-Key': htpc.settings.get('sonarr_apikey', '')}

            url = 'http%s://%s:%s%sapi/%s' % (ssl, host, port, sonarr_basepath, path)

            if banner:
                #  the path includes the basepath automaticly (if fetched from api command 'Series')
                # Cache the image in HTPC Manager aswell.
                return get_image(url, headers=headers)

            if type == 'post':
                r = requests.post(url, data=dumps(data), headers=headers, verify=False)
                return r.content

            elif type == 'put':
                r = requests.put(url, data=dumps(data), headers=headers, verify=False)
                return r.content

            elif type == 'delete':
                r = requests.delete(url, data=dumps(data), headers=headers, verify=False)
                return r.content

            else:
                r = requests.get(url, headers=headers, verify=False)
                return loads(r.text)

        except Exception as e:
            self.logger.error('Failed to fetch url=%s path=%s error %s' % (url, path, e))

    @cherrypy.expose()
    @require(member_of(htpc.role_admin))
    def Version(self, sonarr_host, sonarr_port, sonarr_basepath, sonarr_apikey, sonarr_ssl=False, **kwargs):
        try:
            ssl = 's' if sonarr_ssl else ''

            if not sonarr_basepath:
                sonarr_basepath = fix_basepath(sonarr_basepath)

            headers = {'X-Api-Key': str(sonarr_apikey)}

            url = 'http%s://%s:%s%sapi/system/status' % (ssl, striphttp(sonarr_host), sonarr_port, sonarr_basepath)

            result = requests.get(url, headers=headers, verify=False)
            return result.json()
        except:
            return

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def Rootfolder(self):
        return [folder['path'] for folder in self.fetch('Rootfolder')]

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def Series(self):
        ''' Return info about all your shows '''
        return self.fetch('Series')

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def Show(self, id, tvdbid=None):
        ''' Details about one show '''
        return self.fetch('Series/%s' % id)

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def Delete_Show(self, id, title, delete_date=None):
        self.logger.debug('Deleted tvshow %s' % title)
        return self.fetch('Series/%s' % id, type='delete')

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def History(self):
        return self.fetch('History?page=1&pageSize=100&sortKey=date&sortDir=desc')

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def oldCalendar(self, param=None):
        return self.fetch('Calendar?end=%s' % (DT.date.today() + DT.timedelta(days=7)))

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def Calendar(self, param=None, *args, **kwargs):
        p = urllib.urlencode(kwargs)
        episodes = self.fetch('Calendar?%s' % p)
        cal = []
        for episode in episodes:
            d = {
                'title': episode['series']['title'],
                'season': episode['seasonNumber'],
                'episode': episode['episodeNumber'],
                'start': episode['airDateUtc'],
                'overview': episode.get('overview', ''),
                'all': episode,
                'allDay': False,
            }

            cal.append(d)

        return cal

    @cherrypy.expose()
    @require()
    def View(self, tvdbid, id):
        if not (tvdbid.isdigit()):
            raise cherrypy.HTTPError('500 Error', 'Invalid show ID.')
            self.logger.error('Invalid show ID was supplied: ' + str(id))
            return False
        # tvdbid is acctually id, and id is tvdbid....
        return htpc.LOOKUP.get_template('sonarr_view.html').render(scriptname='sonarr_view', tvdbid=tvdbid, id=id)

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def Episodes(self, id):
        return self.fetch('episode?seriesId=%s' % id)

    @cherrypy.expose()
    @require()
    def GetBanner(self, url=None):
        self.logger.debug('Fetching Banner')
        cherrypy.response.headers['Content-Type'] = 'image/jpeg'
        return self.fetch(url, banner=True)

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def Episode(self, id):
        self.logger.debug('Fetching Episode info')
        return self.fetch('episode/%s' % id)

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def Episodesqly(self, id):
        self.logger.debug('Fetching fileinfo for all episodes in a show')
        return self.fetch('episodefile?seriesId=%s' % id)

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def Episodeqly(self, id):
        return self.fetch('episodefile/%s' % id)

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def Profile(self):
        return self.fetch('profile')

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    def Command(self, **kwargs):
        k = kwargs
        cherrypy.response.headers['Content-Type'] = 'application/json'
        try:
            data = {}
            data['name'] = k['method']
            if k['par'] == 'episodeIds':
                k['id'] = [int(k['id'])]
            data[k['par']] = k['id']
        except KeyError:
            pass

        return self.fetch(path='command', data=data, type='post')

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def Lookup(self, q):
        return self.fetch('Series/lookup?term=%s' % urllib.quote(q))

    @cherrypy.expose()
    @require()
    def AddShow(self, tvdbid, quality, monitor='all', seriestype='standard',
                rootfolder='', seasonfolder='on', specials=False):
        d = {}
        try:
            tvshow = self.fetch('Series/lookup?term=tvdbid:%s' % tvdbid)
            seasoncount = 1
            season = []
            for i in tvshow:

                self.logger.debug('monitor=%s' % monitor)

                d['title'] = i['title']
                d['tvdbId'] = int(i['tvdbId'])
                d['qualityProfileId'] = int(quality)
                d['titleSlug'] = i['titleSlug']
                d['RootFolderPath'] = rootfolder
                d['monitored'] = True
                season_monitoring = False
                d['seriesType'] = seriestype

                if seasonfolder == 'on':
                    d['seasonFolder'] = True
                if specials == 'on':
                    start_on_season = 0
                else:
                    start_on_season = 1

                seasoncount += i['seasonCount']

                options = {'ignoreEpisodesWithFiles': False,
                           'ignoreEpisodesWithoutFiles': False,
                           'searchForMissingEpisodes': True}

                if monitor == 'all':
                    season_monitoring = True

                for x in xrange(start_on_season, int(seasoncount)):
                    s = {'seasonNumber': x, 'monitored': season_monitoring}
                    season.append(s)

                if monitor == 'future':
                    options['ignoreEpisodesWithFiles'] = True
                    options['ignoreEpisodesWithoutFiles'] = True
                elif monitor == 'latest':
                    season[i['seasonCount']]['monitored'] = True
                elif monitor == 'first':
                    season[1]['monitored'] = True
                elif monitor == 'missing':
                    options['ignoreEpisodesWithFiles'] = True
                elif monitor == 'existing':
                    options['ignoreEpisodesWithoutFiles'] = True
                elif monitor == 'none':
                    season_monitoring = False

                d['seasons'] = season
                d['addOptions'] = options

                self.logger.debug('%s' % dumps(d, indent=4))

            # Manually add correct headers since @cherrypy.tools.json_out() renders it wrong
            cherrypy.response.headers['Content-Type'] = 'application/json'
            return self.fetch('Series', data=d, type='post')

        except Exception, e:
            self.logger.error('Failed to add tvshow %s %s' % (tvdbid, e))
コード例 #24
0
ファイル: deluge.py プロジェクト: lopezfra/htpcmanager
class Deluge(object):
    session = requests.Session()

    def __init__(self):
        self.logger = logging.getLogger('modules.deluge')
        htpc.MODULES.append({
            'name':
            'Deluge',
            'id':
            'deluge',
            'test':
            htpc.WEBDIR + 'deluge/ping',
            'fields': [{
                'type': 'bool',
                'label': 'Enable',
                'name': 'deluge_enable'
            }, {
                'type': 'text',
                'label': 'Menu name',
                'name': 'deluge_name'
            }, {
                'type': 'text',
                'label': 'IP / Host *',
                'name': 'deluge_host'
            }, {
                'type': 'text',
                'label': 'Port *',
                'name': 'deluge_port'
            }, {
                'type': 'bool',
                'label': 'Use SSL',
                'name': 'deluge_ssl'
            }, {
                'type': 'text',
                'label': 'Basepath',
                'name': 'deluge_basepath'
            }, {
                'type': 'password',
                'label': 'Password',
                'name': 'deluge_password'
            }, {
                "type": "text",
                "label": "Reverse proxy link",
                "placeholder": "",
                "desc": "Reverse proxy link ex: https://deluge.domain.com",
                "name": "deluge_reverse_proxy_link"
            }]
        })

    @cherrypy.expose()
    @require()
    def index(self):
        return htpc.LOOKUP.get_template('deluge.html').render(
            scriptname='deluge', webinterface=self.webinterface())

    def webinterface(self):
        host = striphttp(htpc.settings.get('deluge_host', ''))
        port = str(htpc.settings.get('deluge_port', ''))
        deluge_basepath = fix_basepath(htpc.settings.get(
            'deluge_basepath', ''))
        ssl = 's' if htpc.settings.get('deluge_ssl') else ''

        url = 'http%s://%s:%s%s' % (ssl, host, port, deluge_basepath)

        if htpc.settings.get('deluge_reverse_proxy_link'):
            url = htpc.settings.get('deluge_reverse_proxy_link')

        return url

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def connected(self):
        return self.fetch('web.connected')

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def connect(self, hostid):
        return self.fetch('web.connect', [hostid])

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def get_hosts(self):
        return self.fetch('web.get_hosts')

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def queue(self):
        fields = [
            'progress', 'is_finished', 'ratio', 'name',
            'download_payload_rate', 'upload_payload_rate', 'eta', 'state',
            'hash', 'total_size'
        ]

        return self.fetch('core.get_torrents_status', [[], fields])

    def q2(self):
        """ not in use atm, todo """
        par = [
            "queue", "name", "total_wanted", "state", "progress", "num_seeds",
            "total_seeds", "num_peers", "total_peers", "download_payload_rate",
            "upload_payload_rate", "eta", "ratio", "distributed_copies",
            "is_auto_managed", "time_added", "tracker_host", "save_path",
            "total_done", "total_uploaded", "max_download_speed",
            "max_upload_speed", "seeds_peers_ratio"
        ]

        return self.fetch('web.update_ui', [par, {}])

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def status(self):
        ''' quick  '''
        results = self.fetch(
            'web.update_ui',
            [['payload_upload_rate', 'payload_download_rate, state'], {}])
        if results['error'] is None:
            # py. 2.6..
            d = dict(tuple(results['result']['filters']['state']))
            results['result']['filters']['state'] = d

        return results

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def stats(self):
        fields = ['payload_upload_rate', 'payload_download_rate, state']
        return self.fetch('core.get_session_status', [fields])

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def start(self, torrentId):
        return self.fetch('core.resume_torrent', [[torrentId]])

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def stop(self, torrentId=None):
        return self.fetch('core.pause_torrent', [[torrentId]])

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def do_all(self, status):
        if status == 'resume':
            method = 'core.resume_all_torrents'
        else:
            method = 'core.pause_all_torrents'

        return self.fetch(method)

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def daemon(self, status, port):
        if status == 'start':
            action = 'web.start_daemon'
        else:
            action = 'web.stop_daemon'
        return self.fetch(action, [int(port)])

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def set_dlspeed(self, speed):
        self.logger.debug('Set download speed to %s' % speed)
        if speed == '0':
            speed = -1
        return self.fetch('core.set_config', [{
            'max_download_speed': int(speed)
        }])

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def set_ulspeed(self, speed):
        if speed == '0':
            speed = -1
        self.logger.debug('Set upload speed to %s' % speed)

        return self.fetch('core.set_config', [{
            'max_upload_speed': int(speed)
        }])

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def addtorrent(self, torrent, filename=''):
        result = self.fetch('core.add_torrent_file', [filename, torrent, {}])
        return result

    '''
    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def getconfig(self):
        #should be removed
        return self.fetch('core.get_config')
    '''

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def get_speed(self):
        ''' speed limit '''
        result = self.fetch('core.get_config')
        # Dunno why the f, core.get_config_values didnt work...
        d = {}
        if result:
            d['max_download_speed'] = result['result']['max_download_speed']
            d['max_upload_speed'] = result['result']['max_upload_speed']
            result['result'] = d
            return result

    @cherrypy.expose()
    @require(member_of(htpc.role_user))
    @cherrypy.tools.json_out()
    def remove(self, torrentId, removeData):
        removeDataBool = bool(int(removeData))
        return self.fetch('core.remove_torrent', [torrentId, removeDataBool])

    @cherrypy.expose()
    @require()
    @cherrypy.tools.json_out()
    def to_client(self, link='', torrentname='', **kwargs):
        try:
            self.logger.info('Added %s to deluge' % torrentname)
            # Find download path
            download_path = self.fetch('core.get_config_value',
                                       ['download_location'])
            if link.startswith('magnet'):
                path = link
            else:
                # deluge doesnt like a named download...
                link = link.split('?title=')[0]
                get_url = self.fetch('web.download_torrent_from_url', [link])
                path = get_url['result']

            return self.fetch('web.add_torrents', [[{
                'path': path,
                'options': {
                    'download_location': download_path['result']
                }
            }]])

        except Exception as e:
            self.logger.debug('Failed adding %s to deluge %s %s' %
                              (torrentname, link, e))

    def fetch(self, method, arguments=None):
        """ Do request to Deluge api """
        if arguments is None:
            arguments = []

        host = striphttp(htpc.settings.get('deluge_host', ''))
        port = htpc.settings.get('deluge_port', '')
        deluge_basepath = fix_basepath(
            htpc.settings.get('deluge_basepath', '/'))
        ssl = 's' if htpc.settings.get('deluge_ssl') else ''

        url = 'http%s://%s:%s%sjson' % (ssl, host, port, deluge_basepath)

        self.logger.debug("Request deluge method: %s arguments %s" %
                          (method, arguments))
        try:
            # format post data
            data = {'id': 1, 'method': method, 'params': arguments}

            response = self.session.post(url, data=dumps(data), verify=False)
            result = response.json()
            if result and result['error']:
                self.logger.debug('Authenticating')
                self.session.post(
                    url,
                    data=dumps({
                        "method":
                        "auth.login",
                        "params": [htpc.settings.get('deluge_password', '')],
                        "id":
                        1
                    }),
                    verify=False)
                response = self.session.post(url,
                                             data=dumps(data),
                                             verify=False)

            return result
        except Exception as e:
            self.logger.error('Failed to fetch method %s  arguments %s %s' %
                              (method, arguments, e))