This commit is contained in:
Mikhail Kilin
2026-01-27 23:29:00 +03:00
parent 356d2d3064
commit f291191577
8 changed files with 923 additions and 43 deletions

View File

@@ -137,6 +137,17 @@ pub struct ForwardInfo {
pub date: i32,
}
/// Информация о реакции на сообщение
#[derive(Debug, Clone)]
pub struct ReactionInfo {
/// Эмодзи реакции (например, "👍")
pub emoji: String,
/// Количество людей, поставивших эту реакцию
pub count: i32,
/// Поставил ли текущий пользователь эту реакцию
pub is_chosen: bool,
}
#[derive(Debug, Clone)]
pub struct MessageInfo {
pub id: i64,
@@ -159,6 +170,8 @@ pub struct MessageInfo {
pub reply_to: Option<ReplyInfo>,
/// Информация о forward (если сообщение переслано)
pub forward_from: Option<ForwardInfo>,
/// Реакции на сообщение
pub reactions: Vec<ReactionInfo>,
}
#[derive(Debug, Clone)]
@@ -623,6 +636,37 @@ impl TdClient {
});
}
}
Update::MessageInteractionInfo(update) => {
// Обновляем реакции в текущем открытом чате
if Some(update.chat_id) == self.current_chat_id {
if let Some(msg) = self.current_chat_messages.iter_mut().find(|m| m.id == update.message_id) {
// Извлекаем реакции из interaction_info
msg.reactions = update
.interaction_info
.as_ref()
.and_then(|info| info.reactions.as_ref())
.map(|reactions| {
reactions
.reactions
.iter()
.filter_map(|reaction| {
let emoji = match &reaction.r#type {
tdlib_rs::enums::ReactionType::Emoji(e) => e.emoji.clone(),
tdlib_rs::enums::ReactionType::CustomEmoji(_) => return None,
};
Some(ReactionInfo {
emoji,
count: reaction.total_count,
is_chosen: reaction.is_chosen,
})
})
.collect()
})
.unwrap_or_default();
}
}
}
_ => {}
}
}
@@ -789,6 +833,9 @@ impl TdClient {
// Извлекаем информацию о forward
let forward_from = self.extract_forward_info(message);
// Извлекаем реакции
let reactions = self.extract_reactions(message);
MessageInfo {
id: message.id,
sender_name,
@@ -803,6 +850,7 @@ impl TdClient {
can_be_deleted_for_all_users: message.can_be_deleted_for_all_users,
reply_to,
forward_from,
reactions,
}
}
@@ -859,6 +907,34 @@ impl TdClient {
})
}
/// Извлекает информацию о реакциях из сообщения
fn extract_reactions(&self, message: &TdMessage) -> Vec<ReactionInfo> {
message
.interaction_info
.as_ref()
.and_then(|info| info.reactions.as_ref())
.map(|reactions| {
reactions
.reactions
.iter()
.filter_map(|reaction| {
// Извлекаем эмодзи из ReactionType
let emoji = match &reaction.r#type {
tdlib_rs::enums::ReactionType::Emoji(e) => e.emoji.clone(),
tdlib_rs::enums::ReactionType::CustomEmoji(_) => return None, // Пока игнорируем custom emoji
};
Some(ReactionInfo {
emoji,
count: reaction.total_count,
is_chosen: reaction.is_chosen,
})
})
.collect()
})
.unwrap_or_default()
}
/// Получает имя отправителя из MessageOrigin
fn get_origin_sender_name(&self, origin: &tdlib_rs::enums::MessageOrigin) -> String {
use tdlib_rs::enums::MessageOrigin;
@@ -1504,12 +1580,96 @@ impl TdClient {
can_be_deleted_for_all_users: msg.can_be_deleted_for_all_users,
reply_to: reply_info,
forward_from: None,
reactions: Vec::new(),
})
}
Err(e) => Err(format!("Ошибка отправки сообщения: {:?}", e)),
}
}
/// Получить доступные реакции для сообщения
pub async fn get_message_available_reactions(
&mut self,
chat_id: i64,
message_id: i64,
) -> Result<Vec<String>, String> {
use tdlib_rs::functions;
let result = functions::get_message_available_reactions(
chat_id,
message_id,
8, // row_size - количество реакций в ряду
self.client_id,
)
.await;
match result {
Ok(tdlib_rs::enums::AvailableReactions::AvailableReactions(reactions)) => {
// Извлекаем эмодзи из доступных реакций
// Используем top_reactions (самые популярные реакции)
let mut emojis: Vec<String> = reactions
.top_reactions
.iter()
.filter_map(|reaction| {
if let tdlib_rs::enums::ReactionType::Emoji(e) = &reaction.r#type {
Some(e.emoji.clone())
} else {
None
}
})
.collect();
// Если top_reactions пустой, используем popular_reactions
if emojis.is_empty() {
emojis = reactions
.popular_reactions
.iter()
.filter_map(|reaction| {
if let tdlib_rs::enums::ReactionType::Emoji(e) = &reaction.r#type {
Some(e.emoji.clone())
} else {
None
}
})
.collect();
}
Ok(emojis)
}
Err(e) => Err(format!("Ошибка получения реакций: {:?}", e)),
}
}
/// Добавить реакцию на сообщение (или убрать, если уже поставлена)
pub async fn toggle_reaction(
&mut self,
chat_id: i64,
message_id: i64,
emoji: String,
) -> Result<(), String> {
use tdlib_rs::functions;
use tdlib_rs::types::ReactionTypeEmoji;
use tdlib_rs::enums::ReactionType;
let reaction_type = ReactionType::Emoji(ReactionTypeEmoji { emoji });
let result = functions::add_message_reaction(
chat_id,
message_id,
reaction_type,
false, // is_big - обычная реакция (не "большая" анимация)
true, // update_recent_reactions - обновить список недавних реакций
self.client_id,
)
.await;
match result {
Ok(_) => Ok(()),
Err(e) => Err(format!("Ошибка добавления реакции: {:?}", e)),
}
}
/// Редактирование текстового сообщения с поддержкой Markdown
/// Устанавливает черновик для чата через TDLib API
pub async fn set_draft_message(&self, chat_id: i64, text: String) -> Result<(), String> {
@@ -1616,6 +1776,7 @@ impl TdClient {
can_be_deleted_for_all_users: msg.can_be_deleted_for_all_users,
reply_to: None, // При редактировании reply сохраняется из оригинала
forward_from: None, // При редактировании forward сохраняется из оригинала
reactions: Vec::new(), // При редактировании реакции сохраняются из оригинала
})
}
Err(e) => Err(format!("Ошибка редактирования сообщения: {:?}", e)),