aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md0
-rw-r--r--TODO.md0
-rwxr-xr-xical2rem279
-rwxr-xr-xparse-remind41
-rwxr-xr-xrem2ics31
5 files changed, 351 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/README.md
diff --git a/TODO.md b/TODO.md
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/TODO.md
diff --git a/ical2rem b/ical2rem
new file mode 100755
index 0000000..aab07d5
--- /dev/null
+++ b/ical2rem
@@ -0,0 +1,279 @@
+#!/usr/bin/perl -w
+#
+# ical2rem.pl -
+# Reads iCal files and outputs remind-compatible files. Tested ONLY with
+# calendar files created by Mozilla Calendar/Sunbird. Use at your own risk.
+# Copyright (c) 2005, 2007, Justin B. Alcorn
+
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+#
+# version 0.5.2 2007-03-23
+# - BUG: leadtime for recurring events had a max of 4 instead of DEFAULT_LEAD_TIME
+# - remove project-lead-time, since Category was a non-standard attribute
+# - NOTE: There is a bug in iCal::Parser v1.14 that causes multiple calendars to
+# fail if a calendar with recurring events is followed by a calendar with no
+# recurring events. This has been reported to the iCal::Parser author.
+# version 0.5.1 2007-03-21
+# - BUG: Handle multiple calendars on STDIN
+# - add --heading option for priority on section headers
+# version 0.5 2007-03-21
+# - Add more help options
+# - --project-lead-time option
+# - Supress printing of heading if there are no todos to print
+# version 0.4
+# - Version 0.4 changes all written or inspired by, and thanks to Mark Stosberg
+# - Change to GetOptions
+# - Change to pipe
+# - Add --label, --help options
+# - Add Help Text
+# - Change to subroutines
+# - Efficiency and Cleanup
+# version 0.3
+# - Convert to GPL (Thanks to Mark Stosberg)
+# - Add usage
+# version 0.2
+# - add command line switches
+# - add debug code
+# - add SCHED _sfun keyword
+# - fix typos
+# version 0.1 - ALPHA CODE.
+
+=head1 SYNOPSIS
+
+ cat /path/to/file*.ics | ical2rem.pl > ~/.ical2rem
+
+ All options have reasonable defaults:
+ --label Calendar name (Default: Calendar)
+ --lead-time Advance days to start reminders (Default: 3)
+ --todos, --no-todos Process Todos? (Default: Yes)
+ --heading Define a priority for static entries
+ --help Usage
+ --man Complete man page
+
+Expects an ICAL stream on STDIN. Converts it to the format
+used by the C<remind> script and prints it to STDOUT.
+
+=head2 --label
+
+ ical2rem.pl --label "Bob's Calendar"
+
+The syntax generated includes a label for the calendar parsed.
+By default this is "Calendar". You can customize this with
+the "--label" option.
+
+=head2 --lead-time
+
+ ical2rem.pl --lead-time 3
+
+How may days in advance to start getting reminders about the events. Defaults to 3.
+
+=head2 --no-todos
+
+ ical2rem.pl --no-todos
+
+If you don't care about the ToDos the calendar, this will surpress
+printing of the ToDo heading, as well as skipping ToDo processing.
+
+=head2 --heading
+
+ ical2rem.pl --heading "PRIORITY 9999"
+
+Set an option on static messages output. Using priorities can made the static messages look different from
+the calendar entries. See the file defs.rem from the remind distribution for more information.
+
+=cut
+
+use strict;
+use iCal::Parser;
+use DateTime;
+use Getopt::Long 2.24 qw':config auto_help';
+use Pod::Usage;
+use Data::Dumper;
+use vars '$VERSION';
+$VERSION = "0.5.2";
+
+# Declare how many days in advance to remind
+my $DEFAULT_LEAD_TIME = 3;
+my $PROCESS_TODOS = 1;
+my $HEADING = "";
+my $help;
+my $man;
+
+my $label = 'Calendar';
+GetOptions (
+ "label=s" => \$label,
+ "lead-time=i" => \$DEFAULT_LEAD_TIME,
+ "todos!" => \$PROCESS_TODOS,
+ "heading=s" => \$HEADING,
+ "help|?" => \$help,
+ "man" => \$man
+);
+pod2usage(1) if $help;
+pod2usage(-verbose => 2) if $man;
+
+my $month = ['None','Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
+
+my @calendars;
+my $in;
+
+while (<>) {
+ $in .= $_;
+ if (/END:VCALENDAR/) {
+ push(@calendars,$in);
+ $in = "";
+ }
+}
+my $parser = iCal::Parser->new();
+my $hash = $parser->parse_strings(@calendars);
+
+##############################################################
+#
+# Subroutines
+#
+#############################################################
+#
+# _process_todos()
+# expects 'todos' hashref from iCal::Parser is input
+# returns String to output
+sub _process_todos {
+ my $todos = shift;
+
+ my ($todo, @newtodos, $leadtime);
+ my $output = "";
+
+ $output .= 'REM '.$HEADING.' MSG '.$label.' ToDos:%"%"%'."\n";
+
+# For sorting, make sure everything's got something
+# To sort on.
+ my $now = DateTime->now;
+ for $todo (@{$todos}) {
+ # remove completed items
+ if ($todo->{'STATUS'} && $todo->{'STATUS'} eq 'COMPLETED') {
+ next;
+ } elsif ($todo->{'DUE'}) {
+ # All we need is a due date, everything else is sugar
+ $todo->{'SORT'} = $todo->{'DUE'}->clone;
+ } elsif ($todo->{'DTSTART'}) {
+ # for sorting, sort on start date if there's no due date
+ $todo->{'SORT'} = $todo->{'DTSTART'}->clone;
+ } else {
+ # if there's no due or start date, just make it now.
+ $todo->{'SORT'} = $now;
+ }
+ push(@newtodos,$todo);
+ }
+ if (! (scalar @newtodos)) {
+ return "";
+ }
+# Now sort on the new Due dates and print them out.
+ for $todo (sort { DateTime->compare($a->{'SORT'}, $b->{'SORT'}) } @newtodos) {
+ my $due = $todo->{'SORT'}->clone();
+ my $priority = "";
+ if (defined($todo->{'PRIORITY'})) {
+ if ($todo->{'PRIORITY'} == 1) {
+ $priority = "PRIORITY 1000";
+ } elsif ($todo->{'PRIORITY'} == 3) {
+ $priority = "PRIORITY 7500";
+ }
+ }
+ if (defined($todo->{'DTSTART'}) && defined($todo->{'DUE'})) {
+ # Lead time is duration of task + lead time
+ my $diff = ($todo->{'DUE'}->delta_days($todo->{'DTSTART'})->days())+$DEFAULT_LEAD_TIME;
+ $leadtime = "+".$diff;
+ } else {
+ $leadtime = "+".$DEFAULT_LEAD_TIME;
+ }
+ $output .= "REM ".$due->month_abbr." ".$due->day." ".$due->year." $leadtime $priority MSG \%a $todo->{'SUMMARY'}\%\"\%\"\%\n";
+ }
+ $output .= 'REM '.$HEADING.' MSG %"%"%'."\n";
+ return $output;
+}
+
+
+#######################################################################
+#
+# Main Program
+#
+######################################################################
+
+print _process_todos($hash->{'todos'}) if $PROCESS_TODOS;
+
+my ($leadtime, $yearkey, $monkey, $daykey,$uid,%eventsbyuid);
+print 'REM '.$HEADING.' MSG '.$label.' Events:%"%"%'."\n";
+my $events = $hash->{'events'};
+foreach $yearkey (sort keys %{$events} ) {
+ my $yearevents = $events->{$yearkey};
+ foreach $monkey (sort {$a <=> $b} keys %{$yearevents}){
+ my $monevents = $yearevents->{$monkey};
+ foreach $daykey (sort {$a <=> $b} keys %{$monevents} ) {
+ my $dayevents = $monevents->{$daykey};
+ foreach $uid (sort {
+ DateTime->compare($dayevents->{$a}->{'DTSTART'}, $dayevents->{$b}->{'DTSTART'})
+ } keys %{$dayevents}) {
+ my $event = $dayevents->{$uid};
+ if ($eventsbyuid{$uid}) {
+ my $curreventday = $event->{'DTSTART'}->clone;
+ $curreventday->truncate( to => 'day' );
+ $eventsbyuid{$uid}{$curreventday->epoch()} =1;
+ for (my $i = 0;$i < $DEFAULT_LEAD_TIME && !defined($event->{'LEADTIME'});$i++) {
+ if ($eventsbyuid{$uid}{$curreventday->subtract( days => $i+1 )->epoch() }) {
+ $event->{'LEADTIME'} = $i;
+ }
+ }
+ } else {
+ $eventsbyuid{$uid} = $event;
+ my $curreventday = $event->{'DTSTART'}->clone;
+ $curreventday->truncate( to => 'day' );
+ $eventsbyuid{$uid}{$curreventday->epoch()} =1;
+ }
+
+ }
+ }
+ }
+}
+foreach $yearkey (sort keys %{$events} ) {
+ my $yearevents = $events->{$yearkey};
+ foreach $monkey (sort {$a <=> $b} keys %{$yearevents}){
+ my $monevents = $yearevents->{$monkey};
+ foreach $daykey (sort {$a <=> $b} keys %{$monevents} ) {
+ my $dayevents = $monevents->{$daykey};
+ foreach $uid (sort {
+ DateTime->compare($dayevents->{$a}->{'DTSTART'}, $dayevents->{$b}->{'DTSTART'})
+ } keys %{$dayevents}) {
+ my $event = $dayevents->{$uid};
+ if (exists($event->{'LEADTIME'})) {
+ $leadtime = "+".$event->{'LEADTIME'};
+ } else {
+ $leadtime = "+".$DEFAULT_LEAD_TIME;
+ }
+ my $start = $event->{'DTSTART'};
+ print "REM ".$start->month_abbr." ".$start->day." ".$start->year." $leadtime ";
+ if ($start->hour > 0) {
+ print " AT ";
+ print $start->strftime("%H:%M");
+ print " SCHED _sfun MSG %a %2 ";
+ } else {
+ print " MSG %a ";
+ }
+ print "%\"$event->{'SUMMARY'}";
+ print " at $event->{'LOCATION'}" if $event->{'LOCATION'};
+ print "\%\"%\n";
+ }
+ }
+ }
+}
+exit 0;
+#:vim set ft=perl ts=4 sts=4 expandtab :
diff --git a/parse-remind b/parse-remind
new file mode 100755
index 0000000..bdd9f23
--- /dev/null
+++ b/parse-remind
@@ -0,0 +1,41 @@
+#!/usr/bin/perl
+#
+# This script is designed to have an email piped to it eg. from mutt.
+# It will split apart all the text/calendar attachments and enter them into
+# the 'remind' calendar.
+#
+
+use strict;
+use warnings;
+
+use MIME::Parser;
+
+my $CONVERT = '~/.mutt/ical2rem.pl';
+my $REMINDERS = '~/remind/mutt.rem';
+
+################################################################################
+
+my $parser = new MIME::Parser;
+$parser->output_under('/tmp');
+my $entity = $parser->parse(\*STDIN);
+
+my @parts = $entity->parts();
+my $count = 0;
+
+foreach my $part (@parts) {
+ if ($part->head->mime_type eq 'text/calendar') {
+ my $body = $part->bodyhandle;
+ my $cmd = $CONVERT.' '.$body->path.' >> '.$REMINDERS;
+ print STDERR `$cmd`;
+ last if ($? != 0);
+ $count++;
+ }
+}
+
+$parser->filer->purge;
+if ($count == 0) {
+ print STDERR "No calendar entries found.";
+ exit(1);
+}
+
+exit(0);
diff --git a/rem2ics b/rem2ics
new file mode 100755
index 0000000..f4c7c05
--- /dev/null
+++ b/rem2ics
@@ -0,0 +1,31 @@
+#!/usr/bin/awk -f
+# rem2ics by Anthony J. Chivetta <achivetta@gmail.com>
+# from http://www.roaringpenguin.com/wiki/index.php/Rem2ics
+# version 0.1 - 2006-06-09
+# version 0.2 - 2010-10-27 (one-line patch by Shane Kerr <shane@time-travellers.org>)
+# Converts output of remind -s to iCalendar
+# usage: remind -s | rem2ics
+#
+# THE FOLLOWING CODE IS RELEASED INTO THE PUBLIC DOMAIN
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
+BEGIN {
+print "BEGIN:VCALENDAR"
+print "VERSION:2.0"
+}
+{
+gsub("/","",$1)
+print "BEGIN:VEVENT"
+if ($5 != "*"){
+printf("DTSTART:%dT%02d%02d00\n",$1,$5/60,$5%60)
+printf("DTEND:%dT%02d%02d00\n",$1,($5+$4)/60,($5+$4)%60)
+print "SUMMARY:" substr($0,match($0,$7))
+} else {
+printf("DTSTART:%d\n",$1)
+print "SUMMARY:" substr($0,match($0,$6))
+}
+print "END:VEVENT"
+}
+END {print "END:VCALENDAR"}