todoist-ruby 0.1.3 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  require "net/http"
2
2
  require "json"
3
- require "todoist/util/config"
3
+ require "todoist/config"
4
4
  require 'net/http/post/multipart'
5
5
  require 'mimemagic'
6
6
 
@@ -8,16 +8,25 @@ module Todoist
8
8
  module Util
9
9
  class NetworkHelper
10
10
 
11
- @@last_request_time = 0.0
12
11
 
13
- def self.configureHTTP(command)
12
+
13
+ def initialize(client)
14
+ @client = client
15
+ @command_cache = Concurrent::Array.new([])
16
+ @command_mutex = Mutex.new
17
+ @temp_id_callback_cache = Concurrent::Array.new([])
18
+ @last_request_time = 0.0
19
+
20
+ end
21
+
22
+ def configure_http(command)
14
23
  http = Net::HTTP.new(Config.getURI()[command].host, Config.getURI()[command].port)
15
24
  http.use_ssl = true
16
25
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE
17
26
  return http
18
27
  end
19
28
 
20
- def self.configureRequest(command, params)
29
+ def configure_request(command, params)
21
30
  request = Net::HTTP::Post.new(Config.getURI()[command].request_uri)
22
31
  request.set_form_data(params)
23
32
  return request
@@ -25,9 +34,9 @@ module Todoist
25
34
 
26
35
  # Files need to be of class UploadIO
27
36
 
28
- def self.getMultipartResponse(command, params={})
29
- token = {token: Todoist::Util::Config.token}
30
- http = configureHTTP(command)
37
+ def get_multipart_response(command, params={})
38
+ token = {token: @client.token}
39
+ http = configure_http(command)
31
40
  url = Config.getURI()[command]
32
41
  http.start do
33
42
  req = Net::HTTP::Post::Multipart.new(url, token.merge(params))
@@ -40,11 +49,11 @@ module Todoist
40
49
  end
41
50
  end
42
51
 
43
- def self.getResponse(command, params ={}, token = true)
44
- token = token ? {token: Todoist::Util::Config.token} : {}
45
- http = configureHTTP(command)
46
- request = configureRequest(command, token.merge(params))
47
- retry_after_secs = Todoist::Util::Config.retry_time
52
+ def get_response(command, params ={}, token = true)
53
+ token = token ? {token: @client.token} : {}
54
+ http = configure_http(command)
55
+ request = configure_request(command, token.merge(params))
56
+ retry_after_secs = Todoist::Config.retry_time
48
57
  # Hack to fix encoding issues with Net:HTTP for login case
49
58
  request.body = request.body.gsub '%40', '@' unless token
50
59
  while true
@@ -67,7 +76,7 @@ module Todoist
67
76
  when 429
68
77
  puts("Encountered 429 - retry after #{retry_after_secs}")
69
78
  sleep(retry_after_secs)
70
- retry_after_secs *= Todoist::Util::Config.retry_time
79
+ retry_after_secs *= Todoist::Config.retry_time
71
80
  when 500
72
81
  raise StandardError, "HTTP 500 Error - The request failed due to a server error."
73
82
  when 503
@@ -77,24 +86,50 @@ module Todoist
77
86
 
78
87
  end
79
88
 
80
- def self.throttle_request(http, request)
81
- time_since_last_request = Time.now.to_f - @@last_request_time
89
+ def throttle_request(http, request)
90
+ time_since_last_request = Time.now.to_f - @last_request_time
82
91
 
83
- if (time_since_last_request < Todoist::Util::Config.delay_between_requests)
84
- wait = Todoist::Util::Config.delay_between_requests - time_since_last_request
92
+ if (time_since_last_request < Todoist::Config.delay_between_requests)
93
+ wait = Todoist::Config.delay_between_requests - time_since_last_request
85
94
  puts("Throttling request by: #{wait}")
86
95
  sleep(wait)
87
96
  end
88
- @@last_request_time = Time.now.to_f
97
+ @last_request_time = Time.now.to_f
89
98
  http.request(request)
