Last active
December 20, 2015 09:48
-
-
Save krrrr38/6110261 to your computer and use it in GitHub Desktop.
RSS管理+ブラウザーで一度に見たいページを開く的な.日々のRSS消化を一度に終わらせるinteractive-mode追加した.http://krrrr.hatenablog.com/entry/20130730/1375179091
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env perl | |
# | |
# | |
use utf8; | |
use strict; | |
use warnings; | |
use LWP::Simple; | |
use XML::RSS; | |
use Getopt::Long; | |
use Readonly; | |
Readonly my $ROW_LENGTH => 60; | |
Readonly my $TITLE_LENGTH => 40; | |
Readonly my $URL_LENGTH => 40; | |
Readonly my $MAX_INDEX => 30; | |
Readonly my $HOUR => 3600; | |
binmode STDIN, ":utf8"; | |
binmode STDOUT, ":utf8"; | |
my $home_dir = $ENV{"HOME"}; | |
my $config_dir = "$home_dir/.myrss"; | |
`mkdir $config_dir` unless (-e $config_dir); | |
my $config_file = "$home_dir/.myrss/config"; | |
`touch $config_file` unless (-e $config_file); | |
sub open_pages { | |
my ($category_index, $open_indexes) = @_; | |
my $contents = get_category_contents($category_index); | |
print("open contents of $contents->[0]\n"); | |
open_browser_with_indexes($contents->[1], $open_indexes); | |
} | |
sub show_category_list { | |
my $category_index = shift; | |
my $contents = get_category_contents($category_index); | |
printf("title : %s\n", $contents->[0]); | |
print("index: contents\n"); | |
show_contents($contents->[1]); | |
} | |
sub get_category_contents { | |
my $category_index = shift; | |
my $data_file = "$home_dir/.myrss/$category_index.data"; | |
my $list = get_rss_list(); | |
my $category = $list->[$category_index]; | |
die "Invalid category index. See `myrss`.\n" unless $category; | |
my ($title, $url, $fetch_time) = split("\t", $category); | |
if(!-e $data_file || time() - $fetch_time > $HOUR){ | |
my $data = fetch_data($url); | |
save_contents_data($data, $data_file); | |
update_fetch_time($category_index, time()); | |
return $data; | |
}else{ | |
return load_contents_data($data_file); | |
} | |
} | |
sub fetch_data { | |
my $url = shift; | |
my $content = get($url) or die "Couldn't get contents. Invalid URL format.\n"; | |
my $rss = XML::RSS->new; | |
eval { | |
$rss->parse($content); | |
}; | |
die "Couldn't get contents. This is not valid RSS format url.\n" if($@); | |
my $title = $rss->{channel}->{title}; | |
my @items = @{$rss->{items}}; | |
return [$title, \@items]; | |
} | |
sub update_fetch_time { | |
my ($category_index, $time) = @_; | |
my $list = get_rss_list(); | |
my @updated_list = map { | |
if($_ == $category_index){ | |
update_time($list->[$_], $time); | |
}else{ | |
$list->[$_]; | |
} | |
} 0..$#$list; | |
rewrite_rss_list(\@updated_list); | |
} | |
sub update_time { | |
my ($line, $time) = @_; | |
my @fields = split("\t", $line); | |
return "$fields[0]\t$fields[1]\t$time\n"; | |
} | |
sub save_contents_data { | |
my ($contents, $file) = @_; | |
open my $fh, '+>:utf8', $file or die $!; | |
print $fh $contents->[0], "\n"; | |
print $fh $_->{title}, "\t", $_->{link}, "\n" for @{$contents->[1]}; | |
close $fh; | |
} | |
sub load_contents_data { | |
my $file = shift; | |
open my $fh, '<:utf8', $file or die $!; | |
my @lines = readline $fh; | |
close $fh; | |
my $title = shift @lines; | |
chomp($title); | |
my @items = map { | |
my @fields = split("\t", $_); | |
{ title => $fields[0], link => $fields[1] }; | |
} @lines; | |
return [$title, \@items]; | |
} | |
sub open_browser_with_indexes { | |
my ($items, $args) = @_; | |
my $links = get_open_page_links($items, $args); | |
open_browser_with_links($links); | |
} | |
sub open_browser_with_links { | |
my $links = shift; | |
if($#$links >= 0){ | |
my $result = system sprintf("open %s", join(" ", @$links)); | |
print "something wrong\n" if $result; | |
}else{ | |
print "Invalid page index. Comfirm with `myrss help`\n"; | |
} | |
} | |
sub get_open_page_links { | |
my ($items, $args) = @_; | |
my @links = map { | |
my $link = $_->{link}; | |
chomp($link); | |
$link | |
} grep {$_} map {$items->[$_-1]} @$args; | |
return \@links; | |
} | |
sub show_contents { | |
my $items = shift; | |
for(0..$#$items){ | |
last if($_ >= $MAX_INDEX); | |
my $title = normalize_item($items->[$_]->{title}); | |
print sprintf(" %3d : %s\n", $_+1, $title) unless $title =~ /^[PR|AD].*/; | |
} | |
} | |
sub interactive_mode { | |
my $rss_list = get_rss_list(); | |
my @open_links = (); | |
my $count = $#$rss_list; | |
for my $category_index (0..$count){ | |
my $contents = get_category_contents($category_index); | |
my $input = show_interactive_contents($contents, $category_index+1, $count+1); | |
my @indexes = grep {is_number($_)} split (/\s+/, $input); | |
my $links = get_open_page_links($contents->[1], \@indexes); | |
push(@open_links, @$links); | |
} | |
open_browser_with_links(\@open_links); | |
} | |
sub show_interactive_contents { | |
my ($contents, $num, $count) = @_; | |
printf("title : %s (%d / %d)\n", $contents->[0], $num, $count); | |
print("index: contents\n"); | |
show_contents($contents->[1]); | |
print("Select open page indexes with space\n > "); | |
my $input = <STDIN>; | |
chomp($input); | |
return $input; | |
} | |
sub register_rss { | |
my $new_rss = shift; | |
my $contents = fetch_data($new_rss); | |
my $write_data = sprintf("%s\t%s\t0\n", $contents->[0], $new_rss); | |
open my $fh, '>>:utf8', $config_file or die $!; | |
print $fh $write_data; | |
close $fh; | |
show_rss_list(); | |
} | |
sub delete_rss { | |
my $category_index = shift; | |
my $categories = get_rss_list(); | |
die "Invalid category index. See `myrss`.\n" unless $categories->[$category_index]; | |
my $deleted = splice @$categories, $category_index, 1; | |
rewrite_rss_list($categories); | |
rearrange_data_files($category_index, $#$categories + 1); | |
print("deleted : $deleted"); | |
} | |
sub rearrange_data_files { | |
my ($delete_index, $count) = @_; | |
if($count == $delete_index){ | |
my $data_file = "$home_dir/.myrss/$delete_index.data"; | |
`rm $data_file` if -e $data_file; | |
}else{ | |
for($delete_index..$count-1){ | |
my $data_file1 = "$home_dir/.myrss/$_.data"; | |
my $data_file2 = sprintf("%s/.myrss/%d.data", $home_dir, $_+1); | |
if(-e $data_file2){ | |
`mv $data_file2 $data_file1`; | |
}elsif(-e $data_file1){ | |
`rm $data_file1`; | |
} | |
} | |
} | |
} | |
sub switch_rss { | |
my ($index1, $index2) = @_; | |
my $categories = get_rss_list(); | |
die "Invalid category index. See `myrss`.\n" unless $categories->[$index1] || $categories->[$index2]; | |
@$categories[$index1, $index2] = @$categories[$index2, $index1]; | |
rewrite_rss_list($categories); | |
switch_data_files($index1, $index2); | |
printf("switch categories : %d & %d\n", $index1+1, $index2+1); | |
show_rss_list(); | |
} | |
sub switch_data_files { | |
my ($index1, $index2) = @_; | |
my $data_file1 = "$home_dir/.myrss/$index1.data"; | |
my $data_file2 = "$home_dir/.myrss/$index2.data"; | |
my $temp_file = "$home_dir/.myrss/tmp.data"; | |
if(-e $data_file1 && -e $data_file2){ | |
`mv $data_file1 $temp_file`; | |
`mv $data_file2 $data_file1`; | |
`mv $temp_file $data_file2`; | |
}elsif(-e $data_file1 && ! -e $data_file2){ | |
`mv $data_file1 $data_file2`; | |
}elsif(! -e $data_file1 && -e $data_file2){ | |
`mv $data_file2 $data_file1`; | |
} | |
} | |
sub show_rss_list{ | |
my $lines = get_rss_list(); | |
if($#$lines < 0){ | |
print "There are no registered rss feed.\n"; | |
print " Register\t`myrss -a <FEED_URL>`\n Usage\t\t`myrss --help`\n"; | |
}else{ | |
print "category\t\t\ttitle(url)\n"; | |
for(0..$#$lines){ | |
last if($_ >= $MAX_INDEX); | |
my @fields = split("\t", $lines->[$_]); | |
my $title = normalize($fields[0], $TITLE_LENGTH); | |
my $url = normalize($fields[1], $URL_LENGTH); | |
chomp($url); | |
printf(" %5d\t%s(%s...)\n", $_+1, $title, $url); | |
} | |
} | |
} | |
sub get_rss_list { | |
open my $fh, '<:utf8', $config_file or die $!; | |
my @lines = readline $fh; | |
close $fh; | |
return \@lines; | |
} | |
sub rewrite_rss_list { | |
my $list = shift; | |
my @list = grep {length($_) > 5} @$list; | |
open my $fh, '>:utf8', $config_file or die $!; | |
print $fh $_ for @$list; | |
close $fh; | |
} | |
sub normalize_item { | |
my $text = shift; | |
my $length = $ROW_LENGTH - 5; | |
normalize($text, $length); | |
} | |
sub normalize { | |
my ($text, $length) = @_; | |
if(length $text >= $length){ | |
$text = substr($text, 0, $length); | |
} | |
return $text; | |
} | |
sub is_number { | |
my $n = shift; | |
return $n =~ /^\d+$/; | |
} | |
sub show_usage { | |
print <<"EOS"; | |
myrss : rss manager to open pages easily | |
Usage: myrss [options...] | |
* myrss\t\t\t\tshow registered rss list with category index | |
* myrss -c 2\t\t\t\tshow rss with category index | |
* myrss -c 2 -o 0 2 7\t\t\topen pages with category index and page indexes | |
* myrss -a http://example.com/rss\tregister rss feed | |
options: | |
* --add/-a <feed_url>\t\t\t\tregister rss feed into myrss | |
* --category/-c <category_index>\t\tchoose category index | |
* --delete/-d <category_index>\t\tdelete category | |
* --open/-o <page_index...>\t\t\topen pages with browser using category(-c) | |
* --switch/-s <category_index> <category>\tswitch category indexes | |
* --interactive/-i\t\t\t\tinteractive shell for opening ALL category pages | |
\tInput open page indexes with spaces | |
\t\tTitle : RSS Feed 1... | |
\t\t > 3 4 7 | |
\t\tTitle : RSS Feed 2... | |
\t\t > 5 11 | |
\t=> open browser with 1-3, 1-4, 1-7, 2-5, 2-11 | |
EOS | |
} | |
my $new_rss = ""; | |
my $category = 0; | |
my $delete = 0; | |
my $help = 0; | |
my $interactive = 0; | |
my $new = 0; | |
my (@open_indexes, @switch_indexes) = (); | |
GetOptions( | |
"add=s" => \$new_rss, | |
"category=i" => \$category, | |
"delete=i" => \$delete, | |
"open=i{1,}" => \@open_indexes, | |
"switch=i{2}" => \@switch_indexes, | |
"help" => \$help, | |
"interactive" => \$interactive, | |
"new" => \$new, | |
) or die("Error in command line arguments. See `myrss --help`\n"); | |
if($help || (defined $ARGV[0] && $ARGV[0] eq 'help')){ | |
show_usage(); | |
}elsif($new_rss){ | |
register_rss($new_rss); | |
}elsif($delete){ | |
delete_rss($delete-1); | |
}elsif($interactive){ | |
interactive_mode(); | |
}elsif(@switch_indexes){ | |
switch_rss($switch_indexes[0]-1, $switch_indexes[1]-1); | |
}elsif($category){ | |
if(@open_indexes){ | |
open_pages($category-1, \@open_indexes); | |
}else{ | |
show_category_list($category-1); | |
} | |
}elsif(@open_indexes){ | |
print("To open pages, you need to select category with -c\n"); | |
}elsif($new){ | |
`rm $home_dir/.myrss/*`; | |
}else{ | |
show_rss_list(); | |
} | |
__END__ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment