Rt-askForFeedback

From Request Tracker Wiki
Jump to navigation Jump to search

Installation

1. Create a Global "Custom Field" with the Name: "Reminder4Stalled".
2. Place this script somewhere on a server:

#!/usr/bin/perl -w

 # This Script bases on:
 # http://requesttracker.wikia.com/wiki/RtUnifiedreminder
 
 ###############################################
 ### Author: Pascal Wagenhofer / Q-X GmbH, Switzerland
 ### Email: wagenhofer@q-x.ch
 ### Date: 07/15/2013
 ###############################################
 ### This script is provided "as it is" and comes without any warranty. Use it, modify
 ### it or do whatever you want with it.
 ###############################################
 ### Feedback is always welcome at wagenhofer@q-x.ch
 ###############################################
 
 ### INSTALLATION ###
 ### Read http://requesttracker.wikia.com/wiki/Rt-askForFeedback
 
 # RT3 reminder script
 # One big reminder report about ALL tickets that are getting to be too long since LastUpdated
 # Sends multipart HTML + plaintext email, so HTML capable mail readers can click links
 # Many pieces cannibalized from the other reminder scripts in the wiki.
 
 # You will run this script from cron as a user with perms to read the RT_SiteConfig.pm config file
 # Crontab would look like this to run twice a day, at 10:15am and 3:15pm
 ## send unified remind email twice per day
 #15 10 * * * /home/crystalfontz/scripts/rt_reminder2cust.pl
 
 # This Script bases on:
 # http://requesttracker.wikia.com/wiki/RtUnifiedreminder
 
 ### Configuration
 
 # Location of RT3's libs -- Change this to where yours are
 use lib ("/usr/share/request-tracker3.8/lib", "/usr/local/share/request-tracker3.8/lib", "/usr/local/rt/lib");
 
 # Address emails should originate from
 my($from) = 'Ticket Sys <your@mail.ticketsys.com>';
 
 # maximum number of seconds since LastUpdated, beyond which the ticket will be reported
 my %max_untouched_ages = (
                           "stalled" => 60 * 60 * 24 * 3,  # 3 days before warn about stalled
                           "2beclosed" => 60 * 60 * 24 * 3,  # 3 days before warn about stalled
                          );
 
 # Queues to operate on. Default is all
 # my @goodqueues = qw[ThisQueue ThatQueue]; # to look only in specific queues, uncomment this line and comment the next one
 my @goodqueues = (); # leave like this to look in all queues
 
 # Queues to skip. Default is none. Use either @goodqueues or @badqueues, not both.
 # my @badqueues = qw[ ]; # If you have no queues to exclude, uncomment this line and comment the next one
 #my @badqueues = qw[Ignoreme IgnoreAnother]; # To exclude certain queues, list them here and comment line above
 
 my($debug) = 0; # nonzero will print plaintext report to STOUT instead of emailing it
 
 # The length at which lines for plaintext mail will be truncated. 78, or thereabouts looks
 # best for most people. Setting to 0 will stop lines being truncated.
 my($linelen) = 78; # has no effect on HTML mail
 
 #Enter here the path/url for the REST-API of Request Tracker
 my($apiurl) = "https://your.url.tld/rt3/REST/1.0/";
 my($username) = "username"; #Username to access RT3 (needs to have rights to update CF in the appropriate Queue(s)
 my($password) = "password"; #Password of the above username
 my($agentname) = "Your LWP::Agent-Name";
 
 #Mail-Section
 my $plainbody = "your Body of the E-Mail (Plaintext)";
 my $subjectline = "Your subject of the e-mail to the customer"; #Example: "[TicketSys #$ticketNumber] $subject"
 
 
 ### Code
 
 use strict;
 use Carp;
 use MIME::Lite;
 use URI::Escape;
 use LWP;
 
 # Pull in the RT stuff
 package RT;
 use RT::Interface::CLI qw(CleanEnv GetCurrentUser GetMessageContent loc);
 
 CleanEnv();       # Clean our the environment
 RT::LoadConfig(); # Load the RT configuration
 RT::Init();       # Initialise RT
 
 use RT::Date;
 use RT::Queue;
 use RT::Queues;
 use RT::Tickets;

 my $max_age = 0;

 my $user = new RT::User($RT::SystemUser); # Define an RT User variable
 my $tickets = new RT::Tickets($RT::SystemUser); # Used to store Ticket search results
 my $date = new RT::Date($RT::SystemUser); # Define a date variable (used for comparisions)
 my $now = new RT::Date($RT::SystemUser); # get current time
 $now->SetToNow();
 
 # Limit the ticket search to new and open only.
 $tickets->LimitCustomField(
	CUSTOMFIELD => 'Reminder4Stalled',
		OPERATOR => '!=',
		VALUE => '1'
 );
 $tickets->LimitStatus(VALUE => 'stalled');
 
 my $searchqueue = ;
 
 if($#goodqueues != -1)
 {
     $tickets->_OpenParen();
     foreach my $queue (@goodqueues)
     {
         $tickets->LimitQueue(VALUE => $queue, OPERATOR => '=');
     }
     $tickets->_CloseParen();
     $searchqueue = " AND (Queue = '". join("' OR Queue = '", @goodqueues) ."')";
 }
 elsif($#badqueues != -1)
 {
     foreach my $queue (@badqueues)
     {
         $tickets->LimitQueue(VALUE => $queue, OPERATOR => '!=');
     }
     $searchqueue = " AND Queue != '". join("' AND Queue != '", @badqueues) ."'";
 }

 $tickets->OrderByCols( {FIELD => 'Status', ORDER => 'ASC'},
                        {FIELD => 'queue', ORDER => 'ASC'},
                        {FIELD => 'Priority', ORDER => 'DESC'},
                        {FIELD => 'LastUpdated', ORDER => 'ASC'},
                       );

 # We might not want to print the message if there are no tickets
 my($printmsg) = 0;

 my $j = 0;
 my $bgcolor = ;
 my $last_status = ;
 my $status_title = ;
 my $count_by_status = 0;
 my $searchURL = ;

 # Loop through tickets for reminder
 while (my $Ticket = $tickets->Next)
 {
     # Compare Dates to see if LastUpdated date is old enough to report
     $max_age = $max_untouched_ages{$Ticket->Status} || 0;
     my $max_age_2resolve = $max_untouched_ages{'2beclosed'} || 0;
 
     $date->Set(Format => "ISO", Value => $Ticket->LastUpdated);
     if ($now->Unix - $date->Unix < $max_age) { next; } # skip it if too young
     $j++;
 
     $user->Load($Ticket->Owner);
     
	use LWP;
	my $ua = LWP::UserAgent->new;
	$ua->timeout(10);
	$ua->agent($agentname);
	my $uri = $apiurl;
	my $access_user = $username;
	my $access_password = $password;
	my $ticketNumber = $Ticket->{values}->{'id'};
	my @customermail = "";

     my $response = $ua->post($uri."ticket/$ticketNumber/edit",
   ['user' => $access_user, 'pass' => $access_password,
    'content' => 'CF.{Reminder4Stalled}: 1']);
    
    if ($response->is_success) {
 
     if($Ticket->Status ne $last_status)
     { 
         $last_status = $Ticket->Status;
 
         $count_by_status = 0; # reset on every difft status

         # get a date object that can give us the datetime cutoff for this query
         $date->SetToNow();
     }
 
     # Use our own date formatting routine
     my($updated) = &formatDate($Ticket->LastUpdatedObj->Unix);
     my($subject) = $Ticket->Subject ? $Ticket->Subject : "(No subject)";
     my($queue) = substr($Ticket->QueueObj->Name, 0, 7);
 
     my($line) = sprintf "%5d  %-7s %3d  %-13s %-7s %-6s %-30s",
                          $Ticket->Id, $Ticket->Status, $Ticket->Priority, $updated, $queue, $user->Name, $subject;
 
     # Truncate lines if required
     if($linelen)
     {
         $line = substr($line, 0, $linelen);
     }
     
     # ---- GET ALL REQUESTORS
	my $response = $ua->post($uri."ticket/$ticketNumber",
	['user' => $access_user, 'pass' => $access_password]);

	if ($response->is_success) {
	my $html = $response->decoded_content;
	my @array1=split(/\n/,$html);
	my @array2=split(/Requestors: (.*)/,$array1[11]);
	if ($#array2 > 1) {
		@customermail=split(m/\ (.*)/,$array2[1]);
	} else {
		@customermail=$array2[1];
	}
	
	# ----- END GET ALL REQUESTORS

	my $receiviers = "";
	my $sendto = $array2[1];
	
	my $subjecttot = $subjectline;
	
	my $msg = MIME::Lite->new(From    => $from,
                           To      =>  join(',', $sendto),
                           Subject => $subjecttot,
                           Type    => 'text/plain',
                           Charset    => 'utf8',
			   Data	=> $plainbody);
 
     if ($debug)
     {
	 print "Would send E-Mail for Ticket #".$ticketNumber."\n";
     }
     else
     {
	$msg->send;
     }
     }
 }
}

 $tickets = new RT::Tickets($RT::SystemUser); # Used to store Ticket search results
 $tickets->LimitCustomField(
	CUSTOMFIELD => 'Reminder4Stalled',
		OPERATOR => '=',
		VALUE => '1'
 );
$searchqueue = ;
 
 if($#goodqueues != -1)
 {
     $tickets->_OpenParen();
     foreach my $queue (@goodqueues)
     {
         $tickets->LimitQueue(VALUE => $queue, OPERATOR => '=');
     }
     $tickets->_CloseParen();
     $searchqueue = " AND (Queue = '". join("' OR Queue = '", @goodqueues) ."')";
 }
 elsif($#badqueues != -1)
 {
     foreach my $queue (@badqueues)
     {
         $tickets->LimitQueue(VALUE => $queue, OPERATOR => '!=');
     }
     $searchqueue = " AND Queue != '". join("' AND Queue != '", @badqueues) ."'";
 }

 $tickets->OrderByCols( {FIELD => 'Status', ORDER => 'ASC'},
                        {FIELD => 'queue', ORDER => 'ASC'},
                        {FIELD => 'Priority', ORDER => 'DESC'},
                        {FIELD => 'LastUpdated', ORDER => 'ASC'},
                       );

 # We might not want to print the message if there are no tickets
($printmsg) = 0;

$j = 0;
$bgcolor = ;
$last_status = ;
$status_title = ;
$count_by_status = 0;
$searchURL = ;

# Loop through tickets to close
 while (my $Ticket = $tickets->Next)
 {
     # Compare Dates to see if LastUpdated date is old enough to report
     $max_age = $max_untouched_ages{$Ticket->Status} || 0;
     my $max_age_2resolve = $max_untouched_ages{'2beclosed'} || 0;
 
     $date->Set(Format => "ISO", Value => $Ticket->LastUpdated);
     if ($now->Unix - $date->Unix < $max_age_2resolve) { next; } # skip it if too young
     $j++;
 
     $user->Load($Ticket->Owner);

     if($Ticket->Status ne $last_status)
     { 
         $last_status = $Ticket->Status;
 
         $count_by_status = 0; # reset on every difft status
 
         # get a date object that can give us the datetime cutoff for this query
         $date->SetToNow();
     }
 
     # Use our own date formatting routine
     my ($updated) = &formatDate($Ticket->LastUpdatedObj->Unix);
     my ($subject) = $Ticket->Subject ? $Ticket->Subject : "(No subject)";
     my ($queue) = substr($Ticket->QueueObj->Name, 0, 7);
 
     my ($line) = sprintf "%5d  %-7s %3d  %-13s %-7s %-6s %-30s",
                          $Ticket->Id, $Ticket->Status, $Ticket->Priority, $updated, $queue, $user->Name, $subject;
			  
     if ($debug)
     {
	 print "Would close Ticket ".$Ticket->Id."\n\n";
     }
     else
     {
	  $Ticket->Resolve();
     }
}

 
 # Disconnect before we finish off
 $RT::Handle->Disconnect();
 exit 0;
 
 # Formats a date like: Thu 10-07-03
 # Designed to be consice yet useful
 sub formatDate() {
     my($unixtime) = @_;
     my(@days) = ( "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" );
     # Return an empty string if we haven't been given a time
     return "" if $unixtime <= 0;
     my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($unixtime);
     return sprintf "%s %02d-%02d-%02d", $days[$wday], $mon+1, $mday, $year%100;
 }

3. install a Cronjob on your server (see script head)

4. Now, we need to setup a new Scrip to reset the "Reminder4Stalled"-Field in case of Correspondance. Create a new Scrip in the Global-Section which looks like this:

Description: "Set Reminder4Stalled = 0"
Condition: "On Correspondance"
Action: "User defined"
Template: "Global Template: empty"
Phase: "TransactionCreate"

User Defined Condition:

return 1;

User Defined Action Preparation Code:

my $ticket = $self->TicketObj;
my $cf_obj = RT::CustomField->new($RT::SystemUser);
my $cf_name = "Reminder4Stalled";
my $cf_value = "0";

$cf_obj->LoadByName( Name => $cf_name );
$RT::Logger->debug( "Loaded \$cf_obj->Name = ". $cf_obj->Name() ."\n" );
$ticket->AddCustomFieldValue( Field=>$cf_obj, Value=>$cf_value,
RecordTransaction=>0 );

User Defined Post Action Code:

return 1;