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
|
pub struct TelegramTransport {
tg: Client,
recipients: HashMap<String, ChatPeerId>,
pub default: ChatPeerId,
}
impl TelegramTransport {
/// Creates new TelegramTransport object.
pub fn new (api_key: String, recipients: HashMap<String, i64>, settings: &config::Config) -> Result<TelegramTransport> {
let default = settings.get_int("default")
.context("[smtp2tg.toml] missing \"default\" recipient.\n")?;
let api_gateway = settings.get_string("api_gateway")
.context("[smtp2tg.toml] missing \"api_gateway\" destination.\n")?;
let tg = Client::new(api_key)
.context("Failed to create API.\n")?
.with_host(api_gateway);
let recipients = recipients.into_iter()
.map(|(a, b)| (a, ChatPeerId::from(b))).collect();
let default = ChatPeerId::from(default);
Ok(TelegramTransport {
tg,
recipients,
default,
})
}
/// Send message to default user, used for debug/log/info purposes
pub async fn debug (&self, msg: &str) -> Result<Message> {
self.send(&self.default, format!("<pre>{}</pre>", validate(msg).stack()?)).await
}
/// Get recipient by address
pub fn get (&self, name: &str) -> Result<&ChatPeerId> {
self.recipients.get(name)
.with_context(|| format!("Recipient \"{name}\" not found in configuration"))
}
/// Send message to specified user
pub async fn send <S> (&self, to: &ChatPeerId, msg: S) -> Result<Message>
where S: Into<String> + Debug{
self.tg.execute(
SendMessage::new(*to, msg)
.with_parse_mode(Html)
).await.stack()
}
/// Send media to specified user
pub async fn sendgroup (&self, to: &ChatPeerId, media: Vec<Attachment>, msg: &str) -> Result<()> {
if media.len() > 1 {
let mut attach = vec![];
let mut pos = media.len();
for file in media {
let mut caption = InputMediaDocument::default();
if pos == 1 {
|
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
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
|
pub struct TelegramTransport {
tg: Client,
recipients: HashMap<String, ChatPeerId>,
pub default: ChatPeerId,
}
impl TelegramTransport {
/// Creates a new `TelegramTransport` instance.
///
/// # Arguments
/// * `api_key` - Telegram Bot API token.
/// * `recipients` - Mapping of email addresses to Telegram chat IDs.
/// * `settings` - Additional configuration (API gateway, default chat).
///
/// # Errors
/// Returns an error if API client creation fails.
pub fn new (api_key: String, recipients: HashMap<String, i64>, settings: &config::Config) -> Result<TelegramTransport> {
let default = settings.get_int("default")
.context("[smtp2tg.toml] missing \"default\" recipient.\n")?;
let api_gateway = settings.get_string("api_gateway")
.context("[smtp2tg.toml] missing \"api_gateway\" destination.\n")?;
let tg = Client::new(api_key)
.context("Failed to create API.\n")?
.with_host(api_gateway);
let recipients = recipients.into_iter()
.map(|(a, b)| (a, ChatPeerId::from(b))).collect();
let default = ChatPeerId::from(default);
Ok(TelegramTransport {
tg,
recipients,
default,
})
}
/// Sends a debug message to the default chat.
///
/// # Arguments
/// * `msg` - Message text to send.
///
/// # Returns
/// * `Result<Message>` - Telegram API response.
pub async fn debug (&self, msg: &str) -> Result<Message> {
self.send(&self.default, format!("<pre>{}</pre>", validate(msg).stack()?)).await
}
/// Retrieves a chat ID by name.
///
/// # Arguments
/// * `name` - Name or email to look up.
///
/// # Returns
/// * `Result<&ChatPeerId>` - Chat ID if found.
pub fn get (&self, name: &str) -> Result<&ChatPeerId> {
self.recipients.get(name)
.with_context(|| format!("Recipient \"{name}\" not found in configuration"))
}
/// Sends a text message to a specified chat.
///
/// # Arguments
/// * `to` - Target chat ID.
/// * `msg` - Message text (supports HTML formatting).
///
/// # Returns
/// * `Result<Message>` - Telegram API response.
pub async fn send <S> (&self, to: &ChatPeerId, msg: S) -> Result<Message>
where S: Into<String> + Debug{
self.tg.execute(
SendMessage::new(*to, msg)
.with_parse_mode(Html)
).await.stack()
}
/// Sends a message with attachments to a specified chat.
///
/// # Arguments
/// * `to` - Target chat ID.
/// * `media` - List of attachments.
/// * `msg` - Message text (supports HTML formatting).
///
/// # Returns
/// * `Result<()>` - Success or error.
pub async fn sendgroup (&self, to: &ChatPeerId, media: Vec<Attachment>, msg: &str) -> Result<()> {
if media.len() > 1 {
let mut attach = vec![];
let mut pos = media.len();
for file in media {
let mut caption = InputMediaDocument::default();
if pos == 1 {
|