Skip to content

Commit

Permalink
feat: allow image storage location to be configured (#976)
Browse files Browse the repository at this point in the history
* feat: allow image storage location to be configured

* update tests

* formatting

Signed-off-by: firstof9@gmail.com <firstof9@gmail.com>

* linting

* fix tests again

* formatting

* fix tests, add error and translations for invalid path

* formatting

* update tests

* more test updates

---------

Signed-off-by: firstof9@gmail.com <firstof9@gmail.com>
  • Loading branch information
firstof9 authored Sep 18, 2024
1 parent 4a39728 commit 2f57315
Show file tree
Hide file tree
Showing 28 changed files with 1,320 additions and 230 deletions.
6 changes: 4 additions & 2 deletions custom_components/mail_and_packages/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ def available(self) -> bool:
def is_on(self) -> bool:
"""Return True if the image is updated."""
if self._type == "usps_update":
if ATTR_IMAGE_NAME in self.coordinator.data.keys():
attributes = (ATTR_IMAGE_NAME, ATTR_IMAGE_PATH)
if set(attributes).issubset(self.coordinator.data.keys()):
image = self.coordinator.data[ATTR_IMAGE_NAME]
path = self.coordinator.data[ATTR_IMAGE_PATH]
usps_image = f"{self.hass.config.path()}/{path}{image}"
Expand All @@ -104,7 +105,8 @@ def is_on(self) -> bool:
return False

if self._type == "amazon_update":
if ATTR_AMAZON_IMAGE in self.coordinator.data.keys():
attributes = (ATTR_AMAZON_IMAGE, ATTR_IMAGE_PATH)
if set(attributes).issubset(self.coordinator.data.keys()):
image = self.coordinator.data[ATTR_AMAZON_IMAGE]
path = f"{self.coordinator.data[ATTR_IMAGE_PATH]}amazon/"
amazon_image = f"{self.hass.config.path()}/{path}{image}"
Expand Down
107 changes: 84 additions & 23 deletions custom_components/mail_and_packages/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
CONF_AMAZON_FWDS,
CONF_CUSTOM_IMG,
CONF_CUSTOM_IMG_FILE,
CONF_STORAGE,
CONF_DURATION,
CONF_FOLDER,
CONF_GENERATE_MP4,
Expand All @@ -45,6 +46,7 @@
DEFAULT_PATH,
DEFAULT_PORT,
DEFAULT_SCAN_INTERVAL,
DEFAULT_STORAGE,
DOMAIN,
)
from .helpers import _check_ffmpeg, _test_login, get_resources, login
Expand Down Expand Up @@ -129,6 +131,14 @@ async def _validate_user_input(user_input: dict) -> tuple:
if not valid:
errors[CONF_CUSTOM_IMG_FILE] = "file_not_found"

# validate path exists
if CONF_STORAGE in user_input:
valid = path.exists(user_input[CONF_STORAGE])
else:
valid = True
if not valid:
errors[CONF_STORAGE] = "path_not_found"

return errors, user_input


Expand Down Expand Up @@ -274,6 +284,22 @@ def _get_default(key: str, fallback_default: Any = None) -> None:
)


def _get_schema_step_storage(user_input: list, default_dict: list) -> Any:
"""Get a schema using the default_dict as a backup."""
if user_input is None:
user_input = {}

def _get_default(key: str, fallback_default: Any = None) -> None:
"""Get default value for key."""
return user_input.get(key, default_dict.get(key, fallback_default))

return vol.Schema(
{
vol.Required(CONF_STORAGE, default=_get_default(CONF_STORAGE)): cv.string,
}
)


@config_entries.HANDLERS.register(DOMAIN)
class MailAndPackagesFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
"""Config flow for Mail and Packages."""
Expand Down Expand Up @@ -374,9 +400,7 @@ async def async_step_config_3(self, user_input=None):
self._data.update(user_input)
self._errors, user_input = await _validate_user_input(self._data)
if len(self._errors) == 0:
return self.async_create_entry(
title=self._data[CONF_HOST], data=self._data
)
return await self.async_step_config_storage()
return await self._show_config_3(user_input)

return await self._show_config_3(user_input)
Expand All @@ -403,9 +427,8 @@ async def async_step_config_amazon(self, user_input=None):
if len(self._errors) == 0:
if self._data[CONF_CUSTOM_IMG]:
return await self.async_step_config_3()
return self.async_create_entry(
title=self._data[CONF_HOST], data=self._data
)
return await self.async_step_config_storage()

return await self._show_config_amazon(user_input)

return await self._show_config_amazon(user_input)
Expand All @@ -425,6 +448,33 @@ async def _show_config_amazon(self, user_input):
errors=self._errors,
)

async def async_step_config_storage(self, user_input=None):
"""Configure form step storage."""
self._errors = {}
if user_input is not None:
self._data.update(user_input)
self._errors, user_input = await _validate_user_input(self._data)
if len(self._errors) == 0:
return self.async_create_entry(
title=self._data[CONF_HOST], data=self._data
)
return await self._show_config_storage(user_input)

