late 0.0.1137

API reference for Zernio. Authenticate with a Bearer API key. Base URL: https://zernio.com/api Versioning and deprecation: all endpoints are versioned in the URL path (current version: /v1). Breaking changes only ship in a new path version; existing versions keep working. Deprecated operations are marked 'deprecated: true' in this spec and announced in the changelog (https://zernio.com/changelog) before removal. Errors: every 4xx/5xx response is application/json with a machine-readable 'code' and a human-readable 'error' message (see the ErrorResponse schema). Request ids: responses carry an X-Request-Id header with the id we log the request under. Quote it when reporting a problem. A valid x-request-id you send is reused as that id.
Documentation
/*
 * Zernio API
 *
 * API reference for Zernio. Authenticate with a Bearer API key. Base URL: https://zernio.com/api  Versioning and deprecation: all endpoints are versioned in the URL path (current version: /v1). Breaking changes only ship in a new path version; existing versions keep working. Deprecated operations are marked 'deprecated: true' in this spec and announced in the changelog (https://zernio.com/changelog) before removal.  Errors: every 4xx/5xx response is application/json with a machine-readable 'code' and a human-readable 'error' message (see the ErrorResponse schema).  Request ids: responses carry an X-Request-Id header with the id we log the request under. Quote it when reporting a problem. A valid x-request-id you send is reused as that id.
 *
 * The version of the OpenAPI document: 1.226.1
 * Contact: support@zernio.com
 * Generated by: https://openapi-generator.tech
 */

use crate::models;
use serde::{Deserialize, Serialize};

