chat_sdk-whatsapp 1.0.1 → 1.1.0

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: 597bcaeccc068737954a05d9a71894f5b5dcdc5398ef51634658c90461f9aa75
4
- data.tar.gz: 23942bc33cb539a45e9e3519dba9a88eb788c17e886ecb8cdf406d712c887c24
3
+ metadata.gz: 56d2740433f6135cc084664554536e8aada5dadc9784f495e63b744d572bb1b1
4
+ data.tar.gz: 97cae7132efd2af77e10be202134f1430b0142477912745158294c7d297afc22
5
5
  SHA512:
6
- metadata.gz: 8f0c5680bbb226b46b3921e75d581ad613cf170085abd8edc5d0819cf03ca6fd67d1ef613eb9fec96e8620b61e90ee1c9b3dfb6bffc4c1df4e50c5c1ced67d42
7
- data.tar.gz: 2254a8b5bcfc1ce79545e489a6289c82a50ae1b475e6cb5e765b5a24f2535ed3914edf4a55c9dbcd036fa5d9e857ba925ab0c03cc1670114fef9fcd6e449c03f
6
+ metadata.gz: 58f760deb91563a1cd2cec6a32725fbdecf1249ad6116509ac6646321b36d116b0630220553c2b00c6dde71f8eb9583570cc6a02ffe6d9c386c47827091120a2
7
+ data.tar.gz: 4475cb8cec45232adfe4a1090b08960071a8f041753b2e75d15f977791f35894285e2bd728be042aca550913e89fda9a87d9abadd0af0bc8fe1b700b9797173b
@@ -6,7 +6,7 @@ module ChatSDK
6
6
  include ChatSDK::Adapter::MetaVerification
7
7
  include ChatSDK::Adapter::MediaTypes
8
8
 
9
- capabilities :direct_messages, :file_uploads, :reactions
9
+ capabilities :direct_messages, :file_uploads, :reactions, :replies, :read_receipts
10
10
 
11
11
  attr_reader :client
12
12
 
@@ -92,10 +92,17 @@ module ChatSDK
92
92
  @client.send_template(to: channel_id, template_name: template_name, language_code: language_code, components: components)
93
93
  end
94
94
 
95
- def mark_as_read(message_id:)
95
+ def mark_as_read(message_id:, channel_id: nil, thread_id: nil, message: nil) # rubocop:disable Lint/UnusedMethodArgument
96
96
  @client.mark_as_read(message_id: message_id)
97
97
  end
98
98
 
99
+ def reply_message(channel_id:, message_id:, message:, thread_id: nil) # rubocop:disable Lint/UnusedMethodArgument
100
+ payload = prepare_message_payload(message)
101
+ payload[:context] = {message_id: message_id}
102
+ result = @client.send_message(to: channel_id, **payload)
103
+ parse_whatsapp_message(result, channel_id)
104
+ end
105
+
99
106
  def download_media(media_id:)
100
107
  meta = @client.get_media_url(media_id: media_id)
101
108
  url = meta["url"]
@@ -1,9 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "uri"
4
+
3
5
  module ChatSDK
4
6
  module WhatsApp
5
7
  class ApiClient < ChatSDK::ApiClient::Base
6
8
  BASE_URL = "https://graph.facebook.com/v25.0"
9
+ MEDIA_HOSTS = %w[fbcdn.net fbsbx.com].freeze
10
+ MEDIA_DOWNLOAD_LIMIT = 25 * 1024 * 1024
11
+ MEDIA_DOWNLOAD_TIMEOUT = 30
7
12
 
8
13
  def initialize(access_token, phone_number_id)
9
14
  @access_token = access_token
@@ -56,9 +61,12 @@ module ChatSDK
56
61
  end
57
62
 
58
63
  def download_media(url:)
64
+ validate_media_url!(url)
59
65
  Faraday.get(url) do |req|
60
66
  req.headers["Authorization"] = "Bearer #{@access_token}"
67
+ req.options.timeout = MEDIA_DOWNLOAD_TIMEOUT
61
68
  end
69
+ .tap { |response| validate_media_response!(response) }
62
70
  end
63
71
 
64
72
  def upload_media(io:, filename:, content_type:)
@@ -87,6 +95,34 @@ module ChatSDK
87
95
  faraday.headers["Authorization"] = "Bearer #{@access_token}"
88
96
  end
89
97
 
98
+ def validate_media_url!(url)
99
+ uri = URI.parse(url)
100
+ host = uri.host&.downcase
101
+ graph_origin = URI.parse(BASE_URL)
102
+ trusted_host = host == graph_origin.host || MEDIA_HOSTS.any? { |allowed| host == allowed || host&.end_with?(".#{allowed}") }
103
+ trusted = uri.is_a?(URI::HTTPS) && uri.port == 443 && trusted_host
104
+ return if trusted
105
+
106
+ raise ChatSDK::PlatformError.new(
107
+ "Refusing to send the WhatsApp access token to an untrusted media URL",
108
+ adapter_name: :whatsapp
109
+ )
110
+ rescue URI::InvalidURIError
111
+ raise ChatSDK::PlatformError.new("Invalid WhatsApp media URL", adapter_name: :whatsapp)
112
+ end
113
+
114
+ def validate_media_response!(response)
115
+ declared_size = response.headers["content-length"]&.to_i
116
+ actual_size = response.body.respond_to?(:bytesize) ? response.body.bytesize : 0
117
+ return if [declared_size, actual_size].compact.max <= MEDIA_DOWNLOAD_LIMIT
118
+
119
+ raise ChatSDK::PlatformError.new(
120
+ "WhatsApp media exceeds the 25 MB download limit",
121
+ status: response.status,
122
+ adapter_name: :whatsapp
123
+ )
124
+ end
125
+
90
126
  def extract_error_message(response)
91
127
  body = response.body
92
128
  body.is_a?(Hash) ? body.dig("error", "message") : response.status.to_s
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: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Quentin Rousseau