telnyx 0.0.8 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) 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 +1 -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 -5
  9. data/README.md +42 -3
  10. data/VERSION +1 -1
  11. data/bin/telnyx-console +7 -1
  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 +22 -2
  21. data/lib/telnyx/address.rb +12 -0
  22. data/lib/telnyx/api_operations/list.rb +1 -1
  23. data/lib/telnyx/api_operations/nested_resource.rb +2 -2
  24. data/lib/telnyx/api_operations/save.rb +1 -1
  25. data/lib/telnyx/api_resource.rb +13 -2
  26. data/lib/telnyx/billing_group.rb +12 -0
  27. data/lib/telnyx/call.rb +3 -1
  28. data/lib/telnyx/call_control_application.rb +12 -0
  29. data/lib/telnyx/conference.rb +36 -0
  30. data/lib/telnyx/connection.rb +9 -0
  31. data/lib/telnyx/credential_connection.rb +12 -0
  32. data/lib/telnyx/fax.rb +13 -0
  33. data/lib/telnyx/fax_application.rb +12 -0
  34. data/lib/telnyx/fqdn.rb +12 -0
  35. data/lib/telnyx/fqdn_connection.rb +12 -0
  36. data/lib/telnyx/ip.rb +12 -0
  37. data/lib/telnyx/ip_connection.rb +12 -0
  38. data/lib/telnyx/list_object.rb +30 -44
  39. data/lib/telnyx/messaging_phone_number.rb +9 -0
  40. data/lib/telnyx/number_lookup.rb +7 -0
  41. data/lib/telnyx/number_order_document.rb +11 -0
  42. data/lib/telnyx/outbound_voice_profile.rb +12 -0
  43. data/lib/telnyx/phone_number.rb +20 -1
  44. data/lib/telnyx/phone_number_regulatory_requirement.rb +10 -0
  45. data/lib/telnyx/portout.rb +12 -0
  46. data/lib/telnyx/regulatory_requirement.rb +9 -0
  47. data/lib/telnyx/sim_card.rb +12 -1
  48. data/lib/telnyx/telnyx_client.rb +17 -26
  49. data/lib/telnyx/util.rb +38 -14
  50. data/lib/telnyx/verification.rb +27 -0
  51. data/lib/telnyx/verify_profile.rb +11 -0
  52. data/lib/telnyx/version.rb +1 -1
  53. data/lib/telnyx/wireless_detail_records_report.rb +12 -0
  54. data/telnyx.gemspec +1 -1
  55. data/test/telnyx/address_test.rb +67 -0
  56. data/test/telnyx/alphanumeric_sender_id_test.rb +4 -0
  57. data/test/telnyx/api_resource_test.rb +14 -5
  58. data/test/telnyx/billing_group_test.rb +40 -0
  59. data/test/telnyx/call_control_application_test.rb +42 -0
  60. data/test/telnyx/call_control_test.rb +54 -30
  61. data/test/telnyx/conference_test.rb +113 -0
  62. data/test/telnyx/connection_test.rb +28 -0
  63. data/test/telnyx/credential_connection_test.rb +44 -0
  64. data/test/telnyx/errors_test.rb +4 -4
  65. data/test/telnyx/fax_application_test.rb +32 -0
  66. data/test/telnyx/fax_test.rb +32 -0
  67. data/test/telnyx/fqdn_connection_test.rb +40 -0
  68. data/test/telnyx/fqdn_test.rb +40 -0
  69. data/test/telnyx/ip_connection_test.rb +40 -0
  70. data/test/telnyx/ip_test.rb +40 -0
  71. data/test/telnyx/list_object_test.rb +48 -90
  72. data/test/telnyx/messaging_phone_number_test.rb +8 -4
  73. data/test/telnyx/messaging_profile_test.rb +16 -5
  74. data/test/telnyx/number_lookup_test.rb +18 -0
  75. data/test/telnyx/number_order_document_test.rb +35 -0
  76. data/test/telnyx/outbound_voice_profile_test.rb +67 -0
  77. data/test/telnyx/phone_number_regulatory_requirement_test.rb +14 -0
  78. data/test/telnyx/phone_number_test.rb +40 -9
  79. data/test/telnyx/public_key_test.rb +1 -0
  80. data/test/telnyx/regulatory_requirement_test.rb +21 -0
  81. data/test/telnyx/sim_card_test.rb +6 -18
  82. data/test/telnyx/telnyx_client_test.rb +1 -1
  83. data/test/telnyx/telnyx_object_test.rb +5 -5
  84. data/test/telnyx/verification_test.rb +22 -0
  85. data/test/telnyx/verify_profile_test.rb +31 -0
  86. data/test/telnyx/wireless_detail_records_report_test.rb +57 -0
  87. data/test/test_helper.rb +1 -1
  88. metadata +93 -12
  89. data/.travis.yml +0 -51
  90. data/lib/telnyx/conferences.rb +0 -19
  91. data/test/telnyx/conferences_test.rb +0 -76
data/Gemfile CHANGED
@@ -6,6 +6,7 @@ gemspec
6
6
 
7
7
  group :development do
8
8
  gem "coveralls", require: false
9
+ gem "faraday", "~> 1.0"
9
10
  gem "mocha", "~> 0.13.2"
10
11
  gem "rake"
11
12
  gem "shoulda-context"
@@ -21,20 +22,20 @@ group :development do
21
22
  gem "guard"
22
23
  gem "guard-rake"
23
24
  gem "guard-rubocop"
24
- gem "rubocop", "0.50.0"
25
+ gem "rubocop", "~> 1.6"
25
26
 
26
27
  # Rack 2.0+ requires Ruby >= 2.2.2 which is problematic for the test suite on
27
28
  # older Ruby versions. Check Ruby the version here and put a maximum
28
29
  # constraint on Rack if necessary.
29
30
  if RUBY_VERSION >= "2.2.2"
30
- gem "rack", ">= 2.0.6"
31
+ gem "rack", ">= 2.1.4"
31
32
  else
32
33
  gem "rack", ">= 1.6.11", "< 2.0" # rubocop:disable Bundler/DuplicatedGem
33
34
  end
34
35
 
35
36
  platforms :mri do
36
- gem "byebug"
37
- gem "pry"
38
- gem "pry-byebug"
37
+ # gem "byebug"
38
+ # gem "pry"
39
+ # gem "pry-byebug"
39
40
  end
40
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/telnyx/telnyx-ruby)
4
- [![Coverage Status](https://coveralls.io/repos/github/team-telnyx/telnyx-ruby/badge.svg?branch=master)](https://coveralls.io/github/telnyx/telnyx-ruby?branch=master)
3
+ ![Build Status](https://github.com/team-telnyx/telnyx-ruby/workflows/Ruby/badge.svg)
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
@@ -34,7 +35,7 @@ If you want to build the gem from source:
34
35
 
35
36
  ### Requirements
36
37
 
37
- * Ruby 2.0+.
38
+ * Ruby 2.1.0+
38
39
 
39
40
  ### Bundler
40
41
 
@@ -65,6 +66,44 @@ Telnyx::MessagingProfile.list()
65
66
  Telnyx::MessagingProfile.retrieve("123")
66
67
  ```
67
68
 
69
+
70
+ ### Iterating over a resource
71
+
72
+ API resources are paginated and the library comes with a handful of methods to
73
+ ease dealing with them seemlessly.
74
+
75
+ ```ruby
76
+ # list messaging profiles
77
+ first_page = Telnyx::MessagingProfile.list()
78
+
79
+ # check whether there are more pages to go through
80
+ if first_page.more?
81
+ puts("There are still more pages to go.")
82
+ else
83
+ puts("This is the last page.")
84
+ end
85
+
86
+ # get current page's size and number
87
+ first_page.page_size
88
+ first_page.page_number
89
+
90
+ # fetch the next and previous pages
91
+ second_page = first_page.next_page
92
+ first_page = second_page.previous_page
93
+
94
+ # iterate over the results of a *single page*
95
+ second_page.each do |messaging_profile|
96
+ puts(messaging_profile.id)
97
+ end
98
+
99
+ # iterate over *all of the messaging profiles* starting at `first_page`
100
+ # similar to `each`, but requests subsequent pages as needed
101
+ first_page.auto_paging_each do |messaging_profile|
102
+ puts(messaging_profile.id)
103
+ end
104
+ ```
105
+
106
+
68
107
  ### Configuring a Client
69
108
 
70
109
  While a default HTTP client is used by default, it's also possible to have the
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.8
1
+ 2.5.0
data/bin/telnyx-console CHANGED
@@ -5,12 +5,18 @@
5
5
  require "irb"
6
6
  require "irb/completion"
7
7
 
8
- require "#{::File.dirname(__FILE__)}/../lib/telnyx"
8
+ $LOAD_PATH.unshift File.expand_path("lib")
9
+ require "telnyx"
9
10
 
10
11
  # Config IRB to enable --simple-prompt and auto indent
11
12
  IRB.conf[:PROMPT_MODE] = :SIMPLE
12
13
  IRB.conf[:AUTO_INDENT] = true
13
14
 
14
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
15
21
 
16
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
@@ -36,19 +36,39 @@ require "telnyx/api_resource"
36
36
  require "telnyx/singleton_api_resource"
37
37
  require "telnyx/webhook"
38
38
 
39
+ require "telnyx/address"
39
40
  require "telnyx/alphanumeric_sender_id"
40
41
  require "telnyx/available_phone_number"
42
+ require "telnyx/billing_group"
43
+ require "telnyx/call_control_application"
41
44
  require "telnyx/call"
42
- require "telnyx/conferences"
45
+ require "telnyx/conference"
46
+ require "telnyx/connection"
47
+ require "telnyx/credential_connection"
43
48
  require "telnyx/event"
49
+ require "telnyx/fax"
50
+ require "telnyx/fax_application"
51
+ require "telnyx/fqdn_connection"
52
+ require "telnyx/fqdn"
53
+ require "telnyx/ip_connection"
54
+ require "telnyx/ip"
44
55
  require "telnyx/message"
45
56
  require "telnyx/messaging_phone_number"
46
57
  require "telnyx/messaging_profile"
58
+ require "telnyx/number_lookup"
59
+ require "telnyx/number_order_document"
47
60
  require "telnyx/number_order"
48
61
  require "telnyx/number_reservation"
62
+ require "telnyx/outbound_voice_profile"
63
+ require "telnyx/phone_number_regulatory_requirement"
49
64
  require "telnyx/phone_number"
65
+ require "telnyx/portout"
50
66
  require "telnyx/public_key"
51
- require "telnyx/sim_card.rb"
67
+ require "telnyx/regulatory_requirement"
68
+ require "telnyx/sim_card"
69
+ require "telnyx/verification"
70
+ require "telnyx/verify_profile"
71
+ require "telnyx/wireless_detail_records_report"
52
72
 
53
73
  module Telnyx
54
74
  @app_info = nil
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Telnyx
4
+ class Address < APIResource
5
+ include APIOperations::Delete
6
+ extend APIOperations::List
7
+ extend APIOperations::Create
8
+
9
+ OBJECT_NAME = "address".freeze
10
+ RESOURCE_PATH = "addresses".freeze
11
+ end
12
+ end
@@ -14,7 +14,7 @@ module Telnyx
14
14
  #
15
15
  # just for general cleanliness, remove any paging options
16
16
  obj.filters = filters.dup
17
- obj.filters.delete(:page)
17
+ # obj.filters.delete(:page) # undo this as it interferes with the pagination system...
18
18
 
19
19
  obj
20
20
  end
@@ -20,8 +20,8 @@ module Telnyx
20
20
 
21
21
  resource_url_method = :"#{resource}s_url"
22
22
  define_singleton_method(resource_url_method) do |id, nested_id = nil|
23
- raise ArgumentError, "id is required" if id.nil?
24
- url = "#{resource_url}/#{CGI.escape(id)}/#{path}"
23
+ # raise ArgumentError, "id is required" if id.nil?
24
+ url = id.nil? ? "#{resource_url}/#{path}" : "#{resource_url}/#{CGI.escape(id)}/#{path}"
25
25
  url += "/#{CGI.escape(nested_id)}" unless nested_id.nil?
26
26
  url
27
27
  end
@@ -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,15 +14,24 @@ 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
+ return "/v2/#{resource_path(inner_id)}" if respond_to?("resource_path")
24
+ return "/v2/#{self::RESOURCE_PATH}" if const_defined?("RESOURCE_PATH")
25
+
23
26
  "/v2/#{self::OBJECT_NAME.downcase.tr('.', '/')}s"
24
27
  end
25
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)}"
33
+ end
34
+
26
35
  # A metaprogramming call that specifies that a field of a resource can be
27
36
  # its own type of API resource (say a nested card under an account for
28
37
  # example), and if that resource is set, it should be transmitted to the
@@ -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