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
|
/Assets-main
|
||||||
/avatars
|
/avatars
|
||||||
/logs
|
/logs
|
||||||
|
/assets
|
||||||
output.log
|
output.log
|
||||||
docker-compose.yml
|
docker-compose.yml
|
||||||
Config.toml
|
Config.toml
|
||||||
|
|
|
||||||
24
Cargo.lock
generated
24
Cargo.lock
generated
|
|
@ -864,6 +864,7 @@ checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"hashbrown 0.14.5",
|
"hashbrown 0.14.5",
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1486,6 +1487,15 @@ version = "1.0.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
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]]
|
[[package]]
|
||||||
name = "schannel"
|
name = "schannel"
|
||||||
version = "0.1.24"
|
version = "0.1.24"
|
||||||
|
|
@ -1503,7 +1513,7 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sculptor"
|
name = "sculptor"
|
||||||
version = "0.3.1"
|
version = "0.4.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"axum",
|
"axum",
|
||||||
|
|
@ -1513,6 +1523,7 @@ dependencies = [
|
||||||
"dashmap",
|
"dashmap",
|
||||||
"dotenvy",
|
"dotenvy",
|
||||||
"hex",
|
"hex",
|
||||||
|
"indexmap 2.5.0",
|
||||||
"rand",
|
"rand",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"ring",
|
"ring",
|
||||||
|
|
@ -1528,6 +1539,7 @@ dependencies = [
|
||||||
"tracing-panic",
|
"tracing-panic",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
"uuid",
|
"uuid",
|
||||||
|
"walkdir",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -2243,6 +2255,16 @@ version = "0.9.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
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]]
|
[[package]]
|
||||||
name = "want"
|
name = "want"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
[package]
|
[package]
|
||||||
name = "sculptor"
|
name = "sculptor"
|
||||||
authors = ["Shiroyashik <shiroyashik@shsr.ru>"]
|
authors = ["Shiroyashik <shiroyashik@shsr.ru>"]
|
||||||
version = "0.3.1"
|
version = "0.4.0-dev"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
|
|
@ -28,6 +28,7 @@ base64 = "0.22.1"
|
||||||
reqwest = { version = "0.12.6", features = ["json"] }
|
reqwest = { version = "0.12.6", features = ["json"] }
|
||||||
dotenvy = "0.15.7"
|
dotenvy = "0.15.7"
|
||||||
semver = "1.0.23"
|
semver = "1.0.23"
|
||||||
|
walkdir = "2.5.0"
|
||||||
|
|
||||||
# Crypto
|
# Crypto
|
||||||
ring = "0.17.8"
|
ring = "0.17.8"
|
||||||
|
|
@ -37,6 +38,7 @@ rand = "0.8.5"
|
||||||
axum = { version = "0.7.5", features = ["ws", "macros", "http2"] }
|
axum = { version = "0.7.5", features = ["ws", "macros", "http2"] }
|
||||||
tower-http = { version = "0.5.2", features = ["trace"] }
|
tower-http = { version = "0.5.2", features = ["trace"] }
|
||||||
tokio = { version = "1.37.0", features = ["full"] }
|
tokio = { version = "1.37.0", features = ["full"] }
|
||||||
|
indexmap = { version = "2.5.0", features = ["serde"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
cross = "0.2.5"
|
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 auth;
|
||||||
pub mod profile;
|
pub mod profile;
|
||||||
pub mod info;
|
pub mod info;
|
||||||
|
pub mod assets;
|
||||||
|
|
||||||
pub use websocket::handler as ws;
|
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
|
// API
|
||||||
mod api;
|
mod api;
|
||||||
use 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::{},
|
// v1::{},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -84,12 +84,12 @@ async fn main() -> Result<()> {
|
||||||
.with(terminal_layer)
|
.with(terminal_layer)
|
||||||
.init();
|
.init();
|
||||||
|
|
||||||
std::panic::set_hook(Box::new(panic_hook));
|
// std::panic::set_hook(Box::new(panic_hook));
|
||||||
// let prev_hook = std::panic::take_hook();
|
let prev_hook = std::panic::take_hook();
|
||||||
// std::panic::set_hook(Box::new(move |panic_info| {
|
std::panic::set_hook(Box::new(move |panic_info| {
|
||||||
// panic_hook(panic_info);
|
panic_hook(panic_info);
|
||||||
// prev_hook(panic_info);
|
prev_hook(panic_info);
|
||||||
// }));
|
}));
|
||||||
|
|
||||||
info!("The Sculptor v{}{}", SCULPTOR_VERSION, check_updates(REPOSITORY, &SCULPTOR_VERSION).await?);
|
info!("The Sculptor v{}{}", SCULPTOR_VERSION, check_updates(REPOSITORY, &SCULPTOR_VERSION).await?);
|
||||||
|
|
||||||
|
|
@ -141,6 +141,7 @@ async fn main() -> Result<()> {
|
||||||
|
|
||||||
let api = Router::new()
|
let api = Router::new()
|
||||||
.nest("//auth", api_auth::router()) // => /api//auth ¯\_(ツ)_/¯
|
.nest("//auth", api_auth::router()) // => /api//auth ¯\_(ツ)_/¯
|
||||||
|
.nest("//assets", api_assets::router())
|
||||||
.nest("/v1", api::v1::router())
|
.nest("/v1", api::v1::router())
|
||||||
.route("/limits", get(api_info::limits))
|
.route("/limits", get(api_info::limits))
|
||||||
.route("/version", get(api_info::version))
|
.route("/version", get(api_info::version))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue