#!/usr/bin/env python # ----------------------------------------------------------------------- # Copyright (C) 2005 Will Uther # http://www.cse.unsw.edu.au/~willu/ # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MER- # CHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. """Grab TV guide information from the Australian Community-based TV Guide version $Date: 2005-04-12 18:37:43 +1000 (Tue, 12 Apr 2005) $. See http://tvguide.org.au/ for more infomation on this guide data. The data itself is gathered from http://minnie.tuhs.org/tivo-bin/tvguide.pl . You need to register to get data from this source. Usage: tv_grab_au_tuhs [options] Options: -h / --help Print this message and exit. --version Print the date this script was last edited and exit. -v / --verbose Increase verbosity of output (to stderr) while grabbing -o / --output Output to FILE rather than standard output -d / --days Grab N days. Defaults to grabbing 7 days of guide data. --offset Start grabbing N days in the future. Defaults to 0; starting grabbing with today's data. --configure Write a default configuration file. This file will need to be edited with appropriate information. -c / --config-file Read configuration information from FILE instead of from ~/.xmltv/tv_grab_au_tuhs.py . --force-explicit-timezone Force any implicitly UTC timestamps in the XMLTV input to have an explicit timezone of +0000 in the output. Configuration File: The config file is itself a python source file (Security Note: don't run this script unless you trust the config file). It needs to contain the list of channels to grab, and must set up the authentication details. See the default config file for a basic example. """ version = "tv_grab_au: Version $Date: 2005-04-12 18:37:43 +1000 (Tue, 12 Apr 2005) $" import sys import os import getopt import time import datetime import urllib2 import string verbose = 0 output = sys.stdout time.tzset() epoch = datetime.date(1970,1,1) today = (datetime.date.today() - epoch).days start_day = today days = 7 config_file = os.path.join('.xmltv','tv_grab_au_tuhs.py') base_url = 'http://minnie.tuhs.org/tivo-bin/tvguide.pl' realm = 'Enter your WikiName: (First name and last name, no space, no dots, capitalized, e.g. JohnSmith). Cancel to register if you do not have one.' opener = None authinfo = urllib2.HTTPBasicAuthHandler() channels = None force_explicit_timezone = False XML_header = '' XMLTV_Tag = """ """ defaultConfigFile = """ global channels, authinfo channels = (('ABC-NSW','ABC Digital'),('Nine-Syd','Nine Digital'), \ ('SBS-NSW','SBS Digital'),('Seven-Syd','Seven Digital'),('Ten-NSW','Ten Digital')) authinfo.add_password(realm, 'minnie.tuhs.org', 'MyCamelCaseName', 'mypassword') """ def getHomeDir(): ''' Try to find user's home directory, otherwise return current directory.''' try: path1=os.path.expanduser("~") except: path1="" try: path2=os.environ["HOME"] except: path2="" try: path3=os.environ["USERPROFILE"] except: path3="" if not os.path.exists(path1): if not os.path.exists(path2): if not os.path.exists(path3): return os.getcwd() else: return path3 else: return path2 else: return path1 def outputChannelTag(channel): (guide_name, display_name) = channel if verbose > 1: print >> sys.stderr, "processing channel " + display_name + \ ". Using guide name: " + guide_name # channelXMLstring = '\n\t' + \ # display_name + '\n' # Joshua flipped these so he didn't lose existing setup: channelXMLstring = '\n\t' + \ guide_name + '\n' output.write(channelXMLstring) if verbose > 2: print >> sys.stderr, "channel string: ", channelXMLstring def outputDayChannel(file, guide_name, display_name): global verbose, output, force_explicit_timezone origData = file.read() if force_explicit_timezone: data = string.replace(origData, '00"', '00 +0000"') else: data = origData # Joshua added the replace for channel names # data = string.replace(data, guide_name, display_name) # This was not strict enough data = string.replace(data, 'channel="' + guide_name + '"', 'channel="' + display_name + '"') headerLoc = data.find(XML_header) if headerLoc < 0: print >> sys.stderr, "Unable to find ISO-8859-1 XML header. Ignoring channel Day." return elif verbose > 3: print >> sys.stderr, "Found ISO-8859-1 XML header at loc:", headerLoc tvLoc = data.find("> sys.stderr, "Unable to find tag. Ignoring channel Day." return elif verbose > 3: print >> sys.stderr, "Found tag at loc:", tvLoc tvEndLoc = data.find('>',tvLoc) if tvEndLoc < 0: print >> sys.stderr, "Malformed tag. Ignoring channel Day." return elif verbose > 3: print >> sys.stderr, "Found end of tag at loc:", tvEndLoc tvEndLoc = tvEndLoc+1 tvEndTagLoc = data.find('',tvEndLoc) if tvEndTagLoc < 0: print >> sys.stderr, "Unable to find tag. Ignoring channel Day." return elif verbose > 3: print >> sys.stderr, "Found tag at loc:", tvEndTagLoc if verbose > 2: print >> sys.stderr, "passing on data from ", tvEndLoc, "to", tvEndTagLoc output.write(data[tvEndLoc:tvEndTagLoc]) output.write("\n\n") def grabDayChannel(day, channel_name, channel_name2): global base_url req = urllib2.Request(base_url + '?page=rawstationday&type=view' + \ '&data=' + str(day) + '&data2=' + channel_name) if verbose > 2: print >> sys.stderr, "requesting url: ", req.get_full_url() f = None dom = None try: f = urllib2.urlopen(req) outputDayChannel(f, channel_name, channel_name2) finally: if f != None: f.close() def grab(): global channels, start_day, days, verbose, opener, authinfo opener = urllib2.build_opener(authinfo) urllib2.install_opener(opener) output.write(XML_header); output.write(XMLTV_Tag); for channel in channels: outputChannelTag(channel) for day in range(start_day, start_day + days): if verbose > 1: print >> sys.stderr, "grabbing day ", day for (guide_name, display_name) in channels: if verbose > 1: print >> sys.stderr, "grabbing channel ", guide_name grabDayChannel(day, guide_name, display_name) output.write("\n\n") def usage(): print >> sys.stderr, __doc__ def main(): global verbose, output, today, start_day, days, config_file, force_explicit_timezone try: opts, args = getopt.getopt(sys.argv[1:], \ "hvo:d:c:", ["help", "version", "verbose", "output=", "days=", "offset=", "configure", "config-file=", "force-explicit-timezone"]) except getopt.GetoptError: # print help information and exit: usage() sys.exit(2) config_file = os.path.join(getHomeDir(), config_file) configure = False for o, a in opts: if o in ("-h", "--help"): usage() sys.exit() elif o in ("--version"): print >> sys.stderr, version sys.exit(0) elif o in ("-v", "--verbose"): verbose = verbose + 1 elif o in ("-o", "--output"): if verbose > 0: print >> sys.stderr, "Outputting to file: ", a output = open(a, 'w') elif o in ("-d", "--days"): days = int(a) if verbose > 0: print >> sys.stderr, "Grabbing " + a + " days of data." elif o in ("--offset"): start_day = today + int(a) if verbose > 0: print >> sys.stderr, "Starting grab offset " + a + " days." elif o in ("--configure"): configure = True elif o in ("-c", "--config-file"): config_file = a if verbose > 0: print >> sys.stderr, "Using config file: ", config_file elif o in ("--force-explicit-timezone"): force_explicit_timezone = True if configure: print >> sys.stderr, "Resetting config file to default: ", config_file try: f = open(config_file, "w") f.write(defaultConfigFile) finally: f.close() sys.exit(0) if os.path.isfile(config_file): if verbose > 1: print >> sys.stderr, "Reading config file: ", config_file execfile(config_file) else: print >> sys.stderr, "Aborting: Config file does not exist: ", config_file, " Do you need to run with --configure?" sys.exit(2) try: grab() finally: if output != sys.stdout: output.close() output = sys.stdout if __name__ == '__main__': try: main() except KeyboardInterrupt: print >> sys.stderr, "User required program abort using Keyboard!"