Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ long failed = client.posts().stream(PostListParams.create().workspaceId(workspac
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `posts()` | `list`, `autoPaginate`, `stream`, `get`, `create`, `update`, `delete`, `duplicate`, `publish`, `retry`, `cancel`, `preflight`, `deliveries`, `publishRuns`, `analytics`, `bulkShift`, `bulkLabel`, `bulkDelete`, `validateImport`, `commitImport`, `rollbackImport` |
| `workspaces()` | `list`, `get`, `create`, `update`, `delete`, `analytics` |
| `accounts()` | `list`, `get`, `create`, `rename`, `move`, `delete`, `healthSummary`, `health`, `togglePrimary`, `validate`, `refreshToken`, `analytics`, `createTelegramConnectCode`, `getTelegramConnectStatus`, `getTelegramBotCommands`, `setTelegramBotCommands`, `deleteTelegramBotCommands`, `listSlackChannels`, `listSlackMembers`, `getSlackIdentity`, `updateSlackIdentity`, `getIceBreakers`, `setIceBreakers`, `deleteIceBreakers`, `getPersistentMenu`, `setPersistentMenu`, `deletePersistentMenu`, `getGreeting`, `setGreeting`, `deleteGreeting`, `getWebhookSubscription`, `resubscribeWebhook`, `communities()`, `listDiscordChannels`, `switchDiscordChannel`, `getDiscordIdentity`, `updateDiscordIdentity`, `listDiscordPins`, `deleteDiscordMessage`, `pinDiscordMessage`, `unpinDiscordMessage`, `crosspostDiscordMessage`, `createDiscordThread`, `sendDiscordDm`, `listDiscordEvents`, `getDiscordEvent`, `createDiscordEvent`, `updateDiscordEvent`, `deleteDiscordEvent`, `listDiscordMembers`, `getDiscordMember`, `listDiscordRoles`, `createDiscordRole`, `updateDiscordRole`, `deleteDiscordRole`, `addDiscordMemberRole`, `removeDiscordMemberRole`, `platformMetrics` |
| `accounts()` | `list`, `get`, `create`, `rename`, `move`, `delete`, `healthSummary`, `health`, `togglePrimary`, `validate`, `refreshToken`, `analytics`, `createTelegramConnectCode`, `getTelegramConnectStatus`, `getTelegramBotCommands`, `setTelegramBotCommands`, `deleteTelegramBotCommands`, `redditSubreddits`, `redditSubredditRules`, `redditFlairs`, `setRedditDefaultSubreddit`, `listSlackChannels`, `listSlackMembers`, `getSlackIdentity`, `updateSlackIdentity`, `getIceBreakers`, `setIceBreakers`, `deleteIceBreakers`, `getPersistentMenu`, `setPersistentMenu`, `deletePersistentMenu`, `getGreeting`, `setGreeting`, `deleteGreeting`, `getWebhookSubscription`, `resubscribeWebhook`, `communities()`, `listDiscordChannels`, `switchDiscordChannel`, `getDiscordIdentity`, `updateDiscordIdentity`, `listDiscordPins`, `deleteDiscordMessage`, `pinDiscordMessage`, `unpinDiscordMessage`, `crosspostDiscordMessage`, `createDiscordThread`, `sendDiscordDm`, `listDiscordEvents`, `getDiscordEvent`, `createDiscordEvent`, `updateDiscordEvent`, `deleteDiscordEvent`, `listDiscordMembers`, `getDiscordMember`, `listDiscordRoles`, `createDiscordRole`, `updateDiscordRole`, `deleteDiscordRole`, `addDiscordMemberRole`, `removeDiscordMemberRole`, `platformMetrics` |
| `accountGroups()` | `list`, `get`, `create`, `update`, `delete`, `setMembers` |
| `labels()` | `list`, `get`, `create`, `update`, `delete` |
| `webhooks()` | `list`, `create`, `update`, `delete`, `test`, `verify` |
Expand All @@ -108,19 +108,19 @@ long failed = client.posts().stream(PostListParams.create().workspaceId(workspac
| `automations()` | `list`, `get`, `create`, `update`, `delete`, `toggle`, `runs`, `run`, `trigger`, `stats` |
| `media()` | `list`, `limits`, `upload`, `presign`, `complete`, `uploadDirect`, `delete` |
| `ai()` | `credits`, `generateCaption`, `rewrite`, `repurposeUrl` |
| `inbox()` | `list`, `threads`, `conversations`, `unreadCount`, `accounts`, `platforms`, `markThreadRead`, `markConversationRead`, `refresh`, `update`, `editComment`, `reply`, `hide`, `unhide`, `delete`, `like`, `unlike`, `pin`, `unpin`, `react`, `startConversation`, `setTyping`, `passThreadControl`, `takeThreadControl`, `handover`, `listApprovals`, `approveReply`, `rejectReply` |
| `inbox()` | `list`, `threads`, `conversations`, `unreadCount`, `accounts`, `platforms`, `markThreadRead`, `markConversationRead`, `refresh`, `update`, `editComment`, `reply`, `hide`, `unhide`, `delete`, `like`, `unlike`, `vote`, `pin`, `unpin`, `react`, `startConversation`, `setTyping`, `passThreadControl`, `takeThreadControl`, `handover`, `listApprovals`, `approveReply`, `rejectReply` |
| `contacts()` | `list`, `get`, `create`, `update`, `delete`, `conversations`, `importCsv`, `listFields`, `createField`, `updateField`, `updateFieldOptions`, `deleteField`, `conversationAnalytics` |
| `broadcasts()` | `list`, `get`, `create`, `update`, `delete`, `send`, `cancel`, `recipients` |
| `sequences()` | `list`, `get`, `create`, `update`, `delete`, `enroll`, `unenroll`, `enrollments` |
| `knowledge()` | `list`, `create`, `createText`, `createUrl`, `createFile`, `update`, `delete`, `sync`, `search` |
| `ads()` | `list`, `external`, `boostable`, `connections`, `sources`, `authorizeMeta`, `deleteConnection`, `boost`, `create`, `refresh`, `setStatus`, `delete`, `accountTree`, `createCampaign`, `campaign`, `updateCampaign`, `deleteCampaign`, `duplicateCampaign`, `createAdSet`, `adSet`, `updateAdSet`, `deleteAdSet`, `duplicateAdSet`, `createNetworkAd`, `networkAd`, `updateNetworkAd`, `deleteNetworkAd`, `duplicateNetworkAd`, `bulkSetStatus`, `creatives`, `createCreative`, `creative`, `deleteCreative`, `estimateReach`, `insights`, `adInsights`, `audiences`, `createAudience`, `audience`, `updateAudience`, `deleteAudience`, `addAudienceUsers`, `searchTargeting`, `leadForms`, `createLeadForm`, `leadForm`, `archiveLeadForm`, `leads`, `leadsFeed`, `leadPages`, `subscribeLeadPage`, `unsubscribeLeadPage`, `goals`, `catalogs`, `createCatalog`, `catalog`, `updateCatalog`, `deleteCatalog`, `catalogProducts`, `writeCatalogProducts`, `productFeeds`, `createProductFeed`, `deleteProductFeed`, `feedUploads`, `startFeedUpload`, `productSets`, `createProductSet`, `updateProductSet`, `deleteProductSet`, `reachFrequency`, `createReachFrequency`, `reachFrequencyPrediction`, `reserveReachFrequency`, `cancelReachFrequency`, `library`, `partnershipCreators`, `requestPartnership`, `revokePartnership`, `accountActivity`, `labels`, `createLabel`, `updateLabel`, `deleteLabel`, `applyLabel`, `studies`, `createStudy`, `study`, `deleteStudy`, `iosCampaignLimits`, `highDemandPeriods`, `createHighDemandPeriod`, `deleteHighDemandPeriod`, `valueRuleSets`, `createValueRuleSet`, `deleteValueRuleSet` |
| `inbox()` | `list`, `threads`, `conversations`, `unreadCount`, `accounts`, `platforms`, `markThreadRead`, `markConversationRead`, `refresh`, `update`, `editComment`, `reply`, `hide`, `unhide`, `delete`, `like`, `unlike`, `pin`, `unpin`, `react`, `startConversation`, `setTyping`, `listApprovals`, `approveReply`, `rejectReply` |
| `inbox()` | `list`, `threads`, `conversations`, `unreadCount`, `accounts`, `platforms`, `markThreadRead`, `markConversationRead`, `refresh`, `update`, `editComment`, `reply`, `hide`, `unhide`, `delete`, `like`, `unlike`, `vote`, `pin`, `unpin`, `react`, `startConversation`, `setTyping`, `listApprovals`, `approveReply`, `rejectReply` |
| `ads()` | `list`, `external`, `boostable`, `connections`, `sources`, `authorizeMeta`, `deleteConnection`, `boost`, `create`, `refresh`, `setStatus`, `delete`, `accountTree`, `createCampaign`, `campaign`, `updateCampaign`, `deleteCampaign`, `duplicateCampaign`, `createAdSet`, `adSet`, `updateAdSet`, `deleteAdSet`, `duplicateAdSet`, `createNetworkAd`, `networkAd`, `updateNetworkAd`, `deleteNetworkAd`, `duplicateNetworkAd`, `bulkSetStatus`, `creatives`, `createCreative`, `creative`, `deleteCreative`, `estimateReach`, `insights`, `adInsights`, `audiences`, `createAudience`, `audience`, `updateAudience`, `deleteAudience`, `addAudienceUsers`, `searchTargeting`, `leadForms`, `createLeadForm`, `leadForm`, `archiveLeadForm`, `leads`, `leadsFeed`, `leadPages`, `subscribeLeadPage`, `unsubscribeLeadPage` |
| `whatsapp()` | `getProfile`, `updateProfile`, `requestDisplayName`, `setUsername`, `listTemplates`, `listTemplateLibrary`, `getTemplate`, `createTemplate`, `importTemplate`, `updateTemplate`, `deleteTemplate`, `listGroups`, `createGroup`, `getGroup`, `updateGroup`, `deleteGroup`, `getGroupInviteLink`, `resetGroupInviteLink`, `removeGroupParticipants`, `listBlocked`, `blockUsers`, `unblockUsers`, `getCommerceSettings`, `updateCommerceSettings`, `linkCatalog`, `listFlows`, `getFlow`, `createFlow`, `updateFlow`, `deleteFlow`, `uploadFlowJson`, `publishFlow`, `deprecateFlow`, `listFlowResponses`, `getEncryptionKeyStatus`, `setEncryptionKey`, `getAccountEvents`, `listSandboxSessions`, `createSandboxSession` |
| `ads()` | `list`, `external`, `boostable`, `connections`, `sources`, `providers`, `authorize`, `deleteConnection`, `boost`, `create`, `refresh`, `setStatus`, `delete`, `accountTree`, `createCampaign`, `campaign`, `updateCampaign`, `deleteCampaign`, `duplicateCampaign`, `createAdSet`, `adSet`, `updateAdSet`, `deleteAdSet`, `duplicateAdSet`, `createNetworkAd`, `networkAd`, `updateNetworkAd`, `deleteNetworkAd`, `duplicateNetworkAd`, `bulkSetStatus`, `creatives`, `createCreative`, `creative`, `deleteCreative`, `estimateReach`, `insights`, `adInsights`, `audiences`, `createAudience`, `audience`, `updateAudience`, `deleteAudience`, `addAudienceUsers`, `addAudienceCompanies`, `searchTargeting`, `leadForms`, `createLeadForm`, `leadForm`, `archiveLeadForm`, `leads`, `leadsFeed`, `leadPages`, `subscribeLeadPage`, `unsubscribeLeadPage`, `bidPricing`, `supplyForecast`, `conversionRules`, `createConversionRule`, `conversionRule`, `updateConversionRule`, `deleteConversionRule`, `attachConversionRule`, `detachConversionRule`, `conversionMetrics`, `sendConversionEvents` |
| `googleAds()` | `recommendations`, `optimizationScore`, `applyRecommendations`, `dismissRecommendations`, `keywords`, `createKeyword`, `updateKeyword`, `deleteKeyword`, `keywordIdeas`, `keywordMetrics`, `searchTerms`, `bidStrategies`, `createBidStrategy`, `adSchedule`, `setAdSchedule`, `negativeKeywordLists`, `createNegativeKeywordList`, `addNegativeKeywords`, `attachNegativeKeywordList`, `assets`, `createAsset`, `attachAsset`, `deleteAsset`, `assetGroups`, `createAssetGroup`, `updateAssetGroup`, `deleteAssetGroup`, `localServicesLeads`, `conversionActions`, `createConversionAction`, `uploadConversions`, `uploadConversionAdjustments`, `query` |
| `googleBusiness()` | `getLocation`, `updateLocation`, `getAttributes`, `updateAttributes`, `getMenus`, `replaceMenus`, `getServices`, `replaceServices`, `listMedia`, `addMedia`, `deleteMedia`, `listPlaceActions`, `createPlaceAction`, `updatePlaceAction`, `deletePlaceAction`, `getVerificationOptions`, `startVerification`, `completeVerification`, `getPerformance`, `getSearchKeywords`, `assign` |
| `validate()` | `post`, `length`, `media` |
| `validate()` | `post`, `length`, `media`, `subreddit` |
| `activity()` | `list` |

`accounts().communities()` covers the X communities an account can post into: `list`, `sync`,
Expand Down
7 changes: 5 additions & 2 deletions src/main/java/com/fopost/sdk/model/Account.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@
* A connected social account.
*
* <p>Named {@code Account} for the platform account, not the billing account. Which fields
* arrive depends on the endpoint: the list gives health and primary state, the detail gives
* timestamps and the owning workspace. {@code name} is the display name when one is set, and
* arrive depends on the endpoint: the list gives health, primary state and
* {@code reconnectRequired}, the detail gives timestamps and the owning workspace.
*
* <p>{@code reconnectRequired} is true when the account was connected before a permission it
* now needs was asked for; reconnecting it is the fix. {@code name} is the display name when one is set, and
* {@code platformName} is always the name from the platform.
*/
public record Account(
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/fopost/sdk/model/InboxItem.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,12 @@ public record InboxItem(
Boolean canHide,
Boolean canDelete,
Boolean liked,
String vote,
Boolean pinned,
String reaction,
Instant editedAt,
Boolean canLike,
Boolean canVote,
Boolean canPin,
Boolean canEdit,
Boolean canReact,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.fopost.sdk.model;

/**
* Where posts from a Reddit account go when a post names no subreddit.
*
* <p>A null {@code subreddit} means the account's own profile page, which always accepts a post.
*/
public record RedditDefaultSubreddit(String subreddit) {}
8 changes: 8 additions & 0 deletions src/main/java/com/fopost/sdk/model/RedditFlair.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.fopost.sdk.model;

/**
* A post flair, valid only in the subreddit it came from.
*
* <p>{@code editable} means the label may be replaced with your own text.
*/
public record RedditFlair(String id, String text, Boolean editable) {}
6 changes: 6 additions & 0 deletions src/main/java/com/fopost/sdk/model/RedditFlairs.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.fopost.sdk.model;

import java.util.List;

/** The post flairs one subreddit offers. */
public record RedditFlairs(String subreddit, List<RedditFlair> flairs) {}
17 changes: 17 additions & 0 deletions src/main/java/com/fopost/sdk/model/RedditSubreddit.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.fopost.sdk.model;

/**
* A subreddit a Reddit account is in, or its own profile page.
*
* <p>{@code name} carries no {@code r/} prefix. {@code canPost} is false where the account may
* read but not submit, and {@code isDefault} marks where posts go when a post names no subreddit.
*/
public record RedditSubreddit(
String name,
String title,
Long subscribers,
Boolean over18,
Boolean canPost,
Boolean flairEnabled,
String iconUrl,
Boolean isDefault) {}
4 changes: 4 additions & 0 deletions src/main/java/com/fopost/sdk/model/RedditSubredditRule.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.fopost.sdk.model;

/** One rule a subreddit publishes. {@code appliesTo} is {@code link}, {@code comment} or {@code all}. */
public record RedditSubredditRule(String name, String description, String appliesTo) {}
6 changes: 6 additions & 0 deletions src/main/java/com/fopost/sdk/model/RedditSubredditRules.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.fopost.sdk.model;

import java.util.List;

/** A subreddit's rules, in its own order. Show them before publishing. */
public record RedditSubredditRules(String subreddit, List<RedditSubredditRule> rules) {}
18 changes: 18 additions & 0 deletions src/main/java/com/fopost/sdk/model/SubredditCheck.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.fopost.sdk.model;

import com.fasterxml.jackson.annotation.JsonAlias;

/**
* Whether a subreddit exists and takes a post from a named Reddit account.
*
* <p>{@code ok} is true when both hold. A private, banned or missing subreddit answers 200 with
* {@code exists} false rather than an error.
*/
public record SubredditCheck(
String subreddit,
Boolean exists,
Boolean canPost,
// Neither the snake strategy nor the camel alias covers a digit boundary.
@JsonAlias("over_18") Boolean over18,
Boolean flairEnabled,
Boolean ok) {}
45 changes: 45 additions & 0 deletions src/main/java/com/fopost/sdk/resource/AccountsResource.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
import com.fopost.sdk.model.InstagramStoryInsights;
import com.fopost.sdk.model.LinkedInMention;
import com.fopost.sdk.model.PinterestBoard;
import com.fopost.sdk.model.RedditDefaultSubreddit;
import com.fopost.sdk.model.RedditFlairs;
import com.fopost.sdk.model.RedditSubreddit;
import com.fopost.sdk.model.RedditSubredditRules;
import com.fopost.sdk.model.SlackChannel;
import com.fopost.sdk.model.SlackIdentity;
import com.fopost.sdk.model.SlackMember;
Expand Down Expand Up @@ -554,6 +558,47 @@ private DiscordAck ack(JsonNode body) {
return http.convert(ApiClient.unwrap(body), DiscordAck.class);
}

/**
* Subreddits a Reddit account is in, busiest first, plus its own profile page.
*
* <p>A 409 with code {@code reconnect_required} means the grant is short of a permission
* this read needs, and the account has to be reconnected.
*/
public List<RedditSubreddit> redditSubreddits(String accountId) {
return http.convertList(
ApiClient.unwrap(http.get("/v1/accounts/" + accountId + "/reddit/subreddits", null)),
RedditSubreddit.class);
}

/** The rules a subreddit publishes, in its own order. Show them before publishing. */
public RedditSubredditRules redditSubredditRules(String accountId, String subreddit) {
String path = "/v1/accounts/" + accountId + "/reddit/subreddits/" + subreddit + "/rules";
return http.convert(ApiClient.unwrap(http.get(path, null)), RedditSubredditRules.class);
}

/**
* Post flairs one subreddit offers. A flair id is valid only there, and one from elsewhere
* fails preflight.
*/
public RedditFlairs redditFlairs(String accountId, String subreddit) {
return http.convert(
ApiClient.unwrap(http.get("/v1/accounts/" + accountId + "/reddit/flairs",
query("subreddit", subreddit))),
RedditFlairs.class);
}

/**
* Where posts from this account go when a post names no subreddit. Pass null to fall back to
* the account's own profile page, which always accepts a post.
*/
public RedditDefaultSubreddit setRedditDefaultSubreddit(String accountId, String subreddit) {
Map<String, Object> body = new LinkedHashMap<>();
body.put("subreddit", subreddit);
return http.convert(
ApiClient.unwrap(http.put("/v1/accounts/" + accountId + "/reddit/default-subreddit", body)),
RedditDefaultSubreddit.class);
}

private static Map<String, Object> query(String key, Object value) {
if (value == null) {
return null;
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/com/fopost/sdk/resource/InboxResource.java
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,18 @@ public InboxItem like(String itemId) {
return http.convert(ApiClient.unwrap(http.post("/v1/inbox/" + itemId + "/like", null)), InboxItem.class);
}

/**
* Vote an item up or down where the network ranks by votes (Reddit). {@code direction} is
* {@code up}, {@code down}, or {@code none} to take an earlier vote back. Only where
* {@code canVote} is true. An upvote is the same call {@code like} makes, so {@code liked}
* moves with it.
*/
public InboxItem vote(String itemId, String direction) {
Map<String, Object> body = new LinkedHashMap<>();
body.put("direction", direction);
return http.convert(ApiClient.unwrap(http.post("/v1/inbox/" + itemId + "/vote", body)), InboxItem.class);
}

public InboxItem unlike(String itemId) {
return http.convert(ApiClient.unwrap(http.post("/v1/inbox/" + itemId + "/unlike", null)), InboxItem.class);
}
Expand Down
Loading
Loading