use mitra_config::Config; use crate::database::{DatabaseClient, DatabaseError}; use crate::ipfs::store as ipfs_store; use crate::media::remove_files; pub struct DeletionQueue { pub files: Vec, pub ipfs_objects: Vec, } impl DeletionQueue { pub async fn process(self, config: &Config) -> () { remove_files(self.files, &config.media_dir()); if !self.ipfs_objects.is_empty() { match &config.ipfs_api_url { Some(ipfs_api_url) => { ipfs_store::remove(ipfs_api_url, self.ipfs_objects).await .unwrap_or_else(|err| log::error!("{}", err)); }, None => { log::error!( "can not remove objects because IPFS API URL is not set: {:?}", self.ipfs_objects, ); }, } } } } pub async fn find_orphaned_files( db_client: &impl DatabaseClient, files: Vec, ) -> Result, DatabaseError> { let rows = db_client.query( " SELECT DISTINCT fname FROM unnest($1::text[]) AS fname WHERE NOT EXISTS ( SELECT 1 FROM media_attachment WHERE file_name = fname ) AND NOT EXISTS ( SELECT 1 FROM actor_profile WHERE avatar ->> 'file_name' = fname OR banner ->> 'file_name' = fname ) AND NOT EXISTS ( SELECT 1 FROM emoji WHERE image ->> 'file_name' = fname ) ", &[&files], ).await?; let orphaned_files = rows.iter() .map(|row| row.try_get("fname")) .collect::>()?; Ok(orphaned_files) } pub async fn find_orphaned_ipfs_objects( db_client: &impl DatabaseClient, ipfs_objects: Vec, ) -> Result, DatabaseError> { let rows = db_client.query( " SELECT DISTINCT cid FROM unnest($1::text[]) AS cid WHERE NOT EXISTS ( SELECT 1 FROM media_attachment WHERE ipfs_cid = cid ) AND NOT EXISTS ( SELECT 1 FROM post WHERE ipfs_cid = cid ) ", &[&ipfs_objects], ).await?; let orphaned_ipfs_objects = rows.iter() .map(|row| row.try_get("cid")) .collect::>()?; Ok(orphaned_ipfs_objects) }