commit 9325442532283a59d47fc768b8ea7a1331e1c88e
parent 49ebb3884d0ce41e0d4c7151c2dcbece6ce64558
Author: Matthias Balk <mbalk@mbalk.de>
Date: Sun, 16 Sep 2018 19:40:08 +0200
Using "vobject" instead of "ical2vcal"
Further improvements:
- configuration file
- `create-appointment.py` for creation of events
Diffstat:
| M | README.rst | | | 32 | +++++++++++--------------------- |
| A | config.py | | | 12 | ++++++++++++ |
| A | create-appointment.py | | | 66 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | ya3 | | | 68 | ++++++++++++++++++++++++++++++++++---------------------------------- |
4 files changed, 123 insertions(+), 55 deletions(-)
diff --git a/README.rst b/README.rst
@@ -4,48 +4,38 @@ ya3 -- yet another appointment application
ya3 wants to be a simple tool helping you to organise your appointments. It is
far away from being finished.
-ya3 uses Charl Botha's ical2vcal to read and write calendar files (vCal). See
-http://cpbotha.net/2007/04/26/google-calendar-to-palm-desktop-conversion/ and
-http://code.google.com/p/ical2vcal/ for more information.
-
For licensing information see LICENSE.txt .
Features
~~~~~~~~
- Reading all vCal files from a directory and spit out appointments of the next
few days on stdout.
+- Creation of new appointments
Features to be implemented
~~~~~~~~~~~~~~~~~~~~~~~~~~
-- Create new appointments.
-- Change existing appointments.
-- Delete appointments.
- Support for recurrence (like birthdays).
- ...
+Requirements
+~~~~~~~~~~~~
+- Python3 (and Python2!!! :-o)
+- Python dateutil
+- Python vobject
+
Installation and setup
~~~~~~~~~~~~~~~~~~~~~~
-First of all, python is needed.
-
-Second, get ya3 via git:
+Get ya3 and place it where you like:
$ cd /path/where/ya3/shall/be/put
$ git pull .... ya3
-Third, get ical2vcal via svn:
-$ cd ya3/ical2vcal
-$ svn checkout http://ical2vcal.googlecode.com/svn/trunk/ .
-ACHTUNG: URL veraltet. Siehe https://code.google.com/archive/p/ical2vcal/
-
-Fourth, copy and edit configuration (not yet implemented):
-$ mkdir -p -m 0700 $HOME/.ya3/calendars
-$ cp /path/where/ya3/shall/be/put/ya3/config.template $HOME/.ya3/
+Edit configuration in config.py to fit your needs.
Usage
~~~~~
-$ ya3 <vcal file>
+$ create-appointment.py
-Future plans:
-$ ya3 -g [date from[-date to]]
+$ ya3 <vcal file>
Example
~~~~~~~
diff --git a/config.py b/config.py
@@ -0,0 +1,12 @@
+from datetime import timedelta
+from os import path
+
+CAL_DIR = path.expanduser('~/.ya3/calendars/')
+
+DEFAULTS = {
+ 'LOCATION': 'Besprechungsraum',
+ 'SUMMARY': 'Meeting'
+}
+
+MAX_AGE = timedelta(days=1)
+MAX_AHEAD = timedelta(days=14)
diff --git a/create-appointment.py b/create-appointment.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python3
+
+import os
+import re
+import time
+import uuid
+from collections import OrderedDict
+from datetime import datetime
+
+from dateutil.parser import parse
+
+import config
+
+
+def localtime2utc(datetimestr):
+ local = parse('%s %s' % (datetimestr, time.tzname[0]))
+ return local - local.utcoffset()
+
+
+def get_input(key):
+ if key in config.DEFAULTS:
+ i = input('%s: [%s] ' % (key, config.DEFAULTS[key]))
+ return i if i.strip() is not '' else config.DEFAULTS[key]
+ return input('%s: ' % key)
+
+
+def create_event():
+ event = OrderedDict([
+ ('BEGIN', 'VEVENT'),
+ ('DTSTART', None),
+ ('DTEND', None),
+ ('LOCATION', None),
+ ('SUMMARY', None),
+ ('UID', str(uuid.uuid4())),
+ ('END', 'VEVENT'),
+ ])
+
+ for key in ['DTSTART', 'DTEND', 'LOCATION', 'SUMMARY']:
+ event[key] = get_input(key)
+ if re.match('DT', key):
+ event[key] = localtime2utc(event[key])
+
+ return event
+
+
+def event2file(event):
+ filename = '%s-%s.ics' % (event['DTSTART'].strftime('%Y-%m-%d'),
+ re.sub(r'\s+', '-', event['SUMMARY'].lower()))
+ f = open(os.path.join(config.CAL_DIR, filename), 'w')
+ f.write('BEGIN:VCALENDAR\nVERSION:2.0\n')
+ f.write('PRODID://ya3//yet another appointment application//\n')
+
+ def item2str(key, value):
+ if isinstance(value, datetime):
+ return '%s:%s\n' % (key, value.strftime('%Y%m%dT%H%M%SZ'))
+ return '%s:%s\n' % (key, value)
+
+ for key in event:
+ f.write(item2str(key, event[key]))
+
+ f.write('END:VCALENDAR\n')
+ f.close()
+
+
+event = create_event()
+event2file(event)
diff --git a/ya3 b/ya3
@@ -1,42 +1,42 @@
#!/usr/bin/env python
-# -*- coding: utf-8 -*-
"""ya3 -- yet another appointment application"""
import sys
-import time
-from ical2vcal import vcal
+from datetime import datetime
+
+import config
+import vobject
+from dateutil.tz import gettz
+
+
+def conv2local(dt):
+ if dt.tzinfo is None:
+ return datetime(dt.year, dt.month, dt.day,
+ dt.hour, dt.minute, dt.second,
+ tzinfo=gettz())
+ return dt.astimezone(gettz())
+
def print_events(icsfilename):
"""foo"""
- try:
- cal = vcal.parse(icsfilename)
- for event in cal.events:
- try:
- start = time.strptime(event.dtstart, '%Y%m%dT%H%M%S')
- except ValueError:
- start = time.strptime(event.dtstart, '%Y%m%d')
-
- try:
- end = time.strptime(event.dtend, '%Y%m%dT%H%M%S')
- except ValueError:
- end = time.strptime(event.dtend, '%Y%m%d')
-
- try:
- location = " (" + event.location + ")"
- except AttributeError:
- location = ""
-
- if start >= time.localtime(time.time() - 86400) and \
- start < time.localtime(time.time() + 14 * 86400):
- print time.strftime('%Y-%m-%d %H:%M', start) + " - " + \
- time.strftime('%H:%M', end) + " " + event.summary + \
- location
- #start = vcal.parsetime(event.dtstart)
- #print start
- return True
-
- except vcal.ParseError:
- return False
-
-for filename in sys.argv:
+
+ f = open(icsfilename)
+ for event in vobject.readComponents(f):
+ start = conv2local(event.vevent.dtstart.value)
+ end = conv2local(event.vevent.dtend.value)
+
+ try:
+ location = " (" + event.vevent.location.value + ")"
+ except AttributeError:
+ location = ""
+
+ if start >= datetime.now(gettz()) - config.MAX_AGE and \
+ start < datetime.now(gettz()) + config.MAX_AHEAD:
+ print('%s - %s %s%s' % (start.strftime('%Y-%m-%d %H:%M'),
+ end.strftime('%H:%M'),
+ event.vevent.summary.value,
+ location))
+
+
+for filename in sys.argv[1:]:
print_events(filename)