google_dfareporting3d5/api.rs
1#![allow(clippy::ptr_arg)]
2
3use std::collections::{BTreeSet, HashMap};
4
5use tokio::time::sleep;
6
7// ##############
8// UTILITIES ###
9// ############
10
11/// Identifies the an OAuth2 authorization scope.
12/// A scope is needed when requesting an
13/// [authorization token](https://developers.google.com/youtube/v3/guides/authentication).
14#[derive(PartialEq, Eq, Ord, PartialOrd, Hash, Debug, Clone, Copy)]
15pub enum Scope {
16 /// View and manage your DoubleClick Campaign Manager's (DCM) display ad campaigns
17 Dfatrafficking,
18}
19
20impl AsRef<str> for Scope {
21 fn as_ref(&self) -> &str {
22 match *self {
23 Scope::Dfatrafficking => "https://www.googleapis.com/auth/dfatrafficking",
24 }
25 }
26}
27
28#[allow(clippy::derivable_impls)]
29impl Default for Scope {
30 fn default() -> Scope {
31 Scope::Dfatrafficking
32 }
33}
34
35// ########
36// HUB ###
37// ######
38
39/// Central instance to access all Dfareporting related resource activities
40///
41/// # Examples
42///
43/// Instantiate a new hub
44///
45/// ```test_harness,no_run
46/// extern crate hyper;
47/// extern crate hyper_rustls;
48/// extern crate google_dfareporting3d5 as dfareporting3d5;
49/// use dfareporting3d5::api::CreativeAssetMetadata;
50/// use dfareporting3d5::{Result, Error};
51/// use std::fs;
52/// # async fn dox() {
53/// use dfareporting3d5::{Dfareporting, FieldMask, hyper_rustls, hyper_util, yup_oauth2};
54///
55/// // Get an ApplicationSecret instance by some means. It contains the `client_id` and
56/// // `client_secret`, among other things.
57/// let secret: yup_oauth2::ApplicationSecret = Default::default();
58/// // Instantiate the authenticator. It will choose a suitable authentication flow for you,
59/// // unless you replace `None` with the desired Flow.
60/// // Provide your own `AuthenticatorDelegate` to adjust the way it operates and get feedback about
61/// // what's going on. You probably want to bring in your own `TokenStorage` to persist tokens and
62/// // retrieve them from storage.
63/// let connector = hyper_rustls::HttpsConnectorBuilder::new()
64/// .with_native_roots()
65/// .unwrap()
66/// .https_only()
67/// .enable_http2()
68/// .build();
69///
70/// let executor = hyper_util::rt::TokioExecutor::new();
71/// let auth = yup_oauth2::InstalledFlowAuthenticator::with_client(
72/// secret,
73/// yup_oauth2::InstalledFlowReturnMethod::HTTPRedirect,
74/// yup_oauth2::client::CustomHyperClientBuilder::from(
75/// hyper_util::client::legacy::Client::builder(executor).build(connector),
76/// ),
77/// ).build().await.unwrap();
78///
79/// let client = hyper_util::client::legacy::Client::builder(
80/// hyper_util::rt::TokioExecutor::new()
81/// )
82/// .build(
83/// hyper_rustls::HttpsConnectorBuilder::new()
84/// .with_native_roots()
85/// .unwrap()
86/// .https_or_http()
87/// .enable_http2()
88/// .build()
89/// );
90/// let mut hub = Dfareporting::new(client, auth);
91/// // As the method needs a request, you would usually fill it with the desired information
92/// // into the respective structure. Some of the parts shown here might not be applicable !
93/// // Values shown here are possibly random and not representative !
94/// let mut req = CreativeAssetMetadata::default();
95///
96/// // You can configure optional parameters by calling the respective setters at will, and
97/// // execute the final call using `upload(...)`.
98/// // Values shown here are possibly random and not representative !
99/// let result = hub.media().upload(req, -28, -27)
100/// .upload(fs::File::open("file.ext").unwrap(), "application/octet-stream".parse().unwrap()).await;
101///
102/// match result {
103/// Err(e) => match e {
104/// // The Error enum provides details about what exactly happened.
105/// // You can also just use its `Debug`, `Display` or `Error` traits
106/// Error::HttpError(_)
107/// |Error::Io(_)
108/// |Error::MissingAPIKey
109/// |Error::MissingToken(_)
110/// |Error::Cancelled
111/// |Error::UploadSizeLimitExceeded(_, _)
112/// |Error::Failure(_)
113/// |Error::BadRequest(_)
114/// |Error::FieldClash(_)
115/// |Error::JsonDecodeError(_, _) => println!("{}", e),
116/// },
117/// Ok(res) => println!("Success: {:?}", res),
118/// }
119/// # }
120/// ```
121#[derive(Clone)]
122pub struct Dfareporting<C> {
123 pub client: common::Client<C>,
124 pub auth: Box<dyn common::GetToken>,
125 _user_agent: String,
126 _base_url: String,
127 _root_url: String,
128}
129
130impl<C> common::Hub for Dfareporting<C> {}
131
132impl<'a, C> Dfareporting<C> {
133 pub fn new<A: 'static + common::GetToken>(
134 client: common::Client<C>,
135 auth: A,
136 ) -> Dfareporting<C> {
137 Dfareporting {
138 client,
139 auth: Box::new(auth),
140 _user_agent: "google-api-rust-client/7.0.0".to_string(),
141 _base_url: "https://dfareporting.googleapis.com/dfareporting/v3.5/".to_string(),
142 _root_url: "https://dfareporting.googleapis.com/".to_string(),
143 }
144 }
145
146 pub fn media(&'a self) -> MediaMethods<'a, C> {
147 MediaMethods { hub: self }
148 }
149
150 /// Set the user-agent header field to use in all requests to the server.
151 /// It defaults to `google-api-rust-client/7.0.0`.
152 ///
153 /// Returns the previously set user-agent.
154 pub fn user_agent(&mut self, agent_name: String) -> String {
155 std::mem::replace(&mut self._user_agent, agent_name)
156 }
157
158 /// Set the base url to use in all requests to the server.
159 /// It defaults to `https://dfareporting.googleapis.com/dfareporting/v3.5/`.
160 ///
161 /// Returns the previously set base url.
162 pub fn base_url(&mut self, new_base_url: String) -> String {
163 std::mem::replace(&mut self._base_url, new_base_url)
164 }
165
166 /// Set the root url to use in all requests to the server.
167 /// It defaults to `https://dfareporting.googleapis.com/`.
168 ///
169 /// Returns the previously set root url.
170 pub fn root_url(&mut self, new_root_url: String) -> String {
171 std::mem::replace(&mut self._root_url, new_root_url)
172 }
173}
174
175// ############
176// SCHEMAS ###
177// ##########
178/// Creative Click Tag.
179///
180/// This type is not used in any activity, and only used as *part* of another schema.
181///
182#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
183#[serde_with::serde_as]
184#[derive(Default, Clone, Debug, serde::Serialize, serde::Deserialize)]
185pub struct ClickTag {
186 /// Parameter value for the specified click tag. This field contains a click-through url.
187 #[serde(rename = "clickThroughUrl")]
188 pub click_through_url: Option<CreativeClickThroughUrl>,
189 /// Advertiser event name associated with the click tag. This field is used by DISPLAY_IMAGE_GALLERY and HTML5_BANNER creatives. Applicable to DISPLAY when the primary asset type is not HTML_IMAGE.
190 #[serde(rename = "eventName")]
191 pub event_name: Option<String>,
192 /// Parameter name for the specified click tag. For DISPLAY_IMAGE_GALLERY creative assets, this field must match the value of the creative asset's creativeAssetId.name field.
193 pub name: Option<String>,
194}
195
196impl common::Part for ClickTag {}
197
198/// Creative Asset ID.
199///
200/// This type is not used in any activity, and only used as *part* of another schema.
201///
202#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
203#[serde_with::serde_as]
204#[derive(Default, Clone, Debug, serde::Serialize, serde::Deserialize)]
205pub struct CreativeAssetId {
206 /// Name of the creative asset. This is a required field while inserting an asset. After insertion, this assetIdentifier is used to identify the uploaded asset. Characters in the name must be alphanumeric or one of the following: ".-_ ". Spaces are allowed.
207 pub name: Option<String>,
208 /// Type of asset to upload. This is a required field. FLASH and IMAGE are no longer supported for new uploads. All image assets should use HTML_IMAGE.
209 #[serde(rename = "type")]
210 pub type_: Option<String>,
211}
212
213impl common::Part for CreativeAssetId {}
214
215/// CreativeAssets contains properties of a creative asset file which will be uploaded or has already been uploaded. Refer to the creative sample code for how to upload assets and insert a creative.
216///
217/// # Activities
218///
219/// This type is used in activities, which are methods you may call on this type or where this type is involved in.
220/// The list links the activity name, along with information about where it is used (one of *request* and *response*).
221///
222/// * [upload media](MediaUploadCall) (request|response)
223#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
224#[serde_with::serde_as]
225#[derive(Default, Clone, Debug, serde::Serialize, serde::Deserialize)]
226pub struct CreativeAssetMetadata {
227 /// ID of the creative asset. This is a required field.
228 #[serde(rename = "assetIdentifier")]
229 pub asset_identifier: Option<CreativeAssetId>,
230 /// List of detected click tags for assets. This is a read-only, auto-generated field. This field is empty for a rich media asset.
231 #[serde(rename = "clickTags")]
232 pub click_tags: Option<Vec<ClickTag>>,
233 /// List of counter events configured for the asset. This is a read-only, auto-generated field and only applicable to a rich media asset.
234 #[serde(rename = "counterCustomEvents")]
235 pub counter_custom_events: Option<Vec<CreativeCustomEvent>>,
236 /// List of feature dependencies for the creative asset that are detected by Campaign Manager. Feature dependencies are features that a browser must be able to support in order to render your HTML5 creative correctly. This is a read-only, auto-generated field.
237 #[serde(rename = "detectedFeatures")]
238 pub detected_features: Option<Vec<String>>,
239 /// List of exit events configured for the asset. This is a read-only, auto-generated field and only applicable to a rich media asset.
240 #[serde(rename = "exitCustomEvents")]
241 pub exit_custom_events: Option<Vec<CreativeCustomEvent>>,
242 /// Numeric ID of the asset. This is a read-only, auto-generated field.
243 #[serde_as(as = "Option<serde_with::DisplayFromStr>")]
244 pub id: Option<i64>,
245 /// Dimension value for the numeric ID of the asset. This is a read-only, auto-generated field.
246 #[serde(rename = "idDimensionValue")]
247 pub id_dimension_value: Option<DimensionValue>,
248 /// Identifies what kind of resource this is. Value: the fixed string "dfareporting#creativeAssetMetadata".
249 pub kind: Option<String>,
250 /// True if the uploaded asset is a rich media asset. This is a read-only, auto-generated field.
251 #[serde(rename = "richMedia")]
252 pub rich_media: Option<bool>,
253 /// List of timer events configured for the asset. This is a read-only, auto-generated field and only applicable to a rich media asset.
254 #[serde(rename = "timerCustomEvents")]
255 pub timer_custom_events: Option<Vec<CreativeCustomEvent>>,
256 /// Rules validated during code generation that generated a warning. This is a read-only, auto-generated field. Possible values are: - "ADMOB_REFERENCED" - "ASSET_FORMAT_UNSUPPORTED_DCM" - "ASSET_INVALID" - "CLICK_TAG_HARD_CODED" - "CLICK_TAG_INVALID" - "CLICK_TAG_IN_GWD" - "CLICK_TAG_MISSING" - "CLICK_TAG_MORE_THAN_ONE" - "CLICK_TAG_NON_TOP_LEVEL" - "COMPONENT_UNSUPPORTED_DCM" - "ENABLER_UNSUPPORTED_METHOD_DCM" - "EXTERNAL_FILE_REFERENCED" - "FILE_DETAIL_EMPTY" - "FILE_TYPE_INVALID" - "GWD_PROPERTIES_INVALID" - "HTML5_FEATURE_UNSUPPORTED" - "LINKED_FILE_NOT_FOUND" - "MAX_FLASH_VERSION_11" - "MRAID_REFERENCED" - "NOT_SSL_COMPLIANT" - "ORPHANED_ASSET" - "PRIMARY_HTML_MISSING" - "SVG_INVALID" - "ZIP_INVALID"
257 #[serde(rename = "warnedValidationRules")]
258 pub warned_validation_rules: Option<Vec<String>>,
259}
260
261impl common::RequestValue for CreativeAssetMetadata {}
262impl common::ResponseResult for CreativeAssetMetadata {}
263
264/// Click-through URL
265///
266/// This type is not used in any activity, and only used as *part* of another schema.
267///
268#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
269#[serde_with::serde_as]
270#[derive(Default, Clone, Debug, serde::Serialize, serde::Deserialize)]
271pub struct CreativeClickThroughUrl {
272 /// Read-only convenience field representing the actual URL that will be used for this click-through. The URL is computed as follows: - If landingPageId is specified then that landing page's URL is assigned to this field. - Otherwise, the customClickThroughUrl is assigned to this field.
273 #[serde(rename = "computedClickThroughUrl")]
274 pub computed_click_through_url: Option<String>,
275 /// Custom click-through URL. Applicable if the landingPageId field is left unset.
276 #[serde(rename = "customClickThroughUrl")]
277 pub custom_click_through_url: Option<String>,
278 /// ID of the landing page for the click-through URL.
279 #[serde(rename = "landingPageId")]
280 #[serde_as(as = "Option<serde_with::DisplayFromStr>")]
281 pub landing_page_id: Option<i64>,
282}
283
284impl common::Part for CreativeClickThroughUrl {}
285
286/// Creative Custom Event.
287///
288/// This type is not used in any activity, and only used as *part* of another schema.
289///
290#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
291#[serde_with::serde_as]
292#[derive(Default, Clone, Debug, serde::Serialize, serde::Deserialize)]
293pub struct CreativeCustomEvent {
294 /// Unique ID of this event used by Reporting and Data Transfer. This is a read-only field.
295 #[serde(rename = "advertiserCustomEventId")]
296 #[serde_as(as = "Option<serde_with::DisplayFromStr>")]
297 pub advertiser_custom_event_id: Option<i64>,
298 /// User-entered name for the event.
299 #[serde(rename = "advertiserCustomEventName")]
300 pub advertiser_custom_event_name: Option<String>,
301 /// Type of the event. This is a read-only field.
302 #[serde(rename = "advertiserCustomEventType")]
303 pub advertiser_custom_event_type: Option<String>,
304 /// Artwork label column, used to link events in Campaign Manager back to events in Studio. This is a required field and should not be modified after insertion.
305 #[serde(rename = "artworkLabel")]
306 pub artwork_label: Option<String>,
307 /// Artwork type used by the creative.This is a read-only field.
308 #[serde(rename = "artworkType")]
309 pub artwork_type: Option<String>,
310 /// Exit click-through URL for the event. This field is used only for exit events.
311 #[serde(rename = "exitClickThroughUrl")]
312 pub exit_click_through_url: Option<CreativeClickThroughUrl>,
313 /// ID of this event. This is a required field and should not be modified after insertion.
314 #[serde_as(as = "Option<serde_with::DisplayFromStr>")]
315 pub id: Option<i64>,
316 /// Properties for rich media popup windows. This field is used only for exit events.
317 #[serde(rename = "popupWindowProperties")]
318 pub popup_window_properties: Option<PopupWindowProperties>,
319 /// Target type used by the event.
320 #[serde(rename = "targetType")]
321 pub target_type: Option<String>,
322 /// Video reporting ID, used to differentiate multiple videos in a single creative. This is a read-only field.
323 #[serde(rename = "videoReportingId")]
324 pub video_reporting_id: Option<String>,
325}
326
327impl common::Part for CreativeCustomEvent {}
328
329/// Represents a DimensionValue resource.
330///
331/// This type is not used in any activity, and only used as *part* of another schema.
332///
333#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
334#[serde_with::serde_as]
335#[derive(Default, Clone, Debug, serde::Serialize, serde::Deserialize)]
336pub struct DimensionValue {
337 /// The name of the dimension.
338 #[serde(rename = "dimensionName")]
339 pub dimension_name: Option<String>,
340 /// The eTag of this response for caching purposes.
341 pub etag: Option<String>,
342 /// The ID associated with the value if available.
343 pub id: Option<String>,
344 /// The kind of resource this is, in this case dfareporting#dimensionValue.
345 pub kind: Option<String>,
346 /// Determines how the 'value' field is matched when filtering. If not specified, defaults to EXACT. If set to WILDCARD_EXPRESSION, '*' is allowed as a placeholder for variable length character sequences, and it can be escaped with a backslash. Note, only paid search dimensions ('dfa:paidSearch*') allow a matchType other than EXACT.
347 #[serde(rename = "matchType")]
348 pub match_type: Option<String>,
349 /// The value of the dimension.
350 pub value: Option<String>,
351}
352
353impl common::Part for DimensionValue {}
354
355/// Offset Position.
356///
357/// This type is not used in any activity, and only used as *part* of another schema.
358///
359#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
360#[serde_with::serde_as]
361#[derive(Default, Clone, Debug, serde::Serialize, serde::Deserialize)]
362pub struct OffsetPosition {
363 /// Offset distance from left side of an asset or a window.
364 pub left: Option<i32>,
365 /// Offset distance from top side of an asset or a window.
366 pub top: Option<i32>,
367}
368
369impl common::Part for OffsetPosition {}
370
371/// Popup Window Properties.
372///
373/// This type is not used in any activity, and only used as *part* of another schema.
374///
375#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
376#[serde_with::serde_as]
377#[derive(Default, Clone, Debug, serde::Serialize, serde::Deserialize)]
378pub struct PopupWindowProperties {
379 /// Popup dimension for a creative. This is a read-only field. Applicable to the following creative types: all RICH_MEDIA and all VPAID
380 pub dimension: Option<Size>,
381 /// Upper-left corner coordinates of the popup window. Applicable if positionType is COORDINATES.
382 pub offset: Option<OffsetPosition>,
383 /// Popup window position either centered or at specific coordinate.
384 #[serde(rename = "positionType")]
385 pub position_type: Option<String>,
386 /// Whether to display the browser address bar.
387 #[serde(rename = "showAddressBar")]
388 pub show_address_bar: Option<bool>,
389 /// Whether to display the browser menu bar.
390 #[serde(rename = "showMenuBar")]
391 pub show_menu_bar: Option<bool>,
392 /// Whether to display the browser scroll bar.
393 #[serde(rename = "showScrollBar")]
394 pub show_scroll_bar: Option<bool>,
395 /// Whether to display the browser status bar.
396 #[serde(rename = "showStatusBar")]
397 pub show_status_bar: Option<bool>,
398 /// Whether to display the browser tool bar.
399 #[serde(rename = "showToolBar")]
400 pub show_tool_bar: Option<bool>,
401 /// Title of popup window.
402 pub title: Option<String>,
403}
404
405impl common::Part for PopupWindowProperties {}
406
407/// Represents the dimensions of ads, placements, creatives, or creative assets.
408///
409/// This type is not used in any activity, and only used as *part* of another schema.
410///
411#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
412#[serde_with::serde_as]
413#[derive(Default, Clone, Debug, serde::Serialize, serde::Deserialize)]
414pub struct Size {
415 /// Height of this size. Acceptable values are 0 to 32767, inclusive.
416 pub height: Option<i32>,
417 /// IAB standard size. This is a read-only, auto-generated field.
418 pub iab: Option<bool>,
419 /// ID of this size. This is a read-only, auto-generated field.
420 #[serde_as(as = "Option<serde_with::DisplayFromStr>")]
421 pub id: Option<i64>,
422 /// Identifies what kind of resource this is. Value: the fixed string "dfareporting#size".
423 pub kind: Option<String>,
424 /// Width of this size. Acceptable values are 0 to 32767, inclusive.
425 pub width: Option<i32>,
426}
427
428impl common::Part for Size {}
429
430// ###################
431// MethodBuilders ###
432// #################
433
434/// A builder providing access to all methods supported on *media* resources.
435/// It is not used directly, but through the [`Dfareporting`] hub.
436///
437/// # Example
438///
439/// Instantiate a resource builder
440///
441/// ```test_harness,no_run
442/// extern crate hyper;
443/// extern crate hyper_rustls;
444/// extern crate google_dfareporting3d5 as dfareporting3d5;
445///
446/// # async fn dox() {
447/// use dfareporting3d5::{Dfareporting, FieldMask, hyper_rustls, hyper_util, yup_oauth2};
448///
449/// let secret: yup_oauth2::ApplicationSecret = Default::default();
450/// let connector = hyper_rustls::HttpsConnectorBuilder::new()
451/// .with_native_roots()
452/// .unwrap()
453/// .https_only()
454/// .enable_http2()
455/// .build();
456///
457/// let executor = hyper_util::rt::TokioExecutor::new();
458/// let auth = yup_oauth2::InstalledFlowAuthenticator::with_client(
459/// secret,
460/// yup_oauth2::InstalledFlowReturnMethod::HTTPRedirect,
461/// yup_oauth2::client::CustomHyperClientBuilder::from(
462/// hyper_util::client::legacy::Client::builder(executor).build(connector),
463/// ),
464/// ).build().await.unwrap();
465///
466/// let client = hyper_util::client::legacy::Client::builder(
467/// hyper_util::rt::TokioExecutor::new()
468/// )
469/// .build(
470/// hyper_rustls::HttpsConnectorBuilder::new()
471/// .with_native_roots()
472/// .unwrap()
473/// .https_or_http()
474/// .enable_http2()
475/// .build()
476/// );
477/// let mut hub = Dfareporting::new(client, auth);
478/// // Usually you wouldn't bind this to a variable, but keep calling *CallBuilders*
479/// // like `upload(...)`
480/// // to build up your call.
481/// let rb = hub.media();
482/// # }
483/// ```
484pub struct MediaMethods<'a, C>
485where
486 C: 'a,
487{
488 hub: &'a Dfareporting<C>,
489}
490
491impl<'a, C> common::MethodsBuilder for MediaMethods<'a, C> {}
492
493impl<'a, C> MediaMethods<'a, C> {
494 /// Create a builder to help you perform the following task:
495 ///
496 /// Inserts a new creative asset.
497 ///
498 /// # Arguments
499 ///
500 /// * `request` - No description provided.
501 /// * `profileId` - User profile ID associated with this request.
502 /// * `advertiserId` - Advertiser ID of this creative. This is a required field.
503 pub fn upload(
504 &self,
505 request: CreativeAssetMetadata,
506 profile_id: i64,
507 advertiser_id: i64,
508 ) -> MediaUploadCall<'a, C> {
509 MediaUploadCall {
510 hub: self.hub,
511 _request: request,
512 _profile_id: profile_id,
513 _advertiser_id: advertiser_id,
514 _delegate: Default::default(),
515 _additional_params: Default::default(),
516 _scopes: Default::default(),
517 }
518 }
519}
520
521// ###################
522// CallBuilders ###
523// #################
524
525/// Inserts a new creative asset.
526///
527/// A builder for the *upload* method supported by a *media* resource.
528/// It is not used directly, but through a [`MediaMethods`] instance.
529///
530/// # Example
531///
532/// Instantiate a resource method builder
533///
534/// ```test_harness,no_run
535/// # extern crate hyper;
536/// # extern crate hyper_rustls;
537/// # extern crate google_dfareporting3d5 as dfareporting3d5;
538/// use dfareporting3d5::api::CreativeAssetMetadata;
539/// use std::fs;
540/// # async fn dox() {
541/// # use dfareporting3d5::{Dfareporting, FieldMask, hyper_rustls, hyper_util, yup_oauth2};
542///
543/// # let secret: yup_oauth2::ApplicationSecret = Default::default();
544/// # let connector = hyper_rustls::HttpsConnectorBuilder::new()
545/// # .with_native_roots()
546/// # .unwrap()
547/// # .https_only()
548/// # .enable_http2()
549/// # .build();
550///
551/// # let executor = hyper_util::rt::TokioExecutor::new();
552/// # let auth = yup_oauth2::InstalledFlowAuthenticator::with_client(
553/// # secret,
554/// # yup_oauth2::InstalledFlowReturnMethod::HTTPRedirect,
555/// # yup_oauth2::client::CustomHyperClientBuilder::from(
556/// # hyper_util::client::legacy::Client::builder(executor).build(connector),
557/// # ),
558/// # ).build().await.unwrap();
559///
560/// # let client = hyper_util::client::legacy::Client::builder(
561/// # hyper_util::rt::TokioExecutor::new()
562/// # )
563/// # .build(
564/// # hyper_rustls::HttpsConnectorBuilder::new()
565/// # .with_native_roots()
566/// # .unwrap()
567/// # .https_or_http()
568/// # .enable_http2()
569/// # .build()
570/// # );
571/// # let mut hub = Dfareporting::new(client, auth);
572/// // As the method needs a request, you would usually fill it with the desired information
573/// // into the respective structure. Some of the parts shown here might not be applicable !
574/// // Values shown here are possibly random and not representative !
575/// let mut req = CreativeAssetMetadata::default();
576///
577/// // You can configure optional parameters by calling the respective setters at will, and
578/// // execute the final call using `upload(...)`.
579/// // Values shown here are possibly random and not representative !
580/// let result = hub.media().upload(req, -8, -80)
581/// .upload(fs::File::open("file.ext").unwrap(), "application/octet-stream".parse().unwrap()).await;
582/// # }
583/// ```
584pub struct MediaUploadCall<'a, C>
585where
586 C: 'a,
587{
588 hub: &'a Dfareporting<C>,
589 _request: CreativeAssetMetadata,
590 _profile_id: i64,
591 _advertiser_id: i64,
592 _delegate: Option<&'a mut dyn common::Delegate>,
593 _additional_params: HashMap<String, String>,
594 _scopes: BTreeSet<String>,
595}
596
597impl<'a, C> common::CallBuilder for MediaUploadCall<'a, C> {}
598
599impl<'a, C> MediaUploadCall<'a, C>
600where
601 C: common::Connector,
602{
603 /// Perform the operation you have build so far.
604 async fn doit<RS>(
605 mut self,
606 mut reader: RS,
607 reader_mime_type: mime::Mime,
608 protocol: common::UploadProtocol,
609 ) -> common::Result<(common::Response, CreativeAssetMetadata)>
610 where
611 RS: common::ReadSeek,
612 {
613 use std::borrow::Cow;
614 use std::io::{Read, Seek};
615
616 use common::{url::Params, ToParts};
617 use hyper::header::{AUTHORIZATION, CONTENT_LENGTH, CONTENT_TYPE, LOCATION, USER_AGENT};
618
619 let mut dd = common::DefaultDelegate;
620 let mut dlg: &mut dyn common::Delegate = self._delegate.unwrap_or(&mut dd);
621 dlg.begin(common::MethodInfo {
622 id: "dfareporting.media.upload",
623 http_method: hyper::Method::POST,
624 });
625
626 for &field in ["alt", "profileId", "advertiserId"].iter() {
627 if self._additional_params.contains_key(field) {
628 dlg.finished(false);
629 return Err(common::Error::FieldClash(field));
630 }
631 }
632
633 let mut params = Params::with_capacity(5 + self._additional_params.len());
634 params.push("profileId", self._profile_id.to_string());
635 params.push("advertiserId", self._advertiser_id.to_string());
636
637 params.extend(self._additional_params.iter());
638
639 params.push("alt", "json");
640 let (mut url, upload_type) = if protocol == common::UploadProtocol::Simple {
641 (self.hub._root_url.clone() + "upload/dfareporting/v3.5/userprofiles/{+profileId}/creativeAssets/{+advertiserId}/creativeAssets", "multipart")
642 } else {
643 unreachable!()
644 };
645 params.push("uploadType", upload_type);
646 if self._scopes.is_empty() {
647 self._scopes
648 .insert(Scope::Dfatrafficking.as_ref().to_string());
649 }
650
651 #[allow(clippy::single_element_loop)]
652 for &(find_this, param_name) in [
653 ("{+profileId}", "profileId"),
654 ("{+advertiserId}", "advertiserId"),
655 ]
656 .iter()
657 {
658 url = params.uri_replacement(url, param_name, find_this, true);
659 }
660 {
661 let to_remove = ["advertiserId", "profileId"];
662 params.remove_params(&to_remove);
663 }
664
665 let url = params.parse_with_url(&url);
666
667 let mut json_mime_type = mime::APPLICATION_JSON;
668 let mut request_value_reader = {
669 let mut value = serde_json::value::to_value(&self._request).expect("serde to work");
670 common::remove_json_null_values(&mut value);
671 let mut dst = std::io::Cursor::new(Vec::with_capacity(128));
672 serde_json::to_writer(&mut dst, &value).unwrap();
673 dst
674 };
675 let request_size = request_value_reader
676 .seek(std::io::SeekFrom::End(0))
677 .unwrap();
678 request_value_reader
679 .seek(std::io::SeekFrom::Start(0))
680 .unwrap();
681
682 loop {
683 let token = match self
684 .hub
685 .auth
686 .get_token(&self._scopes.iter().map(String::as_str).collect::<Vec<_>>()[..])
687 .await
688 {
689 Ok(token) => token,
690 Err(e) => match dlg.token(e) {
691 Ok(token) => token,
692 Err(e) => {
693 dlg.finished(false);
694 return Err(common::Error::MissingToken(e));
695 }
696 },
697 };
698 request_value_reader
699 .seek(std::io::SeekFrom::Start(0))
700 .unwrap();
701 let mut req_result = {
702 let mut mp_reader: common::MultiPartReader = Default::default();
703 let (mut body_reader, content_type) = match protocol {
704 common::UploadProtocol::Simple => {
705 mp_reader.reserve_exact(2);
706 let size = reader.seek(std::io::SeekFrom::End(0)).unwrap();
707 reader.seek(std::io::SeekFrom::Start(0)).unwrap();
708 if size > 1073741824 {
709 return Err(common::Error::UploadSizeLimitExceeded(size, 1073741824));
710 }
711 mp_reader
712 .add_part(
713 &mut request_value_reader,
714 request_size,
715 json_mime_type.clone(),
716 )
717 .add_part(&mut reader, size, reader_mime_type.clone());
718 (
719 &mut mp_reader as &mut (dyn std::io::Read + Send),
720 common::MultiPartReader::mime_type(),
721 )
722 }
723 _ => (
724 &mut request_value_reader as &mut (dyn std::io::Read + Send),
725 json_mime_type.clone(),
726 ),
727 };
728 let client = &self.hub.client;
729 dlg.pre_request();
730 let mut req_builder = hyper::Request::builder()
731 .method(hyper::Method::POST)
732 .uri(url.as_str())
733 .header(USER_AGENT, self.hub._user_agent.clone());
734
735 if let Some(token) = token.as_ref() {
736 req_builder = req_builder.header(AUTHORIZATION, format!("Bearer {}", token));
737 }
738
739 let mut body_reader_bytes = vec![];
740 body_reader.read_to_end(&mut body_reader_bytes).unwrap();
741 let request = req_builder
742 .header(CONTENT_TYPE, content_type.to_string())
743 .body(common::to_body(body_reader_bytes.into()));
744
745 client.request(request.unwrap()).await
746 };
747
748 match req_result {
749 Err(err) => {
750 if let common::Retry::After(d) = dlg.http_error(&err) {
751 sleep(d).await;
752 continue;
753 }
754 dlg.finished(false);
755 return Err(common::Error::HttpError(err));
756 }
757 Ok(res) => {
758 let (mut parts, body) = res.into_parts();
759 let mut body = common::Body::new(body);
760 if !parts.status.is_success() {
761 let bytes = common::to_bytes(body).await.unwrap_or_default();
762 let error = serde_json::from_str(&common::to_string(&bytes));
763 let response = common::to_response(parts, bytes.into());
764
765 if let common::Retry::After(d) =
766 dlg.http_failure(&response, error.as_ref().ok())
767 {
768 sleep(d).await;
769 continue;
770 }
771
772 dlg.finished(false);
773
774 return Err(match error {
775 Ok(value) => common::Error::BadRequest(value),
776 _ => common::Error::Failure(response),
777 });
778 }
779 let response = {
780 let bytes = common::to_bytes(body).await.unwrap_or_default();
781 let encoded = common::to_string(&bytes);
782 match serde_json::from_str(&encoded) {
783 Ok(decoded) => (common::to_response(parts, bytes.into()), decoded),
784 Err(error) => {
785 dlg.response_json_decode_error(&encoded, &error);
786 return Err(common::Error::JsonDecodeError(
787 encoded.to_string(),
788 error,
789 ));
790 }
791 }
792 };
793
794 dlg.finished(true);
795 return Ok(response);
796 }
797 }
798 }
799 }
800
801 /// Upload media all at once.
802 /// If the upload fails for whichever reason, all progress is lost.
803 ///
804 /// * *multipart*: yes
805 /// * *max size*: 1073741824
806 /// * *valid mime types*: '*/*'
807 pub async fn upload<RS>(
808 self,
809 stream: RS,
810 mime_type: mime::Mime,
811 ) -> common::Result<(common::Response, CreativeAssetMetadata)>
812 where
813 RS: common::ReadSeek,
814 {
815 self.doit(stream, mime_type, common::UploadProtocol::Simple)
816 .await
817 }
818
819 ///
820 /// Sets the *request* property to the given value.
821 ///
822 /// Even though the property as already been set when instantiating this call,
823 /// we provide this method for API completeness.
824 pub fn request(mut self, new_value: CreativeAssetMetadata) -> MediaUploadCall<'a, C> {
825 self._request = new_value;
826 self
827 }
828 /// User profile ID associated with this request.
829 ///
830 /// Sets the *profile id* path property to the given value.
831 ///
832 /// Even though the property as already been set when instantiating this call,
833 /// we provide this method for API completeness.
834 pub fn profile_id(mut self, new_value: i64) -> MediaUploadCall<'a, C> {
835 self._profile_id = new_value;
836 self
837 }
838 /// Advertiser ID of this creative. This is a required field.
839 ///
840 /// Sets the *advertiser id* path property to the given value.
841 ///
842 /// Even though the property as already been set when instantiating this call,
843 /// we provide this method for API completeness.
844 pub fn advertiser_id(mut self, new_value: i64) -> MediaUploadCall<'a, C> {
845 self._advertiser_id = new_value;
846 self
847 }
848 /// The delegate implementation is consulted whenever there is an intermediate result, or if something goes wrong
849 /// while executing the actual API request.
850 ///
851 /// ````text
852 /// It should be used to handle progress information, and to implement a certain level of resilience.
853 /// ````
854 ///
855 /// Sets the *delegate* property to the given value.
856 pub fn delegate(mut self, new_value: &'a mut dyn common::Delegate) -> MediaUploadCall<'a, C> {
857 self._delegate = Some(new_value);
858 self
859 }
860
861 /// Set any additional parameter of the query string used in the request.
862 /// It should be used to set parameters which are not yet available through their own
863 /// setters.
864 ///
865 /// Please note that this method must not be used to set any of the known parameters
866 /// which have their own setter method. If done anyway, the request will fail.
867 ///
868 /// # Additional Parameters
869 ///
870 /// * *$.xgafv* (query-string) - V1 error format.
871 /// * *access_token* (query-string) - OAuth access token.
872 /// * *alt* (query-string) - Data format for response.
873 /// * *callback* (query-string) - JSONP
874 /// * *fields* (query-string) - Selector specifying which fields to include in a partial response.
875 /// * *key* (query-string) - API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token.
876 /// * *oauth_token* (query-string) - OAuth 2.0 token for the current user.
877 /// * *prettyPrint* (query-boolean) - Returns response with indentations and line breaks.
878 /// * *quotaUser* (query-string) - Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters.
879 /// * *uploadType* (query-string) - Legacy upload protocol for media (e.g. "media", "multipart").
880 /// * *upload_protocol* (query-string) - Upload protocol for media (e.g. "raw", "multipart").
881 pub fn param<T>(mut self, name: T, value: T) -> MediaUploadCall<'a, C>
882 where
883 T: AsRef<str>,
884 {
885 self._additional_params
886 .insert(name.as_ref().to_string(), value.as_ref().to_string());
887 self
888 }
889
890 /// Identifies the authorization scope for the method you are building.
891 ///
892 /// Use this method to actively specify which scope should be used, instead of the default [`Scope`] variant
893 /// [`Scope::Dfatrafficking`].
894 ///
895 /// The `scope` will be added to a set of scopes. This is important as one can maintain access
896 /// tokens for more than one scope.
897 ///
898 /// Usually there is more than one suitable scope to authorize an operation, some of which may
899 /// encompass more rights than others. For example, for listing resources, a *read-only* scope will be
900 /// sufficient, a read-write scope will do as well.
901 pub fn add_scope<St>(mut self, scope: St) -> MediaUploadCall<'a, C>
902 where
903 St: AsRef<str>,
904 {
905 self._scopes.insert(String::from(scope.as_ref()));
906 self
907 }
908 /// Identifies the authorization scope(s) for the method you are building.
909 ///
910 /// See [`Self::add_scope()`] for details.
911 pub fn add_scopes<I, St>(mut self, scopes: I) -> MediaUploadCall<'a, C>
912 where
913 I: IntoIterator<Item = St>,
914 St: AsRef<str>,
915 {
916 self._scopes
917 .extend(scopes.into_iter().map(|s| String::from(s.as_ref())));
918 self
919 }
920
921 /// Removes all scopes, and no default scope will be used either.
922 /// In this case, you have to specify your API-key using the `key` parameter (see [`Self::param()`]
923 /// for details).
924 pub fn clear_scopes(mut self) -> MediaUploadCall<'a, C> {
925 self._scopes.clear();
926 self
927 }
928}