add ID3 metadata extractor

feat/vaults
Tomáš Mládek 2022-02-28 21:36:55 +01:00
parent 920e67a283
commit 506727356c
No known key found for this signature in database
GPG Key ID: 65E225C8B3E2ED8A
5 changed files with 79 additions and 16 deletions

12
Cargo.lock generated
View File

@ -1232,6 +1232,17 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "id3"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a3598f9ed06d8a7ff358dc1a52f07f98d6625b996ad60588805b3d8cfd4d0cd"
dependencies = [
"bitflags",
"byteorder",
"flate2",
]
[[package]]
name = "idna"
version = "0.2.3"
@ -2894,6 +2905,7 @@ dependencies = [
"env_logger",
"filebuffer",
"futures-util",
"id3",
"image",
"is_executable",
"lazy_static",

View File

@ -69,13 +69,21 @@ image = { version = "0.23.14", optional = true }
webp = { version = "0.2.0", optional = true }
webpage = { version = "1.4.0", optional = true }
id3 = { version = "1.0.2", optional = true }
[build-dependencies]
built = "0.5.1"
[features]
default = ["desktop", "previews", "previews-image", 'extractors-web']
default = [
"desktop",
"previews",
"previews-image",
"extractors-web",
"extractors-audio",
]
desktop = ["webbrowser", "opener", "is_executable"]
previews = []
previews-image = ["image", "webp"]
extractors-web = ["webpage"]
extractors-audio = ["id3"]

View File

@ -4,22 +4,59 @@ use crate::{
database::{entry::Entry, UpEndConnection},
util::jobs::{Job, JobContainer, State},
};
use actix_web::web;
use anyhow::{anyhow, Result};
use async_trait::async_trait;
use std::sync::{Arc, Mutex, RwLock};
use webpage::{Webpage, WebpageOptions};
use std::sync::{Arc, RwLock};
pub struct ID3Extractor;
#[async_trait]
impl Extractor for ID3Extractor {
async fn get(
fn get(
&self,
address: Address,
connection: Arc<Mutex<UpEndConnection>>,
address: &Address,
connection: &UpEndConnection,
job_container: Arc<RwLock<JobContainer>>,
) -> Result<Vec<Entry>> {
todo!();
if let Address::Hash(hash) = address {
let files = connection.retrieve_file(hash)?;
if let Some(file) = files.get(0) {
let job_id = job_container
.write()
.unwrap()
.add_job(Job::new(
None,
&format!(
"Getting ID3 info from {:?}",
file.path.components().last().unwrap()
),
))
.unwrap();
let tags = id3::Tag::read_from_path(&file.path)?;
let result: Vec<Entry> = tags
.frames()
.filter_map(|frame| match frame.content() {
id3::Content::Text(text) => Some(Entry {
entity: address.clone(),
attribute: format!("ID3_{}", frame.id()),
value: text.clone().into(),
}),
_ => None,
})
.collect();
let _ = job_container
.write()
.unwrap()
.update_state(&job_id, State::Done);
Ok(result)
} else {
Err(anyhow!("Couldn't find file for {hash:?}!"))
}
} else {
Ok(vec![])
}
}
}

View File

@ -9,10 +9,14 @@ use std::sync::{Arc, RwLock};
#[cfg(feature = "extractors-web")]
pub mod web;
#[cfg(feature = "extractors-audio")]
pub mod audio;
pub trait Extractor {
fn get(
&self,
address: &Address,
connection: &UpEndConnection,
job_container: Arc<RwLock<JobContainer>>,
) -> Result<Vec<Entry>>;
@ -25,18 +29,19 @@ pub trait Extractor {
address: &Address,
connection: &UpEndConnection,
job_container: Arc<RwLock<JobContainer>>,
) -> Result<()> {
) -> Result<usize> {
if self.is_needed(address, connection)? {
let entries = self.get(address, job_container)?;
let entries = self.get(address, connection, job_container)?;
connection.transaction(|| {
let len = entries.len();
for entry in entries {
connection.insert_entry(entry)?;
}
Ok(())
Ok(len)
})
} else {
Ok(())
Ok(0)
}
}
}
}

View File

@ -1,7 +1,7 @@
use super::Extractor;
use crate::{
addressing::Address,
database::entry::Entry,
database::{entry::Entry, UpEndConnection},
util::jobs::{Job, JobContainer, State},
};
use anyhow::anyhow;
@ -15,6 +15,7 @@ impl Extractor for WebExtractor {
fn get(
&self,
address: &Address,
_: &UpEndConnection,
job_container: Arc<RwLock<JobContainer>>,
) -> anyhow::Result<Vec<Entry>> {
if let Address::Url(url) = address {