1 """Get WHOIS information for a given host."""
3 from __future__
import annotations
5 from collections.abc
import Callable
6 from dataclasses
import dataclass
7 from datetime
import UTC, datetime
8 from typing
import cast
10 from whois
import Domain
15 SensorEntityDescription,
24 DataUpdateCoordinator,
28 from .const
import ATTR_EXPIRES, ATTR_NAME_SERVERS, ATTR_REGISTRAR, ATTR_UPDATED, DOMAIN
31 @dataclass(frozen=True, kw_only=True)
33 """Describes a Whois sensor entity."""
35 value_fn: Callable[[Domain], datetime | int | str |
None]
39 """Calculate days left until domain expires."""
40 if domain.expiration_date
is None:
45 (domain.expiration_date - dt_util.utcnow().replace(tzinfo=
None)).days,
50 """Calculate days left until domain expires."""
55 if timestamp.tzinfo
is None:
56 return timestamp.replace(tzinfo=UTC)
61 SENSORS: tuple[WhoisSensorEntityDescription, ...] = (
64 translation_key=
"admin",
65 entity_category=EntityCategory.DIAGNOSTIC,
66 entity_registry_enabled_default=
False,
67 value_fn=
lambda domain: getattr(domain,
"admin",
None),
71 translation_key=
"creation_date",
72 device_class=SensorDeviceClass.TIMESTAMP,
73 entity_category=EntityCategory.DIAGNOSTIC,
77 key=
"days_until_expiration",
78 translation_key=
"days_until_expiration",
79 native_unit_of_measurement=UnitOfTime.DAYS,
80 value_fn=_days_until_expiration,
83 key=
"expiration_date",
84 translation_key=
"expiration_date",
85 device_class=SensorDeviceClass.TIMESTAMP,
86 entity_category=EntityCategory.DIAGNOSTIC,
91 translation_key=
"last_updated",
92 device_class=SensorDeviceClass.TIMESTAMP,
93 entity_category=EntityCategory.DIAGNOSTIC,
98 translation_key=
"owner",
99 entity_category=EntityCategory.DIAGNOSTIC,
100 entity_registry_enabled_default=
False,
101 value_fn=
lambda domain: getattr(domain,
"owner",
None),
105 translation_key=
"registrant",
106 entity_category=EntityCategory.DIAGNOSTIC,
107 entity_registry_enabled_default=
False,
108 value_fn=
lambda domain: getattr(domain,
"registrant",
None),
112 translation_key=
"registrar",
113 entity_category=EntityCategory.DIAGNOSTIC,
114 entity_registry_enabled_default=
False,
115 value_fn=
lambda domain: domain.registrar
if domain.registrar
else None,
119 translation_key=
"reseller",
120 entity_category=EntityCategory.DIAGNOSTIC,
121 entity_registry_enabled_default=
False,
122 value_fn=
lambda domain: getattr(domain,
"reseller",
None),
130 async_add_entities: AddEntitiesCallback,
132 """Set up the platform from config_entry."""
133 coordinator: DataUpdateCoordinator[Domain |
None] = hass.data[DOMAIN][
139 coordinator=coordinator,
140 description=description,
141 domain=entry.data[CONF_DOMAIN],
143 for description
in SENSORS
149 CoordinatorEntity[DataUpdateCoordinator[Domain |
None]], SensorEntity
151 """Implementation of a WHOIS sensor."""
153 entity_description: WhoisSensorEntityDescription
154 _attr_has_entity_name =
True
158 coordinator: DataUpdateCoordinator[Domain |
None],
159 description: WhoisSensorEntityDescription,
162 """Initialize the sensor."""
163 super().
__init__(coordinator=coordinator)
167 identifiers={(DOMAIN, domain)},
169 entry_type=DeviceEntryType.SERVICE,
175 """Return the state of the sensor."""
176 if self.coordinator.data
is None:
182 """Return the state attributes of the monitored installation."""
188 if self.coordinator.data
is None:
192 if expiration_date := self.coordinator.data.expiration_date:
193 attrs[ATTR_EXPIRES] = expiration_date.isoformat()
195 if name_servers := self.coordinator.data.name_servers:
196 attrs[ATTR_NAME_SERVERS] =
" ".join(name_servers)
198 if last_updated := self.coordinator.data.last_updated:
199 attrs[ATTR_UPDATED] = last_updated.isoformat()
201 if registrar := self.coordinator.data.registrar:
202 attrs[ATTR_REGISTRAR] = registrar
dict[str, int|float|None]|None extra_state_attributes(self)
datetime|int|str|None native_value(self)
None __init__(self, DataUpdateCoordinator[Domain|None] coordinator, WhoisSensorEntityDescription description, str domain)
None async_setup_entry(HomeAssistant hass, ConfigEntry entry, AddEntitiesCallback async_add_entities)
int|None _days_until_expiration(Domain domain)
datetime|None _ensure_timezone(datetime|None timestamp)