#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
pub struct UpdateCommentAutomationRequest {
    #[serde(rename = "name", skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
    /// What fires the automation. Changing it detaches the automation from its bound post or story (a post id and a story id are different objects), unless this same request sets a new binding. Every trigger but 'comment' is Instagram only; 'story_mention' also requires no keywords and no binding.
    #[serde(rename = "trigger", skip_serializing_if = "Option::is_none")]
    pub trigger: Option<Trigger>,
    #[serde(rename = "keywords", skip_serializing_if = "Option::is_none")]
    pub keywords: Option<Vec<String>>,
    /// How a keyword is compared with the comment. 'contains' (default) matches anywhere, even inside another word (keyword 'app' fires on 'happy'). 'word' matches the keyword only as a standalone word. 'exact' requires the whole comment to be exactly the keyword.
    #[serde(rename = "matchMode", skip_serializing_if = "Option::is_none")]
    pub match_mode: Option<MatchMode>,
    /// Comments containing one of these never trigger the automation, even when a trigger keyword also matches. Compared using the same matchMode.
    #[serde(rename = "excludeKeywords", skip_serializing_if = "Option::is_none")]
    pub exclude_keywords: Option<Vec<String>>,
    /// Only with matchMode=word: also fire on close misspellings of a keyword (one edit for 4-7 character keywords, two from 8 up). Keywords shorter than 4 characters are never fuzzy-matched.
    #[serde(rename = "typoTolerance", skip_serializing_if = "Option::is_none")]
    pub typo_tolerance: Option<bool>,
    /// Re-binds the automation to another post: the platform media/post ID (or story media id when trigger=story_reply). postId, platformPostId and postTitle move as a unit: sending any of them replaces all three, and an omitted one is cleared. Send all three as null (or empty) to make it account-wide (any post / any story). Omit all three to keep the current binding. 409 when another active automation already owns the new post.
    #[serde(
        rename = "platformPostId",
        default,
        with = "::serde_with::rust::double_option",
        skip_serializing_if = "Option::is_none"
    )]
    pub platform_post_id: Option<Option<String>>,
    /// Zernio post ID (24 hexadecimal characters); platform IDs return 400. Use it INSTEAD of platformPostId to bind to a not-yet-published Zernio post: the automation stays pending and arms itself when that post publishes. Moves as a unit with platformPostId and postTitle (see platformPostId).
    #[serde(
        rename = "postId",
        default,
        with = "::serde_with::rust::double_option",
        skip_serializing_if = "Option::is_none"
    )]
    pub post_id: Option<Option<String>>,
    /// Post content snippet for display. Moves as a unit with platformPostId and postId (see platformPostId).
    #[serde(
        rename = "postTitle",
        default,
        with = "::serde_with::rust::double_option",
        skip_serializing_if = "Option::is_none"
    )]
    pub post_title: Option<Option<String>>,
    #[serde(rename = "dmMessage", skip_serializing_if = "Option::is_none")]
    pub dm_message: Option<String>,
    /// Inline DM buttons (1-3). Pass [] to clear all buttons.
    #[serde(rename = "buttons", skip_serializing_if = "Option::is_none")]
    pub buttons: Option<Vec<models::DmButton>>,
    #[serde(
        rename = "template",
        default,
        with = "::serde_with::rust::double_option",
        skip_serializing_if = "Option::is_none"
    )]
    pub template: Option<Option<Box<models::CommentAutomationTemplate>>>,
    #[serde(rename = "commentReply", skip_serializing_if = "Option::is_none")]
    pub comment_reply: Option<String>,
    /// Alternate DM texts for random rotation (see create). Pass [] to clear.
    #[serde(
        rename = "dmMessageVariations",
        skip_serializing_if = "Option::is_none"
    )]
    pub dm_message_variations: Option<Vec<String>>,
    /// Alternate public replies for random rotation. Pass [] to clear.
    #[serde(
        rename = "commentReplyVariations",
        skip_serializing_if = "Option::is_none"
    )]
    pub comment_reply_variations: Option<Vec<String>>,
    /// Wrap link buttons in a tracked redirect to count clicks. Pass false to send links untouched.
    #[serde(rename = "linkTracking", skip_serializing_if = "Option::is_none")]
    pub link_tracking: Option<bool>,
    /// Tag applied to a contact when they click a tracked link (requires linkTracking). Empty string clears it.
    #[serde(rename = "clickTag", skip_serializing_if = "Option::is_none")]
    pub click_tag: Option<String>,
    /// Also fire these keywords on a plain inbound DM. Enabling it requires the automation to end up with at least one keyword (this request's keywords if you send them, otherwise the stored ones) and is rejected on story_reply automations.
    #[serde(rename = "alsoMatchInDms", skip_serializing_if = "Option::is_none")]
    pub also_match_in_dms: Option<bool>,
    /// Seconds to wait after the trigger before sending the DM. Send 0 to clear the delay and reply immediately.
    #[serde(rename = "dmDelaySeconds", skip_serializing_if = "Option::is_none")]
    pub dm_delay_seconds: Option<i32>,
    /// Seconds to wait before posting the public comment reply. Send 0 to clear it. The reply never goes out before the DM.
    #[serde(
        rename = "commentReplyDelaySeconds",
        skip_serializing_if = "Option::is_none"
    )]
    pub comment_reply_delay_seconds: Option<i32>,
    #[serde(rename = "audience", skip_serializing_if = "Option::is_none")]
    pub audience: Option<Box<models::CommentAutomationAudience>>,
    #[serde(rename = "followGate", skip_serializing_if = "Option::is_none")]
    pub follow_gate: Option<Box<models::CommentAutomationFollowGate>>,
    #[serde(rename = "isActive", skip_serializing_if = "Option::is_none")]
    pub is_active: Option<bool>,
    #[serde(rename = "repeatPolicy", skip_serializing_if = "Option::is_none")]
    pub repeat_policy: Option<Box<models::CommentAutomationRepeatPolicy>>,
    /// Skip the DM when this recipient already received identical DM text (after personalisation) from this account, from any automation, within this many hours. The skip is logged with status skipped. Send null to clear.
    #[serde(
        rename = "dedupeSameTextHours",
        default,
        with = "::serde_with::rust::double_option",
        skip_serializing_if = "Option::is_none"
    )]
    pub dedupe_same_text_hours: Option<Option<i32>>,
    /// 'after_dm' posts commentReply only after a successful DM. 'always' posts it whatever the audience rule, dedupe or DM outcome: the moment a comment matches, or after commentReplyDelaySeconds when set (raised to dmDelaySeconds, so it never precedes the DM attempt).
    #[serde(rename = "publicReplyPolicy", skip_serializing_if = "Option::is_none")]
    pub public_reply_policy: Option<PublicReplyPolicy>,
    #[serde(rename = "actions", skip_serializing_if = "Option::is_none")]
    pub actions: Option<Box<models::CommentAutomationActions>>,
    /// Opt-in quick-reply chips on the DM (up to 13). Chips do not render in Message Requests, where a first DM to a cold commenter lands, so prefer buttons for first contact. Mutually exclusive with buttons and template (400). Send null to clear.
    #[serde(
        rename = "quickReplies",
        default,
        with = "::serde_with::rust::double_option",
        skip_serializing_if = "Option::is_none"
    )]
    pub quick_replies: Option<Option<Vec<models::CommentAutomationQuickReply>>>,
    #[serde(
        rename = "dmMedia",
        default,
        with = "::serde_with::rust::double_option",
        skip_serializing_if = "Option::is_none"
    )]
    pub dm_media: Option<Option<Box<models::CommentAutomationDmMedia>>>,
}

