Skip to content

Commit

Permalink
Migrate Habitica integration to habiticalib (home-assistant#131032)
Browse files Browse the repository at this point in the history
* Migrate data to habiticalib

* Add habiticalib to init and coordinator

* Migrate Habitica config flow to habiticalib

* migrate init to habiticalib

* migrate buttons to habiticalib

* migrate switch to habiticalib

* update habiticalib

* cast_skill action

* migrate update_score

* migrate transformation items action

* migrate quest actions

* fix fixture errors

* Migrate coordinator data and content

* bump habiticalib

* Remove habitipy and use wrapper in habiticalub

* changes

* some fixes

* minor refactoring

* class_needed annotation

* Update diagnostics

* do integration setup in coordinator setup

* small changes

* raise HomeAssistantError for TooManyRequestsError

* fix docstring

* update tests

* changes to tests/snapshots

* fix update_todo_item
  • Loading branch information
tr4nt0r authored Dec 29, 2024
1 parent 4717eb3 commit 0db07a0
Show file tree
Hide file tree
Showing 42 changed files with 3,548 additions and 1,984 deletions.
62 changes: 10 additions & 52 deletions homeassistant/components/habitica/__init__.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,15 @@
"""The habitica integration."""

from http import HTTPStatus

from aiohttp import ClientResponseError
from habitipy.aio import HabitipyAsync
from habiticalib import Habitica

from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
APPLICATION_NAME,
CONF_API_KEY,
CONF_NAME,
CONF_URL,
CONF_VERIFY_SSL,
Platform,
__version__,
)
from homeassistant.const import CONF_API_KEY, CONF_URL, CONF_VERIFY_SSL, Platform
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.typing import ConfigType

from .const import CONF_API_USER, DEVELOPER_ID, DOMAIN
from .const import CONF_API_USER, DOMAIN, X_CLIENT
from .coordinator import HabiticaDataUpdateCoordinator
from .services import async_setup_services
from .types import HabiticaConfigEntry
Expand Down Expand Up @@ -51,47 +39,17 @@ async def async_setup_entry(
) -> bool:
"""Set up habitica from a config entry."""

class HAHabitipyAsync(HabitipyAsync):
"""Closure API class to hold session."""

def __call__(self, **kwargs):
return super().__call__(websession, **kwargs)

def _make_headers(self) -> dict[str, str]:
headers = super()._make_headers()
headers.update(
{"x-client": f"{DEVELOPER_ID} - {APPLICATION_NAME} {__version__}"}
)
return headers

websession = async_get_clientsession(
session = async_get_clientsession(
hass, verify_ssl=config_entry.data.get(CONF_VERIFY_SSL, True)
)

api = await hass.async_add_executor_job(
HAHabitipyAsync,
{
"url": config_entry.data[CONF_URL],
"login": config_entry.data[CONF_API_USER],
"password": config_entry.data[CONF_API_KEY],
},
api = Habitica(
session,
api_user=config_entry.data[CONF_API_USER],
api_key=config_entry.data[CONF_API_KEY],
url=config_entry.data[CONF_URL],
x_client=X_CLIENT,
)
try:
user = await api.user.get(userFields="profile")
except ClientResponseError as e:
if e.status == HTTPStatus.TOO_MANY_REQUESTS:
raise ConfigEntryNotReady(
translation_domain=DOMAIN,
translation_key="setup_rate_limit_exception",
) from e
raise ConfigEntryNotReady(e) from e

if not config_entry.data.get(CONF_NAME):
name = user["profile"]["name"]
hass.config_entries.async_update_entry(
config_entry,
data={**config_entry.data, CONF_NAME: name},
)

coordinator = HabiticaDataUpdateCoordinator(hass, api)
await coordinator.async_config_entry_first_refresh()
Expand Down
15 changes: 8 additions & 7 deletions homeassistant/components/habitica/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
from collections.abc import Callable
from dataclasses import dataclass
from enum import StrEnum
from typing import Any

from habiticalib import UserData

from homeassistant.components.binary_sensor import (
BinarySensorEntity,
Expand All @@ -23,8 +24,8 @@
class HabiticaBinarySensorEntityDescription(BinarySensorEntityDescription):
"""Habitica Binary Sensor Description."""

value_fn: Callable[[dict[str, Any]], bool | None]
entity_picture: Callable[[dict[str, Any]], str | None]
value_fn: Callable[[UserData], bool | None]
entity_picture: Callable[[UserData], str | None]


class HabiticaBinarySensor(StrEnum):
Expand All @@ -33,18 +34,18 @@ class HabiticaBinarySensor(StrEnum):
PENDING_QUEST = "pending_quest"


def get_scroll_image_for_pending_quest_invitation(user: dict[str, Any]) -> str | None:
def get_scroll_image_for_pending_quest_invitation(user: UserData) -> str | None:
"""Entity picture for pending quest invitation."""
if user["party"]["quest"].get("key") and user["party"]["quest"]["RSVPNeeded"]:
return f"inventory_quest_scroll_{user["party"]["quest"]["key"]}.png"
if user.party.quest.key and user.party.quest.RSVPNeeded:
return f"inventory_quest_scroll_{user.party.quest.key}.png"
return None


BINARY_SENSOR_DESCRIPTIONS: tuple[HabiticaBinarySensorEntityDescription, ...] = (
HabiticaBinarySensorEntityDescription(
key=HabiticaBinarySensor.PENDING_QUEST,
translation_key=HabiticaBinarySensor.PENDING_QUEST,
value_fn=lambda user: user["party"]["quest"]["RSVPNeeded"],
value_fn=lambda user: user.party.quest.RSVPNeeded,
entity_picture=get_scroll_image_for_pending_quest_invitation,
),
)
Expand Down
Loading

0 comments on commit 0db07a0

Please sign in to comment.