use std::path::PathBuf;
use tail_fin_common::TailFinError;
pub struct Ctx {
pub connect: Option<String>,
pub cookies: Option<String>,
pub headed: bool,
}
pub fn default_cookies_path(site: &str) -> PathBuf {
let home = std::env::var("HOME").unwrap_or_else(|_| ".".into());
PathBuf::from(home)
.join(".tail-fin")
.join(format!("{}-cookies.txt", site))
}
pub fn resolve_cookies_path(cookies_flag: &str, site: &str) -> PathBuf {
if cookies_flag == "auto" {
default_cookies_path(site)
} else {
PathBuf::from(cookies_flag)
}
}
#[cfg(feature = "twitter")]
pub fn twitter_http_client(
cookies_flag: &str,
) -> Result<tail_fin_twitter::TwitterHttpClient, TailFinError> {
let path = resolve_cookies_path(cookies_flag, "twitter");
if !path.exists() {
eprintln!("Error: Cookie file not found: {}", path.display());
eprintln!(
" Run `tail-fin --connect twitter export-cookies` to export cookies from Chrome."
);
std::process::exit(1);
}
tail_fin_twitter::TwitterHttpClient::from_cookie_file(
&path,
)
}
pub async fn browser_session(
host: &str,
headed: bool,
) -> Result<night_fury_core::BrowserSession, TailFinError> {
Ok(night_fury_core::BrowserSession::builder()
.connect_to(format!("ws://{}", host))
.headed(headed)
.build()
.await?)
}
pub async fn launch_browser(headed: bool) -> Result<night_fury_core::BrowserSession, TailFinError> {
Ok(night_fury_core::BrowserSession::builder()
.headed(headed)
.build()
.await?)
}
pub async fn launch_stealth_session(
url: &str,
headed: bool,
) -> Result<night_fury_core::BrowserSession, TailFinError> {
Ok(night_fury_core::BrowserSession::builder()
.headed(headed)
.launch_stealth(url)
.await?)
}
pub fn require_browser(connect: &Option<String>, service: &str, action_name: &str) -> String {
match connect {
Some(host) => host.clone(),
None => {
eprintln!(
"Error: `{} {}` requires browser mode (--connect).",
service, action_name
);
eprintln!(
" Use: tail-fin --connect 127.0.0.1:9222 {} {} ...",
service, action_name
);
std::process::exit(1);
}
}
}
pub async fn require_browser_session(
ctx: &Ctx,
service: &str,
) -> Result<night_fury_core::BrowserSession, TailFinError> {
if ctx.cookies.is_some() {
eprintln!("Error: {} cookie mode is not supported.", service);
eprintln!(" Use --connect for browser mode.");
std::process::exit(1);
}
let host = match ctx.connect.as_deref() {
Some(h) => h,
None => {
eprintln!("Error: {} requires --connect.", service);
eprintln!(
" Example: tail-fin --connect 127.0.0.1:9222 {} ...",
service
);
std::process::exit(1);
}
};
browser_session(host, ctx.headed).await
}
pub fn no_mode_error(service: &str, cmd: &str) -> ! {
eprintln!("Error: No connection mode specified for {}.", service);
eprintln!(" Use --connect to use browser mode:");
eprintln!(" tail-fin --connect 127.0.0.1:9222 {} {}", service, cmd);
eprintln!(" Or --cookies to use saved cookies:");
eprintln!(" tail-fin --cookies {} {}", service, cmd);
std::process::exit(1);
}
pub fn print_json(value: &(impl serde::Serialize + ?Sized)) -> Result<(), TailFinError> {
println!("{}", serde_json::to_string_pretty(value)?);
Ok(())
}
pub fn print_list(
key: &str,
items: &impl serde::Serialize,
count: usize,
) -> Result<(), TailFinError> {
println!(
"{}",
serde_json::to_string_pretty(&serde_json::json!({
key: items,
"count": count,
}))?
);
Ok(())
}