hydrus_api/api_core/endpoints/
adding_tags.rs1use crate::api_core::common::ServiceIdentifier;
2use crate::api_core::endpoints::Endpoint;
3use std::collections::HashMap;
4
5#[derive(Debug, Clone, Deserialize)]
6pub struct CleanTagsResponse {
7 pub tags: Vec<String>,
8}
9
10pub struct CleanTags;
11
12impl Endpoint for CleanTags {
13 type Request = ();
14 type Response = CleanTagsResponse;
15
16 fn path() -> String {
17 String::from("add_tags/clean_tags")
18 }
19}
20
21#[derive(Debug, Clone, Serialize)]
22pub struct AddTagsRequest {
23 pub hashes: Vec<String>,
24 pub service_keys_to_tags: HashMap<String, Vec<String>>,
25 pub service_keys_to_actions_to_tags: HashMap<String, HashMap<String, Vec<String>>>,
26}
27
28pub struct AddTags;
29
30impl Endpoint for AddTags {
31 type Request = AddTagsRequest;
32 type Response = ();
33
34 fn path() -> String {
35 String::from("add_tags/add_tags")
36 }
37}
38
39#[derive(Default)]
40pub struct AddTagsRequestBuilder {
41 hashes: Vec<String>,
42 service_keys_to_tags: HashMap<String, Vec<String>>,
43 service_keys_to_actions_to_tags: HashMap<String, HashMap<String, Vec<String>>>,
44}
45
46#[derive(Clone, Debug, PartialOrd, PartialEq, Hash)]
48pub enum TagAction {
49 AddToLocalService,
51
52 DeleteFromLocalService,
54
55 PendAddToRepository,
57
58 RescindPendFromRepository,
60
61 PetitionFromRepository,
63
64 RescindPetitionFromRepository,
66}
67
68impl Eq for TagAction {}
69
70impl TagAction {
71 fn into_id(self) -> u8 {
72 match self {
73 TagAction::AddToLocalService => 0,
74 TagAction::DeleteFromLocalService => 1,
75 TagAction::PendAddToRepository => 2,
76 TagAction::RescindPendFromRepository => 3,
77 TagAction::PetitionFromRepository => 4,
78 TagAction::RescindPetitionFromRepository => 5,
79 }
80 }
81}
82
83impl AddTagsRequestBuilder {
84 pub fn add_hash<S: AsRef<str>>(mut self, hash: S) -> Self {
86 self.hashes.push(hash.as_ref().into());
87
88 self
89 }
90
91 pub fn add_hashes(mut self, mut hashes: Vec<String>) -> Self {
93 self.hashes.append(&mut hashes);
94
95 self
96 }
97
98 pub fn add_tag<S: AsRef<str>>(mut self, service_key: String, tag: S) -> Self {
100 let (service, relevant_mappings) = (service_key, &mut self.service_keys_to_tags);
101 if let Some(mappings) = relevant_mappings.get_mut(&service) {
102 mappings.push(tag.as_ref().into())
103 } else {
104 relevant_mappings.insert(service, vec![tag.as_ref().into()]);
105 }
106
107 self
108 }
109
110 pub fn add_tags(mut self, service_key: String, mut tags: Vec<String>) -> Self {
112 let (service, relevant_mappings) = (service_key, &mut self.service_keys_to_tags);
113 if let Some(mappings) = relevant_mappings.get_mut(&service) {
114 mappings.append(&mut tags);
115 } else {
116 relevant_mappings.insert(service, tags);
117 }
118
119 self
120 }
121
122 pub fn add_tag_with_action<S: AsRef<str>>(
124 mut self,
125 service_key: String,
126 tag: S,
127 action: TagAction,
128 ) -> Self {
129 let (service, relevant_mappings) = (service_key, &mut self.service_keys_to_actions_to_tags);
130 let action_id = action.into_id();
131 if let Some(actions) = relevant_mappings.get_mut(&service) {
132 if let Some(tags) = actions.get_mut(&action_id.to_string()) {
133 tags.push(tag.as_ref().into());
134 } else {
135 actions.insert(action_id.to_string(), vec![tag.as_ref().into()]);
136 }
137 } else {
138 let mut actions = HashMap::new();
139 actions.insert(action_id.to_string(), vec![tag.as_ref().into()]);
140 relevant_mappings.insert(service, actions);
141 }
142 self
143 }
144
145 pub fn build(self) -> AddTagsRequest {
147 AddTagsRequest {
148 hashes: self.hashes,
149 service_keys_to_tags: self.service_keys_to_tags,
150 service_keys_to_actions_to_tags: self.service_keys_to_actions_to_tags,
151 }
152 }
153}
154
155pub struct SearchTags;
156
157impl Endpoint for SearchTags {
158 type Request = ();
159
160 type Response = SearchTagsResponse;
161
162 fn path() -> String {
163 String::from("add_tags/search_tags")
164 }
165}
166
167#[derive(Debug, Deserialize)]
168pub struct SearchTagsResponse {
169 pub tags: Vec<TagWithCount>,
170}
171
172#[derive(Debug, Deserialize)]
173pub struct TagWithCount {
174 pub value: String,
176 pub count: u64,
178}
179
180#[derive(Debug, Default)]
181pub struct TagSearchOptions {
182 pub tag_service: Option<ServiceIdentifier>,
184 pub display_type: TagDisplayType,
186}
187
188#[derive(Debug)]
189pub enum TagDisplayType {
190 Storage,
192 Display,
194}
195
196impl Default for TagDisplayType {
197 fn default() -> Self {
198 Self::Storage
199 }
200}
201
202impl TagDisplayType {
203 fn to_api_string(&self) -> &'static str {
204 match self {
205 TagDisplayType::Storage => "storage",
206 TagDisplayType::Display => "display",
207 }
208 }
209}
210
211impl TagSearchOptions {
212 pub fn display_type(mut self, display_type: TagDisplayType) -> Self {
214 self.display_type = display_type;
215 self
216 }
217
218 pub fn tag_service(mut self, tag_service: ServiceIdentifier) -> Self {
221 self.tag_service = Some(tag_service);
222 self
223 }
224
225 pub(crate) fn into_query_args(self) -> Vec<(&'static str, String)> {
226 let mut args = Vec::new();
227
228 if let Some(service) = self.tag_service {
229 match service {
230 ServiceIdentifier::Name(name) => args.push(("tag_service_name", name)),
231 ServiceIdentifier::Key(key) => args.push(("tag_service_key", key)),
232 }
233 }
234 args.push((
235 "tag_display_type",
236 self.display_type.to_api_string().to_string(),
237 ));
238
239 args
240 }
241}