1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
//! ## Icecast Server Status //! Decode server status from an [icecast server](https://icecast.org/docs/icecast-trunk/server_stats/). //! //! ### Usage example //! ```no_run //! use icecast_stats::fetch; //! //! let url_str = "https://stream.example.com:8000/somestream"; //! let stats = fetch(url_str).unwrap(); //! println!("{:#?}", stats); //! ``` //! //! ### Example for a full icecast stats json file //! ```json //! { //! "icestats": { //! "admin": "icemaster@localhost", //! "host": "localhost", //! "location": "Earth", //! "server_id": "Icecast 2.4.4", //! "server_start": "Fri, 09 Apr 2021 21:49:50 +0200", //! "server_start_iso8601": "2021-04-09T21:49:50+0200", //! "source": { //! "audio_bitrate": 128000, //! "audio_channels": 1, //! "audio_samplerate": 48000, //! "bitrate": 128, //! "genre": "various", //! "ice-bitrate": 128, //! "listener_peak": 1, //! "listeners": 0, //! "listenurl": "http://localhost:8000/test2", //! "server_description": "Unspecified description", //! "server_name": "Unspecified name", //! "server_type": "application/ogg", //! "stream_start": "Fri, 09 Apr 2021 21:49:52 +0200", //! "stream_start_iso8601": "2021-04-09T21:49:52+0200", //! "subtype": "Vorbis", //! "dummy": null //! } //! } //! } //! ``` mod icecast_stats; mod icecast_source; use reqwest::blocking::get; use std::error::Error; use url::ParseError; pub use url::Url; pub use crate::icecast_stats::IcecastStats; pub use crate::icecast_stats::IcecastStatsRoot; pub use crate::icecast_source::IcecastStatsSource; /// Try to generate an icecast status url from any url to the same server /// /// Example: /// ```rust /// use icecast_stats::Url; /// use icecast_stats::generate_icecast_stats_url; /// /// let url_str = "https://stream.example.com:8000/somestream"; /// let url = Url::parse(url_str).unwrap(); /// let stats_url = generate_icecast_stats_url(url).unwrap(); /// assert!(stats_url.to_string().eq("https://stream.example.com:8000/status-json.xsl")); /// ``` pub fn generate_icecast_stats_url(base: Url) -> Result<Url, Box<dyn Error>> { let host: String = base.host().ok_or(ParseError::EmptyHost)?.to_string(); let newu = match base.scheme() { "http" => Url::parse(&format!( "http://{hostname}:{port}/status-json.xsl", hostname = host, port = base.port().unwrap_or(80) )), "https" => Url::parse(&format!( "https://{hostname}:{port}/status-json.xsl", hostname = host, port = base.port().unwrap_or(443) )), _ => Err(ParseError::EmptyHost), }?; Ok(newu) } /// Fetch icecast status information from server /// /// This is a shorthand for /// * generate_icecast_stats_url() /// * downloading json /// * parsing json /// /// Example: /// ```no_run /// use icecast_stats::fetch; /// /// let url_str = "https://stream.example.com:8000/somestream"; /// let stats = fetch(url_str).unwrap(); /// ``` pub fn fetch(url: &str) -> Result<IcecastStats, Box<dyn Error>> { let base_url = Url::parse(url)?; let url = generate_icecast_stats_url(base_url)?; let resp = get(url.to_string())?; let j: icecast_stats::IcecastStatsRoot = resp.json()?; Ok(j.icestats) }