#743 - Trying to fix this.

This commit is contained in:
ccostan 2020-05-21 18:48:00 -04:00
parent cf3764e3e4
commit 5c7334bc05
42 changed files with 863 additions and 513 deletions

8
.gitignore vendored
View File

@ -18,6 +18,9 @@ home-assistant_v2.db
*.sqlite
deps
__pycache__
hacs
alexa_media
custom_components
tts
secrets.yaml
secrets
@ -30,6 +33,5 @@ nest.conf
ipchange.yaml
ip_bans.yaml
production_auth.json
hacs
alexa_media
custom_components

View File

@ -1 +1 @@
0.110.0
0.110.1

View File

@ -2,25 +2,35 @@
"common": {
"about": "Om",
"appdaemon_apps": "AppDaemon-apps",
"appdaemon_plural": "AppDaemon-apps",
"background_task": "Baggrundsopgave kører. Denne side vil genindlæses automatisk.",
"check_log_file": "Tjek din logfil for flere detaljer.",
"continue": "Fortsæt",
"disabled": "Deaktiveret",
"documentation": "Dokumentation",
"element": "element",
"hacs_is_disabled": "HACS er deaktiveret",
"installed": "installeret",
"integration": "Integration",
"integration_plural": "Integrationer",
"integrations": "Integrationer",
"lovelace": "Lovelace",
"lovelace_element": "Lovelace-element",
"lovelace_elements": "Lovelace-elementer",
"manage": "administrer",
"netdaemon": "NetDaemon",
"netdaemon_apps": "NetDaemon-apps",
"plugin": "Plugin",
"plugins": "Plugins",
"netdaemon_plural": "NetDaemon-apps",
"plugin": "Lovelace",
"plugin_plural": "Lovelace-elementer",
"plugins": "Lovelace-elementer",
"python_script": "Python-script",
"python_script_plural": "Python-scripts",
"python_scripts": "Python-scripts",
"repositories": "Repositories",
"settings": "indstillinger",
"theme": "Tema",
"theme_plural": "Temaer",
"themes": "Temaer",
"version": "Version"
},
@ -90,7 +100,7 @@
"integration_not_loaded": "Denne integration er ikke indlæst i Home Assistant.",
"no_restart_required": "Ingen genstart påkrævet",
"not_loaded": "Ikke indlæst",
"plugin_not_loaded": "Dette plugin er ikke føjet til dine Lovelace-ressourcer.",
"plugin_not_loaded": "Dette element er ikke føjet til dine Lovelace-ressourcer.",
"restart": "Du skal genstarte Home Assistant.",
"restart_pending": "Afventer genstart"
},
@ -111,7 +121,7 @@
"installed": "Installeret",
"lovelace_copy_example": "Kopiér eksemplet til din Udklipsholder",
"lovelace_instruction": "Tilføj dette til din lovelace-konfiguration",
"lovelace_no_js_type": "Kunne ikke afgøre typen af dette plugin, tjek venligst repository.",
"lovelace_no_js_type": "Kunne ikke afgøre typen af dette element, tjek venligst repository'et.",
"newest": "nyeste",
"note_appdaemon": "Du skal stadig føje den til filen 'apps.yaml'",
"note_installed": "Når det er installeret, vil dette være placeret i",
@ -119,7 +129,7 @@
"note_plugin": "du skal stadig tilføje det til din lovelace-konfiguration ('ui-lovelace.yaml' eller Tekstbaseret redigering)",
"note_plugin_post_107": "du skal stadig tilføje det til din lovelace-konfiguration ('configuration.yaml' eller ressourceeditoren '\/config\/lovelace\/resources')",
"open_issue": "Opret issue",
"open_plugin": "Åbn plugin",
"open_plugin": "Åbn element",
"reinstall": "Geninstaller",
"repository": "Repository",
"restart_home_assistant": "Genstart Home Assistant",
@ -128,6 +138,25 @@
"update_information": "Opdater oplysninger",
"upgrade": "Opdater"
},
"sections": {
"about": {
"description": "Vis information om HACS",
"title": "Om"
},
"automation": {
"description": "Det er her, du finder python_scripts, AppDaemon-apps og NetDaemon-apps",
"title": "Automatisering"
},
"frontend": {
"description": "Det er her, du finder temaer, brugerdefinerede kort og andre elementer til lovelace",
"title": "Frontend"
},
"integrations": {
"description": "Det er her, du finder brugerdefinerede integrationer (custom_components)",
"title": "Integrationer"
},
"pending_repository_upgrade": "Du kører version {installed}, version {available} er tilgængelig"
},
"settings": {
"add_custom_repository": "TILFØJ ET BRUGERDEFINERET REPOSITORY",
"adding_new_repo": "Tilføjer nyt repository '{repo}'",

View File

@ -3,25 +3,35 @@
"about": "Über",
"appdaemon": "AppDaemon",
"appdaemon_apps": "AppDaemon Apps",
"appdaemon_plural": "AppDaemon Apps",
"background_task": "Hintergrundprozess läuft. Diese Seite lädt neu, sobald dieser fertig ist.",
"check_log_file": "Überprüfe die Logdatei für weitere Informationen.",
"continue": "Fortfahren",
"disabled": "Deaktiviert",
"documentation": "Dokumentation",
"element": "Element",
"hacs_is_disabled": "HACS ist deaktiviert",
"installed": "Installiert",
"integration": "Integration",
"integration_plural": "Integrationen",
"integrations": "Integrationen",
"lovelace": "Lovelace",
"lovelace_element": "Lovelace-Element",
"lovelace_elements": "Lovelace-Elemente",
"manage": "verwalten",
"netdaemon": "NetDaemon",
"netdaemon_apps": "NetDaemon Apps",
"plugin": "Plugin",
"plugins": "Plugins",
"netdaemon_plural": "NetDaemon Apps",
"plugin": "Lovelace",
"plugin_plural": "Lovelace-Elemente",
"plugins": "Lovelace-Elemente",
"python_script": "Python Skript",
"python_script_plural": "Python Skripte",
"python_scripts": "Python Skripte",
"repositories": "Repositories",
"settings": "Einstellungen",
"theme": "Theme",
"theme_plural": "Themes",
"themes": "Themes",
"version": "Version"
},
@ -93,7 +103,7 @@
"integration_not_loaded": "Diese Integration ist in Home Assistant nicht geladen.",
"no_restart_required": "Kein Neustart erforderlich",
"not_loaded": "Nicht geladen",
"plugin_not_loaded": "Dieses Plugin wurde deinen Lovelace-Ressourcen nicht hinzugefügt.",
"plugin_not_loaded": "Dieses Element wird nicht zu Ihren Lovelace-Ressourcen hinzugefügt.",
"restart": "Du musst Home Assistant neu starten.",
"restart_pending": "Neustart ausstehend"
},
@ -114,7 +124,7 @@
"installed": "Installiert",
"lovelace_copy_example": "Beispiel in die Zwischenablage kopieren",
"lovelace_instruction": "Zum Hinzufügen zu deinen Lovelace-Einstellungen, benutze Folgendes",
"lovelace_no_js_type": "Konnte die Art dieses Plugins nicht erkennen. Prüfe das Repository.",
"lovelace_no_js_type": "Der Typ dieses Elements konnte nicht ermittelt werden. Überprüfen Sie das Repository.",
"newest": "neueste",
"note_appdaemon": "du musst es dann noch in die Datei 'apps.yaml' hinzufügen",
"note_installed": "Wird installiert nach",
@ -122,7 +132,7 @@
"note_plugin": "du musst es dann noch in deine Lovelace-Einstellungen ('ui-lovelace.yaml' oder im Raw-Konfigurationseditor) hinzufügen",
"note_plugin_post_107": "Du musst es noch zu deiner Lovelace-Konfiguration hinzufügen ('configuration.yaml' oder der Ressourceneditor '\/config\/lovelace\/resources')",
"open_issue": "Problem melden",
"open_plugin": "Plugin öffnen",
"open_plugin": "Element öffnen",
"reinstall": "Neu installieren",
"repository": "Repository",
"restart_home_assistant": "Home Assistant neu starten",
@ -131,6 +141,25 @@
"update_information": "Aktualisierungsinformationen",
"upgrade": "Aktualisieren"
},
"sections": {
"about": {
"description": "Informationen zu HACS anzeigen",
"title": "Über"
},
"automation": {
"description": "Hier finden Sie python_scripts, AppDaemon-Apps und NetDaemon-Apps",
"title": "Automatisierung"
},
"frontend": {
"description": "Hier finden Sie Themen, individuelle Karten und andere Elemente für Lovelace",
"title": "Frontend"
},
"integrations": {
"description": "Hier finden Sie benutzerdefinierte Integrationen (custom_components)",
"title": "Integrationen"
},
"pending_repository_upgrade": "Sie verwenden Version {installed}, Version {available} ist verfügbar"
},
"settings": {
"add_custom_repository": "BENUTZERDEFINIERTES REPOSITORY HINZUFÜGEN",
"adding_new_repo": "Hinzufügen eines neuen Repository '{repo}'",

View File

@ -1,28 +1,43 @@
{
"common": {
"about": "About",
"add": "add",
"appdaemon": "AppDaemon",
"appdaemon_apps": "AppDaemon Apps",
"appdaemon_plural": "AppDaemon Apps",
"background_task": "Background task running, this page will reload when it's done.",
"check_log_file": "Check your log file for more details.",
"continue": "Continue",
"disabled": "Disabled",
"documentation": "Documentation",
"element": "element",
"hacs_is_disabled": "HACS is disabled",
"install": "Install",
"installed": "installed",
"integration": "Integration",
"integration_plural": "Integrations",
"integrations": "Integrations",
"lovelace": "Lovelace",
"lovelace_element": "Lovelace element",
"lovelace_elements": "Lovelace elements",
"manage": "manage",
"netdaemon": "NetDaemon",
"netdaemon_apps": "NetDaemon Apps",
"netdaemon_plural": "NetDaemon Apps",
"plugin": "Plugin",
"plugin_plural": "Lovelace elements",
"plugins": "Plugins",
"python_script": "Python Script",
"python_script_plural": "Python Scripts",
"python_scripts": "Python Scripts",
"repositories": "Repositories",
"repository": "Repository",
"settings": "settings",
"theme": "Theme",
"theme_plural": "Themes",
"themes": "Themes",
"uninstall": "Uninstall",
"update": "Update",
"version": "Version"
},
"config": {
@ -70,6 +85,74 @@
"upgrade_all": "This will upgrade all of these repositories, make sure that you have read the release notes for all of them before proceeding.",
"yes": "Yes"
},
"dialog_about": {
"frontend_version": "Frontend version",
"installed_repositories": "Installed repositories",
"integration_version": "Integration version",
"useful_links": "Useful links"
},
"dialog_add_repo": {
"limit": "Only the first 100 repositories are shown, use the search to filter what you need",
"no_match": "No repositories found matching your filter",
"title": "Add repository"
},
"dialog_custom_repositories": {
"category": "Category",
"no_category": "Missing category",
"no_repository": "Missing repository",
"title": "Custom repositories",
"url_placeholder": "Add custom repository URL"
},
"dialog_info": {
"author": "Author",
"downloads": "Downloads",
"install": "Install this repository in HACS",
"loading": "Loading information...",
"no_info": "The developer has not provided any more information for this repository",
"open_issues": "Open issues",
"open_repo": "Open repository",
"stars": "Stars",
"version_installed": "Version installed"
},
"dialog_install": {
"select_version": "Select version",
"show_beta": "Show beta versions",
"type": "Type",
"url": "URL"
},
"dialog_update": {
"available_version": "Available version",
"changelog": "Changelog",
"installed_version": "Installed version",
"title": "Update pending"
},
"entry": {
"information": "Information",
"intro": "Updates and important messages will show here if there are any",
"messages": {
"disabled": {
"content": "Check your log file for more details",
"title": "HACS is disabled"
},
"has_pending_tasks": {
"content": "Some repositories might not show untill this is completed",
"title": "Background tasks pending"
},
"startup": {
"content": "HACS is starting up, during this time some information might be missing or incorrect",
"title": "HACS is starting up"
}
},
"pending_updates": "Pending updates"
},
"menu": {
"about": "About HACS",
"clear": "Clear all new",
"custom_repositories": "Custom repositories",
"documentation": "Documentation",
"open_issue": "Open issue",
"reload": "Reload window"
},
"options": {
"step": {
"user": {
@ -97,6 +180,17 @@
"restart": "You need to restart Home Assistant.",
"restart_pending": "Restart pending"
},
"repository_card": {
"hide": "Hide",
"information": "Information",
"new_repository": "New repository",
"open_issue": "Open issue",
"open_source": "Open source",
"pending_update": "Pending update",
"reinstall": "Reinstall",
"report": "Report for removal",
"update_information": "Update information"
},
"repository": {
"add_to_lovelace": "Add to Lovelace",
"authors": "Authors",
@ -131,6 +225,28 @@
"update_information": "Update information",
"upgrade": "Update"
},
"search": {
"placeholder": "Search for repository"
},
"sections": {
"about": {
"description": "Show information about HACS",
"title": "About"
},
"automation": {
"description": "This is where you find python_scripts, AppDaemon apps and NetDaemon apps",
"title": "Automation"
},
"frontend": {
"description": "This is where you find themes, custom cards and other elements for lovelace",
"title": "Frontend"
},
"integrations": {
"description": "This is where you find custom integrations (custom_components)",
"title": "Integrations"
},
"pending_repository_upgrade": "You are running version {installed}, version {available} is available"
},
"settings": {
"add_custom_repository": "ADD CUSTOM REPOSITORY",
"adding_new_repo": "Adding new repository '{repo}'",
@ -162,6 +278,9 @@
"last_updated": "Last updated",
"name": "Name",
"new_repositories": "New Repositories",
"no_repositories": "No repositories",
"no_repositories_desc1": "It seems like you don't have any repositories installed in this section yet.",
"no_repositories_desc2": "Click on the + in the bottom corner to add your first!",
"pending_upgrades": "Pending upgrades",
"placeholder_search": "Please enter a search term...",
"sort": "sort",

View File

@ -3,25 +3,35 @@
"about": "Acerca de",
"appdaemon": "AppDaemon",
"appdaemon_apps": "AppDaemon Apps",
"appdaemon_plural": "AppDaemon Apps",
"background_task": "Ejecutando tareas en segundo plano. Se refrescará automaticamente esta página al finalizar.",
"check_log_file": "Compruebe el archivo de registro para obtener más detalles.",
"continue": "Continuar",
"disabled": "Deshabilitado",
"documentation": "Documentación",
"element": "elemento",
"hacs_is_disabled": "HACS está deshabilitado",
"installed": "instalado",
"integration": "Integración",
"integration_plural": "Integraciones",
"integrations": "Integraciones",
"lovelace": "Lovelace",
"lovelace_element": "Elemento de Lovelace",
"lovelace_elements": "Elementos de Lovelace",
"manage": "Administrar",
"netdaemon": "NetDaemon",
"netdaemon_apps": "NetDaemon Apps",
"netdaemon_plural": "Aplicaciones NetDaemon",
"plugin": "Plugin",
"plugin_plural": "Elementos de Lovelace",
"plugins": "Plugins",
"python_script": "Python Script",
"python_script_plural": "Python Scripts",
"python_scripts": "Python Scripts",
"repositories": "Repositorios",
"settings": "configuraciones",
"theme": "Tema",
"theme_plural": "Temas",
"themes": "Temas",
"version": "Versión"
},
@ -93,7 +103,7 @@
"integration_not_loaded": "Esta integración no se carga en Home Assistant.",
"no_restart_required": "No es necesario reiniciar",
"not_loaded": "No está cargado",
"plugin_not_loaded": "Este plugin no se añade a sus recursos de Lovelace.",
"plugin_not_loaded": "Este plugin aun no se ha añadido a sus recursos de Lovelace.",
"restart": "Es necesario reiniciar Home Assistant.",
"restart_pending": "Reinicio pendiente"
},
@ -131,6 +141,25 @@
"update_information": "Actualizar información",
"upgrade": "Actualizar"
},
"sections": {
"about": {
"description": "Mostrar información sobre HACS",
"title": "Acerca de"
},
"automation": {
"description": "Aquí es donde se encuentran python_scripts, aplicaciones AppDaemon y aplicaciones NetDaemon",
"title": "Automatización"
},
"frontend": {
"description": "Aquí es donde encontrarás temas, tarjetas personalizadas y otros elementos para lovelace",
"title": "Interfaz"
},
"integrations": {
"description": "Aquí es donde se encuentran las integraciones personalizadas (custom_components)",
"title": "Integraciones"
},
"pending_repository_upgrade": "Está ejecutando la versión {installed}, la versión {available} está disponible"
},
"settings": {
"add_custom_repository": "AGREGAR REPOSITORIO PERSONALIZADO",
"adding_new_repo": "Añadiendo un nuevo repositorio '{repo}'.",

View File

@ -3,25 +3,35 @@
"about": "Névjegy",
"appdaemon": "AppDaemon",
"appdaemon_apps": "AppDaemon Appok",
"appdaemon_plural": "AppDaemon appok",
"background_task": "Éppen háttérfeladat fut, ez az oldal frissülni fog, ha kész.",
"check_log_file": "További részletekért ellenőrizd a naplófájlt.",
"continue": "Folytatás",
"disabled": "Tiltva",
"documentation": "Dokumentáció",
"element": "bővítmény",
"hacs_is_disabled": "A HACS le van tiltva",
"installed": "Telepített",
"integration": "Integráció",
"integration_plural": "Integrációk",
"integrations": "Integrációk",
"lovelace": "Lovelace",
"lovelace_element": "Lovelace bővítmény",
"lovelace_elements": "Lovelace bővítmények",
"manage": "kezelés",
"netdaemon": "NetDaemon",
"netdaemon_apps": "NetDaemon Appok",
"plugin": "Bővítmény",
"plugins": "Bővítmények",
"netdaemon_plural": "NetDaemon appok",
"plugin": "Lovelace",
"plugin_plural": "Lovelace bővítmények",
"plugins": "Lovelace bővítmények",
"python_script": "Python Szkript",
"python_script_plural": "Python szkriptek",
"python_scripts": "Python Szkriptek",
"repositories": "Tárolók",
"settings": "beállítások",
"theme": "Téma",
"theme_plural": "Témák",
"themes": "Témák",
"version": "Verzió"
},
@ -93,7 +103,7 @@
"integration_not_loaded": "Ez az integráció nincs betöltve a Home Assistantban.",
"no_restart_required": "Nincs szükség újraindításra",
"not_loaded": "Nincs betöltve",
"plugin_not_loaded": "Ez a bővítmény nincs hozzáadva a Lovelace erőforrásokhoz.",
"plugin_not_loaded": "Ez a bővítmény nincs hozzáadva a Lovelace erőforrásaidhoz.",
"restart": "Indítsd újra a Home Assistant programot.",
"restart_pending": "Újraindítás függőben"
},
@ -114,7 +124,7 @@
"installed": "Telepített",
"lovelace_copy_example": "Példa másolása a vágólapra",
"lovelace_instruction": "Amikor hozzáadod ezt a lovelace konfigurációdhoz, használd ezt",
"lovelace_no_js_type": "Nem sikerült meghatározni a beépülő modul típusát, ellenőrizd a tárolót.",
"lovelace_no_js_type": "Nem sikerült meghatározni a bővítmény típusát, ellenőrizd a tárolót.",
"newest": "legújabb",
"note_appdaemon": "de még hozzá kell adnod az 'apps.yaml' fájlhoz",
"note_installed": "Telepítéskor a következő helyre kerül:",
@ -131,6 +141,25 @@
"update_information": "Frissítési információk",
"upgrade": "Frissítés"
},
"sections": {
"about": {
"description": "Információk megjelenítése a HACS-ről",
"title": "Névjegy"
},
"automation": {
"description": "Itt Python szkripteket, AppDaemon és NetDaemon appokat találsz",
"title": "Automatizálás"
},
"frontend": {
"description": "Itt témákat, egyéni kártyákat és más bővítményeket találsz a Lovelace-hez",
"title": "Frontend"
},
"integrations": {
"description": "Itt találod az egyéni integrációkat (custom_components)",
"title": "Integrációk"
},
"pending_repository_upgrade": "A(z) {installed} verziót futtatod, a(z) {available} verzió már elérhető"
},
"settings": {
"add_custom_repository": "EGYÉNI TÁROLÓ HOZZÁADÁSA",
"adding_new_repo": "Új tároló hozzáadása '{repo}'",

View File

@ -1,28 +1,43 @@
{
"common": {
"about": "Om",
"add": "legg til",
"appdaemon": "AppDaemon",
"appdaemon_apps": "AppDaemon Apper",
"appdaemon_plural": "AppDaemon-apper",
"background_task": "Bakgrunnsoppgaven kjører. Denne siden lastes inn på nytt når den er ferdig.",
"check_log_file": "Sjekk loggfilen din for mer informasjon.",
"continue": "Fortsett",
"disabled": "Deaktivert",
"documentation": "dokumentasjon",
"element": "element",
"hacs_is_disabled": "HACS er deaktivert",
"install": "Installer",
"installed": "Installert",
"integration": "Integrasjon",
"integration_plural": "Integrasjoner",
"integrations": "Integrasjoner",
"lovelace": "Lovelace",
"lovelace_element": "Lovelace-element",
"lovelace_elements": "Lovelace-elementer",
"manage": "manage",
"netdaemon": "NetDaemon",
"netdaemon_apps": "NetDaemon Apper",
"plugin": "Plugin",
"plugins": "Plugins",
"netdaemon_plural": "NetDaemon-apper",
"plugin": "Lovelace",
"plugin_plural": "Lovelace-elementer",
"plugins": "Lovelace-elementer",
"python_script": "Python-skript",
"python_script_plural": "Python-skript",
"python_scripts": "Python-skript",
"repositories": "Repositories",
"repository": "Repository",
"settings": "Innstillinger",
"theme": "Tema",
"theme_plural": "Temaer",
"themes": "Temaer",
"uninstall": "Avinstaller",
"update": "Oppdater",
"version": "Versjon"
},
"config": {
@ -70,6 +85,74 @@
"upgrade_all": "Dette vil oppgradere alle disse repositorene, sørg for at du har lest utgivelses notatene for dem alle før du fortsetter.",
"yes": "Ja"
},
"dialog_about": {
"frontend_version": "Frontend versjon",
"installed_repositories": "Installerte repositories",
"integration_version": "Integrasjonsversjon",
"useful_links": "Nyttige lenker"
},
"dialog_add_repo": {
"limit": "Bare de første 100 elementene vises, bruk søket til å filtrere det du trenger",
"no_match": "Ingen elementer funnet som samsvarer med filteret ditt",
"title": "Legg til repository"
},
"dialog_custom_repositories": {
"category": "Kategori",
"no_category": "Mangler kategori",
"no_repository": "Mangler repository",
"title": "Custom repositories",
"url_placeholder": "Legg til custom repository"
},
"dialog_info": {
"author": "Utgiver",
"downloads": "Nedlastinger",
"install": "Installer dette elementet i HACS",
"loading": "Laster inn informasjon ...",
"no_info": "Utvikleren har ikke gitt mer informasjon for dette elementet",
"open_issues": "Åpne problemer",
"open_repo": "Åpne repository",
"stars": "Stjerner",
"version_installed": "Versjon installert"
},
"dialog_install": {
"select_version": "Velg versjon",
"show_beta": "Vis betaversjoner",
"type": "Type",
"url": "URL"
},
"dialog_update": {
"available_version": "Tilgjengelig versjon",
"changelog": "Endringslogg",
"installed_version": "Installert versjon",
"title": "Oppdatering venter"
},
"entry": {
"information": "Informasjon",
"intro": "Oppdateringer og viktige meldinger vises her hvis det er noen",
"messages": {
"disabled": {
"content": "Sjekk loggfilen din for mer informasjon",
"title": "HACS er deaktivert"
},
"has_pending_tasks": {
"content": "Noen elementer vises kanskje ikke før dette er fullført",
"title": "Venter på bakgrunnsoppgaver"
},
"startup": {
"content": "HACS starter opp, i løpet av denne tiden kan det hende at noe informasjon mangler eller er feil",
"title": "HACS starter opp"
}
},
"pending_updates": "Oppdateringer er klare"
},
"menu": {
"about": "Om HACS",
"clear": "Fjern alt nytt",
"custom_repositories": "Custom repositories",
"documentation": "Dokumentasjon",
"open_issue": "Meld et problem",
"reload": "Last inn vinduet på nytt"
},
"options": {
"step": {
"user": {
@ -93,10 +176,21 @@
"integration_not_loaded": "Integrasjonen er ikke lastet inn i Home Assistant.",
"no_restart_required": "Ingen omstart kreves",
"not_loaded": "Ikke lastet inn",
"plugin_not_loaded": "Denne pluginen er ikke lagt til i lovelace under \"resource\" delen av konfigurasjonen.",
"plugin_not_loaded": "Dette elementet er ikke lagt til i lovelace under \"resource\" delen av konfigurasjonen.",
"restart": "Du må restart Home Assistant",
"restart_pending": "Restart er nødvendig"
},
"repository_card": {
"hide": "Skjul",
"information": "Informasjon",
"new_repository": "Ny",
"open_issue": "Meld et problem",
"open_source": "Åpne kilde",
"pending_update": "Oppdatering venter",
"reinstall": "Installer på nytt",
"report": "Rapporter for fjerning",
"update_information": "Oppdater informasjon"
},
"repository": {
"add_to_lovelace": "Legg til i Lovelace",
"authors": "Laget av",
@ -113,7 +207,7 @@
"installed": "Installert",
"lovelace_copy_example": "Kopier eksemplet til utklippstavlen",
"lovelace_instruction": "Når du legger til dette i lovelace-konfigurasjonen din, bruk dette",
"lovelace_no_js_type": "Kunne ikke bestemme typen for denne plugin, sjekk repository.",
"lovelace_no_js_type": "Kunne ikke bestemme typen for dettte elementet, sjekk repository.",
"newest": "Nyeste",
"note_appdaemon": "du må fortsatt legge den til i 'apps.yaml' filen",
"note_installed": "Når det er installert, vil dette ligge i",
@ -121,7 +215,7 @@
"note_plugin": "du må fortsatt legge den til i lovelace-konfigurasjonen ('ui-lovelace.yaml' eller den rå UI-konfigurasjonsredigereren)",
"note_plugin_post_107": "du må fortsatt legge den til i lovelace konfigurasjonen ('configuration.yaml' eller via resource behanleren i grensesnittet '\/config\/lovelace\/resources')",
"open_issue": "Meld et problem",
"open_plugin": "Åpne plugin",
"open_plugin": "Åpne kilde",
"reinstall": "Installer på nytt",
"repository": "Repository",
"restart_home_assistant": "Start Home Assistant på nytt",
@ -130,6 +224,28 @@
"update_information": "Oppdater informasjon",
"upgrade": "Oppdater"
},
"search": {
"placeholder": "Søk etter repository"
},
"sections": {
"about": {
"description": "Vis informasjon om HACS",
"title": "Om"
},
"automation": {
"description": "Det er her du finner python_scripts, AppDaemon-apper og NetDaemon-apper",
"title": "Automasjon"
},
"frontend": {
"description": "Det er her du finner temaer, tilpassede kort og andre elementer for lovelace",
"title": "Frontend"
},
"integrations": {
"description": "Det er her du finner tilpassede integrasjoner (custom_components)",
"title": "Integrasjoner"
},
"pending_repository_upgrade": "Du kjører versjon {installed} , versjon {available} er tilgjengelig"
},
"settings": {
"add_custom_repository": "LEGG TIL REPOSITORY",
"adding_new_repo": "Legger til ny repository '{repo}'",
@ -161,6 +277,9 @@
"last_updated": "Sist oppdatert",
"name": "Navn",
"new_repositories": "Nye repositories",
"no_repositories": "Ingen repositories",
"no_repositories_desc1": "Det virker som om du ikke har noen elementer installert i denne delen ennå.",
"no_repositories_desc2": "Klikk på + i nederste hjørne for å legge til din første!",
"pending_upgrades": "Venter på oppgradering",
"placeholder_search": "Skriv inn et søkeord ...",
"sort": "sorter",

View File

@ -3,25 +3,35 @@
"about": "Om",
"appdaemon": "AppDaemon",
"appdaemon_apps": "AppDeamon-appar",
"appdaemon_plural": "AppDaemon-appar",
"background_task": "Bakgrunnsoppgåve køyrer. Denne sida kjem til å laste seg omatt når ho er ferdig.",
"check_log_file": "Sjå i loggfila di for meir detaljar.",
"continue": "Hald fram",
"disabled": "Deaktivert",
"documentation": "Dokumentasjon",
"element": "element",
"hacs_is_disabled": "HACS er deaktivert",
"installed": "Installert",
"integration": "Integrasjon",
"integration_plural": "Integrasjonar",
"integrations": "Integrasjonar",
"lovelace": "Lovelace",
"lovelace_element": "Lovelace-element",
"lovelace_elements": "Lovelace-element",
"manage": "Handtere",
"netdaemon": "NetDaemon",
"netdaemon_apps": "NetDeamon-appar",
"netdaemon_plural": "NetDaemon-appar",
"plugin": "Tillegg",
"plugin_plural": "Lovelace-element",
"plugins": "Tillegg",
"python_script": "Pythonskript",
"python_script_plural": "Pythonskript",
"python_scripts": "Pythonskript",
"repositories": "Repositories",
"settings": "innstillingar",
"theme": "Tema",
"theme_plural": "Tema",
"themes": "Tema",
"version": "Versjon"
},
@ -59,7 +69,7 @@
"exist": "{item} eksisterer allereie",
"generic": "Er du sikker?",
"home_assistant_is_restarting": "Vent... Home Assistant starter på nytt no.",
"home_assistant_version_not_correct": "Du køyrer Home Assistant-versjonen '{haversion}', men dette kodedepoet krev minimum versjon '{minversion}' for å bli installert.",
"home_assistant_version_not_correct": "Du køyrer Home Assistant-versjonen '{haversion}', men dette kodedepoet krev minst versjon '{minversion}' for å bli installert.",
"no": "Nei",
"no_upgrades": "Ingen ventande oppgradringer",
"ok": "OK",
@ -120,6 +130,7 @@
"note_installed": "Når dette er installert, kjem den til å vere plassert i",
"note_integration": "du må framleis legge dette til i \"configuration.yaml\"-fila di",
"note_plugin": "du må framleis dette til i Lovelace-konfigurasjonen (\"ui-lovelace.yaml\" eller i rå-brukargrensesnittredigeraren",
"note_plugin_post_107": "du må framleis legge dette til i lovelace-konfigurasjonen ('configuration.yaml' eller i kjelderedigeraren ''\/config\/lovelace\/resources')",
"open_issue": "Opne problem",
"open_plugin": "Opne tillegg",
"reinstall": "Installer på nytt",
@ -130,6 +141,25 @@
"update_information": "Oppdater informasjonen",
"upgrade": "Oppdater"
},
"sections": {
"about": {
"description": "Vis informasjon om HACS",
"title": "Om"
},
"automation": {
"description": "Her finn du python_scripts, AppDaemon-appar og NetDaemon-appar",
"title": "Automasjon"
},
"frontend": {
"description": "Her finn du tema, eigendefinerte kort og andre element for lovelace",
"title": "Frontend"
},
"integrations": {
"description": "Her finn du eigendefinerte ingtegrasjonar (custom_components)",
"title": "Integrasjonar"
},
"pending_repository_upgrade": "Du køyrer versjon {installed}, og versjon {available} er tilgjengeleg"
},
"settings": {
"add_custom_repository": "LEGG TIL EIN ANNAN REPOSITORY",
"adding_new_repo": "Legger til ny repository '{repo}'",

View File

@ -3,6 +3,7 @@
"about": "O",
"appdaemon": "AppDaemon",
"appdaemon_apps": "Aplikacje AppDaemon",
"appdaemon_plural": "Aplikacje AppDaemon",
"background_task": "Wykonywanie zadania w tle, ta strona zostanie odświeżona, gdy zadanie zostanie ukończone.",
"check_log_file": "Sprawdź plik dziennika, aby uzyskać więcej informacji.",
"continue": "Kontynuuj",
@ -11,17 +12,25 @@
"hacs_is_disabled": "HACS jest wyłączony",
"installed": "zainstalowane",
"integration": "Integracja",
"integration_plural": "Integracje",
"integrations": "Integracje",
"lovelace": "Lovelace",
"lovelace_element": "Element Lovelace",
"lovelace_elements": "Elementy Lovelace",
"manage": "zarządzaj",
"netdaemon": "NetDaemon",
"netdaemon_apps": "Aplikacje NetDaemon",
"netdaemon_plural": "Aplikacje NetDaemon",
"plugin": "Wtyczka",
"plugin_plural": "Elementy Lovelace",
"plugins": "Wtyczki",
"python_script": "Skrypt Python",
"python_script_plural": "Skrypty języka Python",
"python_scripts": "Skrypty Python",
"repositories": "Repozytoria",
"settings": "ustawienia",
"theme": "Motyw",
"theme_plural": "Motywy",
"themes": "Motywy",
"version": "Wersja"
},
@ -131,6 +140,22 @@
"update_information": "Uaktualnij informacje",
"upgrade": "Uaktualnij"
},
"sections": {
"about": {
"description": "Pokaż informacje o HACS"
},
"automation": {
"description": "Tutaj znajdziesz skrypty Pythona, aplikacje AppDaemon i NetDaemon",
"title": "Automatyzacja"
},
"frontend": {
"description": "Tutaj znajdziesz motywy, niestandardowe karty i inne elementy dla Lovelace"
},
"integrations": {
"description": "Tutaj znajdziesz niestandardowe integracje (custom_components)",
"title": "Integracje"
}
},
"settings": {
"add_custom_repository": "DODAJ REPOZYTORIUM NIESTANDARDOWE",
"adding_new_repo": "Dodawanie nowego repozytorium '{repo}'",

View File

@ -6,7 +6,7 @@ https://hacs.xyz/
"""
import voluptuous as vol
from aiogithubapi import AIOGitHub, AIOGitHubException
from aiogithubapi import GitHub, AIOGitHubAPIException
from homeassistant import config_entries
from homeassistant.const import EVENT_HOMEASSISTANT_START
from homeassistant.const import __version__ as HAVERSION
@ -15,12 +15,9 @@ from homeassistant.exceptions import ConfigEntryNotReady, ServiceNotFound
from homeassistant.helpers.aiohttp_client import async_create_clientsession
from homeassistant.helpers.event import async_call_later
from custom_components.hacs.configuration_schema import (
hacs_base_config_schema,
hacs_config_option_schema,
)
from custom_components.hacs.configuration_schema import hacs_config_combined
from custom_components.hacs.const import DOMAIN, ELEMENT_TYPES, STARTUP, VERSION
from custom_components.hacs.constrains import check_constans, check_requirements
from custom_components.hacs.constrains import check_constrains
from custom_components.hacs.helpers.remaining_github_calls import get_fetch_updates_for
from custom_components.hacs.hacsbase.configuration import Configuration
from custom_components.hacs.hacsbase.data import HacsData
@ -34,9 +31,7 @@ from custom_components.hacs.globals import get_hacs
from custom_components.hacs.helpers.network import internet_connectivity_check
SCHEMA = hacs_base_config_schema()
SCHEMA[vol.Optional("options")] = hacs_config_option_schema()
CONFIG_SCHEMA = vol.Schema({DOMAIN: SCHEMA}, extra=vol.ALLOW_EXTRA)
CONFIG_SCHEMA = vol.Schema({DOMAIN: hacs_config_combined()}, extra=vol.ALLOW_EXTRA)
async def async_setup(hass, config):
@ -49,17 +44,10 @@ async def async_setup(hass, config):
hass.data[DOMAIN] = config
hacs.hass = hass
hacs.session = async_create_clientsession(hass)
hacs.configuration = Configuration.from_dict(
config[DOMAIN], config[DOMAIN].get("options")
)
hacs.configuration = Configuration.from_dict(config[DOMAIN])
hacs.configuration.config = config
hacs.configuration.config_type = "yaml"
await startup_wrapper_for_yaml()
hass.async_create_task(
hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, data={}
)
)
return True
@ -67,11 +55,10 @@ async def async_setup_entry(hass, config_entry):
"""Set up this integration using UI."""
hacs = get_hacs()
conf = hass.data.get(DOMAIN)
if conf is not None:
return False
if config_entry.source == config_entries.SOURCE_IMPORT:
if conf is None:
hass.async_create_task(
hass.config_entries.async_remove(config_entry.entry_id)
)
hass.async_create_task(hass.config_entries.async_remove(config_entry.entry_id))
return False
hacs.hass = hass
hacs.session = async_create_clientsession(hass)
@ -83,7 +70,7 @@ async def async_setup_entry(hass, config_entry):
config_entry.add_update_listener(reload_hacs)
try:
startup_result = await hacs_startup()
except AIOGitHubException:
except AIOGitHubAPIException:
startup_result = False
if not startup_result:
hacs.system.disabled = True
@ -97,7 +84,7 @@ async def startup_wrapper_for_yaml():
hacs = get_hacs()
try:
startup_result = await hacs_startup()
except AIOGitHubException:
except AIOGitHubAPIException:
startup_result = False
if not startup_result:
hacs.system.disabled = True
@ -115,8 +102,6 @@ async def startup_wrapper_for_yaml():
async def hacs_startup():
"""HACS startup tasks."""
hacs = get_hacs()
if not check_requirements():
return False
if hacs.configuration.debug:
try:
await hacs.hass.services.async_call(
@ -142,7 +127,7 @@ async def hacs_startup():
hacs.system.lovelace_mode = lovelace_info.get("mode", "yaml")
hacs.system.disabled = False
hacs.github = AIOGitHub(
hacs.github = GitHub(
hacs.configuration.token, async_create_clientsession(hacs.hass)
)
hacs.data = HacsData()
@ -154,7 +139,7 @@ async def hacs_startup():
hacs.logger.debug(f"Can update {can_update} repositories")
# Check HACS Constrains
if not await hacs.hass.async_add_executor_job(check_constans):
if not await hacs.hass.async_add_executor_job(check_constrains):
if hacs.configuration.config_type == "flow":
if hacs.configuration.config_entry is not None:
await async_remove_entry(hacs.hass, hacs.configuration.config_entry)
@ -189,18 +174,6 @@ async def hacs_startup():
hacs.common.categories.append("appdaemon")
if hacs.configuration.netdaemon:
hacs.common.categories.append("netdaemon")
if hacs.configuration.python_script:
hacs.configuration.python_script = False
if hacs.configuration.config_type == "yaml":
hacs.logger.warning(
"Configuration option 'python_script' is deprecated and you should remove it from your configuration, HACS will know if you use 'python_script' in your Home Assistant configuration, this option will be removed in a future release."
)
if hacs.configuration.theme:
hacs.configuration.theme = False
if hacs.configuration.config_type == "yaml":
hacs.logger.warning(
"Configuration option 'theme' is deprecated and you should remove it from your configuration, HACS will know if you use 'theme' in your Home Assistant configuration, this option will be removed in a future release."
)
# Setup startup tasks
if hacs.configuration.config_type == "yaml":

View File

@ -2,7 +2,7 @@
# pylint: disable=dangerous-default-value
import logging
import voluptuous as vol
from aiogithubapi import AIOGitHubException, AIOGitHubAuthentication
from aiogithubapi import AIOGitHubAPIException, AIOGitHubAPIAuthenticationException
from homeassistant import config_entries
from homeassistant.core import callback
from homeassistant.helpers import aiohttp_client
@ -47,7 +47,7 @@ class HacsFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
"""Show the configuration form to edit location data."""
return self.async_show_form(
step_id="user",
data_schema=vol.Schema(hacs_base_config_schema(user_input, True)),
data_schema=vol.Schema(hacs_base_config_schema(user_input)),
errors=self._errors,
)
@ -56,23 +56,16 @@ class HacsFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
def async_get_options_flow(config_entry):
return HacsOptionsFlowHandler(config_entry)
async def async_step_import(self, user_input):
"""Import a config entry.
Special type of import, we're not actually going to store any data.
Instead, we're going to rely on the values that are in config file.
"""
if self._async_current_entries():
return self.async_abort(reason="single_instance_allowed")
return self.async_create_entry(title="configuration.yaml", data={})
async def _test_token(self, token):
"""Return true if token is valid."""
try:
session = aiohttp_client.async_get_clientsession(self.hass)
await get_repository(session, token, "hacs/org")
return True
except (AIOGitHubException, AIOGitHubAuthentication) as exception:
except (
AIOGitHubAPIException,
AIOGitHubAPIAuthenticationException,
) as exception:
_LOGGER.error(exception)
return False

View File

@ -9,8 +9,6 @@ SIDEPANEL_TITLE = "sidepanel_title"
SIDEPANEL_ICON = "sidepanel_icon"
APPDAEMON = "appdaemon"
NETDAEMON = "netdaemon"
PYTHON_SCRIPT = "python_script"
THEME = "theme"
# Options:
COUNTRY = "country"
@ -19,46 +17,39 @@ RELEASE_LIMIT = "release_limit"
EXPERIMENTAL = "experimental"
def hacs_base_config_schema(config: dict = {}, config_flow: bool = False) -> dict:
def hacs_base_config_schema(config: dict = {}) -> dict:
"""Return a shcema configuration dict for HACS."""
if not config:
config = {
TOKEN: "xxxxxxxxxxxxxxxxxxxxxxxxxxx",
SIDEPANEL_ICON: "mdi:alpha-c-box",
SIDEPANEL_TITLE: "HACS",
APPDAEMON: False,
NETDAEMON: False,
PYTHON_SCRIPT: False,
THEME: False,
}
if config_flow:
return {
vol.Required(TOKEN, default=config.get(TOKEN)): str,
vol.Optional(SIDEPANEL_TITLE, default=config.get(SIDEPANEL_TITLE)): str,
vol.Optional(SIDEPANEL_ICON, default=config.get(SIDEPANEL_ICON)): str,
vol.Optional(APPDAEMON, default=config.get(APPDAEMON)): bool,
vol.Optional(NETDAEMON, default=config.get(NETDAEMON)): bool,
}
return {
vol.Required(TOKEN, default=config.get(TOKEN)): str,
vol.Optional(SIDEPANEL_TITLE, default=config.get(SIDEPANEL_TITLE)): str,
vol.Optional(SIDEPANEL_ICON, default=config.get(SIDEPANEL_ICON)): str,
vol.Optional(APPDAEMON, default=config.get(APPDAEMON)): bool,
vol.Optional(NETDAEMON, default=config.get(NETDAEMON)): bool,
vol.Optional(PYTHON_SCRIPT, default=config.get(PYTHON_SCRIPT)): bool,
vol.Optional(THEME, default=config.get(THEME)): bool,
}
def hacs_config_option_schema(options: dict = {}) -> dict:
"""Return a shcema for HACS configuration options."""
if not options:
options = {COUNTRY: "ALL", DEBUG: False, RELEASE_LIMIT: 5, EXPERIMENTAL: False}
options = {
APPDAEMON: False,
COUNTRY: "ALL",
DEBUG: False,
EXPERIMENTAL: False,
NETDAEMON: False,
RELEASE_LIMIT: 5,
SIDEPANEL_ICON: "hacs:hacs",
SIDEPANEL_TITLE: "HACS",
}
return {
vol.Optional(COUNTRY, default=options.get(COUNTRY)): vol.In(LOCALE),
vol.Optional(SIDEPANEL_TITLE, default=options.get(SIDEPANEL_TITLE)): str,
vol.Optional(SIDEPANEL_ICON, default=options.get(SIDEPANEL_ICON)): str,
vol.Optional(RELEASE_LIMIT, default=options.get(RELEASE_LIMIT)): int,
vol.Optional(EXPERIMENTAL, default=options.get(EXPERIMENTAL)): bool,
vol.Optional(COUNTRY, default=options.get(COUNTRY)): vol.In(LOCALE),
vol.Optional(APPDAEMON, default=options.get(APPDAEMON)): bool,
vol.Optional(NETDAEMON, default=options.get(NETDAEMON)): bool,
vol.Optional(DEBUG, default=options.get(DEBUG)): bool,
vol.Optional(EXPERIMENTAL, default=options.get(EXPERIMENTAL)): bool,
}

View File

@ -1,7 +1,7 @@
"""Constants for HACS"""
NAME_LONG = "HACS (Home Assistant Community Store)"
NAME_SHORT = "HACS"
VERSION = "0.24.5"
VERSION = "1.0.0"
DOMAIN = "hacs"
PROJECT_URL = "https://github.com/hacs/integration/"
CUSTOM_UPDATER_LOCATIONS = [
@ -15,8 +15,8 @@ DOMAIN_DATA = f"{NAME_SHORT.lower()}_data"
ELEMENT_TYPES = ["integration", "plugin"]
IFRAME = {
"title": "Community",
"icon": "mdi:alpha-c-box",
"title": "HACS",
"icon": "hacs:hacs",
"url": "/community_overview",
"path": "community",
"require_admin": True,

View File

@ -7,10 +7,10 @@ from .helpers.misc import version_left_higher_then_right
from custom_components.hacs.globals import get_hacs
MINIMUM_HA_VERSION = "0.98.0"
MINIMUM_HA_VERSION = "0.110.0"
def check_constans():
def check_constrains():
"""Check HACS constrains."""
if not constrain_translations():
return False
@ -54,46 +54,3 @@ def constrain_translations():
hacs.logger.critical("You are missing the translations directory.")
return False
return True
def check_requirements():
"""Check the requirements"""
missing = []
try:
from aiogithubapi import AIOGitHubException # pylint: disable=unused-import
except ImportError:
missing.append("aiogithubapi")
try:
from hacs_frontend import locate_gz # pylint: disable=unused-import
except ImportError:
missing.append("hacs_frontend")
try:
import semantic_version # pylint: disable=unused-import
except ImportError:
missing.append("semantic_version")
try:
from integrationhelper import Logger # pylint: disable=unused-import
except ImportError:
missing.append("integrationhelper")
try:
import backoff # pylint: disable=unused-import
except ImportError:
missing.append("backoff")
try:
import aiofiles # pylint: disable=unused-import
except ImportError:
missing.append("aiofiles")
if missing:
hacs = get_hacs()
for requirement in missing:
hacs.logger.critical(
f"Required python requirement '{requirement}' is not installed"
)
return False
return True

View File

@ -1,6 +1,7 @@
# pylint: disable=invalid-name, missing-docstring
hacs = []
removed_repositories = []
rules = {}
def get_hacs():

View File

@ -6,7 +6,7 @@ from datetime import timedelta
from homeassistant.helpers.event import async_call_later, async_track_time_interval
from aiogithubapi import AIOGitHubException, AIOGitHubRatelimit
from aiogithubapi import AIOGitHubAPIException, AIOGitHubAPIRatelimitException
from integrationhelper import Logger
from queueman import QueueManager
@ -115,7 +115,7 @@ class Hacs:
"""Get repository by ID."""
try:
for repository in self.repositories:
if repository.information.uid == repository_id:
if str(repository.data.id) == str(repository_id):
return repository
except Exception: # pylint: disable=broad-except
pass
@ -131,11 +131,9 @@ class Hacs:
pass
return None
def is_known(self, repository_full_name):
def is_known(self, repository_id):
"""Return a bool if the repository is known."""
return repository_full_name.lower() in [
x.data.full_name.lower() for x in self.repositories
]
return str(repository_id) in [str(x.data.id) for x in self.repositories]
@property
def sorted_by_name(self):
@ -156,8 +154,6 @@ class Hacs:
self.system.status.background_task = True
await self.hass.async_add_executor_job(setup_extra_stores)
self.hass.bus.async_fire("hacs/status", {})
self.logger.debug(self.github.ratelimits.remaining)
self.logger.debug(self.github.ratelimits.reset_utc)
await self.handle_critical_repositories_startup()
await self.handle_critical_repositories()
@ -186,7 +182,6 @@ class Hacs:
await self.prosess_queue()
self.system.status.startup = False
self.system.status.new = False
self.system.status.background_task = False
self.hass.bus.async_fire("hacs/status", {})
await self.data.async_write()
@ -216,7 +211,7 @@ class Hacs:
try:
critical = await self.data_repo.get_contents("critical")
critical = json.loads(critical.content)
except AIOGitHubException:
except AIOGitHubAPIException:
pass
if not critical:
@ -290,11 +285,10 @@ class Hacs:
)
self.system.status.background_task = True
self.hass.bus.async_fire("hacs/status", {})
self.logger.debug(self.github.ratelimits.remaining)
self.logger.debug(self.github.ratelimits.reset_utc)
for repository in self.repositories:
if (
repository.status.installed
repository.data.installed
and repository.data.category in self.common.categories
):
self.queue.add(self.factory.safe_update(repository))
@ -311,8 +305,7 @@ class Hacs:
await self.hass.async_add_executor_job(setup_extra_stores)
self.system.status.background_task = True
self.hass.bus.async_fire("hacs/status", {})
self.logger.debug(self.github.ratelimits.remaining)
self.logger.debug(self.github.ratelimits.reset_utc)
for repository in self.repositories:
if repository.data.category in self.common.categories:
self.queue.add(self.factory.safe_common_update(repository))
@ -329,9 +322,9 @@ class Hacs:
"""Clear out blaclisted repositories."""
need_to_save = False
for removed in removed_repositories:
if self.is_known(removed.repository):
repository = self.get_by_name(removed.repository)
if repository.status.installed and removed.removal_type != "critical":
repository = self.get_by_name(removed.repository)
if repository is not None:
if repository.data.installed and removed.removal_type != "critical":
self.logger.warning(
f"You have {repository.data.full_name} installed with HACS "
+ f"this repository has been removed, please consider removing it. "
@ -354,11 +347,6 @@ class Hacs:
org = await get_default_repos_orgs(self.github, category)
for repo in org:
repositories[category].append(repo)
for category in repositories:
for repo in repositories[category]:
if repo not in self.common.default:
self.common.default.append(repo)
return repositories
async def load_known_repositories(self):
@ -378,6 +366,11 @@ class Hacs:
for repo in repositories[category]:
if is_removed(repo):
continue
if self.is_known(repo):
repository = self.get_by_name(repo)
if repository is not None:
if str(repository.data.id) not in self.common.default:
self.common.default.append(str(repository.data.id))
else:
continue
continue
self.queue.add(self.factory.safe_register(repo, category))

View File

@ -25,8 +25,8 @@ class Configuration:
plugin_path: str = "www/community/"
python_script_path: str = "python_scripts/"
python_script: bool = False
sidepanel_icon: str = "mdi:alpha-c-box"
sidepanel_title: str = "Community"
sidepanel_icon: str = "hacs:hacs"
sidepanel_title: str = "HACS"
theme_path: str = "themes/"
theme: bool = False
token: str = None
@ -50,7 +50,7 @@ class Configuration:
logger.debug(f"{key}: {config[key]}")
@staticmethod
def from_dict(configuration: dict, options: dict):
def from_dict(configuration: dict, options: dict = None):
"""Set attributes from dicts."""
if isinstance(options, bool) or isinstance(configuration.get("options"), bool):
raise HacsException("Configuration is not valid.")

View File

@ -42,28 +42,39 @@ class HacsData:
repository_manifest = repository.repository_manifest.manifest
else:
repository_manifest = None
content[repository.information.uid] = {
data = {
"authors": repository.data.authors,
"category": repository.data.category,
"description": repository.data.description,
"downloads": repository.releases.downloads,
"domain": repository.data.domain,
"downloads": repository.data.downloads,
"full_name": repository.data.full_name,
"first_install": repository.status.first_install,
"hide": repository.status.hide,
"installed_commit": repository.versions.installed_commit,
"installed": repository.status.installed,
"last_commit": repository.versions.available_commit,
"last_release_tag": repository.versions.available,
"last_updated": repository.information.last_updated,
"installed_commit": repository.data.installed_commit,
"installed": repository.data.installed,
"last_commit": repository.data.last_commit,
"last_release_tag": repository.data.last_version,
"last_updated": repository.data.last_updated,
"name": repository.data.name,
"new": repository.status.new,
"new": repository.data.new,
"repository_manifest": repository_manifest,
"selected_tag": repository.status.selected_tag,
"show_beta": repository.status.show_beta,
"selected_tag": repository.data.selected_tag,
"show_beta": repository.data.show_beta,
"stars": repository.data.stargazers_count,
"topics": repository.data.topics,
"version_installed": repository.versions.installed,
"version_installed": repository.data.installed_version,
}
if data:
if repository.data.installed and (
repository.data.installed_commit
or repository.data.installed_version
):
await async_save_to_store(
self.hacs.hass,
f"hacs/{repository.data.id}.hacs",
repository.data.to_json(),
)
content[str(repository.data.id)] = data
await async_save_to_store(self.hacs.hass, "repositories", content)
self.hacs.hass.bus.async_fire("hacs/repository", {})
@ -79,6 +90,7 @@ class HacsData:
self.hacs.system.status.new = True
return True
self.logger.info("Restore started")
self.hacs.system.status.new = False
# Hacs
self.hacs.configuration.frontend_mode = hacs.get("view", "Grid")
@ -88,21 +100,40 @@ class HacsData:
# Repositories
for entry in repositories:
repo = repositories[entry]
if not self.hacs.is_known(repo["full_name"]):
if not self.hacs.is_known(entry):
await register_repository(
repo["full_name"], repo["category"], False
)
repository = self.hacs.get_by_name(repo["full_name"])
if repository is None:
self.logger.error(f"Did not find {repo['full_name']}")
repository = [
x
for x in self.hacs.repositories
if str(x.data.id) == str(entry)
or x.data.full_name == repo["full_name"]
]
if not repository:
self.logger.error(f"Did not find {repo['full_name']} ({entry})")
continue
repository = repository[0]
# Restore repository attributes
repository.information.uid = entry
repository.data.id = entry
await self.hacs.hass.async_add_executor_job(
restore_repository_data, repository, repo
)
restored = await async_load_from_store(
self.hacs.hass, f"hacs/{entry}.hacs"
)
if restored:
repository.data.update_data(restored)
if not repository.data.installed:
repository.logger.debug(
"Should be installed but is not... Fixing that!"
)
repository.data.installed = True
self.logger.info("Restore done")
except Exception as exception: # pylint: disable=broad-except
self.logger.critical(f"[{exception}] Restore Failed!")
@ -117,27 +148,28 @@ def restore_repository_data(
repository.data.authors = repository_data.get("authors", [])
repository.data.description = repository_data.get("description")
repository.releases.last_release_object_downloads = repository_data.get("downloads")
repository.information.last_updated = repository_data.get("last_updated")
repository.data.last_updated = repository_data.get("last_updated")
repository.data.topics = repository_data.get("topics", [])
repository.data.domain = repository_data.get("domain", None)
repository.data.stargazers_count = repository_data.get("stars", 0)
repository.releases.last_release = repository_data.get("last_release_tag")
repository.status.hide = repository_data.get("hide", False)
repository.status.installed = repository_data.get("installed", False)
repository.status.new = repository_data.get("new", True)
repository.status.selected_tag = repository_data.get("selected_tag")
repository.status.show_beta = repository_data.get("show_beta", False)
repository.versions.available = repository_data.get("last_release_tag")
repository.versions.available_commit = repository_data.get("last_commit")
repository.versions.installed = repository_data.get("version_installed")
repository.versions.installed_commit = repository_data.get("installed_commit")
repository.data.hide = repository_data.get("hide", False)
repository.data.installed = repository_data.get("installed", False)
repository.data.new = repository_data.get("new", True)
repository.data.selected_tag = repository_data.get("selected_tag")
repository.data.show_beta = repository_data.get("show_beta", False)
repository.data.last_version = repository_data.get("last_release_tag")
repository.data.last_commit = repository_data.get("last_commit")
repository.data.installed_version = repository_data.get("version_installed")
repository.data.installed_commit = repository_data.get("installed_commit")
repository.repository_manifest = HacsManifest.from_dict(
repository_data.get("repository_manifest", {})
)
if repository.status.installed:
if repository.data.installed:
repository.status.first_install = False
if repository_data["full_name"] == "hacs/integration":
repository.versions.installed = VERSION
repository.status.installed = True
repository.data.installed_version = VERSION
repository.data.installed = True

View File

@ -3,7 +3,7 @@ import logging
import time
from datetime import timedelta
import asyncio
from aiogithubapi import AIOGitHubException
from aiogithubapi import AIOGitHubAPIException
from custom_components.hacs.hacsbase.exceptions import HacsException
from custom_components.hacs.helpers.register_repository import register_repository
@ -48,7 +48,7 @@ class HacsTaskFactory:
async with max_concurrent_tasks:
try:
await repository.common_update()
except (AIOGitHubException, HacsException) as exception:
except (AIOGitHubAPIException, HacsException) as exception:
logger.error("%s - %s", repository.data.full_name, exception)
# Due to GitHub ratelimits we need to sleep a bit
@ -58,7 +58,7 @@ class HacsTaskFactory:
async with max_concurrent_tasks:
try:
await repository.update_repository()
except (AIOGitHubException, HacsException) as exception:
except (AIOGitHubAPIException, HacsException) as exception:
logger.error("%s - %s", repository.data.full_name, exception)
# Due to GitHub ratelimits we need to sleep a bit
@ -68,7 +68,7 @@ class HacsTaskFactory:
async with max_concurrent_tasks:
try:
await register_repository(repo, category)
except (AIOGitHubException, HacsException) as exception:
except (AIOGitHubAPIException, HacsException) as exception:
logger.error("%s - %s", repo, exception)
# Due to GitHub ratelimits we need to sleep a bit

View File

@ -16,10 +16,10 @@ def render_template(content, context):
try:
render = Template(content)
render = render.render(
installed=context.status.installed,
installed=context.data.installed,
pending_update=context.pending_upgrade,
prerelease=prerelease,
selected_tag=context.status.selected_tag,
selected_tag=context.data.selected_tag,
version_available=context.releases.last_release,
version_installed=context.display_installed_version,
)

View File

@ -26,7 +26,7 @@ def should_try_releases(repository):
return False
if repository.data.category not in ["plugin", "theme"]:
return False
if not repository.releases.releases:
if not repository.data.releases:
return False
return True

View File

@ -1,11 +1,12 @@
"""Helpers to get default repositories."""
import json
from aiogithubapi import AIOGitHub, AIOGitHubException
from aiogithubapi import GitHub, AIOGitHubAPIException
from integrationhelper import Logger
from custom_components.hacs.hacsbase.exceptions import HacsException
from custom_components.hacs.helpers.information import get_repository
async def get_default_repos_orgs(github: type(AIOGitHub), category: str) -> dict:
async def get_default_repos_orgs(github: type(GitHub), category: str) -> dict:
"""Gets default org repositories."""
repositories = []
logger = Logger("hacs")
@ -22,7 +23,7 @@ async def get_default_repos_orgs(github: type(AIOGitHub), category: str) -> dict
for repo in repos:
repositories.append(repo.full_name)
except AIOGitHubException as exception:
except AIOGitHubAPIException as exception:
logger.error(exception)
return repositories
@ -38,7 +39,7 @@ async def get_default_repos_lists(session, token, default: str) -> dict:
content = await repo.get_contents(default)
repositories = json.loads(content.content)
except AIOGitHubException as exception:
except (AIOGitHubAPIException, HacsException) as exception:
logger.error(exception)
return repositories

View File

@ -1,6 +1,6 @@
"""Return repository information if any."""
import json
from aiogithubapi import AIOGitHubException, AIOGitHub
from aiogithubapi import AIOGitHubAPIException, GitHub
from custom_components.hacs.handler.template import render_template
from custom_components.hacs.hacsbase.exceptions import HacsException
@ -29,7 +29,7 @@ async def get_info_md_content(repository):
return ""
info = info.content.replace("<svg", "<disabled").replace("</svg", "</disabled")
return render_template(info, repository)
except (AIOGitHubException, Exception): # pylint: disable=broad-except
except (AIOGitHubAPIException, Exception): # pylint: disable=broad-except
if repository.hacs.action:
raise HacsException("No info file found")
return ""
@ -38,10 +38,10 @@ async def get_info_md_content(repository):
async def get_repository(session, token, repository_full_name):
"""Return a repository object or None."""
try:
github = AIOGitHub(token, session)
github = GitHub(token, session)
repository = await github.get_repo(repository_full_name)
return repository
except AIOGitHubException as exception:
except (AIOGitHubAPIException, Exception) as exception:
raise HacsException(exception)
@ -50,7 +50,7 @@ async def get_tree(repository, ref):
try:
tree = await repository.get_tree(ref)
return tree
except AIOGitHubException as exception:
except AIOGitHubAPIException as exception:
raise HacsException(exception)
@ -59,7 +59,7 @@ async def get_releases(repository, prerelease=False, returnlimit=5):
try:
releases = await repository.get_releases(prerelease, returnlimit)
return releases
except AIOGitHubException as exception:
except AIOGitHubAPIException as exception:
raise HacsException(exception)
@ -84,6 +84,7 @@ async def get_integration_manifest(repository):
repository.data.authors = manifest["codeowners"]
repository.data.domain = manifest["domain"]
repository.data.manifest_name = manifest["name"]
repository.data.config_flow = manifest.get("config_flow", False)
if repository.hacs.action:
if manifest.get("documentation") is None:
@ -115,6 +116,10 @@ def find_file_name(repository):
elif repository.data.category == "python_script":
get_file_name_python_script(repository)
if repository.hacs.action:
repository.logger.info(f"filename {repository.data.file_name}")
repository.logger.info(f"location {repository.content.path.remote}")
def get_file_name_plugin(repository):
"""Get the filename to target."""

View File

@ -26,7 +26,7 @@ async def install_repository(repository):
else:
repository.ref = f"tags/{version}"
if repository.status.installed and repository.data.category == "netdaemon":
if repository.data.installed and repository.data.category == "netdaemon":
persistent_directory = BackupNetDaemon(repository)
persistent_directory.create()
@ -40,7 +40,7 @@ async def install_repository(repository):
)
persistent_directory.create()
if repository.status.installed and not repository.content.single:
if repository.data.installed and not repository.content.single:
backup = Backup(repository.content.path.local)
backup.create()
@ -52,10 +52,10 @@ async def install_repository(repository):
if repository.validate.errors:
for error in repository.validate.errors:
repository.logger.error(error)
if repository.status.installed and not repository.content.single:
if repository.data.installed and not repository.content.single:
backup.restore()
if repository.status.installed and not repository.content.single:
if repository.data.installed and not repository.content.single:
backup.cleanup()
if persistent_directory is not None:
@ -66,13 +66,13 @@ async def install_repository(repository):
if repository.data.full_name not in repository.hacs.common.installed:
if repository.data.full_name == "hacs/integration":
repository.hacs.common.installed.append(repository.data.full_name)
repository.status.installed = True
repository.versions.installed_commit = repository.versions.available_commit
repository.data.installed = True
repository.data.installed_commit = repository.data.last_commit
if version == repository.data.default_branch:
repository.versions.installed = None
repository.data.installed_version = None
else:
repository.versions.installed = version
repository.data.installed_version = version
await reload_after_install(repository)
installation_complete(repository)
@ -81,7 +81,7 @@ async def install_repository(repository):
async def reload_after_install(repository):
"""Reload action after installation success."""
if repository.data.category == "integration":
if repository.config_flow:
if repository.data.config_flow:
if repository.data.full_name != "hacs/integration":
await repository.reload_custom_components()
repository.pending_restart = True
@ -113,18 +113,18 @@ def installation_complete(repository):
def version_to_install(repository):
"""Determine which version to isntall."""
if repository.versions.available is not None:
if repository.status.selected_tag is not None:
if repository.status.selected_tag == repository.versions.available:
repository.status.selected_tag = None
return repository.versions.available
return repository.status.selected_tag
return repository.versions.available
if repository.status.selected_tag is not None:
if repository.status.selected_tag == repository.data.default_branch:
if repository.data.last_version is not None:
if repository.data.selected_tag is not None:
if repository.data.selected_tag == repository.data.last_version:
repository.data.selected_tag = None
return repository.data.last_version
return repository.data.selected_tag
return repository.data.last_version
if repository.data.selected_tag is not None:
if repository.data.selected_tag == repository.data.default_branch:
return repository.data.default_branch
if repository.status.selected_tag in repository.releases.published_tags:
return repository.status.selected_tag
if repository.data.selected_tag in repository.data.published_tags:
return repository.data.selected_tag
if repository.data.default_branch is None:
return "master"
return repository.data.default_branch

View File

@ -1,5 +1,5 @@
"""Register a repository."""
from aiogithubapi import AIOGitHubException
from aiogithubapi import AIOGitHubAPIException
from custom_components.hacs.globals import get_hacs
from custom_components.hacs.hacsbase.exceptions import (
HacsException,
@ -29,7 +29,7 @@ async def register_repository(full_name, category, check=True, ref=None, action=
try:
await repository.registration(ref)
if hacs.system.status.new:
repository.status.new = False
repository.data.new = False
if repository.validate.errors:
hacs.common.skip.append(repository.data.full_name)
if not hacs.system.status.startup:
@ -41,18 +41,29 @@ async def register_repository(full_name, category, check=True, ref=None, action=
repository.logger.info("Validation complete")
else:
repository.logger.info("Registration complete")
except AIOGitHubException as exception:
except AIOGitHubAPIException as exception:
hacs.common.skip.append(repository.data.full_name)
raise HacsException(f"Validation for {full_name} failed with {exception}.")
if hacs.hass is not None:
hacs.hass.bus.async_fire(
"hacs/repository",
{
"id": 1337,
"action": "registration",
"repository": repository.data.full_name,
"repository_id": repository.information.uid,
},
)
exists = (
False
if str(repository.data.id) == "0"
else [x for x in hacs.repositories if str(x.data.id) == str(repository.data.id)]
)
if exists:
if exists[0] in hacs.repositories:
hacs.repositories.remove(exists[0])
else:
if hacs.hass is not None:
hacs.hass.bus.async_fire(
"hacs/repository",
{
"id": 1337,
"action": "registration",
"repository": repository.data.full_name,
"repository_id": repository.data.id,
},
)
hacs.repositories.append(repository)

View File

@ -1,5 +1,5 @@
"""Helper to do common validation for repositories."""
from aiogithubapi import AIOGitHubException
from aiogithubapi import AIOGitHubAPIException
from custom_components.hacs.globals import get_hacs, is_removed
from custom_components.hacs.hacsbase.exceptions import HacsException
from custom_components.hacs.helpers.install import version_to_install
@ -10,19 +10,19 @@ from custom_components.hacs.helpers.information import (
)
async def common_validate(repository):
async def common_validate(repository, ignore_issues=False):
"""Common validation steps of the repository."""
repository.validate.errors = []
# Make sure the repository exist.
repository.logger.debug("Checking repository.")
await common_update_data(repository)
await common_update_data(repository, ignore_issues)
# Step 6: Get the content of hacs.json
await repository.get_repository_manifest_content()
async def common_update_data(repository):
async def common_update_data(repository, ignore_issues=False):
"""Common update data."""
hacs = get_hacs()
try:
@ -31,19 +31,19 @@ async def common_update_data(repository):
)
repository.repository_object = repository_object
repository.data.update_data(repository_object.attributes)
except (AIOGitHubException, HacsException) as exception:
except (AIOGitHubAPIException, HacsException) as exception:
if not hacs.system.status.startup:
repository.logger.error(exception)
repository.validate.errors.append("Repository does not exist.")
raise HacsException(exception)
# Make sure the repository is not archived.
if repository.data.archived:
if repository.data.archived and not ignore_issues:
repository.validate.errors.append("Repository is archived.")
raise HacsException("Repository is archived.")
# Make sure the repository is not in the blacklist.
if is_removed(repository.data.full_name):
if is_removed(repository.data.full_name) and not ignore_issues:
repository.validate.errors.append("Repository is in the blacklist.")
raise HacsException("Repository is in the blacklist.")
@ -51,29 +51,29 @@ async def common_update_data(repository):
try:
releases = await get_releases(
repository.repository_object,
repository.status.show_beta,
repository.data.show_beta,
hacs.configuration.release_limit,
)
if releases:
repository.releases.releases = True
repository.data.releases = True
repository.releases.objects = releases
repository.releases.published_tags = [
repository.data.published_tags = [
x.tag_name for x in releases if not x.draft
]
repository.versions.available = next(iter(releases)).tag_name
repository.data.last_version = next(iter(releases)).tag_name
except (AIOGitHubException, HacsException):
repository.releases.releases = False
except (AIOGitHubAPIException, HacsException):
repository.data.releases = False
if not repository.force_branch:
repository.ref = version_to_install(repository)
if repository.releases.releases:
if repository.data.releases:
for release in releases:
if release.tag_name == repository.ref:
assets = release.assets
if assets:
downloads = next(iter(assets)).attributes.get("download_count")
repository.releases.downloads = downloads
repository.data.downloads = downloads
repository.logger.debug(
f"Running checks against {repository.ref.replace('tags/', '')}"
@ -86,7 +86,7 @@ async def common_update_data(repository):
repository.treefiles = []
for treefile in repository.tree:
repository.treefiles.append(treefile.full_path)
except (AIOGitHubException, HacsException) as exception:
except (AIOGitHubAPIException, HacsException) as exception:
if not hacs.system.status.startup:
repository.logger.error(exception)
raise HacsException(exception)

View File

@ -20,24 +20,6 @@ class HacsFrontend(HomeAssistantView):
return await get_file_response(requested_file)
class HacsPluginViewLegacy(HacsFrontend):
"""Alias for legacy, remove with 1.0"""
name = "community_plugin"
url = r"/community_plugin/{requested_file:.+}"
async def get(self, request, requested_file): # pylint: disable=unused-argument
"""DEPRECATED."""
hacs = get_hacs()
if hacs.system.ha_version.split(".")[1] >= "107":
logger = Logger("hacs.deprecated")
logger.warning(
"The '/community_plugin/*' is deprecated and will be removed in an upcoming version of HACS, it has been replaced by '/hacsfiles/*', if you use the UI to manage your lovelace configuration, you can update this by going to the settings tab in HACS, if you use YAML to manage your lovelace configuration, you manually need to replace the URL in your resources."
)
return await get_file_response(requested_file)
async def get_file_response(requested_file):
"""Get file."""
hacs = get_hacs()

View File

@ -1,20 +1,7 @@
const hacsIconPath = "m 20.064849,22.306912 c -0.0319,0.369835 -0.280561,0.707789 -0.656773,0.918212 -0.280572,0.153036 -0.605773,0.229553 -0.950094,0.229553 -0.0765,0 -0.146661,-0.0064 -0.216801,-0.01275 -0.605774,-0.05739 -1.135016,-0.344329 -1.402827,-0.7588 l 0.784304,-0.516495 c 0.0893,0.146659 0.344331,0.312448 0.707793,0.34433 0.235931,0.02551 0.471852,-0.01913 0.637643,-0.108401 0.101998,-0.05101 0.172171,-0.127529 0.17854,-0.191295 0.0065,-0.08289 -0.0255,-0.369835 -0.733293,-0.439975 -1.013854,-0.09565 -1.645127,-0.688661 -1.568606,-1.460214 0.0319,-0.382589 0.280561,-0.714165 0.663153,-0.930965 0.331571,-0.172165 0.752423,-0.25506 1.166895,-0.210424 0.599382,0.05739 1.128635,0.344329 1.402816,0.7588 l -0.784304,0.510118 c -0.0893,-0.140282 -0.344331,-0.299694 -0.707782,-0.331576 -0.235932,-0.02551 -0.471863,0.01913 -0.637654,0.10202 -0.0956,0.05739 -0.165791,0.133906 -0.17216,0.191295 -0.0255,0.293317 0.465482,0.420847 0.726913,0.439976 v 0.0064 c 1.020234,0.09565 1.638757,0.66953 1.562237,1.460213 z m -7.466854,-0.988354 c 0,-1.192401 0.962855,-2.155249 2.15525,-2.155249 0.599393,0 1.179645,0.25506 1.594117,0.707789 l -0.695033,0.624895 c -0.235931,-0.25506 -0.561133,-0.401718 -0.899084,-0.401718 -0.675903,0 -1.217906,0.542 -1.217906,1.217906 0,0.66953 0.542003,1.217908 1.217906,1.217908 0.337951,0 0.663153,-0.140283 0.899084,-0.401718 l 0.695033,0.631271 c -0.414472,0.452729 -0.988355,0.707788 -1.594117,0.707788 -1.192395,0 -2.15525,-0.969224 -2.15525,-2.148872 z M 8.6573365,23.461054 10.353474,19.14418 h 0.624893 l 1.568618,4.316874 H 11.52037 L 11.265308,22.734136 H 9.964513 l -0.274192,0.726918 z m 1.6833885,-1.68339 h 0.580263 L 10.646796,21.012487 Z M 8.1089536,19.156932 v 4.297745 H 7.1461095 v -1.645131 h -1.606867 v 1.645131 H 4.5763876 v -4.297745 h 0.9628549 v 1.696143 h 1.606867 V 19.156932 Z M 20.115859,4.2997436 C 20.090359,4.159461 19.969198,4.0574375 19.822548,4.0574375 H 14.141102 10.506516 4.8250686 c -0.14665,0 -0.2678112,0.1020202 -0.2933108,0.2423061 L 3.690064,8.8461703 c -0.00651,0.01913 -0.00651,0.03826 -0.00651,0.057391 v 1.5239797 c 0,0.165789 0.133911,0.299694 0.2996911,0.299694 H 4.5762579 20.0711 20.664112 c 0.165781,0 0.299691,-0.133905 0.299691,-0.299694 V 8.8971848 c 0,-0.01913 0,-0.03826 -0.0065,-0.05739 z M 4.5763876,17.358767 c 0,0.184917 0.1466608,0.331577 0.3315819,0.331577 h 5.5985465 3.634586 0.924594 c 0.184911,0 0.331571,-0.14666 0.331571,-0.331577 v -4.744098 c 0,-0.184918 0.146661,-0.331577 0.331582,-0.331577 h 2.894913 c 0.184921,0 0.331582,0.146659 0.331582,0.331577 v 4.744098 c 0,0.184917 0.146661,0.331577 0.331571,0.331577 h 0.446363 c 0.18491,0 0.331571,-0.14666 0.331571,-0.331577 v -5.636804 c 0,-0.184918 -0.146661,-0.331577 -0.331571,-0.331577 H 4.9079695 c -0.1849211,0 -0.3315819,0.146659 -0.3315819,0.331577 z m 1.6578879,-4.852498 h 5.6495565 c 0.15303,0 0.280561,0.12753 0.280561,0.280564 v 3.513438 c 0,0.153036 -0.127531,0.280566 -0.280561,0.280566 H 6.2342755 c -0.1530412,0 -0.2805719,-0.12753 -0.2805719,-0.280566 v -3.513438 c 0,-0.159411 0.1275307,-0.280564 0.2805719,-0.280564 z M 19.790657,3.3879075 H 4.8569594 c -0.1530412,0 -0.2805718,-0.1275296 -0.2805718,-0.2805642 V 1.3665653 C 4.5763876,1.2135296 4.7039182,1.086 4.8569594,1.086 H 19.790657 c 0.153041,0 0.280572,0.1275296 0.280572,0.2805653 v 1.740778 c 0,0.1530346 -0.127531,0.2805642 -0.280572,0.2805642 z"
const haIconSet = window.customElements.get("ha-iconset-svg")
if (haIconSet === undefined) {
window.customIconsets = window.customIconsets || {}
window.customIconsets["hacs"] = async () => { return { hacs: { path: hacsIconPath } } }
} else {
const iconset = document.createElement("ha-iconset-svg");
iconset.name = "hacs";
iconset.size = "24";
iconset.innerHTML = `
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg height="24" width="24" viewBox="0 0 24 24" id="hacs" version="1.1">
<g>
<path style="stroke-width:0.0637648" d="${hacsIconPath}" id="path103" />
</g>
</svg>
`
document.body.appendChild(iconset);
}
window.customIconsets = window.customIconsets || {};
window.customIconsets["hacs"] = async () => {
return {
path:
"m 20.064849,22.306912 c -0.0319,0.369835 -0.280561,0.707789 -0.656773,0.918212 -0.280572,0.153036 -0.605773,0.229553 -0.950094,0.229553 -0.0765,0 -0.146661,-0.0064 -0.216801,-0.01275 -0.605774,-0.05739 -1.135016,-0.344329 -1.402827,-0.7588 l 0.784304,-0.516495 c 0.0893,0.146659 0.344331,0.312448 0.707793,0.34433 0.235931,0.02551 0.471852,-0.01913 0.637643,-0.108401 0.101998,-0.05101 0.172171,-0.127529 0.17854,-0.191295 0.0065,-0.08289 -0.0255,-0.369835 -0.733293,-0.439975 -1.013854,-0.09565 -1.645127,-0.688661 -1.568606,-1.460214 0.0319,-0.382589 0.280561,-0.714165 0.663153,-0.930965 0.331571,-0.172165 0.752423,-0.25506 1.166895,-0.210424 0.599382,0.05739 1.128635,0.344329 1.402816,0.7588 l -0.784304,0.510118 c -0.0893,-0.140282 -0.344331,-0.299694 -0.707782,-0.331576 -0.235932,-0.02551 -0.471863,0.01913 -0.637654,0.10202 -0.0956,0.05739 -0.165791,0.133906 -0.17216,0.191295 -0.0255,0.293317 0.465482,0.420847 0.726913,0.439976 v 0.0064 c 1.020234,0.09565 1.638757,0.66953 1.562237,1.460213 z m -7.466854,-0.988354 c 0,-1.192401 0.962855,-2.155249 2.15525,-2.155249 0.599393,0 1.179645,0.25506 1.594117,0.707789 l -0.695033,0.624895 c -0.235931,-0.25506 -0.561133,-0.401718 -0.899084,-0.401718 -0.675903,0 -1.217906,0.542 -1.217906,1.217906 0,0.66953 0.542003,1.217908 1.217906,1.217908 0.337951,0 0.663153,-0.140283 0.899084,-0.401718 l 0.695033,0.631271 c -0.414472,0.452729 -0.988355,0.707788 -1.594117,0.707788 -1.192395,0 -2.15525,-0.969224 -2.15525,-2.148872 z M 8.6573365,23.461054 10.353474,19.14418 h 0.624893 l 1.568618,4.316874 H 11.52037 L 11.265308,22.734136 H 9.964513 l -0.274192,0.726918 z m 1.6833885,-1.68339 h 0.580263 L 10.646796,21.012487 Z M 8.1089536,19.156932 v 4.297745 H 7.1461095 v -1.645131 h -1.606867 v 1.645131 H 4.5763876 v -4.297745 h 0.9628549 v 1.696143 h 1.606867 V 19.156932 Z M 20.115859,4.2997436 C 20.090359,4.159461 19.969198,4.0574375 19.822548,4.0574375 H 14.141102 10.506516 4.8250686 c -0.14665,0 -0.2678112,0.1020202 -0.2933108,0.2423061 L 3.690064,8.8461703 c -0.00651,0.01913 -0.00651,0.03826 -0.00651,0.057391 v 1.5239797 c 0,0.165789 0.133911,0.299694 0.2996911,0.299694 H 4.5762579 20.0711 20.664112 c 0.165781,0 0.299691,-0.133905 0.299691,-0.299694 V 8.8971848 c 0,-0.01913 0,-0.03826 -0.0065,-0.05739 z M 4.5763876,17.358767 c 0,0.184917 0.1466608,0.331577 0.3315819,0.331577 h 5.5985465 3.634586 0.924594 c 0.184911,0 0.331571,-0.14666 0.331571,-0.331577 v -4.744098 c 0,-0.184918 0.146661,-0.331577 0.331582,-0.331577 h 2.894913 c 0.184921,0 0.331582,0.146659 0.331582,0.331577 v 4.744098 c 0,0.184917 0.146661,0.331577 0.331571,0.331577 h 0.446363 c 0.18491,0 0.331571,-0.14666 0.331571,-0.331577 v -5.636804 c 0,-0.184918 -0.146661,-0.331577 -0.331571,-0.331577 H 4.9079695 c -0.1849211,0 -0.3315819,0.146659 -0.3315819,0.331577 z m 1.6578879,-4.852498 h 5.6495565 c 0.15303,0 0.280561,0.12753 0.280561,0.280564 v 3.513438 c 0,0.153036 -0.127531,0.280566 -0.280561,0.280566 H 6.2342755 c -0.1530412,0 -0.2805719,-0.12753 -0.2805719,-0.280566 v -3.513438 c 0,-0.159411 0.1275307,-0.280564 0.2805719,-0.280564 z M 19.790657,3.3879075 H 4.8569594 c -0.1530412,0 -0.2805718,-0.1275296 -0.2805718,-0.2805642 V 1.3665653 C 4.5763876,1.2135296 4.7039182,1.086 4.8569594,1.086 H 19.790657 c 0.153041,0 0.280572,0.1275296 0.280572,0.2805653 v 1.740778 c 0,0.1530346 -0.127531,0.2805642 -0.280572,0.2805642 z",
};
};

View File

@ -1,24 +1,22 @@
{
"codeowners": [
"@ludeeus"
],
"config_flow": true,
"dependencies": [
"websocket_api",
"frontend",
"persistent_notification",
"lovelace"
],
"documentation": "https://hacs.xyz/docs/configuration/start",
"domain": "hacs",
"name": "HACS (Home Assistant Community Store)",
"requirements": [
"aiofiles==0.5.0",
"aiogithubapi==0.5.0",
"backoff==1.10.0",
"hacs_frontend==20200426112021",
"integrationhelper==0.2.2",
"semantic_version==2.8.5",
"queueman==0.5"
]
"codeowners": ["@ludeeus"],
"config_flow": true,
"dependencies": [
"websocket_api",
"frontend",
"persistent_notification",
"lovelace"
],
"documentation": "https://hacs.xyz/docs/configuration/start",
"domain": "hacs",
"name": "HACS",
"requirements": [
"aiofiles==0.5.0",
"aiogithubapi==1.0.4",
"backoff==1.10.0",
"hacs_frontend==20200521162326",
"integrationhelper==0.2.2",
"semantic_version==2.8.5",
"queueman==0.5"
]
}

View File

@ -1,5 +1,5 @@
"""Class for appdaemon apps in HACS."""
from aiogithubapi import AIOGitHubException
from aiogithubapi import AIOGitHubAPIException
from integrationhelper import Logger
from .repository import HacsRepository
@ -30,7 +30,7 @@ class HacsAppdaemon(HacsRepository):
# Custom step 1: Validate content.
try:
addir = await self.repository_object.get_contents("apps", self.ref)
except AIOGitHubException:
except AIOGitHubAPIException:
raise HacsException(
f"Repostitory structure for {self.ref.replace('tags/','')} is not compliant"
)
@ -64,11 +64,9 @@ class HacsAppdaemon(HacsRepository):
# Set local path
self.content.path.local = self.localpath
async def update_repository(self):
async def update_repository(self, ignore_issues=False):
"""Update."""
if self.hacs.github.ratelimits.remaining == 0:
return
await self.common_update()
await self.common_update(ignore_issues)
# Get appdaemon objects.
if self.repository_manifest:

View File

@ -74,11 +74,9 @@ class HacsIntegration(HacsRepository):
# Set local path
self.content.path.local = self.localpath
async def update_repository(self):
async def update_repository(self, ignore_issues=False):
"""Update."""
if self.hacs.github.ratelimits.remaining == 0:
return
await self.common_update()
await self.common_update(ignore_issues)
if self.data.content_in_root:
self.content.path.remote = ""

View File

@ -72,11 +72,9 @@ class HacsNetdaemon(HacsRepository):
# Set local path
self.content.path.local = self.localpath
async def update_repository(self):
async def update_repository(self, ignore_issues=False):
"""Update."""
if self.hacs.github.ratelimits.remaining == 0:
return
await self.common_update()
await self.common_update(ignore_issues)
# Get appdaemon objects.
if self.repository_manifest:

View File

@ -57,19 +57,13 @@ class HacsPlugin(HacsRepository):
# Run common registration steps.
await self.common_registration()
async def update_repository(self):
async def update_repository(self, ignore_issues=False):
"""Update."""
if self.hacs.github.ratelimits.remaining == 0:
return
# Run common update steps.
await self.common_update()
await self.common_update(ignore_issues)
# Get plugin objects.
find_file_name(self)
# Get JS type
await self.parse_readme_for_jstype()
if self.content.path.remote is None:
self.validate.errors.append("Repostitory structure not compliant")
@ -86,25 +80,3 @@ class HacsPlugin(HacsRepository):
self.data.authors = package["author"]
except Exception: # pylint: disable=broad-except
pass
async def parse_readme_for_jstype(self):
"""Parse the readme looking for js type."""
readme = None
readme_files = ["readme", "readme.md"]
root = await self.repository_object.get_contents("")
for file in root:
if file.name.lower() in readme_files:
readme = await self.repository_object.get_contents(file.name)
break
if readme is None:
return
readme = readme.content
for line in readme.splitlines():
if "type: module" in line:
self.information.javascript_type = "module"
break
elif "type: js" in line:
self.information.javascript_type = "js"
break

View File

@ -63,12 +63,9 @@ class HacsPythonScript(HacsRepository):
# Set name
find_file_name(self)
async def update_repository(self): # lgtm[py/similar-function]
async def update_repository(self, ignore_issues=False):
"""Update."""
if self.hacs.github.ratelimits.remaining == 0:
return
# Run common update steps.
await self.common_update()
await self.common_update(ignore_issues)
# Get python_script objects.
if self.data.content_in_root:

View File

@ -5,7 +5,7 @@ import os
import tempfile
import zipfile
from integrationhelper import Validate
from aiogithubapi import AIOGitHubException
from aiogithubapi import AIOGitHubAPIException
from .manifest import HacsManifest
from ..helpers.misc import get_repository_name
from ..handler.download import async_download_file, async_save_file
@ -13,6 +13,7 @@ from ..helpers.misc import version_left_higher_then_right
from ..helpers.install import install_repository, version_to_install
from custom_components.hacs.hacsbase.exceptions import HacsException
from custom_components.hacs.store import async_remove_store
from custom_components.hacs.globals import get_hacs
from custom_components.hacs.helpers.information import (
get_info_md_content,
@ -126,31 +127,22 @@ class HacsRepository:
"""Return pending upgrade."""
if not self.can_install:
return False
if self.status.installed:
if self.status.selected_tag is not None:
if self.status.selected_tag == self.data.default_branch:
if self.versions.installed_commit != self.versions.available_commit:
if self.data.installed:
if self.data.selected_tag is not None:
if self.data.selected_tag == self.data.default_branch:
if self.data.installed_commit != self.data.last_commit:
return True
return False
if self.display_installed_version != self.display_available_version:
return True
return False
@property
def config_flow(self):
"""Return bool if integration has config_flow."""
if self.integration_manifest:
if self.data.full_name == "hacs/integration":
return False
return self.integration_manifest.get("config_flow", False)
return False
@property
def custom(self):
"""Return flag if the repository is custom."""
if self.data.full_name.split("/")[0] in ["custom-components", "custom-cards"]:
return False
if self.data.full_name.lower() in [x.lower() for x in self.hacs.common.default]:
if str(self.data.id) in [str(x) for x in self.hacs.common.default]:
return False
if self.data.full_name == "hacs/integration":
return False
@ -160,14 +152,13 @@ class HacsRepository:
def can_install(self):
"""Return bool if repository can be installed."""
target = None
if self.information.homeassistant_version is not None:
target = self.information.homeassistant_version
if self.repository_manifest is not None:
if self.data.homeassistant is not None:
target = self.data.homeassistant
if self.data.homeassistant is not None:
target = self.data.homeassistant
if self.data.homeassistant is not None:
target = self.data.homeassistant
if target is not None:
if self.releases.releases:
if self.data.releases:
if not version_left_higher_then_right(
self.hacs.system.ha_version, target
):
@ -182,13 +173,13 @@ class HacsRepository:
@property
def display_status(self):
"""Return display_status."""
if self.status.new:
if self.data.new:
status = "new"
elif self.pending_restart:
status = "pending-restart"
elif self.pending_upgrade:
status = "pending-upgrade"
elif self.status.installed:
elif self.data.installed:
status = "installed"
else:
status = "default"
@ -209,11 +200,11 @@ class HacsRepository:
@property
def display_installed_version(self):
"""Return display_authors"""
if self.versions.installed is not None:
installed = self.versions.installed
if self.data.installed_version is not None:
installed = self.data.installed_version
else:
if self.versions.installed_commit is not None:
installed = self.versions.installed_commit
if self.data.installed_commit is not None:
installed = self.data.installed_commit
else:
installed = ""
return installed
@ -221,11 +212,11 @@ class HacsRepository:
@property
def display_available_version(self):
"""Return display_authors"""
if self.versions.available is not None:
available = self.versions.available
if self.data.last_version is not None:
available = self.data.last_version
else:
if self.versions.available_commit is not None:
available = self.versions.available_commit
if self.data.last_commit is not None:
available = self.data.last_commit
else:
available = ""
return available
@ -233,7 +224,7 @@ class HacsRepository:
@property
def display_version_or_commit(self):
"""Does the repositoriy use releases or commits?"""
if self.releases.releases:
if self.data.releases:
version_or_commit = "version"
else:
version_or_commit = "commit"
@ -251,9 +242,9 @@ class HacsRepository:
}
return actions[self.display_status]
async def common_validate(self):
async def common_validate(self, ignore_issues=False):
"""Common validation steps of the repository."""
await common_validate(self)
await common_validate(self, ignore_issues)
async def common_registration(self):
"""Common registration steps of the repository."""
@ -264,9 +255,6 @@ class HacsRepository:
)
self.data.update_data(self.repository_object.attributes)
# Set id
self.information.uid = str(self.data.id)
# Set topics
self.data.topics = self.data.topics
@ -280,21 +268,19 @@ class HacsRepository:
if self.data.description is None or len(self.data.description) == 0:
raise HacsException("Missing repository description")
async def common_update(self):
async def common_update(self, ignore_issues=False):
"""Common information update steps of the repository."""
self.logger.debug("Getting repository information")
# Attach repository
await common_update_data(self)
await common_update_data(self, ignore_issues)
# Update last updaeted
self.information.last_updated = self.repository_object.attributes.get(
"pushed_at", 0
)
self.data.last_updated = self.repository_object.attributes.get("pushed_at", 0)
# Update last available commit
await self.repository_object.set_last_commit()
self.versions.available_commit = self.repository_object.last_commit
self.data.last_commit = self.repository_object.last_commit
# Get the content of hacs.json
await self.get_repository_manifest_content()
@ -357,30 +343,30 @@ class HacsRepository:
raise HacsException("No hacs.json file in the root of the repository.")
return
if self.hacs.action:
self.logger.debug("Found hacs.json")
self.logger.info("Found hacs.json")
self.ref = version_to_install(self)
if self.ref is None:
self.ref = version_to_install(self)
try:
manifest = await self.repository_object.get_contents("hacs.json", self.ref)
self.repository_manifest = HacsManifest.from_dict(
json.loads(manifest.content)
)
self.data.update_data(json.loads(manifest.content))
except (AIOGitHubException, Exception) as exception: # Gotta Catch 'Em All
except (AIOGitHubAPIException, Exception) as exception: # Gotta Catch 'Em All
if self.hacs.action:
raise HacsException(f"hacs.json file is not valid ({exception}).")
if self.hacs.action:
self.logger.debug("hacs.json is valid")
self.logger.info("hacs.json is valid")
def remove(self):
"""Run remove tasks."""
self.logger.info("Starting removal")
if self.information.uid in self.hacs.common.installed:
self.hacs.common.installed.remove(self.information.uid)
if self.data.id in self.hacs.common.installed:
self.hacs.common.installed.remove(self.data.id)
for repository in self.hacs.repositories:
if repository.information.uid == self.information.uid:
if repository.data.id == self.data.id:
self.hacs.repositories.remove(repository)
async def uninstall(self):
@ -388,9 +374,9 @@ class HacsRepository:
self.logger.info("Uninstalling")
if not await self.remove_local_directory():
raise HacsException("Could not uninstall")
self.status.installed = False
self.data.installed = False
if self.data.category == "integration":
if self.config_flow:
if self.data.config_flow:
await self.reload_custom_components()
else:
self.pending_restart = True
@ -403,8 +389,11 @@ class HacsRepository:
pass
if self.data.full_name in self.hacs.common.installed:
self.hacs.common.installed.remove(self.data.full_name)
self.versions.installed = None
self.versions.installed_commit = None
await async_remove_store(self.hacs.hass, f"hacs/{self.data.id}.hacs")
self.data.installed_version = None
self.data.installed_commit = None
self.hacs.hass.bus.async_fire(
"hacs/repository",
{"id": 1337, "action": "uninstall", "repository": self.data.full_name},

View File

@ -8,32 +8,52 @@ import attr
class RepositoryData:
"""RepositoryData class."""
id: int = 0
full_name: str = ""
pushed_at: str = ""
category: str = ""
archived: bool = False
description: str = ""
manifest_name: str = None
topics: List[str] = []
fork: bool = False
domain: str = ""
default_branch: str = None
stargazers_count: int = 0
last_commit: str = ""
file_name: str = ""
content_in_root: bool = False
zip_release: bool = False
filename: str = ""
render_readme: bool = False
hide_default_branch: bool = False
domains: List[str] = []
country: List[str] = []
authors: List[str] = []
homeassistant: str = None # Minimum Home Assistant version
category: str = ""
content_in_root: bool = False
country: List[str] = []
config_flow: bool = False
default_branch: str = None
description: str = ""
domain: str = ""
domains: List[str] = []
downloads: int = 0
file_name: str = ""
filename: str = ""
first_install: bool = False
fork: bool = False
full_name: str = ""
hacs: str = None # Minimum HACS version
persistent_directory: str = None
hide: bool = False
hide_default_branch: bool = False
homeassistant: str = None # Minimum Home Assistant version
id: int = 0
iot_class: str = None
installed: bool = False
installed_commit: str = None
installed_version: str = None
open_issues: int = 0
last_commit: str = None
last_version: str = None
last_updated: str = 0
manifest_name: str = None
new: bool = True
persistent_directory: str = None
pushed_at: str = ""
releases: bool = False
render_readme: bool = False
published_tags: List[str] = []
selected_tag: str = None
show_beta: bool = False
stargazers_count: int = 0
topics: List[str] = []
zip_release: bool = False
@property
def stars(self):
"""Return the stargazers count."""
return self.stargazers_count or 0
@property
def name(self):
@ -53,9 +73,20 @@ class RepositoryData:
for key in source:
if key in data.__dict__:
if key == "pushed_at":
setattr(
data, key, datetime.strptime(source[key], "%Y-%m-%dT%H:%M:%SZ")
)
if "Z" in source[key]:
setattr(
data,
key,
datetime.strptime(source[key], "%Y-%m-%dT%H:%M:%SZ"),
)
else:
setattr(
data,
key,
datetime.strptime(source[key], "%Y-%m-%dT%H:%M:%S"),
)
elif key == "id":
setattr(data, key, str(source[key]))
elif key == "county":
if isinstance(source[key], str):
setattr(data, key, [source[key]])
@ -70,9 +101,18 @@ class RepositoryData:
for key in data:
if key in self.__dict__:
if key == "pushed_at":
setattr(
self, key, datetime.strptime(data[key], "%Y-%m-%dT%H:%M:%SZ")
)
if "Z" in data[key]:
setattr(
self,
key,
datetime.strptime(data[key], "%Y-%m-%dT%H:%M:%SZ"),
)
else:
setattr(
self, key, datetime.strptime(data[key], "%Y-%m-%dT%H:%M:%S")
)
elif key == "id":
setattr(self, key, str(data[key]))
elif key == "county":
if isinstance(data[key], str):
setattr(self, key, [data[key]])

View File

@ -59,12 +59,9 @@ class HacsTheme(HacsRepository):
find_file_name(self)
self.content.path.local = f"{self.hacs.system.config_path}/themes/{self.data.file_name.replace('.yaml', '')}"
async def update_repository(self): # lgtm[py/similar-function]
async def update_repository(self, ignore_issues=False):
"""Update."""
if self.hacs.github.ratelimits.remaining == 0:
return
# Run common update steps.
await self.common_update()
await self.common_update(ignore_issues)
# Get theme objects.
if self.data.content_in_root:

View File

@ -89,8 +89,8 @@ class HACSSensor(HACSDevice):
{
"name": repository.data.full_name,
"display_name": repository.display_name,
"installed version": repository.display_installed_version,
"available version": repository.display_available_version,
"installed_version": repository.display_installed_version,
"available_version": repository.display_available_version,
}
)
return {"repositories": data}

View File

@ -21,9 +21,9 @@ async def load_hacs_repository():
repository = hacs.get_by_name("hacs/integration")
if repository is None:
raise HacsException("Unknown error")
repository.status.installed = True
repository.versions.installed = VERSION
repository.status.new = False
repository.data.installed = True
repository.data.installed_version = VERSION
repository.data.new = False
hacs.repo = repository.repository_object
hacs.data_repo = await get_repository(
hacs.session, hacs.configuration.token, "hacs/default"
@ -72,7 +72,7 @@ def add_sensor():
async def setup_frontend():
"""Configure the HACS frontend elements."""
from .http import HacsFrontend, HacsPluginViewLegacy
from .http import HacsFrontend
from .ws_api_handlers import setup_ws_api
hacs = get_hacs()
@ -80,9 +80,6 @@ async def setup_frontend():
hacs.hass.http.register_view(HacsFrontend())
hacs.frontend.version_running = FE_VERSION
# Legacy views, remove with 2.0
hacs.hass.http.register_view(HacsPluginViewLegacy())
# Add to sidepanel
custom_panel_config = {
"name": "hacs-frontend",

View File

@ -6,7 +6,8 @@ from .hacsbase.const import STORAGE_VERSION
async def async_load_from_store(hass, key):
"""Load the retained data from store and return de-serialized data."""
store = Store(hass, STORAGE_VERSION, f"hacs.{key}", encoder=JSONEncoder)
key = key if "/" in key else f"hacs.{key}"
store = Store(hass, STORAGE_VERSION, key, encoder=JSONEncoder)
restored = await store.async_load()
if restored is None:
return {}
@ -15,5 +16,14 @@ async def async_load_from_store(hass, key):
async def async_save_to_store(hass, key, data):
"""Generate dynamic data to store and save it to the filesystem."""
store = Store(hass, STORAGE_VERSION, f"hacs.{key}", encoder=JSONEncoder)
key = key if "/" in key else f"hacs.{key}"
store = Store(hass, STORAGE_VERSION, key, encoder=JSONEncoder)
await store.async_save(data)
async def async_remove_store(hass, key):
"""Remove a store element that should no longer be used"""
if "/" not in key:
return
store = Store(hass, STORAGE_VERSION, key, encoder=JSONEncoder)
await store.async_remove()

View File

@ -3,7 +3,7 @@
import sys
import os
import voluptuous as vol
from aiogithubapi import AIOGitHubException
from aiogithubapi import AIOGitHubAPIException
from homeassistant.components import websocket_api
import homeassistant.helpers.config_validation as cv
from .hacsbase.exceptions import HacsException
@ -61,7 +61,7 @@ async def hacs_settings(hass, connection, msg):
hass.bus.async_fire("hacs/status", {})
for repository in hacs.repositories:
if repository.pending_upgrade:
repository.status.selected_tag = None
repository.data.selected_tag = None
await repository.install()
hacs.system.status.upgrading_all = False
hacs.system.status.background_task = False
@ -70,14 +70,14 @@ async def hacs_settings(hass, connection, msg):
elif action == "clear_new":
for repo in hacs.repositories:
if msg.get("category") == repo.data.category:
if repo.status.new:
hacs.logger.debug(f"Clearing new flag from '{repo.data.full_name}'")
repo.status.new = False
if repo.data.new:
hacs.logger.debug(f"Clearing new flag from '{repo.data.full_name}'")
repo.data.new = False
else:
hacs.logger.error(f"WS action '{action}' is not valid")
hass.bus.async_fire("hacs/config", {})
await hacs.data.async_write()
connection.send_message(websocket_api.result_message(msg["id"], {}))
@websocket_api.async_response
@ -113,6 +113,7 @@ async def hacs_status(hass, connection, msg):
"reloading_data": hacs.system.status.reloading_data,
"upgrading_all": hacs.system.status.upgrading_all,
"disabled": hacs.system.disabled,
"has_pending_tasks": hacs.queue.has_pending_tasks,
}
connection.send_message(websocket_api.result_message(msg["id"], content))
@ -130,35 +131,36 @@ async def hacs_repositories(hass, connection, msg):
"additional_info": repo.information.additional_info,
"authors": repo.data.authors,
"available_version": repo.display_available_version,
"beta": repo.status.show_beta,
"beta": repo.data.show_beta,
"can_install": repo.can_install,
"category": repo.data.category,
"country": repo.data.country,
"config_flow": repo.config_flow,
"config_flow": repo.data.config_flow,
"custom": repo.custom,
"default_branch": repo.data.default_branch,
"description": repo.data.description,
"domain": repo.integration_manifest.get("domain"),
"downloads": repo.releases.downloads,
"domain": repo.data.domain,
"downloads": repo.data.downloads,
"file_name": repo.data.file_name,
"first_install": repo.status.first_install,
"full_name": repo.data.full_name,
"hide": repo.status.hide,
"hide": repo.data.hide,
"hide_default_branch": repo.data.hide_default_branch,
"homeassistant": repo.data.homeassistant,
"id": repo.information.uid,
"id": repo.data.id,
"info": repo.information.info,
"installed_version": repo.display_installed_version,
"installed": repo.status.installed,
"installed": repo.data.installed,
"issues": repo.data.open_issues,
"javascript_type": repo.information.javascript_type,
"last_updated": repo.information.last_updated,
"last_updated": repo.data.last_updated,
"local_path": repo.content.path.local,
"main_action": repo.main_action,
"name": repo.display_name,
"new": repo.status.new,
"new": repo.data.new,
"pending_upgrade": repo.pending_upgrade,
"releases": repo.releases.published_tags,
"selected_tag": repo.status.selected_tag,
"releases": repo.data.published_tags,
"selected_tag": repo.data.selected_tag,
"stars": repo.data.stargazers_count,
"state": repo.state,
"status_description": repo.display_status_description,
@ -195,42 +197,48 @@ async def hacs_repository(hass, connection, msg):
hacs.logger.debug(f"Running {action} for {repository.data.full_name}")
if action == "update":
await repository.update_repository()
await repository.update_repository(True)
repository.status.updated_info = True
repository.status.new = False
elif action == "install":
was_installed = repository.status.installed
was_installed = repository.data.installed
await repository.install()
if not was_installed:
hass.bus.async_fire("hacs/reload", {"force": True})
elif action == "not_new":
repository.data.new = False
elif action == "uninstall":
await repository.uninstall()
elif action == "hide":
repository.status.hide = True
repository.data.hide = True
elif action == "unhide":
repository.status.hide = False
repository.data.hide = False
elif action == "show_beta":
repository.status.show_beta = True
repository.data.show_beta = True
await repository.update_repository()
elif action == "hide_beta":
repository.status.show_beta = False
repository.data.show_beta = False
await repository.update_repository()
elif action == "toggle_beta":
repository.data.show_beta = not repository.data.show_beta
await repository.update_repository()
elif action == "delete":
repository.status.show_beta = False
repository.data.show_beta = False
repository.remove()
elif action == "set_version":
if msg["version"] == repository.data.default_branch:
repository.status.selected_tag = None
repository.data.selected_tag = None
else:
repository.status.selected_tag = msg["version"]
repository.data.selected_tag = msg["version"]
await repository.update_repository()
hass.bus.async_fire("hacs/reload", {"force": True})
@ -240,11 +248,11 @@ async def hacs_repository(hass, connection, msg):
await hacs.data.async_write()
message = None
except AIOGitHubException as exception:
except AIOGitHubAPIException as exception:
message = str(exception)
hass.bus.async_fire("hacs/error", {"message": str(exception)})
except AttributeError as exception:
message = f"Could not use repository with ID {repo_id}"
message = f"Could not use repository with ID {repo_id} ({exception})"
except Exception as exception: # pylint: disable=broad-except
message = str(exception)
@ -253,6 +261,7 @@ async def hacs_repository(hass, connection, msg):
hass.bus.async_fire("hacs/error", {"message": message})
repository.state = None
connection.send_message(websocket_api.result_message(msg["id"], {}))
@websocket_api.async_response
@ -318,10 +327,19 @@ async def hacs_repository_data(hass, connection, msg):
repository.state = data
elif action == "set_version":
repository.status.selected_tag = data
repository.data.selected_tag = data
await repository.update_repository()
repository.state = None
elif action == "install":
was_installed = repository.data.installed
repository.data.selected_tag = data
await repository.update_repository()
await repository.install()
repository.state = None
if not was_installed:
hass.bus.async_fire("hacs/reload", {"force": True})
elif action == "add":
repository.state = None
@ -330,6 +348,7 @@ async def hacs_repository_data(hass, connection, msg):
hacs.logger.error(f"WS action '{action}' is not valid")
await hacs.data.async_write()
connection.send_message(websocket_api.result_message(msg["id"], {}))
@websocket_api.async_response