{campaign.game}
{campaign.name}
{benefit.name}
{drop.claimed ? "Claimed" : `${drop.current_minutes}/${drop.required_minutes} min`}
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 10db2a5..d025e02 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,6 +62,53 @@ jobs: run: | python3 -m compileall -q tui tdminer.py network/twitch.py core/utils.py + web: + name: Linux Web UI + runs-on: ubuntu-latest + needs: + - validate + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: ${{env.PYTHON_VERSION}} + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 24 + cache: npm + cache-dependency-path: web/frontend/package-lock.json + + - name: Install web dependencies + run: | + python3 -m pip install -r requirements-web.txt + npm ci --prefix web/frontend + + - name: Build web frontend + run: | + npm run build --prefix web/frontend + git diff --exit-code -- web/static + + - name: Test web server and installer + run: | + python3 -m unittest discover -s tests -p "test_web*.py" -v + python3 -m unittest discover -s tests -p "test_installer.py" -v + python3 -m compileall -q web tdminer_web.py tui/manager.py + bash -n scripts/install.sh + + - name: Upload install scripts + if: github.event_name != 'pull_request' + uses: actions/upload-artifact@v4 + with: + if-no-files-found: error + name: DropForge.Install.Scripts + path: scripts/install.sh + windows: name: Windows runs-on: windows-latest @@ -114,18 +161,18 @@ jobs: - name: Create release folder run: | - $FolderName = 'Twitch Drops Miner' + $FolderName = 'DropForge' New-Item $FolderName -ItemType Directory Copy-Item dist\*.exe $FolderName Copy-Item manual.txt $FolderName - Compress-Archive -Path $FolderName -DestinationPath Twitch.Drops.Miner.Windows.zip + Compress-Archive -Path $FolderName -DestinationPath DropForge.Windows.zip - name: Upload build artifact uses: actions/upload-artifact@v4 with: if-no-files-found: error - name: Twitch.Drops.Miner.Windows - path: Twitch.Drops.Miner.Windows.zip + name: DropForge.Windows + path: DropForge.Windows.zip macos: name: macOS @@ -166,18 +213,18 @@ jobs: - name: Create release folder and Zip run: | - FOLDER="Twitch Drops Miner" + FOLDER="DropForge" mkdir -p "$FOLDER" - cp -r "dist/Twitch Drops Miner (by HimanM).app" "$FOLDER/" + cp -r "dist/DropForge.app" "$FOLDER/" cp manual.txt "$FOLDER/" - zip -r Twitch.Drops.Miner.MacOS.zip "$FOLDER" + zip -r DropForge.MacOS.zip "$FOLDER" - name: Upload build artifact uses: actions/upload-artifact@v4 with: if-no-files-found: error - name: Twitch.Drops.Miner.MacOS - path: Twitch.Drops.Miner.MacOS.zip + name: DropForge.MacOS + path: DropForge.MacOS.zip macos-tui: name: macOS TUI @@ -207,14 +254,14 @@ jobs: run: | mkdir -p tdminer cp dist/tdminer tdminer/ - zip -r Twitch.Drops.Miner.TUI.MacOS.zip tdminer + zip -r DropForge.TUI.MacOS.zip tdminer - name: Upload TUI build artifact uses: actions/upload-artifact@v4 with: if-no-files-found: error - name: Twitch.Drops.Miner.TUI.MacOS - path: Twitch.Drops.Miner.TUI.MacOS.zip + name: DropForge.TUI.MacOS + path: DropForge.TUI.MacOS.zip linux-tui: name: Linux TUI (${{matrix.arch}}) @@ -252,14 +299,14 @@ jobs: run: | mkdir -p tdminer cp dist/tdminer tdminer/ - zip -r Twitch.Drops.Miner.TUI.Linux-${{matrix.arch}}.zip tdminer + zip -r DropForge.TUI.Linux-${{matrix.arch}}.zip tdminer - name: Upload TUI build artifact uses: actions/upload-artifact@v4 with: if-no-files-found: error - name: Twitch.Drops.Miner.TUI.Linux-${{matrix.arch}} - path: Twitch.Drops.Miner.TUI.Linux-${{matrix.arch}}.zip + name: DropForge.TUI.Linux-${{matrix.arch}} + path: DropForge.TUI.Linux-${{matrix.arch}}.zip linux-pyinstaller: name: Linux (PyInstaller) (${{matrix.arch}}) @@ -331,17 +378,17 @@ jobs: - name: Create release folder run: | - folder='Twitch Drops Miner' + folder='DropForge' mkdir "${folder}" cp manual.txt dist/* "${folder}" - 7z a 'Twitch.Drops.Miner.Linux.PyInstaller-${{matrix.arch}}.zip' "${folder}" + 7z a 'DropForge.Linux.PyInstaller-${{matrix.arch}}.zip' "${folder}" - name: Upload build artifact uses: actions/upload-artifact@v4 with: if-no-files-found: error - name: Twitch.Drops.Miner.Linux.PyInstaller-${{matrix.arch}} - path: Twitch.Drops.Miner.Linux.PyInstaller-${{matrix.arch}}.zip + name: DropForge.Linux.PyInstaller-${{matrix.arch}} + path: DropForge.Linux.PyInstaller-${{matrix.arch}}.zip linux-appimage: name: Linux (AppImage) (${{matrix.arch}}) @@ -393,23 +440,24 @@ jobs: - name: Create release folder run: | - folder='Twitch Drops Miner' + folder='DropForge' mkdir "${folder}" cp *.AppImage manual.txt "${folder}" - 7z a 'Twitch.Drops.Miner.Linux.AppImage-${{matrix.arch}}.zip' "${folder}" + 7z a 'DropForge.Linux.AppImage-${{matrix.arch}}.zip' "${folder}" - name: Upload build artifact uses: actions/upload-artifact@v4 with: if-no-files-found: error - name: Twitch.Drops.Miner.Linux.AppImage-${{matrix.arch}} - path: Twitch.Drops.Miner.Linux.AppImage-${{matrix.arch}}.zip + name: DropForge.Linux.AppImage-${{matrix.arch}} + path: DropForge.Linux.AppImage-${{matrix.arch}}.zip update_releases_page: name: Upload builds to Releases if: github.event_name != 'pull_request' needs: - windows + - web - linux-pyinstaller - linux-appimage - linux-tui @@ -442,30 +490,34 @@ jobs: artifactErrorsFailBuild: true artifacts: artifacts/*/* body: | - **Twitch Drops Miner Release** + **DropForge Release** - Build date: `${{steps.vars.outputs.date_now}}` - Reference commit: ${{github.sha}} - **Terminal UI install** + **Linux server or CLI install** - Linux/macOS: + Linux: ```sh curl -fsSL https://raw.githubusercontent.com/HimanM/TwitchDropsMiner/main/scripts/install.sh | sh ``` + Choose the authenticated DropForge Web UI or terminal CLI when prompted. Web installs default to localhost on port `17473`; use Tailscale Serve for private remote access or explicitly select `0.0.0.0` for a trusted LAN. + + macOS uses the same command and installs the terminal release. + On Termux, install prerequisites first: ```sh pkg install python clang curl tar ``` - Run `tdminer tui` for the richer Linux/macOS Textual interface, or `tdminer cli` for the portable prompt-based interface used by Windows/source installs and Termux-style terminals. + Run `tdminer tui` for the richer macOS Textual interface, or `tdminer cli` for the portable prompt-based interface used by source installs and Termux-style terminals. The portable CLI includes a boxed slash-command input. Type `/` for commands, `/priority add ` or `/exclude add ` for game completion, and `/switch ` for channel completion. - The `tdminer` release binaries are self-contained and do not require Linux/macOS users to install Python first. The binary installer needs `curl` and `unzip`, installs to `~/.local/bin` by default, and can be redirected with `TDMINER_INSTALL_DIR=/path/to/bin`. + The Linux installer manages source releases, dependencies, systemd, and persistent data under `~/.local/share/tdminer`. The macOS release binary is self-contained. Launchers install to `~/.local/bin` by default and can be redirected with `TDMINER_INSTALL_DIR=/path/to/bin`. name: "Release v${{steps.vars.outputs.app_version}}" prerelease: false diff --git a/.gitignore b/.gitignore index 2c1ae27..7ea9039 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,7 @@ __pycache__ /*.exe /*.zip /*.tmp -/Twitch Drops Miner +/DropForge # Dev files *.new /env @@ -29,3 +29,5 @@ settings.json /.venv-linux-build /.venv-tui /graphify-out +/web/frontend/node_modules/ +/web/frontend/*.tsbuildinfo diff --git a/DEPLOY.md b/DEPLOY.md index dc1e6d6..355e2ef 100644 --- a/DEPLOY.md +++ b/DEPLOY.md @@ -1,6 +1,6 @@ # Deployment Guide -Complete guide to running and building Twitch Drops Miner across every platform and frontend. +Complete guide to running and building DropForge across every platform and frontend. ## Table of Contents @@ -292,7 +292,7 @@ pyinstaller build.spec pack.bat ``` -Output: `dist/Twitch Drops Miner (by HimanM).exe` +Output: `dist/DropForge.exe` The `build.bat` script: 1. Creates/uses the `env/` virtual environment @@ -329,7 +329,7 @@ cd - LD_LIBRARY_PATH=/tmp/libXft/lib xvfb-run --auto-servernum pyinstaller build.spec ``` -Output: `dist/Twitch Drops Miner (by HimanM)` (one-dir) or single executable +Output: `dist/DropForge` (one-dir) or single executable #### Linux GUI Build (AppImage) @@ -362,7 +362,7 @@ pip install -r requirements.txt pyinstaller pyinstaller build.spec --noconfirm ``` -Output: `dist/Twitch Drops Miner (by HimanM).app` +Output: `dist/DropForge.app` ### Building the TUI / CLI Binary diff --git a/README.md b/README.md index 404029d..f9c4c3e 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,18 @@ -# Twitch Drops Miner by HimanM +
+
+
DropForge
+Private mining control room
++ Drops keep moving. Your miner stays close. +
++ Control campaigns, channels, settings, and Twitch device login from one private server. +
+DropForge
+Private mining control room
+Sign in to manage the miner on this server.
+ + +Use the recovery code printed during installation. Resetting revokes every browser session.
+ + +Save this new one-time recovery code before signing in.
+{nextRecovery}
+
+ {value}
+DropForge
+Self-hosted drops miner
++ {state.miner.running ? (current.campaign || "Inventory and channel state update automatically.") : "Start mining without restarting the web control room."} +
+Connect Twitch
+Open Twitch activation and enter code {state.login.user_code}.
+{current.rewards || "No reward selected yet"}
{channel.name}
{channel.game || "Twitch stream"}
{channel.viewers || "0"} viewers
{description}
No campaigns match
Try another filter or reload the inventory.
{campaign.game}
{benefit.name}
{drop.claimed ? "Claimed" : `${drop.current_minutes}/${drop.required_minutes} min`}
{channel.name}
{channel.watching &&{channel.game || "No category"} · {channel.viewers || "0"} viewers · {channel.drops ? "Drops enabled" : "No drops"}
The miner checks these games in order.
Campaigns for these games are skipped.
Changing the admin password revokes every browser session. Invalidating Twitch auth removes the saved Twitch token and starts device login again.
+{label}
{description}
{label}
{description}
No games added.
:{logs.length ? logs.join("\n") : "No log messages yet."}