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:
Shiroyasha 2024-09-21 15:37:16 +03:00
parent f0599aec9e
commit 0103c31d69
Signed by: shiroyashik
GPG key ID: E4953D3940D7860A
13 changed files with 163 additions and 80 deletions

View file

@ -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 {

View file

@ -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;
}

View file

@ -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,

View file

@ -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(_) => {

View file

@ -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 {

View file

@ -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:?}"));
}