137 lines
5.3 KiB
Rust
137 lines
5.3 KiB
Rust
//! 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<F>(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<i32> = 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();
|
|
}
|