todoist-ruby 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +201 -0
- data/Rakefile +20 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/fixtures/.gitignore +6 -0
- data/fixtures/uuid/.gitignore +4 -0
- data/fixtures/vcr_cassettes/.gitignore +4 -0
- data/lib/todoist.rb +23 -0
- data/lib/todoist/misc/activity.rb +51 -0
- data/lib/todoist/misc/backups.rb +13 -0
- data/lib/todoist/misc/completed.rb +34 -0
- data/lib/todoist/misc/items.rb +55 -0
- data/lib/todoist/misc/projects.rb +31 -0
- data/lib/todoist/misc/query.rb +30 -0
- data/lib/todoist/misc/quick.rb +15 -0
- data/lib/todoist/misc/templates.rb +29 -0
- data/lib/todoist/misc/uploads.rb +28 -0
- data/lib/todoist/misc/user.rb +16 -0
- data/lib/todoist/sync/filters.rb +44 -0
- data/lib/todoist/sync/items.rb +107 -0
- data/lib/todoist/sync/labels.rb +39 -0
- data/lib/todoist/sync/notes.rb +32 -0
- data/lib/todoist/sync/projects.rb +56 -0
- data/lib/todoist/sync/reminders.rb +36 -0
- data/lib/todoist/util/api_helper.rb +89 -0
- data/lib/todoist/util/command_synchronizer.rb +54 -0
- data/lib/todoist/util/config.rb +78 -0
- data/lib/todoist/util/network_helper.rb +100 -0
- data/lib/todoist/util/parse_helper.rb +62 -0
- data/lib/todoist/util/uuid.rb +17 -0
- data/lib/todoist/version.rb +3 -0
- data/todoist.gemspec +44 -0
- metadata +227 -0
@@ -0,0 +1,13 @@
|
|
1
|
+
module Todoist
|
2
|
+
module Misc
|
3
|
+
class Backups
|
4
|
+
include Todoist::Util
|
5
|
+
|
6
|
+
# Returns the backups for a user.
|
7
|
+
def get()
|
8
|
+
result = NetworkHelper.getResponse(Config::TODOIST_BACKUPS_GET_COMMAND, {})
|
9
|
+
ParseHelper.make_objects_as_array(result)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Todoist
|
2
|
+
module Misc
|
3
|
+
class Completed
|
4
|
+
include Todoist::Util
|
5
|
+
|
6
|
+
# Get productivity stats. Returns a hash of statistics as documented
|
7
|
+
# at https://developer.todoist.com/#get-productivity-stats
|
8
|
+
def get_productivity_stats()
|
9
|
+
NetworkHelper.getResponse(Config::TODOIST_COMPLETED_GET_STATS_COMMAND)
|
10
|
+
end
|
11
|
+
|
12
|
+
# Retrieves all completed items as documented at
|
13
|
+
# https://developer.todoist.com/#get-all-completed-items. Several parameters
|
14
|
+
# are possible to limit scope. See link. Dates should be passed
|
15
|
+
# as DateTime. This method takes care of the formatting to send to the
|
16
|
+
# API. Returns projects and items back as :items and :projects keys.
|
17
|
+
|
18
|
+
def get_all_completed_items(params = {})
|
19
|
+
if params["until"]
|
20
|
+
params["until"] = ParseHelper.formatTime(params["until"])
|
21
|
+
end
|
22
|
+
if params["since"]
|
23
|
+
params["since"] = ParseHelper.formatTime(params["since"])
|
24
|
+
end
|
25
|
+
|
26
|
+
result = NetworkHelper.getResponse(Config::TODOIST_COMPLETED_GET_ALL_COMMAND, params)
|
27
|
+
items = ParseHelper.make_objects_as_array(result["items"])
|
28
|
+
projects = ParseHelper.make_objects_as_array(result["projects"])
|
29
|
+
return {"items" => items, "projects" => projects}
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Todoist
|
2
|
+
module Misc
|
3
|
+
class Items
|
4
|
+
include Todoist::Util
|
5
|
+
|
6
|
+
# Add a new task to a project. Note, that this is provided as a
|
7
|
+
# helper method, a shortcut, to quickly add a task without going
|
8
|
+
# through the Sync workflow.
|
9
|
+
# This method takes content as well as an array of optional params as
|
10
|
+
# detailed here: https://developer.todoist.com/#add-item.
|
11
|
+
#
|
12
|
+
# If adding labels, use the key "labels" and input an array of label
|
13
|
+
# objects. For project, add a project object.
|
14
|
+
#
|
15
|
+
# Critically, collaboration features are not supported by this library
|
16
|
+
# so assigned_by_uid and responsible_uid are not implemented.
|
17
|
+
|
18
|
+
def add_item(content, optional_params = {})
|
19
|
+
params = {content: content}
|
20
|
+
if optional_params["project"]
|
21
|
+
params["project_id"] = project.id
|
22
|
+
optional_params.delete("project")
|
23
|
+
end
|
24
|
+
|
25
|
+
if optional_params["labels"]
|
26
|
+
labels = optional_params["labels"]
|
27
|
+
labels_param = labels.collect { |label| label.id }
|
28
|
+
params["labels"] = labels_param.to_json
|
29
|
+
optional_params.delete("labels")
|
30
|
+
end
|
31
|
+
|
32
|
+
params.merge(optional_params)
|
33
|
+
result = NetworkHelper.getResponse(Config::TODOIST_ITEMS_ADD_COMMAND, params)
|
34
|
+
item = ParseHelper.make_object(result)
|
35
|
+
return item
|
36
|
+
end
|
37
|
+
|
38
|
+
# This function is used to extract detailed information about the item,
|
39
|
+
# including all the notes. It’s especially important, because on initial
|
40
|
+
# load we return back no more than 10 last notes.
|
41
|
+
#
|
42
|
+
# For more information see: https://developer.todoist.com/#get-item-info
|
43
|
+
def get_item(item, all_data = true)
|
44
|
+
params = {item_id: item.id, all_data: all_data}
|
45
|
+
|
46
|
+
result = NetworkHelper.getResponse(Config::TODOIST_ITEMS_GET_COMMAND, params)
|
47
|
+
item = ParseHelper.make_object(result["item"])
|
48
|
+
project = ParseHelper.make_object(result["project"])
|
49
|
+
notes = result["notes"] ? ParseHelper.make_objects_as_array(result["notes"]) : nil
|
50
|
+
return {"item" => item, "project" => project, "notes" => notes}
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Todoist
|
2
|
+
module Misc
|
3
|
+
class Projects
|
4
|
+
include Todoist::Util
|
5
|
+
|
6
|
+
# Get archived projects. Returns projects as documented here.
|
7
|
+
def get_archived_projects()
|
8
|
+
result = NetworkHelper.getResponse(Config::TODOIST_PROJECTS_GET_ARCHIVED_COMMAND)
|
9
|
+
return ParseHelper.make_objects_as_array(result)
|
10
|
+
end
|
11
|
+
|
12
|
+
# Gets project information including all notes.
|
13
|
+
|
14
|
+
def get_project_info(project, all_data = true)
|
15
|
+
result = NetworkHelper.getResponse(Config::TODOIST_PROJECTS_GET_COMMAND, {project_id: project.id, all_data: true})
|
16
|
+
|
17
|
+
project = result["project"] ? ParseHelper.make_object(result["project"]) : nil
|
18
|
+
notes = result["notes"] ? ParseHelper.make_objects_as_array(result["notes"]) : nil
|
19
|
+
return {"project" => project, "notes" => notes}
|
20
|
+
end
|
21
|
+
|
22
|
+
# Gets a project's uncompleted items
|
23
|
+
def get_project_data(project)
|
24
|
+
result = NetworkHelper.getResponse(Config::TODOIST_PROJECTS_GET_DATA_COMMAND, {project_id: project.id})
|
25
|
+
project = result["project"] ? ParseHelper.make_object(result["project"]) : nil
|
26
|
+
items = result["items"] ? ParseHelper.make_objects_as_array(result["items"]) : nil
|
27
|
+
return {"project" => project, "items" => items}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# Exposes hidden API that allows queries to be issued to return items. Queries
|
2
|
+
# are restricted to a single "type" of query that is related to priority or date.
|
3
|
+
# When it cannot parse query, it either returns a date result for
|
4
|
+
# today or occasionally a 500 error.
|
5
|
+
|
6
|
+
module Todoist
|
7
|
+
module Misc
|
8
|
+
class Query
|
9
|
+
include Todoist::Util
|
10
|
+
|
11
|
+
# Given an array of queries, return multiple results with key being the
|
12
|
+
# query results. Query results have three key elements: query, type,
|
13
|
+
# and data. Data is where the items are stored.
|
14
|
+
def queries(queries)
|
15
|
+
result = NetworkHelper.getResponse(Config::TODOIST_QUERY_COMMAND,
|
16
|
+
queries: queries.to_json)
|
17
|
+
return ParseHelper.make_objects_as_array(result, "query")
|
18
|
+
end
|
19
|
+
|
20
|
+
# Given a query, return result. See return structure in comments above.
|
21
|
+
def query(query)
|
22
|
+
result = queries([query])
|
23
|
+
return result[query]
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Todoist
|
2
|
+
module Misc
|
3
|
+
class Quick
|
4
|
+
include Todoist::Util
|
5
|
+
|
6
|
+
# Implementation of the Quick Add Task available in the official
|
7
|
+
# clients.
|
8
|
+
def add_item(text)
|
9
|
+
result = NetworkHelper.getResponse(Config::TODOIST_QUICK_ADD_COMMAND, {text: text})
|
10
|
+
return ParseHelper.make_object(result)
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Todoist
|
2
|
+
module Misc
|
3
|
+
class Templates
|
4
|
+
include Todoist::Util
|
5
|
+
|
6
|
+
# Given a project and a File object (Ruby) imports the content onto the
|
7
|
+
# server. Critically, if the file is a CSV file make sure that the
|
8
|
+
# suffix is CSV. Otherwise, the file will be parsed as one item per line
|
9
|
+
# and ignore the formatting altogether.
|
10
|
+
def import_into_project(project, file)
|
11
|
+
multipart_file = NetworkHelper.multipart_file(file)
|
12
|
+
params = {project_id: project.id, file: multipart_file}
|
13
|
+
NetworkHelper.getMultipartResponse(Config::TODOIST_TEMPLATES_IMPORT_INTO_PROJECT_COMMAND, params)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Export the project as a CSV string
|
17
|
+
def export_as_file(project)
|
18
|
+
params = {project_id: project.id}
|
19
|
+
NetworkHelper.getResponse(Config::TODOIST_TEMPLATES_EXPORT_AS_FILE_COMMAND, params)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Export the project as a url that can be accessed over HTTP
|
23
|
+
def export_as_url(project)
|
24
|
+
params = {project_id: project.id}
|
25
|
+
NetworkHelper.getResponse(Config::TODOIST_TEMPLATES_EXPORT_AS_URL_COMMAND, params)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Todoist
|
2
|
+
module Misc
|
3
|
+
class Uploads
|
4
|
+
include Todoist::Util
|
5
|
+
|
6
|
+
# Uploads a file given a Ruby File.
|
7
|
+
def add(file)
|
8
|
+
multipart_file = NetworkHelper.multipart_file(file)
|
9
|
+
params = {file_name: File.basename(file), file: multipart_file}
|
10
|
+
NetworkHelper.getMultipartResponse(Config::TODOIST_UPLOADS_ADD_COMMAND, params)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Get uploads up to limit. If last_id is entered, then the results list
|
14
|
+
# everything from that ID forward.
|
15
|
+
def get(limit = 30, last_id = 0)
|
16
|
+
params = {limit: limit}
|
17
|
+
params["last_id"] = last_id if last_id
|
18
|
+
NetworkHelper.getResponse(Config::TODOIST_UPLOADS_GET_COMMAND, params)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Deletes an upload given a file URL.
|
22
|
+
def delete(file_url)
|
23
|
+
params = {file_url: file_url}
|
24
|
+
NetworkHelper.getResponse(Config::TODOIST_UPLOADS_DELETE_COMMAND, params)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Todoist
|
2
|
+
module Misc
|
3
|
+
class User
|
4
|
+
include Todoist::Util
|
5
|
+
|
6
|
+
# Logs the user in and grabs a token for the login session.
|
7
|
+
def login(email, password)
|
8
|
+
result = NetworkHelper.getResponse(Config::TODOIST_USER_LOGIN_COMMAND, {email: email, password: password}, false)
|
9
|
+
user = ParseHelper.make_object(result)
|
10
|
+
Config.token = user.token
|
11
|
+
return user
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Todoist
|
4
|
+
module Sync
|
5
|
+
class Filters
|
6
|
+
include Todoist::Util
|
7
|
+
|
8
|
+
# Return a Hash of filters where key is the id of a filter and value is a filter
|
9
|
+
def collection
|
10
|
+
return ApiHelper.collection("filters")
|
11
|
+
end
|
12
|
+
|
13
|
+
# Add a filter with a given hash of attributes and returns the filter id.
|
14
|
+
# Please note that item_id is required as is a date as specific in the
|
15
|
+
# documentation. This method can be tricky to all.
|
16
|
+
def add(args)
|
17
|
+
return ApiHelper.add(args, "filter_add")
|
18
|
+
end
|
19
|
+
|
20
|
+
# Update a filter given a filter
|
21
|
+
def update(filter)
|
22
|
+
return ApiHelper.command(filter.to_h, "filter_update")
|
23
|
+
end
|
24
|
+
|
25
|
+
# Delete filter given an array of filters
|
26
|
+
def delete(filter)
|
27
|
+
args = {id: filter.id}
|
28
|
+
return ApiHelper.command(args, "filter_delete")
|
29
|
+
end
|
30
|
+
|
31
|
+
# Update orders for an array of filters
|
32
|
+
def update_multiple_orders(filters)
|
33
|
+
args = {}
|
34
|
+
filters.each do |filter|
|
35
|
+
args[filter.id] = filter.item_order
|
36
|
+
end
|
37
|
+
args = {id_order_mapping: args.to_json}
|
38
|
+
return ApiHelper.command(args, "filter_update_orders")
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
module Todoist
|
2
|
+
module Sync
|
3
|
+
class Items
|
4
|
+
include Todoist::Util
|
5
|
+
|
6
|
+
# Return a Hash of items where key is the id of a item and value is a item
|
7
|
+
def collection
|
8
|
+
return ApiHelper.collection("items")
|
9
|
+
end
|
10
|
+
|
11
|
+
# Add a item with a given hash of attributes and returns the item id
|
12
|
+
def add(args)
|
13
|
+
return ApiHelper.add(args, "item_add")
|
14
|
+
end
|
15
|
+
|
16
|
+
# Update item given a item
|
17
|
+
def update(item)
|
18
|
+
return ApiHelper.command(item.to_h, "item_update")
|
19
|
+
end
|
20
|
+
|
21
|
+
# Delete items given an array of items
|
22
|
+
def delete(items)
|
23
|
+
item_ids = items.collect { |item| item.id }
|
24
|
+
args = {ids: item_ids.to_json}
|
25
|
+
return ApiHelper.command(args, "item_delete")
|
26
|
+
end
|
27
|
+
|
28
|
+
# Move an item from one project to another project given an item and a project.
|
29
|
+
# Note that move requires a fully inflated item object because it uses
|
30
|
+
# the project id in the item object.
|
31
|
+
def move(item, project)
|
32
|
+
project_items = {item.project_id => [item.id]}
|
33
|
+
args = {project_items: project_items, to_project: project.id}
|
34
|
+
return ApiHelper.command(args, "item_move")
|
35
|
+
end
|
36
|
+
|
37
|
+
# Complete items and optionally move them to history given an array of items. When force_history = 1, items should be moved to history (where 1 is true and 0 is false, and the default is 1) This is useful when checking off sub items.
|
38
|
+
|
39
|
+
def complete(items, force_history=1)
|
40
|
+
item_ids = items.collect { |item| item.id }
|
41
|
+
args = {ids: item_ids.to_json, force_history: force_history}
|
42
|
+
return ApiHelper.command(args, "item_complete")
|
43
|
+
end
|
44
|
+
|
45
|
+
# Uncomplete items and move them to the active projects given an array
|
46
|
+
# of items.
|
47
|
+
|
48
|
+
def uncomplete(items)
|
49
|
+
item_ids = items.collect { |item| item.id }
|
50
|
+
args = {ids: item_ids.to_json}
|
51
|
+
return ApiHelper.command(args, "item_uncomplete")
|
52
|
+
end
|
53
|
+
|
54
|
+
# Complete a recurring item given the id of the recurring item.
|
55
|
+
# This method also accepts as optional a new DateTime in UTC, a date
|
56
|
+
# string to reset the object to, and whether or not the item is to
|
57
|
+
# be completed or not using the is_forward flag.
|
58
|
+
|
59
|
+
def complete_recurring(item, new_date_utc = nil, date_string = nil,
|
60
|
+
is_forward = 1)
|
61
|
+
|
62
|
+
args = {id: item.id, is_forward: is_forward}
|
63
|
+
if new_date_utc
|
64
|
+
# Reformat DateTime to the following string: YYYY-MM-DDTHH:MM
|
65
|
+
args["new_date_utc"] = ParseHelper.formatTime(new_date_utc)
|
66
|
+
end
|
67
|
+
|
68
|
+
if date_string
|
69
|
+
args["date_string"] = date_string
|
70
|
+
end
|
71
|
+
|
72
|
+
return ApiHelper.command(args, "item_update_date_complete")
|
73
|
+
end
|
74
|
+
|
75
|
+
# A simplified version of item_complete / item_update_date_complete.
|
76
|
+
# The command does exactly what official clients do when you close a item
|
77
|
+
# given an item.
|
78
|
+
|
79
|
+
def close(item)
|
80
|
+
args = {id: item.id}
|
81
|
+
return ApiHelper.command(args, "item_close")
|
82
|
+
end
|
83
|
+
|
84
|
+
# Update the day orders of multiple items at once given an array of
|
85
|
+
# items
|
86
|
+
def update_day_orders(items)
|
87
|
+
ids_to_orders = {}
|
88
|
+
items.each do |item|
|
89
|
+
ids_to_orders[item.id] = item.day_order
|
90
|
+
end
|
91
|
+
args = {ids_to_orders: ids_to_orders.to_json}
|
92
|
+
return ApiHelper.command(args, "item_update_day_orders")
|
93
|
+
end
|
94
|
+
|
95
|
+
# Update orders and indents for an array of items
|
96
|
+
def update_multiple_orders_and_indents(items)
|
97
|
+
tuples = {}
|
98
|
+
items.each do |item|
|
99
|
+
tuples[item.id] = [item.item_order, item.indent]
|
100
|
+
end
|
101
|
+
args = {ids_to_orders_indents: tuples.to_json}
|
102
|
+
return ApiHelper.command(args, "item_update_orders_indents")
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Todoist
|
2
|
+
module Sync
|
3
|
+
class Labels
|
4
|
+
include Todoist::Util
|
5
|
+
|
6
|
+
# Return a Hash of labels where key is the id of a label and value is a label
|
7
|
+
def collection
|
8
|
+
return ApiHelper.collection("labels")
|
9
|
+
end
|
10
|
+
|
11
|
+
# Add a label with a given hash of attributes and returns the label id
|
12
|
+
def add(args)
|
13
|
+
return ApiHelper.add(args, "label_add")
|
14
|
+
end
|
15
|
+
|
16
|
+
# Update label given a label
|
17
|
+
def update(label)
|
18
|
+
return ApiHelper.command(label.to_h, "label_update")
|
19
|
+
end
|
20
|
+
|
21
|
+
# Delete a label given a label
|
22
|
+
def delete(label)
|
23
|
+
args = {id: label.id}
|
24
|
+
return ApiHelper.command(args, "label_delete")
|
25
|
+
end
|
26
|
+
|
27
|
+
# Update orders for an array of labels
|
28
|
+
def update_multiple_orders(labels)
|
29
|
+
args = {}
|
30
|
+
labels.each do |label|
|
31
|
+
args[label.id] = label.item_order
|
32
|
+
end
|
33
|
+
args = {id_order_mapping: args.to_json}
|
34
|
+
return ApiHelper.command(args, "label_update_orders")
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|