#!/usr/bin/perl use strict; use NIE::Siebel; use NIE::MyWS; use NIE::Issue; use NIE::Utils; use Term::UI; use Term::ReadLine; use Getopt::Long; use Pod::Usage; use Data::Dumper; # this will try and extract siebel ids. Once we have a potential list, we will # check with standard NIE utilitles my $test=" 9 asd 3 ad 23 bb 234 B-4-Q0KEI - Data centeer id B-4-Q0KEI- Data centeer id B-4-Q0KEI# datacenter id B-P-2B9NE3K - ticket id B-P-2B9NE18 - ticket id B-P-2B9NE69- ticket id B-P-2B9IUC7XX- ticket id B-M-2CDHQV4- ticket id B-P-2B3O6BE-ticket id- ticket id B-M-2CRYYTD\$ - orderid "; my $sid_regexp = qr/([[:alpha:]]-[[:alnum:]]-\w+)/; my $ip_regexp = qr/\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/; my $qa = undef; my $debug = undef; my $verbose = undef; my $live = 1; #undef; # default to live (really update) but can turn this off. my $yes_just_once = undef; # Yes to one ticket my $abstract = "Status Change"; my $activity_type = undef; my $comments = undef; my $prompt_to_update = 1; my $issue_status = undef; my $extract_ids_from_comments = 1; # by default we extract ids from the text entered. my $extract_ips_from_comments = 1; # extract ips as well to look up tickets my $login = uc($ENV{USER}); my @issues; my @filters = $ENV{NIE_ISSUE_UPDATE_FILTER} || "and delegated_owner_login = '$login'"; my (%options) = ( "debug!" => sub { NIE::Issue->debug($debug) if ($debug); $debug++; }, "verbose!" => sub { NIE::Issue->verbose($verbose) if ($verbose); $verbose++; }, "qa!" => sub { $qa = 1; }, "abstract|a=s" => \$abstract, "comment|c=s" => \$comments, "dry-run|n" => sub { $live = undef }, "no-extract-ids" => sub { $extract_ids_from_comments = undef }, "extract-ids" => sub { $extract_ids_from_comments = 1 }, "no-extract-ids" => sub { $extract_ids_from_comments = 0 }, "extract-ips" => sub { $extract_ips_from_comments = 1 }, "no-extract-ips" => sub { $extract_ips_from_comments = 0 }, "ips" => sub { $extract_ips_from_comments = 1 }, "type|t=s" => sub { shift; $activity_type = to_activity_type($_[0]); }, "status=s" => sub { shift; $issue_status = to_issue_status($_[0]); }, "issue-status=s" => sub {$issue_status = to_issue_status('closed'); }, "help!" => sub { die_usage(1); }, "yes|y!" => \$yes_just_once, "YES!" => sub { $prompt_to_update = undef; }, "decon" => \&decon_server, ); sub die_usage { my ($a) = @_; if ($a) { pod2usage(-exitstatus => 0, -verbose => 2); exit; } else { pod2usage(2); exit; } } sub usage (;$) { # Print any arguments if (@_) { print join("\n", @_), "\n\n"; } die_usage(); exit(@_ ? 1 : 0); } sub extract_sids { # obscure uniq expression do { my %seen; grep { !$seen{$_}++ } @data }; my (@ids) = do { my %seen; grep { !$seen{$_}++ } ($_[0] =~ m/$sid_regexp/mg)}; return @ids; } sub extract_ips { # obscure uniq expression do { my %seen; grep { !$seen{$_}++ } @data }; my (@ids) = do { my %seen; grep { !$seen{$_}++ } ($_[0] =~ m/$ip_regexp/mg)}; return @ids; } # handle short hand for resolutions my %ACTIVITY_TYPES = ( # 'followup' => 'Follow Up', 'todo' => 'Todo', 'resolution' => 'Resolution', 'statussummary' => 'Status Summary', 'summary' => 'Status Summary', ); my %ISSUE_STATUS = ( 'open' => 'Open', 'closed' => 'Closed', 'cancelled' => 'FOOBAR', 'pending' => 'Pending', 'scheduled' => 'Scheduled', ); sub to_activity_type { my $tag = shift; return alias_to_string(\%ACTIVITY_TYPES, "activity", $tag); } sub to_issue_status { my $tag = shift; return alias_to_string(\%ISSUE_STATUS, "issue status", $tag); } sub decon_server { my $time = time(); my $future_time = $time + (30*24*60*60); #30 days with 24hrs in a day with 60 min in an hour with 60 sec in a min my ($second, $minute, $hour, $day, $month, $year, $dayOfWeek, $dayOfYear, $daylightSavings) = localtime($time); my ($fsecond, $fminute, $fhour, $fday, $fmonth, $fyear, $fdayOfWeek, $fdayOfYear, $fdaylightSavings) = localtime($future_time); $year += 1900; $fyear += 1900; my @month_name = qw(Jan Feb Mar Apr May June July Aug Sept Oct Nov Dec); my $decon_date = "$month_name[$fmonth]/$fday/$fyear"; return $decon_date; #print $decon_date; #main ($options{status}='closed'); #$issue_status = to_issue_status("closed"); #$comments = "Decon on $decon_date"; #$activity_type = to_activity_type("summary"); #$activity_type = "summary"; #$status = "closed"; } sub alias_to_string { my $ALIASES = shift; my $type = shift; my $tag = shift; my @matches = grep(/^${tag}/i, sort(keys(%$ALIASES))); # if we have 'Other' and 'Other H&E..' then we can't possibly handle the # match if we just enter 'Other'. So, if we have an ambiguious match, try an exact match. @matches = grep(/^$tag$/i, sort(keys(%$ALIASES))) if (! (@matches == 1)); if (@matches == 1) { return $ALIASES->{$matches[0]}; } elsif (@matches) { # More than one usage("Ambiguous action abbreviation '$tag' which has multiple matches:" . ' ' . join(', ', @matches)); # NOTREACHED } else { @matches = grep(/^$tag/i, sort(values(%$ALIASES))); return $matches[0] if (@matches == 1); usage("Unknown or unsupported $type type: '$tag'"); #return $tag; # if all else fails, assume it is a type we don't know # about but really exists. # NOTREACHED } } # # modify how lookups work in the Module. # sub replace_lookup { my $lu = shift; my @lookups = (); for my $i (@NIE::Issue::lookups) { if ($lu->{name} eq $i->{name}) { push @lookups, $lu; } else { push @lookups, $i; } } @NIE::Issue::lookups = @lookups; } replace_lookup({ 'name' => 'issue_id', 'type' =>'object', 'func' =>sub { my ($id) = @_; return is_issue_id($id) }, 'query' => "select issue_id from cmn_int.ak_issue where issue_id in (\$refs)", }, ); main: { my $dbh = undef; my $term = Term::ReadLine->new("brand"); die_usage() if (!GetOptions(%options)); NIE::Object->qa(1) if ($qa); if ($qa) { $dbh = openSiebelqa(); printf "open siebel qa\n"; } else { $dbh = openSiebel(); $NIE::MyWS::test_only = 0; } my @stuff_to_search = (); # So, if we specify the tickets from the command line, assume # that is more relevant than extraction from comments. if (@ARGV) { push @stuff_to_search, @ARGV; } else { # Extract everything that looks lke a siebel id. my @siebel_ids = (); push @siebel_ids, extract_sids($comments) if ($extract_ids_from_comments); # Use standard NIE::Util functions to classify tickets. push @stuff_to_search, map {(is_issue_id($_))?$_:()} @siebel_ids; push @stuff_to_search, map {(is_order_id($_))?$_:()} @siebel_ids; # search for ips if requested. push @stuff_to_search, extract_ips($comments) if ($extract_ips_from_comments); } my %search_opts = ('filter' => \@filters); if (! @ARGV) { $search_opts{lookups} = ['order_id','issue_id','ip_address']; } my @issues = NIE::Issue->search(\%search_opts, @stuff_to_search); if (@issues == 0) { printf STDERR "No ticket reference found.\n"; exit 1; } printf "Tickets DelegatedOwner Abstract\n%s\n\n", join("\n", map{sprintf "%-13s %-14s %s", $_->issue_id, $_->delegated_owner_login, $_->abstract} @issues); for my $i (@issues) { my $intid = undef; my $verbage = undef; $verbage .= sprintf "----------\nIssue: %s\n", $i->issue_id ; $verbage .= sprintf "IssueStatus: %s->%s\n", $i->status, $issue_status if ($issue_status); $verbage .= sprintf "ActivityType: %s\nActivityAbstract: \"%s\"\nActivityComments:\n\"%s\"\n", $activity_type, $abstract, $comments if ($activity_type); if ($prompt_to_update && !$yes_just_once) { my $reply = $term->get_reply( prompt => "y/n/YES/NO? (YES/NO => y/n to all tickets)", allow => ['y','n','YES','NO'], print_me => $verbage); next if ($reply eq 'n'); last if ($reply eq 'NO'); $prompt_to_update = undef if ($reply eq 'YES'); } $yes_just_once = 0 if ($yes_just_once); printf "Updating %s\n", $i->issue_id; if ($live) { $intid = addFollowup($i->issue_id, $abstract, $comments, undef, undef, undef, undef, $activity_type); } if ($issue_status) { if ($live && $i->status ne $issue_status) { $intid = UpdateNoccSRTicket( 'SRId' => $i->issue_id, 'Status' => $issue_status ); } } } }