timetree 0.0.1 → 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.
@@ -3,9 +3,13 @@
3
3
  require 'logger'
4
4
 
5
5
  module TimeTree
6
+ # TimeTree apis client configuration.
6
7
  class Configuration
7
- attr_accessor :access_token
8
+ # @return [String]
9
+ attr_accessor :token
10
+ # @return [Logger]
8
11
  attr_accessor :logger
12
+
9
13
  def initialize
10
14
  logger = Logger.new(STDOUT)
11
15
  logger.level = :warn
@@ -0,0 +1,144 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TimeTree
4
+ # Model for TimeTree event or keep.
5
+ class Event < BaseModel
6
+ # @return [Striing]
7
+ attr_accessor :category
8
+ # @return [Striing]
9
+ attr_accessor :title
10
+ # @return [Boolean]
11
+ attr_accessor :all_day
12
+ # @return [Time]
13
+ attr_accessor :start_at
14
+ # @return [Striing]
15
+ attr_accessor :start_timezone
16
+ # @return [Time]
17
+ attr_accessor :end_at
18
+ # @return [String]
19
+ attr_accessor :end_timezone
20
+ # @return [String]
21
+ attr_accessor :recurrences
22
+ # @return [String]
23
+ attr_accessor :recurring_uuid
24
+ # @return [String]
25
+ attr_accessor :description
26
+ # @return [String]
27
+ attr_accessor :location
28
+ # @return [String]
29
+ attr_accessor :url
30
+ # @return [Time]
31
+ attr_accessor :updated_at
32
+ # @return [Time]
33
+ attr_accessor :created_at
34
+ # calendar's id.
35
+ # @return [String]
36
+ attr_accessor :calendar_id
37
+
38
+ # @return [TimeTree::User]
39
+ attr_reader :creator
40
+ # @return [TimeTree::Label]
41
+ attr_reader :label
42
+ # @return [Array<TimeTree::User>]
43
+ attr_reader :attendees
44
+
45
+ TIME_FIELDS = %i[start_at end_at updated_at created_at].freeze
46
+ RELATIONSHIPS = %i[creator label attendees].freeze
47
+
48
+ #
49
+ # Creates an event to the associated calendar.
50
+ #
51
+ # @return [TimeTree::Event]
52
+ # @raise [TimeTree::Error] if @client is not set.
53
+ # @raise [TimeTree::ApiError] if the http response status will not success.
54
+ # @since 0.0.1
55
+ def create
56
+ raise Error, 'client is required.' if @client.nil?
57
+
58
+ @client.create_event calendar_id, data_params
59
+ end
60
+
61
+ #
62
+ # Creates comment to the event.
63
+ #
64
+ # @return [TimeTree::Activity]
65
+ # @raise [TimeTree::Error] if @client is not set.
66
+ # @raise [TimeTree::ApiError] if the http response status will not success.
67
+ # @since 0.0.1
68
+ def create_comment(message)
69
+ raise Error, '@client is nil.' if @client.nil?
70
+
71
+ params = { type: 'activity', attributes: { calendar_id: calendar_id, event_id: id, content: message } }
72
+ activity = to_model params
73
+ return if activity.nil?
74
+
75
+ activity.create
76
+ end
77
+
78
+ #
79
+ # Updates the event.
80
+ #
81
+ # @return [TimeTree::Event]
82
+ # @raise [TimeTree::Error] if @client is not set.
83
+ # @raise [TimeTree::Error] if the id property is not set.
84
+ # @raise [TimeTree::ApiError] if the http response status will not success.
85
+ # @since 0.0.1
86
+ def update
87
+ raise Error, '@client is nil.' if @client.nil?
88
+ raise Error, 'id is required.' if id.nil?
89
+
90
+ @client.update_event calendar_id, id, data_params
91
+ end
92
+
93
+ #
94
+ # Deletes the event.
95
+ #
96
+ # @return [true] if the operation succeeded.
97
+ # @raise [TimeTree::Error] if @client is not set.
98
+ # @raise [TimeTree::Error] if the id property is not set.
99
+ # @raise [TimeTree::ApiError] if the http response status will not success.
100
+ # @since 0.0.1
101
+ def delete
102
+ raise Error, '@client is nil.' if @client.nil?
103
+ raise Error, 'id is required.' if id.nil?
104
+
105
+ @client.delete_event calendar_id, id
106
+ end
107
+
108
+ #
109
+ # convert to a TimeTree request body format.
110
+ #
111
+ # @return [Hash]
112
+ # @since 0.0.1
113
+ def data_params
114
+ {
115
+ data: {
116
+ attributes: {
117
+ category: category,
118
+ title: title,
119
+ all_day: all_day,
120
+ start_at: start_at.iso8601,
121
+ start_timezone: start_timezone,
122
+ end_at: end_at.iso8601,
123
+ end_timezone: end_timezone,
124
+ description: description,
125
+ location: location,
126
+ url: url
127
+ },
128
+ relationships: relationships_params
129
+ }
130
+ }
131
+ end
132
+
133
+ private
134
+
135
+ def relationships_params
136
+ current_label = label ? { type: 'label', id: label.id } : @relationships[:label]
137
+ current_attendees = attendees ? attendees.map { |u| { type: 'user', id: u.id } } : @relationships[:attendees]
138
+ {
139
+ label: { data: current_label },
140
+ attendees: { data: current_attendees }
141
+ }
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'faraday'
4
+ require 'faraday_middleware'
5
+
6
+ module TimeTree
7
+ # Command for HTTP request.
8
+ class HttpCommand
9
+ def initialize(host, client)
10
+ @host = host
11
+ @client = client
12
+ @logger = TimeTree.configuration.logger
13
+ end
14
+
15
+ # @param path [String] String or URI to access.
16
+ # @param params [Hash] Hash of URI query unencoded key/value pairs.
17
+ def get(path, params = {})
18
+ logger.info "GET #{connection.build_url("#{@host}#{path}", params)}"
19
+ res = connection.get path, params
20
+ @client.update_ratelimit(res)
21
+ logger.debug "Response status:#{res.status}, body:#{res.body}"
22
+ res
23
+ end
24
+
25
+ # @param path [String] String or URI to access.
26
+ # @param body_params [Hash]
27
+ # The request bodythat will eventually be converted to JSON.
28
+ def post(path, body_params = {})
29
+ @logger.debug "POST #{@host}#{path} body:#{body_params}"
30
+ headers = { 'Content-Type' => 'application/json' }
31
+ res = connection.run_request :post, path, body_params.to_json, headers
32
+ @client.update_ratelimit(res)
33
+ logger.debug "Response status:#{res.status}, body:#{res.body}"
34
+ res
35
+ end
36
+
37
+ # @param path [String] String or URI to access.
38
+ # @param body_params [Hash]
39
+ # The request bodythat will eventually be converted to JSON.
40
+ def put(path, body_params = {})
41
+ logger.debug "PUT #{@host}#{path} body:#{body_params}"
42
+ headers = { 'Content-Type' => 'application/json' }
43
+ res = connection.run_request :put, path, body_params.to_json, headers
44
+ @client.update_ratelimit(res)
45
+ logger.debug "Response status:#{res.status}, body:#{res.body}"
46
+ res
47
+ end
48
+
49
+ # @param path [String] String or URI to access.
50
+ # @param params [Hash] Hash of URI query unencoded key/value pairs.
51
+ def delete(path, params = {})
52
+ @logger.debug "DELETE #{@host}#{path} params:#{params}"
53
+ res = connection.delete path, params
54
+ @client.update_ratelimit(res)
55
+ logger.debug "Response status:#{res.status}, body:#{res.body}"
56
+ res
57
+ end
58
+
59
+ private
60
+
61
+ attr_reader :logger
62
+
63
+ def connection
64
+ Faraday.new(
65
+ url: @host,
66
+ headers: base_request_headers
67
+ ) do |builder|
68
+ builder.response :json, parser_options: { symbolize_names: true }, content_type: /\bjson$/
69
+ end
70
+ end
71
+
72
+ def base_request_headers
73
+ {
74
+ 'Accept' => 'application/vnd.timetree.v1+json',
75
+ 'Authorization' => "Bearer #{@client.token}"
76
+ }
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TimeTree
4
+ # Model for TimeTree color theme.
5
+ class Label < BaseModel
6
+ # @return [String]
7
+ attr_accessor :name
8
+ # @return [String]
9
+ attr_accessor :color
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TimeTree
4
+ # Model for TimeTree user.
5
+ class User < BaseModel
6
+ # @return [String]
7
+ attr_accessor :name
8
+ # @return [String]
9
+ attr_accessor :description
10
+ # @return [String]
11
+ attr_accessor :image_url
12
+ end
13
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TimeTree
4
- VERSION = '0.0.1'
4
+ VERSION = '0.1.0'
5
5
  end
