diff options
| author | jakka <jakka@jakka.su> | 2025-09-08 22:57:37 +0300 |
|---|---|---|
| committer | jakka <jakka@jakka.su> | 2025-09-08 22:57:37 +0300 |
| commit | dfbc17db741bad16129e0bb8d21cef22e0c439f4 (patch) | |
| tree | 82651c9fe894cf557de906176aadcf6c2633803d /src | |
| parent | 4c56f91c88365a3c5ad890b02e8e9f52c314ea0c (diff) | |
continued working on api. added proper encoding and decoding for permissions and service types
Diffstat (limited to 'src')
| -rw-r--r-- | src/client.rs | 50 | ||||
| -rw-r--r-- | src/lib.rs | 37 | ||||
| -rw-r--r-- | src/types.rs | 132 |
3 files changed, 141 insertions, 78 deletions
diff --git a/src/client.rs b/src/client.rs index 06d55d6..3caa330 100644 --- a/src/client.rs +++ b/src/client.rs @@ -38,25 +38,15 @@ impl HydrusClient { req_url.push_str("&permit_everything=true"); } else { req_url.push_str("&basic_permissions="); - let json_string = musli::json::to_string(&permissions).unwrap(); + let json_string = musli::json::to_string(&permissions)?; req_url.push_str(&urlencoding::encode(&json_string)); }; - let response = ureq::get(req_url).call(); + let response = ureq::get(req_url).call()?.body_mut().read_to_vec()?; - if let Err(error) = response { - return Err(HydrusError::NetworkError(error)); - } - - let key = response.unwrap().body_mut().read_to_vec(); - - if let Err(error) = key { - return Err(HydrusError::DeserializeError(error)); - }; + let key = musli::json::decode(response.as_slice())?; - let accesskey: String = musli::json::decode(key.unwrap().as_slice()).unwrap(); - - Ok(key.unwrap().access_key) + Ok(key) } pub fn get_session_key(&self) -> Result<String> { @@ -69,19 +59,11 @@ impl HydrusClient { request = request.header("Hydrus-Client-API-Access-Key", key); } - let response = request.call(); - - if let Err(error) = response { - return Err(HydrusError::NetworkError(error)); - } + let response = request.call()?.body_mut().read_to_vec()?; - let key = response.unwrap().body_mut().read_json::<SessionKey>(); + let key = musli::json::decode(response.as_slice())?; - if let Err(error) = key { - return Err(HydrusError::DeserializeError(error)); - } - - Ok(key.unwrap().session_key) + Ok(key) } pub fn verify_access_key(&self, key: String) -> Result<KeyInfo> { @@ -89,22 +71,16 @@ impl HydrusClient { req_url.push_str("/verify_access_key"); let response = ureq::get(req_url) .header("Hydrus-Client-API-Access-Key", key) - .call(); - - if let Err(error) = response { - return Err(HydrusError::NetworkError(error)); - } - - let data = response.unwrap().body_mut().read_json::<KeyInfo>(); + .call()? + .body_mut() + .read_to_vec()?; - if let Err(error) = data { - return Err(HydrusError::DeserializeError(error)); - } + let data: KeyInfo = musli::json::decode(response.as_slice())?; - Ok(data.unwrap()) + Ok(data) } - pub fn get_service_name(&self, name: String) -> Result<GetService> { + pub fn get_service_name(&self, name: String) -> Result<Service> { let mut req_url = self.url.to_owned(); req_url.push_str("/get_service?service_name="); req_url.push_str(&urlencoding::encode(&name)); @@ -1,38 +1,3 @@ pub mod client; +mod tests; pub mod types; - -#[cfg(test)] -mod tests { - use crate::types::*; - - #[test] - fn correct_permissions_number() { - assert_eq!(HydrusPermissions::ImportAndEditURLs as u8, 0); - assert_eq!(HydrusPermissions::ImportAndEditFiles as u8, 1); - assert_eq!(HydrusPermissions::EditFileTags as u8, 2); - assert_eq!(HydrusPermissions::SearchAndFetchFiles as u8, 3); - assert_eq!(HydrusPermissions::ManagePages as u8, 4); - assert_eq!(HydrusPermissions::ManageCookiesAndHeaders as u8, 5); - assert_eq!(HydrusPermissions::ManageDatabase as u8, 6); - assert_eq!(HydrusPermissions::EditFileNotes as u8, 7); - assert_eq!(HydrusPermissions::EditFileRelationships as u8, 8); - assert_eq!(HydrusPermissions::EditFileRatings as u8, 9); - assert_eq!(HydrusPermissions::ManagePopups as u8, 10); - assert_eq!(HydrusPermissions::EditFileTimes as u8, 11); - assert_eq!(HydrusPermissions::CommitPending as u8, 12); - assert_eq!(HydrusPermissions::SeeLocalPaths as u8, 13); - } - - #[test] - fn correct_url_encode() { - let perms: [HydrusPermissions; 3] = [ - HydrusPermissions::ImportAndEditURLs, - HydrusPermissions::ImportAndEditFiles, - HydrusPermissions::SeeLocalPaths, - ]; - let json_string = musli::json::to_string(&perms).unwrap(); - let encoded = urlencoding::encode(&json_string); - - assert_eq!(encoded, "%5B0%2C1%2C13%5D") - } -} diff --git a/src/types.rs b/src/types.rs index d13a8aa..c34e56f 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,4 +1,5 @@ -use musli::{Decode, Encode}; +use core::panic; +use musli::{Allocator, Decode, Decoder, Encode, Encoder}; use thiserror::Error; #[derive(Error, Debug)] @@ -6,13 +7,24 @@ pub enum HydrusError { #[error("failed to connect to Hydrus")] NetworkError(ureq::Error), #[error("failed to deserialize data")] - DeserializeError(musli::Error), + DeserializeError(musli::json::Error), } -impl Into +impl From<musli::json::Error> for HydrusError { + fn from(value: musli::json::Error) -> Self { + HydrusError::DeserializeError(value) + } +} + +impl From<ureq::Error> for HydrusError { + fn from(value: ureq::Error) -> Self { + HydrusError::NetworkError(value) + } +} -#[derive(Decode, Encode, PartialEq, Debug)] +#[derive(PartialEq, Debug, Clone)] #[repr(u8)] + pub enum HydrusPermissions { ImportAndEditURLs = 0, ImportAndEditFiles, @@ -30,6 +42,59 @@ pub enum HydrusPermissions { SeeLocalPaths, } +impl<M> Encode<M> for HydrusPermissions { + type Encode = Self; + + #[inline] + fn encode<E>(&self, encoder: E) -> Result<(), E::Error> + where + E: Encoder<Mode = M>, + { + encoder.encode(self.clone() as u8) + } + + #[inline] + fn as_encode(&self) -> &Self::Encode { + self + } +} + +impl From<u8> for HydrusPermissions { + fn from(value: u8) -> Self { + match value { + 0 => HydrusPermissions::ImportAndEditURLs, + 1 => HydrusPermissions::ImportAndEditFiles, + 2 => HydrusPermissions::EditFileTags, + 3 => HydrusPermissions::SearchAndFetchFiles, + 4 => HydrusPermissions::ManagePages, + 5 => HydrusPermissions::ManageCookiesAndHeaders, + 6 => HydrusPermissions::ManageDatabase, + 7 => HydrusPermissions::EditFileNotes, + 8 => HydrusPermissions::EditFileRelationships, + 9 => HydrusPermissions::EditFileRatings, + 10 => HydrusPermissions::ManagePopups, + 11 => HydrusPermissions::EditFileTimes, + 12 => HydrusPermissions::CommitPending, + 13 => HydrusPermissions::SeeLocalPaths, + _ => panic!("incorrect permission id"), + } + } +} + +impl<'de, M, A> Decode<'de, M, A> for HydrusPermissions +where + A: Allocator, +{ + #[inline] + fn decode<D>(decoder: D) -> Result<Self, D::Error> + where + D: Decoder<'de>, + { + let val: u8 = decoder.decode()?; + Ok(val.into()) + } +} + #[derive(Decode)] struct AccessKey { access_key: String, @@ -48,7 +113,7 @@ pub struct KeyInfo { human_permissions: String, } -#[derive(Decode, Encode, PartialEq, Debug)] +#[derive(PartialEq, Debug, Clone)] #[repr(u8)] pub enum ServiceType { TagRepository = 0, @@ -72,6 +137,63 @@ pub enum ServiceType { ServerAdmin = 99, } +impl<M> Encode<M> for ServiceType { + type Encode = Self; + + #[inline] + fn encode<E>(&self, encoder: E) -> Result<(), E::Error> + where + E: Encoder<Mode = M>, + { + encoder.encode(self.clone() as u8) + } + + #[inline] + fn as_encode(&self) -> &Self::Encode { + self + } +} + +impl From<u8> for ServiceType { + fn from(value: u8) -> Self { + match value { + 0 => ServiceType::TagRepository, + 1 => ServiceType::FileRepository, + 2 => ServiceType::LocalFileDomain, + 5 => ServiceType::LocalTagDomain, + 6 => ServiceType::NumericalRating, + 7 => ServiceType::BoolRating, + 10 => ServiceType::AllKnownTags, + 11 => ServiceType::AllKnownFiles, + 12 => ServiceType::LocalBooru, + 13 => ServiceType::IPFS, + 14 => ServiceType::Trash, + 15 => ServiceType::AllLocalFiles, + 17 => ServiceType::FileNotes, + 18 => ServiceType::ClientAPI, + 19 => ServiceType::DeletedFromAnywhere, + 20 => ServiceType::LocalUpdates, + 21 => ServiceType::AllMyFiles, + 22 => ServiceType::IncDecRating, + 99 => ServiceType::ServerAdmin, + _ => panic!("incorrect service id"), + } + } +} + +impl<'de, M, A> Decode<'de, M, A> for ServiceType +where + A: Allocator, +{ + #[inline] + fn decode<D>(decoder: D) -> Result<Self, D::Error> + where + D: Decoder<'de>, + { + Ok(decoder.decode()?) + } +} + #[derive(Decode)] pub struct Service { name: String, |
