fopost 0.2.0 → 0.3.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: 39dcfa4fd395633ab79afe8b23b7888c9c76ad6b07d7bd86c874c56335647f48
4
- data.tar.gz: 49ebacabb32eb4054db27d6bf69e14eae7f828a4071207c921b6dd9b5ef529ad
3
+ metadata.gz: 70877df67981ee15f3e6d672df5edad494ae08fb8ff412fd48814366fb1e3012
4
+ data.tar.gz: c592df81ea3019c84d7effb9a15ddfc868d3e111d32d2ee8f3e2db8503bdf4da
5
5
  SHA512:
6
- metadata.gz: c4e179a15c45093239bd90ec0664c5ce49a491e11a750b7152448dcfebac7edb7fd2538798789f9eb1859efa0bdf6e0d24bc35c9f1b782fdc68ee4dcc337cb4d
7
- data.tar.gz: 82b98ae4e3eb9c9004454abf091c693dbe254a6d7983b990d57e9766bc760b169016f328284730b0292d0b6776d1b6e75da48204cd1e6da0fc16fc80d6e56164
6
+ metadata.gz: beee8ec7c7d035cd0bf7a824e683df0a0b4c6ef469b5db38fa6b6c0a3b2d2c2429269dd305f473c50cd5af8070e7f9c1b594560416cf6d210fe62621700919dc
7
+ data.tar.gz: 54240d5ec9aa83a78553c7c5d32f19d112e0079d48b214d62d9f15f60d2d8ea4044a9bb4810b5669dc75ac9e02f39115c433fb784584b2365f5a88a3e16f016d
data/CHANGELOG.md CHANGED
@@ -4,6 +4,173 @@ All notable changes to this gem are documented here. The format follows
4
4
  [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the gem follows
5
5
  [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.3.0] - 2026-10-18
8
+
9
+ ### Added
10
+
11
+ - `inbox.like`, `unlike`, `pin`, `unpin`, `react`, `edit_comment`, `start_conversation` and
12
+ `set_typing` (`inbox` scope, plus `publish`).
13
+ - `inbox.reply` takes `media_ids` and `quick_replies`; `text` is optional when `media_ids` is given.
14
+ - `InboxItem` reads `liked`, `pinned`, `reaction`, `edited_at` and the `can_like`, `can_pin`,
15
+ `can_edit`, `can_react`, `can_send_media`, `can_quick_reply` and `can_private_reply` flags;
16
+ `InboxAccount` reads `can_start_conversation`.
17
+ - `validate` resource: `post`, `length` and `media` preflight checks (`posts` scope).
18
+ - `account_groups` resource: `list`, `create`, `get`, `update`, `delete` and `set_members`
19
+ (`accounts` scope).
20
+ - `accounts.update` renames an account and `accounts.move` moves it to another workspace;
21
+ `accounts.list` takes `group_id`, and `SocialAccount#platform_name` is read.
22
+ - `posts.create` takes `account_group_id`.
23
+ - `media.presign`, `complete` and `upload_direct` upload a file straight to storage instead of
24
+ through the API (`posts` scope).
25
+ - `ads` campaign tree: `account_tree`, and create, get, update, delete and duplicate for
26
+ campaigns, ad sets and network ads, plus `bulk_set_status` (`ads` scope; writes also need
27
+ `publish`).
28
+ - `ads` creatives (`creatives`, `create_creative`, `get_creative`, `delete_creative`), audiences
29
+ (`get_audience`, `update_audience`, `delete_audience`, `add_audience_users`), `estimate_reach`,
30
+ `insights` and `ad_insights`.
31
+ - `ads` lead forms and leads: `get_lead_form`, `archive_lead_form`, `leads_feed` (cursor
32
+ paginated), `lead_pages`, `subscribe_lead_page` and `unsubscribe_lead_page`.
33
+ - `ads.create` takes `url_tags`.
34
+ - `blog.suggest_seeds(workspace_id, seeds:, prompt:)` suggests about 10 search terms from the
35
+ blog goal and topics (needs `ai`, 402 on an empty balance), and `blog.submit_article` moves a
36
+ draft, failed or rejected article to `in_review` (needs `posts`, 409 otherwise).
37
+ - `BlogSettings#goal`, `#focus_topics`, `#avoid_topics` and `#plan_run` (`BlogPlanRun`: `status`,
38
+ `error`, `added`, `finished_at`); `update_settings` takes `goal:`, `focus_topics:` and
39
+ `avoid_topics:`. `BlogKeyword#fit_reason` says why a keyword serves the goal.
40
+ - `in_review` on `BLOG_ARTICLE_STATUSES`.
41
+ - `whatsapp` resource for a WhatsApp Business connection: the business profile
42
+ (`profile`, `update_profile`, `request_display_name`, `set_username`), message
43
+ templates including the platform's own library (`templates`, `create_template`,
44
+ `import_template`, …), groups, blocking, commerce settings and flows
45
+ (`create_flow`, `upload_flow_json`, `publish_flow`, `flow_responses`, …), plus
46
+ `account_events`. All need the `accounts` scope.
47
+ - `whatsapp.create_sandbox_session` and `sandbox_sessions` invite a tester to the
48
+ platform-owned WhatsApp test number. Inviting sends a template, so it needs the
49
+ `publish` scope.
50
+ - `whatsapp` on `Fopost::PLATFORMS`.
51
+ - `client.blog`: articles for a website. Settings (`get_settings`, `update_settings`,
52
+ `rotate_website_secret`, `test_website`), keywords (`list_keywords`, `plan_keywords`,
53
+ `add_keyword`, `update_keyword`, `delete_keyword`) and articles (`list_articles`,
54
+ `request_article`, `get_article`, `update_article`, `regenerate_article`, `publish_article`,
55
+ `reject_article`, `delete_article`), with the `BlogSettings`, `BlogSettingsUpdate`,
56
+ `BlogWebsiteTest`, `BlogKeyword`, `BlogArticle`, `BlogArticleFull` and `BlogArticleImage`
57
+ models and the `BLOG_ARTICLE_STATUSES`, `BLOG_KEYWORD_STATUSES` and `BLOG_TARGET_KINDS`
58
+ constants. Reads need `posts`; `plan_keywords`, `request_article` and `regenerate_article`
59
+ need `ai` and answer 402 on an empty balance; `publish_article` needs `publish` and answers
60
+ 409 `no_target` with no target set.
61
+ - `Fopost::Webhooks.verify(raw_body, headers, secret)` checks the signature on any FoPost
62
+ webhook over the raw bytes in constant time, preferring the timestamped signature (300 s
63
+ tolerance) and falling back to the plain body signature only when no timestamp was sent.
64
+ It returns a `WebhookEvent` (`event`, `data`, `timestamp`); `#article` types the
65
+ `article.published` payload as `BlogArticlePublished`. A bad signature raises
66
+ `Fopost::WebhookSignatureError`.
67
+
68
+ - `media.limits` reads the account's upload ceilings (`UploadLimits`: `max_file_bytes`,
69
+ `multipart_max_file_bytes`, `max_files_per_upload`, `next_tier`, `allowed_types`).
70
+ - `posts.create` and `posts.update` take `files:` (paths, IOs, or
71
+ `{ filename:, io:/data:, mime_type: }` hashes). Files at or under the multipart ceiling go
72
+ in one multipart request; larger ones go through direct upload and are attached to the first
73
+ block.
74
+ - `media.presign` and `upload_direct` take `folder_id`, `origin`, `brand_role`, `brand_voice_id`
75
+ and `person_consent`; `size` may go up to the account's `max_file_bytes`, which
76
+ `PresignedUpload#max_file_bytes` reports.
77
+ - `Fopost::FileTooLargeError` for a 413 `file_too_large`, with `max_file_bytes`, `file_bytes`
78
+ and `upgrade_url`.
79
+
80
+ - `InboxItem#moderation_status` carries the platform's own state for a comment
81
+ (`published`, `held`, `spam`, `rejected`), and `InboxAccount#reconnect_required`
82
+ flags an account connected before the inbox asked for a permission it needs.
83
+ - `client.broadcasts`: one message into every conversation the workspace already has
84
+ with a segment of its contacts. `list`, `get`, `create`, `update`, `delete`, `send`,
85
+ `cancel`, `recipients`. Reading needs the `inbox` scope; `send` and `cancel` also need
86
+ `publish`.
87
+ - `client.sequences`: a series of messages on a delay. `list`, `get`, `create`, `update`,
88
+ `delete`, `enroll`, `unenroll`, `enrollments`. `enroll` and `unenroll` need `publish`.
89
+ - Both honour each network's messaging window server-side. Messenger and Instagram take a
90
+ business-initiated message only within 24 hours of the contact's last one, so recipients
91
+ outside it come back `skipped` with `skip_reason` `window_closed` and nothing is
92
+ attempted — the number sent is often lower than the audience.
93
+
94
+ - `contacts` resource: the people behind the inbox. `list`, `get`, `create`, `update`,
95
+ `delete`, `conversations` (the threads one person appears in), `import` (CSV), and
96
+ `list_fields` / `create_field` / `update_field` / `delete_field` for the custom columns
97
+ a workspace keeps. All need the `inbox` scope.
98
+ - `contacts.conversation_analytics` reads `/v1/analytics/inbox/conversations`: volume and
99
+ median reply time per thread. Needs the `analytics` scope.
100
+ - `snapchat` added to `Fopost::PLATFORMS`.
101
+
102
+ - `accounts.create_telegram_connect_code`, `get_telegram_connect_status`, `get_telegram_bot_commands`,
103
+ `set_telegram_bot_commands` and `delete_telegram_bot_commands` (`accounts` scope).
104
+ - Meta messaging settings on `accounts`: `get_ice_breakers`, `set_ice_breakers` and
105
+ `delete_ice_breakers` (Facebook Pages and Instagram), plus `get_persistent_menu`,
106
+ `set_persistent_menu`, `delete_persistent_menu`, `get_greeting`, `set_greeting` and
107
+ `delete_greeting` (Facebook Pages). A network without a field answers 400.
108
+ - `accounts.get_webhook_subscription` reports whether the network is still delivering events
109
+ for an account, and `resubscribe_webhook` puts a lapsed subscription back.
110
+ - `inbox.handover` passes a Messenger thread to another Meta app, or takes it back when no
111
+ `app_id` is given (`inbox` scope, plus `publish`).
112
+ - `accounts.list_slack_channels`, `list_slack_members`, `get_slack_identity` and `update_slack_identity`
113
+ (`accounts` scope), with the `SlackChannel`, `SlackMember` and `SlackIdentity` models.
114
+ - The Discord bot surface on `accounts` (`accounts` scope, plus `publish` for anything that
115
+ posts): `list_discord_channels`, `switch_discord_channel`, `get_discord_identity`,
116
+ `update_discord_identity`, `list_discord_pins`, `delete_discord_message`,
117
+ `pin_discord_message`, `unpin_discord_message`, `crosspost_discord_message`,
118
+ `create_discord_thread`, `send_discord_dm`, `list_discord_events`, `get_discord_event`,
119
+ `create_discord_event`, `update_discord_event`, `delete_discord_event`,
120
+ `list_discord_members`, `get_discord_member`, `list_discord_roles`, `create_discord_role`,
121
+ `update_discord_role`, `delete_discord_role`, `add_discord_member_role` and
122
+ `remove_discord_member_role`, with the `DiscordChannel`, `DiscordIdentity`,
123
+ `DiscordMessage`, `DiscordMessageRef`, `DiscordThread`, `DiscordScheduledEvent`,
124
+ `DiscordMember` and `DiscordRole` models. A webhook connection answers
125
+ `409 webhook_connection`.
126
+ - `DiscordChannel#can_post` says whether the bot may actually post in a channel;
127
+ a channel permission in Discord can shut it out. `switch_discord_channel` answers
128
+ `409 channel_not_writable` for one.
129
+ - Per-network extras on `accounts`, all `accounts` scope: Pinterest boards
130
+ (`list_pinterest_boards`, `create_pinterest_board`), YouTube playlists and captions
131
+ (`list_youtube_playlists`, `create_youtube_playlist`, `set_default_youtube_playlist`,
132
+ `list_youtube_captions`, `upload_youtube_captions`, `read_youtube_transcript`), Bluesky post
133
+ languages (`get_bluesky_languages`, `set_bluesky_languages`), TikTok creator info
134
+ (`get_tiktok_creator_info`), TikTok music and place search plus video lookup
135
+ (`search_tiktok_music`, `search_tiktok_locations`, `lookup_tiktok_video`),
136
+ Instagram audio, publishing limit and stories
137
+ (`search_instagram_audio`, `get_instagram_publishing_limit`, `list_instagram_stories`,
138
+ `get_instagram_story_insights`) and LinkedIn mentions (`search_linkedin_mentions`), with a
139
+ model each.
140
+ - `accounts.list_reddit_subreddits`, `list_reddit_subreddit_rules`, `list_reddit_flairs` and
141
+ `set_reddit_default_subreddit` (`accounts` scope): a Reddit account's destinations, a
142
+ subreddit's rules and post flairs, and where posts go when one names no subreddit. With the
143
+ `RedditSubreddit`, `RedditSubredditRule(s)`, `RedditFlair(s)` and `RedditDefaultSubreddit`
144
+ models. An account connected before those permissions were asked for answers 409
145
+ `reconnect_required`.
146
+ - `validate.subreddit` (`posts` scope), with the `SubredditCheck` model.
147
+ - `inbox.vote` (`inbox` and `publish`): up, down, or `'none'` to take an earlier vote back.
148
+ - `SocialAccount#reconnect_required`, and the inbox item's `vote` and `can_vote`.
149
+ - `client.blogs` reaches content a connected site already owns, by the platform's own ids:
150
+ `list_blogs`, `list_articles`, `get_article`, `create_article`, `update_article`,
151
+ `delete_article`, plus `list_products` and `update_product` for a Shopify store, with the
152
+ `RemoteBlog`, `RemoteArticle` and `RemoteProduct` models. `update_article` changes the live
153
+ article in place and never creates a second post. Reads need `posts`; the writes need `publish`.
154
+
155
+ ### Changed
156
+
157
+ - `client.blog` matches the live API contract: the workspace travels as `workspace_id` on the
158
+ query string, single objects are read bare and lists from `{ data }`, and every response is
159
+ read in snake_case. `BlogWebsiteTest` now carries `http_status` (what the website answered)
160
+ instead of `ok`, `status` and `error`; a failed test is still a 502 `Fopost::Error` with
161
+ `http_status` on its body.
162
+ - `blog.plan_keywords` no longer fills the calendar: results land as `suggested` keywords, and
163
+ `update_keyword(status: 'planned')` picks one and gives it the next free date.
164
+ - `blog.publish_article` and `update_article(publish_at:)` need an article in review (or already
165
+ scheduled or failed); a draft answers 409 until it is submitted.
166
+ - `BlogSettings#review_hold_days` is now the number of days before its planned date that a
167
+ picked keyword starts being written.
168
+
169
+ ### Removed
170
+
171
+ - **Breaking:** `BlogSettings#auto_publish` and the `auto_publish:` keyword on
172
+ `blog.update_settings`. Every article now goes through `submit_article` before it publishes.
173
+
7
174
  ## [0.2.0] - 2026-09-19
8
175
 
9
176
  ### Added
@@ -26,5 +193,7 @@ Initial release.
26
193
  - Response models that accept either wire casing and keep unknown fields on `#raw`.
27
194
  - A pluggable transport, so the HTTP stack can be swapped or stubbed.
28
195
 
196
+ [Unreleased]: https://github.com/fopost/fopost-ruby/compare/v0.3.0...HEAD
197
+ [0.3.0]: https://github.com/fopost/fopost-ruby/releases/tag/v0.3.0
29
198
  [0.2.0]: https://github.com/fopost/fopost-ruby/releases/tag/v0.2.0
30
199
  [0.1.0]: https://github.com/fopost/fopost-ruby/releases/tag/v0.1.0