Class: TwilioClient

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
app/services/twilio_client.rb

Overview

Service object: twilio client.

Delegated Instance Attributes collapse

Instance Attribute Summary collapse

Delegated Instance Attributes collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ TwilioClient

Returns a new instance of TwilioClient.

Parameters:

  • options (Hash) (defaults to: {})

    client configuration

Options Hash (options):

  • :logger (Logger)

    logger to use (defaults to Rails.logger)

  • :account_sid (String)

    Twilio account SID (defaults to configuration)

  • :auth_token (String)

    Twilio auth token (defaults to configuration)

  • :sms_status_callback_url (String)

    webhook URL for SMS status updates
    (defaults to the configured base webhook URL + /update_status)

  • :default_sender (String)

    default "from" phone number



23
24
25
26
27
28
29
30
31
32
33
# File 'app/services/twilio_client.rb', line 23

def initialize(options = {})
  @logger = options[:logger] || Rails.logger
   = options[:account_sid] || Heatwave::Configuration.fetch(:twilio, :account_sid)
  auth_token = options[:auth_token] || Heatwave::Configuration.fetch(:twilio, :auth_token)
  @account_sid = 
  @auth_token = auth_token
  @sms_status_callback_url = options[:sms_status_callback_url]
  @sms_status_callback_url ||= "#{Heatwave::Configuration.fetch(:twilio, :sms_base_wehook_url)}/update_status"
  @default_sender = options[:default_sender] || '+18008755285'
  @client = Twilio::REST::Client.new , auth_token
end

Instance Attribute Details

#clientObject (readonly)

Alias for Instance#client

Returns:

  • (Object)

    Instance#client

See Also:



10
11
12
# File 'app/services/twilio_client.rb', line 10

def client
  @client
end

#default_senderObject (readonly)

Returns the value of attribute default_sender.



10
11
12
# File 'app/services/twilio_client.rb', line 10

def default_sender
  @default_sender
end

#loggerObject (readonly)

Returns the value of attribute logger.



10
11
12
# File 'app/services/twilio_client.rb', line 10

def logger
  @logger
end

Instance Method Details

#delete_recording(recording_sid) ⇒ Object

Delete a recording from Twilio (after successful import)

Parameters:

  • recording_sid (String)

    The Recording SID



186
187
188
189
190
191
192
193
# File 'app/services/twilio_client.rb', line 186

def delete_recording(recording_sid)
  client.recordings(recording_sid).delete
  logger.info "[TwilioClient] Deleted recording #{recording_sid}"
  true
rescue Twilio::REST::RestError => e
  logger.error "[TwilioClient] Failed to delete recording #{recording_sid}: #{e.message}"
  false
end

#download_recording(recording_sid, dual_channel: true) ⇒ String

Note:

Twilio error 16109 - When call recording encryption is enabled,
recordings can ONLY be downloaded in WAV format, not MP3.

Download a recording as WAV (required when call recording encryption is enabled)
SIP trunk recordings are natively stereo (2 channels) - preserved in WAV format

Parameters:

  • recording_sid (String)

    The Recording SID

  • dual_channel (Boolean) (defaults to: true)

    Ignored - kept for backwards compatibility

Returns:

  • (String)

    Local file path to downloaded recording

See Also:



154
# File 'app/services/twilio_client.rb', line 154

delegate :client, :send_message, :list_numbers, :list_recordings, :download_recording, :lookup_line_type, to: :instance

#get_call(call_sid) ⇒ Hash

Get call details for a recording (to extract phone numbers)

Parameters:

  • call_sid (String)

    The Twilio Call SID

Returns:

  • (Hash)

    Call metadata including from/to numbers



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'app/services/twilio_client.rb', line 126

def get_call(call_sid)
  call = client.calls(call_sid).fetch
  {
    sid: call.sid,
    from: call.from,
    to: call.to,
    direction: call.direction,
    duration: call.duration.to_i,
    start_time: call.start_time,
    end_time: call.end_time,
    status: call.status,
    # SIP trunk info if available
    trunk_sid: call.trunk_sid
  }
rescue Twilio::REST::RestError => e
  logger.error "[TwilioClient] Failed to fetch call #{call_sid}: #{e.message}"
  nil
end

#list_numbersObject

Alias for Instance#list_numbers

Returns:

  • (Object)

    Instance#list_numbers

See Also:



13
# File 'app/services/twilio_client.rb', line 13

delegate :client, :send_message, :list_numbers, :list_recordings, :download_recording, :lookup_line_type, to: :instance

#list_recordings(date_created_after: nil, limit: 100) ⇒ Array<Hash>

List recordings from Twilio

Parameters:

  • date_created_after (Time) (defaults to: nil)

    Filter recordings created after this time

  • limit (Integer) (defaults to: 100)

    Maximum number of recordings to return

Returns:

  • (Array<Hash>)

    Array of recording metadata



101
# File 'app/services/twilio_client.rb', line 101

delegate :client, :send_message, :list_numbers, :list_recordings, :download_recording, :lookup_line_type, to: :instance

#lookup_line_type(number) ⇒ Symbol

Note:

Logs only the last 4 digits of the number to avoid PII leakage to
centralized log aggregators.

Twilio Lookups v2 Line Type Intelligence.

Returns the carrier-reported line type for an E.164 number, or :unknown
when Twilio can't classify or the lookup fails. Billed per call
(~$0.005 USD as of 2026), so callers should cache by number and re-verify
infrequently.

Logic Details

Twilio's type field is camelCase (fixedVoip, nonFixedVoip,
tollFree, sharedCost); this method normalizes to underscored Ruby
symbols.

Twilio::REST::TwilioError is the parent of both RestError (HTTP 4xx/5xx
responses) and the network/timeout wrappers, so rescuing it preserves the
"always returns :unknown on failure" contract for both flavors of failure.

Parameters:

  • number (String)

    E.164-formatted phone number, e.g. "+15146777418"

Returns:

  • (Symbol)

    one of :mobile, :landline, :fixed_voip,
    :non_fixed_voip, :personal, :toll_free, :premium,
    :shared_cost, :uan, :voicemail, :pager, :unknown

See Also:



81
# File 'app/services/twilio_client.rb', line 81

delegate :client, :send_message, :list_numbers, :list_recordings, :download_recording, :lookup_line_type, to: :instance

#send_message(to:, body:, from: nil, media_urls: nil) ⇒ Object

============================================================================
SMS Methods



38
# File 'app/services/twilio_client.rb', line 38

delegate :client, :send_message, :list_numbers, :list_recordings, :download_recording, :lookup_line_type, to: :instance