Commits

Michael Shepanski  committed 15d4b2e

Add Google Calendar Widget

  • Participants
  • Parent commits a0e4338

Comments (0)

Files changed (15)

   * Add your APIKEY to your ~/.pkmeter/config.py file.
 
 
+IF YOU WANT TO ENABLE GOOGLE CALENDAR
+-------------------------------------
+If you would like to enable Google Calendar to see a list of upcoming
+events, you will need to create a new Google API Application and copy
+your credentials to the settings.
+
+  * Login to your Google Calendar.
+  * Navigate to Settings >> Calendars >> [Calendar] >> Private Address
+  * Click the XML button and copy the URL to your ~/.pkmeter/config.py file.
+  * Optionally specify a color from the choices explained in the config file.
+
+
 IF YOU WANT TO ENABLE SICKBEARD QUEUE
 -------------------------------------
 If you would like to view your Sickbeard queue, you will need to enable and

File pkmeter/meters/googlecalendar.py

+#! /usr/bin/python
+# -*- coding: utf-8 -*-
+import datetime, HTMLParser, optparse, codecs, sys
+from pkmeter.meters.basemeter import BaseMeter
+from pkmeter import utils
+from pkmeter.utils import settings
+
+
+class GoogleCalendar(BaseMeter):
+
+    def __init__(self, ypos=0):
+        BaseMeter.__init__(self, ypos)                              # Call parent init
+        self.parser = HTMLParser.HTMLParser()                       # HTML Parser
+        self.today = datetime.datetime.today()                      # Today
+        self.nextweek = self.today + datetime.timedelta(days=7)     # Next Week
+        self.calendars = []                                         # Responses from calendar API Calls
+        self.events = []                                            # List of all events from calendars
+        self.numevents = 0                                          # Num events in the output
+
+    def conkyrc(self):
+        if not settings.SICKBEARD_APIKEY:
+            utils.gen.info("  GOOGLE_CALENDAR_FEEDS not set (meter disabled)")
+            return self.rclines
+        utils.gen.info("  GOOGLE_CALENDAR_FEEDS set (meter enabled)")
+        self.rclines.append("### %s ###" % self.__class__.__name__)
+        self.add_execpi('30', "python %s -y %s" % (__file__.rstrip('c'), self.ypos))
+        self.add_spacer()
+        return self.rclines
+
+    def execpi(self, args=None):
+        self.update_calendars()
+        self.update_events()
+        eventsthisweek = "%s events this week" % len(self.events)
+        self.add_header('googlecalendar.png', "Google Calendar", eventsthisweek, execp=True)
+        self.add_events()
+        self.add_blank_rows()
+        return u"\n ".join(self.execlines)
+
+    def add_events(self):
+        for event in self.events:
+            self.numevents += 1
+            voffset = self.ypos + 31 + ((self.numevents - 1) * 11)
+            title = "${goto 20}%s" % utils.truncate(event["title"], 25)
+            timestr = self.event_time(event['date'])
+            self.rclines.append("${image %s/bullets/bullet_%s.png -p 0,%s -s 16x16}${voffset -11}" % (settings.IMGPATH, event["color"], voffset))
+            self.add_row(title, timestr, execp=True)
+            if self.numevents >= settings.GOOGLE_CALENDAR_NUMEVENTS: break
+
+    def add_blank_rows(self):
+        """ Fixes the text alignment if not enough shows displayed. """
+        for i in range(self.numevents, settings.GOOGLE_CALENDAR_NUMEVENTS):
+            self.add_row("", execp=True)
+
+    def update_calendars(self):
+        start_min = self.today.strftime("%Y-%m-%d")
+        start_max = self.nextweek.strftime("%Y-%m-%d")
+        singleevents = "true"
+        for i in range(len(settings.GOOGLE_CALENDAR_FEEDS)):
+            calendar = settings.GOOGLE_CALENDAR_FEEDS[i]
+            calendar_link = calendar.get("link")
+            if calendar_link:
+                calendar_link += "?alt=json&singleevents=%s&orderby=starttime" % (singleevents)
+                calendar_link += "&start-min=%s&start-max=%s" % (start_min, start_max)
+                calendar_response = utils.fetch_json(calendar_link, cache_key='googlecalendar_%s' % i)
+                calendar_response['color'] = calendar.get('color', 'white')
+                self.calendars.append(calendar_response)
+
+    def update_events(self):
+        for calendar in self.calendars:
+            color = calendar.get("color", "white")
+            for event in utils.rget(calendar, "feed.entry", []):
+                title = self.parser.unescape(utils.rget(event, "title.$t"))
+                summary = self.parser.unescape(utils.rget(event, "summary.$t")).replace("<br>", "")
+                eventdate = self.parse_event_start(summary)
+                if self.today <= eventdate <= self.nextweek:
+                    self.events.append({"color":color, "title":title, "date":eventdate})
+        self.events = sorted(self.events, key=lambda e: e['date'])
+
+    def parse_event_start(self, summary):
+        datestr, startstr = None, None
+        for line in summary.split("\n"):
+            if line.startswith("When:"):
+                dateparts = line.split(" ")
+                datestr = " ".join(dateparts[2:5])
+                if len(dateparts) > 5 and dateparts[6] == "to":
+                    startstr = line.split(" ")[5]
+                    if ":" not in startstr:
+                        startstr = startstr.replace("am", ":00am").replace("pm", ":00pm")
+                        datetimestr = "%s %s" % (datestr, startstr)
+                        return datetime.datetime.strptime(datetimestr, "%b %d, %Y %I:%M%p")
+                return datetime.datetime.strptime(datestr, "%b %d, %Y")
+            if line.startswith("First start:"):
+                datestr = line.split(" ")[2]
+                return datetime.datetime.strptime(datestr, "%Y-%m-%d")
+
+    def num_calendars(self):
+        num_calendars = 0
+        for calendar in settings.GOOGLE_CALENDAR_FEEDS:
+            if calendar.get("link"):
+                num_calendars += 1
+        return num_calendars
+
+    def event_time(self, indate):
+        time = indate.strftime("%I:%M%p").lower()
+        if time == "12:00am":
+            return "Today" if indate.date() == self.today.date() else indate.strftime("%A")
+        day = "Today" if indate.date() == self.today.date() else indate.strftime("%a")
+        time = time.replace(":00", "").replace("12am", "All Day").lstrip("0")
+        return "%s, %s" % (day, time)
+
+
+if __name__ == '__main__':
+    sys.stdout = codecs.getwriter('UTF-8')(sys.stdout)
+    parser = optparse.OptionParser(description='Conky output for Google Calendar')
+    parser.add_option('-y', '--ypos', type='int', default=0, help='Set the ypos for this meter')
+    opts, args = parser.parse_args()
+    sys.stdout.write("%s\n" % GoogleCalendar(opts.ypos).execpi(opts))

