-
-
Save notconfusing/68c84868098dcaa04e44522bebb77638 to your computer and use it in GitHub Desktop.
Converting Remember-the-milk tasks (ICS) to a Todoist template (CSV)
This file contains 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
#!/usr/bin/env python | |
# coding: utf-8 | |
# whereas the original rtm2todoist.py[1] worked off the .ics export, this version uses the more modern .json export | |
# [1] https://gist.github.com/notconfusing/68c84868098dcaa04e44522bebb77638 | |
import json | |
import pandas as pd | |
import datetime | |
# todo add commandline interface to make this a parameter. Use click? | |
# requires 'in' and 'out' paths in directior #todo automatically make the paths | |
f = open('in/rememberthemilk_export_2022-05-13T17 53 48.222Z.json', 'r') | |
d = json.load(f) | |
config = d['config'] | |
lists = d['lists'] | |
tasks = d['tasks'] | |
notes = d['notes'] | |
def insert_section_heading(section_name, df): | |
"""insert a row with "TYPE"="seciton" CONTENT="section_name" """ | |
section_insert = pd.DataFrame({'TYPE': 'section', 'CONTENT': section_name}, index=[0]) | |
first_section_index = df.list_name.eq(section_name).idxmax() | |
first_section_loc = df.index.get_loc(first_section_index) | |
head = df[:first_section_loc] | |
tail = df[first_section_loc:] | |
section_inserted_df = pd.concat(objs=[head, section_insert, tail]) | |
print(f'Section {section_name}, first loc {first_section_loc}') | |
print(f'length before {len(df)}, length after {len(section_inserted_df)}') | |
return section_inserted_df | |
def insert_section_headings(df): | |
ordered_df = df.sort_values('list_name') | |
all_list_names = ordered_df['list_name'].unique() | |
for list_name in all_list_names: | |
ordered_df = insert_section_heading(list_name, ordered_df) | |
return ordered_df | |
uncompleted_tasks = [t for t in tasks if 'date_completed' not in t.keys()] | |
lists_id_name = {listobj['id']: listobj['name'] for listobj in lists} | |
df = pd.DataFrame.from_records(uncompleted_tasks) | |
df['list_name'] = df['list_id'].apply(lambda lid: lists_id_name[lid]) | |
df = df.sort_values('series_id') | |
# https://todoist.com/help/articles/how-to-format-your-csv-file-so-you-can-import-it-into-todoist | |
# - "TYPE CONTENT PRIORITY INDENT AUTHOR RESPONSIBLE DATE DATE_LANG TIMEZONE" | |
# uncompleted-only tasks | |
df['TYPE'] = 'task' # - type = 'task', 'section', 'note' | |
df['CONTENT'] = df['name'] | |
df['DESCRIPTION'] = df['url'] | |
df['PRIORTITY'] = df['priority'].apply(lambda p: 2 if p == 'PN' else p) # not sure exactly what this PN means | |
df['INDENT'] = df['parent_id'].apply(lambda pid: 1 if pd.isna(pid) else 2) # todo understand more about series_id | |
df['AUTHOR'] = '' # todo get from config | |
df['RESPONSIBLE'] = '' # todo get from config | |
df['DATE'] = df['date_due'].apply(lambda dd: datetime.datetime.utcfromtimestamp(dd / 1000.0) if pd.notna(dd) else '') | |
df['DATE_LANG'] = 'en' # todo get from config | |
df['TIMEZONE'] = 'US/Pacific' # todo get from config | |
sectioned_df = insert_section_headings(df) | |
sectioned_df.to_csv('out/todoist_sections.csv') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment