dev: bump to 0.1.76.0-dev – aeltere Versionen im Update-Dialog, Release-Branch-Zuordnung, README ueberarbeitet
This commit is contained in:
@@ -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
|
## 0.1.73-dev - 2026-03-07
|
||||||
|
|
||||||
- dev: bump to 0.1.73-dev – Autoplay-Setting, Moflix Hoster-Dialog, Update-Hinweis im Hauptmenue
|
- dev: bump to 0.1.73-dev – Autoplay-Setting, Moflix Hoster-Dialog, Update-Hinweis im Hauptmenue
|
||||||
|
|||||||
108
README.md
108
README.md
@@ -2,42 +2,86 @@
|
|||||||
|
|
||||||
<img src="addon/resources/logo.png" alt="ViewIT Logo" width="220" />
|
<img src="addon/resources/logo.png" alt="ViewIT Logo" width="220" />
|
||||||
|
|
||||||
ViewIT ist ein Kodi Addon.
|
**ViewIT** ist ein Kodi-Addon zum Streamen von Filmen und Serien aus verschiedenen Quellen – alles an einem Ort.
|
||||||
Es durchsucht Provider und startet Streams.
|
|
||||||
|
|
||||||
## Projektstruktur
|
## Was kann ViewIT?
|
||||||
- `addon/` Kodi Addon Quellcode
|
|
||||||
- `scripts/` Build Scripts
|
|
||||||
- `dist/` Build Ausgaben
|
|
||||||
- `docs/` Doku
|
|
||||||
- `tests/` Tests
|
|
||||||
|
|
||||||
## Build und Release
|
- **Filme und Serien** aus mehreren Streaming-Quellen durchsuchen und abspielen
|
||||||
- Addon Ordner bauen: `./scripts/build_install_addon.sh`
|
- **Trakt-Anbindung** – Watchlist, Weiterschauen, Watch-History und automatisches Scrobbling
|
||||||
- Kodi ZIP bauen: `./scripts/build_kodi_zip.sh`
|
- **TMDB-Metadaten** – Poster, Beschreibungen, Bewertungen und Fanart automatisch laden
|
||||||
- Version pflegen: `addon/addon.xml`
|
- **Autoplay** – Bevorzugten Hoster einstellen und direkt abspielen
|
||||||
- Reproduzierbares ZIP: `SOURCE_DATE_EPOCH` optional setzen
|
- **Automatische Updates** – Neue Versionen werden erkannt und koennen direkt installiert werden
|
||||||
|
|
||||||
## Lokales Kodi Repository
|
## Installation
|
||||||
- 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`
|
|
||||||
|
|
||||||
## Entwicklung
|
1. Die neueste ZIP-Datei herunterladen (siehe [Releases](https://gitea.it-drui.de/viewit/ViewIT/releases))
|
||||||
- Router: `addon/default.py`
|
2. In Kodi: **Einstellungen** > **Addons** > **Aus ZIP-Datei installieren**
|
||||||
- Plugins: `addon/plugins/*_plugin.py`
|
3. Die heruntergeladene ZIP-Datei auswaehlen
|
||||||
- Settings: `addon/resources/settings.xml`
|
4. ViewIT erscheint unter **Video-Addons**
|
||||||
|
|
||||||
## Tests
|
### Updates
|
||||||
- Dev Pakete installieren: `./.venv/bin/pip install -r requirements-dev.txt`
|
|
||||||
- Tests starten: `./.venv/bin/pytest`
|
|
||||||
- XML Report: `./.venv/bin/pytest --cov-report=xml`
|
|
||||||
|
|
||||||
### Linting & Formatierung
|
ViewIT kann sich selbst aktualisieren. In den Addon-Einstellungen unter **Updates** den gewuenschten Kanal waehlen:
|
||||||
- Ruff Linting: `./.venv/bin/ruff check addon docs`
|
|
||||||
- Black Format Check: `./.venv/bin/black --check addon docs`
|
|
||||||
|
|
||||||
## Dokumentation
|
- **Main** – Stabile Versionen
|
||||||
Siehe `docs/`.
|
- **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>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?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>
|
<requires>
|
||||||
<import addon="xbmc.python" version="3.0.0" />
|
<import addon="xbmc.python" version="3.0.0" />
|
||||||
<import addon="script.module.requests" />
|
<import addon="script.module.requests" />
|
||||||
|
|||||||
@@ -1383,6 +1383,25 @@ def _fetch_repo_versions(info_url: str) -> list[str]:
|
|||||||
version = match.group(1).strip()
|
version = match.group(1).strip()
|
||||||
if version:
|
if version:
|
||||||
versions.append(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)
|
unique = sorted(set(versions), key=_version_sort_key, reverse=True)
|
||||||
return unique
|
return unique
|
||||||
|
|
||||||
@@ -1462,9 +1481,33 @@ def _install_addon_version_manual(info_url: str, version: str) -> bool:
|
|||||||
return True
|
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("/")
|
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.
|
# Prefer Kodi's own installer to get proper install flow and dependency handling.
|
||||||
builtin = getattr(xbmc, "executebuiltin", None)
|
builtin = getattr(xbmc, "executebuiltin", None)
|
||||||
|
|||||||
@@ -7,19 +7,17 @@ branch=$(git symbolic-ref --short HEAD 2>/dev/null)
|
|||||||
root=$(git rev-parse --show-toplevel)
|
root=$(git rev-parse --show-toplevel)
|
||||||
cd "$root"
|
cd "$root"
|
||||||
|
|
||||||
# Aktuelle Version aus addon.xml (bereits vom pre-commit Hook hochgezählt)
|
# Aktuelle Version aus addon.xml (bereits vom pre-commit Hook hochgezaehlt)
|
||||||
version=$(grep -oP 'version="\K[0-9]+\.[0-9]+\.[0-9]+[^"]*' addon/addon.xml | head -1)
|
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
|
# 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")
|
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"
|
echo "$updated_msg" > "$1"
|
||||||
|
|
||||||
today=$(date +%Y-%m-%d)
|
today=$(date +%Y-%m-%d)
|
||||||
|
|
||||||
# Changelog-Eintrag aufbauen
|
# Changelog-Eintrag aufbauen
|
||||||
# Jede nicht-leere Zeile der Commit-Message wird ein "- ..." Eintrag
|
|
||||||
{
|
{
|
||||||
echo "## ${version} - ${today}"
|
echo "## ${version} - ${today}"
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# pre-commit: Patch-Version in addon.xml automatisch hochzählen (nur dev-Branch)
|
# 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=$(git symbolic-ref --short HEAD 2>/dev/null)
|
||||||
[[ "$branch" != "dev" ]] && exit 0
|
[[ "$branch" != "dev" ]] && exit 0
|
||||||
@@ -7,18 +9,43 @@ branch=$(git symbolic-ref --short HEAD 2>/dev/null)
|
|||||||
root=$(git rev-parse --show-toplevel)
|
root=$(git rev-parse --show-toplevel)
|
||||||
cd "$root"
|
cd "$root"
|
||||||
|
|
||||||
# Version aus addon.xml lesen
|
# Version aus addon.xml lesen (3- oder 4-teilig mit optionalem Suffix)
|
||||||
current=$(grep -oP 'version="\K[0-9]+\.[0-9]+\.[0-9]+[^"]*' addon/addon.xml | head -1)
|
current=$(grep -oP 'version="\K[0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?[^"]*' addon/addon.xml | head -1)
|
||||||
if [[ -z "$current" ]]; then
|
if [[ -z "$current" ]]; then
|
||||||
echo "[hook] Fehler: Version nicht gefunden in addon/addon.xml" >&2
|
echo "[hook] Fehler: Version nicht gefunden in addon/addon.xml" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Patch-Nummer extrahieren und hochzählen
|
# Suffix extrahieren (z.B. -dev)
|
||||||
IFS='.' read -r major minor patch_full <<< "$current"
|
suffix=$(echo "$current" | grep -oP '[-][a-zA-Z].*' || true)
|
||||||
patch=$(echo "$patch_full" | grep -oP '^\d+')
|
version_only=$(echo "$current" | sed "s/${suffix}$//")
|
||||||
suffix=$(echo "$patch_full" | grep -oP '[^0-9].*' || true)
|
|
||||||
|
# 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}"
|
new_version="${major}.${minor}.$((patch + 1))${suffix}"
|
||||||
|
else
|
||||||
|
echo "[hook] Fehler: Unerwartetes Versionsformat: $current" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# addon.xml aktualisieren
|
# addon.xml aktualisieren
|
||||||
sed -i "s/version=\"${current}\"/version=\"${new_version}\"/" addon/addon.xml
|
sed -i "s/version=\"${current}\"/version=\"${new_version}\"/" addon/addon.xml
|
||||||
|
|||||||
@@ -128,14 +128,27 @@ print(json.load(open(sys.argv[1], encoding="utf-8"))["id"])
|
|||||||
PY
|
PY
|
||||||
)"
|
)"
|
||||||
elif [[ "${http_code}" == "404" ]]; then
|
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
|
import json,sys
|
||||||
print(json.dumps({
|
print(json.dumps({
|
||||||
"tag_name": sys.argv[1],
|
"tag_name": sys.argv[1],
|
||||||
"name": sys.argv[2],
|
"name": sys.argv[2],
|
||||||
"body": sys.argv[3],
|
"body": sys.argv[3],
|
||||||
|
"target_commitish": sys.argv[4],
|
||||||
"draft": False,
|
"draft": False,
|
||||||
"prerelease": False
|
"prerelease": sys.argv[5] == "true"
|
||||||
}))
|
}))
|
||||||
PY
|
PY
|
||||||
)"
|
)"
|
||||||
|
|||||||
Reference in New Issue
Block a user