File pkmeter/meters/sickbeard.py

 if __name__ == '__main__':
     sys.stdout = codecs.getwriter('UTF-8')(sys.stdout)
     parser = optparse.OptionParser(description='Conky output for Sickbeard')
-    parser.add_option('-s', '--shows', default=False, action='store_true', help='Return the total number of shows.')
     parser.add_option('-y', '--ypos', type='int', default=0, help='Set the ypos for this meter')
     opts, args = parser.parse_args()
     sys.stdout.write("%s\n" % Sickbeard(opts.ypos).execpi(opts))

File pkmeter/utils/settings.py

     'pkmeter.meters.nvidia.Nvidia',
     'pkmeter.meters.filesystems.FileSystems',
     'pkmeter.meters.network.Network',
+    'pkmeter.meters.googlecalendar.GoogleCalendar',
     'pkmeter.meters.sickbeard.Sickbeard',
     #'pkmeter.meters.nowplaying.NowPlaying',
 ]
 ]
 
 
+# GOOGLE CALENDAR
+# ---------------
+# GOOGLE_CALENDAR_FEEDS: List of PRIVATE XML gcal links..
+#   Use the format: [{"link":<XML-LINK>, "color":"<color>"}]
+#   NOTE: Color definiition above is optional. Available colors: black, blue,
+#   green, orange, pink, purple, red, star, white, yellow
+# GOOGLE_CALENDAR_NUMEVENTS: Number of calendar events to display.
+GOOGLE_CALENDAR_FEEDS = [
+    {"link": None, "color": None},
+    {"link": None, "color": None},
+]
+GOOGLE_CALENDAR_NUMEVENTS = 5
+
+
 # SICKBEARD
 # ---------
 # SICKBEARD_URL: Url to sickbeard administration page.

File share/img/bullets/bullet_black.png

Added
New image

File share/img/bullets/bullet_blue.png

Added
New image

File share/img/bullets/bullet_green.png

Added
New image

File share/img/bullets/bullet_orange.png

Added
New image

File share/img/bullets/bullet_pink.png

Added
New image

File share/img/bullets/bullet_purple.png

Added
New image

File share/img/bullets/bullet_red.png

Added
New image

File share/img/bullets/bullet_star.png

Added
New image

File share/img/bullets/bullet_white.png

Added
New image

File share/img/bullets/bullet_yellow.png

Added
New image

File share/img/googlecalendar.png

Added
New image