timetree 0.3.2 → 1.0.0

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