help_scout 0.12.1 → 1.0.0.beta1
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.
- checksums.yaml +5 -5
- data/Gemfile +2 -0
- data/help_scout.gemspec +1 -1
- data/lib/help_scout.rb +231 -116
- data/lib/help_scout/token_storage.rb +4 -0
- data/lib/help_scout/token_storage/memory.rb +13 -0
- data/lib/help_scout/token_storage/redis.rb +19 -0
- data/lib/help_scout/version.rb +1 -1
- metadata +12 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ab8a0fda60b049cfcabe64b115dd2d35df71184e
|
4
|
+
data.tar.gz: 1f42dc562130e722dbf52588f4b0ffe46e732b1c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f5c6c5ab4751da5bfb99b11e788f008d43e64092a5e1a2f3221512ab657cd4fed2bcd70521c1f6357a95c047f93ef87a742f3700f7ff207a9675c6c39ed2f236
|
7
|
+
data.tar.gz: 593e12e794ea41ab29075c3be541f5fb5ffa9e65eb293ce37833cf6d0870c57918458a654ee88b97fd5f0417bf25411cbff9b69cd60a11815bfd5951023a8f08
|
data/Gemfile
CHANGED
data/help_scout.gemspec
CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.add_runtime_dependency "httparty", "~> 0.14"
|
22
22
|
|
23
|
-
spec.add_development_dependency "bundler"
|
23
|
+
spec.add_development_dependency "bundler"
|
24
24
|
spec.add_development_dependency "rake", "~> 10.5"
|
25
25
|
spec.add_development_dependency "rspec", "~> 3.5"
|
26
26
|
spec.add_development_dependency "webmock", "~> 2.1"
|
data/lib/help_scout.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
require "help_scout/version"
|
2
|
+
require "help_scout/token_storage/memory"
|
3
|
+
require "help_scout/token_storage/redis"
|
4
|
+
|
2
5
|
require "httparty"
|
3
6
|
|
4
7
|
class HelpScout
|
@@ -10,188 +13,284 @@ class HelpScout
|
|
10
13
|
class ForbiddenError < StandardError; end
|
11
14
|
class ServiceUnavailable < StandardError; end
|
12
15
|
|
16
|
+
class InvalidDataError < StandardError; end
|
17
|
+
|
13
18
|
# Status codes used by Help Scout, not all are implemented in this gem yet.
|
14
|
-
#
|
19
|
+
# https://developer.helpscout.com/mailbox-api/overview/status_codes/
|
15
20
|
HTTP_OK = 200
|
16
21
|
HTTP_CREATED = 201
|
17
22
|
HTTP_NO_CONTENT = 204
|
18
23
|
HTTP_BAD_REQUEST = 400
|
24
|
+
HTTP_UNAUTHORIZED = 401
|
19
25
|
HTTP_FORBIDDEN = 403
|
20
26
|
HTTP_NOT_FOUND = 404
|
21
27
|
HTTP_TOO_MANY_REQUESTS = 429
|
22
28
|
HTTP_INTERNAL_SERVER_ERROR = 500
|
23
29
|
HTTP_SERVICE_UNAVAILABLE = 503
|
24
30
|
|
31
|
+
# https://developer.helpscout.com/mailbox-api/endpoints/conversations/list/
|
32
|
+
CONVERSATION_STATUSES = ["active", "closed", "open", "pending", "spam"]
|
33
|
+
|
34
|
+
# https://developer.helpscout.com/mailbox-api/overview/authentication/#client-credentials-flow
|
35
|
+
def generate_oauth_token
|
36
|
+
options = {
|
37
|
+
headers: {
|
38
|
+
"Content-Type": "application/json"
|
39
|
+
},
|
40
|
+
body: {
|
41
|
+
grant_type: "client_credentials",
|
42
|
+
client_id: @api_key,
|
43
|
+
client_secret: @api_secret,
|
44
|
+
}
|
45
|
+
}
|
46
|
+
options[:body] = options[:body].to_json
|
47
|
+
response = HTTParty.post("https://api.helpscout.net/v2/oauth2/token", options)
|
48
|
+
JSON.parse(response.body)["access_token"]
|
49
|
+
end
|
50
|
+
|
25
51
|
attr_accessor :last_response
|
26
52
|
|
27
|
-
def initialize(api_key)
|
53
|
+
def initialize(api_key, api_secret, token_storage = TokenStorage::Memory.new)
|
28
54
|
@api_key = api_key
|
55
|
+
@api_secret = api_secret
|
56
|
+
@token_storage = token_storage
|
29
57
|
end
|
30
58
|
|
31
59
|
# Public: Create conversation
|
32
60
|
#
|
33
61
|
# data - hash with data
|
62
|
+
# note: since v2 the status is now required, which had a default of "active" in v1.
|
34
63
|
#
|
35
|
-
# More info:
|
64
|
+
# More info: https://developer.helpscout.com/mailbox-api/endpoints/conversations/create/
|
36
65
|
#
|
37
66
|
# Returns conversation ID
|
38
67
|
def create_conversation(data)
|
68
|
+
# required_fields = ["subject", "type", "mailboxId", "status", "customer", "threads"]
|
69
|
+
|
39
70
|
post("conversations", { body: data })
|
40
71
|
|
41
|
-
|
42
|
-
conversation_uri = last_response.headers["location"]
|
43
|
-
conversation_uri.match(/(\d+)\.json$/)[1]
|
72
|
+
last_response.headers["Resource-ID"]
|
44
73
|
end
|
45
74
|
|
46
75
|
# Public: Get conversation
|
47
76
|
#
|
48
77
|
# id - conversation ID
|
78
|
+
# embed_threads - boolean - This will load in subentities, currently only
|
79
|
+
# Threads are supported by HS
|
49
80
|
#
|
50
|
-
# More info:
|
81
|
+
# More info: https://developer.helpscout.com/mailbox-api/endpoints/conversations/get/
|
51
82
|
#
|
52
83
|
# Returns hash from HS with conversation data
|
53
|
-
def get_conversation(id)
|
54
|
-
|
84
|
+
def get_conversation(id, embed_threads: false)
|
85
|
+
if embed_threads
|
86
|
+
get("conversations/#{id}?embed=threads")
|
87
|
+
else
|
88
|
+
get("conversations/#{id}")
|
89
|
+
end
|
55
90
|
end
|
56
91
|
|
57
|
-
# Public:
|
58
|
-
#
|
59
|
-
# mailbox_id - ID of mailbox (find these with get_mailboxes)
|
60
|
-
# page - integer of page to fetch (default: 1)
|
61
|
-
# modified_since - Only return conversations that have been modified since
|
62
|
-
# this UTC datetime (default: nil)
|
92
|
+
# Public: Update conversation
|
63
93
|
#
|
64
|
-
#
|
94
|
+
# id - conversation id
|
95
|
+
# data - hash with data
|
65
96
|
#
|
66
|
-
#
|
67
|
-
def
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
97
|
+
# More info: https://developer.helpscout.com/mailbox-api/endpoints/conversations/update/
|
98
|
+
def update_conversation(id, data)
|
99
|
+
instructions = []
|
100
|
+
|
101
|
+
if data[:subject]
|
102
|
+
instructions << {
|
103
|
+
op: "replace",
|
104
|
+
path: "/subject",
|
105
|
+
value: data[:subject],
|
72
106
|
}
|
73
|
-
|
107
|
+
end
|
108
|
+
if data[:mailboxId]
|
109
|
+
instructions << {
|
110
|
+
op: "move",
|
111
|
+
path: "/mailboxId",
|
112
|
+
value: data[:mailboxId],
|
113
|
+
}
|
114
|
+
end
|
115
|
+
if data[:status]
|
116
|
+
status = data[:status]
|
117
|
+
if !CONVERSATION_STATUSES.include?(status)
|
118
|
+
raise InvalidDataError.new("status \"#{status}\" not supported, must be one of #{CONVERSATION_STATUSES}")
|
119
|
+
end
|
74
120
|
|
75
|
-
|
121
|
+
instructions << {
|
122
|
+
op: "replace",
|
123
|
+
path: "/status",
|
124
|
+
value: data[:status],
|
125
|
+
}
|
126
|
+
end
|
127
|
+
if data.key?(:assignTo)
|
128
|
+
# change owner
|
129
|
+
if data[:assignTo]
|
130
|
+
instructions << {
|
131
|
+
op: "replace",
|
132
|
+
path: "/assignTo",
|
133
|
+
value: data[:assignTo],
|
134
|
+
}
|
135
|
+
else
|
136
|
+
# un assign
|
137
|
+
instructions << {
|
138
|
+
op: "remove",
|
139
|
+
path: "/assignTo",
|
140
|
+
}
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# Note: HelpScout currently does not support multiple
|
145
|
+
# instructions in the same request, well have to do them
|
146
|
+
# individually :-)
|
147
|
+
instructions.each do |instruction|
|
148
|
+
patch("conversations/#{id}", { body: instruction })
|
149
|
+
end
|
76
150
|
end
|
77
151
|
|
78
|
-
# Public: Update conversation
|
152
|
+
# Public: Update conversation tags
|
79
153
|
#
|
80
|
-
#
|
81
|
-
|
154
|
+
# More info: https://developer.helpscout.com/mailbox-api/endpoints/conversations/tags/update/
|
155
|
+
def update_conversation_tags(id, tags)
|
156
|
+
data = { tags: tags }
|
157
|
+
put("conversations/#{id}/tags", { body: data })
|
158
|
+
end
|
159
|
+
|
160
|
+
# Public: Update conversation custom fields
|
82
161
|
#
|
83
|
-
# More info:
|
84
|
-
def
|
85
|
-
|
162
|
+
# More info: https://developer.helpscout.com/mailbox-api/endpoints/conversations/custom_fields/update/
|
163
|
+
def update_conversation_custom_fields(id, fields)
|
164
|
+
data = { fields: fields }
|
165
|
+
put("conversations/#{id}/fields", { body: data })
|
86
166
|
end
|
87
167
|
|
88
168
|
# Public: Search for conversations
|
89
169
|
#
|
90
170
|
# query - term to search for
|
91
171
|
#
|
92
|
-
# More info:
|
172
|
+
# More info: https://developer.helpscout.com/mailbox-api/endpoints/conversations/list/
|
93
173
|
def search_conversations(query)
|
94
|
-
search("
|
174
|
+
search("conversations", query)
|
95
175
|
end
|
96
176
|
|
97
177
|
# Public: Delete conversation
|
98
178
|
#
|
99
179
|
# id - conversation id
|
100
180
|
#
|
101
|
-
# More info: https://developer.helpscout.com/
|
181
|
+
# More info: https://developer.helpscout.com/mailbox-api/endpoints/conversations/delete/
|
102
182
|
def delete_conversation(id)
|
103
183
|
delete("conversations/#{id}")
|
104
184
|
end
|
105
185
|
|
106
|
-
# Public:
|
107
|
-
#
|
108
|
-
# id - customer id
|
186
|
+
# Public: List all mailboxes
|
109
187
|
#
|
110
|
-
# More info:
|
111
|
-
def get_customer(id)
|
112
|
-
get("customers/#{id}")
|
113
|
-
end
|
114
|
-
|
188
|
+
# More info: https://developer.helpscout.com/mailbox-api/endpoints/mailboxes/list/
|
115
189
|
def get_mailboxes
|
116
190
|
get("mailboxes")
|
117
191
|
end
|
118
192
|
|
119
|
-
# Public:
|
193
|
+
# Public: Create note thread
|
120
194
|
#
|
121
|
-
#
|
122
|
-
#
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
195
|
+
# imported: no outgoing e-mails or notifications will be generated
|
196
|
+
#
|
197
|
+
# More info: https://developer.helpscout.com/mailbox-api/endpoints/conversations/threads/note/
|
198
|
+
def create_note(conversation_id:, text:, user: nil, imported: false)
|
199
|
+
data = {
|
200
|
+
text: text,
|
201
|
+
user: user,
|
202
|
+
imported: imported,
|
129
203
|
}
|
204
|
+
post("conversations/#{conversation_id}/notes", body: data)
|
130
205
|
|
131
|
-
|
206
|
+
last_response.code == HTTP_CREATED
|
132
207
|
end
|
133
208
|
|
134
|
-
# Public:
|
209
|
+
# Public: Create phone thread
|
135
210
|
#
|
136
|
-
#
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
{ reload: reload, imported: imported }.each do |key, value|
|
149
|
-
query[key] = value unless value.nil?
|
150
|
-
end
|
151
|
-
|
152
|
-
post("conversations/#{conversation_id}", body: thread, query: query)
|
211
|
+
# More info: https://developer.helpscout.com/mailbox-api/endpoints/conversations/threads/phone/
|
212
|
+
def create_phone(conversation_id:, text:, customer:, imported: false)
|
213
|
+
# Note, hs does not list user as an accepted type
|
214
|
+
# https://developer.helpscout.com/mailbox-api/endpoints/conversations/threads/phone/
|
215
|
+
data = {
|
216
|
+
text: text,
|
217
|
+
customer: {
|
218
|
+
id: customer
|
219
|
+
},
|
220
|
+
imported: imported,
|
221
|
+
}
|
222
|
+
post("conversations/#{conversation_id}/phones", body: data)
|
153
223
|
|
154
|
-
|
155
|
-
last_response.parsed_response
|
156
|
-
else
|
157
|
-
last_response.code == HTTP_CREATED
|
158
|
-
end
|
224
|
+
last_response.code == HTTP_CREATED
|
159
225
|
end
|
160
226
|
|
161
|
-
# Public:
|
162
|
-
#
|
163
|
-
# conversion_id - conversation id
|
164
|
-
# thread - thread content to be updated (only the body can be updated)
|
165
|
-
# reload - Set to true to get the entire conversation in the result
|
227
|
+
# Public: Create reply thread
|
166
228
|
#
|
167
|
-
# More info:
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
229
|
+
# More info: https://developer.helpscout.com/mailbox-api/endpoints/conversations/threads/reply/
|
230
|
+
def create_reply(conversation_id:, text:, customer:, user: nil, imported: false)
|
231
|
+
data = {
|
232
|
+
text: text,
|
233
|
+
user: user,
|
234
|
+
customer: {
|
235
|
+
id: customer
|
236
|
+
},
|
237
|
+
imported: imported,
|
238
|
+
}
|
239
|
+
post("conversations/#{conversation_id}/reply", body: data)
|
175
240
|
|
176
|
-
|
241
|
+
last_response.code == HTTP_CREATED
|
242
|
+
end
|
177
243
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
244
|
+
# Public: Get customer
|
245
|
+
#
|
246
|
+
# id - customer id
|
247
|
+
#
|
248
|
+
# More info: https://developer.helpscout.com/mailbox-api/endpoints/customers/get/
|
249
|
+
def get_customer(id)
|
250
|
+
get("customers/#{id}")
|
183
251
|
end
|
184
252
|
|
185
|
-
# Public: Update
|
253
|
+
# Public: Update customer
|
254
|
+
#
|
255
|
+
# Note: to update address, chat handles, emails, phones, social profiles or
|
256
|
+
# websites, separate endpoints have to be used.
|
186
257
|
#
|
187
258
|
# id - customer id
|
188
259
|
# data - hash with data
|
189
260
|
#
|
190
|
-
# More info:
|
261
|
+
# More info: https://developer.helpscout.com/mailbox-api/endpoints/customers/update/
|
191
262
|
def update_customer(id, data)
|
192
263
|
put("customers/#{id}", { body: data })
|
193
264
|
end
|
194
265
|
|
266
|
+
# Public: Create phone number
|
267
|
+
#
|
268
|
+
# More info: https://developer.helpscout.com/mailbox-api/endpoints/customers/phones/create/
|
269
|
+
def create_customer_phone(customer_id, data)
|
270
|
+
post("customers/#{customer_id}/phones", { body: data })
|
271
|
+
end
|
272
|
+
|
273
|
+
# Public: Delete phone number
|
274
|
+
#
|
275
|
+
# More info: https://developer.helpscout.com/mailbox-api/endpoints/customers/phones/delete/
|
276
|
+
def delete_customer_phone(customer_id, phone_id)
|
277
|
+
delete("customers/#{customer_id}/phones/#{phone_id}")
|
278
|
+
end
|
279
|
+
|
280
|
+
# Public: Create email
|
281
|
+
#
|
282
|
+
# More info: https://developer.helpscout.com/mailbox-api/endpoints/customers/emails/create/
|
283
|
+
def create_customer_email(customer_id, data)
|
284
|
+
post("customers/#{customer_id}/emails", { body: data })
|
285
|
+
end
|
286
|
+
|
287
|
+
# Public: Delete email
|
288
|
+
#
|
289
|
+
# More info: https://developer.helpscout.com/mailbox-api/endpoints/customers/emails/delete/
|
290
|
+
def delete_customer_email(customer_id, email_id)
|
291
|
+
delete("customers/#{customer_id}/emails/#{email_id}")
|
292
|
+
end
|
293
|
+
|
195
294
|
protected
|
196
295
|
|
197
296
|
def post(path, options = {})
|
@@ -214,43 +313,59 @@ class HelpScout
|
|
214
313
|
request(:delete, path, options)
|
215
314
|
end
|
216
315
|
|
316
|
+
def patch(path, options = {})
|
317
|
+
options[:body] = options[:body].to_json if options[:body]
|
318
|
+
|
319
|
+
request(:patch, path, options)
|
320
|
+
end
|
321
|
+
|
217
322
|
def search(path, query, page_id = 1, items = [])
|
218
323
|
options = { query: { page: page_id, query: "(#{query})" } }
|
219
324
|
|
220
325
|
result = get(path, options)
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
326
|
+
next_page_id = page_id + 1
|
327
|
+
|
328
|
+
if result.key?("_embedded")
|
329
|
+
items += result["_embedded"]["conversations"]
|
330
|
+
end
|
331
|
+
|
332
|
+
if next_page_id > result["page"]["totalPages"]
|
333
|
+
return items
|
334
|
+
else
|
335
|
+
search(path, query, next_page_id, items)
|
229
336
|
end
|
230
337
|
end
|
231
338
|
|
232
339
|
def request(method, path, options)
|
233
|
-
uri = URI("https://api.helpscout.net/
|
340
|
+
uri = URI("https://api.helpscout.net/v2/#{path}")
|
341
|
+
|
342
|
+
token = @token_storage.token
|
343
|
+
if token.nil?
|
344
|
+
token = generate_oauth_token
|
345
|
+
@token_storage.store_token(token)
|
346
|
+
end
|
234
347
|
|
235
|
-
# The password can be anything, it's not used, see:
|
236
|
-
# http://developer.helpscout.net/help-desk-api/
|
237
348
|
options = {
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
349
|
+
headers: {
|
350
|
+
"Content-Type": "application/json",
|
351
|
+
"Authorization": "Bearer #{token}",
|
352
|
+
}
|
242
353
|
}.merge(options)
|
243
354
|
|
244
|
-
if options.key?(:body)
|
245
|
-
options[:headers]['Content-Type'] ||= 'application/json'
|
246
|
-
end
|
247
|
-
|
248
355
|
@last_response = HTTParty.send(method, uri, options)
|
356
|
+
|
249
357
|
case last_response.code
|
358
|
+
when HTTP_UNAUTHORIZED
|
359
|
+
# Unauthorized means our token is expired. We will fetch a new one, and
|
360
|
+
# retry the original request
|
361
|
+
new_token = generate_oauth_token
|
362
|
+
@token_storage.store_token(new_token)
|
363
|
+
options.delete(:headers)
|
364
|
+
request(method, path, options)
|
250
365
|
when HTTP_OK, HTTP_CREATED, HTTP_NO_CONTENT
|
251
366
|
last_response.parsed_response
|
252
367
|
when HTTP_BAD_REQUEST
|
253
|
-
raise ValidationError, last_response.
|
368
|
+
raise ValidationError, JSON.parse(last_response.body)["_embedded"]["errors"]
|
254
369
|
when HTTP_FORBIDDEN
|
255
370
|
raise ForbiddenError
|
256
371
|
when HTTP_NOT_FOUND
|
@@ -261,7 +376,7 @@ class HelpScout
|
|
261
376
|
when HTTP_SERVICE_UNAVAILABLE
|
262
377
|
raise ServiceUnavailable
|
263
378
|
when HTTP_TOO_MANY_REQUESTS
|
264
|
-
retry_after = last_response.headers["Retry-After"]
|
379
|
+
retry_after = last_response.headers["X-RateLimit-Retry-After"]
|
265
380
|
message = "Rate limit of 200 RPM or 12 POST/PUT/DELETE requests per 5 " +
|
266
381
|
"seconds reached. Next request possible in #{retry_after} seconds."
|
267
382
|
raise TooManyRequestsError, message
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class HelpScout
|
2
|
+
module TokenStorage
|
3
|
+
class Redis
|
4
|
+
IDENTIFIER = "helpscout-client-token"
|
5
|
+
|
6
|
+
def initialize(db)
|
7
|
+
@db = db
|
8
|
+
end
|
9
|
+
|
10
|
+
def token
|
11
|
+
@db.get(IDENTIFIER)
|
12
|
+
end
|
13
|
+
|
14
|
+
def store_token(new_token)
|
15
|
+
@db.set(IDENTIFIER, new_token)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/help_scout/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: help_scout
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dennis Paagman
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: exe
|
13
13
|
cert_chain: []
|
14
|
-
date:
|
14
|
+
date: 2019-08-15 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: httparty
|
@@ -31,16 +31,16 @@ dependencies:
|
|
31
31
|
name: bundler
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
33
33
|
requirements:
|
34
|
-
- - "
|
34
|
+
- - ">="
|
35
35
|
- !ruby/object:Gem::Version
|
36
|
-
version: '
|
36
|
+
version: '0'
|
37
37
|
type: :development
|
38
38
|
prerelease: false
|
39
39
|
version_requirements: !ruby/object:Gem::Requirement
|
40
40
|
requirements:
|
41
|
-
- - "
|
41
|
+
- - ">="
|
42
42
|
- !ruby/object:Gem::Version
|
43
|
-
version: '
|
43
|
+
version: '0'
|
44
44
|
- !ruby/object:Gem::Dependency
|
45
45
|
name: rake
|
46
46
|
requirement: !ruby/object:Gem::Requirement
|
@@ -118,6 +118,9 @@ files:
|
|
118
118
|
- bin/setup
|
119
119
|
- help_scout.gemspec
|
120
120
|
- lib/help_scout.rb
|
121
|
+
- lib/help_scout/token_storage.rb
|
122
|
+
- lib/help_scout/token_storage/memory.rb
|
123
|
+
- lib/help_scout/token_storage/redis.rb
|
121
124
|
- lib/help_scout/version.rb
|
122
125
|
homepage: https://github.com/Springest/help_scout
|
123
126
|
licenses:
|
@@ -134,12 +137,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
134
137
|
version: '0'
|
135
138
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
136
139
|
requirements:
|
137
|
-
- - "
|
140
|
+
- - ">"
|
138
141
|
- !ruby/object:Gem::Version
|
139
|
-
version:
|
142
|
+
version: 1.3.1
|
140
143
|
requirements: []
|
141
144
|
rubyforge_project:
|
142
|
-
rubygems_version: 2.
|
145
|
+
rubygems_version: 2.6.14.3
|
143
146
|
signing_key:
|
144
147
|
specification_version: 4
|
145
148
|
summary: HelpScout is an API client for Help Scout
|