assetcleaner.rs
· 2.0 KiB · Rust
Bruto
use log::{info, warn, error};
pub async fn asset_cleaner(pool: &sqlx::PgPool) -> Result<(), crate::Error> {
let type_id_map = indexmap::indexmap! {
"bots" => "bot_id",
"servers" => "server_id",
"teams" => "id",
"partners" => "id",
};
let assets = ["avatars", "banners"];
let Some(cdn_path) = crate::config::CONFIG.panel.cdn_scopes.get(&crate::config::CONFIG.panel.main_scope) else {
return Err("No CDN scope for main scope".into());
};
// Enumerate over every possbility
for asset in assets {
for (entity_type, id_column) in &type_id_map {
let entity_type_dir = format!("{}/{}/{}", cdn_path.path, asset, entity_type);
if let Err(e) = std::fs::metadata(&entity_type_dir) {
if e.kind() != std::io::ErrorKind::NotFound {
error!("Could not validate '{}': {}", entity_type_dir, e);
}
continue;
}
info!("Validating '{}' for entity type '{}'", asset, entity_type);
let dir = std::fs::read_dir(&entity_type_dir)?;
for entry in dir {
let entry = entry?;
let file_name = entry.file_name().into_string().unwrap();
let file_path = entry.path();
let Some(id) = file_name.split('.').next() else {
warn!("Invalid file name: {}", file_name);
std::fs::remove_file(&file_path)?;
continue;
};
let query = format!("SELECT {}::text FROM {} WHERE {}::text = $1::text", id_column, entity_type, id_column);
let id: Option<String> = sqlx::query_scalar(&query).bind(id).fetch_optional(pool).await?;
if id.is_none() {
warn!("Found orphaned file: {}", file_path.display());
std::fs::remove_file(&file_path)?;
}
}
}
}
Ok(())
}
1 | use log::{info, warn, error}; |
2 | |
3 | pub async fn asset_cleaner(pool: &sqlx::PgPool) -> Result<(), crate::Error> { |
4 | let type_id_map = indexmap::indexmap! { |
5 | "bots" => "bot_id", |
6 | "servers" => "server_id", |
7 | "teams" => "id", |
8 | "partners" => "id", |
9 | }; |
10 | |
11 | let assets = ["avatars", "banners"]; |
12 | |
13 | let Some(cdn_path) = crate::config::CONFIG.panel.cdn_scopes.get(&crate::config::CONFIG.panel.main_scope) else { |
14 | return Err("No CDN scope for main scope".into()); |
15 | }; |
16 | |
17 | // Enumerate over every possbility |
18 | for asset in assets { |
19 | for (entity_type, id_column) in &type_id_map { |
20 | let entity_type_dir = format!("{}/{}/{}", cdn_path.path, asset, entity_type); |
21 | |
22 | if let Err(e) = std::fs::metadata(&entity_type_dir) { |
23 | if e.kind() != std::io::ErrorKind::NotFound { |
24 | error!("Could not validate '{}': {}", entity_type_dir, e); |
25 | } |
26 | continue; |
27 | } |
28 | |
29 | info!("Validating '{}' for entity type '{}'", asset, entity_type); |
30 | |
31 | let dir = std::fs::read_dir(&entity_type_dir)?; |
32 | |
33 | for entry in dir { |
34 | let entry = entry?; |
35 | let file_name = entry.file_name().into_string().unwrap(); |
36 | let file_path = entry.path(); |
37 | |
38 | let Some(id) = file_name.split('.').next() else { |
39 | warn!("Invalid file name: {}", file_name); |
40 | std::fs::remove_file(&file_path)?; |
41 | continue; |
42 | }; |
43 | |
44 | let query = format!("SELECT {}::text FROM {} WHERE {}::text = $1::text", id_column, entity_type, id_column); |
45 | let id: Option<String> = sqlx::query_scalar(&query).bind(id).fetch_optional(pool).await?; |
46 | |
47 | if id.is_none() { |
48 | warn!("Found orphaned file: {}", file_path.display()); |
49 | std::fs::remove_file(&file_path)?; |
50 | } |
51 | } |
52 | } |
53 | } |
54 | |
55 | Ok(()) |
56 | } |