OSDN Git Service

80452e06ea833188af466780cba8c99a2cd2b793
[newslash/newslash.git] / src / newslash_web / lib / Newslash / FeedFetcher.pm
1 package Newslash::FeedFetcher;
2
3 use strict;
4 use warnings;
5 use utf8;
6 use feature ':5.10';
7
8 use YAML qw(LoadFile);
9 use constant CONF_PATH => "/etc/newslash/newslash.conf";
10
11 use Newslash::Model::Feeds;
12 use Data::Dumper;
13 use DateTime::Format::MySQL;
14 use Newslash::Util;
15 use File::Spec;
16 use Mojo::Log;
17
18
19 sub new {
20     my $class = shift;
21     bless {_config => {} }, $class;
22 }
23
24 sub config {
25     my ($self, $new_val) = @_;
26     $self->{_config} = $new_val if defined $new_val;
27     return $self->{_config};
28 }
29
30 sub feeds {
31     my ($self, $new_val) = @_;
32     $self->{_feeds} = $new_val if defined $new_val;
33     return $self->{_feeds};
34 }
35
36 sub _detect_home {
37     my ($self,) = @_;
38
39     # Environment variable
40     my $home;
41     if ($ENV{MOJO_HOME}) {
42         $home = $ENV{MOJO_HOME};
43     }
44     else {
45         my $path = $INC{"Newslash/FeedFetcher.pm"};
46         my @terms = split(/[\/\\]/, $path);
47         while (@terms) {
48             my $last = pop(@terms);
49             if ($last =~ m/^(lib|blib)$/) {
50                 $home = File::Spec->catdir(@terms);
51                 last;
52             }
53         }
54     }
55     return $home;
56 }
57
58 sub _load_config {
59     my $self = shift;
60     my $config_file;
61
62     if (-e CONF_PATH) {
63         $config_file = CONF_PATH;
64     }
65     else {
66         my $home = $self->_detect_home;
67         if ($home) {
68             $config_file = File::Spec->catdir($home, "newslash-feedfetcher.yaml");
69             if (! -e $config_file) {
70                 $config_file = File::Spec->catdir($home, "newslash-web.yaml");
71             }
72         }
73    }
74
75     my $config = eval { LoadFile($config_file) };
76     die qq{Can't parse config "$config_file": $@} if $@;
77     die qq{Invalid config "$config_file"} unless ref $config eq 'HASH';
78
79     return $config;
80 }
81
82 sub run {
83     my $self = shift;
84     my $log = Mojo::Log->new;
85
86     if ($ENV{MOJO_LOG_LEVEL}) {
87         $log->level($ENV{MOJO_LOG_LEVEL});
88     }
89     else {
90         $log->level("warn");
91     }
92
93     my $config = $self->_load_config;
94     $self->config($config);
95
96     my $feeds = new Newslash::Model::Feeds($self->config);
97     $self->feeds($feeds);
98
99     my $rs = $feeds->select;
100     if (!$rs) {
101         die "cannot retrieve feed infomations from database.";
102     }
103     for my $feed (@$rs) {
104         if ($feed->{status} ne "active") {
105             $log->info("$feed->{title} is not active. skip ...");
106             next;
107         }
108         $log->info("fetch $feed->{url} ...");
109
110         my $f = $feeds->fetch_url(\$feed->{url}, $config->{FeedFetcher} || {});
111         my $now = DateTime::Format::MySQL->format_datetime(DateTime->now);
112         if (!$f) {
113             my $error = $feeds->last_error;
114             $log->error("fetch $feed->{url} failed - $error.");
115             $feeds->update(feed_id => $feed->{feed_id},
116                            latest_fetch_time => $now,
117                            latest_fetch_result => $feeds->last_errorno);
118             next;
119         }
120         $feeds->update(feed_id => $feed->{feed_id},
121                        latest_fetch_time => $now,
122                        latest_fetch_result => 200);
123
124         for my $item ($f->entries) {
125             my $content = $item->content->body;
126             my $type = $item->content->type;
127             my $modified = $item->modified || $item->issued;
128             #warn $content;
129             #warn $type;
130             #warn $modified;
131
132             my $id = $feeds->items->create(feed_id => $feed->{feed_id},
133                                            url => $item->link || "",
134                                            title => $item->title || "",
135                                            content => $content,
136                                            content_type => $type,
137                                            modified => $modified,
138                                           );
139             if (!defined $id) {
140                 my $error = $feeds->last_error;
141                 $log->error("cannot create feed item: $error");
142             }
143             else {
144                 if ($id == 0) {
145                     $log->debug("update item " . $item->link . " (feed_id: $feed->{feed_id})");
146                 }
147                 else {
148                     $log->debug("create item " . $item->link . " (feed_id: $feed->{feed_id}, item_id: $id)");
149                 }
150             }
151         }
152     }
153
154     return 0;
155 }
156
157 1;