Skip to content

Instantly share code, notes, and snippets.

@stompro
Last active January 22, 2018 21:25
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 stompro/1cd3008785995517e0305fb280a0d8ef to your computer and use it in GitHub Desktop.
Save stompro/1cd3008785995517e0305fb280a0d8ef to your computer and use it in GitHub Desktop.
SendSMSFlowRoute Reactor for Evergreen ILS
Reactor to use the flowroute SMS API to send notices for the Evergreen ILS. Template shown is in test mode, it always sends to the same phone number.
Event params need to be set for the FlowRoute API credentials, accesskey and secretkey.
[% phone = target.0.sms_notify | replace('[\s\-\(\)]', '') -%]
[% cid = target.0.pickup_lib.phone | replace('[\s\-\(\)]', '') -%]
[% IF phone.match('^[2-9]') %][% country = 1 %][% ELSE %][% country = '' %][% END -%]
[%-
user = target.0.usr
system_shortname = user.home_ou.parent_ou.shortname
#target.0.sms_notify
realphone = country _ phone
tophone = '15555552110'
fromphone = '15555556040'
-%]
[%- message = BLOCK -%]
You have [% target.size %] [% IF target.size == 1 %]item[% ELSE %]items[% END %] available at the [% target.0.pickup_lib.name %], please pickup before [% target.0.shelf_expire_time.substr(0,10) %]. Reply with HELP for more info. debug [% target.0.pickup_lib.parent_ou.id %].
[%- END -%]
{"to": "[% tophone %]", "from": "[% fromphone %]", "body": "[% helpers.escape_json(message) %]"}
package OpenILS::Application::Trigger::Reactor::SendSMSFlowRoute;
use strict; use warnings;
use Error qw/:try/;
use Data::Dumper;
use LWP::UserAgent;
use HTTP::Request::Common;
use JSON::XS;
use OpenSRF::Utils::SettingsClient;
use OpenILS::Application::Trigger::Reactor;
use OpenSRF::Utils::Logger qw/:logger/;
use Encode;
$Data::Dumper::Indent = 0;
use base 'OpenILS::Application::Trigger::Reactor';
my $log = 'OpenSRF::Utils::Logger';
# Flowroute API Version 2.1
# http://developer.flowroute.com/api/messages/v2.1/send-an-sms/
my $api_endpoint = 'https://api.flowroute.com/v2.1/messages';
sub ABOUT {
return <<ABOUT;
The SendSMSFlowRoute Reactor Module attempts to make a request to the
flowroute messaging api services, via LWP::UserAgent,
whatever is constructed by the template passed in from the Event Definition.
The template needs to output a json string in the format required by the API.
No default template is assumed, and all information is expected to be
gathered by the
Event Definition through either Environment or Parameter definitions.
Required Action/Trigger parameters:
accesskey = "12345678" #FlowRoute API Access Key
secretkey = "kdjaksjldkfj" #FlowRoute API Secret Key
ABOUT
}
sub handler {
my $self = shift;
my $env = shift;
my $ua = LWP::UserAgent->new();
my $text = encode_utf8($self->run_TT($env));
return 0 if (!$text);
my $req = POST( $api_endpoint,'Content-Type' => 'application/vnd.api+json', Content => $text );
$req->authorization_basic($env->{params}{accesskey},$env->{params}{secretkey});
my $timeout = 1; #First timeout, doubled after each failure;
my $max_timeout = 1024; # 11 retries , ~34 minutes before erring out on transient errors
# Flowroute Error Codes http://developer.flowroute.com/api/errors/
my $perm_failure = '400|401|403|404|405|415|422';
my $temp_failure = '429|500|503';
my $res;
while(1){
$res = $ua->request( $req );
last if $res->code == 202; #Success
if ( $res->code =~ /$perm_failure/ || $timeout > $max_timeout ) {
#print "Perm Failure: Exiting, code:".$res->code.", Response-Message:".$res->message."\n";
$logger->error("SendSMSFlowRoute Reactor: unable to send SMS: Perm Failure: Exiting, code:".$res->code.", Response-Message:".$res->message);
return 0;
}
if ( $res->code =~ /$temp_failure/ ) {
#wait and try again
#print "Temp Failure: Sleep for $timeout seconds, code:".$res->code.", Response-Message:".$res->message."\n";
$logger->error("SendSMSFlowRoute Reactor: unable to send SMS: Temp Failure: Sleep for $timeout seconds, code:".$res->code.", Response-Message:".$res->message);
sleep($timeout);
$timeout *= 2 ;
next;
}
$logger->error("SendSMSFlowRoute Reactor: unable to send SMS: Unknown Failure: Exiting, code:".$res->code.", Response-Message:".$res->message);
#print "Unknown Failure: Exiting, code:".$res->code.", Response-Message:".$res->message."\n";
return 0; #should log this also
}
#success
#print "respose-Code: " . $res->code . " reponse-Message: " . $res->message . " Content: " . $res->content . "\n";
my $content = decode_json $res->content;
#print Dumper($content);
#print "Flowroute Message ID: ".$content->{data}->{id}."\n";
#The Message ID should probably be stored somewhere to process delivery reports.
$logger->info("SendSMSFlowRoute Reactor: successfully sent SMS, Message ID:".$content->{data}->{id});
return 1;
}
1;
package OpenILS::Application::Trigger::Reactor::SendSMSFlowRoute;
use strict; use warnings;
use Error qw/:try/;
use Data::Dumper;
use LWP::UserAgent;
use HTTP::Request::Common;
use JSON::XS;
use OpenSRF::Utils::SettingsClient;
use OpenILS::Application::Trigger::Reactor;
use OpenSRF::Utils::Logger qw/:logger/;
use OpenILS::Utils::CStoreEditor qw/:funcs/;
use Encode;
$Data::Dumper::Indent = 0;
use base 'OpenILS::Application::Trigger::Reactor';
my $log = 'OpenSRF::Utils::Logger';
# Flowroute API Version 2.1
# http://developer.flowroute.com/api/messages/v2.1/send-an-sms/
my $api_endpoint = 'https://api.flowroute.com/v2.1/messages';
sub ABOUT {
return <<ABOUT;
The SendSMSFlowRoute Reactor Module attempts to make a request to the
flowroute messaging api services, via LWP::UserAgent,
whatever is constructed by the template passed in from the Event Definition.
The template needs to output a json string in the format required by the API.
No default template is assumed, and all information is expected to be
gathered by the
Event Definition through either Environment or Parameter definitions.
Required Action/Trigger parameters:
accesskey = "12345678" #FlowRoute API Access Key
secretkey = "kdjaksjldkfj" #FlowRoute API Secret Key
ABOUT
}
sub handler {
my $self = shift;
my $env = shift;
my $ua = LWP::UserAgent->new();
my $text = encode_utf8($self->run_TT($env));
return 0 if (!$text);
my $req = POST( $api_endpoint,'Content-Type' => 'application/vnd.api+json', Content => $text );
$req->authorization_basic($env->{params}{accesskey},$env->{params}{secretkey});
my $timeout = 1; #First timeout, doubled after each failure;
my $max_timeout = 1024; # 11 retries , ~34 minutes before erring out on transient errors
# Flowroute Error Codes http://developer.flowroute.com/api/errors/
my $perm_failure = '400|401|403|404|405|415|422';
my $temp_failure = '429|500|503';
my $res;
while(1){
$res = $ua->request( $req );
last if $res->code == 202; #Success
if ( $res->code =~ /$perm_failure/ || $timeout > $max_timeout ) {
#print "Perm Failure: Exiting, code:".$res->code.", Response-Message:".$res->message."\n";
$logger->error("SendSMSFlowRoute Reactor: unable to send SMS: Perm Failure: Exiting, code:".$res->code.", Response-Message:".$res->message);
return 0;
}
if ( $res->code =~ /$temp_failure/ ) {
#wait and try again
#print "Temp Failure: Sleep for $timeout seconds, code:".$res->code.", Response-Message:".$res->message."\n";
$logger->error("SendSMSFlowRoute Reactor: unable to send SMS: Temp Failure: Sleep for $timeout seconds, code:".$res->code.", Response-Message:".$res->message);
sleep($timeout);
$timeout *= 2 ;
next;
}
$logger->error("SendSMSFlowRoute Reactor: unable to send SMS: Unknown Failure: Exiting, code:".$res->code.", Response-Message:".$res->message);
#print "Unknown Failure: Exiting, code:".$res->code.", Response-Message:".$res->message."\n";
return 0; #should log this also
}
#success
#print "respose-Code: " . $res->code . " reponse-Message: " . $res->message . " Content: " . $res->content . "\n";
my $content = decode_json $res->content;
#print Dumper($content);
#print "Flowroute Message ID: ".$content->{data}->{id}."\n";
#The Message ID should probably be stored somewhere to process delivery reports.
$logger->info("SendSMSFlowRoute Reactor: successfully sent SMS, Message ID:".$content->{data}->{id});
#Store the message ID in a new event_output row - for delivery processing later.
# Copied from AstCall.pm
my $e = new_editor(xact => 1);
my $eo = Fieldmapper::action_trigger::event_output->new;
#Contents of async_output will just be the message ID From flowroute.
$eo->data($content->{data}->{id});
$eo = $e->create_action_trigger_event_output($eo) or return $e->die_event;
my @eventids = map {$_->id} @{$env->{event}};
@eventids or push @eventids, '';
foreach (@eventids) {
my $event = $e->retrieve_action_trigger_event($_);
$event->async_output($eo->id);
$e->update_action_trigger_event($event);
}
$e->commit;
#$logger->info("SendSMSFlowRoute Reactor: commit changes");
return 1;
}
1;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment