Skip to content

Commit fc30d4f

Browse files
committed
Add example script for reading events in iCal format and posting to Spond
1 parent 720acea commit fc30d4f

File tree

1 file changed

+116
-0
lines changed

1 file changed

+116
-0
lines changed

postics.py

+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
#!/usr/bin/env python
2+
3+
import argparse
4+
import asyncio
5+
6+
import ics
7+
8+
from config import password, username
9+
from spond import spond
10+
11+
DESCRIPTION = """
12+
Read in iCal events from .ics file[s] and post them to Spond.
13+
""".strip()
14+
15+
16+
def ics2spond(event):
17+
"""Create Spond event dictionary from ics.Event"""
18+
19+
return {
20+
"heading": event.name,
21+
"description": event.description,
22+
"startTimestamp": event.begin.isoformat(),
23+
"endTimestamp": event.end.isoformat(),
24+
"location": {"feature": event.location},
25+
}
26+
27+
28+
async def post_events(args, gid=None, owners=[]):
29+
"""
30+
Read Calendar from .ics file[s] and post all events to Spond.
31+
32+
Parameters
33+
----------
34+
args : argparse.Namespace
35+
Command line arguments and options returned by ArgumentParser.parse_args(),
36+
containing options and file name[s] (wildcards supported).
37+
gid : str
38+
'id' of Spond group to post to (default: first group from `get_groups()` for user).
39+
owners : list
40+
list of user's {'id': uid} (default: [user] from `config.username`).
41+
"""
42+
43+
s = spond.Spond(username=username, password=password)
44+
45+
if len(owners) == 0:
46+
user = await s.get_person(username)
47+
owners = [user["profile"]]
48+
49+
if gid is None:
50+
groups = await s.get_groups()
51+
for mygroup in groups:
52+
if mygroup["contactPerson"]["id"] == owners[0]["id"]:
53+
break
54+
else:
55+
raise ValueError(f"No group with contact person {owners[0]['id']} found")
56+
recipients = {"group": mygroup}
57+
else:
58+
recipients = {"group": {"id": gid}}
59+
60+
if not args.quiet:
61+
print(f"Posting as {username} ({owners[0]['id']}): {recipients['group']['id']}")
62+
63+
for filename in args.filename: # Support wildcards
64+
if not args.quiet:
65+
print(f"Reading {filename}:")
66+
calendar = ics.Calendar(open(filename).read())
67+
for event in calendar.events:
68+
updates = {"owners": owners, "recipients": recipients}
69+
updates.update(ics2spond(event))
70+
uid = getattr(event, "uid", "")
71+
if args.verbose:
72+
print(event.serialize())
73+
elif not args.quiet:
74+
print(event.name)
75+
events = await s.update_event(uid, updates)
76+
await s.clientsession.close()
77+
78+
79+
def main(args=None):
80+
"""The main function called by the `postics` script."""
81+
parser = argparse.ArgumentParser(
82+
description=DESCRIPTION, formatter_class=argparse.RawDescriptionHelpFormatter
83+
)
84+
# parser.add_argument("--version", action="version", version=f"%(prog)s {__version__}")
85+
parser.add_argument(
86+
"-v",
87+
"--verbose",
88+
default=False,
89+
action="store_true",
90+
help="verbose mode; echo full iCal events parsed",
91+
)
92+
parser.add_argument(
93+
"-q",
94+
"--quiet",
95+
default=False,
96+
action="store_true",
97+
help="quiet mode; do not echo iCal event names",
98+
)
99+
parser.add_argument(
100+
"-g", "--gid", default=None, help="specify Spond group ID of recipients group"
101+
)
102+
parser.add_argument(
103+
"filename",
104+
nargs="+",
105+
help="Path to one or more ics files; wildcards are supported",
106+
)
107+
108+
args = parser.parse_args(args)
109+
110+
loop = asyncio.new_event_loop()
111+
asyncio.set_event_loop(loop)
112+
asyncio.run(post_events(args, gid=args.gid))
113+
114+
115+
if __name__ == "__main__":
116+
main()

0 commit comments

Comments
 (0)