4 # Copyright (C) 2010-2011 Toni Gundogdu <legatvs@gmail.com>
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 binmode STDOUT
, ":utf8";
26 binmode STDERR
, ":utf8";
28 use version
0.77 (); our $VERSION = version
->declare("0.1.0");
30 use Getopt
::ArgvFile
(home
=> 1, startupFilename
=> [qw(.grakerc)]);
31 use Getopt
::Long
qw(:config bundling);
39 Pod
::Usage
::pod2usage
(-exitstatus
=> 0, -verbose
=> 1);
46 if ($config{'interactive'} and not eval 'require Umph::Prompt')
49 qq/WARNING Umph::Prompt not found, ignoring --interactive option/;
50 $config{interactive
} = 0;
64 'version' => \
&print_version
,
65 'help' => \
&print_help
,
68 print_help
if scalar @ARGV == 0;
70 $config{title
} = 0; # NOTE: Inaccesible from cmdline
71 $config{title
} ||= $config{interactive
}; # These imply title fetching
72 $config{title
} ||= $config{json
};
73 $config{title
} ||= $config{csv
};
80 eval "require Umph::Prompt";
81 my $p = $@ ?
"" : ", Umph::Prompt version $Umph::Prompt::VERSION";
82 say "grake version $VERSION$p
83 Copyright (C) 2010-2011 Toni Gundogdu
84 This is free software; see the source for copying conditions. There is NO
85 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.";
89 sub spew_qe
{print STDERR
@_ unless $config{quiet
}}
96 spew_qe
"Checking ...";
99 my $a = new LWP
::UserAgent
;
100 $a->env_proxy; # http://search.cpan.org/perldoc?LWP::UserAgent
101 $a->proxy('http', $config{proxy
}) if $config{proxy
};
102 $a->no_proxy('') if $config{no_proxy
};
104 # Match: /watch?v=, /v/, /embed/
105 # (At least) Hulu uses the same "/embed/" which is why we no longer
106 # use the "(?>[-_\w]{11})".
108 my $q = qr{[?/](?:embed|v)[=/]((?>[-_\w]+))};
119 unless ($r->is_success)
121 printf STDERR
"\nerror: $_: %s\n", $r->status_line;
125 my $d = URI
::Escape
::uri_unescape
($r->content);
126 @ids = weed
(uniq2
((@ids, $d =~ /$q/g)));
128 spew_qe
((++$n % 5 == 0) ?
" " : ".");
131 if (scalar @ids == 0)
133 croak
"error: nothing found\n";
135 else {spew_qe
"done.\n"}
137 spew_qe
"Get video title ..." if $config{title
};
144 url
=> "http://youtube.com/watch?v=$_",
145 gvi
=> "http://www.youtube.com/get_video_info?&video_id=$_"
146 . "&el=detailpage&ps=default&eurl=&gl=US&hl=en",
151 $tmp{title
} = get_title
($a, \
%tmp, $n) if $config{title
};
156 spew_qe
"done.\n" if $config{title
};
158 open_prompt
() if $config{interactive
};
160 say qq/{\n "video": [/ if $config{json
};
166 if ($_->{selected
} or not $config{interactive
})
170 my $t = $_->{title
} || "";
177 say qq/ "title": "$t",/;
178 say qq/ "url": "$_->{url}"/;
182 elsif ($config{csv
}) {say qq/"$t","$_->{url}"/;}
184 else {say "$_->{url}";}
188 if ($config{json
}) {say "\n ]\n}";}
194 my ($a, $video, $n) = @_;
196 my $r = $a->get($$video{gvi
});
198 unless ($r->is_success)
200 printf STDERR
"\nerror: $$video{url}: %s\n", $r->status_line;
205 my $q = CGI
->new($r->content);
209 if ($q->param('reason'))
211 printf STDERR
"\nerror: %s: %s (errorcode: %d)\n",
212 $$video{url
}, trim
($q->param("reason")),
213 $q->param("errorcode");
218 $title = trim
(Encode
::decode_utf8
($q->param('title')));
219 spew_qe
(($n % 5 == 0) ?
" " : ".");
238 push @r, $_ if length $_ == 11;
244 { # http://is.gd/g8jQU
260 my $p = new Umph
::Prompt
(
266 $p->exit(\
@items, $args);
270 $p->display(\
@items, $args);
274 $p->max_shown_items(@
{$args});
278 $p->select(\
@items, $args);
284 {cmd
=> 'normal', desc
=> 'print results in default format'};
285 push @a, {cmd
=> 'json', desc
=> 'print results in json'};
286 push @a, {cmd
=> 'csv', desc
=> 'print results in csv'};
292 say STDERR
"=> print in default format";
297 say STDERR
"=> print in json";
302 say STDERR
"=> print in csv";
306 # Callbacks. All of these are optional.
309 $p->toggle(\
@items, $args);
311 onitems
=> sub {return \
@items},
314 $p->display(\
@items, $args);
317 # Other (required) settings
318 total_items
=> scalar @items,
319 prompt_msg
=> 'umph',
320 max_shown_items
=> 20
323 say STDERR
qq/Enter prompt. Type "help" to get a list of commands./;
331 grake [-q] [-i] [--csv | --json] [--proxy E<lt>addrE<gt> | --no-proxy]
336 --help Print help and exit
337 --version Print version and exit
339 -i, --interactive Run in interactive mode
340 --json Print details in json
341 --csv Print details in csv
342 --proxy arg (=http_proxy) Use proxy for HTTP connections
343 --no-proxy Disable use of HTTP proxy
347 # vim: set ts=2 sw=2 tw=72 expandtab: