138 lines
3.5 KiB
Rust
138 lines
3.5 KiB
Rust
use std::{path::PathBuf, process::Stdio};
|
|
|
|
// yt metadata
|
|
pub fn get_youtube_metadata(path: &PathBuf) -> Option<YouTubeMeta> {
|
|
let cmd = std::process::Command::new("mkvextract")
|
|
.arg("-q")
|
|
.arg("attachments")
|
|
.arg(path.to_str().unwrap())
|
|
.arg("1:/proc/self/fd/1")
|
|
.stdin(Stdio::piped())
|
|
.stdout(Stdio::piped())
|
|
.stderr(Stdio::piped())
|
|
.spawn()
|
|
.unwrap();
|
|
|
|
let out = cmd.wait_with_output().unwrap();
|
|
|
|
let stdout = String::from_utf8_lossy(&out.stdout).to_string();
|
|
//let stderr = String::from_utf8_lossy(&out.stderr).to_string();
|
|
|
|
// println!("path {path:?} -- stdout {stdout} -- stderr {stderr}");
|
|
|
|
let val = serde_json::from_str(&stdout).ok()?;
|
|
log::info!("Extracted YouTube Metadata from {path:?}");
|
|
Some(YouTubeMeta { inner: val })
|
|
}
|
|
|
|
pub struct YouTubeMeta {
|
|
inner: serde_json::Value,
|
|
}
|
|
|
|
impl YouTubeMeta {
|
|
pub fn title(&self) -> String {
|
|
self.inner
|
|
.as_object()
|
|
.unwrap()
|
|
.get("title")
|
|
.unwrap()
|
|
.as_str()
|
|
.unwrap()
|
|
.to_owned()
|
|
}
|
|
|
|
pub fn youtube_id(&self) -> Option<String> {
|
|
self.inner
|
|
.as_object()
|
|
.unwrap()
|
|
.get("id")
|
|
.unwrap()
|
|
.as_str()
|
|
.map(std::borrow::ToOwned::to_owned)
|
|
}
|
|
|
|
pub fn description(&self) -> Option<String> {
|
|
self.inner
|
|
.as_object()
|
|
.unwrap()
|
|
.get("description")
|
|
.unwrap()
|
|
.as_str()
|
|
.map(std::borrow::ToOwned::to_owned)
|
|
}
|
|
|
|
pub fn uploader_name(&self) -> Option<String> {
|
|
self.inner
|
|
.as_object()
|
|
.unwrap()
|
|
.get("uploader")
|
|
.unwrap()
|
|
.as_str()
|
|
.map(std::borrow::ToOwned::to_owned)
|
|
}
|
|
|
|
pub fn uploader_id(&self) -> Option<String> {
|
|
self.inner
|
|
.as_object()
|
|
.unwrap()
|
|
.get("channel_id")
|
|
.unwrap()
|
|
.as_str()
|
|
.map(std::borrow::ToOwned::to_owned)
|
|
}
|
|
|
|
pub fn duration(&self) -> Option<i64> {
|
|
self.inner
|
|
.as_object()
|
|
.unwrap()
|
|
.get("duration")
|
|
.unwrap()
|
|
.as_i64()
|
|
.map(|x| x.to_owned())
|
|
}
|
|
|
|
pub fn views(&self) -> Option<i64> {
|
|
self.inner
|
|
.as_object()
|
|
.unwrap()
|
|
.get("view_count")
|
|
.unwrap()
|
|
.as_i64()
|
|
.map(|x| x.to_owned())
|
|
}
|
|
|
|
pub fn categories(&self) -> Option<Vec<String>> {
|
|
self.inner
|
|
.as_object()
|
|
.unwrap()
|
|
.get("categories")
|
|
.unwrap_or(&serde_json::json!(Vec::<&str>::new()))
|
|
.as_array()
|
|
.unwrap()
|
|
.iter()
|
|
.map(|x| x.as_str().map(std::borrow::ToOwned::to_owned))
|
|
.collect()
|
|
}
|
|
|
|
pub fn tags(&self) -> Option<Vec<String>> {
|
|
if let Some(tags) = self.inner.as_object().unwrap().get("tags") {
|
|
return tags
|
|
.as_array()
|
|
.unwrap()
|
|
.iter()
|
|
.map(|x| x.as_str().map(std::borrow::ToOwned::to_owned))
|
|
.collect();
|
|
}
|
|
None
|
|
}
|
|
|
|
pub fn upload_date(&self) -> Option<chrono::NaiveDate> {
|
|
self.inner
|
|
.as_object()
|
|
.unwrap()
|
|
.get("upload_date")
|
|
.unwrap()
|
|
.as_str()
|
|
.map(|x| chrono::NaiveDate::parse_from_str(x, "%Y%m%d").unwrap())
|
|
}
|
|
}
|