Skip to content

Instantly share code, notes, and snippets.

@mcsquaredjr
Last active December 15, 2015 04:29
Show Gist options
  • Select an option

  • Save mcsquaredjr/5201619 to your computer and use it in GitHub Desktop.

Select an option

Save mcsquaredjr/5201619 to your computer and use it in GitHub Desktop.

Revisions

  1. mcsquaredjr revised this gist Mar 21, 2013. 1 changed file with 1 addition and 2 deletions.
    3 changes: 1 addition & 2 deletions install_green_cal.py
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,3 @@

    # Script to install greencal and required libraries

    import tarfile
    @@ -14,7 +13,7 @@
    ############################################################
    try:
    os.mkdir('greencal')
    json_url = 'https://api.github.com/gists/15a18fa914219c5546f9'
    json_url = 'https://api.github.com/gists/15a18fa914219c5546f9Zz'
    gist_json = requests.get(json_url).text
    gist_info = json.loads(gist_json)
    files = gist_info['files']
  2. mcsquaredjr revised this gist Mar 20, 2013. 1 changed file with 125 additions and 469 deletions.
    594 changes: 125 additions & 469 deletions install_green_cal.py
    Original file line number Diff line number Diff line change
    @@ -1,483 +1,139 @@
    '''
    Green Calendar: process Evernote notes, create events, and
    cross-reference notes with events.
    '''

    __author__ = 'Serge Boyko aka mcsquaredjr'
    __version__ = '0.3'
    __date__ = 'Tuesday, March 5th, 2013'
    __email__ = "serge dot boyko at gmail dot com"
    # Script to install greencal and required libraries

    import tarfile
    import shutil
    import urllib
    import requests
    import os
    import json


    import sys
    # Try to determine if we are in Pythonista
    ############################################################
    # INSTALL GREEN_CAL.PY #
    ############################################################
    try:
    # to import a Pythonista-specific module
    from scene import Layer
    in_pythonista = True
    del(sys.modules['scene'])
    except ImportError:
    in_pythonista = False

    if in_pythonista:
    sys.path.append('../')
    sys.path.append('../evernote-sdk')
    sys.path.append('../google-api')

    import evernote.edam.userstore.constants as UserStoreConstants
    import evernote.edam.type.ttypes as Types
    import evernote.edam.error.ttypes as Errors
    from evernote.api.client import EvernoteClient
    from evernote.edam.notestore import NoteStore

    import gflags
    import httplib2
    os.mkdir('greencal')
    json_url = 'https://api.github.com/gists/15a18fa914219c5546f9'
    gist_json = requests.get(json_url).text
    gist_info = json.loads(gist_json)
    files = gist_info['files']
    file_info = files.values()[0]
    filename = file_info['filename']
    content = file_info['content']
    print 'Installing green_cal.py...'
    f = open('green_cal.py', 'w+')
    f.write(content)
    f.close()
    shutil.move('green_cal.py', 'greencal')
    print 'green_cal.py installed.'
    except Exception, e:
    print e

    from apiclient.discovery import build

    from oauth2client.file import Storage
    from oauth2client.client import OAuth2WebServerFlow
    from oauth2client.tools import run

    import datetime
    import time
    import parsedatetime as pdt
    import argparse
    ############################################################
    # INSTALL EVERNOTE SDK #
    ############################################################
    try:
    os.mkdir('evernote-sdk')
    print 'Downloading evernote...'
    filename, headers = urllib.urlretrieve('https://pypi.python.org/packages/source/e/evernote/evernote-1.23.2.tar.gz')
    print 'Installing evernote...'
    t = tarfile.open(filename, 'r')
    t.extractall()
    t.close()
    shutil.move('evernote-1.23.2/lib/evernote', 'evernote-sdk/evernote')
    shutil.move('evernote-1.23.2/lib/thrift', 'evernote-sdk/thrift')
    shutil.rmtree('evernote-1.23.2')
    print 'evernote-1.23.2 installed'

    print 'Downloading httplib2...'
    filename, headers = urllib.urlretrieve('https://pypi.python.org/packages/source/h/httplib2/httplib2-0.7.7.tar.gz')
    print 'Installing httplib2...'
    t = tarfile.open(filename, 'r')
    t.extractall()
    t.close()
    shutil.move('httplib2-0.7.7/python2/httplib2', 'evernote-sdk/httplib2')
    shutil.rmtree('httplib2-0.7.7')

    print 'Downloading oauth2...'
    filename, headers = urllib.urlretrieve('https://pypi.python.org/packages/source/o/oauth2/oauth2-1.5.211.tar.gz')
    print 'Installing oauth2...'
    t = tarfile.open(filename, 'r')
    t.extractall()
    t.close()
    shutil.move('oauth2-1.5.211/oauth2', 'evernote-sdk/oauth2')
    shutil.rmtree('oauth2-1.5.211')
    print 'oauth2-1.5.211 installed'

    # Replace with the values obtained from Evernote dev site
    EN_TOKEN = 'S=s4:U=4e6ce:E=144843b4814:C=13d2c8a1c15:P=1cd:A=en-devtoken:V=2:H=571cd0a766b20553e40416d9f171f960'
    EN_URL = 'https://www.evernote.com'
    # Replace with the values obtained from Google
    GC_CLIENT_ID = '187093465256.apps.googleusercontent.com'
    GC_CLIENT_SECRET = '7_iClvcZBpyn9rFU63sFKNPT'
    GC_SCOPE = 'https://www.googleapis.com/auth/calendar'
    GC_USER_AGENT = 'Green Calendar for Evernote'
    GC_DEV_KEY = 'AIzaSyDI982IYusCZv2Rf3z5rQ7aGuvtLtcEbOM'
    except:
    pass

    ############################################################
    # CLASS EVERNOTE_PROCESSOR #
    # INSTALL GOOGLE API #
    ############################################################
    class Evernote_Processor(object):
    '''Represents objects and methods to access, update, and
    process Evernote notes and their attributes to extract due
    dates and link with Google Calendar Events.
    '''
    def __init__(self, token):
    self.token = token
    self.client = EvernoteClient(token=EN_TOKEN, sandbox=False)
    self.user_store = self.client.get_user_store()
    self.note_store = self.client.get_note_store()
    self.shard_id = self.get_shard_id()
    try:
    os.mkdir('google-api')


    def check_version(self):
    '''Check for version'''
    version_ok = self.user_store.checkVersion(
    "Version check",
    UserStoreConstants.EDAM_VERSION_MAJOR,
    UserStoreConstants.EDAM_VERSION_MINOR
    )
    if not version_ok:
    return -1
    else:
    return 0


    def _make_note(self, title, content, url):
    '''Prepare a note to be posted'''
    note = Types.Note()
    note.title = title
    # Set up note attributes
    attrs = Types.NoteAttributes()
    attrs.sourceURL = url
    note.attributes = attrs
    note.content = '<?xml version="1.0" encoding="UTF-8"?>'
    note.content += '<!DOCTYPE en-note SYSTEM ' \
    '"http://xml.evernote.com/pub/enml2.dtd">'
    # Wrap content in <en-note>
    note.content += '<en-note>'
    note.content += content
    note.content += '</en-note>'
    return note


    def get_shard_id(self):
    '''
    Get the User from user_store and return the user's shard ID
    '''
    try:
    user = self.user_store.getUser(self.token)
    except (Errors.EDAMUserException,
    Errors.EDAMSystemException), e:
    print "Exception while getting user's shardID:"
    print type(e), e
    return None

    if hasattr(user, 'shardId'):
    return user.shardId
    return None


    def post_note(self, title, note, url):
    '''Post a note to Evernote'''
    ver = self.check_version()
    if ver < 0:
    print '*** VERSION ERROR: Update client to the latest version.'
    else:
    note = self._make_note(title, note, url)
    try:
    created_note = self.note_store.createNote(note)

    except (Errors.EDAMUserException,
    Errors.EDAMSystemException), e:
    print "Exception while getting user's shardID:"
    print type(e), e
    return None

    if hasattr(created_note, 'guid'):
    return created_note.guid
    return None


    def get_notebook_guid(self, notebook_name):
    '''Return notebooks guid given the notebook name'''
    if notebook_name is not None:
    notebooks = self.note_store.listNotebooks()
    # Iterate over notebooks until a given mame is not found
    # Return None if non-existing name is given
    matched_notebook = next((notebook for notebook in notebooks \
    if notebook.name == notebook_name), None)
    if matched_notebook is not None:
    guid = matched_notebook.guid
    else:
    guid = None
    print '*** Warning: notebook {0} was not found.'.format(notebook_name)
    else:
    guid = self.note_store.getDefaultNotebook().guid
    return guid


    def get_notes(self, notebook_name, words=None, offset=0, max_num=25):
    '''Get max_num notes from a notebook'''
    # This is how we construct a filter, we cannot get it from
    # an instance of the NoteStore
    filter = NoteStore.NoteFilter()
    # Evernote search grammar is described here:
    # http://dev.evernote.com/documentation/cloud/chapters/search_grammar.php
    guid = self.get_notebook_guid(notebook_name)
    if guid is not None:
    filter.notebookGuid = guid
    if words is not None:
    # words is an attribute in Python
    filter.words = words
    try:
    notes_list = self.note_store.findNotes(self.token,
    filter,
    0,
    max_num)
    except Exception, e:
    print 'Exception while finding notes: ', e
    notes_list = None
    else:
    notes_list = None
    # NoteList is not a Python list, but a structure
    return notes_list
    print 'Downloading google-api-client...'
    filename, headers = urllib.urlretrieve('https://pypi.python.org/packages/source/g/google-api-python-client/google-api-python-client-1.0.tar.gz')
    print 'Installing google-api-client...'
    t = tarfile.open(filename, 'r')
    t.extractall()
    t.close()
    shutil.move('google-api-python-client-1.0/apiclient', 'google-api/apiclient')
    shutil.move('google-api-python-client-1.0/oauth2client', 'google-api/oauth2client')
    shutil.move('google-api-python-client-1.0/uritemplate', 'google-api/uritemplate')
    shutil.rmtree('google-api-python-client-1.0')
    print 'google-api-python-client-1.0 installed.'

    print 'Downloading python-gflags...'
    filename, headers = urllib.urlretrieve('https://pypi.python.org/packages/source/p/python-gflags/python-gflags-2.0.tar.gz')
    print 'Installing python-gflags...'
    t = tarfile.open(filename, 'r')
    t.extractall()
    t.close()
    shutil.move('python-gflags-2.0/gflags.py', 'google-api/gflags.py')
    shutil.move('python-gflags-2.0/gflags2man.py', 'google-api/gflags2man.py')
    shutil.move('python-gflags-2.0/gflags_validators.py', 'google-api/gflags_validators.py')
    shutil.rmtree('python-gflags-2.0')
    print 'python-gflags-2.0 instaled.'

    print 'Downloading httplib2...'
    filename, headers = urllib.urlretrieve('https://pypi.python.org/packages/source/h/httplib2/httplib2-0.7.7.tar.gz')
    print 'Installing httplib2...'
    t = tarfile.open(filename, 'r')
    t.extractall()
    t.close()
    shutil.move('httplib2-0.7.7/python2/httplib2', 'google-api/httplib2')
    shutil.rmtree('httplib2-0.7.7')
    print 'httplib2 installed.'


    def get_note_url(self, guid):
    '''
    Share a single note and return the public URL for the note
    '''
    if not self.shard_id:
    self.shard_id = self.get_shard_id()
    if not self.shard_id:
    raise SystemExit
    try:
    share_key = self.note_store.shareNote(self.token, guid)
    except (EDAMNotFoundException,
    EDAMSystemException,
    EDAMUserException), e:
    print "Error sharing note:"
    print type(e), e
    return None
    return "%s/shard/%s/sh/%s/%s" % \
    (EN_URL, self.shard_id, guid, share_key)


    def get_note_due_date(self, note):
    '''Extract due date from a note title'''
    title = note.title
    ind = title.find('__')
    ddate = title[ind+2:]
    # Rerurn note's title (without due date) and due date
    return (title[:ind].strip(), ddate.strip())


    def update_note(self, note, new_title, url):
    '''Update note title for processed notes'''
    note.title = new_title
    attrs = Types.NoteAttributes()
    attrs.sourceURL = url
    note.attributes = attrs
    # Update the note with new_title
    try:
    updated_note = self.note_store.updateNote(note)
    return updated_note.guid
    except Exception, e:
    print 'Exception while updating note: ', e
    return None

    except:
    pass

    ############################################################
    # CLASS GCAL_EVENT #
    ############################################################
    class GCal_Event(object):
    '''Access and create events in Google Calendar and link with
    Evernote notes representing actions with due dates.'''

    def __init__(self):
    FLAGS = gflags.FLAGS
    FLOW = OAuth2WebServerFlow(
    client_id=GC_CLIENT_ID,
    client_secret=GC_CLIENT_SECRET,
    scope=GC_SCOPE,
    user_agent=GC_USER_AGENT)
    # We need to disable it for an installed app
    FLAGS.auth_local_webserver = False
    # Read credentials if available
    storage = Storage('calendar.dat')
    credentials = storage.get()
    if credentials is None or credentials.invalid == True:
    credentials = run(FLOW, storage)
    # Create an httplib2.Http object to handle our HTTP requests
    # and authorize it with our good Credentials.
    http = httplib2.Http()
    http = credentials.authorize(http)
    # Build a service object for interacting with the API
    self.service = build(serviceName='calendar',
    version='v3',
    http=http,
    developerKey=GC_DEV_KEY)


    def get_service(self):
    '''Get service object'''
    return self.service


    def generate_event(self, start, end, tz, location, summary, desc):
    '''Generate event from provided data'''
    start_dict = dict()
    start_dict['dateTime'] = start
    start_dict['timeZone'] = tz
    end_dict = dict()
    end_dict['dateTime'] = end
    end_dict['timeZone'] = tz
    evt_dict = dict()
    evt_dict['kind'] = 'calendar#event'
    evt_dict['status'] = 'confirmed'
    evt_dict['summary'] = summary
    evt_dict['description'] = desc
    evt_dict['summary'] = summary
    evt_dict['start'] = start_dict
    evt_dict['end'] = end_dict
    evt_dict['location'] = location
    evt_dict['colorId'] = '2' # Mint!
    return evt_dict


    def create_event(self, cal_id, evt):
    '''Create event in Google calendar, identified by cal_id'''
    try:
    events = self.get_service().events()
    created_evt = events.insert(body=evt,
    calendarId=cal_id).execute()
    return created_evt['htmlLink']
    except Exception, e:
    print 'Exception while creating event: ', e
    return None

    ############################################################
    # CLASS GREEN_CALENDAR #
    # INSTALL PARSEDATETIME #
    ############################################################
    class Green_Calendar(object):
    '''Controller class'''

    def __init__(self):
    self.ep = Evernote_Processor(EN_TOKEN)
    self.gc = GCal_Event()
    self.start_time = time.time()


    def process_due_date(self, due_date_str, duration=15):
    '''Parse date string and return start date/time in format used
    by Google Calendar (RFC-3889).
    '''
    c = pdt.Constants()
    c.BirthdayEpoch = 80
    p = pdt.Calendar(c)
    result = p.parse(due_date_str)
    # Unpack the tuple and convert to string
    start = datetime.datetime(*result[0][0:6])
    end = start + datetime.timedelta(minutes=duration)
    # Ignore seconds
    start_str = start.strftime('%Y-%m-%dT%H:%M:00')
    end_str = end.strftime('%Y-%m-%dT%H:%M:00')
    return (start_str, end_str, result[1])


    def _setup(self,
    notebooks, # list of notebooks, use default if None
    sep, # separator before due date
    sep_proc, # separator in processed notes
    max_age, # seach notes not older than max_age
    cal_id # Google calendar ID
    ):
    '''Configure Green Calendar'''
    self.notebooks = notebooks
    self.sep = sep
    self.sep_proc = sep_proc
    self.max_age = max_age
    self.cal_id = cal_id


    def run(self):
    '''Glue all pieces together, parse dates, cross-link notes
    and events.
    '''
    # Configure search
    words = 'intitle:"{0}"'.format(self.sep)
    # Find all matching notes
    notes_list = []
    if self.notebooks is None:
    notes = self.ep.get_notes(None,
    words=words,
    offset=0,
    max_num=25)
    notes_list.append(notes.notes)
    else:
    if type(self.notebooks) is list:
    for notebook in self.notebooks:
    #print notebook
    notes = self.ep.get_notes(notebook,
    words=words,
    offset=0,
    max_num=25)
    if notes is not None:
    notes_list.append(notes.notes)
    else:
    raise TypeError('Notebooks must be a list or a None-type.')
    # Flatten the note list
    notes_list = [item for sublist in notes_list for item in sublist]
    fmt ='{:<5}{:<24}{:<45}{:<5}'.format('No.', 'Due date/time', 'Note title', 'Result')
    print '\nPROCESSING REPORT'
    print '-'*len(fmt)
    print fmt
    print '-'*len(fmt)
    # Start processing here
    for i, note in enumerate(notes_list):
    title, ddate = self.ep.get_note_due_date(note)
    (start, end, result) = self.process_due_date(ddate)
    if result > 0:
    note_url = self.ep.get_note_url(note.guid)
    # Create time zone string
    # TODO: take into account periods when Europe ans USA are
    # not in sync when switching to the summer/winter time
    tz = str.format('{0:+06.2f}', float(-time.timezone)/3600)
    tz = 'UTC' + tz
    location = 'Evernote'
    description = note_url + '\n\n--Created by Green Calendar'
    evt = self.gc.generate_event(start,
    end,
    tz,
    location,
    title,
    description)
    # Construct new title
    title = title + ' ' + self.sep_proc + ' ' + start
    # Create event and update the note
    evt_url = self.gc.create_event(self.cal_id, evt)
    guid = self.ep.update_note(note, title, evt_url)
    if (guid is not None) and (evt_url is not None):
    result = 'OK'
    else:
    result = 'Error'
    # Truncate the title for report
    title_ = (title[:40] + '...') if len(title) > 40 else title
    fmt ='{:<5}{:<24}{:<45}{:^4}'.format(i+1,
    start,
    title_,
    result)
    print fmt
    else:
    # We cannot parse the date; no events created
    result = 'Error'
    title_ = (title[:40] + '...') if len(title) > 40 else title
    fmt ='{:<5}{:<24}{:<45}{:<5}'.format(i+1,
    'UNDEFINED',
    title_,
    result)
    print fmt
    print '-'*len(fmt)
    e_time = time.time() - self.start_time
    print 'Elapsed time: {0:f}'.format(e_time)
    print 'The number of processed notes is: {0:d}'.format(len(notes_list))

    if __name__ == '__main__':
    # Change the values below if you want different defaults
    # You do not need to supply a value for notebooks if you want
    # to use the default notebook
    defaults = dict()
    defaults['max_age'] = 7
    defaults['sep'] = '__'
    defaults['sep_proc'] = '##'
    defaults['cal_id'] = 'primary'
    # Create a parser
    parser = argparse.ArgumentParser(description='parse evernote notes, \
    create events in google calendar, and \
    cross-reference notes and events',
    usage='python green_calendar.py -h',
    prog='Green Calendar',
    epilog='report bugs to [email protected].')
    parser.add_argument('--notebooks', '-n',
    help='whitepace-delimited list of notebooks to \
    search within',
    nargs='+',
    type=str,
    metavar='LIST'
    )
    parser.add_argument('--max_age', '-a',
    help='do not process notes older than M days',
    type=int,
    metavar='M',
    default=defaults['max_age']
    )
    parser.add_argument('--sep', '-s',
    help='separator used for non-processed notes \
    (default is "__")',
    type=str,
    metavar='S',
    default=defaults['sep']
    )
    parser.add_argument('--sep_proc', '-p',
    help='separator used for proceesed notes \
    (default is "##")',
    type=str,
    metavar='P',
    default=defaults['sep_proc']
    )
    parser.add_argument('--cal_id', '-c',
    help='id of the calendar used for created events',
    type=str,
    metavar='ID',
    default=defaults['cal_id']
    )
    args = parser.parse_args()
    # Now run!
    gc = Green_Calendar()
    gc._setup(notebooks=args.notebooks,
    sep=args.sep,
    sep_proc=args.sep_proc,
    max_age=args.max_age,
    cal_id=args.cal_id)
    gc.run()
    try:
    os.mkdir('parsedatetime')

    print 'Downloading parsedatetime...'
    filename, headers = urllib.urlretrieve('https://github.com/bear/parsedatetime/archive/master.tar.gz')
    print 'Installing parsedatetime...'
    t = tarfile.open(filename, 'r')
    t.extractall()
    t.close()

    shutil.move('parsedatetime-master/parsedatetime/__init__.py', 'parsedatetime')
    shutil.move('parsedatetime-master/parsedatetime/parsedatetime.py', 'parsedatetime')
    shutil.move('parsedatetime-master/parsedatetime/pdt_locales.py', 'parsedatetime')
    shutil.rmtree('parsedatetime-master')
    print 'parsedatetime installed.'
    except:
    pass


    import editor
    editor.reload_files()

    print 'All done.'
  3. mcsquaredjr revised this gist Mar 20, 2013. 1 changed file with 469 additions and 127 deletions.
    596 changes: 469 additions & 127 deletions install_green_cal.py
    Original file line number Diff line number Diff line change
    @@ -1,141 +1,483 @@
    '''
    Green Calendar: process Evernote notes, create events, and
    cross-reference notes with events.
    '''

    __author__ = 'Serge Boyko aka mcsquaredjr'
    __version__ = '0.3'
    __date__ = 'Tuesday, March 5th, 2013'
    __email__ = "serge dot boyko at gmail dot com"

    # Script to install greencal and required libraries

    import tarfile
    import shutil
    import urllib
    import requests
    import os
    import json


    ############################################################
    # INSTALL GREEN_CAL.PY #
    ############################################################
    import sys
    # Try to determine if we are in Pythonista
    try:
    os.mkdir('greencal')
    json_url = 'https://api.github.com/gists/15a18fa914219c5546f9'
    gist_json = requests.get(json_url).text
    gist_info = json.loads(gist_json)
    files = gist_info['files']
    file_info = files.values()[0]
    filename = file_info['filename']
    content = file_info['content']

    print 'Installing green_cal.py...'
    f = open('green_cal.py', 'w')
    f.wrire(r.content)
    f.close()
    shutil.move('green_cal.py', 'greencal')
    print 'green_cal.py installed.'
    except:
    pass
    # to import a Pythonista-specific module
    from scene import Layer
    in_pythonista = True
    del(sys.modules['scene'])
    except ImportError:
    in_pythonista = False

    ############################################################
    # INSTALL EVERNOTE SDK #
    ############################################################
    try:
    os.mkdir('evernote-sdk')
    print 'Downloading evernote...'
    filename, headers = urllib.urlretrieve('https://pypi.python.org/packages/source/e/evernote/evernote-1.23.2.tar.gz')
    print 'Installing evernote...'
    t = tarfile.open(filename, 'r')
    t.extractall()
    t.close()
    shutil.move('evernote-1.23.2/lib/evernote', 'evernote-sdk/evernote')
    shutil.move('evernote-1.23.2/lib/thrift', 'evernote-sdk/thrift')
    shutil.rmtree('evernote-1.23.2')
    print 'evernote-1.23.2 installed'

    print 'Downloading httplib2...'
    filename, headers = urllib.urlretrieve('https://pypi.python.org/packages/source/h/httplib2/httplib2-0.7.7.tar.gz')
    print 'Installing httplib2...'
    t = tarfile.open(filename, 'r')
    t.extractall()
    t.close()
    shutil.move('httplib2-0.7.7/python2/httplib2', 'evernote-sdk/httplib2')
    shutil.rmtree('httplib2-0.7.7')

    print 'Downloading oauth2...'
    filename, headers = urllib.urlretrieve('https://pypi.python.org/packages/source/o/oauth2/oauth2-1.5.211.tar.gz')
    print 'Installing oauth2...'
    t = tarfile.open(filename, 'r')
    t.extractall()
    t.close()
    shutil.move('oauth2-1.5.211/oauth2', 'evernote-sdk/oauth2')
    shutil.rmtree('oauth2-1.5.211')
    print 'oauth2-1.5.211 installed'
    if in_pythonista:
    sys.path.append('../')
    sys.path.append('../evernote-sdk')
    sys.path.append('../google-api')

    import evernote.edam.userstore.constants as UserStoreConstants
    import evernote.edam.type.ttypes as Types
    import evernote.edam.error.ttypes as Errors
    from evernote.api.client import EvernoteClient
    from evernote.edam.notestore import NoteStore

    except:
    pass
    import gflags
    import httplib2

    ############################################################
    # INSTALL GOOGLE API #
    ############################################################
    try:
    os.mkdir('google-api')
    from apiclient.discovery import build

    print 'Downloading google-api-client...'
    filename, headers = urllib.urlretrieve('https://pypi.python.org/packages/source/g/google-api-python-client/google-api-python-client-1.0.tar.gz')
    print 'Installing google-api-client...'
    t = tarfile.open(filename, 'r')
    t.extractall()
    t.close()
    shutil.move('google-api-python-client-1.0/apiclient', 'google-api/apiclient')
    shutil.move('google-api-python-client-1.0/oauth2client', 'google-api/oauth2client')
    shutil.move('google-api-python-client-1.0/uritemplate', 'google-api/uritemplate')
    shutil.rmtree('google-api-python-client-1.0')
    print 'google-api-python-client-1.0 installed.'

    print 'Downloading python-gflags...'
    filename, headers = urllib.urlretrieve('https://pypi.python.org/packages/source/p/python-gflags/python-gflags-2.0.tar.gz')
    print 'Installing python-gflags...'
    t = tarfile.open(filename, 'r')
    t.extractall()
    t.close()
    shutil.move('python-gflags-2.0/gflags.py', 'google-api/gflags.py')
    shutil.move('python-gflags-2.0/gflags2man.py', 'google-api/gflags2man.py')
    shutil.move('python-gflags-2.0/gflags_validators.py', 'google-api/gflags_validators.py')
    shutil.rmtree('python-gflags-2.0')
    print 'python-gflags-2.0 instaled.'

    print 'Downloading httplib2...'
    filename, headers = urllib.urlretrieve('https://pypi.python.org/packages/source/h/httplib2/httplib2-0.7.7.tar.gz')
    print 'Installing httplib2...'
    t = tarfile.open(filename, 'r')
    t.extractall()
    t.close()
    shutil.move('httplib2-0.7.7/python2/httplib2', 'google-api/httplib2')
    shutil.rmtree('httplib2-0.7.7')
    print 'httplib2 installed.'
    from oauth2client.file import Storage
    from oauth2client.client import OAuth2WebServerFlow
    from oauth2client.tools import run

    except:
    pass
    import datetime
    import time
    import parsedatetime as pdt
    import argparse

    # Replace with the values obtained from Evernote dev site
    EN_TOKEN = 'S=s4:U=4e6ce:E=144843b4814:C=13d2c8a1c15:P=1cd:A=en-devtoken:V=2:H=571cd0a766b20553e40416d9f171f960'
    EN_URL = 'https://www.evernote.com'
    # Replace with the values obtained from Google
    GC_CLIENT_ID = '187093465256.apps.googleusercontent.com'
    GC_CLIENT_SECRET = '7_iClvcZBpyn9rFU63sFKNPT'
    GC_SCOPE = 'https://www.googleapis.com/auth/calendar'
    GC_USER_AGENT = 'Green Calendar for Evernote'
    GC_DEV_KEY = 'AIzaSyDI982IYusCZv2Rf3z5rQ7aGuvtLtcEbOM'

    ############################################################
    # INSTALL PARSEDATETIME #
    # CLASS EVERNOTE_PROCESSOR #
    ############################################################
    try:
    os.mkdir('parsedatetime')

    print 'Downloading parsedatetime...'
    filename, headers = urllib.urlretrieve('https://github.com/bear/parsedatetime/archive/master.tar.gz')
    print 'Installing parsedatetime...'
    t = tarfile.open(filename, 'r')
    t.extractall()
    t.close()

    shutil.move('parsedatetime-master/parsedatetime/__init__.py', 'pdt')
    shutil.move('parsedatetime-master/parsedatetime/parsedatetime.py', 'pdt')
    shutil.move('parsedatetime-master/parsedatetime/pdt_locales.py', 'pdt')
    shutil.rmtree('parsedatetime-master')
    ptint 'parsedatetime installed.'
    except:
    pass
    class Evernote_Processor(object):
    '''Represents objects and methods to access, update, and
    process Evernote notes and their attributes to extract due
    dates and link with Google Calendar Events.
    '''
    def __init__(self, token):
    self.token = token
    self.client = EvernoteClient(token=EN_TOKEN, sandbox=False)
    self.user_store = self.client.get_user_store()
    self.note_store = self.client.get_note_store()
    self.shard_id = self.get_shard_id()


    def check_version(self):
    '''Check for version'''
    version_ok = self.user_store.checkVersion(
    "Version check",
    UserStoreConstants.EDAM_VERSION_MAJOR,
    UserStoreConstants.EDAM_VERSION_MINOR
    )
    if not version_ok:
    return -1
    else:
    return 0


    def _make_note(self, title, content, url):
    '''Prepare a note to be posted'''
    note = Types.Note()
    note.title = title
    # Set up note attributes
    attrs = Types.NoteAttributes()
    attrs.sourceURL = url
    note.attributes = attrs
    note.content = '<?xml version="1.0" encoding="UTF-8"?>'
    note.content += '<!DOCTYPE en-note SYSTEM ' \
    '"http://xml.evernote.com/pub/enml2.dtd">'
    # Wrap content in <en-note>
    note.content += '<en-note>'
    note.content += content
    note.content += '</en-note>'
    return note


    def get_shard_id(self):
    '''
    Get the User from user_store and return the user's shard ID
    '''
    try:
    user = self.user_store.getUser(self.token)
    except (Errors.EDAMUserException,
    Errors.EDAMSystemException), e:
    print "Exception while getting user's shardID:"
    print type(e), e
    return None

    if hasattr(user, 'shardId'):
    return user.shardId
    return None


    def post_note(self, title, note, url):
    '''Post a note to Evernote'''
    ver = self.check_version()
    if ver < 0:
    print '*** VERSION ERROR: Update client to the latest version.'
    else:
    note = self._make_note(title, note, url)
    try:
    created_note = self.note_store.createNote(note)

    except (Errors.EDAMUserException,
    Errors.EDAMSystemException), e:
    print "Exception while getting user's shardID:"
    print type(e), e
    return None

    if hasattr(created_note, 'guid'):
    return created_note.guid
    return None


    def get_notebook_guid(self, notebook_name):
    '''Return notebooks guid given the notebook name'''
    if notebook_name is not None:
    notebooks = self.note_store.listNotebooks()
    # Iterate over notebooks until a given mame is not found
    # Return None if non-existing name is given
    matched_notebook = next((notebook for notebook in notebooks \
    if notebook.name == notebook_name), None)
    if matched_notebook is not None:
    guid = matched_notebook.guid
    else:
    guid = None
    print '*** Warning: notebook {0} was not found.'.format(notebook_name)
    else:
    guid = self.note_store.getDefaultNotebook().guid
    return guid


    def get_notes(self, notebook_name, words=None, offset=0, max_num=25):
    '''Get max_num notes from a notebook'''
    # This is how we construct a filter, we cannot get it from
    # an instance of the NoteStore
    filter = NoteStore.NoteFilter()
    # Evernote search grammar is described here:
    # http://dev.evernote.com/documentation/cloud/chapters/search_grammar.php
    guid = self.get_notebook_guid(notebook_name)
    if guid is not None:
    filter.notebookGuid = guid
    if words is not None:
    # words is an attribute in Python
    filter.words = words
    try:
    notes_list = self.note_store.findNotes(self.token,
    filter,
    0,
    max_num)
    except Exception, e:
    print 'Exception while finding notes: ', e
    notes_list = None
    else:
    notes_list = None
    # NoteList is not a Python list, but a structure
    return notes_list

    import editor
    editor.reload_files()

    print 'All done.'

    def get_note_url(self, guid):
    '''
    Share a single note and return the public URL for the note
    '''
    if not self.shard_id:
    self.shard_id = self.get_shard_id()
    if not self.shard_id:
    raise SystemExit
    try:
    share_key = self.note_store.shareNote(self.token, guid)
    except (EDAMNotFoundException,
    EDAMSystemException,
    EDAMUserException), e:
    print "Error sharing note:"
    print type(e), e
    return None
    return "%s/shard/%s/sh/%s/%s" % \
    (EN_URL, self.shard_id, guid, share_key)


    def get_note_due_date(self, note):
    '''Extract due date from a note title'''
    title = note.title
    ind = title.find('__')
    ddate = title[ind+2:]
    # Rerurn note's title (without due date) and due date
    return (title[:ind].strip(), ddate.strip())


    def update_note(self, note, new_title, url):
    '''Update note title for processed notes'''
    note.title = new_title
    attrs = Types.NoteAttributes()
    attrs.sourceURL = url
    note.attributes = attrs
    # Update the note with new_title
    try:
    updated_note = self.note_store.updateNote(note)
    return updated_note.guid
    except Exception, e:
    print 'Exception while updating note: ', e
    return None


    ############################################################
    # CLASS GCAL_EVENT #
    ############################################################
    class GCal_Event(object):
    '''Access and create events in Google Calendar and link with
    Evernote notes representing actions with due dates.'''

    def __init__(self):
    FLAGS = gflags.FLAGS
    FLOW = OAuth2WebServerFlow(
    client_id=GC_CLIENT_ID,
    client_secret=GC_CLIENT_SECRET,
    scope=GC_SCOPE,
    user_agent=GC_USER_AGENT)
    # We need to disable it for an installed app
    FLAGS.auth_local_webserver = False
    # Read credentials if available
    storage = Storage('calendar.dat')
    credentials = storage.get()
    if credentials is None or credentials.invalid == True:
    credentials = run(FLOW, storage)
    # Create an httplib2.Http object to handle our HTTP requests
    # and authorize it with our good Credentials.
    http = httplib2.Http()
    http = credentials.authorize(http)
    # Build a service object for interacting with the API
    self.service = build(serviceName='calendar',
    version='v3',
    http=http,
    developerKey=GC_DEV_KEY)


    def get_service(self):
    '''Get service object'''
    return self.service


    def generate_event(self, start, end, tz, location, summary, desc):
    '''Generate event from provided data'''
    start_dict = dict()
    start_dict['dateTime'] = start
    start_dict['timeZone'] = tz
    end_dict = dict()
    end_dict['dateTime'] = end
    end_dict['timeZone'] = tz
    evt_dict = dict()
    evt_dict['kind'] = 'calendar#event'
    evt_dict['status'] = 'confirmed'
    evt_dict['summary'] = summary
    evt_dict['description'] = desc
    evt_dict['summary'] = summary
    evt_dict['start'] = start_dict
    evt_dict['end'] = end_dict
    evt_dict['location'] = location
    evt_dict['colorId'] = '2' # Mint!
    return evt_dict


    def create_event(self, cal_id, evt):
    '''Create event in Google calendar, identified by cal_id'''
    try:
    events = self.get_service().events()
    created_evt = events.insert(body=evt,
    calendarId=cal_id).execute()
    return created_evt['htmlLink']
    except Exception, e:
    print 'Exception while creating event: ', e
    return None

    ############################################################
    # CLASS GREEN_CALENDAR #
    ############################################################
    class Green_Calendar(object):
    '''Controller class'''

    def __init__(self):
    self.ep = Evernote_Processor(EN_TOKEN)
    self.gc = GCal_Event()
    self.start_time = time.time()


    def process_due_date(self, due_date_str, duration=15):
    '''Parse date string and return start date/time in format used
    by Google Calendar (RFC-3889).
    '''
    c = pdt.Constants()
    c.BirthdayEpoch = 80
    p = pdt.Calendar(c)
    result = p.parse(due_date_str)
    # Unpack the tuple and convert to string
    start = datetime.datetime(*result[0][0:6])
    end = start + datetime.timedelta(minutes=duration)
    # Ignore seconds
    start_str = start.strftime('%Y-%m-%dT%H:%M:00')
    end_str = end.strftime('%Y-%m-%dT%H:%M:00')
    return (start_str, end_str, result[1])


    def _setup(self,
    notebooks, # list of notebooks, use default if None
    sep, # separator before due date
    sep_proc, # separator in processed notes
    max_age, # seach notes not older than max_age
    cal_id # Google calendar ID
    ):
    '''Configure Green Calendar'''
    self.notebooks = notebooks
    self.sep = sep
    self.sep_proc = sep_proc
    self.max_age = max_age
    self.cal_id = cal_id


    def run(self):
    '''Glue all pieces together, parse dates, cross-link notes
    and events.
    '''
    # Configure search
    words = 'intitle:"{0}"'.format(self.sep)
    # Find all matching notes
    notes_list = []
    if self.notebooks is None:
    notes = self.ep.get_notes(None,
    words=words,
    offset=0,
    max_num=25)
    notes_list.append(notes.notes)
    else:
    if type(self.notebooks) is list:
    for notebook in self.notebooks:
    #print notebook
    notes = self.ep.get_notes(notebook,
    words=words,
    offset=0,
    max_num=25)
    if notes is not None:
    notes_list.append(notes.notes)
    else:
    raise TypeError('Notebooks must be a list or a None-type.')
    # Flatten the note list
    notes_list = [item for sublist in notes_list for item in sublist]
    fmt ='{:<5}{:<24}{:<45}{:<5}'.format('No.', 'Due date/time', 'Note title', 'Result')
    print '\nPROCESSING REPORT'
    print '-'*len(fmt)
    print fmt
    print '-'*len(fmt)
    # Start processing here
    for i, note in enumerate(notes_list):
    title, ddate = self.ep.get_note_due_date(note)
    (start, end, result) = self.process_due_date(ddate)
    if result > 0:
    note_url = self.ep.get_note_url(note.guid)
    # Create time zone string
    # TODO: take into account periods when Europe ans USA are
    # not in sync when switching to the summer/winter time
    tz = str.format('{0:+06.2f}', float(-time.timezone)/3600)
    tz = 'UTC' + tz
    location = 'Evernote'
    description = note_url + '\n\n--Created by Green Calendar'
    evt = self.gc.generate_event(start,
    end,
    tz,
    location,
    title,
    description)
    # Construct new title
    title = title + ' ' + self.sep_proc + ' ' + start
    # Create event and update the note
    evt_url = self.gc.create_event(self.cal_id, evt)
    guid = self.ep.update_note(note, title, evt_url)
    if (guid is not None) and (evt_url is not None):
    result = 'OK'
    else:
    result = 'Error'
    # Truncate the title for report
    title_ = (title[:40] + '...') if len(title) > 40 else title
    fmt ='{:<5}{:<24}{:<45}{:^4}'.format(i+1,
    start,
    title_,
    result)
    print fmt
    else:
    # We cannot parse the date; no events created
    result = 'Error'
    title_ = (title[:40] + '...') if len(title) > 40 else title
    fmt ='{:<5}{:<24}{:<45}{:<5}'.format(i+1,
    'UNDEFINED',
    title_,
    result)
    print fmt
    print '-'*len(fmt)
    e_time = time.time() - self.start_time
    print 'Elapsed time: {0:f}'.format(e_time)
    print 'The number of processed notes is: {0:d}'.format(len(notes_list))

    if __name__ == '__main__':
    # Change the values below if you want different defaults
    # You do not need to supply a value for notebooks if you want
    # to use the default notebook
    defaults = dict()
    defaults['max_age'] = 7
    defaults['sep'] = '__'
    defaults['sep_proc'] = '##'
    defaults['cal_id'] = 'primary'
    # Create a parser
    parser = argparse.ArgumentParser(description='parse evernote notes, \
    create events in google calendar, and \
    cross-reference notes and events',
    usage='python green_calendar.py -h',
    prog='Green Calendar',
    epilog='report bugs to [email protected].')
    parser.add_argument('--notebooks', '-n',
    help='whitepace-delimited list of notebooks to \
    search within',
    nargs='+',
    type=str,
    metavar='LIST'
    )
    parser.add_argument('--max_age', '-a',
    help='do not process notes older than M days',
    type=int,
    metavar='M',
    default=defaults['max_age']
    )
    parser.add_argument('--sep', '-s',
    help='separator used for non-processed notes \
    (default is "__")',
    type=str,
    metavar='S',
    default=defaults['sep']
    )
    parser.add_argument('--sep_proc', '-p',
    help='separator used for proceesed notes \
    (default is "##")',
    type=str,
    metavar='P',
    default=defaults['sep_proc']
    )
    parser.add_argument('--cal_id', '-c',
    help='id of the calendar used for created events',
    type=str,
    metavar='ID',
    default=defaults['cal_id']
    )
    args = parser.parse_args()
    # Now run!
    gc = Green_Calendar()
    gc._setup(notebooks=args.notebooks,
    sep=args.sep,
    sep_proc=args.sep_proc,
    max_age=args.max_age,
    cal_id=args.cal_id)
    gc.run()
  4. mcsquaredjr revised this gist Mar 20, 2013. 1 changed file with 10 additions and 3 deletions.
    13 changes: 10 additions & 3 deletions install_green_cal.py
    Original file line number Diff line number Diff line change
    @@ -1,20 +1,28 @@


    # Script to install greencal and required libraries

    import tarfile
    import shutil
    import urllib
    import requests
    import os
    import json


    ############################################################
    # INSTALL GREEN_CAL.PY #
    ############################################################
    try:
    os.mkdir('greencal')
    url = 'https://gist.github.com/mcsquaredjr/15a18fa914219c5546f9'
    r = request.get(url)
    json_url = 'https://api.github.com/gists/15a18fa914219c5546f9'
    gist_json = requests.get(json_url).text
    gist_info = json.loads(gist_json)
    files = gist_info['files']
    file_info = files.values()[0]
    filename = file_info['filename']
    content = file_info['content']

    print 'Installing green_cal.py...'
    f = open('green_cal.py', 'w')
    f.wrire(r.content)
    @@ -131,4 +139,3 @@
    editor.reload_files()

    print 'All done.'

  5. mcsquaredjr revised this gist Mar 20, 2013. 1 changed file with 1 addition and 2 deletions.
    3 changes: 1 addition & 2 deletions install_green_cal.py
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,4 @@


    # Script to install greencal and required libraries

    import tarfile
    @@ -14,7 +13,7 @@
    ############################################################
    try:
    os.mkdir('greencal')
    url = ''
    url = 'https://gist.github.com/mcsquaredjr/15a18fa914219c5546f9'
    r = request.get(url)
    print 'Installing green_cal.py...'
    f = open('green_cal.py', 'w')
  6. mcsquaredjr created this gist Mar 20, 2013.
    135 changes: 135 additions & 0 deletions install_green_cal.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,135 @@


    # Script to install greencal and required libraries

    import tarfile
    import shutil
    import urllib
    import requests
    import os


    ############################################################
    # INSTALL GREEN_CAL.PY #
    ############################################################
    try:
    os.mkdir('greencal')
    url = ''
    r = request.get(url)
    print 'Installing green_cal.py...'
    f = open('green_cal.py', 'w')
    f.wrire(r.content)
    f.close()
    shutil.move('green_cal.py', 'greencal')
    print 'green_cal.py installed.'
    except:
    pass

    ############################################################
    # INSTALL EVERNOTE SDK #
    ############################################################
    try:
    os.mkdir('evernote-sdk')
    print 'Downloading evernote...'
    filename, headers = urllib.urlretrieve('https://pypi.python.org/packages/source/e/evernote/evernote-1.23.2.tar.gz')
    print 'Installing evernote...'
    t = tarfile.open(filename, 'r')
    t.extractall()
    t.close()
    shutil.move('evernote-1.23.2/lib/evernote', 'evernote-sdk/evernote')
    shutil.move('evernote-1.23.2/lib/thrift', 'evernote-sdk/thrift')
    shutil.rmtree('evernote-1.23.2')
    print 'evernote-1.23.2 installed'

    print 'Downloading httplib2...'
    filename, headers = urllib.urlretrieve('https://pypi.python.org/packages/source/h/httplib2/httplib2-0.7.7.tar.gz')
    print 'Installing httplib2...'
    t = tarfile.open(filename, 'r')
    t.extractall()
    t.close()
    shutil.move('httplib2-0.7.7/python2/httplib2', 'evernote-sdk/httplib2')
    shutil.rmtree('httplib2-0.7.7')

    print 'Downloading oauth2...'
    filename, headers = urllib.urlretrieve('https://pypi.python.org/packages/source/o/oauth2/oauth2-1.5.211.tar.gz')
    print 'Installing oauth2...'
    t = tarfile.open(filename, 'r')
    t.extractall()
    t.close()
    shutil.move('oauth2-1.5.211/oauth2', 'evernote-sdk/oauth2')
    shutil.rmtree('oauth2-1.5.211')
    print 'oauth2-1.5.211 installed'

    except:
    pass

    ############################################################
    # INSTALL GOOGLE API #
    ############################################################
    try:
    os.mkdir('google-api')

    print 'Downloading google-api-client...'
    filename, headers = urllib.urlretrieve('https://pypi.python.org/packages/source/g/google-api-python-client/google-api-python-client-1.0.tar.gz')
    print 'Installing google-api-client...'
    t = tarfile.open(filename, 'r')
    t.extractall()
    t.close()
    shutil.move('google-api-python-client-1.0/apiclient', 'google-api/apiclient')
    shutil.move('google-api-python-client-1.0/oauth2client', 'google-api/oauth2client')
    shutil.move('google-api-python-client-1.0/uritemplate', 'google-api/uritemplate')
    shutil.rmtree('google-api-python-client-1.0')
    print 'google-api-python-client-1.0 installed.'

    print 'Downloading python-gflags...'
    filename, headers = urllib.urlretrieve('https://pypi.python.org/packages/source/p/python-gflags/python-gflags-2.0.tar.gz')
    print 'Installing python-gflags...'
    t = tarfile.open(filename, 'r')
    t.extractall()
    t.close()
    shutil.move('python-gflags-2.0/gflags.py', 'google-api/gflags.py')
    shutil.move('python-gflags-2.0/gflags2man.py', 'google-api/gflags2man.py')
    shutil.move('python-gflags-2.0/gflags_validators.py', 'google-api/gflags_validators.py')
    shutil.rmtree('python-gflags-2.0')
    print 'python-gflags-2.0 instaled.'

    print 'Downloading httplib2...'
    filename, headers = urllib.urlretrieve('https://pypi.python.org/packages/source/h/httplib2/httplib2-0.7.7.tar.gz')
    print 'Installing httplib2...'
    t = tarfile.open(filename, 'r')
    t.extractall()
    t.close()
    shutil.move('httplib2-0.7.7/python2/httplib2', 'google-api/httplib2')
    shutil.rmtree('httplib2-0.7.7')
    print 'httplib2 installed.'

    except:
    pass

    ############################################################
    # INSTALL PARSEDATETIME #
    ############################################################
    try:
    os.mkdir('parsedatetime')

    print 'Downloading parsedatetime...'
    filename, headers = urllib.urlretrieve('https://github.com/bear/parsedatetime/archive/master.tar.gz')
    print 'Installing parsedatetime...'
    t = tarfile.open(filename, 'r')
    t.extractall()
    t.close()

    shutil.move('parsedatetime-master/parsedatetime/__init__.py', 'pdt')
    shutil.move('parsedatetime-master/parsedatetime/parsedatetime.py', 'pdt')
    shutil.move('parsedatetime-master/parsedatetime/pdt_locales.py', 'pdt')
    shutil.rmtree('parsedatetime-master')
    ptint 'parsedatetime installed.'
    except:
    pass


    import editor
    editor.reload_files()

    print 'All done.'