diff options
author | Jesse Morgan <jesse@jesterpm.net> | 2013-03-16 10:37:40 -0700 |
---|---|---|
committer | Jesse Morgan <jesse@jesterpm.net> | 2013-03-16 10:37:40 -0700 |
commit | 0593e4279ac6a11c1b95c0cca35f20f631e1ff5c (patch) | |
tree | 06cbfd24ee8efed98881d16ace34b6a7c8c1da3e /mutt-ical.py | |
parent | ac5044074e01f518ae3c837dfad0fa3fc0719962 (diff) |
Adding files from bismuth
Diffstat (limited to 'mutt-ical.py')
-rwxr-xr-x | mutt-ical.py | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/mutt-ical.py b/mutt-ical.py new file mode 100755 index 0000000..69ff4b2 --- /dev/null +++ b/mutt-ical.py @@ -0,0 +1,149 @@ +#!/usr/bin/env python +# -*- coding: utf8 -*- + +""" +This script is meant as a simple way to reply to ical invitations from mutt. +See README for instructions and LICENSE for licensing information. +""" + +from __future__ import with_statement + +__author__="Martin Sander" +__license__="MIT" + + +import vobject +import tempfile, time +import os, sys +import warnings +from datetime import datetime +from subprocess import Popen, PIPE +from getopt import gnu_getopt as getopt + +usage=""" +usage: +%s [OPTIONS] -e your@email.address filename.ics +OPTIONS: + -i interactive + -a accept + -d decline + -t tentatively accept + (accept is default, last one wins) +""" % sys.argv[0] + +def del_if_present(dic, key): + if dic.has_key(key): + del dic[key] + +def set_accept_state(attendees, state): + for attendee in attendees: + attendee.params['PARTSTAT'][0] = state + for i in ["RSVP","ROLE","X-NUM-GUESTS","CUTYPE"]: + del_if_present(attendee.params,i) + return attendees + +def get_accept_decline(): + while True: + sys.stdout.write("Accept Invitation? [Y/n/t]") + ans = sys.stdin.readline() + if ans.lower() == 'y\n' or ans == '\n': + return 'ACCEPTED' + elif ans.lower() == 'n\n': + return 'DECLINED' + elif ans.lower() =='t\n': + return 'TENTATIVE' + +def get_answer(invitation): + # create + ans = vobject.newFromBehavior('vcalendar') + ans.add('method') + ans.method.value = "REPLY" + ans.add('vevent') + + # just copy from invitation + for i in ["uid", "summary", "dtstart", "dtend", "organizer"]: + if invitation.vevent.contents.has_key(i): + ans.vevent.add( invitation.vevent.contents[i][0] ) + + # new timestamp + ans.vevent.add('dtstamp') + ans.vevent.dtstamp.value = datetime.utcnow().replace( + tzinfo = invitation.vevent.dtstamp.value.tzinfo) + return ans + +def write_to_tempfile(ical): + tempdir = tempfile.mkdtemp() + icsfile = tempdir+"/event-reply.ics" + with open(icsfile,"w") as f: + f.write(ical.serialize()) + return icsfile, tempdir + +def get_mutt_command(ical, email_address, accept_decline, icsfile): + accept_decline = accept_decline.capitalize() + sender = ical.vevent.contents['organizer'][0].value.split(':')[1].encode() + summary = ical.vevent.contents['summary'][0].value.encode() + command = ["mutt", "-a", icsfile, + "-e", 'set sendmail=\'ical_reply_sendmail_wrapper.sh\'', + "-s", "'%s: %s'" % (accept_decline, summary), "--", sender] + return command + +def execute(command, mailtext): + process = Popen(command, stdin=PIPE) + process.stdin.write(mailtext) + process.stdin.close() + + result = None + while result is None: + result = process.poll() + time.sleep(.1) + if result != 0: + print "unable to send reply, subprocess exited with\ + exit code %d\nPress return to continue" % result + sys.stdin.readline() + +if __name__=="__main__": + email_address = None + accept_decline = 'ACCEPTED' + opts, args=getopt(sys.argv[1:],"e:aidt") + for opt,arg in opts: + if opt == '-e': + email_address = arg + if opt == '-i': + accept_decline = get_accept_decline() + if opt == '-a': + accept_decline = 'ACCEPTED' + if opt == '-d': + accept_decline = 'DECLINED' + if opt == '-t': + accept_decline = 'TENTATIVE' + + if len(args) < 1 or not email_address: + sys.stderr.write(usage) + sys.exit(1) + + invitation_file = args[0] + with open(invitation_file) as f: + try: + with warnings.catch_warnings(): #vobject uses deprecated Exception stuff + warnings.simplefilter("ignore") + invitation = vobject.readOne(f, ignoreUnreadable=True) + except AttributeError: + invitation = vobject.readOne(f, ignoreUnreadable=True) + + ans = get_answer(invitation) + + attendees = invitation.vevent.contents['attendee'] + set_accept_state(attendees,accept_decline) + ans.vevent.contents['attendee'] = [i for i in attendees if i.value.endswith(email_address)] + if len(ans.vevent.contents) < 1: + sys.stderr.write("Seems like you have not been invited to this event!\n") + sys.exit(1) + + icsfile, tempdir = write_to_tempfile(ans) + + mutt_command = get_mutt_command(ans, email_address, accept_decline, icsfile) + mailtext = "'%s has %s'" % (email_address, accept_decline.lower()) + execute(mutt_command, mailtext) + + os.remove(icsfile) + os.rmdir(tempdir) |