diff --git a/lib/zadarma.rb b/lib/zadarma.rb new file mode 100644 index 0000000..470d3df --- /dev/null +++ b/lib/zadarma.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require 'zadarma/version' +require 'zadarma/client' +require 'zadarma/error' + +# The Zadarma module contains all the classes and methods for the Zadarma API client. +module Zadarma +end diff --git a/lib/zadarma/client.rb b/lib/zadarma/client.rb new file mode 100644 index 0000000..2e4043b --- /dev/null +++ b/lib/zadarma/client.rb @@ -0,0 +1,361 @@ +# frozen_string_literal: true + +require 'json' +require 'faraday' +require 'openssl' +require 'base64' +require 'digest/md5' +require 'cgi' + +require_relative 'resources/info' +require_relative 'resources/pbx' +require_relative 'resources/direct_numbers' +require_relative 'resources/request' +require_relative 'resources/sip' +require_relative 'resources/sms' +require_relative 'resources/statistics' +require_relative 'resources/speech_recognition' +require_relative 'resources/groups_of_documents' +require_relative 'client/resources' +require_relative 'client/http' + +module Zadarma + # The Client class is the main entry point for interacting with the Zadarma API. + class Client + include Resources + include Http + + API_URL = 'https://api.zadarma.com' + + # Initializes a new Client object. + # + # @param api_key [String] The Zadarma API key. + # @param api_secret [String] The Zadarma API secret. + def initialize(api_key:, api_secret:) + @api_key = api_key + @api_secret = api_secret + end + + # Get the current account balance. + # + # @return [Hash] The API response. + # @see https://zadarma.com/en/support/api/#api_balance + def balance + info.balance + end + + # Get the price for a call to a specific number. + # + # @param number [String] The destination number. + # @param caller_id [String] The caller ID. + # @return [Hash] The API response. + # @see https://zadarma.com/en/support/api/#api_price + def price(number:, caller_id: nil) + info.price(number: number, caller_id: caller_id) + end + + # Get a list of internal PBX numbers. + # + # @return [Hash] The API response. + # @see https://zadarma.com/en/support/api/#api_pbx_internal + def internal_numbers + pbx.internal + end + + # Enable or disable call recording for a PBX extension. + # + # @param id [String] The PBX extension ID. + # @param status [String] The recording status. + # @param email [String] The email address to send the recording to. + # @param speech_recognition [String] The speech recognition status. + # @return [Hash] The API response. + # @see https://zadarma.com/en/support/api/#api_pbx_record + def set_call_recording(id:, status:, email: nil, speech_recognition: nil) + pbx.set_call_recording(id: id, status: status, email: email, speech_recognition: speech_recognition) + end + + # Request a call recording from the PBX. + # + # @param call_id [String] The call ID. + # @param pbx_call_id [String] The PBX call ID. + # @param lifetime [String] The lifetime of the recording. + # @return [Hash] The API response. + # @see https://zadarma.com/en/support/api/#api_pbx_record_request + def pbx_record_request(call_id: nil, pbx_call_id: nil, lifetime: nil) + pbx.pbx_record_request(call_id: call_id, pbx_call_id: pbx_call_id, lifetime: lifetime) + end + + # Get a list of direct numbers. + # + # @return [Hash] The API response. + # @see https://zadarma.com/en/support/api/#api_direct_numbers + def direct_numbers + direct_numbers_resource.all + end + + # Get a list of countries for direct numbers. + # + # @param language [String] The language of the response. + # @return [Hash] The API response. + # @see https://zadarma.com/en/support/api/#api_direct_number_countries + def direct_number_countries(language: nil) + direct_numbers_resource.countries(language: language) + end + + # Get a list of direct numbers for a specific country. + # + # @param country [String] The country code. + # @param language [String] The language of the response. + # @param direction_id [String] The direction ID. + # @return [Hash] The API response. + # @see https://zadarma.com/en/support/api/#api_direct_number_country + def direct_number_country(country:, language: nil, direction_id: nil) + direct_numbers_resource.country(country: country, language: language, direction_id: direction_id) + end + + # Get a list of available direct numbers. + # + # @param direction_id [String] The direction ID. + # @param mask [String] The number mask. + # @return [Hash] The API response. + # @see https://zadarma.com/en/support/api/#api_available_direct_numbers + def available_direct_numbers(direction_id:, mask: nil) + direct_numbers_resource.available(direction_id: direction_id, mask: mask) + end + + # Order a direct number. + # + # @param params [Hash] The order parameters. + # @return [Hash] The API response. + # @see https://zadarma.com/en/support/api/#api_order_direct_number + def order_direct_number(params) + direct_numbers_resource.order(params) + end + + # Prolong a direct number. + # + # @param number [String] The direct number. + # @param months [String] The number of months to prolong the number for. + # @return [Hash] The API response. + # @see https://zadarma.com/en/support/api/#api_prolong_direct_number + def prolong_direct_number(number:, months:) + direct_numbers_resource.prolong(number: number, months: months) + end + + # Initiate a callback between two numbers. + # + # @param from [String] The source number. + # @param to [String] The destination number. + # @param sip [String] The SIP number. + # @param predicted [String] The predicted status. + # @return [Hash] The API response. + # @see https://zadarma.com/en/support/api/#api_callback + def callback(from:, to:, sip: nil, predicted: nil) + request_resource.callback(from: from, to: to, sip: sip, predicted: predicted) + end + + # Get a list of SIP numbers. + # + # @return [Hash] The API response. + # @see https://zadarma.com/en/support/api/#api_sips + def sips + sip.all + end + + # Get the status of a SIP number. + # + # @param sip [String] The SIP number. + # @return [Hash] The API response. + # @see https://zadarma.com/en/support/api/#api_sip_status + def sip_status(sip:) + self.sip.status(sip: sip) + end + + # Create a SIP number. + # + # @param name [String] The SIP number name. + # @param password [String] The SIP number password. + # @param callerid [String] The SIP number caller ID. + # @param redirect_to_phone [String] The phone number to redirect to. + # @return [Hash] The API response. + # @see https://zadarma.com/en/support/api/#api_create_sip + def create_sip(name:, password: nil, callerid: nil, redirect_to_phone: nil) + sip.create(name: name, password: password, callerid: callerid, redirect_to_phone: redirect_to_phone) + end + + # Set the password for a SIP number. + # + # @param sip [String] The SIP number. + # @param value [String] The new password. + # @return [Hash] The API response. + # @see https://zadarma.com/en/support/api/#api_set_sip_password + def set_sip_password(sip:, value:) + self.sip.password(sip: sip, value: value) + end + + # Set the caller ID for a SIP number. + # + # @param id [String] The SIP number ID. + # @param number [String] The new caller ID. + # @return [Hash] The API response. + # @see https://zadarma.com/en/support/api/#api_set_sip_caller_id + def set_sip_caller_id(id:, number:) + sip.set_caller_id(id: id, number: number) + end + + # Get call forwarding information for a SIP number. + # + # @param id [String] The SIP number ID. + # @return [Hash] The API response. + # @see https://zadarma.com/en/support/api/#api_redirection + def redirection(id: nil) + sip.redirection(id: id) + end + + # Set call forwarding for a SIP number. + # + # @param id [String] The SIP number ID. + # @param status [String] The forwarding status. + # @param type [String] The forwarding type. + # @param number [String] The forwarding number. + # @param condition [String] The forwarding condition. + # @return [Hash] The API response. + # @see https://zadarma.com/en/support/api/#api_set_redirection + def set_redirection(id:, status:, type: nil, number: nil, condition: nil) + sip.set_redirection(id: id, status: status, type: type, number: number, condition: condition) + end + + # Send an SMS message. + # + # @param number [String] The destination number. + # @param message [String] The message text. + # @param sender [String] The sender ID. + # @return [Hash] The API response. + # @see https://zadarma.com/en/support/api/#api_send_sms + def send_sms(number:, message:, sender: nil) + sms.send_sms(number: number, message: message, sender: sender) + end + + # Get overall call statistics. + # + # @param params [Hash] The statistics parameters. + # @return [Hash] The API response. + # @see https://zadarma.com/en/support/api/#api_statistics + def statistics(params) + statistics_resource.statistics(params) + end + + # Get PBX call statistics. + # + # @param params [Hash] The statistics parameters. + # @return [Hash] The API response. + # @see https://zadarma.com/en/support/api/#api_pbx_statistics + def pbx_statistics(params) + statistics_resource.pbx_statistics(params) + end + + # Get speech recognition results. + # + # @param call_id [String] The call ID. + # @param lang [String] The language of the speech. + # @param return_results [String] Whether to return the results. + # @param alternatives [String] Whether to return alternative results. + # @return [Hash] The API response. + # @see https://zadarma.com/en/support/api/#api_get_speech_recognition + def get_speech_recognition(call_id:, lang: nil, return_results: nil, alternatives: nil) + speech_recognition_resource.get(call_id: call_id, lang: lang, return_results: return_results, + alternatives: alternatives) + end + + # Initiate speech recognition. + # + # @param call_id [String] The call ID. + # @param lang [String] The language of the speech. + # @return [Hash] The API response. + # @see https://zadarma.com/en/support/api/#api_initiate_speech_recognition + def initiate_speech_recognition(call_id:, lang: nil) + speech_recognition_resource.initiate(call_id: call_id, lang: lang) + end + + # Get a list of document files. + # + # @param group_id [String] The group ID. + # @return [Hash] The API response. + # @see https://zadarma.com/en/support/api/#api_document_files + def document_files(group_id: nil) + groups_of_documents_resource.files(group_id: group_id) + end + + # Get a list of document groups. + # + # @return [Hash] The API response. + # @see https://zadarma.com/en/support/api/#api_document_groups + def document_groups + groups_of_documents_resource.list + end + + # Get a document group. + # + # @param id [String] The group ID. + # @return [Hash] The API response. + # @see https://zadarma.com/en/support/api/#api_get_document_group + def get_document_group(id:) + groups_of_documents_resource.get(id: id) + end + + # Create a document group. + # + # @param params [Hash] The group parameters. + # @return [Hash] The API response. + # @see https://zadarma.com/en/support/api/#api_create_document_group + def create_document_group(params:) + groups_of_documents_resource.create(params: params) + end + + # Update a document group. + # + # @param id [String] The group ID. + # @param params [Hash] The group parameters. + # @return [Hash] The API response. + # @see https://zadarma.com/en/support/api/#api_update_document_group + def update_document_group(id:, params:) + groups_of_documents_resource.update(id: id, params: params) + end + + # Make a GET request to the Zadarma API. + # + # @param path [String] The API endpoint path. + # @param params [Hash] The request parameters. + # @return [Hash] The API response. + def get(path, params = {}) + request(:get, path, params) + end + + # Make a POST request to the Zadarma API. + # + # @param path [String] The API endpoint path. + # @param params [Hash] The request parameters. + # @return [Hash] The API response. + def post(path, params = {}) + request(:post, path, params) + end + + # Make a PUT request to the Zadarma API. + # + # @param path [String] The API endpoint path. + # @param params [Hash] The request parameters. + # @return [Hash] The API response. + def put(path, params = {}) + request(:put, path, params) + end + + # Make a DELETE request to the Zadarma API. + # + # @param path [String] The API endpoint path. + # @param params [Hash] The request parameters. + # @return [Hash] The API response. + def delete(path, params = {}) + request(:delete, path, params) + end + end +end diff --git a/lib/zadarma/client/http.rb b/lib/zadarma/client/http.rb new file mode 100644 index 0000000..268cc3d --- /dev/null +++ b/lib/zadarma/client/http.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +module Zadarma + class Client + # A module for handling HTTP requests to the Zadarma API. + module Http + private + + def request(method, path, params) + raise 'No API key or secret provided' unless @api_key && @api_secret + + sorted_params = params.sort.to_h + query_string = to_query(sorted_params) + signature = generate_signature(path, query_string) + + response = execute_request(method, path, sorted_params, signature) + + handle_response(response) + end + + def execute_request(method, path, params, signature) + connection.send(method) do |req| + req.url path + req.headers['Authorization'] = "#{@api_key}:#{signature}" + if %i[post put].include?(method) + req.body = params + else + req.params = params + end + end + end + + def connection + @connection ||= Faraday.new(url: API_URL) do |faraday| + faraday.request :url_encoded + faraday.adapter Faraday.default_adapter + end + end + + def generate_signature(path, query_string) + string_to_sign = path + query_string + Digest::MD5.hexdigest(query_string) + hmac = OpenSSL::HMAC.hexdigest('sha1', @api_secret, string_to_sign) + Base64.strict_encode64(hmac) + end + + def to_query(hash) + hash.map { |k, v| "#{CGI.escape(k.to_s)}=#{CGI.escape(v.to_s)}" }.join('&') + end + + def handle_response(response) + raise Zadarma::Error, "API Error: #{response.status} - #{response.body}" unless response.success? + + body = JSON.parse(response.body) + raise Zadarma::Error, "API Error: #{body['message']}" if body['status'] == 'error' + + body + end + end + end +end diff --git a/lib/zadarma/client/resources.rb b/lib/zadarma/client/resources.rb new file mode 100644 index 0000000..e758580 --- /dev/null +++ b/lib/zadarma/client/resources.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +module Zadarma + class Client + # A module for accessing the various resources of the Zadarma API. + module Resources + private + + # @!group Resources + # @!macro [attach] zadarma.resource + # @return [Zadarma::Resources::$1] the $1 resource + + def info + ::Zadarma::Resources::Info.new(client: self) + end + + def pbx + ::Zadarma::Resources::Pbx.new(client: self) + end + + def direct_numbers_resource + ::Zadarma::Resources::DirectNumbers.new(client: self) + end + + def request_resource + ::Zadarma::Resources::Request.new(client: self) + end + + def sip + ::Zadarma::Resources::Sip.new(client: self) + end + + def sms + ::Zadarma::Resources::Sms.new(client: self) + end + + def statistics_resource + ::Zadarma::Resources::Statistics.new(client: self) + end + + def speech_recognition_resource + ::Zadarma::Resources::SpeechRecognition.new(client: self) + end + + def groups_of_documents_resource + ::Zadarma::Resources::GroupsOfDocuments.new(client: self) + end + end + end +end diff --git a/lib/zadarma/error.rb b/lib/zadarma/error.rb new file mode 100644 index 0000000..9635af3 --- /dev/null +++ b/lib/zadarma/error.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +module Zadarma + class Error < StandardError + end +end diff --git a/lib/zadarma/resources/direct_numbers.rb b/lib/zadarma/resources/direct_numbers.rb new file mode 100644 index 0000000..713f395 --- /dev/null +++ b/lib/zadarma/resources/direct_numbers.rb @@ -0,0 +1,71 @@ +# frozen_string_literal: true + +module Zadarma + module Resources + # The DirectNumbers resource allows you to manage virtual numbers. + class DirectNumbers + def initialize(client:) + @client = client + end + + # Get information about the user's virtual numbers + # @return [Hash] + def all + @client.get('/v1/direct_numbers/') + end + + # Get a list of countries where numbers can be ordered + # @param language [String] The language for the country names + # @return [Hash] + def countries(language: nil) + params = {} + params[:language] = language if language + @client.get('/v1/direct_numbers/countries/', params) + end + + # Get a list of destinations in a country where a number can be ordered + # @param country [String] The ISO country code + # @param language [String] The language for the destination names + # @param direction_id [String] The direction ID + # @return [Hash] + def country(country:, language: nil, direction_id: nil) + params = { country: country } + params[:language] = language if language + params[:direction_id] = direction_id if direction_id + @client.get('/v1/direct_numbers/country/', params) + end + + # Get a list of available numbers for a given direction + # @param direction_id [String] The direction ID + # @param mask [String] A mask for searching number matches + # @return [Hash] + def available(direction_id:, mask: nil) + params = {} + params[:mask] = mask if mask + @client.get("/v1/direct_numbers/available/#{direction_id}/", params) + end + + # Order a virtual number + # @param params [Hash] The parameters for ordering a number + # @option params [String] :direction_id The direction/city ID + # @option params [String] :number_id The ID of the number to be connected + # @option params [String] :documents_group_id The ID of the group of user documents + # @option params [String] :purpose A text description of the purpose of number use + # @option params [String] :receive_sms '1' to enable SMS reception + # @option params [String] :period 'month' or '3month' + # @option params [String] :autorenew_period 'year' or 'month' + # @return [Hash] + def order(params) + @client.post('/v1/direct_numbers/order/', params) + end + + # Prepay the number for the specified number of months + # @param number [String] The number to be prolonged + # @param months [Integer] The number of months + # @return [Hash] + def prolong(number:, months:) + @client.post('/v1/direct_numbers/prolong/', number: number, months: months) + end + end + end +end diff --git a/lib/zadarma/resources/groups_of_documents.rb b/lib/zadarma/resources/groups_of_documents.rb new file mode 100644 index 0000000..a905fc8 --- /dev/null +++ b/lib/zadarma/resources/groups_of_documents.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +module Zadarma + module Resources + # The GroupsOfDocuments resource allows you to manage groups of documents. + class GroupsOfDocuments + def initialize(client:) + @client = client + end + + # Get the list of files/documents in the group of documents + # @param group_id [String] The group of documents ID + # @return [Hash] + def files(group_id: nil) + params = {} + params[:group_id] = group_id if group_id + @client.get('/v1/documents/files/', params) + end + + # Get the list of groups of documents + # @return [Hash] + def list + @client.get('/v1/documents/groups/list/') + end + + # Get information on a certain group + # @param id [String] The group ID + # @return [Hash] + def get(id:) + @client.get("/v1/documents/groups/get/#{id}/") + end + + # Create a new group of documents + # @param params [Hash] The parameters for creating a new group of documents + # @return [Hash] + def create(params:) + @client.post('/v1/documents/groups/create/', params) + end + + # Update a group of documents + # @param id [String] The group ID + # @param params [Hash] The parameters for updating a group of documents + # @return [Hash] + def update(id:, params:) + @client.put("/v1/documents/groups/update/#{id}/", params) + end + end + end +end diff --git a/lib/zadarma/resources/info.rb b/lib/zadarma/resources/info.rb new file mode 100644 index 0000000..78b4f9f --- /dev/null +++ b/lib/zadarma/resources/info.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +module Zadarma + module Resources + # The Info resource provides access to user information, such as balance and call rates. + class Info + def initialize(client:) + @client = client + end + + # Get the user's balance + # @return [Hash] + def balance + @client.get('/v1/info/balance/') + end + + # Get the call rate for a given number + # @param number [String] The phone number + # @param caller_id [String] The CallerID to be used for the call + # @return [Hash] + def price(number:, caller_id: nil) + params = { number: number } + params[:caller_id] = caller_id if caller_id + @client.get('/v1/info/price/', params) + end + end + end +end diff --git a/lib/zadarma/resources/pbx.rb b/lib/zadarma/resources/pbx.rb new file mode 100644 index 0000000..37e0514 --- /dev/null +++ b/lib/zadarma/resources/pbx.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +module Zadarma + module Resources + # The Pbx resource allows you to manage your Zadarma PBX. + class Pbx + def initialize(client:) + @client = client + end + + # Get the list of PBX internal numbers + # @return [Hash] + def internal + @client.get('/v1/pbx/internal/') + end + + # Set the call recording for a PBX extension + # @param id [String] The PBX extension ID + # @param status [String] The call recording status ('on', 'off', etc.) + # @param email [String] The email address to send recordings to + # @param speech_recognition [String] The speech recognition settings + # @return [Hash] + def set_call_recording(id:, status:, email: nil, speech_recognition: nil) + params = { id: id, status: status } + params[:email] = email if email + params[:speech_recognition] = speech_recognition if speech_recognition + @client.put('/v1/pbx/internal/recording/', params) + end + + # Request a call recording file + # @param call_id [String] The unique call ID + # @param pbx_call_id [String] The permanent ID of the external call to the PBX + # @param lifetime [Integer] The link's lifetime in seconds + # @return [Hash] + def pbx_record_request(call_id: nil, pbx_call_id: nil, lifetime: nil) + params = {} + params[:call_id] = call_id if call_id + params[:pbx_call_id] = pbx_call_id if pbx_call_id + params[:lifetime] = lifetime if lifetime + @client.get('/v1/pbx/record/request/', params) + end + end + end +end diff --git a/lib/zadarma/resources/request.rb b/lib/zadarma/resources/request.rb new file mode 100644 index 0000000..4c34a38 --- /dev/null +++ b/lib/zadarma/resources/request.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module Zadarma + module Resources + # The Request resource allows you to initiate callbacks. + class Request + def initialize(client:) + @client = client + end + + # Request a callback + # @param from [String] Your phone/SIP number, the PBX extension or the PBX scenario + # @param to [String] The phone or SIP number that is being called + # @param sip [String] The SIP user's number or the PBX extension + # @param predicted [String] If specified, the request is predicted + # @return [Hash] + def callback(from:, to:, sip: nil, predicted: nil) + params = { from: from, to: to } + params[:sip] = sip if sip + params[:predicted] = predicted if predicted + @client.get('/v1/request/callback/', params) + end + end + end +end diff --git a/lib/zadarma/resources/sip.rb b/lib/zadarma/resources/sip.rb new file mode 100644 index 0000000..34f5602 --- /dev/null +++ b/lib/zadarma/resources/sip.rb @@ -0,0 +1,79 @@ +# frozen_string_literal: true + +module Zadarma + module Resources + # The Sip resource allows you to manage your SIP numbers. + class Sip + def initialize(client:) + @client = client + end + + # Get the list of user's SIP-numbers + # @return [Hash] + def all + @client.get('/v1/sip/') + end + + # Set the CallerID for a SIP number + # @param id [String] The SIP ID + # @param number [String] The new CallerID + # @return [Hash] + def set_caller_id(id:, number:) + @client.put('/v1/sip/callerid/', id: id, number: number) + end + + # Get call forwarding information for a SIP number + # @param id [String] The SIP ID + # @return [Hash] + def redirection(id: nil) + params = {} + params[:id] = id if id + @client.get('/v1/sip/redirection/', params) + end + + # Set call forwarding for a SIP number + # @param id [String] The SIP ID + # @param status [String] The call forwarding status ('on' or 'off') + # @param type [String] The call forwarding type ('phone', 'voicemail', etc.) + # @param number [String] The destination number for call forwarding + # @param condition [String] The call forwarding condition ('always', 'noanswer', etc.) + # @return [Hash] + def set_redirection(id:, status:, type: nil, number: nil, condition: nil) + params = { id: id, status: status } + params[:type] = type if type + params[:number] = number if number + params[:condition] = condition if condition + @client.put('/v1/sip/redirection/', params) + end + + # Get the online status of a SIP number + # @param sip [String] The SIP number + # @return [Hash] + def status(sip:) + @client.get("/v1/sip/#{sip}/status/") + end + + # Create a new SIP number + # @param name [String] The displayed name for the new SIP number + # @param password [String] The password for the new SIP number + # @param callerid [String] The CallerID for the new SIP number + # @param redirect_to_phone [String] The phone number to redirect calls to + # @return [Hash] + def create(name:, password: nil, callerid: nil, redirect_to_phone: nil) + params = { name: name } + params[:password] = password if password + params[:callerid] = callerid if callerid + params[:redirect_to_phone] = redirect_to_phone if redirect_to_phone + @client.post('/v1/sip/create/', params) + end + + # Change the password for a SIP number + # @param sip [String] The SIP number + # @param value [String] The new password + # @return [Hash] + def password(sip:, value:) + @client.put("/v1/sip/#{sip}/password/", value: value) + end + end + end +end diff --git a/lib/zadarma/resources/sms.rb b/lib/zadarma/resources/sms.rb new file mode 100644 index 0000000..e0972de --- /dev/null +++ b/lib/zadarma/resources/sms.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +module Zadarma + module Resources + # The Sms resource allows you to send SMS messages. + class Sms + def initialize(client:) + @client = client + end + + # Send an SMS message + # @param number [String] The destination phone number + # @param message [String] The SMS message text + # @param sender [String] The SMS sender (virtual number or text) + # @return [Hash] + def send_sms(number:, message:, sender: nil) + params = { number: number, message: message } + params[:sender] = sender if sender + @client.post('/v1/sms/send/', params) + end + end + end +end diff --git a/lib/zadarma/resources/speech_recognition.rb b/lib/zadarma/resources/speech_recognition.rb new file mode 100644 index 0000000..06dec86 --- /dev/null +++ b/lib/zadarma/resources/speech_recognition.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +module Zadarma + module Resources + # The SpeechRecognition resource allows you to manage speech recognition. + class SpeechRecognition + def initialize(client:) + @client = client + end + + # Get recognition results + # @param call_id [String] The unique call ID + # @param lang [String] The recognition language + # @param return_results [String] The returned result ('words' or 'phrases') + # @param alternatives [String] Return alternative results ('0' or '1') + # @return [Hash] + def get(call_id:, lang: nil, return_results: nil, alternatives: nil) + params = { call_id: call_id } + params[:lang] = lang if lang + params[:return] = return_results if return_results + params[:alternatives] = alternatives if alternatives + @client.get('/v1/speech_recognition/', params) + end + + # Initiate call recognition + # @param call_id [String] The unique call ID + # @param lang [String] The recognition language + # @return [Hash] + def initiate(call_id:, lang: nil) + params = { call_id: call_id } + params[:lang] = lang if lang + @client.put('/v1/speech_recognition/', params) + end + end + end +end diff --git a/lib/zadarma/resources/statistics.rb b/lib/zadarma/resources/statistics.rb new file mode 100644 index 0000000..e8bcf2b --- /dev/null +++ b/lib/zadarma/resources/statistics.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +require 'time' + +module Zadarma + module Resources + # The Statistics resource provides access to call statistics. + class Statistics + def initialize(client:) + @client = client + end + + # Get overall call statistics + # @param params [Hash] The parameters for the statistics request + # @option params [String] :start The start date of the statistics display + # @option params [String] :end The end date of the statistics display + # @option params [String] :sip Filter based on a specific SIP number + # @option params [String] :cost_only Display only the amount of funds spent + # @option params [String] :type Request type ('overall' or 'toll-free') + # @option params [Integer] :skip Number of lines to be skipped in the sample + # @option params [Integer] :limit The limit on the number of input lines + # @return [Hash] + def statistics(params) + response = @client.get('/v1/statistics/', params) + response['stats']&.each do |stat| + stat['callstart'] = Time.parse(stat['callstart']) if stat['callstart'] + end + response + end + + # Get PBX call statistics + # @param params [Hash] The parameters for the PBX statistics request + # @option params [String] :start The start date of the statistics display + # @option params [String] :end The end date of the statistics display + # @option params [String] :version Format of the statistics result ('1' or '2') + # @option params [Integer] :skip Number of lines to be skipped in the sample + # @option params [Integer] :limit The limit on the number of input lines + # @option params [String] :call_type Call destination ('in' or 'out') + # @return [Hash] + def pbx_statistics(params) + response = @client.get('/v1/statistics/pbx/', params) + response['stats']&.each do |stat| + stat['callstart'] = Time.parse(stat['callstart']) if stat['callstart'] + end + response + end + end + end +end diff --git a/lib/zadarma/version.rb b/lib/zadarma/version.rb new file mode 100644 index 0000000..1de4ee1 --- /dev/null +++ b/lib/zadarma/version.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +module Zadarma + VERSION = '2.0.0' +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index a50ef1b..d504b68 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -22,7 +22,7 @@ # See https://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration RSpec.configure do |config| # rspec-expectations config goes here. You can use an alternate - # assertion/expectation library such as wrong or the stdlib/minest + # assertion/expectation library such as wrong or the stdlib/minitest # assertions if you prefer. config.expect_with :rspec do |expectations| # This option will default to `true` in RSpec 4. It makes the `description` diff --git a/spec/zadarma/client_spec.rb b/spec/zadarma/client_spec.rb new file mode 100644 index 0000000..a11c468 --- /dev/null +++ b/spec/zadarma/client_spec.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require 'spec_helper' +require 'zadarma' + +RSpec.describe Zadarma::Client do + let(:api_key) { 'test_key' } + let(:api_secret) { 'test_secret' } + let(:client) { described_class.new(api_key: api_key, api_secret: api_secret) } + + describe '#initialize' do + it 'initializes with an api_key and api_secret' do + expect(client).to be_a(described_class) + end + end + + describe '#get' do + it 'makes a GET request to the specified path' do + stub_request(:get, 'https://api.zadarma.com/v1/test_path?param=value') + .to_return(status: 200, body: '{"status":"success"}', headers: {}) + + client.get('/v1/test_path', param: 'value') + + expect(WebMock).to have_requested(:get, 'https://api.zadarma.com/v1/test_path?param=value') + .with(headers: { 'Authorization' => /test_key:.*/ }).once + end + end +end diff --git a/spec/zadarma/resources/direct_numbers_spec.rb b/spec/zadarma/resources/direct_numbers_spec.rb new file mode 100644 index 0000000..164d327 --- /dev/null +++ b/spec/zadarma/resources/direct_numbers_spec.rb @@ -0,0 +1,68 @@ +# frozen_string_literal: true + +require 'spec_helper' +require 'zadarma' + +RSpec.describe Zadarma::Resources::DirectNumbers do + subject(:direct_numbers) { described_class.new(client: client) } + + let(:client) { Zadarma::Client.new(api_key: 'test_key', api_secret: 'test_secret') } + + describe '#all' do + it 'returns the list of direct numbers' do + stub_request(:get, 'https://api.zadarma.com/v1/direct_numbers/') + .to_return(status: 200, body: '{"info": [{"number": "1234567890"}]}', headers: {}) + expect(direct_numbers.all).to eq('info' => [{ 'number' => '1234567890' }]) + end + end + + describe '#countries' do + it 'returns the list of countries' do + stub_request(:get, %r{api.zadarma.com/v1/direct_numbers/countries/}) + .to_return(body: { status: 'success', info: [] }.to_json) + + response = direct_numbers.countries + expect(response['status']).to eq('success') + end + end + + describe '#country' do + it 'returns the list of destinations in a country' do + stub_request(:get, %r{api.zadarma.com/v1/direct_numbers/country/}) + .to_return(body: { status: 'success', info: [] }.to_json) + + response = direct_numbers.country(country: 'US') + expect(response['status']).to eq('success') + end + end + + describe '#available' do + it 'returns the list of available numbers' do + stub_request(:get, %r{api.zadarma.com/v1/direct_numbers/available/123/}) + .to_return(body: { status: 'success', numbers: [] }.to_json) + + response = direct_numbers.available(direction_id: '123') + expect(response['status']).to eq('success') + end + end + + describe '#order' do + it 'orders a new direct number' do + stub_request(:post, %r{api.zadarma.com/v1/direct_numbers/order/}) + .to_return(body: { status: 'success', number: '1234567890' }.to_json) + + response = direct_numbers.order(direction_id: '123') + expect(response).to eq('status' => 'success', 'number' => '1234567890') + end + end + + describe '#prolong' do + it 'prolongs a direct number' do + stub_request(:post, %r{api.zadarma.com/v1/direct_numbers/prolong/}) + .to_return(body: { status: 'success' }.to_json) + + response = direct_numbers.prolong(number: '1234567890', months: 1) + expect(response['status']).to eq('success') + end + end +end diff --git a/spec/zadarma/resources/groups_of_documents_spec.rb b/spec/zadarma/resources/groups_of_documents_spec.rb new file mode 100644 index 0000000..7bb42b7 --- /dev/null +++ b/spec/zadarma/resources/groups_of_documents_spec.rb @@ -0,0 +1,58 @@ +# frozen_string_literal: true + +require 'zadarma/client' +require 'webmock/rspec' + +RSpec.describe Zadarma::Resources::GroupsOfDocuments do + let(:client) { Zadarma::Client.new(api_key: 'test_key', api_secret: 'test_secret') } + + describe '#files' do + it 'retrieves the list of files in a group of documents' do + stub_request(:get, %r{api.zadarma.com/v1/documents/files/}) + .to_return(body: { status: 'success' }.to_json) + + response = client.document_files + expect(response['status']).to eq('success') + end + end + + describe '#list' do + it 'retrieves the list of groups of documents' do + stub_request(:get, %r{api.zadarma.com/v1/documents/groups/list/}) + .to_return(body: { status: 'success' }.to_json) + + response = client.document_groups + expect(response['status']).to eq('success') + end + end + + describe '#get' do + it 'retrieves a group of documents' do + stub_request(:get, %r{api.zadarma.com/v1/documents/groups/get/123/}) + .to_return(body: { status: 'success' }.to_json) + + response = client.get_document_group(id: '123') + expect(response['status']).to eq('success') + end + end + + describe '#create' do + it 'creates a new group of documents' do + stub_request(:post, %r{api.zadarma.com/v1/documents/groups/create/}) + .to_return(body: { status: 'success' }.to_json) + + response = client.create_document_group(params: { first_name: 'John', last_name: 'Doe' }) + expect(response['status']).to eq('success') + end + end + + describe '#update' do + it 'updates a group of documents' do + stub_request(:put, %r{api.zadarma.com/v1/documents/groups/update/123/}) + .to_return(body: { status: 'success' }.to_json) + + response = client.update_document_group(id: '123', params: { first_name: 'Jane' }) + expect(response['status']).to eq('success') + end + end +end diff --git a/spec/zadarma/resources/info_spec.rb b/spec/zadarma/resources/info_spec.rb new file mode 100644 index 0000000..c02f616 --- /dev/null +++ b/spec/zadarma/resources/info_spec.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +require 'spec_helper' +require 'zadarma' + +RSpec.describe Zadarma::Resources::Info do + subject(:info) { described_class.new(client: client) } + + let(:client) { Zadarma::Client.new(api_key: 'test_key', api_secret: 'test_secret') } + + describe '#balance' do + it 'returns the current balance' do + stub_request(:get, 'https://api.zadarma.com/v1/info/balance/') + .to_return(status: 200, body: '{"balance": 100.0}', headers: {}) + expect(info.balance).to eq('balance' => 100.0) + end + end + + describe '#price' do + it 'returns the price for a given number' do + stub_request(:get, 'https://api.zadarma.com/v1/info/price/?number=1234567890') + .to_return(status: 200, body: '{"price": 0.01}', headers: {}) + expect(info.price(number: '1234567890')).to eq('price' => 0.01) + end + + it 'returns the price for a given number and caller_id' do + stub_request(:get, 'https://api.zadarma.com/v1/info/price/?caller_id=0987654321&number=1234567890') + .to_return(status: 200, body: '{"price": 0.02}', headers: {}) + expect(info.price(number: '1234567890', caller_id: '0987654321')).to eq('price' => 0.02) + end + end +end diff --git a/spec/zadarma/resources/pbx_spec.rb b/spec/zadarma/resources/pbx_spec.rb new file mode 100644 index 0000000..1c10061 --- /dev/null +++ b/spec/zadarma/resources/pbx_spec.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +require 'spec_helper' +require 'zadarma' + +RSpec.describe Zadarma::Resources::Pbx do + subject(:pbx) { described_class.new(client: client) } + + let(:client) { Zadarma::Client.new(api_key: 'test_key', api_secret: 'test_secret') } + + describe '#internal' do + it 'returns the list of internal numbers' do + stub_request(:get, 'https://api.zadarma.com/v1/pbx/internal/') + .to_return(status: 200, body: '{"numbers": ["100", "101"]}', headers: {}) + expect(pbx.internal).to eq('numbers' => %w[100 101]) + end + end + + describe '#set_call_recording' do + it 'sets the call recording for a pbx' do + stub_request(:put, 'https://api.zadarma.com/v1/pbx/internal/recording/') + .to_return(status: 200, body: '{"status": "success"}', headers: {}) + expect(pbx.set_call_recording(id: '1234', status: 'on')).to eq('status' => 'success') + end + end + + describe '#pbx_record_request' do + it 'requests a call recording' do + stub_request(:get, %r{api.zadarma.com/v1/pbx/record/request/}) + .to_return(body: { status: 'success', link: 'http://example.com/record.mp3' }.to_json) + + response = pbx.pbx_record_request(call_id: '12345') + expect(response).to eq('status' => 'success', 'link' => 'http://example.com/record.mp3') + end + end +end diff --git a/spec/zadarma/resources/request_spec.rb b/spec/zadarma/resources/request_spec.rb new file mode 100644 index 0000000..7b8d2b7 --- /dev/null +++ b/spec/zadarma/resources/request_spec.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +require 'spec_helper' +require 'zadarma' + +RSpec.describe Zadarma::Resources::Request do + subject(:request) { described_class.new(client: client) } + + let(:client) { Zadarma::Client.new(api_key: 'test_key', api_secret: 'test_secret') } + + describe '#callback' do + it 'requests a callback' do + stub_request(:get, 'https://api.zadarma.com/v1/request/callback/?from=1234567890&to=0987654321') + .to_return(status: 200, body: '{"status": "success"}', headers: {}) + expect(request.callback(from: '1234567890', to: '0987654321')).to eq('status' => 'success') + end + end +end diff --git a/spec/zadarma/resources/sip_spec.rb b/spec/zadarma/resources/sip_spec.rb new file mode 100644 index 0000000..d1e688e --- /dev/null +++ b/spec/zadarma/resources/sip_spec.rb @@ -0,0 +1,78 @@ +# frozen_string_literal: true + +require 'spec_helper' +require 'zadarma' + +RSpec.describe Zadarma::Resources::Sip do + subject(:sip) { described_class.new(client: client) } + + let(:client) { Zadarma::Client.new(api_key: 'test_key', api_secret: 'test_secret') } + + describe '#all' do + it 'returns the list of sips' do + stub_request(:get, 'https://api.zadarma.com/v1/sip/') + .to_return(status: 200, body: '{"sips": [{"id": "1234"}]}', headers: {}) + expect(sip.all).to eq('sips' => [{ 'id' => '1234' }]) + end + end + + describe '#set_caller_id' do + it 'sets the caller id for a sip' do + stub_request(:put, 'https://api.zadarma.com/v1/sip/callerid/') + .to_return(status: 200, body: '{"status": "success"}', headers: {}) + expect(sip.set_caller_id(id: '1234', number: '5678')).to eq('status' => 'success') + end + end + + describe '#redirection' do + it 'returns the redirection status for all sips' do + stub_request(:get, 'https://api.zadarma.com/v1/sip/redirection/') + .to_return(status: 200, body: '{"info": "test"}', headers: {}) + expect(sip.redirection).to eq('info' => 'test') + end + + it 'returns the redirection status for a specific sip' do + stub_request(:get, 'https://api.zadarma.com/v1/sip/redirection/?id=1234') + .to_return(status: 200, body: '{"info": "test"}', headers: {}) + expect(sip.redirection(id: '1234')).to eq('info' => 'test') + end + end + + describe '#set_redirection' do + it 'sets the redirection for a sip' do + stub_request(:put, 'https://api.zadarma.com/v1/sip/redirection/') + .to_return(status: 200, body: '{"status": "success"}', headers: {}) + expect(sip.set_redirection(id: '1234', status: 'on')).to eq('status' => 'success') + end + end + + describe '#status' do + it 'returns the status of a sip' do + stub_request(:get, %r{api.zadarma.com/v1/sip/123/status/}) + .to_return(body: { status: 'success', is_online: true }.to_json) + + response = sip.status(sip: '123') + expect(response).to eq('status' => 'success', 'is_online' => true) + end + end + + describe '#create' do + it 'creates a new sip' do + stub_request(:post, %r{api.zadarma.com/v1/sip/create/}) + .to_return(body: { status: 'success', sip: '12345' }.to_json) + + response = sip.create(name: 'New SIP') + expect(response).to eq('status' => 'success', 'sip' => '12345') + end + end + + describe '#password' do + it 'sets the password for a sip' do + stub_request(:put, %r{api.zadarma.com/v1/sip/123/password/}) + .to_return(body: { status: 'success' }.to_json) + + response = sip.password(sip: '123', value: 'new_password') + expect(response['status']).to eq('success') + end + end +end diff --git a/spec/zadarma/resources/sms_spec.rb b/spec/zadarma/resources/sms_spec.rb new file mode 100644 index 0000000..0d8d1cf --- /dev/null +++ b/spec/zadarma/resources/sms_spec.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +require 'spec_helper' +require 'zadarma' + +RSpec.describe Zadarma::Resources::Sms do + subject(:sms) { described_class.new(client: client) } + + let(:client) { Zadarma::Client.new(api_key: 'test_key', api_secret: 'test_secret') } + + describe '#send_sms' do + it 'sends an sms' do + stub_request(:post, 'https://api.zadarma.com/v1/sms/send/') + .to_return(status: 200, body: '{"status": "success"}', headers: {}) + expect(sms.send_sms(number: '1234567890', message: 'test message')).to eq('status' => 'success') + end + end +end diff --git a/spec/zadarma/resources/speech_recognition_spec.rb b/spec/zadarma/resources/speech_recognition_spec.rb new file mode 100644 index 0000000..1e43a8e --- /dev/null +++ b/spec/zadarma/resources/speech_recognition_spec.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require 'zadarma/client' +require 'webmock/rspec' + +RSpec.describe Zadarma::Resources::SpeechRecognition do + let(:client) { Zadarma::Client.new(api_key: 'test_key', api_secret: 'test_secret') } + + describe '#get' do + it 'retrieves speech recognition results' do + stub_request(:get, %r{api.zadarma.com/v1/speech_recognition/}) + .to_return(body: { status: 'success' }.to_json) + + response = client.get_speech_recognition(call_id: '12345') + expect(response['status']).to eq('success') + end + end + + describe '#initiate' do + it 'initiates speech recognition' do + stub_request(:put, %r{api.zadarma.com/v1/speech_recognition/}) + .to_return(body: { status: 'success' }.to_json) + + response = client.initiate_speech_recognition(call_id: '12345') + expect(response['status']).to eq('success') + end + end +end diff --git a/spec/zadarma/resources/statistics_spec.rb b/spec/zadarma/resources/statistics_spec.rb new file mode 100644 index 0000000..1e9b9bd --- /dev/null +++ b/spec/zadarma/resources/statistics_spec.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require 'zadarma/client' +require 'webmock/rspec' + +RSpec.describe Zadarma::Resources::Statistics do + let(:client) { Zadarma::Client.new(api_key: 'test_key', api_secret: 'test_secret') } + + describe '#statistics' do + it 'retrieves statistics' do + stub_request(:get, %r{api.zadarma.com/v1/statistics/}) + .to_return(body: { status: 'success', stats: [] }.to_json) + + response = client.statistics(start: '2023-01-01', end: '2023-01-31') + expect(response['status']).to eq('success') + end + end + + describe '#pbx_statistics' do + it 'retrieves pbx statistics' do + stub_request(:get, %r{api.zadarma.com/v1/statistics/pbx/}) + .to_return(body: { status: 'success', stats: [] }.to_json) + + response = client.pbx_statistics(start: '2023-01-01', end: '2023-01-31') + expect(response['status']).to eq('success') + end + end +end