timetree 0.3.2 → 1.0.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.
@@ -5,13 +5,20 @@ require 'logger'
5
5
  module TimeTree
6
6
  # TimeTree apis client configuration.
7
7
  class Configuration
8
- # @return [String]
9
- attr_accessor :token
8
+ # @return [String] OAuthApp's access token
9
+ attr_accessor :oauth_app_token
10
+
11
+ # @return [String] CalendarApp's app id
12
+ attr_accessor :calendar_app_application_id
13
+ # @return [String] CalendarApp's private key content#
14
+ # e.g. File.read('<YOUR_PATH_TO_PEM_FILE>')
15
+ attr_accessor :calendar_app_private_key
16
+
10
17
  # @return [Logger]
11
18
  attr_accessor :logger
12
19
 
13
20
  def initialize
14
- @logger = Logger.new(STDOUT)
21
+ @logger = Logger.new $stdout
15
22
  @logger.level = :warn
16
23
  end
17
24
  end
@@ -25,10 +25,10 @@ module TimeTree
25
25
  # @param path [String] String or URI to access.
26
26
  # @param body_params [Hash]
27
27
  # The request bodythat will eventually be converted to JSON.
28
- def post(path, body_params = {})
28
+ def post(path, body_params = {}, &block)
29
29
  @logger.debug "POST #{@host}#{path} body:#{body_params}"
30
30
  headers = {'Content-Type' => 'application/json'}
31
- res = connection.run_request :post, path, body_params.to_json, headers
31
+ res = connection.run_request :post, path, body_params.to_json, headers, &block
32
32
  @client.update_ratelimit(res)
33
33
  @logger.debug "Response status:#{res.status}, body:#{res.body}"
34
34
  res
@@ -31,7 +31,7 @@ module TimeTree
31
31
  # @since 0.0.1
32
32
  def create
33
33
  check_client
34
- @client.create_activity calendar_id, event_id, data_params
34
+ _create
35
35
  end
36
36
 
37
37
  #
@@ -44,5 +44,15 @@ module TimeTree
44
44
  data: {attributes: {content: content}}
45
45
  }
46
46
  end
47
+
48
+ private
49
+
50
+ def _create
51
+ if @client.is_a?(CalendarApp::Client)
52
+ @client.create_activity(event_id, data_params)
53
+ else
54
+ @client.create_activity(calendar_id, event_id, data_params)
55
+ end
56
+ end
47
57
  end
48
58
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'timetree/models/base_model'
4
+
5
+ module TimeTree
6
+ # Model for TimeTree application.
7
+ class Application < BaseModel
8
+ # @return [String]
9
+ attr_accessor :name
10
+ # @return [String]
11
+ attr_accessor :description
12
+ # @return [String]
13
+ attr_accessor :image_url
14
+ end
15
+ end
@@ -15,10 +15,10 @@ module TimeTree
15
15
  # @param data [Hash]
16
16
  # TimeTree apis's response data.
17
17
  # @param included [Hash]
18
- # @param client [TimeTree::Client]
19
- # @return [TimeTree::User, TimeTree::Label, TimeTree::Calendar, TimeTree::Event, TimeTree::Activity]
18
+ # @param client [TimeTree::OAuthApp::Client, TimeTree::CalendarApp::Client]
19
+ # @return [TimeTree::User, TimeTree::Label, TimeTree::Calendar, TimeTree::Event, TimeTree::Activity, Hash]
20
20
  # A TimeTree model object that be based on the type.
21
- # @raise [TimeTree::Error] if the type property is not set or unknown.
21
+ # @raise [TimeTree::Error] if the type property is not set.
22
22
  # @since 0.0.1
23
23
  def self.to_model(data, included: nil, client: nil) # rubocop:disable all
24
24
  id = data[:id]
@@ -37,18 +37,22 @@ module TimeTree
37
37
  }
38
38
 
39
39
  case type
