Class: Pinnacle::Wrapper::Messages::Client

Inherits:
Messages::Client show all
Defined in:
lib/pinnacle/wrapper/messages/client.rb

Instance Method Summary collapse

Methods inherited from Messages::Client

#blast, #get, #initialize, #mms, #rcs, #react, #schedule, #sms

Constructor Details

This class inherits a constructor from Pinnacle::Messages::Client

Instance Method Details

#process(request, secret: nil) ⇒ Pinnacle::Types::MessageEvent, Pinnacle::Types::UserEvent

Process incoming webhook request with signature validation.

Examples:

Process a webhook request

client = Pinnacle::Client.new(api_key: "your-api-key")
request = {
  headers: { "PINNACLE-SIGNING-SECRET" => "your-secret" },
  body: '{"type": "MESSAGE.RECEIVED", ...}'
}
event = client.messages.process(request)

Parameters:

  • request (Hash)

    Request with :headers and :body keys

  • secret (String, nil) (defaults to: nil)

    Webhook secret (falls back to PINNACLE_SIGNING_SECRET env var)

Returns:

Raises:



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/pinnacle/wrapper/messages/client.rb', line 25

def process(request, secret: nil)
  headers = request[:headers] || request["headers"] || {}
  body = request[:body] || request["body"]

  header_secret = headers["PINNACLE-SIGNING-SECRET"] ||
                  headers["pinnacle-signing-secret"] ||
                  headers["Pinnacle-Signing-Secret"]

  env_secret = secret || ENV.fetch("PINNACLE_SIGNING_SECRET", nil)

  if header_secret.nil?
    raise Pinnacle::Errors::UnauthorizedError.new(
      "Failed to get PINNACLE-SIGNING-SECRET header from request",
      code: 401
    )
  end

  if env_secret.nil?
    raise Pinnacle::Errors::UnauthorizedError.new(
      "Set PINNACLE_SIGNING_SECRET env var or pass secret argument",
      code: 401
    )
  end

  if header_secret != env_secret
    raise Pinnacle::Errors::UnauthorizedError.new(
      "Invalid webhook signature",
      code: 401
    )
  end

  parsed = body.is_a?(String) ? JSON.parse(body) : body

  if parsed["type"] == "USER.TYPING"
    Pinnacle::Types::UserEvent.coerce(parsed)
  else
    Pinnacle::Types::MessageEvent.coerce(parsed)
  end
rescue JSON::ParserError => e
  raise Pinnacle::Errors::ClientError.new(
    "Invalid message event format: #{e.message}",
    code: 400
  )
end