Created
January 2, 2017 17:15
-
-
Save sglyon/aba88bb833863773c1618f726f7409a8 to your computer and use it in GitHub Desktop.
wunderlist -> todoist -- super ugly, but got the job done for me.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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