Compare commits

..

No commits in common. "main" and "v4.1.13" have entirely different histories.

44 changed files with 7126 additions and 331 deletions

View File

@ -0,0 +1,72 @@
{
"permissions": {
"allow": [
"Bash(ren \"C:\\\\Users\\\\ploet\\\\Desktop\\\\Twitch-YouTube\\\\Twitch\\\\Twitch_VOD_Manager_V_3.2.1.pyw\" \"Twitch_VOD_Manager_V_3.2.2.pyw\")",
"Bash(cmd /c ren:*)",
"Bash(npm install)",
"Bash(npm run build:win:*)",
"Bash(npm run build:portable:*)",
"Bash(npx electron-builder --win portable --config.win.signAndEditExecutable=false)",
"Bash(dir \"C:\\\\Users\\\\ploet\\\\Desktop\\\\Twitch-YouTube\\\\Twitch\\\\TwitchVODManager-Electron\\\\dist\")",
"Bash(python -m py_compile:*)",
"Bash(dir \"C:\\\\Users\\\\ploet\\\\Desktop\\\\Twitch Downloader\\\\*.exe\")",
"Bash(C:UsersploetAppDataRoamingPythonPython311Scriptspyinstaller.exe:*)",
"Bash(python -m PyInstaller:*)",
"Bash(dir \"C:\\\\Users\\\\ploet\\\\Desktop\\\\Twitch Downloader\\\\dist\\\\Twitch_VOD_Manager.exe\")",
"Bash(powershell -command:*)",
"Bash(python:*)",
"Bash(start \"\" \"Twitch_VOD_Manager.exe\")",
"Bash(tasklist:*)",
"Bash(findstr:*)",
"Bash(pip install:*)",
"Bash(taskkill:*)",
"Bash(ping:*)",
"Bash(move:*)",
"Bash(start Twitch_VOD_Manager.exe)",
"Bash(timeout:*)",
"Bash(\"C:\\\\Program Files \\(x86\\)\\\\Inno Setup 6\\\\ISCC.exe\" \"C:\\\\Users\\\\ploet\\\\Desktop\\\\Twitch Downloader\\\\installer.iss\")",
"Bash(\"/c/Users/ploet/AppData/Local/Programs/Inno Setup 6/ISCC.exe\" \"C:/Users/ploet/Desktop/Twitch Downloader/installer.iss\")",
"Bash(curl:*)",
"Bash(start \"\" \"/c/Users/ploet/Desktop/Twitch_VOD_Manager_Setup_test.exe\")",
"Bash(\"/c/Program Files/Twitch VOD Manager/unins000.exe\" /VERYSILENT /SUPPRESSMSGBOXES)",
"Bash(start \"\" \"/c/Users/ploet/Desktop/Twitch_VOD_Manager_Setup_NEW.exe\")",
"Bash(start \"\" \"/c/Users/ploet/Desktop/Twitch Downloader/installer_output/Twitch_VOD_Manager_Setup_3.4.8.exe\")",
"Bash(start \"\" \"/c/Users/ploet/Desktop/Twitch Downloader/installer_output/Twitch_VOD_Manager_Setup_3.4.10.exe\")",
"Bash(find:*)",
"Bash(start \"\" \"/c/Users/ploet/Desktop/Twitch Downloader/installer_output/Twitch_VOD_Manager_Setup_3.4.12.exe\")",
"Bash(start \"\" \"/c/Users/ploet/Desktop/Twitch Downloader/installer_output/Twitch_VOD_Manager_Setup_3.4.14.exe\")",
"Bash(start \"\" \"/c/Users/ploet/Desktop/Twitch Downloader/installer_output/Twitch_VOD_Manager_Setup_3.4.16.exe\")",
"Bash(start \"\" \"/c/Users/ploet/Desktop/Twitch Downloader/installer_output/Twitch_VOD_Manager_Setup_3.4.18.exe\")",
"Bash(\"C:\\\\Program Files \\(x86\\)\\\\Inno Setup 6\\\\ISCC.exe\" installer.iss)",
"Bash(\"C:/Program Files \\(x86\\)/Inno Setup 6/ISCC.exe\" \"C:/Users/ploet/Desktop/Twitch Downloader/installer.iss\")",
"Bash(ls:*)",
"Bash(where:*)",
"Bash(cmd.exe /c \"\"\"C:\\\\Program Files \\(x86\\)\\\\Inno Setup 6\\\\ISCC.exe\"\" \"\"C:\\\\Users\\\\ploet\\\\Desktop\\\\Twitch Downloader\\\\installer.iss\"\"\")",
"Bash(cmd.exe /c \"dir \"\"C:\\\\Program Files \\(x86\\)\\\\Inno Setup 6\"\"\")",
"Bash(powershell.exe -Command \"Test-Path ''C:\\\\Program Files \\(x86\\)\\\\Inno Setup 6\\\\ISCC.exe''\")",
"Bash(powershell.exe:*)",
"Bash(git init:*)",
"Bash(git add:*)",
"Bash(git rm:*)",
"Bash(git commit -m \"$\\(cat <<''EOF''\nInitial commit: Twitch VOD Manager v3.5.3\n\n- Main application with auto-update functionality\n- PyInstaller spec for building standalone EXE\n- Inno Setup installer script with silent update support\n- Server version.json for update checking\n\nFeatures:\n- Download Twitch VODs\n- Auto-update with silent installation\n- Settings stored in ProgramData\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>\nEOF\n\\)\")",
"Bash(git config:*)",
"Bash(git commit:*)",
"Bash(gh auth:*)",
"Bash(npm run build:*)",
"Bash(npm run dist:win:*)",
"Bash(git push:*)",
"Bash(gh release create v3.6.0 \"release/Twitch VOD Manager Setup 3.6.0.exe\" --title \"Twitch VOD Manager v3.6.0\" --notes \"$\\(cat <<''EOF''\n## What''s New in v3.6.0\n\n### New Features\n- **Video Cutter** - Cut and trim your downloaded VODs with a visual timeline\n - Preview frames at any position\n - Set precise start and end times\n - Fast cutting using stream copy \\(no re-encoding\\)\n \n- **Video Merge** - Combine multiple video files into one\n - Add multiple videos and reorder them\n - Fast merging with stream copy\n \n- **Part-based Downloads** - Split long VODs into manageable segments\n - Configure segment length in settings\n - Automatically splits downloads into parts\n\n### Improvements\n- Enhanced download progress with speed and ETA display\n- New navigation tabs for better organization\n- Updated UI with new tool icons\n\n### Technical\n- FFmpeg/FFprobe integration for video processing\n- Improved IPC communication between main and renderer\n- Version bump to 3.6.0\nEOF\n\\)\")",
"Bash(powershell:*)",
"Bash(winget install:*)",
"Bash(\"C:\\\\Program Files\\\\GitHub CLI\\\\gh.exe\" auth status)",
"Bash(\"C:\\\\Program Files\\\\GitHub CLI\\\\gh.exe\" release create:*)",
"Bash(npm start)",
"Bash(\"C:\\\\Program Files\\\\GitHub CLI\\\\gh.exe\" release create v3.6.1 \"release/Twitch VOD Manager Setup 3.6.1.exe\" --title \"Twitch VOD Manager v3.6.1\" --notes \"## What''s New in v3.6.1\n\n### New Feature: Clip erstellen\n- **Time-Range Downloads** - Download specific portions of VODs\n - Click ''Clip'' button on any VOD\n - Use sliders or time inputs to select start/end times\n - Set custom part numbers for continuations\n - Downloads only the selected time range\n\n### All Features \\(v3.6.x\\)\n- VOD Downloads \\(full or part-based\\)\n- Clip Downloads from Twitch\n- Video Cutter for local files \\(FFmpeg\\)\n- Video Merge \\(combine multiple videos\\)\n- Time-Range VOD Downloads \\(new\\)\n- Multiple Themes \\(Twitch/Discord/YouTube/Apple\\)\n- Auto-Update Check\n\n### Technical\n- Uses streamlink --hls-start-offset and --hls-duration for precise downloads\n- CustomClip data structure for queue items\")",
"Bash(explorer \"C:\\\\Users\\\\ploet\\\\Desktop\\\\Twitch Downloader\\\\typescript-version\\\\release\")",
"Bash(wmic:*)",
"Bash(reg query \"HKCU\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Uninstall\" /s)",
"Bash(dir /b /ad \"C:\\\\Users\\\\ploet\\\\AppData\\\\Local\")",
"Bash(start \"\" \"C:\\\\Program Files \\(x86\\)\\\\Twitch VOD Manager\\\\unins000.exe\")"
]
}
}

33
.gitignore vendored
View File

@ -1,5 +1,32 @@
node_modules/
# Build artifacts
build/
dist/
release/
installer_output/
__pycache__/
*.pyc
*.pyw
*.spec
# Config with credentials
config.json
# Temp files
*.log
.DS_Store
nul
download_queue.json
# IDE
.vscode/
.idea/
# Docs workspace
docs/node_modules/
docs/dist/
docs/.astro/
# Executables
Twitch_VOD_Manager.exe
# Legacy artifacts (not used by TypeScript app)
server_files/
installer.iss

72
README.md Normal file
View File

@ -0,0 +1,72 @@
# Twitch VOD Manager
Twitch VOD Manager is a desktop app for browsing Twitch VODs, queueing downloads, creating clips, cutting local videos, and merging files.
The current codebase is TypeScript + Electron and ships Windows installer releases with in-app auto-update support.
## Documentation
- Full docs workspace: `docs/`
- Docs index: `docs/src/pages/index.astro`
Key guides:
- [Getting Started](docs/src/pages/getting-started.mdx)
- [Features](docs/src/pages/features.mdx)
- [Configuration](docs/src/pages/configuration.mdx)
- [Troubleshooting](docs/src/pages/troubleshooting.mdx)
- [Development](docs/src/pages/development.mdx)
- [Release Process](docs/src/pages/release-process.mdx)
## Main Features
- Streamer list with Twitch Helix VOD browser
- Queue-based VOD downloads
- Clip extraction workflow from VOD metadata
- Local video cutter with preview frame extraction
- Local video merge workflow
- GitHub release based in-app updates
## Requirements
- Windows 10/11
- Node.js 18+ and npm (for local development)
- `streamlink` in `PATH`
- `ffmpeg` and `ffprobe` in `PATH`
Optional (recommended for authenticated mode):
- Twitch app `Client ID` and `Client Secret`
## Run from source
```bash
cd "typescript-version"
npm install
npm run build
npm start
```
## Build installer
```bash
cd "typescript-version"
npm run dist:win
```
Output artifacts are generated in `typescript-version/release/`.
## Repository Structure
- `typescript-version/` - Electron app source and build config
- `docs/` - Astro + MDX documentation site
## Auto-Update Notes
For updates to reach installed clients, each release must include:
- `latest.yml`
- `Twitch-VOD-Manager-Setup-<version>.exe`
- `Twitch-VOD-Manager-Setup-<version>.exe.blockmap`
See [Release Process](docs/src/pages/release-process.mdx) for the full checklist.

View File

