#! /usr/bin/perl
use strict;
use warnings;
use Encode;
use Encode::Locale;
use Getopt::Long;
use Pod::Usage;
use SOAP::Lite;
use App::OTRS::CreateTicket;
print "$0 version " . App::OTRS::CreateTicket->VERSION() . "\n\n";
@ARGV = map { decode(locale => $_, 1) } @ARGV if -t STDIN;
binmode STDOUT, ":encoding(console_out)" if -t STDOUT;
binmode STDERR, ":encoding(console_out)" if -t STDERR;
my @TicketFields
= qw ( Title CustomerUser Queue Priority State Type Service SLA Owner Responsible );
my @ArticleFields = qw ( Subject Body ContentType ArticleType SenderType );
my @TicketOptions = map { $_ . '=s' } @TicketFields;
my @ArticleOptions = map { $_ . '=s' } @ArticleFields;
my %Param = ();
GetOptions(
\%Param,
# options for connection
'UserLogin=s',
'Password=s',
'Server=s',
'Operation=s',
'Namespace=s',
'Url=s',
'BodyFile=s',
'Ssl',
'help',
# options for ticket
@TicketOptions,
# options for article
@ArticleOptions,
# dynamic fields; can be multiple
'DynamicField=s%',
);
if ( $Param{help} || !$Param{Url} && !$Param{Server} ) {
pod2usage( -exitstatus => 0 );
}
my $URL;
# if we do not have a URL, compose one
if ( !$Param{Url} ) {
my $Server = $Param{Server} || 'localhost';
my $HTTPType = $Param{Ssl} ? 'https://' : 'http://';
$URL = $HTTPType . $Server . '/otrs/nph-genericinterface.pl/Webservice/GenericTicketConnector'
}
else {
$URL = $Param{Url};
}
# this name space should match the specified name space in the SOAP transport for the web service
my $NameSpace = $Param{Namespace} || 'http://www.otrs.org/TicketConnector/';
# this is operation to execute, it could be TicketCreate, TicketUpdate, TicketGet, TicketSearch
# or SessionCreate. and they must to be defined in the web service.
my $Operation = $Param{Operation} || 'TicketCreate';
# assign values for ticket and article data if undefined
$Param{Queue} ||= 'Postmaster';
$Param{Priority} ||= '3 normal';
$Param{Type} ||= 'default';
$Param{Title} ||= 'No title';
$Param{State} ||= 'new';
$Param{ContentType} ||= 'text/plain; charset=utf8';
$Param{Subject} ||= $Param{Title};
$Param{SenderType} ||= 'customer';
if ( $Param{BodyFile} ) {
open my $Filehandle, '<', $Param{BodyFile} or die "Can't open file $Param{BodyFile}: $!";
# read in file at once as in PBP
$Param{Body} = do { local $/; <$Filehandle> };
close $Filehandle;
} elsif ( !$Param{Body} ) {
binmode STDIN;
while ( my $Line = <> ) {
$Param{Body} .= $Line;
}
}
# Converting Ticket and Article data into SOAP data structure
my @TicketData;
for my $Element (@TicketFields) {
if ( defined $Param{$Element} ) {
my $Param = SOAP::Data->name( $Element => $Param{$Element} );
push @TicketData, $Param;
}
}
my @ArticleData;
for my $Element (@ArticleFields) {
if ( defined $Param{$Element} ) {
my $Param = SOAP::Data->name( $Element => $Param{$Element} );
push @ArticleData, $Param;
}
}
my $DynamicFieldXML;
if ($Param{DynamicField}) {
for my $DynamicField ( keys %{$Param{DynamicField}} ) {
$DynamicFieldXML .= "<DynamicField>\n"
. "\t<Name><![CDATA[$DynamicField]]></Name>\n"
. "\t<Value><![CDATA[$Param{DynamicField}->{$DynamicField}]]></Value>\n"
. "</DynamicField>\n";
}
}
my $SOAPObject = SOAP::Lite
->uri($NameSpace)
->proxy($URL)
->$Operation(
SOAP::Data->name('UserLogin')->value($Param{UserLogin}),
SOAP::Data->name('Password')->value($Param{Password}),
SOAP::Data->name(
'Ticket' => \SOAP::Data->value(
@TicketData,
)
),
SOAP::Data->name(
'Article' => \SOAP::Data->value(
@ArticleData,
)
),
SOAP::Data->type( 'xml'=> $DynamicFieldXML ),
);
# check for a fault in the soap code
if ( $SOAPObject->fault ) {
print $SOAPObject->faultcode, "\n";
print $SOAPObject->faultstring, "\n";
exit 0;
}
# otherwise print the results
else {
# get the XML response part from the SOAP message
my $XMLResponse = $SOAPObject->context()->transport()->proxy()->http_response()->content();
# deserialize response (convert it into a perl structure)
my $Deserialized = eval {
SOAP::Deserializer->deserialize($XMLResponse);
};
# remove all the headers and other not needed parts of the SOAP message
my $Body = $Deserialized->body();
# just output relevant data and no the operation name key (like TicketCreateResponse)
if ( defined $Body->{TicketCreateResponse}->{Error} ) {
print "Could not create ticket.\n\n";
print "ErrorCode: $Body->{TicketCreateResponse}->{Error}->{ErrorCode}\n";
print "ErrorMessage: $Body->{TicketCreateResponse}->{Error}->{ErrorMessage}\n\n";
exit 0;
}
else {
print "Created ticket $Body->{TicketCreateResponse}->{TicketNumber}\n";
}
}
exit 1;
__END__
=head1 NAME
otrs.CreateTicket.pl - create tickets in OTRS via web services.
=head1 SYNOPSIS
Example 1: all arguments on the command line
otrs.CreateTicket.pl --Server otrs.example.com --Ssl --UserLogin myname \
--Password secretpass --Title 'The ticket title' \
--CustomerUser customerlogin --Body 'The ticket body'
--DynamicField Branch="Sales UK" --DynamicField Source=Monitoring
Example 2: read body in from a file
otrs.CreateTicket.pl --Server otrs.example.com --Ssl --UserLogin myname \
--Password secretpass --Title 'The ticket title' \
--CustomerUser customerlogin --BodyFile description.txt
Example 3: read body in from STDIN
otrs.CreateTicket.pl --Server otrs.example.com --Ssl --UserLogin myname \
--Password secretpass --Title 'The ticket title' \
--CustomerUser customerlogin < description.txt
=head1 SYNTAX
otrs.CreateTicket.pl command syntax:
otrs.CreateTicket.pl [arguments]
Arguments:
SERVER CONNECTION
--Server Name of OTRS server.
--Ssl (boolean) If SSL (https) should be used.
Alternatively:
--Url Full URL to GenericTicket web service.
USER AUTHENTICATION
--UserLogin Login name of valid Agent account.
--Password Password for user.
TICKET DATA
--Title Title of ticket.
--CustomerUser Customer of ticket (mandatory!).
--Priority Defaults to '3 normal' if not specified.
--Queue Defaults to 'Postmaster' if not specified.
--Owner Optional.
--Responsible Optional, and only if activated on the server.
--Service Optional, and only if activated on the server.
--SLA Optional, and only if activated on the server.
--Type Optional, and only if activated on the server.
ARTICLE DATA
--Subject Optional, defaults to title if not defined.
--BodyFile Name of file that contains body text of the message
--Body Body text of the message.
--SenderType Optional, defaults to 'Customer'.
--ArticleType Optional, defaults to 'web-request'.
DYNAMIC FIELDS
--DynamicField Optional. Can be passed multiple times. Takes Name=Value pairs.
=cut