1
Fork 0
mirror of https://github.com/thegeneralist01/archivr synced 2026-05-30 08:36:47 +02:00

feat: add archiving of platform media files (#1)

* chore: specify non-ignored `.md` files

* refactor: rename youtube downloader to ytdlp

More generic name since yt-dlp supports many sites beyond YouTube.

* feat: add local file downloader

Supports file:// URLs for archiving local files.

* deps: add regex crate for URL pattern matching

* feat: expand source detection with granular YouTube types

- Split Source::YouTube into YouTubeVideo, YouTubePlaylist, YouTubeChannel
- Add Source::X for Twitter/X posts
- Add Source::Local for file:// URLs
- Add regex-based URL pattern matching for YouTube URLs
- Add shorthand schemes (yt:video/ID, youtube:playlist/ID, etc.)
- Add comprehensive tests for all URL patterns

* docs: update README milestones

Mark YouTube videos, Twitter videos, and local files as done.

* chore: update flake.lock

* feat: add shorthand schemes for X/Twitter media

* chore: move docs into docs dir

* Remove temp file using timestamp path

Delete the temp entry at store_path/temp/<timestamp> in both
the hash-exists and success paths. Stop constructing the full filename
with extension and remove the early process::exit to de-duplicate
cleanup.

* Add Nix caches and default flake package

* Add social platform source detection and update milestones

* Tighten social URL matching to avoid false positives

* Mark media archiving milestone complete
This commit is contained in:
TheGeneralist 2026-03-31 12:39:35 +02:00 committed by GitHub
parent 553cca99ca
commit 2d59ab0af5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 616 additions and 74 deletions

28
src/downloader/local.rs Normal file
View file

@ -0,0 +1,28 @@
use anyhow::{Context, Result, bail};
use std::{path::Path, process::Command};
use crate::hash::hash_file;
pub fn save(path: String, store_path: &Path, timestamp: &String) -> Result<String> {
println!("Saving path: {path}");
let temp_dir = store_path.join("temp").join(timestamp);
std::fs::create_dir_all(&temp_dir)?;
let in_file = Path::new(path.trim_start_matches("file://"));
let extension = in_file
.extension()
.map_or(String::new(), |ext| format!(".{}", ext.to_string_lossy()));
let out_file = temp_dir.join(format!("{timestamp}{extension}"));
let mut binding = Command::new("cp");
let cmd = binding.arg(in_file).arg(&out_file);
let out = cmd.output().with_context(|| "failed to spawn cp process")?;
if !out.status.success() {
let stderr = String::from_utf8_lossy(&out.stderr);
bail!("yt-dlp failed: {stderr}");
}
hash_file(&out_file)
}