From 228f24cb3020b719540fc9665e4aff21528fc69e Mon Sep 17 00:00:00 2001 From: jakka Date: Wed, 1 Oct 2025 12:57:32 +0300 Subject: broke down modules and renamed them --- src/sync_lib/client.rs | 0 src/sync_lib/traits.rs | 67 +++++++++++++ src/sync_lib/types.rs | 249 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 316 insertions(+) create mode 100644 src/sync_lib/client.rs create mode 100644 src/sync_lib/traits.rs create mode 100644 src/sync_lib/types.rs (limited to 'src/sync_lib') diff --git a/src/sync_lib/client.rs b/src/sync_lib/client.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/sync_lib/traits.rs b/src/sync_lib/traits.rs new file mode 100644 index 0000000..1f8e1dd --- /dev/null +++ b/src/sync_lib/traits.rs @@ -0,0 +1,67 @@ +use std::{collections::HashMap, path::PathBuf}; + +use crate::sync_lib::types::*; + +type Result = std::result::Result; + +/// Trait for accessing and managing keys and services. +pub trait AccessManagement { + /// Register a new external program with the client. This requires the 'add from api request' mini-dialog under services->review services to be open, otherwise it will 403. + fn request_new_permissions( + &self, + name: &str, + permissions: &[HydrusPermissions], + ) -> Result; + /// Get a new session key. + fn get_session_key(&self) -> Result; + /// Check your access key is valid. + fn verify_access_key(&self, key: &str) -> Result; + /// Ask the client about a specific service by providing its name. + fn get_service_name(&self, name: &str) -> Result; + /// Ask the client about a specific service by providing its key. + fn get_service_key(&self, key: &str) -> Result; + /// Ask the client about its services. + fn get_services(&self) -> Result>; +} + +/// Trait for importing and deleting files. +pub trait ImportingAndDeletingFiles { + /// Tell the client to import a file by providing a local (hydrus-local) file path. + fn add_file_via_path( + &self, + path: PathBuf, + delete: Option, + domains: Option, + ) -> Result; + /// Tell the client to import a file by sending the file. + fn add_file_via_file(&self, file: PathBuf) -> Result; + /// Tell the client to send files to the trash. + fn delete_files( + &self, + file: HydrusFile, + domain: Option, + reason: Option, + ) -> Result<()>; + /// Tell the client to restore files that were previously deleted to their old file service(s). + fn undelete_files(&self, file: HydrusFile, domain: Option) -> Result<()>; + /// Tell the client to forget that it once deleted files. + fn clear_file_deletion_records(&self, file: HydrusFile) -> Result<()>; + /// Copy files from one local file domain to another. + fn migrate_files(&self, file: HydrusFile, domain: FileDomain) -> Result<()>; + /// Tell the client to archive inboxed files. + fn archive_files(&self, file: HydrusFile) -> Result<()>; + /// Tell the client re-inbox archived files. + fn unarchive_files(&self, file: HydrusFile) -> Result<()>; + /// Generate hashes for an arbitrary file by providing a local path to the file. + fn generate_hashes_for_path(&self, file: PathBuf) -> Result; + /// Generate hashes for an arbitrary file by sending the file. + fn generate_hashes_for_file(&self, file: PathBuf) -> Result; +} + +pub trait ImportingAndEditingUrls { + fn get_url_files( + &self, + url: &str, + doublecheck_file_system: Option, + ) -> Result; +} diff --git a/src/sync_lib/types.rs b/src/sync_lib/types.rs new file mode 100644 index 0000000..7762065 --- /dev/null +++ b/src/sync_lib/types.rs @@ -0,0 +1,249 @@ +use std::path::PathBuf; + +use serde::{Deserialize, Serialize}; +use serde_repr::{Deserialize_repr, Serialize_repr}; +use thiserror::Error; + +/// Error wrapper +#[derive(Error, Debug)] +pub enum HydrusError { + #[error("failed to connect to Hydrus")] + NetworkError(reqwest::Error), + #[error("failed to encode/Deserialize data")] + DeserializeError(serde_json::Error), + #[error("io error")] + IOError(std::io::Error), + #[error("api or session key needed")] + KeyNotSupplied, +} + +impl From for HydrusError { + fn from(value: serde_json::Error) -> Self { + HydrusError::DeserializeError(value) + } +} + +impl From for HydrusError { + fn from(value: std::io::Error) -> Self { + HydrusError::IOError(value) + } +} + +impl From for HydrusError { + fn from(value: reqwest::Error) -> Self { + HydrusError::NetworkError(value) + } +} + +/// Hydrus serivce permissions object +#[derive(PartialEq, Debug, Clone, Serialize_repr, Deserialize_repr)] +#[repr(u8)] +pub enum HydrusPermissions { + ImportAndEditURLs = 0, + ImportAndEditFiles, + EditFileTags, + SearchAndFetchFiles, + ManagePages, + ManageCookiesAndHeaders, + ManageDatabase, + EditFileNotes, + EditFileRelationships, + EditFileRatings, + ManagePopups, + EditFileTimes, + CommitPending, + SeeLocalPaths, + Null = 255, +} + +/// Hydrus key information struct +#[derive(Deserialize, Debug)] +pub struct KeyInfo { + pub name: String, + pub permits_everything: bool, + pub basic_permissions: Vec, + pub human_permissions: String, +} + +/// Hydrus service type object +#[derive(PartialEq, Debug, Clone, Serialize_repr, Deserialize_repr)] +#[repr(u8)] +pub enum ServiceType { + TagRepository = 0, + FileRepository, + LocalFileDomain, + LocalTagDomain = 5, + NumericalRating, + BoolRating, + AllKnownTags = 10, + AllKnownFiles, + LocalBooru, + IPFS, + Trash, + AllLocalFiles, + FileNotes = 17, + ClientAPI, + DeletedFromAnywhere, + LocalUpdates, + AllMyFiles, + IncDecRating, + ServerAdmin = 99, + Null = 255, +} + +/// Hydrus service struct +#[derive(Deserialize, Debug, Clone)] +pub struct Service { + pub name: String, + #[serde(default)] + pub service_key: String, + pub r#type: ServiceType, + pub type_pretty: String, + #[serde(default)] + pub star_shape: Option, + #[serde(default)] + pub min_stars: Option, + #[serde(default)] + pub max_stars: Option, +} + +/// Hydrus file domains +pub enum FileDomain { + FileServiceKey(String), + FileServiceKeys(Vec), + DeletedFileServiceKey(String), + DeletedFileServiceKeys(Vec), +} + +/// Payload for importing a file via providing a local path +#[derive(Serialize, Debug, Default)] +pub struct AddFileRequest { + pub path: PathBuf, + #[serde(skip_serializing_if = "Option::is_none")] + pub delete_after_successful_import: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub file_service_key: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub file_service_keys: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub deleted_file_service_key: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub deleted_file_service_keys: Option>, +} +/// File importing status +#[derive(PartialEq, Debug, Clone, Serialize_repr, Deserialize_repr)] +#[repr(u8)] +pub enum AddFileStatus { + SuccessfulImport = 1, + AlreadyInDatabase, + PreviouslyDeleted, + FailedToImport, + FileVetoed = 7, +} +/// File importing api response +#[derive(Deserialize)] +pub struct AddFileResponse { + pub status: AddFileStatus, + pub hash: String, + pub note: String, +} + +/// Hydrus file object +#[derive(Debug, Clone, Serialize)] +pub enum HydrusFile { + #[serde(rename(serialize = "file_id"))] + FileId(String), + #[serde(rename(serialize = "file_ids"))] + FileIds(Vec), + #[serde(rename(serialize = "hash"))] + Hash(String), + #[serde(rename(serialize = "hashes"))] + Hashes(Vec), +} + +impl Default for HydrusFile { + fn default() -> Self { + Self::FileId(String::from("")) + } +} + +/// Payload for various file-related requests +#[derive(Debug, Default)] +pub struct FileRequest { + pub file: HydrusFile, + pub delete_after_successful_import: Option, + pub file_service_key: Option, + pub file_service_keys: Option>, + pub deleted_file_service_key: Option, + pub deleted_file_service_keys: Option>, + pub reason: Option, +} + +impl Serialize for FileRequest { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + use serde::ser::SerializeMap; + let mut map = serializer.serialize_map(Some(1))?; + + match &self.file { + HydrusFile::FileId(id) => map.serialize_entry("file_id", &id)?, + HydrusFile::FileIds(ids) => map.serialize_entry("file_ids", &ids)?, + HydrusFile::Hash(hash) => map.serialize_entry("hash", &hash)?, + HydrusFile::Hashes(hashes) => map.serialize_entry("hashes", &hashes)?, + } + + if let Some(val) = &self.reason { + map.serialize_entry("reason", &val)?; + } + + if let Some(val) = &self.file_service_key { + map.serialize_entry("file_service_key", &val)?; + } + + if let Some(val) = &self.file_service_keys { + map.serialize_entry("file_service_keys", &val)?; + } + + if let Some(val) = &self.deleted_file_service_key { + map.serialize_entry("deleted_file_service_key", &val)?; + } + + if let Some(val) = &self.deleted_file_service_keys { + map.serialize_entry("deleted_file_service_keys", &val)?; + } + + map.end() + } +} + +#[derive(Debug, Deserialize)] +pub struct HashResponse { + pub hash: String, + #[serde(default)] + pub perceptual_hashes: Option>, + #[serde(default)] + pub pixel_hash: Option, +} + +#[derive(Debug, Deserialize_repr)] +#[repr(u8)] +pub enum UrlStatus { + NotInDatabase = 0, + AlreadyInDatabase = 2, + PreviouslyDeleted, +} + +#[derive(Debug, Deserialize)] +pub struct UrlFileStatus { + pub status: UrlStatus, + pub hash: String, + pub note: String, +} + +#[derive(Debug, Deserialize)] +pub struct FilesUrlResponse { + pub normalised_url: String, + pub url_file_statuses: Vec, +} -- cgit v1.3.1