Add url associating, retrieval etc

Signed-off-by: trivernis <trivernis@protonmail.com>
pull/2/head
trivernis 3 years ago
parent 5563d61155
commit f7c11ce905
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

@ -11,8 +11,7 @@ repository = "https://github.com/trivernis/hydrus-api-rs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
serde = "^1.0"
serde_derive = "^1.0"
serde = {version = "^1.0", features = ["derive"]}
reqwest = {version = "0.11.4", features = ["json"]}
log = "0.4.14"

@ -7,6 +7,10 @@ use crate::endpoints::adding_files::{
DeleteFilesRequest, UnarchiveFiles, UnarchiveFilesRequest, UndeleteFiles, UndeleteFilesRequest,
};
use crate::endpoints::adding_tags::{AddTags, AddTagsRequest, CleanTags, CleanTagsResponse};
use crate::endpoints::adding_urls::{
AddUrl, AddUrlRequest, AddUrlResponse, AssociateUrl, AssociateUrlRequest, GetUrlFiles,
GetUrlFilesResponse, GetUrlInfo, GetUrlInfoResponse,
};
use crate::endpoints::common::{FileIdentifier, FileRecord};
use crate::endpoints::searching_and_fetching_files::{
FileMetadata, FileMetadataResponse, FileSearchLocation, GetFile, SearchFiles,
@ -241,4 +245,49 @@ impl Client {
Ok(FileRecord { bytes, mime_type })
}
/// Returns all files associated with the given url
pub async fn get_url_files<S: AsRef<str>>(&mut self, url: S) -> Result<GetUrlFilesResponse> {
self.get_and_parse::<GetUrlFiles, [(&str, &str)]>(&[("url", url.as_ref())])
.await
}
/// Returns information about the given url
pub async fn get_url_info<S: AsRef<str>>(&mut self, url: S) -> Result<GetUrlInfoResponse> {
self.get_and_parse::<GetUrlInfo, [(&str, &str)]>(&[("url", url.as_ref())])
.await
}
/// Adds an url to hydrus, optionally with additional tags and a destination page
pub async fn add_url(&mut self, request: AddUrlRequest) -> Result<AddUrlResponse> {
self.post_and_parse::<AddUrl>(request).await
}
/// Associates urls with the given file hashes
pub async fn associate_urls(&mut self, urls: Vec<String>, hashes: Vec<String>) -> Result<()> {
self.post::<AssociateUrl>(AssociateUrlRequest {
hashes,
urls_to_add: urls,
urls_to_delete: vec![],
})
.await?;
Ok(())
}
/// Disassociates urls with the given file hashes
pub async fn disassociate_urls(
&mut self,
urls: Vec<String>,
hashes: Vec<String>,
) -> Result<()> {
self.post::<AssociateUrl>(AssociateUrlRequest {
hashes,
urls_to_add: vec![],
urls_to_delete: urls,
})
.await?;
Ok(())
}
}

@ -0,0 +1,187 @@
use crate::endpoints::Endpoint;
use serde::Serialize;
use std::collections::HashMap;
pub static URL_TYPE_POST: u8 = 0;
pub static URL_TYPE_FILE: u8 = 1;
pub static URL_TYPE_GALLERY: u8 = 2;
pub static URL_TYPE_WATCHABLE: u8 = 4;
pub static URL_TYPE_UNKNOWN: u8 = 5;
#[derive(Clone, Debug, Deserialize)]
pub struct GetUrlFilesResponse {
pub normalised_url: String,
pub url_file_statuses: Vec<UrlFileStatus>,
}
#[derive(Clone, Debug, Deserialize)]
pub struct UrlFileStatus {
pub status: u32,
pub hash: String,
pub note: String,
}
pub struct GetUrlFiles;
impl Endpoint for GetUrlFiles {
type Request = ();
type Response = GetUrlFilesResponse;
fn get_path() -> String {
String::from("add_urls/get_url_files")
}
}
#[derive(Clone, Debug, Deserialize)]
pub struct GetUrlInfoResponse {
pub normalised_url: String,
pub url_type: u8,
pub url_type_string: String,
pub match_name: String,
pub can_parse: bool,
}
pub struct GetUrlInfo;
impl Endpoint for GetUrlInfo {
type Request = ();
type Response = GetUrlInfoResponse;
fn get_path() -> String {
String::from("add_urls/get_url_info")
}
}
#[derive(Clone, Debug, Serialize)]
pub struct AddUrlRequest {
pub url: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub destination_page_key: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub destination_page_name: Option<String>,
pub show_destination_page: bool,
pub service_names_to_additional_tags: HashMap<String, Vec<String>>,
pub filterable_tags: Vec<String>,
}
/// A request builder that can be used to create a request for adding urls
/// without having to fill a huge struct manually
///
/// Example:
/// ```
/// use hydrus_api::endpoints::adding_urls::AddUrlRequestBuilder;
///
/// let request = AddUrlRequestBuilder::default()
/// .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()])
/// .show_destination_page(true)
/// .destination_page_name("Rusty Url Import")
/// .build();
/// ```
pub struct AddUrlRequestBuilder {
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 {
pub fn url<S: ToString>(mut self, url: S) -> Self {
self.inner.url = url.to_string();
self
}
pub fn destination_page_key<S: ToString>(mut self, page_key: S) -> Self {
self.inner.destination_page_key = Some(page_key.to_string());
self
}
pub fn destination_page_name<S: ToString>(mut self, page_name: S) -> Self {
self.inner.destination_page_name = Some(page_name.to_string());
self
}
pub fn show_destination_page(mut self, show: bool) -> Self {
self.inner.show_destination_page = show;
self
}
pub fn add_tags<S: AsRef<str>>(mut self, service: S, mut tags: Vec<String>) -> Self {
if let Some(entry) = self
.inner
.service_names_to_additional_tags
.get_mut(service.as_ref())
{
entry.append(&mut tags);
} else {
self.inner
.service_names_to_additional_tags
.insert(service.as_ref().to_string(), tags);
}
self
}
pub fn add_filter_tags(mut self, mut filter_tags: Vec<String>) -> Self {
self.inner.filterable_tags.append(&mut filter_tags);
self
}
pub fn build(self) -> AddUrlRequest {
self.inner
}
}
#[derive(Clone, Debug, Deserialize)]
pub struct AddUrlResponse {
pub human_result_text: String,
pub normalised_url: String,
}
pub struct AddUrl;
impl Endpoint for AddUrl {
type Request = AddUrlRequest;
type Response = AddUrlResponse;
fn get_path() -> String {
String::from("add_urls/add_url")
}
}
#[derive(Clone, Debug, Serialize)]
pub struct AssociateUrlRequest {
pub urls_to_add: Vec<String>,
pub urls_to_delete: Vec<String>,
pub hashes: Vec<String>,
}
pub struct AssociateUrl;
impl Endpoint for AssociateUrl {
type Request = AssociateUrlRequest;
type Response = ();
fn get_path() -> String {
String::from("add_urls/associate_url")
}
}

@ -4,6 +4,7 @@ use serde::Serialize;
pub mod access_management;
pub mod adding_files;
pub mod adding_tags;
pub mod adding_urls;
pub mod common;
pub mod searching_and_fetching_files;

@ -32,7 +32,7 @@
//! ```
#[macro_use]
extern crate serde_derive;
extern crate serde;
pub mod client;
pub mod endpoints;

@ -0,0 +1,71 @@
use hydrus_api::endpoints::adding_urls::{AddUrlRequestBuilder, URL_TYPE_POST};
mod common;
#[tokio::test]
async fn it_returns_files_for_an_url() {
let mut client = common::get_client();
let response = client
.get_url_files("https://www.pixiv.net/member_illust.php?illust_id=83406361&mode=medium")
.await
.unwrap();
assert!(response.normalised_url.len() > 0);
}
#[tokio::test]
async fn it_returns_url_information() {
let mut client = common::get_client();
let info = client
.get_url_info("https://www.pixiv.net/member_illust.php?illust_id=83406361&mode=medium")
.await
.unwrap();
assert!(info.normalised_url.len() > 0);
assert_eq!(info.url_type, URL_TYPE_POST);
}
#[tokio::test]
async fn it_adds_urls() {
let mut client = common::get_client();
let request = AddUrlRequestBuilder::default()
.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()],
)
.show_destination_page(true)
.destination_page_name("Rusty Url Import")
.build();
let response = client.add_url(request).await.unwrap();
assert!(response.normalised_url.len() > 0);
}
#[tokio::test]
async fn it_associates_urls() {
let mut client = common::get_client();
client
.associate_urls(
vec![
"https://www.pixiv.net/member_illust.php?illust_id=83406361&mode=medium"
.to_string(),
],
vec!["0000000000000000000000000000000000000000000000000000000000000000".to_string()],
)
.await
.unwrap();
}
#[tokio::test]
async fn it_disassociates_urls() {
let mut client = common::get_client();
client
.disassociate_urls(
vec![
"https://www.pixiv.net/member_illust.php?illust_id=83406361&mode=medium"
.to_string(),
],
vec!["0000000000000000000000000000000000000000000000000000000000000000".to_string()],
)
.await
.unwrap();
}
Loading…
Cancel
Save