diff options
author | metamuffin <metamuffin@disroot.org> | 2024-01-20 22:40:03 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2024-01-20 22:40:03 +0100 |
commit | 0f74f013128f45a4f34761791203d88228a5eb52 (patch) | |
tree | 32826c46971e3d637b32f67630989a243d4dbb9d /import/src | |
parent | 42f7a95ce67506344b694535ff193745452c6e29 (diff) | |
download | jellything-0f74f013128f45a4f34761791203d88228a5eb52.tar jellything-0f74f013128f45a4f34761791203d88228a5eb52.tar.bz2 jellything-0f74f013128f45a4f34761791203d88228a5eb52.tar.zst |
implement trakt search api
Diffstat (limited to 'import/src')
-rw-r--r-- | import/src/lib.rs | 10 | ||||
-rw-r--r-- | import/src/trakt.rs | 131 |
2 files changed, 139 insertions, 2 deletions
diff --git a/import/src/lib.rs b/import/src/lib.rs index 1d8efd8..ab74ecb 100644 --- a/import/src/lib.rs +++ b/import/src/lib.rs @@ -6,13 +6,17 @@ #![feature(lazy_cell)] pub mod infojson; pub mod tmdb; +pub mod trakt; use crate::tmdb::TmdbKind; use anyhow::{anyhow, bail, Context, Ok}; use async_recursion::async_recursion; use futures::{executor::block_on, stream::FuturesUnordered, StreamExt}; use jellybase::{ - cache::{async_cache_file, cache_memory}, database::{DataAcid, ReadableTable, Ser, T_NODE, T_NODE_IMPORT}, federation::Federation, AssetLocationExt, CONF, SECRETS + cache::{async_cache_file, cache_memory}, + database::{DataAcid, ReadableTable, Ser, T_NODE, T_NODE_IMPORT}, + federation::Federation, + AssetLocationExt, CONF, SECRETS, }; use jellyclient::Session; use jellycommon::{ @@ -238,7 +242,9 @@ async fn process_source( ImportSource::Override(n) => insert_node(&id, n)?, ImportSource::Tmdb { id: tid } => { info!("tmdb lookup {id}"); - let key = SECRETS.api.tmdb + let key = SECRETS + .api + .tmdb .as_ref() .ok_or(anyhow!("no tmdb api key"))?; diff --git a/import/src/trakt.rs b/import/src/trakt.rs new file mode 100644 index 0000000..e142eb6 --- /dev/null +++ b/import/src/trakt.rs @@ -0,0 +1,131 @@ +use reqwest::{ + header::{HeaderMap, HeaderName, HeaderValue}, + Client, ClientBuilder, +}; +use serde::{Deserialize, Serialize}; + +pub struct Trakt { + client: Client, +} + +impl Trakt { + pub fn new(api_key: &str) -> Self { + let client = ClientBuilder::new() + .default_headers(HeaderMap::from_iter([ + ( + HeaderName::from_static("trakt-api-key"), + HeaderValue::from_str(api_key).unwrap(), + ), + ( + HeaderName::from_static("trakt-api-version"), + HeaderValue::from_static("2"), + ), + ( + HeaderName::from_static("content-type"), + HeaderValue::from_static("application/json"), + ), + ])) + .build() + .unwrap(); + Self { client } + } + + pub async fn search( + &self, + types: &[TraktKind], + query: &str, + extended: bool, + ) -> anyhow::Result<Vec<TraktSearchResult>> { + let res = self + .client + .get(format!( + "https://api.trakt.tv/search/{}?query={}{}", + types + .iter() + .map(|t| serde_json::to_string(t).unwrap()) + .collect::<Vec<_>>() + .join(","), + urlencoding::encode(query), + optext(extended) + )) + .send() + .await?; + Ok(res.json().await?) + } +} + +fn optext(extended: bool) -> &'static str { + if extended { + "&extended=full" + } else { + "" + } +} + +#[derive(Debug, Serialize, Deserialize, Clone, Copy)] +#[serde(rename_all = "snake_case")] +pub enum TraktKind { + Movie, + Show, + Season, + Episode, + Person, + User, +} + +impl TraktKind { + pub fn singular(self) -> &'static str { + match self { + TraktKind::Movie => "movie", + TraktKind::Show => "show", + TraktKind::Season => "season", + TraktKind::Episode => "episode", + TraktKind::Person => "person", + TraktKind::User => "user", + } + } + pub fn plural(self) -> &'static str { + match self { + TraktKind::Movie => "movies", + TraktKind::Show => "shows", + TraktKind::Season => "seasons", + TraktKind::Episode => "episodes", + TraktKind::Person => "people", + TraktKind::User => "user", // //! not used in API + } + } +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct TraktSearchResult { + r#type: TraktKind, + score: f64, + inner: TraktKindObject, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum TraktKindObject { + Movie(TraktMediaObject), + Show(TraktMediaObject), + Season(TraktMediaObject), + Episode(TraktMediaObject), + Person(TraktMediaObject), + User(TraktMediaObject), +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct TraktMediaObject { + title: String, + year: Option<u32>, + ids: TraktMediaObjectIds, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct TraktMediaObjectIds { + trakt: u64, + slug: String, + + imdb: Option<String>, + tmdb: Option<u64>, +} |