From 8b5af040752fa11ef1edfcb75d886421e47d2851 Mon Sep 17 00:00:00 2001 From: trivernis Date: Sun, 24 Oct 2021 11:37:22 +0200 Subject: [PATCH] Add file api Signed-off-by: trivernis --- mediarepo-api/Cargo.toml | 10 +++- mediarepo-api/src/client_api/file.rs | 86 ++++++++++++++++++++++++++++ mediarepo-api/src/client_api/mod.rs | 40 ++++++++++++- 3 files changed, 133 insertions(+), 3 deletions(-) create mode 100644 mediarepo-api/src/client_api/file.rs diff --git a/mediarepo-api/Cargo.toml b/mediarepo-api/Cargo.toml index f1071ba..fe61269 100644 --- a/mediarepo-api/Cargo.toml +++ b/mediarepo-api/Cargo.toml @@ -9,8 +9,8 @@ license = "gpl-3" [dependencies] tracing = "0.1.29" thiserror = "1.0.30" +async-trait = {version = "0.1.51", optional=true} rmp-ipc = {version = "0.7.2", optional=true} -tauri = {version = "1.0.0-beta.8", optional=true} [dependencies.serde] version = "1.0.130" @@ -20,6 +20,12 @@ features = ["serde_derive"] version = "0.4.19" features = ["serde"] +[dependencies.tauri] +version = "1.0.0-beta.8" +optional=true +default-features = false +features = [] + [features] tauri-plugin = ["client-api","tauri", "rmp-ipc"] -client-api = ["rmp-ipc"] \ No newline at end of file +client-api = ["rmp-ipc", "async-trait"] \ No newline at end of file diff --git a/mediarepo-api/src/client_api/file.rs b/mediarepo-api/src/client_api/file.rs new file mode 100644 index 0000000..5ffc039 --- /dev/null +++ b/mediarepo-api/src/client_api/file.rs @@ -0,0 +1,86 @@ +use crate::client_api::error::ApiResult; +use crate::client_api::IPCApi; +use crate::types::files::{ + FileMetadataResponse, FindFilesByTagsRequest, GetFileThumbnailsRequest, ReadFileRequest, + TagQuery, ThumbnailMetadataResponse, +}; +use crate::types::identifier::FileIdentifier; +use async_trait::async_trait; +use rmp_ipc::prelude::Context; + +#[derive(Clone)] +pub struct FileApi { + ctx: Context, +} + +#[async_trait] +impl IPCApi for FileApi { + fn namespace() -> &'static str { + "files" + } + + fn ctx(&self) -> &Context { + &self.ctx + } +} + +impl FileApi { + /// Creates a new file api client + pub fn new(ctx: Context) -> Self { + Self { ctx } + } + + /// Returns all known files + #[tracing::instrument(level = "debug", skip(self))] + pub async fn all_files(&self) -> ApiResult> { + self.emit_and_get("all_files", ()).await + } + + /// Searches for a file by a list of tags + #[tracing::instrument(level = "debug", skip(self))] + pub async fn find_files(&self, tags: Vec) -> ApiResult> { + let tags = tags + .into_iter() + .map(|tag| TagQuery { + name: tag, + negate: false, + }) + .collect(); + + self.emit_and_get("find_files", FindFilesByTagsRequest { tags }) + .await + } + + /// Reads the file and returns its contents as bytes + #[tracing::instrument(level = "debug", skip(self))] + pub async fn read_file_by_hash(&self, hash: String) -> ApiResult> { + self.emit_and_get( + "read_file", + ReadFileRequest { + id: FileIdentifier::Hash(hash), + }, + ) + .await + } + + /// Returns a list of all thumbnails of the file + #[tracing::instrument(level = "debug", skip(self))] + pub async fn get_file_thumbnails( + &self, + hash: String, + ) -> ApiResult> { + self.emit_and_get( + "get_thumbnails", + GetFileThumbnailsRequest { + id: FileIdentifier::Hash(hash), + }, + ) + .await + } + + /// Reads the thumbnail of the file and returns its contents in bytes + #[tracing::instrument(level = "debug", skip(self))] + pub async fn read_thumbnail(&self, hash: String) -> ApiResult> { + self.emit_and_get("read_thumbnail", hash).await + } +} diff --git a/mediarepo-api/src/client_api/mod.rs b/mediarepo-api/src/client_api/mod.rs index a6d7b95..10d7311 100644 --- a/mediarepo-api/src/client_api/mod.rs +++ b/mediarepo-api/src/client_api/mod.rs @@ -1,18 +1,49 @@ pub mod error; +pub mod file; +use std::fmt::Debug; use rmp_ipc::ipc::context::Context; use rmp_ipc::IPCBuilder; use crate::client_api::error::ApiResult; +use crate::client_api::file::FileApi; +use crate::types::misc::InfoResponse; +use async_trait::async_trait; +use rmp_ipc::ipc::stream_emitter::EmitMetadata; +use rmp_ipc::payload::{EventReceivePayload, EventSendPayload}; + +#[async_trait] +pub trait IPCApi { + fn namespace() -> &'static str; + fn ctx(&self) -> &Context; + + async fn emit(&self, event_name: &str, data: T) -> ApiResult { + let ctx = self.ctx(); + let meta = ctx.emitter.emit_to(Self::namespace(), event_name, data).await?; + + Ok(meta) + } + + async fn emit_and_get(&self, event_name: &str, data: T) -> ApiResult { + let meta = self.emit(event_name, data).await?; + let response = meta.await_reply(self.ctx()).await?; + + Ok(response.data()?) + } +} #[derive(Clone)] pub struct ApiClient { ctx: Context, + pub file: FileApi, } impl ApiClient { /// Creates a new client from an existing ipc context pub fn new(ctx: Context) -> Self { - Self {ctx} + Self { + file: FileApi::new(ctx.clone()), + ctx + } } /// Connects to the ipc Socket @@ -21,4 +52,11 @@ impl ApiClient { Ok(Self::new(ctx)) } + + /// Returns information about the connected ipc server + #[tracing::instrument(level="debug", skip(self))] + pub async fn info(&self) -> ApiResult { + let res = self.ctx.emitter.emit("info", ()).await?.await_reply(&self.ctx).await?; + Ok(res.data::()?) + } } \ No newline at end of file