chat_sdk-whatsapp 0.2.1 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5a9c659c8408890113cd3a76002744ec05805a84b7f931bc3f5af5d3c8f12b92
4
- data.tar.gz: f75e6904f0de6b2f29b3a7b069abc773044a31cfb189aa4f92ba9b25a9a1ef62
3
+ metadata.gz: b50c0867485e3db72c8642600094c6a648cd4c5f5030357d7b75c4448b3ddd86
4
+ data.tar.gz: 607a03f130b22a02077456128ec0490dd54d2df0d4789739a185c6ce72725191
5
5
  SHA512:
6
- metadata.gz: 2a38e860754f4f1950c9e1353e46a1ab26bd16ab2e8ef4c18861ec79fc2a4a8d17c9a1e79b8e3a2bd8e6b2d305f74f6c08ebbb1a83c6dabc5274c5ab2c841113
7
- data.tar.gz: 7b1be833a9084bd3e65b7a9ba27c795b61323115ae7c0457a3ab24bec9a26e95375f6de6d638f3c56def3895362ebee343df067aa555d0f3c87c21dbdf4569e1
6
+ metadata.gz: 8033901c11f50fe2d076a1f56db90d6c9f0793371c2a313841e7b09a2af76de34d9bcdb665125e8580fa30c77f6235ef3354da85ae9fbab1b536c5353a3426a6
7
+ data.tar.gz: e9e4577b34adeaaeded3213517a3c7ccfb41e4cda3f75577bd02f15134c2d9dd62a757114c284f27bd167ffac40df6b5876be77719d7cea6262bdaa6766f23aa
@@ -1,11 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "openssl"
4
- require "rack/utils"
5
-
6
3
  module ChatSDK
7
4
  module WhatsApp
8
5
  class Adapter < ChatSDK::Adapter::Base
6
+ include ChatSDK::Adapter::MetaVerification
7
+
9
8
  capabilities :direct_messages, :file_uploads, :reactions
10
9
 
11
10
  attr_reader :client
@@ -29,42 +28,15 @@ module ChatSDK
29
28
 
30
29
  # Inbound
31
30
  def verify_request!(rack_request)
32
- signature = rack_request.get_header("HTTP_X_HUB_SIGNATURE_256")
33
-
34
- unless signature
35
- raise ChatSDK::SignatureVerificationError, "Missing WhatsApp signature header"
36
- end
37
-
38
- body = rack_request.body.read
39
- rack_request.body.rewind
40
-
41
- expected = "sha256=#{OpenSSL::HMAC.hexdigest("SHA256", @app_secret, body)}"
42
-
43
- unless Rack::Utils.secure_compare(signature, expected)
44
- raise ChatSDK::SignatureVerificationError, "Invalid WhatsApp signature"
45
- end
46
-
47
- true
31
+ verify_meta_signature!(rack_request, secret: @app_secret, platform_name: "WhatsApp")
48
32
  end
49
33
 
50
34
  def ack_response(rack_request)
51
- return nil unless rack_request.get?
52
-
53
- params = rack_request.params
54
- mode = params["hub.mode"]
55
- token = params["hub.verify_token"]
56
- challenge = params["hub.challenge"]
57
-
58
- if mode == "subscribe" && token == @verify_token
59
- [200, {}, [challenge.to_s]]
60
- end
35
+ meta_ack_response(rack_request, verify_token: @verify_token)
61
36
  end
62
37
 
63
38
  def parse_events(rack_request)
64
- body = rack_request.body.read
65
- rack_request.body.rewind
66
-
67
- payload = JSON.parse(body)
39
+ payload = read_json_body(rack_request)
68
40
  EventParser.parse(payload, @phone_number_id)
69
41
  rescue JSON::ParserError
70
42
  []
@@ -2,7 +2,7 @@
2
2
 
3
3
  module ChatSDK
4
4
  module WhatsApp
5
- class ApiClient
5
+ class ApiClient < ChatSDK::ApiClient::Base
6
6
  BASE_URL = "https://graph.facebook.com/v21.0"