90
99
  end
91
100
 
92
101
  # Prepares a file for multipart upload
93
- def self.multipart_file(file)
102
+ def multipart_file(file)
94
103
  filename = File.basename(file)
95
104
  mime_type = MimeMagic.by_path(filename).type
96
105
  return UploadIO.new(file, mime_type, filename)
97
106
  end
107
+
108
+ def queue(command, callback = nil)
109
+ @command_mutex.synchronize do
110
+ @command_cache.push(command)
111
+ @temp_id_callback_cache.push(callback) if callback
112
+ end
113
+
114
+ end
115
+
116
+ def sync
117
+ @command_mutex.synchronize do
118
+ response = get_sync_response({commands: @command_cache.to_json})
119
+ @command_cache.clear
120
+ # Process callbacks here
121
+ temp_id_mappings = response["temp_id_mapping"]
122
+ @temp_id_callback_cache.each do |callback|
123
+ callback.(temp_id_mappings)
124
+ end
125
+ @temp_id_callback_cache.clear
126
+ end
127
+ end
128
+
129
+ def get_sync_response(params)
130
+ get_response(Config::TODOIST_SYNC_COMMAND, params)
131
+ end
132
+
98
133
  end
99
134
  end
100
135
  end
@@ -4,11 +4,11 @@ module Todoist
4
4
  module Util
5
5
  class ParseHelper
6
6
 
7
- def self.utcOffsetHours
7
+ def self.utc_offset_hours
8
8
  return Time.now.utc_offset/60/60
9
9
  end
10
10
 
11
- def self.parseTodoistDate(item, key)
11
+ def self.parse_todoist_date(item, key)
12
12
  if item[key]
13
13
  time = Time.parse(item[key])
14
14
  return time.to_datetime
@@ -18,17 +18,17 @@ module Todoist
18
18
  end
19
19
 
20
20
 
21
- def self.filterToday(item, key)
21
+ def self.filter_today(item, key)
22
22
 
23
23
  now = DateTime.now
24
- if parseTodoistDate(item, key) && parseTodoistDate(item, key) <= DateTime.new(now.year, now.month, now.day, -utcOffsetHours) + 1
24
+ if parse_todoist_date(item, key) && parse_todoist_date(item, key) <= DateTime.new(now.year, now.month, now.day, -utc_offset_hours) + 1
25
25
  return true
26
26
  else
27
27
  return false
28
28
  end
29
29
  end
30
30
 
31
- def self.formatTime(datetime)
31
+ def self.format_time(datetime)
32
32
  datetime.strftime("%Y-%m-%dT%H:%M")
33
33
  end
34
34
 
@@ -1,3 +1,3 @@
1
1
  module Todoist
2
- VERSION = "0.1.3"
2
+ VERSION = "0.2.1"
3
3
  end
data/todoist.gemspec CHANGED
@@ -33,12 +33,12 @@ Gem::Specification.new do |spec|
33
33
  spec.add_development_dependency "bundler", "~> 1.13"
34
34
  spec.add_development_dependency "rake", "~> 10.0"
35
35
  spec.add_development_dependency "rspec", "~> 3.0"
36
- spec.add_development_dependency "pry"
37
- spec.add_development_dependency "vcr"
38
- spec.add_development_dependency "webmock"
39
- spec.add_development_dependency "simplecov"
40
- spec.add_dependency "concurrent-ruby"
41
- spec.add_dependency "multipart-post"
42
- spec.add_dependency "mimemagic"
36
+ spec.add_development_dependency "pry", "~> 0.10"
37
+ spec.add_development_dependency "vcr", "~> 3.0"
38
+ spec.add_development_dependency "webmock", "~> 3.0"
39
+ spec.add_development_dependency "simplecov", "~> 0.10"
40
+ spec.add_dependency "concurrent-ruby", "~> 1.0"
41
+ spec.add_dependency "multipart-post", "~> 2.0"
42
+ spec.add_dependency "mimemagic", "~> 0.3"
43
43
 
