telnyx 2.3.0 → 2.4.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/.github/scripts/before_install.sh +9 -0
- data/.github/workflows/ruby.yml +39 -0
- data/.rubocop.yml +6 -36
- data/.rubocop_todo.yml +300 -0
- data/.travis.yml.bak +48 -0
- data/Gemfile +6 -6
- data/README.md +1 -1
- data/VERSION +1 -1
- data/bin/telnyx-console +5 -0
- data/examples/2 factor authentication/Gemfile +7 -0
- data/examples/2 factor authentication/main.rb +67 -0
- data/examples/2 factor authentication/readme.md +5 -0
- data/examples/fax/Gemfile +7 -0
- data/examples/fax/config.yaml +4 -0
- data/examples/fax/fax.rb +42 -0
- data/examples/fax/options.rb +41 -0
- data/examples/fax/readme.md +18 -0
- data/lib/telnyx.rb +5 -1
- data/lib/telnyx/api_operations/save.rb +1 -1
- data/lib/telnyx/api_resource.rb +14 -3
- data/lib/telnyx/conference.rb +17 -1
- data/lib/telnyx/fax.rb +13 -0
- data/lib/telnyx/fax_application.rb +12 -0
- data/lib/telnyx/messaging_phone_number.rb +9 -0
- data/lib/telnyx/phone_number.rb +5 -1
- data/lib/telnyx/sim_card.rb +12 -1
- data/lib/telnyx/telnyx_client.rb +15 -24
- data/lib/telnyx/util.rb +7 -1
- data/lib/telnyx/verification.rb +27 -0
- data/lib/telnyx/verify_profile.rb +11 -0
- data/lib/telnyx/version.rb +1 -1
- data/telnyx.gemspec +1 -1
- data/test/telnyx/call_control_test.rb +3 -3
- data/test/telnyx/conference_test.rb +57 -20
- data/test/telnyx/credential_connection_test.rb +5 -1
- data/test/telnyx/fax_application_test.rb +32 -0
- data/test/telnyx/fax_test.rb +32 -0
- data/test/telnyx/fqdn_connection_test.rb +1 -1
- data/test/telnyx/fqdn_test.rb +1 -1
- data/test/telnyx/messaging_phone_number_test.rb +8 -4
- data/test/telnyx/messaging_profile_test.rb +1 -1
- data/test/telnyx/phone_number_test.rb +9 -21
- data/test/telnyx/sim_card_test.rb +6 -6
- data/test/telnyx/telnyx_object_test.rb +5 -5
- data/test/telnyx/verification_test.rb +22 -0
- data/test/telnyx/verify_profile_test.rb +31 -0
- data/test/test_helper.rb +1 -1
- metadata +36 -7
- data/.travis.yml +0 -51
data/Gemfile
CHANGED
@@ -6,7 +6,7 @@ gemspec
|
|
6
6
|
|
7
7
|
group :development do
|
8
8
|
gem "coveralls", require: false
|
9
|
-
gem "faraday", "0.
|
9
|
+
gem "faraday", "0.17.3"
|
10
10
|
gem "mocha", "~> 0.13.2"
|
11
11
|
gem "rake"
|
12
12
|
gem "shoulda-context"
|
@@ -22,20 +22,20 @@ group :development do
|
|
22
22
|
gem "guard"
|
23
23
|
gem "guard-rake"
|
24
24
|
gem "guard-rubocop"
|
25
|
-
gem "rubocop", "
|
25
|
+
gem "rubocop", "~> 1.6"
|
26
26
|
|
27
27
|
# Rack 2.0+ requires Ruby >= 2.2.2 which is problematic for the test suite on
|
28
28
|
# older Ruby versions. Check Ruby the version here and put a maximum
|
29
29
|
# constraint on Rack if necessary.
|
30
30
|
if RUBY_VERSION >= "2.2.2"
|
31
|
-
gem "rack", ">= 2.
|
31
|
+
gem "rack", ">= 2.1.4"
|
32
32
|
else
|
33
33
|
gem "rack", ">= 1.6.11", "< 2.0" # rubocop:disable Bundler/DuplicatedGem
|
34
34
|
end
|
35
35
|
|
36
36
|
platforms :mri do
|
37
|
-
gem "byebug"
|
38
|
-
gem "pry"
|
39
|
-
gem "pry-byebug"
|
37
|
+
# gem "byebug"
|
38
|
+
# gem "pry"
|
39
|
+
# gem "pry-byebug"
|
40
40
|
end
|
41
41
|
end
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Telnyx Ruby Library
|
2
2
|
|
3
|
-
|
3
|
+

|
4
4
|
[](https://coveralls.io/github/team-telnyx/telnyx-ruby?branch=master)
|
5
5
|
[](https://joinslack.telnyx.com/)
|
6
6
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2.4.0
|
data/bin/telnyx-console
CHANGED
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "telnyx"
|
4
|
+
require "amazing_print" # for displaying the api requests nicely.
|
5
|
+
require "tty-prompt" # for prettier interactive prompts.
|
6
|
+
|
7
|
+
Telnyx.api_key = ENV["TELNYX_KEY"] # Set your key here
|
8
|
+
raise "Please set your API key in this script, or set the TELNYX_KEY env variable!" unless Telnyx.api_key
|
9
|
+
|
10
|
+
class Demo
|
11
|
+
def initialize
|
12
|
+
@prompt = TTY::Prompt.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def start
|
16
|
+
create_profile
|
17
|
+
puts "Profile object returned from API:"
|
18
|
+
ap @profile
|
19
|
+
|
20
|
+
verify
|
21
|
+
puts "Verification object returned from API:"
|
22
|
+
ap @verification
|
23
|
+
|
24
|
+
puts "A SMS should be sent to the phone number soon."
|
25
|
+
check_prompt
|
26
|
+
end
|
27
|
+
|
28
|
+
def create_profile
|
29
|
+
# Ask what to call the new verification profile.
|
30
|
+
profile_name = @prompt.ask("Profile name:", default: "demo profile")
|
31
|
+
# Check if we already created a demo profile.
|
32
|
+
existing_profile = Telnyx::VerifyProfile.list.first { |p| p.name == profile_name }
|
33
|
+
# Check if we should use the existing one.
|
34
|
+
return @profile = existing_profile if existing_profile && @prompt.yes?(%(Found a profile already called "#{profile_name}", would you like to use that instead of creating a new profile?))
|
35
|
+
|
36
|
+
# Create a new profile.
|
37
|
+
@profile = Telnyx::VerifyProfile.create name: profile_name
|
38
|
+
end
|
39
|
+
|
40
|
+
def verify
|
41
|
+
# Create a new verification, this will send a code via SMS to the number provided.
|
42
|
+
@verification = Telnyx::Verification.create(
|
43
|
+
type: "sms",
|
44
|
+
verify_profile_id: @profile.id,
|
45
|
+
phone_number: @prompt.ask("Enter a phone number to send a verification code to (must be e164 format, e.g., +15554443333):", value: "+1") { |p| p.validate(/^\+?[1-9]\d{1,14}$/) }
|
46
|
+
)
|
47
|
+
end
|
48
|
+
|
49
|
+
def check_prompt
|
50
|
+
loop do
|
51
|
+
# Ask the user for the verification code.
|
52
|
+
code = @prompt.ask "Enter verification code:"
|
53
|
+
# Ask the api if this is the correct code.
|
54
|
+
response = Telnyx::Verification.submit_code code: code, phone_number: @verification.phone_number
|
55
|
+
puts "Api responded with:"
|
56
|
+
ap response
|
57
|
+
|
58
|
+
# If it's not the right code try again.
|
59
|
+
break if response.response_code == "accepted"
|
60
|
+
|
61
|
+
puts "\e[31mIncorrect code, try again!\e[0m"
|
62
|
+
create_profile if @prompt.yes?("Resend code?")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
Demo.new.start
|
data/examples/fax/fax.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "telnyx"
|
4
|
+
require_relative "options"
|
5
|
+
require "sinatra/base"
|
6
|
+
require "json"
|
7
|
+
require "amazing_print"
|
8
|
+
require "uri"
|
9
|
+
|
10
|
+
class WebhookServer < Sinatra::Base
|
11
|
+
set :port, 9090
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
super
|
15
|
+
Thread.new { telnyx_setup }
|
16
|
+
end
|
17
|
+
|
18
|
+
def telnyx_setup
|
19
|
+
@fax_application = Telnyx::FaxApplication.retrieve CONFIG.fax_app_id
|
20
|
+
@fax_application.webhook_event_url = CONFIG.webhook_url
|
21
|
+
@fax_application.save
|
22
|
+
|
23
|
+
puts "## Fax Send Request ##"
|
24
|
+
ap @sent_fax = Telnyx::Fax.create(
|
25
|
+
connection_id: CONFIG["outbound_connection_id"],
|
26
|
+
media_url: CONFIG.document_url,
|
27
|
+
to: CONFIG.to,
|
28
|
+
from: CONFIG.from,
|
29
|
+
outbound_voice_profile_id: CONFIG.outbound_voice_profile_id
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Receive webhooks
|
34
|
+
post "/*" do
|
35
|
+
hook = JSON.parse(request.body.read, symbolize_names: true)
|
36
|
+
puts "## Received Webhook ##"
|
37
|
+
ap hook
|
38
|
+
200
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
WebhookServer.run!
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Helper script to parse the command line options.
|
4
|
+
|
5
|
+
require "optparse"
|
6
|
+
require "ostruct"
|
7
|
+
require "yaml"
|
8
|
+
|
9
|
+
CONFIG = OpenStruct.new(
|
10
|
+
document_url: "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
|
11
|
+
**YAML.safe_load(open("config.yaml")).to_h
|
12
|
+
)
|
13
|
+
OptionParser.new do |opts|
|
14
|
+
opts.banner = "Telnyx fax demo\nUsage: bundle exec fax.rb -- [options]"
|
15
|
+
|
16
|
+
opts.on("-h", "--help", "Prints this help") do
|
17
|
+
puts opts
|
18
|
+
exit
|
19
|
+
end
|
20
|
+
|
21
|
+
opts.on(
|
22
|
+
"-h=URL", "--webhook-url=URL",
|
23
|
+
"[REQUIRED] URL to send webhook events to. This should be an address exposed to the internet. For testing purposes try Ngrok or Hookbin."
|
24
|
+
) { |url| CONFIG.webhook_url = url }
|
25
|
+
|
26
|
+
opts.on(
|
27
|
+
"-k=KEY", "--api-key=KEY", "[REQUIRED] Telnyx API key."
|
28
|
+
) { |key| CONFIG.api_key = Telnyx.api_key = key }
|
29
|
+
|
30
|
+
opts.on(
|
31
|
+
"--to=NUMBER", "Phone number to send a fax to"
|
32
|
+
) { |number| CONFIG.to = number }
|
33
|
+
|
34
|
+
opts.on(
|
35
|
+
"--document-url=URL", "URL for document to fax. Default is https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"
|
36
|
+
) { |url| CONFIG.document_url = url }
|
37
|
+
end.parse!
|
38
|
+
|
39
|
+
missing_args = %i[webhook_url api_key] - CONFIG.to_h.keys
|
40
|
+
missing_args.any? and raise OptionParser::MissingArgument, "missing the following options: [#{missing_args.join ', '}]. Use --help for more information."
|
41
|
+
CONFIG.to_h.values.any?(&:nil?) and raise "Missing config values, check config.yaml"
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Usage
|
2
|
+
|
3
|
+
For convince use a utility like Ngrok or Hookbin to expose the demo server to the internet. For example with Ngrok run the following: `ngrok http 9090` and copy the exposed url, you will need this to properly complete the setup below.
|
4
|
+
|
5
|
+
Before you can use the demo application you will need to login to your telnyx portal and configure the following:
|
6
|
+
|
7
|
+
1. You will need to setup an inbound and an outbound Fax Application for this demo.
|
8
|
+
2. Create two phone numbers:
|
9
|
+
- One for inbound faxes, this will need to be associated with a fax application.
|
10
|
+
- One for outbound faxes.
|
11
|
+
3. You will also need to create a SIP Connection for your outbound faxes, be sure to configure it to use your webhook url.
|
12
|
+
|
13
|
+
Finally you will need to fill out `config.yaml` with the IDs listed, as well as with the outbound and inbound phone numbers.
|
14
|
+
|
15
|
+
```
|
16
|
+
bundle
|
17
|
+
bundle exec ruby main.rb --api-key=<YOUR API KEY>
|
18
|
+
```
|
data/lib/telnyx.rb
CHANGED
@@ -40,12 +40,14 @@ require "telnyx/address"
|
|
40
40
|
require "telnyx/alphanumeric_sender_id"
|
41
41
|
require "telnyx/available_phone_number"
|
42
42
|
require "telnyx/billing_group"
|
43
|
+
require "telnyx/call_control_application"
|
43
44
|
require "telnyx/call"
|
44
45
|
require "telnyx/conference"
|
45
46
|
require "telnyx/connection"
|
46
|
-
require "telnyx/call_control_application"
|
47
47
|
require "telnyx/credential_connection"
|
48
48
|
require "telnyx/event"
|
49
|
+
require "telnyx/fax"
|
50
|
+
require "telnyx/fax_application"
|
49
51
|
require "telnyx/fqdn_connection"
|
50
52
|
require "telnyx/fqdn"
|
51
53
|
require "telnyx/ip_connection"
|
@@ -64,6 +66,8 @@ require "telnyx/portout"
|
|
64
66
|
require "telnyx/public_key"
|
65
67
|
require "telnyx/regulatory_requirement"
|
66
68
|
require "telnyx/sim_card"
|
69
|
+
require "telnyx/verification"
|
70
|
+
require "telnyx/verify_profile"
|
67
71
|
require "telnyx/wireless_detail_records_report"
|
68
72
|
|
69
73
|
module Telnyx
|
data/lib/telnyx/api_resource.rb
CHANGED
@@ -14,13 +14,22 @@ module Telnyx
|
|
14
14
|
name.split("::")[-1]
|
15
15
|
end
|
16
16
|
|
17
|
-
def self.resource_url
|
17
|
+
def self.resource_url(inner_id = nil)
|
18
18
|
if self == APIResource
|
19
19
|
raise NotImplementedError, "APIResource is an abstract class. You should perform actions on its subclasses"
|
20
20
|
end
|
21
21
|
# Namespaces are separated in object names with periods (.) and in URLs
|
22
22
|
# with forward slashes (/), so replace the former with the latter.
|
23
|
-
|
23
|
+
return "/v2/#{resource_path(inner_id)}" if respond_to?("resource_path")
|
24
|
+
return "/v2/#{self::RESOURCE_PATH}" if const_defined?("RESOURCE_PATH")
|
25
|
+
|
26
|
+
"/v2/#{self::OBJECT_NAME.downcase.tr('.', '/')}s"
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.identified_resource_url(id)
|
30
|
+
return "/v2/#{resource_path(id)}" if respond_to?("resource_path")
|
31
|
+
|
32
|
+
"#{resource_url}/#{CGI.escape(id)}"
|
24
33
|
end
|
25
34
|
|
26
35
|
# A metaprogramming call that specifies that a field of a resource can be
|
@@ -51,6 +60,8 @@ module Telnyx
|
|
51
60
|
unless (id = self["id"])
|
52
61
|
raise InvalidRequestError, "Could not determine which URL to request: #{self.class} instance has invalid ID: #{id.inspect}"
|
53
62
|
end
|
63
|
+
return self.class.resource_url(id).to_s if self.class.respond_to?("resource_path") # Use resource_path defined paths
|
64
|
+
|
54
65
|
"#{self.class.resource_url}/#{CGI.escape(id)}"
|
55
66
|
end
|
56
67
|
|
@@ -61,7 +72,7 @@ module Telnyx
|
|
61
72
|
|
62
73
|
def self.retrieve(id, opts = {})
|
63
74
|
opts = Util.normalize_opts(opts)
|
64
|
-
instance = new(id, opts)
|
75
|
+
instance = new(id, **opts)
|
65
76
|
instance.refresh
|
66
77
|
instance
|
67
78
|
end
|
data/lib/telnyx/conference.rb
CHANGED
@@ -6,7 +6,7 @@ module Telnyx
|
|
6
6
|
extend APIOperations::Create
|
7
7
|
extend APIOperations::NestedResource
|
8
8
|
|
9
|
-
ACTIONS = %w[join mute unmute hold unhold].freeze
|
9
|
+
ACTIONS = %w[join mute unmute hold unhold speak play dial_participant update].freeze
|
10
10
|
|
11
11
|
ACTIONS.each do |action|
|
12
12
|
nested_resource_class_methods action,
|
@@ -14,6 +14,22 @@ module Telnyx
|
|
14
14
|
operations: [:create],
|
15
15
|
instance_methods: { create: action }
|
16
16
|
end
|
17
|
+
|
18
|
+
nested_resource_class_methods "record_start",
|
19
|
+
path: ["actions", "record_start"],
|
20
|
+
operations: [:create],
|
21
|
+
instance_methods: { create: "start_recording" }
|
22
|
+
|
23
|
+
nested_resource_class_methods "record_stop",
|
24
|
+
path: ["actions", "record_stop"],
|
25
|
+
operations: [:create],
|
26
|
+
instance_methods: { create: "stop_recording" }
|
27
|
+
|
28
|
+
nested_resource_class_methods "participants",
|
29
|
+
path: "participants",
|
30
|
+
operations: [:list],
|
31
|
+
instance_methods: { list: "participants" }
|
32
|
+
|
17
33
|
OBJECT_NAME = "conference".freeze
|
18
34
|
end
|
19
35
|
Conferences = Conference # Name change without breaking existing code
|
data/lib/telnyx/fax.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Telnyx
|
4
|
+
class Fax < APIResource
|
5
|
+
extend Telnyx::APIOperations::List
|
6
|
+
extend Telnyx::APIOperations::Create
|
7
|
+
include Telnyx::APIOperations::Delete
|
8
|
+
include Telnyx::APIOperations::Save
|
9
|
+
|
10
|
+
OBJECT_NAME = "fax".freeze
|
11
|
+
RESOURCE_PATH = "faxes".freeze
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Telnyx
|
4
|
+
class FaxApplication < APIResource
|
5
|
+
extend Telnyx::APIOperations::List
|
6
|
+
extend Telnyx::APIOperations::Create
|
7
|
+
include Telnyx::APIOperations::Delete
|
8
|
+
include Telnyx::APIOperations::Save
|
9
|
+
|
10
|
+
OBJECT_NAME = "fax_application".freeze
|
11
|
+
end
|
12
|
+
end
|
@@ -5,6 +5,15 @@ module Telnyx
|
|
5
5
|
include Telnyx::APIOperations::Save
|
6
6
|
extend Telnyx::APIOperations::List
|
7
7
|
|
8
|
+
def initialize(*)
|
9
|
+
super
|
10
|
+
warn "[DEPRECATION] MessagingPhoneNumber is deprecated, use PhoneNumber instead"
|
11
|
+
end
|
12
|
+
|
8
13
|
OBJECT_NAME = "messaging_phone_number".freeze
|
14
|
+
def self.resource_path(id = nil)
|
15
|
+
return "phone_numbers/#{CGI.escape(id)}/messaging" if id
|
16
|
+
"phone_numbers/messaging"
|
17
|
+
end
|
9
18
|
end
|
10
19
|
end
|
data/lib/telnyx/phone_number.rb
CHANGED
@@ -13,7 +13,7 @@ module Telnyx
|
|
13
13
|
instance_methods: { list: "voice" }
|
14
14
|
nested_resource_class_methods "messaging",
|
15
15
|
path: ["messaging"],
|
16
|
-
operations: %i[update list],
|
16
|
+
operations: %i[update list retrieve],
|
17
17
|
instance_methods: { list: "messaging" }
|
18
18
|
nested_resource_class_methods "inbound_channel",
|
19
19
|
path: ["inbound_channels"],
|
@@ -39,6 +39,10 @@ module Telnyx
|
|
39
39
|
list_voices nil
|
40
40
|
end
|
41
41
|
|
42
|
+
def self.messaging
|
43
|
+
list_messagings(nil)
|
44
|
+
end
|
45
|
+
|
42
46
|
OBJECT_NAME = "phone_number".freeze
|
43
47
|
end
|
44
48
|
end
|
data/lib/telnyx/sim_card.rb
CHANGED
@@ -6,7 +6,7 @@ module Telnyx
|
|
6
6
|
extend APIOperations::NestedResource
|
7
7
|
extend APIOperations::List
|
8
8
|
|
9
|
-
ACTIONS = %w[
|
9
|
+
ACTIONS = %w[enable disable].freeze
|
10
10
|
ACTIONS.each do |action|
|
11
11
|
nested_resource_class_methods action,
|
12
12
|
path: %W[actions #{action}],
|
@@ -20,5 +20,16 @@ module Telnyx
|
|
20
20
|
end
|
21
21
|
|
22
22
|
OBJECT_NAME = "sim_card".freeze
|
23
|
+
|
24
|
+
# depreciated api
|
25
|
+
def activate
|
26
|
+
warn "[DEPRECATION] SimCard#activate is deprecated, use enable instead."
|
27
|
+
enable
|
28
|
+
end
|
29
|
+
|
30
|
+
def deactivate
|
31
|
+
warn "[DEPRECATION] SimCard#deactivate is deprecated, use enable instead."
|
32
|
+
disable
|
33
|
+
end
|
23
34
|
end
|
24
35
|
end
|