diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..ab7f490 Binary files /dev/null and b/.DS_Store differ diff --git a/README.md b/README.md index fe435e9..2279a03 100644 --- a/README.md +++ b/README.md @@ -1,117 +1,57 @@ # slskd Transfer Statistics -A tool to analyze upload and download statistics from your slskd transfers database with both command-line and GUI interfaces. +A GUI tool to analyze upload and download statistics from your slskd transfers database. ## Features - Analyzes uploads and downloads stored in the transfers.db database(s) - Automatically finds and combines data from multiple database files +- Backwards compatible with both old and new database formats - Calculates total transfers, data transferred, and unique users - Shows average transfer speed and duration - Lists top users by data transferred - Shows statistics by file type -- Filter statistics by date range -- Graphical user interface for easier analysis -- Maintains full command-line functionality +- Filter statistics by time period (All time, Last month, Last year) +- User-friendly graphical interface with summary and detailed tables ## Requirements - Python 3.6+ - SQLite3 -- PyQt5 (for GUI version) +- PyQt5 ## Installation 1. Clone or download this repository to your local machine -2. Ensure Python 3 is installed -3. Place your `transfers.db` file in the same directory as the script, or specify database paths using the `--db` option +2. Ensure Python 3 and PyQt5 are installed +3. Place your `transfers.db` file in the same directory as the script, or use the file browser to select database files ## Usage -### Command Line Interface - ```bash -# Basic usage (uses transfers.db in current directory) -# Shows both upload and download stats by default -./slskd_stats.py - -# Show only upload stats -./slskd_stats.py --uploads - -# Show only download stats -./slskd_stats.py --downloads - -# Explicitly show both upload and download stats (same as default) -./slskd_stats.py --all - -# Specify single database file -./slskd_stats.py --db /path/to/transfers.db - -# Specify multiple database files -./slskd_stats.py --db /path/to/transfers.db --db /path/to/another-transfers.db - -# Only show transfers from the last 30 days -./slskd_stats.py --days 30 - -# Show top 15 entries in each category -./slskd_stats.py --top 15 - -# Combine options -./slskd_stats.py --all --days 7 --top 20 --db /path/to/transfers.db -``` - -### GUI Interface - -```bash -# Launch the GUI version -./slskd_stats_gui.py - -# Launch GUI even when providing command line arguments -./slskd_stats_gui.py --gui +# Launch the GUI application +python3 slskd_stats_gui.py ``` With the GUI, you can: - Select one or more database files using the file browser -- Choose to show upload stats, download stats, or both -- Filter by time period (last X days) +- Choose time period from dropdown (All time, Last month, Last year) - Set the number of top entries to display -- View statistics in a user-friendly tabbed interface +- View upload and download statistics side-by-side +- See summary statistics and detailed tables for users and file types ## Example Output -``` -=== UPLOAD STATISTICS === +The GUI displays: +- **Summary sections** showing total transfers, data transferred, unique users, average speeds, and error rates +- **Top Users tables** showing users ranked by data transferred +- **Top File Types tables** showing file extensions ranked by data transferred -Total Uploads: 8583 -Total Data Uploaded: 241.97 GB -Unique Users: 650 -Average Upload Speed: 8.50 MB/s -Average Upload Duration: 10.02 seconds +## Database Compatibility ---- Top Users by Data Uploaded --- -1. username1: 279 files, 18.01 GB -2. username2: 494 files, 12.29 GB -3. username3: 378 files, 11.05 GB -... - ---- Top File Types --- -1. .flac: 8456 files, 241.00 GB -2. .mp3: 105 files, 830.71 MB -3. .m4a: 22 files, 165.58 MB - -=== DOWNLOAD STATISTICS === - -Total Downloads: 357 -Total Data Downloaded: 10.94 GB -Unique Users: 36 -Average Download Speed: 2.03 MB/s -Average Download Duration: 26.21 seconds - ---- Top Users by Data Downloaded --- -1. username1: 6 files, 1.45 GB -2. username2: 58 files, 1.33 GB -... -``` +This tool automatically detects and works with both: +- **Old format**: Text-based `State` column +- **New format**: Integer `State` + `StateDescription` columns ## About diff --git a/slskd_stats_gui.py b/slskd_stats_gui.py index b19139b..c5683bf 100644 --- a/slskd_stats_gui.py +++ b/slskd_stats_gui.py @@ -3,10 +3,7 @@ import sys import os import datetime import sqlite3 -import argparse -import glob from collections import defaultdict -from pathlib import Path # For GUI from PyQt5.QtWidgets import ( @@ -191,48 +188,6 @@ def get_transfer_stats(db_paths, direction="Upload", days=None): return stats -def display_stats(stats, direction, top_n=10): - """Display the statistics in a readable format for CLI""" - if not stats or stats["total_transfers"] == 0: - print(f"No {direction.lower()} data found for the specified period.") - return - - output = [] - output.append(f"\n=== {direction.upper()} STATISTICS ===\n") - - output.append(f"Total {direction}s: {stats['total_transfers']}") - output.append(f"Total Data {direction}ed: {format_size(stats['total_bytes'])}") - output.append(f"Unique Users: {stats['unique_users']}") - output.append(f"Average {direction} Speed: {format_size(stats['avg_speed'])}/s") - output.append(f"Average {direction} Duration: {format_time(stats['avg_duration'])}") - - # Top users by data transferred - output.append(f"\n--- Top Users by Data {direction}ed ---") - sorted_users = sorted( - stats["user_stats"].items(), - key=lambda x: x[1]["bytes"], - reverse=True - ) - - for i, (username, data) in enumerate(sorted_users[:top_n], 1): - output.append(f"{i}. {username}: {data['count']} files, {format_size(data['bytes'])}") - - # Top file types - output.append("\n--- Top File Types ---") - sorted_extensions = sorted( - stats["extension_stats"].items(), - key=lambda x: x[1]["bytes"], - reverse=True - ) - - for i, (ext, data) in enumerate(sorted_extensions[:top_n], 1): - output.append(f"{i}. {ext}: {data['count']} files, {format_size(data['bytes'])}") - - # Print all lines - for line in output: - print(line) - - return output class MainWindow(QMainWindow): def __init__(self): @@ -526,75 +481,11 @@ class MainWindow(QMainWindow): self.downloadSummary.setText("No download data found for the specified period.") def main(): - # Check if command line args were provided - if len(sys.argv) > 1: - # Command line mode - parser = argparse.ArgumentParser(description="Analyze transfer statistics from slskd transfers database") - parser.add_argument("--db", action="append", help="Path to transfers.db file(s). Can be specified multiple times.") - parser.add_argument("--days", type=int, help="Only analyze transfers from the last X days") - parser.add_argument("--top", type=int, default=10, help="Show top N entries in each category") - parser.add_argument("--uploads", action="store_true", help="Show only upload statistics") - parser.add_argument("--downloads", action="store_true", help="Show only download statistics") - parser.add_argument("--all", action="store_true", help="Show both upload and download statistics (default)") - parser.add_argument("--gui", action="store_true", help="Launch the GUI instead of command line mode") - args = parser.parse_args() - - # Check if GUI mode is requested - if args.gui: - # Launch GUI mode - app = QApplication(sys.argv) - window = MainWindow() - window.show() - sys.exit(app.exec_()) - - # Determine which db files to use - db_paths = [] - if args.db: - # User specified database files - for db_path in args.db: - if os.path.exists(db_path): - db_paths.append(db_path) - else: - print(f"Warning: Database file not found: {db_path}") - else: - # Default: Only look for transfers.db in the current directory - if os.path.exists("transfers.db"): - db_paths.append("transfers.db") - else: - print("Default transfers.db not found in current directory.") - - if not db_paths: - print("Error: No database files found. Please specify with --db option.") - return - - print(f"Using database file(s): {', '.join(db_paths)}") - - # Default behavior is to show both uploads and downloads - # Only change from default if specific flags are set - if args.uploads and not args.downloads and not args.all: - show_uploads = True - show_downloads = False - elif args.downloads and not args.uploads and not args.all: - show_uploads = False - show_downloads = True - else: - # Default behavior or --all flag - show_uploads = True - show_downloads = True - - if show_uploads: - upload_stats = get_transfer_stats(db_paths, "Upload", args.days) - display_stats(upload_stats, "Upload", args.top) - - if show_downloads: - download_stats = get_transfer_stats(db_paths, "Download", args.days) - display_stats(download_stats, "Download", args.top) - else: - # No args provided, launch GUI - app = QApplication(sys.argv) - window = MainWindow() - window.show() - sys.exit(app.exec_()) + # Launch GUI application + app = QApplication(sys.argv) + window = MainWindow() + window.show() + sys.exit(app.exec_()) if __name__ == "__main__": main() \ No newline at end of file diff --git a/transfers.db b/transfers.db new file mode 100755 index 0000000..f6f8031 Binary files /dev/null and b/transfers.db differ