Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python
- #encoding:utf-8
- import urllib
- import xml.dom.minidom
- import re
- import time
- import os
- import sys
- import string
- import pickle
- import feedparser
- import logging
- import dailylogrotation
- import ConfigParser
- from tvdb_api import (tvdb_error, tvdb_shownotfound, tvdb_seasonnotfound,
- tvdb_episodenotfound, tvdb_episodenotfound, tvdb_attributenotfound, tvdb_userabort)
- from tvdb_api import Tvdb
- ################################
- # SABzndb Smart Downlader - TV #
- ################################
- __author__ = "minimad/Neil"
- __version__ = "0.9.3"
- # Use a config File
- # defaults to same dir as script
- config = ConfigParser.RawConfigParser()
- config.read('SSD.cfg')
- # Use a Alias file
- aliases = ConfigParser.RawConfigParser()
- aliases.read('Aliases.cfg')
- ################################### START VALUES FROM CONFIG FILE #####################################
- # Media Location
- tv_dirs = []
- if sys.platform == "win32":
- for dir in config.items('MEDIA LOCATION - WIN32'):
- tv_dirs.append(dir[1])
- else:
- for dir in config.items('MEDIA LOCATION - LINUX'):
- tv_dirs.append(dir[1])
- # Define Log Files
- errorlog = config.get('LOGGING' , 'ERROR_LOG')
- debuglog = config.get('LOGGING' , 'DEBUG_LOG')
- # Season Directory Numbering Format
- SeasonType = config.get('NAMING_FORMAT' , 'SeasonType')
- # Episode File Numbering Format
- EpisodeType = config.get('NAMING_FORMAT' , 'EpisodeType')
- # RSS Feeds
- nzbfeeds = []
- feeds = config.items('NZB_FEEDS')
- for feed in feeds:
- nzbfeeds.append(feed[1])
- # SABnzbd Config
- my_SAB = config.get('SABnzbd Config' , 'URL')
- my_SAB_params = config.get('SABnzbd Config' , 'ADD_PARAMS')
- my_SAB_username = config.get('SABnzbd Config' , 'USERNAME')
- my_SAB_password = config.get('SABnzbd Config' , 'PASSWORD')
- SAB_API_KEY = config.get('SABnzbd Config' , 'API_KEY')
- # theTVDB api
- tvdb_interactive = config.getboolean('TVDB_API' , 'INTERACTIVE')
- tvdb_debug = config.getboolean('TVDB_API' , 'DEBUG')
- # Video Format
- video_formats = config.get('VIDEO_FORMAT' , 'FORMAT')
- # DEBUG
- debug = config.getboolean('SSD' , 'DEBUG')
- # 'Smart' Queue checking
- useSmartQueue = config.getboolean('SSD' , 'SMART_QUEUE')
- # SABnzbd or tvnamer.py style illegal char replaement
- SABnzbdIllegalCharsStyle = config.getboolean('SSD' , 'SABnzbdIllegalCharsStyle')
- # Windows Compliant Names
- force_windows_compliant_filenames = config.getboolean('SSD' , 'WINDOWS_COMPLIANT')
- # NZBDownload
- NZBdownload = config.getboolean('SSD' , 'NZB_DOWNLOAD')
- # NZB 'blackhole' directory
- if sys.platform == "win32":
- NZB_BlackHole = config.get('SSD' , 'NZB_BLACKHOLE_WIN32')
- else:
- NZB_BlackHole = config.get('SSD' , 'NZB_BLACKHOLE_LINUX')
- # NZBs.org UserID & password
- nzbs_org_userid = config.get('SSD' , 'NZBS_ORG_USERID')
- nzbs_org_password = config.get('SSD' , 'NZBS_ORG_PASSWORD')
- ################################### END VALUES FROM CONFIG FILE #####################################
- # Setup Logging
- # create logger
- logger = logging.getLogger("SABnzbd Smart Downloader")
- logger.setLevel(logging.DEBUG)
- # create console handler and set level to debug
- consoleloghandler = logging.StreamHandler()
- consoleloghandler.setLevel(logging.DEBUG)
- # create formatter
- formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
- # add formatter to consoleloghandler
- consoleloghandler.setFormatter(formatter)
- # add consoleloghandler to logger
- logger.addHandler(consoleloghandler)
- # create file log handler and set level to debug
- #fileloghandler = logging.FileHandler(errorlog)
- # Use new Daily Log Rotation
- fileloghandler = dailylogrotation.DailyRollingFileHandler(errorlog)
- fileloghandler.setLevel(logging.DEBUG)
- # add formatter to fileloghandler
- fileloghandler.setFormatter(formatter)
- # add fileloghandler to logger
- logger.addHandler(fileloghandler)
- config = {}
- reportdict = {}
- nzbDetails = {}
- config['valid_filename_chars'] = """0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@£$%^&*()_+=-[]:{}"'.,<>`~? """
- config['with_ep_name'] = '%(seriesname)s - S%(seasno)02dE%(epno)02d - %(epname)s'
- # Force the stripping of invalid Windows characters, even if the current
- # platform is not detected as Windows
- config['force_windows_compliant_filenames'] = True
- if sys.platform == "win32" or config['force_windows_compliant_filenames']:
- # " * : < > ? | \ are all invalid on Windows
- config['valid_filename_chars'] = config['valid_filename_chars'].replace("\"*:<>?|\\","")
- config['valid_filename_chars_regex'] = re.escape(config['valid_filename_chars'])
- # Regex's to parse filenames with. Must have 3 groups, seriesname, season number
- # and episode number. Use (?: optional) non-capturing groups if you need others.
- # taken from tvnamer.py script
- config['name_parse'] = [
- # foo_[s01]_[e01]
- re.compile('''^([%s]+?)[ \._\-]\[[Ss]([0-9]+?)\]_\[[Ee]([0-9]+?)\]?([%s]+)[^\\/]*$''' % (config['valid_filename_chars_regex'], config['valid_filename_chars_regex']) ),
- # foo.1x09*
- re.compile('''^([%s]+?)[ \._\-]\[?([0-9]+)x([0-9]+)([%s]+)[^\\/]*$''' % (config['valid_filename_chars_regex'], config['valid_filename_chars_regex']) ),
- # foo.s01e01.title
- re.compile('''^([%s]+?)[ \._\-][Ss]([0-9]+)[\.\- ]?[Ee]([0-9]+)[ \._\-]([%s]+)[^\\/]*$''' % (config['valid_filename_chars_regex'], config['valid_filename_chars_regex']) ),
- # foo.s01.e01, foo.s01_e01, foo.s01e01
- re.compile('''^([%s]+?)[ \._\-][Ss]([0-9]+)[\.\- ]?[Ee]([0-9]+)([%s]+)[^\\/]*$''' % (config['valid_filename_chars_regex'], config['valid_filename_chars_regex']) ),
- # foo.103*
- re.compile('''^([%s]+)[ \._\-]([0-9]{1})([0-9]{2})[\._ -]([%s]+)[^\\/]*$''' % (config['valid_filename_chars_regex'], config['valid_filename_chars_regex']) ),
- # foo.0103*
- re.compile('''^([%s]+)[ \._\-]([0-9]{2})([0-9]{2,3})[\._ -]([%s]+)[^\\/]*$''' % (config['valid_filename_chars_regex'], config['valid_filename_chars_regex']) ),
- ]
- # Class to allow an exception to be raised
- # if format is not wanted
- class FormatNotWanted:
- pass
- class formatError:
- pass
- # SABnzbd style illegal chars
- illegal = r'\/<>?*:;|"'
- legal = r'++{}!@--#`'
- translate_table = string.maketrans(illegal, legal)
- #Directory Seperator Character (default linux)
- ds="/"
- #If Win32 then double backslash
- if sys.platform == "win32":
- ds="\\"
- already=[]
- #RegEx Compiles
- daily=re.compile("([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9])|([0-9][0-9][0-9][0-9]\.[0-9][0-9]\.[0-9][0-9])")
- video_formats_re = re.compile( video_formats, re.IGNORECASE )
- class SimpleCache:
- def __init__(self, filename="TVDBNames.cache", debug=1, safe=1):
- self.file = os.path.join(os.path.dirname(sys.argv[0]),filename)
- self.debug = debug
- self.safe = safe
- self.init = 0
- self.msg("loading " + self.file + " .. ")
- try:
- cached = file(self.file,"r")
- except IOError, EOFError:
- try:
- self.msg("new cache file: " + self.file)
- cached = file(self.file,"w")
- self.data = {'evalcacheversion_creation':'20090212a-jmf'}
- self.msg(self.data)
- pickle.dump(self.data, cached)
- cached.close()
- self.msg(".. created.")
- cached = file(self.file,"r")
- except IOError, EOFError:
- self.msg("cannot open/create " + self.file)
- return 0
- self.data = pickle.load(cached)
- self.msg(".. done.")
- self.msg(self.data)
- cached.close()
- def msg(self, val):
- if self.debug:
- print val
- def save(self):
- self.msg("saving " + self.file)
- self.msg(self.data)
- try:
- cached = file(self.file,"w")
- pickle.dump(self.data, cached)
- cached.close()
- except IOError:
- self.msg("error")
- self.msg(".. done.")
- def read(self, key):
- self.msg("looking for " + str(key))
- if str(key) in self.data:
- if self.debug:
- self.msg("hit: " + str(key) + " = " + str(self.data[str(key)]))
- return self.data[str(key)]
- self.msg("not cached.")
- return 0
- def write(self, key, value):
- self.msg("storing " + str(key))
- self.data[str(key)] = str(value)
- if self.debug and self.data[str(key)]:
- self.msg(".. done: " + str(self.data[str(key)]))
- if self.safe:
- self.save()
- return self.data[str(key)]
- # end class SimpleCache
- cache = SimpleCache()
- def removeIllegalChars(origstring):
- if SABnzbdIllegalCharsStyle:
- try:
- return str(origstring).translate(translate_table)
- except:
- return origstring
- else:
- try:
- # convert unicode to ASCII
- newstring = origstring.encode('ascii', 'ignore')
- # replace illegal chars with nothing
- return re.sub("[*:<>|]", "", newstring).strip()
- except:
- return origstring
- #end if SABnzbdIllegalStyle
- #end def removeIllegalChars
- def isInQueue(download_title):
- queue=xml.dom.minidom.parse(urllib.urlopen(my_SAB + "/sabnzbd/api?mode=qstatus&output=xml" + "&apikey=" + SAB_API_KEY + "&ma_username=" + my_SAB_username + "&ma_password=" + my_SAB_password))
- for job in queue.getElementsByTagName("job"):
- filename=job.getElementsByTagName("filename")[0].childNodes[0].data
- regex_download_title_string = removeIllegalChars(download_title)
- regex_download_title = re.compile(regex_download_title_string, re.IGNORECASE)
- if re.match(regex_download_title, filename):
- if debug:
- logger.info("IS IN QUEUE: " + regex_download_title.pattern)
- #end if debug
- return 1
- #end if re.match
- #end for job
- if debug:
- logger.info("IS NOT IN QUEUE: " + regex_download_title.pattern)
- #end if debug
- return 0
- #end def isInQueue
- def isInQueueSmart(nzbDetails):
- logger.info("ENTERED isInQueueSmart")
- # Compile the regex
- regex_download_title = re.compile(nzbDetails['SeriesName'] + " - S" + str(nzbDetails['SeasonNumber_Type' + SeasonType]) + "E" + str(nzbDetails['EpisodeNumber_Type' + EpisodeType]), re.IGNORECASE)
- # Get the Queue
- queue=xml.dom.minidom.parse(urllib.urlopen(my_SAB + "/sabnzbd/api?mode=qstatus&output=xml" + "&apikey=" + SAB_API_KEY + "&ma_username=" + my_SAB_username + "&ma_password=" + my_SAB_password))
- # Process each job in Queue
- for job in queue.getElementsByTagName("job"):
- filename=job.getElementsByTagName("filename")[0].childNodes[0].data
- try:
- if debug:
- logger.info("CHECK QUEUE: " + filename)
- #end if debug
- filename = formatReport(filename)
- series,epstr,eptitle=filename.split(' - ')
- series=cleanSeriesName(series)
- filename=series + " - " + epstr + " - " + eptitle
- if debug:
- logger.info("CHECK REFORMAT QUEUE: " + filename)
- #end if debug
- if re.search(regex_download_title, filename):
- if debug:
- logger.info("IS IN QUEUE: " + regex_download_title.pattern)
- #end if debug
- return 1
- #end if re.match
- except:
- # Queue Check Failed, so assume it's not in Queue
- pass
- #end for job
- if debug:
- logger.info("IS NOT IN QUEUE: " + regex_download_title.pattern)
- #end if debug
- return 0
- #end def isInQueue
- def isInHistorySmart(series, season, episode):
- # Compile the regex
- regex_download_title = re.compile(series + " - S" + season + "E" + episode, re.IGNORECASE)
- # Get the Histroy
- queue=xml.dom.minidom.parse(urllib.urlopen(my_SAB + "/sabnzbd/api?mode=history&output=xml" + "&apikey=" + SAB_API_KEY + "&ma_username=" + my_SAB_username + "&ma_password=" + my_SAB_password))
- # Process each job in Queue
- for job in queue.getElementsByTagName("slot"):
- jobname=job.getElementsByTagName("name")[0].childNodes[0].data
- try:
- if debug:
- logger.info("CHECK HISTORY: " + jobname)
- #end if debug
- jobname=reformatReport(filename)
- series,epstr,eptitle=jobname.split(' - ')
- series=cleanSeriesName(series)
- jobname=series + " - " + epstr + " - " + eptitle
- if debug:
- logger.info("CHECK REFORMAT HISTORY: " + jobname)
- #end if debug
- if re.search(regex_download_title, jobname):
- if debug:
- printlogger.info("IS IN HISTORY: " + regex_download_title.pattern)
- #end if debug
- return 1
- #end if re.match
- except:
- # Queue Check Failed, so assume it's not in Queue
- pass
- #end for job
- if debug:
- logger.info("IS NOT IN HISTORY: " + regex_download_title.pattern)
- #end if debug
- return 0
- #end def isInHistorySmart
- def isWanted(nzbDetails):
- if debug:
- logger.info("CHECK WANTED: " + nzbDetails['SeriesName'].lower() )
- #end if debug
- for dir in tv_dirs:
- for filename in os.listdir(dir):
- #if debug:
- # logger.info("DEBUG: " + filename.lower() )
- #end if debug
- if filename.lower() == nzbDetails['SeriesName'].lower():
- if debug:
- logger.info("SHOW WANTED: " + nzbDetails['SeriesName'])
- #end if debug
- return 1
- #end if os.path
- #end for filename
- #end for dir
- if debug:
- logger.info("SHOW NOT WANTED: " + nzbDetails['SeriesName'])
- #end if debug
- return 0
- #end def isWanted
- def isFormatWanted(nzbDetails, feed_type):
- # Override Format checking for NewzBin feeds
- if feed_type == 'NewzBin':
- if debug:
- logger.info("NEWZBIN FORMAT OVERRIDE: " + nzbDetails['Report-Formatted'])
- #end if debug
- return 1
- #end if feed_type
- # Allow per Show/Season Format OverRide
- for dir in tv_dirs:
- if os.path.exists(dir + ds + nzbDetails['SeriesName'] ):
- for filename in os.listdir(dir + ds + nzbDetails['SeriesName'] ):
- if filename[9:] == 'format':
- if filename[1:3] == season:
- if re.search(filename[4:8], report , re.IGNORECASE):
- if debug:
- logger.info("SHOW FORMAT WANTED: " + nzbDetails['Report-Formatted'] )
- #end if debug
- return 1
- else:
- if debug:
- logger.info("SHOW FORMAT NOT WANTED: " + nzbDetails['Report-Formatted'] )
- #end if debug
- return 0
- #end if re.search
- #end if file[1:3]
- #end if file[9:]
- #end for file
- #end if os.path
- #end for dir
- # General Format Wanted
- # Used if Show/Season not specified
- format_object = video_formats_re.search( nzbDetails['Report-Formatted'] , re.IGNORECASE)
- if format_object:
- if debug:
- logger.info("FORMAT WANTED: " + nzbDetails['Report-Formatted'] )
- #end if debug
- return 1
- #end if format_object
- if debug:
- logger.info("FORMAT NOT WANTED: " + video_formats_re.pattern + " " + nzbDetails['Report-Formatted'] )
- #end if debug
- raise FormatNotWanted
- #end def isFormatWanted
- def isMissing(nzbDetails):
- logger.info("LOOKING: " + "Season " + str(nzbDetails['SeasonNumber']) + ", Episode " + str(nzbDetails['EpisodeNumber']) )
- for dir in tv_dirs:
- nzbDetails['FolderName'] = showToFolder(nzbDetails['SeriesName'])
- logger.info("FOLDERNAME: " + nzbDetails['FolderName'] )
- series_path=dir + ds + nzbDetails['FolderName'] + ds + "Season " + str(nzbDetails['SeasonNumber_Type' + SeasonType])
- logger.info("CHECK: " + nzbDetails['SeriesName'] + " for seasons to IGNORE")
- # ignore this season if told to do so (existence of file or directory called ignore Season x)
- if os.path.exists(dir + ds + nzbDetails['FolderName'] + ds + "ignore Season " + str(nzbDetails['SeasonNumber_Type' + SeasonType]) ):
- if debug:
- logger.info("IGNORE: Season " + str(nzbDetails['SeasonNumber']) )
- #end if debug
- return 0
- else:
- if debug:
- logger.info("PROCESS: Season " + str(nzbDetails['SeasonNumber_Type' + SeasonType]) )
- #end if debug
- #end if os.path.exists
- if os.path.exists(series_path):
- if debug:
- logger.info("EXIST: " + series_path)
- #end if debug
- for tested_episode in os.listdir(series_path):
- if debug:
- logger.info("CHECK: " + tested_episode)
- #end if debug
- for r in config['name_parse']:
- match = r.match(tested_episode)
- if match:
- logger.info("FOUND " + str(match.lastindex) + " Items.")
- if match.lastindex == 4:
- seriesname, seasno, epno, epname = match.groups()
- elif match.lastindex == 3:
- seriesname, seasno, epno = match.groups()
- #end if
- if re.search(nzbDetails['SeriesName'], seriesname, re.IGNORECASE):
- if seasno == nzbDetails['SeasonNumber_Type' + SeasonType]:
- if epno == nzbDetails['EpisodeNumber_Type' + SeasonType]:
- if debug:
- logger.info("MATCH FOUND: " + "Season " + str(nzbDetails['SeasonNumber']) + ", Episode " + str(nzbDetails['EpisodeNumber']) )
- #end if debug
- return 0
- #end if epno
- #end if seasno
- #end if seriesname
- #end if match
- #end for r
- #end for tested_episode
- else:
- if debug:
- logger.info("NOT EXIST: " + series_path)
- #end if debug
- #end if os.path.exists
- if debug:
- logger.info("MISSING: " + "Season " + str(nzbDetails['SeasonNumber']) + ", Episode " + str(nzbDetails['EpisodeNumber']) )
- #end if debug
- #end for dir
- return 1
- #end def isMissing
- def addToQueue(report_id, feed_type):
- logger.info("ADD QUEUE: " + time.strftime("%Y-%m-%d %H:%M:%S")+": "+ report_id)
- #if feed_type == 'NewzBin':
- # NewzBin RSS
- #newzbin_id = re.search('[0-9][0-9][0-9]+',report_id)
- #if newzbin_id:
- # report_id = re.sub("/", "", newzbin_id.group(0))
- # logger.info("REPORT_ID: " + report_id)
- # urllib.urlopen(my_SAB + "/sabnzbd/api?mode=addid&name=" + report_id + my_SAB_params + "&apikey=" + SAB_API_KEY + "&ma_username=" + my_SAB_username + "&ma_password=" + my_SAB_password)
- if feed_type == 'NewzBin':
- # NewzBin RSS - Commented Out....
- newzbin_id = re.search('[0-9][0-9][0-9]+',report_id)
- if newzbin_id:
- report_id = re.sub("/", "", newzbin_id.group(0))
- logger.info("REPORT_ID: " + report_id)
- urllib.urlopen(my_SAB + "/sabnzbd/api?mode=addid"+ "&name=" + report_id + my_SAB_params + "&apikey=" + SAB_API_KEY)
- #urllib.urlopen(my_SAB + "/sabnzbd/api?mode=addid"+ "&name=" + report_id + my_SAB_params + "&ma_username=" + my_SAB_username + "&ma_password=" + my_SAB_password + "&apikey=" + SAB_API_KEY)
- else:
- # 'Other' NZB RSS
- urllib.urlopen(my_SAB + "/sabnzbd/api?mode=addurl&name=" + report_id + my_SAB_params + "&apikey=" + SAB_API_KEY + "&ma_username=" + my_SAB_username + "&ma_password=" + my_SAB_password)
- #end if
- #end def download
- def downloadNZB(nzb_url, report):
- logger.info("DOWNLOADING: " + nzb_url)
- # Code originally taken from urlgrabber.py (SABnzbd Team)
- opener = urllib.FancyURLopener({})
- opener.prompt_user_passwd = None
- opener.addheader('Accept-encoding','gzip')
- filename = NZB_BlackHole + ds + report + '.nzb'
- try:
- fn, header = opener.retrieve(nzb_url, filename)
- return 1
- except:
- fn = None
- filename = True
- return 0
- #end def downloadNZB
- def cleanSeriesNameCache(series_title):
- global cache
- theTVDB = Tvdb(debug = tvdb_debug, interactive = tvdb_interactive)
- good_series_title = removeIllegalChars(series_title)
- #good_series_title = good_series_title.replace("(", "\(").replace(")", "\)")
- good_series_title = re.sub('\.|_', ' ', good_series_title)
- if debug:
- logger.info("NZB: " + good_series_title)
- #end if debug
- try:
- good_series_title = showAlias(good_series_title)
- if cache.read(good_series_title.lower()):
- good_series_title = cache.read(good_series_title.lower())
- else:
- good_series_title = cache.write(good_series_title.lower(),theTVDB[good_series_title]['seriesname'])
- #end if cache.read
- if debug:
- logger.info("TVDB: " + good_series_title)
- #end if debug
- except tvdb_shownotfound:
- # Didn't find the show @ theTVDB,
- # most likely has 'and' and theTVDB has '&'
- try:
- if cache.read(re.sub(' [aA]nd ', ' & ', good_series_title.lower())):
- good_series_title = cache.read(re.sub(' [aA]nd ', ' & ', good_series_title.lower()))
- else:
- good_series_title = cache.write(good_series_title.strtolower(),theTVDB[re.sub(' [aA]nd ', ' & ', good_series_title.strtolower())]['seriesname'])
- #end if cache.read
- if debug:
- logger.info("TVDB: " + good_series_title)
- #end if debug
- except tvdb_shownotfound:
- # Well, didn't find it a second time, even using '&'
- # return cleaned good_series_title
- good_series_title = good_series_title
- if debug:
- logger.info("TVDB NOT FOUND: " + good_series_title)
- #end if debug
- #If Win32 then remove illegal chars
- if sys.platform == "win32" or force_windows_compliant_filenames:
- good_series_title = removeIllegalChars(good_series_title)
- #end if sys.platform
- return good_series_title
- #end def cleanSeriesNameCache
- def cleanSeriesName(series_title):
- good_series_title = removeIllegalChars(series_title)
- #good_series_title = good_series_title.replace("(", "\(").replace(")", "\)")
- good_series_title = re.sub('\.|_', ' ', good_series_title)
- theTVDB = Tvdb(debug = tvdb_debug, interactive = tvdb_interactive)
- if debug:
- logger.info("NZB: " + good_series_title)
- #end if debug
- try:
- good_series_title = showAlias(good_series_title)
- good_series_title = theTVDB[ good_series_title ]['seriesname']
- if debug:
- logger.info("TVDB: " + good_series_title)
- #end if debug
- except tvdb_shownotfound:
- # Didn't find the show @ theTVDB,
- # most likely has 'and' and theTVDB has '&'
- try:
- good_series_title = theTVDB[ re.sub(' [aA]nd ', ' & ', good_series_title) ]['seriesname']
- if debug:
- logger.info("TVDB: " + good_series_title)
- #end if debug
- except tvdb_shownotfound:
- # Well, didn't find it a second time, even using '&'
- # return cleaned good_series_title
- good_series_title = good_series_title
- if debug:
- logger.info("TVDB NOT FOUND: " + good_series_title)
- #end if debug
- #If Win32 then remove illegal chars
- if sys.platform == "win32" or force_windows_compliant_filenames:
- good_series_title = removeIllegalChars(good_series_title)
- #end if sys.platform
- return good_series_title
- #end def cleanSeriesName
- def formatReport( report ):
- # format into ' - ' seperated parts
- # showname - seasonepisode - title
- for r in config['name_parse']:
- match = r.match( report )
- if match:
- seriesname, seasno, epno, epname = match.groups()
- # Remove any space dash space that might be left over
- # We're going to put them in anyway but need to make sure we don't 'double' them
- reportdict['seriesname'] = re.sub("\s\-\s|\s\-", "", seriesname)
- reportdict['seasno'] = int(seasno)
- reportdict['epno'] = int(epno)
- reportdict['epname'] = re.sub("\s\-\s|\s\-", "", epname)
- # Format the report name
- report = config['with_ep_name'] % (reportdict)
- return report
- #end if match
- #end for r
- raise formatError
- #end def formatReport
- def showAlias(showname):
- # Takes a showname and matches it to an alias
- # e.g. CSI should map to CSI: Crime Scene Investigation and not CSI: NY
- # as returned by theTVDB api
- for alias in aliases.items('ALIASES'):
- if re.match(alias[0], showname, re.IGNORECASE):
- logger.info("MATCHED " + alias[1])
- return alias[1]
- #end if re.match
- #end for alias
- # Didn't match anything so return the passed showname
- return showname
- #def showAlias
- def showToFolder(showname):
- # Takes a showname and returns the foldername associated
- # e.g. CSI NY could return CSI New York
- for folder_alias in aliases.items('FOLDER ALIASES'):
- if re.match(folder_alias[0], showname, re.IGNORECASE):
- logger.info("MATCHED " + folder_alias[1])
- return folder_alias[1]
- #end if re.match
- #end for alias
- # Didn't match anything so return the passed showname
- return showname
- #def showToFolder
- def Main():
- for feed in nzbfeeds:
- logger.info("PROCESS NZB FEED: " + feed)
- # Set feed type
- # NewzBin feeds have different 'titles'
- if re.search('newzbin', feed, re.IGNORECASE):
- feed_type = 'NewzBin'
- if debug:
- logger.debug("FEED: " + feed_type)
- #end if debug
- elif re.search('nzbs.org', feed, re.IGNORECASE):
- feed_type = 'nzbs.org'
- if debug:
- logger.debug("FEED: " + feed_type)
- #end if debug
- else:
- feed_type = 'Other'
- if debug:
- logger.debug("FEED: " + feed_type)
- #end if debug
- #end if re.search
- # use feedparser to parse the 'feed'
- RSSfeed = feedparser.parse( feed )
- for RSSitem in RSSfeed.entries:
- nzbDetails['Report-Original'] = RSSitem.title
- logger.info("PROCESSING: " + nzbDetails['Report-Original'] )
- try:
- nzbDetails['Report-Formatted'] = formatReport( nzbDetails['Report-Original'] )
- #Split report into 3 parts
- series,epstr,title = nzbDetails['Report-Formatted'].split(' - ')
- if daily.match(epstr):
- year,month,date=epstr.split("-")
- season=year+"-"+month
- episode=date
- else:
- season = epstr[1:3]
- episode = epstr[4:]
- #end if daily.match
- # Clean series name here (reduces number of times the same code is called)
- nzbDetails['SeriesName'] =cleanSeriesName(series)
- nzbDetails['SeasonNumber'] = int(season)
- nzbDetails['EpisodeNumber'] = int(episode)
- nzbDetails['SeasonNumber_Type2'] = '%(SeasonNumber)d' % nzbDetails
- nzbDetails['SeasonNumber_Type1'] = '%(SeasonNumber)02d' % nzbDetails
- nzbDetails['EpisodeNumber_Type2'] = '%(EpisodeNumber)d' % nzbDetails
- nzbDetails['EpisodeNumber_Type1'] = '%(EpisodeNumber)02d' % nzbDetails
- toDownload = False
- if isWanted(nzbDetails):
- if isFormatWanted(nzbDetails, feed_type):
- if isMissing(nzbDetails):
- if not useSmartQueue:
- if not isInQueue(nzbDetails):
- toDownload = True
- #end if not isInQueue
- else:
- if not isInQueueSmart(nzbDetails):
- toDownload = True
- #end if not isInQueueSmart
- #end if useSmartQueue
- #end if isMissing
- #end if isFormatWanted
- #end if isWanted(seies)
- if toDownload:
- if feed_type == 'NewzBin':
- msgid=RSSitem.id
- elif feed_type == 'nzbs.org':
- msgid=RSSitem.guid
- else:
- msgid=RSSitem.link
- #end if NewzBin
- msgid=urllib.quote(msgid, safe=":/")
- if NZBdownload:
- downloadNZB(msgid, nzbDetails['Report-Formatted'] )
- else:
- addToQueue(msgid, feed_type)
- #end if NZBdownload
- #end if toDownload
- except KeyboardInterrupt:
- logger.info("CTRL-C Intercepted.")
- logger.info("Exiting......")
- logging.shutdown()
- sys.exit(0)
- except:
- logger.info("FAILED PROCESSING: " + nzbDetails['Report-Original'] )
- pass
- #end try:
- #end for RSSitem
- #end for feed
- # Shutdown logging
- logging.shutdown()
- sys.exit(0)
- #end def Main
- if __name__ == '__main__':
- Main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement