steam-user 0.1.0

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

use scraper::{Html, Selector};
use steamid::SteamID;

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

impl SteamUser {
    /// Retrieves the history of players that the authenticated user has
    /// reported.
    ///
    /// Scrapes the user's report history page at `https://steamcommunity.com/my/reports/`.
    ///
    /// # Returns
    ///
    /// Returns a `Vec<PlayerReport>` containing details such as report IDs,
    /// dates, and reasons.
    #[steam_endpoint(GET, host = Community, path = "/my/reports/", kind = Read)]
    pub async fn get_player_reports(&self) -> Result<Vec<crate::types::PlayerReport>, SteamUserError> {
        let response = self.get_path("/my/reports/").send().await?;
        self.check_response(&response)?;

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

        let row_selector = Selector::parse(".report_history_row").expect("valid CSS selector");
        // Fallback or specific internal selectors
        let date_selector = Selector::parse(".report_date").expect("valid CSS selector");
        let account_selector = Selector::parse(".report_account").expect("valid CSS selector");
        let category_selector = Selector::parse(".report_category").expect("valid CSS selector");
        let description_selector = Selector::parse(".report_description").expect("valid CSS selector");

        let mut reports = Vec::new();

        for row in document.select(&row_selector) {
            let report_id = row.value().attr("data-reportid").unwrap_or("").to_string();

            let date = row.select(&date_selector).next().map(|e| e.text().collect::<String>().trim().to_string()).unwrap_or_default();

            // Account column usually contains a link to the profile
            let mut reported_player_name = String::new();
            let mut reported_steam_id = None;

            if let Some(account_col) = row.select(&account_selector).next() {
                reported_player_name = account_col.text().collect::<String>().trim().to_string();

                if let Some(link) = account_col.select(&Selector::parse("a").expect("valid CSS selector")).next() {
                    let href = link.value().attr("href").unwrap_or("");
                    // Check for /profiles/STEAMID64
                    if let Some(start) = href.find("/profiles/") {
                        let id_str = href[start + 10..].split('/').next().unwrap_or("");
                        if let Ok(id) = id_str.parse::<u64>() {
                            reported_steam_id = Some(SteamID::from(id));
                        }
                    } else if let Some(_start) = href.find("/id/") {
                        // We can't easily resolve custom URLs here without
                        // another request, so we leave
                        // it None or just store the name.
                        // The user can resolve it if they really need to.
                    }
                }
            }

            let reason = row.select(&category_selector).next().map(|e| e.text().collect::<String>().trim().to_string()).unwrap_or_default();

            let description = row.select(&description_selector).next().map(|e| e.text().collect::<String>().trim().to_string()).unwrap_or_default();

            reports.push(crate::types::PlayerReport { report_id, reported_steam_id, reported_player_name, date, reason, description });
        }

        Ok(reports)
    }
}