rootspring revised this gist . Go to revision
1 file changed, 56 insertions
assetcleaner.rs(file created)
@@ -0,0 +1,56 @@ | |||
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 | + | } |
Newer
Older