av_stream_info_rust/
http_config.rs

1use crate::request_error::RequestError;
2use crate::DecodeError;
3use crate::LatLong;
4use serde::de::{self, Deserializer, Unexpected};
5use serde::{Deserialize, Serialize};
6use std::convert::TryFrom;
7
8/// Does contain decoded information from a stream information file
9#[derive(Serialize, Deserialize, Debug, Clone)]
10pub struct MetaInfoFile {
11    #[serde(rename = "icy-index-metadata")]
12    #[serde(deserialize_with = "bool_from_int")]
13    pub index_metadata: bool,
14    #[serde(rename = "icy-version")]
15    pub version: u8,
16    #[serde(rename = "icy-main-stream-url")]
17    pub main_stream_url: Option<String>,
18    #[serde(rename = "icy-name")]
19    pub name: Option<String>,
20    #[serde(rename = "icy-description")]
21    pub description: Option<String>,
22    #[serde(rename = "icy-genre")]
23    pub genre: Option<String>,
24    #[serde(rename = "icy-language-codes")]
25    pub languages: Option<String>,
26    #[serde(rename = "icy-country-code")]
27    pub countrycode: Option<String>,
28    #[serde(rename = "icy-country-subdivision-code")]
29    pub country_subdivision_code: Option<String>,
30    #[serde(rename = "icy-logo")]
31    pub logo: Option<String>,
32    #[serde(rename = "icy-geo-lat-long")]
33    geo_lat_long: Option<String>,
34}
35
36impl MetaInfoFile {
37    /// Decodes lat/long information contained in a stream information file
38    pub fn get_lat_long(&self) -> Option<Result<LatLong, DecodeError>> {
39        self.geo_lat_long.clone().map(|x| LatLong::try_from(x))
40    }
41}
42
43#[cfg(feature = "blocking")]
44pub fn extract_from_homepage(homepage: &str) -> Result<MetaInfoFile, RequestError> {
45    use reqwest::blocking::get;
46    let stream_info_link = format!("{}/streaminfo.json", homepage);
47
48    trace!(
49        "extract_from_homepage({}) Download file '{}'",
50        homepage,
51        stream_info_link
52    );
53    let resp = get(&stream_info_link)?.text()?;
54    let deserialized: MetaInfoFile = serde_json::from_str(&resp)?;
55    Ok(deserialized)
56}
57
58pub async fn extract_from_homepage_async(homepage: &str) -> Result<MetaInfoFile, RequestError> {
59    use reqwest::get;    
60    let stream_info_link = format!("{}/streaminfo.json", homepage);
61
62    trace!(
63        "extract_from_homepage({}) Download file '{}'",
64        homepage,
65        stream_info_link
66    );
67    let resp = get(&stream_info_link).await?.text().await?;
68    let deserialized: MetaInfoFile = serde_json::from_str(&resp)?;
69    Ok(deserialized)
70}
71
72fn bool_from_int<'de, D>(deserializer: D) -> Result<bool, D::Error>
73where
74    D: Deserializer<'de>,
75{
76    match u8::deserialize(deserializer)? {
77        0 => Ok(false),
78        1 => Ok(true),
79        other => Err(de::Error::invalid_value(
80            Unexpected::Unsigned(other as u64),
81            &"zero or one",
82        )),
83    }
84}