@ -1,90 +0,0 @@
# AI Release Guide (Gitea)
Diese Datei ist die verbindliche Anleitung fuer KI-Agenten, um Releases fuer dieses Projekt zu erstellen.
## Zielsystem
- Git Host: `https://git.24-music.de`
- Repo: `Administrator/Twitch-VOD-Manager`
- Default Branch: `main`
- Release-Assets muessen auf Gitea liegen, nicht auf GitHub/Codeberg.
## Sicherheitsregeln
- Token niemals in Dateien committen.
- Token niemals in Logs, README oder Code schreiben.
- Nur als Environment Variable nutzen:
- PowerShell: ``$env:GITEA_TOKEN="<token>"``
- Wenn Token kompromittiert wirkt: sofort rotieren.
## Voraussetzungen vor Release
1. `origin` muss auf Gitea zeigen:
- `https://git.24-music.de/Administrator/Twitch-VOD-Manager.git`
2. Working Tree darf keine ungewollten Aenderungen enthalten.
3. DNS fuer `git.24-music.de` muss auf `159.195.45.29` aufloesen.
4. Die App verwendet Gitea-Updater-URLs:
- In `src/main.ts` via `GITEA_*` Konstanten/API.
- In `package.json`:
- `"build.publish.url": "https://git.24-music.de/Administrator/Twitch-VOD-Manager/releases/download/v${version}/"`
## Standardablauf fuer neues Release
Beispiel fuer `4.2.2`.
1. Version setzen:
- `npm version 4.2.2 --no-git-tag-version`
2. Build + Schnelltest:
- `npm run build`
- `npm run test:e2e:update-logic`
3. Windows Installer bauen:
- `npx electron-builder --win`
4. Pruefen, dass Dateien existieren:
- `release/Twitch-VOD-Manager-Setup-4.2.2.exe`
- `release/Twitch-VOD-Manager-Setup-4.2.2.exe.blockmap`
- `release/latest.yml`
5. Commit + Tag:
- `git add package.json package-lock.json`
- `git commit -m "release: 4.2.2"`
- `git tag v4.2.2`
6. Push:
- `git push origin main`
- `git push origin v4.2.2`
7. Release auf Gitea anlegen und Assets hochladen (API):
- Endpoint: `POST /api/v1/repos/Administrator/Twitch-VOD-Manager/releases`
- Endpoint: `POST /api/v1/repos/Administrator/Twitch-VOD-Manager/releases/{id}/assets?name=<file>`
8. Verifikation:
- `GET /api/v1/repos/Administrator/Twitch-VOD-Manager/releases/latest` muss `v4.2.2` liefern.
- Download-Links muessen `200` geben:
- `/releases/download/v4.2.2/latest.yml`
- `/releases/download/v4.2.2/Twitch-VOD-Manager-Setup-4.2.2.exe`
## Verbindliche Asset-Regel
Pro aktuellem Release muessen mindestens diese 3 Dateien vorhanden sein:
- `Twitch-VOD-Manager-Setup-<version>.exe`
- `Twitch-VOD-Manager-Setup-<version>.exe.blockmap`
- `latest.yml`
Ohne diese Dateien funktioniert der Auto-Updater nicht zuverlaessig.
## Script-Hinweis
Es gibt ein Script: `scripts/release_gitea.mjs` (npm: `release:gitea`).
- Vor Nutzung sicherstellen, dass:
- `GITEA_TOKEN` gesetzt ist.
- `origin` korrekt ist.
- der Tag existiert oder der Workflow diesen sauber erstellt.
Wenn das Script fehlschlaegt, immer auf den manuellen Standardablauf oben zurueckfallen.
## DNS/Netzwerk Fallback (nur wenn lokal noetig)
Wenn lokales DNS noch alt cached und Requests fehlschlagen, HTTP-Tests mit erzwungener Aufloesung:
- `curl --resolve git.24-music.de:443:159.195.45.29 https://git.24-music.de/api/v1/version`
Nur fuer Tests nutzen, nicht als dauerhaften Workaround.

30
docs/README.md Normal file
View File

@ -0,0 +1,30 @@
# Twitch VOD Manager Docs
Documentation site for users and contributors, built with Astro + MDX.
## Local development
```bash
npm install
npm run dev
```
## Production build
```bash
npm run build
npm run preview
```
## Writing docs
- Add pages in `src/pages/` (`.astro` or `.mdx`)
- Shared layout lives in `src/layouts/BaseLayout.astro`
- Global styles live in `src/styles/global.css`
- Keep command examples copy-paste ready
## Scope
- User setup and troubleshooting
- Feature documentation
- Developer architecture and release workflow

7
docs/astro.config.mjs Normal file
View File

@ -0,0 +1,7 @@
import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';
export default defineConfig({
integrations: [mdx()],
site: 'https://github.com/Sucukdeluxe/Twitch-VOD-Manager'
});

6199
docs/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

15
docs/package.json Normal file
View File

@ -0,0 +1,15 @@
{
"name": "twitch-vod-manager-docs",
"private": true,
"version": "0.1.0",
"type": "module",
"scripts": {
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview"
},
"dependencies": {
"@astrojs/mdx": "^4.3.0",
"astro": "^5.5.0"
}
}

View File

@ -0,0 +1,62 @@
---
import '../styles/global.css';
interface Props {
title: string;
description?: string;
}
const { title, description = 'Twitch VOD Manager documentation' } = Astro.props;
const nav = [
{ href: '/', label: 'Overview' },
{ href: '/getting-started', label: 'Getting Started' },
{ href: '/features', label: 'Features' },
{ href: '/configuration', label: 'Configuration' },
{ href: '/troubleshooting', label: 'Troubleshooting' },
{ href: '/development', label: 'Development' },
{ href: '/release-process', label: 'Release Process' }
];
const pathname = Astro.url.pathname.endsWith('/') ? Astro.url.pathname : `${Astro.url.pathname}/`;
const isActive = (href: string): boolean => {
if (href === '/') {
return pathname === '/';
}
const normalizedHref = href.endsWith('/') ? href : `${href}/`;
return pathname.startsWith(normalizedHref);
};
---
<html lang="de">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content={description} />
<title>{title}</title>
</head>
<body>
<div class="layout">
<aside class="sidebar">
<h1 class="brand">Twitch VOD Manager</h1>
<p class="tagline">Product and developer documentation</p>
<nav>
<ul class="nav-list">
{nav.map((item) => (
<li>
<a href={item.href} class={isActive(item.href) ? 'active' : undefined}>{item.label}</a>
</li>
))}
</ul>
</nav>
</aside>
<main class="content">
<article class="doc">
<slot />
</article>
</main>
</div>
</body>
</html>

