diff --git a/Cargo.toml b/Cargo.toml index 6e5d4de..4d0d679 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hydrus-api" -version = "0.2.0" +version = "0.3.0" authors = ["trivernis "] edition = "2018" license = "Apache-2.0" diff --git a/README.md b/README.md index 1f72a5b..3a88b9d 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,51 @@ -# Hydrus Rust API +

+Hydrus Rust API +

+

+ + + + + + +

+ This is a WIP Rust Wrapper for the Hydrus Client API. The official API documentation can be found [here](https://hydrusnetwork.github.io/hydrus/help/client_api.html). -## Example +## Example with Wrapper + +```rust +use std::env; +use hydrus_api::api_core::searching_and_fetching_files::FileSearchLocation; +use hydrus_api::wrapper::tag::Tag; +use hydrus_api::wrapper::service::ServiceName; +use hydrus_api::wrapper::hydrus_file::FileStatus; +use hydrus_api::wrapper::page::PageIdentifier; + +#[tokio::main] +async fn main() { + let hydrus_url = env::var("HYDRUS_URL").unwrap(); + let access_key = env::var("HYDRUS_ACCESS_KEY").unwrap(); + + let hydrus = Hydrus::new(Client::new(hydrus_url, access_key)); + let files = hydrus.search(FileSearchLocation::Archive,vec![Tag::from("character:megumin")]).await.unwrap(); + + for mut file in files { + file.add_tags(ServiceName::my_tags(), vec![Tag::from("ark mage")]).await.unwrap(); + } + + let url = hydrus.import() + .url("https://www.pixiv.net/member_illust.php?illust_id=83406361&mode=medium") + .page(PageIdentifier::name("My Import Page")) + .add_additional_tag(ServiceName::my_tags(), Tag::from("character:megumin")) + .show_page(true) + .run().await.unwrap(); +} +``` + +## Example with Client ```rust use hydrus_api::Client; @@ -15,7 +57,7 @@ async fn main() { Client::new( env::var("HYDRUS_URL").unwrap(), env::var("HYDRUS_ACCESS_KEY").unwrap(), - ).unwrap(); + ); // let's first import a file let hash = client.add_file("/path/to/my/file").await.unwrap().hash; diff --git a/src/endpoints/access_management.rs b/src/api_core/access_management.rs similarity index 95% rename from src/endpoints/access_management.rs rename to src/api_core/access_management.rs index d7c55ad..8c5ff11 100644 --- a/src/endpoints/access_management.rs +++ b/src/api_core/access_management.rs @@ -1,5 +1,5 @@ -use crate::endpoints::common::BasicServiceInfo; -use crate::endpoints::Endpoint; +use crate::api_core::common::BasicServiceInfo; +use crate::api_core::Endpoint; use std::collections::HashMap; pub static SERVICE_TYPE_LOCAL_TAGS: &str = "local_tags"; diff --git a/src/endpoints/adding_files.rs b/src/api_core/adding_files.rs similarity index 95% rename from src/endpoints/adding_files.rs rename to src/api_core/adding_files.rs index 412cf09..fce22b4 100644 --- a/src/endpoints/adding_files.rs +++ b/src/api_core/adding_files.rs @@ -1,5 +1,5 @@ -use crate::endpoints::common::BasicHashList; -use crate::endpoints::Endpoint; +use crate::api_core::common::BasicHashList; +use crate::api_core::Endpoint; pub static STATUS_IMPORT_SUCCESS: u8 = 1; pub static STATUS_IMPORT_ALREADY_EXISTS: u8 = 2; diff --git a/src/endpoints/adding_tags.rs b/src/api_core/adding_tags.rs similarity index 99% rename from src/endpoints/adding_tags.rs rename to src/api_core/adding_tags.rs index 0a4c338..91c883f 100644 --- a/src/endpoints/adding_tags.rs +++ b/src/api_core/adding_tags.rs @@ -1,4 +1,4 @@ -use crate::endpoints::Endpoint; +use crate::api_core::Endpoint; use std::collections::HashMap; #[derive(Debug, Clone, Deserialize)] diff --git a/src/endpoints/adding_urls.rs b/src/api_core/adding_urls.rs similarity index 97% rename from src/endpoints/adding_urls.rs rename to src/api_core/adding_urls.rs index 094262b..a92aabc 100644 --- a/src/endpoints/adding_urls.rs +++ b/src/api_core/adding_urls.rs @@ -1,4 +1,4 @@ -use crate::endpoints::Endpoint; +use crate::api_core::Endpoint; use serde::Serialize; use std::collections::HashMap; @@ -72,7 +72,7 @@ pub struct AddUrlRequest { /// /// Example: /// ``` -/// use hydrus_api::endpoints::adding_urls::AddUrlRequestBuilder; +/// use hydrus_api::api_core::adding_urls::AddUrlRequestBuilder; /// /// let request = AddUrlRequestBuilder::default() /// .url("https://www.pixiv.net/member_illust.php?illust_id=83406361&mode=medium") diff --git a/src/client.rs b/src/api_core/client.rs similarity index 94% rename from src/client.rs rename to src/api_core/client.rs index 1e9f2c2..b714320 100644 --- a/src/client.rs +++ b/src/api_core/client.rs @@ -1,22 +1,22 @@ -use crate::endpoints::access_management::{ +use crate::api_core::access_management::{ ApiVersion, ApiVersionResponse, GetServices, GetServicesResponse, SessionKey, SessionKeyResponse, VerifyAccessKey, VerifyAccessKeyResponse, }; -use crate::endpoints::adding_files::{ +use crate::api_core::adding_files::{ AddFile, AddFileRequest, AddFileResponse, ArchiveFiles, ArchiveFilesRequest, DeleteFiles, DeleteFilesRequest, UnarchiveFiles, UnarchiveFilesRequest, UndeleteFiles, UndeleteFilesRequest, }; -use crate::endpoints::adding_tags::{AddTags, AddTagsRequest, CleanTags, CleanTagsResponse}; -use crate::endpoints::adding_urls::{ +use crate::api_core::adding_tags::{AddTags, AddTagsRequest, CleanTags, CleanTagsResponse}; +use crate::api_core::adding_urls::{ AddUrl, AddUrlRequest, AddUrlResponse, AssociateUrl, AssociateUrlRequest, GetUrlFiles, GetUrlFilesResponse, GetUrlInfo, GetUrlInfoResponse, }; -use crate::endpoints::common::{FileIdentifier, FileMetadataInfo, FileRecord}; -use crate::endpoints::searching_and_fetching_files::{ +use crate::api_core::common::{FileIdentifier, FileMetadataInfo, FileRecord}; +use crate::api_core::searching_and_fetching_files::{ FileMetadata, FileMetadataResponse, FileSearchLocation, GetFile, SearchFiles, SearchFilesResponse, }; -use crate::endpoints::Endpoint; +use crate::api_core::Endpoint; use crate::error::{Error, Result}; use crate::utils::{number_list_to_json_array, string_list_to_json_array}; use reqwest::Response; @@ -26,6 +26,8 @@ use serde::Serialize; static ACCESS_KEY_HEADER: &str = "Hydrus-Client-API-Access-Key"; #[derive(Clone)] +/// A low level Client for the hydrus API. It provides basic abstraction +/// over the REST api. pub struct Client { inner: reqwest::Client, base_url: String, @@ -34,12 +36,12 @@ pub struct Client { impl Client { /// Creates a new client to start requests against the hydrus api. - pub fn new>(url: S, access_key: S) -> Result { - Ok(Self { + pub fn new>(url: S, access_key: S) -> Self { + Self { inner: reqwest::Client::new(), access_key: access_key.as_ref().to_string(), base_url: url.as_ref().to_string(), - }) + } } /// Starts a get request to the path diff --git a/src/endpoints/common.rs b/src/api_core/common.rs similarity index 100% rename from src/endpoints/common.rs rename to src/api_core/common.rs diff --git a/src/endpoints/mod.rs b/src/api_core/mod.rs similarity index 95% rename from src/endpoints/mod.rs rename to src/api_core/mod.rs index 468521c..222f522 100644 --- a/src/endpoints/mod.rs +++ b/src/api_core/mod.rs @@ -5,6 +5,7 @@ pub mod access_management; pub mod adding_files; pub mod adding_tags; pub mod adding_urls; +pub mod client; pub mod common; pub mod searching_and_fetching_files; diff --git a/src/endpoints/searching_and_fetching_files.rs b/src/api_core/searching_and_fetching_files.rs similarity index 93% rename from src/endpoints/searching_and_fetching_files.rs rename to src/api_core/searching_and_fetching_files.rs index 3a46d66..b3e20ef 100644 --- a/src/endpoints/searching_and_fetching_files.rs +++ b/src/api_core/searching_and_fetching_files.rs @@ -1,5 +1,5 @@ -use crate::endpoints::common::FileMetadataInfo; -use crate::endpoints::Endpoint; +use crate::api_core::common::FileMetadataInfo; +use crate::api_core::Endpoint; #[derive(Debug, Clone, Deserialize)] pub struct SearchFilesResponse { diff --git a/src/error.rs b/src/error.rs index 4bc8549..60f3ad6 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,4 +1,4 @@ -use crate::endpoints::common::FileIdentifier; +use crate::api_core::common::FileIdentifier; use std::error::Error as StdError; use std::fmt; diff --git a/src/lib.rs b/src/lib.rs index 956c588..05af9c0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,10 +3,41 @@ //! token that can be retrieved in the hydrus client from the *review services* dialog. //! Different actions require different permissions, you can read about it in the [official docs](https://hydrusnetwork.github.io/hydrus/help/client_api.html). //! -//! ## Usage Example +//! ## Hydrus Usage Example +//! +//! ``` +//! # use hydrus_api::{Hydrus, Client}; +//! use std::env; +//! use hydrus_api::api_core::searching_and_fetching_files::FileSearchLocation; +//! use hydrus_api::wrapper::tag::Tag; +//! use hydrus_api::wrapper::service::ServiceName; +//! use hydrus_api::wrapper::hydrus_file::FileStatus; +//! use hydrus_api::wrapper::page::PageIdentifier; +//! +//! # #[tokio::test] +//! # async fn doctest() { +//! let hydrus_url = env::var("HYDRUS_URL").unwrap(); +//! let access_key = env::var("HYDRUS_ACCESS_KEY").unwrap(); +//! let hydrus = Hydrus::new(Client::new(hydrus_url, access_key)); +//! let files = hydrus.search(FileSearchLocation::Archive,vec![Tag::from("character:megumin")]).await.unwrap(); +//! +//! for mut file in files { +//! file.add_tags(ServiceName::my_tags(), vec![Tag::from("ark mage")]).await.unwrap(); +//! } +//! +//! let url = hydrus.import() +//! .url("https://www.pixiv.net/member_illust.php?illust_id=83406361&mode=medium") +//! .page(PageIdentifier::name("My Import Page")) +//! .add_additional_tag(ServiceName::my_tags(), Tag::from("character:megumin")) +//! .show_page(true) +//! .run().await.unwrap(); +//! # } +//! ``` +//! +//! ## Client Usage Example //! ``` //! use hydrus_api::Client; -//! use hydrus_api::endpoints::adding_tags::{AddTagsRequestBuilder, TagAction}; +//! use hydrus_api::api_core::adding_tags::{AddTagsRequestBuilder, TagAction}; //! use std::env; //! # #[tokio::test] //! # async fn doctest() { @@ -14,7 +45,7 @@ //! Client::new( //! env::var("HYDRUS_URL").unwrap(), //! env::var("HYDRUS_ACCESS_KEY").unwrap(), -//! ).unwrap(); +//! ); //! // let's first import a file //! let hash = client.add_file("/path/to/my/file").await.unwrap().hash; //! @@ -34,12 +65,10 @@ #[macro_use] extern crate serde; -pub mod client; -pub mod endpoints; +pub use api_core::client::Client; +pub use wrapper::hydrus::Hydrus; + +pub mod api_core; pub mod error; -mod models; pub(crate) mod utils; - -pub use client::Client; -pub use models::hydrus::Hydrus; -pub use models::*; +pub mod wrapper; diff --git a/src/utils.rs b/src/utils.rs index b06ba26..95f308a 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,4 +1,4 @@ -use crate::models::tag::Tag; +use crate::wrapper::tag::Tag; pub fn string_list_to_json_array(l: Vec) -> String { format!("[\"{}\"]", l.join("\",\"")) diff --git a/src/models/builders/import_builder.rs b/src/wrapper/builders/import_builder.rs similarity index 93% rename from src/models/builders/import_builder.rs rename to src/wrapper/builders/import_builder.rs index 48c5e4b..f9b9e6d 100644 --- a/src/models/builders/import_builder.rs +++ b/src/wrapper/builders/import_builder.rs @@ -1,12 +1,12 @@ -use crate::endpoints::adding_files::{STATUS_IMPORT_FAILED, STATUS_IMPORT_VETOED}; -use crate::endpoints::adding_urls::AddUrlRequestBuilder; +use crate::api_core::adding_files::{STATUS_IMPORT_FAILED, STATUS_IMPORT_VETOED}; +use crate::api_core::adding_urls::AddUrlRequestBuilder; use crate::error::{Error, Result}; -use crate::hydrus_file::HydrusFile; -use crate::models::url::Url; -use crate::page::PageIdentifier; -use crate::service::ServiceName; -use crate::tag::Tag; use crate::utils::tag_list_to_string_list; +use crate::wrapper::hydrus_file::HydrusFile; +use crate::wrapper::page::PageIdentifier; +use crate::wrapper::service::ServiceName; +use crate::wrapper::tag::Tag; +use crate::wrapper::url::Url; use crate::Client; use std::collections::HashMap; use std::io::Read; diff --git a/src/models/builders/mod.rs b/src/wrapper/builders/mod.rs similarity index 100% rename from src/models/builders/mod.rs rename to src/wrapper/builders/mod.rs diff --git a/src/models/builders/tagging_builder.rs b/src/wrapper/builders/tagging_builder.rs similarity index 93% rename from src/models/builders/tagging_builder.rs rename to src/wrapper/builders/tagging_builder.rs index 435d44c..c80fa8b 100644 --- a/src/models/builders/tagging_builder.rs +++ b/src/wrapper/builders/tagging_builder.rs @@ -1,7 +1,7 @@ -use crate::endpoints::adding_tags::{AddTagsRequestBuilder, TagAction}; +use crate::api_core::adding_tags::{AddTagsRequestBuilder, TagAction}; use crate::error::Result; -use crate::models::tag::Tag; -use crate::service::ServiceName; +use crate::wrapper::service::ServiceName; +use crate::wrapper::tag::Tag; use crate::Client; use std::collections::HashMap; diff --git a/src/models/hydrus.rs b/src/wrapper/hydrus.rs similarity index 83% rename from src/models/hydrus.rs rename to src/wrapper/hydrus.rs index 004d5ea..0cf58ab 100644 --- a/src/models/hydrus.rs +++ b/src/wrapper/hydrus.rs @@ -1,16 +1,18 @@ -use crate::builders::import_builder::ImportBuilder; -use crate::builders::tagging_builder::TaggingBuilder; -use crate::endpoints::common::FileIdentifier; -use crate::endpoints::searching_and_fetching_files::FileSearchLocation; +use crate::api_core::common::FileIdentifier; +use crate::api_core::searching_and_fetching_files::FileSearchLocation; use crate::error::Result; -use crate::hydrus_file::HydrusFile; -use crate::models::url::Url; -use crate::models::version::Version; -use crate::service::Services; -use crate::tag::Tag; use crate::utils::tag_list_to_string_list; +use crate::wrapper::builders::import_builder::ImportBuilder; +use crate::wrapper::builders::tagging_builder::TaggingBuilder; +use crate::wrapper::hydrus_file::HydrusFile; +use crate::wrapper::service::Services; +use crate::wrapper::tag::Tag; +use crate::wrapper::url::Url; +use crate::wrapper::version::Version; use crate::Client; +/// A high level wrapper for the hydrus API for easier management of files, tags +/// urls etc. pub struct Hydrus { client: Client, } diff --git a/src/models/hydrus_file.rs b/src/wrapper/hydrus_file.rs similarity index 97% rename from src/models/hydrus_file.rs rename to src/wrapper/hydrus_file.rs index 6c8267f..12036cc 100644 --- a/src/models/hydrus_file.rs +++ b/src/wrapper/hydrus_file.rs @@ -1,9 +1,9 @@ -use crate::endpoints::adding_tags::{AddTagsRequestBuilder, TagAction}; -use crate::endpoints::common::{FileIdentifier, FileMetadataInfo, FileRecord}; +use crate::api_core::adding_tags::{AddTagsRequestBuilder, TagAction}; +use crate::api_core::common::{FileIdentifier, FileMetadataInfo, FileRecord}; use crate::error::{Error, Result}; -use crate::service::ServiceName; -use crate::tag::Tag; use crate::utils::tag_list_to_string_list; +use crate::wrapper::service::ServiceName; +use crate::wrapper::tag::Tag; use crate::Client; use mime::Mime; use std::collections::HashMap; diff --git a/src/models/mod.rs b/src/wrapper/mod.rs similarity index 100% rename from src/models/mod.rs rename to src/wrapper/mod.rs diff --git a/src/models/page.rs b/src/wrapper/page.rs similarity index 100% rename from src/models/page.rs rename to src/wrapper/page.rs diff --git a/src/models/service.rs b/src/wrapper/service.rs similarity index 97% rename from src/models/service.rs rename to src/wrapper/service.rs index 447213c..1109616 100644 --- a/src/models/service.rs +++ b/src/wrapper/service.rs @@ -1,5 +1,5 @@ -use crate::endpoints::access_management::GetServicesResponse; -use crate::endpoints::access_management::{ +use crate::api_core::access_management::GetServicesResponse; +use crate::api_core::access_management::{ SERVICE_TYPE_ALL_KNOWN_FILES, SERVICE_TYPE_ALL_KNOWN_TAGS, SERVICE_TYPE_ALL_LOCAL_FILES, SERVICE_TYPE_FILE_REPOSITORIES, SERVICE_TYPE_LOCAL_FILES, SERVICE_TYPE_LOCAL_TAGS, SERVICE_TYPE_TAG_REPOSITORIES, SERVICE_TYPE_TRASH, diff --git a/src/models/tag.rs b/src/wrapper/tag.rs similarity index 100% rename from src/models/tag.rs rename to src/wrapper/tag.rs diff --git a/src/models/url.rs b/src/wrapper/url.rs similarity index 93% rename from src/models/url.rs rename to src/wrapper/url.rs index 5e124e3..bd82056 100644 --- a/src/models/url.rs +++ b/src/wrapper/url.rs @@ -1,9 +1,9 @@ -use crate::builders::import_builder::UrlImportBuilder; -use crate::endpoints::adding_urls::{ +use crate::api_core::adding_urls::{ URL_TYPE_FILE, URL_TYPE_GALLERY, URL_TYPE_POST, URL_TYPE_WATCHABLE, }; use crate::error::Result; -use crate::hydrus_file::HydrusFile; +use crate::wrapper::builders::import_builder::UrlImportBuilder; +use crate::wrapper::hydrus_file::HydrusFile; use crate::Client; #[derive(Clone, Debug, PartialOrd, PartialEq)] diff --git a/src/models/version.rs b/src/wrapper/version.rs similarity index 100% rename from src/models/version.rs rename to src/wrapper/version.rs diff --git a/tests/client/test_adding_tags.rs b/tests/client/test_adding_tags.rs index 2bc6fa3..2dacb13 100644 --- a/tests/client/test_adding_tags.rs +++ b/tests/client/test_adding_tags.rs @@ -1,5 +1,5 @@ use super::super::common; -use hydrus_api::endpoints::adding_tags::{AddTagsRequestBuilder, TagAction}; +use hydrus_api::api_core::adding_tags::{AddTagsRequestBuilder, TagAction}; #[tokio::test] async fn it_cleans_tags() { diff --git a/tests/client/test_adding_urls.rs b/tests/client/test_adding_urls.rs index ab6dd3b..8b1f9aa 100644 --- a/tests/client/test_adding_urls.rs +++ b/tests/client/test_adding_urls.rs @@ -1,5 +1,5 @@ use super::super::common; -use hydrus_api::endpoints::adding_urls::{AddUrlRequestBuilder, URL_TYPE_POST}; +use hydrus_api::api_core::adding_urls::{AddUrlRequestBuilder, URL_TYPE_POST}; #[tokio::test] async fn it_returns_files_for_an_url() { diff --git a/tests/client/test_searching_and_fetching_files.rs b/tests/client/test_searching_and_fetching_files.rs index db0ffaf..5d4b146 100644 --- a/tests/client/test_searching_and_fetching_files.rs +++ b/tests/client/test_searching_and_fetching_files.rs @@ -1,6 +1,6 @@ use super::super::common; -use hydrus_api::endpoints::common::FileIdentifier; -use hydrus_api::endpoints::searching_and_fetching_files::FileSearchLocation; +use hydrus_api::api_core::common::FileIdentifier; +use hydrus_api::api_core::searching_and_fetching_files::FileSearchLocation; #[tokio::test] async fn is_searches_files() { diff --git a/tests/common.rs b/tests/common.rs index 48d41c4..dba8290 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -1,4 +1,4 @@ -use hydrus_api::client::Client; +use hydrus_api::api_core::client::Client; use hydrus_api::Hydrus; use log::LevelFilter; use std::env; @@ -21,7 +21,6 @@ pub fn get_client() -> Client { env::var("HYDRUS_URL").unwrap(), env::var("HYDRUS_ACCESS_KEY").unwrap(), ) - .unwrap() } pub fn get_hydrus() -> Hydrus { diff --git a/tests/wrapper/test_files.rs b/tests/wrapper/test_files.rs index 2304681..5291bfe 100644 --- a/tests/wrapper/test_files.rs +++ b/tests/wrapper/test_files.rs @@ -1,8 +1,8 @@ use super::super::common; -use hydrus_api::endpoints::adding_tags::TagAction; -use hydrus_api::endpoints::common::FileIdentifier; -use hydrus_api::hydrus_file::HydrusFile; -use hydrus_api::service::ServiceName; +use hydrus_api::api_core::adding_tags::TagAction; +use hydrus_api::api_core::common::FileIdentifier; +use hydrus_api::wrapper::hydrus_file::HydrusFile; +use hydrus_api::wrapper::service::ServiceName; async fn get_file() -> HydrusFile { let hydrus = common::get_hydrus(); diff --git a/tests/wrapper/test_hydrus.rs b/tests/wrapper/test_hydrus.rs index b919b87..794c347 100644 --- a/tests/wrapper/test_hydrus.rs +++ b/tests/wrapper/test_hydrus.rs @@ -1,8 +1,8 @@ use super::super::common; -use hydrus_api::endpoints::adding_tags::TagAction; -use hydrus_api::endpoints::searching_and_fetching_files::FileSearchLocation; -use hydrus_api::service::{ServiceName, ServiceType}; -use hydrus_api::url::UrlType; +use hydrus_api::api_core::adding_tags::TagAction; +use hydrus_api::api_core::searching_and_fetching_files::FileSearchLocation; +use hydrus_api::wrapper::service::{ServiceName, ServiceType}; +use hydrus_api::wrapper::url::UrlType; #[tokio::test] async fn it_retrieves_version_info() { diff --git a/tests/wrapper/test_import.rs b/tests/wrapper/test_import.rs index 39281c0..21a988e 100644 --- a/tests/wrapper/test_import.rs +++ b/tests/wrapper/test_import.rs @@ -1,9 +1,9 @@ use super::super::common; -use hydrus_api::builders::import_builder::FileImport; -use hydrus_api::page::PageIdentifier; -use hydrus_api::service::ServiceName; -use hydrus_api::tag::Tag; -use hydrus_api::url::UrlType; +use hydrus_api::wrapper::builders::import_builder::FileImport; +use hydrus_api::wrapper::page::PageIdentifier; +use hydrus_api::wrapper::service::ServiceName; +use hydrus_api::wrapper::tag::Tag; +use hydrus_api::wrapper::url::UrlType; #[tokio::test] async fn it_imports_file_paths() { diff --git a/tests/wrapper/test_url.rs b/tests/wrapper/test_url.rs index cc97bd6..700bad5 100644 --- a/tests/wrapper/test_url.rs +++ b/tests/wrapper/test_url.rs @@ -1,8 +1,8 @@ use super::super::common; -use hydrus_api::page::PageIdentifier; -use hydrus_api::service::ServiceName; -use hydrus_api::tag::Tag; -use hydrus_api::url::Url; +use hydrus_api::wrapper::page::PageIdentifier; +use hydrus_api::wrapper::service::ServiceName; +use hydrus_api::wrapper::tag::Tag; +use hydrus_api::wrapper::url::Url; async fn get_url() -> Url { let hydrus = common::get_hydrus();