Merge pull request #317 from facetoe/google_calendar

Add GoogleCalendar module
This commit is contained in:
enkore 2016-02-14 14:56:33 +01:00
commit bf2e992fc9
2 changed files with 126 additions and 0 deletions

View File

@ -35,6 +35,12 @@ MOCK_MODULES = [
"speedtest_cli", "speedtest_cli",
"pyzabbix", "pyzabbix",
"vk", "vk",
"google-api-python-client",
"dateutil",
"httplib2",
"oauth2client",
"apiclient"
] ]
for mod_name in MOCK_MODULES: for mod_name in MOCK_MODULES:

View File

@ -0,0 +1,120 @@
import datetime
import httplib2
import oauth2client
import pytz
from apiclient import discovery
from dateutil import parser
from i3pystatus import IntervalModule
from i3pystatus.core.color import ColorRangeModule
from i3pystatus.core.util import internet, require
class GoogleCalendar(IntervalModule, ColorRangeModule):
"""
Simple module for displaying next Google Calendar event.
Requires the Google Calendar API package - https://developers.google.com/google-apps/calendar/quickstart/python.
Additionally requires the `colour`, `httplib2`, `oauth2client`, `pytz`, `apiclient` and `dateutil` modules.
All top level keys returned by the Google Calendar API can be used as formatters. Some
examples include:
.. rubric:: Available formatters
* `{kind}` type of event
* `{status}` eg, confirmed
* `{summary}` essentially the title
* `{htmlLink}` link to the calendar event
"""
settings = (
('format', 'format string'),
("credential_path", "Path to credentials"),
("skip_recurring", "Skip recurring events."),
("urgent_seconds", "Add urgent hint when this many seconds until event startTime"),
("start_color", "Hex or English name for start of color range, eg '#00FF00' or 'green'"),
("end_color", "Hex or English name for end of color range, eg '#FF0000' or 'red'"),
)
required = ('credential_path',)
format = "{summary} ({remaining_time})"
urgent_seconds = 300
interval = 30
color = '#FFFFFF'
skip_recurring = True
credential_path = None
service = None
credentials = None
def init(self):
self.colors = self.get_hex_color_range(self.end_color, self.start_color, self.urgent_seconds * 2)
@require(internet)
def run(self):
if not self.service:
self.connect_service()
display_event = self.get_next_event()
if display_event:
start_time = parser.parse(display_event['start']['dateTime'])
now = datetime.datetime.now(tz=pytz.UTC)
alert_time = now + datetime.timedelta(seconds=self.urgent_seconds)
display_event['remaining_time'] = str((start_time - now)).partition('.')[0]
urgent = alert_time > start_time
color = self.get_color(now, start_time)
self.output = {
'full_text': self.format.format(**display_event),
'color': color,
'urgent': urgent
}
else:
self.output = {
'full_text': "",
}
def connect_service(self):
self.credentials = oauth2client.file.Storage(self.credential_path).get()
self.service = discovery.build('calendar', 'v3', http=self.credentials.authorize(httplib2.Http()))
def get_next_event(self):
for event in self.get_events():
start_time = parser.parse(event['start']['dateTime'])
now = datetime.datetime.now(tz=pytz.UTC)
if 'recurringEventId' in event and self.skip_recurring:
continue
elif start_time < now:
continue
return event
def get_events(self):
now, later = self.get_timerange()
events_result = self.service.events().list(
calendarId='primary',
timeMin=now,
timeMax=later,
maxResults=10,
singleEvents=True,
orderBy='startTime',
timeZone='utc'
).execute()
return events_result.get('items', [])
def get_timerange(self):
now = datetime.datetime.utcnow()
later = now + datetime.timedelta(days=1)
now = now.isoformat() + 'Z'
later = later.isoformat() + 'Z'
return now, later
def get_color(self, now, start_time):
seconds_to_event = (start_time - now).seconds
v = self.percentage(seconds_to_event, self.urgent_seconds)
color = self.get_gradient(v, self.colors)
return color