snapchat_api 0.1.5 → 0.1.7

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: f835d1d5764f58f10ea61e25aa7bec86ba1ff18670ec3e62461968385d3e0c08
4
- data.tar.gz: edc4635f63d1811a567a8e382c395b54fb5bc19d9a3e05344c4ed2a15bcad10b
3
+ metadata.gz: 3d2fddf9efbe9f9729c3684370ed34e34c3eb2e7bcb852c31fd20f8704bce3e4
4
+ data.tar.gz: 5239d2a84ec3bf82425ec3ec6c3dc1a90a0885c65200a72e020cec2e9217a64d
5
5
  SHA512:
6
- metadata.gz: a50dcef0a90a743017da6405e26fbc4f46b551d50e7012aed4ecd7c40efe5eefcd77ee0c31193ade4d8aaab1921d753051589a68891def9a6bbc7c6a986a042d
7
- data.tar.gz: b7d88ee3f394e8d0e869b7a28691fe94a2fe92414147fde541e2a1a100a02bdc6475b2f0d13804c77a34562337542d3b2c80cd337e118a910204c0c79670e82e
6
+ metadata.gz: 358a31a8b86397994b76f6c0fafd80a874a48a589f5482ece61bcd185c3547887cfa039dc9e5ce536b22b2f34813823ded87b0eddd35e4250417b1ab57dfdccc
7
+ data.tar.gz: 42afb3def8554e05bbf827096756db9a86146a2762d56c6e2a9535a81d1871f8d0c24947b812e463dd610bb4ed4b14b1e8ad5bea6006322f1ceda1d694f89532
data/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.1.7](https://github.com/k0va1/snapchat_api/compare/v0.1.6...v0.1.7) (2026-01-13)
4
+
5
+
6
+ ### Features
7
+
8
+ * add new endpoint for filtering ad squads by campaign ([#11](https://github.com/k0va1/snapchat_api/issues/11)) ([06a1aa3](https://github.com/k0va1/snapchat_api/commit/06a1aa389f69e7757760c26bb17d8a80cf588328))
9
+
10
+ ## [0.1.6](https://github.com/k0va1/snapchat_api/compare/v0.1.5...v0.1.6) (2025-12-30)
11
+
12
+
13
+ ### Features
14
+
15
+ * add error handling for API responses with request_status ERROR ([554d4c5](https://github.com/k0va1/snapchat_api/commit/554d4c5f8ec3545f632110875cd436de84faaac2))
16
+ * add error handling for API responses with request_status ERROR ([6ebe619](https://github.com/k0va1/snapchat_api/commit/6ebe6190b4283678dbec9104dee051ccc25bd80f))
17
+
3
18
  ## [0.1.5](https://github.com/k0va1/snapchat_api/compare/v0.1.4...v0.1.5) (2025-08-25)
4
19
 
5
20
 
@@ -135,10 +135,17 @@ module SnapchatApi
135
135
  private
136
136
 
137
137
  def handle_response(response)
138
+ body = response.body
139
+ status = response.status
140
+
141
+ # Check for request-level errors (API returns 200 but request_status is ERROR)
142
+ if response.success? && body.is_a?(Hash)
143
+ check_request_status_error(body, status)
144
+ return response
145
+ end
146
+
138
147
  return response if response.success?
139
148
 
140
- status = response.status
141
- body = response.body
142
149
  error_message = body.is_a?(Hash) ? body&.dig("message") : body
143
150
 
144
151
  klass = case status
@@ -158,5 +165,47 @@ module SnapchatApi
158
165
 
159
166
  raise klass.new(error_message || "HTTP #{status}", status, body)
160
167
  end
168
+
169
+ def check_request_status_error(body, status)
170
+ return unless body["request_status"] == "ERROR"
171
+
172
+ request_id = body["request_id"]
173
+ sub_errors = extract_sub_errors(body)
174
+ error_message = build_error_message(body, sub_errors)
175
+
176
+ raise SnapchatApi::RequestError.new(error_message, status, body, request_id, sub_errors)
177
+ end
178
+
179
+ def extract_sub_errors(body)
180
+ sub_errors = []
181
+
182
+ # Look for sub-request errors in various response keys
183
+ # The API may return errors under different keys depending on the endpoint
184
+ possible_keys = %w[creatives ads campaigns ad_squads media adaccounts]
185
+
186
+ possible_keys.each do |key|
187
+ next unless body[key].is_a?(Array)
188
+
189
+ body[key].each do |item|
190
+ if item.is_a?(Hash) && item["sub_request_status"] == "ERROR"
191
+ sub_errors << {
192
+ reason: item["sub_request_error_reason"],
193
+ status: item["sub_request_status"]
194
+ }
195
+ end
196
+ end
197
+ end
198
+
199
+ sub_errors
200
+ end
201
+
202
+ def build_error_message(body, sub_errors)
203
+ if sub_errors.any?
204
+ messages = sub_errors.map { |e| e[:reason] }.compact
205
+ messages.join("; ")
206
+ else
207
+ body["debug_message"] || body["display_message"] || "Request failed with status ERROR"
208
+ end
209
+ end
161
210
  end
162
211
  end
@@ -2,10 +2,12 @@ module SnapchatApi
2
2
  class Error < StandardError
3
3
  attr_reader :status_code
4
4
  attr_reader :body
5
+ attr_reader :request_id
5
6
 
6
- def initialize(message = nil, status_code = nil, body = nil)
7
+ def initialize(message = nil, status_code = nil, body = nil, request_id = nil)
7
8
  @status_code = status_code
8
9
  @body = body
10
+ @request_id = request_id
9
11
  super(message)
10
12
  end
11
13
  end
@@ -19,4 +21,14 @@ module SnapchatApi
19
21
  class ApiError < Error; end
20
22
 
21
23
  class RateLimitError < Error; end
24
+
25
+ # Raised when API returns HTTP 200 but request_status is ERROR
26
+ class RequestError < Error
27
+ attr_reader :sub_errors
28
+
29
+ def initialize(message = nil, status_code = nil, body = nil, request_id = nil, sub_errors = [])
30
+ @sub_errors = sub_errors
31
+ super(message, status_code, body, request_id)
32
+ end
33
+ end
22
34
  end
@@ -1,20 +1,14 @@
1
+ require "uri"
2
+
1
3
  module SnapchatApi
2
4
  module Resources
3
5
  class AdSquad < Base
4
6
  def list_all(ad_account_id:, params: {})
5
- params[:limit] ||= 50
6
-
7
- ad_squads = []
8
- next_link = "adaccounts/#{ad_account_id}/adsquads?limit=#{params[:limit]}"
9
-
10
- loop do
11
- response = client.request(:get, next_link)
12
- next_link = response.body["paging"]["next_link"]
13
- ad_squads.concat(response.body["adsquads"].map { |el| el["adsquad"] })
14
- break if next_link.nil?
15
- end
7
+ fetch_all_adsquads("adaccounts/#{ad_account_id}/adsquads", params)
8
+ end
16
9
 
17
- ad_squads
10
+ def list_all_by_campaign(campaign_id:, params: {})
11
+ fetch_all_adsquads("campaigns/#{campaign_id}/adsquads", params)
18
12
  end
19
13
 
20
14
  def get(ad_squad_id:)
@@ -49,6 +43,23 @@ module SnapchatApi
49
43
  response = client.request(:get, "adsquads/#{ad_squad_id}/stats", params)
50
44
  response.body
51
45
  end
46
+
47
+ private
48
+
49
+ def fetch_all_adsquads(base_path, params)
50
+ params[:limit] ||= 50
51
+ ad_squads = []
52
+ next_link = "#{base_path}?#{URI.encode_www_form(params)}"
53
+
54
+ loop do
55
+ response = client.request(:get, next_link)
56
+ next_link = response.body["paging"]["next_link"]
57
+ ad_squads.concat(response.body["adsquads"].map { |el| el["adsquad"] })
58
+ break if next_link.nil?
59
+ end
60
+
61
+ ad_squads
62
+ end
52
63
  end
53
64
  end
54
65
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SnapchatApi
4
- VERSION = "0.1.5"
4
+ VERSION = "0.1.7"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: snapchat_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Koval