-
-
Save Terrance/0e21ef32801c846f07b28fc6fc3310e9 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3 | |
from csv import DictReader | |
from datetime import datetime | |
from dateutil.rrule import rrulestr | |
from icalendar import Alarm, Calendar, Todo, vRecur | |
PRIORITY = {"0": "0", "1": "6", "3": "5", "5": "4"} | |
STATUS = {"0": "NEEDS-ACTION", "1": "COMPLETED", "2": "COMPLETED"} | |
def date(value): | |
value = value.replace("-", "").replace(":", "").replace("+0000", "Z") | |
assert value.endswith("Z") | |
return value | |
def main(): | |
with open("backup.csv") as backup: | |
for _ in range(6): | |
next(backup) | |
reader = DictReader(backup) | |
for item in reader: | |
print(item["taskId"]) | |
uid = "{}@ticktick.com.ics".format(item["taskId"]) | |
todo = Todo() | |
todo["uid"] = uid | |
todo["created"] = datetime.utcnow().strftime("%Y%m%dT%H%M%SZ") | |
todo["summary"] = item["Title"] | |
if item["Content"]: | |
todo["description"] = item["Content"].replace("\r", "\n") | |
if item["Is Check list"]: | |
todo["description"] = todo["description"].replace("▫", "- [ ] ").replace("▪", "- [x] ") | |
if item["Start Date"]: | |
todo["dtstart"] = date(item["Start Date"]) | |
if item["Due Date"]: | |
todo["due"] = date(item["Due Date"]) | |
for repeat in item["Repeat"].rstrip().splitlines(): | |
todo.add("rrule", vRecur.from_ical(repeat)) | |
todo["priority"] = PRIORITY[item["Priority"]] | |
todo["status"] = STATUS[item["Status"]] | |
todo["dtstamp"] = date(item["Created Time"]) | |
if item["Completed Time"]: | |
todo["completed"] = date(item["Completed Time"]) | |
cal = Calendar() | |
cal.add_component(todo) | |
with open("{}@ticktick.com.ics".format(item["taskId"]), "wb") as out: | |
out.write(cal.to_ical()) | |
if __name__ == "__main__": | |
main() |
It's a dict
, that should be cals.items()
.
Wow, yeah, this code works now perfectly :)
This script creates one .ics file per list, each .ics file can be imported into Nextcloud, which in turns add the todos to the tasks app, which in turn is synced via webdav. With this, I can completely move away from ticktick without losing any current and historical todo.
Thank you, this is awesome.
Here's the working version:
#!/usr/bin/env python3
from csv import DictReader
from datetime import datetime
from dateutil.rrule import rrulestr
from icalendar import Alarm, Calendar, Todo, vRecur
import os.path
from collections import defaultdict
PRIORITY = {"0": "0", "1": "6", "3": "5", "5": "4"}
STATUS = {"0": "NEEDS-ACTION", "1": "COMPLETED", "2": "COMPLETED"}
def date(value):
value = value.replace("-", "").replace(":", "").replace("+0000", "Z")
assert value.endswith("Z")
return value
def main():
cals = defaultdict(Calendar)
with open("backup.csv") as backup:
for _ in range(6):
next(backup)
reader = DictReader(backup)
for item in reader:
uid = format(item["taskId"])
todo = Todo()
todo["uid"] = uid
todo["created"] = datetime.utcnow().strftime("%Y%m%dT%H%M%SZ")
todo["summary"] = item["Title"]
if item["Content"]:
todo["description"] = item["Content"].replace("\r", "\n")
if item["Is Check list"]:
todo["description"] = todo["description"].replace("▫", "- [ ] ").replace("▪", "- [x] ")
if item["Start Date"]:
todo["dtstart"] = date(item["Start Date"])
if item["Due Date"]:
todo["due"] = date(item["Due Date"])
for repeat in item["Repeat"].rstrip().splitlines():
todo.add("rrule", vRecur.from_ical(repeat))
todo["priority"] = PRIORITY[item["Priority"]]
todo["status"] = STATUS[item["Status"]]
todo["dtstamp"] = date(item["Created Time"])
if item["Completed Time"]:
todo["completed"] = date(item["Completed Time"])
cal = cals[item["List Name"]] # get or create a calendar for the current list
cal.add_component(todo)
for name, cal in cals.items(): # write calendars out at the end
listname = name + ".ics"
print(listname)
with open(listname, "wb") as out:
out.write(cal.to_ical())
if __name__ == "__main__":
main()
Wow, yeah, this code works now perfectly :)
This script creates one .ics file per list, each .ics file can be imported into Nextcloud, which in turns add the todos to the tasks app, which in turn is synced via webdav. With this, I can completely move away from ticktick without losing any current and historical todo. Thank you, this is awesome.
Here's the working version:
#!/usr/bin/env python3 from csv import DictReader from datetime import datetime from dateutil.rrule import rrulestr from icalendar import Alarm, Calendar, Todo, vRecur import os.path from collections import defaultdict PRIORITY = {"0": "0", "1": "6", "3": "5", "5": "4"} STATUS = {"0": "NEEDS-ACTION", "1": "COMPLETED", "2": "COMPLETED"} def date(value): value = value.replace("-", "").replace(":", "").replace("+0000", "Z") assert value.endswith("Z") return value def main(): cals = defaultdict(Calendar) with open("backup.csv") as backup: for _ in range(6): next(backup) reader = DictReader(backup) for item in reader: uid = format(item["taskId"]) todo = Todo() todo["uid"] = uid todo["created"] = datetime.utcnow().strftime("%Y%m%dT%H%M%SZ") todo["summary"] = item["Title"] if item["Content"]: todo["description"] = item["Content"].replace("\r", "\n") if item["Is Check list"]: todo["description"] = todo["description"].replace("▫", "- [ ] ").replace("▪", "- [x] ") if item["Start Date"]: todo["dtstart"] = date(item["Start Date"]) if item["Due Date"]: todo["due"] = date(item["Due Date"]) for repeat in item["Repeat"].rstrip().splitlines(): todo.add("rrule", vRecur.from_ical(repeat)) todo["priority"] = PRIORITY[item["Priority"]] todo["status"] = STATUS[item["Status"]] todo["dtstamp"] = date(item["Created Time"]) if item["Completed Time"]: todo["completed"] = date(item["Completed Time"]) cal = cals[item["List Name"]] # get or create a calendar for the current list cal.add_component(todo) for name, cal in cals.items(): # write calendars out at the end listname = name + ".ics" print(listname) with open(listname, "wb") as out: out.write(cal.to_ical()) if __name__ == "__main__": main()
how do you use it? I just copied it into a py script
Ok, I tried to adapt your snippet to the rest of your python script, but the code below throws an error:
I get the following result: