radiobrowser-lib-rust/src/api.rs

138 lines
4.1 KiB
Rust
Raw Normal View History

2022-05-06 21:18:52 +00:00
use crate::ApiStationClickResult;
use crate::ApiStationVoteResult;
use crate::ApiStatus;
2022-04-21 19:18:17 +00:00
use crate::external::post_api;
2022-04-21 18:56:01 +00:00
use crate::ApiConfig;
2022-04-21 19:18:17 +00:00
use crate::CountrySearchBuilder;
use crate::LanguageSearchBuilder;
use crate::StationSearchBuilder;
2022-04-21 20:47:23 +00:00
use crate::TagSearchBuilder;
2022-04-21 18:56:01 +00:00
use serde::de::DeserializeOwned;
use std::collections::HashMap;
use std::error::Error;
use rand::seq::SliceRandom;
use rand::thread_rng;
2022-04-26 20:26:46 +00:00
use log::trace;
2022-04-21 18:56:01 +00:00
use async_std_resolver::proto::rr::RecordType;
use async_std_resolver::{config, resolver};
2022-05-06 21:18:52 +00:00
/// RadioBrowser client for async communication
///
/// It uses crate:async_std
///
/// Example
/// ```rust
/// use std::error::Error;
/// use radiobrowser::RadioBrowserAPI;
/// #[async_std::main]
/// async fn main() -> Result<(), Box<dyn Error>> {
/// let mut api = RadioBrowserAPI::new().await?;
/// Ok(())
/// }
/// ```
2022-04-21 18:56:01 +00:00
#[derive(Clone, Debug)]
pub struct RadioBrowserAPI {
servers: Vec<String>,
current: usize,
}
impl RadioBrowserAPI {
2022-05-06 21:18:52 +00:00
/// Create a new instance of a radiobrowser api client.
/// It will fetch a list of radiobrowser server with get_servers()
/// and save it internally.
2022-04-21 18:56:01 +00:00
pub async fn new() -> Result<Self, Box<dyn Error>> {
Ok(RadioBrowserAPI {
servers: RadioBrowserAPI::get_servers().await?,
current: 0,
})
}
2022-04-26 20:26:46 +00:00
fn get_current_server(&mut self) -> String {
trace!("get_current_server()");
2022-04-21 18:56:01 +00:00
if self.servers.len() > 0 {
self.current = self.current % self.servers.len();
format!("https://{}", self.servers[self.current])
} else {
String::from("https://de1.api.radio-browser.info")
}
}
2022-04-26 20:26:46 +00:00
async fn post_api<P: DeserializeOwned, A: AsRef<str>>(
2022-04-21 18:56:01 +00:00
&mut self,
endpoint: A,
) -> Result<P, Box<dyn Error>> {
let mapjson = HashMap::new();
post_api(self.get_current_server(), endpoint.as_ref(), mapjson).await
}
pub async fn get_server_config(&mut self) -> Result<ApiConfig, Box<dyn Error>> {
Ok(self.post_api("/json/config").await?)
}
2022-05-06 21:18:52 +00:00
pub async fn get_server_status(&mut self) -> Result<ApiStatus, Box<dyn Error>> {
Ok(self.post_api("/json/stats").await?)
}
/// Add a click to a station found by stationuuid
pub async fn station_click<P: AsRef<str>>(&mut self, stationuuid: P) -> Result<ApiStationClickResult, Box<dyn Error>> {
Ok(self.post_api(format!("/json/url/{}",stationuuid.as_ref())).await?)
}
/// Add a vote to a station found by a stationuuid
pub async fn station_vote<P: AsRef<str>>(&mut self, stationuuid: P) -> Result<ApiStationVoteResult, Box<dyn Error>> {
Ok(self.post_api(format!("/json/vote/{}",stationuuid.as_ref())).await?)
}
2022-04-21 19:18:17 +00:00
pub fn get_stations(&self) -> StationSearchBuilder {
2022-04-21 18:56:01 +00:00
StationSearchBuilder::new(self.clone())
}
2022-04-21 19:18:17 +00:00
pub fn get_countries(&self) -> CountrySearchBuilder {
2022-04-21 18:56:01 +00:00
CountrySearchBuilder::new(self.clone())
}
2022-04-21 19:18:17 +00:00
pub fn get_languages(&self) -> LanguageSearchBuilder {
LanguageSearchBuilder::new(self.clone())
}
2022-04-21 20:47:23 +00:00
pub fn get_tags(&self) -> TagSearchBuilder {
TagSearchBuilder::new(self.clone())
}
2022-04-21 18:56:01 +00:00
pub async fn send<P: AsRef<str>, Q: DeserializeOwned>(
&mut self,
endpoint: P,
mapjson: HashMap<String, String>,
) -> Result<Q, Box<dyn Error>> {
post_api(self.get_current_server(), endpoint, mapjson).await
}
pub async fn get_servers() -> Result<Vec<String>, Box<dyn Error>> {
2022-04-26 20:26:46 +00:00
trace!("get_servers()");
2022-04-21 18:56:01 +00:00
let resolver = resolver(
config::ResolverConfig::default(),
config::ResolverOpts::default(),
)
.await?;
let response = resolver
.lookup(
"_api._tcp.radio-browser.info",
RecordType::SRV,
)
.await?;
let mut list: Vec<String> = response
.iter()
.filter_map(|entry| entry.as_srv())
.map(|entry| entry.target().to_string().trim_matches('.').to_string())
.collect();
list.shuffle(&mut thread_rng());
2022-04-26 20:26:46 +00:00
trace!("Servers: {:?}", list);
2022-04-21 18:56:01 +00:00
Ok(list)
}
2022-04-21 19:18:17 +00:00
}