dev: bump to 0.1.76.0-dev – aeltere Versionen im Update-Dialog, Release-Branch-Zuordnung, README ueberarbeitet

This commit is contained in:
2026-03-10 14:28:41 +01:00
parent 5564851d35
commit 649929ca5d
7 changed files with 178 additions and 49 deletions

View File

@@ -1,3 +1,7 @@
## 0.1.74-dev - 2026-03-10
- dev: bump to 0.1.74-dev BurningSeries entfernt, Paging-Fix Neuste Titel
## 0.1.73-dev - 2026-03-07
- dev: bump to 0.1.73-dev Autoplay-Setting, Moflix Hoster-Dialog, Update-Hinweis im Hauptmenue

108
README.md
View File

@@ -2,42 +2,86 @@
<img src="addon/resources/logo.png" alt="ViewIT Logo" width="220" />
ViewIT ist ein Kodi Addon.
Es durchsucht Provider und startet Streams.
**ViewIT** ist ein Kodi-Addon zum Streamen von Filmen und Serien aus verschiedenen Quellen alles an einem Ort.
## Projektstruktur
- `addon/` Kodi Addon Quellcode
- `scripts/` Build Scripts
- `dist/` Build Ausgaben
- `docs/` Doku
- `tests/` Tests
## Was kann ViewIT?
## Build und Release
- Addon Ordner bauen: `./scripts/build_install_addon.sh`
- Kodi ZIP bauen: `./scripts/build_kodi_zip.sh`
- Version pflegen: `addon/addon.xml`
- Reproduzierbares ZIP: `SOURCE_DATE_EPOCH` optional setzen
- **Filme und Serien** aus mehreren Streaming-Quellen durchsuchen und abspielen
- **Trakt-Anbindung** Watchlist, Weiterschauen, Watch-History und automatisches Scrobbling
- **TMDB-Metadaten** Poster, Beschreibungen, Bewertungen und Fanart automatisch laden
- **Autoplay** Bevorzugten Hoster einstellen und direkt abspielen
- **Automatische Updates** Neue Versionen werden erkannt und koennen direkt installiert werden
## Lokales Kodi Repository
- Repository bauen: `./scripts/build_local_kodi_repo.sh`
- Repository starten: `./scripts/serve_local_kodi_repo.sh`
- Repo-Artefakte pruefen: `./scripts/verify_repo_artifacts.py ./dist/repo`
- Standard URL: `http://127.0.0.1:8080/repo/addons.xml`
- Eigene URL beim Build: `REPO_BASE_URL=http://<host>:<port>/repo ./scripts/build_local_kodi_repo.sh`
## Installation
## Entwicklung
- Router: `addon/default.py`
- Plugins: `addon/plugins/*_plugin.py`
- Settings: `addon/resources/settings.xml`
1. Die neueste ZIP-Datei herunterladen (siehe [Releases](https://gitea.it-drui.de/viewit/ViewIT/releases))
2. In Kodi: **Einstellungen** > **Addons** > **Aus ZIP-Datei installieren**
3. Die heruntergeladene ZIP-Datei auswaehlen
4. ViewIT erscheint unter **Video-Addons**
## Tests
- Dev Pakete installieren: `./.venv/bin/pip install -r requirements-dev.txt`
- Tests starten: `./.venv/bin/pytest`
- XML Report: `./.venv/bin/pytest --cov-report=xml`
### Updates
### Linting & Formatierung
- Ruff Linting: `./.venv/bin/ruff check addon docs`
- Black Format Check: `./.venv/bin/black --check addon docs`
ViewIT kann sich selbst aktualisieren. In den Addon-Einstellungen unter **Updates** den gewuenschten Kanal waehlen:
## Dokumentation
Siehe `docs/`.
- **Main** Stabile Versionen
- **Nightly** Aktuelle Entwicklungsversionen
- **Dev** Neueste Aenderungen (kann instabil sein)
## Einstellungen
Die wichtigsten Einstellungen im Addon:
- **Quellen** Basis-URLs der einzelnen Streaming-Seiten (falls sich Domains aendern)
- **Metadaten** TMDB aktivieren/deaktivieren, Sprache einstellen
- **Wiedergabe** Autoplay und bevorzugten Hoster festlegen
- **Trakt** Konto verbinden fuer Watchlist und Scrobbling
## Voraussetzungen
- Kodi 19 (Matrix) oder neuer
- **ResolveURL** wird beim ersten Start automatisch installiert (kann auch manuell ueber die Einstellungen nachinstalliert werden)
## Fuer Entwickler
<details>
<summary>Build und Projektstruktur</summary>
### Projektstruktur
```
addon/ Kodi-Addon Quellcode
default.py Hauptdatei und Router
plugins/ Streaming-Plugins (eins pro Quelle)
core/ Kernmodule (Trakt, Metadaten, Updates, ...)
resources/ Einstellungen, Icons, Sprachdateien
scripts/ Build- und Deploy-Skripte
tests/ Automatisierte Tests
dist/ Build-Ausgaben
```
### Addon bauen
```bash
# Addon-Ordner erzeugen
bash scripts/build_install_addon.sh
# ZIP fuer Kodi-Installation erzeugen
bash scripts/build_kodi_zip.sh
```
### Tests ausfuehren
```bash
pip install -r requirements-dev.txt
pytest
```
### Lokales Kodi-Repository
```bash
bash scripts/build_local_kodi_repo.sh
bash scripts/serve_local_kodi_repo.sh
# Erreichbar unter http://127.0.0.1:8080/repo/addons.xml
```
</details>

View File

@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
<addon id="plugin.video.viewit" name="ViewIt" version="0.1.74-dev" provider-name="ViewIt">
<addon id="plugin.video.viewit" name="ViewIt" version="0.1.76.0-dev" provider-name="ViewIt">
<requires>
<import addon="xbmc.python" version="3.0.0" />
<import addon="script.module.requests" />

View File

@@ -1383,6 +1383,25 @@ def _fetch_repo_versions(info_url: str) -> list[str]:
version = match.group(1).strip()
if version:
versions.append(version)
# Zusaetzlich Gitea Releases API abfragen (aeltere Versionen)
try:
source_repo = repo.replace("ViewIT-Kodi-Repo", "ViewIT").replace("-Kodi-Repo", "")
releases_api = f"{scheme}://{host}/api/v1/repos/{owner}/{source_repo}/releases?limit=50"
releases_payload = _read_text_url(releases_api)
releases_data = json.loads(releases_payload)
if isinstance(releases_data, list):
for release in releases_data:
for asset in release.get("assets", []):
aname = str(asset.get("name") or "")
m = re.match(rf"^{re.escape(UPDATE_ADDON_ID)}-(.+)\.zip$", aname)
if m:
v = m.group(1).strip()
if v:
versions.append(v)
except Exception:
pass
unique = sorted(set(versions), key=_version_sort_key, reverse=True)
return unique
@@ -1462,9 +1481,33 @@ def _install_addon_version_manual(info_url: str, version: str) -> bool:
return True
def _install_addon_version(info_url: str, version: str) -> bool:
def _resolve_zip_url(info_url: str, version: str) -> str:
"""Gibt die Download-URL fuer eine bestimmte Version zurueck.
Prueft zuerst das Kodi-Repo, dann den Gitea-Release-Download.
"""
base = info_url[: -len("/addons.xml")] if info_url.endswith("/addons.xml") else info_url.rstrip("/")
zip_url = f"{base}/{UPDATE_ADDON_ID}/{UPDATE_ADDON_ID}-{version}.zip"
repo_url = f"{base}/{UPDATE_ADDON_ID}/{UPDATE_ADDON_ID}-{version}.zip"
# Pruefen ob die ZIP im Kodi-Repo existiert
try:
req = Request(repo_url, method="HEAD", headers={"User-Agent": "ViewIT/1.0"})
resp = urlopen(req, timeout=UPDATE_HTTP_TIMEOUT_SEC)
if resp.status == 200:
return repo_url
except Exception:
pass
# Fallback: Gitea Release Asset
identity = _extract_repo_identity(info_url)
if identity:
scheme, host, owner, repo_branch = identity
repo = repo_branch.split("|", 1)[0]
source_repo = repo.replace("ViewIT-Kodi-Repo", "ViewIT").replace("-Kodi-Repo", "")
return f"{scheme}://{host}/{owner}/{source_repo}/releases/download/v{version}/{UPDATE_ADDON_ID}-{version}.zip"
return repo_url
def _install_addon_version(info_url: str, version: str) -> bool:
zip_url = _resolve_zip_url(info_url, version)
# Prefer Kodi's own installer to get proper install flow and dependency handling.
builtin = getattr(xbmc, "executebuiltin", None)

View File

@@ -7,19 +7,17 @@ branch=$(git symbolic-ref --short HEAD 2>/dev/null)
root=$(git rev-parse --show-toplevel)
cd "$root"
# Aktuelle Version aus addon.xml (bereits vom pre-commit Hook hochgezählt)
version=$(grep -oP 'version="\K[0-9]+\.[0-9]+\.[0-9]+[^"]*' addon/addon.xml | head -1)
# Aktuelle Version aus addon.xml (bereits vom pre-commit Hook hochgezaehlt)
version=$(grep -oP 'version="\K[0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?[^"]*' addon/addon.xml | head -1)
# Commit-Message: alte Versionsnummern durch aktuelle ersetzen
# z.B. "dev: bump to 0.1.72-dev ..." → "dev: bump to 0.1.73-dev ..."
msg=$(cat "$1")
updated_msg=$(echo "$msg" | sed -E "s/bump to [0-9]+\.[0-9]+\.[0-9]+[^ ]*/bump to ${version}/g")
updated_msg=$(echo "$msg" | sed -E "s/bump to [0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?[^ ]*/bump to ${version}/g")
echo "$updated_msg" > "$1"
today=$(date +%Y-%m-%d)
# Changelog-Eintrag aufbauen
# Jede nicht-leere Zeile der Commit-Message wird ein "- ..." Eintrag
{
echo "## ${version} - ${today}"
echo ""

View File

@@ -1,5 +1,7 @@
#!/bin/bash
# pre-commit: Patch-Version in addon.xml automatisch hochzählen (nur dev-Branch)
# Unterstuetzt 3-teilig (x.x.xx) und 4-teilig (x.x.xx.x)
# 4-teilig: zaehlt den 4. Teil in 5er-Schritten hoch (z.B. 0.1.75.5 → 0.1.76.0)
branch=$(git symbolic-ref --short HEAD 2>/dev/null)
[[ "$branch" != "dev" ]] && exit 0
@@ -7,18 +9,43 @@ branch=$(git symbolic-ref --short HEAD 2>/dev/null)
root=$(git rev-parse --show-toplevel)
cd "$root"
# Version aus addon.xml lesen
current=$(grep -oP 'version="\K[0-9]+\.[0-9]+\.[0-9]+[^"]*' addon/addon.xml | head -1)
# Version aus addon.xml lesen (3- oder 4-teilig mit optionalem Suffix)
current=$(grep -oP 'version="\K[0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?[^"]*' addon/addon.xml | head -1)
if [[ -z "$current" ]]; then
echo "[hook] Fehler: Version nicht gefunden in addon/addon.xml" >&2
exit 1
fi
# Patch-Nummer extrahieren und hochzählen
IFS='.' read -r major minor patch_full <<< "$current"
patch=$(echo "$patch_full" | grep -oP '^\d+')
suffix=$(echo "$patch_full" | grep -oP '[^0-9].*' || true)
new_version="${major}.${minor}.$((patch + 1))${suffix}"
# Suffix extrahieren (z.B. -dev)
suffix=$(echo "$current" | grep -oP '[-][a-zA-Z].*' || true)
version_only=$(echo "$current" | sed "s/${suffix}$//")
# Parts zaehlen
IFS='.' read -ra parts <<< "$version_only"
num_parts=${#parts[@]}
if [[ $num_parts -eq 4 ]]; then
# 4-teilig: 4. Teil um 5 erhoehen, bei >= 10 den 3. Teil erhoehen
major=${parts[0]}
minor=${parts[1]}
patch=${parts[2]}
sub=${parts[3]}
new_sub=$((sub + 5))
if [[ $new_sub -ge 10 ]]; then
new_sub=$((new_sub - 10))
patch=$((patch + 1))
fi
new_version="${major}.${minor}.${patch}.${new_sub}${suffix}"
elif [[ $num_parts -eq 3 ]]; then
# 3-teilig: Patch hochzaehlen
major=${parts[0]}
minor=${parts[1]}
patch=${parts[2]}
new_version="${major}.${minor}.$((patch + 1))${suffix}"
else
echo "[hook] Fehler: Unerwartetes Versionsformat: $current" >&2
exit 1
fi
# addon.xml aktualisieren
sed -i "s/version=\"${current}\"/version=\"${new_version}\"/" addon/addon.xml

View File

@@ -128,14 +128,27 @@ print(json.load(open(sys.argv[1], encoding="utf-8"))["id"])
PY
)"
elif [[ "${http_code}" == "404" ]]; then
payload="$(python3 - "${TAG}" "${TITLE}" "${NOTES}" <<'PY'
# Branch und prerelease aus Version ableiten
read -r TARGET_BRANCH IS_PRERELEASE < <(python3 - "${ADDON_VERSION}" <<'PY'
import sys
v = sys.argv[1]
if "-dev" in v:
print("dev", "true")
elif "-nightly" in v:
print("nightly", "true")
else:
print("main", "false")
PY
)
payload="$(python3 - "${TAG}" "${TITLE}" "${NOTES}" "${TARGET_BRANCH}" "${IS_PRERELEASE}" <<'PY'
import json,sys
print(json.dumps({
"tag_name": sys.argv[1],
"name": sys.argv[2],
"body": sys.argv[3],
"target_commitish": sys.argv[4],
"draft": False,
"prerelease": False
"prerelease": sys.argv[5] == "true"
}))
PY
)"