Skip to main content

hydrus_api/wrapper/builders/
search_builder.rs

1use crate::api_core::endpoints::searching_and_fetching_files::{
2    FileSearchOptions, SearchQueryEntry,
3};
4use crate::error::Result;
5use crate::wrapper::hydrus_file::HydrusFile;
6use crate::wrapper::or_chain::OrChain;
7use crate::wrapper::service::ServiceName;
8use crate::wrapper::tag::Tag;
9use crate::Client;
10
11pub enum SortType {
12    FileSize,
13    Duration,
14    ImportTime,
15    FileType,
16    Random,
17    Width,
18    Height,
19    Ratio,
20    NumberOfPixels,
21    NumberOfTags,
22    NumberOfMediaViewers,
23    MediaViewTime,
24    Bitrate,
25    HasAudio,
26    ModifiedTime,
27    Framerate,
28    NumberOfFrames,
29}
30
31#[derive(Clone, Debug)]
32pub struct SearchBuilder {
33    client: Client,
34    tags: Vec<Tag>,
35    or_chains: Vec<OrChain>,
36    options: FileSearchOptions,
37}
38
39impl SearchBuilder {
40    pub(crate) fn new(client: Client) -> Self {
41        Self {
42            client,
43            tags: Vec::new(),
44            or_chains: Vec::new(),
45            options: FileSearchOptions::new(),
46        }
47    }
48
49    /// Add multiple tags to filter by
50    pub fn add_tags(mut self, mut tags: Vec<Tag>) -> Self {
51        self.tags.append(&mut tags);
52        self
53    }
54
55    /// Add a tag to filter by
56    pub fn add_tag(mut self, tag: Tag) -> Self {
57        self.tags.push(tag);
58        self
59    }
60
61    /// Adds a new or chain
62    pub fn add_or_chain(mut self, chain: OrChain) -> Self {
63        self.or_chains.push(chain);
64        self
65    }
66
67    /// Sets the sort type
68    pub fn sort_by(mut self, sort_type: SortType) -> Self {
69        self.options = self.options.sort_type(sort_type as u8);
70        self
71    }
72
73    /// Sorts descending
74    pub fn sort_descending(mut self) -> Self {
75        self.options = self.options.desc();
76        self
77    }
78
79    /// Sorts ascending
80    pub fn sort_ascending(mut self) -> Self {
81        self.options = self.options.asc();
82        self
83    }
84
85    /// Sets the file service name to search in
86    pub fn file_service_name(mut self, service: ServiceName) -> Self {
87        self.options = self.options.file_service_name(service);
88        self
89    }
90
91    /// Sets the tag service to search by
92    pub fn tag_service_name(mut self, service: ServiceName) -> Self {
93        self.options = self.options.tag_service_name(service);
94        self
95    }
96
97    /// Sets the file service key. This option is preferred over
98    /// setting it by name because it's faster
99    pub fn file_service_key<S: ToString>(mut self, key: S) -> Self {
100        self.options = self.options.file_service_key(key);
101        self
102    }
103
104    /// Sets the tag service key. This option is preferred over
105    /// setting it by name because it's faster
106    pub fn tag_service_key<S: ToString>(mut self, key: S) -> Self {
107        self.options = self.options.tag_service_key(key);
108        self
109    }
110
111    /// Runs the search
112    pub async fn run(self) -> Result<Vec<HydrusFile>> {
113        let client = self.client.clone();
114        let mut entries: Vec<SearchQueryEntry> = self
115            .tags
116            .into_iter()
117            .map(|t| SearchQueryEntry::Tag(t.to_string()))
118            .collect();
119        entries.append(
120            &mut self
121                .or_chains
122                .into_iter()
123                .map(|c| SearchQueryEntry::OrChain(c.into_string_list()))
124                .collect(),
125        );
126        let response = client.search_file_hashes(entries, self.options).await?;
127        let files = response
128            .hashes
129            .into_iter()
130            .map(|hash| HydrusFile::from_hash(client.clone(), hash))
131            .collect();
132
133        Ok(files)
134    }
135}