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}