cda-dl 0.1.0

Minimal async library for extracting video stream URLs from cda.pl
Documentation
use anyhow::{anyhow, Result};
use reqwest::{Client, header};
use scraper::{Html, Selector};
use serde_json::Value;

pub async fn extract_best_quality(base_url: &str) -> Result<String> {
    let client = Client::builder()
        .user_agent("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:123.0) Gecko/20100101 Firefox/123.0")
        .build()?;

    let html = client.get(base_url).send().await?.text().await?;
    let document = Html::parse_document(&html);

    let selector = Selector::parse("div[id^=mediaplayer]").unwrap();
    let div = document.select(&selector)
        .find(|el| el.value().attr("player_data").is_some())
        .ok_or_else(|| anyhow!("Could not find player_data"))?;

    let player_data_raw = div.value().attr("player_data").unwrap();
    let player_data: Value = serde_json::from_str(player_data_raw)?;

    let video_id = player_data["id"].as_str()
        .ok_or_else(|| anyhow!("Missing ID"))?
        .trim_start_matches("mediaplayer");

    let video = &player_data["video"];
    let ts = video["ts"].as_i64().ok_or_else(|| anyhow!("Missing ts"))?;
    let hash2 = video["hash2"].as_str().ok_or_else(|| anyhow!("Missing hash2"))?;
    let qualities = video["qualities"].as_object().ok_or_else(|| anyhow!("Missing qualities"))?;

    let quality = ["1080p", "720p", "480p", "360p"]
        .iter()
        .find(|q| qualities.contains_key(**q))
        .ok_or_else(|| anyhow!("No available qualities found"))?;

    let body = serde_json::json!({
        "id": 3,
        "jsonrpc": "2.0",
        "method": "videoGetLink",
        "params": [
            video_id,
            qualities[*quality].as_str().unwrap_or(""),
            ts,
            hash2,
            serde_json::Map::<String, Value>::new(),
        ]
    });

    let post_url = format!("https://www.cda.pl/video/{}/vjs", video_id);

    let res = client.post(&post_url)
        .header(header::CONTENT_TYPE, "application/json")
        .header("X-Requested-With", "XMLHttpRequest")
        .json(&body)
        .send().await?;

    let json: Value = res.json().await?;
    let url = json["result"]["resp"].as_str()
        .ok_or_else(|| anyhow!("Missing result.resp in response"))?;

    Ok(url.to_string())
}