View File

@ -0,0 +1,41 @@
---
layout: ../layouts/BaseLayout.astro
title: Configuration
description: File locations and configuration keys used by the app.
---
# Configuration
## File Locations
The app stores runtime data in:
`C:\ProgramData\Twitch_VOD_Manager`
| File | Purpose |
| --- | --- |
| `config.json` | User settings and Twitch credentials |
| `download_queue.json` | Persistent download queue state |
Default download path:
`%USERPROFILE%\Desktop\Twitch_VODs`
## Main Config Keys
| Key | Description |
| --- | --- |
| `client_id` | Twitch application client id |
| `client_secret` | Twitch application client secret |
| `download_path` | Base output folder |
| `streamers` | Sidebar streamer list |
| `theme` | UI theme (`twitch`, `discord`, `youtube`, `apple`) |
| `download_mode` | Full VOD or parts mode |
| `part_minutes` | Split length in minutes for parts mode |
## Notes
- Credentials are optional. If empty, the app uses public mode for streamer/VOD discovery.
- Credentials are currently stored in plain text config file.
- The app trims credential fields before saving to reduce whitespace issues.
- Legacy keys can exist in config from older versions; unknown keys are ignored.

View File

@ -0,0 +1,72 @@
---
layout: ../layouts/BaseLayout.astro
title: Development
description: Local development setup and architecture for contributors.
---
# Development
## Local Setup
```bash
cd "typescript-version"
npm install
npm run build
npm start
```
## Architecture
| Layer | File(s) | Responsibility |
| --- | --- | --- |
| Main process | `src/main.ts` | IPC handlers, Twitch API, downloads, ffmpeg/streamlink execution, updater |
| Preload bridge | `src/preload.ts` | Safe API surface exposed to renderer |
| Renderer shell | `src/index.html` + `src/styles.css` | UI markup and styling |
| Renderer modules | `src/renderer*.ts` | UI logic by feature (streamers, queue, settings, updates, shared state) |
## Renderer Module Split
- `renderer-shared.ts`: common state + DOM helper functions
- `renderer-streamers.ts`: streamer list + VOD loading
- `renderer-queue.ts`: queue rendering + start/stop behavior
- `renderer-settings.ts`: credentials, folder, and theme handling
- `renderer-updates.ts`: update banner and download/install flow
- `renderer.ts`: app init + clip/cutter/merge orchestration
## Useful Commands
```bash
# Build TypeScript only
npm run build
# Run app in dev mode
npm start
# Quick UI smoke test
npm run test:e2e
# Template guide + live preview checks
npm run test:e2e:guide
# Full end-to-end validation pass
npm run test:e2e:full
# Release validation suite (build + smoke + guide + full)
npm run test:e2e:release
# Extra stress pass (runs release suite 3x)
npm run test:e2e:stress
# Build Windows installer
npm run dist:win
```
## Docs Workspace
```bash
cd "docs"
npm install
npm run dev
```
Docs site is Astro + MDX and can be updated independently from app runtime code.

View File

@ -0,0 +1,44 @@
---
layout: ../layouts/BaseLayout.astro
title: Features
description: Complete feature overview for Twitch VOD Manager.
---
# Features
## Twitch VOD Browser
- Add streamers to a persistent sidebar list.
- Fetches user + archive VODs through Twitch Helix API when credentials are configured.
- Falls back to public Twitch GraphQL mode when no credentials are set.
- Automatic reconnect/re-auth if the app is temporarily disconnected.
## Download Queue
- Add full VODs to queue with one click.
- Queue supports start/stop and removal of completed entries.
- Download process persists in local queue file.
## Clip Creation from VODs
- Open **Clip** dialog from any VOD card.
- Set start/end time and optional part number.
- Queue clip jobs with metadata for naming strategy.
## Video Cutter (Local Files)
- Select any local video and inspect duration/fps/resolution.
- Extract preview frames via `ffprobe`/`ffmpeg`.
- Export cut segment as new MP4 file.
## Video Merge (Local Files)
- Choose multiple local video files.
- Reorder via up/down controls.
- Merge into one output file.
## In-App Auto-Update
- Uses GitHub release artifacts through `electron-updater`.
- Detects new versions, downloads update, then installs on restart.
- Requires release assets: installer, blockmap, and `latest.yml`.

View File

@ -0,0 +1,52 @@
---
layout: ../layouts/BaseLayout.astro
title: Getting Started
description: Install and configure Twitch VOD Manager quickly.
---
# Getting Started
## Requirements
- Windows 10/11 (installer and paths are currently Windows-first)
The app can auto-install missing runtime tools (`streamlink`, `ffmpeg`, `ffprobe`) into:
`C:\ProgramData\Twitch_VOD_Manager\tools`
Manual installation is still supported.
Optional but recommended:
- Twitch API app with `Client ID` and `Client Secret` (for authenticated Helix mode)
## Install
1. Download the latest setup from GitHub Releases.
2. Run `Twitch-VOD-Manager-Setup-<version>.exe`.
3. Launch the app.
## First-Time Setup
1. Open **Einstellungen**.
2. Choose your download path.
3. Optional: enter `Client ID` and `Client Secret` for authenticated mode.
4. Click **Speichern & Verbinden**.
5. Add a streamer in the header input and press `+`.
If everything is correct, VOD cards appear.
- With credentials: status is `Verbunden`.
- Without credentials: status shows `Ohne Login (Public Modus)` and VOD downloads still work.
## Verify Tools
In PowerShell or CMD:
```bash
streamlink --version
ffmpeg -version
ffprobe -version
```
If one command fails, install the missing tool and restart the app.

View File

@ -0,0 +1,51 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
---
<BaseLayout title="Twitch VOD Manager Docs" description="Official documentation for Twitch VOD Manager users and contributors.">
<h1>Twitch VOD Manager Documentation</h1>
<p>
This documentation covers end-user setup, Twitch API configuration, troubleshooting,
and developer workflows for the TypeScript/Electron app.
</p>
<div class="chips">
<span class="chip">Electron</span>
<span class="chip">TypeScript</span>
<span class="chip">Streamlink</span>
<span class="chip">FFmpeg</span>
<span class="chip">Auto-Update</span>
</div>
<div class="card-grid">
<a class="card" href="/getting-started">
<h3>Getting Started</h3>
<p>Install the app, set Twitch API credentials, and run your first VOD download.</p>
</a>
<a class="card" href="/features">
<h3>Features</h3>
<p>Learn VOD browsing, queue processing, clip creation, cutter, merge, and updates.</p>
</a>
<a class="card" href="/configuration">
<h3>Configuration</h3>
<p>Understand config paths, available settings, and how local files are stored.</p>
</a>
<a class="card" href="/troubleshooting">
<h3>Troubleshooting</h3>
<p>Fix common issues like "Keine VODs", missing tools, and update problems.</p>
</a>
<a class="card" href="/development">
<h3>Development</h3>
<p>Set up local development, architecture overview, and code structure details.</p>
</a>
<a class="card" href="/release-process">
<h3>Release Process</h3>
<p>Ship new installer builds and GitHub releases compatible with auto-updater.</p>
</a>
</div>
</BaseLayout>

View File

@ -0,0 +1,64 @@
---
layout: ../layouts/BaseLayout.astro
title: Release Process
description: Standardized release checklist for auto-update compatible builds.
---
# Release Process
This project uses GitHub Releases + `electron-updater`.
## 1) Bump Version
Update app version consistently:
- `typescript-version/package.json`
- `typescript-version/package-lock.json`
- `typescript-version/src/main.ts` (`APP_VERSION`)
- Optional visible fallback text in `src/index.html`
## 2) Build Installer Artifacts
```bash
cd "typescript-version"
npm run dist:win
```
`dist:win` already runs the full release validation gate (`test:e2e:release`) before packaging.
For extra confidence before major releases, run:
```bash
npm run test:e2e:stress
```
Expected outputs in `typescript-version/release/`:
- `latest.yml`
- `Twitch-VOD-Manager-Setup-<version>.exe`
- `Twitch-VOD-Manager-Setup-<version>.exe.blockmap`
## 3) Commit + Push
Commit code/version changes and push to `master`.
## 4) Create GitHub Release
Tag format: `v<version>` (example: `v3.7.6`).
Attach exactly the 3 update artifacts from step 2.
## 5) Verify Update Path
- Open app on older version.
- Trigger update check.
- Confirm banner appears and update can be downloaded/installed.
## Quick Checklist
- [ ] Version bumped everywhere
- [ ] `npm run build` passes
- [ ] `npm run dist:win` passes
- [ ] Release tag created
- [ ] `latest.yml` + `.exe` + `.blockmap` uploaded
- [ ] Manual update flow verified

View File

@ -0,0 +1,17 @@
---
layout: ../layouts/BaseLayout.astro
title: Migration Roadmap
---
# Migration Roadmap
## UI Stack
- Renderer wird schrittweise von HTML-Monolith zu TypeScript-Modulen migriert.
- Styles sind bereits in eine eigene CSS-Datei ausgelagert.
## Nächste Schritte
1. Renderer in weitere Feature-Module aufteilen (Cutter/Merge/Clips).
2. Komponenten-Ansatz einführen (Astro UI docs, später optional Rust-backend tooling).
3. API- und Release-Prozess in MDX dokumentieren.

View File

@ -0,0 +1,64 @@
---
layout: ../layouts/BaseLayout.astro
title: Troubleshooting
description: Fix common Twitch VOD Manager issues quickly.
---
# Troubleshooting
## "Keine VODs" after adding streamer
1. Ensure the streamer exists and has archive VODs.
2. Press **Aktualisieren**.
3. If you use credentials, re-save `Client ID` + `Client Secret` in **Einstellungen**.
4. Check bottom status bar:
- `Verbunden` in authenticated mode
- `Ohne Login (Public Modus)` in credential-free mode
The app retries auth automatically on expired tokens and can continue in public mode without credentials.
## "Streamer nicht gefunden"
- Use login name only (no URL, no `@`).
- Names are normalized to lowercase.
- Verify streamer spelling directly on Twitch.
## Clip/Cutter/Merge duration shows 0 or preview fails
Usually caused by broken `ffprobe` detection.
Check:
```bash
ffprobe -version
```
If missing, install FFmpeg package that includes `ffprobe` and restart app.
## "Streamlink not found"
Install streamlink and verify:
```bash
streamlink --version
```
Then restart the app.
## Auto-update does not trigger
Release must include all of:
- `latest.yml`
- `Twitch-VOD-Manager-Setup-<version>.exe`
- `Twitch-VOD-Manager-Setup-<version>.exe.blockmap`
Tag version must match app version (example: `v3.7.6`).
## Debug log for failed downloads
From `v3.7.8`, detailed downloader logs are written to:
`C:\ProgramData\Twitch_VOD_Manager\debug.log`
If a download instantly switches from `Stoppen` back to `Start`, check the latest lines in that file for streamlink exit reasons.

