1 """Support for haveibeenpwned (email breaches) sensor."""
3 from __future__
import annotations
5 from datetime
import timedelta
6 from http
import HTTPStatus
10 import voluptuous
as vol
13 PLATFORM_SCHEMA
as SENSOR_PLATFORM_SCHEMA,
25 _LOGGER = logging.getLogger(__name__)
27 DATE_STR_FORMAT =
"%Y-%m-%d %H:%M:%S"
29 HA_USER_AGENT =
"Home Assistant HaveIBeenPwned Sensor Component"
31 MIN_TIME_BETWEEN_FORCED_UPDATES =
timedelta(seconds=5)
34 URL =
"https://haveibeenpwned.com/api/v3/breachedaccount/"
36 PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
38 vol.Required(CONF_EMAIL): vol.All(cv.ensure_list, [cv.string]),
39 vol.Required(CONF_API_KEY): cv.string,
47 add_entities: AddEntitiesCallback,
48 discovery_info: DiscoveryInfoType |
None =
None,
50 """Set up the HaveIBeenPwned sensor."""
51 emails = config[CONF_EMAIL]
52 api_key = config[CONF_API_KEY]
59 """Implementation of a HaveIBeenPwned sensor."""
61 _attr_attribution =
"Data provided by Have I Been Pwned (HIBP)"
64 """Initialize the HaveIBeenPwned sensor."""
72 """Return the name of the sensor."""
73 return f
"Breaches {self._email}"
77 """Return the unit the value is expressed in."""
82 """Return the state of the device."""
87 """Return the attributes of the sensor."""
92 for idx, value
in enumerate(self.
_data_data.data[self.
_email_email]):
93 tmpname = f
"breach {idx + 1}"
94 datetime_local = dt_util.as_local(
95 dt_util.parse_datetime(value[
"AddedDate"])
97 tmpvalue = f
"{value['Title']} {datetime_local.strftime(DATE_STR_FORMAT)}"
98 val[tmpname] = tmpvalue
103 """Get initial data."""
109 """Update sensor without throttle."""
110 self.
_data_data.update_no_throttle()
121 dt_util.now() + MIN_TIME_BETWEEN_FORCED_UPDATES,
129 """Update data and see if it contains data for our email."""
137 """Class for handling the data retrieval."""
140 """Initialize the data object."""
149 """Set the next email to be looked up."""
154 """Get the data for a specific email."""
155 self.
updateupdate(no_throttle=
True)
157 @Throttle(MIN_TIME_BETWEEN_UPDATES, MIN_TIME_BETWEEN_FORCED_UPDATES)
159 """Get the latest data for current email from REST service."""
161 url = f
"{URL}{self._email}?truncateResponse=false"
162 header = {
"User-Agent": HA_USER_AGENT,
"hibp-api-key": self.
_api_key_api_key}
163 _LOGGER.debug(
"Checking for breaches for email: %s", self.
_email_email)
164 req = requests.get(url, headers=header, allow_redirects=
True, timeout=5)
166 except requests.exceptions.RequestException:
167 _LOGGER.error(
"Failed fetching data for %s", self.
_email_email)
170 if req.status_code == HTTPStatus.OK:
172 req.json(), key=
lambda k: k[
"AddedDate"], reverse=
True
179 elif req.status_code == HTTPStatus.NOT_FOUND:
188 "Failed fetching data for %s (HTTP Status_code = %d)",
def update_no_throttle(self)
def __init__(self, emails, api_key)
def update(self, **kwargs)
def native_unit_of_measurement(self)
None async_added_to_hass(self)
def extra_state_attributes(self)
def update_nothrottle(self, dummy=None)
def __init__(self, data, email)
None schedule_update_ha_state(self, bool force_refresh=False)
None setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback add_entities, DiscoveryInfoType|None discovery_info=None)
def add_entities(account, async_add_entities, tracked)