use crate::client::AuthenticatedClient;
use crate::client::DeviceClient;
use crate::error::Error;
use serde::{Deserialize, Serialize};
use std::cmp::Ordering;
use std::fmt;
use std::hash::{Hash, Hasher};
use url::Url;
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Suggestion {
pub website: Url,
pub mygpo_link: Url,
pub description: String,
pub subscribers: u16,
pub title: String,
pub url: Url,
pub subscribers_last_week: u16,
pub logo_url: Option<Url>,
}
pub trait RetrieveSuggestedPodcasts {
fn retrieve_suggested_podcasts(&self, max_results: u8) -> Result<Vec<Suggestion>, Error>;
}
impl RetrieveSuggestedPodcasts for AuthenticatedClient {
fn retrieve_suggested_podcasts(&self, max_results: u8) -> Result<Vec<Suggestion>, Error> {
Ok(self
.get(&format!(
"https://gpodder.net/suggestions/{}.json",
max_results
))?
.json()?)
}
}
impl RetrieveSuggestedPodcasts for DeviceClient {
fn retrieve_suggested_podcasts(&self, max_results: u8) -> Result<Vec<Suggestion>, Error> {
self.as_ref().retrieve_suggested_podcasts(max_results)
}
}
impl PartialEq for Suggestion {
fn eq(&self, other: &Self) -> bool {
self.url == other.url
}
}
impl Eq for Suggestion {}
impl Ord for Suggestion {
fn cmp(&self, other: &Self) -> Ordering {
self.url.cmp(&other.url)
}
}
impl PartialOrd for Suggestion {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Hash for Suggestion {
fn hash<H: Hasher>(&self, state: &mut H) {
self.url.hash(state);
}
}
impl fmt::Display for Suggestion {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}: {} <{}>", self.title, self.description, self.url)
}
}
#[cfg(test)]
mod tests {
use super::Suggestion;
use std::cmp::Ordering;
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
use url::Url;
#[test]
fn equal_suggestion_means_equal_hash() {
let suggestion1 = Suggestion {
url: Url::parse("http://goinglinux.com/mp3podcast.xml").unwrap(),
website: Url::parse("http://www.linuxgeekdom.com").unwrap(),
mygpo_link: Url::parse("http://gpodder.net/podcast/64439").unwrap(),
description: String::from("Linux Geekdom"),
subscribers: 0,
title: String::from("Linux Geekdom"),
subscribers_last_week: 0,
logo_url: None,
};
let suggestion2 = Suggestion {
url: Url::parse("http://goinglinux.com/mp3podcast.xml").unwrap(),
website: Url::parse("http://goinglinux.com").unwrap(),
mygpo_link: Url::parse("http://gpodder.net/podcast/11171").unwrap(),
description: String::from("Going Linux"),
subscribers: 571,
title: String::from("Going Linux"),
subscribers_last_week: 571,
logo_url: Some(Url::parse("http://goinglinux.com/images/GoingLinux80.png").unwrap()),
};
assert_eq!(suggestion1, suggestion2);
assert_eq!(suggestion1.partial_cmp(&suggestion2), Some(Ordering::Equal));
let mut hasher1 = DefaultHasher::new();
suggestion1.hash(&mut hasher1);
let mut hasher2 = DefaultHasher::new();
suggestion2.hash(&mut hasher2);
assert_eq!(hasher1.finish(), hasher2.finish());
}
#[test]
fn display() {
let suggestion = Suggestion {
url: Url::parse("http://goinglinux.com/mp3podcast.xml").unwrap(),
website: Url::parse("http://goinglinux.com").unwrap(),
mygpo_link: Url::parse("http://gpodder.net/podcast/11171").unwrap(),
description: String::from("Going Linux"),
subscribers: 571,
title: String::from("Going Linux"),
subscribers_last_week: 571,
logo_url: Some(Url::parse("http://goinglinux.com/images/GoingLinux80.png").unwrap()),
};
assert_eq!(
"Going Linux: Going Linux <http://goinglinux.com/mp3podcast.xml>".to_owned(),
format!("{}", suggestion)
);
}
}