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