| 1 | #!/usr/bin/perl -w |
|---|
| 2 | |
|---|
| 3 | # OzTivo grabber |
|---|
| 4 | |
|---|
| 5 | my $version = '0.9'; |
|---|
| 6 | |
|---|
| 7 | # Requires configuration! |
|---|
| 8 | # 1. Register at http://www.tvguide.org.au/ |
|---|
| 9 | # 2. Run "./oztivo --configure" to create "oztivo.pw" file. |
|---|
| 10 | # |
|---|
| 11 | # Changelog: |
|---|
| 12 | # 0.1 : Yucky little initial version |
|---|
| 13 | # 0.2 : --ready option |
|---|
| 14 | # 0.3. : Don't log password |
|---|
| 15 | # 0.4 : Changed password filename |
|---|
| 16 | # 0.5 : Identify user agent; support gzip compression; turn off |
|---|
| 17 | # output buffering |
|---|
| 18 | # 0.6 : Decodes HTML characters |
|---|
| 19 | # 0.6.1 : Bugfix: Don't decode HTML characters (invalid XMLTV), |
|---|
| 20 | # Bugfix: translate SBS NEWS XMLTVID properly |
|---|
| 21 | # 0.7 : Decodes apostrophes |
|---|
| 22 | # 0.9 : --configure |
|---|
| 23 | |
|---|
| 24 | use strict; |
|---|
| 25 | |
|---|
| 26 | use LWP::UserAgent; |
|---|
| 27 | use Cwd; |
|---|
| 28 | use Getopt::Long; |
|---|
| 29 | use HTML::Entities; |
|---|
| 30 | |
|---|
| 31 | my $config_file = cwd() . "/oztivo.pw"; |
|---|
| 32 | my $output_file = cwd() . "/output.xmltv"; |
|---|
| 33 | my $channels_file; |
|---|
| 34 | my $channels, my $opt_channels; |
|---|
| 35 | my @clist; |
|---|
| 36 | my $ver; |
|---|
| 37 | my $ready; |
|---|
| 38 | my $configure; |
|---|
| 39 | |
|---|
| 40 | print "OzTivo Grabber v$version\n"; |
|---|
| 41 | |
|---|
| 42 | $| = 1; |
|---|
| 43 | |
|---|
| 44 | GetOptions( |
|---|
| 45 | 'channels_file=s' => \$channels_file, |
|---|
| 46 | 'output=s' => \$output_file, |
|---|
| 47 | 'version' => \$ver, |
|---|
| 48 | 'ready' => \$ready, |
|---|
| 49 | 'configure' => \$configure |
|---|
| 50 | ); |
|---|
| 51 | |
|---|
| 52 | exit 0 if ($ver); |
|---|
| 53 | |
|---|
| 54 | configure() if ($configure); |
|---|
| 55 | |
|---|
| 56 | unless (-r $config_file) |
|---|
| 57 | { |
|---|
| 58 | die "Can't find $config_file!\nTry running $0 --configure.\n"; |
|---|
| 59 | } |
|---|
| 60 | |
|---|
| 61 | print "Reading configuration file $config_file.\n"; |
|---|
| 62 | |
|---|
| 63 | |
|---|
| 64 | open(CONF, $config_file) |
|---|
| 65 | or die "Unable to read config file $config_file: $!"; |
|---|
| 66 | my $line = <CONF>; |
|---|
| 67 | close CONF; |
|---|
| 68 | |
|---|
| 69 | unless ($line =~ /^(.*):(.*)$/) |
|---|
| 70 | { |
|---|
| 71 | die "Unable to parse config file!\n" . |
|---|
| 72 | "Should be in format: username:password\n"; |
|---|
| 73 | } |
|---|
| 74 | my ($user, $pw) = ($1, $2); |
|---|
| 75 | |
|---|
| 76 | exit 0 if ($ready); |
|---|
| 77 | |
|---|
| 78 | unless ($channels_file) |
|---|
| 79 | { |
|---|
| 80 | die "No --channels_file specified.\n"; |
|---|
| 81 | } |
|---|
| 82 | |
|---|
| 83 | unless( -r $channels_file) |
|---|
| 84 | { |
|---|
| 85 | die "Unable to read channels file $channels_file: $!"; |
|---|
| 86 | } |
|---|
| 87 | local (@ARGV, $/) = ($channels_file); |
|---|
| 88 | eval <>; |
|---|
| 89 | die "\nError in channels file!\nDetails:\n$@" if ($@); |
|---|
| 90 | |
|---|
| 91 | # Create a list of channel names from longest to shortest |
|---|
| 92 | @clist = sort { length $b <=> length $a } keys %$channels; |
|---|
| 93 | print "Channels: @clist.\n"; |
|---|
| 94 | |
|---|
| 95 | my $ua = LWP::UserAgent->new(); |
|---|
| 96 | $ua->agent("Shepherd OzTivo Grabber/$version"); |
|---|
| 97 | $ua->default_header('Accept-Encoding' => 'gzip'); |
|---|
| 98 | |
|---|
| 99 | my $fn = "http://$user:YOURPASSWORD\@minnie.tuhs.org/tivo-bin/xmlguide.pl"; |
|---|
| 100 | print "Retrieving $fn...\n"; |
|---|
| 101 | |
|---|
| 102 | $fn =~ s/YOURPASSWORD/$pw/; |
|---|
| 103 | |
|---|
| 104 | my $response = $ua->get($fn); |
|---|
| 105 | unless ($response->is_success()) |
|---|
| 106 | { |
|---|
| 107 | print "Download failed.\n" . $response->status_line() . "\nExiting.\n"; |
|---|
| 108 | exit; |
|---|
| 109 | } |
|---|
| 110 | my $data = $response->content(); |
|---|
| 111 | print "Downloaded " . int((do {use bytes; length($data)}) / 1024) . "KB.\n"; |
|---|
| 112 | |
|---|
| 113 | if ($response->header('Content-Encoding') |
|---|
| 114 | and |
|---|
| 115 | $response->header('Content-Encoding') eq 'gzip') |
|---|
| 116 | { |
|---|
| 117 | print "Unzipping.\n"; |
|---|
| 118 | $data = Compress::Zlib::memGunzip($data); |
|---|
| 119 | #$data = Compress::Zlib::memGunzip($response->content()); |
|---|
| 120 | } |
|---|
| 121 | |
|---|
| 122 | # print "Decoding HTML.\n"; |
|---|
| 123 | # HTML::Entities::decode($data); |
|---|
| 124 | |
|---|
| 125 | print "Converting apostrophes.\n"; |
|---|
| 126 | $data =~ s/\'/'/g; |
|---|
| 127 | |
|---|
| 128 | print "Transforming XMLTVIDs.\n"; |
|---|
| 129 | $data =~ s/channel="(.*)"/'channel="'.subme($1).'"'/ge; |
|---|
| 130 | |
|---|
| 131 | print "Writing output.\n"; |
|---|
| 132 | open (OUT, ">$output_file"); |
|---|
| 133 | print OUT $data; |
|---|
| 134 | close OUT; |
|---|
| 135 | |
|---|
| 136 | print "Done.\n"; |
|---|
| 137 | |
|---|
| 138 | sub configure |
|---|
| 139 | { |
|---|
| 140 | print "Configuring...\n\n" . |
|---|
| 141 | "Before you can use the OzTivo grabber, you must create an\n" . |
|---|
| 142 | "account on the OzTivo website:\n\n" . |
|---|
| 143 | ' http://minnie.tuhs.org/twiki/bin/view/TWiki/TWikiRegistration' . |
|---|
| 144 | "\n\n" . |
|---|
| 145 | "When you're done, you'll have a username and a password. Enter\n" . |
|---|
| 146 | "these here.\n\n" . |
|---|
| 147 | "Username? "; |
|---|
| 148 | my $username = <>; |
|---|
| 149 | chomp $username; |
|---|
| 150 | print "Password? "; |
|---|
| 151 | my $pw = <>; |
|---|
| 152 | chomp $pw; |
|---|
| 153 | |
|---|
| 154 | print "Creating config file $config_file...\n"; |
|---|
| 155 | open (CONF, ">$config_file") |
|---|
| 156 | or die "Unable to create $config_file: $!"; |
|---|
| 157 | print CONF "$username:$pw"; |
|---|
| 158 | close CONF; |
|---|
| 159 | |
|---|
| 160 | print "Done.\n"; |
|---|
| 161 | exit 0; |
|---|
| 162 | } |
|---|
| 163 | |
|---|
| 164 | sub subme |
|---|
| 165 | { |
|---|
| 166 | my $station = shift; |
|---|
| 167 | |
|---|
| 168 | $station = "SBS NEWS" if ($station eq "SBS-NEWS"); |
|---|
| 169 | |
|---|
| 170 | foreach (@clist) |
|---|
| 171 | { |
|---|
| 172 | return $channels->{$_} if ($station =~ /$_/i); |
|---|
| 173 | } |
|---|
| 174 | print "Warning: station \"$station\" unknown.\n"; |
|---|
| 175 | return $station; |
|---|
| 176 | } |
|---|