Welcome Guest Login Register Member List
ExpressionEngine Forums
Advanced Search
Username: Password:
Remember Me? forgot password?
You are here: Forum Home  >  Usage  >  Tips and Tricks  >  Thread
   
 
Perl Script to generate recurring tasks
 
selberg
Posted: 18 May 2008 09:00 AM   [ Ignore ]  
Newbie
Rank
Total Posts:  2
Joined  2008-05-18

Hi,  I really wanted to have recurring tasks so I wrote a perl script which I can automate via a cron job.  I leveraged the code by lkraven on “Create Tasks in Tracks via Email using the RESTFul API”, so I thought it would be good to share the results.  As with lkraven’s post, this is not for the begineer.  If you look inside the attachment you will see examples of adding a task with LWP.  I was also querying and parsing the contexts and projects using LWP and XML::Simple which avoided the need to know the context or project id’s.

The real magic comes from the Perl CPAN module Date::Manip.  The basic idea is to map a hash to a task and add an extra key for a recurrence.  The script is designed to execute once a day on a cron job, and if the recurrence of a given task ‘matched’ the present day, the task would be added to tracks.  Date::Manip provides all the support for the date descriptions.  The code seems to be too long for this page, and won’t attach, so I’ll try and include it via several posts.

Part 1 of 2

#!/usr/bin/perl
use strict;
use 
LWP::UserAgent;
use 
XML::Simple;
use 
Date::Manip;

my $userName = 'selberg';
my $password = 'password';
my $auth     = "$userName:$password";
my $baseurl  = 'http://apasrv02.soco.agilent.com:81';
my $this_month     = UnixDate( ParseDate('today'), '%B' );

# useful strings
# for every day => today
# for a given weekday => <weekday> (such as "Monday")
# for once a month => "First Wednesday in $this_month", "Second Thursday in $this_month"
# for once a month => 1st, 2nd, 12th, 22nd
# once a year => June 25th or YYYYMM or YY-MM

# list of tasks.  This might be nice to put into a config file or perhaps
# a database.  It should be a list of hashes where each hash defines a key.
# I think every field is optional except for the TITLE (which maps to the 
# Description)
my @recurringTasks = ( 
   
{ 'TITLE'     => 'Teach Omar a Script',
     
'CONTEXT'   => 'Mentor',
     
#'PROJECT'   => 'Linux Migration',
     
'TAGS'      => ['automated reminder'],
     
'DUE'       => 'Friday',
     
#'SHOW_FROM' => 'yesterday',
     
'RECURRANCE' => 'Sunday',
     
#'NOTES'     => ''
   
},
   
{ 'TITLE'     => 'Document a System',
     
'CONTEXT'   => 'Support Engineer',
     
#'PROJECT'   => 'Linux Migration',
     
'TAGS'      => ['automated reminder'],
     
'DUE'       => 'Wednesday',
     
#'SHOW_FROM' => 'yesterday',
     
'RECURRANCE' => 'Monday',
     
#'NOTES'     => '' 
   
},
);

foreach 
my $recurringTask (@recurringTasks)
{
   addTask
( $recurringTask ) if bTriggerTask( $recurringTask->{'RECURRANCE'} );
}

########################################
# This routine tries to figure of if a task
# should be added based upon the current day
# and the recurrance.  The recurrance date
# should start at midnight of the day.  The 
# test is if noon on the current day is between
# midnight of the recurrance date and midnight
# of the next day.
sub bTriggerTask
{
   
use strict;
   
my $triggerDate = ParseDate( shift( @_ ) );
   
my $today = ParseDate( 'today at noon' );
   
my $triggerDate2 = DateCalc( $triggerDate, "+ 1days" );
   
my $bFlag = 0;
   
$bFlag = 1 if Date_Cmp( $triggerDate, $today ) < 0 and Date_Cmp( $today, $triggerDate2 ) < 0;

   return( 
$bFlag );
}
########################################
# a methode to add a task. It maps some
# custom keys to the parameter names expected
# by tracks 1.5
sub addTask
{
   
use strict;
   
my %args;
   
my %contextId = hGetContexts();
   
my %projectId = hGetProjects();
   
my %params;

   if( $
#_ >= 0 and ref( $_[0] ) eq 'HASH' )
   
{
      
%args = %{ shift( @_ ) };
   
}
   
else
   
{
      
%args = @_;
   
}

   $params{ 
'todo[context_id]' } = $contextId{ $args{ 'CONTEXT' } } if defined( $args{ 'CONTEXT' } ) and defined( $contextId{ $args{ 'CONTEXT' } } );
   
$params{ 'todo[project_id]' } = $projectId{ $args{ 'PROJECT' } } if defined( $args{ 'PROJECT' } ) and defined( $projectId{ $args{ 'PROJECT' } } );
   
$params{ 'todo[description]' } = $args{ 'TITLE'       } if defined( $args{ 'TITLE' } );
   
$params{ 'todo[description]' } = $args{ 'DESCRIPTION' } if defined( $args{ 'DESCRIPTION' } );
   
$params{ 'tag_list' } = join( ",", @{ $args{ 'TAGS' } } ) if defined( $args{ 'TAGS' }) and ref($args{'TAGS'}) eq 'ARRAY';
   
$params{ 'todo[notes]' } = $args{ 'NOTES' } if defined( $args{ 'NOTES' } );
   
   if( 
defined( $args{ 'DUE' } ) )
   
{
      $params{ 
'todo[due]' } = UnixDate( ParseDate( $args{ 'DUE' } ), "%d/%m/%Y" );
   
}
   
   
if( defined( $args{ 'SHOW_FROM' } ) )
   
{
      $params{ 
'todo[show_from]' } = UnixDate( ParseDate( $args{ 'SHOW_FROM' } ), "%d/%m/%Y" );
   
}
   
   
return callIt( 'todos.xml', sCGIEncodeHash( %params ) );
} 
Profile
 
selberg
Posted: 18 May 2008 09:00 AM   [ Ignore ]   [ # 1 ]  
Newbie
Rank
Total Posts:  2
Joined  2008-05-18

Part 2/2

########################################
# A method to contact tracks 1.5 and get a mapping of
# context ids to context names.  Using the
# id's would be faster, but I prefer to think
# in english.
sub hGetContexts
{
   
use strict;
   
my $buffer;
   
my %buffer;
   
my %context;
   
my $context;
   
my @contexts;

   
my @buffer = callIt( "contexts.xml" );
   if( $
#buffer >= 0 and $buffer[0] == 0 )
   
{
      $buffer 
= XMLin( $buffer[1] ) if $buffer[1] =~ /<\?xml/i;
      %
buffer = %{$buffer} if ref( $buffer ) eq 'HASH';
   
}
 
   
@contexts = keys( %{ $buffer->{'context'} } ) if ref( $buffer->{'context'} ) eq 'HASH';
   foreach 
$context ( @contexts )
   
{
      $context{ $context } 
= $buffer->{'context'}->{$context}->{'id'}->{'content'};
   
}

   
return %context;
}
########################################
# A method to contact tracks 1.5 and get a mapping of
# project ids to project names.  Using the
# id's would be faster, but I prefer to think
# in english.
sub hGetProjects
{
   
use strict;
   
my $buffer;
   
my %buffer;
   
my %project;
   
my $project;
   
my @projects;

   
my @buffer = callIt( "projects.xml" );
   if( $
#buffer >= 0 and $buffer[0] == 0 )
   
{
      $buffer 
= XMLin( $buffer[1] ) if $buffer[1] =~ /<\?xml/i;
      %
buffer = %{$buffer} if ref( $buffer ) eq 'HASH';
   
}
   
@projects = keys( %{ $buffer->{'project'} } ) if ref( $buffer->{'project'} ) eq 'HASH';
   foreach 
$project ( @projects )
   
{
      $project{ $project } 
= $buffer->{'project'}->{$project}->{'id'}->{'content'};
   
}

   
return %project;
}
########################################
# The method which talks to tracks.  In the 
# examples, a number of people were using 
# WWW::Curl::Easy.  I was unable to get version
# 4.00 to install on a RedHat Enterprise 4.0
# machine, and 3.12 didn't let me access the
# contents from the query.  So, I dropped back
# to LWP.
sub callIt
{
   
use strict;
   
my $browser = LWP::UserAgent->new;
   
my $type = 'GET';
   
my $error;
   
my $return;

   
my $controller = shift;
   
my $cgiData  = shift if $#_ >= 0 and $_[0] =~ /\w/;
   
$type = 'POST' if defined( $cgiData );

   
# Create a user agent object
   
my $request = HTTP::Request->new( $type => "$baseurl/$controller" );
   
$request->authorization_basic( $userName => $password );
   
$request->content_type('application/x-www-form-urlencoded');
   
$request->content( $cgiData ) if defined( $cgiData );

   
my $response = $browser->request($request);
   if (
$response->is_success) {
      $error 
= 0;
      
$return = $response->content;
   
} else {
      $error 
= 1;
      
$return = $response->status_line . "\n";
   
}
   
   
return( $error, $return);
}
########################################
# This is a methode to join a hash into
# a CGI encoded string.
sub sCGIEncodeHash
{
   
use strict;
   
my @args = @_;
   
my $i;
   
my @items;

   for( 
$i = 0; $i <= $#args; $i+=2)
   
{
      push
( @items,  sCGIEncodeScalar( $args[$i] ) . "=" . sCGIEncodeScalar( $args[ $i+1 ] ) ); 
      
#push( @items,  $args[$i]  . "=" .  $args[ $i+1 ]  ); 
   
}

   
return( join( '&', @items ) );
}
########################################
# A function to CGI Encode a scalar variable
sub sCGIEncodeScalar
{
   
use strict;
   
my $string = $_[0];
   
$string =~ s/([^a-zA-Z0-9 ])/Encode( $1 )/ge;
   
$string =~ s/ /+/g;
   return( 
$string );
}
########################################
# A support function for sCGIEncodeScalar
sub Encode
{
   
use strict;
   
my $value = shift;
   
my $encoded;
   
   
$encoded = sprintf( "%X", unpack( "c", $value ) );
   
unless( $encoded =~ /../ ){ $encoded = '0' . $encoded; }
   
return( '%' . $encoded );
} 
Profile
 
   
 
 
‹‹ feature request: delegate tasks to other users      How to autologin from a specific IP or UserAgent ? ››

Powered By ExpressionEngine
Template Design By Sonnenvogel.com
Select a theme:

ExpressionEngine Discussion Forum - Version 2.1.2 (20091002)
Script Executed in 0.1159 seconds

Atom Feed
RSS 2.0