Skip to content

Instantly share code, notes, and snippets.

@chrisroos
Last active November 8, 2018 19:24
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save chrisroos/a1f7d5cea46844839f4c to your computer and use it in GitHub Desktop.
Save chrisroos/a1f7d5cea46844839f4c to your computer and use it in GitHub Desktop.
Exploring Todoist's API

The todoist.rb script uses their API to print a list of all my completed tasks in CSV format.

The standard Todoist backup doesn't contain completed tasks.

require 'json'
require 'logger'
require 'csv'
LOGGER = Logger.new('todoist.log')
def get_api_token(email, password)
cmd = %(curl https://todoist.com/API/v6/login \
-d email="#{email}" \
-d password="#{password}" \
--silent)
json_response = `#{cmd}`
response = JSON.parse(json_response)
response['api_token']
end
def get_productivity_stats(api_token)
cmd = %(curl https://todoist.com/API/v6/get_productivity_stats \
-d token="#{api_token}" \
--silent)
json_response = `#{cmd}`
JSON.parse(json_response)
end
def get_completed_tasks(api_token, limit, offset)
cmd = %(curl https://todoist.com/API/v6/get_all_completed_items -X GET \
-d token=#{api_token} \
-d limit=#{limit} \
-d offset=#{offset} \
--silent)
json_response = `#{cmd}`
response = JSON.parse(json_response)
response['items']
end
def get_all_completed_tasks(api_token)
limit, offset = 50, 0
all_tasks, tasks = [], []
while offset == 0 || tasks.any?
LOGGER.info "Getting tasks #{offset} to #{offset + limit}"
tasks = get_completed_tasks(api_token, limit, offset)
all_tasks += tasks
offset = offset + limit
end
all_tasks
end
email = '<email>'
password = '<password>'
api_token = get_api_token(email, password)
stats = get_productivity_stats(api_token)
LOGGER.info "Number of completed tasks: #{stats['completed_count']}"
tasks = get_all_completed_tasks(api_token)
headers = %w(user_id project_id id task_id content note_count meta_data completed_date)
puts headers.to_csv
tasks.each do |task|
row = headers.map { |header| task[header] }
puts row.to_csv
end
# /get_all_completed_items
# By default returns the 30 most recent completed items
# Using the `limit` parameter allows me to retrieve up to 50 completed items
# Specifying a `limit` of more than 50 has no effect - it'll still only return 50 items
# I can use `from_date` and `to_date` to restrict the results to a date range
# The arguments are the opposite way round to what I'd expect
# `from_date` is the latest date you want to consider
# `to_date` is the earliest date you want to consider
__END__
# seq_no = 0
# seq_no_global = 0
# cmd = %(curl https://todoist.com/API/v6/sync -X GET \
# -d token=#{api_token} \
# -d seq_no=#{seq_no} \
# -d seq_no_global="#{seq_no_global}" \
# -d resource_types='["items"]' \
# --silent)
# json_response = `#{cmd}`
# response = JSON.parse(json_response)
# p seq_no_global = response['seq_no_global']
# p seq_no = response['seq_no']
# response['Items'].each do |item|
# # headers = %w()
# # csv = CSV.new(headers, values)
# # puts item.to_csv
# p [item['is_history'], item['is_archived']]
# end
#
# cmd = %(curl https://todoist.com/API/v6/sync -X GET \
# -d token=#{api_token} \
# -d seq_no="#{seq_no}" \
# -d seq_no_global="#{seq_no_global}" \
# -d resource_types='["items"]' \
# --silent)
# json_response = `#{cmd}`
# response = JSON.parse(json_response)
# seq_no_global = response['seq_no_global']
# seq_no = response['seq_no']
# p response
# p response['Items'].length
{"due_date"=>nil, "day_order"=>-1, "assigned_by_uid"=>2028296, "due_date_utc"=>nil, "is_archived"=>0, "labels"=>[], "sync_id"=>nil, "in_history"=>0, "date_added"=>"Thu 30 Oct 2014 10:37:41 +0000", "checked"=>0, "date_lang"=>"en", "id"=>40124258, "content"=>"Cancel my Pingdom account", "indent"=>1, "user_id"=>2028296, "is_deleted"=>0, "priority"=>1, "item_order"=>1, "responsible_uid"=>nil, "project_id"=>130983902, "collapsed"=>0, "date_string"=>""}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment