Add support for adding tags to services by service keys

Signed-off-by: trivernis <trivernis@protonmail.com>
pull/9/head
trivernis 3 years ago
parent be51ac4054
commit 7260eb825a
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

@ -1,3 +1,4 @@
use crate::api_core::common::ServiceIdentifier;
use crate::api_core::Endpoint; use crate::api_core::Endpoint;
use std::collections::HashMap; use std::collections::HashMap;
@ -21,7 +22,9 @@ impl Endpoint for CleanTags {
pub struct AddTagsRequest { pub struct AddTagsRequest {
pub hashes: Vec<String>, pub hashes: Vec<String>,
pub service_names_to_tags: HashMap<String, 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_names_to_actions_to_tags: HashMap<String, HashMap<String, Vec<String>>>,
pub service_keys_to_actions_to_tags: HashMap<String, HashMap<String, Vec<String>>>,
} }
pub struct AddTags; pub struct AddTags;
@ -35,10 +38,13 @@ impl Endpoint for AddTags {
} }
} }
#[derive(Default)]
pub struct AddTagsRequestBuilder { pub struct AddTagsRequestBuilder {
hashes: Vec<String>, hashes: Vec<String>,
service_names_to_tags: HashMap<String, 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_names_to_actions_to_tags: HashMap<String, HashMap<String, Vec<String>>>,
service_keys_to_actions_to_tags: HashMap<String, HashMap<String, Vec<String>>>,
} }
/// List of actions for a given tag /// List of actions for a given tag
@ -78,16 +84,6 @@ impl TagAction {
} }
} }
impl Default for AddTagsRequestBuilder {
fn default() -> Self {
Self {
hashes: vec![],
service_names_to_tags: Default::default(),
service_names_to_actions_to_tags: Default::default(),
}
}
}
impl AddTagsRequestBuilder { impl AddTagsRequestBuilder {
/// Adds a file hash to the request /// Adds a file hash to the request
pub fn add_hash<S: AsRef<str>>(mut self, hash: S) -> Self { pub fn add_hash<S: AsRef<str>>(mut self, hash: S) -> Self {
@ -104,41 +100,48 @@ impl AddTagsRequestBuilder {
} }
/// Adds a single tag for a given service /// Adds a single tag for a given service
pub fn add_tag<S1: AsRef<str>, S2: AsRef<str>>(mut self, service_name: S1, tag: S2) -> Self { pub fn add_tag<S: AsRef<str>>(mut self, service_id: ServiceIdentifier, tag: S) -> Self {
if let Some(mappings) = self.service_names_to_tags.get_mut(service_name.as_ref()) { 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),
};
if let Some(mappings) = relevant_mappings.get_mut(&service) {
mappings.push(tag.as_ref().into()) mappings.push(tag.as_ref().into())
} else { } else {
self.service_names_to_tags relevant_mappings.insert(service, vec![tag.as_ref().into()]);
.insert(service_name.as_ref().into(), vec![tag.as_ref().into()]);
} }
self self
} }
/// Adds multiple tags for a given service /// Adds multiple tags for a given service
pub fn add_tags<S1: AsRef<str>>(mut self, service_name: S1, mut tags: Vec<String>) -> Self { pub fn add_tags(mut self, service_id: ServiceIdentifier, mut tags: Vec<String>) -> Self {
if let Some(mappings) = self.service_names_to_tags.get_mut(service_name.as_ref()) { 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),
};
if let Some(mappings) = relevant_mappings.get_mut(&service) {
mappings.append(&mut tags); mappings.append(&mut tags);
} else { } else {
self.service_names_to_tags relevant_mappings.insert(service, tags);
.insert(service_name.as_ref().into(), tags);
} }
self self
} }
/// Adds one tag for a given service with a defined action /// Adds one tag for a given service with a defined action
pub fn add_tag_with_action<S1: AsRef<str>, S2: AsRef<str>>( pub fn add_tag_with_action<S: AsRef<str>>(
mut self, mut self,
service_name: S1, service_id: ServiceIdentifier,
tag: S2, tag: S,
action: TagAction, action: TagAction,
) -> Self { ) -> 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 action_id = action.into_id(); let action_id = action.into_id();
if let Some(actions) = self if let Some(actions) = relevant_mappings.get_mut(&service) {
.service_names_to_actions_to_tags
.get_mut(service_name.as_ref())
{
if let Some(tags) = actions.get_mut(&action_id.to_string()) { if let Some(tags) = actions.get_mut(&action_id.to_string()) {
tags.push(tag.as_ref().into()); tags.push(tag.as_ref().into());
} else { } else {
@ -147,8 +150,7 @@ impl AddTagsRequestBuilder {
} else { } else {
let mut actions = HashMap::new(); let mut actions = HashMap::new();
actions.insert(action_id.to_string(), vec![tag.as_ref().into()]); actions.insert(action_id.to_string(), vec![tag.as_ref().into()]);
self.service_names_to_actions_to_tags relevant_mappings.insert(service, actions);
.insert(service_name.as_ref().into(), actions);
} }
self self
} }
@ -158,7 +160,9 @@ impl AddTagsRequestBuilder {
AddTagsRequest { AddTagsRequest {
hashes: self.hashes, hashes: self.hashes,
service_names_to_tags: self.service_names_to_tags, 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_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,
} }
} }
} }

@ -228,6 +228,7 @@ impl Client {
} }
/// Adds tags to files with the given hashes /// Adds tags to files with the given hashes
#[tracing::instrument(skip(self), level = "debug")]
pub async fn add_tags(&self, request: AddTagsRequest) -> Result<()> { pub async fn add_tags(&self, request: AddTagsRequest) -> Result<()> {
self.post::<AddTags>(request).await?; self.post::<AddTags>(request).await?;

@ -6,6 +6,22 @@ pub struct BasicServiceInfo {
pub service_key: String, pub service_key: String,
} }
#[derive(Clone, Debug, Serialize, Deserialize, Hash, PartialOrd, PartialEq, Ord, Eq)]
pub enum ServiceIdentifier {
Name(String),
Key(String),
}
impl ServiceIdentifier {
pub fn name<S: ToString>(name: S) -> Self {
Self::Name(name.to_string())
}
pub fn key<S: ToString>(key: S) -> Self {
Self::Key(key.to_string())
}
}
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BasicHashList { pub struct BasicHashList {
pub hashes: Vec<String>, pub hashes: Vec<String>,

@ -1,6 +1,6 @@
use crate::api_core::adding_tags::{AddTagsRequestBuilder, TagAction}; use crate::api_core::adding_tags::{AddTagsRequestBuilder, TagAction};
use crate::api_core::common::ServiceIdentifier;
use crate::error::Result; use crate::error::Result;
use crate::wrapper::service::ServiceName;
use crate::wrapper::tag::Tag; use crate::wrapper::tag::Tag;
use crate::Client; use crate::Client;
use std::collections::HashMap; use std::collections::HashMap;
@ -8,7 +8,7 @@ use std::collections::HashMap;
pub struct TaggingBuilder { pub struct TaggingBuilder {
client: Client, client: Client,
hashes: Vec<String>, hashes: Vec<String>,
tag_mappings: HashMap<ServiceName, HashMap<TagAction, Vec<Tag>>>, tag_mappings: HashMap<ServiceIdentifier, HashMap<TagAction, Vec<Tag>>>,
} }
impl TaggingBuilder { impl TaggingBuilder {
@ -28,12 +28,17 @@ impl TaggingBuilder {
} }
/// Adds a single tag for a given service /// Adds a single tag for a given service
pub fn add_tag(self, service: ServiceName, action: TagAction, tag: Tag) -> Self { pub fn add_tag(self, service: ServiceIdentifier, action: TagAction, tag: Tag) -> Self {
self.add_tags(service, action, vec![tag]) self.add_tags(service, action, vec![tag])
} }
/// Adds tags with actions for the given service /// Adds tags with actions for the given service
pub fn add_tags(mut self, service: ServiceName, action: TagAction, mut tags: Vec<Tag>) -> Self { pub fn add_tags(
mut self,
service: ServiceIdentifier,
action: TagAction,
mut tags: Vec<Tag>,
) -> Self {
let service_action_mappings = let service_action_mappings =
if let Some(service_action_mappings) = self.tag_mappings.get_mut(&service) { if let Some(service_action_mappings) = self.tag_mappings.get_mut(&service) {
service_action_mappings service_action_mappings
@ -57,7 +62,7 @@ impl TaggingBuilder {
for (action, tags) in action_tag_mappings { for (action, tags) in action_tag_mappings {
for tag in tags { for tag in tags {
request = request.add_tag_with_action( request = request.add_tag_with_action(
service.0.clone(), service.clone().into(),
tag.to_string(), tag.to_string(),
action.clone(), action.clone(),
); );

@ -217,7 +217,7 @@ impl HydrusFile {
let hash = self.hash().await?; let hash = self.hash().await?;
let request = AddTagsRequestBuilder::default() let request = AddTagsRequestBuilder::default()
.add_hash(hash) .add_hash(hash)
.add_tags(service.0, tag_list_to_string_list(tags)) .add_tags(service.into(), tag_list_to_string_list(tags))
.build(); .build();
self.client.add_tags(request).await self.client.add_tags(request).await
@ -234,8 +234,11 @@ impl HydrusFile {
let mut reqwest = AddTagsRequestBuilder::default().add_hash(hash); let mut reqwest = AddTagsRequestBuilder::default().add_hash(hash);
for tag in tags { for tag in tags {
reqwest = reqwest = reqwest.add_tag_with_action(
reqwest.add_tag_with_action(service.0.clone(), tag.to_string(), action.clone()); service.clone().into(),
tag.to_string(),
action.clone(),
);
} }
self.client.add_tags(reqwest.build()).await self.client.add_tags(reqwest.build()).await

@ -5,6 +5,7 @@ use crate::api_core::access_management::{
SERVICE_TYPE_TAG_REPOSITORIES, SERVICE_TYPE_TRASH, SERVICE_TYPE_TAG_REPOSITORIES, SERVICE_TYPE_TRASH,
}; };
use crate::api_core::common::ServiceIdentifier;
use crate::error::Error; use crate::error::Error;
use crate::wrapper::builders::search_builder::SearchBuilder; use crate::wrapper::builders::search_builder::SearchBuilder;
use crate::Client; use crate::Client;
@ -96,6 +97,12 @@ impl Display for ServiceName {
} }
} }
impl Into<ServiceIdentifier> for ServiceName {
fn into(self) -> ServiceIdentifier {
ServiceIdentifier::Name(self.0)
}
}
#[derive(Clone)] #[derive(Clone)]
pub struct Service { pub struct Service {
client: Client, client: Client,

@ -1,5 +1,6 @@
use super::super::common; use super::super::common;
use hydrus_api::api_core::adding_tags::{AddTagsRequestBuilder, TagAction}; use hydrus_api::api_core::adding_tags::{AddTagsRequestBuilder, TagAction};
use hydrus_api::api_core::common::ServiceIdentifier;
#[tokio::test] #[tokio::test]
async fn it_cleans_tags() { async fn it_cleans_tags() {
@ -21,8 +22,15 @@ async fn it_adds_tags() {
let client = common::get_client(); let client = common::get_client();
let request = AddTagsRequestBuilder::default() let request = AddTagsRequestBuilder::default()
.add_hash("0000000000000000000000000000000000000000000000000000000000000000") // valid hash, I hope no files are affected .add_hash("0000000000000000000000000000000000000000000000000000000000000000") // valid hash, I hope no files are affected
.add_tags("my tags", vec!["beach".into(), "summer".into()]) .add_tags(
.add_tag_with_action("my tags", "rain", TagAction::DeleteFromLocalService) ServiceIdentifier::name("my tags"),
vec!["beach".into(), "summer".into()],
)
.add_tag_with_action(
ServiceIdentifier::name("my tags"),
"rain",
TagAction::DeleteFromLocalService,
)
.build(); .build();
client.add_tags(request).await.unwrap(); client.add_tags(request).await.unwrap();
} }

@ -60,7 +60,7 @@ async fn it_adds_tags() {
hydrus hydrus
.tagging() .tagging()
.add_tag( .add_tag(
ServiceName::my_tags(), ServiceName::my_tags().into(),
TagAction::AddToLocalService, TagAction::AddToLocalService,
"summer".into(), "summer".into(),
) )

Loading…
Cancel
Save