telnyx 2.3.0 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.github/scripts/before_install.sh +9 -0
  3. data/.github/workflows/ruby.yml +39 -0
  4. data/.rubocop.yml +6 -36
  5. data/.rubocop_todo.yml +300 -0
  6. data/.travis.yml.bak +48 -0
  7. data/Gemfile +6 -6
  8. data/README.md +1 -1
  9. data/VERSION +1 -1
  10. data/bin/telnyx-console +5 -0
  11. data/examples/2 factor authentication/Gemfile +7 -0
  12. data/examples/2 factor authentication/main.rb +67 -0
  13. data/examples/2 factor authentication/readme.md +5 -0
  14. data/examples/fax/Gemfile +7 -0
  15. data/examples/fax/config.yaml +4 -0
  16. data/examples/fax/fax.rb +42 -0
  17. data/examples/fax/options.rb +41 -0
  18. data/examples/fax/readme.md +18 -0
  19. data/lib/telnyx.rb +5 -1
  20. data/lib/telnyx/api_operations/save.rb +1 -1
  21. data/lib/telnyx/api_resource.rb +14 -3
  22. data/lib/telnyx/conference.rb +17 -1
  23. data/lib/telnyx/fax.rb +13 -0
  24. data/lib/telnyx/fax_application.rb +12 -0
  25. data/lib/telnyx/messaging_phone_number.rb +9 -0
  26. data/lib/telnyx/phone_number.rb +5 -1
  27. data/lib/telnyx/sim_card.rb +12 -1
  28. data/lib/telnyx/telnyx_client.rb +15 -24
  29. data/lib/telnyx/util.rb +7 -1
  30. data/lib/telnyx/verification.rb +27 -0
  31. data/lib/telnyx/verify_profile.rb +11 -0
  32. data/lib/telnyx/version.rb +1 -1
  33. data/telnyx.gemspec +1 -1
  34. data/test/telnyx/call_control_test.rb +3 -3
  35. data/test/telnyx/conference_test.rb +57 -20
  36. data/test/telnyx/credential_connection_test.rb +5 -1
  37. data/test/telnyx/fax_application_test.rb +32 -0
  38. data/test/telnyx/fax_test.rb +32 -0
  39. data/test/telnyx/fqdn_connection_test.rb +1 -1
  40. data/test/telnyx/fqdn_test.rb +1 -1
  41. data/test/telnyx/messaging_phone_number_test.rb +8 -4
  42. data/test/telnyx/messaging_profile_test.rb +1 -1
  43. data/test/telnyx/phone_number_test.rb +9 -21
  44. data/test/telnyx/sim_card_test.rb +6 -6
  45. data/test/telnyx/telnyx_object_test.rb +5 -5
  46. data/test/telnyx/verification_test.rb +22 -0
  47. data/test/telnyx/verify_profile_test.rb +31 -0
  48. data/test/test_helper.rb +1 -1
  49. metadata +36 -7
  50. 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.15.4"
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", "0.50.0"
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.0.6"
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
- [![Build Status](https://travis-ci.org/team-telnyx/telnyx-ruby.svg?branch=master)](https://travis-ci.org/team-telnyx/telnyx-ruby)
3
+ ![Build Status](https://github.com/team-telnyx/telnyx-ruby/workflows/Ruby/badge.svg)
4
4
  [![Coverage Status](https://coveralls.io/repos/github/team-telnyx/telnyx-ruby/badge.svg?branch=master)](https://coveralls.io/github/team-telnyx/telnyx-ruby?branch=master)
5
5
  [![Join Slack](https://img.shields.io/badge/join-slack-infomational)](https://joinslack.telnyx.com/)
6
6
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 2.4.0
data/bin/telnyx-console CHANGED
@@ -13,5 +13,10 @@ IRB.conf[:PROMPT_MODE] = :SIMPLE
13
13
  IRB.conf[:AUTO_INDENT] = true
14
14
 
15
15
  puts "Loaded gem 'telnyx'"
16
+ def load_mock_settings!
17
+ Telnyx.api_base = "http://localhost:12111"
18
+ Telnyx.api_key = "KEYSUPERSECRET"
19
+ nil
20
+ end
16
21
 
17
22
  IRB.start
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "amazing_print"
6
+ gem "telnyx", path: "../../."
7
+ gem "tty-prompt"
@@ -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
@@ -0,0 +1,5 @@
1
+ # Usage
2
+ ```
3
+ bundle
4
+ bundle exec ruby main.rb
5
+ ```
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "amazing_print"
6
+ gem "sinatra"
7
+ gem "telnyx", path: "../../."
@@ -0,0 +1,4 @@
1
+ fax_app_id:
2
+ outbound_connection_id:
3
+ to:
4
+ from:
@@ -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
@@ -22,7 +22,7 @@ module Telnyx
22
22
  end
23
23
  end
24
24
 
25
- resp, opts = request(:patch, "#{resource_url}/#{id}", params, opts)
25
+ resp, opts = request(:patch, identified_resource_url(id), params, opts)
26
26
  Util.convert_to_telnyx_object(resp.data, opts)
27
27
  end
28
28
  end
@@ -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
- const_defined?("RESOURCE_PATH") ? "/v2/#{self::RESOURCE_PATH}" : "/v2/#{self::OBJECT_NAME.downcase.tr('.', '/')}s"
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
@@ -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
@@ -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
@@ -6,7 +6,7 @@ module Telnyx
6
6
  extend APIOperations::NestedResource
7
7
  extend APIOperations::List
8
8
 
9
- ACTIONS = %w[deactivate activate].freeze
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