namelessjon-todoist 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|