From 649929ca5db79d25cdbee222b3d46bd32807237e Mon Sep 17 00:00:00 2001 From: "itdrui.de" Date: Tue, 10 Mar 2026 14:28:41 +0100 Subject: [PATCH] =?UTF-8?q?dev:=20bump=20to=200.1.76.0-dev=20=E2=80=93=20a?= =?UTF-8?q?eltere=20Versionen=20im=20Update-Dialog,=20Release-Branch-Zuord?= =?UTF-8?q?nung,=20README=20ueberarbeitet?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG-DEV.md | 4 ++ README.md | 108 ++++++++++++++++++++++--------- addon/addon.xml | 2 +- addon/default.py | 47 +++++++++++++- scripts/hooks/commit-msg | 8 +-- scripts/hooks/pre-commit | 41 ++++++++++-- scripts/publish_gitea_release.sh | 17 ++++- 7 files changed, 178 insertions(+), 49 deletions(-) diff --git a/CHANGELOG-DEV.md b/CHANGELOG-DEV.md index 7f23348..3cb9b44 100644 --- a/CHANGELOG-DEV.md +++ b/CHANGELOG-DEV.md @@ -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 diff --git a/README.md b/README.md index 25690bc..73a7483 100644 --- a/README.md +++ b/README.md @@ -2,42 +2,86 @@ ViewIT Logo -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://:/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 + +
+Build und Projektstruktur + +### 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 +``` + +
diff --git a/addon/addon.xml b/addon/addon.xml index 14a66b2..babd149 100644 --- a/addon/addon.xml +++ b/addon/addon.xml @@ -1,5 +1,5 @@ - + diff --git a/addon/default.py b/addon/default.py index 03e8b37..b6e0a24 100644 --- a/addon/default.py +++ b/addon/default.py @@ -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) diff --git a/scripts/hooks/commit-msg b/scripts/hooks/commit-msg index b776d73..46df79c 100755 --- a/scripts/hooks/commit-msg +++ b/scripts/hooks/commit-msg @@ -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 "" diff --git a/scripts/hooks/pre-commit b/scripts/hooks/pre-commit index 436c7e9..6b23805 100755 --- a/scripts/hooks/pre-commit +++ b/scripts/hooks/pre-commit @@ -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 diff --git a/scripts/publish_gitea_release.sh b/scripts/publish_gitea_release.sh index 3cb2031..7bde309 100755 --- a/scripts/publish_gitea_release.sh +++ b/scripts/publish_gitea_release.sh @@ -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 )"