Browse Source

adding SMS stuff so we don't forget about it

Signed-off-by: Chris Cormack <crc@liblime.com>
Signed-off-by: Joshua Ferraro <jmf@liblime.com>
3.0.x
Joshua Ferraro 16 years ago
parent
commit
76064f4623
  1. 149
      C4/SMS.pm
  2. 40
      koha-tmpl/intranet-tmpl/prog/en/modules/sms/sms-home.tmpl
  3. 351
      misc/cronjobs/smsoverdues.pl
  4. 43
      sms/sms.pl
  5. 131
      sms/sms_listen.pl
  6. 16
      sms/sms_listen_windows_start.pl

149
C4/SMS.pm

@ -0,0 +1,149 @@
package C4::SMS;
#Written by tgarip@neu.edu.tr for SMS message sending and other SMS related services
use strict;
require Exporter;
use LWP::UserAgent;
use C4::Context;
use vars qw($VERSION @ISA @EXPORT);
$VERSION = 0.01;
my $user=C4::Context->config('smsuser');
my $pwd=C4::Context->config('smspass');
my $uri ="https://spgw.kktcell.com/smshttpproxy/SmsHttpProxyServlet";
@ISA = qw(Exporter);
@EXPORT = qw(
&get_sms_auth
&send_sms
&read_sms
&error_codes
&parse_phone
&parse_message
&write_sms
&mod_sms
&kill_sms
);
sub get_sms_auth {
my $ua = LWP::UserAgent->new;
my $commands;
my $res=$ua->post($uri,[cmd=>'REGISTER',pUser=>$user,pPwd=>$pwd]);
if ($res->is_success){
$commands=parse_content($res->content);
}
return($commands,$ua);
}
sub send_sms{
my $ua=shift;
my $phone=shift;
my $message=shift;
my $session=shift;
my $res=$ua->post($uri,[cmd=>'SENDSMS',pUser=>$user,pPwd=>$pwd,pSessionId=>$session,pService_Code=>4130,pMsisdn=>$phone,
pContent=>$message]);
return parse_content($res->content);
}
sub read_sms{
my $ua=shift;
my $session=shift;
my $res=$ua->post($uri,[cmd=>'GETSMS',pUser=>$user,pPwd=>$pwd,pSessionId=>$session,pService_Code=>4130]);
return parse_content($res->content);
}
sub parse_content{
my $content=shift;
my %commands;
my @attributes=split /&/,$content;
foreach my $params(@attributes){
my (@param)=split /=/,$params;
$commands{$param[0]}=$param[1];
}
return(\%commands);
}
sub error_codes{
my $error=shift;
if ($error==-1){
return "Closed session - Retry ";
}elsif($error==-2){
return "Invalid session - Retry ";
}elsif($error==-3){
return "Invalid password" ;
}elsif($error==-103){
return "Invalid user";
}elsif($error==-422){
return "Invalid Parameter";
}elsif($error==-426){
return "User doesn’t have permission to send message";
}elsif($error==-700){
return "No permission";
}elsif($error==-801){
return " Msdisn count differs-warn administartor";
}elsif($error==-803){
return "Content count differs from XSER count";
}elsif($error==-1101){
return " Insufficient Credit Do not retry" ;
}elsif($error==-1104){
return "Invalid Phone number";
}elsif($error==-10001){
return " Internal system error- Tell Turkcell/Telsim";
}elsif($error==-9005){
return " No messages to read";
}elsif ($error){
return "Unknow error no $error occured - tell Turkcell/Telsim";
}
}
sub parse_phone{
## checks acceptable phone numbers
## Fix to accept Telsim when available (542 numbers)
my $phone=shift;
$phone=~s/^0//g;
$phone=~s/ //g;
my $length=length($phone);
if ($length==10 || $length==12){
my $code=substr($phone,0,3) if $length==10;
$code=substr($phone,0,5) if $length==12;
if ($code=~/533/){
return $phone;
}else{
return 0;
}
}else{
return 0;
}
}
sub parse_message{
my $message=shift;
$message=~s/ / /g;
my @parsed=split / /,$message;
return (@parsed);
}
sub write_sms{
my ($userid,$message,$phone)=@_;
my $dbh=C4::Context->dbh;
my $sth=$dbh->prepare("INSERT into sms_messages(userid,message,user_phone,date_received) values(?,?,?,now())");
$sth->execute($userid,$message,$phone);
$sth->finish;
return $dbh->{'mysql_insertid'};
}
sub mod_sms{
my ($smsid,$message)=@_;
my $dbh=C4::Context->dbh;
my $sth=$dbh->prepare("UPDATE sms_messages set reply=? ,date_replied=now() where smsid=?");
$sth->execute($message,$smsid);
$sth->finish;
}
sub kill_sms{
#end a session
my $ua=shift;
my $session=shift;
my $res=$ua->post($uri,[cmd=>'KILLSESSION',pSessionId=>$session]);
}
1;
__END__

