Class: Walinko::Messages

Inherits:
Object
  • Object
show all
Defined in:
lib/walinko/messages.rb

Overview

The ‘messages` resource on `Walinko::Client`. Wraps:

POST /api/v1/public/messages
GET  /api/v1/public/messages/:tracking_id

Constant Summary collapse

SEND_PATH =
'/api/v1/public/messages'

Instance Method Summary collapse

Constructor Details

#initialize(http_client) ⇒ Messages

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of Messages.



18
19
20
# File 'lib/walinko/messages.rb', line 18

def initialize(http_client)
  @http = http_client
end

Instance Method Details

#enqueue(device_id:, template_id:, phone:, variables: nil, variant_index: nil, idempotency_key: nil) ⇒ Walinko::AsyncJob

Asynchronous enqueue: server returns immediately with a tracking id; the actual WhatsApp send happens out-of-band. Poll ‘fetch` (or use `wait_until_done`) for the final state.

Returns:



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/walinko/messages.rb', line 57

def enqueue(device_id:, template_id:, phone:,
            variables: nil, variant_index: nil,
            idempotency_key: nil)
  payload = build_payload(
    device_id: device_id, template_id: template_id,
    phone: phone, variables: variables,
    variant_index: variant_index, async: true
  )

  response = post(payload, idempotency_key: idempotency_key)
  data = extract_data(response.body)

  AsyncJob.new(
    data: data,
    request_id: response.request_id,
    rate_limit: response.rate_limit,
    idempotent_replayed: response.idempotent_replayed
  )
end

#fetch(tracking_id) ⇒ Walinko::MessageStatus

Look up a delivery by its tracking id.

Parameters:

  • tracking_id (String)

    e.g. ‘tx_767fd2faca0f4037b2a2bbcb91e5735f`

Returns:

Raises:

  • (ArgumentError)


81
82
83
84
85
86
87
88
# File 'lib/walinko/messages.rb', line 81

def fetch(tracking_id)
  raise ArgumentError, 'tracking_id is required' if tracking_id.nil? || tracking_id.to_s.empty?

  response = @http.request(method: :get, path: "#{SEND_PATH}/#{tracking_id}")
  data = extract_data(response.body)

  MessageStatus.new(data: data, request_id: response.request_id)
end

#send(device_id:, template_id:, phone:, variables: nil, variant_index: nil, idempotency_key: nil) ⇒ Walinko::SyncResult

Synchronous send: blocks until the WhatsApp gateway acknowledges delivery (or the server’s 15s timeout fires).

Parameters:

  • device_id (Integer)

    required

  • template_id (Integer)

    required

  • phone (String)

    required, E.164 (‘+8801617738431`)

  • variables (Hash) (defaults to: nil)

    optional ‘{ name: ’value’ }‘ map

  • variant_index (Integer) (defaults to: nil)

    optional, 0 = primary

  • idempotency_key (String) (defaults to: nil)

    optional; auto-generated otherwise

Returns:



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/walinko/messages.rb', line 32

def send(device_id:, template_id:, phone:,
         variables: nil, variant_index: nil,
         idempotency_key: nil)
  payload = build_payload(
    device_id: device_id, template_id: template_id,
    phone: phone, variables: variables,
    variant_index: variant_index, async: false
  )

  response = post(payload, idempotency_key: idempotency_key)
  data = extract_data(response.body)

  SyncResult.new(
    data: data,
    request_id: response.request_id,
    rate_limit: response.rate_limit,
    idempotent_replayed: response.idempotent_replayed
  )
end

#wait_until_done(tracking_id, timeout: 60, interval: 2) ⇒ Walinko::MessageStatus

Poll ‘fetch` until the delivery reaches a terminal state (sent / failed) or the timeout expires.

Parameters:

  • tracking_id (String)
  • timeout (Integer) (defaults to: 60)

    max seconds to wait, default 60

  • interval (Numeric) (defaults to: 2)

    seconds between polls, default 2

Returns:

Raises:

  • (Walinko::TimeoutError)

    if the message is still pending when ‘timeout` elapses (the message is not failed —continue polling later if you need to)



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/walinko/messages.rb', line 100

def wait_until_done(tracking_id, timeout: 60, interval: 2)
  raise ArgumentError, 'timeout must be > 0'  if timeout.to_i  <= 0
  raise ArgumentError, 'interval must be > 0' if interval.to_f <= 0

  deadline = monotonic_now + timeout.to_f
  loop do
    status = fetch(tracking_id)
    return status if status.done?

    if monotonic_now + interval.to_f >= deadline
      raise TimeoutError.new(
        "Timed out waiting for #{tracking_id} after #{timeout}s (still #{status.status})",
        http_status: 504,
        error_code: 'send_timeout',
        request_id: status.request_id,
        details: { 'last_status' => status.status }
      )
    end

    sleep(interval.to_f)
  end
end