7
7
 
8
8
  def initialize(access_token, phone_number_id)
@@ -30,7 +30,7 @@ module ChatSDK
30
30
  end
31
31
 
32
32
  def upload_media(io:, filename:, content_type:)
33
- response = media_connection.post("#{@phone_number_id}/media") do |req|
33
+ response = upload_connection.post("#{@phone_number_id}/media") do |req|
34
34
  req.body = {
35
35
  "messaging_product" => "whatsapp",
36
36
  "file" => Faraday::Multipart::FilePart.new(io, content_type, filename),
@@ -43,52 +43,21 @@ module ChatSDK
43
43
 
44
44
  private
45
45
 
46
- def connection
47
- @connection ||= build_connection { |f| f.request :json }
46
+ def base_url
47
+ BASE_URL
48
48
  end
49
49
 
50
- def media_connection
51
- @media_connection ||= build_connection { |f| f.request :multipart }
50
+ def adapter_name
51
+ :whatsapp
52
52
  end
53
53
 
54
- def build_connection
55
- Faraday.new(url: BASE_URL) do |f|
56
- yield f
57
- f.response :json
58
- f.adapter :net_http
59
- f.headers["Authorization"] = "Bearer #{@access_token}"
60
- end
61
- end
62
-
63
- def request(method, path, body = nil)
64
- response = connection.public_send(method, path) do |req|
65
- req.body = body if body && method != :get
66
- end
67
-
68
- handle_response(response)
54
+ def configure_auth(faraday)
55
+ faraday.headers["Authorization"] = "Bearer #{@access_token}"
69
56
  end
70
57
 
71
- def handle_response(response)
58
+ def extract_error_message(response)
72
59
  body = response.body
73
- return body.is_a?(Hash) ? body : {} if response.success?
74
-
75
- if response.status == 429
76
- raise ChatSDK::RateLimitedError.new(
77
- "WhatsApp API rate limited",
78
- retry_after: nil,
79
- status: response.status,
80
- body: body,
81
- adapter_name: :whatsapp
82
- )
83
- end
84
-
85
- error_message = body.is_a?(Hash) ? body.dig("error", "message") : response.status
86
- raise ChatSDK::PlatformError.new(
87
- "WhatsApp API error: #{error_message}",
88
- status: response.status,
89
- body: body,
90
- adapter_name: :whatsapp
91
- )
60
+ body.is_a?(Hash) ? body.dig("error", "message") : response.status.to_s
92
61
  end
93
62
  end
94
63
  end
@@ -3,6 +3,8 @@
3
3
  module ChatSDK
4
4
  module WhatsApp
5
5
  class InteractiveRenderer
6
+ include ChatSDK::Cards::TextHelpers
7
+
6
8
  def render(node)
7
9
  case node.type
8
10
  when :card then render_card(node)
@@ -75,26 +77,6 @@ module ChatSDK
75
77
  buttons
76
78
  end
77
79
 
78
- def collect_text_parts(node)
79
- parts = []
80
- node.children.each do |child|
81
- case child.type
82
- when :text
83
- parts << child.attributes[:content]
84
- when :divider
85
- parts << "---"
86
- when :fields
87
- child.children.each do |field|
88
- parts << "#{field.attributes[:label]}: #{field.attributes[:value]}"
89
- end
90
- when :section
91
- parts << child.attributes[:title] if child.attributes[:title]
92
- parts.concat(collect_text_parts(child))
93
- end
94
- end
95
- parts
96
- end
97
-
98
80
  def render_single(node)
99
81
  case node.type
100
82
  when :text
@@ -103,12 +85,6 @@ module ChatSDK
103
85
  {text: node.fallback_text}
104
86
  end
105
87
  end
106
-
107
- def truncate(text, max)
108
- return "" unless text
109
-
110
- (text.length > max) ? "#{text[0..max - 4]}..." : text
111
- end
112
88
  end
113
89
  end
114
90
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chat_sdk-whatsapp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Quentin Rousseau