twi 0.8.0 → 0.9.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 +9 -0
- data/README.md +66 -2
- data/lib/twi/call.rb +36 -0
- data/lib/twi/mock/call.rb +25 -0
- data/lib/twi/mock.rb +4 -0
- data/lib/twi/mocking.rb +4 -0
- data/lib/twi/version.rb +1 -3
- data/lib/twi.rb +2 -2
- metadata +63 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a7531d7fa92db501d0d81a5b9d8ad8108614c63d1260b465a2a0367ef716293c
|
|
4
|
+
data.tar.gz: 496ac9be22cf2840ae6eeaa5897347ad0402039daad423030b446aae17a8c23e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e2d906451f3d4c5e8fc2f1cb8fd26b998998bee953d89675594b822b2cad6f55b06b80770540a135d0381d0f537cd16c0f5faada49e0ead42c23cf54302a5460
|
|
7
|
+
data.tar.gz: c1605aa3aca9c09af360e1ee871c3a9e29787498ad85ba3c38547bda3568f9237d9c6c7c4d45919c7875eb0b08bca0140677aa2145f654cb1e559fb6de34b23b
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
## [Unreleased]
|
|
2
|
+
|
|
3
|
+
## [0.9.0] - 2026-09-14
|
|
4
|
+
|
|
5
|
+
- [New] Place a call with Twi.create_call, telling Twilio where to read its TwiML
|
|
6
|
+
- [New] Add Twi::Call, to read the webhook Twilio reports a call on
|
|
7
|
+
- [New] Add Twi::Call.params_for, to build a call webhook payload in a test
|
|
8
|
+
- [New] Add Twi.mock.call, Twi.mock.call_error and Twi.mock.calls
|
|
9
|
+
|
|
1
10
|
## [0.8.0] - 2026-09-11
|
|
2
11
|
|
|
3
12
|
- [New] Send media with a message: `Twi.create_message media_url:` carries it as an MMS
|
data/README.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# The enhanced Twilio API Ruby client
|
|
2
2
|
|
|
3
|
+
## How to install
|
|
4
|
+
|
|
5
|
+
To install on your system, run:
|
|
6
|
+
|
|
7
|
+
gem install twi
|
|
8
|
+
|
|
9
|
+
To use inside a bundled Ruby project, add this line to the Gemfile:
|
|
10
|
+
|
|
11
|
+
gem 'twi', '~> 0.9.0'
|
|
12
|
+
|
|
13
|
+
This gem follows [Semantic Versioning](https://semver.org). Below 1.0 a minor release may
|
|
14
|
+
break an API, so the pin stops short of 0.10: `bundle update` never crosses one.
|
|
15
|
+
|
|
3
16
|
## Available methods
|
|
4
17
|
|
|
5
18
|
### Twi::Message
|
|
@@ -43,6 +56,36 @@ Twi::Delivery.params_for id: 'SM12', status: 'sent'
|
|
|
43
56
|
# => { SmsSid: 'SM12', MessgeStatus: 'sent', ErrorCode: nil }
|
|
44
57
|
```
|
|
45
58
|
|
|
59
|
+
### Twi::Call
|
|
60
|
+
|
|
61
|
+
To place an outbound call, telling Twilio where to read its instructions and where to
|
|
62
|
+
report on how it went:
|
|
63
|
+
|
|
64
|
+
```ruby
|
|
65
|
+
call = Twi.create_call sender: '8008008000', recipient: '8009007000',
|
|
66
|
+
url: 'https://example.com/twiml', status_callback: 'https://example.com/calls'
|
|
67
|
+
call.id # => 'CA083e290bef7794c407f14e22a891aa6d'
|
|
68
|
+
call.status # => 'queued'
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
When receiving an update about a call via webhook:
|
|
72
|
+
|
|
73
|
+
```ruby
|
|
74
|
+
call = Twi::Call.new params
|
|
75
|
+
call.id # => 'CA083e290bef7794c407f14e22a891aa6d'
|
|
76
|
+
call.status # => 'completed'
|
|
77
|
+
call.digits # => '2'
|
|
78
|
+
call.sender # => '8008008000'
|
|
79
|
+
call.recipient # => '8009007000'
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
When building a Twilio-like webhook payload:
|
|
83
|
+
|
|
84
|
+
```ruby
|
|
85
|
+
Twi::Call.params_for id: 'CA12', status: 'completed', digits: '2'
|
|
86
|
+
# => { CallSid: 'CA12', CallStatus: 'completed', Digits: '2' }
|
|
87
|
+
```
|
|
88
|
+
|
|
46
89
|
### Twi::Event
|
|
47
90
|
|
|
48
91
|
When receiving events about a conversation:
|
|
@@ -74,13 +117,34 @@ Use these methods to mock request to Twilio when testing an app:
|
|
|
74
117
|
Mock an error when creating an incoming phone number:
|
|
75
118
|
|
|
76
119
|
```ruby
|
|
77
|
-
|
|
120
|
+
Twi.mock.phone_error = { code: '21452' }
|
|
78
121
|
```
|
|
79
122
|
|
|
80
123
|
Mock successfully creating an incoming phone number:
|
|
81
124
|
|
|
82
125
|
```ruby
|
|
83
|
-
|
|
126
|
+
Twi.mock.phone = { id: 'SM083e290bef7794c407f14e65a891aa6d', number: '8009005000' }
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Calls
|
|
130
|
+
|
|
131
|
+
Mock an error when placing a call:
|
|
132
|
+
|
|
133
|
+
```ruby
|
|
134
|
+
Twi.mock.call_error = { code: '21215' }
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Mock successfully placing a call:
|
|
138
|
+
|
|
139
|
+
```ruby
|
|
140
|
+
Twi.mock.call = { id: 'CA083e290bef7794c407f14e22a891aa6d', status: 'queued' }
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Read back every call placed since the mock was reset, to assert what a suite sent:
|
|
144
|
+
|
|
145
|
+
```ruby
|
|
146
|
+
Twi.mock.calls # => [{ sender: '8008008000', recipient: '8009007000', url: 'https://example.com/twiml',
|
|
147
|
+
# status_callback: 'https://example.com/calls' }]
|
|
84
148
|
```
|
|
85
149
|
|
|
86
150
|
|
data/lib/twi/call.rb
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Enhances the Twilio Ruby gem with an object-oriented approach.
|
|
2
|
+
module Twi
|
|
3
|
+
# The representation of an outbound phone call.
|
|
4
|
+
class Call < Resource
|
|
5
|
+
# @return [String] unique identifier
|
|
6
|
+
def id = @params['CallSid']
|
|
7
|
+
|
|
8
|
+
# @return [String] call status, one of queued, ringing, in-progress, completed, busy,
|
|
9
|
+
# no-answer, canceled, failed # TODO: make an enum
|
|
10
|
+
def status = @params['CallStatus']
|
|
11
|
+
|
|
12
|
+
# @return [String, nil] digits the callee pressed in answer to a Gather.
|
|
13
|
+
def digits = @params['Digits']
|
|
14
|
+
|
|
15
|
+
# @return [String] 10-digit phone number placing the call.
|
|
16
|
+
def sender = remove_prefix_from @params['From']
|
|
17
|
+
|
|
18
|
+
# @return [String] 10-digit phone number being called.
|
|
19
|
+
def recipient = remove_prefix_from @params['To']
|
|
20
|
+
|
|
21
|
+
# Places the call, asking Twilio to fetch its instructions from +url+.
|
|
22
|
+
def create
|
|
23
|
+
call = api_client.calls.create from: "+1#{@params[:sender]}", to: "+1#{@params[:recipient]}",
|
|
24
|
+
url: @params[:url], method: 'GET', status_callback: @params[:status_callback]
|
|
25
|
+
|
|
26
|
+
@params = { 'CallSid' => call.sid, 'CallStatus' => call.status }
|
|
27
|
+
rescue Twilio::REST::RestError => error
|
|
28
|
+
raise Error, code: error.code, message: error.error_message
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# @return [Hash] the shape of the payload send by Twilio to the callback URL.
|
|
32
|
+
def self.params_for(id:, status:, digits: nil)
|
|
33
|
+
{ CallSid: id, CallStatus: status, Digits: digits }.compact
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Twi
|
|
2
|
+
class Mock::Call < Call
|
|
3
|
+
# @return [String] unique identifier
|
|
4
|
+
def id = @params[:id]
|
|
5
|
+
|
|
6
|
+
# @return [String] call status
|
|
7
|
+
def status = @params[:status]
|
|
8
|
+
|
|
9
|
+
# Records the call rather than placing it, and answers whatever the suite arranged.
|
|
10
|
+
def create
|
|
11
|
+
Twi.mock.calls << @params.slice(:sender, :recipient, :url, :status_callback)
|
|
12
|
+
|
|
13
|
+
if error = Twi.mock.call_error
|
|
14
|
+
Twi.mock.call_error = nil
|
|
15
|
+
raise Error, error
|
|
16
|
+
elsif Twi.mock.call
|
|
17
|
+
@params[:id] = Twi.mock.call[:id]
|
|
18
|
+
@params[:status] = Twi.mock.call[:status]
|
|
19
|
+
else
|
|
20
|
+
@params[:id] = "CA#{rand}"
|
|
21
|
+
@params[:status] = 'queued'
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
data/lib/twi/mock.rb
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
module Twi
|
|
2
2
|
class Mock
|
|
3
3
|
attr_accessor :phone, :phone_error
|
|
4
|
+
attr_accessor :call, :call_error
|
|
4
5
|
attr_accessor :message, :message_error
|
|
5
6
|
attr_accessor :conversation, :conversation_error
|
|
6
7
|
attr_accessor :medium
|
|
7
8
|
|
|
8
9
|
# @return [Array<Hash>] every message sent since the mock was reset, in order.
|
|
9
10
|
def messages = @messages ||= []
|
|
11
|
+
|
|
12
|
+
# @return [Array<Hash>] every call placed since the mock was reset, in order.
|
|
13
|
+
def calls = @calls ||= []
|
|
10
14
|
end
|
|
11
15
|
end
|
data/lib/twi/mocking.rb
CHANGED
data/lib/twi/version.rb
CHANGED
data/lib/twi.rb
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
1
|
require 'action_controller'
|
|
4
2
|
require 'action_controller/metal/strong_parameters'
|
|
5
3
|
require 'active_support/core_ext/enumerable'
|
|
@@ -14,6 +12,7 @@ require 'twi/config'
|
|
|
14
12
|
require 'twi/resource'
|
|
15
13
|
require 'twi/message'
|
|
16
14
|
require 'twi/delivery'
|
|
15
|
+
require 'twi/call'
|
|
17
16
|
require 'twi/participant'
|
|
18
17
|
require 'twi/medium'
|
|
19
18
|
require 'twi/event'
|
|
@@ -30,4 +29,5 @@ require 'twi/mock/conversation'
|
|
|
30
29
|
require 'twi/mock/event'
|
|
31
30
|
require 'twi/mock/medium'
|
|
32
31
|
require 'twi/mock/message'
|
|
32
|
+
require 'twi/mock/call'
|
|
33
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.9.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Claudio Baccigalupo
|
|
@@ -37,7 +37,64 @@ dependencies:
|
|
|
37
37
|
- - ">="
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
39
|
version: '0'
|
|
40
|
-
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: minitest
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '0'
|
|
47
|
+
type: :development
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: rake
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0'
|
|
61
|
+
type: :development
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '0'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: simplecov
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - ">="
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '0'
|
|
75
|
+
type: :development
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - ">="
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '0'
|
|
82
|
+
- !ruby/object:Gem::Dependency
|
|
83
|
+
name: webmock
|
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - ">="
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '0'
|
|
89
|
+
type: :development
|
|
90
|
+
prerelease: false
|
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - ">="
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: '0'
|
|
96
|
+
description: Sends messages, places calls and reads the webhooks Twilio answers them
|
|
97
|
+
with.
|
|
41
98
|
email:
|
|
42
99
|
- claudiob@users.noreply.github.com
|
|
43
100
|
executables: []
|
|
@@ -48,6 +105,7 @@ files:
|
|
|
48
105
|
- LICENSE.txt
|
|
49
106
|
- README.md
|
|
50
107
|
- lib/twi.rb
|
|
108
|
+
- lib/twi/call.rb
|
|
51
109
|
- lib/twi/config.rb
|
|
52
110
|
- lib/twi/conversation.rb
|
|
53
111
|
- lib/twi/conversation_event.rb
|
|
@@ -60,6 +118,7 @@ files:
|
|
|
60
118
|
- lib/twi/message.rb
|
|
61
119
|
- lib/twi/message_event.rb
|
|
62
120
|
- lib/twi/mock.rb
|
|
121
|
+
- lib/twi/mock/call.rb
|
|
63
122
|
- lib/twi/mock/conversation.rb
|
|
64
123
|
- lib/twi/mock/event.rb
|
|
65
124
|
- lib/twi/mock/medium.rb
|
|
@@ -78,6 +137,7 @@ metadata:
|
|
|
78
137
|
homepage_uri: https://github.com/claudiob/twi
|
|
79
138
|
source_code_uri: https://github.com/claudiob/twi
|
|
80
139
|
changelog_uri: https://github.com/claudiob/twi
|
|
140
|
+
documentation_uri: https://rubydoc.info/gems/twi
|
|
81
141
|
rdoc_options: []
|
|
82
142
|
require_paths:
|
|
83
143
|
- lib
|
|
@@ -94,5 +154,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
94
154
|
requirements: []
|
|
95
155
|
rubygems_version: 4.0.3
|
|
96
156
|
specification_version: 4
|
|
97
|
-
summary:
|
|
157
|
+
summary: An object-oriented Ruby client for the Twilio API.
|
|
98
158
|
test_files: []
|