Skip to content

noman1228/StreamDownloader

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

StreamDownloader

Automated Stream Deck plugin installer for Windows. Download and install Elgato marketplace plugins directly into StreamDock/VSD plugin folders with minimal friction—supports both GUI and browser-triggered installation via protocol handler.

Features

  • Graphical Interface: Modern dark-themed PySide6 UI for manual plugin installation
  • Browser Integration: Windows protocol handler for one-click install from marketplace browser links
  • Persistent Authentication: Chromium profile caching eliminates repeated logins
  • Streaming Downloads: Real-time progress tracking for large plugin files
  • Flexible Configuration: Customizable Chromium profile, plugins root, download directory
  • Smart Login Fallback: Automatically switches to headful browser if cached auth expires
  • Plugin Management: Direct ZIP extraction with folder replacement (handles updates)

Installation

Prerequisites

  • Windows 10 or later
  • Python 3.8+
  • ~200 MB free disk space (for Chromium browser)

Setup Steps

  1. Clone or download the repository:
git clone https://github.com/noman1228/StreamDownloader.git
cd StreamDownloader
  1. Install Python dependencies:
pip install -r requirements.txt
  1. Install Chromium browser for Playwright (one-time setup):
python -m playwright install chromium
  1. Run the application:
python PluginDown.py

Optional: Building a Standalone Executable

To create a self-contained Windows executable (no Python required):

Easy way (Windows):

build.bat

Manual way:

python build_exe.py

This will:

  • Install PyInstaller
  • Bundle Python, all dependencies, and the Chromium browser
  • Create dist/StreamDownloader/StreamDownloader.exe
  • The build takes 5-10 minutes and creates a ~500 MB folder

Share the executable:

  • Zip the dist/StreamDownloader folder
  • Users can extract and run StreamDownloader.exe directly
  • No Python installation needed

Build requirements:

pip install -r requirements-dev.txt

Usage

GUI Mode (Default)

Launch the graphical interface:

python PluginDown.py

The GUI provides:

  • Plugin UUID input field (copy from marketplace plugin page)
  • Chromium Profile path for persistent browser cookies
  • Plugins Root Directory (auto-detects StreamDock/VSD installation)
  • Download Directory (defaults to ~/Downloads)
  • Headless Mode checkbox (recommended; auto-falls back for login)
  • Keep Downloaded File checkbox (retain .streamDeckPlugin archive)
  • Progress Bar with live download percentage
  • Protocol Handler Registration for browser integration

Protocol Mode (Browser Integration)

Register a protocol handler to install via browser links:

  1. In the GUI, set your desired Scheme (default: streamdeck)
  2. Click Register Handler
  3. Click any plugin install link in the marketplace; the app launches automatically
REM Manual invocation (for testing):
python PluginDown.py --protocol "streamdeck://plugins/install/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

The protocol handler will:

  • Read settings from the registry (persisted from GUI mode)
  • Launch Chromium for authentication if needed
  • Download and install silently with console output

No-GUI Mode

Minimal mode for scripting (currently placeholder):

python PluginDown.py --no-gui

Configuration

Settings are persisted in the Windows registry under:

HKEY_CURRENT_USER\Software\JMT\StreamDeck to StreamDock Auto Installer

Available Settings

Key Type Default Purpose
profile_dir Path %LOCALAPPDATA%\ElgatoCookieProfile Chromium persistent context (stores auth cookies)
plugins_root Path Auto-detect Root folder where plugin folders are installed
download_dir Path ~/Downloads Where .streamDeckPlugin archives are saved
protocol_scheme String streamdeck Protocol scheme for scheme://plugins/install/<uuid>
headless Boolean true Launch Chromium in headless mode (auto-fallback on login needed)
keep_download Boolean true Retain downloaded plugin archive after installation

Auto-Detected Plugins Roots (in priority order):

  • %APPDATA%\HotSpot\StreamDock\plugins
  • %APPDATA%\VSDinside\StreamDock\Plugins
  • %APPDATA%\VSDStreamDock\Plugins
  • %LOCALAPPDATA%\VSDinside\VSDStreamDock\Plugins
  • %LOCALAPPDATA%\VSDStreamDock\Plugins

Architecture

Installation Pipeline

UUID Validation
    ↓
Cookie Acquisition (Playwright/Chromium)
    ↓
Marketplace API → Purchase Link Resolution
    ↓
