Skip to main content

rustigram_types/
story.rs

1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Serialize, Deserialize)]
4/// A Telegram Story posted by a user or channel.
5pub struct Story {
6    /// The chat that posted the story.
7    pub chat: crate::chat::Chat,
8    /// Unique identifier of the story in that chat.
9    pub id: i64,
10}
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
13/// The position and size of a story area overlay.
14pub struct StoryAreaPosition {
15    /// Horizontal position as a percentage of the story width (0–100).
16    pub x_percentage: f64,
17    /// Vertical position as a percentage of the story height (0–100).
18    pub y_percentage: f64,
19    /// Width of the area as a percentage of the story width (0–100).
20    pub width_percentage: f64,
21    /// Height of the area as a percentage of the story height (0–100).
22    pub height_percentage: f64,
23    /// Rotation angle of the area in degrees (0–360).
24    pub rotation_angle: f64,
25    /// Corner radius of the area as a percentage of the shorter side (0–100).
26    pub corner_radius_percentage: f64,
27}
28
29/// The type of interactive area overlaid on a story.
30#[derive(Debug, Clone, Serialize, Deserialize)]
31#[serde(tag = "type", rename_all = "snake_case")]
32pub enum StoryAreaType {
33    /// An area pointing to a geographic location.
34    Location {
35        /// The geographic location.
36        location: crate::chat::Location,
37        /// Optional human-readable address.
38        #[serde(skip_serializing_if = "Option::is_none")]
39        address: Option<LocationAddress>,
40    },
41    /// An area for a suggested emoji reaction.
42    SuggestedReaction {
43        /// The reaction type.
44        reaction_type: crate::message::ReactionType,
45        /// `true` to display a dark background for the reaction.
46        #[serde(skip_serializing_if = "Option::is_none")]
47        is_dark: Option<bool>,
48        /// `true` to mirror the reaction emoji.
49        #[serde(skip_serializing_if = "Option::is_none")]
50        is_flipped: Option<bool>,
51    },
52    /// An area that links to a URL.
53    Link {
54        /// The URL to open.
55        url: String,
56    },
57    /// An area showing weather information.
58    Weather {
59        /// Temperature in Celsius.
60        temperature: f64,
61        /// Weather emoji.
62        emoji: String,
63        /// Background color as an ARGB integer.
64        background_color: i32,
65    },
66    /// An area highlighting a unique gift.
67    UniqueGift {
68        /// Name of the unique gift.
69        name: String,
70    },
71}
72
73/// A human-readable address associated with a location.
74#[derive(Debug, Clone, Serialize, Deserialize)]
75pub struct LocationAddress {
76    /// Two-letter ISO 3166-1 alpha-2 country code.
77    pub country_code: String,
78    /// State or region name.
79    #[serde(skip_serializing_if = "Option::is_none")]
80    pub state: Option<String>,
81    /// City name.
82    #[serde(skip_serializing_if = "Option::is_none")]
83    pub city: Option<String>,
84    /// Street name and number.
85    #[serde(skip_serializing_if = "Option::is_none")]
86    pub street: Option<String>,
87}
88
89#[derive(Debug, Clone, Serialize, Deserialize)]
90/// An interactive area overlaid on a story frame.
91///
92/// Areas can represent locations, reactions, links, weather widgets, or
93/// unique gift labels. Used when posting stories via the Business API.
94pub struct StoryArea {
95    /// Position and size of the area.
96    pub position: StoryAreaPosition,
97    /// Type and content of the area.
98    #[serde(rename = "type")]
99    pub kind: StoryAreaType,
100}
101
102// ─── InputStoryContent ────────────────────────────────────────────────────────
103
104/// A photo to post as a story.
105#[derive(Debug, Clone, Serialize, Deserialize)]
106pub struct InputStoryContentPhoto {
107    /// The photo to post.
108    ///
109    /// Must be 1080×1920 pixels, ≤10 MB.
110    /// Pass a `file_id`, HTTP URL, or `"attach://<name>"` for a multipart upload.
111    pub photo: String,
112}
113
114/// A video to post as a story.
115#[derive(Debug, Clone, Serialize, Deserialize)]
116pub struct InputStoryContentVideo {
117    /// The video to post.
118    ///
119    /// Must be 720×1280, streamable H.265, with key frames every second, ≤30 MB.
120    /// Pass a `file_id`, HTTP URL, or `"attach://<name>"` for a multipart upload.
121    pub video: String,
122    /// Precise duration of the video in seconds (0–60).
123    #[serde(skip_serializing_if = "Option::is_none")]
124    pub duration: Option<f64>,
125    /// Timestamp in seconds of the frame to use as the static cover. Defaults to `0.0`.
126    #[serde(skip_serializing_if = "Option::is_none")]
127    pub cover_frame_timestamp: Option<f64>,
128    /// Pass `true` if the video has no sound.
129    #[serde(skip_serializing_if = "Option::is_none")]
130    pub is_animation: Option<bool>,
131}
132
133/// The content of a story to post or edit.
134///
135/// Pass to [`postStory`](https://core.telegram.org/bots/api#poststory) and
136/// [`editStory`](https://core.telegram.org/bots/api#editstory) as a
137/// `serde_json::Value` — use `serde_json::to_value(&content)`.
138#[derive(Debug, Clone, Serialize, Deserialize)]
139#[serde(tag = "type", rename_all = "snake_case")]
140pub enum InputStoryContent {
141    /// A photo story.
142    Photo(InputStoryContentPhoto),
143    /// A video story.
144    Video(InputStoryContentVideo),
145}