rustybook-messenger 0.2.1

Messenger client for Rustybook
Documentation
use std::time::Duration;

use rumqttc::{
    MqttOptions,
    Protocol,
    Transport,
};
use tracing::debug;

use crate::state::State;

const DEFAULT_TOPICS: [&str; 4] = [
    "/t_ms",
    "/thread_typing",
    "/orca_presence",
    "/notify_disconnect",
];

const CONNECT_TOPICS: [&str; 22] = [
    "/legacy_web",
    "/ls_req",
    "/ls_resp",
    "/t_ms",
    "/rtc_multi",
    "/thread_typing",
    "/orca_typing_notifications",
    "/orca_presence",
    "/br_sr",
    "/friend_request",
    "/friending_state_change",
    "/friend_requests_seen",
    "/sr_res",
    "/webrtc",
    "/onevc",
    "/notify_disconnect",
    "/mercury",
    "/inbox",
    "/messaging_events",
    "/orca_message_notifications",
    "/pp",
    "/webrtc_response",
];

pub(super) fn default_topics() -> &'static [&'static str] {
    &DEFAULT_TOPICS
}

pub(super) fn build_connect_options(state: &State, online: bool, session_id: u64) -> MqttOptions {
    let websocket_url = format!(
        "wss://edge-chat.facebook.com/chat?region={}&sid={}&cid={}",
        state.region, session_id, state.mqtt_client_id
    );

    let username = serde_json::json!({
        "u": state.user_id,
        "s": session_id,
        "chat_on": online,
        "fg": online,
        "d": state.mqtt_client_id,
        "aid": state.mqtt_app_id,
        "st": CONNECT_TOPICS,
        "pm": [],
        "cp": 3,
        "ecp": 10,
        "ct": "websocket",
        "mqtt_sid": "",
        "dc": "",
        "no_auto_fg": true,
        "gas": serde_json::Value::Null,
        "pack": [],
        "p": serde_json::Value::Null,
        "aids": serde_json::Value::Null,
        "a": state.user_agent,
    });

    debug!(
        session_id,
        online,
        region = state.region,
        mqtt_client_id = state.mqtt_client_id,
        mqtt_app_id = state.mqtt_app_id,
        ls_app_id = state.ls_app_id,
        ls_version_id = state.ls_version_id,
        websocket_url,
        "built messenger mqtt connect options"
    );

    let mut options = MqttOptions::new("mqttwsclient", websocket_url, 443);
    options.set_protocol(Protocol::V3);
    options.set_clean_session(true);
    options.set_keep_alive(Duration::from_secs(60));
    options.set_transport(Transport::wss_with_default_config());
    options.set_credentials(username.to_string(), String::new());

    let cookie = state.cookie_header.clone();
    let user_agent = state.user_agent.clone();
    options.set_request_modifier(move |mut request| {
        let cookie = cookie.clone();
        let user_agent = user_agent.clone();
        async move {
            if let Ok(value) = cookie.parse() {
                request.headers_mut().insert("Cookie", value);
            }
            if let Ok(value) = user_agent.parse() {
                request.headers_mut().insert("User-Agent", value);
            }
            if let Ok(value) = "https://www.facebook.com".parse() {
                request.headers_mut().insert("Origin", value);
            }
            if let Ok(value) = "edge-chat.facebook.com".parse() {
                request.headers_mut().insert("Host", value);
            }
            request
        }
    });

    options
}