Plugin Download (streamed, with progress)
    ↓
ZIP Extraction → Plugins Root
    ↓
(Optional) Clean Up Downloaded Archive

Key Components

get_marketplace_cookies()

  • Uses Chromium's persistent context for auth cookie caching
  • Launches headless by default; falls back to headful for login
  • Detects auth tokens: __Host-kc_at, __Secure-kc_rt, next-auth

fetch_purchase_link()

  • Calls Elgato API: marketplace.elgato.com/api/proxy/items/{item_id}/purchase-link
  • Returns direct download link for the .streamDeckPlugin file

download_with_progress()

  • Streams download in 256 KB chunks
  • Emits progress updates every 0.1 seconds
  • Gracefully handles missing Content-Length header

install_streamdeckplugin()

  • Extracts ZIP directly to plugins root
  • Auto-replaces existing folder (handles plugin updates)
  • Detects single top-level folder in archive

InstallWorker(QThread)

  • Runs installation in background thread
  • Maps download progress (25–80%) to progress bar
  • Emits status messages and final success/error signal

Protocol Handler Registration

  • Writes to HKCU\Software\Classes\<scheme>
  • Launches: python "<script_path>" --protocol "%1"
  • Windows invokes handler when user clicks scheme:// link

Status Callback Pattern

Instead of logging frameworks, this codebase uses a simple status_cb callable:

def status_callback(message: str):
    # Update UI or print to console
    pass

get_marketplace_cookies(profile_dir, headless_preferred=True, status_cb=status_callback)

All major functions accept optional status_cb for real-time progress updates.

Development

Running Locally

REM GUI mode with your settings
python PluginDown.py

REM Test protocol mode
python PluginDown.py --protocol "streamdeck://plugins/install/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

REM Debug no-GUI mode
python PluginDown.py --no-gui

Code Structure

Section Purpose
Config/Constants Market domain, API endpoints, app identity
Helpers UUID validation, path helpers, byte formatting
Playwright Cookie Grabber Auth cookie acquisition via persistent Chromium
Marketplace + Download + Install Core pipeline functions
Windows Protocol Handler Registry manipulation (Windows-only)
Protocol Invocation Install run_protocol_install() entrypoint
Qt Worker InstallWorker thread for GUI responsiveness
Qt GUI InstallerWindow with layout, styling, event handlers
Main CLI argument parsing and mode dispatch

Modifying Installation Logic

When changing install behavior, ensure both codepaths stay in sync:

  1. GUI path: InstallWorker.run()on_install_done()
  2. Protocol path: run_protocol_install() → console output

Adding New Settings

  1. Add key to _load_settings() (read from registry with default)
  2. Add key to _save_settings() (write to registry)
  3. Add UI control in _build_ui()
  4. Read from QSettings in run_protocol_install()

Example:

# _load_settings()
self.my_checkbox.setChecked(self.settings.value("my_key", False, type=bool))

# _save_settings()
self.settings.setValue("my_key", self.my_checkbox.isChecked())

# run_protocol_install()
my_setting = settings.value("my_key", False, type=bool)

Dependencies

Package Version Purpose
playwright 1.58.0+ Chromium automation and cookie persistence
pyside6 6.10.2+ Qt GUI framework
requests 2.32.5+ HTTP client for API calls and downloads

Install all with:

pip install -r requirements.txt
python -m playwright install chromium

Troubleshooting

"Chromium not found"

You haven't installed the Chromium browser. Run:

python -m playwright install chromium

Login loop when headless is enabled

If the app keeps opening a browser window despite headless mode:

  • Browser window means cached cookies have expired
  • Log in once, and credentials are cached for future runs
  • This is expected behavior; headless falls back automatically

Plugin fails to install

  • Verify plugins root path exists and is writable
  • Check UUID is valid (copy directly from marketplace page)
  • Ensure .streamDeckPlugin archive isn't corrupted (check downloads folder)

Protocol handler doesn't work after registration

  • Verify scheme is set correctly in the GUI before registering
  • Restart your browser after registration
  • Check registry: HKEY_CURRENT_USER\Software\Classes\<scheme>
  • Test manually: Open PowerShell and run: python PluginDown.py --protocol "streamdeck://plugins/install/<uuid>"

"Not logged in (no auth cookies)"

  • First run requires manual login via headful browser
  • Log in once through the opened window; credentials are cached
  • Subsequent runs use cached cookies in headless mode

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors