use std::sync::Arc;
use std::sync::atomic::AtomicU64;
use rustybook_http::client::Client as HttpClient;
use tokio::sync::{
Mutex,
RwLock,
broadcast,
};
use super::{
Inner,
MessengerClient,
MessengerConfig,
};
#[cfg(feature = "cache")]
use crate::cache::Cache;
use crate::error::MessengerError;
use crate::http::send::PendingRequests;
#[derive(Debug, Clone)]
pub struct MessengerClientBuilder {
cookies_file: Option<String>,
user_id: Option<String>,
cookies: Option<String>,
http: Option<HttpClient>,
user_agent: Option<String>,
proxy: Option<String>,
online: bool,
}
impl Default for MessengerClientBuilder {
fn default() -> Self {
Self::new()
}
}
impl MessengerClientBuilder {
pub fn new() -> Self {
Self {
cookies_file: None,
user_id: None,
cookies: None,
http: None,
user_agent: None,
proxy: None,
online: true,
}
}
pub fn cookies_file_path(mut self, path: impl Into<String>) -> Self {
self.cookies_file = Some(path.into());
self
}
pub fn shared_session(
mut self,
user_id: impl Into<String>,
cookie_header: impl Into<String>,
http: HttpClient,
) -> Self {
self.user_id = Some(user_id.into());
self.cookies = Some(cookie_header.into());
self.http = Some(http);
self
}
pub fn user_agent(mut self, user_agent: impl Into<String>) -> Self {
self.user_agent = Some(user_agent.into());
self
}
pub fn proxy(mut self, proxy: impl Into<String>) -> Self {
self.proxy = Some(proxy.into());
self
}
pub fn online(mut self, online: bool) -> Self {
self.online = online;
self
}
pub fn build(self) -> Result<MessengerClient, MessengerError> {
let has_cookie_path = self.cookies_file.is_some();
let has_shared = self.user_id.is_some() || self.cookies.is_some() || self.http.is_some();
if !has_cookie_path && !has_shared {
return Err(MessengerError::Config(
"cookies_file_path or shared_session must be provided".to_string(),
));
}
if has_cookie_path && has_shared {
return Err(MessengerError::Config(
"cookies_file_path cannot be combined with shared_session".to_string(),
));
}
if has_shared && (self.user_id.is_none() || self.cookies.is_none() || self.http.is_none()) {
return Err(MessengerError::Config(
"shared_session requires user_id, cookie_header, and http client".to_string(),
));
}
let (events, _) = broadcast::channel(1024);
let inner = Inner {
config: MessengerConfig {
cookies_file_path: self.cookies_file,
shared_user_id: self.user_id,
shared_cookie_header: self.cookies,
shared_http: self.http,
user_agent: self.user_agent,
proxy: self.proxy,
online: self.online,
},
state: RwLock::new(None),
mqtt: Mutex::new(None),
listener: Mutex::new(None),
handler: Mutex::new(None),
events,
pending: PendingRequests::new(),
request_id: AtomicU64::new(rand::random::<u64>() & 0x7fff_ffff_ffff_ffff),
task_id: AtomicU64::new(1),
#[cfg(feature = "cache")]
cache: Arc::new(Cache::new()),
};
Ok(MessengerClient {
inner: Arc::new(inner),
})
}
}