40
- when 'user'
41
- User.new(**params)
42
- when 'label'
43
- Label.new(**params)
40
+ when 'activity'
41
+ Activity.new(**params)
42
+ when 'application'
43
+ Application.new(**params)
44
44
  when 'calendar'
45
45
  Calendar.new(**params)
46
46
  when 'event'
47
47
  Event.new(**params)
48
- when 'activity'
49
- Activity.new(**params)
48
+ when 'label'
49
+ Label.new(**params)
50
+ when 'user'
51
+ User.new(**params)
50
52
  else
51
- raise Error.new("type '#{type}' is unknown.")
53
+ TimeTree.configuration.logger.warn("type '#{type}' is unknown. id:#{id}")
54
+ # when unexpected model type, return the 'data' argument.
55
+ data
52
56
  end
53
57
  end
54
58
 
@@ -114,8 +118,17 @@ module TimeTree
114
118
  item = to_model(data)
115
119
  next unless item
116
120
 
117
- @_relation_data_dic[item.type] ||= {}
118
- @_relation_data_dic[item.type][item.id] = item
121
+ if item.is_a? Hash
122
+ item_id = item[:id]
123
+ item_type = item[:type]
124
+ else
125
+ item_id = item.id
126
+ item_type = item.type
127
+ end
128
+ next unless item_id && item_type
129
+
130
+ @_relation_data_dic[item_type] ||= {}
131
+ @_relation_data_dic[item_type][item_id] = item
119
132
  end
120
133
  detect_relation_data = lambda { |type, id|
121
134
  return unless @_relation_data_dic[type]
@@ -32,7 +32,7 @@ module TimeTree
32
32
  # @since 0.0.1
33
33
  def event(event_id)
34
34
  check_client
35
- @client.event id, event_id
35
+ get_event(event_id)
36
36
  end
37
37
 
38
38
  #
@@ -48,7 +48,7 @@ module TimeTree
48
48
  # @since 0.0.1
49
49
  def upcoming_events(days: 7, timezone: 'UTC')
50
50
  check_client
51
- @client.upcoming_events id, days: days, timezone: timezone
51
+ get_upcoming_event(days, timezone)
52
52
  end
53
53
 
54
54
  #
@@ -62,7 +62,7 @@ module TimeTree
62
62
  return @members if defined? @members
63
63
 
64
64
  check_client
65
- @members = @client.calendar_members id
65
+ @members = get_members
66
66
  end
67
67
 
68
68
  #
@@ -76,7 +76,41 @@ module TimeTree
76
76
  return @labels if defined? @labels
77
77
 
78
78
  check_client
79
- @labels = @client.calendar_labels id
79
+ @labels = get_labels
80
+ end
81
+
82
+ private
83
+
84
+ def get_event(event_id)
85
+ if @client.is_a?(CalendarApp::Client)
86
+ @client.event(event_id)
87
+ else
88
+ @client.event(id, event_id)
89
+ end
90
+ end
91
+
92
+ def get_upcoming_event(days, timezone)
93
+ if @client.is_a?(CalendarApp::Client)
94
+ @client.upcoming_events(days: days, timezone: timezone)
95
+ else
96
+ @client.upcoming_events(id, days: days, timezone: timezone)
97
+ end
98
+ end
99
+
100
+ def get_members
101
+ if @client.is_a?(CalendarApp::Client)
102
+ @client.calendar_members
103
+ else
104
+ @client.calendar_members(id)
105
+ end
106
+ end
107
+
108
+ def get_labels
109
+ if @client.is_a?(CalendarApp::Client)
110
+ raise Error.new 'CalendarApp does not support label api'
111
+ else
112
+ @client.calendar_labels(id)
113
+ end
80
114
  end
81
115
  end
82
116
  end
@@ -56,7 +56,7 @@ module TimeTree
56
56
  # @since 0.0.1
57
57
  def create
58
58
  check_client
59
- @client.create_event calendar_id, data_params
59
+ _create_event
60
60
  end
61
61
 
62
62
  #
@@ -68,7 +68,7 @@ module TimeTree
68
68
  # @since 0.0.1
69
69
  def update
70
70
  check_client
71
- @client.update_event calendar_id, id, data_params
71
+ _update_event
72
72
  end
73
73
 
74
74
  #
@@ -80,7 +80,7 @@ module TimeTree
80
80
  # @since 0.0.1
81
81
  def delete
82
82
  check_client
83
- @client.delete_event calendar_id, id
83
+ _delete_event
84
84
  end
85
85
 
86
86
  #
@@ -132,5 +132,29 @@ module TimeTree
132
132
  attendees: {data: current_attendees}
133
133
  }
