Skip to content

Instantly share code, notes, and snippets.

@sglyon
Created January 2, 2017 17:15
Show Gist options
  • Save sglyon/aba88bb833863773c1618f726f7409a8 to your computer and use it in GitHub Desktop.
Save sglyon/aba88bb833863773c1618f726f7409a8 to your computer and use it in GitHub Desktop.
wunderlist -> todoist -- super ugly, but got the job done for me.
import json
import os
import time
from collections import OrderedDict
from contextlib import contextmanager
import wunderpy2
import todoist
import pandas as pd
def build_map(td, wl):
# map from wl_folder to td_folder
out = OrderedDict()
td_folders = api.projects.all()
for f in td:
nm = f["name"]
for f2 in wl:
if f2["title"] == nm:
out[f2["id"]] = f["id"]
continue
if len(out) != len(wl):
raise ValueError("matched {} instead of {}".format(len(out), len(td)))
return out
@contextmanager
def commit_sync(api):
api.sync()
yield
api.commit()
api.sync()
def chunks(l, n):
n = max(1, n)
return (l[i:i + n] for i in range(0, len(l), n))
# set up connection to wunderlist api
wl_id = os.environ["WL_ID"]
wl_token = os.environ["WL_TOKEN"]
wl_api = wunderpy2.WunderApi()
wl_client = wl_api.get_client(wl_token, wl_id)
# set up connection to todoist api
api_key = os.environ["TD_KEY"]
api = todoist.TodoistAPI(api_key)
api.sync();
# delete all todoist projects
projects = api.projects.all()
proj_keys = [_["id"] for _ in projects]
with commit_sync(api):
api.projects.delete(proj_keys)
# delete all todoist items
items = api.items.all()
item_keys = [_["id"] for _ in items]
for its in chunks(item_keys, 50):
with commit_sync(api):
api.items.delete(its)
time.sleep(2)
# get list of all wunderlist projects
wl_lists = wl_client.get_lists()
wl_folders = wl_client.authenticated_request("folders").json()
# map from wl_id to list of ids for all children
wl_children = {}
for f in wl_folders:
wl_children[f["id"]] = f["list_ids"]
# add folders to todoist
with commit_sync(api):
for f in wl_folders:
api.projects.add(f["title"], color=4)
# map from wl_folder to td_folder
td_folders = api.projects.all()
folder_map = build_map(td_folders, wl_folders)
# now make all the lists
with commit_sync(api):
for l in wl_lists:
api.projects.add(l["title"], color=5)
# map from wl_list to td_project
td_projects = api.projects.all()
project_map = build_map(td_projects, wl_lists)
# now update all lists so they are in the right folder
ix = 0
with commit_sync(api):
for (wl_id, td_id) in folder_map.items():
# get current parent and make sure order is set properly
td_parent = api.projects.get_by_id(td_id)
td_parent.update(item_order=ix, indent=1, color=4)
ix += 1
for child in wl_children[wl_id]:
td_child = api.projects.get_by_id(project_map[child])
td_child.update(parent_id=td_id, indent=2, item_order=ix, color=5)
ix += 1
# time to process items
for l in wl_lists:
wl_id = l["id"]
td_id = project_map[wl_id]
print("\n\n\n\n\nprocessing list {}".format(l["title"]))
# add yet-to-be-completed tasks
for done in (True, False):
for ts in chunks(wl_client.get_tasks(wl_id, completed=done), 30):
with commit_sync(api):
for t in ts:
print(" adding: {}".format(t["title"]))
data = {"project_id": td_id}
if "created_at" in t:
dd = pd.to_datetime(t["created_at"])
data.update(
{"date_added": dd.strftime("%a %d %b %Y %H:%M:%S +0000")}
)
if "due_date" in t:
dd = pd.to_datetime(t["due_date"])
data.update(
{"due_date_utc": dd.strftime("%Y-%m-%dT%H:%M")}
)
it = api.items.add(t["title"], **data)
if done:
it.update(checked=1, in_history=1)
print("sleeping for 4 seconds!!")
time.sleep(4)
print("all done!")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment