todoist-ruby 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|