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"=>""} |