namelessjon-todoist 0.1.0
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.
- data/Rakefile +44 -0
- data/bin/todoist +90 -0
- data/lib/todoist.rb +8 -0
- data/lib/todoist/base.rb +38 -0
- data/lib/todoist/project.rb +126 -0
- data/lib/todoist/task.rb +252 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/todoist_spec.rb +7 -0
- metadata +90 -0
data/Rakefile
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
require 'rcov/rcovtask'
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'jeweler'
|
8
|
+
Jeweler::Tasks.new do |s|
|
9
|
+
s.name = "todoist"
|
10
|
+
s.summary = "a library for interacting with the Todoist public API"
|
11
|
+
s.email = "jonathan.stott@gmail.com"
|
12
|
+
s.homepage = "http://github.com/namelessjon/todoist"
|
13
|
+
s.description = "The todoist gem offers convinience methods and wrappers for the todoist list management service, easing retrival and parsing of the responses. It also offers a simple command-line client."
|
14
|
+
s.authors = ["Jonathan Stott"]
|
15
|
+
s.files = FileList["lib/**/*.rb", "spec/**/*.rb", 'Rakefile', "[A-Z]+"]
|
16
|
+
s.add_dependency('highline', '~> 1.5')
|
17
|
+
s.add_dependency('thor', '~> 0.9')
|
18
|
+
s.add_dependency('httparty', '~> 0.3')
|
19
|
+
end
|
20
|
+
rescue LoadError
|
21
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
22
|
+
end
|
23
|
+
|
24
|
+
Rake::TestTask.new do |t|
|
25
|
+
t.libs << 'lib'
|
26
|
+
t.pattern = 'spec/**/*_spec.rb'
|
27
|
+
t.verbose = true
|
28
|
+
end
|
29
|
+
|
30
|
+
Rake::RDocTask.new do |rdoc|
|
31
|
+
rdoc.rdoc_dir = 'rdoc'
|
32
|
+
rdoc.title = 'Todoist'
|
33
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
34
|
+
rdoc.rdoc_files.include('README*')
|
35
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
36
|
+
end
|
37
|
+
|
38
|
+
Rcov::RcovTask.new do |t|
|
39
|
+
t.libs << "spec"
|
40
|
+
t.test_files = FileList['spec/**/*_spec.rb']
|
41
|
+
t.verbose = true
|
42
|
+
end
|
43
|
+
|
44
|
+
task :default => :rcov
|
data/bin/todoist
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'highline'
|
3
|
+
|
4
|
+
HighLine.track_eof = false
|
5
|
+
|
6
|
+
dir = File.dirname(__FILE__)
|
7
|
+
require File.join(dir, '..', 'lib', 'todoist')
|
8
|
+
|
9
|
+
class TodoistCLI < Thor
|
10
|
+
|
11
|
+
desc "tasks", "list of projects with uncompleted tasks, and their tasks"
|
12
|
+
def tasks(name=nil)
|
13
|
+
setup_todoist_base
|
14
|
+
|
15
|
+
Todoist::Project.all.each do |project|
|
16
|
+
next if name and project.name !~ /#{name}/
|
17
|
+
|
18
|
+
if project.task_count > 0
|
19
|
+
print_project(project)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
desc "complete", "Completes the task with the given content"
|
25
|
+
method_options :all => :boolean
|
26
|
+
def complete(content)
|
27
|
+
setup_todoist_base
|
28
|
+
|
29
|
+
@h = HighLine.new
|
30
|
+
|
31
|
+
to_complete = []
|
32
|
+
Todoist::Task.all.each do |task|
|
33
|
+
next if task.content !~ /#{content}/
|
34
|
+
to_complete << task
|
35
|
+
end
|
36
|
+
|
37
|
+
tasks = []
|
38
|
+
if to_complete.size > 1 and !options[:all]
|
39
|
+
@h.say("Choose tasks to delete:")
|
40
|
+
to_complete.each do |task|
|
41
|
+
if @h.agree("Delete #{task} (#{task.project})?")
|
42
|
+
tasks << task
|
43
|
+
end
|
44
|
+
end
|
45
|
+
else
|
46
|
+
tasks = to_complete
|
47
|
+
end
|
48
|
+
|
49
|
+
Todoist::Task.complete(tasks)
|
50
|
+
end
|
51
|
+
|
52
|
+
desc "overdue", "Fetch all overdue tasks"
|
53
|
+
def overdue
|
54
|
+
setup_todoist_base
|
55
|
+
Todoist::Task.overdue.each do |task|
|
56
|
+
puts task
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
protected
|
61
|
+
def print_project(project)
|
62
|
+
puts project
|
63
|
+
project.tasks.each do |task|
|
64
|
+
print " " * (task.indent.to_i - 1)
|
65
|
+
print (task.content =~ /\* /) ? '' : '- '
|
66
|
+
puts task
|
67
|
+
end
|
68
|
+
puts ""
|
69
|
+
end
|
70
|
+
|
71
|
+
def setup_todoist_base
|
72
|
+
if File.file?(File.expand_path('~/.todoistrc'))
|
73
|
+
require 'yaml'
|
74
|
+
conf = YAML.load_file(File.expand_path('~/.todoistrc'))
|
75
|
+
Todoist::Base.setup(conf['token'], conf['premium'])
|
76
|
+
else
|
77
|
+
puts <<-eos
|
78
|
+
You need to setup ~/.todoistrc, for example:
|
79
|
+
token: 91b1ce9e153fc5390ac3db4f0ded9f31a1a7ba23 # use your api key
|
80
|
+
premium: false # if this is true, ssl will be used.
|
81
|
+
eos
|
82
|
+
exit(1)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
TodoistCLI.start
|
89
|
+
|
90
|
+
# vim: set ft=ruby:
|
data/lib/todoist.rb
ADDED
data/lib/todoist/base.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'json'
|
3
|
+
module Todoist
|
4
|
+
##
|
5
|
+
# The Todoist::Base class is responsible for making all queries to the
|
6
|
+
# todoist web API.
|
7
|
+
class Base
|
8
|
+
include HTTParty
|
9
|
+
format :json
|
10
|
+
|
11
|
+
##
|
12
|
+
# Sets up the Todoist::Base class for making requests, setting the API key
|
13
|
+
# and if the account is a premium one or not.
|
14
|
+
def self.setup(token, premium = false)
|
15
|
+
self.default_params :token => token
|
16
|
+
@@premium = premium
|
17
|
+
set_base_uri
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def self.set_base_uri
|
22
|
+
if premium?
|
23
|
+
base_uri 'https://todoist.com/API'
|
24
|
+
else
|
25
|
+
base_uri 'http://todoist.com/API'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.premium?
|
30
|
+
(@@premium) ? true : false
|
31
|
+
end
|
32
|
+
|
33
|
+
def id_array(ids)
|
34
|
+
ids.flatten.map {|i| i.to_i }.to_json
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module Todoist
|
2
|
+
##
|
3
|
+
# Project
|
4
|
+
#
|
5
|
+
# A todoist project.
|
6
|
+
class Project
|
7
|
+
attr_reader :name, :id, :user_id, :color, :collapsed, :order, :indent
|
8
|
+
|
9
|
+
##
|
10
|
+
# Get all projects
|
11
|
+
#
|
12
|
+
# Fetches all the user's todist projects.
|
13
|
+
#
|
14
|
+
# @return [Array] An Array of todoist project instances.
|
15
|
+
def self.all
|
16
|
+
projects = []
|
17
|
+
Base.get('/getProjects').each do |project|
|
18
|
+
projects << new_from_api_request(project)
|
19
|
+
end
|
20
|
+
projects
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# Get a project
|
25
|
+
#
|
26
|
+
# Fetches a todoist project
|
27
|
+
#
|
28
|
+
# @param [Integer,Todoist::Project] id The id, or project, to fetch
|
29
|
+
#
|
30
|
+
# @return [Todoist::Project] The fetched project.
|
31
|
+
def self.get(id)
|
32
|
+
new_from_api_request(get_project(id))
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Create a new project
|
37
|
+
#
|
38
|
+
# Creates a new Todoist project.
|
39
|
+
#
|
40
|
+
# @param [String] name The name of the project
|
41
|
+
#
|
42
|
+
# @param [Hash] parameters The other parameters which make up the project.
|
43
|
+
#
|
44
|
+
# @return [Todoist::Project] The new todoist project.
|
45
|
+
def initialize(name, parameters={})
|
46
|
+
@name = name
|
47
|
+
@id = parameters['id']
|
48
|
+
@user_id = parameters['user_id']
|
49
|
+
@color = parameters['color']
|
50
|
+
@collapsed = parameters['collapsed']
|
51
|
+
@order = parameters['item_order']
|
52
|
+
@count = parameters['cache_count']
|
53
|
+
@indent = parameters['indent']
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
def to_s
|
58
|
+
"#{name}"
|
59
|
+
end
|
60
|
+
|
61
|
+
def to_i
|
62
|
+
id
|
63
|
+
end
|
64
|
+
|
65
|
+
def inspect
|
66
|
+
"<Project:#{name}:#{id}:#{task_count}:user_id=#{user_id} color='#{color}' collapsed=#{collapsed?} order=#{order} indent=#{indent}>"
|
67
|
+
end
|
68
|
+
|
69
|
+
def collapsed?
|
70
|
+
(collapsed == 1) ? true : false
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
##
|
75
|
+
# The task count
|
76
|
+
#
|
77
|
+
# The number of tasks a project has, according to its cache_count when it was fetched
|
78
|
+
#
|
79
|
+
# @return [Integer] The number of tasks this project has
|
80
|
+
def task_count
|
81
|
+
@count
|
82
|
+
end
|
83
|
+
|
84
|
+
##
|
85
|
+
# Get uncompleted tasks for the project
|
86
|
+
#
|
87
|
+
# @return [Array] An Array of Todoist::Tasks
|
88
|
+
def tasks
|
89
|
+
Task.uncompleted(self)
|
90
|
+
end
|
91
|
+
|
92
|
+
##
|
93
|
+
# Get completed tasks for the project
|
94
|
+
#
|
95
|
+
# @return [Array] An Array of completed Todoist::Tasks
|
96
|
+
def completed_tasks
|
97
|
+
Task.completed(self)
|
98
|
+
end
|
99
|
+
|
100
|
+
##
|
101
|
+
# Add task
|
102
|
+
#
|
103
|
+
# Adds a task to the project.
|
104
|
+
#
|
105
|
+
# @param [String] content The content of the new task
|
106
|
+
#
|
107
|
+
# @param [Hash] opts The options for the new task
|
108
|
+
#
|
109
|
+
# @return [Todoist::Task] The new task.
|
110
|
+
def add_task(content, opts={})
|
111
|
+
Task.new(content, self, opts).save
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
def self.new_from_api_request(project)
|
117
|
+
name = project.delete('name')
|
118
|
+
new(name, project)
|
119
|
+
end
|
120
|
+
|
121
|
+
def self.get_project(id)
|
122
|
+
Base.get('/getProject', :query => {:project_id => id.to_i })
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
end
|
data/lib/todoist/task.rb
ADDED
@@ -0,0 +1,252 @@
|
|
1
|
+
require 'time'
|
2
|
+
module Todoist
|
3
|
+
##
|
4
|
+
# Todoist Task
|
5
|
+
#
|
6
|
+
# A todoist task.
|
7
|
+
class Task
|
8
|
+
attr_accessor :content, :priority, :task_details, :project_id
|
9
|
+
attr_reader :date, :id
|
10
|
+
##
|
11
|
+
# Get tasks for a project
|
12
|
+
#
|
13
|
+
# Retrieves all uncompleted tasks from the todoist service for the project id.
|
14
|
+
#
|
15
|
+
# @param [Integer,Todoist::Project] project The project to get tasks for
|
16
|
+
#
|
17
|
+
# @return [Array] An array of todoist tasks.
|
18
|
+
def self.uncompleted(project)
|
19
|
+
make_tasks(Base.get('/getUncompletedItems', :query => { :project_id => project.to_i }))
|
20
|
+
end
|
21
|
+
|
22
|
+
##
|
23
|
+
# Get completed tasks for project
|
24
|
+
#
|
25
|
+
# Retrieves completed tasks from the todoist service for the project id.
|
26
|
+
#
|
27
|
+
# @param [Integer,Todoist::Project] project The project to get tasks for
|
28
|
+
#
|
29
|
+
# @return [Array] An array of todoist tasks.
|
30
|
+
def self.completed(project)
|
31
|
+
make_tasks(Base.get('/getCompletedItems', :query => { :project_id => project.to_i }))
|
32
|
+
end
|
33
|
+
|
34
|
+
##
|
35
|
+
# Complete tasks
|
36
|
+
#
|
37
|
+
# Completes a list of tasks
|
38
|
+
#
|
39
|
+
# @param [Array,Integer,Todist::Task] ids A list of tasks to complete.
|
40
|
+
def self.complete(*ids)
|
41
|
+
make_tasks(Base.get('/completeItems', :query => {:ids => id_array(ids)}))
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# Get Tasks by ID
|
46
|
+
#
|
47
|
+
# Retrives a list of tasks from the todoist service.
|
48
|
+
#
|
49
|
+
# @param [Array,Integer,Todist::Task] ids A list of tasks to retrieve
|
50
|
+
#
|
51
|
+
# @return [Array] An array of Todist::Tasks
|
52
|
+
def self.get(*ids)
|
53
|
+
make_tasks(Base.get('/getItemsById', :query => {:ids => id_array(ids)}))
|
54
|
+
end
|
55
|
+
|
56
|
+
##
|
57
|
+
# Get all tasks
|
58
|
+
#
|
59
|
+
# Retrieves all the uncompleted tasks
|
60
|
+
#
|
61
|
+
# @return [Array] An array of Todist::Tasks
|
62
|
+
def self.all
|
63
|
+
query('viewall')['viewall']
|
64
|
+
end
|
65
|
+
|
66
|
+
##
|
67
|
+
# Get overdue tasks
|
68
|
+
#
|
69
|
+
# Retrieves all the overdue tasks
|
70
|
+
#
|
71
|
+
# @return [Array] An array of overdue Todist::Tasks
|
72
|
+
def self.overdue
|
73
|
+
query('overdue')['overdue']
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
##
|
78
|
+
# Query
|
79
|
+
#
|
80
|
+
# Use the task query API to get back several arrays of tasks.
|
81
|
+
#
|
82
|
+
# @param [String,Array] query A query or a list of queries to perform
|
83
|
+
#
|
84
|
+
# @return [Hash] a hash keyed on query, containing arrays of tasks.
|
85
|
+
#
|
86
|
+
# Allowed queries
|
87
|
+
# viewall:: All tasks
|
88
|
+
# overdue:: All overdue tasks
|
89
|
+
# p[123]:: All tasks of priority 1, 2 ,3
|
90
|
+
def self.query(*queries)
|
91
|
+
query = '["' + queries.flatten.map { |q| q.to_s }.join('","') + '"]'
|
92
|
+
results = {}
|
93
|
+
response = Base.get('/query', :query => { :queries => query })
|
94
|
+
|
95
|
+
response.each do |q|
|
96
|
+
if q['type'] == 'viewall'
|
97
|
+
tasks = []
|
98
|
+
q['data'].each do |stuff|
|
99
|
+
tasks << make_tasks(stuff['uncompleted'])
|
100
|
+
end
|
101
|
+
results[q['type']] = tasks.flatten
|
102
|
+
else
|
103
|
+
results[q['type']] = make_tasks(q['data'])
|
104
|
+
end
|
105
|
+
end
|
106
|
+
results
|
107
|
+
end
|
108
|
+
|
109
|
+
##
|
110
|
+
# Create a new task
|
111
|
+
#
|
112
|
+
# @param [String] content The content of the new task.
|
113
|
+
#
|
114
|
+
# @param [Integer,Todoist::Project] project The project to create the new task in
|
115
|
+
#
|
116
|
+
# @param [Hash] opts Optional priority and due date for creation.
|
117
|
+
def self.create(content, project, opts={})
|
118
|
+
query = {:project_id => project.to_i, :content => content.to_s }
|
119
|
+
query['priority'] = opts.delete('priority') if opts.has_key?('priority')
|
120
|
+
query['date_string'] = opts.delete('date_string') if opts.has_key?('date_string')
|
121
|
+
|
122
|
+
new_from_api(Base.get('/addItem', :query => query))
|
123
|
+
end
|
124
|
+
|
125
|
+
##
|
126
|
+
# Updates a task
|
127
|
+
#
|
128
|
+
# @param [String] content The new content of the task.
|
129
|
+
#
|
130
|
+
# @param [Integer,Todoist::Task] id The task to update
|
131
|
+
#
|
132
|
+
# @param [Hash] opts Optional priority and due date for creation.
|
133
|
+
def self.update(content, id, opts={})
|
134
|
+
query = {:id => project.to_i, :content => content.to_s }
|
135
|
+
query['priority'] = opts.delete('priority') if opts.has_key?('priority')
|
136
|
+
query['date_string'] = opts.delete('date_string') if opts.has_key?('date_string')
|
137
|
+
|
138
|
+
new_from_api(Base.get('/updateItem', :query => query))
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
|
143
|
+
def initialize(content, project_id, d={})
|
144
|
+
@content = content
|
145
|
+
@project_id = project_id.to_i
|
146
|
+
@date = d.delete('date') || d.delete('date_string')
|
147
|
+
@priority = d.delete('priority')
|
148
|
+
@id = d.delete('id')
|
149
|
+
@task_details = d
|
150
|
+
end
|
151
|
+
|
152
|
+
##
|
153
|
+
# Is the task complete
|
154
|
+
def complete?
|
155
|
+
(@task_details['in_history'] == 1) ? true : false
|
156
|
+
end
|
157
|
+
|
158
|
+
|
159
|
+
##
|
160
|
+
# Complete
|
161
|
+
#
|
162
|
+
# Completes the todoist task
|
163
|
+
def complete
|
164
|
+
self.class.complete(self) unless complete?
|
165
|
+
@task_details['in_history'] = 1
|
166
|
+
end
|
167
|
+
|
168
|
+
##
|
169
|
+
# Is the task overdue?
|
170
|
+
def overdue?
|
171
|
+
return false unless due_date
|
172
|
+
Time.now > Time.parse(due_date)
|
173
|
+
end
|
174
|
+
|
175
|
+
##
|
176
|
+
# Project
|
177
|
+
#
|
178
|
+
# Retreives the project for the task
|
179
|
+
def project
|
180
|
+
Project.get(project_id)
|
181
|
+
end
|
182
|
+
|
183
|
+
##
|
184
|
+
# Saves the task
|
185
|
+
#
|
186
|
+
# Save the task, either creating a new task on the todoist service, or
|
187
|
+
# updating a previously retrieved task with new content, priority etc.
|
188
|
+
def save
|
189
|
+
opts = {}
|
190
|
+
opts['priority'] = priority if priority
|
191
|
+
opts['date_string'] = date if date
|
192
|
+
# if we don't have an id, then we can assume this is a new task.
|
193
|
+
unless (task_details.has_key?('id'))
|
194
|
+
result = self.class.create(self.content, self.project_id, opts)
|
195
|
+
else
|
196
|
+
result = self.class.update(self.content, self.id, opts)
|
197
|
+
end
|
198
|
+
|
199
|
+
self.content = result.content
|
200
|
+
self.project_id = result.project_id
|
201
|
+
self.task_details = result.task_details
|
202
|
+
self
|
203
|
+
end
|
204
|
+
|
205
|
+
|
206
|
+
|
207
|
+
def to_s
|
208
|
+
@content
|
209
|
+
end
|
210
|
+
|
211
|
+
def to_i
|
212
|
+
id
|
213
|
+
end
|
214
|
+
|
215
|
+
def inspect
|
216
|
+
"<Todoist::Task:#{content}:#{id}:#{project_id}:#{task_details.inspect}>"
|
217
|
+
end
|
218
|
+
|
219
|
+
def method_missing(*args, &block)
|
220
|
+
# the method name
|
221
|
+
m = args.shift
|
222
|
+
if @task_details.has_key?(m.to_s)
|
223
|
+
return @task_details[m.to_s]
|
224
|
+
else
|
225
|
+
raise NoMethodError, "undefined method `#{m}' for #{self.inspect}"
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
private
|
230
|
+
|
231
|
+
def self.new_from_api(task)
|
232
|
+
content = task.delete('content')
|
233
|
+
project_id = task.delete('project_id')
|
234
|
+
new(content, project_id, task)
|
235
|
+
end
|
236
|
+
|
237
|
+
def self.make_tasks(tasks)
|
238
|
+
new_tasks = []
|
239
|
+
tasks.each do |task|
|
240
|
+
new_tasks << new_from_api(task)
|
241
|
+
end
|
242
|
+
new_tasks
|
243
|
+
end
|
244
|
+
|
245
|
+
def self.id_array(*ids)
|
246
|
+
"[" + ids.flatten.map { |q| q.to_i }.join(",") + "]"
|
247
|
+
end
|
248
|
+
|
249
|
+
|
250
|
+
# {"due_date": null, "collapsed": 0, "labels": [], "is_dst": 0, "has_notifications": 0, "checked": 0, "indent": 1, "children": null, "content": "Finish this gem", "user_id": 34615, "mm_offset": 0, "in_history": 0, "id": 4152190, "priority": 4, "item_order": 1, "project_id": 528294, "chains": null, "date_string": ""}
|
251
|
+
end
|
252
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: namelessjon-todoist
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jonathan Stott
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-02-15 00:00:00 -08:00
|
13
|
+
default_executable: todoist
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: highline
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ~>
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "1.5"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: thor
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0.9"
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: httparty
|
37
|
+
type: :runtime
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: "0.3"
|
44
|
+
version:
|
45
|
+
description: The todoist gem offers convinience methods and wrappers for the todoist list management service, easing retrival and parsing of the responses. It also offers a simple command-line client.
|
46
|
+
email: jonathan.stott@gmail.com
|
47
|
+
executables:
|
48
|
+
- todoist
|
49
|
+
extensions: []
|
50
|
+
|
51
|
+
extra_rdoc_files: []
|
52
|
+
|
53
|
+
files:
|
54
|
+
- lib/todoist/base.rb
|
55
|
+
- lib/todoist/project.rb
|
56
|
+
- lib/todoist/task.rb
|
57
|
+
- lib/todoist.rb
|
58
|
+
- spec/spec_helper.rb
|
59
|
+
- spec/todoist_spec.rb
|
60
|
+
- Rakefile
|
61
|
+
- bin/todoist
|
62
|
+
has_rdoc: true
|
63
|
+
homepage: http://github.com/namelessjon/todoist
|
64
|
+
post_install_message:
|
65
|
+
rdoc_options:
|
66
|
+
- --inline-source
|
67
|
+
- --charset=UTF-8
|
68
|
+
require_paths:
|
69
|
+
- lib
|
70
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: "0"
|
75
|
+
version:
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: "0"
|
81
|
+
version:
|
82
|
+
requirements: []
|
83
|
+
|
84
|
+
rubyforge_project:
|
85
|
+
rubygems_version: 1.2.0
|
86
|
+
signing_key:
|
87
|
+
specification_version: 2
|
88
|
+
summary: a library for interacting with the Todoist public API
|
89
|
+
test_files: []
|
90
|
+
|