mirror of
https://github.com/shiroyashik/sculptor.git
synced 2025-12-06 04:51:13 +03:00
+ Assets support
This commit is contained in:
parent
d5433101f1
commit
7a37ce8a6b
6 changed files with 105 additions and 9 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -2,6 +2,7 @@
|
|||
/Assets-main
|
||||
/avatars
|
||||
/logs
|
||||
/assets
|
||||
output.log
|
||||
docker-compose.yml
|
||||
Config.toml
|
||||
|
|
|
|||
24
Cargo.lock
generated
24
Cargo.lock
generated
|
|
@ -864,6 +864,7 @@ checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5"
|
|||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.14.5",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1486,6 +1487,15 @@ version = "1.0.18"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "schannel"
|
||||
version = "0.1.24"
|
||||
|
|
@ -1503,7 +1513,7 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
|||
|
||||
[[package]]
|
||||
name = "sculptor"
|
||||
version = "0.3.1"
|
||||
version = "0.4.0-dev"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
|
|
@ -1513,6 +1523,7 @@ dependencies = [
|
|||
"dashmap",
|
||||
"dotenvy",
|
||||
"hex",
|
||||
"indexmap 2.5.0",
|
||||
"rand",
|
||||
"reqwest",
|
||||
"ring",
|
||||
|
|
@ -1528,6 +1539,7 @@ dependencies = [
|
|||
"tracing-panic",
|
||||
"tracing-subscriber",
|
||||
"uuid",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2243,6 +2255,16 @@ version = "0.9.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "want"
|
||||
version = "0.3.1"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
name = "sculptor"
|
||||
authors = ["Shiroyashik <shiroyashik@shsr.ru>"]
|
||||
version = "0.3.1"
|
||||
version = "0.4.0-dev"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
|
|
@ -28,6 +28,7 @@ base64 = "0.22.1"
|
|||
reqwest = { version = "0.12.6", features = ["json"] }
|
||||
dotenvy = "0.15.7"
|
||||
semver = "1.0.23"
|
||||
walkdir = "2.5.0"
|
||||
|
||||
# Crypto
|
||||
ring = "0.17.8"
|
||||
|
|
@ -37,6 +38,7 @@ rand = "0.8.5"
|
|||
axum = { version = "0.7.5", features = ["ws", "macros", "http2"] }
|
||||
tower-http = { version = "0.5.2", features = ["trace"] }
|
||||
tokio = { version = "1.37.0", features = ["full"] }
|
||||
indexmap = { version = "2.5.0", features = ["serde"] }
|
||||
|
||||
[dev-dependencies]
|
||||
cross = "0.2.5"
|
||||
|
|
|
|||
69
src/api/figura/assets.rs
Normal file
69
src/api/figura/assets.rs
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use axum::{extract::Path, routing::get, Json, Router};
|
||||
use indexmap::IndexMap;
|
||||
use ring::digest::{digest, SHA256};
|
||||
use serde_json::{json, Value};
|
||||
use tokio::{fs, io::AsyncReadExt as _};
|
||||
use walkdir::WalkDir;
|
||||
|
||||
use crate::{api::errors::internal_and_log, ApiError, ApiResult, AppState};
|
||||
|
||||
pub fn router() -> Router<AppState> {
|
||||
Router::new()
|
||||
.route("/", get(versions))
|
||||
.route("/v1", get(v1))
|
||||
.route("/v2", get(v2))
|
||||
.route("/*path", get(download))
|
||||
}
|
||||
|
||||
async fn versions() -> Json<Value> {
|
||||
Json(json!(["v1", "v2"]))
|
||||
}
|
||||
|
||||
async fn v1() -> ApiResult<Json<IndexMap<String, Value>>> {
|
||||
let map = index_assets("v1").await.map_err(|err| internal_and_log(err))?;
|
||||
Ok(Json(map))
|
||||
}
|
||||
|
||||
async fn v2() -> ApiResult<Json<IndexMap<String, Value>>> {
|
||||
let map = index_assets("v2").await.map_err(|err| internal_and_log(err))?;
|
||||
Ok(Json(map))
|
||||
}
|
||||
|
||||
async fn download(Path(path): Path<String>) -> ApiResult<Vec<u8>> {
|
||||
let mut file = if let Ok(file) = fs::File::open(format!("assets/{path}")).await {
|
||||
file
|
||||
} else {
|
||||
return Err(ApiError::NotFound)
|
||||
};
|
||||
let mut buffer = Vec::new();
|
||||
file.read_to_end(&mut buffer).await.map_err(|err| internal_and_log(err))?;
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
// non web
|
||||
|
||||
async fn index_assets(version: &str) -> anyhow::Result<IndexMap<String, Value>> {
|
||||
let mut map = IndexMap::new();
|
||||
let version_path = PathBuf::from("assets/").join(version);
|
||||
|
||||
for entry in WalkDir::new(version_path.clone()).into_iter().filter_map(|e| e.ok()) {
|
||||
let data = match fs::read(entry.path()).await {
|
||||
Ok(d) => d,
|
||||
Err(_) => continue
|
||||
};
|
||||
|
||||
let path: String;
|
||||
|
||||
if cfg!(windows) {
|
||||
path = entry.path().strip_prefix(version_path.clone())?.to_string_lossy().to_string().replace("\\", "/");
|
||||
} else {
|
||||
path = entry.path().strip_prefix(version_path.clone())?.to_string_lossy().to_string();
|
||||
}
|
||||
|
||||
map.insert(path, Value::from(hex::encode(digest(&SHA256, &data).as_ref())));
|
||||
}
|
||||
|
||||
Ok(map)
|
||||
}
|
||||
|
|
@ -3,5 +3,6 @@ mod websocket;
|
|||
pub mod auth;
|
||||
pub mod profile;
|
||||
pub mod info;
|
||||
pub mod assets;
|
||||
|
||||
pub use websocket::handler as ws;
|
||||
15
src/main.rs
15
src/main.rs
|
|
@ -21,7 +21,7 @@ pub use api::errors::{ApiResult, ApiError};
|
|||
// API
|
||||
mod api;
|
||||
use api::{
|
||||
figura::{ws, info as api_info, profile as api_profile, auth as api_auth},
|
||||
figura::{ws, info as api_info, profile as api_profile, auth as api_auth, assets as api_assets},
|
||||
// v1::{},
|
||||
};
|
||||
|
||||
|
|
@ -84,12 +84,12 @@ async fn main() -> Result<()> {
|
|||
.with(terminal_layer)
|
||||
.init();
|
||||
|
||||
std::panic::set_hook(Box::new(panic_hook));
|
||||
// let prev_hook = std::panic::take_hook();
|
||||
// std::panic::set_hook(Box::new(move |panic_info| {
|
||||
// panic_hook(panic_info);
|
||||
// prev_hook(panic_info);
|
||||
// }));
|
||||
// std::panic::set_hook(Box::new(panic_hook));
|
||||
let prev_hook = std::panic::take_hook();
|
||||
std::panic::set_hook(Box::new(move |panic_info| {
|
||||
panic_hook(panic_info);
|
||||
prev_hook(panic_info);
|
||||
}));
|
||||
|
||||
info!("The Sculptor v{}{}", SCULPTOR_VERSION, check_updates(REPOSITORY, &SCULPTOR_VERSION).await?);
|
||||
|
||||
|
|
@ -141,6 +141,7 @@ async fn main() -> Result<()> {
|
|||
|
||||
let api = Router::new()
|
||||
.nest("//auth", api_auth::router()) // => /api//auth ¯\_(ツ)_/¯
|
||||
.nest("//assets", api_assets::router())
|
||||
.nest("/v1", api::v1::router())
|
||||
.route("/limits", get(api_info::limits))
|
||||
.route("/version", get(api_info::version))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue