Skip to content

Instantly share code, notes, and snippets.

@riywo
Created April 5, 2011 16:31
Show Gist options
  • Save riywo/903948 to your computer and use it in GitHub Desktop.
Save riywo/903948 to your computer and use it in GitHub Desktop.
#!/usr/bin/env perl
use strict;
use warnings;
use FindBin;
use lib "$FindBin::RealBin/lib";
use lib "$FindBin::RealBin/extlib/lib/perl5";
use Cache::LRU;
use Config::Simple;
use Cybozu::Garoon::Notify;
use DateTime;
use DateTime::Duration;
use Cocoa::Growl qw(:all);
use AnyEvent;
use AnyEvent::Impl::NSRunLoop;
use Try::Tiny;
use Encode;
use Data::Dumper;
my $APP_NAME = 'garoon2growl';
my $NOTIFICATION_WHATSNEW ='garoon-whatsnew';
my $NOTIFICATION_SCHEDULE ='garoon-schedule';
# setup config
my $config = do {
my $config_fn = shift(@ARGV) || "$ENV{HOME}/etc/cybozu-garoon-notify.ini";
Config::Simple->new($config_fn)
or die "failed to read $config_fn:$!";
};
for my $n (qw(url username password check_interval schedule_notify_before)) {
die "mandatory parameter $n is missing in the ini file"
unless $config->param($n);
}
growl_register(
app => $APP_NAME,
icon => $config->param('growl_icon') || undef,
notifications => [ $NOTIFICATION_WHATSNEW, $NOTIFICATION_SCHEDULE ],
);
# instantiate
my $gr = Cybozu::Garoon::Notify->new(
map { $_ => $config->param($_) } qw(url username password),
);
# caches used prevent notifying more than once
my $whatsnew_cache = Cache::LRU->new(size => 1024);
my $sched_cache = Cache::LRU->new(size => 1024);
growl_notify(
name => $NOTIFICATION_WHATSNEW,
title => 'garoon2growl',
description => 'started!',
icon => $config->param('growl_icon') || undef,
);
my $cv = AnyEvent->condvar;
my $timer; $timer = AnyEvent->timer(
after => 0,
interval => $config->param('check_interval'),
cb => sub {
try {
notify_whatsnew($gr);
notify_schedule($gr);
} catch {
warn $_;
};
},
);
my $signal; $signal = AnyEvent->signal(
signal => 'INT',
cb => sub {
undef $signal;
undef $timer;
$cv->send;
},
);
$cv->recv;
#----------------------------------------------------------------------------
# handle whatsnew notifications
sub notify_whatsnew {
my $gr = shift;
my @topics = $gr->get_whatsnew();
for my $topic (@topics) {
my $renotify_key = join '::', $topic->{link}, $topic->{updated};
if (! $whatsnew_cache->get($renotify_key)) {
$whatsnew_cache->set($renotify_key => 1);
my $content = $topic->{author} ? $topic->{author}.":¥n" : '';
$content .= $topic->{content} if($topic->{content});
growl_notify(
name => $NOTIFICATION_WHATSNEW,
title => '[NEW]'.decode('utf-8', $topic->{subject}),
description => decode('utf-8', $content),
icon => $config->param('growl_icon') || undef,
on_click => sub {
`open '$topic->{link}'`;
},
);
}
}
}
# handle schedule notifications
sub notify_schedule {
my $gr = shift;
my @scheds = $gr->get_schedule;
my $now = DateTime->now(time_zone => 'Asia/Tokyo');
my $notify_before = DateTime::Duration->new(
seconds => $config->param('schedule_notify_before'),
);
for my $sched (@scheds) {
my $s_dt = $gr->datetime_fmt->parse_datetime($sched->{startdate})
or next;
next
if $now + $notify_before < $s_dt;
my $e_dt = $gr->datetime_fmt->parse_datetime($sched->{enddate})
|| '';
my $renotify_key = join '::', $s_dt, $e_dt, $sched->{title};
if (! $sched_cache->get($renotify_key)) {
$sched_cache->set($renotify_key => 1);
growl_notify(
name => $NOTIFICATION_SCHEDULE,
title => '[SCHEDULE]'.sprintf(
'%s - %s',
$s_dt->strftime('%H:%M'),
$e_dt ? $e_dt->strftime('%H:%M') : '',
),
description => decode('utf-8', $sched->{title} . (
$sched->{facility} ? " ($sched->{facility})" : '',
)),
icon => $config->param('growl_icon') || undef,
on_click => sub {
`open '$sched->{link}'`;
},
);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment