update helpstrings.
[umph.git] / bin / umph
blob987e783be14726c6ba0fbe94575ee5d48411dde4
1 #!/usr/bin/perl
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/>.
21 use warnings;
22 use strict;
24 binmode( STDOUT, ":utf8" );
25 binmode( STDERR, ":utf8" );
27 use Getopt::ArgvFile( home => 1, startupFilename => [qw(.umphrc)] );
28 use Getopt::Long qw(:config bundling);
30 my $VERSION = "0.1.5";
31 my %config;
32 my @entries;
33 my $done = 0;
35 exit main();
37 sub init {
39 GetOptions(
40 \%config,
41 'type|t=s',
42 'start_index|start-index|s=s',
43 'max_results|max-results|m=s',
44 'interactive|i',
45 'csv',
46 'version|v' => \&print_version,
47 'license' => \&print_license,
48 'help|h' => \&print_help,
49 ) or exit(1);
51 $config{type} ||= 'p'; # Default to "playlist".
52 $config{start_index} ||= 1; # Default to 1.
53 $config{max_results} ||= 25; # Default 25.
56 sub print_version {
57 print "umph version $VERSION\n";
58 exit 0;
61 sub print_license {
62 print
63 "Copyright (C) 2010 Toni Gundogdu. GNU GPL v3+. This is free software;
64 see the source for copying conditions. There is NO warranty; not even
65 for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
67 exit 0;
70 sub print_help {
71 require Pod::Usage;
72 Pod::Usage::pod2usage( -exitstatus => 0, -verbose => 1 );
75 sub main {
77 init();
79 print_help if scalar @ARGV == 0;
81 print STDERR "Checking ...";
83 require XML::DOM;
85 my $p = new XML::DOM::Parser;
86 my $doc = $p->parsefile (from_arg ($ARGV[0]));
87 my $root = $doc->getDocumentElement;
89 for my $entry ( $root->getElementsByTagName("entry") ) {
91 my $title = to_item( $entry, "title" )->getFirstChild->getNodeValue;
93 my $link =
94 to_item( $entry, "link" )->getAttributeNode("href")->getValue;
96 my %data = ( title => $title, url => $link, selected => 1 );
98 push @entries, \%data;
100 print STDERR ".";
103 print STDERR "done.\n";
105 $doc->dispose;
107 print STDERR "error: nothing found.\n" and return 1
108 unless scalar @entries;
110 prompt() if $config{interactive};
112 foreach (@entries) {
113 if ($_->{selected} or not $config{interactive}) {
114 $config{csv}
115 ? print qq/"$_->{title}","$_->{url}"\n/
116 : print "$_->{url}\n";
120 return 0;
123 sub from_arg {
124 my ($arg0, $u) = @_;
126 if ($config{type} eq "u" or $config{type} eq "uploads")
127 { $u = "http://gdata.youtube.com/feeds/api/users/$arg0/uploads?v=2"; }
128 elsif ($config{type} eq "f" or $config{type} eq "favorites")
129 { $u = "http://gdata.youtube.com/feeds/api/users/$arg0/favorites?v=2"; }
130 else
131 { $u = "http://gdata.youtube.com/feeds/api/playlists/$arg0?v=2"; }
133 $u .= "&start-index=$config{start_index}";
134 $u .= "&max-results=$config{max_results}";
136 return $u;
139 sub to_item {
140 my ( $entry, $name ) = @_;
141 return $entry->getElementsByTagName($name)->item(0);
144 sub prompt {
146 my %cmds = (
147 'h' => \&help,
148 'q' => \&quit,
149 'l' => \&list,
150 'd' => \&dump,
151 'a' => \&select_all,
152 'n' => \&select_none,
153 'r' => \&revert_selection,
156 print STDERR "Enter prompt. Type \"help\" to get a list of commands.\n";
157 list();
159 my $p = "(umph) ";
161 while ( !$done ) {
162 print STDERR $p;
163 my $ln = <STDIN>;
164 next if !$ln;
165 chomp $ln;
166 if ( $ln =~ /(\d+)/ ) {
167 toggle_number($1);
169 else {
170 next if $ln !~ /(\w)/;
171 $cmds{$1}() if defined $cmds{$1};
176 sub toggle_number {
177 my $i = (shift) - 1;
178 if ( $i >= 0 && exists $entries[$i] ) {
179 $entries[$i]->{selected} = !$entries[$i]->{selected};
180 list();
182 else {
183 printf STDERR "error: out of range\n";
187 sub help {
188 print STDERR "Commands:
189 help .. this
190 list .. list found videos (> indicates selected)
191 all .. select all videos
192 none .. select none
193 revert .. revert selection
194 (number) .. toggle (select, unselect) video, see list output
195 dump .. dump selected video urls to stdout and exit
196 quit .. terminate program
197 Command name abbreviations are allowed, e.g. \"a\" instead of \"all\".
201 sub list {
202 my $i = 0;
203 foreach (@entries) {
204 printf STDERR "%2s%02d: $_->{title}\n", $_->{selected} ? ">" : "",
205 ++$i;
209 sub select_all {
210 $_->{selected} = 1 foreach @entries;
211 list();
214 sub select_none {
215 $_->{selected} = 0 foreach @entries;
216 list();
219 sub revert_selection {
220 $_->{selected} = !$_->{selected} foreach @entries;
221 list();
224 sub quit { exit 0; }
226 sub dump { $done = 1; }
228 __END__
230 =head1 NAME
232 umph - Command line tool for parsing video links from Youtube feeds
234 =head1 SYNOPSIS
236 umph [-i] [--csv] [-t E<lt>typeE<gt>] [E<lt>playlist_idE<gt> | E<lt>usernameE<gt>]
238 =head1 DESCRIPTION
240 umph is a command line tool for parsing video links from Youtube feeds,
241 such as playlists, favorites and uploads. The parsed video links are
242 printed to the standard output each separated with a newline.
244 If you need to select the videos, use the C<--interactive> switch.
246 =head1 OPTIONS
248 -h, --help print help and exit
249 -v, --version print version and exit
250 --license print license and exit
251 -i, --interactive run in interactive mode (default:no)
252 -t, --type =arg feed type, default is playlist (default:p)
253 -s, --start-index =arg index of first matching result (default:1)
254 -m, --max-results =arg max number of results included (default:25)
255 --csv print details in csv (default:no)
257 =head1 OPTION DESCRIPTIONS
259 =over 4
261 =item B<-h, --help>
263 Print help and exit.
265 =item B<-v, --version>
267 Print version and exit.
269 =item B<--license>
271 Print license and exit.
273 =item B<-t, --type>=I<arg>
275 Specifies the feed type to get. I<arg> can be one of the following:
277 p, playlist (arg0 will be treated as playlist ID)
278 f, favorites (arg0 will be treated as username)
279 u, uploads (same)
281 Default is "p" (playlist). See also L</EXAMPLES>.
283 =item B<-s, --start-index>=I<arg>
285 "The start-index parameter specifies the index of the first matching result
286 that should be included in the result set. This parameter uses a one-based
287 index, meaning the first result is 1, the second result is 2 and so forth.
289 This parameter works in conjunction with the C<--max-results> parameter to
290 determine which results to return. For example, to request the second set
291 of 10 results, i.e. results 11-20, set the start-index parameter to 11
292 and the max-results parameter to 10."
294 <http://code.google.com/apis/youtube/2.0/reference.html#start-indexsp>
296 umph defaults to 1.
298 =item B<-m, --max-results>=I<arg>
300 "The max-results parameter specifies the maximum number of results that
301 should be included in the result set.
303 This parameter works in conjunction with the C<--start-index> parameter
304 to determine which results to return. For example, to request the second
305 set of 10 results, i.e. results 11-20, set the max-results parameter
306 to 10 and the start-index parameter to 11.
308 The default value of this parameter is 25, and the maximum value is 50.
309 However, for displaying lists of videos, we recommend that you set the
310 max-results parameter to 10."
312 <http://code.google.com/apis/youtube/2.0/reference.html#max-resultssp>
314 umph defaults to 25.
316 =item B<-i, --interactive>
318 Enable interactive prompt which can be used to select the videos from the
319 feed. By default umph selects all of the feed items.
321 =item B<--csv>
323 Print details in CSV ("$title","$url"\n).
325 =back
327 =head1 EXAMPLES
329 =over 4
331 =item umph AAF3A1D0CA1E304F
333 Fetch and parse playlist "AAF3A1D0CA1E304F".
335 =item umph -s 11 -m 10 AAF3A1D0CA1E304F
337 Same as above but get the items 11-20 from the playlist.
339 =item umph -t f youtube
341 Fetch and parse favorites for user "youtube".
343 =item umph -t u youtube
345 Fetch and parse uploads for user "youtube".
347 =item umph AAF3A1D0CA1E304F | cclive -f sd_270p
349 Print the parsed playlist items (links) to stdout, use C<cclive(1)>
350 to download them.
352 =back
354 =head1 EXIT STATUS
356 Exits 0 on success, otherwise 1.
358 =head1 FILES
360 =over 4
362 =item $HOME/.umphrc, for example:
364 echo "--interactive" >> ~/.umphrc
366 =back
368 =head1 NOTES
370 =over 4
372 =item B<http_proxy>
374 umph depends on XML::DOM which uses LWP::UserAgent to fetch the data
375 over the network. LWP::UserAgent reads the http_proxy environment
376 setting. e.g.:
378 env http_proxy=http://foo:1234 umph AAF3A1D0CA1E304F
380 =item B<Unavailable feeds>
382 Some feeds may have been set private by the Youtube users. umph
383 cannot currently fetch and parse those.
385 =item B<Project>
387 <http://umph.googlecode.com/>
389 =item B<Development repository>
391 <git://repo.or.cz/umph.git>
393 e.g. git clone git://repo.or.cz/umph.git
395 =back
397 =head1 SEE ALSO
399 C<cclive(1)> C<clive(1)>
401 =head1 AUTHOR
403 Toni Gundogdu <legatvs gmail com>
405 =cut