40
koha-tmpl/intranet-tmpl/prog/en/modules/sms/sms-home.tmpl

@ -0,0 +1,40 @@
<!-- TMPL_INCLUDE NAME="doc-head-open.inc" -->
<title>SMS Administration</title>
<!-- TMPL_INCLUDE NAME="doc-head-close.inc" -->
</head>
<body>
<!-- TMPL_INCLUDE NAME="header.inc" -->
<div id="doc3" class="yui-t2">
<div id="bd">
<div id="yui-main">
<div class="yui-b"><div class="yui-g">
<h1>NEULIS SMS Administration</h1>
<table>
<caption>SMS Messaging </caption>
<!--TMPL_IF NAME="error"--><div class="error"><!--TMPL_VAR NAME="error"--> </div><!--/TMPL_IF-->
<form action="/cgi-bin/koha/sms/sms.pl" method="post">
<tr><input type="hidden" value="sendsms" name="operation"/>
<td >Your Message<textarea name="message" cols="35" rows="4"><!--TMPL_VAR NAME="message"--></textarea></td>
</tr>
<tr>
<td>Phone:<input type="text" name="phone" value="<!--TMPL_VAR NAME="phone"-->"/>5338644143</th>
</tr>
<tr>
<td><input type="submit" value="Send SMS"></td>
</tr>
</form>
<th>Şu anda sadece KTcell abonelerine mesaj gönderilebilir. Rezervasyonu gelenler için kullanın!</th>
</table>
</div>
</div>
</div>
<!-- TMPL_INCLUDE NAME="mainmenu.inc" -->
<!-- TMPL_INCLUDE name="intranet-bottom.inc" -->

351
misc/cronjobs/smsoverdues.pl

