Implement api to add files

Signed-off-by: trivernis <trivernis@protonmail.com>
pull/4/head
trivernis 3 years ago
parent 31f0345fbe
commit de0f6fcbdf

@ -849,8 +849,8 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
[[package]] [[package]]
name = "mediarepo-api" name = "mediarepo-api"
version = "0.5.1" version = "0.6.0"
source = "git+https://github.com/Trivernis/mediarepo-api.git?rev=17a7ade9a8112d3c8450ab6ea67c4f184d05744e#17a7ade9a8112d3c8450ab6ea67c4f184d05744e" source = "git+https://github.com/Trivernis/mediarepo-api.git?rev=ddebf4bf0c3e96ede64182ff52bd84f134acc33a#ddebf4bf0c3e96ede64182ff52bd84f134acc33a"
dependencies = [ dependencies = [
"chrono", "chrono",
"serde", "serde",

@ -140,16 +140,17 @@ impl File {
hash_id: i64, hash_id: i64,
file_type: FileType, file_type: FileType,
mime_type: Option<String>, mime_type: Option<String>,
creation_time: NaiveDateTime,
change_time: NaiveDateTime,
) -> RepoResult<Self> { ) -> RepoResult<Self> {
let now = Local::now().naive_local();
let file = file::ActiveModel { let file = file::ActiveModel {
hash_id: Set(hash_id), hash_id: Set(hash_id),
file_type: Set(file_type as u32), file_type: Set(file_type as u32),
mime_type: Set(mime_type), mime_type: Set(mime_type),
storage_id: Set(storage_id), storage_id: Set(storage_id),
import_time: Set(now.clone()), import_time: Set(Local::now().naive_local()),
creation_time: Set(now.clone()), creation_time: Set(creation_time),
change_time: Set(now), change_time: Set(change_time),
..Default::default() ..Default::default()
}; };
let file: file::ActiveModel = file.insert(&db).await?.into(); let file: file::ActiveModel = file.insert(&db).await?.into();

@ -4,16 +4,18 @@ use crate::namespace::Namespace;
use crate::storage::Storage; use crate::storage::Storage;
use crate::tag::Tag; use crate::tag::Tag;
use crate::thumbnail::Thumbnail; use crate::thumbnail::Thumbnail;
use chrono::{Local, NaiveDateTime};
use mediarepo_core::error::{RepoError, RepoResult}; use mediarepo_core::error::{RepoError, RepoResult};
use mediarepo_core::thumbnailer::ThumbnailSize; use mediarepo_core::thumbnailer::ThumbnailSize;
use mediarepo_core::utils::parse_namespace_and_tag; use mediarepo_core::utils::parse_namespace_and_tag;
use mediarepo_database::get_database; use mediarepo_database::get_database;
use sea_orm::DatabaseConnection; use sea_orm::DatabaseConnection;
use std::collections::HashMap; use std::collections::{HashMap, HashSet};
use std::fmt::Debug; use std::fmt::Debug;
use std::io::Cursor; use std::io::Cursor;
use std::iter::FromIterator; use std::iter::FromIterator;
use std::path::PathBuf; use std::path::PathBuf;
use std::str::FromStr;
use tokio::fs::OpenOptions; use tokio::fs::OpenOptions;
use tokio::io::BufReader; use tokio::io::BufReader;
@ -129,6 +131,36 @@ impl Repo {
File::find_by_tags(self.db.clone(), tag_ids).await File::find_by_tags(self.db.clone(), tag_ids).await
} }
/// Adds a file from bytes to the database
#[tracing::instrument(level = "debug", skip(self))]
pub async fn add_file(
&self,
mime_type: Option<String>,
content: Vec<u8>,
creation_time: NaiveDateTime,
change_time: NaiveDateTime,
) -> RepoResult<File> {
let storage = self.get_main_storage()?;
let reader = Cursor::new(content);
let hash = storage.store_entry(reader).await?;
let (mime_type, file_type) = mime_type
.and_then(|m| mime::Mime::from_str(&m).ok())
.map(|m| (Some(m.to_string()), FileType::from(m)))
.unwrap_or((None, FileType::Unknown));
File::add(
self.db.clone(),
storage.id(),
hash.id(),
file_type,
mime_type,
creation_time,
change_time,
)
.await
}
/// Adds a file to the database by its readable path in the file system /// Adds a file to the database by its readable path in the file system
#[tracing::instrument(level = "debug", skip(self))] #[tracing::instrument(level = "debug", skip(self))]
pub async fn add_file_by_path(&self, path: PathBuf) -> RepoResult<File> { pub async fn add_file_by_path(&self, path: PathBuf) -> RepoResult<File> {
@ -150,6 +182,8 @@ impl Repo {
hash.id(), hash.id(),
file_type, file_type,
mime_type, mime_type,
Local::now().naive_local(),
Local::now().naive_local(),
) )
.await .await
} }
@ -243,6 +277,31 @@ impl Repo {
Tag::for_hash_list(self.db.clone(), hashes).await Tag::for_hash_list(self.db.clone(), hashes).await
} }
/// Adds all tags that are not in the database to the database and returns the ones already existing as well
#[tracing::instrument(level = "debug", skip_all)]
pub async fn add_all_tags(&self, tags: Vec<(Option<String>, String)>) -> RepoResult<Vec<Tag>> {
let mut tags_to_add = tags;
let mut existing_tags = self.tags_by_names(tags_to_add.clone()).await?;
{
let existing_tags_set = existing_tags
.iter()
.map(|t| (t.namespace().map(|n| n.name().clone()), t.name().clone()))
.collect::<HashSet<(Option<String>, String)>>();
tags_to_add.retain(|t| !existing_tags_set.contains(t));
}
for (namespace, name) in tags_to_add {
let tag = if let Some(namespace) = namespace {
self.add_namespaced_tag(namespace, name).await?
} else {
self.add_unnamespaced_tag(name).await?
};
existing_tags.push(tag);
}
Ok(existing_tags)
}
/// Adds or finds a tag /// Adds or finds a tag
#[tracing::instrument(level = "debug", skip(self))] #[tracing::instrument(level = "debug", skip(self))]
pub async fn add_or_find_tag<S: ToString + Debug>(&self, tag: S) -> RepoResult<Tag> { pub async fn add_or_find_tag<S: ToString + Debug>(&self, tag: S) -> RepoResult<Tag> {

@ -790,8 +790,8 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
[[package]] [[package]]
name = "mediarepo-api" name = "mediarepo-api"
version = "0.5.1" version = "0.6.0"
source = "git+https://github.com/Trivernis/mediarepo-api.git?rev=17a7ade9a8112d3c8450ab6ea67c4f184d05744e#17a7ade9a8112d3c8450ab6ea67c4f184d05744e" source = "git+https://github.com/Trivernis/mediarepo-api.git?rev=ddebf4bf0c3e96ede64182ff52bd84f134acc33a#ddebf4bf0c3e96ede64182ff52bd84f134acc33a"
dependencies = [ dependencies = [
"chrono", "chrono",
"serde", "serde",

@ -34,4 +34,4 @@ features = ["tokio-executor"]
[dependencies.mediarepo-api] [dependencies.mediarepo-api]
git = "https://github.com/Trivernis/mediarepo-api.git" git = "https://github.com/Trivernis/mediarepo-api.git"
rev = "17a7ade9a8112d3c8450ab6ea67c4f184d05744e" rev = "ddebf4bf0c3e96ede64182ff52bd84f134acc33a"

@ -2,18 +2,18 @@ use crate::from_model::FromModel;
use crate::utils::{file_by_identifier, get_repo_from_context}; use crate::utils::{file_by_identifier, get_repo_from_context};
use compare::Compare; use compare::Compare;
use mediarepo_api::types::files::{ use mediarepo_api::types::files::{
AddFileRequest, FileMetadataResponse, FindFilesByTagsRequest, GetFileThumbnailOfSizeRequest, AddFileRequestHeader, FileMetadataResponse, FindFilesByTagsRequest,
GetFileThumbnailsRequest, ReadFileRequest, SortDirection, SortKey, ThumbnailMetadataResponse, GetFileThumbnailOfSizeRequest, GetFileThumbnailsRequest, ReadFileRequest, SortDirection,
UpdateFileNameRequest, SortKey, ThumbnailMetadataResponse, UpdateFileNameRequest,
}; };
use mediarepo_core::error::RepoError; use mediarepo_core::error::RepoError;
use mediarepo_core::rmp_ipc::prelude::*; use mediarepo_core::rmp_ipc::prelude::*;
use mediarepo_core::thumbnailer::ThumbnailSize; use mediarepo_core::thumbnailer::ThumbnailSize;
use mediarepo_core::utils::parse_namespace_and_tag;
use mediarepo_database::queries::tags::get_hashes_with_namespaced_tags; use mediarepo_database::queries::tags::get_hashes_with_namespaced_tags;
use mediarepo_model::file::File; use mediarepo_model::file::File;
use std::cmp::Ordering; use std::cmp::Ordering;
use std::collections::HashMap; use std::collections::HashMap;
use std::path::PathBuf;
use tokio::io::AsyncReadExt; use tokio::io::AsyncReadExt;
pub struct FilesNamespace; pub struct FilesNamespace;
@ -95,10 +95,27 @@ impl FilesNamespace {
/// Adds a file to the repository /// Adds a file to the repository
#[tracing::instrument(skip_all)] #[tracing::instrument(skip_all)]
async fn add_file<S: AsyncProtocolStream>(ctx: &Context<S>, event: Event) -> IPCResult<()> { async fn add_file<S: AsyncProtocolStream>(ctx: &Context<S>, event: Event) -> IPCResult<()> {
let request = event.data::<AddFileRequest>()?; let (request, bytes) = event
let path = PathBuf::from(request.path); .data::<TandemPayload<AddFileRequestHeader, BytePayload>>()?
.into_inner();
let AddFileRequestHeader { metadata, tags } = request;
let repo = get_repo_from_context(ctx).await; let repo = get_repo_from_context(ctx).await;
let file = repo.add_file_by_path(path).await?;
let mut file = repo
.add_file(
metadata.mime_type,
bytes.into_inner(),
metadata.creation_time,
metadata.change_time,
)
.await?;
file.set_name(metadata.name).await?;
let tags = repo
.add_all_tags(tags.into_iter().map(parse_namespace_and_tag).collect())
.await?;
let tag_ids: Vec<i64> = tags.into_iter().map(|t| t.id()).collect();
file.add_tags(tag_ids).await?;
ctx.emitter ctx.emitter
.emit_response_to( .emit_response_to(

Loading…
Cancel
Save