diff --git a/src/api_core/client.rs b/src/api_core/client.rs index abe4391..f3b288f 100644 --- a/src/api_core/client.rs +++ b/src/api_core/client.rs @@ -21,7 +21,8 @@ use crate::api_core::managing_pages::{ GetPages, GetPagesResponse, }; use crate::api_core::searching_and_fetching_files::{ - FileMetadata, FileMetadataResponse, GetFile, SearchFiles, SearchFilesResponse, + FileMetadata, FileMetadataResponse, FileSearchOptions, GetFile, SearchFiles, + SearchFilesResponse, }; use crate::api_core::Endpoint; use crate::error::{Error, Result}; @@ -222,13 +223,16 @@ impl Client { } /// Searches for files in the inbox, the archive or both - pub async fn search_files(&self, tags: Vec) -> Result { + pub async fn search_files( + &self, + tags: Vec, + options: FileSearchOptions, + ) -> Result { log::trace!("Searching for files with tags {:?}", tags); - self.get_and_parse::(&[( - "tags", - string_list_to_json_array(tags), - )]) - .await + let mut args = options.into_query_args(); + args.push(("tags", string_list_to_json_array(tags))); + self.get_and_parse::(&args) + .await } /// Returns the metadata for a given list of file_ids or hashes diff --git a/src/api_core/mod.rs b/src/api_core/mod.rs index b046348..9f87869 100644 --- a/src/api_core/mod.rs +++ b/src/api_core/mod.rs @@ -10,6 +10,7 @@ pub mod common; pub mod managing_cookies_and_http_headers; pub mod managing_pages; pub mod searching_and_fetching_files; +pub use searching_and_fetching_files::file_sort_type; pub(crate) trait Endpoint { type Request: Serialize; diff --git a/src/api_core/searching_and_fetching_files.rs b/src/api_core/searching_and_fetching_files.rs index 9b47857..677858c 100644 --- a/src/api_core/searching_and_fetching_files.rs +++ b/src/api_core/searching_and_fetching_files.rs @@ -1,6 +1,101 @@ use crate::api_core::common::FileMetadataInfo; use crate::api_core::Endpoint; +pub mod file_sort_type { + pub const SORT_FILE_SIZE: u8 = 0; + pub const SORT_FILE_DURATION: u8 = 1; + pub const SORT_FILE_IMPORT_TIME: u8 = 2; + pub const SORT_FILE_TYPE: u8 = 3; + pub const SORT_FILE_RANDOM: u8 = 4; + pub const SORT_FILE_WIDTH: u8 = 5; + pub const SORT_FILE_HEIGHT: u8 = 6; + pub const SORT_FILE_RATIO: u8 = 7; + pub const SORT_FILE_PIXEL_COUNT: u8 = 8; + pub const SORT_FILE_TAG_COUNT: u8 = 9; + pub const SORT_FILE_MEDIA_VIEWS: u8 = 10; + pub const SORT_FILE_MEDIA_VIEWTIME: u8 = 11; + pub const SORT_FILE_BITRATE: u8 = 12; + pub const SORT_FILE_HAS_AUDIO: u8 = 13; + pub const SORT_FILE_MODIFIED_TIME: u8 = 14; + pub const SORT_FILE_FRAMERATE: u8 = 15; + pub const SORT_FILE_FRAME_COUNT: u8 = 16; +} + +#[derive(Clone, Debug, Default)] +pub struct FileSearchOptions { + file_service_name: Option, + file_service_key: Option, + tag_service_name: Option, + tag_service_key: Option, + file_sort_type: Option, + file_sort_asc: Option, +} + +impl FileSearchOptions { + pub fn new() -> Self { + Self::default() + } + + pub fn file_service_name(mut self, name: S) -> Self { + self.file_service_name = Some(name.to_string()); + self + } + + pub fn file_service_key(mut self, key: S) -> Self { + self.file_service_key = Some(key.to_string()); + self + } + + pub fn tag_service_name(mut self, name: S) -> Self { + self.tag_service_name = Some(name.to_string()); + self + } + + pub fn tag_service_key(mut self, key: S) -> Self { + self.tag_service_key = Some(key.to_string()); + self + } + + pub fn sort_type(mut self, sort_type: u8) -> Self { + self.file_sort_type = Some(sort_type); + self + } + + pub fn asc(mut self) -> Self { + self.file_sort_asc = Some(true); + self + } + + pub fn desc(mut self) -> Self { + self.file_sort_asc = Some(false); + self + } + + pub(crate) fn into_query_args(self) -> Vec<(&'static str, String)> { + let mut args = Vec::new(); + if let Some(sort) = self.file_sort_type { + args.push(("file_sort_type", sort.to_string())); + } + if let Some(file_service_name) = self.file_service_name { + args.push(("file_service_name", file_service_name)); + } + if let Some(file_service_key) = self.file_service_key { + args.push(("file_service_key", file_service_key)); + } + if let Some(tag_service_name) = self.tag_service_name { + args.push(("tag_service_name", tag_service_name)) + } + if let Some(tag_service_key) = self.tag_service_key { + args.push(("tag_service_key", tag_service_key)); + } + if let Some(sort_asc) = self.file_sort_asc { + args.push(("file_sort_asc", sort_asc.to_string())) + } + + args + } +} + #[derive(Debug, Clone, Deserialize)] pub struct SearchFilesResponse { pub file_ids: Vec, diff --git a/src/wrapper/hydrus.rs b/src/wrapper/hydrus.rs index 39dd6f9..390e92f 100644 --- a/src/wrapper/hydrus.rs +++ b/src/wrapper/hydrus.rs @@ -1,4 +1,5 @@ use crate::api_core::common::FileIdentifier; +use crate::api_core::searching_and_fetching_files::FileSearchOptions; use crate::error::Result; use crate::utils::tag_list_to_string_list; use crate::wrapper::address::Address; @@ -86,7 +87,7 @@ impl Hydrus { pub async fn search(&self, tags: Vec) -> Result> { let search_result = self .client - .search_files(tag_list_to_string_list(tags)) + .search_files(tag_list_to_string_list(tags), FileSearchOptions::new()) .await?; let files = search_result .file_ids diff --git a/tests/client/test_searching_and_fetching_files.rs b/tests/client/test_searching_and_fetching_files.rs index 4289443..9859b6b 100644 --- a/tests/client/test_searching_and_fetching_files.rs +++ b/tests/client/test_searching_and_fetching_files.rs @@ -1,11 +1,17 @@ use super::super::common; use hydrus_api::api_core::common::FileIdentifier; +use hydrus_api::api_core::file_sort_type::SORT_FILE_PIXEL_COUNT; +use hydrus_api::api_core::searching_and_fetching_files::FileSearchOptions; #[tokio::test] async fn is_searches_files() { let client = common::get_client(); + let options = FileSearchOptions::new() + .sort_type(SORT_FILE_PIXEL_COUNT) + .tag_service_name("public tag repository") + .file_service_name("all known files"); client - .search_files(vec!["beach".to_string()]) + .search_files(vec!["beach".to_string()], options) .await .unwrap(); }