From 0103c31d697d3030b19bf2eb92e2a38a95492af8 Mon Sep 17 00:00:00 2001 From: shiroyashik Date: Sat, 21 Sep 2024 15:37:16 +0300 Subject: [PATCH] The Assets update is now working properly on Linux Also added a new Workflow and disabled the Rust workflow. Redesigned Dockerfile --- .github/workflows/dev-release.yml | 41 ++++++++++++++++++++++++++ .github/workflows/release.yml | 6 +--- .github/workflows/rust.yml | 12 ++++---- Cargo.lock | 49 +++++++++++++++++++------------ Cargo.toml | 7 +++-- Dockerfile | 35 +++++++++++++++------- docker-compose.example.yml | 6 +++- src/api/figura/assets.rs | 8 ++--- src/api/figura/profile.rs | 12 ++++---- src/api/figura/websocket.rs | 2 ++ src/api/v1/avatars.rs | 8 ++--- src/main.rs | 38 +++++++++++++++--------- src/utils/check_updates.rs | 19 +++++++----- 13 files changed, 163 insertions(+), 80 deletions(-) create mode 100644 .github/workflows/dev-release.yml diff --git a/.github/workflows/dev-release.yml b/.github/workflows/dev-release.yml new file mode 100644 index 0000000..4368b9c --- /dev/null +++ b/.github/workflows/dev-release.yml @@ -0,0 +1,41 @@ +name: Push Dev + +on: + push: + branches: [ "dev" ] + +jobs: + docker: + runs-on: ubuntu-latest + steps: + # - name: Checkout code + # uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + # - name: Login to Docker Hub + # uses: docker/login-action@v3 + # with: + # username: ${{ vars.DOCKERHUB_USERNAME }} + # password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Get short SHA + id: short_sha + run: echo "::set-output name=sha::$(echo ${GITHUB_SHA} | cut -c1-7)" + + - name: Build and push + uses: docker/build-push-action@v6 + with: + push: true + # context: . + tags: ghcr.io/${{ github.repository_owner }}/sculptor:${{ steps.short_sha.outputs.sha }} + cache-from: type=registry,ref=ghcr.io/${{ github.repository_owner }}/sculptor:buildcache + cache-to: type=registry,ref=ghcr.io/${{ github.repository_owner }}/sculptor:buildcache,mode=max \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 798fc89..bf3997a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -130,10 +130,6 @@ jobs: # username: ${{ secrets.DOCKERHUB_USERNAME }} # password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Write release version to env - run: | - CURRENT_SEMVER=${GITHUB_REF_NAME} - echo "CURRENT_SEMVER=$CURRENT_SEMVER" >> $GITHUB_ENV - uses: docker/setup-buildx-action@v3 id: buildx with: @@ -142,7 +138,7 @@ jobs: run: | docker build --platform linux/amd64 \ -t ghcr.io/${{ github.repository_owner }}/sculptor:latest \ - -t ghcr.io/${{ github.repository_owner }}/sculptor:${{env.CURRENT_SEMVER}} \ + -t ghcr.io/${{ github.repository_owner }}/sculptor:${{ github.ref_name }} \ --provenance=false --sbom=false \ --push \ -f Dockerfile . \ No newline at end of file diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 000bb2c..dcacd7e 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -1,10 +1,10 @@ name: Rust -on: - push: - branches: [ "master" ] - pull_request: - branches: [ "master" ] +on: workflow_dispatch + # push: + # branches: [ "master" ] + # pull_request: + # branches: [ "master" ] env: CARGO_TERM_COLOR: always @@ -16,7 +16,9 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Build run: cargo build --verbose + - name: Run tests run: cargo test --verbose diff --git a/Cargo.lock b/Cargo.lock index a4c4652..a33164c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -109,9 +109,9 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "axum" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" +checksum = "8f43644eed690f5374f1af436ecd6aea01cd201f6fbdf0178adaf6907afb2cec" dependencies = [ "async-trait", "axum-core", @@ -139,7 +139,7 @@ dependencies = [ "sync_wrapper 1.0.1", "tokio", "tokio-tungstenite", - "tower", + "tower 0.5.1", "tower-layer", "tower-service", "tracing", @@ -147,9 +147,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" +checksum = "5e6b8ba012a258d63c9adfa28b9ddcf66149da6f986c5b5452e629d5ee64bf00" dependencies = [ "async-trait", "bytes", @@ -160,7 +160,7 @@ dependencies = [ "mime", "pin-project-lite", "rustversion", - "sync_wrapper 0.1.2", + "sync_wrapper 1.0.1", "tower-layer", "tower-service", "tracing", @@ -168,11 +168,10 @@ dependencies = [ [[package]] name = "axum-macros" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00c055ee2d014ae5981ce1016374e8213682aa14d9bf40e48ab48b5f3ef20eaa" +checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce" dependencies = [ - "heck", "proc-macro2", "quote", "syn 2.0.77", @@ -948,7 +947,7 @@ dependencies = [ "pin-project-lite", "socket2", "tokio", - "tower", + "tower 0.4.13", "tower-service", "tracing", ] @@ -1724,6 +1723,7 @@ dependencies = [ "dotenvy", "hex", "indexmap 2.5.0", + "lazy_static", "rand", "reqwest", "ring", @@ -2164,9 +2164,9 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.21.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c83b561d025642014097b66e6c1bb422783339e0909e4429cde4749d1990bc38" +checksum = "c6989540ced10490aaf14e6bad2e3d33728a2813310a0c71d1574304c49631cd" dependencies = [ "futures-util", "log", @@ -2243,20 +2243,34 @@ dependencies = [ "tokio", "tower-layer", "tower-service", +] + +[[package]] +name = "tower" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper 0.1.2", + "tokio", + "tower-layer", + "tower-service", "tracing", ] [[package]] name = "tower-http" -version = "0.5.2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" +checksum = "41515cc9e193536d93fd0dbbea0c73819c08eca76e0b30909a325c3ec90985bb" dependencies = [ "bitflags 2.6.0", "bytes", "http", "http-body", - "http-body-util", "pin-project-lite", "tower-layer", "tower-service", @@ -2368,9 +2382,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tungstenite" -version = "0.21.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ef1a641ea34f399a848dea702823bbecfb4c486f911735368f1f137cb8257e1" +checksum = "6e2e2ce1e47ed2994fd43b04c8f618008d4cabdd5ee34027cf14f9d918edd9c8" dependencies = [ "byteorder", "bytes", @@ -2381,7 +2395,6 @@ dependencies = [ "rand", "sha1", "thiserror", - "url", "utf-8", ] diff --git a/Cargo.toml b/Cargo.toml index 845ad16..6e011fc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ thiserror = "1.0.63" chrono = { version = "0.4.38", features = ["now", "serde"] } serde = { version = "1.0.201", features = ["derive"] } serde_json = "1.0.117" -toml = "0.8.13" +toml = "0.8.19" # Other dashmap = { version = "6.0.1", features = ["serde"] } @@ -35,11 +35,12 @@ ring = "0.17.8" rand = "0.8.5" # Web framework -axum = { version = "0.7.5", features = ["ws", "macros", "http2"] } -tower-http = { version = "0.5.2", features = ["trace"] } +axum = { version = "0.7.6", features = ["ws", "macros", "http2"] } +tower-http = { version = "0.6.0", features = ["trace"] } tokio = { version = "1.37.0", features = ["full"] } indexmap = { version = "2.5.0", features = ["serde"] } zip = "2.2.0" +lazy_static = "1.5.0" [dev-dependencies] cross = "0.2.5" diff --git a/Dockerfile b/Dockerfile index b6b92ee..cf23f02 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,22 +1,37 @@ -FROM rust:1.80.1-alpine3.20 as builder - +## Chef +# FROM clux/muslrust:stable AS chef +FROM rust:1.81.0-alpine3.20 as chef +USER root +RUN apk add musl-dev libressl-dev +RUN cargo install cargo-chef WORKDIR /build -RUN apk add musl-dev libressl-dev - +## Planner +FROM chef AS planner COPY Cargo.toml Cargo.lock ./ COPY src src +RUN cargo chef prepare --recipe-path recipe.json -RUN cargo build --release - -FROM alpine:3.20.0 +## Builder +FROM chef AS builder +COPY --from=planner /build/recipe.json recipe.json +# Build dependencies - this is the caching Docker layer! +RUN cargo chef cook --release --target x86_64-unknown-linux-musl --recipe-path recipe.json +# Build application +COPY Cargo.toml Cargo.lock ./ +COPY src src +RUN cargo build --release --target x86_64-unknown-linux-musl --bin sculptor +## Runtime +FROM alpine:3.20.0 AS runtime WORKDIR /app +COPY --from=builder /build/target/x86_64-unknown-linux-musl/release/sculptor /app/sculptor -COPY --from=builder /build/target/release/sculptor /app/sculptor +RUN apk add --no-cache tzdata +ENV TZ=Etc/UTC -VOLUME [ "/app/avatars" ] +VOLUME [ "/app/data" ] VOLUME [ "/app/logs" ] EXPOSE 6665/tcp -CMD ["./sculptor"] \ No newline at end of file +CMD [ "./sculptor" ] \ No newline at end of file diff --git a/docker-compose.example.yml b/docker-compose.example.yml index 9d59b6c..0963667 100644 --- a/docker-compose.example.yml +++ b/docker-compose.example.yml @@ -14,13 +14,17 @@ services: restart: unless-stopped volumes: - ./Config.toml:/app/Config.toml:ro - - ./avatars:/app/avatars + - ./data:/app/data - ./logs:/app/logs # You can specify the path to the server folder # for Sculptor to use the ban list from it # - ./minecraft-server:/app/mc environment: - RUST_LOG=info + # Set your timezone. https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + - TZ=Europe/Moscow + # ports: + # - 6665 ## Recommended for use with reverse proxy. # networks: # - traefik diff --git a/src/api/figura/assets.rs b/src/api/figura/assets.rs index 74df255..436a151 100644 --- a/src/api/figura/assets.rs +++ b/src/api/figura/assets.rs @@ -7,7 +7,7 @@ use serde_json::Value; use tokio::{fs, io::AsyncReadExt as _}; use walkdir::WalkDir; -use crate::{api::errors::internal_and_log, ApiError, ApiResult, AppState, ASSETS_ENV}; +use crate::{api::errors::internal_and_log, ApiError, ApiResult, AppState, ASSETS_VAR}; pub fn router() -> Router { Router::new() @@ -17,7 +17,7 @@ pub fn router() -> Router { } async fn versions() -> ApiResult> { - let dir_path = PathBuf::from(&std::env::var(ASSETS_ENV).unwrap()); + let dir_path = PathBuf::from(&*ASSETS_VAR); let mut directories = Vec::new(); @@ -43,7 +43,7 @@ async fn hashes(Path(version): Path) -> ApiResult) -> ApiResult> { - let mut file = if let Ok(file) = fs::File::open(format!("{}/{version}/{path}", std::env::var(ASSETS_ENV).unwrap())).await { + let mut file = if let Ok(file) = fs::File::open(format!("{}/{version}/{path}", *ASSETS_VAR)).await { file } else { return Err(ApiError::NotFound) @@ -57,7 +57,7 @@ async fn download(Path((version, path)): Path<(String, String)>) -> ApiResult anyhow::Result> { let mut map = IndexMap::new(); - let version_path = PathBuf::from(std::env::var(ASSETS_ENV).unwrap()).join(version); + let version_path = PathBuf::from(&*ASSETS_VAR).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 { diff --git a/src/api/figura/profile.rs b/src/api/figura/profile.rs index 0783fe3..3511c37 100644 --- a/src/api/figura/profile.rs +++ b/src/api/figura/profile.rs @@ -1,5 +1,3 @@ -use std::env::var; - use axum::{ body::Bytes, extract::{Path, State}, Json }; @@ -14,7 +12,7 @@ use uuid::Uuid; use crate::{ api::errors::internal_and_log, auth::Token, utils::{calculate_file_sha256, format_uuid}, - ApiError, ApiResult, AppState, AVATARS_ENV + ApiError, ApiResult, AppState, AVATARS_VAR }; use super::types::S2CMessage; @@ -26,7 +24,7 @@ pub async fn user_info( let formatted_uuid = format_uuid(&uuid); - let avatar_file = format!("{}/{}.moon", var(AVATARS_ENV).unwrap(), formatted_uuid); + let avatar_file = format!("{}/{}.moon", *AVATARS_VAR, formatted_uuid); let userinfo = if let Some(info) = state.user_manager.get_by_uuid(&uuid) { info } else { return Err(ApiError::BadRequest) // NOTE: Not Found (404) shows badge @@ -81,7 +79,7 @@ pub async fn user_info( pub async fn download_avatar(Path(uuid): Path) -> ApiResult> { let uuid = format_uuid(&uuid); tracing::info!("Requesting an avatar: {}", uuid); - let mut file = if let Ok(file) = fs::File::open(format!("{}/{}.moon", var(AVATARS_ENV).unwrap(), uuid)).await { + let mut file = if let Ok(file) = fs::File::open(format!("{}/{}.moon", *AVATARS_VAR, uuid)).await { file } else { return Err(ApiError::NotFound) @@ -104,7 +102,7 @@ pub async fn upload_avatar( user_info.uuid, user_info.username ); - let avatar_file = format!("{}/{}.moon", var(AVATARS_ENV).unwrap(), user_info.uuid); + let avatar_file = format!("{}/{}.moon", *AVATARS_VAR, user_info.uuid); let mut file = BufWriter::new(fs::File::create(&avatar_file).await.map_err(|err| internal_and_log(err))?); io::copy(&mut request_data.as_ref(), &mut file).await.map_err(|err| internal_and_log(err))?; } @@ -125,7 +123,7 @@ pub async fn delete_avatar(Token(token): Token, State(state): State) - user_info.uuid, user_info.username ); - let avatar_file = format!("{}/{}.moon", var(AVATARS_ENV).unwrap(), user_info.uuid); + let avatar_file = format!("{}/{}.moon", *AVATARS_VAR, user_info.uuid); fs::remove_file(avatar_file).await.map_err(|err| internal_and_log(err))?; send_event(&state, &user_info.uuid).await; } diff --git a/src/api/figura/websocket.rs b/src/api/figura/websocket.rs index b661b8e..1d26bb5 100644 --- a/src/api/figura/websocket.rs +++ b/src/api/figura/websocket.rs @@ -76,6 +76,8 @@ async fn handle_socket(mut socket: WebSocket, state: AppState) { // Next is the code for processing msg let msg_vec = msg.clone().into_data(); let msg_array = msg_vec.as_slice(); + + if msg_array.len() == 0 { tracing::debug!("[WebSocket{}] Deprecated len 0 msg", owner.name()); continue; }; let newmsg = match C2SMessage::try_from(msg_array) { Ok(data) => data, diff --git a/src/api/v1/avatars.rs b/src/api/v1/avatars.rs index 3f17654..e2a8707 100644 --- a/src/api/v1/avatars.rs +++ b/src/api/v1/avatars.rs @@ -1,11 +1,9 @@ -use std::env::var; - use axum::{body::Bytes, extract::{Path, State}}; use tokio::{fs, io::{self, BufWriter}}; use tracing::warn; use uuid::Uuid; -use crate::{api::figura::profile::send_event, auth::Token, ApiResult, AppState, AVATARS_ENV}; +use crate::{api::figura::profile::send_event, auth::Token, ApiResult, AppState, AVATARS_VAR}; pub async fn upload_avatar( Path(uuid): Path, @@ -22,7 +20,7 @@ pub async fn upload_avatar( uuid, ); - let avatar_file = format!("{}/{}.moon", var(AVATARS_ENV).unwrap(), &uuid); + let avatar_file = format!("{}/{}.moon", *AVATARS_VAR, &uuid); let mut file = BufWriter::new(fs::File::create(&avatar_file).await.unwrap()); io::copy(&mut request_data.as_ref(), &mut file).await.unwrap(); send_event(&state, &uuid).await; @@ -42,7 +40,7 @@ pub async fn delete_avatar( uuid, ); - let avatar_file = format!("{}/{}.moon", var(AVATARS_ENV).unwrap(), &uuid); + let avatar_file = format!("{}/{}.moon", *AVATARS_VAR, &uuid); match fs::remove_file(avatar_file).await { Ok(_) => {}, Err(_) => { diff --git a/src/main.rs b/src/main.rs index b933592..699c5b3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,10 +5,11 @@ use axum::{ use dashmap::DashMap; use tracing_panic::panic_hook; use tracing_subscriber::{fmt::{self, time::ChronoLocal}, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; -use std::{path::PathBuf, sync::Arc, env::{set_var, var}}; +use std::{path::PathBuf, sync::Arc, env::var}; use tokio::{fs, sync::{broadcast, mpsc, RwLock}, time::Instant}; use tower_http::trace::TraceLayer; use uuid::Uuid; +use lazy_static::lazy_static; // Consts mod consts; @@ -52,21 +53,30 @@ pub struct AppState { figura_versions: Arc>>, } -fn apply_default_environment() { - if var(LOGGER_ENV).is_err() { set_var(LOGGER_ENV, "info") }; - if var(CONFIG_ENV).is_err() { set_var(CONFIG_ENV, "Config.toml") }; - if var(LOGS_ENV).is_err() { set_var(LOGS_ENV, "logs") }; - if var(ASSETS_ENV).is_err() { set_var(ASSETS_ENV, "data/assets") }; - if var(AVATARS_ENV).is_err() { set_var(ASSETS_ENV, "data/avatars") }; +lazy_static! { + pub static ref LOGGER_VAR: String = { + var(LOGGER_ENV).unwrap_or(String::from("info")) + }; + pub static ref CONFIG_VAR: String = { + var(CONFIG_ENV).unwrap_or(String::from("Config.toml")) + }; + pub static ref LOGS_VAR: String = { + var(LOGS_ENV).unwrap_or(String::from("logs")) + }; + pub static ref ASSETS_VAR: String = { + var(ASSETS_ENV).unwrap_or(String::from("data/assets")) + }; + pub static ref AVATARS_VAR: String = { + var(AVATARS_ENV).unwrap_or(String::from("data/avatars")) + }; } #[tokio::main] async fn main() -> Result<()> { let _ = dotenvy::dotenv(); - apply_default_environment(); // "trace,axum=info,tower_http=info,tokio=info,tungstenite=info,tokio_tungstenite=info", - let file_appender = tracing_appender::rolling::never(&var(LOGS_ENV).unwrap(), get_log_file(&var(LOGS_ENV).unwrap())); + let file_appender = tracing_appender::rolling::never(&*LOGS_VAR, get_log_file(&*LOGS_VAR)); let timer = ChronoLocal::new(String::from("%Y-%m-%dT%H:%M:%S%.3f%:z")); let file_layer = fmt::layer() @@ -84,7 +94,7 @@ async fn main() -> Result<()> { // Combine the layers and set the global subscriber tracing_subscriber::registry() - .with(EnvFilter::from(var(LOGGER_ENV).unwrap())) + .with(EnvFilter::from(&*LOGGER_VAR)) .with(file_layer) .with(terminal_layer) .init(); @@ -100,7 +110,7 @@ async fn main() -> Result<()> { // Preparing for launch { - let path = PathBuf::from(var(AVATARS_ENV).unwrap()); + let path = PathBuf::from(&*AVATARS_VAR); if !path.exists() { fs::create_dir_all(path).await.expect("Can't create avatars folder!"); tracing::info!("Created avatars directory"); @@ -108,12 +118,12 @@ async fn main() -> Result<()> { } // Config - let config = Arc::new(RwLock::new(Config::parse(var(CONFIG_ENV).unwrap().into()))); + let config = Arc::new(RwLock::new(Config::parse(CONFIG_VAR.clone().into()))); let listen = config.read().await.listen.clone(); if config.read().await.assets_updater_enabled { // Force update assets if folder or hash file doesn't exists. - if !(PathBuf::from(var(ASSETS_ENV).unwrap()).is_dir() && get_path_to_assets_hash().is_file()) { + if !(PathBuf::from(&*ASSETS_VAR).is_dir() && get_path_to_assets_hash().is_file()) { tracing::debug!("Removing broken assets..."); remove_assets().await } @@ -153,7 +163,7 @@ async fn main() -> Result<()> { tokio::spawn(async move { loop { tokio::time::sleep(std::time::Duration::from_secs(10)).await; - let new_config = Config::parse(var(CONFIG_ENV).unwrap().into()); + let new_config = Config::parse(CONFIG_VAR.clone().into()); let mut config = config_update.write().await; if new_config != *config { diff --git a/src/utils/check_updates.rs b/src/utils/check_updates.rs index bb713ae..d1bee0f 100644 --- a/src/utils/check_updates.rs +++ b/src/utils/check_updates.rs @@ -1,4 +1,4 @@ -use std::{env::{self, var}, path::{self, PathBuf}}; +use std::path::{self, PathBuf}; use anyhow::anyhow; use reqwest::Client; @@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize}; use tokio::{fs::{self, File}, io::{AsyncReadExt as _, AsyncWriteExt as _}}; use tracing::error; -use crate::{ASSETS_ENV, FIGURA_ASSETS_ZIP_URL, FIGURA_RELEASES_URL, TIMEOUT, USER_AGENT}; +use crate::{ASSETS_VAR, FIGURA_ASSETS_ZIP_URL, FIGURA_RELEASES_URL, TIMEOUT, USER_AGENT}; #[derive(Deserialize, Debug)] struct Tag { @@ -116,7 +116,7 @@ struct Commit { } pub fn get_path_to_assets_hash() -> PathBuf { - path::PathBuf::from(&env::var(ASSETS_ENV).unwrap()).join("..").join("assets_last_commit") + path::PathBuf::from(&*ASSETS_VAR).join("..").join("assets_last_commit") } pub async fn get_commit_sha(url: &str) -> anyhow::Result { @@ -157,19 +157,22 @@ pub async fn is_assets_outdated(last_sha: &str) -> anyhow::Result { pub fn download_assets() -> anyhow::Result<()> { use std::{fs::{File, self}, io::Write as _}; - let assets_folder = var(ASSETS_ENV).unwrap(); + let assets_folder = ASSETS_VAR.clone(); // Path to save the downloaded ZIP file - let zip_file_path = path::PathBuf::from(&assets_folder).join("..").join("assets.zip"); + let mut zip_file_path = path::PathBuf::from(&*ASSETS_VAR); + zip_file_path.pop(); + let zip_file_path = zip_file_path.join("assets.zip"); // Download the ZIP file - - let response = reqwest::blocking::get(FIGURA_ASSETS_ZIP_URL)?; + let client = reqwest::blocking::Client::builder().timeout(TIMEOUT).user_agent(USER_AGENT).build().unwrap(); + let response: reqwest::blocking::Response = client.get(FIGURA_ASSETS_ZIP_URL).send()?; let bytes = response.bytes()?; // Save the downloaded ZIP file to disk let mut file = File::create(&zip_file_path)?; file.write_all(&bytes)?; + file.flush()?; // Open the downloaded ZIP file let file = File::open(&zip_file_path)?; @@ -237,6 +240,6 @@ pub async fn write_sha_to_file(sha: &str) -> anyhow::Result<()> { } pub async fn remove_assets() { - fs::remove_dir_all(&var(ASSETS_ENV).unwrap()).await.unwrap_or_else(|err| tracing::debug!("Assets dir remove failed due {err:?}")); + fs::remove_dir_all(&*ASSETS_VAR).await.unwrap_or_else(|err| tracing::debug!("Assets dir remove failed due {err:?}")); fs::remove_file(get_path_to_assets_hash()).await.unwrap_or_else(|err| tracing::debug!("Assets hash file remove failed due {err:?}")); } \ No newline at end of file