rustybook 0.2.1

An ergonomic Facebook client in Rust
Documentation
use serde::Deserialize;

use crate::error::Error;

#[derive(Clone)]
pub struct SessionConfig {
    #[cfg(feature = "messenger")]
    pub user_id: String,
    pub cookie_header: String,
}

#[derive(Debug, Deserialize)]
struct Cookie {
    name: String,
    value: String,
}

impl SessionConfig {
    /// load session from cookies file
    pub fn from_file(path: &str) -> Result<SessionConfig, Error> {
        let content = std::fs::read_to_string(path)
            .map_err(|error| Error::Config(format!("failed to read cookie file: {error}")))?;

        let cookies: Vec<Cookie> = serde_json::from_str(&content)
            .map_err(|error| Error::Config(format!("failed to parse cookie file: {error}")))?;

        let mut parts = Vec::with_capacity(cookies.len());
        #[cfg(feature = "messenger")]
        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));

            #[cfg(feature = "messenger")]
            if cookie.name == "c_user" {
                user_id = Some(cookie.value.clone());
            }

            if cookie.name == "xs" {
                has_xs = true;
            }
        }

        #[cfg(feature = "messenger")]
        let Some(user_id) = user_id else {
            return Err(Error::Config(
                "missing c_user cookie in cookie file".to_string(),
            ));
        };

        if !has_xs {
            return Err(Error::Config(
                "missing xs cookie in cookie file".to_string(),
            ));
        }

        Ok(Self {
            #[cfg(feature = "messenger")]
            user_id,
            cookie_header: parts.join("; "),
        })
    }
}