2 # -*- coding: ascii -*-
5 # Copyright (C) 2010 Toni Gundogdu <legatvs@gmail.com>.
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 use version
0.77 (); our $VERSION = version
->declare("0.0.6");
26 binmode STDOUT
, ":utf8";
27 binmode STDERR
, ":utf8";
29 use Getopt
::ArgvFile
( home
=> 1, startupFilename
=> [qw(.grakerc)] );
30 use Getopt
::Long
qw(:config bundling);
46 'version' => \
&print_version
,
47 'license' => \
&print_license
,
48 'help' => \
&print_help
,
51 $config{title
} ||= $config{json
};
52 $config{title
} ||= $config{csv
};
56 print "grake version $VERSION\n";
62 "Copyright (C) 2010 Toni Gundogdu. GNU GPL v3+. This is free software;
63 see the source for copying conditions. There is NO warranty; not even
64 for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
71 Pod
::Usage
::pod2usage
( -exitstatus
=> 0, -verbose
=> 1 );
81 print_help
() unless scalar @ARGV;
83 print STDERR
"Checking ..." unless $config{quiet
};
87 my $a = new LWP
::UserAgent
;
89 $a->env_proxy; # http://search.cpan.org/perldoc?LWP::UserAgent
91 $a->proxy( 'http', $config{proxy
} ) if $config{proxy
};
92 $a->no_proxy('') if $config{no_proxy
};
96 my $q = qr{v[=/]((?>[-_\w]{11}))};
102 unless ( $r->is_success ) {
103 printf STDERR
"\nerror: $_: %s\n", $r->status_line;
107 my $d = URI
::Escape
::uri_unescape
( $r->content );
108 @ids = uniq
( ( @ids, $d =~ /$q/g ) );
110 print STDERR
"." unless $config{quiet
};
113 unless ( scalar @ids ) {
114 print STDERR
"error: nothing found.\n";
117 else { print STDERR
"done.\n" unless $config{quiet
}; }
119 print STDERR
"Getting ..." unless $config{quiet
};
121 foreach my $id (@ids) {
125 url
=> "http://youtube.com/watch?v=$id",
126 gvi
=> "http://www.youtube.com/get_video_info?&video_id=$id"
127 . "&el=detailpage&ps=default&eurl=&gl=US&hl=en",
132 $tmp{title
} = get_title
( $a, $tmp{gvi
} ) if $config{title
};
137 print STDERR
"done.\n" unless $config{quiet
};
139 prompt
() if $config{interactive
};
141 if ( $config{json
} ) { print qq/{\n "video": [\n/; }
147 if ( $_->{selected
} or not $config{interactive
} ) {
151 my $t = $_->{title
} || "";
154 if ( $config{json
} ) {
156 print ",\n" if $i > 1;
159 . qq/ "title": "$t",\n/
160 . qq/ "url": "$_->{url}"\n/ . " }",
164 elsif ( $config{csv
} ) { print qq/"$t","$_->{url}"\n/; }
166 else { print "$_->{url}\n"; }
172 if ( $config{json
} ) { print "\n ]\n}\n"; }
179 my ( $a, $url ) = @_;
181 my $r = $a->get($url);
183 unless ( $r->is_success ) {
184 printf STDERR
"\nerror: $url: %s\n", $r->status_line;
192 my $q = CGI
->new( $r->content );
194 if ( $q->param('reason') ) {
195 printf STDERR
"\nerror: %s: %s (errorcode: %d)\n",
196 $url, $q->param("reason"), $q->param("errorcode");
200 $title = Encode
::decode_utf8
( $q->param('title') );
204 print STDERR
"\nwarning: $url: use id instead\n"
205 unless $config{quiet
};
207 else { print STDERR
"." unless $config{quiet
}; }
213 return keys %{ { map { $_ => 1 } @_ } };
214 } # Original order lost.
225 'n' => \
&select_none
,
226 'i' => \
&invert_selection
,
231 "Enter prompt. Type \"help\" to get a list of commands.\n";
236 while ( not $done ) {
245 if ( $ln =~ /(\d+)/ ) { toggle_caption
($1); }
248 next unless $ln =~ /(\w)/;
249 $cmds{$1}() if defined $cmds{$1};
257 print STDERR
"Commands:
259 list .. display found links (> indicates selected for download)
262 invert .. invert selection
263 (number) .. toggle caption
264 dump .. dump selected links and exit
265 quit .. quit without dumping links\n"
266 . qq/Command name abbreviations are allowed, e.g. "h" instead of "help"\n/;
274 printf STDERR
"%2s%02d: %s\n", $_->{selected
}
278 $_->{title
} || $_->{url
};
283 $_->{selected
} = 1 foreach @links;
288 $_->{selected
} = 0 foreach @links;
292 sub invert_selection
{
293 $_->{selected
} = not $_->{selected
} foreach @links;
297 sub dump { $done = 1; }
301 if ( $i >= 0 && exists $links[$i] ) {
302 $links[$i]->{selected
} = not $links[$i]->{selected
};
305 else { print STDERR
"error: out of range\n"; }
312 grake - Youtube video link scanner
316 grake [-q] [-i] [-t] [--csv | --json] [--proxy E<lt>addrE<gt> | --no-proxy]
321 grake is a command line tool for scanning webpages for Youtube video links.
322 Each found link is separated with a newline and dumped to the standard output.
324 You can use grake together with such tools like C<cclive(1)>. If you
325 need to select the videos, use the C<--interactive> switch.
329 --help print help and exit
330 --version print version and exit
331 --license print license and exit
333 -i, --interactive run in interactive mode
334 -t, --title get title for video link
335 --json print details in json, implies -t
336 --csv print details in csv, implies -t
337 --proxy arg (=http_env) use proxy for http connections
338 --no-proxy disable use of http proxy
340 =head1 OPTION DESCRIPTIONS
350 Print version and exit.
354 Print license and exit.
360 =item B<-i, --interactive>
362 Enable interactive prompt which can be used to select the found
363 video links to be dumped to stdout. By default grake dumps all
364 found links without prompting.
368 Get a video title for each found link. The default is no.
372 Print details in JSON. Negates C<--csv>. Implies C<--title>.
376 Print details in CSV ("$title","$url"\n). Implies C<--title>.
378 =item B<--proxy> I<arg>
380 Use I<arg> for HTTP proxy, e.g. "http://foo:1234". Overrides the http_proxy
385 Disable use of HTTP proxy. Overrides both C<--proxy> and http_proxy environment
394 =item B<grake "http://youtube.com">
398 =item B<grake --json "http://youtube.com">
400 Same but print details in JSON.
402 =item B<grake "http://youtube.com" | cclive>
404 Download the found videos with C<cclive(1)>.
410 Exits 0 on success, otherwise E<gt>0;
416 =item $HOME/.grakerc, for example:
418 echo "--title" >> ~/.grakerc
428 grake depends on LWP::UserAgent which reads the http_proxy environment
430 env http_proxy=http://foo:1234 grake URL
434 <http://grake.googlecode.com/>
436 =item B<Development repository>
438 <git://repo.or.cz/grake.git>
440 e.g. git clone git://repo.or.cz/grake.git
450 Toni Gundogdu <legatvs gmail com>