Beispiel #1
0
    def three(self, **kwargs):
        """ Accept webserver parms and show Indexers page """
        if kwargs:
            if 'access' in kwargs:
                cfg.cherryhost.set(kwargs['access'])
            cfg.enable_https.set(kwargs.get('enable_https', 0))
            cfg.autobrowser.set(kwargs.get('autobrowser', 0))
            cfg.username.set(kwargs.get('web_user', ''))
            cfg.password.set(kwargs.get('web_pass', ''))
            if not cfg.username() or not cfg.password():
                sabnzbd.interface.set_auth(cherrypy.config)

        # Create Indexers page
        info = self.info.copy()
        info['num'] = '» %s' % T('Step Three')
        info['number'] = 3
        info['newzbin_user'] = cfg.newzbin_username()
        info['newzbin_pass'] = cfg.newzbin_password.get_stars()
        info['newzbin_bookmarks'] = cfg.newzbin_bookmarks()
        info['newzbin_url'] = cfg.newzbin_url()
        info['matrix_user'] = cfg.matrix_username()
        info['matrix_apikey'] = cfg.matrix_apikey()
        info['T'] = Ttemplate
        template = Template(file=os.path.join(self.__web_dir, 'three.html'),
                            searchList=[info],
                            compilerSettings=sabnzbd.interface.DIRECTIVES)
        return template.respond()
Beispiel #2
0
    def three(self, **kwargs):
        """ Accept webserver parms and show Indexers page """
        if kwargs:
            if 'access' in kwargs:
                cfg.cherryhost.set(kwargs['access'])
            cfg.enable_https.set(kwargs.get('enable_https',0))
            cfg.autobrowser.set(kwargs.get('autobrowser',0))
            cfg.username.set(kwargs.get('web_user', ''))
            cfg.password.set(kwargs.get('web_pass', ''))
            if not cfg.username() or not cfg.password():
                sabnzbd.interface.set_auth(cherrypy.config)

        # Create Indexers page
        info = self.info.copy()
        info['num'] = '» %s' % T('Step Three')
        info['number'] = 3
        info['newzbin_user'] = cfg.newzbin_username()
        info['newzbin_pass'] = cfg.newzbin_password.get_stars()
        info['newzbin_bookmarks'] = cfg.newzbin_bookmarks()
        info['newzbin_url'] = cfg.newzbin_url()
        info['matrix_user'] = cfg.matrix_username()
        info['matrix_apikey'] = cfg.matrix_apikey()
        info['T'] = Ttemplate
        template = Template(file=os.path.join(self.__web_dir, 'three.html'),
                            searchList=[info], compilerSettings=sabnzbd.interface.DIRECTIVES)
        return template.respond()
Beispiel #3
0
def format_source_url(url):
    """ Format URL suitable for 'Source' stage """
    if _HAVE_SSL:
        prot = 'https'
    else:
        prot = 'http:'
    if url and str(url).isdigit():
        return '%s://%s/browse/post/%s/' % (prot, cfg.newzbin_url(), str(url))
    else:
        return url
Beispiel #4
0
def format_source_url(url):
    """ Format URL suitable for 'Source' stage """
    if _HAVE_SSL:
        prot = 'https'
    else:
        prot = 'http:'
    if url and str(url).isdigit():
        return '%s://%s/browse/post/%s/' % (prot, cfg.newzbin_url(), str(url))
    else:
        return url
Beispiel #5
0
    def run(self, delete=None, force=False):

        if not (cfg.newzbin_bookmarks() or force):
            return
        if not (cfg.newzbin_username() and cfg.newzbin_password()):
            return

        headers = { 'User-Agent': 'SABnzbd+/%s' % sabnzbd.__version__, }

        # Connect to Newzbin
        try:
            if _HAVE_SSL:
                conn = httplib.HTTPSConnection(cfg.newzbin_url())
            else:
                conn = httplib.HTTPConnection(cfg.newzbin_url())

            if delete:
                logging.debug('Trying to delete Newzbin bookmark %s', delete)
                postdata = { 'username': cfg.newzbin_username(), 'password': cfg.newzbin_password(), 'action': 'delete', \
                             'reportids' : delete }
            else:
                logging.info('Fetching Newzbin bookmarks')
                postdata = { 'username': cfg.newzbin_username(), 'password': cfg.newzbin_password(), 'action': 'fetch'}
            postdata = urllib.urlencode(postdata)

            headers['Content-type'] = 'application/x-www-form-urlencoded'

            fetchurl = '/api/bookmarks/'
            conn.request('POST', fetchurl, postdata, headers)
            response = conn.getresponse()
        except:
            _warn_user('Problem accessing Newzbin server.')
            logging.info("Traceback: ", exc_info = True)
            return

        data = response.read()

        # Get the status
        rcode = str(response.status)

        # Official return codes:
        # 200 = OK, NZB content follows
        # 204 = No content
        # 400 = Bad Request, please supply all parameters
        #       (this generally means reportid or fileid is missing; missing user/pass gets you a 401)
        # 401 = Unauthorised, check username/password?
        # 402 = Payment Required, not Premium
        # 403 = Forbidden (incorrect auth)
        # 500 = Internal Server Error, please report to Administrator
        # 503 = Service Unavailable, site is currently down

        if rcode not in ('500', '503'):
            _access_ok()

        if rcode == '204':
            logging.debug("No bookmarks set")
        elif rcode in ('401', '403'):
            logging.warning(Ta('Unauthorised, check your newzbin username/password'))
        elif rcode in ('402'):
            logging.warning(Ta('You have no credit on your Newzbin account'))
        elif rcode in ('500', '503'):
            _warn_user('Newzbin has a server problem (%s).' % rcode)
        elif rcode == '200':
            if delete:
                if data.startswith('1'):
                    logging.info('Deleted newzbin bookmark %s', delete)
                    if delete in self.bookmarks:
                        self.bookmarks.remove(delete)
                else:
                    if delete in self.bookmarks:
                        logging.warning(Ta('Could not delete newzbin bookmark %s'), delete)
            else:
                for line in data.split('\n'):
                    try:
                        msgid, size, text = line.split('\t', 2)
                    except:
                        msgid = size = text = None
                    if msgid and (msgid not in self.bookmarks):
                        self.bookmarks.append(msgid)
                        logging.info("Found new bookmarked msgid %s (%s)", msgid, text)
                        sabnzbd.add_msgid(int(msgid), None, None, priority=None)
        else:
            logging.error(Ta('Newzbin gives undocumented error code (%s)'), rcode)

        self._save()
        self.__busy = False