44
44
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: todoist-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Han Yuan
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-05-30 00:00:00.000000000 Z
11
+ date: 2017-07-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -56,100 +56,100 @@ dependencies:
56
56
  name: pry
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">="
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: '0.10'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ">="
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0'
68
+ version: '0.10'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: vcr
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ">="
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '0'
75
+ version: '3.0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ">="
80
+ - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '0'
82
+ version: '3.0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: webmock
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ">="
87
+ - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '0'
89
+ version: '3.0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ">="
94
+ - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '0'
96
+ version: '3.0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: simplecov
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - ">="
101
+ - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '0'
103
+ version: '0.10'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - ">="
108
+ - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '0'
110
+ version: '0.10'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: concurrent-ruby
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - ">="
115
+ - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '0'
117
+ version: '1.0'
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - ">="
122
+ - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '0'
124
+ version: '1.0'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: multipart-post
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - ">="
129
+ - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: '0'
131
+ version: '2.0'
132
132
  type: :runtime
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - ">="
136
+ - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: '0'
138
+ version: '2.0'
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: mimemagic
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
- - - ">="
143
+ - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: '0'
145
+ version: '0.3'
146
146
  type: :runtime
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
- - - ">="
150
+ - - "~>"
151
151
  - !ruby/object:Gem::Version
152
- version: '0'
152
+ version: '0.3'
153
153
  description: This gem provides access to the latest Todoist API. It is designed to
154
154
  be as lightweight as possible. While the gem provides interfaces for the sync API
155
155
  calls, no support is provided for persisting the result of these calls. Collaboration
@@ -174,6 +174,8 @@ files:
174
174
  - fixtures/uuid/.gitignore
175
175
  - fixtures/vcr_cassettes/.gitignore
176
176
  - lib/todoist.rb
177
+ - lib/todoist/client.rb
178
+ - lib/todoist/config.rb
177
179
  - lib/todoist/misc/activity.rb
178
180
  - lib/todoist/misc/backups.rb
179
181
  - lib/todoist/misc/completed.rb
@@ -183,7 +185,7 @@ files:
183
185
  - lib/todoist/misc/quick.rb
184
186
  - lib/todoist/misc/templates.rb
185
187
  - lib/todoist/misc/uploads.rb
186
- - lib/todoist/misc/user.rb
188
+ - lib/todoist/service.rb
187
189
  - lib/todoist/sync/filters.rb
188
190
  - lib/todoist/sync/items.rb
189
191
  - lib/todoist/sync/labels.rb
@@ -191,8 +193,6 @@ files:
191
193
  - lib/todoist/sync/projects.rb
192
194
  - lib/todoist/sync/reminders.rb
193
195
  - lib/todoist/util/api_helper.rb
194
- - lib/todoist/util/command_synchronizer.rb
195
- - lib/todoist/util/config.rb
196
196
  - lib/todoist/util/network_helper.rb
197
197
  - lib/todoist/util/parse_helper.rb
198
198
  - lib/todoist/util/uuid.rb
