131 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			131 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
#!/usr/bin/env python2.7
 | 
						|
import sys
 | 
						|
import time
 | 
						|
import datetime
 | 
						|
import optparse
 | 
						|
import urlparse
 | 
						|
import itertools
 | 
						|
import traceback
 | 
						|
import os
 | 
						|
 | 
						|
sys.path.append(os.path.join(os.path.dirname(__file__), '../api'))
 | 
						|
import zulip
 | 
						|
 | 
						|
parser = optparse.OptionParser(r"""
 | 
						|
 | 
						|
%prog \
 | 
						|
    --user foo@zulip.com \
 | 
						|
    --calendar http://www.google.com/calendar/feeds/foo%40zulip.com/private-fedcba9876543210fedcba9876543210/basic
 | 
						|
 | 
						|
    Send yourself reminders on Zulip of Google Calendar events.
 | 
						|
 | 
						|
    To get the calendar URL:
 | 
						|
      - Load Google Calendar in a web browser
 | 
						|
      - Find your calendar in the "My calendars" list on the left
 | 
						|
      - Click the down-wedge icon that appears on mouseover, and select "Calendar settings"
 | 
						|
      - Copy the link address for the "XML" button under "Private Address"
 | 
						|
 | 
						|
    Run this on your personal machine.  Your API key and calendar URL are revealed to local
 | 
						|
    users through the command line.
 | 
						|
 | 
						|
    Depends on: python-gdata
 | 
						|
""")
 | 
						|
 | 
						|
parser.add_option('--calendar',
 | 
						|
    dest='calendar',
 | 
						|
    action='store',
 | 
						|
    help='Google Calendar XML "Private Address"',
 | 
						|
    metavar='URL')
 | 
						|
parser.add_option('--interval',
 | 
						|
    dest='interval',
 | 
						|
    default=10,
 | 
						|
    type=int,
 | 
						|
    action='store',
 | 
						|
    help='Minutes before event for reminder [default: 10]',
 | 
						|
    metavar='MINUTES')
 | 
						|
parser.add_option_group(zulip.generate_option_group(parser))
 | 
						|
 | 
						|
(options, args) = parser.parse_args()
 | 
						|
 | 
						|
if not (options.zulip_email and options.calendar):
 | 
						|
    parser.error('You must specify --user and --calendar')
 | 
						|
 | 
						|
try:
 | 
						|
    from gdata.calendar.client import CalendarClient
 | 
						|
except ImportError:
 | 
						|
    parser.error('Install python-gdata')
 | 
						|
 | 
						|
def get_calendar_url():
 | 
						|
    parts = urlparse.urlparse(options.calendar)
 | 
						|
    pat = os.path.split(parts.path)
 | 
						|
    if pat[1] != 'basic':
 | 
						|
        parser.error('The --calendar URL should be the XML "Private Address" ' +
 | 
						|
                     'from your calendar settings')
 | 
						|
    return urlparse.urlunparse((parts.scheme, parts.netloc, pat[0] + '/full',
 | 
						|
                                '', 'futureevents=true&orderby=startdate', ''))
 | 
						|
 | 
						|
calendar_url = get_calendar_url()
 | 
						|
 | 
						|
client = zulip.init_from_options(options)
 | 
						|
 | 
						|
def get_events():
 | 
						|
    feed = CalendarClient().GetCalendarEventFeed(uri=calendar_url)
 | 
						|
 | 
						|
    for event in feed.entry:
 | 
						|
        start = event.when[0].start.split('.')[0]
 | 
						|
        # All-day events can have only a date
 | 
						|
        fmt = '%Y-%m-%dT%H:%M:%S' if 'T' in start else '%Y-%m-%d'
 | 
						|
        start = datetime.datetime.strptime(start, fmt)
 | 
						|
        yield (event.uid.value, start, event.title.text)
 | 
						|
 | 
						|
# Our cached view of the calendar, updated periodically.
 | 
						|
events = []
 | 
						|
 | 
						|
# Unique keys for events we've already sent, so we don't remind twice.
 | 
						|
sent = set()
 | 
						|
 | 
						|
def send_reminders():
 | 
						|
    global sent
 | 
						|
 | 
						|
    messages = []
 | 
						|
    keys = set()
 | 
						|
    now = datetime.datetime.now()
 | 
						|
 | 
						|
    for uid, start, title in events:
 | 
						|
        dt = start - now
 | 
						|
        if dt.days == 0 and dt.seconds < 60*options.interval:
 | 
						|
            # The unique key includes the start time, because of
 | 
						|
            # repeating events.
 | 
						|
            key = (uid, start)
 | 
						|
            if key not in sent:
 | 
						|
                line = '%s starts at %s' % (title, start.strftime('%H:%M'))
 | 
						|
                print 'Sending reminder:', line
 | 
						|
                messages.append(line)
 | 
						|
                keys.add(key)
 | 
						|
 | 
						|
    if not messages:
 | 
						|
        return
 | 
						|
 | 
						|
    if len(messages) == 1:
 | 
						|
        message = 'Reminder: ' + messages[0]
 | 
						|
    else:
 | 
						|
        message = 'Reminder:\n\n' + '\n'.join('* ' + m for m in messages)
 | 
						|
 | 
						|
    client.send_message(dict(
 | 
						|
        type    = 'private',
 | 
						|
        to      = options.user,
 | 
						|
        content = message))
 | 
						|
 | 
						|
    sent |= keys
 | 
						|
 | 
						|
# Loop forever
 | 
						|
for i in itertools.count():
 | 
						|
    try:
 | 
						|
        # We check reminders every minute, but only
 | 
						|
        # download the calendar every 10 minutes.
 | 
						|
        if not i % 10:
 | 
						|
            events = list(get_events())
 | 
						|
        send_reminders()
 | 
						|
    except:
 | 
						|
        traceback.print_exc()
 | 
						|
    time.sleep(60)
 |