domingo, 3 de agosto de 2014

Pequeño ejemplo de crear archivos ical con Perl

¡Hola de nuevo!

    Estuve trabajando en un programa que en una parte guarda eventos en un archivo ical. Me costó un poco encontrar un buen módulo. El mejor y más sencillo es Tie::iCal, aunque verán que tiene un bug al final.

sub guardar_evento {
    # segundos: tiempo que falta para el final del evento
    # contenido: la descripción del evento (ej "Reunión con Pepe")
    my ($segundos, $contenido) = @_;
    my %my_events;
    my $calfile = "/.mycalendar.ics";
    tie %my_events, 'Tie::iCal', $calfile or die "Failed to tie file!\n";

    # Summary no puede tener enter, así que lo cambio por \n
    $contenido =~ s/\n/\\n/gs;



    # Cada evento es una entrada, y c/u tiene un UID
    my $uid = time();
    $my_events{$uid} = [
    'VEVENT',
             {
              'SUMMARY' => $contenido,
              'DTSTART' => secs_to_ical_date(0),
              'DTEND'   => secs_to_ical_date($segundos),
             }
    ];
    untie %my_events;
}



# Esta func agrega $secs segundos a la fecha/hora actual
# y lo devuevle en el formato para iCal
sub secs_to_ical_date {
    my ($secs) = @_;


  
    # Usamos Time::Piece, que viene con Perl y nos lo hace más facil
    my $now = mk_time_piece_now();
    $now += $secs;
    my $date = $now->strftime( "%Y%m%d" )  . "T" .
               $now->strftime( "%H%M00" ) . "Z";
    return $date;
}

sub mk_time_piece_now {
      # Esto pasa porque el objeto Time::Piece que resulta de

      # localtime tiene mal el timezone. Así que lo hago string,
      # y lo vuelvo a hacer objeto. Grrrr.
      my $now        = localtime;
      my $now_string = $now->strftime("%d-%m-%Y %H:%M");
         $now        = Time::Piece->strptime($now_string, 

                                            "%d-%m-%Y %H:%M");
      return $now;
}



Pero resulta que el archivo iCal queda mal hecho, así que este pedazo de código lo arregla. Reporté el bug acá.

open( my $ical, "<", ".mycalendar.ics") or die $!;

my $head = "";
foreach my $n (1, 2, 3) {
     my $temp = <$ical>;
     $head = $head . $temp;
}


my $body = "";
while ( <$ical> ) {
    next if ( /BEGIN:VCALENDAR/ );
    next if ( /VERSION:/ );
    next if ( /PRODID:/ );
    next if ( /END:VCALENDAR/ );
    $body = $body . $_;
}

my $foot = "END:VCALENDAR\n";


# Y escribirlo a un archivo.
use File::Slurp;
write_file( ".mycalendar_fixed.ics", $head . $body . $foot );



Dos bugs. No está nada bien :(

Les dejo un conejo.



Saludos!
-- Diego



No hay comentarios:

Publicar un comentario