Add service selection to undelete, archive and unarchive

Signed-off-by: trivernis <trivernis@protonmail.com>
pull/15/head
trivernis 2 years ago
parent 0e8c28c948
commit 6b06a9cf60
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

@ -1,4 +1,7 @@
use crate::api_core::common::{FileIdentifier, FileMetadataInfo, FileRecord, OptionalStringNumber};
use crate::api_core::common::{
FileIdentifier, FileMetadataInfo, FileRecord, FileSelection, FileServiceSelection,
OptionalStringNumber,
};
use crate::api_core::endpoints::access_management::{
ApiVersion, ApiVersionResponse, GetServices, GetServicesResponse, SessionKey,
SessionKeyResponse, VerifyAccessKey, VerifyAccessKeyResponse,
@ -110,35 +113,66 @@ impl Client {
/// Moves files with matching hashes to the trash
#[tracing::instrument(skip(self), level = "debug")]
pub async fn delete_files(&self, request: DeleteFilesRequest) -> Result<()> {
self.post::<DeleteFiles>(request).await?;
pub async fn delete_files(
&self,
files: FileSelection,
service: FileServiceSelection,
reason: Option<String>,
) -> Result<()> {
self.post::<DeleteFiles>(DeleteFilesRequest {
file_selection: files,
service_selection: service,
reason,
})
.await?;
Ok(())
}
/// Pulls files out of the trash by hash
#[tracing::instrument(skip(self), level = "debug")]
pub async fn undelete_files(&self, hashes: Vec<String>) -> Result<()> {
self.post::<UndeleteFiles>(UndeleteFilesRequest { hashes })
.await?;
pub async fn undelete_files(
&self,
files: FileSelection,
service: FileServiceSelection,
) -> Result<()> {
self.post::<UndeleteFiles>(UndeleteFilesRequest {
file_selection: files,
service_selection: service,
})
.await?;
Ok(())
}
/// Moves files from the inbox into the archive
#[tracing::instrument(skip(self), level = "debug")]
pub async fn archive_files(&self, hashes: Vec<String>) -> Result<()> {
self.post::<ArchiveFiles>(ArchiveFilesRequest { hashes })
.await?;
pub async fn archive_files(
&self,
files: FileSelection,
service: FileServiceSelection,
) -> Result<()> {
self.post::<ArchiveFiles>(ArchiveFilesRequest {
file_selection: files,
service_selection: service,
})
.await?;
Ok(())
}
/// Moves files from the archive into the inbox
#[tracing::instrument(skip(self), level = "debug")]
pub async fn unarchive_files(&self, hashes: Vec<String>) -> Result<()> {
self.post::<UnarchiveFiles>(UnarchiveFilesRequest { hashes })
.await?;
pub async fn unarchive_files(
&self,
files: FileSelection,
service: FileServiceSelection,
) -> Result<()> {
self.post::<UnarchiveFiles>(UnarchiveFilesRequest {
file_selection: files,
service_selection: service,
})
.await?;
Ok(())
}

@ -1,3 +1,5 @@
use crate::wrapper::service::ServiceName;
use serde::Serialize;
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
@ -98,6 +100,119 @@ impl FileIdentifier {
}
}
/// A generic selection for one or multiple files
#[derive(Clone, Debug, Serialize, Default)]
pub struct FileSelection {
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) hash: Option<String>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub(crate) hashes: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) file_id: Option<u64>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub(crate) file_ids: Vec<u64>,
}
impl From<FileIdentifier> for FileSelection {
fn from(id: FileIdentifier) -> Self {
let mut selection = Self::default();
match id {
FileIdentifier::ID(id) => selection.file_id = Some(id),
FileIdentifier::Hash(hash) => selection.hash = Some(hash),
}
selection
}
}
impl FileSelection {
/// Creates a new single hash file selection
pub fn by_hash<S: ToString>(hash: S) -> Self {
Self {
hash: Some(hash.to_string()),
..Default::default()
}
}
/// Creates a new file selection with a single file id
pub fn by_file_id(file_id: u64) -> Self {
Self {
file_id: Some(file_id),
..Default::default()
}
}
/// Creates a new file selection with several hashes
pub fn by_hashes(mut hashes: Vec<String>) -> Self {
if hashes.len() == 1 {
Self::by_hash(hashes.pop().unwrap())
} else {
Self {
hashes,
..Default::default()
}
}
}
/// Creates a new file selection with several IDs
pub fn by_file_ids(mut file_ids: Vec<u64>) -> Self {
if file_ids.len() == 1 {
Self::by_file_id(file_ids.pop().unwrap())
} else {
Self {
file_ids,
..Default::default()
}
}
}
}
/// A selection for a single file service
#[derive(Clone, Debug, Serialize, Default)]
pub struct FileServiceSelection {
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) file_service_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) file_service_key: Option<String>,
}
impl FileServiceSelection {
/// Creates a new file service selection by name
pub fn by_name<S: ToString>(name: S) -> Self {
Self {
file_service_name: Some(name.to_string()),
..Default::default()
}
}
/// Creates a new file service selection by service key
pub fn by_key<S: ToString>(key: S) -> Self {
Self {
file_service_key: Some(key.to_string()),
..Default::default()
}
}
/// Selects no service
pub fn none() -> Self {
Self::default()
}
}
impl From<ServiceIdentifier> for FileServiceSelection {
fn from(id: ServiceIdentifier) -> Self {
match id {
ServiceIdentifier::Name(n) => Self::by_name(n),
ServiceIdentifier::Key(k) => Self::by_key(k),
}
}
}
impl From<ServiceName> for FileServiceSelection {
fn from(name: ServiceName) -> Self {
Self::by_name(name)
}
}
#[derive(Clone)]
pub struct FileRecord {
pub bytes: Vec<u8>,

@ -1,4 +1,4 @@
use crate::api_core::common::{BasicHashList, ServiceIdentifier};
use crate::api_core::common::{FileSelection, FileServiceSelection};
use crate::api_core::endpoints::Endpoint;
use serde::Serialize;
@ -33,41 +33,13 @@ impl Endpoint for AddFile {
#[derive(Clone, Debug, Serialize)]
pub struct DeleteFilesRequest {
/// The files by hashes to delete
pub hashes: Vec<String>,
/// The files by file ids to delete
pub file_ids: Vec<u64>,
pub file_service_name: Option<String>,
pub file_service_key: Option<String>,
#[serde(flatten)]
pub file_selection: FileSelection,
#[serde(flatten)]
pub service_selection: FileServiceSelection,
pub reason: Option<String>,
}
impl DeleteFilesRequest {
pub fn new(hashes: Vec<String>, file_ids: Vec<u64>) -> Self {
Self {
hashes,
file_ids,
file_service_key: None,
file_service_name: None,
reason: None,
}
}
/// Sets the service to delete from. If none is given it deletes
/// from all files.
pub fn set_service(&mut self, service: ServiceIdentifier) {
match service {
ServiceIdentifier::Name(name) => self.file_service_name = Some(name),
ServiceIdentifier::Key(key) => self.file_service_key = Some(key),
}
}
/// Sets the reason for deletion
pub fn set_reason<S: ToString>(&mut self, reason: S) {
self.reason = Some(reason.to_string());
}
}
pub struct DeleteFiles;
impl Endpoint for DeleteFiles {
@ -79,7 +51,14 @@ impl Endpoint for DeleteFiles {
}
}
pub type UndeleteFilesRequest = BasicHashList;
#[derive(Clone, Debug, Serialize)]
pub struct UndeleteFilesRequest {
#[serde(flatten)]
pub file_selection: FileSelection,
#[serde(flatten)]
pub service_selection: FileServiceSelection,
}
pub struct UndeleteFiles;
impl Endpoint for UndeleteFiles {
@ -91,7 +70,14 @@ impl Endpoint for UndeleteFiles {
}
}
pub type ArchiveFilesRequest = BasicHashList;
#[derive(Clone, Debug, Serialize)]
pub struct ArchiveFilesRequest {
#[serde(flatten)]
pub file_selection: FileSelection,
#[serde(flatten)]
pub service_selection: FileServiceSelection,
}
pub struct ArchiveFiles;
impl Endpoint for ArchiveFiles {
@ -103,11 +89,18 @@ impl Endpoint for ArchiveFiles {
}
}
pub type UnarchiveFilesRequest = BasicHashList;
#[derive(Clone, Debug, Serialize)]
pub struct UnarchiveFilesRequest {
#[serde(flatten)]
pub file_selection: FileSelection,
#[serde(flatten)]
pub service_selection: FileServiceSelection,
}
pub struct UnarchiveFiles;
impl Endpoint for UnarchiveFiles {
type Request = UndeleteFilesRequest;
type Request = UnarchiveFilesRequest;
type Response = ();
fn path() -> String {

@ -1,5 +1,6 @@
use crate::api_core::common::{FileIdentifier, ServiceIdentifier};
use crate::api_core::endpoints::adding_files::DeleteFilesRequest;
use crate::api_core::common::{
FileIdentifier, FileSelection, FileServiceSelection, ServiceIdentifier,
};
use crate::error::Result;
use crate::Client;
@ -53,20 +54,18 @@ impl DeleteFilesBuilder {
/// Deletes all files specified in this builder
pub async fn run(self) -> Result<()> {
let mut request = DeleteFilesRequest {
reason: self.reason,
let file_selection = FileSelection {
hashes: self.hashes,
file_ids: self.ids,
file_service_key: None,
file_service_name: None,
..Default::default()
};
if let Some(service) = self.service {
match service {
ServiceIdentifier::Name(name) => request.file_service_name = Some(name),
ServiceIdentifier::Key(key) => request.file_service_key = Some(key),
}
}
let service_selection = self
.service
.map(FileServiceSelection::from)
.unwrap_or_default();
self.client.delete_files(request).await
self.client
.delete_files(file_selection, service_selection, self.reason)
.await
}
}

@ -1,4 +1,7 @@
use crate::api_core::common::{FileIdentifier, FileMetadataInfo, FileRecord, ServiceIdentifier};
use crate::api_core::common::{
FileIdentifier, FileMetadataInfo, FileRecord, FileSelection, FileServiceSelection,
ServiceIdentifier,
};
use crate::api_core::endpoints::adding_tags::{AddTagsRequestBuilder, TagAction};
use crate::error::{Error, Result};
use crate::utils::tag_list_to_string_list;
@ -240,7 +243,9 @@ impl HydrusFile {
pub async fn undelete(&mut self) -> Result<()> {
let hash = self.hash().await?;
self.metadata = None;
self.client.undelete_files(vec![hash]).await
self.client
.undelete_files(FileSelection::by_hash(hash), FileServiceSelection::none())
.await
}
/// Associates the file with a list of urls

@ -1,7 +1,7 @@
use crate::common;
use crate::common::create_testdata;
use crate::common::test_data::get_test_hashes;
use hydrus_api::api_core::endpoints::adding_files::DeleteFilesRequest;
use crate::common::test_data::{get_test_hashes, TEST_HASH_1};
use hydrus_api::api_core::common::FileSelection;
use hydrus_api::wrapper::service::ServiceName;
#[tokio::test]
@ -25,29 +25,51 @@ async fn it_adds_binary_files() {
async fn it_deletes_files() {
let client = common::get_client();
create_testdata(&client).await;
let mut delete_request = DeleteFilesRequest::new(get_test_hashes(), vec![]);
delete_request.set_reason("Testing");
delete_request.set_service(ServiceName::my_files().into());
client.delete_files(delete_request).await.unwrap();
client
.delete_files(
FileSelection::by_hashes(get_test_hashes()),
ServiceName::my_files().into(),
Some("Test".to_string()),
)
.await
.unwrap();
}
#[tokio::test]
async fn it_undeletes_files() {
let client = common::get_client();
create_testdata(&client).await;
client.undelete_files(get_test_hashes()).await.unwrap();
client
.undelete_files(
FileSelection::by_hashes(get_test_hashes()),
ServiceName::my_files().into(),
)
.await
.unwrap();
}
#[tokio::test]
async fn it_archives_files() {
let client = common::get_client();
create_testdata(&client).await;
client.archive_files(get_test_hashes()).await.unwrap();
client
.archive_files(
FileSelection::by_hashes(vec![TEST_HASH_1.to_string()]),
ServiceName::my_files().into(),
)
.await
.unwrap();
}
#[tokio::test]
async fn it_unarchives_files() {
let client = common::get_client();
create_testdata(&client).await;
client.unarchive_files(get_test_hashes()).await.unwrap();
client
.unarchive_files(
FileSelection::by_hashes(get_test_hashes()),
ServiceName::my_files().into(),
)
.await
.unwrap();
}

Loading…
Cancel
Save