refactor: complete large files/functions refactoring (Phase 6-7)
Phase 6: Refactor tdlib/client.rs ✅ - Extract update handlers to update_handlers.rs (302 lines, 8 functions) - Extract message converter to message_converter.rs (250 lines, 6 functions) - Extract chat helpers to chat_helpers.rs (149 lines, 3 functions) - Result: client.rs 1259 → 599 lines (-52%) Phase 7: Refactor tdlib/messages.rs ✅ - Create message_conversion.rs module (158 lines) - Extract 6 helper functions: - extract_content_text() - content extraction (~80 lines) - extract_entities() - formatting extraction (~10 lines) - extract_sender_name() - sender name with API call (~15 lines) - extract_forward_info() - forward info (~12 lines) - extract_reply_info() - reply info (~15 lines) - extract_reactions() - reactions extraction (~26 lines) - Result: convert_message() 150 → 57 lines (-62%) - Result: messages.rs 850 → 757 lines (-11%) Summary: - ✅ All 4 large files refactored (100%) - ✅ All 629 tests passing - ✅ Category #2 "Large files/functions" COMPLETE - ✅ Documentation updated (REFACTORING_OPPORTUNITIES.md, CONTEXT.md) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
158
src/tdlib/message_conversion.rs
Normal file
158
src/tdlib/message_conversion.rs
Normal file
@@ -0,0 +1,158 @@
|
||||
//! Вспомогательные функции для конвертации TDLib сообщений в MessageInfo
|
||||
//!
|
||||
//! Этот модуль содержит функции для извлечения различных частей сообщения
|
||||
//! из TDLib Message и конвертации их в наш внутренний формат MessageInfo.
|
||||
|
||||
use crate::types::MessageId;
|
||||
use tdlib_rs::enums::{MessageContent, MessageSender};
|
||||
use tdlib_rs::types::Message as TdMessage;
|
||||
|
||||
use super::types::{ForwardInfo, ReactionInfo, ReplyInfo};
|
||||
|
||||
/// Извлекает текст контента из TDLib Message
|
||||
///
|
||||
/// Обрабатывает различные типы сообщений (текст, фото, видео, стикеры, и т.д.)
|
||||
/// и возвращает текстовое представление.
|
||||
pub fn extract_content_text(msg: &TdMessage) -> String {
|
||||
match &msg.content {
|
||||
MessageContent::MessageText(t) => t.text.text.clone(),
|
||||
MessageContent::MessagePhoto(p) => {
|
||||
let caption_text = p.caption.text.clone();
|
||||
if caption_text.is_empty() {
|
||||
"[Фото]".to_string()
|
||||
} else {
|
||||
caption_text
|
||||
}
|
||||
}
|
||||
MessageContent::MessageVideo(v) => {
|
||||
let caption_text = v.caption.text.clone();
|
||||
if caption_text.is_empty() {
|
||||
"[Видео]".to_string()
|
||||
} else {
|
||||
caption_text
|
||||
}
|
||||
}
|
||||
MessageContent::MessageDocument(d) => {
|
||||
let caption_text = d.caption.text.clone();
|
||||
if caption_text.is_empty() {
|
||||
format!("[Файл: {}]", d.document.file_name)
|
||||
} else {
|
||||
caption_text
|
||||
}
|
||||
}
|
||||
MessageContent::MessageSticker(s) => {
|
||||
format!("[Стикер: {}]", s.sticker.emoji)
|
||||
}
|
||||
MessageContent::MessageAnimation(a) => {
|
||||
let caption_text = a.caption.text.clone();
|
||||
if caption_text.is_empty() {
|
||||
"[GIF]".to_string()
|
||||
} else {
|
||||
caption_text
|
||||
}
|
||||
}
|
||||
MessageContent::MessageVoiceNote(v) => {
|
||||
let caption_text = v.caption.text.clone();
|
||||
if caption_text.is_empty() {
|
||||
"[Голосовое]".to_string()
|
||||
} else {
|
||||
caption_text
|
||||
}
|
||||
}
|
||||
MessageContent::MessageAudio(a) => {
|
||||
let caption_text = a.caption.text.clone();
|
||||
if caption_text.is_empty() {
|
||||
let title = a.audio.title.clone();
|
||||
let performer = a.audio.performer.clone();
|
||||
if !title.is_empty() || !performer.is_empty() {
|
||||
format!("[Аудио: {} - {}]", performer, title)
|
||||
} else {
|
||||
"[Аудио]".to_string()
|
||||
}
|
||||
} else {
|
||||
caption_text
|
||||
}
|
||||
}
|
||||
_ => "[Неподдерживаемый тип сообщения]".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Извлекает entities (форматирование) из TDLib Message
|
||||
pub fn extract_entities(msg: &TdMessage) -> Vec<tdlib_rs::types::TextEntity> {
|
||||
if let MessageContent::MessageText(t) = &msg.content {
|
||||
t.text.entities.clone()
|
||||
} else {
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
|
||||
/// Извлекает имя отправителя из TDLib Message
|
||||
///
|
||||
/// Для пользователей делает API вызов get_user для получения имени.
|
||||
/// Для чатов возвращает ID чата.
|
||||
pub async fn extract_sender_name(msg: &TdMessage, client_id: i32) -> String {
|
||||
match &msg.sender_id {
|
||||
MessageSender::User(user) => {
|
||||
match tdlib_rs::functions::get_user(user.user_id, client_id).await {
|
||||
Ok(tdlib_rs::enums::User::User(u)) => {
|
||||
format!("{} {}", u.first_name, u.last_name).trim().to_string()
|
||||
}
|
||||
_ => format!("User {}", user.user_id),
|
||||
}
|
||||
}
|
||||
MessageSender::Chat(chat) => format!("Chat {}", chat.chat_id),
|
||||
}
|
||||
}
|
||||
|
||||
/// Извлекает информацию о пересылке из TDLib Message
|
||||
pub fn extract_forward_info(msg: &TdMessage) -> Option<ForwardInfo> {
|
||||
msg.forward_info.as_ref().and_then(|fi| {
|
||||
if let tdlib_rs::enums::MessageOrigin::User(origin_user) = &fi.origin {
|
||||
Some(ForwardInfo {
|
||||
sender_name: format!("User {}", origin_user.sender_user_id),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Извлекает информацию об ответе из TDLib Message
|
||||
pub fn extract_reply_info(msg: &TdMessage) -> Option<ReplyInfo> {
|
||||
msg.reply_to.as_ref().and_then(|reply_to| {
|
||||
if let tdlib_rs::enums::MessageReplyTo::Message(reply_msg) = reply_to {
|
||||
Some(ReplyInfo {
|
||||
message_id: MessageId::new(reply_msg.message_id),
|
||||
sender_name: "Unknown".to_string(),
|
||||
text: "...".to_string(),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Извлекает реакции из TDLib Message
|
||||
pub fn extract_reactions(msg: &TdMessage) -> Vec<ReactionInfo> {
|
||||
msg.interaction_info
|
||||
.as_ref()
|
||||
.and_then(|ii| ii.reactions.as_ref())
|
||||
.map(|reactions| {
|
||||
reactions
|
||||
.reactions
|
||||
.iter()
|
||||
.filter_map(|r| {
|
||||
if let tdlib_rs::enums::ReactionType::Emoji(emoji_type) = &r.r#type {
|
||||
Some(ReactionInfo {
|
||||
emoji: emoji_type.emoji.clone(),
|
||||
count: r.total_count,
|
||||
is_chosen: r.is_chosen,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.unwrap_or_default()
|
||||
}
|
||||
Reference in New Issue
Block a user