@@ -30,6 +30,7 @@ Gem::Specification.new do |spec|
30
30
 
31
31
  spec.add_runtime_dependency 'faraday', '~> 1.0.1'
32
32
  spec.add_runtime_dependency 'faraday_middleware', '~> 1.0.0'
33
+ spec.add_runtime_dependency 'zeitwerk', '~> 2.3.0'
33
34
 
34
35
  spec.add_development_dependency 'bundler', '~> 2.0'
35
36
  spec.add_development_dependency 'minitest', '~> 5.14.0'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timetree
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kenji Koshikawa
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-06-21 00:00:00.000000000 Z
11
+ date: 2020-06-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: 1.0.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: zeitwerk
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 2.3.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 2.3.0
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: bundler
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -127,9 +141,16 @@ files:
127
141
  - bin/console
128
142
  - bin/setup
129
143
  - lib/timetree.rb
144
+ - lib/timetree/activity.rb
145
+ - lib/timetree/api_error.rb
146
+ - lib/timetree/base_model.rb
147
+ - lib/timetree/calendar.rb
130
148
  - lib/timetree/client.rb
131
149
  - lib/timetree/configuration.rb
132
- - lib/timetree/models.rb
150
+ - lib/timetree/event.rb
151
+ - lib/timetree/http_command.rb
152
+ - lib/timetree/label.rb
153
+ - lib/timetree/user.rb
133
154
  - lib/timetree/version.rb
