Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python
- import urllib
- import xml.dom.minidom
- import re
- import time
- import os
- import sys
- import string
- from stat import S_ISDIR
- from tvdb_api import (tvdb_error, tvdb_shownotfound, tvdb_seasonnotfound,
- tvdb_episodenotfound, tvdb_episodenotfound, tvdb_attributenotfound, tvdb_userabort)
- from tvdb_api import Tvdb
- ######
- # TV #
- ######
- ################################### CHANGE LOG ######################################################
- #
- # 090103 1600 Now uses SAB 0.4.6 illegal character replacement behaviour
- # 090112 2300 Uses tvdb_api to validate show name
- # 090114 2300 Cleaned up the code, used re.pattern in print statements where possible
- # and tried to limit number of places to change for new formats by using vars
- # 090117 2300 Fixed bug - Queued name is meant to be original report, NOT reformated version
- # 090117 2330 Added required video format functionality
- # 090117 2345 Moved Season/Episode regex formats to user config area
- # 090120 2045 Added Debug setting for 'print' statements
- # Fixed IsMissing regex to look for both cases of S and E i.e. s and S
- # Fixed season_to_check variable
- # A few wording changes
- # 090121 2330 Made 'Smart' queue optional
- # Removing Illegal Chars at end of cleanSeriesName if Win32
- # Moved Format check into isWanted. Check format before checking for show.
- # Should reduce processing time by not checking all shows then finding out that format isn't wanted
- # Removed sum_file_size function as not
- # 090122 0000 Added 'extra' debug messages
- # Fixed 'Smart' Queue
- # Moved Change Log to Top of Script
- # Added 'Known Issues'
- # Made Code more consistant
- #
- ################################### CHANGE LOG ######################################################
- ################################### KNOWN ISSUES ####################################################
- #
- # Trying to fetch NZB from
- #
- ################################### KNOWN ISSUES ####################################################
- ################################### IMPORTANT INFO ##################################################
- # To ignore a whole season, create a file or directory in the directory for your show with this name
- # ignore Season x
- # e.g. c:\tv\lost\ignore Season 1
- ################################### IMPORTANT INFO ##################################################
- #################################### CHANGE TO YOUR OWN VALUES ######################################
- #
- # set this to the location of your downloads. the first entry must be your live download area
- if sys.platform == "win32":
- tv_dirs=[ "Z:" ]
- else:
- tv_dirs=[ "/shares/LVM/TV_Shows" ]
- # the RSS link to your search
- tvurl="http://feeds.feedburner.com/minimad"
- # your SABNZB address
- my_SAB="http://192.168.1.3:9002"
- # additional SAB parameters to e.g. specify the category, and/or script to run. see http://sabnzbd.wikidot.com/automation-support
- my_SAB_params="&cat=tv"
- # Use NewzBin feed
- # Changes several sections to use NewzBin specific functionality
- NewzBin=False
- # theTVDB api
- # Set tvdb_debug=True to see debug info from theTVDB api
- tvdb_debug=False
- # Set tvdb_interactive=True to select shows returned, otherwise it takes first show returned (usually the right one)
- tvdb_interactive=False
- # Required video formats
- # for x264 enter [xX]264
- # for xvid enter [xX][vV][iI][dD]
- # for 720p enter 720[pP]
- # for 1080p enter 1080[pP]
- # for multiple formats put | between them and brackets around each group e.g.
- # ([xX]264)|([xX][vV][iI][dD])
- #
- video_formats="[xX][vV][iI][dD]"
- # Season/Episode Formats
- # Standard Regex with brackets around each format and seperated by |
- season_formats="([sS][0-9][0-9])|([0-9]?[0-9][xX])"
- episode_formats="([eE][0-9][0-9])|([xX][0-9][0-9])"
- # DEBUG
- # Set to True, to print what it's doing
- debug = True
- # 'Smart' Queue checking
- # Set to True to use 'Smart' Queue checking
- # Looks for the Show, Episode in Queue rather than the filename
- useSmartQueue = True
- ################################### CHANGE TO YOUR OWN VALUES #####################################
- # Class to allow an exception to be raised
- # if format is not wanted
- class FormatNotWanted:
- pass
- 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]")
- season_re = re.compile( season_formats )
- episode_re = re.compile( episode_formats )
- video_formats_re = re.compile( video_formats )
- def removeIllegalChars(origstring):
- try:
- return str(origstring).translate(translate_table)
- except:
- return origstring
- #end def removeIllegalChars
- def isInQueue(download_title):
- queue=xml.dom.minidom.parse(urllib.urlopen(my_SAB+"/sabnzbd/api?mode=qstatus&output=xml"))
- 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:
- print("IS IN QUEUE: " + regex_download_title.pattern)
- #end if debug
- return 1
- #end if re.match
- #end for job
- if debug:
- print("IS NOT IN QUEUE: " + regex_download_title.pattern)
- #end if debug
- return 0
- #end def isInQueue
- def isInQueueSmart(series, season, episode):
- # Compile the regex
- regex_download_title = re.compile(series + " - S" + season + "E" + episode, re.IGNORECASE)
- # Get the Queue
- queue=xml.dom.minidom.parse(urllib.urlopen(my_SAB+"/sabnzbd/api?mode=qstatus&output=xml"))
- # Process each job in Queue
- for job in queue.getElementsByTagName("job"):
- filename=job.getElementsByTagName("filename")[0].childNodes[0].data
- try:
- if debug:
- print("Checking Queue Entry: " + filename)
- #end if debug
- filename=reformatReport(filename)
- series,epstr,title=report.split(' - ')
- if re.search(regex_download_title, filename):
- if debug:
- print("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:
- print("IS NOT IN QUEUE: " + regex_download_title.pattern)
- #end if debug
- return 0
- #end def isInQueue
- def isWanted(series_title, report):
- if debug:
- print("Checking if " + series_title + " is wanted")
- #end if debug
- # if not using NewzBin, perform format check
- # return 0 if its not wanted
- # No point checking your TV directory if the format isn't wanted in the first place
- if not NewzBin:
- if not isFormatWanted(report):
- if debug:
- print("Video Format not Wanted")
- #end if debug
- return 0
- if debug:
- print("Video Format is Wanted")
- #end if debug
- #end if not NewzBin
- for dir in tv_dirs:
- series_path = dir + ds+ series_title
- # print series_path
- if os.path.exists(series_path):
- if debug:
- print("WANTED: " + series_title)
- #end if debug
- return 1
- else:
- if debug:
- print("NOT WANTED: " + series_title)
- #end if debug
- return 0
- #end if os.path
- #end for dir
- #end def isWanted
- def isFormatWanted(report):
- if debug:
- print("Checking format")
- #end if debug
- format_object = video_formats_re.search( report )
- if format_object:
- return 1
- #end if format_object
- if debug:
- print("Format Not Wanted: " + report)
- #end if debug
- raise FormatNotWanted
- #end def isFormatWanted
- def isMissing(series_title, season_number, episode_number):
- #
- #regex_episode = re.compile(episode_number)
- ############### uncomment this regex episode code if you want this to work how it used to
- regex_episode = re.compile(series_title + " - S" + season_number + "E" + episode_number, re.IGNORECASE)
- print "Looking for: " + regex_episode.pattern
- ###############
- for dir in tv_dirs:
- #
- series_path=series_title + ds
- season_path=series_path + series_title + " - " + season_number
- ###############
- print "checking: "+dir
- # ignore this season if told to do so (existence of file or directory called ignore Season x)
- if os.path.exists(dir + ds + series_path + "ignore Season " + season_number):
- if debug:
- print "ignoring: Season " + season_number
- #end if debug
- return 0
- #end if os.path.exists
- if os.path.exists(dir + ds + season_path):
- if debug:
- print(season_path + " exists...")
- #end if debug
- for tested_episode in os.listdir(dir + ds + season_path):
- if debug:
- print("checking: " + tested_episode)
- #end if debug
- if re.match(regex_episode, tested_episode):
- if debug:
- print("FOUND: " + regex_episode.pattern)
- #end if debug
- return 0
- #end if re.match
- #end for tested_episode
- #end if os.path.exists
- #end for dir
- if debug:
- print("MISSING: " + regex_episode.pattern)
- #end if debug
- # create the destination directory (PRIMARY tv dir). this should prevent multiple downloads of the same thing in this session, or if we delete the download by hand
- #os.makedirs(tv_dirs[0] + ds + series_path + season_path + ds + episode_number)
- return 1
- #end def isMissing
- def download(report_id):
- print "Adding to QUEUE: " + time.strftime("%Y-%m-%d %H:%M:%S")+": "+ report
- #put your address for the api stuff here
- if NewzBin:
- #NewzBin Style
- urllib.urlopen(my_SAB+"/sabnzbd/api?mode=addid&name="+report_id+my_SAB_params)
- else:
- #'Other' NZB RSS
- urllib.urlopen(my_SAB+"/sabnzbd/api?mode=addurl&name="+report_id+my_SAB_params)
- #end if NewzBin
- #end def download
- 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:
- print "ORIG: ", good_series_title
- #end if debug
- try:
- good_series_title = theTVDB[ good_series_title ]['seriesname']
- if debug:
- print "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:
- print "TVDB2: ", 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:
- print "ERR: ", good_series_title
- #end if debug
- #If Win32 then remove illegal chars
- if sys.platform == "win32":
- good_series_title = removeIllegalChars(good_series_title)
- #end if sys.platform
- return good_series_title
- #end def cleanSeriesName
- def reformatReport(report):
- # Reformat report into ' - ' seperated parts
- # show_name - seasonepisode - title
- seasonobject = season_re.search(report)
- episodeobject = episode_re.search(report)
- # Only reformat if we have a 'report' in '.SxxExx.' or '0x00' format
- if seasonobject:
- # ShowName = Everything before '.Sxx'
- ShowName = report[:seasonobject.start()-1]
- # SeasonNumber = 'Sxx'
- SeasonLength = seasonobject.end() - seasonobject.start()
- if report[seasonobject.end()-1].lower() == 'x':
- SeasonNumber = 'S0' + report[seasonobject.start()]
- else:
- SeasonNumber = report[seasonobject.start():seasonobject.end()]
- #end if SeasonLength
- # EpisodeNumber = 'Exx'
- if report[episodeobject.start()] == 'x':
- EpisodeNumber = 'E' + report[episodeobject.start()+1:episodeobject.end()]
- else:
- EpisodeNumber = report[episodeobject.start():episodeobject.end()]
- #end if report
- # EpisodeName = Everything after 'Exx.'
- EpisodeName = report[episodeobject.end()+1:]
- # Reformat 'report'
- report=ShowName + ' - ' + SeasonNumber + EpisodeNumber + ' - ' + EpisodeName
- return report
- #def reformatReport
- dom=xml.dom.minidom.parse(urllib.urlopen(tvurl))
- for node in dom.getElementsByTagName("item"):
- report=node.getElementsByTagName("title")[0].childNodes[0].data
- report_original=report
- print "Processing :"+report
- #try-catch block because some of this stuff fails hard when it gets a weird report, and pythons default behavior is to terminate
- try:
- # Next Section for 'Other' RSS feeds
- if not NewzBin:
- report=reformatReport(report)
- #end if not Newzbin
- #Split report into 3 parts
- series,epstr,title=report.split(' - ')
- if daily.match(epstr):
- year,month,date=epstr.split("-")
- season=year+"-"+month
- episode=date
- else:
- if NewzBin:
- season,episode=epstr.split("x")
- else:
- season=epstr[1:3]
- episode=epstr[4:]
- #end if NewzBin
- #end if daily.match
- # Clean series name here (reduces number of times the same code is called)
- series=cleanSeriesName(series)
- if not useSmartQueue:
- print("Using Original Queue Check")
- if isWanted(series, report) and isMissing(series, season, episode) and (not isInQueue(report_original)):
- msgid=node.getElementsByTagName("link")[0].childNodes[0].data
- msgid=urllib.quote(msgid)
- download(msgid)
- #end if isWanted(series)
- else:
- print("Using Smart Queue Check")
- if isWanted(series, report) and isMissing(series, season, episode) and (not isInQueueSmart(series, season, episode)):
- msgid=node.getElementsByTagName("link")[0].childNodes[0].data
- msgid=urllib.quote(msgid)
- download(msgid)
- #end if isWanted(seies)
- #end if not useSmartQueue
- except:
- pass
- #end try:
- #end for node
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement