1use crate::error::{MktError, Result};
12use crate::models::{
13 Ad, AdSet, Audience, AudienceId, AudienceUpdateResult, AudienceUser, Campaign, CampaignFilters,
14 CampaignId, CreateAdSetInput, CreateAudienceInput, CreateCampaignInput, CreateCreativeInput,
15 CreateDarkPostInput, Creative, HttpMethod, InsightsQuery, InsightsReport, MediaAsset,
16 Paginated, Post, PostId, PromotePostInput, ProviderHealth, PublishPostInput,
17 UpdateCampaignInput, UploadImageInput, UploadVideoInput,
18};
19
20#[derive(Debug, Clone)]
25#[allow(clippy::struct_excessive_bools)] pub struct ProviderCapabilities {
27 pub campaigns: bool,
29 pub adsets: bool,
31 pub ads: bool,
33 pub creatives: bool,
35 pub audiences: bool,
37 pub insights: bool,
39 pub organic_posts: bool,
41 pub dark_posts: bool,
43 pub video_upload: bool,
45 pub image_upload: bool,
47 pub workflow_templates: bool,
49}
50
51pub trait MarketingProvider: Send + Sync {
62 fn name(&self) -> &'static str;
64
65 fn display_name(&self) -> &'static str;
67
68 fn capabilities(&self) -> ProviderCapabilities;
70
71 fn list_campaigns(
75 &self,
76 filters: &CampaignFilters,
77 ) -> impl std::future::Future<Output = Result<Paginated<Campaign>>> + Send;
78
79 fn get_campaign(
81 &self,
82 id: &CampaignId,
83 ) -> impl std::future::Future<Output = Result<Campaign>> + Send;
84
85 fn create_campaign(
87 &self,
88 input: &CreateCampaignInput,
89 ) -> impl std::future::Future<Output = Result<Campaign>> + Send;
90
91 fn update_campaign(
93 &self,
94 id: &CampaignId,
95 input: &UpdateCampaignInput,
96 ) -> impl std::future::Future<Output = Result<Campaign>> + Send;
97
98 fn delete_campaign(
100 &self,
101 id: &CampaignId,
102 ) -> impl std::future::Future<Output = Result<()>> + Send;
103
104 fn list_adsets(
108 &self,
109 _campaign_id: &CampaignId,
110 ) -> impl std::future::Future<Output = Result<Paginated<AdSet>>> + Send {
111 async { Err(MktError::not_supported(self.name(), "adsets")) }
112 }
113
114 fn create_adset(
116 &self,
117 _input: &CreateAdSetInput,
118 ) -> impl std::future::Future<Output = Result<AdSet>> + Send {
119 async { Err(MktError::not_supported(self.name(), "adsets")) }
120 }
121
122 fn create_creative(
126 &self,
127 _input: &CreateCreativeInput,
128 ) -> impl std::future::Future<Output = Result<Creative>> + Send {
129 async { Err(MktError::not_supported(self.name(), "creatives")) }
130 }
131
132 fn create_dark_post(
134 &self,
135 _input: &CreateDarkPostInput,
136 ) -> impl std::future::Future<Output = Result<Creative>> + Send {
137 async { Err(MktError::not_supported(self.name(), "dark_posts")) }
138 }
139
140 fn list_audiences(&self) -> impl std::future::Future<Output = Result<Vec<Audience>>> + Send {
144 async { Err(MktError::not_supported(self.name(), "audiences")) }
145 }
146
147 fn create_audience(
149 &self,
150 _input: &CreateAudienceInput,
151 ) -> impl std::future::Future<Output = Result<Audience>> + Send {
152 async { Err(MktError::not_supported(self.name(), "audiences")) }
153 }
154
155 fn add_users_to_audience(
157 &self,
158 _id: &AudienceId,
159 _users: &[AudienceUser],
160 ) -> impl std::future::Future<Output = Result<AudienceUpdateResult>> + Send {
161 async { Err(MktError::not_supported(self.name(), "audience_users")) }
162 }
163
164 fn get_insights(
168 &self,
169 _query: &InsightsQuery,
170 ) -> impl std::future::Future<Output = Result<InsightsReport>> + Send {
171 async { Err(MktError::not_supported(self.name(), "insights")) }
172 }
173
174 fn publish_post(
178 &self,
179 _input: &PublishPostInput,
180 ) -> impl std::future::Future<Output = Result<Post>> + Send {
181 async { Err(MktError::not_supported(self.name(), "organic_posts")) }
182 }
183
184 fn promote_post(
186 &self,
187 _post_id: &PostId,
188 _input: &PromotePostInput,
189 ) -> impl std::future::Future<Output = Result<Ad>> + Send {
190 async { Err(MktError::not_supported(self.name(), "promote_post")) }
191 }
192
193 fn upload_image(
197 &self,
198 _input: &UploadImageInput,
199 ) -> impl std::future::Future<Output = Result<MediaAsset>> + Send {
200 async { Err(MktError::not_supported(self.name(), "image_upload")) }
201 }
202
203 fn upload_video(
205 &self,
206 _input: &UploadVideoInput,
207 ) -> impl std::future::Future<Output = Result<MediaAsset>> + Send {
208 async { Err(MktError::not_supported(self.name(), "video_upload")) }
209 }
210
211 fn raw_request(
215 &self,
216 _method: HttpMethod,
217 _path: &str,
218 _params: &serde_json::Value,
219 ) -> impl std::future::Future<Output = Result<serde_json::Value>> + Send {
220 async { Err(MktError::not_supported(self.name(), "raw_request")) }
221 }
222
223 fn health_check(&self) -> impl std::future::Future<Output = Result<ProviderHealth>> + Send {
227 async { Err(MktError::not_supported(self.name(), "health_check")) }
228 }
229}