Parent:
[f344e8]
(diff)
Download this file
rclics
173 lines (145 with data), 5.6 kB
#!/usr/bin/env python2
from __future__ import print_function
# Read an ICS file, break it into "documents" which are events, todos,
# or journal entries, and interface with recoll execm
#
# For historical reasons, this can use either the icalendar or the
# vobject Python modules, or an internal splitter. The default is now
# to use the internal splitter, the other modules are more trouble
# than they're worth (to us and until we will want to get into date
# computations etc.)
import rclexecm
import sys
# Decide how we'll process the file.
modules = ("internal", "icalendar", "vobject")
usemodule = "internal"
forcevobject = 0
if usemodule != "internal":
try:
if forcevobject:
raise Exception
from icalendar import Calendar, Event
usemodule = "icalendar"
except:
try:
import vobject
usemodule = "vobject"
except:
print("RECFILTERROR HELPERNOTFOUND python:icalendar")
print("RECFILTERROR HELPERNOTFOUND python:vobject")
sys.exit(1);
class IcalExtractor:
def __init__(self, em):
self.file = ""
self.contents = []
self.em = em
def extractone(self, index):
if index >= len(self.contents):
return(False, "", "", True)
docdata = self.contents[index]
#self.em.rclog(docdata)
iseof = rclexecm.RclExecM.noteof
if self.currentindex >= len(self.contents) -1:
iseof = rclexecm.RclExecM.eofnext
self.em.setmimetype("text/plain")
return (True, docdata, str(index), iseof)
###### File type handler api, used by rclexecm ---------->
def openfile(self, params):
self.file = params["filename:"]
try:
calstr = open(self.file, "rb")
except Exception as e:
self.em.rclog("Openfile: open: %s" % str(e))
return False
self.currentindex = -1
if usemodule == "internal":
self.contents = ICalSimpleSplitter().splitcalendar(calstr)
elif usemodule == "icalendar":
try:
cal = Calendar.from_string(calstr.read())
except Exception as e:
self.em.rclog("Openfile: read or parse error: %s" % str(e))
return False
self.contents = cal.walk()
self.contents = [item.as_string() for item in self.contents
if (item.name == "VEVENT" or item.name == "VTODO"
or item.name == "VJOURNAL")]
else:
try:
cal = vobject.readOne(calstr)
except Exception as e:
self.em.rclog("Openfile: cant parse object: %s" % str(e))
return False
for lstnm in ("vevent_list", "vtodo_list", "vjournal_list"):
lst = getattr(cal, lstnm, [])
for ev in lst:
self.contents.append(ev.serialize())
#self.em.rclog("openfile: Entry count: %d"%(len(self.contents)))
return True
def getipath(self, params):
try:
if params["ipath:"] == b'':
index = 0
else:
index = int(params["ipath:"])
except:
return (False, "", "", True)
return self.extractone(index)
def getnext(self, params):
if self.currentindex == -1:
# Return "self" doc
self.currentindex = 0
self.em.setmimetype(b'text/plain')
if len(self.contents) == 0:
eof = rclexecm.RclExecM.eofnext
else:
eof = rclexecm.RclExecM.noteof
return (True, "", "", eof)
if self.currentindex >= len(self.contents):
self.em.rclog("getnext: EOF hit")
return (False, "", "", rclexecm.RclExecM.eofnow)
else:
ret= self.extractone(self.currentindex)
self.currentindex += 1
return ret
# Trivial splitter: cut objects on BEGIN/END (only for 'interesting' objects)
# ignore all other syntax
class ICalSimpleSplitter:
# Note that if an 'interesting' element is nested inside another one,
# it will not be extracted (stay as text in external event). This is
# not an issue and I don't think it can happen with the current list
interesting = (b'VTODO', b'VEVENT', b'VJOURNAL')
def splitcalendar(self, fin):
curblkname = b''
curblk = b''
lo = []
for line in fin:
line = line.rstrip()
if line == b'':
continue
if curblkname:
curblk = curblk + line + b'\n'
l = line.split(b':')
if len(l) < 2:
continue
# If not currently inside a block and we see an
# 'interesting' BEGIN, start block
if curblkname == b'' and l[0].upper() == b'BEGIN':
name = l[1].upper()
if name in ICalSimpleSplitter.interesting:
curblkname = name
curblk = curblk + line + b'\n'
# If currently accumulating block lines, check for end
if curblkname and l[0].upper() == b'END' and \
l[1].upper() == curblkname:
lo.append(curblk)
curblkname = b''
curblk = b''
if curblk:
lo.append(curblk)
curblkname = b''
curblk = b''
return lo
proto = rclexecm.RclExecM()
extract = IcalExtractor(proto)
rclexecm.main(proto, extract)