Beispiel #6
0
def _grabnzb(msgid):
    """ Grab one msgid from newzbin """

    msg = ''
    retry = (60, None, None, None)
    nzo_info = {'msgid': msgid}

    logging.info('Fetching NZB for Newzbin report #%s', msgid)

    headers = {'User-agent' : 'SABnzbd+/%s' % sabnzbd.version.__version__}

    # Connect to Newzbin
    try:
        if _HAVE_SSL:
            conn = httplib.HTTPSConnection(cfg.newzbin_url())
        else:
            conn = httplib.HTTPConnection(cfg.newzbin_url())

        postdata = { 'username': cfg.newzbin_username(), 'password': cfg.newzbin_password(), 'reportid': msgid }
        postdata = urllib.urlencode(postdata)

        headers['Content-type'] = 'application/x-www-form-urlencoded'

        fetchurl = '/api/dnzb/'
        conn.request('POST', fetchurl, postdata, headers)
        response = conn.getresponse()

        # Save debug info if we have to
        data = response.read()

    except:
        _warn_user('Problem accessing Newzbin server, wait 1 min.')
        logging.info("Traceback: ", exc_info = True)
        return retry

    # Get the filename
    rcode = response.getheader('X-DNZB-RCode')
    rtext = response.getheader('X-DNZB-RText')
    try:
        nzo_info['more_info'] = response.getheader('X-DNZB-MoreInfo')
    except:
        # Only some reports will generate a moreinfo header
        pass
    if not (rcode or rtext):
        logging.error(T('Newzbin server changed its protocol'))
        return retry

    # Official return codes:
    # 200 = OK, NZB content follows
    # 400 = Bad Request, please supply all parameters
    #       (this generally means reportid or fileid is missing; missing user/pass gets you a 401)
    # 401 = Unauthorised, check username/password?
    # 402 = Payment Required, not Premium
    # 404 = Not Found, data doesn't exist?
    #       (only working for reportids, see Technical Limitations)
    # 450 = Try Later, wait <x> seconds for counter to reset
    #       (for an explanation of this, see DNZB Rate Limiting)
    # 500 = Internal Server Error, please report to Administrator
    # 503 = Service Unavailable, site is currently down

    if rcode in ('500', '503'):
        _warn_user('Newzbin has a server problem (%s, %s), wait 5 min.' % (rcode, rtext))
        return retry

    _access_ok()

    if rcode == '450':
        wait_re = re.compile('wait (\d+) seconds')
        try:
            wait = int(wait_re.findall(rtext)[0])
        except:
            wait = 60
        if wait > 60:
            wait = 60
        logging.debug("Newzbin says we should wait for %s sec", wait)
        return int(wait+1), None, None, None

    if rcode in ('402'):
        msg = Ta('You have no credit on your Newzbin account')
        return None, None, None, msg

    if rcode in ('401'):
        msg = Ta('Unauthorised, check your newzbin username/password')
        return None, None, None, msg

    if rcode in ('400', '404'):
        msg = Ta('Newzbin report %s not found') % msgid
        return None, None, None, msg

    if rcode != '200':
        msg = Ta('Newzbin gives undocumented error code (%s, %s)') % (rcode, rtext)
        return 60, None, None, msg

    # Process data
    report_name = response.getheader('X-DNZB-Name')
    report_cat  = response.getheader('X-DNZB-Category')
    if not (report_name and report_cat):
        msg = Ta('Newzbin server fails to give info for %s') %  msgid
        return 60, None, None, msg

    # sanitize report_name
    newname = sanitize_foldername(report_name)
    if len(newname) > 80:
        newname = newname[0:79].strip('. ')
    newname += ".nzb"

    logging.info('Successfully fetched report %s - %s (cat=%s) (%s)', msgid, report_name, report_cat, newname)

    return (newname, data, report_cat, nzo_info)
