twi 0.2.0 → 0.3.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +29 -7
- data/lib/twi/conversation.rb +82 -0
- data/lib/twi/conversation_event.rb +10 -0
- data/lib/twi/delivery_event.rb +13 -0
- data/lib/twi/error.rb +11 -0
- data/lib/twi/event.rb +28 -11
- data/lib/twi/lio.rb +23 -7
- data/lib/twi/medium.rb +2 -2
- data/lib/twi/message.rb +12 -0
- data/lib/twi/message_event.rb +21 -0
- data/lib/twi/mock/conversation.rb +29 -0
- data/lib/twi/mock/event.rb +6 -0
- data/lib/twi/mock/medium.rb +8 -0
- data/lib/twi/mock/message.rb +12 -0
- data/lib/twi/mock/phone.rb +12 -0
- data/lib/twi/mock.rb +5 -0
- data/lib/twi/mocking.rb +33 -0
- data/lib/twi/participant_event.rb +19 -0
- data/lib/twi/phone.rb +21 -0
- data/lib/twi/resource.rb +8 -0
- data/lib/twi/version.rb +1 -1
- data/lib/twi.rb +17 -0
- metadata +15 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a3da0ed4a9e8746dd8609affeb9cf316a156dafa9a20b0da5e5307c37ea95ad0
|
|
4
|
+
data.tar.gz: 647d377b97c2fc7951ecd61f3caeb100b5d4ceeb8e1a8d788a5ba0b623a60ef9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 375a364348e16d823426c5670e22a900f52d50d5ee9ac2405f80cd6cd9e3cd7052e20d2d8511f50d44036f579ce273d8a2929908f470fd01aeeaf576e0ec6993
|
|
7
|
+
data.tar.gz: 97361223e531df80107ed916fa9f81774a9a8694a2e9df8b7acc5dd58468f02c10616df901e798d88f3be3e93b9f1cd4b4c8a3952525ab618378ea1d5a520063
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
## [0.3.0] - 2026-05-27
|
|
2
|
+
|
|
3
|
+
- [New] Add Twi::Message#create
|
|
4
|
+
- [New] Add Twi::Conversation#upload
|
|
5
|
+
- [New] Add Twi.event, Twi.mock.medium
|
|
6
|
+
- [New] Add Twi.conversation, Twi.mock.conversation, Twi.mock.conversation_error
|
|
7
|
+
- [New] Add Twi::Event.params_for
|
|
8
|
+
- [New] Add Twi.create_phone, Twi.mock.phone, Twi.mock.phone_error
|
|
9
|
+
- [New] Add Twi::Phone
|
|
10
|
+
|
|
1
11
|
## [0.2.0] - 2026-05-25
|
|
2
12
|
|
|
3
13
|
- [New] Twi::Delivery as a wrapper for direct message deliveries
|
data/README.md
CHANGED
|
@@ -55,20 +55,42 @@ event.target # => :participant
|
|
|
55
55
|
event.participant # => #<Participant id: 'SH12', phone: '9008009000', identity: nil>
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
+
### Twi::Phone
|
|
59
|
+
|
|
60
|
+
To create an incoming phone number:
|
|
61
|
+
|
|
62
|
+
```ruby
|
|
63
|
+
phone = Twi.create_phone area_code:, friendly_name:
|
|
64
|
+
phone.id # => 'SM083e290bef7794c407f14e65a891aa6d'
|
|
65
|
+
phone.number # => '5556667777'
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Available mocks
|
|
69
|
+
|
|
70
|
+
Use these methods to mock request to Twilio when testing an app:
|
|
71
|
+
|
|
72
|
+
### Credentials
|
|
73
|
+
|
|
74
|
+
Mock an error when creating an incoming phone number:
|
|
75
|
+
|
|
76
|
+
```ruby
|
|
77
|
+
Jbr.mock.phone_error = { code: '21452' }
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Mock successfully creating an incoming phone number:
|
|
81
|
+
|
|
82
|
+
```ruby
|
|
83
|
+
Jbr.mock.phone = { id: 'SM083e290bef7794c407f14e65a891aa6d', number: '8009005000' }
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
|
|
58
87
|
## To Do
|
|
59
88
|
|
|
60
|
-
1. have a Rails engine with the webhook URLs already set?
|
|
61
89
|
4. have an interface to send and receive SMS with photos
|
|
62
|
-
5. another webhook for conversations
|
|
63
|
-
6. another one to be notified of deliveries
|
|
64
|
-
7. Assistant > create a phone number
|
|
65
90
|
8. have an error code URL for each error code and a sid_url
|
|
66
91
|
9. Declare some phones like Twilio.homeowner_phone or Twilio.numbers[:ddd] and a default Twilio.number and similar Twilio.messaging_service
|
|
67
92
|
10. a way to reopen closed conversations
|
|
68
93
|
11. a way to create conversations
|
|
69
94
|
12. and upload pictures in a conversation
|
|
70
95
|
13. x_twilio_webhook_enabled: true
|
|
71
|
-
14. return SIDs so we can store them
|
|
72
|
-
15. Set up defaults likw Twi::Lio.sid
|
|
73
|
-
16. Twi.mock = true
|
|
74
96
|
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Enhances the Twilio Ruby gem with an object-oriented approach.
|
|
2
|
+
module Twi
|
|
3
|
+
# The representation of a (classic) group conversation.
|
|
4
|
+
class Conversation < Resource
|
|
5
|
+
attr_reader :id, :status
|
|
6
|
+
|
|
7
|
+
def create_with(participants:)
|
|
8
|
+
params = create_params_for participants
|
|
9
|
+
conversation = conversation_service.conversation_with_participants.create **params
|
|
10
|
+
|
|
11
|
+
@id = conversation.sid
|
|
12
|
+
@status = conversation.state
|
|
13
|
+
rescue Twilio::REST::RestError => error
|
|
14
|
+
case error.code
|
|
15
|
+
when 50438 then raise ExistingConversationError.new(error.error_message)
|
|
16
|
+
when 50214 then raise TooManyConversationsError.new(error.error_message)
|
|
17
|
+
else raise
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def rename(friendly_name)
|
|
22
|
+
conversation.update friendly_name: friendly_name
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def close
|
|
26
|
+
conversation.update state: :closed
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def delete
|
|
30
|
+
conversation.delete
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def create_message(content:, image_ids: [])
|
|
34
|
+
conversation.messages.create **message_params_for(content, image_ids)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# TODO: Move into Medium -- this method doesn't use anything from this class
|
|
38
|
+
def upload(file)
|
|
39
|
+
uri = URI "https://mcs.us1.twilio.com/v1/Services/#{Twi.lio.conversation_sid}/Media"
|
|
40
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
41
|
+
http.use_ssl = true
|
|
42
|
+
|
|
43
|
+
headers = { 'Content-Type' => file.content_type, 'Content-Size' => file.byte_size.to_s }
|
|
44
|
+
request = Net::HTTP::Post.new uri.request_uri, headers
|
|
45
|
+
request.basic_auth Twi.lio.api_key, Twi.lio.secret
|
|
46
|
+
request.body = file.download
|
|
47
|
+
response = http.request request
|
|
48
|
+
JSON(response.body)['sid']
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
|
|
53
|
+
def conversation
|
|
54
|
+
conversation_service.conversations @params[:id]
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def create_params_for(participants)
|
|
58
|
+
{
|
|
59
|
+
messaging_service_sid: Twi.lio.messaging_sid, x_twilio_webhook_enabled: 'true',
|
|
60
|
+
friendly_name: @params[:friendly_name], participant: participant_params_for(participants),
|
|
61
|
+
}
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def participant_params_for(participants)
|
|
65
|
+
participants.map do |participant|
|
|
66
|
+
phone = "+1#{participant[:phone]}"
|
|
67
|
+
if participant[:identity]
|
|
68
|
+
{ messaging_binding: { projected_address: phone }, identity: participant[:identity] }
|
|
69
|
+
else
|
|
70
|
+
{ messaging_binding: { address: phone } }
|
|
71
|
+
end
|
|
72
|
+
end.map(&:to_json)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def message_params_for(content, image_ids)
|
|
76
|
+
{
|
|
77
|
+
author: @params[:author], body: content,
|
|
78
|
+
media_sid: image_ids, x_twilio_webhook_enabled: 'true',
|
|
79
|
+
}.compact_blank
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Enhances the Twilio Ruby gem with an object-oriented approach.
|
|
2
|
+
module Twi
|
|
3
|
+
# An event signaling a status change for a conversation.
|
|
4
|
+
class ConversationEvent < Event
|
|
5
|
+
# @return [Hash] the shape of the payload send by Twilio to the callback URL.
|
|
6
|
+
def self.params_for(id:, status:)
|
|
7
|
+
{ ConversationSid: id, EventType: 'onConversationChanged', State: status.to_s }
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Enhances the Twilio Ruby gem with an object-oriented approach.
|
|
2
|
+
module Twi
|
|
3
|
+
# An event signaling the delivery of a message in a conversation.
|
|
4
|
+
class DeliveryEvent < Event
|
|
5
|
+
# @return [Hash] the shape of the payload send by Twilio to the callback URL.
|
|
6
|
+
def self.params_for(id:, participant_id:, message_id:, status:, code: nil)
|
|
7
|
+
{
|
|
8
|
+
ConversationSid: id, EventType: 'onDeliveryChanged', ParticipantSid: participant_id.to_s,
|
|
9
|
+
MessageSid: message_id, Status: status.to_s, ErrorCode: code
|
|
10
|
+
}.compact
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
data/lib/twi/error.rb
ADDED
data/lib/twi/event.rb
CHANGED
|
@@ -1,16 +1,9 @@
|
|
|
1
1
|
# Enhances the Twilio Ruby gem with an object-oriented approach.
|
|
2
2
|
module Twi
|
|
3
|
-
#
|
|
3
|
+
# An event tied to a (classic) conversation.
|
|
4
4
|
class Event < Resource
|
|
5
|
-
# @return [Symbol]
|
|
6
|
-
def target
|
|
7
|
-
case @params['EventType']
|
|
8
|
-
when 'onConversationAdded', 'onConversationStateUpdated' then :conversation
|
|
9
|
-
when 'onParticipantAdded' then :participant
|
|
10
|
-
when 'onMessageAdded' then :message
|
|
11
|
-
when 'onDeliveryUpdated' then :delivery
|
|
12
|
-
end
|
|
13
|
-
end
|
|
5
|
+
# @return [Symbol] event target type, can be :conversation, :participant, :message, :delivery.
|
|
6
|
+
def target = @params['EventType'].underscore.split('_').second.to_sym
|
|
14
7
|
|
|
15
8
|
# @return [String] conversation state, one of active, inactive, closed, initializing.
|
|
16
9
|
def status = @params['Status'] || @params['StateTo'] || @params['State']
|
|
@@ -26,7 +19,7 @@ module Twi
|
|
|
26
19
|
|
|
27
20
|
# @return [Array<String>] URLs of image attachments
|
|
28
21
|
def image_urls
|
|
29
|
-
media = JSON(@params.fetch('Media', '[]')).map { |params|
|
|
22
|
+
media = JSON(@params.fetch('Media', '[]')).map { |params| medium_for params }
|
|
30
23
|
media.filter(&:image?).map { |image| image.url }
|
|
31
24
|
end
|
|
32
25
|
|
|
@@ -35,5 +28,29 @@ module Twi
|
|
|
35
28
|
|
|
36
29
|
# @return [String, nil] error code
|
|
37
30
|
def code = @params['ErrorCode']
|
|
31
|
+
|
|
32
|
+
# @return [Hash] the shape of the payload send by Twilio to the callback URL.
|
|
33
|
+
def self.params_for(id:, type:, status: nil, participant: nil)
|
|
34
|
+
{
|
|
35
|
+
ConversationSid: id, EventType: "on_#{type}_changed".camelize(:lower),
|
|
36
|
+
State: status&.to_s,
|
|
37
|
+
}.merge(participant_params_for participant).compact
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def self.participant_params_for(participant = nil)
|
|
41
|
+
if participant
|
|
42
|
+
if participant[:identity]
|
|
43
|
+
{ ParticipantSid: participant[:id], Identity: participant[:identity] }
|
|
44
|
+
else
|
|
45
|
+
{ ParticipantSid: participant[:id], 'MessagingBinding.Address' => "+1#{participant[:phone]}" }
|
|
46
|
+
end
|
|
47
|
+
else
|
|
48
|
+
{}
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
def medium_for(params) = Medium.new params
|
|
38
55
|
end
|
|
39
56
|
end
|
data/lib/twi/lio.rb
CHANGED
|
@@ -30,18 +30,34 @@ module Twi
|
|
|
30
30
|
class Lio
|
|
31
31
|
# Initialize the global configuration settings defaulting to matching environment variables.
|
|
32
32
|
def initialize
|
|
33
|
-
@
|
|
33
|
+
@api_key = ENV['TWILIO_SID']
|
|
34
34
|
@secret = ENV['TWILIO_SECRET']
|
|
35
|
-
@
|
|
35
|
+
@account_sid = ENV['TWILIO_ACCOUNT_SID']
|
|
36
|
+
@auth_token = ENV['TWILIO_AUTH_TOKEN']
|
|
37
|
+
@conversation_sid = ENV['TWILIO_CONVERSATION_SERVICE_SID']
|
|
38
|
+
@messaging_sid = ENV['TWILIO_MESSAGING_SID']
|
|
39
|
+
@emergency_address_sid = ENV['TWILIO_EMERGENCY_SID']
|
|
36
40
|
end
|
|
37
41
|
|
|
38
|
-
# @return [String]
|
|
39
|
-
attr_reader :
|
|
42
|
+
# @return [String] API key - used for basic operations like sending messages.
|
|
43
|
+
attr_reader :api_key
|
|
40
44
|
|
|
41
|
-
# @return [String]
|
|
45
|
+
# @return [String] secret - to authenticate API requests made with +api_key+.
|
|
42
46
|
attr_reader :secret
|
|
43
47
|
|
|
44
|
-
# @return [String]
|
|
45
|
-
attr_reader :
|
|
48
|
+
# @return [String] Account SID - used for advanced operations like creating numbers.
|
|
49
|
+
attr_reader :account_sid
|
|
50
|
+
|
|
51
|
+
# @return [String] OAuth token - to authenticate API requests made with +account_sid+.
|
|
52
|
+
attr_reader :auth_token
|
|
53
|
+
|
|
54
|
+
# @return [String] the SID of the default Conversation service.
|
|
55
|
+
attr_reader :conversation_sid
|
|
56
|
+
|
|
57
|
+
# @return [String] the SID of the default Messaging service.
|
|
58
|
+
attr_reader :messaging_sid
|
|
59
|
+
|
|
60
|
+
# @return [String] the SID of the emergency address.
|
|
61
|
+
attr_reader :emergency_address_sid
|
|
46
62
|
end
|
|
47
63
|
end
|
data/lib/twi/medium.rb
CHANGED
|
@@ -18,7 +18,7 @@ module Twi
|
|
|
18
18
|
http.use_ssl = true
|
|
19
19
|
|
|
20
20
|
request = Net::HTTP::Get.new(uri.request_uri)
|
|
21
|
-
request.basic_auth Twi.lio.
|
|
21
|
+
request.basic_auth Twi.lio.api_key, Twi.lio.secret
|
|
22
22
|
response = http.request(request)
|
|
23
23
|
|
|
24
24
|
JSON(response.body).dig 'links', 'content_direct_temporary'
|
|
@@ -27,7 +27,7 @@ module Twi
|
|
|
27
27
|
private
|
|
28
28
|
|
|
29
29
|
def service_url
|
|
30
|
-
"https://mcs.us1.twilio.com/v1/Services/#{Twi.lio.
|
|
30
|
+
"https://mcs.us1.twilio.com/v1/Services/#{Twi.lio.conversation_sid}/Media/#{id}"
|
|
31
31
|
end
|
|
32
32
|
end
|
|
33
33
|
end
|
data/lib/twi/message.rb
CHANGED
|
@@ -30,6 +30,18 @@ module Twi
|
|
|
30
30
|
end
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
+
attr_reader :status
|
|
34
|
+
|
|
35
|
+
# Sends a message.
|
|
36
|
+
def create
|
|
37
|
+
message = api_client.messages.create messaging_service_sid: Twi.lio.messaging_sid.to_s,
|
|
38
|
+
from: "+1#{@params[:sender]}", to: "+1#{@params[:recipient]}", body: @params[:content]
|
|
39
|
+
|
|
40
|
+
@id = message.sid
|
|
41
|
+
@status = message.status
|
|
42
|
+
# todo rescue and then set @code
|
|
43
|
+
end
|
|
44
|
+
|
|
33
45
|
# @return [Hash] the shape of the payload send by Twilio to the callback URL.
|
|
34
46
|
def self.params_for(id:, sender:, recipient:, wallflower: nil, content: nil, opt: nil, media: [])
|
|
35
47
|
{
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Enhances the Twilio Ruby gem with an object-oriented approach.
|
|
2
|
+
module Twi
|
|
3
|
+
# An event signaling a new message in a conversation.
|
|
4
|
+
class MessageEvent < Event
|
|
5
|
+
# @return [Hash] the shape of the payload send by Twilio to the callback URL.
|
|
6
|
+
def self.params_for(id:, participant_id:, content: nil, media: [])
|
|
7
|
+
{
|
|
8
|
+
ConversationSid: id, EventType: 'onMessageChanged', ParticipantSid: participant_id.to_s,
|
|
9
|
+
MessageSid: "SM#{rand}", Body: content, Media: media_params_for(media),
|
|
10
|
+
}.compact_blank
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def self.media_params_for(media)
|
|
16
|
+
media.map do |medium|
|
|
17
|
+
{ Sid: medium[:id], ContentType: medium[:content_type] }
|
|
18
|
+
end.to_json if media.present?
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module Twi
|
|
2
|
+
class Mock::Conversation < Conversation
|
|
3
|
+
def create_with(participants:)
|
|
4
|
+
if Twi.mock.conversation_error
|
|
5
|
+
if Twi.mock.conversation_error[:code] == 50438
|
|
6
|
+
raise ExistingConversationError.new(Twi.mock.conversation_error[:message])
|
|
7
|
+
elsif Twi.mock.conversation_error[:code] == 50214
|
|
8
|
+
Twi.mock.conversation_error = nil
|
|
9
|
+
raise TooManyConversationsError
|
|
10
|
+
end
|
|
11
|
+
elsif Twi.mock.conversation
|
|
12
|
+
@id = Twi.mock.conversation[:id]
|
|
13
|
+
@status = Twi.mock.conversation[:status]
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def upload(file) = 'fake-sid'
|
|
18
|
+
|
|
19
|
+
def rename(friendly_name); end
|
|
20
|
+
|
|
21
|
+
def close; end
|
|
22
|
+
|
|
23
|
+
def delete; end
|
|
24
|
+
|
|
25
|
+
def create_message(content:, image_ids: [])
|
|
26
|
+
Mock::Message.new Twi.mock.message
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
data/lib/twi/mock.rb
ADDED
data/lib/twi/mocking.rb
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module Twi
|
|
2
|
+
module Mocking
|
|
3
|
+
def mock
|
|
4
|
+
@mock ||= Twi::Mock.new
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def create_phone(...)
|
|
8
|
+
phone(...).tap &:create
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def create_message(...)
|
|
12
|
+
message(...).tap &:create
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def conversation(...)
|
|
16
|
+
(@mock ? Mock::Conversation : Conversation).new(...)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def event(...)
|
|
20
|
+
(@mock ? Mock::Event : Event).new(...)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def phone(...)
|
|
24
|
+
(@mock ? Mock::Phone : Phone).new(...)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def message(...)
|
|
28
|
+
(@mock ? Mock::Message : Message).new(...)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
extend Mocking
|
|
33
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Enhances the Twilio Ruby gem with an object-oriented approach.
|
|
2
|
+
module Twi
|
|
3
|
+
# An event signaling a participant added to a conversation.
|
|
4
|
+
class ParticipantEvent < Event
|
|
5
|
+
# @return [Hash] the shape of the payload send by Twilio to the callback URL.
|
|
6
|
+
def self.params_for(id:, participant_id:, identity: nil, phone: nil)
|
|
7
|
+
{
|
|
8
|
+
ConversationSid: id, EventType: 'onParticipantChanged',
|
|
9
|
+
ParticipantSid: participant_id.to_s
|
|
10
|
+
}.merge participant_params_for(identity, phone)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def self.participant_params_for(identity, phone)
|
|
16
|
+
identity ? { Identity: identity } : { 'MessagingBinding.Address' => "+1#{phone}" }
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
data/lib/twi/phone.rb
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Enhances the Twilio Ruby gem with an object-oriented approach.
|
|
2
|
+
module Twi
|
|
3
|
+
# The representation of a phone number associated to the default messaging service.
|
|
4
|
+
class Phone < Resource
|
|
5
|
+
# Create an incoming phone number within the area code and friendly name.
|
|
6
|
+
def create
|
|
7
|
+
phone = client.incoming_phone_numbers.create area_code: @params[:area_code],
|
|
8
|
+
emergency_address_sid: Twi.lio.emergency_address_sid, friendly_name: @params[:friendly_name]
|
|
9
|
+
messaging_service.phone_numbers.create phone_number_sid: phone.sid
|
|
10
|
+
|
|
11
|
+
@id = phone.sid
|
|
12
|
+
@number = remove_prefix_from phone.phone_number
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# @return [String] unique identifier of the phone.
|
|
16
|
+
attr_reader :id
|
|
17
|
+
|
|
18
|
+
# @return [String] 10-digit number.
|
|
19
|
+
attr_reader :number
|
|
20
|
+
end
|
|
21
|
+
end
|
data/lib/twi/resource.rb
CHANGED
|
@@ -10,5 +10,13 @@ module Twi
|
|
|
10
10
|
private
|
|
11
11
|
|
|
12
12
|
def remove_prefix_from(number) = number&.strip&.delete_prefix '+1'
|
|
13
|
+
|
|
14
|
+
def client = Twilio::REST::Client.new Twi.lio.account_sid, Twi.lio.auth_token
|
|
15
|
+
|
|
16
|
+
def api_client = Twilio::REST::Client.new Twi.lio.api_key, Twi.lio.secret
|
|
17
|
+
|
|
18
|
+
def messaging_service = client.messaging.v1.services Twi.lio.messaging_sid.to_s
|
|
19
|
+
|
|
20
|
+
def conversation_service = client.conversations.v1.services Twi.lio.conversation_sid.to_s
|
|
13
21
|
end
|
|
14
22
|
end
|
data/lib/twi/version.rb
CHANGED
data/lib/twi.rb
CHANGED
|
@@ -2,11 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
require 'action_controller'
|
|
4
4
|
require 'action_controller/metal/strong_parameters'
|
|
5
|
+
require 'active_support/core_ext/enumerable'
|
|
6
|
+
require 'active_support/core_ext/object/blank'
|
|
5
7
|
require 'json'
|
|
6
8
|
require 'net/http'
|
|
7
9
|
require 'twilio-ruby'
|
|
8
10
|
|
|
9
11
|
require 'twi/lio'
|
|
12
|
+
require 'twi/error'
|
|
10
13
|
require 'twi/config'
|
|
11
14
|
require 'twi/resource'
|
|
12
15
|
require 'twi/message'
|
|
@@ -14,3 +17,17 @@ require 'twi/delivery'
|
|
|
14
17
|
require 'twi/participant'
|
|
15
18
|
require 'twi/medium'
|
|
16
19
|
require 'twi/event'
|
|
20
|
+
require 'twi/conversation_event'
|
|
21
|
+
require 'twi/delivery_event'
|
|
22
|
+
require 'twi/message_event'
|
|
23
|
+
require 'twi/participant_event'
|
|
24
|
+
require 'twi/phone'
|
|
25
|
+
require 'twi/conversation'
|
|
26
|
+
|
|
27
|
+
require 'twi/mock'
|
|
28
|
+
require 'twi/mock/phone'
|
|
29
|
+
require 'twi/mock/conversation'
|
|
30
|
+
require 'twi/mock/event'
|
|
31
|
+
require 'twi/mock/medium'
|
|
32
|
+
require 'twi/mock/message'
|
|
33
|
+
require 'twi/mocking'
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: twi
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Claudio Baccigalupo
|
|
@@ -49,12 +49,26 @@ files:
|
|
|
49
49
|
- README.md
|
|
50
50
|
- lib/twi.rb
|
|
51
51
|
- lib/twi/config.rb
|
|
52
|
+
- lib/twi/conversation.rb
|
|
53
|
+
- lib/twi/conversation_event.rb
|
|
52
54
|
- lib/twi/delivery.rb
|
|
55
|
+
- lib/twi/delivery_event.rb
|
|
56
|
+
- lib/twi/error.rb
|
|
53
57
|
- lib/twi/event.rb
|
|
54
58
|
- lib/twi/lio.rb
|
|
55
59
|
- lib/twi/medium.rb
|
|
56
60
|
- lib/twi/message.rb
|
|
61
|
+
- lib/twi/message_event.rb
|
|
62
|
+
- lib/twi/mock.rb
|
|
63
|
+
- lib/twi/mock/conversation.rb
|
|
64
|
+
- lib/twi/mock/event.rb
|
|
65
|
+
- lib/twi/mock/medium.rb
|
|
66
|
+
- lib/twi/mock/message.rb
|
|
67
|
+
- lib/twi/mock/phone.rb
|
|
68
|
+
- lib/twi/mocking.rb
|
|
57
69
|
- lib/twi/participant.rb
|
|
70
|
+
- lib/twi/participant_event.rb
|
|
71
|
+
- lib/twi/phone.rb
|
|
58
72
|
- lib/twi/resource.rb
|
|
59
73
|
- lib/twi/version.rb
|
|
60
74
|
homepage: https://github.com/claudiob/twi
|