File Coverage

blib/lib/App/FeedDeduplicator.pm
Criterion Covered Total %
statement 26 26 100.0
branch n/a
condition n/a
subroutine 9 9 100.0
pod n/a
total 35 35 100.0


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             App::FeedDeduplicator - A simple feed deduplicator
4              
5             =head1 SYNOPSIS
6              
7             use App::FeedDeduplicator;
8              
9             my $deduplicator = App::FeedDeduplicator->new();
10             $deduplicator->run();
11              
12             =head1 DESCRIPTION
13              
14             App::FeedDeduplicator is a simple Perl application that aggregates,
15             deduplicates, and publishes feeds. It uses the LWP::UserAgent module to
16             fetch feeds and XML::Feed parse them.
17              
18             The deduplication process is based on the entry's unique identifier, the
19             canonical link or the title of the entry.
20              
21             The application can output the deduplicated feed in either Atom or JSON format.
22              
23             It is designed to be run from the command line, and it can be configured using
24             a JSON configuration file. The configuration file should specify the feeds to
25             be aggregated, the output format, and the maximum number of entries to include
26             in the output.
27              
28             The application is designed to be extensible, allowing for additional features
29             and functionality to be added in the future.
30              
31             =head1 CONFIGURATION
32              
33             The configuration file is a JSON file that specifies the feeds to be
34             aggregated, the output format, and the maximum number of entries to include
35             in the output.
36              
37             By default, the configuration file should be located at
38             C<~/.feed-deduplicator/config.json>, but this can be overridden by setting
39             the C<FEED_DEDUP_CONFIG> environment variable.
40              
41             The configuration file should have the following structure:
42              
43             {
44             "feeds": [{
45             "name": "Feed Name",
46             "feed": "http://example.com/feed",
47             "web": "http://example.com"
48             }],
49             "output_format": "Atom",
50             "max_entries": 10
51             }
52              
53             =head1 METHODS
54              
55             =head2 new
56              
57             Creates a new instance of App::FeedDeduplicator. The constructor accepts a
58             configuration file path as an optional parameter.
59              
60             If the configuration file is not provided, it defaults to
61             C<~/.feed-deduplicator/config.json> or the path specified by the
62             C<FEED_DEDUP_CONFIG> environment variable.
63              
64             =head2 run
65              
66             The main method that runs the application. It aggregates feeds, deduplicates
67             entries, and publishes the output.
68              
69             It creates instances of the Aggregator, Deduplicator, and Publisher classes
70             and calls their respective methods to perform the operations.
71              
72             =cut
73              
74             package App::FeedDeduplicator;
75              
76 1     1   301022 use v5.40;
  1         5  
77 1     1   9 use feature 'class';
  1         2  
  1         215  
78 1     1   7 no warnings 'experimental::class';
  1         2  
  1         141  
79              
80             our $VERSION = '0.4.1';
81              
82             class App::FeedDeduplicator {
83 1     1   663 use App::FeedDeduplicator::Aggregator;
  1         4  
  1         38  
84 1     1   463 use App::FeedDeduplicator::Deduplicator;
  1         3  
  1         35  
85 1     1   422 use App::FeedDeduplicator::Publisher;
  1         2  
  1         32  
86 1     1   5 use JSON::MaybeXS;
  1         2  
  1         66  
87 1     1   5 use File::Spec;
  1         1  
  1         16  
88 1     1   500 use File::HomeDir;
  1         4837  
  1         378  
89              
90             field $config_file :param //= $ENV{FEED_DEDUP_CONFIG}
91             // File::Spec->catfile(File::HomeDir->my_home, '.feed-deduplicator', 'config.json');
92              
93             field $config = do {
94             unless (-e $config_file) {
95             die "Configuration file not found: $config_file\n";
96             }
97              
98             open my $fh, '<', $config_file or die "Can't read config file: $config_file\n";
99             decode_json(do { local $/; <$fh> });
100             };
101              
102             field $ua = LWP::UserAgent->new(
103             timeout => 5,
104             agent => 'App::FeedDeduplicator',
105             );
106              
107             method run () {
108             my $aggregator =
109             App::FeedDeduplicator::Aggregator->new(
110             feeds => $config->{feeds},
111             ua => $ua,
112             );
113              
114             $aggregator->aggregate;
115              
116             my $deduplicator =
117             App::FeedDeduplicator::Deduplicator->new(
118             entries => $aggregator->entries,
119             ua => $ua,
120             );
121              
122             $deduplicator->deduplicate;
123              
124             my $publisher =
125             App::FeedDeduplicator::Publisher->new(
126             entries => $deduplicator->deduplicated,
127             format => $config->{output_format} // 'Atom',
128             max_entries => $config->{max_entries} // 10,
129             );
130              
131             $publisher->publish;
132             }
133             }
134              
135             =head1 AUTHOR
136              
137             Dave Cross, <dave@perlhacks.com>
138              
139             =head1 COPYRIGHT AND LICENSE
140              
141             This software is copyright (c) 2025 Magnum Solutions Ltd.
142             All rights reserved.
143              
144             This program is free software; you can redistribute it and/or modify it
145             under the same terms as Perl itself.
146              
147             See L<http://dev.perl.org/licenses/artistic.html> for more details.
148              
149             =cut
150