trycourier 1.0.1 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/gem-push.yml +49 -0
- data/CHANGELOG.md +93 -0
- data/CONTRIBUTING.md +28 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +39 -1
- data/README.md +364 -11
- data/Rakefile +2 -1
- data/lib/trycourier/automations.rb +67 -0
- data/lib/trycourier/brands.rb +70 -0
- data/lib/trycourier/bulk.rb +79 -0
- data/lib/trycourier/events.rb +35 -0
- data/lib/trycourier/exceptions.rb +37 -0
- data/lib/trycourier/lists.rb +109 -0
- data/lib/trycourier/messages.rb +51 -0
- data/lib/trycourier/profiles.rb +64 -0
- data/lib/trycourier/session.rb +81 -0
- data/lib/trycourier/version.rb +1 -1
- data/lib/trycourier.rb +62 -26
- data/trycourier.gemspec +15 -12
- metadata +45 -6
- data/.travis.yml +0 -6
@@ -0,0 +1,67 @@
|
|
1
|
+
module Courier
|
2
|
+
class Automations
|
3
|
+
KEY = "/automations"
|
4
|
+
|
5
|
+
def initialize(session)
|
6
|
+
@session = session
|
7
|
+
end
|
8
|
+
|
9
|
+
def invoke(automation:, brand: nil, data: nil, profile: nil, recipient: nil, template: nil)
|
10
|
+
path = "#{KEY}/invoke"
|
11
|
+
payload = {
|
12
|
+
"automation": automation
|
13
|
+
}
|
14
|
+
|
15
|
+
if brand
|
16
|
+
payload["brand"] = brand
|
17
|
+
end
|
18
|
+
|
19
|
+
if data
|
20
|
+
payload["data"] = data
|
21
|
+
end
|
22
|
+
|
23
|
+
if profile
|
24
|
+
payload["profile"] = profile
|
25
|
+
end
|
26
|
+
|
27
|
+
if recipient
|
28
|
+
payload["recipient"] = recipient
|
29
|
+
end
|
30
|
+
|
31
|
+
if template
|
32
|
+
payload["template"] = template
|
33
|
+
end
|
34
|
+
|
35
|
+
res = @session.send(path, "POST", body: payload, headers: {})
|
36
|
+
ErrorHandler.check_err(res)
|
37
|
+
end
|
38
|
+
|
39
|
+
def invoke_template(template_id:, brand: nil, data: nil, profile: nil, recipient: nil, template: nil)
|
40
|
+
path = "#{KEY}/#{template_id}/invoke"
|
41
|
+
payload = {}
|
42
|
+
|
43
|
+
if brand
|
44
|
+
payload["brand"] = brand
|
45
|
+
end
|
46
|
+
|
47
|
+
if data
|
48
|
+
payload["data"] = data
|
49
|
+
end
|
50
|
+
|
51
|
+
if profile
|
52
|
+
payload["profile"] = profile
|
53
|
+
end
|
54
|
+
|
55
|
+
if recipient
|
56
|
+
payload["recipient"] = recipient
|
57
|
+
end
|
58
|
+
|
59
|
+
if template
|
60
|
+
payload["template"] = template
|
61
|
+
end
|
62
|
+
|
63
|
+
res = @session.send(path, "POST", body: payload, headers: {})
|
64
|
+
ErrorHandler.check_err(res)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Courier
|
2
|
+
class Brands
|
3
|
+
KEY = "/brands"
|
4
|
+
|
5
|
+
def initialize(session)
|
6
|
+
@session = session
|
7
|
+
end
|
8
|
+
|
9
|
+
def list(cursor: nil)
|
10
|
+
params = {}
|
11
|
+
if cursor
|
12
|
+
params["cursor"] = cursor
|
13
|
+
end
|
14
|
+
res = @session.send(KEY, "GET", params: params)
|
15
|
+
ErrorHandler.check_err(res)
|
16
|
+
end
|
17
|
+
|
18
|
+
def get(brand_id:)
|
19
|
+
path = "#{KEY}/#{brand_id}"
|
20
|
+
res = @session.send(path, "GET")
|
21
|
+
ErrorHandler.check_err(res)
|
22
|
+
end
|
23
|
+
|
24
|
+
def add(name:, settings:, id: nil, snippets: nil, idempotency_key: nil)
|
25
|
+
create(name: name, settings: settings, id: id, snippets: snippets, idempotency_key: idempotency_key)
|
26
|
+
end
|
27
|
+
|
28
|
+
def create(name:, settings:, id: nil, snippets: nil, idempotency_key: nil)
|
29
|
+
headers = {}
|
30
|
+
if idempotency_key
|
31
|
+
headers["idempotency_key"] = idempotency_key
|
32
|
+
end
|
33
|
+
|
34
|
+
payload = {
|
35
|
+
"name" => name,
|
36
|
+
"settings" => settings
|
37
|
+
}
|
38
|
+
if id
|
39
|
+
payload["id"] = id
|
40
|
+
end
|
41
|
+
if snippets
|
42
|
+
payload["snippets"] = snippets
|
43
|
+
end
|
44
|
+
|
45
|
+
res = @session.send(KEY, "POST", body: payload, headers: headers)
|
46
|
+
ErrorHandler.check_err(res)
|
47
|
+
end
|
48
|
+
|
49
|
+
def replace(brand_id:, name:, settings:, snippets: nil)
|
50
|
+
path = "#{KEY}/#{brand_id}"
|
51
|
+
|
52
|
+
payload = {
|
53
|
+
"name" => name,
|
54
|
+
"settings" => settings
|
55
|
+
}
|
56
|
+
if snippets
|
57
|
+
payload["snippets"] = snippets
|
58
|
+
end
|
59
|
+
|
60
|
+
res = @session.send(path, "PUT", body: payload)
|
61
|
+
ErrorHandler.check_err_non_json(res)
|
62
|
+
end
|
63
|
+
|
64
|
+
def delete(brand_id:)
|
65
|
+
path = "#{KEY}/#{brand_id}"
|
66
|
+
res = @session.send(path, "DELETE")
|
67
|
+
ErrorHandler.check_err_non_json(res)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Courier
|
2
|
+
class Bulk
|
3
|
+
KEY = "/bulk"
|
4
|
+
|
5
|
+
def initialize(session)
|
6
|
+
@session = session
|
7
|
+
end
|
8
|
+
|
9
|
+
def create_job(message:, idempotency_key: nil, idempotency_expiry: nil)
|
10
|
+
path = "#{KEY}"
|
11
|
+
payload = {
|
12
|
+
"message": message
|
13
|
+
}
|
14
|
+
|
15
|
+
headers = {}
|
16
|
+
if idempotency_key
|
17
|
+
headers["idempotency_key"] = idempotency_key
|
18
|
+
end
|
19
|
+
if idempotency_expiry
|
20
|
+
headers["x-idempotency-expiration"] = idempotency_expiry
|
21
|
+
end
|
22
|
+
|
23
|
+
res = @session.send(path, "POST", body: payload, headers: headers)
|
24
|
+
ErrorHandler.check_err(res)
|
25
|
+
end
|
26
|
+
|
27
|
+
def ingest_job(job_id:, users:, idempotency_key: nil, idempotency_expiry: nil)
|
28
|
+
path = "#{KEY}/#{job_id}"
|
29
|
+
payload = {
|
30
|
+
"users": users
|
31
|
+
}
|
32
|
+
|
33
|
+
headers = {}
|
34
|
+
if idempotency_key
|
35
|
+
headers["idempotency_key"] = idempotency_key
|
36
|
+
end
|
37
|
+
if idempotency_expiry
|
38
|
+
headers["x-idempotency-expiration"] = idempotency_expiry
|
39
|
+
end
|
40
|
+
|
41
|
+
res = @session.send(path, "POST", body: payload, headers: headers)
|
42
|
+
ErrorHandler.check_err(res)
|
43
|
+
end
|
44
|
+
|
45
|
+
def run_job(job_id:, idempotency_key: nil, idempotency_expiry: nil)
|
46
|
+
path = "#{KEY}/#{job_id}/run"
|
47
|
+
payload = {}
|
48
|
+
|
49
|
+
headers = {}
|
50
|
+
if idempotency_key
|
51
|
+
headers["idempotency_key"] = idempotency_key
|
52
|
+
end
|
53
|
+
if idempotency_expiry
|
54
|
+
headers["x-idempotency-expiration"] = idempotency_expiry
|
55
|
+
end
|
56
|
+
|
57
|
+
res = @session.send(path, "POST", body: payload, headers: headers)
|
58
|
+
ErrorHandler.check_err_non_json(res)
|
59
|
+
end
|
60
|
+
|
61
|
+
def get_job(job_id:)
|
62
|
+
path = "#{KEY}/#{job_id}"
|
63
|
+
res = @session.send(path, "GET")
|
64
|
+
ErrorHandler.check_err(res)
|
65
|
+
end
|
66
|
+
|
67
|
+
def get_job_users(job_id:, cursor: nil)
|
68
|
+
path = "#{KEY}/#{job_id}/users"
|
69
|
+
|
70
|
+
params = {}
|
71
|
+
if cursor
|
72
|
+
params["cursor"] = cursor
|
73
|
+
end
|
74
|
+
|
75
|
+
res = @session.send(path, "GET", params: params)
|
76
|
+
ErrorHandler.check_err(res)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Courier
|
2
|
+
class Events
|
3
|
+
KEY = "/events"
|
4
|
+
|
5
|
+
def initialize(session)
|
6
|
+
@session = session
|
7
|
+
end
|
8
|
+
|
9
|
+
def list
|
10
|
+
res = @session.send(KEY, "GET")
|
11
|
+
ErrorHandler.check_err(res)
|
12
|
+
end
|
13
|
+
|
14
|
+
def get(event_id:)
|
15
|
+
path = "#{KEY}/#{event_id}"
|
16
|
+
res = @session.send(path, "GET")
|
17
|
+
ErrorHandler.check_err(res)
|
18
|
+
end
|
19
|
+
|
20
|
+
def add(event_id:, id:, type: "notification")
|
21
|
+
replace(event_id: event_id, id: id, type: type)
|
22
|
+
end
|
23
|
+
|
24
|
+
def replace(event_id:, id:, type: "notification")
|
25
|
+
path = "#{KEY}/#{event_id}"
|
26
|
+
|
27
|
+
payload = {
|
28
|
+
"id" => id,
|
29
|
+
"type" => type
|
30
|
+
}
|
31
|
+
res = @session.send(path, "PUT", body: payload)
|
32
|
+
ErrorHandler.check_err_non_json(res)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require "trycourier/version"
|
2
|
+
require "net/http"
|
3
|
+
require "json"
|
4
|
+
require "openssl"
|
5
|
+
|
6
|
+
module Courier
|
7
|
+
#ResponseError in order to maintain v1.0.2 signature.
|
8
|
+
class InputError < StandardError; end
|
9
|
+
class ResponseError < StandardError; end
|
10
|
+
class CourierAPIError < ResponseError; end
|
11
|
+
|
12
|
+
class ErrorHandler
|
13
|
+
def self.check_err(res)
|
14
|
+
code = res.code.to_i
|
15
|
+
obj = JSON.parse res.read_body
|
16
|
+
|
17
|
+
if code < 400
|
18
|
+
obj
|
19
|
+
elsif (message = obj["Message"].nil? ? obj["message"] : obj["Message"])
|
20
|
+
err = "#{code}: #{message}"
|
21
|
+
raise CourierAPIError.new err
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.check_err_non_json(res)
|
26
|
+
code = res.code.to_i
|
27
|
+
if code >= 400
|
28
|
+
obj = JSON.parse res.read_body
|
29
|
+
if (message = obj["Message"].nil? ? obj["message"] : obj["Message"])
|
30
|
+
err = "#{code}: #{message}"
|
31
|
+
raise CourierAPIError.new err
|
32
|
+
end
|
33
|
+
end
|
34
|
+
res
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module Courier
|
2
|
+
class Lists
|
3
|
+
KEY = "/lists"
|
4
|
+
|
5
|
+
def initialize(session)
|
6
|
+
@session = session
|
7
|
+
end
|
8
|
+
|
9
|
+
def send(event:, list: nil, pattern: nil, data: {}, brand: nil, override: nil, idempotency_key: nil)
|
10
|
+
path = "/send/list"
|
11
|
+
payload = {
|
12
|
+
"event": event,
|
13
|
+
"data": data
|
14
|
+
}
|
15
|
+
if list
|
16
|
+
payload["list"] = list
|
17
|
+
end
|
18
|
+
if pattern
|
19
|
+
payload["pattern"] = pattern
|
20
|
+
end
|
21
|
+
if brand
|
22
|
+
payload["brand"] = brand
|
23
|
+
end
|
24
|
+
if override
|
25
|
+
payload["override"] = override
|
26
|
+
end
|
27
|
+
|
28
|
+
headers = {}
|
29
|
+
if idempotency_key
|
30
|
+
headers["idempotency_key"] = idempotency_key
|
31
|
+
end
|
32
|
+
|
33
|
+
res = @session.send(path, "POST", body: payload, headers: headers)
|
34
|
+
ErrorHandler.check_err(res)
|
35
|
+
end
|
36
|
+
|
37
|
+
def list(cursor: nil, pattern: nil)
|
38
|
+
params = {}
|
39
|
+
if cursor
|
40
|
+
params["cursor"] = cursor
|
41
|
+
end
|
42
|
+
if pattern
|
43
|
+
params["pattern"] = pattern
|
44
|
+
end
|
45
|
+
res = @session.send(KEY, "GET", params: params)
|
46
|
+
ErrorHandler.check_err(res)
|
47
|
+
end
|
48
|
+
|
49
|
+
def get(list_id:)
|
50
|
+
path = "#{KEY}/#{list_id}"
|
51
|
+
res = @session.send(path, "GET")
|
52
|
+
ErrorHandler.check_err(res)
|
53
|
+
end
|
54
|
+
|
55
|
+
def put(list_id:, name:)
|
56
|
+
path = "#{KEY}/#{list_id}"
|
57
|
+
|
58
|
+
payload = {
|
59
|
+
"name": name.to_s
|
60
|
+
}
|
61
|
+
|
62
|
+
res = @session.send(path, "PUT", body: payload)
|
63
|
+
ErrorHandler.check_err_non_json(res)
|
64
|
+
end
|
65
|
+
|
66
|
+
def delete(list_id:)
|
67
|
+
path = "#{KEY}/#{list_id}"
|
68
|
+
res = @session.send(path, "DELETE")
|
69
|
+
ErrorHandler.check_err_non_json(res)
|
70
|
+
end
|
71
|
+
|
72
|
+
def restore(list_id:)
|
73
|
+
path = "#{KEY}/#{list_id}/restore"
|
74
|
+
res = @session.send(path, "PUT")
|
75
|
+
ErrorHandler.check_err_non_json(res)
|
76
|
+
end
|
77
|
+
|
78
|
+
def get_subscriptions(list_id:, cursor: nil)
|
79
|
+
path = "#{KEY}/#{list_id}/subscriptions"
|
80
|
+
params = {}
|
81
|
+
if cursor
|
82
|
+
params["cursor"] = cursor
|
83
|
+
end
|
84
|
+
res = @session.send(path, "GET", params: params)
|
85
|
+
ErrorHandler.check_err(res)
|
86
|
+
end
|
87
|
+
|
88
|
+
def put_subscriptions(list_id:, recipients:)
|
89
|
+
path = "#{KEY}/#{list_id}/subscriptions"
|
90
|
+
payload = {
|
91
|
+
"recipients": recipients
|
92
|
+
}
|
93
|
+
res = @session.send(path, "PUT", body: payload)
|
94
|
+
ErrorHandler.check_err_non_json(res)
|
95
|
+
end
|
96
|
+
|
97
|
+
def subscribe(list_id:, recipient_id:)
|
98
|
+
path = "#{KEY}/#{list_id}/subscriptions/#{recipient_id}"
|
99
|
+
res = @session.send(path, "PUT")
|
100
|
+
ErrorHandler.check_err_non_json(res)
|
101
|
+
end
|
102
|
+
|
103
|
+
def unsubscribe(list_id:, recipient_id:)
|
104
|
+
path = "#{KEY}/#{list_id}/subscriptions/#{recipient_id}"
|
105
|
+
res = @session.send(path, "DELETE")
|
106
|
+
ErrorHandler.check_err_non_json(res)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Courier
|
2
|
+
class Messages
|
3
|
+
KEY = "/messages"
|
4
|
+
|
5
|
+
def initialize(session)
|
6
|
+
@session = session
|
7
|
+
end
|
8
|
+
|
9
|
+
def list(cursor: nil, event: nil, list_id: nil, message_id: nil,
|
10
|
+
notification: nil, recipient: nil)
|
11
|
+
params = {}
|
12
|
+
|
13
|
+
if cursor
|
14
|
+
params["cursor"] = cursor
|
15
|
+
end
|
16
|
+
if event
|
17
|
+
params["event"] = event
|
18
|
+
end
|
19
|
+
if list_id
|
20
|
+
params["list"] = list_id
|
21
|
+
end
|
22
|
+
if message_id
|
23
|
+
params["messageId"] = message_id
|
24
|
+
end
|
25
|
+
if notification
|
26
|
+
params["notification"] = notification
|
27
|
+
end
|
28
|
+
if recipient
|
29
|
+
params["recipient"] = recipient
|
30
|
+
end
|
31
|
+
res = @session.send(KEY, "GET", params: params)
|
32
|
+
ErrorHandler.check_err(res)
|
33
|
+
end
|
34
|
+
|
35
|
+
def get(message_id:)
|
36
|
+
path = "#{KEY}/#{message_id}"
|
37
|
+
res = @session.send(path, "GET")
|
38
|
+
ErrorHandler.check_err(res)
|
39
|
+
end
|
40
|
+
|
41
|
+
def get_history(message_id:, type: nil)
|
42
|
+
path ="#{KEY}/#{message_id}/history"
|
43
|
+
params = {}
|
44
|
+
if type
|
45
|
+
params["type"] = type
|
46
|
+
end
|
47
|
+
res = @session.send(path, "GET", params: params)
|
48
|
+
ErrorHandler.check_err(res)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Courier
|
2
|
+
class Profiles
|
3
|
+
KEY = "/profiles"
|
4
|
+
|
5
|
+
def initialize(session)
|
6
|
+
@session = session
|
7
|
+
end
|
8
|
+
|
9
|
+
def get(recipient_id:)
|
10
|
+
path = "#{KEY}/#{recipient_id}"
|
11
|
+
res = @session.send(path, "GET")
|
12
|
+
ErrorHandler.check_err(res)
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_subscriptions(recipient_id:, cursor: nil)
|
16
|
+
path = "#{KEY}/#{recipient_id}/subscriptions"
|
17
|
+
|
18
|
+
params = {}
|
19
|
+
if cursor
|
20
|
+
params["cursor"] = cursor
|
21
|
+
end
|
22
|
+
|
23
|
+
res = @session.send(path, "GET", params: params)
|
24
|
+
ErrorHandler.check_err(res)
|
25
|
+
end
|
26
|
+
|
27
|
+
def add(recipient_id:, profile:)
|
28
|
+
replace(recipient_id: recipient_id, profile: profile)
|
29
|
+
end
|
30
|
+
|
31
|
+
def replace(recipient_id:, profile:)
|
32
|
+
path = "#{KEY}/#{recipient_id}"
|
33
|
+
|
34
|
+
payload = {
|
35
|
+
'profile': profile
|
36
|
+
}
|
37
|
+
|
38
|
+
res = @session.send(path, "PUT", body: payload)
|
39
|
+
ErrorHandler.check_err_non_json(res)
|
40
|
+
end
|
41
|
+
|
42
|
+
def merge(recipient_id:, profile:, idempotency_key: nil)
|
43
|
+
path = "#{KEY}/#{recipient_id}"
|
44
|
+
payload = {
|
45
|
+
'profile': profile
|
46
|
+
}
|
47
|
+
headers = {}
|
48
|
+
if idempotency_key
|
49
|
+
headers["Idempotency-Key"] = idempotency_key
|
50
|
+
end
|
51
|
+
res = @session.send(path, "POST", body: payload, headers: headers)
|
52
|
+
ErrorHandler.check_err(res)
|
53
|
+
end
|
54
|
+
|
55
|
+
def patch(recipient_id:, operations:)
|
56
|
+
path = "#{KEY}/#{recipient_id}"
|
57
|
+
payload = {
|
58
|
+
'patch': operations
|
59
|
+
}
|
60
|
+
res = @session.send(path, "PATCH", body: payload)
|
61
|
+
ErrorHandler.check_err(res)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require "net/http"
|
2
|
+
require "json"
|
3
|
+
require "openssl"
|
4
|
+
|
5
|
+
module Courier
|
6
|
+
class CourierAPISession
|
7
|
+
|
8
|
+
def initialize(base_url)
|
9
|
+
@base_url = base_url
|
10
|
+
end
|
11
|
+
|
12
|
+
def init_token_auth(auth_token)
|
13
|
+
@auth_token = "Bearer #{auth_token}"
|
14
|
+
@auth_method = "token"
|
15
|
+
end
|
16
|
+
|
17
|
+
def init_basic_auth(username, password)
|
18
|
+
@username = username
|
19
|
+
@password = password
|
20
|
+
@auth_method = "basic"
|
21
|
+
end
|
22
|
+
|
23
|
+
def send(path, method, params: nil, body: nil, headers: nil)
|
24
|
+
uri = URI.parse(@base_url + path.to_s)
|
25
|
+
if params
|
26
|
+
uri.query = URI.encode_www_form(params)
|
27
|
+
end
|
28
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
29
|
+
http.use_ssl = true
|
30
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
31
|
+
|
32
|
+
req = case method
|
33
|
+
when "GET"
|
34
|
+
Net::HTTP::Get.new(uri)
|
35
|
+
when "POST"
|
36
|
+
Net::HTTP::Post.new(uri)
|
37
|
+
when "PUT"
|
38
|
+
Net::HTTP::Put.new(uri)
|
39
|
+
when "PATCH"
|
40
|
+
Net::HTTP::Patch.new(uri)
|
41
|
+
when "DELETE"
|
42
|
+
Net::HTTP::Delete.new(uri)
|
43
|
+
else
|
44
|
+
Net::HTTP::Get.new(uri)
|
45
|
+
end
|
46
|
+
|
47
|
+
case @auth_method
|
48
|
+
when "token"
|
49
|
+
req["authorization"] = @auth_token
|
50
|
+
when "basic"
|
51
|
+
req.basic_auth @username, @password
|
52
|
+
end
|
53
|
+
|
54
|
+
req["content-type"] = "application/json"
|
55
|
+
req["User-Agent"] = "courier-ruby/#{Courier::VERSION}"
|
56
|
+
|
57
|
+
if body
|
58
|
+
req.body = body.to_json
|
59
|
+
end
|
60
|
+
|
61
|
+
if headers
|
62
|
+
headers.each do |k, v|
|
63
|
+
req.add_field(k.to_s, v.to_s)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
http.request(req)
|
68
|
+
end
|
69
|
+
|
70
|
+
def is_authenticated
|
71
|
+
if !@auth_method.nil?
|
72
|
+
true
|
73
|
+
else
|
74
|
+
false
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
#getter for base url (for testing)
|
79
|
+
attr_reader :base_url
|
80
|
+
end
|
81
|
+
end
|
data/lib/trycourier/version.rb
CHANGED