Python Wrapper

Running FileBot from the console, Groovy scripting, shell scripts, etc
Post Reply
tlarcombe
Posts: 5
Joined: 29 Apr 2020, 15:17

Python Wrapper

Post by tlarcombe »

I use (manually) very basic functionality - just renaming or getting subs. This was vibe coded (I am a network guy not a dev), so if the LLM ripped off your code, I apologize. Just thought I would leave it here in case it is useful to someone.

python: Select all

#!/usr/bin/env python3
"""
FileBot Wrapper - Interactive CLI for simplified FileBot operations
Simplifies the process of renaming media files and downloading subtitles.
"""

import subprocess
import sys
import glob
from pathlib import Path


class FileType:
    """Media file extensions supported by FileBot"""
    VIDEO = ['.mkv', '.mp4', '.avi', '.m4v', '.mov', '.wmv', '.flv', '.mpg', '.mpeg']
    SUBTITLE = ['.srt', '.sub', '.idx', '.ass', '.ssa']


def get_media_files(directory='.', file_types=None):
    """Find all media files in the current directory"""
    if file_types is None:
        file_types = FileType.VIDEO

    files = []
    for ext in file_types:
        files.extend(glob.glob(f'{directory}/*{ext}'))
    return files


def prompt_choice(question, choices):
    """Display a question with numbered choices and return the selected value"""
    print(f"\n{question}")
    for i, choice in enumerate(choices, 1):
        print(f"  {i}. {choice}")

    while True:
        try:
            selection = input(f"Enter your choice (1-{len(choices)}): ").strip()
            index = int(selection) - 1
            if 0 <= index < len(choices):
                return choices[index]
            else:
                print(f"Please enter a number between 1 and {len(choices)}")
        except (ValueError, KeyboardInterrupt):
            print("\nInvalid input. Please enter a number.")


def prompt_text(question, default=None):
    """Prompt for text input with optional default"""
    if default:
        prompt = f"{question} [{default}]: "
    else:
        prompt = f"{question}: "

    response = input(prompt).strip()
    return response if response else default


def build_filebot_command(operation, media_type, show_name, files_pattern='*'):
    """Build the appropriate FileBot command based on user inputs"""
    command = ['filebot']

    if operation == 'Get Subtitles':
        command.extend(['-get-subtitles'])
        db = 'TheMovieDB' if media_type == 'Movie' else 'TheTVDB'
        command.extend([
            '--db', db,
            '--lang', 'en',
            '--output', 'srt',
            '--encoding', 'utf8'
        ])
    else:  # Rename
        command.extend(['-rename'])
        db = 'TheMovieDB' if media_type == 'Movie' else 'TheTVDB'
        command.extend([
            '--db', db,
            '--lang', 'en'
        ])

    # Add query parameter
    command.extend(['--q', show_name])

    # Expand glob pattern and add actual files
    # This is needed because subprocess doesn't do shell globbing
    expanded_files = glob.glob(files_pattern)
    if not expanded_files:
        # If no match, pass the pattern itself as fallback
        command.append(files_pattern)
    else:
        # Add all matching files
        command.extend(expanded_files)

    return command


def detect_file_pattern():
    """Auto-detect the most common video file extension in current directory"""
    video_files = get_media_files()

    if not video_files:
        return '*.mkv'  # Default fallback

    # Count extensions
    extensions = {}
    for file in video_files:
        ext = Path(file).suffix
        extensions[ext] = extensions.get(ext, 0) + 1

    # Return most common extension pattern
    most_common = max(extensions.items(), key=lambda x: x[1])
    return f'*{most_common[0]}'


def main():
    """Main interactive workflow"""
    print("=" * 60)
    print("FileBot Wrapper - Simplified Media Management")
    print("=" * 60)

    # Check if FileBot is available
    try:
        result = subprocess.run(['filebot', '-version'],
                              capture_output=True,
                              text=True,
                              timeout=5)
        if result.returncode != 0:
            print("Warning: FileBot may not be installed or configured correctly")
    except FileNotFoundError:
        print("Error: FileBot is not installed or not in PATH")
        print("Please install FileBot from https://www.filebot.net/")
        sys.exit(1)
    except subprocess.TimeoutExpired:
        print("Warning: FileBot check timed out")

    # Question 1: Operation type
    operation = prompt_choice(
        "What would you like to do?",
        ['Get Subtitles', 'Rename']
    )

    # Question 2: Media type
    media_type = prompt_choice(
        "What type of media?",
        ['TV Show', 'Movie']
    )

    # Question 3: Show/Movie name
    show_name = prompt_text("Enter the show/movie name")
    if not show_name:
        print("Error: Show/movie name is required")
        sys.exit(1)

    # Auto-detect or confirm file pattern
    detected_pattern = detect_file_pattern()
    video_files = get_media_files()

    if video_files:
        print(f"\nFound {len(video_files)} video file(s) matching pattern: {detected_pattern}")
        for f in video_files[:5]:  # Show first 5
            print(f"  - {Path(f).name}")
        if len(video_files) > 5:
            print(f"  ... and {len(video_files) - 5} more")

    # Allow user to override pattern
    file_pattern = prompt_text(
        "\nFile pattern to process",
        default=detected_pattern
    )

    # Build and display command
    command = build_filebot_command(operation, media_type, show_name, file_pattern)

    print("\n" + "=" * 60)
    print("Generated FileBot Command:")
    print("=" * 60)
    print(' '.join(command))
    print("=" * 60)

    # Confirm execution
    confirm = input("\nExecute this command? [Y/n]: ").strip().lower()
    if confirm and confirm not in ['y', 'yes']:
        print("Cancelled.")
        sys.exit(0)

    # Execute FileBot command
    print("\nExecuting FileBot...\n")
    try:
        result = subprocess.run(command, text=True)
        sys.exit(result.returncode)
    except KeyboardInterrupt:
        print("\n\nOperation cancelled by user")
        sys.exit(130)
    except Exception as e:
        print(f"\nError executing FileBot: {e}")
        sys.exit(1)


if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        print("\n\nOperation cancelled by user")
        sys.exit(130)

Post Reply