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