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 address: Option<LocationAddress>,
39 },
40 /// An area for a suggested emoji reaction.
41 SuggestedReaction {
42 /// The reaction type.
43 reaction_type: crate::message::ReactionType,
44 /// `true` to display a dark background for the reaction.
45 is_dark: Option<bool>,
46 /// `true` to mirror the reaction emoji.
47 is_flipped: Option<bool>,
48 },
49 /// An area that links to a URL.
50 Link {
51 /// The URL to open.
52 url: String,
53 },
54 /// An area showing weather information.
55 Weather {
56 /// Temperature in Celsius.
57 temperature: f64,
58 /// Weather emoji.
59 emoji: String,
60 /// Background color as an ARGB integer.
61 background_color: i32,
62 },
63 /// An area highlighting a unique gift.
64 UniqueGift {
65 /// Name of the unique gift.
66 name: String,
67 },
68}
69
70/// A human-readable address associated with a location.
71#[derive(Debug, Clone, Serialize, Deserialize)]
72pub struct LocationAddress {
73 /// Two-letter ISO 3166-1 alpha-2 country code.
74 pub country_code: String,
75 /// State or region name.
76 pub state: Option<String>,
77 /// City name.
78 pub city: Option<String>,
79 /// Street name and number.
80 pub street: Option<String>,
81}
82
83#[derive(Debug, Clone, Serialize, Deserialize)]
84/// An interactive area overlaid on a story frame.
85///
86/// Areas can represent locations, reactions, links, weather widgets, or
87/// unique gift labels. Used when posting stories via the Business API.
88pub struct StoryArea {
89 /// Position and size of the area.
90 pub position: StoryAreaPosition,
91 /// Type and content of the area.
92 #[serde(rename = "type")]
93 pub kind: StoryAreaType,
94}
95
96// ─── InputStoryContent ────────────────────────────────────────────────────────
97
98/// A photo to post as a story.
99#[derive(Debug, Clone, Serialize, Deserialize)]
100pub struct InputStoryContentPhoto {
101 /// The photo to post.
102 ///
103 /// Must be 1080×1920 pixels, ≤10 MB.
104 /// Pass a `file_id`, HTTP URL, or `"attach://<name>"` for a multipart upload.
105 pub photo: String,
106}
107
108/// A video to post as a story.
109#[derive(Debug, Clone, Serialize, Deserialize)]
110pub struct InputStoryContentVideo {
111 /// The video to post.
112 ///
113 /// Must be 720×1280, streamable H.265, with key frames every second, ≤30 MB.
114 /// Pass a `file_id`, HTTP URL, or `"attach://<name>"` for a multipart upload.
115 pub video: String,
116 /// Precise duration of the video in seconds (0–60).
117 #[serde(skip_serializing_if = "Option::is_none")]
118 pub duration: Option<f64>,
119 /// Timestamp in seconds of the frame to use as the static cover. Defaults to `0.0`.
120 #[serde(skip_serializing_if = "Option::is_none")]
121 pub cover_frame_timestamp: Option<f64>,
122 /// Pass `true` if the video has no sound.
123 #[serde(skip_serializing_if = "Option::is_none")]
124 pub is_animation: Option<bool>,
125}
126
127/// The content of a story to post or edit.
128///
129/// Pass to [`postStory`](https://core.telegram.org/bots/api#poststory) and
130/// [`editStory`](https://core.telegram.org/bots/api#editstory) as a
131/// `serde_json::Value` — use `serde_json::to_value(&content)`.
132#[derive(Debug, Clone, Serialize, Deserialize)]
133#[serde(tag = "type", rename_all = "snake_case")]
134pub enum InputStoryContent {
135 /// A photo story.
136 Photo(InputStoryContentPhoto),
137 /// A video story.
138 Video(InputStoryContentVideo),
139}