Files
telegram-tui/tests/helpers/fake_tdclient_impl.rs
2026-05-17 17:58:29 +03:00

361 lines
10 KiB
Rust

//! Test implementation of the TDLib client traits for FakeTdClient.
use super::fake_tdclient::FakeTdClient;
use async_trait::async_trait;
use std::borrow::Cow;
use std::path::PathBuf;
use tdlib_rs::enums::{ChatAction, Update};
use tele_tui::tdlib::{
AccountClient, AuthClient, ChatActionClient, ChatClient, ClientState, FileClient,
MessageClient, NotificationClient, ReactionClient, UpdateClient, UserClient,
};
use tele_tui::tdlib::{
AuthState, ChatInfo, FolderInfo, MessageInfo, ProfileInfo, ReplyInfo, UserCache,
UserOnlineStatus,
};
use tele_tui::types::{ChatId, MessageId, UserId};
#[async_trait]
impl AuthClient for FakeTdClient {
async fn send_phone_number(&self, _phone: String) -> Result<(), String> {
Ok(())
}
async fn send_code(&self, _code: String) -> Result<(), String> {
Ok(())
}
async fn send_password(&self, _password: String) -> Result<(), String> {
Ok(())
}
}
#[async_trait]
impl ChatClient for FakeTdClient {
async fn load_chats(&mut self, limit: i32) -> Result<(), String> {
let _ = FakeTdClient::load_chats(self, limit as usize).await?;
Ok(())
}
async fn load_folder_chats(&mut self, folder_id: i32, limit: i32) -> Result<(), String> {
FakeTdClient::load_folder_chats(self, folder_id, limit as usize).await
}
async fn leave_chat(&self, _chat_id: ChatId) -> Result<(), String> {
Ok(())
}
async fn get_profile_info(&self, chat_id: ChatId) -> Result<ProfileInfo, String> {
FakeTdClient::get_profile_info(self, chat_id).await
}
fn chats(&self) -> &[ChatInfo] {
&[]
}
fn folders(&self) -> &[FolderInfo] {
&[]
}
fn main_chat_list_position(&self) -> i32 {
0
}
fn set_main_chat_list_position(&mut self, _position: i32) {}
fn update_chats<F>(&mut self, updater: F)
where
F: FnOnce(&mut Vec<ChatInfo>),
{
updater(&mut self.chats.lock().unwrap());
}
fn update_folders<F>(&mut self, updater: F)
where
F: FnOnce(&mut Vec<FolderInfo>),
{
updater(&mut self.folders.lock().unwrap());
}
}
#[async_trait]
impl ChatActionClient for FakeTdClient {
async fn send_chat_action(&self, chat_id: ChatId, action: ChatAction) {
FakeTdClient::send_chat_action(self, chat_id, format!("{:?}", action)).await;
}
fn clear_stale_typing_status(&mut self) -> bool {
false
}
fn typing_status(&self) -> Option<&(UserId, String, std::time::Instant)> {
None
}
fn set_typing_status(&mut self, _status: Option<(UserId, String, std::time::Instant)>) {}
}
#[async_trait]
impl MessageClient for FakeTdClient {
async fn get_chat_history(
&mut self,
chat_id: ChatId,
limit: i32,
) -> Result<Vec<MessageInfo>, String> {
FakeTdClient::get_chat_history(self, chat_id, limit).await
}
async fn load_older_messages(
&mut self,
chat_id: ChatId,
from_message_id: MessageId,
) -> Result<Vec<MessageInfo>, String> {
FakeTdClient::load_older_messages(self, chat_id, from_message_id).await
}
async fn get_pinned_messages(&mut self, _chat_id: ChatId) -> Result<Vec<MessageInfo>, String> {
Ok(vec![])
}
async fn load_current_pinned_message(&mut self, _chat_id: ChatId) {}
async fn search_messages(
&self,
chat_id: ChatId,
query: &str,
) -> Result<Vec<MessageInfo>, String> {
FakeTdClient::search_messages(self, chat_id, query).await
}
async fn send_message(
&mut self,
chat_id: ChatId,
text: String,
reply_to_message_id: Option<MessageId>,
reply_info: Option<ReplyInfo>,
) -> Result<MessageInfo, String> {
FakeTdClient::send_message(self, chat_id, text, reply_to_message_id, reply_info).await
}
async fn edit_message(
&mut self,
chat_id: ChatId,
message_id: MessageId,
new_text: String,
) -> Result<MessageInfo, String> {
FakeTdClient::edit_message(self, chat_id, message_id, new_text).await
}
async fn delete_messages(
&mut self,
chat_id: ChatId,
message_ids: Vec<MessageId>,
revoke: bool,
) -> Result<(), String> {
FakeTdClient::delete_messages(self, chat_id, message_ids, revoke).await
}
async fn forward_messages(
&mut self,
to_chat_id: ChatId,
from_chat_id: ChatId,
message_ids: Vec<MessageId>,
) -> Result<(), String> {
FakeTdClient::forward_messages(self, from_chat_id, to_chat_id, message_ids).await
}
async fn set_draft_message(&self, chat_id: ChatId, text: String) -> Result<(), String> {
FakeTdClient::set_draft_message(self, chat_id, text).await
}
fn current_chat_messages(&self) -> Cow<'_, [MessageInfo]> {
if let Some(chat_id) = *self.current_chat_id.lock().unwrap() {
Cow::Owned(self.get_messages(chat_id))
} else {
Cow::Owned(Vec::new())
}
}
fn current_chat_id(&self) -> Option<ChatId> {
self.get_current_chat_id().map(ChatId::new)
}
fn current_pinned_message(&self) -> Option<MessageInfo> {
self.current_pinned_message.lock().unwrap().clone()
}
fn push_message(&mut self, msg: MessageInfo) {
if let Some(chat_id) = *self.current_chat_id.lock().unwrap() {
self.messages
.lock()
.unwrap()
.entry(chat_id)
.or_default()
.push(msg);
}
}
fn clear_current_chat_messages(&mut self) {
if let Some(chat_id) = *self.current_chat_id.lock().unwrap() {
self.messages.lock().unwrap().remove(&chat_id);
}
}
fn set_current_chat_messages(&mut self, messages: Vec<MessageInfo>) {
if let Some(chat_id) = *self.current_chat_id.lock().unwrap() {
self.messages.lock().unwrap().insert(chat_id, messages);
}
}
fn update_current_chat_messages<F>(&mut self, updater: F)
where
F: FnOnce(&mut Vec<MessageInfo>),
{
if let Some(chat_id) = *self.current_chat_id.lock().unwrap() {
let mut all_messages = self.messages.lock().unwrap();
updater(all_messages.entry(chat_id).or_default());
}
}
fn set_current_chat_id(&mut self, chat_id: Option<ChatId>) {
*self.current_chat_id.lock().unwrap() = chat_id.map(|id| id.as_i64());
}
fn set_current_pinned_message(&mut self, msg: Option<MessageInfo>) {
*self.current_pinned_message.lock().unwrap() = msg;
}
fn pending_view_messages(&self) -> &[(ChatId, Vec<MessageId>)] {
&[]
}
fn enqueue_pending_view_messages(&mut self, chat_id: ChatId, message_ids: Vec<MessageId>) {
self.pending_view_messages
.lock()
.unwrap()
.push((chat_id, message_ids));
}
async fn fetch_missing_reply_info(&mut self) {}
async fn process_pending_view_messages(&mut self) {
let mut pending = self.pending_view_messages.lock().unwrap();
for (chat_id, message_ids) in pending.drain(..) {
let ids: Vec<i64> = message_ids.iter().map(|id| id.as_i64()).collect();
self.viewed_messages
.lock()
.unwrap()
.push((chat_id.as_i64(), ids));
}
}
}
#[async_trait]
impl UserClient for FakeTdClient {
fn get_user_status_by_chat_id(&self, _chat_id: ChatId) -> Option<&UserOnlineStatus> {
None
}
fn pending_user_ids(&self) -> &[UserId] {
&[]
}
fn user_cache(&self) -> &UserCache {
use std::sync::OnceLock;
static EMPTY_CACHE: OnceLock<UserCache> = OnceLock::new();
EMPTY_CACHE.get_or_init(|| UserCache::new(0))
}
fn update_user_cache<F>(&mut self, _updater: F)
where
F: FnOnce(&mut UserCache),
{
}
async fn process_pending_user_ids(&mut self) {}
}
#[async_trait]
impl ReactionClient for FakeTdClient {
async fn get_message_available_reactions(
&self,
chat_id: ChatId,
message_id: MessageId,
) -> Result<Vec<String>, String> {
FakeTdClient::get_message_available_reactions(self, chat_id, message_id).await
}
async fn toggle_reaction(
&self,
chat_id: ChatId,
message_id: MessageId,
reaction: String,
) -> Result<(), String> {
FakeTdClient::toggle_reaction(self, chat_id, message_id, reaction).await
}
}
#[async_trait]
impl FileClient for FakeTdClient {
async fn download_file(&self, file_id: i32) -> Result<String, String> {
FakeTdClient::download_file(self, file_id).await
}
async fn download_voice_note(&self, file_id: i32) -> Result<String, String> {
Ok(format!("/tmp/fake_voice_{}.ogg", file_id))
}
}
#[async_trait]
impl ClientState for FakeTdClient {
fn client_id(&self) -> i32 {
0
}
async fn get_me(&self) -> Result<i64, String> {
Ok(12345)
}
fn auth_state(&self) -> &AuthState {
use std::sync::OnceLock;
static AUTH_STATE_READY: AuthState = AuthState::Ready;
static AUTH_STATE_WAIT_PHONE: OnceLock<AuthState> = OnceLock::new();
static AUTH_STATE_WAIT_CODE: OnceLock<AuthState> = OnceLock::new();
static AUTH_STATE_WAIT_PASSWORD: OnceLock<AuthState> = OnceLock::new();
let current = self.auth_state.lock().unwrap();
match *current {
AuthState::Ready => &AUTH_STATE_READY,
AuthState::WaitPhoneNumber => {
AUTH_STATE_WAIT_PHONE.get_or_init(|| AuthState::WaitPhoneNumber)
}
AuthState::WaitCode => AUTH_STATE_WAIT_CODE.get_or_init(|| AuthState::WaitCode),
AuthState::WaitPassword => {
AUTH_STATE_WAIT_PASSWORD.get_or_init(|| AuthState::WaitPassword)
}
_ => &AUTH_STATE_READY,
}
}
fn network_state(&self) -> tele_tui::tdlib::types::NetworkState {
FakeTdClient::get_network_state(self)
}
}
impl NotificationClient for FakeTdClient {
fn configure_notifications(&mut self, _config: &tele_tui::config::NotificationsConfig) {}
fn sync_notification_muted_chats(&mut self) {}
}
#[async_trait]
impl AccountClient for FakeTdClient {
async fn recreate_client(&mut self, _db_path: PathBuf) -> Result<(), String> {
Ok(())
}
}
impl UpdateClient for FakeTdClient {
fn handle_update(&mut self, _update: Update) {}
}