134
155
  - timetree.gemspec
135
156
  homepage: https://github.com/koshilife/timetree-api-ruby-client
@@ -1,282 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'time'
4
-
5
- module TimeTree
6
- class BaseModel
7
- attr_reader :id
8
- attr_reader :type
9
- attr_accessor :relationships
10
-
11
- # @param data [Hash]
12
- # @param client [TimeTree::Client]
13
- # @return [TimeTree::BaseModel]
14
- def self.to_model(data, included: nil, client: nil)
15
- id = data[:id]
16
- type = data[:type]
17
- return if type.nil?
18
-
19
- attributes = data[:attributes] || {}
20
- relationships = data[:relationships] || {}
21
- params = {
22
- id: id,
23
- type: type,
24
- client: client,
25
- attributes: attributes,
26
- relationships: relationships,
27
- included: included
28
- }
29
-
30
- case type
31
- when 'user'
32
- User.new(**params)
33
- when 'label'
34
- Label.new(**params)
35
- when 'event'
36
- Event.new(**params)
37
- when 'calendar'
38
- Calendar.new(**params)
39
- when 'activity'
40
- Activity.new(**params)
41
- end
42
- end
43
-
44
- def initialize(id:, type:, client: nil, attributes: nil, relationships: nil, included: nil)
45
- @id = id
46
- @type = type
47
- @client = client
48
- set_attributes attributes
49
- set_relationships relationships, included
50
- end
51
-
52
- def inspect
53
- "\#<#{self.class}:#{object_id} id:#{id}>"
54
- end
55
-
56
- private
57
-
58
- def to_model(data)
59
- self.class.to_model data, client: @client
60
- end
61
-
62
- def set_attributes(attributes)
63
- return unless attributes.is_a? Hash
64
- return if attributes.empty?
65
-
66
- setter_methods = self.class.instance_methods.select { |method| method.to_s.end_with? '=' }
67
- attributes.each do |key, value|
68
- setter = "#{key.to_sym}=".to_sym
69
- next unless setter_methods.include? setter
70
-
71
- if defined?(self.class::TIME_FIELDS) && self.class::TIME_FIELDS.include?(key)
72
- value = Time.parse value
73
- end
74
- instance_variable_set "@#{key}", value
75
- end
76
- end
77
-
78
- def set_relationships(relationships, included)
79
- return unless relationships.is_a? Hash
80
- return if relationships.empty?
81
- return unless defined? self.class::RELATIONSHIPS
82
- return if self.class::RELATIONSHIPS.empty?
83
-
84
- self.class::RELATIONSHIPS.each do |key|
85
- relation = relationships[key]
86
- next unless relation
87
- next unless relation[:data]
88
-
89
- @relationships ||= {}
90
- @relationships[key] = relation[:data]
91
- end
92
-
93
- return if included.nil?
94
- return unless included.is_a? Array
95
- return if included.empty?
96
-
97
- set_relationship_data_if_included(included)
98
- end
99
-
100
- def set_relationship_data_if_included(included)
101
- @_relation_data_dic = {}
102
- included.each do |data|
103
- item = to_model(data)
104
- next unless item
105
-
106
- @_relation_data_dic[item.type] ||= {}
107
- @_relation_data_dic[item.type][item.id] = item
108
- end
109
- detect_relation_data = lambda { |type, id|
110
- return unless @_relation_data_dic[type]
111
-
112
- @_relation_data_dic[type][id]
113
- }
114
- @relationships.each do |key, id_data|
115
- relation_data = nil
116
- if id_data.is_a? Array
117
- relation_data = []
118
- id_data.each do |d|
119
- item = detect_relation_data.call(d[:type], d[:id])
120
- relation_data << item if item
121
- end
122
- elsif id_data.is_a? Hash
123
- relation_data = detect_relation_data.call(id_data[:type], id_data[:id])
124
- end
125
- instance_variable_set "@#{key}", relation_data if relation_data
126
- end
127
- end
128
- end
129
-
130
- class User < BaseModel
131
- attr_accessor :name
132
- attr_accessor :description
133
- attr_accessor :image_url
134
- end
135
-
136
- class Label < BaseModel
137
- attr_accessor :name
138
- attr_accessor :color
139
- end
140
-
141
- class Calendar < BaseModel
142
- attr_accessor :name
143
- attr_accessor :description
144
- attr_accessor :color
145
- attr_accessor :order
146
- attr_accessor :image_url
147
- attr_accessor :created_at
148
-
149
- TIME_FIELDS = %i[created_at].freeze
150
- RELATIONSHIPS = %i[labels members].freeze
151
-
152
- def event(event_id)
153
- return if @client.nil?
154
-
155
- @client.event id, event_id
156
- end
157
-
158
- def upcoming_events(days: 7, timezone: 'UTC')
159
- return if @client.nil?
160
-
161
- @client.upcoming_events id, days: days, timezone: timezone
162
- end
163
-
164
- def labels
165
- return @labels if defined? @labels
166
- return if @client.nil?
167
-
168
- @labels = @client.calendar_labels id
169
- end
170
-
171
- def members
172
- return @members if defined? @members
173
- return if @client.nil?
174
-
175
- @members = @client.calendar_members id
176
- end
177
- end
178
-
179
- class Event < BaseModel
180
- attr_accessor :category
181
- attr_accessor :title
182
- attr_accessor :all_day
183
- attr_accessor :start_at
184
- attr_accessor :start_timezone
185
- attr_accessor :end_at
186
- attr_accessor :end_timezone
187
- attr_accessor :recurrences
188
- attr_accessor :recurring_uuid
189
- attr_accessor :description
190
- attr_accessor :location
191
- attr_accessor :url
192
- attr_accessor :updated_at
193
- attr_accessor :created_at
194
- attr_accessor :calendar_id
195
-
196
- attr_reader :creator
197
- attr_reader :label
198
- attr_reader :attendees
199
-
200
- TIME_FIELDS = %i[start_at end_at updated_at created_at].freeze
201
- RELATIONSHIPS = %i[creator label attendees].freeze
202
-
203
- def create
204
- return if @client.nil?
205
-
206
- @client.create_event calendar_id, data_params
207
- end
208
-
209
- def create_comment(message)
210
- return if @client.nil?
211
-
212
- params = { type: 'activity', attributes: { calendar_id: calendar_id, event_id: id, content: message } }
213
- activity = to_model params
214
- return if activity.nil?
215
-
216
- activity.create
217
- end
218
-
219
- def update
220
- return if @client.nil?
221
- return if id.nil?
222
-
223
- @client.update_event calendar_id, id, data_params
224
- end
225
-
226
- def delete
227
- return if @client.nil?
228
- return if id.nil?
229
-
230
- @client.delete_event calendar_id, id
231
- end
232
-
233
- def data_params
234
- attributes_params = {
235
- category: category,
236
- title: title,
237
- all_day: all_day,
238
- start_at: start_at.iso8601,
239
- start_timezone: start_timezone,
240
- end_at: end_at.iso8601,
241
- end_timezone: end_timezone,
242
- description: description,
243
- location: location,
244
- url: url
245
- }
246
- relationhips_params = {}
247
- if @relationships[:label]
248
- label_data = { id: @relationships[:label], type: 'label' }
249
- relationhips_params[:label] = { data: label_data }
250
- end
251
- if @relationships[:attendees]
252
- attendees_data = @relationships[:attendees].map { |_id| { id: _id, type: 'user' } }
253
- relationhips_params[:attendees] = { data: attendees_data }
254
- end
255
- {
256
- data: { attributes: attributes_params, relationships: relationhips_params }
257
- }
258
- end
259
- end
260
-
261
- class Activity < BaseModel
262
- attr_accessor :content
263
- attr_accessor :updated_at
264
- attr_accessor :created_at
265
- attr_accessor :calendar_id
266
- attr_accessor :event_id
267
-
268
- TIME_FIELDS = %i[updated_at created_at].freeze
269
-
270
- def create
271
- return if @client.nil?
272
-
273
- @client.create_activity calendar_id, event_id, data_params
274
- end
275
-
276
- def data_params
277
- {
278
- data: { attributes: { content: content } }
279
- }
280
- end
281
- end
282
- end