Skip to content

Instantly share code, notes, and snippets.

@natejgreene
Last active Feb 7, 2016
Embed
What would you like to do?
#!/usr/bin/env python
#heavy use of https://github.com/oeey/gcalendar Thanks oeey!
import httplib2
import sys
import time
import BaseHTTPServer
import urlparse
import urllib
from apiclient.discovery import build
from oauth2client.file import Storage
from oauth2client.client import AccessTokenRefreshError
from oauth2client.client import OAuth2WebServerFlow
from oauth2client.tools import run_flow
from oauth2client.client import flow_from_clientsecrets
from xml.sax.saxutils import escape
HOST_NAME = '192.168.1.114' # !!!REMEMBER TO CHANGE THIS!!!
PORT_NUMBER = 80
ACCOUNT_EMAIL_ADDRESS = 'example@gmail.com'
ACCOUNT_NAME = 'John Doe'
CALENDAR_NAME = 'Our Calendar'
CALENDAR_ID = '[id]@group.calendar.google.com'
class GoogleCalendarV3ToV2:
def get_service(self):
scope = 'https://www.googleapis.com/auth/calendar'
flow = flow_from_clientsecrets('client_secret.json', scope=scope)
storage = Storage('credentials.dat')
credentials = storage.get()
class fakeargparse(object): # fake argparse.Namespace
noauth_local_webserver = True
logging_level = "ERROR"
flags = fakeargparse()
if credentials is None or credentials.invalid:
credentials = run_flow(flow, storage, flags)
http = httplib2.Http()
http = credentials.authorize(http)
return build('calendar', 'v3', http=http)
def get_calendar(self):
response = """<feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearch/1.1/' xmlns:gCal='http://schemas.google.com/gCal/2005' xmlns:gd='http://schemas.google.com/g/2005' gd:etag='etagblah'>
<id>http://www.google.com/calendar/feeds/default/allcalendars/full</id>
<updated>2014-11-18T01:01:59.657Z</updated>
<title>{0}</title>
<link rel='alternate' type='text/html' href='http://www.google.com/calendar/render' />
<link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/allcalendars/full' />
<link rel='http://schemas.google.com/g/2005#post' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/allcalendars/full' />
<link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/allcalendars/full' />
<author>
<name>{0}</name>
<email>{1}</email>
</author>
<generator version='1.0' uri='http://www.google.com/calendar'>Google Calendar</generator>
<openSearch:startIndex>1</openSearch:startIndex>""".format(ACCOUNT_NAME, ACCOUNT_EMAIL_ADDRESS)
page_token = None
while True:
calendar_list = self.get_service().calendarList().list(pageToken=page_token).execute()
for calendar_list_entry in calendar_list['items']:
if calendar_list_entry['summary'] == CALENDAR_NAME:
temp="""<entry gd:etag='{0}'>
<id>http://www.google.com/calendar/feeds/default/allcalendars/full/{6}/{5}</id>
<published>2014-07-11T22:10:30.257Z</published>
<updated>2014-07-11T21:46:35.000Z</updated>
<title>{1}</title>
<summary type='text'>{2}</summary>
<link rel='alternate' type='application/atom+xml' href='http://www.google.com/calendar/feeds/{6}/private/full' />
<link rel='http://schemas.google.com/gCal/2005#eventFeed' type='application/atom+xml' href='http://www.google.com/calendar/feeds/{6}/private/full' />
<link rel='http://schemas.google.com/acl/2007#accessControlList' type='application/atom+xml' href='http://www.google.com/calendar/feeds/{6}/acl/full' />
<link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/allcalendars/full/{6}' />
<link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/allcalendars/full/{6}' />
<author>
<name>{7}</name>
<email>{6}</email>
</author>
<gCal:timezone value='{3}' />
<gCal:hidden value='false' />
<gCal:color value='#42d692' />
<gCal:selected value='true' />
<gCal:accesslevel value='owner' />
<gd:where valueString='{4}' />
</entry>"""
response+=temp.format(calendar_list_entry['etag'],
calendar_list_entry['summary'],
calendar_list_entry['summary'],
calendar_list_entry['timeZone'],
"Minneapolis",
calendar_list_entry['id'],
ACCOUNT_EMAIL_ADDRESS,
ACCOUNT_NAME)
page_token = calendar_list.get('nextPageToken')
if not page_token:
break
response+="</feed>"
return response
def get_events(self, startmin, endmax, tz):
response="""<feed xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' gd:etag='etagblah'>
<id>http://www.google.com/calendar/feeds/{2}/private/composite</id>
<updated>2014-03-29T07:35:59.000Z</updated>
<title type='text'>{0}</title>
<subtitle type='text'>This is my main calendar.</subtitle>
<link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://www.google.com/calendar/feeds/{2}/private/composite'></link>
<link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/{2}/private/composite'></link>
<author>
<name>{1}</name>
<email>{2}</email>
</author>
<generator version='1.0' uri='http://www.google.com/calendar/'>CL2</generator>
<gd:where valueString='Minnesota'></gd:where>""".format(CALENDAR_NAME, ACCOUNT_NAME, ACCOUNT_EMAIL_ADDRESS)
events = self.get_service().events().list(calendarId=CALENDAR_ID, timeZone=tz, timeMin=startmin+'Z', timeMax=endmax+'Z', singleEvents=True).execute()
for event in events['items']:
temp="""<entry gd:etag='{0}'>
<id>urn:id:{1}</id>
<published>{8}</published>
<updated>{9}</updated>
<category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category>
<title type='text'>{2}</title>
<content type='text'>{3}</content>
<link rel='alternate' type='text/html' href='http://www.google.com/calendar/event?eid={1}' title='alternate'></link>
<link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/{12}/private/composite/{1}'></link>
<link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/{12}/private/composite/{1}'></link>
<author>
<name>{6}</name>
<email>{7}</email>
</author>
<gd:transparency value='http://schemas.google.com/g/2005#event.opaque'></gd:transparency>
<gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed'></gd:eventStatus>
<gd:comments>
<gd:feedLink href='http://www.google.com/calendar/feeds/{12}/private/composite/{1}/comments/'></gd:feedLink>
</gd:comments>
<gd:when startTime='{4}' endTime='{5}'></gd:when>
<gd:where></gd:where>
</entry>"""
response+=temp.format(event["etag"],
event["id"],
escape(event["summary"]),
escape(event["summary"]),
self.d(event["start"]),
self.d(event["end"]),
event['creator']['displayName'],
event['creator']['email'],
self.get(event,'updated'),
self.get(event,'updated'),
escape(self.get(event,'location')),
ACCOUNT_NAME,
ACCOUNT_EMAIL_ADDRESS)
response+="</feed>"
return response
def d(self, d):
if 'dateTime' in d:
return d['dateTime']
elif 'date' in d:
return d['date']
else:
return ''
def get(self, hash,key):
if key in hash:
return hash[key]
else:
return ''
class GoogleServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_HEAD(self):
self.send_response(200)
self.send_header("Content-type", "text/xml")
self.end_headers()
def do_POST(self):
self.send_response(200)
self.end_headers()
self.wfile.write("Auth=SomeFuckingToken")
def do_GET(self):
cal = GoogleCalendarV3ToV2()
self.path = self.path.replace('composite&ctz','composite?ctz') #well not sure why the app is sending this.
parsed_path = urlparse.urlparse(self.path)
self.send_response(200)
qs = urlparse.parse_qs(parsed_path.query)
if parsed_path.path == '/calendar/feeds/default/allcalendars/full':
self.send_header("Content-type", "application/atom+xml")
self.end_headers()
self.wfile.write(cal.get_calendar())
if parsed_path.path == '/calendar/feeds/' + ACCOUNT_EMAIL_ADDRESS + '/private/composite':
self.send_header("Content-type", "application/atom+xml")
self.end_headers()
self.wfile.write(cal.get_events(qs['start-min'][0], qs['start-max'][0], qs['ctz'][0]))
if __name__ == '__main__':
server_class = BaseHTTPServer.HTTPServer
httpd = server_class((HOST_NAME, PORT_NUMBER), GoogleServerHandler)
print time.asctime(), "Server Starts - %s:%s" % (HOST_NAME, PORT_NUMBER)
try:
httpd.serve_forever()
except KeyboardInterrupt:
pass
httpd.server_close()
print time.asctime(), "Server Stops - %s:%s" % (HOST_NAME, PORT_NUMBER)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment