Compare commits

...

5 Commits

@ -1,6 +1,6 @@
[package]
name = "hydrus-api"
version = "0.9.3"
version = "0.10.2"
authors = ["trivernis <trivernis@protonmail.com>"]
edition = "2018"
license = "Apache-2.0"
@ -36,4 +36,4 @@ features = ["macros", "rt-multi-thread"]
default = ["json"]
rustls = ["reqwest/rustls"]
cbor = ["ciborium", "base64"]
json = ["serde_json"]
json = ["serde_json"]

@ -6,6 +6,17 @@ use std::collections::HashMap;
pub struct BasicServiceInfo {
pub name: String,
pub service_key: String,
#[serde(alias = "type")]
pub service_type: u64,
pub type_pretty: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServiceItem {
pub name: String,
#[serde(alias = "type")]
pub service_type: u64,
pub type_pretty: String,
}
impl BasicServiceInfo {
@ -200,6 +211,10 @@ pub struct FileMetadataServices {
#[derive(Clone, Debug, Deserialize)]
pub struct FileMetadataServiceCurrent {
pub name: String,
#[serde(alias = "type")]
pub service_type: u64,
pub type_pretty: String,
pub time_imported: u64,
}

@ -1,4 +1,4 @@
use crate::api_core::common::BasicServiceInfo;
use crate::api_core::common::{BasicServiceInfo, ServiceItem};
use crate::api_core::endpoints::Endpoint;
use std::collections::HashMap;
@ -62,7 +62,13 @@ impl Endpoint for VerifyAccessKey {
}
#[derive(Debug, Clone, Deserialize)]
pub struct GetServicesResponse(pub HashMap<String, Vec<BasicServiceInfo>>);
pub struct GetServicesResponse {
pub services: HashMap<String, ServiceItem>,
pub version: u64,
pub hydrus_version: u64,
#[serde(flatten)]
pub other: HashMap<String, Vec<BasicServiceInfo>>,
}
pub struct GetServices;

@ -21,9 +21,7 @@ impl Endpoint for CleanTags {
#[derive(Debug, Clone, Serialize)]
pub struct AddTagsRequest {
pub hashes: Vec<String>,
pub service_names_to_tags: HashMap<String, Vec<String>>,
pub service_keys_to_tags: HashMap<String, Vec<String>>,
pub service_names_to_actions_to_tags: HashMap<String, HashMap<String, Vec<String>>>,
pub service_keys_to_actions_to_tags: HashMap<String, HashMap<String, Vec<String>>>,
}
@ -41,9 +39,7 @@ impl Endpoint for AddTags {
#[derive(Default)]
pub struct AddTagsRequestBuilder {
hashes: Vec<String>,
service_names_to_tags: HashMap<String, Vec<String>>,
service_keys_to_tags: HashMap<String, Vec<String>>,
service_names_to_actions_to_tags: HashMap<String, HashMap<String, Vec<String>>>,
service_keys_to_actions_to_tags: HashMap<String, HashMap<String, Vec<String>>>,
}
@ -100,11 +96,8 @@ impl AddTagsRequestBuilder {
}
/// Adds a single tag for a given service
pub fn add_tag<S: AsRef<str>>(mut self, service_id: ServiceIdentifier, tag: S) -> Self {
let (service, relevant_mappings) = match service_id {
ServiceIdentifier::Name(name) => (name, &mut self.service_names_to_tags),
ServiceIdentifier::Key(key) => (key, &mut self.service_keys_to_tags),
};
pub fn add_tag<S: AsRef<str>>(mut self, service_key: String, tag: S) -> Self {
let (service, relevant_mappings) = (service_key, &mut self.service_keys_to_tags);
if let Some(mappings) = relevant_mappings.get_mut(&service) {
mappings.push(tag.as_ref().into())
} else {
@ -115,11 +108,8 @@ impl AddTagsRequestBuilder {
}
/// Adds multiple tags for a given service
pub fn add_tags(mut self, service_id: ServiceIdentifier, mut tags: Vec<String>) -> Self {
let (service, relevant_mappings) = match service_id {
ServiceIdentifier::Name(name) => (name, &mut self.service_names_to_tags),
ServiceIdentifier::Key(key) => (key, &mut self.service_keys_to_tags),
};
pub fn add_tags(mut self, service_key: String, mut tags: Vec<String>) -> Self {
let (service, relevant_mappings) = (service_key, &mut self.service_keys_to_tags);
if let Some(mappings) = relevant_mappings.get_mut(&service) {
mappings.append(&mut tags);
} else {
@ -132,14 +122,11 @@ impl AddTagsRequestBuilder {
/// Adds one tag for a given service with a defined action
pub fn add_tag_with_action<S: AsRef<str>>(
mut self,
service_id: ServiceIdentifier,
service_key: String,
tag: S,
action: TagAction,
) -> Self {
let (service, relevant_mappings) = match service_id {
ServiceIdentifier::Name(name) => (name, &mut self.service_names_to_actions_to_tags),
ServiceIdentifier::Key(key) => (key, &mut self.service_keys_to_actions_to_tags),
};
let (service, relevant_mappings) = (service_key, &mut self.service_keys_to_actions_to_tags);
let action_id = action.into_id();
if let Some(actions) = relevant_mappings.get_mut(&service) {
if let Some(tags) = actions.get_mut(&action_id.to_string()) {
@ -159,9 +146,7 @@ impl AddTagsRequestBuilder {
pub fn build(self) -> AddTagsRequest {
AddTagsRequest {
hashes: self.hashes,
service_names_to_tags: self.service_names_to_tags,
service_keys_to_tags: self.service_keys_to_tags,
service_names_to_actions_to_tags: self.service_names_to_actions_to_tags,
service_keys_to_actions_to_tags: self.service_keys_to_actions_to_tags,
}
}

@ -207,8 +207,18 @@ pub struct FileFullMetadata {
pub is_trashed: bool,
pub file_services: FileMetadataServices,
pub known_urls: Vec<String>,
pub service_keys_to_statuses_to_tags: HashMap<String, HashMap<String, Vec<String>>>,
pub service_keys_to_statuses_to_display_tags: HashMap<String, HashMap<String, Vec<String>>>,
/// map of service keys to tags
pub tags: HashMap<String, ServiceTags>,
}
#[derive(Clone, Debug, Default, Deserialize)]
pub struct ServiceTags {
pub name: String,
#[serde(alias = "type")]
pub service_type: u64,
pub type_pretty: String,
pub storage_tags: HashMap<String, Vec<String>>,
pub display_tags: HashMap<String, Vec<String>>,
}
pub trait FileMetadataType: Clone + Debug {

@ -1,6 +1,6 @@
use crate::api_core::common::ServiceIdentifier;
use crate::api_core::endpoints::adding_tags::{AddTagsRequestBuilder, TagAction};
use crate::error::Result;
use crate::error::{Error, Result};
use crate::wrapper::tag::Tag;
use crate::Client;
use std::collections::HashMap;
@ -59,10 +59,25 @@ impl TaggingBuilder {
pub async fn run(self) -> Result<()> {
let mut request = AddTagsRequestBuilder::default().add_hashes(self.hashes);
for (service, action_tag_mappings) in self.tag_mappings {
let service_key = match service {
ServiceIdentifier::Name(n) => self
.client
.get_services()
.await?
.other
.values()
.flatten()
.filter(|v| *v.name == n)
.next()
.ok_or_else(|| Error::Hydrus(String::from("Service not found")))?
.service_key
.clone(),
ServiceIdentifier::Key(k) => k,
};
for (action, tags) in action_tag_mappings {
for tag in tags {
request = request.add_tag_with_action(
service.clone().into(),
service_key.clone(),
tag.to_string(),
action.clone(),
);

@ -1,6 +1,6 @@
use crate::api_core::common::FileIdentifier;
use crate::api_core::common::{FileIdentifier, ServiceIdentifier};
use crate::api_core::endpoints::searching_and_fetching_files::FullMetadata;
use crate::error::Result;
use crate::error::{Error, Result};
use crate::wrapper::address::Address;
use crate::wrapper::builders::delete_files_builder::DeleteFilesBuilder;
use crate::wrapper::builders::import_builder::ImportBuilder;
@ -125,4 +125,25 @@ impl Hydrus {
pub async fn set_user_agent<S: ToString + Debug>(&self, user_agent: S) -> Result<()> {
self.client.set_user_agent(user_agent).await
}
/// Returns the key for a given service identifier
pub async fn get_service_key(&self, service: ServiceIdentifier) -> Result<String> {
let key = match service {
ServiceIdentifier::Name(n) => self
.client
.get_services()
.await?
.other
.values()
.flatten()
.filter(|v| *v.name == n)
.next()
.ok_or_else(|| Error::Hydrus(String::from("Service not found")))?
.service_key
.clone(),
ServiceIdentifier::Key(k) => k,
};
Ok(key)
}
}

@ -295,10 +295,10 @@ impl HydrusFile {
let metadata = self.metadata().await?;
let mut tag_mappings = HashMap::new();
for (service, status_tags) in &metadata.service_keys_to_statuses_to_tags {
for (service, service_tags) in &metadata.tags {
let mut tag_list = Vec::new();
for (_, tags) in status_tags {
for (_, tags) in &service_tags.storage_tags {
tag_list.append(&mut tags.into_iter().map(|t| t.into()).collect())
}
tag_mappings.insert(ServiceIdentifier::Key(service.clone()), tag_list);
@ -312,10 +312,10 @@ impl HydrusFile {
let metadata = self.metadata().await?;
let mut tag_mappings = HashMap::new();
for (service, status_tags) in &metadata.service_keys_to_statuses_to_tags {
for (service, service_tags) in &metadata.tags {
let mut tag_list = Vec::new();
for (_, tags) in status_tags {
for (_, tags) in &service_tags.storage_tags {
tag_list.append(&mut tags.into_iter().map(|t| t.into()).collect())
}
tag_mappings.insert(ServiceIdentifier::Key(service.clone()), tag_list);
@ -337,11 +337,11 @@ impl HydrusFile {
}
/// Adds tags for a specific service to the file
pub async fn add_tags(&mut self, service: ServiceIdentifier, tags: Vec<Tag>) -> Result<()> {
pub async fn add_tags(&mut self, service_key: String, tags: Vec<Tag>) -> Result<()> {
let hash = self.hash().await?;
let request = AddTagsRequestBuilder::default()
.add_hash(hash)
.add_tags(service, tag_list_to_string_list(tags))
.add_tags(service_key, tag_list_to_string_list(tags))
.build();
self.client.add_tags(request).await
@ -350,7 +350,7 @@ impl HydrusFile {
/// Allows modification of tags by using the defined tag actions
pub async fn modify_tags(
&mut self,
service: ServiceIdentifier,
service_key: String,
action: TagAction,
tags: Vec<Tag>,
) -> Result<()> {
@ -358,7 +358,8 @@ impl HydrusFile {
let mut reqwest = AddTagsRequestBuilder::default().add_hash(hash);
for tag in tags {
reqwest = reqwest.add_tag_with_action(service.clone(), tag.to_string(), action.clone());
reqwest =
reqwest.add_tag_with_action(service_key.clone(), tag.to_string(), action.clone());
}
self.client.add_tags(reqwest.build()).await

@ -135,7 +135,7 @@ pub struct Services {
impl Services {
/// Creates the services list from a given hydrus response
pub fn from_response(client: Client, response: GetServicesResponse) -> Self {
let mut response = response.0;
let mut response = response.other;
let mut mapped_types = HashMap::with_capacity(response.keys().len());
let keys = response.keys().cloned().collect::<Vec<String>>().clone();

@ -27,5 +27,5 @@ async fn it_verifies_the_access_key() {
async fn it_returns_a_list_of_services() {
let client = common::get_client();
let services_response = client.get_services().await.unwrap();
assert!(services_response.0.keys().len() > 0);
assert!(services_response.other.keys().len() > 0);
}

@ -27,11 +27,11 @@ async fn it_adds_tags() {
let request = AddTagsRequestBuilder::default()
.add_hash(EMPTY_HASH) // valid hash, I hope no files are affected
.add_tags(
ServiceIdentifier::name("my tags"),
"6c6f63616c2074616773".into(),
vec!["beach".into(), "summer".into()],
)
.add_tag_with_action(
ServiceIdentifier::name("my tags"),
"6c6f63616c2074616773".into(),
"rain",
TagAction::DeleteFromLocalService,
)
@ -49,7 +49,7 @@ async fn it_searches_for_tags() {
"*",
TagSearchOptions::default()
.display_type(TagDisplayType::Display)
.tag_service(ServiceIdentifier::name("public tag repository")),
.tag_service(ServiceIdentifier::name("all known tags")),
)
.await
.unwrap();

@ -52,7 +52,7 @@ async fn it_fetches_file_metadata() {
client
.get_file_metadata::<FullMetadata>(
vec![],
vec!["0000000000000000000000000000000000000000000000000000000000000000".to_string()],
vec!["9641a590e66d9f2e5137b6bcba07fdf6cec3ffaa54de2565c3afcc2125ad1160".to_string()],
)
.await
.unwrap();

@ -58,7 +58,7 @@ async fn it_has_tags() {
async fn it_adds_tags() {
let mut file = get_file().await;
file.add_tags(
ServiceName::my_tags().into(),
"6c6f63616c2074616773".into(),
vec!["character:megumin".into(), "ark mage".into()],
)
.await
@ -69,8 +69,8 @@ async fn it_adds_tags() {
async fn it_modifies_tags() {
let mut file = get_file().await;
file.modify_tags(
ServiceName::my_tags().into(),
TagAction::RescindPendFromRepository,
"6c6f63616c2074616773".into(),
TagAction::DeleteFromLocalService,
vec!["ark mage".into()],
)
.await

Loading…
Cancel
Save