telnyx 0.1.0 → 2.6.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.
Files changed (56) 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/.gitignore +3 -0
  5. data/.rubocop.yml +6 -36
  6. data/.rubocop_todo.yml +300 -0
  7. data/.travis.yml.bak +48 -0
  8. data/Gemfile +6 -6
  9. data/README.md +2 -1
  10. data/VERSION +1 -1
  11. data/bin/telnyx-console +5 -0
  12. data/examples/2 factor authentication/Gemfile +7 -0
  13. data/examples/2 factor authentication/main.rb +67 -0
  14. data/examples/2 factor authentication/readme.md +5 -0
  15. data/examples/fax/Gemfile +7 -0
  16. data/examples/fax/config.yaml +4 -0
  17. data/examples/fax/fax.rb +42 -0
  18. data/examples/fax/options.rb +41 -0
  19. data/examples/fax/readme.md +18 -0
  20. data/lib/telnyx.rb +6 -1
  21. data/lib/telnyx/api_operations/save.rb +1 -1
  22. data/lib/telnyx/api_resource.rb +14 -3
  23. data/lib/telnyx/call.rb +3 -1
  24. data/lib/telnyx/conference.rb +17 -1
  25. data/lib/telnyx/fax.rb +13 -0
  26. data/lib/telnyx/fax_application.rb +12 -0
  27. data/lib/telnyx/messaging_phone_number.rb +9 -0
  28. data/lib/telnyx/number_lookup.rb +7 -0
  29. data/lib/telnyx/phone_number.rb +9 -1
  30. data/lib/telnyx/phone_number_regulatory_requirement.rb +1 -0
  31. data/lib/telnyx/sim_card.rb +12 -1
  32. data/lib/telnyx/telnyx_client.rb +16 -25
  33. data/lib/telnyx/util.rb +12 -6
  34. data/lib/telnyx/verification.rb +27 -0
  35. data/lib/telnyx/verify_profile.rb +11 -0
  36. data/lib/telnyx/version.rb +1 -1
  37. data/telnyx.gemspec +2 -2
  38. data/test/telnyx/call_control_test.rb +54 -30
  39. data/test/telnyx/conference_test.rb +57 -20
  40. data/test/telnyx/credential_connection_test.rb +5 -1
  41. data/test/telnyx/fax_application_test.rb +32 -0
  42. data/test/telnyx/fax_test.rb +32 -0
  43. data/test/telnyx/fqdn_connection_test.rb +1 -1
  44. data/test/telnyx/fqdn_test.rb +1 -1
  45. data/test/telnyx/messaging_phone_number_test.rb +8 -4
  46. data/test/telnyx/messaging_profile_test.rb +1 -1
  47. data/test/telnyx/number_lookup_test.rb +18 -0
  48. data/test/telnyx/phone_number_regulatory_requirement_test.rb +1 -1
  49. data/test/telnyx/phone_number_test.rb +14 -21
  50. data/test/telnyx/sim_card_test.rb +6 -6
  51. data/test/telnyx/telnyx_object_test.rb +5 -5
  52. data/test/telnyx/verification_test.rb +22 -0
  53. data/test/telnyx/verify_profile_test.rb +31 -0
  54. data/test/test_helper.rb +1 -1
  55. metadata +55 -12
  56. 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", "~> 1.0"
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,7 +1,8 @@
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
+ [![Join Slack](https://img.shields.io/badge/join-slack-infomational)](https://joinslack.telnyx.com/)
5
6
 
6
7
  The Telnyx Ruby library provides convenient access to the Telnyx API from
7
8
  applications written in the Ruby language. It includes a pre-defined set of
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 2.6.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"
@@ -53,6 +55,7 @@ require "telnyx/ip"
53
55
  require "telnyx/message"
54
56
  require "telnyx/messaging_phone_number"
55
57
  require "telnyx/messaging_profile"
58
+ require "telnyx/number_lookup"
56
59
  require "telnyx/number_order_document"
57
60
  require "telnyx/number_order"
58
61
  require "telnyx/number_reservation"
@@ -63,6 +66,8 @@ require "telnyx/portout"
63
66
  require "telnyx/public_key"
64
67
  require "telnyx/regulatory_requirement"
65
68
  require "telnyx/sim_card"
69
+ require "telnyx/verification"
70
+ require "telnyx/verify_profile"
66
71
  require "telnyx/wireless_detail_records_report"
67
72
 
68
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
data/lib/telnyx/call.rb CHANGED
@@ -33,7 +33,9 @@ module Telnyx
33
33
 
34
34
  ACTIONS = %w[reject answer hangup bridge speak fork_start fork_stop
35
35
  gather_using_audio gather_using_speak playback_start
36
- playback_stop record_start record_stop send_dtmf transfer].freeze
36
+ playback_stop record_start record_stop send_dtmf transfer
37
+ transcription_start transcription_stop record_pause
38
+ record_resume gather_stop refer].freeze
37
39
 
38
40
  ACTIONS.each do |action|
39
41
  nested_resource_class_methods action,
@@ -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