From ad30c14ddb5d25fb6cfd85430e47f70bd071016e Mon Sep 17 00:00:00 2001 From: trivernis Date: Sat, 14 Aug 2021 14:49:19 +0200 Subject: [PATCH] Add additional parameter to search requests With the new client api 19 there's options to sort results returned by search and filter by tag and file service. The FileSearchOptions struct allows using those extra parameters. Signed-off-by: trivernis --- src/api_core/client.rs | 18 ++-- src/api_core/mod.rs | 1 + src/api_core/searching_and_fetching_files.rs | 95 +++++++++++++++++++ src/wrapper/hydrus.rs | 3 +- .../test_searching_and_fetching_files.rs | 8 +- 5 files changed, 116 insertions(+), 9 deletions(-) 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(); }