mirror of
https://github.com/shiroyashik/sculptor.git
synced 2025-12-06 04:51:13 +03:00
The Assets update is now working properly on Linux
Also added a new Workflow and disabled the Rust workflow. Redesigned Dockerfile
This commit is contained in:
parent
f0599aec9e
commit
0103c31d69
13 changed files with 163 additions and 80 deletions
41
.github/workflows/dev-release.yml
vendored
Normal file
41
.github/workflows/dev-release.yml
vendored
Normal file
|
|
@ -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
|
||||
6
.github/workflows/release.yml
vendored
6
.github/workflows/release.yml
vendored
|
|
@ -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 .
|
||||
12
.github/workflows/rust.yml
vendored
12
.github/workflows/rust.yml
vendored
|
|
@ -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
|
||||
|
|
|
|||
49
Cargo.lock
generated
49
Cargo.lock
generated
|
|
@ -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",
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
33
Dockerfile
33
Dockerfile
|
|
@ -1,21 +1,36 @@
|
|||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<AppState> {
|
||||
Router::new()
|
||||
|
|
@ -17,7 +17,7 @@ pub fn router() -> Router<AppState> {
|
|||
}
|
||||
|
||||
async fn versions() -> ApiResult<Json<Value>> {
|
||||
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<String>) -> ApiResult<Json<IndexMap<String,
|
|||
}
|
||||
|
||||
async fn download(Path((version, path)): Path<(String, String)>) -> ApiResult<Vec<u8>> {
|
||||
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<Ve
|
|||
|
||||
async fn index_assets(version: &str) -> anyhow::Result<IndexMap<String, Value>> {
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -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<Uuid>) -> ApiResult<Vec<u8>> {
|
||||
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<AppState>) -
|
|||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,6 +77,8 @@ async fn handle_socket(mut socket: WebSocket, state: AppState) {
|
|||
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,
|
||||
Err(e) => {
|
||||
|
|
|
|||
|
|
@ -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<Uuid>,
|
||||
|
|
@ -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(_) => {
|
||||
|
|
|
|||
38
src/main.rs
38
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<RwLock<Option<FiguraVersions>>>,
|
||||
}
|
||||
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -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<String> {
|
||||
|
|
@ -157,19 +157,22 @@ pub async fn is_assets_outdated(last_sha: &str) -> anyhow::Result<bool> {
|
|||
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:?}"));
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue