steam-user 0.1.0

Steam User web client for Rust - HTTP-based Steam Community interactions
Documentation
//! Steam Help Request services.

use std::sync::OnceLock;

use scraper::{Html, Selector};

use crate::{client::SteamUser, endpoint::steam_endpoint, error::SteamUserError};

static SEL_HELP_ROW: OnceLock<Selector> = OnceLock::new();
fn sel_help_row() -> &'static Selector {
    SEL_HELP_ROW.get_or_init(|| Selector::parse(".help_request_table a.help_request_row").expect("valid CSS selector"))
}

static SEL_HELP_STATUS: OnceLock<Selector> = OnceLock::new();
fn sel_help_status() -> &'static Selector {
    SEL_HELP_STATUS.get_or_init(|| Selector::parse(".status").expect("valid CSS selector"))
}

static SEL_HELP_TITLE: OnceLock<Selector> = OnceLock::new();
fn sel_help_title() -> &'static Selector {
    SEL_HELP_TITLE.get_or_init(|| Selector::parse(".help_request_name").expect("valid CSS selector"))
}

static SEL_HELP_DATE: OnceLock<Selector> = OnceLock::new();
fn sel_help_date() -> &'static Selector {
    SEL_HELP_DATE.get_or_init(|| Selector::parse(".date_created").expect("valid CSS selector"))
}

static SEL_HELP_PAGE: OnceLock<Selector> = OnceLock::new();
fn sel_help_page() -> &'static Selector {
    SEL_HELP_PAGE.get_or_init(|| Selector::parse(".help_request_page").expect("valid CSS selector"))
}

impl SteamUser {
    /// Lists active and past Steam support tickets (Help Requests).
    ///
    /// Scrapes the Steam Help Requests page at `https://help.steampowered.com/en/wizard/HelpRequests`.
    ///
    /// # Returns
    ///
    /// Returns a `Vec<HelpRequest>` containing a summary of each support
    /// ticket.
    #[steam_endpoint(GET, host = Help, path = "/en/wizard/HelpRequests", kind = Read)]
    pub async fn get_help_requests(&self) -> Result<Vec<crate::types::HelpRequest>, SteamUserError> {
        let response = self.get_path("/en/wizard/HelpRequests").send().await?.text().await?;

        let document = Html::parse_document(&response);

        let mut requests = Vec::new();

        for element in document.select(sel_help_row()) {
            let link = element.value().attr("href").unwrap_or("");
            // Extract ID from link: .../HelpRequest/HT-XXXX-XXXX-XXXX
            let id = link.trim_end_matches('/').split('/').next_back().unwrap_or("").to_string();

            let title = element.select(sel_help_title()).next().map(|e| e.text().collect::<String>().trim().to_string()).unwrap_or_default();

            // Status and date are inside columns, but we can search within the row element
            let status = element.select(sel_help_status()).next().map(|e| e.text().collect::<String>().trim().to_string()).unwrap_or_default();

            let date_created = element.select(sel_help_date()).next().map(|e| e.text().collect::<String>().trim().to_string()).unwrap_or_default();

            requests.push(crate::types::HelpRequest { id, title, date_created, status });
        }

        Ok(requests)
    }

    /// Retrieves the detailed conversation for a specific support ticket.
    ///
    /// # Arguments
    ///
    /// * `id` - The Steam help request ID (e.g., "HT-XXXX-XXXX-XXXX").
    ///
    /// # Returns
    ///
    /// Returns the raw HTML content of the help request conversation details.
    #[steam_endpoint(GET, host = Help, path = "/en/wizard/HelpRequest/{id}", kind = Read)]
    pub async fn get_help_request_detail(&self, id: &str) -> Result<String, SteamUserError> {
        let response = self.get_path(format!("/en/wizard/HelpRequest/{}", id)).send().await?;

        if !response.status().is_success() {
            return Err(SteamUserError::Other(format!("Failed to get help request detail: {}", response.status())));
        }

        let html = response.text().await?;
        let document = Html::parse_document(&html);

        if let Some(element) = document.select(sel_help_page()).next() {
            Ok(element.inner_html())
        } else {
            // If the element is not found, it might be an error page or a different layout
            // For now, return empty string or error? JS returns empty if not found logic
            // implies? JS: const $ = jq.load(result.data); return
            // $(".help_request_page").html(); If selector finds nothing, jq
            // returns null/undefined.
            Ok(String::new())
        }
    }
}