Add progress deco
[umph.git] / bin / umph
blob0031394419bfe23fa17373e859e9a1a13da220ef
1 #!/usr/bin/perl
2 # -*- coding: ascii -*-
4 # umph
5 # Copyright (C) 2010-2011 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;
23 use v5.10;
25 binmode STDOUT, ":utf8";
26 binmode STDERR, ":utf8";
28 use version 0.77 (); our $VERSION = version->declare("0.1.9");
30 use Getopt::ArgvFile(home => 1, startupFilename => [qw(.umphrc)]);
31 use Getopt::Long qw(:config bundling);
33 exit main();
35 sub print_help
37 require Pod::Usage;
38 Pod::Usage::pod2usage(-exitstatus => 0, -verbose => 1);
41 use constant MAX_RESULTS_LIMIT => 50; # Refer to http://is.gd/OcSjwU
42 my %config;
44 sub check_max_results_value
46 if ($config{max_results} > MAX_RESULTS_LIMIT)
48 say STDERR
49 "WARNING --max-results exceeds max. accepted value, using "
50 . MAX_RESULTS_LIMIT
51 . " instead";
52 $config{max_results} = MAX_RESULTS_LIMIT;
56 sub init
58 GetOptions(
59 \%config,
60 'type|t=s',
61 'start_index|start-index|s=s',
62 'max_results|max-results|m=s',
63 'interactive|i',
64 'json',
65 'csv',
66 'proxy=s',
67 'no_proxy|no-proxy',
68 'quiet|q',
69 'version' => sub {say "umph version $VERSION"; exit 0},
70 'help' => \&print_help,
71 ) or exit 1;
73 print_help if scalar @ARGV == 0;
75 $config{type} ||= 'p'; # Default to "playlist".
76 $config{start_index} ||= 1; # Default to 1.
77 $config{max_results} ||= 25; # Default 25.
79 check_max_results_value;
82 sub spew_qe {print STDERR @_ unless $config{quiet}}
84 my @items;
86 sub main
88 init;
89 spew_qe "Checking ... ";
91 require LWP;
92 my $a = new LWP::UserAgent;
93 $a->env_proxy; # http://search.cpan.org/perldoc?LWP::UserAgent
94 $a->proxy('http', $config{proxy}) if $config{proxy};
95 $a->no_proxy('') if $config{no_proxy};
97 require XML::DOM;
99 my $p = new XML::DOM::Parser(LWP_UserAgent => $a);
100 my $doc = $p->parsefile(from_arg($ARGV[0]));
101 my $root = $doc->getDocumentElement;
103 my $n = 0;
104 for my $entry ($root->getElementsByTagName("entry"))
106 my $t = to_item($entry, "title")->getFirstChild->getNodeValue;
107 my $l = to_item($entry, "link")->getAttributeNode("href")->getValue;
108 my %data = (title => $t, url => $l, selected => 1);
109 push @items, \%data;
110 spew_qe((++$n % 9 == 0) ? " " : ".");
112 $doc->dispose;
114 spew_qe "done.\n";
116 say STDERR "error: nothing found." and return 1
117 unless scalar @items;
119 prompt() if $config{interactive};
121 say qq/{\n "video": [/ if $config{json};
123 my $i = 0;
125 foreach (@items)
127 if ($_->{selected} or not $config{interactive})
129 ++$i;
131 my $t = $_->{title} || "";
132 $t =~ s/"/\\"/g;
134 if ($config{json})
136 say "," if $i > 1;
137 say " {";
138 say qq/ "title": "$t",/;
139 say qq/ "url": "$_->{url}"/;
140 print " }";
142 elsif ($config{csv}) {say qq/"$t","$_->{url}"/}
143 else {say "$_->{url}"}
147 say "\n ]\n}" if $config{json};
151 use constant GURL => "http://gdata.youtube.com/feeds/api";
153 sub from_arg
155 my ($arg0, $u) = @_;
157 if ($config{type} eq "u" or $config{type} eq "uploads")
159 $u = GURL . "/users/$arg0/uploads?v=2";
161 elsif ($config{type} eq "f" or $config{type} eq "favorites")
163 $u = GURL . "/users/$arg0/favorites?v=2";
165 else
167 $u = GURL . "/playlists/$arg0?v=2";
170 $u .= "&start-index=$config{start_index}";
171 $u .= "&max-results=$config{max_results}";
175 sub to_item
177 my ($entry, $name) = @_;
178 $entry->getElementsByTagName($name)->item(0);
181 my $done = 0;
183 sub prompt
185 my %cmds = (
186 'h' => \&help,
187 'q' => sub {exit 0},
188 'd' => sub {$done = 1},
189 'l' => \&list,
190 'a' => \&select_all,
191 'n' => \&select_none,
192 'r' => \&revert_selection,
195 say STDERR qq/Enter prompt. Type "help" to get a list of commands./;
196 list();
198 use constant P => "(umph) ";
200 while (not $done)
202 print STDERR P;
204 my $ln = <STDIN>;
205 next unless $ln;
206 chomp $ln;
208 if ($ln =~ /(\d+)/) {toggle_number($1)}
209 else
211 next if $ln !~ /(\w)/;
212 $cmds{$1}() if defined $cmds{$1};
217 sub toggle_number
219 my $i = (shift) - 1;
220 if ($i >= 0 && exists $items[$i])
222 $items[$i]->{selected} = not $items[$i]->{selected};
223 list();
225 else {say STDERR "error: out of range"}
228 sub help
230 say STDERR qq/Commands:
231 help .. this
232 list .. list found videos (> indicates selected)
233 all .. select all videos
234 none .. select none
235 revert .. revert selection
236 (number) .. toggle (select, unselect) video, see list output
237 dump .. dump selected video urls to stdout and exit
238 quit .. terminate program
239 Command name abbreviations are allowed, e.g. "a" instead of "all"./;
242 sub list
244 my $i = 0;
245 foreach (@items)
247 printf STDERR "%2s%02d: $_->{title}\n", $_->{selected}
248 ? ">"
249 : "",
250 ++$i;
254 sub select_all
256 $_->{selected} = 1 foreach @items;
257 list();
260 sub select_none
262 $_->{selected} = 0 foreach @items;
263 list();
266 sub revert_selection
268 $_->{selected} = not $_->{selected} foreach @items;
269 list();
272 __END__
274 =head1 SYNOPSIS
276 umph [-q] [-i] [--csv | --json] [-t E<lt>typeE<gt>]
277 [--proxy E<lt>addrE<gt> | --no-proxy]
278 [E<lt>playlist_idE<gt> | E<lt>usernameE<gt>]
280 =head1 OPTIONS
282 --help Print help and exit
283 --version Print version and exit
284 -q, --quiet Be quiet
285 -i, --interactive Run in interactive mode
286 -t, --type arg (=p) Get feed type
287 -s, --start-index arg (=1) Index of first matching result
288 -m, --max-results arg (=25) Max number of results included
289 --json Print details in JSON
290 --csv Print details in CSV
291 --proxy arg (=http_proxy) Use proxy for HTTP connections
292 --no-proxy Disable use of HTTP proxy
294 =cut
296 # vim: set ts=2 sw=2 tw=72 expandtab: