Import existing code
This commit is contained in:
1646
Cargo.lock
generated
Normal file
1646
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
13
Cargo.toml
Normal file
13
Cargo.toml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[package]
|
||||||
|
name = "audiothek"
|
||||||
|
description = "ARD Audiothek query tool"
|
||||||
|
authors = [
|
||||||
|
"Henning Oschwald"
|
||||||
|
]
|
||||||
|
version = "0.2.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
clap = { version = "4.5.40", features = ["cargo", "derive"] }
|
||||||
|
reqwest = { version = "0.12.20", features = ["blocking", "json"] }
|
||||||
|
serde_json = "1.0.140"
|
||||||
50
src/main.rs
Normal file
50
src/main.rs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
// this script queries the ARD Audiothek via it's SQLGraph API, passes a show ID and returns all downloadable audio URLs from the result.
|
||||||
|
use clap::Parser;
|
||||||
|
use reqwest::blocking::Client;
|
||||||
|
const GRAPHQL_API_URL: &str = "https://api.ardaudiothek.de/graphql";
|
||||||
|
|
||||||
|
/// This function takes a show_id and a limit and queries the API for it
|
||||||
|
fn request(show_id: i32, last: i8) -> Result<serde_json::Value, Box<dyn std::error::Error>> {
|
||||||
|
let query = format!(
|
||||||
|
"{{\"query\":\"{{programSet(id:{}){{title,path,synopsis,sharingUrl,items(orderBy:PUBLISH_DATE_DESC,filter:{{isPublished:{{equalTo:true}}}}first:{}){{nodes{{title,summary,synopsis,sharingUrl,publicationStartDateAndTime:publishDate,url,episodeNumber,duration,isPublished,audios{{url,downloadUrl,size,mimeType,}}}}}}}}}}\"}}",
|
||||||
|
show_id, last
|
||||||
|
);
|
||||||
|
let response = Client::builder()
|
||||||
|
.build()?
|
||||||
|
.post(GRAPHQL_API_URL)
|
||||||
|
.header("Content-Type", "application/json")
|
||||||
|
.body(query)
|
||||||
|
.send()?;
|
||||||
|
|
||||||
|
Ok(response.json::<serde_json::Value>()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
// command line arguments
|
||||||
|
#[derive(Parser)]
|
||||||
|
#[command(arg_required_else_help(true), author, version, about, long_about = None)]
|
||||||
|
struct Args {
|
||||||
|
/// Audiothek show ID, can be taken from show URLs.
|
||||||
|
show_id: i32,
|
||||||
|
/// how many episodes to fetch
|
||||||
|
#[arg(short, long, default_value("10"))]
|
||||||
|
last: i8,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// parse command line arguments
|
||||||
|
let args = Args::parse();
|
||||||
|
// send the request
|
||||||
|
let res = request(args.show_id, args.last).unwrap();
|
||||||
|
// extract episodes from result
|
||||||
|
let episodes = &res["data"]["programSet"]["items"]["nodes"]
|
||||||
|
.as_array()
|
||||||
|
.unwrap();
|
||||||
|
dbg!(episodes);
|
||||||
|
let urls: Vec<String> = episodes
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|episode| episode["audios"].as_array().cloned().unwrap_or_default())
|
||||||
|
.flat_map(|audio| audio["downloadUrl"].as_str().map(|s| s.to_string()))
|
||||||
|
.collect();
|
||||||
|
urls.iter().for_each(|u| println!("{}", &u));
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user