[Rt-commit] rtir branch, 4.2/rss_feed_reader, created. 4.0.1rc1-91-gfc69f027
Aaron Trevena
ast at bestpractical.com
Fri Feb 21 10:42:04 EST 2020
The branch, 4.2/rss_feed_reader has been created
at fc69f0276690f4c88b722ba4b61db51cd88a1d14 (commit)
- Log -----------------------------------------------------------------
commit fc69f0276690f4c88b722ba4b61db51cd88a1d14
Author: Aaron Trevena <aaron at aarontrevena.co.uk>
Date: Fri Feb 21 08:33:56 2020 +0000
Added external feeds to tools to create incidents from RSS
Added new page and class to fetch external feeds, initially RSS
based on configuration, and create pre-populated incidents from items
diff --git a/Makefile.PL b/Makefile.PL
index ea0a3645..a16f3cbe 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -7,7 +7,7 @@ author('Best Practical Solutions <sales at bestpractical.com>');
all_from('lib/RT/IR.pm');
# update README and docs/UPGRADING
-requires_rt('4.6.0');
+requires_rt('4.2.0');
rt_too_new('4.8.0',"\nThis version of RTIR is only compatible with RT 4.6.x and you are using RT %s\n");
# XXX: This should be reported by M::I::RTx
@@ -31,6 +31,10 @@ requires('Regexp::Common');
# queries parsing
requires('Parse::BooleanLogic');
+# For RSS feeds
+requires('HTML::Entities');
+requires('XML::RSS');
+
# for tests
build_requires('Test::More');
build_requires('File::Find');
diff --git a/html/Callbacks/RTIR/Elements/Tabs/Privileged b/html/Callbacks/RTIR/Elements/Tabs/Privileged
index c8a2f21f..5fce34a4 100644
--- a/html/Callbacks/RTIR/Elements/Tabs/Privileged
+++ b/html/Callbacks/RTIR/Elements/Tabs/Privileged
@@ -142,6 +142,7 @@ $tools->child( reporting => title => loc('Reporting'), path => RT::IR->HREFTo('R
my $scripted_actions = $tools->child( scripted_actions => title => loc('Scripted Action') );
$scripted_actions->child( email => title => loc('By Email address'), path => RT::IR->HREFTo('Tools/ScriptedAction.html', IncludeWebPath => 0) );
$scripted_actions->child( ip => title => loc('By IP address'), path => RT::IR->HREFTo('Tools/ScriptedAction.html?loop=IP', IncludeWebPath => 0) );
+my $external_feeds = $tools->child( 'external_feeds', title => loc('External Feeds'), path => RT::IR->HREFTo('Tools//ExternalFeeds.html') );
my $request_path = $HTML::Mason::Commands::r->path_info;
$request_path =~ s!/{2,}!/!g;
diff --git a/html/RTIR/Tools/ExternalFeeds.html b/html/RTIR/Tools/ExternalFeeds.html
new file mode 100644
index 00000000..3d02ae30
--- /dev/null
+++ b/html/RTIR/Tools/ExternalFeeds.html
@@ -0,0 +1,121 @@
+%# BEGIN BPS TAGGED BLOCK {{{
+%#
+%# COPYRIGHT:
+%#
+%# This software is Copyright (c) 1996-2018 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
+%#
+%#
+%# LICENSE:
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work is distributed in the hope that it will be useful, but
+%# WITHOUT ANY WARRANTY; without even the implied warranty of
+%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+%# General Public License for more details.
+%#
+%# You should have received a copy of the GNU General Public License
+%# along with this program; if not, write to the Free Software
+%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+%# 02110-1301 or visit their web page on the internet at
+%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
+%#
+%#
+%# CONTRIBUTION SUBMISSION POLICY:
+%#
+%# (The following paragraph is not intended to limit the rights granted
+%# to you to modify and distribute this software under the terms of
+%# the GNU General Public License and is only of importance to you if
+%# you choose to contribute your changes and enhancements to the
+%# community by submitting them to Best Practical Solutions, LLC.)
+%#
+%# By intentionally submitting any modifications, corrections or
+%# derivatives to this work, or any other work intended for use with
+%# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+%# you are the copyright holder for those contributions and you grant
+%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+%# royalty-free, perpetual, license to use, copy, create derivative
+%# works based on those contributions, and sublicense and distribute
+%# those contributions and any derivatives thereof.
+%#
+%# END BPS TAGGED BLOCK }}}
+
+<& /RTIR/Elements/Header, Title => $title &>
+<& /Elements/Tabs &>
+% my $i = 0;
+% if ($FeedName) {
+% my $feed = $ExternalFeeds->fetch_rss_feed($FeedName);
+ <h2><% $feed->{Title} %></h2>
+ <% $feed->{Description} %> <i>updated <% $feed->{PubDate} || $feed->{LastBuildDate} || '-'%></i>
+ <table cellspacing="0" class="collection-as-table">
+ <tr class="collection-as-table">
+ <th class="collection-as-table"><&|/l&>Name</&></th>
+ <th class="collection-as-table" colspan="2"><&|/l&>Description</&></th>
+ </tr>
+% foreach my $item (@{ $feed->{items} }) {
+% my $GeneratedSubject = sprintf('Incident from RSS feed %s : %s', $feed->{Title}, $item->{Title});
+% my $GeneratedMessage = join("\n",
+% sprintf('Incident created from RSS feed %s : %s', $feed->{Title}, $item->{Title}),
+% sprintf('Source : %s on %s', $item->{Link} , $item->{PubDate} || $item->{LastBuildDate} || '-'),
+% $item->{Description} || '' );
+ <tr class="<% $i%2 ? 'oddline' : 'evenline'%>" >
+ <td class="collection-as-table"><% $item->{Title} %></td>
+ <td class="collection-as-table">
+ <form action="<% $CreateURI %>" name="CreateIncident-<% $i %>" id="CreateIncident-<% $i %>" method="post">
+ <input type="hidden" value="<% $GeneratedSubject %>" name="Subject">
+ <input type="hidden" value="<% $GeneratedMessage %>" name="Content">
+ <&|/l_unsafe, $ticket_type,
+ $m->scomp('/RTIR/Elements/SelectRTIRQueue',
+ Name => 'Queue',
+ ShowNullOption => 0,
+ Lifecycle => $Lifecycle,
+ LimitToConstituency => 1,
+ Constituency => $m->{'RTIR_ConstituencyFilter'})
+ &>Create a new [_1] in the queue [_2]</&>
+ <& /Elements/Submit, Label => loc("Go"), Caption => loc("This will take you to a partially prefilled [_1] creation form.", $ticket_type) &>
+ </form>
+ </td>
+ <td class="collection-as-table"> </td>
+ </tr>
+ <tr class="<% $i%2 ? 'oddline' : 'evenline'%>" >
+ <td class="collection-as-table" colspan="3"><% substr($item->{Description}, 0, 1024) %></td>
+ </tr>
+% $i++;
+% }
+</table>
+% }
+% else {
+<h2>RSS Feeds</h2>
+<table cellspacing="0" class="collection-as-table">
+<tr class="collection-as-table">
+<th class="collection-as-table"><&|/l&>Name</&></th>
+<th class="collection-as-table"><&|/l&>Description</&></th>
+</tr>
+% foreach my $feed ($ExternalFeeds->rss_feeds) {
+<tr class="<% $i%2 ? 'oddline' : 'evenline'%>" >
+ <td class="collection-as-table"><a href="/RTIR/Tools/ExternalFeeds.html?FeedName=<% uri_escape($feed->{Name}) %>"><%$feed->{Name}%></a></td>
+ <td class="collection-as-table"><%$feed->{Description}%></td>
+</tr>
+% $i++;
+% }
+</table>
+% }
+<%INIT>
+use URI::Escape;
+use RT::IR::ExternalFeeds;
+my $CreateURI = RT::IR->HREFTo('Incident/Create.html');
+my $ExternalFeeds = new RT::IR::ExternalFeeds;
+my $Lifecycle = 'incidents';
+my $ticket_type = lc RT::IR::TicketType( Lifecycle => $Lifecycle );
+my $title = 'External Feeds';
+</%INIT>
+<%ARGS>
+$FeedName => undef
+</%ARGS>
+
diff --git a/lib/RT/IR/ExternalFeeds.pm b/lib/RT/IR/ExternalFeeds.pm
new file mode 100644
index 00000000..e2da97dd
--- /dev/null
+++ b/lib/RT/IR/ExternalFeeds.pm
@@ -0,0 +1,116 @@
+# BEGIN BPS TAGGED BLOCK {{{
+#
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2018 Best Practical Solutions, LLC
+# <sales at bestpractical.com>
+#
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
+#
+# This work is made available to you under the terms of Version 2 of
+# the GNU General Public License. A copy of that license should have
+# been provided with this software, but in any event can be snarfed
+# from www.gnu.org.
+#
+# This work is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 or visit their web page on the internet at
+# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
+#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
+#
+# END BPS TAGGED BLOCK }}}
+
+package RT::IR::ExternalFeeds;
+use strict;
+use warnings;
+
+use LWP::UserAgent;
+use XML::RSS;
+use HTML::Entities;
+
+sub new {
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+ my $self = {};
+ bless( $self, $class );
+ $self->_Init(@_);
+ return $self;
+}
+
+sub _Init {
+ my $self = shift;
+ my %args = (
+ Constituency => undef,
+ @_,
+ );
+ $self->{ua} = LWP::UserAgent->new(timeout => 20);
+ $self->{rss_feeds} = {
+ map { $_->{Name} => $_ }
+ @{RT->Config->Get('ExternalFeeds')->{RSS}}
+ };
+ $self->{_rss_parser} = XML::RSS->new();
+}
+
+sub rss_feeds {
+ my $self = shift;
+ return values %{$self->{rss_feeds}};
+}
+
+sub fetch_rss_feed {
+ my ($self, $name) = @_;
+ my $url = $self->{rss_feeds}{$name}{URI};
+ my $response = $self->{ua}->get($url);
+ return $self->_parse_rss_feed($response);
+}
+
+######
+
+sub _parse_rss_feed {
+ my ($self, $response) = @_;
+ return { } unless ($response->is_success);
+ $self->{_rss_parser}->parse($response->content);
+ my $parsed_feed = { map { ucfirst($_) => $self->{_rss_parser}{channel}{$_} }
+ ( qw(title description pubDate lastBuildDate) ) };
+ foreach my $item (@{$self->{_rss_parser}{items}}) {
+ my $item_values = {
+ map { ucfirst($_) => $item->{$_} }
+ (qw(title link url guid pubDate) )
+ };
+ $item_values->{Link} //= $item_values->{Url};
+ if (defined( $item->{'description'} ) ) {
+ $item_values->{Description} = decode_entities($item->{'description'});
+ } else {
+ $item_values->{Description} = 'No content/description for this item';
+ }
+ push (@{$parsed_feed->{items}}, $item_values);
+ }
+ return $parsed_feed;
+}
+
+1;
-----------------------------------------------------------------------
More information about the rt-commit
mailing list