Improve types

Signed-off-by: trivernis <trivernis@protonmail.com>
pull/2/head
trivernis 3 years ago
parent 6a0df2c7fb
commit 2c5b3225f0
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

@ -1,14 +1,14 @@
use crate::error::{Error, Result};
use crate::paths::access_management::{
ApiVersionResponse, GetServicesResponse, SessionKeyResponse, VerifyAccessKeyResponse,
use crate::endpoints::access_management::{
ApiVersion, ApiVersionResponse, GetServices, GetServicesResponse, SessionKey,
SessionKeyResponse, VerifyAccessKey, VerifyAccessKeyResponse,
};
use crate::paths::adding_files::{
AddFileRequest, AddFileResponse, ArchiveFilesRequest, ArchiveFilesResponse, DeleteFilesRequest,
DeleteFilesResponse, UnarchiveFilesRequest, UnarchiveFilesResponse, UndeleteFilesRequest,
UndeleteFilesResponse,
use crate::endpoints::adding_files::{
AddFile, AddFileRequest, AddFileResponse, ArchiveFiles, ArchiveFilesRequest, DeleteFiles,
DeleteFilesRequest, UnarchiveFiles, UnarchiveFilesRequest, UndeleteFiles, UndeleteFilesRequest,
};
use crate::paths::adding_tags::{AddTagsRequest, AddTagsResponse, CleanTagsResponse};
use crate::paths::Path;
use crate::endpoints::adding_tags::{AddTags, AddTagsRequest, CleanTags, CleanTagsResponse};
use crate::endpoints::Endpoint;
use crate::error::{Error, Result};
use crate::utils::string_list_to_json_array;
use reqwest::Response;
use serde::de::DeserializeOwned;
@ -23,6 +23,7 @@ pub struct Client {
}
impl Client {
/// Creates a new client to start requests against the hydrus api.
pub fn new<S: AsRef<str>>(url: S, access_key: S) -> Result<Self> {
Ok(Self {
inner: reqwest::Client::new(),
@ -32,13 +33,13 @@ impl Client {
}
/// Starts a get request to the path associated with the return type
async fn get_and_parse<T: DeserializeOwned + Path, Q: Serialize + ?Sized>(
async fn get_and_parse<E: Endpoint, Q: Serialize + ?Sized>(
&mut self,
query: &Q,
) -> Result<T> {
) -> Result<E::Response> {
let response = self
.inner
.get(format!("{}/{}", self.base_url, T::get_path()))
.get(format!("{}/{}", self.base_url, E::get_path()))
.header(ACCESS_KEY_HEADER, &self.access_key)
.query(query)
.send()
@ -49,10 +50,10 @@ impl Client {
}
/// Stats a post request to the path associated with the return type
async fn post<T: Path, B: Serialize>(&mut self, body: B) -> Result<Response> {
async fn post<E: Endpoint>(&mut self, body: E::Request) -> Result<Response> {
let response = self
.inner
.post(format!("{}/{}", self.base_url, T::get_path()))
.post(format!("{}/{}", self.base_url, E::get_path()))
.json(&body)
.header(ACCESS_KEY_HEADER, &self.access_key)
.send()
@ -62,20 +63,17 @@ impl Client {
}
/// Stats a post request and parses the body as json
async fn post_and_parse<T: DeserializeOwned + Path, B: Serialize>(
&mut self,
body: B,
) -> Result<T> {
let response = self.post::<T, B>(body).await?;
async fn post_and_parse<E: Endpoint>(&mut self, body: E::Request) -> Result<E::Response> {
let response = self.post::<E>(body).await?;
Self::extract_content(response).await
}
/// Stats a post request to the path associated with the return type
async fn post_binary<T: DeserializeOwned + Path>(&mut self, data: Vec<u8>) -> Result<T> {
async fn post_binary<E: Endpoint>(&mut self, data: Vec<u8>) -> Result<E::Response> {
let response = self
.inner
.post(format!("{}/{}", self.base_url, T::get_path()))
.post(format!("{}/{}", self.base_url, E::get_path()))
.body(data)
.header(ACCESS_KEY_HEADER, &self.access_key)
.header("Content-Type", "application/octet-stream")
@ -103,27 +101,27 @@ impl Client {
/// Returns the current API version. It's being incremented every time the API changes.
pub async fn api_version(&mut self) -> Result<ApiVersionResponse> {
self.get_and_parse(&()).await
self.get_and_parse::<ApiVersion, ()>(&()).await
}
/// Creates a new session key
pub async fn session_key(&mut self) -> Result<SessionKeyResponse> {
self.get_and_parse(&()).await
self.get_and_parse::<SessionKey, ()>(&()).await
}
/// Verifies if the access key is valid and returns some information about its permissions
pub async fn verify_access_key(&mut self) -> Result<VerifyAccessKeyResponse> {
self.get_and_parse(&()).await
self.get_and_parse::<VerifyAccessKey, ()>(&()).await
}
/// Returns the list of tag and file services of the client
pub async fn get_services(&mut self) -> Result<GetServicesResponse> {
self.get_and_parse(&()).await
self.get_and_parse::<GetServices, ()>(&()).await
}
/// Adds a file to hydrus
pub async fn add_file<S: AsRef<str>>(&mut self, path: S) -> Result<AddFileResponse> {
self.post_and_parse(AddFileRequest {
self.post_and_parse::<AddFile>(AddFileRequest {
path: path.as_ref().to_string(),
})
.await
@ -131,12 +129,12 @@ impl Client {
/// Adds a file from binary data to hydrus
pub async fn add_binary_file(&mut self, data: Vec<u8>) -> Result<AddFileResponse> {
self.post_binary(data).await
self.post_binary::<AddFile>(data).await
}
/// Moves files with matching hashes to the trash
pub async fn delete_files(&mut self, hashes: Vec<String>) -> Result<()> {
self.post::<DeleteFilesResponse, DeleteFilesRequest>(DeleteFilesRequest { hashes })
self.post::<DeleteFiles>(DeleteFilesRequest { hashes })
.await?;
Ok(())
@ -144,7 +142,7 @@ impl Client {
/// Pulls files out of the trash by hash
pub async fn undelete_files(&mut self, hashes: Vec<String>) -> Result<()> {
self.post::<UndeleteFilesResponse, UndeleteFilesRequest>(UndeleteFilesRequest { hashes })
self.post::<UndeleteFiles>(UndeleteFilesRequest { hashes })
.await?;
Ok(())
@ -152,7 +150,7 @@ impl Client {
/// Moves files from the inbox into the archive
pub async fn archive_files(&mut self, hashes: Vec<String>) -> Result<()> {
self.post::<ArchiveFilesResponse, ArchiveFilesRequest>(ArchiveFilesRequest { hashes })
self.post::<ArchiveFiles>(ArchiveFilesRequest { hashes })
.await?;
Ok(())
@ -160,9 +158,7 @@ impl Client {
/// Moves files from the archive into the inbox
pub async fn unarchive_files(&mut self, hashes: Vec<String>) -> Result<()> {
self.post::<UnarchiveFilesResponse, UnarchiveFilesRequest>(UnarchiveFilesRequest {
hashes,
})
self.post::<UnarchiveFiles>(UnarchiveFilesRequest { hashes })
.await?;
Ok(())
@ -170,14 +166,16 @@ impl Client {
/// Returns the list of tags as the client would see them in a human friendly order
pub async fn clean_tags(&mut self, tags: Vec<String>) -> Result<CleanTagsResponse> {
self.get_and_parse(&[("tags", string_list_to_json_array(tags))])
self.get_and_parse::<CleanTags, [(&str, String)]>(&[(
"tags",
string_list_to_json_array(tags),
)])
.await
}
/// Adds tags to files with the given hashes
pub async fn add_tags(&mut self, request: AddTagsRequest) -> Result<()> {
self.post::<AddTagsResponse, AddTagsRequest>(request)
.await?;
self.post::<AddTags>(request).await?;
Ok(())
}

@ -1,5 +1,5 @@
use crate::paths::common::BasicServiceInfo;
use crate::paths::Path;
use crate::endpoints::common::BasicServiceInfo;
use crate::endpoints::Endpoint;
use std::collections::HashMap;
#[derive(Debug, Clone, Deserialize)]
@ -8,7 +8,12 @@ pub struct ApiVersionResponse {
pub hydrus_version: u32,
}
impl Path for ApiVersionResponse {
pub struct ApiVersion;
impl Endpoint for ApiVersion {
type Request = ();
type Response = ApiVersionResponse;
fn get_path() -> String {
String::from("api_version")
}
@ -19,7 +24,12 @@ pub struct SessionKeyResponse {
pub session_key: String,
}
impl Path for SessionKeyResponse {
pub struct SessionKey;
impl Endpoint for SessionKey {
type Request = ();
type Response = SessionKeyResponse;
fn get_path() -> String {
String::from("session_key")
}
@ -31,7 +41,12 @@ pub struct VerifyAccessKeyResponse {
pub human_description: String,
}
impl Path for VerifyAccessKeyResponse {
pub struct VerifyAccessKey;
impl Endpoint for VerifyAccessKey {
type Request = ();
type Response = VerifyAccessKeyResponse;
fn get_path() -> String {
String::from("verify_access_key")
}
@ -40,7 +55,12 @@ impl Path for VerifyAccessKeyResponse {
#[derive(Debug, Clone, Deserialize)]
pub struct GetServicesResponse(pub HashMap<String, Vec<BasicServiceInfo>>);
impl Path for GetServicesResponse {
pub struct GetServices;
impl Endpoint for GetServices {
type Request = ();
type Response = GetServicesResponse;
fn get_path() -> String {
String::from("get_services")
}

@ -1,5 +1,5 @@
use crate::paths::common::BasicHashList;
use crate::paths::Path;
use crate::endpoints::common::BasicHashList;
use crate::endpoints::Endpoint;
#[derive(Debug, Clone, Serialize)]
pub struct AddFileRequest {
@ -13,43 +13,61 @@ pub struct AddFileResponse {
pub note: String,
}
impl Path for AddFileResponse {
pub struct AddFile;
impl Endpoint for AddFile {
type Request = AddFileRequest;
type Response = AddFileResponse;
fn get_path() -> String {
String::from("add_files/add_file")
}
}
pub type DeleteFilesRequest = BasicHashList;
pub struct DeleteFilesResponse;
impl Path for DeleteFilesResponse {
pub struct DeleteFiles;
impl Endpoint for DeleteFiles {
type Request = DeleteFilesRequest;
type Response = ();
fn get_path() -> String {
String::from("add_files/delete_files")
}
}
pub type UndeleteFilesRequest = BasicHashList;
pub struct UndeleteFilesResponse;
pub struct UndeleteFiles;
impl Endpoint for UndeleteFiles {
type Request = UndeleteFilesRequest;
type Response = ();
impl Path for UndeleteFilesResponse {
fn get_path() -> String {
String::from("add_files/undelete_files")
}
}
pub type ArchiveFilesRequest = BasicHashList;
pub struct ArchiveFilesResponse;
pub struct ArchiveFiles;
impl Endpoint for ArchiveFiles {
type Request = ArchiveFilesRequest;
type Response = ();
impl Path for ArchiveFilesResponse {
fn get_path() -> String {
String::from("add_files/archive_files")
}
}
pub type UnarchiveFilesRequest = BasicHashList;
pub struct UnarchiveFilesResponse;
pub struct UnarchiveFiles;
impl Endpoint for UnarchiveFiles {
type Request = UndeleteFilesRequest;
type Response = ();
impl Path for UnarchiveFilesResponse {
fn get_path() -> String {
String::from("add_files/unarchive_files")
}

@ -1,4 +1,4 @@
use crate::paths::Path;
use crate::endpoints::Endpoint;
use std::collections::HashMap;
#[derive(Debug, Clone, Deserialize)]
@ -6,7 +6,12 @@ pub struct CleanTagsResponse {
pub tags: Vec<String>,
}
impl Path for CleanTagsResponse {
pub struct CleanTags;
impl Endpoint for CleanTags {
type Request = ();
type Response = CleanTagsResponse;
fn get_path() -> String {
String::from("add_tags/clean_tags")
}
@ -19,9 +24,12 @@ pub struct AddTagsRequest {
pub service_names_to_actions_to_tags: HashMap<String, HashMap<String, Vec<String>>>,
}
pub struct AddTagsResponse;
pub struct AddTags;
impl Endpoint for AddTags {
type Request = AddTagsRequest;
type Response = ();
impl Path for AddTagsResponse {
fn get_path() -> String {
String::from("add_tags/add_tags")
}

@ -0,0 +1,14 @@
use serde::de::DeserializeOwned;
use serde::Serialize;
pub mod access_management;
pub mod adding_files;
pub mod adding_tags;
pub mod common;
pub trait Endpoint {
type Request: Serialize;
type Response: DeserializeOwned;
fn get_path() -> String;
}

@ -6,7 +6,7 @@
//! ## Usage Example
//! ```
//! use hydrus_api::Client;
//! use hydrus_api::paths::adding_tags::{AddTagsRequestBuilder, TagAction};
//! use hydrus_api::endpoints::adding_tags::{AddTagsRequestBuilder, TagAction};
//! use std::env;
//! # #[tokio::test]
//! # async fn doctest() {
@ -35,8 +35,8 @@
extern crate serde_derive;
pub mod client;
pub mod endpoints;
mod error;
pub mod paths;
pub(crate) mod utils;
pub use client::Client;

@ -1,8 +0,0 @@
pub mod access_management;
pub mod adding_files;
pub mod adding_tags;
pub mod common;
pub trait Path {
fn get_path() -> String;
}

@ -1,4 +1,4 @@
use hydrus_api::paths::adding_tags::{AddTagsRequestBuilder, TagAction};
use hydrus_api::endpoints::adding_tags::{AddTagsRequestBuilder, TagAction};
mod common;
#[tokio::test]

Loading…
Cancel
Save