From 1f0732c963033d099fa3e6794422035737234614 Mon Sep 17 00:00:00 2001 From: Andrew Williams Date: Sun, 7 Oct 2012 19:34:11 +0100 Subject: [PATCH] Initial commit --- .gitignore | 3 ++ evecal.py | 88 ++++++++++++++++++++++++++++++++++++++++++++++++ reqirements.txt | 3 ++ scripts/evetoics | 46 +++++++++++++++++++++++++ setup.py | 14 ++++++++ 5 files changed, 154 insertions(+) create mode 100644 .gitignore create mode 100644 evecal.py create mode 100644 reqirements.txt create mode 100755 scripts/evetoics create mode 100644 setup.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7259378 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.pyc +env +build diff --git a/evecal.py b/evecal.py new file mode 100644 index 0000000..3698cc0 --- /dev/null +++ b/evecal.py @@ -0,0 +1,88 @@ +from datetime import datetime, timedelta +from logging import getLogger +from HTMLParser import HTMLParser +from icalendar import Calendar, Event +from eveapi import EVEAPIConnection, Error + +api = EVEAPIConnection() + + +def mask_check(accessmask, bit): + """Returns a bool indicating if the bit is set in the accessmask""" + mask = 1 << bit + return (accessmask & mask) > 0 + + +class EVEEvent(Event): + """Represents a EVE Event, a subclassed iCal event""" + + @staticmethod + def from_eveapi(tree): + event = EVEEvent() + h = HTMLParser() + + startdate = datetime.fromtimestamp(tree.eventDate) + if tree.duration > 0: + enddate = startdate + timedelta(minutes=tree.duration) + else: + enddate = None + + event['uid'] = '%s@api.eveonline.com' % tree.eventID + event.add('summary', tree.eventTitle) + event.add('description', h.unescape(tree.eventText)) + event.add('dtstart', startdate) + if enddate: + event.add('dtend', enddate) + if tree.duration > 0: + event.add('duration', timedelta(minutes=tree.duration)) + event.add('organiser', tree.ownerName) + + return event + + +class EVECal(Calendar): + """Represents a EVE Calendar from the API""" + + _auth = None + _calendar = None + log = getLogger(__name__) + + def __init__(self, keyID, vCode, characterID, **kwargs): + super(EVECal, self).__init__(self, **kwargs) + self.add('prodid', '-//EVECalICS//') + self.add('version', '2.0') + self._auth = api.auth(keyID=keyID, vCode=vCode) + self._characterID = characterID + + def _check_access(self): + """Checks if the provided API key has access to the calendar""" + + if self._auth: + try: + doc = self._auth.account.ApiKeyInfo() + except Error as e: + self.log.error('Error checking API Key: %s' % e) + pass + else: + return mask_check(doc.key.accessMask, 20) + return False + + def _generate_calendar(self): + + if not self._check_access(): + self.log.error('Key does not have access to UpcomingCalendarEvents') + return False + + try: + doc = self._auth.char.UpcomingCalendarEvents(characterID=self._characterID) + except Error as e: + self.log('Error retreiving UpcomingCalendarEvents: %s' % e) + return False + + for event in doc.upcomingEvents: + self.add_component(EVEEvent.from_eveapi(event)) + + def as_string(self): + if not len(self.subcomponents): + self._generate_calendar() + return super(EVECal, self).as_string() diff --git a/reqirements.txt b/reqirements.txt new file mode 100644 index 0000000..bc87e7c --- /dev/null +++ b/reqirements.txt @@ -0,0 +1,3 @@ +argparse +icalendar +-e git+git://github.com/ntt/eveapi.git#egg=eveapi diff --git a/scripts/evetoics b/scripts/evetoics new file mode 100755 index 0000000..4eec20d --- /dev/null +++ b/scripts/evetoics @@ -0,0 +1,46 @@ +#!/usr/bin/env python + +import os +import sys +import logging +import argparse +from ConfigParser import ConfigParser +from evecal import EVECal + +def main(): + + parser = argparse.ArgumentParser(description='Convert EVE API Calendar to iCal format') + parser.add_argument('-k', '--keyid', help='EVE API Key ID') + parser.add_argument('-v', '--vcode', help='EVE API Verification Code') + parser.add_argument('-c', '--character', help='Character ID of the calander you wish to export') + parser.add_argument('--config', help='Configuration file', default='~/.evetoics.conf') + args = parser.parse_args() + + if not args.config and (not args.keyid or not args.vcode or not args.character): + print >> sys.stderr, 'You did not provide either a Key, vCode, or character ID' + return -1 + elif args.config: + file = os.path.abspath(os.path.expanduser(args.config)) + if os.path.exists(file): + config = ConfigParser() + config.read(file) + keyid = config.get('evetoics', 'keyid') + vcode = config.get('evetoics', 'vcode') + character = config.get('evetoics', 'character') + else: + print >> sys.stderr, 'Invalid configuration file provided: %s' % args.config + return -1 + else: + keyid = args.keyid + vcode = args.vcode + character = args.character + + logging.basicConfig(level=logging.INFO) + print keyid, vcode, character + c = EVECal(keyID=keyid, vCode=vcode, characterID=character) + print c.as_string() + return 0 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..1a9ccdc --- /dev/null +++ b/setup.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python + +from distutils.core import setup + +setup(name = "evecal", + version = '0.1', + description = "EVE API Calendar abstraction library", + author = "Andrew Williams", + author_email = "andy@tensixtyone.com", + url = "https://github.com/nikdoof/evecal/", + keywords = "eve api eveonline calendar ics", + py_modules = ['evecal',], + scripts = ['scripts/evetoics'], +)