From 62052c98d6052c357d6cf7f1aca7d4f88bb66665 Mon Sep 17 00:00:00 2001 From: Matthew Trumbell Date: Fri, 20 Feb 2009 15:27:47 -0600 Subject: [PATCH] De-scripted the thetvdb module. --- meliman.py | 24 ++-- thetvdb.py | 326 ++++++++++++++++++++++++++--------------------------- 2 files changed, 171 insertions(+), 179 deletions(-) diff --git a/meliman.py b/meliman.py index 5a8cd33..7c39f78 100755 --- a/meliman.py +++ b/meliman.py @@ -10,10 +10,10 @@ from datetime import datetime from config import MelimanConfig +from thetvdb import TheTvDb import database import file_manager import metadata -import thetvdb def main(): @@ -40,7 +40,7 @@ def parse_options(): action_group = OptionGroup(opt_parser, "Options Triggering an Action", "Exactly one of these must be present in every run.") action_group.add_option("-s", "--series-lookup", action="store", dest="series_lookup", help="Lookup the TV series matching the provided string.", metavar="SERIES_NAME") - action_group.add_option("-e", "--episode-lookup", action="store", dest="episode_lookup", help="Lookup the TV episode matching the pattern: 'series_id[:series_number[:episode_number]]'", metavar="EPISODE_PATTERN") + action_group.add_option("-e", "--episode-lookup", action="store", dest="episode_lookup", help="Lookup the TV episode matching the pattern: 'series_id[:season_number[:episode_number]]'", metavar="EPISODE_PATTERN") action_group.add_option("-w", "--watch-series", action="store", dest="watch_series", help="Tells the application to start watching the series with the provided id.", metavar="SERIES_ID") action_group.add_option("-u", "--unwatch-series", action="store", dest="unwatch_series", help="Tells the application to stop watching the series with the provided id.", metavar="SERIES_ID") action_group.add_option("-l", "--list-watched-series", action="store_true", dest="list_watched_series", help="Lists the series currently being watched by the application.") @@ -104,7 +104,7 @@ def do_action(options, args, config, debug, move): def do_series_lookup(name, config, debug): try: - thetvdb.init(config, debug) + thetvdb = TheTvDb(config, debug) database.init(config) results = thetvdb.lookup_series_info(name, debug) @@ -121,7 +121,7 @@ def do_series_lookup(name, config, debug): def do_episode_lookup(episode_search_pattern, config, debug): try: - thetvdb.init(config, debug) + thetvdb = TheTvDb(config, debug) database.init(config) split_pattern = episode_search_pattern.split(':') @@ -152,7 +152,7 @@ def do_episode_lookup(episode_search_pattern, config, debug): season = int(split_pattern[1]) episode = int(split_pattern[2]) - result = get_specific_episode(series, season, episode, debug) + result = get_specific_episode(thetvdb, series, season, episode, debug) if result is None: print "Could not locate an episode matching pattern: %s" % (episode_search_pattern, ) return 3 @@ -164,7 +164,7 @@ def do_episode_lookup(episode_search_pattern, config, debug): traceback.print_exc() return 11 -def get_specific_episode(series, season_number, episode_number, debug): +def get_specific_episode(thetvdb, series, season_number, episode_number, debug): result = database.get_episode(series.id, season_number, episode_number) if result is None: result = thetvdb.get_specific_episode(series, season_number, episode_number, debug) @@ -193,7 +193,7 @@ def do_unwatch_series(series_id_str, config, debug): def watch_series_guts(series_id_str, watch, config, debug): try: - thetvdb.init(config, debug) + thetvdb = TheTvDb(config, debug) database.init(config) try: @@ -233,7 +233,7 @@ def print_series(series_list): def do_clear_episodes(series_id_str, config, debug): try: - thetvdb.init(config, debug) + thetvdb = TheTvDb(config, debug) database.init(config) try: @@ -257,7 +257,7 @@ def do_clear_episodes(series_id_str, config, debug): def do_cleanup_file_name(input_file_name, config, debug): try: - thetvdb.init(config, debug) + thetvdb = TheTvDb(config, debug) database.init(config) file_manager.init(config) @@ -278,7 +278,7 @@ def do_cleanup_file_name(input_file_name, config, debug): def do_metadata(input_file_path, config, debug): try: - thetvdb.init(config, debug) + thetvdb = TheTvDb(config, debug) database.init(config) file_manager.init(config) @@ -309,7 +309,7 @@ def do_generate(input_directory, config, debug): return 1 try: - thetvdb.init(config, debug) + thetvdb = TheTvDb(config, debug) database.init(config) file_manager.init(config) @@ -352,7 +352,7 @@ def do_regenerate(config, debug): def do_process(config, debug, move): - thetvdb.init(config, debug) + thetvdb = TheTvDb(config, debug) database.init(config) file_manager.init(config) diff --git a/thetvdb.py b/thetvdb.py index a072e31..92a9c69 100644 --- a/thetvdb.py +++ b/thetvdb.py @@ -18,235 +18,227 @@ API_KEY = "0403764A0DA51955" +class TheTvDb: + # this finds an acceptable mirror for future thetvdb requests. + def __init__(self, config, debug): + full_url = MIRROR_URL % (API_KEY, ) -# this finds an acceptable mirror for future thetvdb requests. -def init(config, debug): - global active_mirror + mirrors_xml = parse(urllib2.urlopen(full_url)) + mirrors = mirrors_xml.findall('Mirror') - full_url = MIRROR_URL % (API_KEY, ) + random.seed() + mirror_to_get = random.randrange(0, len(mirrors), 1) - mirrors_xml = parse(urllib2.urlopen(full_url)) - mirrors = mirrors_xml.findall('Mirror') - - random.seed() - mirror_to_get = random.randrange(0, len(mirrors), 1) - - mirror = mirrors[mirror_to_get] - active_mirror = mirror.findtext('mirrorpath') - - if debug: - print "Using thetvdb mirror: %s" % (active_mirror, ) + mirror = mirrors[mirror_to_get] + self.active_mirror = mirror.findtext('mirrorpath') + if debug: + print "Using thetvdb mirror: %s" % (self.active_mirror, ) -# returns an integer timestamp -def get_server_time(debug): - global active_mirror - full_url = active_mirror + SERVER_TIME_URL % (API_KEY, ) - if debug: - print "Getting data for url: %s" % full_url + # returns an integer timestamp + def get_server_time(self, debug): + full_url = self.active_mirror + SERVER_TIME_URL % (API_KEY, ) - series_xml = parse(urllib2.urlopen(full_url)) - data_element = series_xml.getroot() - to_return = int(data_element.attrib['time']) + if debug: + print "Getting data for url: %s" % full_url - if debug: - print " result: %i" % to_return + series_xml = parse(urllib2.urlopen(full_url)) + data_element = series_xml.getroot() + to_return = int(data_element.attrib['time']) - return to_return + if debug: + print " result: %i" % to_return + return to_return -# returns a metadata.Series object -def lookup_series_info(name, debug): - global active_mirror - full_url = active_mirror + SERIES_LOOKUP_URL % (name.strip().replace(' ', '%20'),) - if debug: - print "Getting data for url: %s" % full_url + # returns a metadata.Series object + def lookup_series_info(self, name, debug): + full_url = self.active_mirror + SERIES_LOOKUP_URL % (name.strip().replace(' ', '%20'),) - series_xml = parse(urllib2.urlopen(full_url)) - series = [Series for Series in series_xml.findall('Series')] + if debug: + print "Getting data for url: %s" % full_url + + series_xml = parse(urllib2.urlopen(full_url)) + series = [Series for Series in series_xml.findall('Series')] + + # now that we have the id's, get the full series info + full_series = [] + for s in series: + id = self.get_int(s, 'id', 0) + full_url = self.active_mirror + SERIES_URL % (API_KEY, id) + full_series_xml = parse(urllib2.urlopen(full_url)) + for full_s in full_series_xml.findall('Series'): + full_series.append(full_s) + + if debug: + print " found %i series:" % len(full_series) - # now that we have the id's, get the full series info - full_series = [] - for s in series: - id = get_int(s, 'id', 0) - full_url = active_mirror + SERIES_URL % (API_KEY, id) - full_series_xml = parse(urllib2.urlopen(full_url)) - for full_s in full_series_xml.findall('Series'): - full_series.append(full_s) + to_return = [] - if debug: - print " found %i series:" % len(full_series) + for s in full_series: + s_obj = self.parse_series_xml(s) + to_return.append(s_obj) - to_return = [] - - for s in full_series: - s_obj = parse_series_xml(s) - to_return.append(s_obj) + if debug: + print " found series '%s'" % s_obj.title - if debug: - print " found series '%s'" % s_obj.title - - return to_return + return to_return -# returns a list of metadata.Episode objects: -def get_full_episode_list(series, debug): - global active_mirror - full_url = active_mirror + EPISODE_HISTORY_URL % (API_KEY, series.id) + # returns a list of metadata.Episode objects: + def get_full_episode_list(self, series, debug): + full_url = self.active_mirror + EPISODE_HISTORY_URL % (API_KEY, series.id) - if debug: - print "Getting data for url: %s" % full_url - - zip_stream = urllib2.urlopen(full_url) - zip_file_string = create_string_from_stream(zip_stream, debug) - local_stream = StringIO.StringIO(zip_file_string) - zip_file = zipfile.ZipFile(local_stream) + if debug: + print "Getting data for url: %s" % full_url - episode_xml = zip_file.read('en.xml') - to_return = parse_episode_xml(episode_xml, series, debug) + zip_stream = urllib2.urlopen(full_url) + zip_file_string = self.create_string_from_stream(zip_stream, debug) + local_stream = StringIO.StringIO(zip_file_string) + zip_file = zipfile.ZipFile(local_stream) - return to_return + episode_xml = zip_file.read('en.xml') + to_return = self.parse_episode_xml(episode_xml, series, debug) + return to_return -# returns a metadata.Episode object -def get_specific_episode(series, season_number, episode_number, debug): - global active_mirror - full_url = active_mirror + EPISODE_URL % (API_KEY, series.id, season_number, episode_number) - if debug: - print "Getting data for url: %s" % full_url + # returns a metadata.Episode object + def get_specific_episode(self, series, season_number, episode_number, debug): + full_url = self.active_mirror + EPISODE_URL % (API_KEY, series.id, season_number, episode_number) - try: - xml_stream = urllib2.urlopen(full_url) - xml_file_string = create_string_from_stream(xml_stream, debug) - to_return = parse_episode_xml(xml_file_string, series, debug) + if debug: + print "Getting data for url: %s" % full_url - return to_return[0] - except urllib2.HTTPError: - return None + try: + xml_stream = urllib2.urlopen(full_url) + xml_file_string = self.create_string_from_stream(xml_stream, debug) + to_return = self.parse_episode_xml(xml_file_string, series, debug) + return to_return[0] + except urllib2.HTTPError: + return None -# returns a metadata.Episode object -def get_specific_episode_by_date(series, year, month, day, debug): - global active_mirror - formatted_date='%i-%i-%i' % (year, month, day) - full_url = active_mirror + EPISODE_LOOKUP_BY_DATE_URL % (API_KEY, series.id, formatted_date) + # returns a metadata.Episode object + def get_specific_episode_by_date(self, series, year, month, day, debug): + formatted_date='%i-%i-%i' % (year, month, day) + full_url = self.active_mirror + EPISODE_LOOKUP_BY_DATE_URL % (API_KEY, series.id, formatted_date) - if debug: - print "Getting data for url: %s" % full_url + if debug: + print "Getting data for url: %s" % full_url - try: - xml_stream = urllib2.urlopen(full_url) - xml_file_string = create_string_from_stream(xml_stream, debug) - to_return = parse_episode_xml(xml_file_string, series, debug) + try: + xml_stream = urllib2.urlopen(full_url) + xml_file_string = self.create_string_from_stream(xml_stream, debug) + to_return = self.parse_episode_xml(xml_file_string, series, debug) - return to_return[0] - except urllib2.HTTPError: - return None + return to_return[0] + except urllib2.HTTPError: + return None -def create_string_from_stream(stream, debug): - to_return = '' + def create_string_from_stream(self, stream, debug): + to_return = '' - try: - while True: - to_return = to_return + stream.next() - except: - to_return = to_return + try: + while True: + to_return = to_return + stream.next() + except: + to_return = to_return - return to_return + return to_return -def parse_series_xml(series_xml): - to_return = metadata.Series() + def parse_series_xml(self, series_xml): + to_return = metadata.Series() - to_return.id = get_int(series_xml, 'id', -1) - to_return.zap2it_id = get_string(series_xml, 'zap2it_id', '') - to_return.imdb_id = get_string(series_xml, 'IMDB_ID', '') - to_return.title = get_string(series_xml, 'SeriesName', '') - to_return.description = get_string(series_xml, 'Overview', '') - to_return.actors = get_string_list(series_xml, 'Actors', '|', []) - to_return.genres = get_string_list(series_xml, 'Genre', '|', []) - to_return.content_rating = get_string(series_xml, 'ContentRating', '') + to_return.id = self.get_int(series_xml, 'id', -1) + to_return.zap2it_id = self.get_string(series_xml, 'zap2it_id', '') + to_return.imdb_id = self.get_string(series_xml, 'IMDB_ID', '') + to_return.title = self.get_string(series_xml, 'SeriesName', '') + to_return.description = self.get_string(series_xml, 'Overview', '') + to_return.actors = self.get_string_list(series_xml, 'Actors', '|', []) + to_return.genres = self.get_string_list(series_xml, 'Genre', '|', []) + to_return.content_rating = self.get_string(series_xml, 'ContentRating', '') - return to_return + return to_return -def parse_episode_xml(xml_string, series, debug): - xml_stream = StringIO.StringIO(xml_string) - xml_object = parse(xml_stream) - episodes = [Episode for Episode in xml_object.findall('Episode')] + def parse_episode_xml(self, xml_string, series, debug): + xml_stream = StringIO.StringIO(xml_string) + xml_object = parse(xml_stream) + episodes = [Episode for Episode in xml_object.findall('Episode')] - to_return = [] + to_return = [] - for episode in episodes: - episode_metadata = metadata.Episode() - to_return.append(episode_metadata) + for episode in episodes: + episode_metadata = metadata.Episode() + to_return.append(episode_metadata) - episode_metadata.series = series; + episode_metadata.series = series; - episode_metadata.title = get_string(episode, 'EpisodeName', '') - episode_metadata.description = get_string(episode, 'Overview', '') - episode_metadata.rating = get_float(episode, 'Rating', 0.0) + episode_metadata.title = self.get_string(episode, 'EpisodeName', '') + episode_metadata.description = self.get_string(episode, 'Overview', '') + episode_metadata.rating = self.get_float(episode, 'Rating', 0.0) - episode_metadata.season_number = get_int(episode, 'SeasonNumber', 0) - episode_metadata.episode_number = get_int(episode, 'EpisodeNumber', 0) + episode_metadata.season_number = self.get_int(episode, 'SeasonNumber', 0) + episode_metadata.episode_number = self.get_int(episode, 'EpisodeNumber', 0) - episode_metadata.director = get_string(episode, 'Director', '') - episode_metadata.host = get_string(episode, 'Host', '') - episode_metadata.writers = get_string_list(episode, 'Writer', ',', []) - episode_metadata.guest_stars = get_string_list(episode, 'GuestStars', '|', []) + episode_metadata.director = self.get_string(episode, 'Director', '') + episode_metadata.host = self.get_string(episode, 'Host', '') + episode_metadata.writers = self.get_string_list(episode, 'Writer', ',', []) + episode_metadata.guest_stars = self.get_string_list(episode, 'GuestStars', '|', []) - episode_metadata.original_air_date = get_datetime(episode, 'FirstAired', - None, debug) - episode_metadata.time = datetime.now() + episode_metadata.original_air_date = self.get_datetime(episode, 'FirstAired', + None, debug) + episode_metadata.time = datetime.now() - return to_return + return to_return -def get_string(xml_element, sub_element_name, default): - try: - return xml_element.findtext(sub_element_name) - except: - return default + def get_string(self, xml_element, sub_element_name, default): + try: + return xml_element.findtext(sub_element_name) + except: + return default -def get_string_list(xml_element, sub_element_name, separator, default): - try: - text = xml_element.findtext(sub_element_name) - return text.split(separator) - except: - return default + def get_string_list(self, xml_element, sub_element_name, separator, default): + try: + text = xml_element.findtext(sub_element_name) + return text.split(separator) + except: + return default -def get_int(xml_element, sub_element_name, default): - try: - return int(xml_element.findtext(sub_element_name)) - except: - return default + def get_int(self, xml_element, sub_element_name, default): + try: + return int(xml_element.findtext(sub_element_name)) + except: + return default -def get_float(xml_element, sub_element_name, default): - try: - return float(xml_element.findtext(sub_element_name)) - except: - return default + def get_float(self, xml_element, sub_element_name, default): + try: + return float(xml_element.findtext(sub_element_name)) + except: + return default -def get_datetime(xml_element, sub_element_name, default, debug): - try: - date_text = xml_element.findtext(sub_element_name) - return datetime.strptime(date_text, "%Y-%m-%d") - except ValueError: - if debug: - print "Error parsing string '%s' into datetime.\n" % date_text, - return default - except: - return default + def get_datetime(self, xml_element, sub_element_name, default, debug): + try: + date_text = xml_element.findtext(sub_element_name) + return datetime.strptime(date_text, "%Y-%m-%d") + except ValueError: + if debug: + print "Error parsing string '%s' into datetime.\n" % date_text, + return default + except: + return default