#!/usr/bin/perl # # IrTimer専用 EPGファイルを読み込んで録画予約する # # 2015.11.15 KAWAKAMI Yukio use strict; use utf8; use Encode; require bytes; use Socket; use Tk; use DateTime; # テスト用サーバ #my $HostName = "localhost"; #my $Path = "test/up.cgi"; # IrTimer接続先 my $HostName = "192.168.1.20"; my $Path = "up.cgi"; my $Port = 80; #番組名 -> CATVチャンネル番号( my %StationCh = ( "NHK総合"=>11, "NHK総合・新潟"=>11, "NHK総合1・新潟"=>11, "NHK教育"=>21, "NHKEテレ1・新潟"=>21, "NHKEテレ1新潟"=>21, "テレビ新潟"=>41, "TeNY"=>41, "TeNY1"=>41, "新潟テレビ21"=>51, "新潟テレビ21_1"=>51, "新潟放送"=>61, "BSN"=>61, "BSN1"=>61, "新潟総合テレビ"=>81, "NST1"=>81, "NHK衛星第一"=>1101, "NHKBS1"=>1101, "NHK衛星第二"=>1103, "NHKBSプレミアム"=>1101, "BS日テレ"=>1141, "BS朝日"=>1151, "BS朝日1"=>1151, "BS-i"=>1161, "BS-TBS"=>1161, "BSジャパン"=>1171, "BSフジ"=>1181, "BSフジ・181"=>1181, "WOWOWプライム"=>1191, "WOWOWライブ"=>1192, "WOWOWシネマ"=>1193, "スター・チャンネル1"=>1200, "スター・チャンネル2"=>1201, "スター・チャンネル3"=>1202, "BS11"=>1211, "Dlife"=>1258, "ディーライフ"=>1258, "BS日本映画専門チャンネル"=>2125, "BS日本映画専門ch"=>2125, "日本映画専門チャンネル"=>2125, "ザ・シネマ"=>2133, "フジテレビONE"=>2138, "フジテレビTWO"=>2139, "ナショナルジオグラフィックチャンネル"=>2142, "ナショジオチャンネル"=>2142, "TBSチャンネル1"=>2144, "時代劇専門チャンネル"=>2159, "ムービープラス"=>2220, "チャンネルNECO"=>2222, "映画・chNECO"=>2222, "イマジカBS"=>2224, "ファミリー劇場"=>2230, "ディズニー・チャンネル"=>2239, # "ディズニー・チャンネル"=>2183, "海外アニメ!カートゥーンネットワーク"=>2240, "BSアニマックス"=>2241, "アニマックス"=>2241, # "BSアニマックス"=>2149, # "アニマックス"=>2149, "キッズステーション"=>2242, "テレ朝チャンネル1"=>2245, # "テレ朝チャンネル1"=>2136, "ディスカバリー"=>2256, "ディスカバリーチャンネル"=>2256, # "ディスカバリー"=>2121, # "ディスカバリーチャンネル"=>2121, ); ################################################################# binmode(STDOUT, ":utf8"); my $Tvpi = $ARGV[0]; my $Station; my $Ch; my $Year; my $Month; my $Day; my $Start; my $End; my $Title; if (!$Tvpi){ print "usage:\tepgrsv iEPGファイル\n"; print "\n"; print "or\n"; print "\tepgrsv \n"; exit 1; } if ($Tvpi =~ /http:\/\/tv.yahoo.co.jp\//){ get_yahoo($Tvpi); } elsif ($Tvpi =~ /http:\/\//){ my $fname = download_file($Tvpi); get_epg($fname); } else { get_epg($Tvpi); } # 送信データ。IrTimerは POST内容のエンコード不要。というかデコードをサボっている my $Content = <<"CONTENT"; id=0 date=$Year/$Month/$Day start=$Start end=$End ch=$Ch title=$Title CONTENT my $content_length = bytes::length($Content); my $text; if ($Ch){ $text =<<"TEXT"; $Year/$Month/$Day $Start - $End $Station $Title この番組を録画予約しますか? TEXT } else { $text = "\n$Station のチャンネル番号が不明です\n"; } # Tkウィンドウの生成 my $TopWindow; $TopWindow = MainWindow->new(-title => "IrTimer予約"); $TopWindow->optionAdd( '*font' => 'Sans 16' ); $TopWindow->Label(-textvariable =>\$text)->pack(); my $buttons = $TopWindow->Frame()->pack(); my $ok; my $cancel; if ($Ch){ $cancel = $buttons->Button(-text => 'Cancel', -command => \&button_cancel )->pack(-side => 'left', -fill => 'x'); $buttons->Label(-text => ' ')->pack(-side => 'left', -fill => 'x'); $ok = $buttons->Button(-text => 'OK', -command => \&button_ok )->pack( -side => 'left', -fill => 'x'); } else { $ok = $buttons->Button(-text => 'OK', -command => \&button_cancel )->pack( -side => 'left', -fill => 'x'); } $ok->focus; MainLoop(); exit; # 終了 sub button_cancel{ exit; } # ファイルダウンロード sub download_file { my $url = $_[0]; my $fname = "/tmp/epgrsv_temp.html"; unlink($fname); system("wget -T30 -O $fname $url"); if (! -e $fname){ printf "File Not Download : $url\n"; exit 1; } return $fname; } # Yahoo!テレビ.Gガイドからデータを取得 sub get_yahoo { my $line; my $fname = download_file($_[0]); open(my $in, "<", $fname) or die; while($line = <$in>){ $line = decode('UTF-8', $line); if ($line =~ /class=\"yjS pb5p\"/){ $line = <$in>; $line = decode('UTF-8', $line); if ($line =~ /]*?>(.+?)(\d+)年(\d+)月(\d+)日.+?(\d+)時(\d+)分.+?(\d+)時(\d+)分/){ $Year = $1; $Month = $2; $Day = $3; my $st_h = $4; my $st_m = $5; my $ed_h = $6; my $ed_m = $7; if ($st_h >= 24){ $st_h %= 24; $ed_h %= 24; my $dt = DateTime->new( time_zone => 'local', year => $Year, month => $Month, day => $Day, hour => 0, minute => 0, second => 0 ); $dt->add(days => 1); $Year = $dt->year; $Month = sprintf("%02d", $dt->month); $Day = sprintf("%02d", $dt->day); } $Start = sprintf("%02d:%02d", $st_h, $st_m); $End = sprintf("%02d:%02d", $ed_h, $ed_m); } elsif ((!$Title && ($line =~ /itemprop=\"name\">(.+?)<\/span/))|| (!$Title && ($line =~ /\(.+?) /))){ $Title = $1; # 余分な記号を削除 if ($Title =~ /※一部地域|▽/){ $Title = $`; } $Title =~ s/\[(字|再|デ|二|映|生|終|無|新|HV|S|SS)\]//g; $Title =~ s/【.+?】//g; $Title =~ s/ / /g; $Title =~ s/\s/ /g; $Title =~ s/^ +| +$//g; } } close($in); } # iEPGファイルからデータを取得 sub get_epg { my $line; open(my $in, "<", $_[0]) or die; $line = <$in>; $line = decode('Shift_JIS', $line); if ($line !~ /^Content-type:\sapplication\/x-tv-program-/){ close($in); print "File is Not iEPG file : $_[0]\n"; exit 1; } while($line = <$in>){ $line = decode('Shift_JIS', $line); if (($line =~ /station: (.+)/)|| ($line =~ /station-name: (.+)/)){ $Station = $1; $Station =~ s/\s//g; $Station =~ tr/0-9a-zA-Z/0-9a-zA-Z/; $Ch = $StationCh{$Station}; if (!$Ch &&($Station =~ /(.+?)HD$/)){ # 局名末尾HDを削除 $Ch = $StationCh{$1}; } } elsif ($line =~ /year: (\d+)/){ $Year = $1; } elsif ($line =~ /month: (\d+)/){ $Month = $1; } elsif ($line =~ /date: (\d+)/){ $Day = $1; } elsif ($line =~ /start: ([\d:]+)/){ $Start = $1; } elsif ($line =~ /end: ([\d:]+)/){ $End = $1; } elsif ($line =~ /program-title: (.+)/){ $Title = $1; # 余分な記号を削除 if ($Title =~ /※一部地域/){ $Title = $`; } $Title =~ s/\[(字|再|デ|二|映|生|終|無|新|HV|S|SS)\]//g; $Title =~ s/【.+?】//g; $Title =~ s/ / /g; $Title =~ s/\s/ /g; $Title =~ s/^ +| +$//g; } } close($in); } # 録画予約データ送信 sub button_ok{ my $addr = inet_aton($HostName); if (!$addr){ print "$HostName : Server Not Found\n"; exit; } my $sock_addr = pack_sockaddr_in($Port, $addr); socket(SOCK, PF_INET, SOCK_STREAM, 0) or die; connect(SOCK, $sock_addr) or die; binmode(SOCK, ":utf8"); select(SOCK); $| = 1; print SOCK "POST /$Path HTTP/1.0\r\n"; print SOCK "Host: $HostName\r\n"; print SOCK "Content-Length: $content_length\r\n"; print SOCK "\r\n"; print SOCK $Content; my $linedata; my $res; my $icon = 'error'; $res = ; if ($res =~ /200 OK/){ while($linedata = ){ $linedata =~ s/\s+$//; if (length($linedata) == 0){ last; } } $linedata = ; $linedata =~ /msg\":\"(.+?)\"/; $res = $1; if ($res =~ /Inserted/){ $res = "録画予約しました"; $icon = 'info'; } } close(SOCK); $TopWindow->messageBox(-type => 'ok', -icon => $icon, -title => "IrTimer予約", -message => $res); exit; }