posthubify 0.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 +7 -0
- data/README.md +76 -0
- data/lib/posthubify/client.rb +138 -0
- data/lib/posthubify/errors.rb +21 -0
- data/lib/posthubify/http.rb +102 -0
- data/lib/posthubify/resources/accounts.rb +185 -0
- data/lib/posthubify/resources/ads.rb +226 -0
- data/lib/posthubify/resources/analytics.rb +170 -0
- data/lib/posthubify/resources/messaging.rb +882 -0
- data/lib/posthubify/resources/platform.rb +227 -0
- data/lib/posthubify/resources/posts.rb +102 -0
- data/lib/posthubify/resources/telecom.rb +86 -0
- data/lib/posthubify/version.rb +5 -0
- data/lib/posthubify.rb +16 -0
- metadata +57 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Posthubify
|
|
4
|
+
# Ads lifecycle (Node sdk .ads): accounts, campaigns, audiences,
|
|
5
|
+
# lead-gen, conversions (CAPI), targeting, ad-set/ad hierarchy, comments, catalogs.
|
|
6
|
+
class AdsResource
|
|
7
|
+
def initialize(http)
|
|
8
|
+
@http = http
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Connected ad accounts.
|
|
12
|
+
def accounts
|
|
13
|
+
@http.data('GET', '/ads/accounts')
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# ── Headless ADS OAuth connect (D8 cp4) — tempToken start/status. ──
|
|
17
|
+
# Start headless ADS OAuth → {tempToken, authUrl}: open authUrl in a browser, then poll status.
|
|
18
|
+
def connect_oauth_start(platform, profile_id: nil, label: nil)
|
|
19
|
+
@http.data('POST', '/ads/connect/oauth/start', body: { 'platform' => platform, 'profileId' => profile_id, 'label' => label })
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Headless ADS OAuth status (poll): pending | connected (+account) | error.
|
|
23
|
+
def connect_oauth_status(temp_token)
|
|
24
|
+
@http.data('GET', '/ads/connect/oauth/status', query: { 'tempToken' => temp_token })
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# This ad account's platform capabilities (pre-discovery instead of trial-and-error).
|
|
28
|
+
def capabilities(id)
|
|
29
|
+
@http.data('GET', "/ads/accounts/#{id}/capabilities")
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Platform-side ad accounts (one login → multiple accounts; for select).
|
|
33
|
+
def customers(id)
|
|
34
|
+
@http.data('GET', "/ads/accounts/#{id}/customers")
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Select the active ad account for this login.
|
|
38
|
+
def select(id, ad_account_id)
|
|
39
|
+
@http.data('POST', "/ads/accounts/#{id}/select", body: { 'adAccountId' => ad_account_id })
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Billing/publishing readiness — check before promote.
|
|
43
|
+
def readiness(id)
|
|
44
|
+
@http.data('GET', "/ads/accounts/#{id}/readiness")
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# List campaigns (optional status filter).
|
|
48
|
+
def campaigns(id, status: nil)
|
|
49
|
+
@http.data('GET', "/ads/accounts/#{id}/campaigns", query: { 'status' => status })
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Create a campaign. input is a camelCase-keyed Hash (name/budget/budgetType/objective/status).
|
|
53
|
+
def create_campaign(id, input, idempotency_key: nil)
|
|
54
|
+
@http.data('POST', "/ads/accounts/#{id}/campaigns", body: input, idempotency_key: idempotency_key)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Single campaign status (enabled/paused).
|
|
58
|
+
def set_campaign_status(id, campaign_id, status)
|
|
59
|
+
@http.data('POST', "/ads/accounts/#{id}/campaigns/#{campaign_id}/status", body: { 'status' => status })
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Bulk status (≤50 campaigns) — returns a per-campaign ok/error result.
|
|
63
|
+
def bulk_campaign_status(id, campaign_ids, status)
|
|
64
|
+
@http.data('POST', "/ads/accounts/#{id}/campaigns/bulk-status", body: { 'campaignIds' => campaign_ids, 'status' => status })
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Duplicate a campaign — the copy starts PAUSED (to avoid accidental spend).
|
|
68
|
+
def duplicate_campaign(id, campaign_id, name = nil)
|
|
69
|
+
body = name ? { 'name' => name } : {}
|
|
70
|
+
@http.data('POST', "/ads/accounts/#{id}/campaigns/#{campaign_id}/duplicate", body: body)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Delete a campaign.
|
|
74
|
+
def delete_campaign(id, campaign_id)
|
|
75
|
+
@http.data('DELETE', "/ads/accounts/#{id}/campaigns/#{campaign_id}")
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Campaign's daily performance timeline (from report rows).
|
|
79
|
+
def campaign_timeline(id, campaign_id, since: nil, until_: nil)
|
|
80
|
+
@http.data('GET', "/ads/accounts/#{id}/campaigns/#{campaign_id}/timeline", query: { 'since' => since, 'until' => until_ })
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Account report rows (optional date range).
|
|
84
|
+
def report(id, since: nil, until_: nil)
|
|
85
|
+
@http.data('GET', "/ads/accounts/#{id}/report", query: { 'since' => since, 'until' => until_ })
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Creative targets (pages/boards).
|
|
89
|
+
def creative_targets(id)
|
|
90
|
+
@http.data('GET', "/ads/accounts/#{id}/creative-targets")
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Create an ad with a creative. mediaUrl may only come from your own media store (SSRF protection).
|
|
94
|
+
def promote(id, input, idempotency_key: nil)
|
|
95
|
+
@http.data('POST', "/ads/accounts/#{id}/promote", body: input, idempotency_key: idempotency_key)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# ---- Audiences / Lead-gen / Conversions / Pixels / Targeting (Meta ilk) ----
|
|
99
|
+
|
|
100
|
+
# Custom audiences.
|
|
101
|
+
def audiences(id)
|
|
102
|
+
@http.data('GET', "/ads/accounts/#{id}/audiences")
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Create an audience (name/description).
|
|
106
|
+
def create_audience(id, input)
|
|
107
|
+
@http.data('POST', "/ads/accounts/#{id}/audiences", body: input)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Delete an audience.
|
|
111
|
+
def delete_audience(id, audience_id)
|
|
112
|
+
@http.data('DELETE', "/ads/accounts/#{id}/audiences/#{audience_id}")
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Upload members to an audience (≤10k/request). Raw emails/phones → server SHA-256; if pre-hashed, use the hashed* fields.
|
|
116
|
+
def upload_audience_users(id, audience_id, input)
|
|
117
|
+
@http.data('POST', "/ads/accounts/#{id}/audiences/#{audience_id}/users", body: input)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Lead-gen forms.
|
|
121
|
+
def lead_forms(id)
|
|
122
|
+
@http.data('GET', "/ads/accounts/#{id}/lead-forms")
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# A form's lead records (optional limit).
|
|
126
|
+
def leads(id, form_id, limit: nil)
|
|
127
|
+
@http.data('GET', "/ads/accounts/#{id}/lead-forms/#{form_id}/leads", query: { 'limit' => limit })
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Conversion pixels.
|
|
131
|
+
def pixels(id)
|
|
132
|
+
@http.data('GET', "/ads/accounts/#{id}/pixels")
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# CAPI relay (≤1000 events) — raw email/phone is hashed on the server; use testEventCode for a safe trial.
|
|
136
|
+
def send_conversions(id, input)
|
|
137
|
+
@http.data('POST', "/ads/accounts/#{id}/conversions", body: input)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Interest targeting search.
|
|
141
|
+
def search_interests(id, q)
|
|
142
|
+
@http.data('GET', "/ads/accounts/#{id}/targeting/interests", query: { 'q' => q })
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Reach estimate (targeting is a camelCase-keyed Hash).
|
|
146
|
+
def reach_estimate(id, targeting)
|
|
147
|
+
@http.data('POST', "/ads/accounts/#{id}/reach-estimate", body: targeting)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# ---- Campaign update + ad-set/ad hierarchy (C-T3) ----
|
|
151
|
+
|
|
152
|
+
# Update a campaign (patch: name/budget/budgetType/bidAmount/status).
|
|
153
|
+
def update_campaign(id, campaign_id, patch)
|
|
154
|
+
@http.data('PATCH', "/ads/accounts/#{id}/campaigns/#{campaign_id}", body: patch)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# A campaign's ad sets.
|
|
158
|
+
def ad_sets(id, campaign_id)
|
|
159
|
+
@http.data('GET', "/ads/accounts/#{id}/campaigns/#{campaign_id}/adsets")
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Campaign → ad sets → ads hierarchy (single call).
|
|
163
|
+
def campaign_tree(id, campaign_id)
|
|
164
|
+
@http.data('GET', "/ads/accounts/#{id}/campaigns/#{campaign_id}/tree")
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# An ad set's ads.
|
|
168
|
+
def ads(id, ad_set_id)
|
|
169
|
+
@http.data('GET', "/ads/accounts/#{id}/adsets/#{ad_set_id}/ads")
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# Ad set status (enabled/paused).
|
|
173
|
+
def set_ad_set_status(id, ad_set_id, status)
|
|
174
|
+
@http.data('POST', "/ads/accounts/#{id}/adsets/#{ad_set_id}/status", body: { 'status' => status })
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Delete an ad set.
|
|
178
|
+
def delete_ad_set(id, ad_set_id)
|
|
179
|
+
@http.data('DELETE', "/ads/accounts/#{id}/adsets/#{ad_set_id}")
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Ad status (enabled/paused).
|
|
183
|
+
def set_ad_status(id, ad_id, status)
|
|
184
|
+
@http.data('POST', "/ads/accounts/#{id}/ads/#{ad_id}/status", body: { 'status' => status })
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Delete an ad.
|
|
188
|
+
def delete_ad(id, ad_id)
|
|
189
|
+
@http.data('DELETE', "/ads/accounts/#{id}/ads/#{ad_id}")
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# ---- Ads-comment moderation (C-T4) ----
|
|
193
|
+
|
|
194
|
+
# An ad's comments.
|
|
195
|
+
def ad_comments(id, ad_id)
|
|
196
|
+
@http.data('GET', "/ads/accounts/#{id}/ads/#{ad_id}/comments")
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# Reply to an ad comment.
|
|
200
|
+
def reply_ad_comment(id, comment_id, message)
|
|
201
|
+
@http.data('POST', "/ads/accounts/#{id}/comments/#{comment_id}/reply", body: { 'message' => message })
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# Hide/show an ad comment (default hide).
|
|
205
|
+
def hide_ad_comment(id, comment_id, hidden = true)
|
|
206
|
+
@http.data('POST', "/ads/accounts/#{id}/comments/#{comment_id}/hide", body: { 'hidden' => hidden })
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
# Delete an ad comment.
|
|
210
|
+
def delete_ad_comment(id, comment_id)
|
|
211
|
+
@http.data('DELETE', "/ads/accounts/#{id}/comments/#{comment_id}")
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# ---- Catalogs (C-T5) ----
|
|
215
|
+
|
|
216
|
+
# Product catalogs.
|
|
217
|
+
def catalogs(id)
|
|
218
|
+
@http.data('GET', "/ads/accounts/#{id}/catalogs")
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# A catalog's product sets.
|
|
222
|
+
def product_sets(id, catalog_id)
|
|
223
|
+
@http.data('GET', "/ads/accounts/#{id}/catalogs/#{catalog_id}/product-sets")
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
end
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Posthubify
|
|
4
|
+
# Derived insights (Node sdk .insights) — from stored history, no live platform call.
|
|
5
|
+
class InsightsResource
|
|
6
|
+
def initialize(http)
|
|
7
|
+
@http = http
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# Best posting times (slots sorted by average engagement; dayOfWeek 1=Mon..7=Sun, UTC).
|
|
11
|
+
def best_time(days: nil, platform: nil, account_id: nil)
|
|
12
|
+
@http.data('GET', '/analytics/best-time',
|
|
13
|
+
query: { 'days' => days, 'platform' => platform, 'accountId' => account_id })
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Content lifetime curve (day buckets; avgPctOfFinal = average % reached by end of bucket).
|
|
17
|
+
def content_decay(days: nil, platform: nil, account_id: nil)
|
|
18
|
+
@http.data('GET', '/analytics/content-decay',
|
|
19
|
+
query: { 'days' => days, 'platform' => platform, 'accountId' => account_id })
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Weekly posting frequency ↔ engagement correlation (Pearson; <2 weeks → null).
|
|
23
|
+
def posting_frequency(days: nil, platform: nil, account_id: nil)
|
|
24
|
+
@http.data('GET', '/analytics/posting-frequency',
|
|
25
|
+
query: { 'days' => days, 'platform' => platform, 'accountId' => account_id })
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Daily metric timeline for a post (cumulative + delta; post_id = platform post id).
|
|
29
|
+
def post_timeline(post_id, days: nil)
|
|
30
|
+
@http.data('GET', "/analytics/posts/#{post_id}/timeline", query: { 'days' => days })
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Platform-specific analytics (Node sdk .platformAnalytics) — live data via the account connector.
|
|
35
|
+
class PlatformAnalyticsResource
|
|
36
|
+
def initialize(http)
|
|
37
|
+
@http = http
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Instagram daily follower history (from our own snapshot store; Meta does not provide a historical series).
|
|
41
|
+
def instagram_follower_history(account_id:, days: nil)
|
|
42
|
+
@http.data('GET', '/analytics/instagram/follower-history',
|
|
43
|
+
query: { 'accountId' => account_id, 'days' => days })
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Facebook Page insights (current metric names as of November 2025).
|
|
47
|
+
def facebook_page_insights(account_id)
|
|
48
|
+
@http.data('GET', '/analytics/facebook/page-insights', query: { 'accountId' => account_id })
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Instagram account insights (reach/views/accounts_engaged/total_interactions…).
|
|
52
|
+
def instagram_insights(account_id)
|
|
53
|
+
@http.data('GET', '/analytics/instagram/insights', query: { 'accountId' => account_id })
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Instagram audience demographics (age/gender/country/city; Meta requires min 100 followers).
|
|
57
|
+
def instagram_demographics(account_id)
|
|
58
|
+
@http.data('GET', '/analytics/instagram/demographics', query: { 'accountId' => account_id })
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Active Instagram stories (24-hour window).
|
|
62
|
+
def instagram_stories(account_id)
|
|
63
|
+
@http.data('GET', '/analytics/instagram/stories', query: { 'accountId' => account_id })
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Story metrics + navigation breakdown (tapsForward/tapsBack/exits/swipesForward).
|
|
67
|
+
def instagram_story_insights(account_id, story_id)
|
|
68
|
+
@http.data('GET', "/analytics/instagram/stories/#{story_id}/insights",
|
|
69
|
+
query: { 'accountId' => account_id })
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# TikTok account insights (follower/like/video counts — current totals).
|
|
73
|
+
def tiktok_account_insights(account_id)
|
|
74
|
+
@http.data('GET', '/analytics/tiktok/account-insights', query: { 'accountId' => account_id })
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# YouTube channel insights (cumulative + 28-day Analytics metrics).
|
|
78
|
+
def youtube_channel_insights(account_id)
|
|
79
|
+
@http.data('GET', '/analytics/youtube/channel-insights', query: { 'accountId' => account_id })
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# YouTube viewer demographics (age×gender percentages + country breakdown).
|
|
83
|
+
def youtube_demographics(account_id)
|
|
84
|
+
@http.data('GET', '/analytics/youtube/demographics', query: { 'accountId' => account_id })
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# LinkedIn organization page statistics (12-month window; engagement=rate).
|
|
88
|
+
def linkedin_org_aggregate(account_id)
|
|
89
|
+
@http.data('GET', '/analytics/linkedin/org-aggregate', query: { 'accountId' => account_id })
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Pinterest account insights (last 30 days: impression/save/pin-click/outbound-click/engagement + followers).
|
|
93
|
+
def pinterest_account_insights(account_id)
|
|
94
|
+
@http.data('GET', '/analytics/pinterest/account-insights', query: { 'accountId' => account_id })
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# LinkedIn post reaction breakdown.
|
|
98
|
+
def linkedin_post_reactions(account_id, post_id)
|
|
99
|
+
@http.data('GET', "/analytics/linkedin/post-reactions/#{post_id}",
|
|
100
|
+
query: { 'accountId' => account_id })
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Inbox analytics (Node sdk .inboxAnalytics) — dm-based volume/heatmap/response-time/source/leaderboard.
|
|
105
|
+
# from_date is required (YYYY-MM-DD); common filters to_date/platform/account_id/source.
|
|
106
|
+
class InboxAnalyticsResource
|
|
107
|
+
def initialize(http)
|
|
108
|
+
@http = http
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# DM volume (summary + daily + platform breakdown).
|
|
112
|
+
def volume(from_date:, to_date: nil, platform: nil, account_id: nil, source: nil)
|
|
113
|
+
@http.data('GET', '/analytics/inbox/volume',
|
|
114
|
+
query: inbox_query(from_date, to_date, platform, account_id, source))
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Activity heatmap (dow 1=Mon..7=Sun, hour 0-23 UTC; only non-empty buckets).
|
|
118
|
+
def heatmap(from_date:, to_date: nil, platform: nil, account_id: nil, source: nil)
|
|
119
|
+
@http.data('GET', '/analytics/inbox/heatmap',
|
|
120
|
+
query: inbox_query(from_date, to_date, platform, account_id, source))
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Response time metrics.
|
|
124
|
+
def response_time(from_date:, to_date: nil, platform: nil, account_id: nil, source: nil)
|
|
125
|
+
@http.data('GET', '/analytics/inbox/response-time',
|
|
126
|
+
query: inbox_query(from_date, to_date, platform, account_id, source))
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Source breakdown.
|
|
130
|
+
def source_breakdown(from_date:, to_date: nil, platform: nil, account_id: nil, source: nil)
|
|
131
|
+
@http.data('GET', '/analytics/inbox/source-breakdown',
|
|
132
|
+
query: inbox_query(from_date, to_date, platform, account_id, source))
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Leaderboard of the most active accounts.
|
|
136
|
+
def top_accounts(from_date:, to_date: nil, platform: nil, account_id: nil, source: nil)
|
|
137
|
+
@http.data('GET', '/analytics/inbox/top-accounts',
|
|
138
|
+
query: inbox_query(from_date, to_date, platform, account_id, source))
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Per-conversation statistics — paginated (Paged envelope; @http.req returns the raw body).
|
|
142
|
+
def conversations(from_date:, to_date: nil, platform: nil, account_id: nil, source: nil,
|
|
143
|
+
limit: nil, cursor: nil)
|
|
144
|
+
query = inbox_query(from_date, to_date, platform, account_id, source)
|
|
145
|
+
query['limit'] = limit
|
|
146
|
+
query['cursor'] = cursor
|
|
147
|
+
@http.req('GET', '/analytics/inbox/conversations', query: query)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Detail for a single conversation's analytics.
|
|
151
|
+
def conversation(conversation_id, from_date:, to_date: nil, platform: nil, account_id: nil,
|
|
152
|
+
source: nil)
|
|
153
|
+
@http.data('GET', "/analytics/inbox/conversations/#{conversation_id}",
|
|
154
|
+
query: inbox_query(from_date, to_date, platform, account_id, source))
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
private
|
|
158
|
+
|
|
159
|
+
# Common inbox query Hash (wire-camelCase keys; nil values are skipped in transport).
|
|
160
|
+
def inbox_query(from_date, to_date, platform, account_id, source)
|
|
161
|
+
{
|
|
162
|
+
'fromDate' => from_date,
|
|
163
|
+
'toDate' => to_date,
|
|
164
|
+
'platform' => platform,
|
|
165
|
+
'accountId' => account_id,
|
|
166
|
+
'source' => source
|
|
167
|
+
}
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|