Improve tests and wrapper functions

Signed-off-by: trivernis <trivernis@protonmail.com>
pull/9/head
trivernis 3 years ago
parent 7260eb825a
commit b52c28e31e
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 serde::Serialize; use serde::Serialize;
use std::collections::HashMap; use std::collections::HashMap;
@ -52,7 +53,7 @@ impl Endpoint for GetUrlInfo {
} }
} }
#[derive(Clone, Debug, Serialize)] #[derive(Clone, Default, Debug, Serialize)]
pub struct AddUrlRequest { pub struct AddUrlRequest {
pub url: String, pub url: String,
@ -64,6 +65,7 @@ pub struct AddUrlRequest {
pub show_destination_page: bool, pub show_destination_page: bool,
pub service_names_to_additional_tags: HashMap<String, Vec<String>>, pub service_names_to_additional_tags: HashMap<String, Vec<String>>,
pub service_keys_to_additional_tags: HashMap<String, Vec<String>>,
pub filterable_tags: Vec<String>, pub filterable_tags: Vec<String>,
} }
@ -73,33 +75,20 @@ pub struct AddUrlRequest {
/// Example: /// Example:
/// ``` /// ```
/// use hydrus_api::api_core::adding_urls::AddUrlRequestBuilder; /// use hydrus_api::api_core::adding_urls::AddUrlRequestBuilder;
/// use hydrus_api::api_core::common::ServiceIdentifier;
/// ///
/// let request = AddUrlRequestBuilder::default() /// let request = AddUrlRequestBuilder::default()
/// .url("https://www.pixiv.net/member_illust.php?illust_id=83406361&mode=medium") /// .url("https://www.pixiv.net/member_illust.php?illust_id=83406361&mode=medium")
/// .add_tags("my tags", vec!["ark mage".to_string(), "grinning".to_string()]) /// .add_tags(ServiceIdentifier::name("my tags"), vec!["ark mage".to_string(), "grinning".to_string()])
/// .show_destination_page(true) /// .show_destination_page(true)
/// .destination_page_name("Rusty Url Import") /// .destination_page_name("Rusty Url Import")
/// .build(); /// .build();
/// ``` /// ```
#[derive(Default)]
pub struct AddUrlRequestBuilder { pub struct AddUrlRequestBuilder {
inner: AddUrlRequest, inner: AddUrlRequest,
} }
impl Default for AddUrlRequestBuilder {
fn default() -> Self {
Self {
inner: AddUrlRequest {
url: String::new(),
destination_page_key: None,
destination_page_name: None,
show_destination_page: false,
service_names_to_additional_tags: Default::default(),
filterable_tags: vec![],
},
}
}
}
impl AddUrlRequestBuilder { impl AddUrlRequestBuilder {
pub fn url<S: ToString>(mut self, url: S) -> Self { pub fn url<S: ToString>(mut self, url: S) -> Self {
self.inner.url = url.to_string(); self.inner.url = url.to_string();
@ -125,17 +114,17 @@ impl AddUrlRequestBuilder {
self self
} }
pub fn add_tags<S: AsRef<str>>(mut self, service: S, mut tags: Vec<String>) -> Self { pub fn add_tags(mut self, service_id: ServiceIdentifier, mut tags: Vec<String>) -> Self {
if let Some(entry) = self let (service, mappings) = match service_id {
.inner ServiceIdentifier::Name(name) => {
.service_names_to_additional_tags (name, &mut self.inner.service_names_to_additional_tags)
.get_mut(service.as_ref()) }
{ ServiceIdentifier::Key(key) => (key, &mut self.inner.service_keys_to_additional_tags),
};
if let Some(entry) = mappings.get_mut(&service) {
entry.append(&mut tags); entry.append(&mut tags);
} else { } else {
self.inner mappings.insert(service, tags);
.service_names_to_additional_tags
.insert(service.as_ref().to_string(), tags);
} }
self self

@ -11,6 +11,7 @@ use crate::api_core::adding_urls::{
AddUrl, AddUrlRequest, AddUrlResponse, AssociateUrl, AssociateUrlRequest, GetUrlFiles, AddUrl, AddUrlRequest, AddUrlResponse, AssociateUrl, AssociateUrlRequest, GetUrlFiles,
GetUrlFilesResponse, GetUrlInfo, GetUrlInfoResponse, GetUrlFilesResponse, GetUrlInfo, GetUrlInfoResponse,
}; };
use crate::api_core::client_builder::ClientBuilder;
use crate::api_core::common::{FileIdentifier, FileMetadataInfo, FileRecord, OptionalStringNumber}; use crate::api_core::common::{FileIdentifier, FileMetadataInfo, FileRecord, OptionalStringNumber};
use crate::api_core::managing_cookies_and_http_headers::{ use crate::api_core::managing_cookies_and_http_headers::{
GetCookies, GetCookiesResponse, SetCookies, SetCookiesRequest, SetUserAgent, GetCookies, GetCookiesResponse, SetCookies, SetCookiesRequest, SetUserAgent,
@ -41,12 +42,17 @@ static ACCESS_KEY_HEADER: &str = "Hydrus-Client-API-Access-Key";
/// over the REST api. /// over the REST api.
#[derive(Debug)] #[derive(Debug)]
pub struct Client { pub struct Client {
inner: reqwest::Client, pub(crate) inner: reqwest::Client,
base_url: String, pub(crate) base_url: String,
access_key: String, pub(crate) access_key: String,
} }
impl Client { impl Client {
/// Returns a builder for the client
pub fn builder() -> ClientBuilder {
ClientBuilder::default()
}
/// Creates a new client to start requests against the hydrus api. /// Creates a new client to start requests against the hydrus api.
pub fn new<S: AsRef<str>>(url: S, access_key: S) -> Self { pub fn new<S: AsRef<str>>(url: S, access_key: S) -> Self {
Self { Self {

@ -0,0 +1,56 @@
use crate::error::{Error, Result};
use crate::Client;
use std::time::Duration;
pub struct ClientBuilder {
reqwest_builder: reqwest::ClientBuilder,
base_url: String,
access_key: Option<String>,
}
impl Default for ClientBuilder {
fn default() -> Self {
Self {
reqwest_builder: Default::default(),
base_url: "127.0.0.1:45869".to_string(),
access_key: None,
}
}
}
impl ClientBuilder {
/// Set the base url with port for the client api
/// The default value is `127.0.0.1:45869`
pub fn url<S: ToString>(mut self, url: S) -> Self {
self.base_url = url.to_string();
self
}
/// Sets the access key for the client.
/// The key is required
pub fn access_key<S: ToString>(mut self, key: S) -> Self {
self.access_key = Some(key.to_string());
self
}
/// Sets the default timeout for requests to the API
pub fn timeout(mut self, timeout: Duration) -> Self {
self.reqwest_builder = self.reqwest_builder.timeout(timeout);
self
}
/// Builds the client
pub fn build(self) -> Result<Client> {
let access_key = self
.access_key
.ok_or_else(|| Error::BuildError(String::from("missing access key")))?;
Ok(Client {
inner: self.reqwest_builder.build()?,
base_url: self.base_url,
access_key,
})
}
}

@ -6,6 +6,14 @@ pub struct BasicServiceInfo {
pub service_key: String, pub service_key: String,
} }
impl BasicServiceInfo {
/// Converts the Service into into an identifier
/// that can be used for requests consuming service references
pub fn into_id(self) -> ServiceIdentifier {
ServiceIdentifier::Key(self.service_key)
}
}
#[derive(Clone, Debug, Serialize, Deserialize, Hash, PartialOrd, PartialEq, Ord, Eq)] #[derive(Clone, Debug, Serialize, Deserialize, Hash, PartialOrd, PartialEq, Ord, Eq)]
pub enum ServiceIdentifier { pub enum ServiceIdentifier {
Name(String), Name(String),

@ -7,10 +7,12 @@ pub mod adding_files;
pub mod adding_tags; pub mod adding_tags;
pub mod adding_urls; pub mod adding_urls;
pub mod client; pub mod client;
pub mod client_builder;
pub mod common; pub mod common;
pub mod managing_cookies_and_http_headers; pub mod managing_cookies_and_http_headers;
pub mod managing_pages; pub mod managing_pages;
pub mod searching_and_fetching_files; pub mod searching_and_fetching_files;
pub use searching_and_fetching_files::file_sort_type; pub use searching_and_fetching_files::file_sort_type;
pub(crate) trait Endpoint { pub(crate) trait Endpoint {

@ -13,6 +13,7 @@ pub enum Error {
ImportFailed(String), ImportFailed(String),
FileNotFound(FileIdentifier), FileNotFound(FileIdentifier),
InvalidMime(String), InvalidMime(String),
BuildError(String),
} }
impl fmt::Display for Error { impl fmt::Display for Error {
@ -27,6 +28,7 @@ impl fmt::Display for Error {
Self::ImportVetoed(msg) => write!(f, "File import vetoed: {}", msg), Self::ImportVetoed(msg) => write!(f, "File import vetoed: {}", msg),
Self::FileNotFound(id) => write!(f, "File {:?} not found", id), Self::FileNotFound(id) => write!(f, "File {:?} not found", id),
Self::InvalidMime(mime) => write!(f, "Failed to parse invalid mime {}", mime), Self::InvalidMime(mime) => write!(f, "Failed to parse invalid mime {}", mime),
Self::BuildError(error) => write!(f, "Build error {}", error),
} }
} }
} }

@ -1,5 +1,6 @@
use crate::api_core::adding_files::{STATUS_IMPORT_FAILED, STATUS_IMPORT_VETOED}; use crate::api_core::adding_files::{STATUS_IMPORT_FAILED, STATUS_IMPORT_VETOED};
use crate::api_core::adding_urls::AddUrlRequestBuilder; use crate::api_core::adding_urls::AddUrlRequestBuilder;
use crate::api_core::common::ServiceIdentifier;
use crate::error::{Error, Result}; use crate::error::{Error, Result};
use crate::utils::tag_list_to_string_list; use crate::utils::tag_list_to_string_list;
use crate::wrapper::hydrus_file::HydrusFile; use crate::wrapper::hydrus_file::HydrusFile;
@ -141,7 +142,10 @@ impl UrlImportBuilder {
let mut request = AddUrlRequestBuilder::default().url(&self.url); let mut request = AddUrlRequestBuilder::default().url(&self.url);
for (service, tags) in self.service_tag_mappings { for (service, tags) in self.service_tag_mappings {
request = request.add_tags(service, tag_list_to_string_list(tags)); request = request.add_tags(
ServiceIdentifier::name(service),
tag_list_to_string_list(tags),
);
} }
request = request.add_filter_tags(tag_list_to_string_list(self.filter_tags)); request = request.add_filter_tags(tag_list_to_string_list(self.filter_tags));
if let Some(page) = self.page { if let Some(page) = self.page {

@ -1,5 +1,5 @@
use crate::api_core::adding_tags::{AddTagsRequestBuilder, TagAction}; use crate::api_core::adding_tags::{AddTagsRequestBuilder, TagAction};
use crate::api_core::common::{FileIdentifier, FileMetadataInfo, FileRecord}; use crate::api_core::common::{FileIdentifier, FileMetadataInfo, FileRecord, ServiceIdentifier};
use crate::error::{Error, Result}; use crate::error::{Error, Result};
use crate::utils::tag_list_to_string_list; use crate::utils::tag_list_to_string_list;
use crate::wrapper::service::ServiceName; use crate::wrapper::service::ServiceName;
@ -213,11 +213,11 @@ impl HydrusFile {
} }
/// Adds tags for a specific service to the file /// Adds tags for a specific service to the file
pub async fn add_tags(&mut self, service: ServiceName, tags: Vec<Tag>) -> Result<()> { pub async fn add_tags(&mut self, service: ServiceIdentifier, tags: Vec<Tag>) -> Result<()> {
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.into(), tag_list_to_string_list(tags)) .add_tags(service, tag_list_to_string_list(tags))
.build(); .build();
self.client.add_tags(request).await self.client.add_tags(request).await
@ -226,7 +226,7 @@ impl HydrusFile {
/// Allows modification of tags by using the defined tag actions /// Allows modification of tags by using the defined tag actions
pub async fn modify_tags( pub async fn modify_tags(
&mut self, &mut self,
service: ServiceName, service: ServiceIdentifier,
action: TagAction, action: TagAction,
tags: Vec<Tag>, tags: Vec<Tag>,
) -> Result<()> { ) -> Result<()> {
@ -234,11 +234,7 @@ 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.add_tag_with_action( reqwest = reqwest.add_tag_with_action(service.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

@ -1,5 +1,6 @@
use super::super::common; use super::super::common;
use hydrus_api::api_core::adding_urls::{AddUrlRequestBuilder, URL_TYPE_POST}; use hydrus_api::api_core::adding_urls::{AddUrlRequestBuilder, URL_TYPE_POST};
use hydrus_api::api_core::common::ServiceIdentifier;
#[tokio::test] #[tokio::test]
async fn it_returns_files_for_an_url() { async fn it_returns_files_for_an_url() {
@ -29,7 +30,7 @@ async fn it_adds_urls() {
let request = AddUrlRequestBuilder::default() let request = AddUrlRequestBuilder::default()
.url("https://www.pixiv.net/member_illust.php?illust_id=83406361&mode=medium") .url("https://www.pixiv.net/member_illust.php?illust_id=83406361&mode=medium")
.add_tags( .add_tags(
"my tags", ServiceIdentifier::name("my tags"),
vec!["ark mage".to_string(), "grinning".to_string()], vec!["ark mage".to_string(), "grinning".to_string()],
) )
.show_destination_page(true) .show_destination_page(true)

@ -2,6 +2,7 @@ use hydrus_api::api_core::client::Client;
use hydrus_api::Hydrus; use hydrus_api::Hydrus;
use std::env; use std::env;
use std::sync::{Arc, Mutex, MutexGuard}; use std::sync::{Arc, Mutex, MutexGuard};
use std::time::Duration;
pub fn setup() { pub fn setup() {
lazy_static::lazy_static! { static ref SETUP_DONE: Arc<Mutex<bool>> = Arc::new(Mutex::new(false)); } lazy_static::lazy_static! { static ref SETUP_DONE: Arc<Mutex<bool>> = Arc::new(Mutex::new(false)); }
@ -16,11 +17,12 @@ pub fn setup() {
pub fn get_client() -> Client { pub fn get_client() -> Client {
setup(); setup();
Client::builder()
Client::new( .url(env::var("HYDRUS_URL").unwrap())
env::var("HYDRUS_URL").unwrap(), .access_key(env::var("HYDRUS_ACCESS_KEY").unwrap())
env::var("HYDRUS_ACCESS_KEY").unwrap(), .timeout(Duration::from_secs(5))
) .build()
.unwrap()
} }
pub fn get_hydrus() -> Hydrus { pub fn get_hydrus() -> Hydrus {

@ -54,7 +54,7 @@ async fn it_has_tags() {
async fn it_adds_tags() { async fn it_adds_tags() {
let mut file = get_file().await; let mut file = get_file().await;
file.add_tags( file.add_tags(
ServiceName::my_tags(), ServiceName::my_tags().into(),
vec!["character:megumin".into(), "ark mage".into()], vec!["character:megumin".into(), "ark mage".into()],
) )
.await .await
@ -65,7 +65,7 @@ async fn it_adds_tags() {
async fn it_modifies_tags() { async fn it_modifies_tags() {
let mut file = get_file().await; let mut file = get_file().await;
file.modify_tags( file.modify_tags(
ServiceName::my_tags(), ServiceName::my_tags().into(),
TagAction::RescindPendFromRepository, TagAction::RescindPendFromRepository,
vec!["ark mage".into()], vec!["ark mage".into()],
) )

@ -7,8 +7,12 @@ use hydrus_api::wrapper::builders::tag_builder::{
}; };
use hydrus_api::wrapper::service::ServiceName; use hydrus_api::wrapper::service::ServiceName;
use hydrus_api::wrapper::tag::Tag; use hydrus_api::wrapper::tag::Tag;
use std::sync::Arc;
use tokio::sync::Mutex;
async fn retrieve_single_tag(tag: Tag) -> Result<()> { async fn retrieve_single_tag(tag: Tag) -> Result<()> {
lazy_static::lazy_static! { static ref SEM: Arc<Mutex<()>> = Arc::new(Mutex::new(())); }
SEM.lock().await;
let hydrus = common::get_hydrus(); let hydrus = common::get_hydrus();
hydrus.search().add_tag(tag).run().await?; hydrus.search().add_tag(tag).run().await?;

Loading…
Cancel
Save