twilio_base 1.9.0 → 1.11.11
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 +4 -4
- data/.gitignore +4 -0
- data/.rubocop.yml +2 -7
- data/app/services/twilio_base/phone_number.rb +5 -1
- data/app/services/twilio_base/protocols/voice/base.rb +16 -0
- data/app/services/twilio_base/protocols/voice/sip.rb +26 -1
- data/app/services/twilio_base/routers/voice/base.rb +19 -14
- data/circle.yml +7 -4
- data/lib/twilio_base/version.rb +1 -1
- data/spec/services/twilio_base/phone_number_spec.rb +15 -0
- data/spec/services/twilio_base/protocols/voice/base_spec.rb +35 -0
- data/spec/services/twilio_base/protocols/voice/sip_spec.rb +116 -5
- data/spec/services/twilio_base/routers/voice/base_spec.rb +49 -21
- data/spec/spec_helper.rb +1 -0
- data/spec/support/twilio_base/fake/account.rb +20 -0
- data/spec/support/twilio_base/fake/chat/channel.rb +10 -6
- data/spec/support/twilio_base/fake/clients/rest.rb +4 -0
- data/spec/support/twilio_base/fake/sync/services/document.rb +6 -6
- data/spec/support/twilio_base/fake/sync/services/list.rb +5 -5
- data/spec/support/twilio_base/fake/sync/services/lists/item.rb +9 -3
- data/spec/support/twilio_base/fake/sync/services/map.rb +28 -7
- data/spec/support/twilio_base/fake/sync/services/maps/item.rb +42 -5
- data/spec/support/twilio_base/fake/task_router/worker.rb +4 -0
- data/spec/support/twilio_base/fake/task_router/worker_statistic.rb +49 -0
- data/spec/support/twilio_base/responses/twiml.rb +11 -0
- data/spec/twilio_base_dummy/config/database.example.yml +1 -1
- data/twilio_base.gemspec +2 -1
- metadata +28 -12
- data/.tool-versions +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f5cca3af8d5d0d1cccb5338087a09cebd0d2eafea819ff77a2bd1b5ee830029d
|
4
|
+
data.tar.gz: a578e6a7fa3d0ddcc2b01101923f5a4803a0e3b0fc938f77f7de12812b139b41
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 329f90af23c78753e3947f7e9b41ad5879ff566f0145764d9b85e1f81df8172d6052abe168ba52ef251704c216894838bddcbb67577a9fd7fe9e80956a27bf13
|
7
|
+
data.tar.gz: 26a104211a55761bf40ae03269cdc8c2dd66c68875466c44c48a371061a1263451204910dfa0482414b34dd9c2aee49d356f66e3148ca4100a2406872e7aa5af
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -11,19 +11,14 @@ Layout/ExtraSpacing:
|
|
11
11
|
Exclude:
|
12
12
|
- 'bin/*'
|
13
13
|
|
14
|
-
Layout/IndentFirstArgument:
|
15
|
-
EnforcedStyle: consistent
|
16
|
-
|
17
|
-
Layout/IndentFirstArrayElement:
|
18
|
-
EnforcedStyle: consistent
|
19
|
-
|
20
14
|
Layout/MultilineMethodCallIndentation:
|
21
15
|
EnforcedStyle: indented
|
22
16
|
|
23
17
|
Metrics/AbcSize:
|
24
18
|
Exclude:
|
25
|
-
- 'spec/support/twilio_base/responses/twiml.rb'
|
26
19
|
- 'spec/support/twilio_base/fake/helpers.rb'
|
20
|
+
- 'spec/support/twilio_base/fake/task_router/worker_statistic.rb'
|
21
|
+
- 'spec/support/twilio_base/responses/twiml.rb'
|
27
22
|
|
28
23
|
Metrics/LineLength:
|
29
24
|
Max: 80
|
@@ -11,10 +11,14 @@ module TwilioBase
|
|
11
11
|
phone_number ? find(phone_number) : create
|
12
12
|
end
|
13
13
|
|
14
|
+
def incoming_phone_number_list(**args)
|
15
|
+
incoming_phone_numbers.list(args)
|
16
|
+
end
|
17
|
+
|
14
18
|
private
|
15
19
|
|
16
20
|
def find(phone_number)
|
17
|
-
|
21
|
+
incoming_phone_number_list(phone_number: phone_number).first
|
18
22
|
end
|
19
23
|
|
20
24
|
def create
|
@@ -52,10 +52,26 @@ module TwilioBase
|
|
52
52
|
params[:wait_url]
|
53
53
|
end
|
54
54
|
|
55
|
+
def routing_method
|
56
|
+
:dial
|
57
|
+
end
|
58
|
+
|
59
|
+
def routing_attributes
|
60
|
+
dial_attribues
|
61
|
+
end
|
62
|
+
|
55
63
|
private
|
56
64
|
|
57
65
|
attr_accessor :params, :to
|
58
66
|
|
67
|
+
def dial_attribues
|
68
|
+
{
|
69
|
+
action: action_url,
|
70
|
+
caller_id: caller_uuid,
|
71
|
+
timeout: timeout
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
59
75
|
def mpoa
|
60
76
|
extract_mpoa(params[:caller_uuid])
|
61
77
|
end
|
@@ -4,6 +4,8 @@ module TwilioBase
|
|
4
4
|
module Protocols
|
5
5
|
module Voice
|
6
6
|
class Sip < Base
|
7
|
+
UTU_HEADER_NAME = 'User-to-User'
|
8
|
+
|
7
9
|
def endpoint
|
8
10
|
"sip:#{sip_endpoint}?#{parsed_headers}"
|
9
11
|
end
|
@@ -12,11 +14,22 @@ module TwilioBase
|
|
12
14
|
:sip
|
13
15
|
end
|
14
16
|
|
17
|
+
def routing_method
|
18
|
+
sip_refer_enabled? ? :refer : :dial
|
19
|
+
end
|
20
|
+
|
21
|
+
def routing_attributes
|
22
|
+
sip_refer_enabled? ? refer_attribues : dial_attribues
|
23
|
+
end
|
24
|
+
|
15
25
|
private
|
16
26
|
|
17
27
|
def parsed_headers
|
18
28
|
hash = headers.each_with_object({}) do |(k, v), obj|
|
19
|
-
key =
|
29
|
+
key = k.to_s
|
30
|
+
|
31
|
+
key = "X-#{key}" unless utu_header?(key)
|
32
|
+
|
20
33
|
value = v.presence || '-'
|
21
34
|
|
22
35
|
obj[key] = value
|
@@ -33,6 +46,14 @@ module TwilioBase
|
|
33
46
|
sip_whip
|
34
47
|
end
|
35
48
|
|
49
|
+
def sip_refer_enabled?
|
50
|
+
params[:sip_refer_enabled]
|
51
|
+
end
|
52
|
+
|
53
|
+
def refer_attribues
|
54
|
+
{ action: action_url }
|
55
|
+
end
|
56
|
+
|
36
57
|
def sip_whip
|
37
58
|
@sip_whip ||= sip_endpoints.sample.to_s.strip
|
38
59
|
end
|
@@ -42,6 +63,10 @@ module TwilioBase
|
|
42
63
|
|
43
64
|
value.flat_map { |v| v.split(',') }
|
44
65
|
end
|
66
|
+
|
67
|
+
def utu_header?(key)
|
68
|
+
key == UTU_HEADER_NAME
|
69
|
+
end
|
45
70
|
end
|
46
71
|
end
|
47
72
|
end
|
@@ -6,6 +6,17 @@ module TwilioBase
|
|
6
6
|
class Base
|
7
7
|
include Rails.application.routes.url_helpers
|
8
8
|
|
9
|
+
delegate :action_url,
|
10
|
+
:caller_uuid,
|
11
|
+
:endpoint,
|
12
|
+
:name,
|
13
|
+
:routing_attributes,
|
14
|
+
:routing_method,
|
15
|
+
:status_callback_events,
|
16
|
+
:status_callback_url,
|
17
|
+
:timeout,
|
18
|
+
to: :protocol
|
19
|
+
|
9
20
|
def initialize(protocol:)
|
10
21
|
self.protocol = protocol
|
11
22
|
end
|
@@ -13,12 +24,14 @@ module TwilioBase
|
|
13
24
|
def route
|
14
25
|
yield_response = yield if block_given?
|
15
26
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
27
|
+
vr = yield_response || voice_response
|
28
|
+
|
29
|
+
vr.public_send(routing_method, routing_attributes) do |router|
|
30
|
+
router.public_send(
|
31
|
+
name,
|
32
|
+
endpoint,
|
33
|
+
status_callback_event: status_callback_events,
|
34
|
+
status_callback: status_callback_url
|
22
35
|
)
|
23
36
|
end.to_s
|
24
37
|
end
|
@@ -30,14 +43,6 @@ module TwilioBase
|
|
30
43
|
def voice_response
|
31
44
|
@voice_response ||= Twilio::TwiML::VoiceResponse.new
|
32
45
|
end
|
33
|
-
|
34
|
-
def dial_attribues
|
35
|
-
{
|
36
|
-
action: protocol.action_url,
|
37
|
-
caller_id: protocol.caller_uuid,
|
38
|
-
timeout: protocol.timeout
|
39
|
-
}
|
40
|
-
end
|
41
46
|
end
|
42
47
|
end
|
43
48
|
end
|
data/circle.yml
CHANGED
@@ -1,17 +1,20 @@
|
|
1
1
|
version: 2
|
2
2
|
jobs:
|
3
3
|
build:
|
4
|
+
working_directory: ~/twilio_base
|
4
5
|
docker:
|
5
6
|
- image: circleci/ruby:2.5.1-node-browsers
|
6
7
|
environment:
|
7
8
|
PGHOST: 127.0.0.1
|
8
|
-
PGUSER:
|
9
|
+
PGUSER: postgres
|
9
10
|
RAILS_ENV: test
|
10
|
-
|
11
|
+
RACK_ENV: test
|
12
|
+
|
13
|
+
- image: circleci/postgres:9.6.2-alpine
|
11
14
|
environment:
|
12
|
-
POSTGRES_USER:
|
15
|
+
POSTGRES_USER: postgres
|
13
16
|
POSTGRES_DB: twilio_base_test
|
14
|
-
|
17
|
+
|
15
18
|
steps:
|
16
19
|
- checkout
|
17
20
|
- run: bundle install
|
data/lib/twilio_base/version.rb
CHANGED
@@ -46,4 +46,19 @@ RSpec.describe TwilioBase::PhoneNumber do
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
49
|
+
|
50
|
+
describe '.incoming_phone_number_list' do
|
51
|
+
it 'returns active numbers' do
|
52
|
+
phone_numbers = []
|
53
|
+
3.times do
|
54
|
+
phone_numbers << TwilioBase::Fake::IncomingPhoneNumber::PhoneNumber.new(
|
55
|
+
Faker::PhoneNumber.phone_number
|
56
|
+
)
|
57
|
+
end
|
58
|
+
TwilioBase::Fake::IncomingPhoneNumber.phone_numbers = phone_numbers
|
59
|
+
|
60
|
+
expect(described_class.incoming_phone_number_list)
|
61
|
+
.to match_array(phone_numbers)
|
62
|
+
end
|
63
|
+
end
|
49
64
|
end
|
@@ -131,4 +131,39 @@ RSpec.describe TwilioBase::Protocols::Voice::Base do
|
|
131
131
|
expect(protocol.wait_url).to eq(wait_url)
|
132
132
|
end
|
133
133
|
end
|
134
|
+
|
135
|
+
describe '#routing_attributes' do
|
136
|
+
it 'returns dial attributes' do
|
137
|
+
action_url = 'https://example.com'
|
138
|
+
caller_uuid = '+1234567890'
|
139
|
+
timeout = 1
|
140
|
+
sip = described_class.new(
|
141
|
+
params: {
|
142
|
+
action_url: action_url,
|
143
|
+
caller_uuid: caller_uuid,
|
144
|
+
timeout: timeout
|
145
|
+
},
|
146
|
+
to: caller_uuid
|
147
|
+
)
|
148
|
+
|
149
|
+
expected_result = {
|
150
|
+
action: action_url,
|
151
|
+
caller_id: caller_uuid,
|
152
|
+
timeout: timeout
|
153
|
+
}
|
154
|
+
|
155
|
+
expect(sip.routing_attributes).to eq(expected_result)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
describe '#routing_method' do
|
160
|
+
it 'returns dial' do
|
161
|
+
sip = described_class.new(
|
162
|
+
params: {},
|
163
|
+
to: '+1234567890'
|
164
|
+
)
|
165
|
+
|
166
|
+
expect(sip.routing_method).to eq(:dial)
|
167
|
+
end
|
168
|
+
end
|
134
169
|
end
|
@@ -24,7 +24,7 @@ RSpec.describe TwilioBase::Protocols::Voice::Sip do
|
|
24
24
|
|
25
25
|
sip_headers = build_sip_headers(
|
26
26
|
headers: {
|
27
|
-
'X-
|
27
|
+
'X-call_sid' => 'CAsid'
|
28
28
|
}
|
29
29
|
)
|
30
30
|
|
@@ -47,7 +47,7 @@ RSpec.describe TwilioBase::Protocols::Voice::Sip do
|
|
47
47
|
|
48
48
|
sip_headers = build_sip_headers(
|
49
49
|
headers: {
|
50
|
-
'X-
|
50
|
+
'X-call_sid' => 'CAsid'
|
51
51
|
}
|
52
52
|
)
|
53
53
|
|
@@ -60,7 +60,7 @@ RSpec.describe TwilioBase::Protocols::Voice::Sip do
|
|
60
60
|
end
|
61
61
|
|
62
62
|
context 'header has blank value' do
|
63
|
-
it 'returns -' do
|
63
|
+
it 'returns "-" as a value' do
|
64
64
|
endpoint = '3000@127.0.0.1'
|
65
65
|
params = {
|
66
66
|
headers: {
|
@@ -72,14 +72,58 @@ RSpec.describe TwilioBase::Protocols::Voice::Sip do
|
|
72
72
|
|
73
73
|
expected_result = build_sip_headers(
|
74
74
|
headers: {
|
75
|
-
'X-
|
76
|
-
'X-
|
75
|
+
'X-blank_value' => '-',
|
76
|
+
'X-call_sid' => 'CAsid'
|
77
77
|
}
|
78
78
|
)
|
79
79
|
|
80
80
|
expect(sip.endpoint).to eq("sip:#{endpoint}?#{expected_result}")
|
81
81
|
end
|
82
82
|
end
|
83
|
+
|
84
|
+
describe 'prefix adding' do
|
85
|
+
context 'with UTU header' do
|
86
|
+
it 'does not add an X- prefix' do
|
87
|
+
endpoint = '3000@127.0.0.1'
|
88
|
+
header_name = described_class::UTU_HEADER_NAME
|
89
|
+
params = {
|
90
|
+
headers: {
|
91
|
+
header_name => 'value'
|
92
|
+
}
|
93
|
+
}
|
94
|
+
sip = described_class.new(params: params, to: endpoint)
|
95
|
+
|
96
|
+
expected_result = build_sip_headers(
|
97
|
+
headers: {
|
98
|
+
header_name => 'value'
|
99
|
+
}
|
100
|
+
)
|
101
|
+
|
102
|
+
expect(sip.endpoint).to eq("sip:#{endpoint}?#{expected_result}")
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context 'without UTU header' do
|
107
|
+
it 'does not add an X- prefix' do
|
108
|
+
endpoint = '3000@127.0.0.1'
|
109
|
+
header_name = 'random-key'
|
110
|
+
params = {
|
111
|
+
headers: {
|
112
|
+
header_name => 'value'
|
113
|
+
}
|
114
|
+
}
|
115
|
+
sip = described_class.new(params: params, to: endpoint)
|
116
|
+
|
117
|
+
expected_result = build_sip_headers(
|
118
|
+
headers: {
|
119
|
+
'X-random-key' => 'value'
|
120
|
+
}
|
121
|
+
)
|
122
|
+
|
123
|
+
expect(sip.endpoint).to eq("sip:#{endpoint}?#{expected_result}")
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
83
127
|
end
|
84
128
|
|
85
129
|
describe '#name' do
|
@@ -90,6 +134,73 @@ RSpec.describe TwilioBase::Protocols::Voice::Sip do
|
|
90
134
|
end
|
91
135
|
end
|
92
136
|
|
137
|
+
describe '#routing_attributes' do
|
138
|
+
context 'with sip refer enabled' do
|
139
|
+
it 'returns refer attributes' do
|
140
|
+
action_url = 'https://example.com'
|
141
|
+
sip = described_class.new(
|
142
|
+
params: {
|
143
|
+
action_url: action_url,
|
144
|
+
sip_refer_enabled: true
|
145
|
+
},
|
146
|
+
to: '+1234567890'
|
147
|
+
)
|
148
|
+
|
149
|
+
expected_result = { action: action_url }
|
150
|
+
expect(sip.routing_attributes).to eq(expected_result)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
context 'with sip refer disabled' do
|
155
|
+
it 'returns dial attributes' do
|
156
|
+
action_url = 'https://example.com'
|
157
|
+
caller_uuid = '+1234567890'
|
158
|
+
timeout = 1
|
159
|
+
sip = described_class.new(
|
160
|
+
params: {
|
161
|
+
action_url: action_url,
|
162
|
+
caller_uuid: caller_uuid,
|
163
|
+
sip_refer_enabled: false,
|
164
|
+
timeout: timeout
|
165
|
+
},
|
166
|
+
to: caller_uuid
|
167
|
+
)
|
168
|
+
|
169
|
+
expected_result = {
|
170
|
+
action: action_url,
|
171
|
+
caller_id: caller_uuid,
|
172
|
+
timeout: timeout
|
173
|
+
}
|
174
|
+
|
175
|
+
expect(sip.routing_attributes).to eq(expected_result)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
describe '#routing_method' do
|
181
|
+
context 'with sip refer enabled' do
|
182
|
+
it 'returns refer' do
|
183
|
+
sip = described_class.new(
|
184
|
+
params: { sip_refer_enabled: true },
|
185
|
+
to: '+1234567890'
|
186
|
+
)
|
187
|
+
|
188
|
+
expect(sip.routing_method).to eq(:refer)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
context 'with sip refer disabled' do
|
193
|
+
it 'returns dial' do
|
194
|
+
sip = described_class.new(
|
195
|
+
params: { sip_refer_enabled: false },
|
196
|
+
to: '+1234567890'
|
197
|
+
)
|
198
|
+
|
199
|
+
expect(sip.routing_method).to eq(:dial)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
93
204
|
def build_sip_headers(headers: {})
|
94
205
|
Addressable::URI.new(query_values: headers).query
|
95
206
|
end
|
@@ -62,29 +62,57 @@ RSpec.describe TwilioBase::Routers::Voice::DirectDial do
|
|
62
62
|
end
|
63
63
|
|
64
64
|
context 'protocol is Sip' do
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
65
|
+
context 'with refer disabled' do
|
66
|
+
it 'returns sip dial Twiml' do
|
67
|
+
protocol = TwilioBase::Protocols::Voice::Sip.new(
|
68
|
+
params: {
|
69
|
+
action_url: 'https://someurl.com',
|
70
|
+
sip_endpoint: '124@abc.net',
|
71
|
+
status_callback_url: 'https://somestatusurl.com'
|
72
|
+
},
|
73
|
+
to: '+442039605098'
|
74
|
+
)
|
75
|
+
direct_dial = described_class.new(protocol: protocol)
|
75
76
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
77
|
+
expected_result = dial_twiml(
|
78
|
+
params: {
|
79
|
+
action_url: protocol.action_url,
|
80
|
+
caller_id: protocol.caller_uuid,
|
81
|
+
endpoint: protocol.endpoint,
|
82
|
+
protocol: protocol.name,
|
83
|
+
status_callback_url: protocol.status_callback_url,
|
84
|
+
status_callback_events: protocol.status_callback_events
|
85
|
+
}
|
86
|
+
)
|
86
87
|
|
87
|
-
|
88
|
+
expect(direct_dial.route).to eq(expected_result)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'with refer enabled' do
|
93
|
+
it 'returns sip refer Twiml' do
|
94
|
+
protocol = TwilioBase::Protocols::Voice::Sip.new(
|
95
|
+
params: {
|
96
|
+
action_url: 'https://someurl.com',
|
97
|
+
sip_endpoint: '124@abc.net',
|
98
|
+
status_callback_url: 'https://somestatusurl.com',
|
99
|
+
sip_refer_enabled: true
|
100
|
+
},
|
101
|
+
to: '+442039605098'
|
102
|
+
)
|
103
|
+
direct_dial = described_class.new(protocol: protocol)
|
104
|
+
|
105
|
+
expected_result = refer_twiml(
|
106
|
+
params: {
|
107
|
+
action_url: protocol.action_url,
|
108
|
+
endpoint: protocol.endpoint,
|
109
|
+
status_callback_url: protocol.status_callback_url,
|
110
|
+
status_callback_events: protocol.status_callback_events
|
111
|
+
}
|
112
|
+
)
|
113
|
+
|
114
|
+
expect(direct_dial.route).to eq(expected_result)
|
115
|
+
end
|
88
116
|
end
|
89
117
|
end
|
90
118
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TwilioBase
|
4
|
+
module Fake
|
5
|
+
class Account
|
6
|
+
Account = Struct.new(:sid)
|
7
|
+
|
8
|
+
cattr_accessor :accounts, :sid
|
9
|
+
self.accounts = []
|
10
|
+
|
11
|
+
def initialize(sid = nil)
|
12
|
+
self.sid = sid
|
13
|
+
end
|
14
|
+
|
15
|
+
def fetch
|
16
|
+
accounts.detect { |account| account.sid == sid }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -4,9 +4,13 @@ module TwilioBase
|
|
4
4
|
module Fake
|
5
5
|
module Chat
|
6
6
|
class Channel
|
7
|
-
Channel = Struct.new(:
|
7
|
+
Channel = Struct.new(:attrs) do
|
8
8
|
def friendly_name
|
9
|
-
|
9
|
+
attrs[:friendly_name]
|
10
|
+
end
|
11
|
+
|
12
|
+
def attributes
|
13
|
+
attrs.dig(:attributes)
|
10
14
|
end
|
11
15
|
|
12
16
|
def messages
|
@@ -25,8 +29,8 @@ module TwilioBase
|
|
25
29
|
TwilioBase::Fake::Chat::Channel.channels.pop
|
26
30
|
end
|
27
31
|
|
28
|
-
def update(
|
29
|
-
|
32
|
+
def update(update_attrs)
|
33
|
+
attrs.merge! update_attrs
|
30
34
|
end
|
31
35
|
end
|
32
36
|
|
@@ -37,8 +41,8 @@ module TwilioBase
|
|
37
41
|
self.channel_sid = channel_sid
|
38
42
|
end
|
39
43
|
|
40
|
-
def create(
|
41
|
-
self.class.channels << Channel.new(
|
44
|
+
def create(attrs)
|
45
|
+
self.class.channels << Channel.new(attrs)
|
42
46
|
channels.last
|
43
47
|
end
|
44
48
|
|
@@ -5,21 +5,21 @@ module TwilioBase
|
|
5
5
|
module Sync
|
6
6
|
module Services
|
7
7
|
class Document
|
8
|
+
attr_accessor :data, :date_expires, :unique_name
|
9
|
+
|
8
10
|
cattr_accessor :documents
|
9
11
|
self.documents = []
|
10
12
|
|
11
|
-
def initialize(data: {},
|
13
|
+
def initialize(data: {}, date_expires: '', unique_name: '')
|
12
14
|
self.data = data
|
13
|
-
self.
|
15
|
+
self.date_expires = date_expires
|
14
16
|
self.unique_name = unique_name
|
15
17
|
end
|
16
18
|
|
17
|
-
|
18
|
-
|
19
|
-
def create(data: {}, ttl: '', unique_name: '')
|
19
|
+
def create(data: {}, ttl: 0, unique_name: '')
|
20
20
|
document = Document.new(
|
21
21
|
data: data,
|
22
|
-
|
22
|
+
date_expires: Time.current + ttl,
|
23
23
|
unique_name: unique_name
|
24
24
|
)
|
25
25
|
self.class.documents << document
|
@@ -8,18 +8,18 @@ module TwilioBase
|
|
8
8
|
cattr_accessor :lists
|
9
9
|
self.lists = []
|
10
10
|
|
11
|
-
attr_accessor :data, :
|
11
|
+
attr_accessor :data, :date_expires, :unique_name
|
12
12
|
|
13
|
-
def initialize(data: {},
|
13
|
+
def initialize(data: {}, date_expires: '', unique_name: '')
|
14
14
|
self.data = data
|
15
|
-
self.
|
15
|
+
self.date_expires = date_expires
|
16
16
|
self.unique_name = unique_name
|
17
17
|
end
|
18
18
|
|
19
|
-
def create(data: {}, ttl:
|
19
|
+
def create(data: {}, ttl: 0, unique_name: '')
|
20
20
|
list = List.new(
|
21
21
|
data: data,
|
22
|
-
|
22
|
+
date_expires: Time.current + ttl,
|
23
23
|
unique_name: unique_name
|
24
24
|
)
|
25
25
|
self.class.lists << list
|
@@ -9,8 +9,13 @@ module TwilioBase
|
|
9
9
|
Item = Struct.new(:data) do
|
10
10
|
attr_accessor :sid
|
11
11
|
|
12
|
-
def create(data: {})
|
12
|
+
def create(data: {}, date_expires: '')
|
13
13
|
self.data = data
|
14
|
+
self.date_expires = date_expires
|
15
|
+
end
|
16
|
+
|
17
|
+
def date_expires
|
18
|
+
data[:date_expires]
|
14
19
|
end
|
15
20
|
end
|
16
21
|
|
@@ -21,9 +26,10 @@ module TwilioBase
|
|
21
26
|
self.sid = sid
|
22
27
|
end
|
23
28
|
|
24
|
-
def create(data: {})
|
29
|
+
def create(data: {}, ttl: 0)
|
25
30
|
item = Item.new(
|
26
|
-
data: data
|
31
|
+
data: data,
|
32
|
+
date_expires: Time.current + ttl
|
27
33
|
)
|
28
34
|
self.class.items << item
|
29
35
|
item
|
@@ -8,18 +8,19 @@ module TwilioBase
|
|
8
8
|
cattr_accessor :maps
|
9
9
|
self.maps = {}
|
10
10
|
|
11
|
-
attr_accessor :data, :
|
11
|
+
attr_accessor :data, :date_expires, :unique_name, :context
|
12
12
|
|
13
|
-
def initialize(data: {},
|
13
|
+
def initialize(data: {}, date_expires: '', unique_name: '')
|
14
|
+
self.context = MapContext.new
|
14
15
|
self.data = data
|
15
|
-
self.
|
16
|
+
self.date_expires = date_expires
|
16
17
|
self.unique_name = unique_name
|
17
18
|
end
|
18
19
|
|
19
|
-
def create(data: {}, ttl:
|
20
|
+
def create(data: {}, ttl: 0, unique_name: '')
|
20
21
|
map = Map.new(
|
21
22
|
data: data,
|
22
|
-
|
23
|
+
date_expires: Time.current + ttl,
|
23
24
|
unique_name: unique_name
|
24
25
|
)
|
25
26
|
self.class.maps << map
|
@@ -37,11 +38,31 @@ module TwilioBase
|
|
37
38
|
end
|
38
39
|
|
39
40
|
def maps(unique_name = nil)
|
40
|
-
Map.new(unique_name || rand(999).to_s)
|
41
|
+
Map.new(unique_name: unique_name || rand(999).to_s)
|
41
42
|
end
|
42
43
|
|
43
44
|
def sync_map_items
|
44
|
-
|
45
|
+
context.sync_map_items
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class MapContext
|
50
|
+
def sync_map_items(key = :unset)
|
51
|
+
if key.nil?
|
52
|
+
raise(ArgumentError, 'key cannot be nil')
|
53
|
+
end
|
54
|
+
|
55
|
+
if key == :unset
|
56
|
+
item_klass.items
|
57
|
+
else
|
58
|
+
item_klass.find_or_create(key)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def item_klass
|
65
|
+
Fake::Sync::Services::Maps::Item
|
45
66
|
end
|
46
67
|
end
|
47
68
|
end
|
@@ -6,35 +6,72 @@ module TwilioBase
|
|
6
6
|
module Services
|
7
7
|
module Maps
|
8
8
|
class Item
|
9
|
-
Map = Struct.new(:data, :key) do
|
9
|
+
Map = Struct.new(:data, :date_expires, :key) do
|
10
10
|
attr_accessor :sid
|
11
11
|
|
12
|
-
def create(data: {}, key: '')
|
12
|
+
def create(data: {}, date_expires: '', key: '')
|
13
13
|
self.data = data
|
14
|
+
self.date_expires = date_expires
|
14
15
|
self.key = key
|
15
16
|
end
|
16
17
|
|
17
|
-
def update(data: {})
|
18
|
+
def update(data: {}, ttl: 0)
|
19
|
+
if self.data.empty?
|
20
|
+
raise(Twilio::REST::RestError, 'Unable to update record')
|
21
|
+
end
|
22
|
+
|
18
23
|
self.data = data
|
24
|
+
self.date_expires = (Time.current + ttl) if ttl
|
19
25
|
end
|
20
26
|
end
|
21
27
|
|
22
28
|
cattr_accessor :items
|
23
|
-
|
29
|
+
Items = Struct.new(:name) do
|
30
|
+
delegate(*[].methods, to: :items)
|
31
|
+
|
32
|
+
def create(data: {}, date_expires: '', key: '')
|
33
|
+
item = Item.find_or_create(key)
|
34
|
+
unless item.data.blank?
|
35
|
+
raise(Twilio::REST::RestError, 'Unable to create record')
|
36
|
+
end
|
37
|
+
|
38
|
+
item.update(data: data, date_expires: date_expires)
|
39
|
+
item
|
40
|
+
end
|
41
|
+
|
42
|
+
def items
|
43
|
+
@items ||= []
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
self.items = Items.new(name: 'SyncItemListMock')
|
24
48
|
|
25
49
|
def initialize(sid = nil)
|
26
50
|
self.sid = sid
|
27
51
|
end
|
28
52
|
|
29
|
-
def create(data: {}, key: '')
|
53
|
+
def create(data: {}, ttl: 0, key: '')
|
30
54
|
item = Map.new(
|
31
55
|
data: data,
|
56
|
+
date_expires: Time.current + ttl,
|
32
57
|
key: key
|
33
58
|
)
|
34
59
|
self.class.items << item
|
60
|
+
item.key = key
|
35
61
|
item
|
36
62
|
end
|
37
63
|
|
64
|
+
class << self
|
65
|
+
def find_or_create(key)
|
66
|
+
items.select { |item| item.key == key }.first ||
|
67
|
+
new.create(key: key)
|
68
|
+
end
|
69
|
+
|
70
|
+
def items=(value)
|
71
|
+
items.items = Array(value)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
38
75
|
private
|
39
76
|
|
40
77
|
attr_accessor :sid
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TwilioBase
|
4
|
+
module Fake
|
5
|
+
module TaskRouter
|
6
|
+
class WorkerStatistic
|
7
|
+
cattr_accessor :attributes
|
8
|
+
|
9
|
+
WorkerStatistic = Struct.new(:attributes) do
|
10
|
+
def realtime
|
11
|
+
activities = attributes.map do |a|
|
12
|
+
{ activity: a.activity_name, sid: a.sid }
|
13
|
+
end.uniq
|
14
|
+
|
15
|
+
statistics = []
|
16
|
+
|
17
|
+
activities.each do |a|
|
18
|
+
stats = {}
|
19
|
+
stats[:friendly_name] = a[:activity]
|
20
|
+
stats[:sid] = a[:sid]
|
21
|
+
stats[:workers] = attributes.select do |w|
|
22
|
+
w.activity_name == a[:activity]
|
23
|
+
end.length
|
24
|
+
|
25
|
+
statistics << stats
|
26
|
+
end
|
27
|
+
|
28
|
+
{
|
29
|
+
total_workers: attributes.length,
|
30
|
+
activity_statistics: statistics
|
31
|
+
}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def initialize(attributes = {})
|
36
|
+
self.attributes = attributes
|
37
|
+
end
|
38
|
+
|
39
|
+
def statistics
|
40
|
+
@statistics ||= WorkerStatistic.new(attributes)
|
41
|
+
end
|
42
|
+
|
43
|
+
def fetch
|
44
|
+
statistics
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -24,6 +24,17 @@ module TwilioBase
|
|
24
24
|
"\n</Dial>\n" \
|
25
25
|
"</Response>\n"
|
26
26
|
end
|
27
|
+
|
28
|
+
def refer_twiml(params: {})
|
29
|
+
vr = Twilio::TwiML::VoiceResponse.new
|
30
|
+
vr.refer(action: params[:action_url]) do |refer|
|
31
|
+
refer.sip(
|
32
|
+
params[:endpoint],
|
33
|
+
status_callback: params[:status_callback_url],
|
34
|
+
status_callback_event: params[:status_callback_events]
|
35
|
+
)
|
36
|
+
end.to_s
|
37
|
+
end
|
27
38
|
end
|
28
39
|
end
|
29
40
|
end
|
data/twilio_base.gemspec
CHANGED
@@ -26,12 +26,13 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.require_paths = ['lib']
|
27
27
|
|
28
28
|
spec.add_dependency 'addressable', '~> 2.5.2'
|
29
|
-
spec.add_dependency 'twilio-ruby', '~> 5.
|
29
|
+
spec.add_dependency 'twilio-ruby', '~> 5.39.3'
|
30
30
|
|
31
31
|
spec.add_development_dependency 'bundler'
|
32
32
|
spec.add_development_dependency 'byebug', '9.0.6'
|
33
33
|
spec.add_development_dependency 'database_cleaner', '1.6.1'
|
34
34
|
spec.add_development_dependency 'factory_bot_rails'
|
35
|
+
spec.add_development_dependency 'faker'
|
35
36
|
spec.add_development_dependency 'generator_spec'
|
36
37
|
spec.add_development_dependency 'listen'
|
37
38
|
spec.add_development_dependency 'pg', '0.20.0'
|
metadata
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: twilio_base
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.11.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Richard Brown
|
8
8
|
- Vania Ermakovets
|
9
9
|
- Ilya Umanets
|
10
|
-
autorequire:
|
10
|
+
autorequire:
|
11
11
|
bindir: exe
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2020-09-28 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: addressable
|
@@ -32,14 +32,14 @@ dependencies:
|
|
32
32
|
requirements:
|
33
33
|
- - "~>"
|
34
34
|
- !ruby/object:Gem::Version
|
35
|
-
version: 5.
|
35
|
+
version: 5.39.3
|
36
36
|
type: :runtime
|
37
37
|
prerelease: false
|
38
38
|
version_requirements: !ruby/object:Gem::Requirement
|
39
39
|
requirements:
|
40
40
|
- - "~>"
|
41
41
|
- !ruby/object:Gem::Version
|
42
|
-
version: 5.
|
42
|
+
version: 5.39.3
|
43
43
|
- !ruby/object:Gem::Dependency
|
44
44
|
name: bundler
|
45
45
|
requirement: !ruby/object:Gem::Requirement
|
@@ -96,6 +96,20 @@ dependencies:
|
|
96
96
|
- - ">="
|
97
97
|
- !ruby/object:Gem::Version
|
98
98
|
version: '0'
|
99
|
+
- !ruby/object:Gem::Dependency
|
100
|
+
name: faker
|
101
|
+
requirement: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
type: :development
|
107
|
+
prerelease: false
|
108
|
+
version_requirements: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
99
113
|
- !ruby/object:Gem::Dependency
|
100
114
|
name: generator_spec
|
101
115
|
requirement: !ruby/object:Gem::Requirement
|
@@ -236,7 +250,7 @@ dependencies:
|
|
236
250
|
- - ">="
|
237
251
|
- !ruby/object:Gem::Version
|
238
252
|
version: '0'
|
239
|
-
description:
|
253
|
+
description:
|
240
254
|
email:
|
241
255
|
- richard@dvelp.co.uk
|
242
256
|
executables: []
|
@@ -247,7 +261,6 @@ files:
|
|
247
261
|
- ".rspec"
|
248
262
|
- ".rubocop.yml"
|
249
263
|
- ".ruby-version"
|
250
|
-
- ".tool-versions"
|
251
264
|
- Gemfile
|
252
265
|
- LICENSE.txt
|
253
266
|
- README.md
|
@@ -327,6 +340,7 @@ files:
|
|
327
340
|
- spec/support/factory_bot.rb
|
328
341
|
- spec/support/shared_contexts/global_config.rb
|
329
342
|
- spec/support/shared_contexts/twilio_controller.rb
|
343
|
+
- spec/support/twilio_base/fake/account.rb
|
330
344
|
- spec/support/twilio_base/fake/api_key.rb
|
331
345
|
- spec/support/twilio_base/fake/application.rb
|
332
346
|
- spec/support/twilio_base/fake/available_phone_number.rb
|
@@ -364,6 +378,7 @@ files:
|
|
364
378
|
- spec/support/twilio_base/fake/task_router/task.rb
|
365
379
|
- spec/support/twilio_base/fake/task_router/task_queue.rb
|
366
380
|
- spec/support/twilio_base/fake/task_router/worker.rb
|
381
|
+
- spec/support/twilio_base/fake/task_router/worker_statistic.rb
|
367
382
|
- spec/support/twilio_base/fake/task_router/workflow.rb
|
368
383
|
- spec/support/twilio_base/fake/task_router/workspace.rb
|
369
384
|
- spec/support/twilio_base/fake/voice_call.rb
|
@@ -422,11 +437,11 @@ files:
|
|
422
437
|
- spec/twilio_base_dummy/vendor/assets/stylesheets/.keep
|
423
438
|
- spec/twilio_base_spec.rb
|
424
439
|
- twilio_base.gemspec
|
425
|
-
homepage:
|
440
|
+
homepage:
|
426
441
|
licenses: []
|
427
442
|
metadata:
|
428
443
|
allowed_push_host: https://rubygems.org
|
429
|
-
post_install_message:
|
444
|
+
post_install_message:
|
430
445
|
rdoc_options: []
|
431
446
|
require_paths:
|
432
447
|
- lib
|
@@ -441,9 +456,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
441
456
|
- !ruby/object:Gem::Version
|
442
457
|
version: '0'
|
443
458
|
requirements: []
|
444
|
-
|
445
|
-
|
446
|
-
signing_key:
|
459
|
+
rubygems_version: 3.0.8
|
460
|
+
signing_key:
|
447
461
|
specification_version: 4
|
448
462
|
summary: It provides twilio logic
|
449
463
|
test_files:
|
@@ -487,6 +501,7 @@ test_files:
|
|
487
501
|
- spec/support/factory_bot.rb
|
488
502
|
- spec/support/shared_contexts/global_config.rb
|
489
503
|
- spec/support/shared_contexts/twilio_controller.rb
|
504
|
+
- spec/support/twilio_base/fake/account.rb
|
490
505
|
- spec/support/twilio_base/fake/api_key.rb
|
491
506
|
- spec/support/twilio_base/fake/application.rb
|
492
507
|
- spec/support/twilio_base/fake/available_phone_number.rb
|
@@ -524,6 +539,7 @@ test_files:
|
|
524
539
|
- spec/support/twilio_base/fake/task_router/task.rb
|
525
540
|
- spec/support/twilio_base/fake/task_router/task_queue.rb
|
526
541
|
- spec/support/twilio_base/fake/task_router/worker.rb
|
542
|
+
- spec/support/twilio_base/fake/task_router/worker_statistic.rb
|
527
543
|
- spec/support/twilio_base/fake/task_router/workflow.rb
|
528
544
|
- spec/support/twilio_base/fake/task_router/workspace.rb
|
529
545
|
- spec/support/twilio_base/fake/voice_call.rb
|
data/.tool-versions
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
ruby 2.5.1
|