custom_components/bahmcloud_store/core.py aktualisiert

This commit is contained in:
2026-01-15 07:05:58 +00:00
parent 0339ad4ecb
commit 80eefabbc2

View File

@@ -1,9 +1,9 @@
from __future__ import annotations from __future__ import annotations
import asyncio
import logging import logging
from dataclasses import dataclass from dataclasses import dataclass
from typing import Any from typing import Any
from urllib.parse import urlparse
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import async_get_clientsession
@@ -12,6 +12,7 @@ from homeassistant.util import yaml as ha_yaml
from .storage import BCSStorage, CustomRepo from .storage import BCSStorage, CustomRepo
from .views import StaticAssetsView, BCSApiView from .views import StaticAssetsView, BCSApiView
from .custom_repo_view import BCSCustomRepoView from .custom_repo_view import BCSCustomRepoView
from .providers import fetch_repo_info, detect_provider
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@@ -36,7 +37,7 @@ class RepoItem:
url: str url: str
source: str # "index" | "custom" source: str # "index" | "custom"
# Enrichment fields (filled later) # Enrichment fields (best-effort)
owner: str | None = None owner: str | None = None
description: str | None = None description: str | None = None
provider: str | None = None provider: str | None = None
@@ -70,28 +71,8 @@ class BCSCore:
self.hass.http.register_view(BCSApiView(self)) self.hass.http.register_view(BCSApiView(self))
self.hass.http.register_view(BCSCustomRepoView(self)) self.hass.http.register_view(BCSCustomRepoView(self))
@staticmethod
def _provider_name(repo_url: str) -> str:
"""Best-effort provider detection by hostname."""
host = urlparse(repo_url).netloc.lower()
if "github.com" in host:
return "github"
if "gitlab.com" in host:
return "gitlab"
# Likely self-hosted (Gitea/GitLab/other)
return "generic"
@staticmethod
def _owner_from_url(repo_url: str) -> str | None:
"""Extract owner/group from common URL patterns."""
u = urlparse(repo_url.rstrip("/"))
parts = u.path.strip("/").split("/")
if len(parts) >= 2:
return parts[0]
return None
async def refresh(self) -> None: async def refresh(self) -> None:
"""Refresh merged repo list (index + custom).""" """Refresh merged repo list (index + custom) and enrich metadata."""
index_repos, refresh_seconds = await self._load_index_repos() index_repos, refresh_seconds = await self._load_index_repos()
self.refresh_seconds = refresh_seconds self.refresh_seconds = refresh_seconds
@@ -112,13 +93,33 @@ class BCSCore:
source="custom", source="custom",
) )
# Enrich basic data (owner/provider); description will come later via provider APIs # Basic provider detection (cheap)
for r in merged.values(): for r in merged.values():
r.provider = self._provider_name(r.url) r.provider = detect_provider(r.url)
r.owner = self._owner_from_url(r.url)
# Enrich owner/description (best-effort; never break the store)
await self._enrich_repos(merged)
self.repos = merged self.repos = merged
async def _enrich_repos(self, merged: dict[str, RepoItem]) -> None:
"""
Enrich repositories using provider APIs (GitHub/Gitea).
This is intentionally best-effort and concurrency-limited.
"""
sem = asyncio.Semaphore(6)
async def enrich_one(r: RepoItem) -> None:
async with sem:
info = await fetch_repo_info(self.hass, r.url)
r.provider = info.provider or r.provider
if info.owner:
r.owner = info.owner
if info.description:
r.description = info.description
await asyncio.gather(*(enrich_one(r) for r in merged.values()), return_exceptions=True)
async def _load_index_repos(self) -> tuple[list[RepoItem], int]: async def _load_index_repos(self) -> tuple[list[RepoItem], int]:
"""Load store.yaml and return (repos, refresh_seconds).""" """Load store.yaml and return (repos, refresh_seconds)."""
session = async_get_clientsession(self.hass) session = async_get_clientsession(self.hass)