From 82865bd072399346eb3cf70ba24fb6d4ef2dff6f Mon Sep 17 00:00:00 2001 From: lunarfyre7 Date: Wed, 10 Mar 2021 13:36:10 -0800 Subject: [PATCH] add fax endpoint; add example app (#51) fix failed validation in fqdn tests add endpoint add fax application add example update readme linting linting Co-authored-by: d-telnyx <68876596+d-telnyx@users.noreply.github.com> --- examples/fax/Gemfile | 7 +++++ examples/fax/config.yaml | 4 +++ examples/fax/fax.rb | 42 +++++++++++++++++++++++++++++ examples/fax/options.rb | 41 ++++++++++++++++++++++++++++ examples/fax/readme.md | 18 +++++++++++++ lib/telnyx.rb | 2 ++ lib/telnyx/fax.rb | 13 +++++++++ lib/telnyx/fax_application.rb | 12 +++++++++ lib/telnyx/util.rb | 2 ++ test/telnyx/fax_application_test.rb | 32 ++++++++++++++++++++++ test/telnyx/fax_test.rb | 32 ++++++++++++++++++++++ 11 files changed, 205 insertions(+) create mode 100644 examples/fax/Gemfile create mode 100644 examples/fax/config.yaml create mode 100644 examples/fax/fax.rb create mode 100644 examples/fax/options.rb create mode 100644 examples/fax/readme.md create mode 100644 lib/telnyx/fax.rb create mode 100644 lib/telnyx/fax_application.rb create mode 100644 test/telnyx/fax_application_test.rb create mode 100644 test/telnyx/fax_test.rb diff --git a/examples/fax/Gemfile b/examples/fax/Gemfile new file mode 100644 index 0000000..d03bba3 --- /dev/null +++ b/examples/fax/Gemfile @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +source "https://rubygems.org" + +gem "amazing_print" +gem "sinatra" +gem "telnyx", path: "../../." diff --git a/examples/fax/config.yaml b/examples/fax/config.yaml new file mode 100644 index 0000000..a8f817e --- /dev/null +++ b/examples/fax/config.yaml @@ -0,0 +1,4 @@ +fax_app_id: +outbound_connection_id: +to: +from: \ No newline at end of file diff --git a/examples/fax/fax.rb b/examples/fax/fax.rb new file mode 100644 index 0000000..e9353c7 --- /dev/null +++ b/examples/fax/fax.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +require "telnyx" +require_relative "options" +require "sinatra/base" +require "json" +require "amazing_print" +require "uri" + +class WebhookServer < Sinatra::Base + set :port, 9090 + + def initialize + super + Thread.new { telnyx_setup } + end + + def telnyx_setup + @fax_application = Telnyx::FaxApplication.retrieve CONFIG.fax_app_id + @fax_application.webhook_event_url = CONFIG.webhook_url + @fax_application.save + + puts "## Fax Send Request ##" + ap @sent_fax = Telnyx::Fax.create( + connection_id: CONFIG["outbound_connection_id"], + media_url: CONFIG.document_url, + to: CONFIG.to, + from: CONFIG.from, + outbound_voice_profile_id: CONFIG.outbound_voice_profile_id + ) + end + + # Receive webhooks + post "/*" do + hook = JSON.parse(request.body.read, symbolize_names: true) + puts "## Received Webhook ##" + ap hook + 200 + end +end + +WebhookServer.run! diff --git a/examples/fax/options.rb b/examples/fax/options.rb new file mode 100644 index 0000000..7e9999a --- /dev/null +++ b/examples/fax/options.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +# Helper script to parse the command line options. + +require "optparse" +require "ostruct" +require "yaml" + +CONFIG = OpenStruct.new( + document_url: "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf", + **YAML.safe_load(open("config.yaml")).to_h +) +OptionParser.new do |opts| + opts.banner = "Telnyx fax demo\nUsage: bundle exec fax.rb -- [options]" + + opts.on("-h", "--help", "Prints this help") do + puts opts + exit + end + + opts.on( + "-h=URL", "--webhook-url=URL", + "[REQUIRED] URL to send webhook events to. This should be an address exposed to the internet. For testing purposes try Ngrok or Hookbin." + ) { |url| CONFIG.webhook_url = url } + + opts.on( + "-k=KEY", "--api-key=KEY", "[REQUIRED] Telnyx API key." + ) { |key| CONFIG.api_key = Telnyx.api_key = key } + + opts.on( + "--to=NUMBER", "Phone number to send a fax to" + ) { |number| CONFIG.to = number } + + opts.on( + "--document-url=URL", "URL for document to fax. Default is https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf" + ) { |url| CONFIG.document_url = url } +end.parse! + +missing_args = %i[webhook_url api_key] - CONFIG.to_h.keys +missing_args.any? and raise OptionParser::MissingArgument, "missing the following options: [#{missing_args.join ', '}]. Use --help for more information." +CONFIG.to_h.values.any?(&:nil?) and raise "Missing config values, check config.yaml" diff --git a/examples/fax/readme.md b/examples/fax/readme.md new file mode 100644 index 0000000..0d4f6e5 --- /dev/null +++ b/examples/fax/readme.md @@ -0,0 +1,18 @@ +# Usage + +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. + +Before you can use the demo application you will need to login to your telnyx portal and configure the following: + +1. You will need to setup an inbound and an outbound Fax Application for this demo. +2. Create two phone numbers: + - One for inbound faxes, this will need to be associated with a fax application. + - One for outbound faxes. +3. You will also need to create a SIP Connection for your outbound faxes, be sure to configure it to use your webhook url. + +Finally you will need to fill out `config.yaml` with the IDs listed, as well as with the outbound and inbound phone numbers. + +``` +bundle +bundle exec ruby main.rb --api-key= +``` \ No newline at end of file diff --git a/lib/telnyx.rb b/lib/telnyx.rb index e551c06..3d5fe95 100644 --- a/lib/telnyx.rb +++ b/lib/telnyx.rb @@ -46,6 +46,8 @@ require "telnyx/connection" require "telnyx/credential_connection" require "telnyx/event" +require "telnyx/fax" +require "telnyx/fax_application" require "telnyx/fqdn_connection" require "telnyx/fqdn" require "telnyx/ip_connection" diff --git a/lib/telnyx/fax.rb b/lib/telnyx/fax.rb new file mode 100644 index 0000000..281ea16 --- /dev/null +++ b/lib/telnyx/fax.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module Telnyx + class Fax < APIResource + extend Telnyx::APIOperations::List + extend Telnyx::APIOperations::Create + include Telnyx::APIOperations::Delete + include Telnyx::APIOperations::Save + + OBJECT_NAME = "fax".freeze + RESOURCE_PATH = "faxes".freeze + end +end diff --git a/lib/telnyx/fax_application.rb b/lib/telnyx/fax_application.rb new file mode 100644 index 0000000..ea699f0 --- /dev/null +++ b/lib/telnyx/fax_application.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +module Telnyx + class FaxApplication < APIResource + extend Telnyx::APIOperations::List + extend Telnyx::APIOperations::Create + include Telnyx::APIOperations::Delete + include Telnyx::APIOperations::Save + + OBJECT_NAME = "fax_application".freeze + end +end diff --git a/lib/telnyx/util.rb b/lib/telnyx/util.rb index f53c91e..7597d50 100644 --- a/lib/telnyx/util.rb +++ b/lib/telnyx/util.rb @@ -48,6 +48,8 @@ def self.object_classes Conferences::OBJECT_NAME => Conferences, Connection::OBJECT_NAME => Connection, CredentialConnection::OBJECT_NAME => CredentialConnection, + Fax::OBJECT_NAME => Fax, + FaxApplication::OBJECT_NAME => FaxApplication, FQDN::OBJECT_NAME => FQDN, FQDNConnection::OBJECT_NAME => FQDNConnection, IP::OBJECT_NAME => IP, diff --git a/test/telnyx/fax_application_test.rb b/test/telnyx/fax_application_test.rb new file mode 100644 index 0000000..f533fea --- /dev/null +++ b/test/telnyx/fax_application_test.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +require_relative "../test_helper" + +module Telnyx + class FaxApplicationTest < Test::Unit::TestCase + should "fetch index" do + fax_applications = FaxApplication.list + assert_requested :get, "#{Telnyx.api_base}/v2/fax_applications" + assert_kind_of ListObject, fax_applications + assert_kind_of FaxApplication, fax_applications.first + end + + should "create" do + fax_application = FaxApplication.create application_name: "foo", webhook_event_url: "https://foo.bar.com" + assert_requested :post, "#{Telnyx.api_base}/v2/fax_applications" + assert_kind_of FaxApplication, fax_application + end + + should "retrieve" do + fax_application = FaxApplication.retrieve "foo" + assert_requested :get, "#{Telnyx.api_base}/v2/fax_applications/foo" + assert_kind_of FaxApplication, fax_application + end + + should "delete" do + fax_application = FaxApplication.retrieve "foo" + fax_application.delete + assert_requested :delete, "#{Telnyx.api_base}/v2/fax_applications/foo" + end + end +end diff --git a/test/telnyx/fax_test.rb b/test/telnyx/fax_test.rb new file mode 100644 index 0000000..0b4b859 --- /dev/null +++ b/test/telnyx/fax_test.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +require_relative "../test_helper" +module Telnyx + class FaxTest < Test::Unit::TestCase + should "fetch index" do + faxes = Fax.list + assert_requested :get, "#{Telnyx.api_base}/v2/faxes" + assert_kind_of ListObject, faxes + assert_kind_of Fax, faxes.first + end + + should "send fax" do + fax = Fax.create connection_id: "foo", media_url: "example.com", to: "+13127367276" + assert_requested :post, "#{Telnyx.api_base}/v2/faxes" + assert_kind_of Fax, fax + end + + should "view fax" do + fax = Fax.retrieve "foo" + assert_requested :get, "#{Telnyx.api_base}/v2/faxes/foo" + assert_kind_of Fax, fax + end + + should "delete fax" do + omit "!!waiting for mock!!" + fax = Fax.retrieve "foo" + fax.delete + assert_requested :delete, "#{Telnyx.api_base}/v2/faxes/foo" + end + end +end