//! Chat management helper functions. //! //! This module contains utility functions for managing chats, //! including finding, updating, and adding/removing chats. use crate::constants::{MAX_CHATS, MAX_CHAT_USER_IDS}; use crate::types::{ChatId, MessageId, UserId}; use tdlib_rs::enums::{Chat as TdChat, ChatList, ChatType}; use super::client::TdClient; use super::types::ChatInfo; /// Обновляет поле чата, если чат найден. pub fn update_chat(client: &mut TdClient, chat_id: ChatId, updater: F) where F: FnOnce(&mut ChatInfo), { client.update_chat(chat_id, updater); } /// Добавляет новый чат или обновляет существующий pub fn add_or_update_chat(client: &mut TdClient, td_chat_enum: &TdChat) { // Pattern match to get inner Chat struct let TdChat::Chat(td_chat) = td_chat_enum; // Пропускаем удалённые аккаунты if td_chat.title == "Deleted Account" || td_chat.title.is_empty() { // Удаляем из списка если уже был добавлен client.remove_chat(ChatId::new(td_chat.id)); return; } // Ищем позицию в Main списке (если есть) let main_position = td_chat .positions .iter() .find(|pos| matches!(pos.list, ChatList::Main)); // Получаем order и is_pinned из позиции, или используем значения по умолчанию let (order, is_pinned) = main_position .map(|p| (p.order, p.is_pinned)) .unwrap_or((1, false)); // order=1 чтобы чат отображался let (last_message, last_message_date) = td_chat .last_message .as_ref() .map(|m| (TdClient::extract_message_text_static(m).0, m.date)) .unwrap_or_default(); // Извлекаем user_id для приватных чатов и сохраняем связь let username = match &td_chat.r#type { ChatType::Private(private) => { // Ограничиваем размер chat_user_ids let chat_id = ChatId::new(td_chat.id); let user_id = UserId::new(private.user_id); client.update_user_cache(|cache| { if cache.chat_user_ids.len() >= MAX_CHAT_USER_IDS && !cache.chat_user_ids.contains_key(&chat_id) { // Удаляем случайную запись (первую найденную) if let Some(&key) = cache.chat_user_ids.keys().next() { cache.chat_user_ids.remove(&key); } } cache.chat_user_ids.insert(chat_id, user_id); // Проверяем, есть ли уже username в кэше (peek не обновляет LRU) cache .user_usernames .peek(&user_id) .map(|u| format!("@{}", u)) }) } _ => None, }; // Извлекаем ID папок из позиций let folder_ids: Vec = td_chat .positions .iter() .filter_map(|pos| match &pos.list { ChatList::Folder(folder) => Some(folder.chat_folder_id), _ => None, }) .collect(); // Проверяем mute статус let is_muted = td_chat.notification_settings.mute_for > 0; let chat_info = ChatInfo { id: ChatId::new(td_chat.id), title: td_chat.title.clone(), username, last_message, last_message_date, unread_count: td_chat.unread_count, unread_mention_count: td_chat.unread_mention_count, is_pinned, order, last_read_outbox_message_id: MessageId::new(td_chat.last_read_outbox_message_id), folder_ids, is_muted, draft_text: None, }; let chat_info_for_update = chat_info.clone(); let updated_existing = client.update_chat(ChatId::new(td_chat.id), |existing| { existing.title = chat_info_for_update.title; existing.last_message = chat_info_for_update.last_message; existing.last_message_date = chat_info_for_update.last_message_date; existing.unread_count = chat_info_for_update.unread_count; existing.unread_mention_count = chat_info_for_update.unread_mention_count; existing.last_read_outbox_message_id = chat_info_for_update.last_read_outbox_message_id; existing.folder_ids = chat_info_for_update.folder_ids; existing.is_muted = chat_info_for_update.is_muted; // Обновляем username если он появился if let Some(username) = chat_info_for_update.username { existing.username = Some(username); } // Обновляем позицию только если она пришла if main_position.is_some() { existing.is_pinned = chat_info_for_update.is_pinned; existing.order = chat_info_for_update.order; } }); if !updated_existing { client.push_chat(chat_info); // Ограничиваем количество чатов client.trim_chats_to_max_by_order(MAX_CHATS); } // Сортируем чаты по order (TDLib order учитывает pinned и время) client.sort_chats_by_order(); }