impl UpdateCommentAutomationRequest {
    pub fn new() -> UpdateCommentAutomationRequest {
        UpdateCommentAutomationRequest {
            name: None,
            trigger: None,
            keywords: None,
            match_mode: None,
            exclude_keywords: None,
            typo_tolerance: None,
            platform_post_id: None,
            post_id: None,
            post_title: None,
            dm_message: None,
            buttons: None,
            template: None,
            comment_reply: None,
            dm_message_variations: None,
            comment_reply_variations: None,
            link_tracking: None,
            click_tag: None,
            also_match_in_dms: None,
            dm_delay_seconds: None,
            comment_reply_delay_seconds: None,
            audience: None,
            follow_gate: None,
            is_active: None,
            repeat_policy: None,
            dedupe_same_text_hours: None,
            public_reply_policy: None,
            actions: None,
            quick_replies: None,
            dm_media: None,
        }
    }
}
/// What fires the automation. Changing it detaches the automation from its bound post or story (a post id and a story id are different objects), unless this same request sets a new binding. Every trigger but 'comment' is Instagram only; 'story_mention' also requires no keywords and no binding.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum Trigger {
    #[serde(rename = "comment")]
    Comment,
    #[serde(rename = "live_comment")]
    LiveComment,
    #[serde(rename = "story_reply")]
    StoryReply,
    #[serde(rename = "story_mention")]
    StoryMention,
}

impl Default for Trigger {
    fn default() -> Trigger {
        Self::Comment
    }
}
/// How a keyword is compared with the comment. 'contains' (default) matches anywhere, even inside another word (keyword 'app' fires on 'happy'). 'word' matches the keyword only as a standalone word. 'exact' requires the whole comment to be exactly the keyword.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum MatchMode {
    #[serde(rename = "exact")]
    Exact,
    #[serde(rename = "contains")]
    Contains,
    #[serde(rename = "word")]
    Word,
}

impl Default for MatchMode {
    fn default() -> MatchMode {
        Self::Exact
    }
}
/// 'after_dm' posts commentReply only after a successful DM. 'always' posts it whatever the audience rule, dedupe or DM outcome: the moment a comment matches, or after commentReplyDelaySeconds when set (raised to dmDelaySeconds, so it never precedes the DM attempt).
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum PublicReplyPolicy {
    #[serde(rename = "after_dm")]
    AfterDm,
    #[serde(rename = "always")]
    Always,
}

impl Default for PublicReplyPolicy {
    fn default() -> PublicReplyPolicy {
        Self::AfterDm
    }
}