Skip to content

Instantly share code, notes, and snippets.

@krrrr38
Last active December 20, 2015 09:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save krrrr38/6110261 to your computer and use it in GitHub Desktop.
Save krrrr38/6110261 to your computer and use it in GitHub Desktop.
RSS管理+ブラウザーで一度に見たいページを開く的な.日々のRSS消化を一度に終わらせるinteractive-mode追加した.http://krrrr.hatenablog.com/entry/20130730/1375179091
#!/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