@@ -1,16 +0,0 @@
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
@@ -1,54 +0,0 @@
1
- require 'concurrent'
2
- require "todoist/util/api_helper"
3
-
4
- module Todoist
5
-
6
- module Util
7
- class CommandSynchronizer
8
-
9
- @@command_cache = Concurrent::Array.new([])
10
- @@command_mutex = Mutex.new
11
- @@temp_id_callback_cache = Concurrent::Array.new([])
12
-
13
- def self.start
14
- @@sync_thread = Thread.new do
15
- while(true) do
16
- process()
17
- sleep(3)
18
- end
19
- end unless @@sync_thread
20
- end
21
-
22
- def self.stop
23
- Thread.kill(@@sync_thread) if @@sync_thread
24
- @@sync_thread = nil
25
- end
26
-
27
- def self.queue(command, callback = nil)
28
- @@command_mutex.synchronize do
29
- @@command_cache.push(command)
30
- @@temp_id_callback_cache.push(callback) if callback
31
- end
32
- end
33
-
34
- def self.sync
35
- @@command_mutex.synchronize do
36
- response = ApiHelper.getSyncResponse({commands: @@command_cache.to_json})
37
- @@command_cache.clear
38
- # Process callbacks here
39
- temp_id_mappings = response["temp_id_mapping"]
40
- @@temp_id_callback_cache.each do |callback|
41
- callback.(temp_id_mappings)
42
- end
43
- @@temp_id_callback_cache.clear
44
- end
45
- end
46
-
47
-
48
- protected
49
-
50
- end
51
-
52
- end
53
-
54
- end
@@ -1,78 +0,0 @@
1
- module Todoist
2
- module Util
3
- class Config
4
- TODOIST_API_URL = "https://todoist.com/API/v7"
5
-
6
- # List of commands supported
7
- @@command_list = [
8
- TODOIST_SYNC_COMMAND = "/sync",
9
- TODOIST_QUERY_COMMAND = "/query",
10
- TODOIST_TEMPLATES_IMPORT_INTO_PROJECT_COMMAND = "/templates/import_into_project",
11
- TODOIST_TEMPLATES_EXPORT_AS_FILE_COMMAND = "/templates/export_as_file",
12
- TODOIST_TEMPLATES_EXPORT_AS_URL_COMMAND = "/templates/export_as_url",
13
- TODOIST_UPLOADS_ADD_COMMAND = "/uploads/add",
14
- TODOIST_UPLOADS_GET_COMMAND = "/uploads/get",
15
- TODOIST_UPLOADS_DELETE_COMMAND = "/uploads/delete",
16
- TODOIST_COMPLETED_GET_STATS_COMMAND = "/completed/get_stats",
17
- TODOIST_COMPLETED_GET_ALL_COMMAND = "/completed/get_all",
18
- TODOIST_PROJECTS_GET_ARCHIVED_COMMAND = "/projects/get_archived",
19
- TODOIST_PROJECTS_GET_COMMAND = "/projects/get",
20
- TODOIST_PROJECTS_GET_DATA_COMMAND = "/projects/get_data",
21
- TODOIST_ITEMS_ADD_COMMAND = "/items/add",
22
- TODOIST_ITEMS_GET_COMMAND = "/items/get",
23
- TODOIST_QUICK_ADD_COMMAND = "/quick/add",
24
- TODOIST_ACTIVITY_GET_COMMAND = "/activity/get",
25
- TODOIST_BACKUPS_GET_COMMAND = "/backups/get",
26
- TODOIST_USER_LOGIN_COMMAND = "/user/login"
27
- ]
28
-
29
- # Map of commands to URIs
30
- @@uri = nil
31
-
32
- # User token
33
- @@token = nil
34
-
35
- # Artificial delay between requests to avoid API throttling
36
- @@delay_between_requests = 0
37
-
38
- # Should API throttling happen (HTTP Error 429), retry_time between requests
39
- # with exponential backoff
40
- @@retry_time = 20
41
-
42
- def self.token=(token)
43
- @@token = token
44
- end
45
-
46
- def self.token
47
- @@token
48
- end
49
-
50
- def self.retry_time=(retry_time)
51
- @@retry_time = retry_time
52
- end
53
-
54
- def self.retry_time
55
- @@retry_time
56
- end
57
-
58
- def self.delay_between_requests=(delay_between_requests)
59
- @@delay_between_requests = delay_between_requests
60
- end
61
-
62
- def self.delay_between_requests
63
- @@delay_between_requests
64
- end
65
-
66
- def self.getURI
67
- if @@uri == nil
68
- @@uri = {}
69
- @@command_list.each do |command|
70
- @@uri[command] = URI.parse(TODOIST_API_URL + command)
71
- end
72
- end
73
- return @@uri
74
- end
75
-
76
- end
77
- end
78
- end