#!/usr/bin/env python3 """ Cleanup daemon for expired files and pastes in Sharey Runs continuously and checks for expired files at regular intervals Supports both local storage and Backblaze B2 storage backends """ import os import sys import json import sqlite3 import time import signal from datetime import datetime, timezone from pathlib import Path # Add the project root to Python path project_root = Path(__file__).parent sys.path.append(str(project_root)) from src.config import config from src.storage import StorageManager from expiry_db import ExpiryDatabase # Configuration CLEANUP_INTERVAL = 60 # seconds (1 minute) CHECK_INTERVAL = 5 # seconds between startup checks # Global flag for graceful shutdown running = True def signal_handler(signum, frame): """Handle shutdown signals gracefully""" global running print(f"\n๐Ÿ›‘ Received signal {signum}, shutting down gracefully...") running = False def cleanup_expired_files(): """Perform cleanup of expired files (same logic as cleanup script)""" try: # Initialize storage manager storage_manager = StorageManager(config) backend_info = storage_manager.get_backend_info() # Initialize expiry database expiry_db = ExpiryDatabase() # Get expired files from database expired_files = expiry_db.get_expired_files() if not expired_files: print(f"โฐ {datetime.now().strftime('%H:%M:%S')} - No expired files found") return 0 print(f"๐Ÿ—‘๏ธ {datetime.now().strftime('%H:%M:%S')} - Found {len(expired_files)} expired files to delete") deleted_count = 0 for file_info in expired_files: file_path = file_info['file_path'] expires_at = file_info['expires_at'] try: print(f"๐Ÿ—‘๏ธ Deleting: {file_path} (expired: {expires_at})") # Delete from storage backend if storage_manager.delete_file(file_path): # Remove from expiry database expiry_db.remove_file(file_path) deleted_count += 1 print(f"โœ… Deleted: {file_path}") else: print(f"โŒ Failed to delete: {file_path}") except Exception as e: print(f"โŒ Error deleting {file_path}: {e}") if deleted_count > 0: print(f"โœ… Cleanup completed! Deleted {deleted_count} expired files") return deleted_count except Exception as e: print(f"โŒ Cleanup error: {e}") return -1 def main(): """Main daemon function""" # Set up signal handlers for graceful shutdown signal.signal(signal.SIGINT, signal_handler) # Ctrl+C signal.signal(signal.SIGTERM, signal_handler) # systemctl stop print("๐Ÿงน Sharey Cleanup Daemon") print("=" * 40) print(f"๐Ÿš€ Started at: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") print(f"โฐ Cleanup interval: {CLEANUP_INTERVAL} seconds") print(f"๐Ÿ“ Storage backend: {config.get('storage', {}).get('backend', 'b2')}") print(f"๐Ÿ—„๏ธ Database: expiry.db") print("=" * 40) print("Press Ctrl+C to stop") print() last_cleanup = 0 try: while running: current_time = time.time() # Check if it's time for cleanup if current_time - last_cleanup >= CLEANUP_INTERVAL: try: cleanup_expired_files() last_cleanup = current_time except Exception as e: print(f"โŒ Cleanup cycle failed: {e}") # Sleep for a short interval to avoid busy waiting time.sleep(CHECK_INTERVAL) except KeyboardInterrupt: pass # Handle Ctrl+C gracefully print(f"\n๐Ÿ›‘ Cleanup daemon stopped at: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") print("๐Ÿ‘‹ Goodbye!") if __name__ == "__main__": try: main() except Exception as e: print(f"โŒ Daemon failed to start: {e}") sys.exit(1) sys.exit(0)