Beispiel #7
0
    def run(self, delete=None, force=False):

        if not (cfg.newzbin_bookmarks() or force):
            return
        if not (cfg.newzbin_username() and cfg.newzbin_password()):
            return

        headers = {
            'User-Agent': 'SABnzbd+/%s' % sabnzbd.__version__,
        }

        # Connect to Newzbin
        try:
            if _HAVE_SSL:
                conn = httplib.HTTPSConnection(cfg.newzbin_url())
            else:
                conn = httplib.HTTPConnection(cfg.newzbin_url())

            if delete:
                logging.debug('Trying to delete Newzbin bookmark %s', delete)
                postdata = { 'username': cfg.newzbin_username(), 'password': cfg.newzbin_password(), 'action': 'delete', \
                             'reportids' : delete }
            else:
                logging.info('Fetching Newzbin bookmarks')
                postdata = {
                    'username': cfg.newzbin_username(),
                    'password': cfg.newzbin_password(),
                    'action': 'fetch'
                }
            postdata = urllib.urlencode(postdata)

            headers['Content-type'] = 'application/x-www-form-urlencoded'

            fetchurl = '/api/bookmarks/'
            conn.request('POST', fetchurl, postdata, headers)
            response = conn.getresponse()
        except:
            _warn_user('Problem accessing Newzbin server.')
            logging.info("Traceback: ", exc_info=True)
            return

        data = response.read()

        # Get the status
        rcode = str(response.status)

        # Official return codes:
        # 200 = OK, NZB content follows
        # 204 = No content
        # 400 = Bad Request, please supply all parameters
        #       (this generally means reportid or fileid is missing; missing user/pass gets you a 401)
        # 401 = Unauthorised, check username/password?
        # 402 = Payment Required, not Premium
        # 403 = Forbidden (incorrect auth)
        # 500 = Internal Server Error, please report to Administrator
        # 503 = Service Unavailable, site is currently down

        if rcode not in ('500', '503'):
            _access_ok()

        if rcode == '204':
            logging.debug("No bookmarks set")
        elif rcode in ('401', '403'):
            logging.warning(
                Ta('Unauthorised, check your newzbin username/password'))
        elif rcode in ('402'):
            logging.warning(Ta('You have no credit on your Newzbin account'))
        elif rcode in ('500', '503'):
            _warn_user('Newzbin has a server problem (%s).' % rcode)
        elif rcode == '200':
            if delete:
                if data.startswith('1'):
                    logging.info('Deleted newzbin bookmark %s', delete)
                    if delete in self.bookmarks:
                        self.bookmarks.remove(delete)
                else:
                    if delete in self.bookmarks:
                        logging.warning(
                            Ta('Could not delete newzbin bookmark %s'), delete)
            else:
                for line in data.split('\n'):
                    try:
                        msgid, size, text = line.split('\t', 2)
                    except:
                        msgid = size = text = None
                    if msgid and (msgid not in self.bookmarks):
                        self.bookmarks.append(msgid)
                        logging.info("Found new bookmarked msgid %s (%s)",
                                     msgid, text)
                        sabnzbd.add_msgid(int(msgid),
                                          None,
                                          None,
                                          priority=None)
        else:
            logging.error(Ta('Newzbin gives undocumented error code (%s)'),
                          rcode)

        self._save()
        self.__busy = False
Beispiel #8
0
def _grabnzb(msgid):
    """ Grab one msgid from newzbin """

    msg = ''
    retry = (60, None, None, None)
    nzo_info = {'msgid': msgid}

    logging.info('Fetching NZB for Newzbin report #%s', msgid)

    headers = {'User-agent': 'SABnzbd+/%s' % sabnzbd.version.__version__}

    # Connect to Newzbin
    try:
        if _HAVE_SSL:
            conn = httplib.HTTPSConnection(cfg.newzbin_url())
        else:
            conn = httplib.HTTPConnection(cfg.newzbin_url())

        postdata = {
            'username': cfg.newzbin_username(),
            'password': cfg.newzbin_password(),
            'reportid': msgid
        }
        postdata = urllib.urlencode(postdata)

        headers['Content-type'] = 'application/x-www-form-urlencoded'

        fetchurl = '/api/dnzb/'
        conn.request('POST', fetchurl, postdata, headers)
        response = conn.getresponse()

        # Save debug info if we have to
        data = response.read()

    except:
        _warn_user('Problem accessing Newzbin server, wait 1 min.')
        logging.info("Traceback: ", exc_info=True)
        return retry

    # Get the filename
    rcode = response.getheader('X-DNZB-RCode')
    rtext = response.getheader('X-DNZB-RText')
    try:
        nzo_info['more_info'] = response.getheader('X-DNZB-MoreInfo')
    except:
        # Only some reports will generate a moreinfo header
        pass
    if not (rcode or rtext):
        logging.error(T('Newzbin server changed its protocol'))
        return retry

    # Official return codes:
    # 200 = OK, NZB content follows
    # 400 = Bad Request, please supply all parameters
    #       (this generally means reportid or fileid is missing; missing user/pass gets you a 401)
    # 401 = Unauthorised, check username/password?
    # 402 = Payment Required, not Premium
    # 404 = Not Found, data doesn't exist?
    #       (only working for reportids, see Technical Limitations)
    # 450 = Try Later, wait <x> seconds for counter to reset
    #       (for an explanation of this, see DNZB Rate Limiting)
    # 500 = Internal Server Error, please report to Administrator
    # 503 = Service Unavailable, site is currently down

    if rcode in ('500', '503'):
        _warn_user('Newzbin has a server problem (%s, %s), wait 5 min.' %
                   (rcode, rtext))
        return retry

    _access_ok()

    if rcode == '450':
        wait_re = re.compile('wait (\d+) seconds')
        try:
            wait = int(wait_re.findall(rtext)[0])
        except:
            wait = 60
        if wait > 60:
            wait = 60
        logging.debug("Newzbin says we should wait for %s sec", wait)
        return int(wait + 1), None, None, None

    if rcode in ('402'):
        msg = Ta('You have no credit on your Newzbin account')
        return None, None, None, msg

    if rcode in ('401'):
        msg = Ta('Unauthorised, check your newzbin username/password')
        return None, None, None, msg

    if rcode in ('400', '404'):
        msg = Ta('Newzbin report %s not found') % msgid
        return None, None, None, msg

    if rcode != '200':
        msg = Ta('Newzbin gives undocumented error code (%s, %s)') % (rcode,
                                                                      rtext)
        return 60, None, None, msg

    # Process data
    report_name = response.getheader('X-DNZB-Name')
    report_cat = response.getheader('X-DNZB-Category')
    if not (report_name and report_cat):
        msg = Ta('Newzbin server fails to give info for %s') % msgid
        return 60, None, None, msg

    # sanitize report_name
    newname = sanitize_foldername(report_name)
    if len(newname) > 80:
        newname = newname[0:79].strip('. ')
    newname += ".nzb"

    logging.info('Successfully fetched report %s - %s (cat=%s) (%s)', msgid,
                 report_name, report_cat, newname)

    return (newname, data, report_cat, nzo_info)
Beispiel #9
0
    def __init__(self):
        def check_str(p):
            return p is None or p == '' or isinstance(p, str)
        def check_int(p):
            try:
                int(p)
                return True
            except:
                return False

        self.jobs = {}
        try:
            defined = config.get_rss().keys()
            feeds = sabnzbd.load_admin(RSS_FILE_NAME)
            if type(feeds) == type({}):
                for feed in feeds:
                    if feed not in defined:
                        logging.debug('Dropping obsolete data for feed "%s"', feed)
                        continue
                    self.jobs[feed] = {}
                    for link in feeds[feed]:
                        data = feeds[feed][link]
                        if type(data) == type([]):
                            # Convert previous list-based store to dictionary
                            new = {}
                            try:
                                new['status'] = data[0]
                                new['title'] = data[1]
                                new['url'] = data[2]
                                new['cat'] = data[3]
                                new['pp'] = data[4]
                                new['script'] = data[5]
                                new['time'] = data[6]
                                new['prio'] = str(NORMAL_PRIORITY)
                                new['rule'] = 0
                                self.jobs[feed][link] = new
                            except IndexError:
                                del new
                        else:
                            # Consistency check on data
                            try:
                                item = feeds[feed][link]
                                if not isinstance(item, dict) or not isinstance(item.get('title'), unicode):
                                    raise IndexError
                                if item.get('status', ' ')[0] not in ('D', 'G', 'B', 'X'):
                                    item['status'] = 'X'
                                if not isinstance(item.get('url'), unicode): item['url'] = ''
                                item['url'] = item['url'].replace('www.newzbin.com', cfg.newzbin_url())
                                if not check_str(item.get('cat')): item['cat'] = ''
                                if not check_str(item.get('orgcat')): item['orgcat'] = ''
                                if not check_str(item.get('pp')): item['pp'] = '3'
                                if not check_str(item.get('script')): item['script'] = 'None'
                                if not check_str(item.get('prio')): item['prio'] = '-100'
                                if not check_int(item.get('rule', 0)): item['rule'] = 0
                                if not isinstance(item.get('time'), float): item['time'] = time.time()
                                if not check_int(item.get('order', 0)): item.get['order'] = 0
                                self.jobs[feed][link] = item
                            except (KeyError, IndexError):
                                logging.info('Incorrect entry in %s detected, discarding %s', RSS_FILE_NAME, item)

                    remove_obsolete(self.jobs[feed], self.jobs[feed].keys())

        except IOError:
            logging.debug('Cannot read file %s', RSS_FILE_NAME)

        # jobs is a NAME-indexed dictionary
        #    Each element is link-indexed dictionary
        #        Each element is another dictionary:
        #           status : 'D', 'G', 'B', 'X' (downloaded, good-match, bad-match, obsolete)
        #               '*' added means: from the initial batch
        #               '-' added to 'D' means downloaded, but not displayed anymore
        #           title : Title
        #           url : URL or MsgId
        #           cat : category
        #           orgcat : category as read from feed
        #           pp : pp
        #           script : script
        #           prio : priority
        #           time : timestamp (used for time-based clean-up)
        #           order : order in the RSS feed

        self.shutdown = False
Beispiel #10
0
    def __init__(self):
        def check_str(p):
            return p is None or p == '' or isinstance(p, str)

        def check_int(p):
            try:
                int(p)
                return True
            except:
                return False

        self.jobs = {}
        try:
            defined = config.get_rss().keys()
            feeds = sabnzbd.load_admin(RSS_FILE_NAME)
            if type(feeds) == type({}):
                for feed in feeds:
                    if feed not in defined:
                        logging.debug('Dropping obsolete data for feed "%s"',
                                      feed)
                        continue
                    self.jobs[feed] = {}
                    for link in feeds[feed]:
                        data = feeds[feed][link]
                        if type(data) == type([]):
                            # Convert previous list-based store to dictionary
                            new = {}
                            try:
                                new['status'] = data[0]
                                new['title'] = data[1]
                                new['url'] = data[2]
                                new['cat'] = data[3]
                                new['pp'] = data[4]
                                new['script'] = data[5]
                                new['time'] = data[6]
                                new['prio'] = str(NORMAL_PRIORITY)
                                new['rule'] = 0
                                self.jobs[feed][link] = new
                            except IndexError:
                                del new
                        else:
                            # Consistency check on data
                            try:
                                item = feeds[feed][link]
                                if not isinstance(
                                        item, dict) or not isinstance(
                                            item.get('title'), unicode):
                                    raise IndexError
                                if item.get('status',
                                            ' ')[0] not in ('D', 'G', 'B',
                                                            'X'):
                                    item['status'] = 'X'
                                if not isinstance(item.get('url'), unicode):
                                    item['url'] = ''
                                item['url'] = item['url'].replace(
                                    'www.newzbin.com', cfg.newzbin_url())
                                if not check_str(item.get('cat')):
                                    item['cat'] = ''
                                if not check_str(item.get('orgcat')):
                                    item['orgcat'] = ''
                                if not check_str(item.get('pp')):
                                    item['pp'] = '3'
                                if not check_str(item.get('script')):
                                    item['script'] = 'None'
                                if not check_str(item.get('prio')):
                                    item['prio'] = '-100'
                                if not check_int(item.get('rule', 0)):
                                    item['rule'] = 0
                                if not isinstance(item.get('time'), float):
                                    item['time'] = time.time()
                                if not check_int(item.get('order', 0)):
                                    item.get['order'] = 0
                                self.jobs[feed][link] = item
                            except (KeyError, IndexError):
                                logging.info(
                                    'Incorrect entry in %s detected, discarding %s',
                                    RSS_FILE_NAME, item)

                    remove_obsolete(self.jobs[feed], self.jobs[feed].keys())

        except IOError:
            logging.debug('Cannot read file %s', RSS_FILE_NAME)

        # jobs is a NAME-indexed dictionary
        #    Each element is link-indexed dictionary
        #        Each element is another dictionary:
        #           status : 'D', 'G', 'B', 'X' (downloaded, good-match, bad-match, obsolete)
        #               '*' added means: from the initial batch
        #               '-' added to 'D' means downloaded, but not displayed anymore
        #           title : Title
        #           url : URL or MsgId
        #           cat : category
        #           orgcat : category as read from feed
        #           pp : pp
        #           script : script
        #           prio : priority
        #           time : timestamp (used for time-based clean-up)
        #           order : order in the RSS feed

        self.shutdown = False