feat: serve legacy void.cat uploads
This commit is contained in:
parent
961a6910ac
commit
b0571efcb3
@ -29,3 +29,6 @@ vit_model:
|
|||||||
|
|
||||||
# Support legacy void
|
# Support legacy void
|
||||||
# void_cat_database: "postgres://postgres:postgres@localhost:41911/void"
|
# void_cat_database: "postgres://postgres:postgres@localhost:41911/void"
|
||||||
|
|
||||||
|
# Legacy file path for void.cat uploads
|
||||||
|
# void_cat_files: "/my/void.cat/data"
|
@ -6,7 +6,8 @@ use nostr::bitcoin::base58;
|
|||||||
use route96::db::{Database, FileUpload};
|
use route96::db::{Database, FileUpload};
|
||||||
use route96::filesystem::FileStore;
|
use route96::filesystem::FileStore;
|
||||||
use route96::settings::Settings;
|
use route96::settings::Settings;
|
||||||
use route96::void_db::{VoidCatDb, VoidFile};
|
use route96::void_db::VoidCatDb;
|
||||||
|
use route96::void_file::VoidFile;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use tokio::io::{AsyncWriteExt, BufWriter};
|
use tokio::io::{AsyncWriteExt, BufWriter};
|
||||||
|
|
||||||
@ -54,7 +55,7 @@ async fn main() -> Result<(), Error> {
|
|||||||
let mut page = 0;
|
let mut page = 0;
|
||||||
loop {
|
loop {
|
||||||
let files = db_void.list_files(page).await?;
|
let files = db_void.list_files(page).await?;
|
||||||
if files.len() == 0 {
|
if files.is_empty() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
for f in files {
|
for f in files {
|
||||||
@ -73,7 +74,7 @@ async fn main() -> Result<(), Error> {
|
|||||||
let mut page = 0;
|
let mut page = 0;
|
||||||
loop {
|
loop {
|
||||||
let files = db_void.list_files(page).await?;
|
let files = db_void.list_files(page).await?;
|
||||||
if files.len() == 0 {
|
if files.is_empty() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
for f in files {
|
for f in files {
|
||||||
@ -99,7 +100,9 @@ async fn migrate_file(
|
|||||||
let id_vec = hex::decode(&f.digest)?;
|
let id_vec = hex::decode(&f.digest)?;
|
||||||
|
|
||||||
// copy file
|
// copy file
|
||||||
let src_path = PathBuf::new().join(&args.data_path).join(f.map_to_path());
|
let src_path = PathBuf::new()
|
||||||
|
.join(&args.data_path)
|
||||||
|
.join(VoidFile::map_to_path(&f.id));
|
||||||
let dst_path = fs.map_path(&id_vec);
|
let dst_path = fs.map_path(&id_vec);
|
||||||
if src_path.exists() && !dst_path.exists() {
|
if src_path.exists() && !dst_path.exists() {
|
||||||
info!(
|
info!(
|
||||||
|
@ -10,4 +10,5 @@ pub mod routes;
|
|||||||
pub mod settings;
|
pub mod settings;
|
||||||
#[cfg(any(feature = "void-cat-redirects", feature = "bin-void-cat-migrate"))]
|
#[cfg(any(feature = "void-cat-redirects", feature = "bin-void-cat-migrate"))]
|
||||||
pub mod void_db;
|
pub mod void_db;
|
||||||
|
pub mod void_file;
|
||||||
pub mod webhook;
|
pub mod webhook;
|
||||||
|
@ -6,16 +6,13 @@ pub use crate::routes::blossom::blossom_routes;
|
|||||||
#[cfg(feature = "nip96")]
|
#[cfg(feature = "nip96")]
|
||||||
pub use crate::routes::nip96::nip96_routes;
|
pub use crate::routes::nip96::nip96_routes;
|
||||||
use crate::settings::Settings;
|
use crate::settings::Settings;
|
||||||
#[cfg(feature = "void-cat-redirects")]
|
use crate::void_file::VoidFile;
|
||||||
use crate::void_db::VoidCatDb;
|
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
use http_range_header::{parse_range_header, EndPosition, StartPosition};
|
use http_range_header::{parse_range_header, EndPosition, StartPosition};
|
||||||
use log::warn;
|
use log::warn;
|
||||||
use nostr::Event;
|
use nostr::Event;
|
||||||
use rocket::fs::NamedFile;
|
use rocket::fs::NamedFile;
|
||||||
use rocket::http::{ContentType, Header, Status};
|
use rocket::http::{ContentType, Header, Status};
|
||||||
#[cfg(feature = "void-cat-redirects")]
|
|
||||||
use rocket::response::Redirect;
|
|
||||||
use rocket::response::Responder;
|
use rocket::response::Responder;
|
||||||
use rocket::serde::Serialize;
|
use rocket::serde::Serialize;
|
||||||
use rocket::{Request, Response, State};
|
use rocket::{Request, Response, State};
|
||||||
@ -355,25 +352,24 @@ pub async fn head_blob(sha256: &str, fs: &State<FileStore>) -> Status {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "void-cat-redirects")]
|
/// Legacy URL redirect for void.cat uploads
|
||||||
#[rocket::get("/d/<id>")]
|
#[rocket::get("/d/<id>")]
|
||||||
pub async fn void_cat_redirect(
|
pub async fn void_cat_redirect(id: &str, settings: &State<Settings>) -> Option<NamedFile> {
|
||||||
id: &str,
|
|
||||||
settings: &State<Settings>,
|
|
||||||
vdb: &State<VoidCatDb>,
|
|
||||||
) -> Option<Redirect> {
|
|
||||||
let id = if id.contains(".") {
|
let id = if id.contains(".") {
|
||||||
id.split('.').next().unwrap()
|
id.split('.').next().unwrap()
|
||||||
} else {
|
} else {
|
||||||
id
|
id
|
||||||
};
|
};
|
||||||
|
if let Some(base) = &settings.void_cat_files {
|
||||||
let uuid =
|
let uuid =
|
||||||
uuid::Uuid::from_slice_le(nostr::bitcoin::base58::decode(id).unwrap().as_slice()).unwrap();
|
uuid::Uuid::from_slice_le(nostr::bitcoin::base58::decode(id).unwrap().as_slice())
|
||||||
if let Ok(Some(d)) = vdb.get_digest(&uuid).await {
|
.unwrap();
|
||||||
Some(Redirect::permanent(format!(
|
let f = base.join(VoidFile::map_to_path(&uuid));
|
||||||
"{}/{}",
|
if let Ok(f) = NamedFile::open(f).await {
|
||||||
&settings.public_url, &d
|
Some(f)
|
||||||
)))
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,9 @@ pub struct Settings {
|
|||||||
|
|
||||||
#[cfg(feature = "void-cat-redirects")]
|
#[cfg(feature = "void-cat-redirects")]
|
||||||
pub void_cat_database: Option<String>,
|
pub void_cat_database: Option<String>,
|
||||||
|
|
||||||
|
/// Path to void.cat uploads (files-v2)
|
||||||
|
pub void_cat_files: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
@ -1,42 +1,7 @@
|
|||||||
use chrono::{DateTime, Utc};
|
use crate::void_file::VoidFile;
|
||||||
use sqlx::FromRow;
|
|
||||||
use sqlx_postgres::{PgPool, PgPoolOptions};
|
use sqlx_postgres::{PgPool, PgPoolOptions};
|
||||||
use std::path::PathBuf;
|
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
#[derive(FromRow)]
|
|
||||||
pub struct VoidFile {
|
|
||||||
#[sqlx(rename = "Id")]
|
|
||||||
pub id: Uuid,
|
|
||||||
#[sqlx(rename = "Name")]
|
|
||||||
pub name: Option<String>,
|
|
||||||
#[sqlx(rename = "Size")]
|
|
||||||
pub size: i64,
|
|
||||||
#[sqlx(rename = "Uploaded")]
|
|
||||||
pub uploaded: DateTime<Utc>,
|
|
||||||
#[sqlx(rename = "Description")]
|
|
||||||
pub description: Option<String>,
|
|
||||||
#[sqlx(rename = "MimeType")]
|
|
||||||
pub mime_type: String,
|
|
||||||
#[sqlx(rename = "Digest")]
|
|
||||||
pub digest: String,
|
|
||||||
#[sqlx(rename = "MediaDimensions")]
|
|
||||||
pub media_dimensions: Option<String>,
|
|
||||||
#[sqlx(rename = "Email")]
|
|
||||||
pub email: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VoidFile {
|
|
||||||
pub fn map_to_path(&self) -> PathBuf {
|
|
||||||
let id_str = self.id.as_hyphenated().to_string();
|
|
||||||
PathBuf::new()
|
|
||||||
.join("files-v2/")
|
|
||||||
.join(&id_str[..2])
|
|
||||||
.join(&id_str[2..4])
|
|
||||||
.join(&id_str)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct VoidCatDb {
|
pub struct VoidCatDb {
|
||||||
pub pool: PgPool,
|
pub pool: PgPool,
|
||||||
}
|
}
|
||||||
|
37
src/void_file.rs
Normal file
37
src/void_file.rs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use sqlx::FromRow;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
#[derive(FromRow)]
|
||||||
|
pub struct VoidFile {
|
||||||
|
#[sqlx(rename = "Id")]
|
||||||
|
pub id: Uuid,
|
||||||
|
#[sqlx(rename = "Name")]
|
||||||
|
pub name: Option<String>,
|
||||||
|
#[sqlx(rename = "Size")]
|
||||||
|
pub size: i64,
|
||||||
|
#[sqlx(rename = "Uploaded")]
|
||||||
|
pub uploaded: DateTime<Utc>,
|
||||||
|
#[sqlx(rename = "Description")]
|
||||||
|
pub description: Option<String>,
|
||||||
|
#[sqlx(rename = "MimeType")]
|
||||||
|
pub mime_type: String,
|
||||||
|
#[sqlx(rename = "Digest")]
|
||||||
|
pub digest: String,
|
||||||
|
#[sqlx(rename = "MediaDimensions")]
|
||||||
|
pub media_dimensions: Option<String>,
|
||||||
|
#[sqlx(rename = "Email")]
|
||||||
|
pub email: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VoidFile {
|
||||||
|
pub fn map_to_path(id: &Uuid) -> PathBuf {
|
||||||
|
let id_str = id.as_hyphenated().to_string();
|
||||||
|
PathBuf::new()
|
||||||
|
.join("files-v2/")
|
||||||
|
.join(&id_str[..2])
|
||||||
|
.join(&id_str[2..4])
|
||||||
|
.join(&id_str)
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user