Spaces:
Runtime error
Runtime error
| import streamlit as st | |
| import os | |
| import configparser | |
| import glob | |
| import shutil | |
| from datetime import datetime | |
| from pathlib import Path | |
| import re | |
| from utils import parse_winapp2_ini, scan_files, delete_files, get_file_size, format_size | |
| st.set_page_config( | |
| page_title="Windows Data Cleaner", | |
| page_icon="π§Ή", | |
| layout="wide", | |
| initial_sidebar_state="expanded" | |
| ) | |
| # Custom CSS for better UI | |
| st.markdown(""" | |
| <style> | |
| .main-header { | |
| font-size: 2.5rem; | |
| font-weight: bold; | |
| color: #1f77b4; | |
| margin-bottom: 1rem; | |
| } | |
| .stat-box { | |
| background-color: #f0f2f6; | |
| padding: 1rem; | |
| border-radius: 0.5rem; | |
| margin: 0.5rem 0; | |
| } | |
| .warning-box { | |
| background-color: #fff3cd; | |
| border: 1px solid #ffc107; | |
| padding: 1rem; | |
| border-radius: 0.5rem; | |
| margin: 1rem 0; | |
| } | |
| .success-box { | |
| background-color: #d4edda; | |
| border: 1px solid #28a745; | |
| padding: 1rem; | |
| border-radius: 0.5rem; | |
| margin: 1rem 0; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # Header with anycoder link | |
| st.markdown('<div class="main-header">π§Ή Windows Data Cleaner</div>', unsafe_allow_html=True) | |
| st.markdown('[Built with anycoder](https://huggingface.co/spaces/akhaliq/anycoder)', unsafe_allow_html=True) | |
| st.markdown("---") | |
| # Initialize session state | |
| if 'cleaning_results' not in st.session_state: | |
| st.session_state.cleaning_results = None | |
| if 'scanned_files' not in st.session_state: | |
| st.session_state.scanned_files = [] | |
| if 'ini_config' not in st.session_state: | |
| st.session_state.ini_config = None | |
| if 'scan_complete' not in st.session_state: | |
| st.session_state.scan_complete = False | |
| # Sidebar configuration | |
| with st.sidebar: | |
| st.header("βοΈ Configuration") | |
| # INI File Upload | |
| st.subheader("WinApp2.ini File") | |
| ini_file = st.file_uploader( | |
| "Upload winapp2.ini", | |
| type=["ini", "txt"], | |
| help="Upload the winapp2.ini configuration file" | |
| ) | |
| # Base directory for cleaning | |
| st.subheader("Base Directory") | |
| base_dir = st.text_input( | |
| "Base Directory Path", | |
| value=os.getenv('USERPROFILE', 'C:/Users') or 'C:/Users', | |
| help="Root directory to scan for files" | |
| ) | |
| # Cleaning options | |
| st.subheader("Cleaning Options") | |
| dry_run = st.checkbox("Dry Run Mode", value=True, help="Preview files without deleting") | |
| confirm_delete = st.checkbox("Require Confirmation", value=True, help="Ask before deleting files") | |
| # Advanced options | |
| with st.expander("Advanced Options"): | |
| include_hidden = st.checkbox("Include Hidden Files", value=False) | |
| include_system = st.checkbox("Include System Files", value=False, help="Warning: May affect system stability") | |
| max_file_age_days = st.number_input("Max File Age (days)", min_value=0, value=365, help="Only clean files older than this") | |
| # Main content area | |
| st.header("π Configuration File") | |
| if ini_file: | |
| try: | |
| # Parse the INI file | |
| with st.spinner("Parsing winapp2.ini..."): | |
| config_content = ini_file.getvalue().decode('utf-8') | |
| st.session_state.ini_config = parse_winapp2_ini(config_content) | |
| if st.session_state.ini_config: | |
| st.success("β Configuration file loaded successfully!") | |
| # Display configuration sections | |
| st.subheader("Available Cleaning Sections") | |
| for section_name, section_data in st.session_state.ini_config.items(): | |
| with st.expander(f"π {section_name}", expanded=False): | |
| st.code(f"Description: {section_data.get('description', 'No description')}") | |
| st.code(f"Warning: {section_data.get('warning', 'No warnings')}") | |
| if 'path' in section_data: | |
| st.code(f"Paths: {section_data['path']}") | |
| if 'file' in section_data: | |
| st.code(f"File Patterns: {section_data['file']}") | |
| if 'regex' in section_data: | |
| st.code(f"Regex Patterns: {section_data['regex']}") | |
| except Exception as e: | |
| st.error(f"β Error parsing INI file: {str(e)}") | |
| else: | |
| st.info("π Please upload a winapp2.ini configuration file to continue.") | |
| st.code(""" | |
| # Example winapp2.ini structure | |
| [SectionName] | |
| Description=Description of what this cleans | |
| Warning=Warning message | |
| path=C:\\Users\\*\\AppData\\Local\\Temp | |
| file=*.tmp; *.log | |
| regex=pattern_to_match | |
| """) | |
| # Scan and Preview Section | |
| st.header("π Scan & Preview") | |
| if st.session_state.ini_config and base_dir: | |
| if st.button("π Scan for Files", type="primary", disabled=not st.session_state.ini_config): | |
| with st.spinner("Scanning directories..."): | |
| try: | |
| scanned_files = scan_files( | |
| st.session_state.ini_config, | |
| base_dir, | |
| include_hidden=include_hidden, | |
| include_system=include_system, | |
| max_age_days=max_file_age_days | |
| ) | |
| st.session_state.scanned_files = scanned_files | |
| st.session_state.scan_complete = True | |
| # Calculate totals | |
| total_files = len(scanned_files) | |
| total_size = sum(f['size'] for f in scanned_files) | |
| st.session_state.scan_summary = { | |
| 'total_files': total_files, | |
| 'total_size': total_size, | |
| 'sections': len(st.session_state.ini_config) | |
| } | |
| st.success(f"β Scan complete! Found {total_files} files ({format_size(total_size)})") | |
| except Exception as e: | |
| st.error(f"β Error during scan: {str(e)}") | |
| st.session_state.scan_complete = False | |
| # Display scan results | |
| if st.session_state.scan_complete and st.session_state.scanned_files: | |
| st.subheader("π Scan Results") | |
| # Summary statistics | |
| col1, col2, col3 = st.columns(3) | |
| with col1: | |
| st.metric( | |
| label="Total Files", | |
| value=st.session_state.scan_summary['total_files'] | |
| ) | |
| with col2: | |
| st.metric( | |
| label="Total Size", | |
| value=format_size(st.session_state.scan_summary['total_size']) | |
| ) | |
| with col3: | |
| st.metric( | |
| label="Sections", | |
| value=st.session_state.scan_summary['sections'] | |
| ) | |
| # File list with selection | |
| st.subheader("π Files to Clean") | |
| # Create a table of files | |
| if st.session_state.scanned_files: | |
| # Display first 100 files in table | |
| display_files = st.session_state.scanned_files[:100] | |
| file_data = { | |
| 'Section': [f['section'] for f in display_files], | |
| 'Path': [f['path'] for f in display_files], | |
| 'Size': [format_size(f['size']) for f in display_files], | |
| 'Age (days)': [f['age_days'] for f in display_files] | |
| } | |
| st.table(file_data) | |
| if len(st.session_state.scanned_files) > 100: | |
| st.info(f"Showing first 100 of {len(st.session_state.scanned_files)} files") | |
| # Download full list | |
| if len(st.session_state.scanned_files) > 0: | |
| import json | |
| file_list_json = json.dumps(st.session_state.scanned_files, indent=2) | |
| st.download_button( | |
| label="π₯ Download Full File List", | |
| data=file_list_json, | |
| file_name="scan_results.json", | |
| mime="application/json" | |
| ) | |
| # Cleaning Execution Section | |
| st.header("π§Ή Execute Cleaning") | |
| if st.session_state.scan_complete and st.session_state.scanned_files: | |
| warning_msg = """ | |
| <div class="warning-box"> | |
| <strong>β οΈ WARNING:</strong> This operation will delete files from your system. | |
| Please review the file list carefully before proceeding. | |
| Make sure you have backups of important data. | |
| </div> | |
| """ | |
| st.markdown(warning_msg, unsafe_allow_html=True) | |
| # Execution controls | |
| col1, col2 = st.columns([3, 1]) | |
| with col1: | |
| execute_clean = st.button( | |
| "ποΈ Execute Clean Operation", | |
| type="primary", | |
| disabled=dry_run and not st.session_state.scanned_files | |
| ) | |
| with col2: | |
| reset_scan = st.button("π Reset Scan") | |
| if reset_scan: | |
| st.session_state.scanned_files = [] | |
| st.session_state.scan_complete = False | |
| st.session_state.cleaning_results = None | |
| st.rerun() | |
| if execute_clean: | |
| if confirm_delete and not dry_run: | |
| if not st.checkbox("β I confirm I want to delete these files"): | |
| st.warning("Please confirm before proceeding") | |
| st.stop() | |
| with st.spinner("Executing clean operation..."): | |
| try: | |
| results = delete_files( | |
| st.session_state.scanned_files, | |
| dry_run=dry_run | |
| ) | |
| st.session_state.cleaning_results = results | |
| if dry_run: | |
| success_msg = """ | |
| <div class="success-box"> | |
| <strong>β Dry Run Complete:</strong> No files were deleted. | |
| This was a preview of what would be cleaned. | |
| </div> | |
| """ | |
| else: | |
| success_msg = """ | |
| <div class="success-box"> | |
| <strong>β Cleaning Complete:</strong> Files have been deleted successfully. | |
| </div> | |
| """ | |
| st.markdown(success_msg, unsafe_allow_html=True) | |
| # Display results | |
| if results: | |
| st.subheader("π Cleaning Results") | |
| result_col1, result_col2, result_col3 = st.columns(3) | |
| with result_col1: | |
| st.metric("Files Processed", results.get('processed', 0)) | |
| with result_col2: | |
| st.metric("Files Deleted", results.get('deleted', 0)) | |
| with result_col3: | |
| st.metric("Space Freed", format_size(results.get('size_freed', 0))) | |
| if results.get('errors', []): | |
| st.subheader("β οΈ Errors") | |
| for error in results['errors']: | |
| st.error(error) | |
| except Exception as e: | |
| st.error(f"β Error during cleaning: {str(e)}") | |
| import traceback | |
| st.code(traceback.format_exc()) | |
| # Help and Documentation | |
| st.header("β Help & Documentation") | |
| with st.expander("How to Use winapp2.ini", expanded=False): | |
| st.markdown(""" | |
| **winapp2.ini** is a configuration file format used by cleaning tools like BleachBit. | |
| **Structure:** | |
| ```ini | |
| [SectionName] | |
| Description=What this section cleans | |
| Warning=Warning message for users | |
| path=C:\\path\\to\\directory | |
| file=*.ext; *.log | |
| regex=pattern_to_match | |
| **Common Sections:** | |
| - `Temp`: Temporary files | |
| - `Cache`: Browser and application caches | |
| - `Logs`: Application log files | |
| - `Recycle`: Recycle bin contents | |
| """) | |
| with st.expander("Safety Tips", expanded=False): | |
| st.markdown(""" | |
| **β οΈ Important Safety Guidelines:** | |
| 1. **Always use Dry Run mode first** to preview what will be deleted | |
| 2. **Review the file list** before executing deletion | |
| 3. **Backup important data** before cleaning | |
| 4. **Don't clean system files** unless you know what they do | |
| 5. **Start with user data** (Temp, Cache, Logs) before system files | |
| 6. **Check application behavior** after cleaning to ensure nothing broke | |
| """) | |
| with st.expander("Troubleshooting", expanded=False): | |
| st.markdown(""" | |
| **Common Issues:** | |
| - **Permission Errors**: Run as administrator or check file permissions | |
| - **File Not Found**: Paths may be incorrect or files already deleted | |
| - **INI Parse Errors**: Check INI file format and encoding | |
| - **Slow Scanning**: Large directories or network drives can be slow | |
| ** Solutions:** | |
| - Use specific paths instead of wildcards | |
| - Exclude system directories if not needed | |
| - Run in dry run mode first | |
| - Check antivirus software isn't blocking access | |
| """) | |
| # Footer | |
| st.markdown("---") | |
| st.markdown("Made with β€οΈ using Streamlit | [Built with anycoder](https://huggingface.co/spaces/akhaliq/anycoder)") |