soapy_cake 1.21.0 → 1.22.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 +4 -4
- data/Gemfile +1 -0
- data/Rakefile +1 -0
- data/api.yml +187 -0
- data/lib/soapy_cake.rb +2 -1
- data/lib/soapy_cake/admin.rb +1 -0
- data/lib/soapy_cake/admin_addedit.rb +2 -1
- data/lib/soapy_cake/admin_batched.rb +3 -2
- data/lib/soapy_cake/admin_track.rb +1 -0
- data/lib/soapy_cake/affiliate.rb +1 -0
- data/lib/soapy_cake/client.rb +27 -21
- data/lib/soapy_cake/const.rb +1 -0
- data/lib/soapy_cake/error.rb +1 -0
- data/lib/soapy_cake/helper.rb +5 -5
- data/lib/soapy_cake/request.rb +8 -5
- data/lib/soapy_cake/response.rb +4 -4
- data/lib/soapy_cake/response_value.rb +4 -4
- data/lib/soapy_cake/time_converter.rb +2 -2
- data/lib/soapy_cake/version.rb +1 -1
- data/soapy_cake.gemspec +1 -0
- data/spec/integration/soapy_cake/admin_addedit_spec.rb +30 -14
- data/spec/integration/soapy_cake/admin_spec.rb +1 -0
- data/spec/integration/soapy_cake/admin_track_spec.rb +1 -0
- data/spec/lib/soapy_cake/admin_addedit_spec.rb +3 -1
- data/spec/lib/soapy_cake/admin_batched_spec.rb +1 -0
- data/spec/lib/soapy_cake/admin_spec.rb +1 -0
- data/spec/lib/soapy_cake/admin_track_spec.rb +1 -0
- data/spec/lib/soapy_cake/affiliate_spec.rb +1 -0
- data/spec/lib/soapy_cake/request_spec.rb +1 -0
- data/spec/lib/soapy_cake/response_spec.rb +1 -0
- data/spec/lib/soapy_cake/response_value_spec.rb +1 -0
- data/spec/lib/soapy_cake/time_converter_spec.rb +1 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/support/admin_method_example.rb +1 -0
- metadata +3 -3
- data/api_versions.yml +0 -113
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 56f71b18325d9c37c28fa1eb52a36785b29cbde1
|
|
4
|
+
data.tar.gz: 489dfd14ad0e7fe93571ae955544830dced450c1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ea22778f46a5c0097f0b182c1f84cff5c509694011dabde1c2794f505a713fa5abae06efe7009c479e81fb4e90cfef16962bb2ea181da0f2dbb4df98a60331d2
|
|
7
|
+
data.tar.gz: 0ce89c5f006bc80e3daafd7a46cecba01ced9fef6a61afc33a617dd2d820b68b67be0c7e6990ac35a1e829f078dc04750be186ede15c2fbbbf67a554824d17d8
|
data/Gemfile
CHANGED
data/Rakefile
CHANGED
data/api.yml
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
---
|
|
2
|
+
versions:
|
|
3
|
+
admin:
|
|
4
|
+
accounting:
|
|
5
|
+
mark_affiliate_bill_as_received: 1
|
|
6
|
+
export_advertiser_bills: 1
|
|
7
|
+
export_affiliate_bills: 1
|
|
8
|
+
mark_affiliate_bill_as_paid: 1
|
|
9
|
+
add:
|
|
10
|
+
advertiser_credit: 1
|
|
11
|
+
creative: 1
|
|
12
|
+
manual_credit: 1
|
|
13
|
+
addedit:
|
|
14
|
+
advertiser: 1
|
|
15
|
+
advertiser_credit_limit: 1
|
|
16
|
+
affiliate: 2
|
|
17
|
+
apply_suppression_list_to_offer: 1
|
|
18
|
+
blacklist: 1
|
|
19
|
+
campaign: 3
|
|
20
|
+
caps: 1
|
|
21
|
+
contact: 2
|
|
22
|
+
creative: 1
|
|
23
|
+
creative_files: 1
|
|
24
|
+
exchange_rates: 1
|
|
25
|
+
geo_targets: 2
|
|
26
|
+
offer: 5
|
|
27
|
+
offer_contract: 1
|
|
28
|
+
offer_tiers: 1
|
|
29
|
+
remove_blacklist: 1
|
|
30
|
+
suppresion_list: 1
|
|
31
|
+
vertical: 1
|
|
32
|
+
auth:
|
|
33
|
+
login: 2
|
|
34
|
+
doc:
|
|
35
|
+
posting_doc: 1
|
|
36
|
+
edit:
|
|
37
|
+
buyer: 1
|
|
38
|
+
export:
|
|
39
|
+
advertisers: 5
|
|
40
|
+
affiliate_referrals: 1
|
|
41
|
+
affiliates: 5
|
|
42
|
+
blacklists: 1
|
|
43
|
+
buyer_contracts: 1
|
|
44
|
+
buyers: 1
|
|
45
|
+
campaigns: 6
|
|
46
|
+
creatives: 3
|
|
47
|
+
offers: 5
|
|
48
|
+
rules_targets: 3
|
|
49
|
+
schedules: 1
|
|
50
|
+
get:
|
|
51
|
+
account_statuses: 1
|
|
52
|
+
advertisers: 1
|
|
53
|
+
affiliate_tags: 1
|
|
54
|
+
affiliate_tiers: 1
|
|
55
|
+
billing_cycles: 1
|
|
56
|
+
blacklist_reasons: 1
|
|
57
|
+
cap_intervals: 1
|
|
58
|
+
cap_types: 1
|
|
59
|
+
countries: 1
|
|
60
|
+
currencies: 1
|
|
61
|
+
departments: 1
|
|
62
|
+
exchange_rates: 1
|
|
63
|
+
get_api_key: 1
|
|
64
|
+
inactive_reasons: 1
|
|
65
|
+
languages: 1
|
|
66
|
+
offer_statuses: 1
|
|
67
|
+
offer_types: 1
|
|
68
|
+
payment_settings: 1
|
|
69
|
+
payment_types: 1
|
|
70
|
+
price_formats: 1
|
|
71
|
+
roles: 1
|
|
72
|
+
tracking_domains: 1
|
|
73
|
+
verticals: 2
|
|
74
|
+
reports:
|
|
75
|
+
advertiser_summary: 2
|
|
76
|
+
affiliate_summary: 2
|
|
77
|
+
campaign_summary: 2
|
|
78
|
+
creative_summary: 2
|
|
79
|
+
caps: 4
|
|
80
|
+
clicks: 7
|
|
81
|
+
conversion_changes: 10
|
|
82
|
+
conversions: 11
|
|
83
|
+
daily_summary_export: 1
|
|
84
|
+
leads_by_affiliate_export: 1
|
|
85
|
+
leads_by_buyer: 4
|
|
86
|
+
login_export: 1
|
|
87
|
+
offer_summary: 2
|
|
88
|
+
traffic_export: 1
|
|
89
|
+
signup:
|
|
90
|
+
advertiser: 1
|
|
91
|
+
affiliate: 4
|
|
92
|
+
get_media_types: 1
|
|
93
|
+
get_price_formats: 1
|
|
94
|
+
get_traffic_types: 1
|
|
95
|
+
get_vertical_categories: 1
|
|
96
|
+
track:
|
|
97
|
+
accepted_dispositions: 1
|
|
98
|
+
conversion_dispositions: 2
|
|
99
|
+
decrypt_affiliate_link: 1
|
|
100
|
+
mass_conversion_adjustment: 2
|
|
101
|
+
# Version 2 returns an error about an invalid action, so using version 1
|
|
102
|
+
mass_conversion_insert: 1
|
|
103
|
+
rejected_dispositions: 1
|
|
104
|
+
update_conversion: 4
|
|
105
|
+
update_conversion_disposition: 2
|
|
106
|
+
update_conversion_price: 2
|
|
107
|
+
update_conversion_revenue: 1
|
|
108
|
+
update_lead_price: 2
|
|
109
|
+
update_sale_revenue: 1
|
|
110
|
+
affiliate:
|
|
111
|
+
reports:
|
|
112
|
+
bills: 3
|
|
113
|
+
offers:
|
|
114
|
+
offer_feed: 4
|
|
115
|
+
|
|
116
|
+
# Whitelist of read-only actions (don't modify CAKE data).
|
|
117
|
+
read_only:
|
|
118
|
+
admin:
|
|
119
|
+
accounting:
|
|
120
|
+
- export_advertiser_bills
|
|
121
|
+
- export_affiliate_bills
|
|
122
|
+
export:
|
|
123
|
+
- advertisers
|
|
124
|
+
- affiliate_referrals
|
|
125
|
+
- affiliates
|
|
126
|
+
- blacklists
|
|
127
|
+
- buyer_contracts
|
|
128
|
+
- buyers
|
|
129
|
+
- campaigns
|
|
130
|
+
- creatives
|
|
131
|
+
- offers
|
|
132
|
+
- rules_targets
|
|
133
|
+
- schedules
|
|
134
|
+
get:
|
|
135
|
+
- account_statuses
|
|
136
|
+
- advertisers
|
|
137
|
+
- affiliate_tags
|
|
138
|
+
- affiliate_tiers
|
|
139
|
+
- billing_cycles
|
|
140
|
+
- blacklist_reasons
|
|
141
|
+
- cap_intervals
|
|
142
|
+
- cap_types
|
|
143
|
+
- countries
|
|
144
|
+
- currencies
|
|
145
|
+
- departments
|
|
146
|
+
- exchange_rates
|
|
147
|
+
- get_api_key
|
|
148
|
+
- inactive_reasons
|
|
149
|
+
- languages
|
|
150
|
+
- offer_statuses
|
|
151
|
+
- offer_types
|
|
152
|
+
- payment_settings
|
|
153
|
+
- payment_types
|
|
154
|
+
- price_formats
|
|
155
|
+
- roles
|
|
156
|
+
- tracking_domains
|
|
157
|
+
- verticals
|
|
158
|
+
reports:
|
|
159
|
+
- advertiser_summary
|
|
160
|
+
- affiliate_summary
|
|
161
|
+
- campaign_summary
|
|
162
|
+
- creative_summary
|
|
163
|
+
- caps
|
|
164
|
+
- clicks
|
|
165
|
+
- conversion_changes
|
|
166
|
+
- conversions
|
|
167
|
+
- daily_summary_export
|
|
168
|
+
- leads_by_affiliate_export
|
|
169
|
+
- leads_by_buyer
|
|
170
|
+
- login_export
|
|
171
|
+
- offer_summary
|
|
172
|
+
- traffic_export
|
|
173
|
+
signup:
|
|
174
|
+
- get_media_types
|
|
175
|
+
- get_price_formats
|
|
176
|
+
- get_traffic_types
|
|
177
|
+
- get_vertical_categories
|
|
178
|
+
track:
|
|
179
|
+
- accepted_dispositions
|
|
180
|
+
- conversion_dispositions
|
|
181
|
+
- decrypt_affiliate_link
|
|
182
|
+
- rejected_dispositions
|
|
183
|
+
affiliate:
|
|
184
|
+
reports:
|
|
185
|
+
- bills
|
|
186
|
+
offers:
|
|
187
|
+
- offer_feed
|
data/lib/soapy_cake.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'logger'
|
|
2
3
|
require 'nokogiri'
|
|
3
4
|
require 'saxerator'
|
|
@@ -23,6 +24,6 @@ require 'soapy_cake/admin_track'
|
|
|
23
24
|
require 'soapy_cake/affiliate'
|
|
24
25
|
|
|
25
26
|
module SoapyCake
|
|
26
|
-
|
|
27
|
+
API_CONFIG = YAML.load(File.read(File.expand_path('../../api.yml', __FILE__)))
|
|
27
28
|
NET_TIMEOUT = 600
|
|
28
29
|
end
|
data/lib/soapy_cake/admin.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module SoapyCake
|
|
2
3
|
# rubocop:disable Metrics/ClassLength
|
|
3
4
|
class AdminAddedit < Client
|
|
@@ -114,7 +115,7 @@ module SoapyCake
|
|
|
114
115
|
opts = opts.dup
|
|
115
116
|
redirects = opts.delete(:redirects)
|
|
116
117
|
unless redirects.is_a?(Hash) && redirects.keys.count > 0
|
|
117
|
-
|
|
118
|
+
raise Error, "Parameter 'redirects' must be a COUNTRY=>REDIRECT_OFFER_CONTRACT_ID hash!"
|
|
118
119
|
end
|
|
119
120
|
|
|
120
121
|
opts[:countries] = redirects.keys.join(',')
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module SoapyCake
|
|
2
3
|
class AdminBatched
|
|
3
4
|
ALLOWED_METHODS = %i(
|
|
@@ -20,7 +21,7 @@ module SoapyCake
|
|
|
20
21
|
|
|
21
22
|
def initialize(admin, method, opts, limit)
|
|
22
23
|
if opts.key?(:row_limit) || opts.key?(:start_at_row)
|
|
23
|
-
|
|
24
|
+
raise Error, 'Cannot set row_limit/start_at_row in batched mode!'
|
|
24
25
|
end
|
|
25
26
|
|
|
26
27
|
@admin = admin
|
|
@@ -60,7 +61,7 @@ module SoapyCake
|
|
|
60
61
|
end
|
|
61
62
|
|
|
62
63
|
def method_missing(name, method_opts = {}, limit = nil)
|
|
63
|
-
|
|
64
|
+
raise Error, "Invalid method #{name}" unless ALLOWED_METHODS.include?(name)
|
|
64
65
|
|
|
65
66
|
BatchedRequest.new(admin, name, method_opts, limit).to_enum
|
|
66
67
|
end
|
data/lib/soapy_cake/affiliate.rb
CHANGED
data/lib/soapy_cake/client.rb
CHANGED
|
@@ -1,18 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module SoapyCake
|
|
2
3
|
class Client
|
|
3
4
|
HEADERS = { 'Content-Type' => 'application/soap+xml;charset=UTF-8' }.freeze
|
|
4
5
|
|
|
5
6
|
def initialize(opts = {})
|
|
6
|
-
@domain = opts.fetch(:domain, ENV['CAKE_DOMAIN']) || fail(Error, 'Cake domain missing')
|
|
7
|
-
@api_key = opts.fetch(:api_key, ENV['CAKE_API_KEY']) || fail(Error, 'Cake API key missing')
|
|
8
|
-
@retry_count = opts.fetch(:retry_count, ENV['CAKE_RETRY_COUNT']) || 4
|
|
9
|
-
|
|
10
|
-
@time_converter = TimeConverter.new(
|
|
11
|
-
opts.fetch(:time_zone, ENV['CAKE_TIME_ZONE']),
|
|
12
|
-
opts.fetch(:time_offset, ENV['CAKE_TIME_OFFSET'])
|
|
13
|
-
)
|
|
14
|
-
|
|
15
7
|
@opts = opts
|
|
8
|
+
@domain = fetch_opt(:domain) || raise(Error, 'Cake domain missing')
|
|
9
|
+
@api_key = fetch_opt(:api_key) || raise(Error, 'Cake API key missing')
|
|
10
|
+
@retry_count = fetch_opt(:retry_count, 4)
|
|
11
|
+
@write_enabled = ['yes', true].include?(fetch_opt(:write_enabled))
|
|
12
|
+
@time_converter = TimeConverter.new(fetch_opt(:time_zone), fetch_opt(:time_offset))
|
|
16
13
|
end
|
|
17
14
|
|
|
18
15
|
def xml_response?
|
|
@@ -21,17 +18,14 @@ module SoapyCake
|
|
|
21
18
|
|
|
22
19
|
protected
|
|
23
20
|
|
|
24
|
-
attr_reader :domain, :api_key, :time_converter, :opts, :logger, :retry_count
|
|
21
|
+
attr_reader :domain, :api_key, :time_converter, :opts, :logger, :retry_count, :write_enabled
|
|
25
22
|
|
|
26
23
|
def run(request)
|
|
24
|
+
check_write_enabled!(request)
|
|
27
25
|
request.api_key = api_key
|
|
28
26
|
request.time_converter = time_converter
|
|
29
27
|
|
|
30
|
-
|
|
31
|
-
tries: retry_count + 1,
|
|
32
|
-
on: [RateLimitError, SocketError],
|
|
33
|
-
sleep: -> (n) { 3**n }
|
|
34
|
-
) do
|
|
28
|
+
with_retries do
|
|
35
29
|
response = Response.new(response_body(request), request.short_response?, time_converter)
|
|
36
30
|
xml_response? ? response.to_xml : response.to_enum
|
|
37
31
|
end
|
|
@@ -39,6 +33,21 @@ module SoapyCake
|
|
|
39
33
|
|
|
40
34
|
private
|
|
41
35
|
|
|
36
|
+
def fetch_opt(key, fallback = nil)
|
|
37
|
+
opts.fetch(key, ENV.fetch("CAKE_#{key.to_s.upcase}", fallback))
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def check_write_enabled!(request)
|
|
41
|
+
unless request.read_only? || write_enabled
|
|
42
|
+
raise Error, 'Writes not enabled (pass write_enabled: true or set CAKE_WRITE_ENABLED=yes)'
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def with_retries(&block)
|
|
47
|
+
opts = { tries: retry_count + 1, on: [RateLimitError, SocketError], sleep: -> (n) { 3**n } }
|
|
48
|
+
Retryable.retryable(opts, &block)
|
|
49
|
+
end
|
|
50
|
+
|
|
42
51
|
def logger
|
|
43
52
|
@logger ||= opts[:logger] || (defined?(::Rails) && ::Rails.logger)
|
|
44
53
|
end
|
|
@@ -51,12 +60,9 @@ module SoapyCake
|
|
|
51
60
|
logger.info("soapy_cake:request #{request}") if logger
|
|
52
61
|
|
|
53
62
|
url = "https://#{domain}#{request.path}"
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
"#{http_response.body}" unless http_response.success?
|
|
58
|
-
|
|
59
|
-
http_response
|
|
63
|
+
HTTParty.post(url, headers: HEADERS, body: request.xml, timeout: NET_TIMEOUT).tap do |res|
|
|
64
|
+
raise RequestFailed, "Request failed with HTTP #{res.code}: #{res.body}" unless res.success?
|
|
65
|
+
end
|
|
60
66
|
end
|
|
61
67
|
end
|
|
62
68
|
end
|
data/lib/soapy_cake/const.rb
CHANGED
data/lib/soapy_cake/error.rb
CHANGED
data/lib/soapy_cake/helper.rb
CHANGED
|
@@ -15,20 +15,20 @@ module SoapyCake
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def validate_id(opts, key)
|
|
18
|
-
|
|
18
|
+
raise Error, "Parameter '#{key}' must be > 0!" if opts[key].to_i < 1
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def require_params(opts, params)
|
|
22
22
|
params.each do |param|
|
|
23
|
-
|
|
23
|
+
raise Error, "Parameter '#{param}' missing!" unless opts.key?(param)
|
|
24
24
|
end
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
def translate_booleans(opts)
|
|
28
28
|
opts.transform_values do |v|
|
|
29
29
|
case v
|
|
30
|
-
when true then 'on'
|
|
31
|
-
when false then 'off'
|
|
30
|
+
when true then 'on'
|
|
31
|
+
when false then 'off'
|
|
32
32
|
else v
|
|
33
33
|
end
|
|
34
34
|
end
|
|
@@ -45,7 +45,7 @@ module SoapyCake
|
|
|
45
45
|
|
|
46
46
|
def const_lookup(type, key)
|
|
47
47
|
Const::CONSTS[type].fetch(key) do
|
|
48
|
-
|
|
48
|
+
raise ArgumentError, "#{key} is not a valid value for #{type}"
|
|
49
49
|
end
|
|
50
50
|
end
|
|
51
51
|
|
data/lib/soapy_cake/request.rb
CHANGED
|
@@ -38,6 +38,10 @@ module SoapyCake
|
|
|
38
38
|
"#{role}:#{service}:#{method}:#{version} #{opts.to_json}"
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
+
def read_only?
|
|
42
|
+
(API_CONFIG.dig('read_only', role, service) || []).include?(method)
|
|
43
|
+
end
|
|
44
|
+
|
|
41
45
|
private
|
|
42
46
|
|
|
43
47
|
def api_path
|
|
@@ -61,17 +65,16 @@ module SoapyCake
|
|
|
61
65
|
def format_param(key, value)
|
|
62
66
|
return time_converter.to_cake(value) if DATE_CLASSES.include?(value.class)
|
|
63
67
|
|
|
64
|
-
if key.to_s.end_with?('_date'
|
|
65
|
-
|
|
68
|
+
if key.to_s.end_with?('_date')
|
|
69
|
+
raise Error, "You need to use a Time/DateTime/Date object for '#{key}'"
|
|
66
70
|
end
|
|
67
71
|
|
|
68
72
|
value
|
|
69
73
|
end
|
|
70
74
|
|
|
71
75
|
def version
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
raise(Error, "Unknown API call #{role}::#{service}::#{method}")
|
|
76
|
+
API_CONFIG.dig('versions', role, service, method) ||
|
|
77
|
+
raise(Error, "Unknown API call #{role}::#{service}::#{method}")
|
|
75
78
|
end
|
|
76
79
|
end
|
|
77
80
|
end
|
data/lib/soapy_cake/response.rb
CHANGED
|
@@ -63,13 +63,13 @@ module SoapyCake
|
|
|
63
63
|
|
|
64
64
|
def error_check_fault!
|
|
65
65
|
fault = sax.for_tag(:fault).first
|
|
66
|
-
|
|
66
|
+
raise RequestFailed, fault[:reason][:text] if fault
|
|
67
67
|
end
|
|
68
68
|
|
|
69
69
|
def error_check_success!
|
|
70
|
-
return if sax.for_tag(:success).first == 'true'
|
|
71
|
-
|
|
72
|
-
|
|
70
|
+
return if sax.for_tag(:success).first == 'true'
|
|
71
|
+
raise RateLimitError if error_message == 'Restricted'
|
|
72
|
+
raise RequestFailed, error_message
|
|
73
73
|
end
|
|
74
74
|
|
|
75
75
|
def error_check_special_case?
|
|
@@ -27,11 +27,11 @@ module SoapyCake
|
|
|
27
27
|
attr_reader :time_converter
|
|
28
28
|
|
|
29
29
|
def false?
|
|
30
|
-
value == 'false'
|
|
30
|
+
value == 'false'
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
def true?
|
|
34
|
-
value == 'true'
|
|
34
|
+
value == 'true'
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
def date?
|
|
@@ -39,7 +39,7 @@ module SoapyCake
|
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
def id?
|
|
42
|
-
key.end_with?('_id'
|
|
42
|
+
key.end_with?('_id')
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
def string_id?
|
|
@@ -52,7 +52,7 @@ module SoapyCake
|
|
|
52
52
|
|
|
53
53
|
def parse_int
|
|
54
54
|
unless value.nil? || numeric?
|
|
55
|
-
|
|
55
|
+
raise Error, "'#{key}' contains non-digit chars but was to be parsed as an integer id"
|
|
56
56
|
end
|
|
57
57
|
value.to_i
|
|
58
58
|
end
|
|
@@ -9,13 +9,13 @@ module SoapyCake
|
|
|
9
9
|
time_zone = format('Etc/GMT%+d', -time_offset.to_i)
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
raise Error, 'Cake time zone missing' if time_zone.blank?
|
|
13
13
|
@zone = ActiveSupport::TimeZone[time_zone]
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def to_cake(date)
|
|
17
17
|
date = date.to_datetime if date.is_a?(Date)
|
|
18
|
-
date.in_time_zone(zone).strftime('%Y-%m-%dT%H:%M:%S'
|
|
18
|
+
date.in_time_zone(zone).strftime('%Y-%m-%dT%H:%M:%S')
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def from_cake(value)
|
data/lib/soapy_cake/version.rb
CHANGED
data/soapy_cake.gemspec
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
RSpec.describe SoapyCake::AdminAddedit do
|
|
2
3
|
around { |example| Timecop.freeze(Time.utc(2015, 2, 17, 12), &example) }
|
|
3
4
|
|
|
@@ -37,6 +38,21 @@ RSpec.describe SoapyCake::AdminAddedit do
|
|
|
37
38
|
end
|
|
38
39
|
|
|
39
40
|
describe 'offers' do
|
|
41
|
+
let(:update_params) do
|
|
42
|
+
{
|
|
43
|
+
offer_id: offer_id,
|
|
44
|
+
advertiser_id: advertiser_id,
|
|
45
|
+
vertical_id: vertical_id,
|
|
46
|
+
postback_url_ms_delay: 50,
|
|
47
|
+
offer_contract_hidden: false,
|
|
48
|
+
price_format_id: :cpa,
|
|
49
|
+
received: 2.0,
|
|
50
|
+
received_percentage: false,
|
|
51
|
+
payout: 1.5,
|
|
52
|
+
tags: ''
|
|
53
|
+
}
|
|
54
|
+
end
|
|
55
|
+
|
|
40
56
|
it 'creates an offer', :vcr do
|
|
41
57
|
result = subject.add_offer(
|
|
42
58
|
hidden: false,
|
|
@@ -86,20 +102,7 @@ RSpec.describe SoapyCake::AdminAddedit do
|
|
|
86
102
|
end
|
|
87
103
|
|
|
88
104
|
it 'updates an offer', :vcr do
|
|
89
|
-
result = subject.edit_offer(
|
|
90
|
-
offer_id: offer_id,
|
|
91
|
-
|
|
92
|
-
advertiser_id: advertiser_id,
|
|
93
|
-
vertical_id: vertical_id,
|
|
94
|
-
postback_url_ms_delay: 50,
|
|
95
|
-
offer_contract_hidden: false,
|
|
96
|
-
price_format_id: :cpa,
|
|
97
|
-
received: 2.0,
|
|
98
|
-
received_percentage: false,
|
|
99
|
-
payout: 1.5,
|
|
100
|
-
tags: ''
|
|
101
|
-
)
|
|
102
|
-
|
|
105
|
+
result = subject.edit_offer(update_params)
|
|
103
106
|
expect(result).to include(offer_id: offer_id)
|
|
104
107
|
end
|
|
105
108
|
|
|
@@ -115,6 +118,19 @@ RSpec.describe SoapyCake::AdminAddedit do
|
|
|
115
118
|
subject.edit_offer(offer_id: -1)
|
|
116
119
|
end.to raise_error(SoapyCake::Error, "Parameter 'offer_id' must be > 0!")
|
|
117
120
|
end
|
|
121
|
+
|
|
122
|
+
context 'when writes not enabled' do
|
|
123
|
+
before do
|
|
124
|
+
allow(ENV).to receive(:fetch).and_call_original
|
|
125
|
+
allow(ENV).to receive(:fetch).with('CAKE_WRITE_ENABLED', nil).and_return('no')
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it 'fails with error' do
|
|
129
|
+
expect do
|
|
130
|
+
subject.edit_offer(update_params)
|
|
131
|
+
end.to raise_error(SoapyCake::Error, /Writes not enabled/)
|
|
132
|
+
end
|
|
133
|
+
end
|
|
118
134
|
end
|
|
119
135
|
end
|
|
120
136
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
RSpec.describe SoapyCake::AdminAddedit do
|
|
2
3
|
before do
|
|
3
|
-
allow_any_instance_of(SoapyCake::Client)
|
|
4
|
+
allow_any_instance_of(SoapyCake::Client) # rubocop:disable RSpec/AnyInstance
|
|
5
|
+
.to receive(:run).and_return({})
|
|
4
6
|
end
|
|
5
7
|
|
|
6
8
|
describe '#edit_offer' do
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
if ENV['CODECLIMATE_REPO_TOKEN']
|
|
2
3
|
require 'codeclimate-test-reporter'
|
|
3
4
|
CodeClimate::TestReporter.start
|
|
@@ -42,6 +43,7 @@ end
|
|
|
42
43
|
ENV['CAKE_API_KEY'] = 'cake-api-key' if ENV['CAKE_API_KEY'].blank?
|
|
43
44
|
ENV['CAKE_DOMAIN'] = 'cake-partner-domain.com' if ENV['CAKE_DOMAIN'].blank?
|
|
44
45
|
ENV['CAKE_TIME_ZONE'] = 'Europe/Berlin' if ENV['CAKE_TIME_ZONE'].blank?
|
|
46
|
+
ENV['CAKE_WRITE_ENABLED'] = 'yes' if ENV['CAKE_WRITE_ENABLED'].blank?
|
|
45
47
|
|
|
46
48
|
VCR.configure do |c|
|
|
47
49
|
c.configure_rspec_metadata!
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: soapy_cake
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.22.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- ad2games GmbH
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2016-
|
|
11
|
+
date: 2016-02-18 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport
|
|
@@ -192,7 +192,7 @@ files:
|
|
|
192
192
|
- LICENSE.txt
|
|
193
193
|
- README.md
|
|
194
194
|
- Rakefile
|
|
195
|
-
-
|
|
195
|
+
- api.yml
|
|
196
196
|
- circle.yml
|
|
197
197
|
- lib/soapy_cake.rb
|
|
198
198
|
- lib/soapy_cake/admin.rb
|
data/api_versions.yml
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
admin:
|
|
3
|
-
accounting:
|
|
4
|
-
mark_affiliate_bill_as_received: 1
|
|
5
|
-
export_advertiser_bills: 1
|
|
6
|
-
export_affiliate_bills: 1
|
|
7
|
-
mark_affiliate_bill_as_paid: 1
|
|
8
|
-
add:
|
|
9
|
-
advertiser_credit: 1
|
|
10
|
-
creative: 1
|
|
11
|
-
manual_credit: 1
|
|
12
|
-
addedit:
|
|
13
|
-
advertiser: 1
|
|
14
|
-
advertiser_credit_limit: 1
|
|
15
|
-
affiliate: 2
|
|
16
|
-
apply_suppression_list_to_offer: 1
|
|
17
|
-
blacklist: 1
|
|
18
|
-
campaign: 3
|
|
19
|
-
caps: 1
|
|
20
|
-
contact: 2
|
|
21
|
-
creative: 1
|
|
22
|
-
creative_files: 1
|
|
23
|
-
exchange_rates: 1
|
|
24
|
-
geo_targets: 2
|
|
25
|
-
offer: 5
|
|
26
|
-
offer_contract: 1
|
|
27
|
-
offer_tiers: 1
|
|
28
|
-
remove_blacklist: 1
|
|
29
|
-
suppresion_list: 1
|
|
30
|
-
vertical: 1
|
|
31
|
-
auth:
|
|
32
|
-
login: 2
|
|
33
|
-
doc:
|
|
34
|
-
posting_doc: 1
|
|
35
|
-
edit:
|
|
36
|
-
buyer: 1
|
|
37
|
-
export:
|
|
38
|
-
advertisers: 5
|
|
39
|
-
affiliate_referrals: 1
|
|
40
|
-
affiliates: 5
|
|
41
|
-
blacklists: 1
|
|
42
|
-
buyer_contracts: 1
|
|
43
|
-
buyers: 1
|
|
44
|
-
campaigns: 6
|
|
45
|
-
creatives: 3
|
|
46
|
-
offers: 5
|
|
47
|
-
rules_targets: 3
|
|
48
|
-
schedules: 1
|
|
49
|
-
get:
|
|
50
|
-
account_statuses: 1
|
|
51
|
-
advertisers: 1
|
|
52
|
-
affiliate_tags: 1
|
|
53
|
-
affiliate_tiers: 1
|
|
54
|
-
billing_cycles: 1
|
|
55
|
-
blacklist_reasons: 1
|
|
56
|
-
cap_intervals: 1
|
|
57
|
-
cap_types: 1
|
|
58
|
-
countries: 1
|
|
59
|
-
currencies: 1
|
|
60
|
-
departments: 1
|
|
61
|
-
exchange_rates: 1
|
|
62
|
-
get_api_key: 1
|
|
63
|
-
inactive_reasons: 1
|
|
64
|
-
languages: 1
|
|
65
|
-
offer_statuses: 1
|
|
66
|
-
offer_types: 1
|
|
67
|
-
payment_settings: 1
|
|
68
|
-
payment_types: 1
|
|
69
|
-
price_formats: 1
|
|
70
|
-
roles: 1
|
|
71
|
-
tracking_domains: 1
|
|
72
|
-
verticals: 2
|
|
73
|
-
reports:
|
|
74
|
-
advertiser_summary: 2
|
|
75
|
-
affiliate_summary: 2
|
|
76
|
-
campaign_summary: 2
|
|
77
|
-
creative_summary: 2
|
|
78
|
-
caps: 4
|
|
79
|
-
clicks: 7
|
|
80
|
-
conversion_changes: 10
|
|
81
|
-
conversions: 11
|
|
82
|
-
daily_summary_export: 1
|
|
83
|
-
leads_by_affiliate_export: 1
|
|
84
|
-
leads_by_buyer: 4
|
|
85
|
-
login_export: 1
|
|
86
|
-
offer_summary: 2
|
|
87
|
-
traffic_export: 1
|
|
88
|
-
signup:
|
|
89
|
-
advertiser: 1
|
|
90
|
-
affiliate: 4
|
|
91
|
-
get_media_types: 1
|
|
92
|
-
get_price_formats: 1
|
|
93
|
-
get_traffic_types: 1
|
|
94
|
-
get_vertical_categories: 1
|
|
95
|
-
track:
|
|
96
|
-
accepted_dispositions: 1
|
|
97
|
-
conversion_dispositions: 2
|
|
98
|
-
decrypt_affiliate_link: 1
|
|
99
|
-
mass_conversion_adjustment: 2
|
|
100
|
-
# Version 2 returns an error about an invalid action, so using version 1
|
|
101
|
-
mass_conversion_insert: 1
|
|
102
|
-
rejected_dispositions: 1
|
|
103
|
-
update_conversion: 4
|
|
104
|
-
update_conversion_disposition: 2
|
|
105
|
-
update_conversion_price: 2
|
|
106
|
-
update_conversion_revenue: 1
|
|
107
|
-
update_lead_price: 2
|
|
108
|
-
update_sale_revenue: 1
|
|
109
|
-
affiliate:
|
|
110
|
-
reports:
|
|
111
|
-
bills: 3
|
|
112
|
-
offers:
|
|
113
|
-
offer_feed: 4
|