@ -0,0 +1,351 @@
#!/usr/bin/perl
# This script loops through each overdue item, determines the fine,
# and updates the total amount of fines due by each user. It relies on
# the existence of /tmp/fines, which is created by ???
# Doesnt really rely on it, it relys on being able to write to /tmp/
# It creates the fines file
#
# This script is meant to be run nightly out of cron.
# Copyright 2000-2002 Katipo Communications
#
# This file is part of Koha.
#
# Koha is free software; you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# Koha 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
# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
# Suite 330, Boston, MA 02111-1307 USA
# $Id: sendoverdues.pl,v 1.1.2.1 2007/03/26 22:38:09 tgarip1957 Exp $
use C4::Context;
use C4::Search;
use C4::Circulation;
use C4::Circulation::Fines;
use C4::Members;
use C4::Date;
use HTML::Template::Pro;
use Mail::Sendmail;
use Mail::RFC822::Address;
use C4::SMS;
use utf8;
my ($res,$ua);##variables for SMS
my $date=get_today();
my $dbh = C4::Context->dbh;
notifyOverdues();
sub notifyOverdues {
# Look up the overdues for today.
# Capture overdues which fall on our dates of interest.
####################################################################################################
# Creating a big hash of available templates
my %email;
%email->{'template'}='email-2.txt';
my %sms;
%sms->{'template'}='sms-2.txt';
my %firstReminder->{'email'} = \%email;
%firstReminder->{'sms'} = \%sms;
my %email2;
%email2->{'template'}='email-7.txt';
my %secondReminder->{'email'} = \%email2;
my %sms2;
%sms2->{'template'}='sms-7.txt';
%secondReminder->{'sms'} = \%sms2;
my %letter2;
%letter2->{'template'}='letter-7.html';
%secondReminder->{'letter'} = \%letter2;
my %email3;
%email3->{'template'}='email-29.txt';
my %sms3;
%sms3->{'template'}='sms-29.txt';
my %letter3;
%letter3->{'template'}='letter-29.html';
my %finalReminder->{'email'} = \%email3;
%finalReminder->{'letter'} = \%letter3;
%finalReminder->{'sms'} = \%sms3;
my %actions;
%actions->{'1'}=\%firstReminder;
%actions->{'3'}=\%secondReminder;###This was 7 days changed to 3 days
%actions->{'20'}=\%finalReminder;###This was 29 days changed to 20 days
##################################################################################################################
my @overdues2;#an array for each actiondate
my @overdues7;
my @overdues29;
my $filename;
# Retrieve an array of overdues.
my ($count, $overduesReference) = Getoverdues();
my @overdues=@$overduesReference;
# We're going to build a hash of arrays, containing the items requiring action.
# ->borrowernumber, date, @overdues
my %actionItems;
foreach my $overdue (@overdues) {
my $due_day=$overdue->{'date_due'};
my $difference=DATE_subtract($date,$due_day);
# If does this item fall on a day of interest?
$overdue->{'difference'}=$difference;
foreach my $actiondate (keys(%actions)) {
if ($actiondate == $difference) {
$filename='overdues'.$actiondate;
push @$$filename,$overdue;
#print "$actiondate,-,$overdue->{borrowernumber}\n";
}
$actionItems{$actiondate} = \@$$filename;
}
}
# We now have a hash containing overdues which need actioning, we can step through each set.
# Work from earilest to latest. We only wish to send the most urgent message.
my %messages;
my %borritem;
foreach my $actiondate (keys %actions) {
# print "\n\nThe following items are $actiondate days overdue.\n";
my $items = $actionItems{$actiondate};
$filename='overdues'.$actiondate;
foreach my $overdue (@$$filename) {
# Detemine which borrower is responsible for this overdue;
# if the offender is a child, then the guarantor is the person to notify
my $borrowernumber=$overdue->{borrowernumber};
my $borrower=responsibleBorrower($borrowernumber);
my ($method, $address) = preferedContactMethod($borrower);
if ($method && $address) {
# Do we have to send something, using this method on this day?
if (%actions->{$actiondate}->{$method}->{'template'}) {
my $intranetdir=C4::Context->config('intranetdir');
# Template the message
my $template = HTML::Template::Pro->new(filename => $intranetdir.'/scripts/misc/notifys/templates/'.%actions->{$actiondate}->{$method}->{'template'}, die_on_bad_params => 0);
my @bookdetails;
my %row_data;
my $item = getiteminformation("", $overdue->{'itemnumber'});
$row_data{'BARCODE'}=$item->{'barcode'};
my $title=substr($item->{'title'},0,25)."...";
$title=changecharacter($title);
$row_data{'TITLE'}=$title;
$row_data{'DATE_DUE'}=format_date($overdue->{'date_due'});
$row_data{'cardnumber'}=$borrower->{'cardnumber'};
push(@bookdetails, \%row_data);
$template->param(BOOKDETAILS => \@bookdetails);
my $name= "$borrower->{'firstname'} $borrower->{'surname'}";
$template->param(NAME=> $name);
%messages->{$borrower->{'borrowernumber'}} = $template->output();
if ($method eq 'email') {
$result = sendEmail($address, 'library@library.neu.edu.tr', 'Overdue Library Items', %messages->{$borrowernumber});
logContact($borrowernumber, $method, $address, $result, %messages->{$borrowernumber});
}
elsif ($method eq 'sms') {
$result = sendSMS($address, %messages->{$borrowernumber});
logContact($borrowernumber, $method, $address, $result, %messages->{$borrowernumber});
}
elsif ($method eq 'letter') {
$result = printLetter($address, %messages->{$borrowernumber});
}
}##template exists
}else{
print "$borrowernumber has an overdue item, but no means of contact\n";
}##$method
} #end of 'foreach overdue'
} # end of foreach actiondate
}
sub responsibleBorrower {
# Given an overdue item, return the details of the borrower responible as a hash of database columns.
my $borrowernumber=shift;
if ($borrowernumber) {
my $borrower=BorType($borrowernumber);
# Overdue books assigned to children have notices sent to the guarantor.
if ($borrower->{'categorycode'} eq 'C') {
my $guarantor=BorType($borrower->{'guarantor'});
$borrower = $guarantor;
}
return $borrower;
}
}
sub preferedContactMethod {
# Given a reference to borrower details, in the format
# returned by BorType(), determine the prefered contact method, and address to use.
my $borrower=$_[0];
my $borrcat = getborrowercategoryinfo($borrower->{'categorycode'});
if( !$borrcat->{'overduenoticerequired'}){
return (undef,undef);
}
my $method='';
my $address='';
## if borrower has a phone set that as our preferrred contact
if ($borrower->{'phoneday'}) {
if (parse_phone($borrower->{phoneday})){
$address = parse_phone($borrower->{phoneday});
$method="sms";
return ($method, $address);
}
}
if (($borrower->{'emailaddress'}) and (Mail::RFC822::Address::valid($borrower->{'emailaddress'}))) {
$address = $borrower->{'emailaddress'};
$method="email";
return ($method, $address);
}
if ($borrower->{'streetaddress'}) {
$address = mailingAddress($borrower);
$method = 'letter';
}
#print "$method, $address\n";
return ($method, $address);
}
sub logContact {
# Given the details of an attempt to contact a borrower,
# log them in the attempted_contacts table of the koha database.
my ($borrowernumber, $method, $address, $result, $message) = @_;
my $querystring = " insert into attempted_contacts
(borrowernumber, method, address, result, message, date)
values (?, ?, ?, ?, ?, now())";
my $sth= $dbh->prepare($querystring);
$sth->execute($borrowernumber, $method, $address, $result, $message);
$sth->finish();
}
sub mailingAddress {
# Given a hash of borrower information, such as that returned by BorType,
# return a mailing address.
my $borrower=$_[0];
my $address = $borrower->{'firstname'}."\n".
$borrower->{'streetaddress'}."\n".
$borrower->{'streetcity'};
return $address;
}
sub sendEmail {
# Given an email address, and a subject and message, attempt to send email.
my $to=$_[0];
my $from=$_[1];
my $subject=$_[2];
my $message=$_[3];
# print "in email area";
# print "\nSending Email To: $to\n$message\n";
my %mail = ( To => $to,
CC => 'library@library.neu.edu.tr',
From => $from,
Subject => $subject,
Message => $message);
if (not(sendmail %mail)) {
warn $Mail::Sendmail::error;
warn "sendEmail to $to failed.";
return 0;
}
return 1;
}
sub sendSMS {
my ($phone, $message)=@_;
($res,$ua)=get_sms_auth() unless $res;
# Given a cell number and a message, attempt to send an SMS message.
my $sendresult=send_sms($ua,$phone,$message,$res->{pSessionId});
my $error=error_codes($sendresult->{pErrCode});
return 1 unless $error;
return $error;
}
sub printLetter {
print "letter\n";
# Print a letter
# FIXME - decide where to print
return 1;
}
sub changecharacter {
my ($string)=@_;
$_=$string;
s/ş/s/g;
s/Ş/S/g;
s/ü/u/g;
s/Ü/U/g;
s/ç/c/g;
s/Ç/C/g;
s/ö/o/g;
s/Ö/O/g;
s/ı/i/g;
s/İ/I/g;
s/ğ/g/g;
s/Ğ/G/g;
$string=$_;
return $string;
}
$dbh->disconnect();

43
sms/sms.pl

@ -0,0 +1,43 @@
#!/usr/bin/perl
use strict;
use CGI;
use C4::SMS;
use C4::Output;
use C4::Auth;
my ($res,$ua);
my %commands;
my $query = new CGI;
my $message=$query->param('message');
my $phone=$query->param('phone');
my $operation=$query->param('operation');
my $result;
my $errorcode;
my ($template, $loggedinuser, $cookie)
= get_template_and_user({template_name => "sms/sms-home.tmpl",
query => $query,
type => "intranet",
authnotrequired => 0,
flagsrequired => {circulate => 1},
debug => 1,
});
if ($operation eq"sendsms"){
$phone=parse_phone($phone);
if ($phone>0){
##write to a queue and exit
my $me=C4::Context->userenv;
my $card=$me->{cardnumber};
$result=write_sms($card,$message,$phone);
}else{
$errorcode=-1104;
}
}
my $error=error_codes($errorcode);
$template->param(error=>$error);
output_html_with_http_headers $query, $cookie, $template->output;

131
sms/sms_listen.pl

@ -0,0 +1,131 @@
#!/usr/bin/perl
use strict;
use C4::SMS;
use C4::Auth;
use C4::Context;
use C4::Members;
use C4::Circulation;
my ($res,$ua);
my %commands;
my $message;
my $phone;
my $result;
my $errorcode;
my $smsid;
my $wait=600;## 10 mn. wait between sms checking
my $dbh=C4::Context->dbh;
STARTAGAIN:
($res,$ua)=get_sms_auth();
AGAIN:
$errorcode=0;
if ($res->{pRetCode}==200){
$result=read_sms($ua,$res->{pSessionId});
$errorcode=$result->{pErrCode};
print "connected\n";
}else{
kill_sms($ua,$res->{pSessionId});
warn (error_codes($res->{pErrCode}),$res->{pErrcode}) ;
# sleep $wait;
goto FINISH;
}
if ($errorcode && $errorcode !=-9005){
kill_sms($ua,$res->{pSessionId});
warn error_codes($errorcode) ;
# sleep $wait;
goto FINISH;
}elsif ($errorcode ==-9005){
print "no more messages to read\n";
goto WAITING;
}
#Parse the message to a useful hash
my @action=parse_message( $result->{pContent});
## Log the request in our database;
$smsid=write_sms($action[1], $result->{pContent},$result->{pMsisdn});
print "message logged\n";
##Now do the service required
if (uc($action[0]) eq "RN"){
print "dealing request\n";
my ($ok,$cardnumber)=C4::Auth::checkpw($dbh,$action[1],$action[2]);
if($ok){
my $item=getiteminformation(undef,0,$action[3]);
if ($item){
my $borrower=getmember($cardnumber);
my $status=renewstatus(undef,$borrower->{borrowernumber},$item->{itemnumber});
if ($status==1){
my $date=renewbook(undef,$borrower->{borrowernumber},$item->{itemnumber});
$message="Uzatildi :Renewed ".$item->{barcode}." : ".$date;
my $send=send_message($result,$message,$smsid);
}elsif($status==2){
$message="Cok erken- yenilenmedi! :Too early-not renewed:".$item->{barcode};
my $send=send_message($result,$message,$smsid);
}elsif($status==3){
$message="Uzatamazsiniz GERI getiriniz! :No more renewals RETURN the item:".$item->{barcode};
my $send=send_message($result,$message,$smsid);
}elsif($status==4){
$message="Ayirtildi GERI getiriniz! :Reserved RETURN the item:".$item->{barcode};
my $send=send_message($result,$message,$smsid);
}elsif($status==0){
$message="Uzatilamaz! :Can not renew:".$item->{barcode};
my $send=send_message($result,$message,$smsid);
}
}else{
$message="Yanlis barkot! :Wrong barcode!";
my $send=send_message($result,$message,$smsid);
}#wrong barcode
}else{
$message="Yanlis kullanici/sifre! :Wrong username/password!";
my $send=send_message($result,$message,$smsid);
}##wrong user/pass
}else{
## reply about error
$message="Yanlis mesaj formati! :Wrong message! :
RN usercardno password barcode";
my $send=send_message($result,$message,$smsid);
}### wrong service
goto AGAIN;
WAITING:
##Now send the messages waiting in queue
my $smssth=$dbh->prepare("SELECT smsid,user_phone,message from sms_messages where date_replied like '0000-00-00%' ");
$smssth->execute();
my @phones;
while (my $data=$smssth->fetchrow_hashref){
push @phones,$data;
}
$smssth->finish;
foreach my $user(@phones){
print "replying $user->{user_phone}";
my $send=send_sms($ua,$user->{user_phone},$user->{message},$res->{pSessionId});
my $reply="--failed\n";
if ($send->{pRetCode}==200){
$reply= "--replied\n";
mod_sms($user->{smsid},"Sent");
}
print $reply;
}
$dbh->disconnect;
sub send_message{
my ($mes,$message,$smsid)=@_;
my $send=send_sms($ua,$mes->{pMsisdn},$message,$res->{pSessionId});
if ($send->{pRetCode}==200){
mod_sms($smsid,$message);
}else{
my $error=error_codes($send->{pErrCode});
mod_sms($smsid,"Not replied error:".$error);
}
return $send;
}
FINISH:
1;
__END__

16
sms/sms_listen_windows_start.pl

@ -0,0 +1,16 @@
#!/usr/bin/perl
# script that starts the zebraquee
# Written by TG on 01/08/2006
use strict;
use Win32::Process;
use Win32;
use C4::Context;
use CGI;
my $input=new CGI;
my $fileplace=C4::Context->config('intranetdir');
my $fullpath=$fileplace."/cgi-bin/sms";
my $ZebraObj;
my $pid=Win32::Process::Create($ZebraObj, "C:/perl/bin/perl.exe",'perl sms_listen.pl', 0, DETACHED_PROCESS,$fullpath) ;
print $input->redirect("/cgi-bin/koha/mainpage.pl?pid=$pid");
Loading…
Cancel
Save