You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
hydrus-api-rs/src/wrapper/builders/import_builder.rs

168 lines
4.8 KiB
Rust

use crate::api_core::adding_files::{STATUS_IMPORT_FAILED, STATUS_IMPORT_VETOED};
use crate::api_core::adding_urls::AddUrlRequestBuilder;
use crate::api_core::common::ServiceIdentifier;
use crate::error::{Error, Result};
use crate::utils::tag_list_to_string_list;
use crate::wrapper::hydrus_file::HydrusFile;
use crate::wrapper::page::PageIdentifier;
use crate::wrapper::tag::Tag;
use crate::wrapper::url::Url;
use crate::Client;
use std::collections::HashMap;
use std::io::Read;
pub struct ImportBuilder {
pub(crate) client: Client,
}
impl ImportBuilder {
pub fn file(self, file: FileImport) -> FileImportBuilder {
FileImportBuilder {
client: self.client,
file,
}
}
pub fn url<S: ToString>(self, url: S) -> UrlImportBuilder {
UrlImportBuilder::new(self.client.clone(), url)
}
}
pub enum FileImport {
Path(String),
Binary(Vec<u8>),
}
impl FileImport {
pub fn path<S: ToString>(path: S) -> Self {
Self::Path(path.to_string())
}
pub fn binary<R: Read>(reader: &mut R) -> Self {
let mut bytes = Vec::new();
let _ = reader.read_to_end(&mut bytes);
Self::Binary(bytes)
}
}
pub struct FileImportBuilder {
client: Client,
file: FileImport,
}
impl FileImportBuilder {
pub async fn run(self) -> Result<HydrusFile> {
let response = match self.file {
FileImport::Path(path) => self.client.add_file(path).await?,
FileImport::Binary(b) => self.client.add_binary_file(b).await?,
};
if response.status == STATUS_IMPORT_FAILED {
Err(Error::ImportFailed(response.note))
} else if response.status == STATUS_IMPORT_VETOED {
Err(Error::ImportVetoed(response.note))
} else {
Ok(HydrusFile::from_raw_status_and_hash(
self.client,
response.status,
response.hash,
))
}
}
}
pub struct UrlImportBuilder {
client: Client,
url: String,
page: Option<PageIdentifier>,
show_page: bool,
filter_tags: Vec<Tag>,
service_tag_mappings: HashMap<ServiceIdentifier, Vec<Tag>>,
}
impl UrlImportBuilder {
pub fn new<S: ToString>(client: Client, url: S) -> Self {
Self {
client,
url: url.to_string(),
page: None,
show_page: false,
filter_tags: vec![],
service_tag_mappings: Default::default(),
}
}
/// Sets the destination page of the import
pub fn page(mut self, page: PageIdentifier) -> Self {
self.page = Some(page);
self
}
/// If the destination page of the import should be focussed
pub fn show_page(mut self, show: bool) -> Self {
self.show_page = show;
self
}
/// Adds a tag that should be filtered
pub fn add_filter_tag(mut self, tag: Tag) -> Self {
self.filter_tags.push(tag);
self
}
/// Adds multiple tags that should be filtered
pub fn add_filter_tags(mut self, mut tags: Vec<Tag>) -> Self {
self.filter_tags.append(&mut tags);
self
}
/// Adds an additional tag for the imported file
pub fn add_additional_tag(self, service: ServiceIdentifier, tag: Tag) -> Self {
self.add_additional_tags(service, vec![tag])
}
/// Adds multiple additional tags for the import
pub fn add_additional_tags(mut self, service: ServiceIdentifier, mut tags: Vec<Tag>) -> Self {
if let Some(service_tags) = self.service_tag_mappings.get_mut(&service) {
service_tags.append(&mut tags);
} else {
self.service_tag_mappings.insert(service, tags);
}
self
}
/// Imports the URL
pub async fn run(self) -> Result<Url> {
let mut request = AddUrlRequestBuilder::default().url(&self.url);
for (service, tags) in self.service_tag_mappings {
request = request.add_tags(service, tag_list_to_string_list(tags));
}
request = request.add_filter_tags(tag_list_to_string_list(self.filter_tags));
if let Some(page) = self.page {
request = match page {
PageIdentifier::Name(n) => request.destination_page_name(n),
PageIdentifier::Key(k) => request.destination_page_key(k),
};
}
request = request.show_destination_page(self.show_page);
let response = self.client.add_url(request.build()).await?;
let url_info = self.client.get_url_info(&self.url).await?;
Ok(Url {
url: self.url,
client: self.client,
normalised_url: response.normalised_url,
url_type: url_info.url_type.into(),
match_name: url_info.match_name,
can_parse: url_info.can_parse,
})
}
}