use serde::Deserialize;
use crate::error::MessengerError;
#[derive(Debug, Clone, Deserialize)]
pub struct Cookie {
pub name: String,
pub value: String,
}
#[derive(Debug, Clone)]
pub struct AuthCookies {
pub cookie_header: String,
pub user_id: String,
}
pub fn load_cookies(path: &str) -> Result<AuthCookies, MessengerError> {
let content = std::fs::read_to_string(path)?;
let cookies: Vec<Cookie> = serde_json::from_str(&content)
.map_err(|error| MessengerError::Auth(format!("failed to parse cookie file: {error}")))?;
let mut parts = Vec::with_capacity(cookies.len());
let mut user_id = None;
let mut has_xs = false;
for cookie in &cookies {
if cookie.name.is_empty() {
continue;
}
parts.push(format!("{}={}", cookie.name, cookie.value));
if cookie.name == "c_user" {
user_id = Some(cookie.value.clone());
}
if cookie.name == "xs" {
has_xs = true;
}
}
let Some(user_id) = user_id else {
return Err(MessengerError::Auth(
"missing c_user cookie in cookie file".to_string(),
));
};
if !has_xs {
return Err(MessengerError::Auth(
"missing xs cookie in cookie file".to_string(),
));
}
Ok(AuthCookies {
cookie_header: parts.join("; "),
user_id,
})
}
#[cfg(test)]
mod tests {
use std::time::{
SystemTime,
UNIX_EPOCH,
};
use super::load_cookies;
fn write_temp(content: &str) -> String {
let timestamp = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("time went backwards")
.as_nanos();
let path =
std::env::temp_dir().join(format!("rustybook-messenger-cookies-{timestamp}.json"));
std::fs::write(&path, content).expect("failed to write cookie fixture");
path.display().to_string()
}
#[test]
fn loads_valid_cookie_file() {
let path = write_temp(
r#"[
{"name":"c_user","value":"123"},
{"name":"xs","value":"abcd"},
{"name":"datr","value":"test"}
]"#,
);
let loaded = load_cookies(&path).expect("expected valid cookie file");
assert_eq!(loaded.user_id, "123");
assert!(loaded.cookie_header.contains("xs=abcd"));
}
#[test]
fn fails_when_c_user_missing() {
let path = write_temp(r#"[{"name":"xs","value":"abcd"}]"#);
let result = load_cookies(&path);
assert!(result.is_err());
}
#[test]
fn fails_when_xs_missing() {
let path = write_temp(r#"[{"name":"c_user","value":"123"}]"#);
let result = load_cookies(&path);
assert!(result.is_err());
}
}