134
134
  end
135
+
136
+ def _create_event
137
+ if @client.is_a?(CalendarApp::Client)
138
+ @client.create_event(data_params)
139
+ else
140
+ @client.create_event(calendar_id, data_params)
141
+ end
142
+ end
143
+
144
+ def _update_event
145
+ if @client.is_a?(CalendarApp::Client)
146
+ @client.update_event(id, data_params)
147
+ else
148
+ @client.update_event(calendar_id, id, data_params)
149
+ end
150
+ end
151
+
152
+ def _delete_event
153
+ if @client.is_a?(CalendarApp::Client)
154
+ @client.delete_event(id)
155
+ else
156
+ @client.delete_event(calendar_id, id)
157
+ end
158
+ end
135
159
  end
136
160
  end
@@ -0,0 +1,256 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TimeTree
4
+ module OAuthApp
5
+ # TimeTree API OAuthApp client.
6
+ class Client < BaseClient
7
+ # @return [String]
8
+ attr_reader :token
9
+
10
+ # @param token [String] a TimeTree's access token.
11
+ def initialize(token = nil)
12
+ @token = token || TimeTree.configuration.oauth_app_token
13
+ check_token
14
+ @http_cmd = HttpCommand.new(API_HOST, self)
15
+ end
16
+
17
+ #
18
+ # Get current user information.
19
+ #
20
+ # @return [TimeTree::User]
21
+ # @raise [TimeTree::ApiError] if the http response status will not success.
22
+ # @since 0.0.1
23
+ def current_user
24
+ res = @http_cmd.get '/user'
25
+ raise ApiError.new(res) if res.status != 200
26
+
27
+ to_model res.body[:data]
28
+ end
29
+
30
+ #
31
+ # Get a single calendar's information.
32
+ #
33
+ # @param cal_id [String] calendar's id.
34
+ # @param include_relationships [Array<symbol>]
35
+ # includes association's object in the response.
36
+ # @return [TimeTree::Calendar]
37
+ # @raise [TimeTree::Error] if the cal_id arg is empty.
38
+ # @raise [TimeTree::ApiError] if the http response status will not success.
39
+ # @since 0.0.1
40
+ def calendar(cal_id, include_relationships: nil)
41
+ check_calendar_id cal_id
42
+ params = relationships_params(include_relationships, Calendar::RELATIONSHIPS)
43
+ res = @http_cmd.get "/calendars/#{cal_id}", params
44
+ raise ApiError.new(res) if res.status != 200
45
+
46
+ to_model(res.body[:data], included: res.body[:included])
47
+ end
48
+
49
+ #
50
+ # Get calendar list that current user can access.
51
+ #
52
+ # @param include_relationships [Array<symbol>]
53
+ # includes association's object in the response.
54
+ # @return [Array<TimeTree::Calendar>]
55
+ # @raise [TimeTree::ApiError] if the http response status will not success.
56
+ # @since 0.0.1
57
+ def calendars(include_relationships: nil)
58
+ params = relationships_params(include_relationships, Calendar::RELATIONSHIPS)
59
+ res = @http_cmd.get '/calendars', params
60
+ raise ApiError.new(res) if res.status != 200
61
+
62
+ included = res.body[:included]
63
+ res.body[:data].map { |item| to_model(item, included: included) }
64
+ end
65
+
66
+ #
67
+ # Get a calendar's label information used in event.
68
+ #
69
+ # @param cal_id [String] calendar's id.
70
+ # @return [Array<TimeTree::Label>]
71
+ # @raise [TimeTree::Error] if the cal_id arg is empty.
72
+ # @raise [TimeTree::ApiError] if the http response status will not success.
73
+ # @since 0.0.1
74
+ def calendar_labels(cal_id)
75
+ check_calendar_id cal_id
76
+ res = @http_cmd.get "/calendars/#{cal_id}/labels"
77
+ raise ApiError.new(res) if res.status != 200
78
+
79
+ res.body[:data].map { |item| to_model(item) }
80
+ end
81
+
82
+ #
83
+ # Get a calendar's member information.
84
+ #
85
+ # @param cal_id [String] calendar's id.
86
+ # @return [Array<TimeTree::User>]
87
+ # @raise [TimeTree::Error] if the cal_id arg is empty.
88
+ # @raise [TimeTree::ApiError] if the http response status will not success.
89
+ # @since 0.0.1
90
+ def calendar_members(cal_id)
91
+ check_calendar_id cal_id
92
+ res = @http_cmd.get "/calendars/#{cal_id}/members"
93
+ raise ApiError.new(res) if res.status != 200
94
+
95
+ res.body[:data].map { |item| to_model item }
96
+ end
97
+
98
+ #
99
+ # Get the event's information.
100
+ #
101
+ # @param cal_id [String] calendar's id.
102
+ # @param event_id [String] event's id.
103
+ # @param include_relationships [Array<symbol>]
104
+ # includes association's object in the response.
105
+ # @return [TimeTree::Event]
106
+ # @raise [TimeTree::Error] if the cal_id arg is empty.
107
+ # @raise [TimeTree::Error] if the event_id arg is empty.
108
+ # @raise [TimeTree::ApiError] if the http response status will not success.
109
+ # @since 0.0.1
110
+ def event(cal_id, event_id, include_relationships: nil)
111
+ check_calendar_id cal_id
112
+ check_event_id event_id
113
+ params = relationships_params(include_relationships, Event::RELATIONSHIPS)
114
+ res = @http_cmd.get "/calendars/#{cal_id}/events/#{event_id}", params
115
+ raise ApiError.new(res) if res.status != 200
116
+
117
+ ev = to_model(res.body[:data], included: res.body[:included])
118
+ ev.calendar_id = cal_id
119
+ ev
120
+ end
121
+
122
+ #
123
+ # Get the events' information after a request date.
124
+ #
125
+ # @param cal_id[String] calendar's id.
126
+ # @param days [Integer] The number of days to get.
127
+ # @param timezone [String] Timezone.
128
+ # @param include_relationships [Array<symbol>]
129
+ # includes association's object in the response.
130
+ # @return [Array<TimeTree::Event>]
131
+ # @raise [TimeTree::Error] if the cal_id arg is empty.
132
+ # @raise [TimeTree::ApiError] if the http response status will not success.
133
+ # @since 0.0.1
134
+ def upcoming_events(cal_id, days: 7, timezone: 'UTC', include_relationships: nil)
135
+ check_calendar_id cal_id
136
+ params = relationships_params(include_relationships, Event::RELATIONSHIPS)
137
+ params.merge!(days: days, timezone: timezone)
138
+ res = @http_cmd.get "/calendars/#{cal_id}/upcoming_events", params
139
+ raise ApiError.new(res) if res.status != 200
140
+
141
+ included = res.body[:included]
142
+ res.body[:data].map do |item|
143
+ ev = to_model(item, included: included)
144
+ ev.calendar_id = cal_id
145
+ ev
146
+ end
147
+ end
148
+
149
+ #
150
+ # Creates an event to the calendar.
151
+ #
152
+ # @param cal_id [String] calendar's id.
153
+ # @param params [Hash] TimeTree request body format.
154
+ # @return [TimeTree::Event]
155
+ # @raise [TimeTree::Error] if the cal_id arg is empty.
156
+ # @raise [TimeTree::ApiError] if the http response status will not success.
157
+ # @since 0.0.1
158
+ def create_event(cal_id, params)
159
+ check_calendar_id cal_id
160
+ res = @http_cmd.post "/calendars/#{cal_id}/events", params
161
+ raise ApiError.new(res) if res.status != 201
162
+
163
+ ev = to_model res.body[:data]
164
+ ev.calendar_id = cal_id
165
+ ev
166
+ end
167
+
168
+ #
169
+ # Updates an event.
170
+ #
171
+ # @param cal_id [String] calendar's id.
172
+ # @param event_id [String] event's id.
173
+ # @param params [Hash]
174
+ # event's information specified in TimeTree request body format.
175
+ # @return [TimeTree::Event]
176
+ # @raise [TimeTree::Error] if the cal_id arg is empty.
177
+ # @raise [TimeTree::Error] if the event_id arg is empty.
178
+ # @raise [TimeTree::ApiError] if the http response status will not success.
179
+ # @since 0.0.1
180
+ def update_event(cal_id, event_id, params)
181
+ check_calendar_id cal_id
182
+ check_event_id event_id
183
+ res = @http_cmd.put "/calendars/#{cal_id}/events/#{event_id}", params
184
+ raise ApiError.new(res) if res.status != 200
185
+
186
+ ev = to_model res.body[:data]
187
+ ev.calendar_id = cal_id
188
+ ev
189
+ end
190
+
191
+ #
192
+ # Deletes an event.
193
+ #
194
+ # @param cal_id [String] calendar's id.
195
+ # @param event_id [String] event's id.
196
+ # @return [true] if the operation succeeded.
197
+ # @raise [TimeTree::Error] if the cal_id arg is empty.
198
+ # @raise [TimeTree::Error] if the event_id arg is empty.
199
+ # @raise [TimeTree::ApiError] if the http response status will not success.
200
+ # @since 0.0.1
201
+ def delete_event(cal_id, event_id)
202
+ check_calendar_id cal_id
203
+ check_event_id event_id
204
+ res = @http_cmd.delete "/calendars/#{cal_id}/events/#{event_id}"
205
+ raise ApiError.new(res) if res.status != 204
206
+
207
+ true
208
+ end
209
+
210
+ #
211
+ # Creates comment to an event.
212
+ #
213
+ # @param cal_id [String] calendar's id.
214
+ # @param event_id [String] event's id.
215
+ # @param params [Hash]
216
+ # comment's information specified in TimeTree request body format.
217
+ # @return [TimeTree::Activity]
218
+ # @raise [TimeTree::Error] if the cal_id arg is empty.
219
+ # @raise [TimeTree::Error] if the event_id arg is empty.
220
+ # @raise [TimeTree::ApiError] if the http response status is not success.
221
+ # @since 0.0.1
222
+ def create_activity(cal_id, event_id, params)
223
+ check_calendar_id cal_id
224
+ check_event_id event_id
225
+ res = @http_cmd.post "/calendars/#{cal_id}/events/#{event_id}/activities", params
226
+ raise ApiError.new(res) if res.status != 201
227
+
228
+ activity = to_model res.body[:data]
229
+ activity.calendar_id = cal_id
230
+ activity.event_id = event_id
231
+ activity
232
+ end
233
+
234
+ def inspect
235
+ limit_info = nil
236
+ if defined?(@ratelimit_limit) && @ratelimit_limit
237
+ limit_info = " ratelimit:#{ratelimit_remaining}/#{ratelimit_limit}"
238
+ end
239
+ if defined?(@ratelimit_reset_at) && @ratelimit_reset_at
240
+ limit_info = "#{limit_info}, reset_at:#{ratelimit_reset_at.strftime('%m/%d %R')}"
241
+ end
242
+ "\#<#{self.class}:#{object_id}#{limit_info}>"
243
+ end
244
+
245
+ private
246
+
247
+ def check_token
248
+ check_required_property(@token, 'token')
249
+ end
250
+
251
+ def check_calendar_id(value)
252
+ check_required_property(value, 'calendar_id')
253
+ end
254
+ end
255
+ end
256
+ end