feat: Update typegen enums and the UI
This commit is contained in:
106
api/src/lib.rs
106
api/src/lib.rs
@@ -1,6 +1,7 @@
|
||||
pub mod jellyfin;
|
||||
|
||||
use ::tap::*;
|
||||
use reqwest::Method;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
@@ -9,6 +10,8 @@ pub enum JellyfinApiError {
|
||||
ReqwestError(#[from] reqwest::Error),
|
||||
#[error("Serialization/Deserialization error: {0}")]
|
||||
SerdeError(#[from] serde_json::Error),
|
||||
#[error("IO error: {0}")]
|
||||
IoError(#[from] std::io::Error),
|
||||
}
|
||||
|
||||
type Result<T, E = JellyfinApiError> = std::result::Result<T, E>;
|
||||
@@ -29,9 +32,9 @@ impl JellyfinClient {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn save_token(&self, path: impl AsRef<std::path::Path>) -> std::io::Result<()> {
|
||||
pub async fn save_token(&self, path: impl AsRef<std::path::Path>) -> std::io::Result<()> {
|
||||
if let Some(token) = &self.access_token {
|
||||
std::fs::write(path, token)
|
||||
tokio::fs::write(path, token).await
|
||||
} else {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
@@ -40,17 +43,20 @@ impl JellyfinClient {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_token(&mut self, path: impl AsRef<std::path::Path>) -> std::io::Result<()> {
|
||||
let token = std::fs::read_to_string(path)?;
|
||||
pub async fn load_token(&mut self, path: impl AsRef<std::path::Path>) -> std::io::Result<()> {
|
||||
let token = tokio::fs::read_to_string(path).await?;
|
||||
self.access_token = Some(token);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn post_builder(&self, uri: impl AsRef<str>) -> reqwest::RequestBuilder {
|
||||
pub fn request_builder(
|
||||
&self,
|
||||
method: reqwest::Method,
|
||||
uri: impl AsRef<str>,
|
||||
) -> reqwest::RequestBuilder {
|
||||
let url = format!("{}/{}", self.config.server_url.as_str(), uri.as_ref());
|
||||
self.client.post(&url)
|
||||
self.client.request(method, &url)
|
||||
.header("X-Emby-Authorization", format!("MediaBrowser Client=\"Jello\", Device=\"Jello\", DeviceId=\"{}\", Version=\"1.0.0\"", self.config.device_id))
|
||||
.header("Content-Type", "application/json")
|
||||
.pipe(|builder| {
|
||||
if let Some(token) = &self.access_token {
|
||||
builder.header("X-MediaBrowser-Token", token)
|
||||
@@ -60,18 +66,18 @@ impl JellyfinClient {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_builder(&self, uri: impl AsRef<str>) -> reqwest::RequestBuilder {
|
||||
let url = format!("{}/{}", self.config.server_url.as_str(), uri.as_ref());
|
||||
self.client.get(&url)
|
||||
.header("X-Emby-Authorization", format!("MediaBrowser Client=\"Jello\", Device=\"Jello\", DeviceId=\"{}\", Version=\"1.0.0\"", self.config.device_id))
|
||||
.pipe(|builder| {
|
||||
if let Some(token) = &self.access_token {
|
||||
builder.header("X-MediaBrowser-Token", token)
|
||||
} else {
|
||||
builder
|
||||
}
|
||||
})
|
||||
}
|
||||
// pub fn get_builder(&self, uri: impl AsRef<str>) -> reqwest::RequestBuilder {
|
||||
// let url = format!("{}/{}", self.config.server_url.as_str(), uri.as_ref());
|
||||
// self.client.get(&url)
|
||||
// .header("X-Emby-Authorization", format!("MediaBrowser Client=\"Jello\", Device=\"Jello\", DeviceId=\"{}\", Version=\"1.0.0\"", self.config.device_id))
|
||||
// .pipe(|builder| {
|
||||
// if let Some(token) = &self.access_token {
|
||||
// builder.header("X-MediaBrowser-Token", token)
|
||||
// } else {
|
||||
// builder
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
|
||||
pub async fn post<T: Serialize + ?Sized, U: serde::de::DeserializeOwned>(
|
||||
&self,
|
||||
@@ -79,7 +85,7 @@ impl JellyfinClient {
|
||||
body: &T,
|
||||
) -> Result<U> {
|
||||
let text = self
|
||||
.post_builder(uri)
|
||||
.request_builder(reqwest::Method::POST, uri)
|
||||
.json(body)
|
||||
.send()
|
||||
.await?
|
||||
@@ -92,7 +98,7 @@ impl JellyfinClient {
|
||||
|
||||
pub async fn get<U: serde::de::DeserializeOwned>(&self, uri: impl AsRef<str>) -> Result<U> {
|
||||
let text = self
|
||||
.get_builder(uri)
|
||||
.request_builder(reqwest::Method::GET, uri)
|
||||
.send()
|
||||
.await?
|
||||
.error_for_status()?
|
||||
@@ -103,25 +109,34 @@ impl JellyfinClient {
|
||||
}
|
||||
|
||||
pub async fn authenticate(&mut self) -> Result<jellyfin::AuthenticationResult> {
|
||||
let out = self
|
||||
.post_builder("Users/AuthenticateByName")
|
||||
.json(&jellyfin::AuthenticateUserByName {
|
||||
username: Some(self.config.username.clone()),
|
||||
pw: Some(self.config.password.clone()),
|
||||
})
|
||||
.send()
|
||||
.await?
|
||||
.error_for_status()?
|
||||
.text()
|
||||
let auth_result: jellyfin::AuthenticationResult = self
|
||||
.post(
|
||||
"Users/AuthenticateByName",
|
||||
&jellyfin::AuthenticateUserByName {
|
||||
username: Some(self.config.username.clone()),
|
||||
pw: Some(self.config.password.clone()),
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
let auth_result: jellyfin::AuthenticationResult = serde_json::from_str(&out)?;
|
||||
self.access_token = auth_result.access_token.clone();
|
||||
Ok(auth_result)
|
||||
}
|
||||
|
||||
async fn items(&self) -> Result<jellyfin::BaseItemDtoQueryResult> {
|
||||
pub async fn authenticate_with_cached_token(
|
||||
&mut self,
|
||||
path: impl AsRef<std::path::Path>,
|
||||
) -> Result<()> {
|
||||
let path = path.as_ref();
|
||||
if !self.load_token(path).await.is_ok() {
|
||||
self.authenticate().await?;
|
||||
self.save_token(path).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn raw_items(&self) -> Result<jellyfin::BaseItemDtoQueryResult> {
|
||||
let text = &self
|
||||
.get_builder("/Items")
|
||||
.request_builder(Method::GET, "Items")
|
||||
.send()
|
||||
.await?
|
||||
.error_for_status()?
|
||||
@@ -130,8 +145,31 @@ impl JellyfinClient {
|
||||
let out: jellyfin::BaseItemDtoQueryResult = serde_json::from_str(&text)?;
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
pub async fn items(
|
||||
&self,
|
||||
root: impl Into<Option<String>>,
|
||||
) -> Result<Vec<jellyfin::BaseItemDto>> {
|
||||
let text = &self
|
||||
.request_builder(Method::GET, "Items")
|
||||
.query(&[("parentId", root.into())])
|
||||
.send()
|
||||
.await?
|
||||
.error_for_status()?
|
||||
.text()
|
||||
.await?;
|
||||
let out: jellyfin::BaseItemDtoQueryResult = serde_json::from_str(&text)?;
|
||||
Ok(out.items)
|
||||
}
|
||||
}
|
||||
|
||||
// pub trait Item {
|
||||
// fn id(&self) -> &str;
|
||||
// fn name(&self) -> &str;
|
||||
// fn type_(&self) -> jellyfin::BaseItemKind;
|
||||
// fn media_type(&self) -> &str;
|
||||
// }
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct JellyfinConfig {
|
||||
pub username: String,
|
||||
|
||||
Reference in New Issue
Block a user