repositories.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. """Register info websocket commands."""
  2. from __future__ import annotations
  3. import sys
  4. from typing import TYPE_CHECKING, Any
  5. from homeassistant.components import websocket_api
  6. from homeassistant.core import HomeAssistant
  7. import homeassistant.helpers.config_validation as cv
  8. import voluptuous as vol
  9. from custom_components.hacs.utils import regex
  10. from ..const import DOMAIN
  11. from ..enums import HacsDispatchEvent
  12. if TYPE_CHECKING:
  13. from ..base import HacsBase
  14. @websocket_api.websocket_command(
  15. {
  16. vol.Required("type"): "hacs/repositories/list",
  17. vol.Optional("categories"): [str],
  18. }
  19. )
  20. @websocket_api.require_admin
  21. @websocket_api.async_response
  22. async def hacs_repositories_list(
  23. hass: HomeAssistant,
  24. connection: websocket_api.ActiveConnection,
  25. msg: dict[str, Any],
  26. ):
  27. """List repositories."""
  28. hacs: HacsBase = hass.data.get(DOMAIN)
  29. connection.send_message(
  30. websocket_api.result_message(
  31. msg["id"],
  32. [
  33. {
  34. "authors": repo.data.authors,
  35. "available_version": repo.display_available_version,
  36. "installed_version": repo.display_installed_version,
  37. "config_flow": repo.data.config_flow,
  38. "can_download": repo.can_download,
  39. "category": repo.data.category,
  40. "country": repo.repository_manifest.country,
  41. "custom": not hacs.repositories.is_default(str(repo.data.id)),
  42. "description": repo.data.description,
  43. "domain": repo.data.domain,
  44. "downloads": repo.data.downloads,
  45. "file_name": repo.data.file_name,
  46. "full_name": repo.data.full_name,
  47. "hide": repo.data.hide,
  48. "homeassistant": repo.repository_manifest.homeassistant,
  49. "id": repo.data.id,
  50. "installed": repo.data.installed,
  51. "last_updated": repo.data.last_updated,
  52. "local_path": repo.content.path.local,
  53. "name": repo.display_name,
  54. "new": repo.data.new,
  55. "pending_upgrade": repo.pending_update,
  56. "stars": repo.data.stargazers_count,
  57. "state": repo.state,
  58. "status": repo.display_status,
  59. "topics": repo.data.topics,
  60. }
  61. for repo in hacs.repositories.list_all
  62. if repo.data.category in (msg.get("categories") or hacs.common.categories)
  63. and not repo.ignored_by_country_configuration
  64. ],
  65. )
  66. )
  67. @websocket_api.websocket_command(
  68. {
  69. vol.Required("type"): "hacs/repositories/clear_new",
  70. vol.Optional("categories"): cv.ensure_list,
  71. vol.Optional("repository"): cv.string,
  72. }
  73. )
  74. @websocket_api.require_admin
  75. @websocket_api.async_response
  76. async def hacs_repositories_clear_new(
  77. hass: HomeAssistant,
  78. connection: websocket_api.ActiveConnection,
  79. msg: dict[str, Any],
  80. ) -> None:
  81. """Clear new repositories for spesific categories."""
  82. hacs: HacsBase = hass.data.get(DOMAIN)
  83. if repo := msg.get("repository"):
  84. repository = hacs.repositories.get_by_id(repo)
  85. repository.data.new = False
  86. else:
  87. for repo in hacs.repositories.list_all:
  88. if repo.data.new and repo.data.category in msg.get("categories", []):
  89. hacs.log.debug(
  90. "Clearing new flag from '%s'",
  91. repo.data.full_name,
  92. )
  93. repo.data.new = False
  94. hacs.async_dispatch(HacsDispatchEvent.REPOSITORY, {})
  95. await hacs.data.async_write()
  96. connection.send_message(websocket_api.result_message(msg["id"]))
  97. @websocket_api.websocket_command(
  98. {
  99. vol.Required("type"): "hacs/repositories/removed",
  100. }
  101. )
  102. @websocket_api.require_admin
  103. @websocket_api.async_response
  104. async def hacs_repositories_removed(
  105. hass: HomeAssistant,
  106. connection: websocket_api.ActiveConnection,
  107. msg: dict[str, Any],
  108. ):
  109. """Get information about removed repositories."""
  110. hacs: HacsBase = hass.data.get(DOMAIN)
  111. content = []
  112. for repo in hacs.repositories.list_removed:
  113. if repo.repository not in hacs.common.ignored_repositories:
  114. content.append(repo.to_json())
  115. connection.send_message(websocket_api.result_message(msg["id"], content))
  116. @websocket_api.websocket_command(
  117. {
  118. vol.Required("type"): "hacs/repositories/add",
  119. vol.Required("repository"): cv.string,
  120. vol.Required("category"): vol.Lower,
  121. }
  122. )
  123. @websocket_api.require_admin
  124. @websocket_api.async_response
  125. async def hacs_repositories_add(
  126. hass: HomeAssistant,
  127. connection: websocket_api.ActiveConnection,
  128. msg: dict[str, Any],
  129. ):
  130. """Add custom repositoriy."""
  131. hacs: HacsBase = hass.data.get(DOMAIN)
  132. repository = regex.extract_repository_from_url(msg["repository"])
  133. category = msg["category"]
  134. if repository is None:
  135. return
  136. if repository in hacs.common.skip:
  137. hacs.common.skip.remove(repository)
  138. if renamed := hacs.common.renamed_repositories.get(repository):
  139. repository = renamed
  140. if not hacs.repositories.get_by_full_name(repository):
  141. try:
  142. await hacs.async_register_repository(
  143. repository_full_name=repository,
  144. category=category,
  145. )
  146. except BaseException as exception: # lgtm [py/catch-base-exception] pylint: disable=broad-except
  147. hacs.async_dispatch(
  148. HacsDispatchEvent.ERROR,
  149. {
  150. "action": "add_repository",
  151. "exception": str(sys.exc_info()[0].__name__),
  152. "message": str(exception),
  153. },
  154. )
  155. else:
  156. hacs.async_dispatch(
  157. HacsDispatchEvent.ERROR,
  158. {
  159. "action": "add_repository",
  160. "message": f"Repository '{repository}' exists in the store.",
  161. },
  162. )
  163. connection.send_message(websocket_api.result_message(msg["id"], {}))
  164. @websocket_api.websocket_command(
  165. {
  166. vol.Required("type"): "hacs/repositories/remove",
  167. vol.Required("repository"): cv.string,
  168. }
  169. )
  170. @websocket_api.require_admin
  171. @websocket_api.async_response
  172. async def hacs_repositories_remove(
  173. hass: HomeAssistant,
  174. connection: websocket_api.ActiveConnection,
  175. msg: dict[str, Any],
  176. ):
  177. """Remove custom repositoriy."""
  178. hacs: HacsBase = hass.data.get(DOMAIN)
  179. hacs.log.warning(connection.context)
  180. hacs.log.warning(msg)
  181. repository = hacs.repositories.get_by_id(msg["repository"])
  182. repository.remove()
  183. await hacs.data.async_write()
  184. connection.send_message(websocket_api.result_message(msg["id"], {}))