use crate::request::SimklRequest;
#[derive(Debug, Clone, PartialEq)]
pub enum RedirectTarget {
Simkl,
Trailer,
Twitter,
Watched,
}
impl RedirectTarget {
pub fn as_str(&self) -> &'static str {
match self {
RedirectTarget::Simkl => "Simkl",
RedirectTarget::Trailer => "trailer",
RedirectTarget::Twitter => "twitter",
RedirectTarget::Watched => "watched",
}
}
}
#[derive(Debug, Clone)]
pub struct RedirectRequest {
pub to: RedirectTarget,
pub title: Option<String>,
pub year: Option<u16>,
pub season: Option<u32>,
pub episode: Option<u32>,
pub r#type: Option<String>,
pub simkl: Option<u64>,
pub hulu: Option<u64>,
pub netflix: Option<u64>,
pub mal: Option<u64>,
pub tvdb: Option<u64>,
pub tmdb: Option<u64>,
pub imdb: Option<String>,
pub anidb: Option<u64>,
pub crunchyroll: Option<u64>,
pub anilist: Option<u64>,
pub kitsu: Option<u64>,
pub livechart: Option<u64>,
pub anisearch: Option<u64>,
pub animeplanet: Option<u64>,
pub traktslug: Option<String>,
pub letterboxd: Option<String>,
}
impl Default for RedirectRequest {
fn default() -> Self {
Self {
to: RedirectTarget::Simkl,
title: None,
year: None,
season: None,
episode: None,
r#type: None,
simkl: None,
hulu: None,
netflix: None,
mal: None,
tvdb: None,
tmdb: None,
imdb: None,
anidb: None,
crunchyroll: None,
anilist: None,
kitsu: None,
livechart: None,
anisearch: None,
animeplanet: None,
traktslug: None,
letterboxd: None,
}
}
}
impl RedirectRequest {
pub fn new(to: RedirectTarget) -> Self {
Self {
to,
..Default::default()
}
}
pub fn with_to(mut self, to: RedirectTarget) -> Self {
self.to = to;
self
}
pub fn with_title(mut self, title: impl Into<String>) -> Self {
self.title = Some(title.into());
self
}
pub fn with_year(mut self, year: u16) -> Self {
self.year = Some(year);
self
}
pub fn with_season(mut self, season: u32) -> Self {
self.season = Some(season);
self
}
pub fn with_episode(mut self, episode: u32) -> Self {
self.episode = Some(episode);
self
}
pub fn with_type(mut self, media_type: impl Into<String>) -> Self {
self.r#type = Some(media_type.into());
self
}
pub fn with_simkl(mut self, id: u64) -> Self {
self.simkl = Some(id);
self
}
pub fn with_hulu(mut self, id: u64) -> Self {
self.hulu = Some(id);
self
}
pub fn with_netflix(mut self, id: u64) -> Self {
self.netflix = Some(id);
self
}
pub fn with_mal(mut self, id: u64) -> Self {
self.mal = Some(id);
self
}
pub fn with_tvdb(mut self, id: u64) -> Self {
self.tvdb = Some(id);
self
}
pub fn with_tmdb(mut self, id: u64) -> Self {
self.tmdb = Some(id);
self
}
pub fn with_imdb(mut self, id: impl Into<String>) -> Self {
self.imdb = Some(id.into());
self
}
pub fn with_anidb(mut self, id: u64) -> Self {
self.anidb = Some(id);
self
}
pub fn with_crunchyroll(mut self, id: u64) -> Self {
self.crunchyroll = Some(id);
self
}
pub fn with_anilist(mut self, id: u64) -> Self {
self.anilist = Some(id);
self
}
pub fn with_kitsu(mut self, id: u64) -> Self {
self.kitsu = Some(id);
self
}
pub fn with_livechart(mut self, id: u64) -> Self {
self.livechart = Some(id);
self
}
pub fn with_anisearch(mut self, id: u64) -> Self {
self.anisearch = Some(id);
self
}
pub fn with_animeplanet(mut self, id: u64) -> Self {
self.animeplanet = Some(id);
self
}
pub fn with_traktslug(mut self, slug: impl Into<String>) -> Self {
self.traktslug = Some(slug.into());
self
}
pub fn with_letterboxd(mut self, slug: impl Into<String>) -> Self {
self.letterboxd = Some(slug.into());
self
}
}
impl SimklRequest for RedirectRequest {
fn endpoint(&self) -> String {
"/redirect".to_string()
}
fn query_params(&self) -> Vec<(String, String)> {
let mut params: Vec<(String, String)> = Vec::new();
params.push(("to".to_string(), self.to.as_str().to_string()));
if let Some(ref title) = self.title {
params.push(("title".to_string(), title.clone()));
}
if let Some(year) = self.year {
params.push(("year".to_string(), year.to_string()));
}
if let Some(season) = self.season {
params.push(("season".to_string(), season.to_string()));
}
if let Some(episode) = self.episode {
params.push(("episode".to_string(), episode.to_string()));
}
if let Some(ref t) = self.r#type {
params.push(("type".to_string(), t.clone()));
}
if let Some(id) = self.simkl {
params.push(("simkl".to_string(), id.to_string()));
}
if let Some(id) = self.hulu {
params.push(("hulu".to_string(), id.to_string()));
}
if let Some(id) = self.netflix {
params.push(("netflix".to_string(), id.to_string()));
}
if let Some(id) = self.mal {
params.push(("mal".to_string(), id.to_string()));
}
if let Some(id) = self.tvdb {
params.push(("tvdb".to_string(), id.to_string()));
}
if let Some(id) = self.tmdb {
params.push(("tmdb".to_string(), id.to_string()));
}
if let Some(ref id) = self.imdb {
params.push(("imdb".to_string(), id.clone()));
}
if let Some(id) = self.anidb {
params.push(("anidb".to_string(), id.to_string()));
}
if let Some(id) = self.crunchyroll {
params.push(("crunchyroll".to_string(), id.to_string()));
}
if let Some(id) = self.anilist {
params.push(("anilist".to_string(), id.to_string()));
}
if let Some(id) = self.kitsu {
params.push(("kitsu".to_string(), id.to_string()));
}
if let Some(id) = self.livechart {
params.push(("livechart".to_string(), id.to_string()));
}
if let Some(id) = self.anisearch {
params.push(("anisearch".to_string(), id.to_string()));
}
if let Some(id) = self.animeplanet {
params.push(("animeplanet".to_string(), id.to_string()));
}
if let Some(ref slug) = self.traktslug {
params.push(("traktslug".to_string(), slug.clone()));
}
if let Some(ref slug) = self.letterboxd {
params.push(("letterboxd".to_string(), slug.clone()));
}
params
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::request::SimklRequest;
#[test]
fn test_redirect_to_simkl_by_id() {
let url = RedirectRequest::new(RedirectTarget::Simkl)
.with_simkl(10280)
.build_url();
assert_eq!(url, "https://api.simkl.com/redirect?to=Simkl&simkl=10280");
}
#[test]
fn test_redirect_trailer_by_imdb() {
let url = RedirectRequest::new(RedirectTarget::Trailer)
.with_imdb("tt0944947")
.build_url();
assert_eq!(
url,
"https://api.simkl.com/redirect?to=trailer&imdb=tt0944947"
);
}
#[test]
fn test_redirect_watched_with_episode() {
let url = RedirectRequest::new(RedirectTarget::Watched)
.with_simkl(10280)
.with_season(1)
.with_episode(3)
.build_url();
assert_eq!(
url,
"https://api.simkl.com/redirect?to=watched&season=1&episode=3&simkl=10280"
);
}
#[test]
fn test_redirect_twitter_with_title_and_year() {
let url = RedirectRequest::new(RedirectTarget::Twitter)
.with_title("Game of Thrones")
.with_year(2011)
.build_url();
assert_eq!(
url,
"https://api.simkl.com/redirect?to=twitter&title=Game%20of%20Thrones&year=2011"
);
}
#[test]
fn test_redirect_target_as_str() {
assert_eq!(RedirectTarget::Simkl.as_str(), "Simkl");
assert_eq!(RedirectTarget::Trailer.as_str(), "trailer");
assert_eq!(RedirectTarget::Twitter.as_str(), "twitter");
assert_eq!(RedirectTarget::Watched.as_str(), "watched");
}
#[test]
fn test_redirect_default_target_is_simkl() {
let req = RedirectRequest::default();
assert_eq!(req.to, RedirectTarget::Simkl);
}
#[test]
fn test_redirect_no_client_id_in_params() {
let url = RedirectRequest::new(RedirectTarget::Simkl)
.with_simkl(42)
.build_url();
assert!(!url.contains("client_id"));
}
#[test]
fn test_redirect_all_id_fields() {
let url = RedirectRequest::new(RedirectTarget::Simkl)
.with_hulu(1)
.with_netflix(2)
.with_mal(3)
.with_tvdb(4)
.with_tmdb(5)
.with_anidb(6)
.with_crunchyroll(7)
.with_anilist(8)
.with_kitsu(9)
.with_livechart(10)
.with_anisearch(11)
.with_animeplanet(12)
.with_traktslug("game-of-thrones")
.with_letterboxd("john-wick")
.build_url();
assert!(url.contains("hulu=1"));
assert!(url.contains("netflix=2"));
assert!(url.contains("mal=3"));
assert!(url.contains("tvdb=4"));
assert!(url.contains("tmdb=5"));
assert!(url.contains("anidb=6"));
assert!(url.contains("crunchyroll=7"));
assert!(url.contains("anilist=8"));
assert!(url.contains("kitsu=9"));
assert!(url.contains("livechart=10"));
assert!(url.contains("anisearch=11"));
assert!(url.contains("animeplanet=12"));
assert!(url.contains("traktslug=game-of-thrones"));
assert!(url.contains("letterboxd=john-wick"));
}
}