|
|
|
@ -11,7 +11,7 @@ use crate::endpoints::adding_urls::{
|
|
|
|
|
AddUrl, AddUrlRequest, AddUrlResponse, AssociateUrl, AssociateUrlRequest, GetUrlFiles,
|
|
|
|
|
GetUrlFilesResponse, GetUrlInfo, GetUrlInfoResponse,
|
|
|
|
|
};
|
|
|
|
|
use crate::endpoints::common::{FileIdentifier, FileRecord};
|
|
|
|
|
use crate::endpoints::common::{FileIdentifier, FileMetadataInfo, FileRecord};
|
|
|
|
|
use crate::endpoints::searching_and_fetching_files::{
|
|
|
|
|
FileMetadata, FileMetadataResponse, FileSearchLocation, GetFile, SearchFiles,
|
|
|
|
|
SearchFilesResponse,
|
|
|
|
@ -43,10 +43,10 @@ impl Client {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Starts a get request to the path
|
|
|
|
|
async fn get<E: Endpoint, Q: Serialize + ?Sized>(&mut self, query: &Q) -> Result<Response> {
|
|
|
|
|
async fn get<E: Endpoint, Q: Serialize + ?Sized>(&self, query: &Q) -> Result<Response> {
|
|
|
|
|
let response = self
|
|
|
|
|
.inner
|
|
|
|
|
.get(format!("{}/{}", self.base_url, E::get_path()))
|
|
|
|
|
.get(format!("{}/{}", self.base_url, E::path()))
|
|
|
|
|
.header(ACCESS_KEY_HEADER, &self.access_key)
|
|
|
|
|
.query(query)
|
|
|
|
|
.send()
|
|
|
|
@ -57,7 +57,7 @@ impl Client {
|
|
|
|
|
|
|
|
|
|
/// Starts a get request to the path associated with the Endpoint Type
|
|
|
|
|
async fn get_and_parse<E: Endpoint, Q: Serialize + ?Sized>(
|
|
|
|
|
&mut self,
|
|
|
|
|
&self,
|
|
|
|
|
query: &Q,
|
|
|
|
|
) -> Result<E::Response> {
|
|
|
|
|
let response = self.get::<E, Q>(query).await?;
|
|
|
|
@ -66,10 +66,10 @@ impl Client {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Stats a post request to the path associated with the Endpoint Type
|
|
|
|
|
async fn post<E: Endpoint>(&mut self, body: E::Request) -> Result<Response> {
|
|
|
|
|
async fn post<E: Endpoint>(&self, body: E::Request) -> Result<Response> {
|
|
|
|
|
let response = self
|
|
|
|
|
.inner
|
|
|
|
|
.post(format!("{}/{}", self.base_url, E::get_path()))
|
|
|
|
|
.post(format!("{}/{}", self.base_url, E::path()))
|
|
|
|
|
.json(&body)
|
|
|
|
|
.header(ACCESS_KEY_HEADER, &self.access_key)
|
|
|
|
|
.send()
|
|
|
|
@ -79,17 +79,17 @@ impl Client {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Stats a post request and parses the body as json
|
|
|
|
|
async fn post_and_parse<E: Endpoint>(&mut self, body: E::Request) -> Result<E::Response> {
|
|
|
|
|
async fn post_and_parse<E: Endpoint>(&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<E: Endpoint>(&mut self, data: Vec<u8>) -> Result<E::Response> {
|
|
|
|
|
async fn post_binary<E: Endpoint>(&self, data: Vec<u8>) -> Result<E::Response> {
|
|
|
|
|
let response = self
|
|
|
|
|
.inner
|
|
|
|
|
.post(format!("{}/{}", self.base_url, E::get_path()))
|
|
|
|
|
.post(format!("{}/{}", self.base_url, E::path()))
|
|
|
|
|
.body(data)
|
|
|
|
|
.header(ACCESS_KEY_HEADER, &self.access_key)
|
|
|
|
|
.header("Content-Type", "application/octet-stream")
|
|
|
|
@ -116,27 +116,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> {
|
|
|
|
|
pub async fn api_version(&self) -> Result<ApiVersionResponse> {
|
|
|
|
|
self.get_and_parse::<ApiVersion, ()>(&()).await
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Creates a new session key
|
|
|
|
|
pub async fn session_key(&mut self) -> Result<SessionKeyResponse> {
|
|
|
|
|
pub async fn session_key(&self) -> Result<SessionKeyResponse> {
|
|
|
|
|
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> {
|
|
|
|
|
pub async fn verify_access_key(&self) -> Result<VerifyAccessKeyResponse> {
|
|
|
|
|
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> {
|
|
|
|
|
pub async fn get_services(&self) -> Result<GetServicesResponse> {
|
|
|
|
|
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> {
|
|
|
|
|
pub async fn add_file<S: AsRef<str>>(&self, path: S) -> Result<AddFileResponse> {
|
|
|
|
|
self.post_and_parse::<AddFile>(AddFileRequest {
|
|
|
|
|
path: path.as_ref().to_string(),
|
|
|
|
|
})
|
|
|
|
@ -144,12 +144,12 @@ impl Client {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// 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(&self, data: Vec<u8>) -> Result<AddFileResponse> {
|
|
|
|
|
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<()> {
|
|
|
|
|
pub async fn delete_files(&self, hashes: Vec<String>) -> Result<()> {
|
|
|
|
|
self.post::<DeleteFiles>(DeleteFilesRequest { hashes })
|
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
|
@ -157,7 +157,7 @@ impl Client {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Pulls files out of the trash by hash
|
|
|
|
|
pub async fn undelete_files(&mut self, hashes: Vec<String>) -> Result<()> {
|
|
|
|
|
pub async fn undelete_files(&self, hashes: Vec<String>) -> Result<()> {
|
|
|
|
|
self.post::<UndeleteFiles>(UndeleteFilesRequest { hashes })
|
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
|
@ -165,7 +165,7 @@ impl Client {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Moves files from the inbox into the archive
|
|
|
|
|
pub async fn archive_files(&mut self, hashes: Vec<String>) -> Result<()> {
|
|
|
|
|
pub async fn archive_files(&self, hashes: Vec<String>) -> Result<()> {
|
|
|
|
|
self.post::<ArchiveFiles>(ArchiveFilesRequest { hashes })
|
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
|
@ -173,7 +173,7 @@ impl Client {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Moves files from the archive into the inbox
|
|
|
|
|
pub async fn unarchive_files(&mut self, hashes: Vec<String>) -> Result<()> {
|
|
|
|
|
pub async fn unarchive_files(&self, hashes: Vec<String>) -> Result<()> {
|
|
|
|
|
self.post::<UnarchiveFiles>(UnarchiveFilesRequest { hashes })
|
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
|
@ -181,7 +181,7 @@ 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> {
|
|
|
|
|
pub async fn clean_tags(&self, tags: Vec<String>) -> Result<CleanTagsResponse> {
|
|
|
|
|
self.get_and_parse::<CleanTags, [(&str, String)]>(&[(
|
|
|
|
|
"tags",
|
|
|
|
|
string_list_to_json_array(tags),
|
|
|
|
@ -190,7 +190,7 @@ impl Client {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Adds tags to files with the given hashes
|
|
|
|
|
pub async fn add_tags(&mut self, request: AddTagsRequest) -> Result<()> {
|
|
|
|
|
pub async fn add_tags(&self, request: AddTagsRequest) -> Result<()> {
|
|
|
|
|
self.post::<AddTags>(request).await?;
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
@ -198,7 +198,7 @@ impl Client {
|
|
|
|
|
|
|
|
|
|
/// Searches for files in the inbox, the archive or both
|
|
|
|
|
pub async fn search_files(
|
|
|
|
|
&mut self,
|
|
|
|
|
&self,
|
|
|
|
|
tags: Vec<String>,
|
|
|
|
|
location: FileSearchLocation,
|
|
|
|
|
) -> Result<SearchFilesResponse> {
|
|
|
|
@ -212,19 +212,37 @@ impl Client {
|
|
|
|
|
|
|
|
|
|
/// Returns the metadata for a given list of file_ids or hashes
|
|
|
|
|
pub async fn get_file_metadata(
|
|
|
|
|
&mut self,
|
|
|
|
|
&self,
|
|
|
|
|
file_ids: Vec<u64>,
|
|
|
|
|
hashes: Vec<String>,
|
|
|
|
|
) -> Result<FileMetadataResponse> {
|
|
|
|
|
self.get_and_parse::<FileMetadata, [(&str, String)]>(&[
|
|
|
|
|
("file_ids", number_list_to_json_array(file_ids)),
|
|
|
|
|
("hashes", string_list_to_json_array(hashes)),
|
|
|
|
|
])
|
|
|
|
|
.await
|
|
|
|
|
let query = if file_ids.len() > 0 {
|
|
|
|
|
("file_ids", number_list_to_json_array(file_ids))
|
|
|
|
|
} else {
|
|
|
|
|
("hashes", string_list_to_json_array(hashes))
|
|
|
|
|
};
|
|
|
|
|
self.get_and_parse::<FileMetadata, [(&str, String)]>(&[query])
|
|
|
|
|
.await
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns the metadata for a single file identifier
|
|
|
|
|
pub async fn get_file_metadata_by_identifier(
|
|
|
|
|
&self,
|
|
|
|
|
identifier: FileIdentifier,
|
|
|
|
|
) -> Result<FileMetadataInfo> {
|
|
|
|
|
let mut response = match identifier.clone() {
|
|
|
|
|
FileIdentifier::ID(id) => self.get_file_metadata(vec![id], vec![]).await?,
|
|
|
|
|
FileIdentifier::Hash(hash) => self.get_file_metadata(vec![], vec![hash]).await?,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
response
|
|
|
|
|
.metadata
|
|
|
|
|
.pop()
|
|
|
|
|
.ok_or_else(|| Error::FileNotFound(identifier))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns the bytes of a file from hydrus
|
|
|
|
|
pub async fn get_file(&mut self, id: FileIdentifier) -> Result<FileRecord> {
|
|
|
|
|
pub async fn get_file(&self, id: FileIdentifier) -> Result<FileRecord> {
|
|
|
|
|
let response = match id {
|
|
|
|
|
FileIdentifier::ID(id) => {
|
|
|
|
|
self.get::<GetFile, [(&str, u64)]>(&[("file_id", id)])
|
|
|
|
@ -248,24 +266,24 @@ impl Client {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns all files associated with the given url
|
|
|
|
|
pub async fn get_url_files<S: AsRef<str>>(&mut self, url: S) -> Result<GetUrlFilesResponse> {
|
|
|
|
|
pub async fn get_url_files<S: AsRef<str>>(&self, url: S) -> Result<GetUrlFilesResponse> {
|
|
|
|
|
self.get_and_parse::<GetUrlFiles, [(&str, &str)]>(&[("url", url.as_ref())])
|
|
|
|
|
.await
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns information about the given url
|
|
|
|
|
pub async fn get_url_info<S: AsRef<str>>(&mut self, url: S) -> Result<GetUrlInfoResponse> {
|
|
|
|
|
pub async fn get_url_info<S: AsRef<str>>(&self, url: S) -> Result<GetUrlInfoResponse> {
|
|
|
|
|
self.get_and_parse::<GetUrlInfo, [(&str, &str)]>(&[("url", url.as_ref())])
|
|
|
|
|
.await
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Adds an url to hydrus, optionally with additional tags and a destination page
|
|
|
|
|
pub async fn add_url(&mut self, request: AddUrlRequest) -> Result<AddUrlResponse> {
|
|
|
|
|
pub async fn add_url(&self, request: AddUrlRequest) -> Result<AddUrlResponse> {
|
|
|
|
|
self.post_and_parse::<AddUrl>(request).await
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Associates urls with the given file hashes
|
|
|
|
|
pub async fn associate_urls(&mut self, urls: Vec<String>, hashes: Vec<String>) -> Result<()> {
|
|
|
|
|
pub async fn associate_urls(&self, urls: Vec<String>, hashes: Vec<String>) -> Result<()> {
|
|
|
|
|
self.post::<AssociateUrl>(AssociateUrlRequest {
|
|
|
|
|
hashes,
|
|
|
|
|
urls_to_add: urls,
|
|
|
|
@ -277,11 +295,7 @@ impl Client {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Disassociates urls with the given file hashes
|
|
|
|
|
pub async fn disassociate_urls(
|
|
|
|
|
&mut self,
|
|
|
|
|
urls: Vec<String>,
|
|
|
|
|
hashes: Vec<String>,
|
|
|
|
|
) -> Result<()> {
|
|
|
|
|
pub async fn disassociate_urls(&self, urls: Vec<String>, hashes: Vec<String>) -> Result<()> {
|
|
|
|
|
self.post::<AssociateUrl>(AssociateUrlRequest {
|
|
|
|
|
hashes,
|
|
|
|
|
urls_to_add: vec![],
|
|
|
|
|