205
docs/src/styles/global.css Normal file
View File

@ -0,0 +1,205 @@
:root {
color-scheme: dark;
font-family: 'Segoe UI', Tahoma, sans-serif;
--bg-1: #0f1217;
--bg-2: #161c26;
--bg-3: #1d2734;
--text: #eef3fb;
--muted: #aab8cf;
--line: #2b3546;
--link: #7db6ff;
--link-hover: #a8cdff;
--chip: #22344b;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
min-height: 100vh;
background: radial-gradient(circle at top, #1a2432 0%, var(--bg-1) 55%);
color: var(--text);
}
.layout {
max-width: 1280px;
margin: 0 auto;
padding: 28px;
display: grid;
grid-template-columns: 290px minmax(0, 1fr);
gap: 24px;
}
.sidebar {
position: sticky;
top: 18px;
align-self: start;
background: linear-gradient(180deg, var(--bg-2), #131922);
border: 1px solid var(--line);
border-radius: 14px;
padding: 18px;
}
.brand {
margin: 0;
font-size: 1.2rem;
}
.tagline {
margin-top: 8px;
color: var(--muted);
font-size: 0.9rem;
}
.nav-list {
list-style: none;
margin: 20px 0 0;
padding: 0;
display: flex;
flex-direction: column;
gap: 8px;
}
.nav-list a {
display: block;
padding: 8px 10px;
border-radius: 8px;
text-decoration: none;
color: var(--muted);
border: 1px solid transparent;
}
.nav-list a:hover {
color: var(--text);
border-color: var(--line);
background: rgba(125, 182, 255, 0.08);
}
.nav-list a.active {
color: var(--text);
background: rgba(125, 182, 255, 0.16);
border-color: rgba(125, 182, 255, 0.35);
}
.content {
min-width: 0;
}
.doc {
background: linear-gradient(180deg, var(--bg-2), #121822);
border: 1px solid var(--line);
border-radius: 14px;
padding: 26px;
}
h1,
h2,
h3 {
line-height: 1.3;
}
h1 {
margin-top: 0;
font-size: 2rem;
}
h2,
h3 {
margin-top: 1.7rem;
}
p,
li {
color: var(--muted);
line-height: 1.65;
}
a {
color: var(--link);
}
a:hover {
color: var(--link-hover);
}
pre {
overflow-x: auto;
background: #0c1118;
border: 1px solid var(--line);
border-radius: 10px;
padding: 14px;
}
code {
font-family: Consolas, 'Courier New', monospace;
font-size: 0.92em;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 10px;
}
th,
td {
border: 1px solid var(--line);
text-align: left;
padding: 10px;
}
th {
background: #111a25;
}
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 12px;
margin-top: 20px;
}
.card {
border: 1px solid var(--line);
border-radius: 12px;
background: linear-gradient(180deg, #172233, #111824);
padding: 14px;
}
.card h3 {
margin-top: 0;
margin-bottom: 8px;
font-size: 1rem;
}
.card p {
margin: 0;
}
.chips {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.chip {
border: 1px solid rgba(125, 182, 255, 0.35);
background: var(--chip);
color: #dbe9ff;
border-radius: 999px;
padding: 4px 10px;
font-size: 0.84rem;
}
@media (max-width: 980px) {
.layout {
grid-template-columns: 1fr;
padding: 16px;
}
.sidebar {
position: static;
}
}

3
docs/tsconfig.json Normal file
View File

@ -0,0 +1,3 @@
{
"extends": "astro/tsconfigs/strict"
}

View File

@ -1,159 +0,0 @@
import fs from "node:fs";
import path from "node:path";
import { spawnSync } from "node:child_process";
const NPM_EXECUTABLE = process.platform === "win32" ? "npm.cmd" : "npm";
const BASE_URL = String(process.env.GITEA_BASE_URL || "https://git.24-music.de").replace(/\/+$/, "");
const OWNER = String(process.env.GITEA_REPO_OWNER || "Administrator").trim();
const REPO = String(process.env.GITEA_REPO_NAME || "Twitch-VOD-Manager").trim();
function run(command, args, options = {}) {
const result = spawnSync(command, args, {
cwd: process.cwd(),
encoding: "utf8",
input: options.input,
stdio: options.capture ? ["pipe", "pipe", "pipe"] : "inherit"
});
if (result.status !== 0) {
const stderr = String(result.stderr || "").trim();
const stdout = String(result.stdout || "").trim();
const details = [stderr, stdout].filter(Boolean).join("\n");
throw new Error(`Command failed: ${command} ${args.join(" ")}${details ? `\n${details}` : ""}`);
}
return String(result.stdout || "");
}
function parseArgs(argv) {
const args = argv.slice(2);
if (args.includes("--help") || args.includes("-h")) {
return { help: true };
}
const dryRun = args.includes("--dry-run");
const version = args.find((arg) => arg !== "--dry-run") || "";
const notes = args.filter((arg) => arg !== "--dry-run").slice(1).join(" ").trim();
return { help: false, dryRun, version, notes };
}
function ensureVersion(version) {
if (!/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(String(version || "").trim())) {
throw new Error("Invalid version format. Expected e.g. 4.2.0");
}
return String(version).trim();
}
function getAuthHeader() {
const token = String(process.env.GITEA_TOKEN || process.env.FORGEJO_TOKEN || "").trim();
if (token) {
return `token ${token}`;
}
const output = run("git", ["credential", "fill"], {
capture: true,
input: `protocol=https\nhost=${new URL(BASE_URL).host}\n\n`
});
const map = new Map();
for (const line of output.split(/\r?\n/)) {
if (!line.includes("=")) continue;
const [key, value] = line.split("=", 2);
map.set(key, value);
}
const username = map.get("username");
const password = map.get("password");
if (!username || !password) {
throw new Error("Missing Gitea credentials. Set GITEA_TOKEN or configure git credential helper.");
}
return `Basic ${Buffer.from(`${username}:${password}`, "utf8").toString("base64")}`;
}
async function apiRequest(method, url, authHeader, body, contentType = "application/json") {
const headers = { Accept: "application/json", Authorization: authHeader };
if (body !== undefined) headers["Content-Type"] = contentType;
const response = await fetch(url, { method, headers, body });
const text = await response.text();
let parsed = null;
try { parsed = text ? JSON.parse(text) : null; } catch { parsed = text; }
return { ok: response.ok, status: response.status, body: parsed };
}
function ensureAssets(version) {
const releaseDir = path.join(process.cwd(), "release");
const files = [
`Twitch-VOD-Manager-Setup-${version}.exe`,
`Twitch-VOD-Manager-Setup-${version}.exe.blockmap`,
"latest.yml"
];
for (const file of files) {
const fullPath = path.join(releaseDir, file);
if (!fs.existsSync(fullPath)) {
throw new Error(`Missing release artifact: ${fullPath}`);
}
}
return { releaseDir, files };
}
async function createOrGetRelease(baseApi, tag, authHeader, notes) {
const existing = await apiRequest("GET", `${baseApi}/releases/tags/${encodeURIComponent(tag)}`, authHeader);
if (existing.ok) return existing.body;
const payload = {
tag_name: tag,
target_commitish: "main",
name: tag,
body: notes || `Release ${tag}`,
draft: false,
prerelease: false
};
const created = await apiRequest("POST", `${baseApi}/releases`, authHeader, JSON.stringify(payload));
if (!created.ok) {
throw new Error(`Failed to create release (${created.status}): ${JSON.stringify(created.body)}`);
}
return created.body;
}
async function uploadAssets(baseApi, releaseId, authHeader, releaseDir, files) {
for (const fileName of files) {
const filePath = path.join(releaseDir, fileName);
const fileData = fs.readFileSync(filePath);
const uploadUrl = `${baseApi}/releases/${releaseId}/assets?name=${encodeURIComponent(fileName)}`;
const response = await apiRequest("POST", uploadUrl, authHeader, fileData, "application/octet-stream");
if (response.ok || response.status === 409 || response.status === 422) {
continue;
}
throw new Error(`Asset upload failed for ${fileName} (${response.status}): ${JSON.stringify(response.body)}`);
}
}
async function main() {
const args = parseArgs(process.argv);
if (args.help) {
process.stdout.write("Usage: npm run release:gitea -- <version> [release notes] [--dry-run]\n");
process.stdout.write("Env: GITEA_BASE_URL, GITEA_REPO_OWNER, GITEA_REPO_NAME, GITEA_TOKEN\n");
return;
}
const version = ensureVersion(args.version);
const tag = `v${version}`;
const authHeader = getAuthHeader();
const baseApi = `${BASE_URL}/api/v1/repos/${OWNER}/${REPO}`;
run("git", ["fetch", "--tags"]);
if (!args.dryRun) {
run("git", ["push", "origin", "main"]);
run("git", ["push", "origin", tag]);
}
run(NPM_EXECUTABLE, ["run", "dist:win"]);
const assets = ensureAssets(version);
if (args.dryRun) {
process.stdout.write(`Dry run complete for ${tag}\n`);
return;
}
const release = await createOrGetRelease(baseApi, tag, authHeader, args.notes);
await uploadAssets(baseApi, release.id, authHeader, assets.releaseDir, assets.files);
process.stdout.write(`Release published: ${release.html_url || `${BASE_URL}/${OWNER}/${REPO}/releases/tag/${tag}`}\n`);
}
main().catch((error) => {
process.stderr.write(`${String(error?.message || error)}\n`);
process.exit(1);
});

5
typescript-version/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
node_modules/
dist/
release/
*.log
.DS_Store

View File

@ -1,12 +1,12 @@
{
"name": "twitch-vod-manager",
"version": "4.2.1",
"version": "4.1.13",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "twitch-vod-manager",
"version": "4.2.1",
"version": "4.1.13",
"license": "MIT",
"dependencies": {
"axios": "^1.6.0",
@ -682,6 +682,7 @@
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
@ -836,7 +837,6 @@
"integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"archiver-utils": "^2.1.0",
"async": "^3.2.4",
@ -856,7 +856,6 @@
"integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"glob": "^7.1.4",
"graceful-fs": "^4.2.0",
@ -879,7 +878,6 @@
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
@ -895,8 +893,7 @@
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"dev": true,
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/archiver-utils/node_modules/string_decoder": {
"version": "1.1.1",
@ -904,7 +901,6 @@
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"safe-buffer": "~5.1.0"
}
@ -1015,7 +1011,6 @@
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"buffer": "^5.5.0",
"inherits": "^2.0.4",
@ -1386,7 +1381,6 @@
"integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"buffer-crc32": "^0.2.13",
"crc32-stream": "^4.0.2",
@ -1487,7 +1481,6 @@
"integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==",
"dev": true,
"license": "Apache-2.0",
"peer": true,
"bin": {
"crc32": "bin/crc32.njs"
},
@ -1501,7 +1494,6 @@
"integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"crc-32": "^1.2.0",
"readable-stream": "^3.4.0"
@ -1860,7 +1852,6 @@
"integrity": "sha512-oHkV0iogWfyK+ah9ZIvMDpei1m9ZRpdXcvde1wTpra2U8AFDNNpqJdnin5z+PM1GbQ5BoaKCWas2HSjtR0HwMg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"app-builder-lib": "24.13.3",
"archiver": "^5.3.1",
@ -1874,7 +1865,6 @@
"integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
@ -1890,7 +1880,6 @@
"integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"universalify": "^2.0.0"
},
@ -1904,7 +1893,6 @@
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">= 10.0.0"
}
@ -2329,8 +2317,7 @@
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
"dev": true,
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/fs-extra": {
"version": "8.1.0",
@ -2818,8 +2805,7 @@
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
"dev": true,
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/isbinaryfile": {
"version": "5.0.7",
@ -2954,7 +2940,6 @@
"integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"readable-stream": "^2.0.5"
},
@ -2968,7 +2953,6 @@
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
@ -2984,8 +2968,7 @@
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"dev": true,
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/lazystream/node_modules/string_decoder": {
"version": "1.1.1",
@ -2993,7 +2976,6 @@
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"safe-buffer": "~5.1.0"
}
@ -3010,16 +2992,14 @@
"resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
"integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==",
"dev": true,
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/lodash.difference": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz",
"integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==",
"dev": true,
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/lodash.escaperegexp": {
"version": "4.1.2",
@ -3032,8 +3012,7 @@
"resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
"integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==",
"dev": true,
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/lodash.isequal": {
"version": "4.5.0",
@ -3047,16 +3026,14 @@
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
"dev": true,
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/lodash.union": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz",
"integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==",
"dev": true,
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/lowercase-keys": {
"version": "2.0.0",
@ -3241,7 +3218,6 @@
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">=0.10.0"
}
@ -3375,8 +3351,7 @@
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
"dev": true,
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/progress": {
"version": "2.0.3",
@ -3466,7 +3441,6 @@
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
@ -3482,7 +3456,6 @@
"integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==",
"dev": true,
"license": "Apache-2.0",
"peer": true,
"dependencies": {
"minimatch": "^5.1.0"
}
@ -3565,8 +3538,7 @@
"url": "https://feross.org/support"
}
],
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/safer-buffer": {
"version": "2.1.2",
@ -3764,7 +3736,6 @@
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"safe-buffer": "~5.2.0"
}
@ -3878,7 +3849,6 @@
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"bl": "^4.0.3",
"end-of-stream": "^1.4.1",
@ -4042,8 +4012,7 @@
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"dev": true,
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/verror": {
"version": "1.10.1",
@ -4194,7 +4163,6 @@
"integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"archiver-utils": "^3.0.4",
"compress-commons": "^4.1.2",
@ -4210,7 +4178,6 @@
"integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"glob": "^7.2.3",
"graceful-fs": "^4.2.0",

View File

@ -1,6 +1,6 @@
{
"name": "twitch-vod-manager",
"version": "4.2.1",
"version": "4.1.13",
"description": "Twitch VOD Manager - Download Twitch VODs easily",
"main": "dist/main.js",
"author": "xRangerDE",
@ -16,8 +16,7 @@
"test:e2e:stress": "npm run test:e2e:release && npm run test:e2e:release && npm run test:e2e:release",
"pack": "npm run build && electron-builder --dir",
"dist": "npm run build && electron-builder",
"dist:win": "npm run test:e2e:release && electron-builder --win",
"release:gitea": "node scripts/release_gitea.mjs"
"dist:win": "npm run test:e2e:release && electron-builder --win"
},
"dependencies": {
"axios": "^1.6.0",
@ -50,8 +49,9 @@
"include": "build/installer.nsh"
},
"publish": {
"provider": "generic",
"url": "https://git.24-music.de/Administrator/Twitch-VOD-Manager/releases/download/v${version}/"
"provider": "github",
"owner": "Sucukdeluxe",
"repo": "Twitch-VOD-Manager"
}
}
}

View File

@ -9,13 +9,8 @@ import { compareUpdateVersions, isNewerUpdateVersion, normalizeUpdateVersion } f
// ==========================================
// CONFIG & CONSTANTS
// ==========================================
const APP_VERSION = app.getVersion();
const APP_VERSION = '4.1.13';
const UPDATE_CHECK_URL = 'http://24-music.de/version.json';
const GITEA_BASE_URL = (process.env.GITEA_BASE_URL || 'https://git.24-music.de').replace(/\/+$/, '');
const GITEA_REPO_OWNER = process.env.GITEA_REPO_OWNER || 'Administrator';
const GITEA_REPO_NAME = process.env.GITEA_REPO_NAME || 'Twitch-VOD-Manager';
const GITEA_RELEASES_API_LATEST_URL = `${GITEA_BASE_URL}/api/v1/repos/${GITEA_REPO_OWNER}/${GITEA_REPO_NAME}/releases/latest`;
const GITEA_RELEASES_DOWNLOAD_BASE_URL = `${GITEA_BASE_URL}/${GITEA_REPO_OWNER}/${GITEA_REPO_NAME}/releases/download`;
// Paths
const APPDATA_DIR = path.join(process.env.PROGRAMDATA || 'C:\\ProgramData', 'Twitch_VOD_Manager');
@ -2973,26 +2968,6 @@ async function requestUpdateCheck(source: UpdateCheckSource, force = false): Pro
appendDebugLog('update-check-start', { source });
try {
try {
const giteaRes = await axios.get(GITEA_RELEASES_API_LATEST_URL, {
timeout: 5000,
headers: {
'Accept': 'application/json',
'User-Agent': 'Twitch-VOD-Manager'
}
});
const tagName = giteaRes.data?.tag_name;
if (tagName) {
autoUpdater.setFeedURL({
provider: 'generic',
url: `${GITEA_RELEASES_DOWNLOAD_BASE_URL}/${tagName}`
});
appendDebugLog('gitea-feed-url-set', { tagName, owner: GITEA_REPO_OWNER, repo: GITEA_REPO_NAME });
}
} catch (apiErr) {
appendDebugLog('gitea-api-failed', String(apiErr));
}
let timeoutHandle: NodeJS.Timeout | null = null;
try {
await Promise.race([