return await self._show_config_storage(user_input)

async def _show_config_storage(self, user_input):
"""Step 3 setup."""
# Defaults
defaults = {
CONF_STORAGE: DEFAULT_STORAGE,
}

return self.async_show_form(
step_id="config_storage",
data_schema=_get_schema_step_storage(user_input, defaults),
errors=self._errors,
)

async def async_step_reconfigure(self, user_input: dict[str, Any] | None = None):
"""Add reconfigure step to allow to reconfigure a config entry."""
self._entry = self.hass.config_entries.async_get_entry(self.context["entry_id"])
Expand Down Expand Up @@ -473,12 +523,7 @@ async def async_step_reconfig_2(self, user_input=None):
if self._data[CONF_CUSTOM_IMG]:
return await self.async_step_reconfig_3()

self.hass.config_entries.async_update_entry(
self._entry, data=self._data
)
await self.hass.config_entries.async_reload(self._entry.entry_id)
_LOGGER.debug("%s reconfigured.", DOMAIN)
return self.async_abort(reason="reconfigure_successful")
return await self.async_step_reconfig_storage()

return await self._show_reconfig_2(user_input)

Expand All @@ -502,12 +547,7 @@ async def async_step_reconfig_3(self, user_input=None):
self._data.update(user_input)
self._errors, user_input = await _validate_user_input(self._data)
if len(self._errors) == 0:
self.hass.config_entries.async_update_entry(
self._entry, data=self._data
)
await self.hass.config_entries.async_reload(self._entry.entry_id)
_LOGGER.debug("%s reconfigured.", DOMAIN)
return self.async_abort(reason="reconfigure_successful")
return await self.async_step_reconfig_storage()

return await self._show_reconfig_3(user_input)

Expand Down Expand Up @@ -536,21 +576,42 @@ async def async_step_reconfig_amazon(self, user_input=None):
if self._data[CONF_CUSTOM_IMG]:
return await self.async_step_reconfig_3()

return await self.async_step_reconfig_storage()

return await self._show_reconfig_amazon(user_input)

return await self._show_reconfig_amazon(user_input)

async def _show_reconfig_amazon(self, user_input):
"""Step 3 setup."""
return self.async_show_form(
step_id="reconfig_amazon",
data_schema=_get_schema_step_amazon(user_input, self._data),
errors=self._errors,
)

async def async_step_reconfig_storage(self, user_input=None):
"""Configure form step storage."""
self._errors = {}
if user_input is not None:
self._data.update(user_input)
self._errors, user_input = await _validate_user_input(self._data)
if len(self._errors) == 0:
self.hass.config_entries.async_update_entry(
self._entry, data=self._data
)
await self.hass.config_entries.async_reload(self._entry.entry_id)
_LOGGER.debug("%s reconfigured.", DOMAIN)
return self.async_abort(reason="reconfigure_successful")

return await self._show_reconfig_amazon(user_input)
return await self._show_reconfig_storage(user_input)

return await self._show_reconfig_amazon(user_input)
return await self._show_reconfig_storage(user_input)

async def _show_reconfig_amazon(self, user_input):
async def _show_reconfig_storage(self, user_input):
"""Step 3 setup."""
return self.async_show_form(
step_id="reconfig_amazon",
data_schema=_get_schema_step_amazon(user_input, self._data),
step_id="reconfig_storage",
data_schema=_get_schema_step_storage(user_input, self._data),
errors=self._errors,
)
2 changes: 2 additions & 0 deletions custom_components/mail_and_packages/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
CONF_CAMERA_NAME = "camera_name"
CONF_CUSTOM_IMG = "custom_img"
CONF_CUSTOM_IMG_FILE = "custom_img_file"
CONF_STORAGE = "storage"
CONF_FOLDER = "folder"
CONF_PATH = "image_path"
CONF_DURATION = "gif_duration"
Expand Down Expand Up @@ -76,6 +77,7 @@
DEFAULT_CUSTOM_IMG_FILE = "custom_components/mail_and_packages/images/mail_none.gif"
DEFAULT_AMAZON_DAYS = 3
DEFAULT_AMAZON_DOMAIN = "amazon.com"
DEFAULT_STORAGE = "custom_components/mail_and_packages/images/"

# Amazon
AMAZON_DOMAINS = [
Expand Down
7 changes: 5 additions & 2 deletions custom_components/mail_and_packages/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
CONF_GENERATE_MP4,
CONF_IMAP_SECURITY,
CONF_VERIFY_SSL,
CONF_STORAGE,
DEFAULT_AMAZON_DAYS,
OVERLAY,
SENSOR_DATA,
Expand Down Expand Up @@ -158,9 +159,11 @@ def default_image_path(
) -> str:
"""Return value of the default image path.
Returns the default path based on logic (placeholder for future code)
Returns the default path based on logic
"""
# Return the default
storage = config_entry.get(CONF_STORAGE)
if storage:
return storage
return "custom_components/mail_and_packages/images/"


Expand Down
Loading

0 comments on commit 2f57315

Please sign in to comment.