Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions .github/workflows/blank.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# This is a basic workflow to help you get started with Actions
# CI workflow for BotDesk

name: CI

Expand All @@ -25,12 +25,18 @@ jobs:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v4

# Runs a single command using the runners shell
- name: Run a one-line script
run: echo Hello, world!
# Set up Python
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'

# Runs a set of commands using the runners shell
- name: Run a multi-line script
# Install dependencies
- name: Install dependencies
run: |
echo Add other actions to build,
echo test, and deploy your project.
python -m pip install --upgrade pip
pip install -r requirements.txt

# Run tests
- name: Run tests
run: python -m unittest discover tests
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,13 @@ cython_debug/
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
.idea/

# Visual Studio
.vs/

# Error logs
error_log.txt

# PyPI configuration file
.pypirc
29 changes: 29 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Use an official Python runtime as the base image
FROM python:3.10-slim

# Set environment variables to prevent Python from buffering output
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

# Set the working directory in the container
WORKDIR /app

# Copy only the requirements file initially to take advantage of Docker's layer caching
COPY requirements.txt /app/requirements.txt

# Install dependencies
RUN pip install --no-cache-dir -r requirements.txt

# Copy the entire project to the entire container
COPY . /app

# Export port 5000 (optional, in case you use Flask or other servers in the future)
EXPOSE 5000

# Set the entry point to run the main.py file
CMD ["python", "main.py"]

#FROM ubuntu:latest
#LABEL authors="irfan"

#ENTRYPOINT ["top", "-b"]
156 changes: 154 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,154 @@
# BotDesk
A desktop automation application to automate tasks on your computer.
# Botdesk

**Botdesk** is a powerful desktop automation tool designed to simplify repetitive tasks on your computer. It provides a user-friendly
dashboard for automating common tasks like organizing files, finding duplicate files and analyzing folder structures. Built with Python
and PyQt5, BotDesk is ideal for professionals and everyday users seeking efficiency and time savings.

---

## Features

- **File Organizer**: Automatically organizes files into subfolders based on their extensions.
- **Duplicate Finder**: Detects and lists duplicate files in a selected folder.
- **Folder Analyzer**: Provides insights into folder sizes, file counts, and storage usage.
- **Batch File Renamer**: Rename multiple files in a folder with customizable patterns or by appending timestamps for better organization.
- **File Search and Filter**: Quickly search for specific files based on extensions sizes or modification dates includes advanced filtering options to locate files faster.
- **Scheduled Automation**: Set up automation tasks to run at specific times, such as organizing files or clearing duplicates daily, weekly, or monthly.
- **Drag-and-Drop Support**: Simplifies file selection by allowing users to drag folders or files directly into the app interface.
- **Custom Rules for File Organization**: Set up custom rules to sort files not just by extensions but also by file size, date, or even keywords in filenames.
- **Multi-Folder Support**: Automate actions across multiple folders simultaneously, saving you time for large-scale file operations.
- **Backup & Restore**: Automatically create backups of files before applying any changes, with a one-click restore option for added safety.

---

## Upcoming Features

- **Cloud Integration**: Automate file organization and synchronization with popular cloud storage services like Google Drive, Dropbox, and OneDrive.
- **Advanced File Filters**: Filter files by metadata such as creation date, size range, and custom tags for precise automation.
- **Email Automation**: Automatically download, sort, and organize email attachments into specified folders.
- **File Conversion Tools**: Convert files between popular formats (e.g., PDF to Word, image formats) directly within the app.
- **Text Extraction and OCR**: Extract text from images or scanned documents using Optical Character Recognition (OCR) for document processing tasks.
- **Task Scheduler Enhancements**: Introduce an intuitive task calendar to manage recurring tasks
- **Duplicate Detection Improvements**: Add visual previews and advanced duplicate comparison options, such as by resolution for images or embedded metadata.
- **System Cleanup Tools**: Automate cleaning temporary files, caches, and unused programs to optimize computer performance.
- **Zip and Archive Management**: Automate compression and extraction of files, with options to organize extracted content into subfolders.
- **Integration with External APIs**: Enable automations that interact with external APIs for custom workflows, such as downloading reports or scraping web content.
- **Customizable Themes**: Personalize your BotDesk experience with light, dark, and high-contrast themes.
- **Multi-Language Support**: Expand accessibility with support for multiple languages, starting with French, Spanish and German.
- **Ai-Powered Suggestions**: Leverage AI to analyze usage patterns and recommend automation tasks tailored to your workflow.

---

## Installation
### Prerequisites

1. Install 3.8 or higher
2. Install pip (Python's package manager)
3. Install the required dependencies using the command
``
pip install -r requirements.txt
``

### Steps to Run
1. Clone this repository:
```
git clone https://github.com/C4bbage64/BotDesk
```
2. Navigate to the project directory:
```
cd BotDesk
```
3. Run the application:
```
python main.py
```

---

## Usage
### Dashboard Overview

When you launch BotDesk, you'll be greeted with a dashboard featuring multiple automation options. Each option provides a dedicated
interface to execute the desired automation.

1. File Organizer:
- Enter a folder path.
- Specify file extensions (comma-separated).
- Click "Organize Files" to sort files into subfolders by extension.
2. Duplicate Finder:
- Enter a folder path
- Click "Find Duplicates" to detect duplicate files in the selected folder.
- View duplicate results in the log area.
3. Folder Analyzer:
- Enter a folder path.
- Click "Analyzer" to get detailed statistics about the folder and its contents

---

## Project Structure

```
BotDesk/
├── automations/
│ ├── file_organizer.py # Core logic for file organization
│ ├── duplicate_finder.py # Core logic for finding duplicate files
│ ├── folder_analyzer.py # Core logic for analyzing folders
├── ui/
│ ├── dashboard.py # Main dashboard UI
│ ├── file_organizer.py # File Organizer UI
│ ├── duplicate_finder.py # Duplicate Finder UI
│ ├── folder_analyzer.py # Folder Analyzer UI
├── main.py # Entry point of the application
├── requirements.txt # Python dependencies
└── README.md # Project documentation
```

## Dependencies

The following Python libraries are required:
- PyQt5
- os
- shutil
- hashlib

Install all dependencies with:
```
pip install -r requirements.txt
```

---

# Future Enhancements

Planned features for upcoming versions
- Add more automation tools, like scheduled tasks or batch renaming.
- Introduce drag-and-drop functionality for file selection.
- Save user preferences for faster operations
- Support for advanced file (e.g., by size or date)

---

# Contributing
Contributions are welcome! If you'd like to improve this project:
1. Fork the repository.
2. Create a feature branch:
```
git checkout -b feature-name
```
3. Commit your changes and push the branch:
```
git push origin feature-name
```
4. Create a pull request

---

## License

This project is licensed under the MIT License

---

## Acknowledgements

Special thanks to the open-source community for their tools and inspirations
Empty file added automations/__init__.py
Empty file.
97 changes: 97 additions & 0 deletions automations/batch_renamer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import os

def get_rename_preview(folder_path, replace_text="", with_text="", add_prefix="", add_suffix=""):
"""
Generates a preview of file renames based on the provided criteria.

Args:
folder_path (str): Path to the folder containing files.
replace_text (str): Text to replace in the filename.
with_text (str): Text to replace with.
add_prefix (str): Text to add to the beginning of the filename.
add_suffix (str): Text to add to the end of the filename (before extension).

Returns:
list: A list of tuples (original_name, new_name) for files that will be changed.
"""
preview = []
if not os.path.exists(folder_path):
return []

try:
files = [f for f in os.listdir(folder_path) if os.path.isfile(os.path.join(folder_path, f))]
except Exception:
return []

for filename in files:
new_name = filename
name, ext = os.path.splitext(filename)

# Replace text
if replace_text:
new_name = new_name.replace(replace_text, with_text)
# Re-split in case replacement affected extension (though usually we operate on full name or just base?)
# Standard behavior: replace in the whole name including extension?
# Or just base? Let's do whole name for flexibility, but usually people want base.
# Let's stick to simple string replacement on the whole name for now,
# but prefix/suffix usually apply to base.

# Actually, let's refine: Replace usually applies to the whole string.
# Prefix/Suffix apply to the base name.

# Let's re-calculate name/ext after replacement if we want to be safe,
# but if we replace in 'new_name', we are modifying the whole thing.
pass

# Apply prefix/suffix to the current state of the name (excluding extension for suffix)
# To do this correctly, we need to split the potentially modified new_name
current_base, current_ext = os.path.splitext(new_name)

if add_prefix:
current_base = f"{add_prefix}{current_base}"

if add_suffix:
current_base = f"{current_base}{add_suffix}"

final_name = f"{current_base}{current_ext}"

if final_name != filename:
preview.append((filename, final_name))

return preview

def execute_renames(folder_path, rename_map):
"""
Executes the renaming of files based on a map of {old_name: new_name}.

Args:
folder_path (str): Path to the folder.
rename_map (dict): Dictionary mapping original filenames to new filenames.

Returns:
tuple: (success_message, error_list)
"""
renamed_count = 0
errors = []

if not os.path.exists(folder_path):
return "Folder not found.", ["Folder does not exist."]

for old_name, new_name in rename_map.items():
if old_name == new_name:
continue

try:
old_path = os.path.join(folder_path, old_name)
new_path = os.path.join(folder_path, new_name)

if os.path.exists(new_path):
errors.append(f"Skipped {old_name}: Destination {new_name} already exists.")
continue

os.rename(old_path, new_path)
renamed_count += 1
except Exception as e:
errors.append(f"Error renaming {old_name}: {str(e)}")

return f"Successfully renamed {renamed_count} files.", errors
48 changes: 48 additions & 0 deletions automations/duplicate_finder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import os
import hashlib

class DuplicateFinder:
@staticmethod
def calculate_file_hash(file_path, chunk_size=1024):
"""Calculate the hash of a file for comparison."""
hasher = hashlib.md5()
try:
with open(file_path, "rb") as file:
while chunk := file.read(chunk_size):
hasher.update(chunk)
except Exception as e:
return None
return hasher.hexdigest()

@staticmethod
def find_duplicates(folder_path):
"""Find and return duplicate files in the folder."""
if not os.path.exists(folder_path):
return {"error": "Folder does not exist."}

file_hashes = {}
duplicates = []

for root, _, files in os.walk(folder_path):
for file in files:
file_path = os.path.join(root, file)
file_hash = DuplicateFinder.calculate_file_hash(file_path)
if file_hash:
if file_hash in file_hashes:
duplicates.append((file_path, file_hashes[file_hash]))
else:
file_hashes[file_hash] = file_path

return {"duplicates": duplicates}

@staticmethod
def delete_duplicates(duplicates):
"""Delete the duplicate files provided in the list."""
deleted_files = []
for duplicate, _ in duplicates:
try:
os.remove(duplicate)
deleted_files.append(duplicate)
except Exception as e:
pass # Handle specific errors if needed
return deleted_files
Loading