From 6cc7212cefaf658b90e18fa3eaee2ae931f7d91b Mon Sep 17 00:00:00 2001 From: Franco Pellicciotti Date: Thu, 9 Jul 2026 13:30:12 -0400 Subject: [PATCH] Updated apps --- .../integrations/systemmonitor/logo.png | Bin 0 -> 4244 bytes .ha_run.lock | 2 +- automations.yaml | 351 +++- .../amazon_order_status/__init__.py | 93 + .../__pycache__/__init__.cpython-314.pyc | Bin 0 -> 5554 bytes .../__pycache__/config_flow.cpython-314.pyc | Bin 0 -> 5152 bytes .../__pycache__/const.cpython-314.pyc | Bin 0 -> 765 bytes .../__pycache__/coordinator.cpython-314.pyc | Bin 0 -> 28083 bytes .../__pycache__/options_flow.cpython-314.pyc | Bin 0 -> 3645 bytes .../amazon_order_status/config_flow.py | 101 + .../amazon_order_status/const.py | 18 + .../amazon_order_status/coordinator.py | 488 +++++ .../amazon_order_status/manifest.json | 12 + .../amazon_order_status/options_flow.py | 78 + .../purge_script_example.yaml | 13 + .../amazon_order_status/sensor.py | 95 + .../amazon_order_status/services.yaml | 10 + .../amazon_order_status/translations/en.json | 34 + .../mail_and_packages/__init__.py | 371 ++++ .../__pycache__/__init__.cpython-314.pyc | Bin 0 -> 14251 bytes .../application_credentials.cpython-314.pyc | Bin 0 -> 1699 bytes .../__pycache__/config_flow.cpython-314.pyc | Bin 0 -> 70901 bytes .../__pycache__/const.cpython-314.pyc | Bin 0 -> 36421 bytes .../__pycache__/coordinator.cpython-314.pyc | Bin 0 -> 28765 bytes .../__pycache__/entity.cpython-314.pyc | Bin 0 -> 822 bytes .../__pycache__/helpers.cpython-314.pyc | Bin 0 -> 7079 bytes .../application_credentials.py | 40 + .../mail_and_packages/binary_sensor.py | 88 + custom_components/mail_and_packages/camera.py | 666 ++++++ .../mail_and_packages/config_flow.py | 1427 +++++++++++++ custom_components/mail_and_packages/const.py | 1812 +++++++++++++++++ .../mail_and_packages/coordinator.py | 555 +++++ .../mail_and_packages/diagnostics.py | 47 + custom_components/mail_and_packages/entity.py | 14 + .../mail_and_packages/helpers.py | 131 ++ .../image-no-mailpieces700.jpg | Bin 0 -> 44385 bytes .../mail_and_packages/images/.PLACEHOLDER | 1 + .../mail_and_packages/mail_none.gif | Bin 0 -> 41094 bytes .../mail_and_packages/manifest.json | 22 + .../no_deliveries_amazon.jpg | Bin 0 -> 35660 bytes .../mail_and_packages/no_deliveries_fedex.jpg | Bin 0 -> 41496 bytes .../no_deliveries_generic.jpg | Bin 0 -> 27660 bytes .../mail_and_packages/no_deliveries_ups.jpg | Bin 0 -> 34834 bytes .../no_deliveries_walmart.jpg | Bin 0 -> 47455 bytes .../mail_and_packages/overlay.png | Bin 0 -> 8764 bytes custom_components/mail_and_packages/sensor.py | 289 +++ .../mail_and_packages/services.yaml | 13 + .../mail_and_packages/shippers/__init__.py | 42 + .../__pycache__/__init__.cpython-314.pyc | Bin 0 -> 1498 bytes .../__pycache__/amazon.cpython-314.pyc | Bin 0 -> 32673 bytes .../shippers/__pycache__/base.cpython-314.pyc | Bin 0 -> 3187 bytes .../__pycache__/generic.cpython-314.pyc | Bin 0 -> 30475 bytes .../__pycache__/post_de.cpython-314.pyc | Bin 0 -> 18872 bytes .../shippers/__pycache__/usps.cpython-314.pyc | Bin 0 -> 22673 bytes .../mail_and_packages/shippers/amazon.py | 612 ++++++ .../mail_and_packages/shippers/base.py | 54 + .../mail_and_packages/shippers/generic.py | 697 +++++++ .../mail_and_packages/shippers/post_de.py | 370 ++++ .../mail_and_packages/shippers/usps.py | 425 ++++ .../mail_and_packages/strings.json | 199 ++ .../mail_and_packages/translations/ca.json | 203 ++ .../mail_and_packages/translations/cs.json | 269 +++ .../mail_and_packages/translations/de.json | 207 ++ .../mail_and_packages/translations/en.json | 213 ++ .../mail_and_packages/translations/es.json | 203 ++ .../translations/es_419.json | 203 ++ .../mail_and_packages/translations/fi.json | 203 ++ .../mail_and_packages/translations/fr.json | 203 ++ .../mail_and_packages/translations/hu.json | 203 ++ .../mail_and_packages/translations/it.json | 203 ++ .../mail_and_packages/translations/ko.json | 203 ++ .../mail_and_packages/translations/nl.json | 203 ++ .../mail_and_packages/translations/no.json | 203 ++ .../mail_and_packages/translations/pl.json | 203 ++ .../mail_and_packages/translations/pt.json | 203 ++ .../mail_and_packages/translations/pt_BR.json | 203 ++ .../mail_and_packages/translations/ru.json | 203 ++ .../mail_and_packages/translations/sk.json | 203 ++ .../mail_and_packages/translations/sl.json | 203 ++ .../mail_and_packages/translations/sv.json | 203 ++ .../translations/zh_Hant_HK.json | 203 ++ .../mail_and_packages/utils/__init__.py | 1 + .../__pycache__/__init__.cpython-314.pyc | Bin 0 -> 215 bytes .../utils/__pycache__/amazon.cpython-314.pyc | Bin 0 -> 20354 bytes .../utils/__pycache__/cache.cpython-314.pyc | Bin 0 -> 5382 bytes .../utils/__pycache__/date.cpython-314.pyc | Bin 0 -> 1646 bytes .../utils/__pycache__/email.cpython-314.pyc | Bin 0 -> 8731 bytes .../utils/__pycache__/image.cpython-314.pyc | Bin 0 -> 22575 bytes .../utils/__pycache__/imap.cpython-314.pyc | Bin 0 -> 36487 bytes .../utils/__pycache__/shipper.cpython-314.pyc | Bin 0 -> 12250 bytes .../mail_and_packages/utils/amazon.py | 396 ++++ .../mail_and_packages/utils/cache.py | 104 + .../mail_and_packages/utils/date.py | 27 + .../mail_and_packages/utils/email.py | 201 ++ .../mail_and_packages/utils/image.py | 485 +++++ .../mail_and_packages/utils/imap.py | 722 +++++++ .../mail_and_packages/utils/shipper.py | 294 +++ .../mail_and_packages/vignette.png | Bin 0 -> 38527 bytes custom_components/mail_and_packages/white.png | Bin 0 -> 171 bytes .../maintenance_supporter/__init__.py | 46 + .../__pycache__/__init__.cpython-314.pyc | Bin 73202 -> 75402 bytes .../__pycache__/binary_sensor.cpython-314.pyc | Bin 9157 -> 9157 bytes .../__pycache__/button.cpython-314.pyc | Bin 7122 -> 7122 bytes .../__pycache__/calendar.cpython-314.pyc | Bin 23835 -> 23835 bytes .../__pycache__/condition.cpython-314.pyc | Bin 2192 -> 2192 bytes .../__pycache__/config_flow.cpython-314.pyc | Bin 60016 -> 61054 bytes .../config_flow_helpers.cpython-314.pyc | Bin 16585 -> 16585 bytes ...config_flow_options_global.cpython-314.pyc | Bin 41821 -> 41821 bytes .../config_flow_trigger.cpython-314.pyc | Bin 48044 -> 48044 bytes .../__pycache__/const.cpython-314.pyc | Bin 16830 -> 16830 bytes .../__pycache__/coordinator.cpython-314.pyc | Bin 62257 -> 62257 bytes .../__pycache__/diagnostics.cpython-314.pyc | Bin 10306 -> 10306 bytes .../__pycache__/logbook.cpython-314.pyc | Bin 12851 -> 12851 bytes .../__pycache__/panel.cpython-314.pyc | Bin 5123 -> 5559 bytes .../__pycache__/repairs.cpython-314.pyc | Bin 34819 -> 36507 bytes .../__pycache__/sensor.cpython-314.pyc | Bin 32074 -> 32074 bytes .../__pycache__/storage.cpython-314.pyc | Bin 20946 -> 20946 bytes .../__pycache__/templates.cpython-314.pyc | Bin 9371 -> 9371 bytes .../templates_i18n.cpython-314.pyc | Bin 45580 -> 45580 bytes .../__pycache__/todo.cpython-314.pyc | Bin 9384 -> 9384 bytes .../__pycache__/trigger.cpython-314.pyc | Bin 2954 -> 2954 bytes .../__pycache__/views.cpython-314.pyc | Bin 16783 -> 16783 bytes .../maintenance_supporter/config_flow.py | 19 + .../__pycache__/__init__.cpython-314.pyc | Bin 365 -> 365 bytes .../__pycache__/entity_base.cpython-314.pyc | Bin 5235 -> 5235 bytes .../summary_coordinator.cpython-314.pyc | Bin 7694 -> 7694 bytes .../__pycache__/__init__.cpython-314.pyc | Bin 8303 -> 8303 bytes .../__pycache__/base_trigger.cpython-314.pyc | Bin 14559 -> 14559 bytes .../__pycache__/compound.cpython-314.pyc | Bin 16033 -> 16033 bytes .../__pycache__/counter.cpython-314.pyc | Bin 8148 -> 8148 bytes .../__pycache__/runtime.cpython-314.pyc | Bin 16850 -> 16850 bytes .../__pycache__/state_change.cpython-314.pyc | Bin 9768 -> 9768 bytes .../__pycache__/threshold.cpython-314.pyc | Bin 9628 -> 9628 bytes .../__tests__/dashboard-kpi-chips.test.ts | 54 + .../maintenance-dashboard-strategy.ts | 50 +- .../__pycache__/__init__.cpython-314.pyc | Bin 3742 -> 3742 bytes .../maintenance-dashboard-strategy.js | 4 +- .../__pycache__/__init__.cpython-314.pyc | Bin 285 -> 285 bytes .../action_listener.cpython-314.pyc | Bin 6226 -> 6226 bytes .../__pycache__/aggregate.cpython-314.pyc | Bin 5113 -> 5113 bytes .../helpers/__pycache__/dates.cpython-314.pyc | Bin 9812 -> 9812 bytes .../__pycache__/documents.cpython-314.pyc | Bin 30574 -> 30574 bytes .../entity_analyzer.cpython-314.pyc | Bin 9598 -> 9598 bytes .../global_options.cpython-314.pyc | Bin 3716 -> 3716 bytes .../helpers/__pycache__/i18n.cpython-314.pyc | Bin 1337 -> 1337 bytes .../notification_manager.cpython-314.pyc | Bin 62232 -> 62232 bytes .../notify_targets.cpython-314.pyc | Bin 2701 -> 2701 bytes .../helpers/__pycache__/pause.cpython-314.pyc | Bin 4217 -> 4217 bytes .../__pycache__/permissions.cpython-314.pyc | Bin 5960 -> 5960 bytes .../__pycache__/qr_generator.cpython-314.pyc | Bin 8279 -> 8279 bytes .../__pycache__/qrcodegen.cpython-314.pyc | Bin 50344 -> 50344 bytes .../__pycache__/retention.cpython-314.pyc | Bin 10544 -> 10544 bytes .../__pycache__/sanitize.cpython-314.pyc | Bin 13146 -> 13146 bytes .../__pycache__/schedule.cpython-314.pyc | Bin 27060 -> 27060 bytes .../settings_registry.cpython-314.pyc | Bin 7903 -> 7903 bytes .../__pycache__/status.cpython-314.pyc | Bin 2481 -> 2481 bytes .../__pycache__/task_fields.cpython-314.pyc | Bin 2021 -> 2021 bytes .../threshold_calculator.cpython-314.pyc | Bin 6238 -> 6238 bytes .../__pycache__/vacation.cpython-314.pyc | Bin 16497 -> 16497 bytes .../__pycache__/workday.cpython-314.pyc | Bin 9006 -> 9006 bytes .../maintenance_supporter/manifest.json | 2 +- .../__pycache__/__init__.cpython-314.pyc | Bin 529 -> 529 bytes .../maintenance_object.cpython-314.pyc | Bin 5037 -> 5037 bytes .../maintenance_task.cpython-314.pyc | Bin 27020 -> 27020 bytes .../maintenance_type.cpython-314.pyc | Bin 3085 -> 3085 bytes .../maintenance_supporter/panel.py | 34 +- .../maintenance_supporter/repairs.py | 24 + .../maintenance_supporter/strings.json | 11 + .../translations/cs.json | 11 + .../translations/da.json | 11 + .../translations/de.json | 11 + .../translations/en.json | 11 + .../translations/es.json | 11 + .../translations/fi.json | 11 + .../translations/fr.json | 11 + .../translations/hi.json | 11 + .../translations/it.json | 11 + .../translations/ja.json | 11 + .../translations/nb.json | 11 + .../translations/nl.json | 11 + .../translations/pl.json | 11 + .../translations/pt.json | 11 + .../translations/ru.json | 11 + .../translations/sv.json | 11 + .../translations/uk.json | 11 + .../translations/zh-Hans.json | 11 + .../__pycache__/__init__.cpython-314.pyc | Bin 23939 -> 23939 bytes .../__pycache__/analysis.cpython-314.pyc | Bin 12878 -> 12878 bytes .../__pycache__/dashboard.cpython-314.pyc | Bin 26401 -> 26435 bytes .../__pycache__/documents.cpython-314.pyc | Bin 13158 -> 13158 bytes .../__pycache__/groups.cpython-314.pyc | Bin 8318 -> 8318 bytes .../websocket/__pycache__/io.cpython-314.pyc | Bin 29379 -> 29379 bytes .../__pycache__/objects.cpython-314.pyc | Bin 45695 -> 45695 bytes .../__pycache__/tags.cpython-314.pyc | Bin 2930 -> 2930 bytes .../__pycache__/tasks.cpython-314.pyc | Bin 1755 -> 1755 bytes .../__pycache__/tasks_actions.cpython-314.pyc | Bin 16986 -> 16986 bytes .../__pycache__/tasks_crud.cpython-314.pyc | Bin 34236 -> 34236 bytes .../__pycache__/tasks_history.cpython-314.pyc | Bin 6477 -> 6477 bytes .../tasks_lifecycle.cpython-314.pyc | Bin 9040 -> 9040 bytes .../__pycache__/tasks_persist.cpython-314.pyc | Bin 8441 -> 8441 bytes .../tasks_validation.cpython-314.pyc | Bin 10170 -> 10170 bytes .../__pycache__/users.cpython-314.pyc | Bin 7375 -> 7375 bytes .../__pycache__/vacation.cpython-314.pyc | Bin 11145 -> 11145 bytes .../websocket/dashboard.py | 5 + scripts.yaml | 8 - www/NestLiving.jpg | Bin 2689 -> 0 bytes www/blink.jpg | Bin 139485 -> 0 bytes www/blinkTree.jpg | Bin 152018 -> 0 bytes www/blink_Front.jpg | Bin 213715 -> 0 bytes www/blink_Front_20260708_164225.jpg | Bin 0 -> 217307 bytes www/blink_Front_20260708_181316.jpg | Bin 0 -> 217949 bytes www/blink_Front_20260708_181402.jpg | Bin 0 -> 194894 bytes www/blink_Front_20260708_183708.jpg | Bin 0 -> 190405 bytes www/blink_Front_20260708_184115.jpg | Bin 0 -> 190405 bytes www/blink_Front_20260708_190004.jpg | Bin 0 -> 212738 bytes www/blink_Front_20260708_194438.jpg | Bin 0 -> 200069 bytes www/blink_Front_20260708_203838.jpg | Bin 0 -> 143102 bytes www/blink_Front_20260708_203948.jpg | Bin 0 -> 178782 bytes www/blink_Front_20260708_212230.jpg | Bin 0 -> 175005 bytes www/blink_Front_20260708_212718.jpg | Bin 0 -> 61691 bytes www/blink_Front_20260708_213737.jpg | Bin 0 -> 59777 bytes www/blink_Front_20260709_044712.jpg | Bin 0 -> 63335 bytes www/blink_Front_20260709_051616.jpg | Bin 0 -> 159051 bytes www/blink_Front_20260709_055424.jpg | Bin 0 -> 180713 bytes www/blink_Front_20260709_063716.jpg | Bin 0 -> 186288 bytes www/blink_Front_20260709_071123.jpg | Bin 0 -> 186288 bytes www/blink_Front_20260709_072634.jpg | Bin 0 -> 190492 bytes www/blink_Front_20260709_080013.jpg | Bin 0 -> 178193 bytes www/blink_Front_20260709_084809.jpg | Bin 0 -> 191112 bytes www/blink_Front_20260709_091613.jpg | Bin 0 -> 196683 bytes www/blink_Front_20260709_091658.jpg | Bin 0 -> 196109 bytes www/blink_Front_20260709_110546.jpg | Bin 0 -> 193758 bytes www/blink_Front_20260709_123831.jpg | Bin 0 -> 193134 bytes www/blink_Front_20260709_124048.jpg | Bin 0 -> 199537 bytes www/blink_Front_20260709_124228.jpg | Bin 0 -> 192176 bytes www/blink_Front_20260709_124441.jpg | Bin 0 -> 200689 bytes www/blink_Front_20260709_124445.jpg | Bin 0 -> 200689 bytes www/blink_Front_20260709_131005.jpg | Bin 0 -> 200689 bytes www/blink_backyard_shed_snapshot.jpg | Bin 167248 -> 0 bytes www/blink_backyard_snapshot.jpg | Bin 167248 -> 0 bytes www/blink_shed.jpg | Bin 0 -> 186190 bytes www/blink_shed_20260709_083918.jpg | Bin 0 -> 137841 bytes www/blink_shed_20260709_084046.jpg | Bin 0 -> 143888 bytes www/blink_shed_20260709_085752.jpg | Bin 0 -> 151729 bytes www/blink_shed_20260709_090024.jpg | Bin 0 -> 152721 bytes www/blink_shed_20260709_090207.jpg | Bin 0 -> 151916 bytes www/blink_shed_20260709_090442.jpg | Bin 0 -> 154682 bytes www/blink_shed_20260709_090548.jpg | Bin 0 -> 158120 bytes www/blink_shed_20260709_091016.jpg | Bin 0 -> 152572 bytes www/blink_shed_20260709_091131.jpg | Bin 0 -> 152826 bytes www/blink_shed_20260709_091214.jpg | Bin 0 -> 152900 bytes www/blink_shed_20260709_093518.jpg | Bin 0 -> 149485 bytes www/blink_shed_20260709_103911.jpg | Bin 0 -> 158089 bytes www/blink_shed_20260709_110048.jpg | Bin 0 -> 146966 bytes www/blink_shed_20260709_110120.jpg | Bin 0 -> 145552 bytes www/blink_shed_20260709_110147.jpg | Bin 0 -> 144642 bytes .../statistics-graph-chart-card.js | 1 + .../statistics-graph-chart-card.js.gz | Bin 0 -> 266845 bytes .../multiple-entity-row.js | 2 +- .../multiple-entity-row.js.gz | Bin 12003 -> 19518 bytes www/nest.jpg | Bin 2689 -> 0 bytes zigbee2mqtt/coordinator_backup.json | 30 +- 262 files changed, 16124 insertions(+), 107 deletions(-) create mode 100644 .cache/brands/integrations/systemmonitor/logo.png create mode 100644 custom_components/amazon_order_status/__init__.py create mode 100644 custom_components/amazon_order_status/__pycache__/__init__.cpython-314.pyc create mode 100644 custom_components/amazon_order_status/__pycache__/config_flow.cpython-314.pyc create mode 100644 custom_components/amazon_order_status/__pycache__/const.cpython-314.pyc create mode 100644 custom_components/amazon_order_status/__pycache__/coordinator.cpython-314.pyc create mode 100644 custom_components/amazon_order_status/__pycache__/options_flow.cpython-314.pyc create mode 100644 custom_components/amazon_order_status/config_flow.py create mode 100644 custom_components/amazon_order_status/const.py create mode 100644 custom_components/amazon_order_status/coordinator.py create mode 100644 custom_components/amazon_order_status/manifest.json create mode 100644 custom_components/amazon_order_status/options_flow.py create mode 100644 custom_components/amazon_order_status/purge_script_example.yaml create mode 100644 custom_components/amazon_order_status/sensor.py create mode 100644 custom_components/amazon_order_status/services.yaml create mode 100644 custom_components/amazon_order_status/translations/en.json create mode 100644 custom_components/mail_and_packages/__init__.py create mode 100644 custom_components/mail_and_packages/__pycache__/__init__.cpython-314.pyc create mode 100644 custom_components/mail_and_packages/__pycache__/application_credentials.cpython-314.pyc create mode 100644 custom_components/mail_and_packages/__pycache__/config_flow.cpython-314.pyc create mode 100644 custom_components/mail_and_packages/__pycache__/const.cpython-314.pyc create mode 100644 custom_components/mail_and_packages/__pycache__/coordinator.cpython-314.pyc create mode 100644 custom_components/mail_and_packages/__pycache__/entity.cpython-314.pyc create mode 100644 custom_components/mail_and_packages/__pycache__/helpers.cpython-314.pyc create mode 100644 custom_components/mail_and_packages/application_credentials.py create mode 100644 custom_components/mail_and_packages/binary_sensor.py create mode 100644 custom_components/mail_and_packages/camera.py create mode 100644 custom_components/mail_and_packages/config_flow.py create mode 100644 custom_components/mail_and_packages/const.py create mode 100644 custom_components/mail_and_packages/coordinator.py create mode 100644 custom_components/mail_and_packages/diagnostics.py create mode 100644 custom_components/mail_and_packages/entity.py create mode 100644 custom_components/mail_and_packages/helpers.py create mode 100644 custom_components/mail_and_packages/image-no-mailpieces700.jpg create mode 100644 custom_components/mail_and_packages/images/.PLACEHOLDER create mode 100644 custom_components/mail_and_packages/mail_none.gif create mode 100644 custom_components/mail_and_packages/manifest.json create mode 100644 custom_components/mail_and_packages/no_deliveries_amazon.jpg create mode 100644 custom_components/mail_and_packages/no_deliveries_fedex.jpg create mode 100644 custom_components/mail_and_packages/no_deliveries_generic.jpg create mode 100644 custom_components/mail_and_packages/no_deliveries_ups.jpg create mode 100644 custom_components/mail_and_packages/no_deliveries_walmart.jpg create mode 100644 custom_components/mail_and_packages/overlay.png create mode 100644 custom_components/mail_and_packages/sensor.py create mode 100644 custom_components/mail_and_packages/services.yaml create mode 100644 custom_components/mail_and_packages/shippers/__init__.py create mode 100644 custom_components/mail_and_packages/shippers/__pycache__/__init__.cpython-314.pyc create mode 100644 custom_components/mail_and_packages/shippers/__pycache__/amazon.cpython-314.pyc create mode 100644 custom_components/mail_and_packages/shippers/__pycache__/base.cpython-314.pyc create mode 100644 custom_components/mail_and_packages/shippers/__pycache__/generic.cpython-314.pyc create mode 100644 custom_components/mail_and_packages/shippers/__pycache__/post_de.cpython-314.pyc create mode 100644 custom_components/mail_and_packages/shippers/__pycache__/usps.cpython-314.pyc create mode 100644 custom_components/mail_and_packages/shippers/amazon.py create mode 100644 custom_components/mail_and_packages/shippers/base.py create mode 100644 custom_components/mail_and_packages/shippers/generic.py create mode 100644 custom_components/mail_and_packages/shippers/post_de.py create mode 100644 custom_components/mail_and_packages/shippers/usps.py create mode 100644 custom_components/mail_and_packages/strings.json create mode 100644 custom_components/mail_and_packages/translations/ca.json create mode 100644 custom_components/mail_and_packages/translations/cs.json create mode 100644 custom_components/mail_and_packages/translations/de.json create mode 100644 custom_components/mail_and_packages/translations/en.json create mode 100644 custom_components/mail_and_packages/translations/es.json create mode 100644 custom_components/mail_and_packages/translations/es_419.json create mode 100644 custom_components/mail_and_packages/translations/fi.json create mode 100644 custom_components/mail_and_packages/translations/fr.json create mode 100644 custom_components/mail_and_packages/translations/hu.json create mode 100644 custom_components/mail_and_packages/translations/it.json create mode 100644 custom_components/mail_and_packages/translations/ko.json create mode 100644 custom_components/mail_and_packages/translations/nl.json create mode 100644 custom_components/mail_and_packages/translations/no.json create mode 100644 custom_components/mail_and_packages/translations/pl.json create mode 100644 custom_components/mail_and_packages/translations/pt.json create mode 100644 custom_components/mail_and_packages/translations/pt_BR.json create mode 100644 custom_components/mail_and_packages/translations/ru.json create mode 100644 custom_components/mail_and_packages/translations/sk.json create mode 100644 custom_components/mail_and_packages/translations/sl.json create mode 100644 custom_components/mail_and_packages/translations/sv.json create mode 100644 custom_components/mail_and_packages/translations/zh_Hant_HK.json create mode 100644 custom_components/mail_and_packages/utils/__init__.py create mode 100644 custom_components/mail_and_packages/utils/__pycache__/__init__.cpython-314.pyc create mode 100644 custom_components/mail_and_packages/utils/__pycache__/amazon.cpython-314.pyc create mode 100644 custom_components/mail_and_packages/utils/__pycache__/cache.cpython-314.pyc create mode 100644 custom_components/mail_and_packages/utils/__pycache__/date.cpython-314.pyc create mode 100644 custom_components/mail_and_packages/utils/__pycache__/email.cpython-314.pyc create mode 100644 custom_components/mail_and_packages/utils/__pycache__/image.cpython-314.pyc create mode 100644 custom_components/mail_and_packages/utils/__pycache__/imap.cpython-314.pyc create mode 100644 custom_components/mail_and_packages/utils/__pycache__/shipper.cpython-314.pyc create mode 100644 custom_components/mail_and_packages/utils/amazon.py create mode 100644 custom_components/mail_and_packages/utils/cache.py create mode 100644 custom_components/mail_and_packages/utils/date.py create mode 100644 custom_components/mail_and_packages/utils/email.py create mode 100644 custom_components/mail_and_packages/utils/image.py create mode 100644 custom_components/mail_and_packages/utils/imap.py create mode 100644 custom_components/mail_and_packages/utils/shipper.py create mode 100644 custom_components/mail_and_packages/vignette.png create mode 100644 custom_components/mail_and_packages/white.png create mode 100644 custom_components/maintenance_supporter/frontend-src/__tests__/dashboard-kpi-chips.test.ts delete mode 100644 www/NestLiving.jpg delete mode 100644 www/blink.jpg delete mode 100644 www/blinkTree.jpg delete mode 100644 www/blink_Front.jpg create mode 100644 www/blink_Front_20260708_164225.jpg create mode 100644 www/blink_Front_20260708_181316.jpg create mode 100644 www/blink_Front_20260708_181402.jpg create mode 100644 www/blink_Front_20260708_183708.jpg create mode 100644 www/blink_Front_20260708_184115.jpg create mode 100644 www/blink_Front_20260708_190004.jpg create mode 100644 www/blink_Front_20260708_194438.jpg create mode 100644 www/blink_Front_20260708_203838.jpg create mode 100644 www/blink_Front_20260708_203948.jpg create mode 100644 www/blink_Front_20260708_212230.jpg create mode 100644 www/blink_Front_20260708_212718.jpg create mode 100644 www/blink_Front_20260708_213737.jpg create mode 100644 www/blink_Front_20260709_044712.jpg create mode 100644 www/blink_Front_20260709_051616.jpg create mode 100644 www/blink_Front_20260709_055424.jpg create mode 100644 www/blink_Front_20260709_063716.jpg create mode 100644 www/blink_Front_20260709_071123.jpg create mode 100644 www/blink_Front_20260709_072634.jpg create mode 100644 www/blink_Front_20260709_080013.jpg create mode 100644 www/blink_Front_20260709_084809.jpg create mode 100644 www/blink_Front_20260709_091613.jpg create mode 100644 www/blink_Front_20260709_091658.jpg create mode 100644 www/blink_Front_20260709_110546.jpg create mode 100644 www/blink_Front_20260709_123831.jpg create mode 100644 www/blink_Front_20260709_124048.jpg create mode 100644 www/blink_Front_20260709_124228.jpg create mode 100644 www/blink_Front_20260709_124441.jpg create mode 100644 www/blink_Front_20260709_124445.jpg create mode 100644 www/blink_Front_20260709_131005.jpg delete mode 100644 www/blink_backyard_shed_snapshot.jpg delete mode 100644 www/blink_backyard_snapshot.jpg create mode 100644 www/blink_shed.jpg create mode 100644 www/blink_shed_20260709_083918.jpg create mode 100644 www/blink_shed_20260709_084046.jpg create mode 100644 www/blink_shed_20260709_085752.jpg create mode 100644 www/blink_shed_20260709_090024.jpg create mode 100644 www/blink_shed_20260709_090207.jpg create mode 100644 www/blink_shed_20260709_090442.jpg create mode 100644 www/blink_shed_20260709_090548.jpg create mode 100644 www/blink_shed_20260709_091016.jpg create mode 100644 www/blink_shed_20260709_091131.jpg create mode 100644 www/blink_shed_20260709_091214.jpg create mode 100644 www/blink_shed_20260709_093518.jpg create mode 100644 www/blink_shed_20260709_103911.jpg create mode 100644 www/blink_shed_20260709_110048.jpg create mode 100644 www/blink_shed_20260709_110120.jpg create mode 100644 www/blink_shed_20260709_110147.jpg create mode 100644 www/community/Statistics-Graph-Chart-Card/statistics-graph-chart-card.js create mode 100644 www/community/Statistics-Graph-Chart-Card/statistics-graph-chart-card.js.gz delete mode 100644 www/nest.jpg diff --git a/.cache/brands/integrations/systemmonitor/logo.png b/.cache/brands/integrations/systemmonitor/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..34a3524fb2c079a7f8747a2c93a8f8ec2589c3ef GIT binary patch literal 4244 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 literal 0 HcmV?d00001 diff --git a/.ha_run.lock b/.ha_run.lock index e467328..e5a67a4 100644 --- a/.ha_run.lock +++ b/.ha_run.lock @@ -1 +1 @@ -{"pid": 71, "version": 1, "ha_version": "2026.7.1", "start_ts": 1783526323.4156625} \ No newline at end of file +{"pid": 71, "version": 1, "ha_version": "2026.7.1", "start_ts": 1783610735.5698383} \ No newline at end of file diff --git a/automations.yaml b/automations.yaml index fc284c9..c3628ec 100644 --- a/automations.yaml +++ b/automations.yaml @@ -467,14 +467,14 @@ - action: persistent_notification.create data: title: Dishwasher Filter Maintenance - message: The dishwasher has completed 40 cycles. Please clean the physical mesh + message: The dishwasher has completed 30 cycles. Please clean the physical mesh filter and press Reset on your dashboard. notification_id: dishwasher_filter_reminder - action: notify.notify metadata: {} data: title: Dishwasher Filter Maintenance - message: The dishwasher has completed 40 cycles. Please clean the physical mesh + message: The dishwasher has completed 30 cycles. Please clean the physical mesh filter and press Reset on your dashboard. mode: single - id: '1781283661169' @@ -701,45 +701,56 @@ - id: '1781445544080' alias: 'Kitchen: Coffee Maker Cycle Status' description: 'Triggers on the high-wattage grinder spike. Dynamically waits for - the cycle to finish: it requires a minimum of 4 minutes to pass AND the power - to drop back to the TV baseline.' + the cycle to finish: it requires a minimum of 1 minute to pass AND the power to + drop back to the TV baseline.' triggers: - - trigger: state + - trigger: numeric_state entity_id: sensor.coffee_maker_power - conditions: - - condition: template - value_template: '{{ states(''sensor.coffee_maker_power'') | float(0) > 1000 }}' - - condition: state - entity_id: input_boolean.coffee_maker_running - state: 'off' + above: 800 + id: coffee_started + - trigger: numeric_state + entity_id: sensor.coffee_maker_power + below: 15 + for: + hours: 0 + minutes: 1 + seconds: 0 + id: coffee_finished + conditions: [] actions: - - action: input_boolean.turn_on - target: - entity_id: input_boolean.coffee_maker_running - - action: notify.notify - data: - title: ☕ Coffee Time - message: Someone is making coffee. - - action: notify.persistent_notification - data: - title: ☕ Coffee Time - message: Someone is making coffee. - - delay: - hours: 0 - minutes: 4 - seconds: 0 - - wait_template: '{{ states(''sensor.coffee_maker_power'') | float(0) < 350 }}' - timeout: - hours: 0 - minutes: 5 - seconds: 0 - - action: input_boolean.turn_off - target: - entity_id: input_boolean.coffee_maker_running - - action: notify.notify - data: - title: ☕ Coffee Ready - message: Your coffee is ready to enjoy! + - choose: + - conditions: + - condition: trigger + id: coffee_started + - condition: state + entity_id: input_boolean.coffee_maker_running + state: 'off' + sequence: + - action: input_boolean.turn_on + target: + entity_id: input_boolean.coffee_maker_running + - action: notify.notify + data: + title: ☕ Coffee Time + message: Someone is making coffee. + - action: notify.persistent_notification + data: + title: ☕ Coffee Time + message: Someone is making coffee. + - conditions: + - condition: trigger + id: coffee_finished + - condition: state + entity_id: input_boolean.coffee_maker_running + state: 'on' + sequence: + - action: input_boolean.turn_off + target: + entity_id: input_boolean.coffee_maker_running + - action: notify.notify + data: + title: ☕ Coffee Ready + message: Your coffee is ready to enjoy! mode: single - id: '1781793117883' alias: Basement Temperature Change @@ -806,14 +817,16 @@ data: title: "\U0001F6A8 Commute Delay Alert!" message: "Traffic is heavier than usual this morning. \nGoogle Maps: {{ states('sensor.google_travel_time_work_work') - }} mins. Waze: {{ states('sensor.waze_travel_time') }} mins." + }} mins. Waze: {{ states('sensor.waze_to_work_travel_time') }} mins." data: image: /local/commute_snapshot.jpg + enabled: false - action: notify.persistent_notification data: title: "\U0001F6A8 Commute Delay Alert!" message: "Traffic is heavier than usual this morning. \nGoogle Maps: {{ states('sensor.google_travel_time_work_work') - }} mins. Waze: {{ states('sensor.waze_travel_time') }} mins.\n![Commute Map](/local/commute_snapshot.jpg)" + }} mins. Waze: {{ states('sensor.waze_to_work_travel_time') }} mins.\n![Commute + Map](/local/commute_snapshot.jpg)" mode: single - *id001 - *id001 @@ -863,7 +876,7 @@ data: title: "\U0001F697 Morning Commute" message: "Google: {{ states('sensor.google_travel_time_work_work') }} min\nWaze: - {{ states('sensor.waze_travel_time') }} min\n{% set g = states('sensor.google_travel_time_work_work') + {{ states('sensor.waze_to_work_travel_time') }} min\n{% set g = states('sensor.google_travel_time_work_work') | float(0) %} {% if g > 50 %} \U0001F6A8 Major traffic delays. {% elif g > 40 %} ⚠️ Heavy traffic. {% else %} \U0001F7E1 Moderate traffic. {% endif %}" mode: single @@ -891,38 +904,96 @@ action_rotate_ccw_face_1: [] action_flipped90_face_1: [] - id: '1783162325964' - alias: Backyard Shed Camera Motion AI Description - description: Takes a snapshot when the Blink camera detects motion, analyzes it - with AI, and sends a mobile and persistent notification. + alias: Motion Shed - AI Description + description: Takes a snapshot when the Nest camera detects motion, a person, an + animal, or a doorbell press, analyzes it with AI, and sends a mobile and persistent + notification. triggers: + - trigger: event + event_type: state_changed + event_data: + entity_id: event.front_door_front_door_motion + enabled: false - trigger: state - entity_id: binary_sensor.backyard_shed_motion - to: 'on' + entity_id: event.living_room_living_room_camera_motion + enabled: false + - trigger: state + entity_id: event.front_door_front_door_motion + enabled: false + - trigger: event.received + target: + entity_id: event.entryway_entryway_camera_motion + options: + event_type: + - camera_motion + - camera_person + - camera_sound + enabled: false + - trigger: event.received + target: + device_id: 290f56e5a655e3af82cbf3cf9fd22406 + options: + event_type: + - camera_motion + - camera_person + - camera_sound + - ring + enabled: false + - trigger: event.received + target: + device_id: 679d52e0d16cf48648d11dd024b961f8 + options: + event_type: + - camera_motion + - camera_sound + - camera_person + enabled: true + conditions: + - condition: template + value_template: '{{ trigger.event.data.new_state.attributes.event_type in [''motion'', + ''person'', ''animal'', ''chime''] }}' + enabled: false actions: - action: blink.trigger_camera target: entity_id: camera.backyard_shed - - delay: 00:00:02 + data: {} + - delay: + hours: 0 + minutes: 0 + seconds: 5 + milliseconds: 0 + - action: homeassistant.update_entity + target: + entity_id: camera.backyard_shed + - variables: + snapshot_filename: blink_shed_{{ now().strftime('%Y%m%d_%H%M%S') }}.jpg + - variables: + notification_id: blink_shed_{{ now().strftime('%Y%m%d_%H%M%S_%f') }} - action: camera.snapshot target: entity_id: camera.backyard_shed data: - filename: /media/blink_shed.jpg + filename: /media/{{ snapshot_filename }} - action: camera.snapshot target: entity_id: camera.backyard_shed data: - filename: /config/www/blink_shed.jpg - - delay: 00:00:02 + filename: /config/www/{{ snapshot_filename }} + - delay: + hours: 0 + minutes: 0 + seconds: 4 + milliseconds: 0 - action: ai_task.generate_data continue_on_error: true data: - task_name: Backyard Shed Camera Analysis + task_name: Blink Shed Camera Analysis entity_id: ai_task.google_ai_task instructions: Describe what you see in this image in brief. Focus on any people, objects, animals or activities. Text needs to be max 240 characters. attachments: - - media_content_id: media-source://media_source/local/blink_shed.jpg + - media_content_id: media-source://media_source/local/{{ snapshot_filename }} media_content_type: image/jpeg response_variable: ai_profile - action: notify.notify @@ -932,16 +1003,15 @@ message: '{{ ai_profile.data if ai_profile is defined and ''data'' in ai_profile else ''Motion detected, but the AI Task integration failed to return a response.'' }}' - - action: notify.persistent_notification + - action: persistent_notification.create data: title: Motion Detected - Backyard Shed message: '{{ ai_profile.data if ai_profile is defined and ''data'' in ai_profile else ''Motion detected, but the AI Task integration failed to return a response.'' }} - ![Snapshot](/local/blink_shed.jpg)' - data: - notification_id: backyard_shed_motion + ![Snapshot](/local/{{ snapshot_filename }})' + notification_id: '{{ notification_id }}' mode: queued max: 10 - id: '1783293479398' @@ -1115,7 +1185,7 @@ ![Snapshot](/local/blinkTree.jpg)' mode: queued max: 10 -- id: '1783469453396' +- id: '1783540959739' alias: Motion Front Door - AI Description description: Takes a snapshot when the Nest camera detects motion, a person, an animal, or a doorbell press, analyzes it with AI, and sends a mobile and persistent @@ -1169,18 +1239,33 @@ target: entity_id: camera.front data: {} - - delay: 00:00:02 + - delay: + hours: 0 + minutes: 0 + seconds: 5 + milliseconds: 0 + - action: homeassistant.update_entity + target: + entity_id: camera.front + - variables: + snapshot_filename: blink_Front_{{ now().strftime('%Y%m%d_%H%M%S') }}.jpg + - variables: + notification_id: blink_front_{{ now().strftime('%Y%m%d_%H%M%S_%f') }} - action: camera.snapshot target: entity_id: camera.front data: - filename: /media/blink_Front.jpg + filename: /media/{{ snapshot_filename }} - action: camera.snapshot target: entity_id: camera.front data: - filename: /config/www/blink_Front.jpg - - delay: 00:00:02 + filename: /config/www/{{ snapshot_filename }} + - delay: + hours: 0 + minutes: 0 + seconds: 4 + milliseconds: 0 - action: ai_task.generate_data continue_on_error: true data: @@ -1189,7 +1274,7 @@ instructions: Describe what you see in this image in brief. Focus on any people, objects, animals or activities. Text needs to be max 240 characters. attachments: - - media_content_id: media-source://media_source/local/blink_Front.jpg + - media_content_id: media-source://media_source/local/{{ snapshot_filename }} media_content_type: image/jpeg response_variable: ai_profile - action: notify.notify @@ -1206,8 +1291,148 @@ else ''Motion detected, but the AI Task integration failed to return a response.'' }} - ![Snapshot](/local/blink_Front.jpg)' + ![Snapshot](/local/{{ snapshot_filename }})' data: notification_id: nest_front_motion + enabled: false + - action: persistent_notification.create + metadata: {} + data: + message: '{{ ai_profile.data if ai_profile is defined and ''data'' in ai_profile + else ''Motion detected, but the AI Task integration failed to return a response.'' + }} ![Snapshot](/local/{{ snapshot_filename }})' + title: Motion Detected - Front Door + notification_id: '{{ notification_id }}' + mode: queued + max: 10 +- id: '1783541174963' + alias: Daily Snapshot Purge + description: Triggers the snapshot purge script every night at midnight. + triggers: + - trigger: time + at: 00:00:00 + conditions: [] + actions: + - action: script.purge_old_blink_snapshot + data: {} + mode: single +- id: '1783615071224' + alias: 'TEST: AI Camera Motion Detection OLLAMA' + description: Takes a snapshot when the Nest camera detects motion, a person, an + animal, or a doorbell press, analyzes it with AI, and sends a mobile and persistent + notification. + triggers: + - trigger: event + event_type: state_changed + event_data: + entity_id: event.front_door_front_door_motion + enabled: false + - trigger: state + entity_id: event.living_room_living_room_camera_motion + enabled: false + - trigger: state + entity_id: event.front_door_front_door_motion + enabled: false + - trigger: event.received + target: + entity_id: event.entryway_entryway_camera_motion + options: + event_type: + - camera_motion + - camera_person + - camera_sound + enabled: false + - trigger: event.received + target: + device_id: 290f56e5a655e3af82cbf3cf9fd22406 + options: + event_type: + - camera_motion + - camera_person + - camera_sound + - ring + - trigger: event.received + target: + device_id: 679d52e0d16cf48648d11dd024b961f8 + options: + event_type: + - camera_motion + - camera_sound + - camera_person + enabled: false + conditions: + - condition: template + value_template: '{{ trigger.event.data.new_state.attributes.event_type in [''motion'', + ''person'', ''animal'', ''chime''] }}' + enabled: false + actions: + - action: blink.trigger_camera + target: + entity_id: camera.front + data: {} + - delay: + hours: 0 + minutes: 0 + seconds: 10 + milliseconds: 0 + - action: homeassistant.update_entity + target: + entity_id: camera.front + - variables: + snapshot_filename: blink_Front_{{ now().strftime('%Y%m%d_%H%M%S') }}.jpg + - variables: + notification_id: blink_front_{{ now().strftime('%Y%m%d_%H%M%S_%f') }} + - action: camera.snapshot + target: + entity_id: camera.front + data: + filename: /media/{{ snapshot_filename }} + - action: camera.snapshot + target: + entity_id: camera.front + data: + filename: /config/www/{{ snapshot_filename }} + - delay: + hours: 0 + minutes: 0 + seconds: 4 + milliseconds: 0 + - action: ai_task.generate_data + continue_on_error: true + data: + task_name: Nest Front Camera Analysis + entity_id: ai_task.ollama_ai_task + instructions: Describe what you see in this image in brief. Focus on any people, + objects, animals or activities. Text needs to be max 240 characters. + attachments: + - media_content_id: media-source://media_source/local/{{ snapshot_filename }} + media_content_type: image/jpeg + response_variable: ai_profile + - action: notify.notify + continue_on_error: true + data: + title: Motion Detected - Front Door + message: '{{ ai_profile.data if ai_profile is defined and ''data'' in ai_profile + else ''Motion detected, but the AI Task integration failed to return a response.'' + }}' + - action: notify.persistent_notification + data: + title: Motion Detected - Front Door + message: '{{ ai_profile.data if ai_profile is defined and ''data'' in ai_profile + else ''Motion detected, but the AI Task integration failed to return a response.'' + }} + + ![Snapshot](/local/{{ snapshot_filename }})' + data: + notification_id: nest_front_motion + enabled: false + - action: persistent_notification.create + metadata: {} + data: + message: '{{ ai_profile.data if ai_profile is defined and ''data'' in ai_profile + else ''Motion detected, but the AI Task integration failed to return a response.'' + }} ![Snapshot](/local/{{ snapshot_filename }})' + title: Motion Detected - Front Door + notification_id: '{{ notification_id }}' mode: queued max: 10 diff --git a/custom_components/amazon_order_status/__init__.py b/custom_components/amazon_order_status/__init__.py new file mode 100644 index 0000000..7cdd915 --- /dev/null +++ b/custom_components/amazon_order_status/__init__.py @@ -0,0 +1,93 @@ +"""Amazon Order Status integration.""" + +import logging +from datetime import timedelta +import voluptuous as vol +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant, ServiceCall +from homeassistant.helpers import config_validation as cv + +from .const import DOMAIN, SERVICE_PURGE_ORDER, ATTR_ORDER_ID +from .coordinator import AmazonOrdersCoordinator + +_LOGGER = logging.getLogger(__name__) + +PLATFORMS = ["sensor"] +DEFAULT_UPDATE_INTERVAL = 5 # minutes + +PURGE_ORDER_SCHEMA = vol.Schema( + {vol.Optional(ATTR_ORDER_ID, default=""): cv.string} +) + + +async def _handle_purge_order(hass: HomeAssistant, call: ServiceCall) -> None: + """Remove a specific order from tracking.""" + order_id = (call.data.get(ATTR_ORDER_ID) or "").strip() + if not order_id: + _LOGGER.warning( + "purge_order called with empty order_id. " + "If using a dashboard button, call script.purge_amazon_order instead so the order ID is read when you tap." + ) + return + domain_data = hass.data.get(DOMAIN) or {} + removed = False + for key, value in domain_data.items(): + if isinstance(value, AmazonOrdersCoordinator): + if await value.async_purge_order(order_id): + removed = True + if not removed: + _LOGGER.warning("Order %s not found or already purged", order_id) + + +def _make_purge_order_handler(hass: HomeAssistant): + """Return an async service handler that closes over hass.""" + + async def handler(call: ServiceCall) -> None: + await _handle_purge_order(hass, call) + + return handler + + +async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: + """Set up Amazon Order Status from a config entry.""" + # Create the coordinator + coordinator = AmazonOrdersCoordinator(hass, entry) + await coordinator.async_config_entry_first_refresh() + + # Ensure DOMAIN dict exists + hass.data.setdefault(DOMAIN, {}) + + # Store coordinator under a fixed key for options_flow + hass.data[DOMAIN]["coordinator"] = coordinator + + # Also store by entry_id for platform setup + hass.data[DOMAIN][entry.entry_id] = coordinator + + # Register purge_order service (idempotent if multiple entries) + if not hass.services.has_service(DOMAIN, SERVICE_PURGE_ORDER): + hass.services.async_register( + DOMAIN, + SERVICE_PURGE_ORDER, + _make_purge_order_handler(hass), + schema=PURGE_ORDER_SCHEMA, + ) + + # Forward entry setups (sensors) + await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) + + return True + + +async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: + """Unload a config entry.""" + # Unload platforms + await hass.config_entries.async_unload_platforms(entry, PLATFORMS) + + # Remove coordinator references + if DOMAIN in hass.data: + if "coordinator" in hass.data[DOMAIN]: + hass.data[DOMAIN].pop("coordinator") + if entry.entry_id in hass.data[DOMAIN]: + hass.data[DOMAIN].pop(entry.entry_id) + + return True diff --git a/custom_components/amazon_order_status/__pycache__/__init__.cpython-314.pyc b/custom_components/amazon_order_status/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..47e6d500167b7d0aa07548d09348b6d4fad72451 GIT binary patch literal 5554 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 literal 0 HcmV?d00001 diff --git a/custom_components/amazon_order_status/__pycache__/config_flow.cpython-314.pyc b/custom_components/amazon_order_status/__pycache__/config_flow.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5993dffbcf960c39874e0170190d8e5452132c2d GIT binary patch literal 5152 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 UVRECfccroS&gF-QjE%GZ2hA#XX8-^I literal 0 HcmV?d00001 diff --git a/custom_components/amazon_order_status/__pycache__/const.cpython-314.pyc b/custom_components/amazon_order_status/__pycache__/const.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d0018ebeb98fac7f32a36a0b977452c3576b0975 GIT binary patch literal 765 zcmZuv-D(p-6rQwAy7}2OZ4xcgN@)ctg1z%XL>RMEUEJ)3la11=VaRUl>i)4iQR-D5 z!Pn5I30^I8RqzFbzJMp2hzicd;e6jY=Q|%W^Qf&i2%c|W?Dy3TLVhg4?^9VPw=Xc6 z6Cjd6MOI)#ZosD8ge|!RRau3atiiV222E;Emvv~!1~g?8TCxSY)S)fguyaCAJE|)p z@i~ckl6ii{b1CF3S5-d}L8zKRBvPLH*+)N9^%A5>CY3frE*6omv{dBzC!AG!nuH+_ zVu{@%RINy4AGpYQ<_k~ldwv+8i0>hmek=pr=!xrmz2Y(nal2|yMI0xRPm?(Ir&6_o z7_|bAifQcw(=WzfwoPEeY&G+hBKt5tr`QzKIaT`OLfZJ9MTaVGkC*5 zwf`_92VA9>c!E`%4%r%x=y?3r0YmMT)sbUa+_YU(pqAP#xgmwuoQ^p#YN*4KGMHuJ z3T7bbGTSvBn;Z0E{I`p9$1>1Gj{!Kq2h_G5m*cd}2Cmv$v8Ih{OoP*j`$~0}zRdyS zqY1oZ98KZ4PF)vPIX4Z}H`qCyST6s^=vQ*P{4DCp8D8gQaCJ7FjVEN~KcN@6T&DdT-t+x!Gi1+z2gPhEsmZp$lPx# literal 0 HcmV?d00001 diff --git a/custom_components/amazon_order_status/__pycache__/coordinator.cpython-314.pyc b/custom_components/amazon_order_status/__pycache__/coordinator.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a8e975941b0846972a76a4333644775302b7ad78 GIT binary patch literal 28083 zcmc(IdvF`andjg|0w6$uB=`hK4xb_@5!8cvQ4gEqL!?Af^pJ+^H6;WhKnWH_!UNC} zVXaqjvKuPviYdn_QM=w1z45N;T(-h&c`wSA_iQJrJKsL;2!RsdiCoqu*-EAA?uuH; z>p1`1{k|Ry0Md|TCwFySWKT~|cTZ3E_kI1ny0J0eY~&EWGdKA3&VG*jIo&A1DkoHT zZ>c!$0w-``?l>o?`c%E@u)3Pk>OM_a!>-z}mR)sW9j=c`Q%YXX-VF%`BbMm)~m%TUa``&)QoMF6b=`7qWYOUs10uY-4FdUvY0q zxP+yReWkr+;WCz1_mzjs(SBZEMXx<}z=d<{3>w`TD}YHk#o!kdH=^r@8fsYNIg%7qI2+wt$fe<=N=?DLOJ`TU+!elK2y3~g6nEbLTE=H96@{*F*65DI%I!;*f?J27#> zJ9e60-8nTm9yr-O85U=7TTI=1JV@`)=p!EJhS67gwfTVGI~@*;PfrX_O$X6=C*Ko`7^7I_(@9GxD2n>>-z-f`jAgS*1NL=9D+;R1;uX3CZ zc@FL|)hU&r64Zi5(6-V5>V8ENELj7SVZS)(ouICHLSa$TP?RJ3!_(sAZ!F4)@#pzL zjM1AMx|%aSC7$tyL-gWWX>aQo`_$I4=};J>Ha2x8h?0}xP^*{CkOy<(7tyviJRL&e z^b`eWB$LOJoFu=;BUYeA`VUcbf%}9jP}%NKv{<)Fm!(#AcNb4N_U)9Qkc)qOr|zzZ zue!k5@%2N>xUd3p)Rs&KxzQvzaVV)E)A5R3h01sdsyc2|t5hAzQBvt^4QdMNP1Mt5 z5Ht$X1XXyZ&3yL2-l*N`4aqi6*3fLZRYL}))%10g5k9&fGNp5sl%U(0{Ng&!tv=3W zzFo-K^+f8+j039Us-R}nqSSP&h1|^2%6J5|8Kb0Da*ykFy^XetsGn=v&}VA{@8W{G z(LCi{qXkOpXxs6(@=0Ue9eZyrw5e&+gDSZg$WFH}SPI?rE(8KlN!6T@&UdQp= zs7S^tLw)v^Na5 zi1}K=u1daha(|E(MFyHv7G7@d4e=#o=gfP z?!Xg90e+3d1#VSq(b;a>H^%K-qV_E@`?h6$*{!_%WlMD|k6+ljlGpG-QRyvnaok*W z-CVU?-MXZ?QQfw@qc3JYG^F0aiWRtKb3U>ZCyI(Mw_j?1{fRe5 zUmKlkj}>iQHf>E5+vhvJ_2fd`N^!$QadFG6_LjA1u4jJRw+_dw{H*R)UE{*D-`=xS zvr@P1#n9Z2`MPiIS+P`KD?mYW@hgEv?KSn^8n2Dq*xYfW>A*@!XUyD%4p<6aid>8= z6wXFsmioA*HEL;nOaBAY_f0X&zGeNsU*9s7ylPy|tGmakbT-LSw5q}NH=#Ow{0n?n z4fpz9MDNv9BmR-<09}4kQ_!_T^ONl=#J?5!S2Oaj6+!AaaWh2(6Jjw%rHGs=u?!cP zy0e*LWSK=SdZ5r|t!l#^4$+)`l`iv7ushL?GHYlv!4h7fyZb5aqN^g^}C~w%>1&6Fbw1^OQ5%a_qS+n>YQwGg6jG^F~7(Ynz@rUVCh#v-Y=w z(IktK6-J3lJ`_;9Q7A<7LrjEPbwG88#dGIY*>#~)zW*$+(iAdaJ;y3%2UbC4#?n8U zx#^G@jhS6 zz|>^R35IV)5nVJlraxxel?(Psed->tM!Om`%q}jaHC-Uf%Q!8nFUShcz z2RU$LaHMxw(y@w?cE;}&#oZ{D39tE{z!`7Qqwt0z4J#YkEl2=t^Q|w9UmTwso*kVp zcy;fh`g{5}^-Ej++H}LdeYs-ClJ}bWo!lShF3l|Gbu4Q;*l0(pLepboV6(yLPR#IZ z_3`mDSS)x3t5Pn5Q@<}#e%8O?SwAoO$NYh3{h4JV4MD71KtrsntR^_;DR88LF_az; zOiaj4MM|>gOS$Y#exH;ZIu!^8DKRW3BG#$tFdIY&2Y9PE6R{pymm?XH&rr|MB^UGi z*1$QepsvUupXjut zC0_iYNHBt;A<$KZ1m!Bn9S+faOkP4trFO zX%BHekUe6A+^TI5EFiDx1+|qUaz>#C3~Gv{MGFq@Fj&AU$k_un16{QPRxr?6>na3U zso$;gwNeYMz_UqWdRP#2!>S>|)^$P15poqaJnM6vpjVz}GMvI1_A^NMNn@}sDBlP6 zImMv6HEFg|X<6yJ534NLdCib{T|>AP49b@ds75qFty?P?GkfG#XWj{UnRh`Q`j=wh z(`~zTLn#J3ohz7>Hz`-l8<&ki7R>IH5OWsrAf5zEoxkfW7=9o7lHAmn?WFsRQOFgF zGX;PLj0qSBjLEw4Sx3kuSdF0@A_D?+P z54ns+@W?%2H732#M(}3?;ZuAl2p%0ojR(<#WPQpX@`pC@Nh-k_3n{IQ_(Md%h+yzd z)059kPlf$H=O%O`Fm{SH4VGa5T?VOq8lMs3y&-->-{iC4dVE+#e1Y)*s$xwEZ*cL$ z=qFKGrV8Po4S0Ey@6X^H`7wO|2|phe{m>lvsAV+dMMdZnyc4K8#h>-_C#C}vJ`5EN z2qJWy_n-4(^ysVG`H_x;O2=#EPS=`^^cose7gcF;ZlbnPagsml4amfqni2gW=ov7U za^qnd`moeQlb=-DM zK=r0-P$sb&N$uJ!sm8=XlnqgPjr;|fp)>3~>7VqU3yS-t8jn2X9{D?5dncx#4+`yf zrHT*<4UxF?>tCS@%f`mnbn{#0a=x+W+qzFfTI7GFz^005_$KE_kEE)VRHG5~DE-$; zI&Ww!5QylN!HTHO#^30s!{aTxq#PNJB=wQQj17(GX?g*Xe8j{<{{?86p7gczk*~V= zPGS|=EF?jMfQw3$ zD&uXN2tJ|h0t^JbfZ2(_X^6vA*p&g3E=ezUx4UalY{WM^^CgXUaz-kgo(y|Wp7i@X z%EX4)*GPKLr2ni3&m?0Y1Yr^gHs+Uf3?ii*Sv4nV2~?yU|0F5uqyhy=L&c7Hwy?-s{O58fy^_&x;Nf!Ulye&I`JE}r@0 zsaee}=eDKJw~OP>N3J^`nX9|pe5rZ<=t^P3yTh}&2}{X*#SKf{!uSo#rp0G(Shmk< z6MEB2hKq)|`pX+HZJa+DD{NfRZ%Ek6;pIA9M8b5IC`hjC}^>gC4nl86qYF*f{xO=5=`^wn(^2yV&v5DEvL}AJ0 z=9ioA=5V%(Ki#&fQy1`eHQJ(lh>Pa@RU=oz&uYJ6yp3+;UCf*7xv96yd*6 z(gv2+3&v6|Y&d2V@{nhuJY{VU=OH(xRZr!bkekx4r*h56EkFx}Yg))hZV_^AYjQ0@ zG4h}fM=!0U6Bo)@x5MZDF-q@eG6;SkLqTcyj=9(E_g zQxb+yoa3k)xHsG#0e7<(eC<)|Bzr*7Q9jLIj;44^w`w#csg3HD!iqftoJ6W5<4{v& z-RhxyrF8n5l|SQ-r+8MhM}1`B^S6*zR|+bHV?s+Qwd)sXiIhJq2x_IJpvJ99@qI`z zjy4Owq+ms=EO^m}l^p=)qNk~m612EWakiho-+~Th`DE8KE?LK0cU-4@n{tJ+yH=?- z4DR|%eUR%_qqIb^AmofXl{7f@Tt(?5=ywuUAb>~I0tXFJSxP>{S{4S#V>N{gJrnAY zfC6ku9F#26%o-$XKf!!Oijo+}P?sNO))KKE?ZOtMrDa+?PdCNlG%n(^6p>INS%ycB z2ptEzJ??H{xbMiIl&54I?tW6r!2$*Ylawo4VM367<<(u%ob&@1sTmq=$?Q4f6;FG- zA@ten6UmY)(mX<4z;pmIzaZ|R{3*)Ug{Fgk5z8|^ArSU>@QVH;2M=}&OnL0gp*4A8 zJfpY7Jtgf;_+C#^Ni7*Xo-wGgLLN_uP^YmGN@AJ262C?@l9cH)6b-aMelep1|B9km zV6l9?Xh;-SylA{tVxRANz4fgRio(Ms1!>!a^B#43B~NyY7glFOBsD&qyU(SlkifR}_=!7k{M zU2WG&-f{fU@lMs>Rn7NY?Z49h>frlFsY-cbV=G=~SLshjgJ`e_nU8xB|BPcL zHJVljTO6WA54)s0fwiK*=CdK4$vV+V_j(H}gygn(vzhijB)7jhIdDsK|lIS`NcJUx?Z+@k4^P{n%j%8EF2bQ8cxm@AqPeV2|^FmcerD{RdVb{KvhtyxU zB3iTT|8@{|1Wi8_!d^z96olz@Shf)@K`VvJXCaK{7!YQ@+YI3U9Ux3~UkE$MRxDLE z%~2Y{S~+Faz*?1p#O50dZfV7OK_`L7XC~e4f0nI^zW~Vk% z*AM9BL9oeL0m{@QpGSZT!FfuA(}Qa;Qbnckv;pEeEgQbIY+?k>I+o|ihxB23V=mO{dGqJ;x%YQvk1!eg}7&V!9}g4h3<19)vG9; z;*4{MGe)#jwn~?4K6WSL77e@-lDK8KyMUZ8id$*g3d4M^(q#IoQ1>+djFln7I--

`SriBRxKFgd|Q-ni}5>dSu5tdh&@=QI7IpRg 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 KJ4XpNBL4?j!jaVg literal 0 HcmV?d00001 diff --git a/custom_components/amazon_order_status/__pycache__/options_flow.cpython-314.pyc b/custom_components/amazon_order_status/__pycache__/options_flow.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..42cc33d6db19d0d5984063fe149965fa990c16d1 GIT binary patch literal 3645 zcmb_f+fN(W89#IJ1z*6}2E1Mt8w@mNsa-Z?11XSAHl$cI;7%%6Y6+uRdkE8xXS_4V zMDT=qQPZb(_a&RBq;E;phdlDwKOq*R_MUFlO5Lj3H@Bc>tG@I*G(&oey0)d<6=e+@ifpa{soy5; zNUBn@fN7SvZ>-g9^AK}O81WMxp)X$D2p%3#*^RitUoRCY-~6eUg5;ZPPul73ytGM&&M zXgA|9eYuZbBE~iKcRKxgvp#XPHgVPZIEGVH>15557|B|uX*6<9&d1wy zX9v}SEAVG#liM6|vMqQW+cqX0∈u*IvI;7k`c}e$(}T*X24#mrLk*t*)uIKhCbh zuW5(YULnTqJ91_$+vkG&4BZ(=R+e|}e8mMfWyYbmSHV|s34SLVDRhZbm~>!o`j(_g zcjYABmZ4TFSdrAEiRDUC-?C_(m5vs0k4+%{q7G$3(Il)JBvz7DWk)vTl4!^nN(q#E zu_W!9q_0|mqAtV3i)8~!JPDK~<42-o0#GUuC~L%p6|BmH2b@GTl;ka`s^aewo*D!I z4>d?sO2khgqFLOQ%ToFc;DEYj(D%TgVI=OBF2Zj^&1)6Luw?FPMbS2bb{)IMD8+Jj zWo*#rm&95SQ^wu451e9t<-uT^q0<+GHetl(q0*GHR1vpy6>2H5?I?oN5Dd!>!tLlP zao@JQAznfLu&O`+30vGDfr@TIE_STA5zhy@uF8@|yz5rq0a4^kY>+;;Wiaz7?%f#l)}4_e48q#+z_zhpH7s(+!l#$s~+ciF8C-0f*?5>DN|D+W-e0 z0%_*Ip@4k>W$@4bfkXf3=kbwGa6K_oOU%?0^R>kMVf@Pd)ka{b9vG7h?gX*H-lh+|nRt|bn0}Obn5oC7 zYw_vd7M=-*@ws|@p%z~_xN{g^y}$aWzIY?@^=I*;$Tu6&L_IoJi_SG-W6x8IFJen4 z96K-wDx(umd`FRYEWo8&^pXXbeG$9#3NZHg`$v(i1$eg>eHQ?amtMr)vCdCG!1&|6 zqsUCBfTPsK7qQuv056Kh>XE5hWa?S?VCs2f>M*kWJg^L!BSZD@cr83$4^P*^)Av0f zD?IQZ{&D>CP~<`2<3J;tX$+?xtv+0Re&PD>t{)D6>%_(NhpEcJ2UkD3`k4cpcmVIJrY}|N zOEseLMr@?%LZR_v#D#oK#P#_8WnHNs=c2hm#)#7U7J(_?;)5!dO+fZ{ zw7NxERYft)7*+#E`>FS=+ilQx%9^a!a2US6{5jmzPx<+mJoKVX+K|3px7VL b{NK>qC+-^z<9obRPc7C`i~mIQ%aZgT7v~(o literal 0 HcmV?d00001 diff --git a/custom_components/amazon_order_status/config_flow.py b/custom_components/amazon_order_status/config_flow.py new file mode 100644 index 0000000..5bc75b2 --- /dev/null +++ b/custom_components/amazon_order_status/config_flow.py @@ -0,0 +1,101 @@ +"""Config flow for Amazon Order Status integration.""" + +from homeassistant import config_entries +import voluptuous as vol +import imaplib +import socket + +from .const import DOMAIN, CONF_IMAP_FOLDER +from .options_flow import AmazonOrderStatusOptionsFlow + + +def _select_folder_quoted(imap, folder: str) -> None: + """Select IMAP mailbox using quoted name (IMAP4rev2-compatible).""" + quoted = '"' + folder.replace("\\", "\\\\").replace('"', '\\"') + '"' + imap._simple_command("SELECT", quoted.encode("utf-8")) + + +async def validate_imap_config(hass, host, port, username, password, folder=None): + """Test connection to IMAP server.""" + def _validate(): + try: + imap = imaplib.IMAP4_SSL(host, port) + imap.login(username, password) + folder_to_test = folder.strip() if folder and folder.strip() else "INBOX" + _select_folder_quoted(imap, folder_to_test) + imap.logout() + return None + except imaplib.IMAP4.error: + return "invalid_auth" + except (OSError, socket.gaierror): + return "cannot_connect" + + return await hass.async_add_executor_job(_validate) + + +class AmazonOrdersConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): + """Handle a config flow for Amazon Orders.""" + + VERSION = 1 + CONNECTION_CLASS = config_entries.CONN_CLASS_CLOUD_POLL + + async def async_step_user(self, user_input=None): + """Handle the initial step of the config flow.""" + errors = {} + + if user_input is not None: + # Validate IMAP connection + error = await validate_imap_config( + self.hass, + user_input["imap_server"], + user_input.get("imap_port", 993), + user_input["username"], + user_input["password"], + user_input.get(CONF_IMAP_FOLDER), + ) + + if error is None: + # Create config entry with initial options including mark_as_read + return self.async_create_entry( + title="Amazon Orders", + data={ + "email": user_input["email"], + "imap_server": user_input["imap_server"], + "username": user_input["username"], + "password": user_input["password"], + "imap_port": user_input.get("imap_port", 993), + }, + options={ + "update_interval": user_input.get("poll_interval", 5), + "delivered_retention_days": 30, + "mark_as_read": user_input.get("mark_as_read", True), + CONF_IMAP_FOLDER: user_input.get(CONF_IMAP_FOLDER, ""), + }, + ) + + errors["base"] = error + + # Show the form with mark_as_read option + schema = vol.Schema( + { + vol.Required("email"): str, + vol.Required("imap_server"): str, + vol.Required("username"): str, + vol.Required("password"): str, + vol.Optional("imap_port", default=993): int, + vol.Optional("poll_interval", default=5): int, + vol.Optional("mark_as_read", default=True): bool, + vol.Optional(CONF_IMAP_FOLDER, default=""): str, + } + ) + + return self.async_show_form( + step_id="user", + data_schema=schema, + errors=errors, + ) + + @staticmethod + def async_get_options_flow(config_entry): + """Return the options flow handler for this config entry.""" + return AmazonOrderStatusOptionsFlow(config_entry) diff --git a/custom_components/amazon_order_status/const.py b/custom_components/amazon_order_status/const.py new file mode 100644 index 0000000..de7c068 --- /dev/null +++ b/custom_components/amazon_order_status/const.py @@ -0,0 +1,18 @@ +DOMAIN = "amazon_order_status" + +CONF_EMAIL = "email" +CONF_IMAP_SERVER = "imap_server" +CONF_IMAP_PORT = "imap_port" +CONF_USERNAME = "username" +CONF_PASSWORD = "password" +CONF_POLL_INTERVAL = "poll_interval" +CONF_MARK_AS_READ = "mark_as_read" +CONF_DELIVERED_RETENTION_DAYS = "delivered_retention_days" +CONF_IMAP_FOLDER = "imap_folder" +ERROR_CANNOT_CONNECT = "cannot_connect" +ERROR_INVALID_AUTH = "invalid_auth" + +SERVICE_PURGE_ORDER = "purge_order" +ATTR_ORDER_ID = "order_id" + +DEFAULT_POLL_INTERVAL = 1800 # 30 minutes diff --git a/custom_components/amazon_order_status/coordinator.py b/custom_components/amazon_order_status/coordinator.py new file mode 100644 index 0000000..20d57cf --- /dev/null +++ b/custom_components/amazon_order_status/coordinator.py @@ -0,0 +1,488 @@ +"""Amazon Orders Data Coordinator.""" + +from __future__ import annotations + +import imaplib +import logging +import re +from datetime import datetime, timedelta, timezone +import email.utils +from email import message_from_bytes +from email.header import decode_header +from typing import Dict + +from homeassistant.core import HomeAssistant, callback +from homeassistant.config_entries import ConfigEntry +from homeassistant.helpers.update_coordinator import DataUpdateCoordinator +from homeassistant.helpers.storage import Store +import html +from bs4 import BeautifulSoup + +from .const import CONF_MARK_AS_READ, CONF_IMAP_FOLDER + +_LOGGER = logging.getLogger(__name__) + + +def _parse_internaldate(internaldate_str: str) -> datetime | None: + """Parse IMAP INTERNALDATE string to timezone-aware UTC datetime.""" + try: + # Format: "08-Feb-2025 18:30:00 +0000" or "08-Feb-2025 10:30:00 -0800" + internaldate_str = internaldate_str.strip() + if len(internaldate_str) < 26: + return None + dt = datetime.strptime(internaldate_str[:20], "%d-%b-%Y %H:%M:%S") + tz_str = internaldate_str[20:].strip() + if not tz_str: + return dt.replace(tzinfo=timezone.utc) + sign = -1 if tz_str[0] == "-" else 1 + hours = int(tz_str[1:3]) + mins = int(tz_str[3:5]) if len(tz_str) >= 5 else 0 + tz = timezone(timedelta(minutes=sign * (hours * 60 + mins))) + return dt.replace(tzinfo=tz).astimezone(timezone.utc) + except (ValueError, IndexError): + return None + + +def _to_utc(dt: datetime) -> datetime: + """Normalize a datetime to UTC for comparison.""" + if dt.tzinfo is None: + return dt.replace(tzinfo=timezone.utc) + return dt.astimezone(timezone.utc) +LAST_CHECK_KEY = "last_check" +STORAGE_VERSION = 1 +STORAGE_KEY = "amazon_order_status" +ORDERS_KEY = "orders" + +ORDER_REGEX = re.compile( + r"(?:Order|Purchase)\s*(?:#|number|ID|No\.?)?\s*[:#]?\s*" + r"([0-9]{3}-[0-9]{7}-[0-9]{7}|[0-9\-]{10,})", + re.IGNORECASE, +) + +# IMAP INTERNALDATE format: "08-Feb-2025 18:30:00 +0000" +INTERNALDATE_RE = re.compile(r'INTERNALDATE\s+"([^"]+)"', re.IGNORECASE) + +# English month abbreviations for IMAP date (RFC 3501); avoid locale-dependent strftime +_IMAP_MONTHS = ("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec") + + +def _imap_date_str(dt: datetime) -> str: + """Return date in IMAP format dd-Mon-yyyy (English month) for SEARCH SINCE.""" + return f"{dt.day:02d}-{_IMAP_MONTHS[dt.month - 1]}-{dt.year}" + +STATUS_MAP = { + "successfully placed your order": "Ordered", + "we've received your order": "Ordered", + "preparing your automatic refill order": "Ordered", + "automatic refill order": "Ordered", + "ordered": "Ordered", + "shipped": "Shipped", + "out for delivery": "Out for delivery", + "delivered": "Delivered", +} + +def _select_folder(mail: imaplib.IMAP4, folder: str) -> None: + """Select an IMAP mailbox. Use standard select() when safe; otherwise send SELECT line ourselves. + + For names with space or parentheses, imaplib sends SELECT Test folder (unquoted), which + FastMail rejects as 'Invalid modifier list'. Sending bytes via _command can be treated + as a literal. So we build and send the exact line: TAG SELECT "folder"\r\n via mail.send(), + then wait for the response and set state. + """ + if any(c in folder for c in " ()"): + mail.untagged_responses = {} + quoted = '"' + folder.replace("\\", "\\\\").replace('"', '\\"') + '"' + tag = mail._new_tag() + tag_str = tag.decode("ascii") if isinstance(tag, bytes) else tag + line = tag_str + " SELECT " + quoted + "\r\n" + mail.send(line.encode("utf-8")) + typ, data = mail._command_complete("SELECT", tag) + if typ != "OK": + msg = data[-1].decode("utf-8", "replace") if data and isinstance(data[-1], bytes) else str(data) + raise mail.error( + "Mailbox %r not found: %s. Check the folder name in integration options " + "(case-sensitive). Use INBOX for the main inbox, or try a path like INBOX.Test folder." + % (folder, msg) + ) + mail.state = "SELECTED" + else: + mail.select(folder) + + +class AmazonOrdersCoordinator(DataUpdateCoordinator): + """Coordinator to fetch and track Amazon orders via email.""" + + def __init__(self, hass: HomeAssistant, entry: ConfigEntry): + self.hass = hass + self.entry = entry + self._store = Store(hass, STORAGE_VERSION, STORAGE_KEY) + self._orders: Dict[str, dict] = {} + self.delivered_retention_days = entry.options.get("delivered_retention_days", 7) + self._mark_as_read = entry.options.get(CONF_MARK_AS_READ, False) + # Get IMAP folder from options, default to "INBOX" if empty or not set + folder = entry.options.get(CONF_IMAP_FOLDER, "") + self._imap_folder = folder.strip() if folder and folder.strip() else "INBOX" + self.last_check: datetime | None = None + + # Determine update interval from options or config entry, default 5 min + interval_minutes = entry.options.get( + "update_interval", entry.data.get("update_interval", 5) + ) + + super().__init__( + hass, + _LOGGER, + name="Amazon Order Status", + update_interval=timedelta(minutes=interval_minutes), + ) + + """ Timestamp storage/retrieval functions to reduce email check time """ + async def async_load_last_check(self) -> datetime | None: + stored = await self._store.async_load() + if stored and LAST_CHECK_KEY in stored: + return datetime.fromisoformat(stored[LAST_CHECK_KEY]) + return None + + async def async_load_stored_orders(self) -> None: + """Load persisted orders from storage.""" + stored = await self._store.async_load() + if stored: + self._orders = stored.get(ORDERS_KEY, {}) + _LOGGER.debug("Loaded %d stored Amazon orders", len(self._orders)) + else: + self._orders = {} + _LOGGER.debug("No stored Amazon orders found") + + async def async_save_state(self, last_check: datetime) -> None: + await self._store.async_save( + { + LAST_CHECK_KEY: last_check.isoformat(), + ORDERS_KEY: self._orders, + } + ) + + async def _async_update_data(self): + _LOGGER.debug("Coordinator update triggered at %s", datetime.now(timezone.utc)) + + if not self._orders: + await self.async_load_stored_orders() + + last_check = await self.async_load_last_check() + now = datetime.now(timezone.utc) + self.last_check = now + + await self.hass.async_add_executor_job( + self._fetch_and_parse_emails, + last_check, + now, + ) + + # Purge old delivered orders + self._purge_old_delivered_orders(now) + + await self.async_save_state(now) + + # Include order_id in each item so sensors and services can use it + return [{**v, "order_id": k} for k, v in self._orders.items()] + + @callback + def async_update_interval(self, minutes: int): + """Dynamically update the coordinator's refresh interval.""" + self.update_interval = timedelta(minutes=minutes) + _LOGGER.debug("Coordinator update interval set to %d minutes", minutes) + self.hass.async_create_task(self.async_refresh()) + + @callback + def async_set_retention_days(self, days: int): + """Update delivered retention days and immediately purge old delivered orders.""" + self.delivered_retention_days = days + _LOGGER.debug("Delivered retention days updated to %d", days) + self._purge_old_delivered_orders(datetime.now(timezone.utc)) + + @callback + def async_set_mark_as_read(self, mark_as_read: bool): + """Enable or disable marking emails as read.""" + self._mark_as_read = mark_as_read + _LOGGER.debug("Mark as read option updated: %s", mark_as_read) + + # Update the config entry safely + new_options = dict(self.entry.options) + new_options[CONF_MARK_AS_READ] = mark_as_read + self.hass.config_entries.async_update_entry(self.entry, options=new_options) + + @callback + def async_set_imap_folder(self, folder: str): + """Update the IMAP folder to search.""" + folder_clean = folder.strip() if folder and folder.strip() else "INBOX" + self._imap_folder = folder_clean + _LOGGER.debug("IMAP folder updated to: %s", self._imap_folder) + + # Update the config entry safely + new_options = dict(self.entry.options) + new_options[CONF_IMAP_FOLDER] = folder + self.hass.config_entries.async_update_entry(self.entry, options=new_options) + + @callback + def _purge_old_delivered_orders(self, now: datetime): + """Remove delivered orders older than retention period.""" + if not self._orders: + return + + retention_cutoff = now - timedelta(days=self.delivered_retention_days) + to_remove = [ + order_id + for order_id, order in self._orders.items() + if order.get("status") == "Delivered" + and datetime.fromisoformat(order.get("updated")) < retention_cutoff + ] + + for order_id in to_remove: + _LOGGER.debug( + "Purging delivered order %s (older than %d days)", + order_id, + self.delivered_retention_days, + ) + self._orders.pop(order_id, None) + + async def async_purge_order(self, order_id: str) -> bool: + """Remove a specific order from tracking and persist state. Returns True if removed.""" + if order_id not in self._orders: + return False + self._orders.pop(order_id, None) + _LOGGER.debug("Purged order %s by user request", order_id) + now = self.last_check or datetime.now(timezone.utc) + await self.async_save_state(now) + self.async_set_updated_data( + [{**v, "order_id": k} for k, v in self._orders.items()] + ) + return True + + def _fetch_and_parse_emails(self, last_check: datetime | None, now: datetime): + """Connect to IMAP and parse Amazon emails.""" + email_addr = self.entry.data["email"] + password = self.entry.data["password"] + imap_server = self.entry.data["imap_server"] + mark_as_read = self._mark_as_read + + _LOGGER.debug("Connecting to IMAP server %s as %s", imap_server, email_addr) + + mail = imaplib.IMAP4_SSL(imap_server) + mail.login(email_addr, password) + # Send SELECT with mailbox as a quoted string so IMAP4rev2 servers (e.g. FastMail) + # do not misparse the command as having an invalid modifier list (RFC 9051). + _select_folder(mail, self._imap_folder) + _LOGGER.debug("Selected IMAP folder: %s", self._imap_folder) + + if last_check: + since = last_check + _LOGGER.debug("Checking emails since last run: %s", since) + else: + since = now - timedelta(days=14) + _LOGGER.debug("First run: checking last 14 days") + + since_utc = _to_utc(since) + # IMAP SINCE is interpreted in the server's timezone (e.g. Gmail uses PST), so + # using the UTC date can ask for "future" emails and return 0. Use one day + # earlier so we always fetch recent emails; we filter by since_utc in Python. + since_date_imap = _imap_date_str(since_utc - timedelta(days=1)) + # No charset for date-only criterion; some servers reject CHARSET with SINCE + typ, data = mail.search(None, f'(SINCE "{since_date_imap}")') + + if typ != "OK": + _LOGGER.error("IMAP search failed") + mail.logout() + return + + email_nums = data[0].split() + _LOGGER.debug( + "Found %d emails since %s (processing all; applying updates when email is newer than stored)", + len(email_nums), + since_date_imap, + ) + + for num in email_nums: + typ, msg_data = mail.fetch(num, "(BODY.PEEK[] INTERNALDATE)") + if typ != "OK" or not msg_data or not msg_data[0]: + _LOGGER.warning("Failed to fetch email %s", num) + continue + + # Prefer INTERNALDATE (when mailbox received the message) over Date header + raw_response = msg_data[0][0] + if isinstance(raw_response, bytes): + raw_response = raw_response.decode(errors="ignore") + internaldate_utc = None + internaldate_match = INTERNALDATE_RE.search(raw_response) + if internaldate_match: + internaldate_utc = _parse_internaldate(internaldate_match.group(1)) + + msg = message_from_bytes(msg_data[0][1]) + msg_date = msg.get("Date") + msg_datetime = None + if msg_date: + msg_datetime = email.utils.parsedate_to_datetime(msg_date) + if msg_datetime.tzinfo is None: + msg_datetime = msg_datetime.replace(tzinfo=timezone.utc) + else: + msg_datetime = msg_datetime.astimezone(timezone.utc) + + received_utc = internaldate_utc if internaldate_utc is not None else msg_datetime + if received_utc is None: + _LOGGER.debug("Email %s: no INTERNALDATE or Date header, skipping", num) + continue + + # Ignore emails that arrived before our last check (avoids re-adding purged orders) + if last_check is not None and received_utc < since_utc: + _LOGGER.debug( + "Email %s: received %s before last check %s, skipping", + num, + received_utc, + since_utc, + ) + continue + + subject = self._decode_header(msg.get("Subject", "")) + subject_lower = subject.lower() + + status = self._status_from_subject(subject_lower) + if not status: + _LOGGER.debug( + "Email %s: subject not recognized as order status, skipping: %s", + num, + subject[:80], + ) + continue + + body_text = self._extract_text(msg) + html_body = self._extract_html(msg) + + # Collect order IDs from both plain text and HTML; many "shipped" emails + # put the order number only in the HTML part, so we must check both. + order_ids = list( + dict.fromkeys( + ORDER_REGEX.findall(body_text) + + (ORDER_REGEX.findall(html_body) if html_body else []) + ) + ) + if not order_ids: + _LOGGER.debug( + "No order numbers found in email (subject: %s). " + "Checked plain text (%d chars) and HTML (%d chars).", + subject, + len(body_text), + len(html_body) if html_body else 0, + ) + continue + + tracking_url = self._extract_tracking_url(html_body) if html_body else None + + updated_ts = (msg_datetime if msg_datetime is not None else received_utc).isoformat() + did_update = False + for order_id in order_ids: + # Only overwrite if we don't have this order or this email is newer than stored + existing = self._orders.get(order_id) + if existing: + try: + existing_updated = _to_utc( + datetime.fromisoformat(existing["updated"]) + ) + if received_utc < existing_updated: + _LOGGER.debug( + "Order %s: skipping (email %s older than stored)", + order_id, + received_utc, + ) + continue + except (ValueError, TypeError): + pass + + self._orders[order_id] = { + "status": status, + "subject": subject, + "updated": updated_ts, + "tracking_url": tracking_url, + } + did_update = True + _LOGGER.debug( + "Order %s → %s (%s) [tracking: %s]", + order_id, + status, + subject, + tracking_url, + ) + + if mark_as_read: + _LOGGER.debug("Marking email %s as read (order email processed)", num) + mail.store(num, "+FLAGS", "\\Seen") + + mail.logout() + + def _status_from_subject(self, subject: str) -> str | None: + """Determine order status from email subject.""" + for key, value in STATUS_MAP.items(): + if key in subject: + return value + return None + + def _decode_header(self, value: str) -> str: + """Decode email headers safely.""" + parts = decode_header(value) + decoded = "" + for text, encoding in parts: + if isinstance(text, bytes): + decoded += text.decode(encoding or "utf-8", errors="ignore") + else: + decoded += text + return decoded + + def _extract_text(self, msg) -> str: + """Extract flattened text from email.""" + if msg.is_multipart(): + for part in msg.walk(): + if part.get_content_type() in ("text/plain", "text/html"): + payload = part.get_payload(decode=True) + if payload: + return payload.decode(errors="ignore") + else: + payload = msg.get_payload(decode=True) + if payload: + return payload.decode(errors="ignore") + return "" + + def _extract_html(self, msg) -> str: + """Extract HTML body from email.""" + if msg.is_multipart(): + for part in msg.walk(): + if part.get_content_type() == "text/html": + payload = part.get_payload(decode=True) + if payload: + return payload.decode(errors="ignore") + else: + if msg.get_content_type() == "text/html": + payload = msg.get_payload(decode=True) + if payload: + return payload.decode(errors="ignore") + return "" + + def _extract_tracking_url(self, html_body: str) -> str | None: + """Extract Amazon tracking URL or order link from email HTML.""" + soup = BeautifulSoup(html_body, "html.parser") + + for link in soup.find_all("a", href=True): + text = link.get_text(" ", strip=True).lower() + href = html.unescape(link["href"]) + + # Case 1: Tracking links + if "track package" in text or "progress-tracker" in href: + match = re.search( + r"https://www\.amazon\.com/progress-tracker/[^&\"]+", + href, + ) + if match: + return match.group(0) + return href + + # Case 2: Order management links + if "your-orders" in href and ("view" in text or "edit order" in text): + return href + + return None diff --git a/custom_components/amazon_order_status/manifest.json b/custom_components/amazon_order_status/manifest.json new file mode 100644 index 0000000..7d0f8a5 --- /dev/null +++ b/custom_components/amazon_order_status/manifest.json @@ -0,0 +1,12 @@ +{ + "domain": "amazon_order_status", + "name": "Amazon Order Status", + "codeowners": ["@koconnorgit"], + "config_flow": true, + "documentation": "https://github.com/koconnorgit/ha-amazon-order-status", + "iot_class": "local_polling", + "issue_tracker": "https://github.com/koconnorgit/ha-amazon-order-status/issues", + "requirements": ["beautifulsoup4"], + "version": "1.4.5" +} + diff --git a/custom_components/amazon_order_status/options_flow.py b/custom_components/amazon_order_status/options_flow.py new file mode 100644 index 0000000..6e1fe5e --- /dev/null +++ b/custom_components/amazon_order_status/options_flow.py @@ -0,0 +1,78 @@ +"""Options flow for Amazon Order Status integration.""" + +from homeassistant import config_entries +import voluptuous as vol +from homeassistant.helpers import config_validation as cv + +from .const import DOMAIN, CONF_IMAP_FOLDER + + +class AmazonOrderStatusOptionsFlow(config_entries.OptionsFlow): + """Handle an options flow for Amazon Order Status.""" + + def __init__(self, config_entry: config_entries.ConfigEntry): + self._config_entry = config_entry + + async def async_step_init(self, user_input=None): + """Manage the initial step of the options flow.""" + if user_input is not None: + # Merge new options with existing ones + new_options = dict(self._config_entry.options) + new_options.update(user_input) + + # Update the config entry + self.hass.config_entries.async_update_entry( + self._config_entry, options=new_options + ) + + # Apply updates to the coordinator if it exists + coordinator = self.hass.data.get(DOMAIN, {}).get("coordinator") + if coordinator: + if "delivered_retention_days" in user_input: + coordinator.async_set_retention_days( + user_input["delivered_retention_days"] + ) + if "update_interval" in user_input: + coordinator.async_update_interval( + user_input["update_interval"] + ) + if "mark_as_read" in user_input: + coordinator.async_set_mark_as_read( + user_input["mark_as_read"] + ) + if CONF_IMAP_FOLDER in user_input: + coordinator.async_set_imap_folder( + user_input[CONF_IMAP_FOLDER] + ) + + return self.async_create_entry(title="", data=user_input) + + # Current options to use as defaults + options = self._config_entry.options + + # Standard vol.Schema + schema = vol.Schema( + { + vol.Required( + "delivered_retention_days", + default=options.get("delivered_retention_days", 30), + ): cv.positive_int, + vol.Required( + "update_interval", + default=options.get("update_interval", 5), + ): cv.positive_int, + vol.Required( + "mark_as_read", + default=options.get("mark_as_read", True), + ): cv.boolean, + vol.Optional( + CONF_IMAP_FOLDER, + default=options.get(CONF_IMAP_FOLDER, ""), + ): str, + } + ) + + return self.async_show_form( + step_id="init", + data_schema=schema, + ) diff --git a/custom_components/amazon_order_status/purge_script_example.yaml b/custom_components/amazon_order_status/purge_script_example.yaml new file mode 100644 index 0000000..8a2287c --- /dev/null +++ b/custom_components/amazon_order_status/purge_script_example.yaml @@ -0,0 +1,13 @@ +# Copy this script into Home Assistant so the Purge order button works. +# +# Settings → Automations & scenes → Scripts → Add script → (paste in YAML mode) +# +# IMPORTANT: Use "data_template" so the order_id is read when you tap the button. +# Using "data" would pass the literal template string and the order would not be found. +# +purge_amazon_order: + alias: Purge Amazon order + sequence: + - service: amazon_order_status.purge_order + data_template: + order_id: "{{ states('input_text.amazon_order_purge_id') }}" diff --git a/custom_components/amazon_order_status/sensor.py b/custom_components/amazon_order_status/sensor.py new file mode 100644 index 0000000..1d7bbb7 --- /dev/null +++ b/custom_components/amazon_order_status/sensor.py @@ -0,0 +1,95 @@ +"""Amazon Orders sensors.""" + +import logging +from homeassistant.helpers.entity import Entity +from homeassistant.helpers.update_coordinator import CoordinatorEntity +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant +from datetime import datetime +from homeassistant.components.sensor import SensorEntity +from .coordinator import AmazonOrdersCoordinator +from homeassistant.util.dt import as_local + +_LOGGER = logging.getLogger(__name__) + +STATUSES = [ + "Ordered", + "Shipped", + "Out for delivery", + "Delivered", +] + + +async def async_setup_entry( + hass: HomeAssistant, + entry: ConfigEntry, + async_add_entities, +): + """Set up Amazon Order Status sensors.""" + coordinator: AmazonOrdersCoordinator = hass.data["amazon_order_status"][entry.entry_id] + + sensors = [ + AmazonOrderStatusSensor(coordinator, status) + for status in STATUSES + ] + sensors.append(AmazonOrdersLastUpdatedSensor(coordinator)) + + async_add_entities(sensors) + + +class AmazonOrderStatusSensor(CoordinatorEntity, Entity): + """Sensor representing Amazon orders in a specific status.""" + + def __init__(self, coordinator: AmazonOrdersCoordinator, status: str): + super().__init__(coordinator) + self.status = status + self._attr_unique_id = f"amazon_order_status_{status.lower().replace(' ', '_')}" + self._attr_name = f"Amazon Orders {status}" + self._attr_icon = "mdi:package-variant" + + @property + def state(self) -> int: + """Return number of orders in this status.""" + return len(self._orders_for_status()) + + @property + def extra_state_attributes(self): + """Return order details for this status.""" + orders = self._orders_for_status() + return { + "order_count": len(orders), + "orders": orders, + } + + def _orders_for_status(self) -> list[dict]: + """Return orders matching this sensor's status.""" + if not self.coordinator.data: + return [] + + return [ + { + "order_id": data.get("order_id"), + "subject": data.get("subject"), + "updated": data.get("updated"), + "tracking_url": data.get("tracking_url"), + } + for data in self.coordinator.data + if data.get("status") == self.status + ] + + +class AmazonOrdersLastUpdatedSensor(CoordinatorEntity, Entity): + """Sensor showing when Amazon orders were last updated.""" + + def __init__(self, coordinator: AmazonOrdersCoordinator): + super().__init__(coordinator) + self._attr_unique_id = "amazon_order_status_last_updated" + self._attr_name = "Amazon Orders Last Updated" + self._attr_icon = "mdi:clock-check-outline" + + @property + def state(self): + """Return ISO timestamp of last successful update.""" + if not getattr(self.coordinator, "last_check", None): + return None + return self.coordinator.last_check.isoformat() diff --git a/custom_components/amazon_order_status/services.yaml b/custom_components/amazon_order_status/services.yaml new file mode 100644 index 0000000..2fb0c56 --- /dev/null +++ b/custom_components/amazon_order_status/services.yaml @@ -0,0 +1,10 @@ +# Service definitions for Amazon Order Status +# https://developers.home-assistant.io/docs/dev_101_services + +purge_order: + description: Remove a specific order from tracking. The order will no longer appear in the sensors. + fields: + order_id: + description: The Amazon order number to remove (e.g. 123-4567890-1234567). Copy from sensor attributes. + required: true + example: "123-4567890-1234567" diff --git a/custom_components/amazon_order_status/translations/en.json b/custom_components/amazon_order_status/translations/en.json new file mode 100644 index 0000000..8e29453 --- /dev/null +++ b/custom_components/amazon_order_status/translations/en.json @@ -0,0 +1,34 @@ +{ + "config": { + "error": { + "cannot_connect": "Cannot connect to IMAP server", + "invalid_auth": "Invalid username or password" + }, + "step": { + "user": { + "title": "Amazon Orders", + "description": "Configure IMAP access for Amazon order emails. imap_folder is an optional field - leave blank for the root inbox, or provide a folder name to search a specific folder. Note that some email providers require 'INBOX/Folder name', others will accept simply 'Folder name'" + } + } + }, + "options": { + "step": { + "init": { + "title": "Amazon Order Options", + "description": "Configure how Home Assistant tracks and processes Amazon order emails. delivered_retention_days - How many days should HA track delivered orders? update_interval - how often should HA check for delivery updates? imap_folder - Optional email folder to search (leave empty for INBOX)." + } + } + }, + "services": { + "purge_order": { + "name": "Purge order", + "description": "Remove a specific order from tracking. The order will no longer appear in the Amazon Order Status sensors.", + "fields": { + "order_id": { + "name": "Order ID", + "description": "The Amazon order number to remove (e.g. 123-4567890-1234567). You can copy this from the sensor's order list." + } + } + } + } +} diff --git a/custom_components/mail_and_packages/__init__.py b/custom_components/mail_and_packages/__init__.py new file mode 100644 index 0000000..9f99302 --- /dev/null +++ b/custom_components/mail_and_packages/__init__.py @@ -0,0 +1,371 @@ +"""Mail and Packages Integration.""" + +import asyncio +import logging + +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import CONF_RESOURCES +from homeassistant.core import HomeAssistant +from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady +from homeassistant.helpers import device_registry as dr + +from . import const +from .const import ( + ATTR_IMAGE_NAME, + ATTR_IMAGE_PATH, + AUTH_TYPE_PASSWORD, + CONF_AMAZON_CUSTOM_IMG, + CONF_AMAZON_CUSTOM_IMG_FILE, + CONF_AMAZON_DAYS, + CONF_AMAZON_DOMAIN, + CONF_AMAZON_FWDS, + CONF_AUTH_TYPE, + CONF_FEDEX_CUSTOM_IMG, + CONF_FEDEX_CUSTOM_IMG_FILE, + CONF_FOLDER, + CONF_FORWARDED_EMAILS, + CONF_GENERIC_CUSTOM_IMG, + CONF_GENERIC_CUSTOM_IMG_FILE, + CONF_IMAGE_SECURITY, + CONF_IMAP_SECURITY, + CONF_IMAP_TIMEOUT, + CONF_PATH, + CONF_SCAN_INTERVAL, + CONF_STORAGE, + CONF_UPS_CUSTOM_IMG, + CONF_UPS_CUSTOM_IMG_FILE, + CONF_VERIFY_SSL, + CONF_WALMART_CUSTOM_IMG, + CONF_WALMART_CUSTOM_IMG_FILE, + CONFIG_VER, + DEFAULT_AMAZON_CUSTOM_IMG_FILE, + DEFAULT_AMAZON_DAYS, + DEFAULT_FEDEX_CUSTOM_IMG_FILE, + DEFAULT_GENERIC_CUSTOM_IMG_FILE, + DEFAULT_UPS_CUSTOM_IMG_FILE, + DEFAULT_WALMART_CUSTOM_IMG_FILE, + DOMAIN, + ISSUE_URL, + PLATFORMS, + VERSION, +) +from .coordinator import ( + MailAndPackagesConfigEntry, + MailAndPackagesData, + MailDataUpdateCoordinator, +) +from .utils.image import default_image_path, hash_file + +__all__ = [ + "ATTR_IMAGE_NAME", + "ATTR_IMAGE_PATH", + "AUTH_TYPE_PASSWORD", + "CONFIG_VER", + "CONF_AMAZON_CUSTOM_IMG", + "CONF_AMAZON_CUSTOM_IMG_FILE", + "CONF_AMAZON_DAYS", + "CONF_AMAZON_DOMAIN", + "CONF_AMAZON_FWDS", + "CONF_AUTH_TYPE", + "CONF_FEDEX_CUSTOM_IMG", + "CONF_FEDEX_CUSTOM_IMG_FILE", + "CONF_GENERIC_CUSTOM_IMG", + "CONF_GENERIC_CUSTOM_IMG_FILE", + "CONF_IMAGE_SECURITY", + "CONF_IMAP_SECURITY", + "CONF_IMAP_TIMEOUT", + "CONF_PATH", + "CONF_SCAN_INTERVAL", + "CONF_STORAGE", + "CONF_UPS_CUSTOM_IMG", + "CONF_UPS_CUSTOM_IMG_FILE", + "CONF_VERIFY_SSL", + "CONF_WALMART_CUSTOM_IMG", + "CONF_WALMART_CUSTOM_IMG_FILE", + "DEFAULT_AMAZON_CUSTOM_IMG_FILE", + "DEFAULT_AMAZON_DAYS", + "DEFAULT_FEDEX_CUSTOM_IMG_FILE", + "DEFAULT_GENERIC_CUSTOM_IMG_FILE", + "DEFAULT_UPS_CUSTOM_IMG_FILE", + "DEFAULT_WALMART_CUSTOM_IMG_FILE", + "DOMAIN", + "ISSUE_URL", + "PLATFORMS", + "VERSION", + "MailAndPackagesConfigEntry", + "MailAndPackagesData", + "MailDataUpdateCoordinator", + "const", + "default_image_path", + "hash_file", +] + +_LOGGER = logging.getLogger(__name__) + + +async def async_setup(hass: HomeAssistant, config_entry: MailAndPackagesConfigEntry): # pylint: disable=unused-argument + """Disallow configuration via YAML.""" + return True + + +async def async_setup_entry( + hass: HomeAssistant, + config_entry: MailAndPackagesConfigEntry, +) -> bool: + """Load the saved entities.""" + _LOGGER.info( + "Version %s is starting, if you have any issues please report them here: %s", + VERSION, + ISSUE_URL, + ) + hass.data.setdefault(DOMAIN, {}) + updated_config = config_entry.data.copy() + + # Sort the resources + updated_config[CONF_RESOURCES] = sorted(updated_config[CONF_RESOURCES]) + + if updated_config != config_entry.data: + hass.config_entries.async_update_entry(config_entry, data=updated_config) + + # Variables for data coordinator + config = config_entry.data + + # Setup the data coordinator + coordinator = MailDataUpdateCoordinator(hass, config, config_entry) + + # Fetch initial data so we have data when entities subscribe + await coordinator.async_refresh() + + # Raise ConfigEntryNotReady if coordinator didn't update + if not coordinator.last_update_success: + if isinstance(coordinator.last_exception, ConfigEntryAuthFailed): + raise coordinator.last_exception + exc = coordinator.last_exception + detail = (str(exc) or type(exc).__name__) if exc else "unknown error" + _LOGGER.error("Error updating sensor data: %s", detail) + raise ConfigEntryNotReady + + config_entry.runtime_data = MailAndPackagesData(coordinator=coordinator, cameras=[]) + + await hass.config_entries.async_forward_entry_setups(config_entry, PLATFORMS) + return True + + +async def async_remove_config_entry_device( # pylint: disable-next=unused-argument + hass: HomeAssistant, + config_entry: ConfigEntry, + device_entry: dr.DeviceEntry, +) -> bool: + """Remove config entry from a device if its no longer present.""" + return not any( + identifier + for identifier in device_entry.identifiers + if identifier[0] == DOMAIN + and config_entry.runtime_data.get_device(identifier[1]) + ) + + +async def async_unload_entry( + hass: HomeAssistant, + config_entry: MailAndPackagesConfigEntry, +) -> bool: + """Handle removal of an entry.""" + _LOGGER.debug("Attempting to unload sensors from the %s integration", DOMAIN) + + unload_ok = all( + await asyncio.gather( + *[ + hass.config_entries.async_forward_entry_unload(config_entry, platform) + for platform in PLATFORMS + ], + ), + ) + + if unload_ok: + _LOGGER.debug("Successfully removed sensors from the %s integration", DOMAIN) + + return unload_ok + + +async def async_migrate_entry(hass, config_entry): + """Migrate an old config entry.""" + version = config_entry.version + new_version = CONFIG_VER + + _LOGGER.debug("Migrating from version %s", version) + updated_config = {**config_entry.data} + + _migrate_legacy_versions(updated_config, version, config_entry) + _apply_default_config(updated_config) + + if updated_config != config_entry.data: + hass.config_entries.async_update_entry( + config_entry, + data=updated_config, + version=new_version, + ) + + _LOGGER.debug("Migration complete to version %s", new_version) + + return True + + +def _migrate_legacy_versions(updated_config, version, config_entry): + """Handle migration of legacy versions.""" + _migrate_versions_1_to_3(updated_config, version, config_entry) + _migrate_versions_4_to_16(updated_config, version) + _migrate_version_17(updated_config, version) + _migrate_version_18(updated_config, version) + + +def _migrate_versions_1_to_3(updated_config, version, config_entry): + """Handle migration for versions 1 to 3.""" + if version == 1: + if CONF_AMAZON_FWDS in updated_config: + if not isinstance(updated_config[CONF_AMAZON_FWDS], list): + updated_config[CONF_AMAZON_FWDS] = [ + x.strip() for x in updated_config[CONF_AMAZON_FWDS].split(",") + ] + else: + updated_config[CONF_AMAZON_FWDS] = [] + else: + _LOGGER.warning("Missing configuration data: %s", CONF_AMAZON_FWDS) + + # Force path change + updated_config[CONF_PATH] = "custom_components/mail_and_packages/images/" + + # Always on image security + if not config_entry.data.get(CONF_IMAGE_SECURITY, False): + updated_config[CONF_IMAGE_SECURITY] = True + + # Add default Amazon Days configuration + updated_config[CONF_AMAZON_DAYS] = DEFAULT_AMAZON_DAYS + + # 2 -> 4 + if version <= 2: + # Force path change + updated_config[CONF_PATH] = "custom_components/mail_and_packages/images/" + + # Always on image security + if not config_entry.data.get(CONF_IMAGE_SECURITY, False): + updated_config[CONF_IMAGE_SECURITY] = True + + # Add default Amazon Days configuration + updated_config[CONF_AMAZON_DAYS] = DEFAULT_AMAZON_DAYS + + if version <= 3: + # Add default Amazon Days configuration + updated_config[CONF_AMAZON_DAYS] = DEFAULT_AMAZON_DAYS + + +def _migrate_versions_4_to_16(updated_config, version): + """Handle migration for versions 4 to 16.""" + _migrate_versions_4_to_7(updated_config, version) + _migrate_versions_15_to_16(updated_config, version) + + +def _migrate_versions_4_to_7(updated_config, version): + """Handle migration for versions 4 to 7.""" + if version <= 4: + if CONF_AMAZON_FWDS in updated_config and updated_config[CONF_AMAZON_FWDS] == [ + '""', + ]: + updated_config[CONF_AMAZON_FWDS] = [] + + if version <= 5: + if CONF_VERIFY_SSL not in updated_config: + updated_config[CONF_VERIFY_SSL] = True + + if version <= 6: + if CONF_IMAP_SECURITY not in updated_config: + updated_config[CONF_IMAP_SECURITY] = "SSL" + + if version <= 7: + if CONF_AMAZON_DOMAIN not in updated_config: + updated_config[CONF_AMAZON_DOMAIN] = "amazon.com" + + +def _migrate_versions_15_to_16(updated_config, version): + """Handle migration for versions 15 to 16.""" + if version <= 15: + if updated_config.get(CONF_IMAP_SECURITY) == "startTLS": + updated_config[CONF_IMAP_SECURITY] = "SSL" + if CONF_AUTH_TYPE not in updated_config: + updated_config[CONF_AUTH_TYPE] = AUTH_TYPE_PASSWORD + + if version <= 16: + if "auth" in updated_config: + auth_data = updated_config.pop("auth") + updated_config.update(auth_data) + + +def _migrate_version_17(updated_config, version): + """Handle migration for version 17.""" + if version <= 17: + fwds = updated_config.get(CONF_FORWARDED_EMAILS) + if isinstance(fwds, str): + if fwds and fwds != "(none)": + updated_config[CONF_FORWARDED_EMAILS] = [ + e.strip() for e in fwds.split(",") if e.strip() + ] + else: + updated_config.pop(CONF_FORWARDED_EMAILS, None) + + +def _migrate_version_18(updated_config, version): + """Handle migration for version 18.""" + if version <= 18: + if CONF_FOLDER in updated_config: + folder = updated_config[CONF_FOLDER] + if isinstance(folder, str): + updated_config[CONF_FOLDER] = folder.strip('"') + elif isinstance(folder, (list, tuple, set)): + updated_config[CONF_FOLDER] = [ + f.strip('"') for f in folder if isinstance(f, str) + ] + + +def _apply_default_config(updated_config): + """Ensure default configurations are present.""" + # Require configs on all migration paths + if CONF_PATH not in updated_config: + updated_config[CONF_PATH] = "custom_components/mail_and_packages/images/" + + if CONF_RESOURCES not in updated_config: + updated_config[CONF_RESOURCES] = [] + + # Add default for image storage config + if CONF_STORAGE not in updated_config: + updated_config[CONF_STORAGE] = "custom_components/mail_and_packages/images/" + + _apply_courier_image_defaults(updated_config) + _apply_walmart_generic_fedex_defaults(updated_config) + + +def _apply_courier_image_defaults(updated_config): + """Apply default Amazon and UPS custom image configurations.""" + if CONF_AMAZON_CUSTOM_IMG not in updated_config: + updated_config[CONF_AMAZON_CUSTOM_IMG] = False + if CONF_AMAZON_CUSTOM_IMG_FILE not in updated_config: + updated_config[CONF_AMAZON_CUSTOM_IMG_FILE] = DEFAULT_AMAZON_CUSTOM_IMG_FILE + if CONF_UPS_CUSTOM_IMG not in updated_config: + updated_config[CONF_UPS_CUSTOM_IMG] = False + if CONF_UPS_CUSTOM_IMG_FILE not in updated_config: + updated_config[CONF_UPS_CUSTOM_IMG_FILE] = DEFAULT_UPS_CUSTOM_IMG_FILE + + +def _apply_walmart_generic_fedex_defaults(updated_config): + """Apply default Walmart, Generic and FedEx custom image configurations.""" + if CONF_WALMART_CUSTOM_IMG not in updated_config: + updated_config[CONF_WALMART_CUSTOM_IMG] = False + if CONF_WALMART_CUSTOM_IMG_FILE not in updated_config: + updated_config[CONF_WALMART_CUSTOM_IMG_FILE] = DEFAULT_WALMART_CUSTOM_IMG_FILE + if CONF_GENERIC_CUSTOM_IMG not in updated_config: + updated_config[CONF_GENERIC_CUSTOM_IMG] = False + if CONF_GENERIC_CUSTOM_IMG_FILE not in updated_config: + updated_config[CONF_GENERIC_CUSTOM_IMG_FILE] = DEFAULT_GENERIC_CUSTOM_IMG_FILE + + if CONF_FEDEX_CUSTOM_IMG not in updated_config: + updated_config[CONF_FEDEX_CUSTOM_IMG] = False + if CONF_FEDEX_CUSTOM_IMG_FILE not in updated_config: + updated_config[CONF_FEDEX_CUSTOM_IMG_FILE] = DEFAULT_FEDEX_CUSTOM_IMG_FILE diff --git a/custom_components/mail_and_packages/__pycache__/__init__.cpython-314.pyc b/custom_components/mail_and_packages/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a5dbd18c399c2def5b3e4dfdab9664ab005b6968 GIT binary patch literal 14251 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 PPxB8;^Z8kx@#X&kX3}f3 literal 0 HcmV?d00001 diff --git a/custom_components/mail_and_packages/__pycache__/application_credentials.cpython-314.pyc b/custom_components/mail_and_packages/__pycache__/application_credentials.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..28f40af5cae0c0b163fdf74ce9d3e7b7144e3443 GIT binary patch literal 1699 zcmbVM&2Jk;6rcUf+KHWy=CicTrhy2n#ap75R#p|sYE#*VCh4a56uR23C-&0y&T3{H z6pMoeTsU#zz=3~&|ArhQ%&MFyhu$2e5OL$p+8ZZGTo`F)-u&L1H*eDUpwl03 zKP^|c;;A9r@;yoz+2@^&Cg%|=Syn(AepozLkTCE=T=YoGg5DybHP~t$tQYTC!np_% zcS`?jKPRtnSdin~xg)1dgE*7miI^Kk+90G6;Lh#z7}xViJLIf5P$U78QEW+Moz>KO z;ACj)Mm|gIlT$niGAz1if<+4S(>)lvsD@t1557UD4%jvHOlnHDBs7C&%X>q1AY?0h zz{nx4?&+z#lkzeJV764?iS}0Pjn$^hSUfJS@6<`l^}{$j;!Lbl%-b|9XjBu{3geWD zbEr5VzE*w-fa~$?vPkk}28nC~<616f;&wOVCy+ov49jaXPFfD6Ga@0dgjsNI-~cO~ zXvj*-9dXzh#lwoxVLai0X-I&l*m3AQ_+Em}K7pZ&&d{W!pNQdgcA>Ap{APN#ufhCI zN7F0)F(Da9zwwJ!I?_rf8CajfPUMMaPn)>i*9fVnUxIKGEra74+DWw+=1~G}Umd}= zba543NKH+-q*3?A(p@!FlWKBJy*o_fD!QlmQbF!)+DQsbks{N-RHWuhm*KhzWgby- z;MXxV84j?=0ra8vljk-?=@sLALO~}rEU2+scezVN0C8@+{OR+Gv%6{6Htk(1m;ouz z!$c>=FeQwPbZ@M)F+)4O!IaqoFY?4fEfbbTcw4X;) zv)>(ld-&u0@ud0l%E!l(>)p!h+|?f*9OvHeK6x{Ky=P4Hj4M53rf1|&GunjSN1CSp z&BP;pReC6G6>{;I1I+atC%)5!p9ttY_=!Y?4f$344>lzir6TbOspFY{JD_;L`?<@C zCJrJ@*`NqCcxI>q@s9L8F^GHqgy@2hlXo#5wn)7l;0^i#V4@hJpcdz literal 0 HcmV?d00001 diff --git a/custom_components/mail_and_packages/__pycache__/config_flow.cpython-314.pyc b/custom_components/mail_and_packages/__pycache__/config_flow.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..14cd8d08b801486993a0ebfc10ae3b7aa45af58b GIT binary patch literal 70901 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 literal 0 HcmV?d00001 diff --git a/custom_components/mail_and_packages/__pycache__/const.cpython-314.pyc b/custom_components/mail_and_packages/__pycache__/const.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3b8947c88e9077c881969a2f776af7faa905a3fe GIT binary patch literal 36421 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 AD*ylh literal 0 HcmV?d00001 diff --git a/custom_components/mail_and_packages/__pycache__/coordinator.cpython-314.pyc b/custom_components/mail_and_packages/__pycache__/coordinator.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9678665d41ed1e622524997ce73fcab7b2c3d51c GIT binary patch literal 28765 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 literal 0 HcmV?d00001 diff --git a/custom_components/mail_and_packages/__pycache__/entity.cpython-314.pyc b/custom_components/mail_and_packages/__pycache__/entity.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e6123968d6fd612e2d8813f4eb4c934e2a311cdf GIT binary patch literal 822 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 config_entry_oauth2_flow.AbstractOAuth2Implementation: + """Return auth implementation based on provider selected in config flow.""" + # Config flow stores the selected provider before triggering OAuth + provider = hass.data[DOMAIN]["oauth_provider"] + server = OAUTH_SERVERS[provider] + + return AuthImplementation( + hass, + auth_domain, + credential, + server, + ) diff --git a/custom_components/mail_and_packages/binary_sensor.py b/custom_components/mail_and_packages/binary_sensor.py new file mode 100644 index 0000000..faba768 --- /dev/null +++ b/custom_components/mail_and_packages/binary_sensor.py @@ -0,0 +1,88 @@ +"""Binary sensors for Mail and Packages.""" + +import logging + +from homeassistant.components.binary_sensor import ( + BinarySensorEntity, +) +from homeassistant.const import CONF_HOST, CONF_RESOURCES +from homeassistant.helpers.update_coordinator import ( + CoordinatorEntity, + DataUpdateCoordinator, +) + +from . import MailAndPackagesConfigEntry +from .const import BINARY_SENSORS, DOMAIN, VERSION +from .entity import MailandPackagesBinarySensorEntityDescription + +_LOGGER = logging.getLogger(__name__) + + +async def async_setup_entry(hass, entry: MailAndPackagesConfigEntry, async_add_devices): + """Initialize binary_sensor platform.""" + coordinator = entry.runtime_data.coordinator + resources = entry.data.get(CONF_RESOURCES, []) + + binary_sensors = [ + PackagesBinarySensor(value, coordinator, entry) + for value in BINARY_SENSORS.values() + if not value.selectable or value.key in resources + ] + async_add_devices(binary_sensors, False) + + +class PackagesBinarySensor(CoordinatorEntity, BinarySensorEntity): + """Implementation of an Mail and Packages binary sensor.""" + + def __init__( + self, + sensor_description: MailandPackagesBinarySensorEntityDescription, + coordinator: DataUpdateCoordinator, + config: MailAndPackagesConfigEntry, + ) -> None: + """Initialize the sensor.""" + super().__init__(coordinator) + self.coordinator = coordinator + self._config = config + self.entity_description = sensor_description + self._name = sensor_description.name + self._type = sensor_description.key + self._unique_id = config.entry_id + self._host = config.data[CONF_HOST] + + self._attr_name = f"{self._name}" + self._attr_unique_id = ( + f"binary_sensor_{self._host}_{self._type}_{self._unique_id}" + ) + + @property + def device_info(self) -> dict: + """Return device information about the mailbox.""" + return { + "connections": {(DOMAIN, self._unique_id)}, + "name": self._host, + "manufacturer": "IMAP E-Mail", + "sw_version": VERSION, + } + + @property + def should_poll(self) -> bool: + """No need to poll. Coordinator notifies entity of updates.""" + return False + + @property + def available(self) -> bool: + """Return if entity is available.""" + return self.coordinator.data is not None + + @property + def is_on(self) -> bool: + """Return True if the image is updated.""" + if self._type in self.coordinator.data: + _LOGGER.debug( + "binary_sensor: %s value: %s", + self._type, + self.coordinator.data[self._type], + ) + return bool(self.coordinator.data[self._type]) + return False diff --git a/custom_components/mail_and_packages/camera.py b/custom_components/mail_and_packages/camera.py new file mode 100644 index 0000000..8931fb4 --- /dev/null +++ b/custom_components/mail_and_packages/camera.py @@ -0,0 +1,666 @@ +"""Camera that loads a picture from a local file.""" + +from __future__ import annotations + +import logging +import os +from pathlib import Path + +import anyio +import voluptuous as vol +from homeassistant.components.camera import Camera +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import ATTR_ENTITY_ID, CONF_HOST +from homeassistant.core import ServiceCall +from homeassistant.helpers.update_coordinator import CoordinatorEntity + +from . import MailAndPackagesConfigEntry, const +from .const import ( + ATTR_IMAGE_PATH, + ATTR_USPS_IMAGE, + CAMERA_DATA, + CONF_CUSTOM_IMG, + CONF_CUSTOM_IMG_FILE, + CONF_DURATION, + CONF_POST_DE_CUSTOM_IMG, + CONF_POST_DE_CUSTOM_IMG_FILE, + DOMAIN, + SENSOR_NAME, + VERSION, +) +from .utils.image import cleanup_images, generate_delivery_gif, resize_images + +SERVICE_UPDATE_IMAGE = "update_image" +_LOGGER = logging.getLogger(__name__) + + +async def async_setup_entry( + hass, + config: MailAndPackagesConfigEntry, + async_add_entities, +): + """Set up the Camera that works with local files.""" + coordinator = config.runtime_data.coordinator + camera = [] + + for variable in CAMERA_DATA: + temp_cam = MailCam(hass, variable, config, coordinator) + camera.append(temp_cam) + config.runtime_data.cameras.append(temp_cam) + + async def _update_image(service: ServiceCall) -> None: + """Refresh camera image.""" + _LOGGER.debug("Updating image: %s", service) + cameras = config.runtime_data.cameras + entity_id = None + + if ATTR_ENTITY_ID in service.data: + entity_id = service.data[ATTR_ENTITY_ID] + + # Update all cameras if no entity_id + if entity_id is None: + for cam in cameras: + await cam.update_file_path() + + else: + for cam in cameras: + if cam.entity_id in entity_id: + await cam.update_file_path() + return True + + hass.services.async_register( + DOMAIN, + SERVICE_UPDATE_IMAGE, + _update_image, + schema=vol.Schema( + { + vol.Optional(ATTR_ENTITY_ID): vol.Coerce(str), + }, + ), + ) + + async_add_entities(camera) + + +class MailCam(CoordinatorEntity, Camera): + """Representation of a local file camera.""" + + def __init__( + self, + hass, + name: str, + config: ConfigEntry, + coordinator, + ) -> None: + """Initialize Local File Camera component.""" + CoordinatorEntity.__init__(self, coordinator) + Camera.__init__(self) + + self.hass = hass + self.config = config + self._name = CAMERA_DATA[name][SENSOR_NAME] + self._type = name + self._host = config.data.get(CONF_HOST) + self._unique_id = config.entry_id + + # Derive config keys and default image from camera type name + # Remove "_camera" suffix to get base name (e.g., "usps_camera" -> "usps") + base_name = self._type.removesuffix("_camera") + + # USPS and Post DE use mail_none.gif, others use no_deliveries_*.jpg + if base_name in ("usps", "post_de"): + if base_name == "usps": + custom_img_key = CONF_CUSTOM_IMG + custom_img_file_key = CONF_CUSTOM_IMG_FILE + else: + custom_img_key = CONF_POST_DE_CUSTOM_IMG + custom_img_file_key = CONF_POST_DE_CUSTOM_IMG_FILE + default_image = "mail_none.gif" + else: + # Derive config key names dynamically (e.g., "amazon" -> CONF_AMAZON_CUSTOM_IMG) + custom_img_key = getattr( + const, + f"CONF_{base_name.upper()}_CUSTOM_IMG", + None, + ) + custom_img_file_key = getattr( + const, + f"CONF_{base_name.upper()}_CUSTOM_IMG_FILE", + None, + ) + default_image = f"no_deliveries_{base_name}.jpg" + + # Set custom image paths + self._no_mail = None + if custom_img_key and config.data.get(custom_img_key): + self._no_mail = config.data.get(custom_img_file_key) + _LOGGER.debug( + "%s camera - custom image enabled: %s", + self._type, + self._no_mail, + ) + + # Set initial file path based on camera type and custom settings + if custom_img_key and config.data.get(custom_img_key): + self._file_path = config.data.get(custom_img_file_key) + _LOGGER.debug( + "%s camera - initial file path set to: %s", + self._type, + self._file_path, + ) + else: + self._file_path = f"{Path(__file__).parent}/{default_image}" + + # Canonical bundled placeholder for this camera. Always available + # regardless of later _file_path changes, so a missing delivery image + # can fall back to it instead of returning None (which makes the HA + # camera proxy serve HTTP 500). + self._default_image_path = f"{Path(__file__).parent}/{default_image}" + + self._cached_image_path: str | None = None + self._cached_image_bytes: bytes | None = None + self._last_delivery_images: list[str] | None = None + self._is_generic: bool = True + + async def async_camera_image( + self, + width: int | None = None, + height: int | None = None, + ) -> bytes | None: + """Return image response.""" + if ( + self._file_path == self._cached_image_path + and self._cached_image_bytes is not None + ): + return self._cached_image_bytes + + _LOGGER.debug( + "Camera %s reading image from: %s", + self._name, + self._file_path, + ) + + def _read_file(path: str) -> bytes: + with Path(path).open("rb") as f: + return f.read() + + try: + image_bytes = await self.hass.async_add_executor_job( + _read_file, self._file_path + ) + except FileNotFoundError: + _LOGGER.debug( + "Could not read camera %s image from file: %s; " + "falling back to bundled placeholder %s", + self._name, + self._file_path, + self._default_image_path, + ) + # Fall back to the bundled placeholder so the camera proxy never + # serves HTTP 500 when a delivery image is missing on disk. Skip the + # fallback when the primary path already IS the placeholder (true for + # non-custom cameras, where _file_path and _default_image_path are + # both built from the same default image): re-reading the same + # missing file would only fail again, so return None instead. + if self._file_path != self._default_image_path: + try: + image_bytes = await self.hass.async_add_executor_job( + _read_file, self._default_image_path + ) + except FileNotFoundError: + _LOGGER.warning( + "Camera %s placeholder image also missing: %s", + self._name, + self._default_image_path, + ) + return None + else: + # Cache against the placeholder path so repeated reads are + # cheap; update_file_path() invalidates the cache when the + # primary path changes. + self._cached_image_path = self._default_image_path + self._cached_image_bytes = image_bytes + return image_bytes + return None + else: + self._cached_image_path = self._file_path + self._cached_image_bytes = image_bytes + return image_bytes + + def check_file_path_access(self, file_path: str) -> None: + """Check that filepath given is readable.""" + if not os.access(file_path, os.R_OK): + _LOGGER.debug( + "Could not read camera %s image from file: %s", + self._name, + file_path, + ) + + async def update_file_path(self) -> None: + """Update the file_path.""" + _LOGGER.debug("Camera Update: %s", self._type) + _LOGGER.debug("Custom No Mail: %s", self._no_mail) + + if not self.coordinator.last_update_success: + _LOGGER.debug("Update to update camera image. Unavailable.") + return + + if self.coordinator.data is None: + _LOGGER.debug("Unable to update camera image, no data.") + return + + if self._type == "usps_camera": + self._update_usps_camera() + elif self._type == "generic_camera": + await self._update_generic_camera() + else: + await self._update_standard_camera() + + # Invalidate the cache so the next frontend request re-reads the image from disk. + # This is necessary because for some shippers (like USPS), the image file path + # stays the same but the underlying image content on disk changes. + self._cached_image_path = None + self._cached_image_bytes = None + + self.check_file_path_access(self._file_path) + self.schedule_update_ha_state() + + def _update_usps_camera(self) -> None: + """Update file path for USPS camera.""" + self._file_path = f"{Path(__file__).parent}/mail_none.gif" + self._is_generic = True + required_keys = {ATTR_USPS_IMAGE, ATTR_IMAGE_PATH} + if required_keys.issubset(self.coordinator.data): + image = self.coordinator.data[ATTR_USPS_IMAGE] + path = self.coordinator.data[ATTR_IMAGE_PATH] + self._file_path = f"{self.hass.config.path()}/{path}{image}" + self._is_generic = not self.coordinator.data.get("usps_update", False) + _LOGGER.debug( + "usps_camera camera - file path set to: %s", + self._file_path, + ) + elif self._no_mail: + self._file_path = self._no_mail + + async def _update_generic_camera(self) -> None: + """Update file path for Generic camera.""" + if self._no_mail: + self._file_path = self._no_mail + self._is_generic = True + _LOGGER.debug("Generic camera - using custom no mail: %s", self._file_path) + return + + delivery_images = self._collect_generic_delivery_images() + + if ( + self._last_delivery_images is not None + and delivery_images == self._last_delivery_images + ): + _LOGGER.debug( + "Generic camera - delivery images unchanged, skipping GIF regeneration" + ) + return + + self._last_delivery_images = delivery_images + + if not delivery_images: + self._file_path = f"{Path(__file__).parent}/no_deliveries_generic.jpg" + self._is_generic = True + _LOGGER.debug( + "Generic camera - no deliveries found, using default: %s", + self._file_path, + ) + return + + image_path = self.coordinator.data.get(ATTR_IMAGE_PATH, "") + full_storage_path = Path(f"{self.hass.config.path()}/{image_path}") + gif_path = str(full_storage_path / "generic_deliveries.gif") + + resized_images = await self.hass.async_add_executor_job( + resize_images, delivery_images, 800, 600 + ) + + duration = self.config.data.get(CONF_DURATION, 5) * 1000 + gif_created = await self.hass.async_add_executor_job( + generate_delivery_gif, + resized_images, + gif_path, + duration, + ) + + if gif_created: + self._file_path = gif_path + self._is_generic = False + _LOGGER.debug( + "Generic camera - created animated GIF with %d delivery images at %s", + len(delivery_images), + gif_path, + ) + else: + _LOGGER.warning( + "Failed to create animated GIF, using first delivery image", + ) + self._file_path = delivery_images[0] + self._is_generic = False + + for img in resized_images: + if await anyio.Path(img).exists(): + await self.hass.async_add_executor_job( + cleanup_images, str(Path(img).parent) + "/", Path(img).name + ) + + def _collect_generic_delivery_images(self) -> list[str]: + """Collect delivery images for the generic camera.""" + delivery_images = [] + enabled_resources = self.config.data.get("resources", []) + + for camera_type in CAMERA_DATA: + # Skip generic, USPS, and Post DE cameras + if camera_type in ("generic_camera", "usps_camera", "post_de_camera"): + continue + + base_name = camera_type.removesuffix("_camera") + delivered_key = f"{base_name}_delivered" + + # Check if this shipper's delivery sensor is enabled + if delivered_key not in enabled_resources: + _LOGGER.debug( + "Generic camera - skipping %s (sensor %s not enabled)", + base_name, + delivered_key, + ) + continue + + # Set image attributes + image_attr_name = f"ATTR_{base_name.upper()}_IMAGE" + image_attr = getattr(const, image_attr_name, None) + path_suffix = f"{base_name}/" + no_mail_check = "no_deliveries" + + required_keys = {image_attr, ATTR_IMAGE_PATH} + if not required_keys.issubset(self.coordinator.data): + continue + + image = self.coordinator.data[image_attr] + path = f"{self.coordinator.data[ATTR_IMAGE_PATH]}{path_suffix}" + delivery_file_path = f"{self.hass.config.path()}/{path}{image}" + + is_no_mail = image.startswith( + no_mail_check, + ) or self._is_custom_no_mail_image(base_name, delivery_file_path) + + delivery_count_key = f"{base_name}_delivered" + has_current_deliveries = ( + delivery_count_key in self.coordinator.data + and self.coordinator.data[delivery_count_key] > 0 + ) + + if ( + not is_no_mail + and Path(delivery_file_path).exists() + and has_current_deliveries + ): + delivery_images.append(delivery_file_path) + elif is_no_mail: + _LOGGER.debug( + "Generic camera - filtered out %s no-mail image: %s", + base_name, + image, + ) + elif not has_current_deliveries: + _LOGGER.debug( + "Generic camera - filtered out %s (no current deliveries, count=%s): %s", + base_name, + self.coordinator.data.get(delivery_count_key, 0), + image, + ) + + return delivery_images + + async def _update_standard_camera(self) -> None: + """Update file path for standard cameras (Amazon, UPS, etc).""" + base_name = self._type.removesuffix("_camera") + if base_name == "post_de": + self._file_path = f"{Path(__file__).parent}/mail_none.gif" + else: + self._file_path = f"{Path(__file__).parent}/no_deliveries_{base_name}.jpg" + self._is_generic = True + + if self._no_mail: + self._file_path = self._no_mail + _LOGGER.debug( + "%s camera - using custom no mail: %s", + self._type, + self._file_path, + ) + return + + image_attr_name = f"ATTR_{base_name.upper()}_IMAGE" + image_attr = getattr(const, image_attr_name, None) + + if not image_attr: + return + + required_keys = {image_attr, ATTR_IMAGE_PATH} + if not required_keys.issubset(self.coordinator.data): + return + + image = self.coordinator.data[image_attr] + image_path = self.coordinator.data[ATTR_IMAGE_PATH].rstrip("/") + "/" + path = f"{image_path}{base_name}/" + coordinator_file_path = f"{self.hass.config.path()}/{path}{image}" + + _LOGGER.debug( + "=== %s CAMERA UPDATE === coordinator %s = '%s'", + self._type, + image_attr, + image, + ) + + # Log all image-related keys in coordinator for this camera + all_image_keys = { + k: self.coordinator.data.get(k, "NOT SET") + for k in self.coordinator.data + if "image" in k.lower() + } + _LOGGER.debug( + "%s camera - All image keys in coordinator: %s", + self._type, + all_image_keys, + ) + + if await anyio.Path(coordinator_file_path).exists() and os.access( + coordinator_file_path, + os.R_OK, + ): + self._file_path = coordinator_file_path + _LOGGER.debug( + "%s camera - found coordinator file: %s", + self._type, + self._file_path, + ) + else: + await self._find_alternative_image(coordinator_file_path, image) + + # Coordinator hashes the delivery image against the placeholder to detect + # whether a real email image was saved; use that result rather than guessing + # from file existence (the placeholder may have been copied to the same path). + self._is_generic = not self.coordinator.data.get(f"{base_name}_update", False) + + async def _find_alternative_image( + self, + coordinator_file_path: str, + expected_image: str, + ) -> None: + """Attempt to find an alternative image in the directory.""" + path_dir = Path(coordinator_file_path).parent + _LOGGER.debug( + "%s camera - coordinator file not found: %s", + self._type, + coordinator_file_path, + ) + + # Define a helper to run blocking I/O in the executor + def _scan_images(): + if not path_dir.exists(): + _LOGGER.debug( + "%s camera - directory does not exist: %s", + self._type, + path_dir, + ) + return None + + try: + found_images = [] + for file_path in path_dir.iterdir(): + if file_path.name.lower().endswith( + (".jpg", ".jpeg", ".png", ".gif"), + ): + if file_path.exists() and os.access(file_path, os.R_OK): + if "no_deliveries" not in file_path.name: + found_images.append( + (str(file_path), file_path.stat().st_mtime), + ) + except OSError as err: + _LOGGER.debug( + "%s camera - error listing directory %s: %s", + self._type, + path_dir, + err, + ) + return None + else: + return found_images + + # Execute the scan in a background thread + image_files = await self.hass.async_add_executor_job(_scan_images) + + if image_files: + image_files.sort(key=lambda x: x[1], reverse=True) + self._file_path = image_files[0][0] + _LOGGER.debug( + "%s camera - found alternative image file (most recent): %s", + self._type, + self._file_path, + ) + + def _is_custom_no_mail_image(self, base_name: str, file_path: str) -> bool: + """Check if the given file path is a custom 'no mail' image for the specified camera. + + Args: + base_name: The base name of the camera (e.g., 'amazon', 'ups', 'walmart', 'usps') + file_path: The full file path to check + + Returns: + True if this is a custom 'no mail' image, False otherwise + + """ + # Handle USPS camera differently (uses CONF_CUSTOM_IMG instead of CONF_USPS_CUSTOM_IMG) + if base_name == "usps": + custom_img_key = "CONF_CUSTOM_IMG" + custom_img_file_key = "CONF_CUSTOM_IMG_FILE" + else: + # Handle other cameras (Amazon, UPS, Walmart) + custom_img_key = f"CONF_{base_name.upper()}_CUSTOM_IMG" + custom_img_file_key = f"CONF_{base_name.upper()}_CUSTOM_IMG_FILE" + + custom_img_conf = getattr(const, custom_img_key, None) + custom_img_file_conf = getattr(const, custom_img_file_key, None) + + if ( + custom_img_conf + and custom_img_file_conf + and self.config.data.get(custom_img_conf) + ): + custom_file_path = self.config.data.get(custom_img_file_conf) + if custom_file_path and Path(custom_file_path).exists(): + # Check if the file path matches the custom "no mail" image + return Path(file_path).resolve() == Path(custom_file_path).resolve() + + return False + + def _get_sensor_name_for_camera(self, camera_type: str) -> str: + """Get the sensor name that corresponds to a camera type. + + Args: + camera_type: The camera type (e.g., 'amazon_camera', 'ups_camera', etc.) + + Returns: + The corresponding sensor name, or None if no mapping exists + + """ + # Remove "_camera" suffix to get base name + base_name = camera_type.removesuffix("_camera") + + # Special cases for mail scans cameras + if base_name == "usps": + return "usps_mail" + if base_name == "post_de": + return "post_de_mail" + + # For other cameras, use the pattern: {base_name}_delivered + return f"{base_name}_delivered" + + async def async_added_to_hass(self) -> None: + """Run when entity is added to hass.""" + await super().async_added_to_hass() + if self.coordinator.data is not None: + await self.update_file_path() + + async def async_on_demand_update(self): + """Update state.""" + self.async_schedule_update_ha_state(True) + + @property + def device_info(self) -> dict: + """Return device information about the mailbox.""" + return { + "connections": {(DOMAIN, self._unique_id)}, + "name": self._host, + "manufacturer": "IMAP E-Mail", + "sw_version": VERSION, + } + + @property + def unique_id(self) -> str: + """Return a unique, Home Assistant friendly identifier for this entity.""" + return f"camera_{self._host}_{self._type}_{self._unique_id}" + + @property + def name(self): + """Return the name of this camera.""" + return self._name + + @property + def extra_state_attributes(self): + """Return the camera state attributes.""" + return { + "file_path": self._file_path, + "is_generic": self._is_generic, + } + + @property + def should_poll(self) -> bool: + """Return True if entity has to be polled for state. + + False if entity pushes its state to HA. + """ + return False + + @property + def available(self) -> bool: + """Return if entity is available.""" + return self.coordinator.data is not None + + def _handle_coordinator_update(self) -> None: + """Handle updated data from the coordinator.""" + _LOGGER.debug( + "%s camera - coordinator update received, updating file path", + self._type, + ) + self.hass.async_create_task(self._async_handle_coordinator_update()) + + async def _async_handle_coordinator_update(self) -> None: + """Update file path then write state so the frontend gets the correct image URL.""" + await self.update_file_path() + self.async_write_ha_state() diff --git a/custom_components/mail_and_packages/config_flow.py b/custom_components/mail_and_packages/config_flow.py new file mode 100644 index 0000000..c331ed6 --- /dev/null +++ b/custom_components/mail_and_packages/config_flow.py @@ -0,0 +1,1427 @@ +"""Adds config flow for Mail and Packages.""" + +import contextlib +import logging +import ssl +from collections.abc import Mapping +from pathlib import Path +from typing import Any + +import homeassistant.helpers.config_validation as cv +import voluptuous as vol +from aioimaplib import AioImapException +from homeassistant import config_entries +from homeassistant.config_entries import ConfigFlowResult +from homeassistant.const import ( + CONF_HOST, + CONF_PASSWORD, + CONF_PORT, + CONF_RESOURCES, + CONF_USERNAME, +) +from homeassistant.core import HomeAssistant +from homeassistant.helpers import config_entry_oauth2_flow, selector + +from .const import ( + AUTH_TYPE_OAUTH_GOOGLE, + AUTH_TYPE_OAUTH_MICROSOFT, + AUTH_TYPE_PASSWORD, + CONF_ALLOW_EXTERNAL, + CONF_ALLOW_FORWARDED_EMAILS, + CONF_AMAZON_CUSTOM_IMG, + CONF_AMAZON_CUSTOM_IMG_FILE, + CONF_AMAZON_DAYS, + CONF_AMAZON_DOMAIN, + CONF_AMAZON_FWDS, + CONF_AUTH_TYPE, + CONF_CUSTOM_DAYS, + CONF_CUSTOM_IMG, + CONF_CUSTOM_IMG_FILE, + CONF_DURATION, + CONF_FEDEX_CUSTOM_IMG, + CONF_FEDEX_CUSTOM_IMG_FILE, + CONF_FOLDER, + CONF_FORWARDED_EMAILS, + CONF_FORWARDING_HEADER, + CONF_GENERATE_GRID, + CONF_GENERATE_MP4, + CONF_GENERIC_CUSTOM_IMG, + CONF_GENERIC_CUSTOM_IMG_FILE, + CONF_IMAGE_SECURITY, + CONF_IMAP_SECURITY, + CONF_IMAP_TIMEOUT, + CONF_PATH, + CONF_POST_DE_CUSTOM_IMG, + CONF_POST_DE_CUSTOM_IMG_FILE, + CONF_SCAN_INTERVAL, + CONF_STORAGE, + CONF_UPS_CUSTOM_IMG, + CONF_UPS_CUSTOM_IMG_FILE, + CONF_VERIFY_SSL, + CONF_WALMART_CUSTOM_IMG, + CONF_WALMART_CUSTOM_IMG_FILE, + CONFIG_VER, + DEFAULT_ALLOW_EXTERNAL, + DEFAULT_ALLOW_FORWARDED_EMAILS, + DEFAULT_AMAZON_CUSTOM_IMG, + DEFAULT_AMAZON_CUSTOM_IMG_FILE, + DEFAULT_AMAZON_DAYS, + DEFAULT_AMAZON_DOMAIN, + DEFAULT_AMAZON_FWDS, + DEFAULT_CUSTOM_DAYS, + DEFAULT_CUSTOM_IMG, + DEFAULT_CUSTOM_IMG_FILE, + DEFAULT_FEDEX_CUSTOM_IMG, + DEFAULT_FEDEX_CUSTOM_IMG_FILE, + DEFAULT_FOLDER, + DEFAULT_FORWARDED_EMAILS, + DEFAULT_FORWARDING_HEADER, + DEFAULT_GENERIC_CUSTOM_IMG, + DEFAULT_GENERIC_CUSTOM_IMG_FILE, + DEFAULT_GIF_DURATION, + DEFAULT_IMAGE_SECURITY, + DEFAULT_IMAP_TIMEOUT, + DEFAULT_PATH, + DEFAULT_PORT, + DEFAULT_POST_DE_CUSTOM_IMG, + DEFAULT_POST_DE_CUSTOM_IMG_FILE, + DEFAULT_SCAN_INTERVAL, + DEFAULT_STORAGE, + DEFAULT_UPS_CUSTOM_IMG, + DEFAULT_UPS_CUSTOM_IMG_FILE, + DEFAULT_WALMART_CUSTOM_IMG, + DEFAULT_WALMART_CUSTOM_IMG_FILE, + DOMAIN, + OAUTH_IMAP_DEFAULTS, + OAUTH_SCOPES, +) +from .helpers import get_resources +from .utils.email import generate_service_email_domains, validate_email_address +from .utils.image import _check_ffmpeg +from .utils.imap import InvalidAuth, decode_imap_utf7, login, logout + +ERROR_MAILBOX_FAIL = "Problem getting mailbox listing using 'INBOX' message" +IMAP_SECURITY = ["none", "SSL"] +AMAZON_SENSORS = ["amazon_packages", "amazon_delivered", "amazon_exception"] +_LOGGER = logging.getLogger(__name__) +AMAZON_EMAIL_ERROR = ( + "Amazon domain found in email: %s, this may cause errors when searching emails." +) +FORWARDED_EMAIL_ERROR = "A service domain was found in email: %s, this may cause errors when searching emails." # pylint: disable=line-too-long + + +async def _check_amazon_forwards(forwards: str, domain: str) -> tuple: + """Validate and format amazon forward emails for user input. + + Returns tuple: dict of errors, list of email addresses + """ + emails = forwards.split(",") + errors = [] + + # Validate each email address + for email in emails: + email = email.strip() + + if "@" in email: + # Check for amazon domains + if f"@{domain}" in email: + _LOGGER.error( + AMAZON_EMAIL_ERROR, + email, + ) + + # No forwards + elif forwards in ["", "(none)", '""']: + forwards = [] + + else: + _LOGGER.error("Missing '@' in email address: %s", email) + errors.append("invalid_email_format") + + if len(errors) == 0: + errors.append("ok") + + return errors, forwards + + +async def _check_forwarded_emails(user_input: dict[str, Any]) -> list[str]: + """Validate forwarded email addresses provided by the user. + + Use Voluptuous to make sure that none of the forwarded email addresses use domains + that match any of the Mail service domains, as this was known to cause issues when + searching for Amazon emails. + + Args: + user_input (dict[str, Any]): The user input dictionary. + + Returns: + list[str]: A list of error codes (e.g. "missing_forwarded_emails") or "ok" if the + email addresses are valid + + """ + forwarded_emails = user_input[CONF_FORWARDED_EMAILS] + + _LOGGER.debug("checking forwarded emails: '%s'", forwarded_emails) + + # No forwards + if not forwarded_emails: + _LOGGER.error( + "Allowed forwarded emails but no forwards or '(none)' were entered.", + ) + return ["missing_forwarded_emails"] + if forwarded_emails == "(none)": + return ["ok"] + + errors = [] + + service_email_domains = generate_service_email_domains( + user_input.get(CONF_AMAZON_FWDS, []), + ) + + emails = [email.strip() for email in forwarded_emails.split(",")] + for email in emails: + _LOGGER.debug("validating email address %s", email) + if not validate_email_address(email): + _LOGGER.error("%s does not look like a valid email address", email) + errors.append("invalid_email_format") + continue + + domain = email.split("@")[1] + if domain in service_email_domains: + _LOGGER.error( + FORWARDED_EMAIL_ERROR, + email, + ) + if len(errors) == 0: + return ["ok"] + + return errors + + +def _validate_path_input(user_input: dict, errors: dict) -> None: + """Validate path and file inputs.""" + # List of (Toggle Key, File Key, Error Key) + file_checks = [ + (CONF_CUSTOM_IMG, CONF_CUSTOM_IMG_FILE, CONF_CUSTOM_IMG_FILE), + ( + CONF_AMAZON_CUSTOM_IMG, + CONF_AMAZON_CUSTOM_IMG_FILE, + CONF_AMAZON_CUSTOM_IMG_FILE, + ), + (CONF_UPS_CUSTOM_IMG, CONF_UPS_CUSTOM_IMG_FILE, CONF_UPS_CUSTOM_IMG_FILE), + ( + CONF_WALMART_CUSTOM_IMG, + CONF_WALMART_CUSTOM_IMG_FILE, + CONF_WALMART_CUSTOM_IMG_FILE, + ), + ( + CONF_FEDEX_CUSTOM_IMG, + CONF_FEDEX_CUSTOM_IMG_FILE, + CONF_FEDEX_CUSTOM_IMG_FILE, + ), + ( + CONF_GENERIC_CUSTOM_IMG, + CONF_GENERIC_CUSTOM_IMG_FILE, + CONF_GENERIC_CUSTOM_IMG_FILE, + ), + ( + CONF_POST_DE_CUSTOM_IMG, + CONF_POST_DE_CUSTOM_IMG_FILE, + CONF_POST_DE_CUSTOM_IMG_FILE, + ), + ] + + for toggle, file_key, error_key in file_checks: + if user_input.get(toggle) and file_key in user_input: + if not Path(user_input[file_key]).is_file(): + errors[error_key] = "file_not_found" + + if CONF_STORAGE in user_input: + if not Path(user_input[CONF_STORAGE]).exists(): + errors[CONF_STORAGE] = "path_not_found" + + +async def _validate_amazon_fwds(user_input: dict, errors: dict) -> None: + """Validate amazon forwarding email addresses in user_input.""" + if CONF_AMAZON_FWDS not in user_input: + return + if not isinstance(user_input[CONF_AMAZON_FWDS], str): + return + status, amazon_list = await _check_amazon_forwards( + user_input[CONF_AMAZON_FWDS], + user_input[CONF_AMAZON_DOMAIN], + ) + user_input[CONF_AMAZON_FWDS] = amazon_list + if status[0] != "ok": + errors[CONF_AMAZON_FWDS] = status[0] + + +async def _validate_forwarded_emails(user_input: dict, errors: dict) -> None: + """Validate forwarded email address list in user_input.""" + if CONF_FORWARDED_EMAILS not in user_input: + return + if not isinstance(user_input[CONF_FORWARDED_EMAILS], str): + return + status = await _check_forwarded_emails(user_input) + if status[0] == "ok" and user_input[CONF_FORWARDED_EMAILS] == "(none)": + # the user changed their mind, remove the flag and config entry + user_input[CONF_ALLOW_FORWARDED_EMAILS] = False + del user_input[CONF_FORWARDED_EMAILS] + elif status[0] == "ok": + user_input[CONF_FORWARDED_EMAILS] = [ + e.strip() for e in user_input[CONF_FORWARDED_EMAILS].split(",") if e.strip() + ] + else: + errors[CONF_FORWARDED_EMAILS] = status[0] + + +async def _validate_user_input(user_input: dict) -> tuple: + """Validate user input from config flow. + + Returns tuple with error messages and modified user_input + """ + errors = {} + + await _validate_amazon_fwds(user_input, errors) + + # Check for forwarding header mode first — it takes precedence over address list + forwarding_header = user_input.get(CONF_FORWARDING_HEADER, "") + if isinstance(forwarding_header, str): + forwarding_header = forwarding_header.strip() + if forwarding_header and forwarding_header not in ("(none)", ""): + # Header mode: store the header name, clear address list if present + user_input[CONF_FORWARDING_HEADER] = forwarding_header + user_input.pop(CONF_FORWARDED_EMAILS, None) + else: + # No header provided — clear the key and fall through to address list validation + user_input.pop(CONF_FORWARDING_HEADER, None) + await _validate_forwarded_emails(user_input, errors) + + # Check for ffmpeg if option enabled + if user_input[CONF_GENERATE_MP4]: + if not await _check_ffmpeg(): + errors[CONF_GENERATE_MP4] = "ffmpeg_not_found" + + # Validate file paths + _validate_path_input(user_input, errors) + + # Normalize CONF_FOLDER: if it has exactly 1 folder, store as string + if CONF_FOLDER in user_input: + folder_val = user_input[CONF_FOLDER] + if isinstance(folder_val, (list, set, tuple)): + folder_list = [f for f in folder_val if isinstance(f, str) and f] + if not folder_list: + user_input[CONF_FOLDER] = "INBOX" + elif len(folder_list) == 1: + user_input[CONF_FOLDER] = folder_list[0] + else: + user_input[CONF_FOLDER] = folder_list + elif not isinstance(folder_val, str) or not folder_val: + user_input[CONF_FOLDER] = "INBOX" + + return errors, user_input + + +async def _get_mailboxes( + hass: HomeAssistant, + host: str, + port: int, + user: str, + pwd: str, + security: str, + verify: bool, + oauth_token: str | None = None, +) -> list: + """Get list of mailbox folders from mail server.""" + _LOGGER.debug("Getting mailboxes, login...") + try: + account = await login( + hass, + host, + port, + user, + pwd, + security, + verify, + oauth_token=oauth_token, + ) + + except (TimeoutError, AioImapException, ConnectionRefusedError) as err: + _LOGGER.error("Unable to connect: %s", err) + return [] + + _LOGGER.debug("Attempting to get mailbox list...") + try: + result = await account.list('""', '"*"') + status = result.result + folderlist = result.lines + _LOGGER.debug("Get mailbox status: %s folder list: %s", status, folderlist) + mailboxes = [] + if status != "OK" or not isinstance(folderlist, list): + _LOGGER.error("Error listing mailboxes ... using default") + mailboxes.append(DEFAULT_FOLDER) + else: + mailboxes = await _parse_folder_list(folderlist) + finally: + await logout(account) + + return mailboxes + + +async def _parse_folder_list(folderlist: list) -> list: + """Parse folder list from IMAP server response.""" + mailboxes = [] + with contextlib.suppress(IndexError): + mailboxes.extend( + decode_imap_utf7(i.decode().split(' "/" ')[1].strip('"')) + for i in folderlist + ) + + with contextlib.suppress(IndexError): + mailboxes.extend( + decode_imap_utf7(i.decode().split(' "." ')[1].strip('"')) + for i in folderlist + ) + + if len(mailboxes) == 0: + _LOGGER.error("Problem reading mailbox folders, using default.") + mailboxes.append(DEFAULT_FOLDER) + + return mailboxes + + +def _get_schema_auth(user_input: list, default_dict: list) -> Any: + """Get the first schema for auth type.""" + if user_input is None: + user_input = {} + + def _get_default(key: str, fallback_default: Any = None) -> None: + return user_input.get(key, default_dict.get(key, fallback_default)) + + return vol.Schema( + { + vol.Required( + CONF_AUTH_TYPE, + default=_get_default(CONF_AUTH_TYPE, AUTH_TYPE_PASSWORD), + ): selector.SelectSelector( + selector.SelectSelectorConfig( + options=[ + selector.SelectOptionDict( + value=AUTH_TYPE_PASSWORD, + label="Password", + ), + selector.SelectOptionDict( + value=AUTH_TYPE_OAUTH_MICROSOFT, + label="OAuth2 - Microsoft (Outlook/Exchange)", + ), + selector.SelectOptionDict( + value=AUTH_TYPE_OAUTH_GOOGLE, + label="OAuth2 - Google (Gmail)", + ), + ], + mode=selector.SelectSelectorMode.DROPDOWN, + translation_key="auth_type", + ), + ), + }, + ) + + +def _get_schema_imap(user_input: list, default_dict: list) -> Any: + """Get the secondary schema for IMAP configuration.""" + if user_input is None: + user_input = {} + + def _get_default(key: str, fallback_default: Any = None) -> None: + return user_input.get(key, default_dict.get(key, fallback_default)) + + # Determine if password field should be shown based on chosen auth_type + auth_type = _get_default(CONF_AUTH_TYPE, AUTH_TYPE_PASSWORD) + schema = { + vol.Required(CONF_HOST, default=_get_default(CONF_HOST)): cv.string, + vol.Required(CONF_PORT, default=_get_default(CONF_PORT, 993)): cv.port, + vol.Required(CONF_USERNAME, default=_get_default(CONF_USERNAME)): cv.string, + } + + if auth_type == AUTH_TYPE_PASSWORD: + schema[vol.Required(CONF_PASSWORD, default=_get_default(CONF_PASSWORD, ""))] = ( + cv.string + ) + + schema.update( + { + vol.Required( + CONF_IMAP_SECURITY, + default=_get_default(CONF_IMAP_SECURITY), + ): vol.In(IMAP_SECURITY), + vol.Optional( + CONF_VERIFY_SSL, + default=_get_default(CONF_VERIFY_SSL, False), + ): cv.boolean, + }, + ) + + return vol.Schema(schema) + + +class multi_folder_select(cv.multi_select): + """Multi select validator that allows a single string and converts it to a list, stripping quotes.""" + + def __call__(self, value: Any) -> list[Any]: + """Validate and format the folder selection value.""" + if isinstance(value, str): + value = [value.strip('"')] + elif isinstance(value, (list, tuple, set)): + value = [v.strip('"') if isinstance(v, str) else v for v in value] + return super().__call__(value) + + +async def _get_schema_step_2( + data: list, + user_input: list, + default_dict: list, + hass: HomeAssistant, +) -> 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)) + + mailboxes = await _get_mailboxes( + hass, + data[CONF_HOST], + data[CONF_PORT], + data[CONF_USERNAME], + data.get(CONF_PASSWORD, ""), + data[CONF_IMAP_SECURITY], + data[CONF_VERIFY_SSL], + data.get("token", {}).get("access_token"), + ) + + default_folder = _get_default(CONF_FOLDER) + if isinstance(default_folder, str): + default_folder = [default_folder.strip('"')] + elif isinstance(default_folder, (list, tuple, set)): + default_folder = [ + f.strip('"') for f in default_folder if isinstance(f, str) and f + ] + else: + default_folder = [] + + # Clean up legacy folders that don't exist anymore/prevent validation failures + default_folder = [f for f in default_folder if f in mailboxes] + + # Pre-select "INBOX" if default_folder is empty and "INBOX" is available + if not default_folder and "INBOX" in mailboxes: + default_folder = ["INBOX"] + + return vol.Schema( + { + vol.Required(CONF_FOLDER, default=default_folder): multi_folder_select( + {m: m for m in mailboxes} + ), + vol.Required( + CONF_RESOURCES, + default=_get_default(CONF_RESOURCES), + ): cv.multi_select(get_resources()), + vol.Optional( + CONF_SCAN_INTERVAL, + default=_get_default(CONF_SCAN_INTERVAL), + ): vol.All(vol.Coerce(int), vol.Range(min=5)), + vol.Optional( + CONF_CUSTOM_DAYS, + default=_get_default(CONF_CUSTOM_DAYS, DEFAULT_CUSTOM_DAYS), + ): vol.All(vol.Coerce(int), vol.Range(min=1)), + vol.Optional( + CONF_IMAP_TIMEOUT, + default=_get_default(CONF_IMAP_TIMEOUT), + ): vol.All(vol.Coerce(int), vol.Range(min=10)), + vol.Optional( + CONF_DURATION, + default=_get_default(CONF_DURATION), + ): vol.Coerce(int), + vol.Optional( + CONF_ALLOW_FORWARDED_EMAILS, + default=_get_default(CONF_ALLOW_FORWARDED_EMAILS, False), + ): cv.boolean, + vol.Optional( + CONF_GENERATE_GRID, + default=_get_default(CONF_GENERATE_GRID, False), + ): cv.boolean, + vol.Optional( + CONF_GENERATE_MP4, + default=_get_default(CONF_GENERATE_MP4, False), + ): cv.boolean, + vol.Optional( + CONF_ALLOW_EXTERNAL, + default=_get_default(CONF_ALLOW_EXTERNAL, False), + ): cv.boolean, + vol.Optional( + CONF_CUSTOM_IMG, + default=_get_default(CONF_CUSTOM_IMG, False), + ): cv.boolean, + vol.Optional( + CONF_AMAZON_CUSTOM_IMG, + default=_get_default(CONF_AMAZON_CUSTOM_IMG, False), + ): cv.boolean, + vol.Optional( + CONF_UPS_CUSTOM_IMG, + default=_get_default(CONF_UPS_CUSTOM_IMG, False), + ): cv.boolean, + vol.Optional( + CONF_WALMART_CUSTOM_IMG, + default=_get_default(CONF_WALMART_CUSTOM_IMG, False), + ): cv.boolean, + vol.Optional( + CONF_FEDEX_CUSTOM_IMG, + default=_get_default(CONF_FEDEX_CUSTOM_IMG, False), + ): cv.boolean, + vol.Optional( + CONF_GENERIC_CUSTOM_IMG, + default=_get_default(CONF_GENERIC_CUSTOM_IMG, False), + ): cv.boolean, + vol.Optional( + CONF_POST_DE_CUSTOM_IMG, + default=_get_default(CONF_POST_DE_CUSTOM_IMG, False), + ): cv.boolean, + }, + ) + + +def _get_schema_step_3(user_input: dict, default_dict: dict) -> 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) -> str: + """Get default value for key.""" + return user_input.get(key, default_dict.get(key, fallback_default)) + + schema = {} + + # Only show custom image file field if custom image is enabled + if user_input.get(CONF_CUSTOM_IMG): + schema[ + vol.Optional( + CONF_CUSTOM_IMG_FILE, + default=_get_default(CONF_CUSTOM_IMG_FILE, DEFAULT_CUSTOM_IMG_FILE), + ) + ] = cv.string + + # Only show Amazon custom image file field if Amazon custom image is enabled + if user_input.get(CONF_AMAZON_CUSTOM_IMG): + schema[ + vol.Optional( + CONF_AMAZON_CUSTOM_IMG_FILE, + default=_get_default( + CONF_AMAZON_CUSTOM_IMG_FILE, + DEFAULT_AMAZON_CUSTOM_IMG_FILE, + ), + ) + ] = cv.string + + # Only show UPS custom image file field if UPS custom image is enabled + if user_input.get(CONF_UPS_CUSTOM_IMG): + schema[ + vol.Optional( + CONF_UPS_CUSTOM_IMG_FILE, + default=_get_default( + CONF_UPS_CUSTOM_IMG_FILE, + DEFAULT_UPS_CUSTOM_IMG_FILE, + ), + ) + ] = cv.string + + # Only show Walmart custom image file field if Walmart custom image is enabled + if user_input.get(CONF_WALMART_CUSTOM_IMG): + schema[ + vol.Optional( + CONF_WALMART_CUSTOM_IMG_FILE, + default=_get_default( + CONF_WALMART_CUSTOM_IMG_FILE, + DEFAULT_WALMART_CUSTOM_IMG_FILE, + ), + ) + ] = cv.string + + # Only show FedEx custom image file field if FedEx custom image is enabled + if user_input.get(CONF_FEDEX_CUSTOM_IMG): + schema[ + vol.Optional( + CONF_FEDEX_CUSTOM_IMG_FILE, + default=_get_default( + CONF_FEDEX_CUSTOM_IMG_FILE, + DEFAULT_FEDEX_CUSTOM_IMG_FILE, + ), + ) + ] = cv.string + + # Only show Generic custom image file field if Generic custom image is enabled + if user_input.get(CONF_GENERIC_CUSTOM_IMG): + schema[ + vol.Optional( + CONF_GENERIC_CUSTOM_IMG_FILE, + default=_get_default( + CONF_GENERIC_CUSTOM_IMG_FILE, + DEFAULT_GENERIC_CUSTOM_IMG_FILE, + ), + ) + ] = cv.string + + # Only show Post DE custom image file field if Post DE custom image is enabled + if user_input.get(CONF_POST_DE_CUSTOM_IMG): + schema[ + vol.Optional( + CONF_POST_DE_CUSTOM_IMG_FILE, + default=_get_default( + CONF_POST_DE_CUSTOM_IMG_FILE, + DEFAULT_POST_DE_CUSTOM_IMG_FILE, + ), + ) + ] = cv.string + + return vol.Schema(schema) + + +def _get_schema_step_amazon( + user_input: list, + default_dict: list, + forwarding_header: str = "", +) -> 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)) + + schema_dict: dict = { + vol.Required( + CONF_AMAZON_DOMAIN, + default=_get_default(CONF_AMAZON_DOMAIN), + ): cv.string, + } + + if not forwarding_header or forwarding_header == "(none)": + schema_dict[ + vol.Optional( + CONF_AMAZON_FWDS, + default=_get_default(CONF_AMAZON_FWDS), + ) + ] = cv.string + + schema_dict[ + vol.Optional(CONF_AMAZON_DAYS, default=_get_default(CONF_AMAZON_DAYS)) + ] = int + + return vol.Schema(schema_dict) + + +def _get_schema_step_forwarded_emails( + user_input: list, + default_dict: list, +) -> vol.Schema: + """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) -> list: + """Get default value for key.""" + value = user_input.get(key, default_dict.get(key, fallback_default)) + if isinstance(value, list): + value = ", ".join(value) + return value + + return vol.Schema( + { + vol.Optional( + CONF_FORWARDING_HEADER, + default=_get_default(CONF_FORWARDING_HEADER, DEFAULT_FORWARDING_HEADER), + ): cv.string, + vol.Optional( + CONF_FORWARDED_EMAILS, + default=_get_default(CONF_FORWARDED_EMAILS, DEFAULT_FORWARDED_EMAILS), + ): cv.string, + }, + ) + + +def _get_schema_step_storage(user_input: dict, default_dict: dict) -> 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, DEFAULT_STORAGE), + ): cv.string, + }, + ) + + +async def _validate_login( + hass: HomeAssistant, + user_input: dict[str, Any], +) -> dict[str, str]: + """Validate login credentials.""" + errors = {} + _LOGGER.debug("Testing login...") + + auth_type = user_input.get(CONF_AUTH_TYPE, AUTH_TYPE_PASSWORD) + + # Skip login validation for OAuth2 — auth happens via the OAuth flow + if auth_type != AUTH_TYPE_PASSWORD: + return errors + + imap_client = None + try: + imap_client = await login( + hass, + host=user_input[CONF_HOST], + port=user_input[CONF_PORT], + user=user_input[CONF_USERNAME], + pwd=user_input[CONF_PASSWORD], + security=user_input[CONF_IMAP_SECURITY], + verify=user_input[CONF_VERIFY_SSL], + ) + result, data = await imap_client.select() + + except InvalidAuth: + errors[CONF_USERNAME] = errors[CONF_PASSWORD] = "invalid_auth" + except ssl.SSLError: + errors["base"] = "ssl_error" + except (TimeoutError, AioImapException, ConnectionRefusedError) as err: + _LOGGER.error("Unable to connect: %s", err) + errors["base"] = "cannot_connect" + else: + if result != "OK": + errors["base"] = "missing_inbox" + finally: + if imap_client is not None: + await logout(imap_client) + + return errors + + +@config_entries.HANDLERS.register(DOMAIN) +class MailAndPackagesFlowHandler( + config_entry_oauth2_flow.AbstractOAuth2FlowHandler, + domain=DOMAIN, +): + """Config flow for Mail and Packages.""" + + VERSION = CONFIG_VER + CONNECTION_CLASS = config_entries.CONN_CLASS_CLOUD_POLL + DOMAIN = DOMAIN + + @property + def logger(self) -> logging.Logger: + """Return logger.""" + return _LOGGER + + @property + def extra_authorize_data(self) -> dict: + """Extra data that needs to be appended to the authorize url.""" + auth_type = self._data.get(CONF_AUTH_TYPE, AUTH_TYPE_PASSWORD) + scopes = OAUTH_SCOPES.get(auth_type, "") + data = {"scope": scopes} + if auth_type == AUTH_TYPE_OAUTH_GOOGLE: + data.update( + { + "access_type": "offline", + "prompt": "consent", + } + ) + return data + + def __init__(self): + """Initialize.""" + super().__init__() + self._entry = None + self._data = {} + self._errors = {} + + async def async_step_user(self, user_input=None): + """Handle a flow initialized by the user.""" + self._errors = {} + + if user_input is not None: + self._data.update(user_input) + return await self.async_step_imap_config() + + return await self._show_auth_form(user_input) + + async def async_step_reauth( + self, entry_data: Mapping[str, Any] + ) -> ConfigFlowResult: + """Handle re-authentication.""" + self._entry = self.hass.config_entries.async_get_entry(self.context["entry_id"]) + self._data.update(entry_data) + return await self.async_step_reauth_confirm() + + async def async_step_reauth_confirm( + self, user_input: dict[str, Any] | None = None + ) -> ConfigFlowResult: + """Confirm re-authentication.""" + self._errors = {} + auth_type = self._data.get(CONF_AUTH_TYPE, AUTH_TYPE_PASSWORD) + + if user_input is not None: + self._data.update(user_input) + if auth_type != AUTH_TYPE_PASSWORD: + return await self.async_step_pick_implementation() + + self._errors = await _validate_login(self.hass, self._data) + if not self._errors: + return self.async_update_reload_and_abort( + self._entry, + data=self._data, + ) + + if auth_type != AUTH_TYPE_PASSWORD: + return self.async_show_form(step_id="reauth_confirm") + + schema = vol.Schema( + { + vol.Required(CONF_USERNAME, default=self._data.get(CONF_USERNAME)): str, + vol.Required(CONF_PASSWORD): str, + } + ) + return self.async_show_form( + step_id="reauth_confirm", data_schema=schema, errors=self._errors + ) + + async def async_step_imap_config(self, user_input=None): + """Handle IMAP config step after auth selection.""" + self._errors = {} + + if user_input is not None: + self._data.update(user_input) + auth_type = self._data.get(CONF_AUTH_TYPE, AUTH_TYPE_PASSWORD) + + if auth_type != AUTH_TYPE_PASSWORD: + # OAuth2 flow: store provider and auto-fill IMAP defaults + self._data[CONF_VERIFY_SSL] = True + self.hass.data.setdefault(DOMAIN, {}) + self.hass.data[DOMAIN]["oauth_provider"] = auth_type + return await self.async_step_pick_implementation() + + # Password flow: validate login + self._errors = await _validate_login( + self.hass, + self._data, + ) + if self._errors == {}: + return await self.async_step_config_2() + + return await self._show_imap_form(user_input) + + return await self._show_imap_form(user_input) + + async def async_oauth_create_entry( + self, + data: dict, + ) -> config_entries.ConfigFlowResult: + """Handle OAuth2 completion — store token and continue to step 2.""" + self._data.update(data) + if self._entry: + if self.source == config_entries.SOURCE_REAUTH: + return self.async_update_reload_and_abort( + self._entry, + data=self._data, + ) + return await self.async_step_reconfig_2() + return await self.async_step_config_2() + + async def _show_auth_form(self, user_input): + """Show the authentication form.""" + defaults = {CONF_AUTH_TYPE: AUTH_TYPE_PASSWORD} + return self.async_show_form( + step_id="user", + data_schema=_get_schema_auth(user_input, defaults), + errors=self._errors, + ) + + async def _show_imap_form(self, user_input): + """Show the configuration form to edit IMAP configuration data.""" + auth_type = self._data.get(CONF_AUTH_TYPE, AUTH_TYPE_PASSWORD) + defaults = OAUTH_IMAP_DEFAULTS.get( + auth_type, + { + CONF_PORT: DEFAULT_PORT, + CONF_IMAP_SECURITY: "SSL", + CONF_VERIFY_SSL: False, + }, + ) + defaults[CONF_AUTH_TYPE] = auth_type + + return self.async_show_form( + step_id="imap_config", + data_schema=_get_schema_imap(user_input, defaults), + errors=self._errors, + ) + + async def async_step_config_2(self, user_input=None): + """Configure form step 2.""" + self._errors = {} + if user_input is not None: + self._errors, user_input = await _validate_user_input(user_input) + self._data.update(user_input) + _LOGGER.debug("RESOURCES: %s", self._data[CONF_RESOURCES]) + if len(self._errors) == 0: + if self._data[CONF_ALLOW_FORWARDED_EMAILS]: + return await self.async_step_config_forwarded_emails() + if any( + sensor in self._data[CONF_RESOURCES] for sensor in AMAZON_SENSORS + ): + return await self.async_step_config_amazon() + has_custom_image = ( + self._data.get(CONF_CUSTOM_IMG) + or self._data.get(CONF_AMAZON_CUSTOM_IMG) + or self._data.get(CONF_UPS_CUSTOM_IMG) + or self._data.get(CONF_WALMART_CUSTOM_IMG) + or self._data.get(CONF_FEDEX_CUSTOM_IMG) + or self._data.get(CONF_GENERIC_CUSTOM_IMG) + or self._data.get(CONF_POST_DE_CUSTOM_IMG) + ) + if has_custom_image: + return await self.async_step_config_3() + + return self.async_create_entry( + title=f"Mail and Packages ({self._data[CONF_HOST]})", + data=self._data, + ) + return await self._show_config_2(user_input) + + return await self._show_config_2(user_input) + + async def _show_config_2(self, user_input): + """Step 2 setup.""" + # Defaults + defaults = { + CONF_FOLDER: DEFAULT_FOLDER, + CONF_SCAN_INTERVAL: DEFAULT_SCAN_INTERVAL, + CONF_CUSTOM_DAYS: DEFAULT_CUSTOM_DAYS, + CONF_PATH: self.hass.config.path() + DEFAULT_PATH, + CONF_DURATION: DEFAULT_GIF_DURATION, + CONF_IMAGE_SECURITY: DEFAULT_IMAGE_SECURITY, + CONF_IMAP_TIMEOUT: DEFAULT_IMAP_TIMEOUT, + CONF_GENERATE_GRID: False, + CONF_GENERATE_MP4: False, + CONF_ALLOW_EXTERNAL: DEFAULT_ALLOW_EXTERNAL, + CONF_CUSTOM_IMG: DEFAULT_CUSTOM_IMG, + CONF_AMAZON_CUSTOM_IMG: DEFAULT_AMAZON_CUSTOM_IMG, + CONF_UPS_CUSTOM_IMG: DEFAULT_UPS_CUSTOM_IMG, + CONF_WALMART_CUSTOM_IMG: DEFAULT_WALMART_CUSTOM_IMG, + CONF_FEDEX_CUSTOM_IMG: DEFAULT_FEDEX_CUSTOM_IMG, + CONF_GENERIC_CUSTOM_IMG: DEFAULT_GENERIC_CUSTOM_IMG, + CONF_POST_DE_CUSTOM_IMG: DEFAULT_POST_DE_CUSTOM_IMG, + CONF_ALLOW_FORWARDED_EMAILS: DEFAULT_ALLOW_FORWARDED_EMAILS, + } + + return self.async_show_form( + step_id="config_2", + data_schema=await _get_schema_step_2( + self._data, + user_input, + defaults, + self.hass, + ), + errors=self._errors, + ) + + async def async_step_config_3(self, user_input=None): + """Configure form step 2.""" + 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 await self.async_step_config_storage() + return await self._show_config_3(user_input) + + return await self._show_config_3(user_input) + + async def _show_config_3(self, user_input=None): # pylint: disable=unused-argument + """Step 3 setup.""" + # Defaults + defaults = { + CONF_CUSTOM_IMG_FILE: DEFAULT_CUSTOM_IMG_FILE, + CONF_AMAZON_CUSTOM_IMG_FILE: DEFAULT_AMAZON_CUSTOM_IMG_FILE, + CONF_UPS_CUSTOM_IMG_FILE: DEFAULT_UPS_CUSTOM_IMG_FILE, + CONF_WALMART_CUSTOM_IMG_FILE: DEFAULT_WALMART_CUSTOM_IMG_FILE, + CONF_FEDEX_CUSTOM_IMG_FILE: DEFAULT_FEDEX_CUSTOM_IMG_FILE, + CONF_GENERIC_CUSTOM_IMG_FILE: DEFAULT_GENERIC_CUSTOM_IMG_FILE, + CONF_POST_DE_CUSTOM_IMG_FILE: DEFAULT_POST_DE_CUSTOM_IMG_FILE, + } + + return self.async_show_form( + step_id="config_3", + data_schema=_get_schema_step_3(self._data, defaults), + errors=self._errors, + ) + + async def async_step_config_amazon(self, user_input=None): + """Configure form step amazon.""" + 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: + if ( + self._data.get(CONF_CUSTOM_IMG) + or self._data.get(CONF_AMAZON_CUSTOM_IMG) + or self._data.get(CONF_UPS_CUSTOM_IMG) + or self._data.get(CONF_WALMART_CUSTOM_IMG) + or self._data.get(CONF_GENERIC_CUSTOM_IMG) + or self._data.get(CONF_POST_DE_CUSTOM_IMG) + ): + return await self.async_step_config_3() + return await self.async_step_config_storage() + + return await self._show_config_amazon(user_input) + + return await self._show_config_amazon(user_input) + + async def _show_config_amazon(self, user_input): + """Step 3 setup.""" + # Defaults + defaults = { + CONF_AMAZON_DOMAIN: DEFAULT_AMAZON_DOMAIN, + CONF_AMAZON_FWDS: DEFAULT_AMAZON_FWDS, + CONF_AMAZON_DAYS: DEFAULT_AMAZON_DAYS, + } + + return self.async_show_form( + step_id="config_amazon", + data_schema=_get_schema_step_amazon( + user_input, + defaults, + forwarding_header=self._data.get(CONF_FORWARDING_HEADER, ""), + ), + errors=self._errors, + ) + + async def async_step_config_forwarded_emails(self, user_input=None): + """Configure form step forwarded emails.""" + 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: + if any( + sensor in self._data[CONF_RESOURCES] for sensor in AMAZON_SENSORS + ): + return await self.async_step_config_amazon() + if self._data[CONF_CUSTOM_IMG]: + return await self.async_step_config_3() + + return await self.async_step_config_storage() + + return await self._show_config_forwarded_emails(user_input) + + return await self._show_config_forwarded_emails(user_input) + + async def _show_config_forwarded_emails(self, user_input): + """Configure forwarded emails setup.""" + # Defaults + defaults = { + CONF_FORWARDED_EMAILS: DEFAULT_FORWARDED_EMAILS, + } + + return self.async_show_form( + step_id="config_forwarded_emails", + data_schema=_get_schema_step_forwarded_emails(user_input, defaults), + 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=f"Mail and Packages ({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"]) + assert self._entry + self._data = dict(self._entry.data) + self._errors = {} + + if user_input is not None: + self._data.update(user_input) + return await self.async_step_reconfig_imap() + + return await self._show_reconfig_auth_form(user_input) + + async def async_step_reconfig_imap(self, user_input=None): + """Handle IMAP step for reconfigure.""" + self._errors = {} + + if user_input is not None: + self._data.update(user_input) + auth_type = self._data.get(CONF_AUTH_TYPE, AUTH_TYPE_PASSWORD) + + if auth_type != AUTH_TYPE_PASSWORD: + self._data[CONF_VERIFY_SSL] = True + self.hass.data.setdefault(DOMAIN, {}) + self.hass.data[DOMAIN]["oauth_provider"] = auth_type + return await self.async_step_pick_implementation() + + self._errors = await _validate_login(self.hass, self._data) + if self._errors == {}: + return await self.async_step_reconfig_2() + + return await self._show_reconfig_imap_form(user_input) + + return await self._show_reconfig_imap_form(user_input) + + async def _show_reconfig_auth_form(self, user_input): + """Show the auth form for reconfigure.""" + defaults = { + CONF_AUTH_TYPE: self._entry.data.get(CONF_AUTH_TYPE, AUTH_TYPE_PASSWORD), + } + return self.async_show_form( + step_id="reconfigure", + data_schema=_get_schema_auth(user_input, defaults), + errors=self._errors, + ) + + async def _show_reconfig_imap_form(self, user_input): + """Show the configuration form to edit IMAP data.""" + auth_type = self._data.get(CONF_AUTH_TYPE, AUTH_TYPE_PASSWORD) + defaults = OAUTH_IMAP_DEFAULTS.get( + auth_type, + { + CONF_PORT: self._entry.data.get(CONF_PORT, DEFAULT_PORT), + CONF_IMAP_SECURITY: self._entry.data.get(CONF_IMAP_SECURITY, "SSL"), + CONF_VERIFY_SSL: self._entry.data.get(CONF_VERIFY_SSL, False), + }, + ) + + defaults[CONF_HOST] = self._entry.data.get(CONF_HOST, defaults.get(CONF_HOST)) + defaults[CONF_USERNAME] = self._entry.data.get( + CONF_USERNAME, + defaults.get(CONF_USERNAME), + ) + defaults[CONF_PASSWORD] = self._entry.data.get( + CONF_PASSWORD, + defaults.get(CONF_PASSWORD), + ) + defaults[CONF_AUTH_TYPE] = auth_type + + return self.async_show_form( + step_id="reconfig_imap", + data_schema=_get_schema_imap(user_input, defaults), + errors=self._errors, + ) + + async def async_step_reconfig_2(self, user_input=None): + """Configure form step 2.""" + self._errors = {} + _LOGGER.debug("Loading step 2...") + if user_input is not None: + self._data.update(user_input) + self._errors, user_input = await _validate_user_input(user_input) + if len(self._errors) == 0: + if self._data.get(CONF_ALLOW_FORWARDED_EMAILS, False): + return await self.async_step_reconfig_forwarded_emails() + + if any( + sensor in self._data.get(CONF_RESOURCES, []) + for sensor in AMAZON_SENSORS + ): + return await self.async_step_reconfig_amazon() + has_custom_image = ( + self._data.get(CONF_CUSTOM_IMG) + or self._data.get(CONF_AMAZON_CUSTOM_IMG) + or self._data.get(CONF_UPS_CUSTOM_IMG) + or self._data.get(CONF_WALMART_CUSTOM_IMG) + or self._data.get(CONF_FEDEX_CUSTOM_IMG) + or self._data.get(CONF_GENERIC_CUSTOM_IMG) + or self._data.get(CONF_POST_DE_CUSTOM_IMG) + ) + if has_custom_image: + return await self.async_step_reconfig_3() + + return await self.async_step_reconfig_storage() + + return await self._show_reconfig_2(user_input) + + return await self._show_reconfig_2(user_input) + + async def _show_reconfig_2(self, user_input): + """Step 2 setup.""" + return self.async_show_form( + step_id="reconfig_2", + data_schema=await _get_schema_step_2( + self._data, + user_input, + self._data, + self.hass, + ), + errors=self._errors, + ) + + async def async_step_reconfig_3(self, user_input=None): + """Configure form step 2.""" + 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 await self.async_step_reconfig_storage() + + return await self._show_reconfig_3(user_input) + + return await self._show_reconfig_3(user_input) + + async def _show_reconfig_3(self, user_input=None): # pylint: disable=unused-argument + """Step 3 setup.""" + # Defaults + defaults = { + CONF_CUSTOM_IMG_FILE: DEFAULT_CUSTOM_IMG_FILE, + CONF_AMAZON_CUSTOM_IMG_FILE: DEFAULT_AMAZON_CUSTOM_IMG_FILE, + CONF_UPS_CUSTOM_IMG_FILE: DEFAULT_UPS_CUSTOM_IMG_FILE, + CONF_WALMART_CUSTOM_IMG_FILE: DEFAULT_WALMART_CUSTOM_IMG_FILE, + CONF_FEDEX_CUSTOM_IMG_FILE: DEFAULT_FEDEX_CUSTOM_IMG_FILE, + CONF_GENERIC_CUSTOM_IMG_FILE: DEFAULT_GENERIC_CUSTOM_IMG_FILE, + CONF_POST_DE_CUSTOM_IMG_FILE: DEFAULT_POST_DE_CUSTOM_IMG_FILE, + } + + return self.async_show_form( + step_id="reconfig_3", + data_schema=_get_schema_step_3(self._data, defaults), + errors=self._errors, + ) + + async def async_step_reconfig_amazon(self, user_input=None): + """Configure form step amazon.""" + 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: + has_custom_image = ( + self._data.get(CONF_CUSTOM_IMG) + or self._data.get(CONF_AMAZON_CUSTOM_IMG) + or self._data.get(CONF_UPS_CUSTOM_IMG) + or self._data.get(CONF_WALMART_CUSTOM_IMG) + or self._data.get(CONF_FEDEX_CUSTOM_IMG) + or self._data.get(CONF_GENERIC_CUSTOM_IMG) + or self._data.get(CONF_POST_DE_CUSTOM_IMG) + ) + if has_custom_image: + 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.""" + if self._data.get(CONF_AMAZON_FWDS, []) == []: + self._data[CONF_AMAZON_FWDS] = "(none)" + + return self.async_show_form( + step_id="reconfig_amazon", + data_schema=_get_schema_step_amazon( + user_input, + self._data, + forwarding_header=self._data.get(CONF_FORWARDING_HEADER, ""), + ), + errors=self._errors, + ) + + async def async_step_reconfig_forwarded_emails( + self, + user_input: dict[str, Any] | None = None, + ): + """Configure form step forwarded emails.""" + 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: + if any( + sensor in self._data.get(CONF_RESOURCES, []) + for sensor in AMAZON_SENSORS + ): + return await self.async_step_reconfig_amazon() + if self._data.get(CONF_CUSTOM_IMG, False): + return await self.async_step_reconfig_3() + return await self.async_step_reconfig_storage() + return await self._show_reconfig_forwarded_emails(user_input) + return await self._show_reconfig_forwarded_emails(user_input) + + async def _show_reconfig_forwarded_emails(self, user_input=None): + """Step forwarded emails.""" + if self._data.get(CONF_FORWARDED_EMAILS, []) == []: + self._data[CONF_FORWARDED_EMAILS] = "(none)" + + return self.async_show_form( + step_id="reconfig_forwarded_emails", + data_schema=_get_schema_step_forwarded_emails(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_storage(user_input) + + return await self._show_reconfig_storage(user_input) + + async def _show_reconfig_storage(self, user_input): + """Step 3 setup.""" + return self.async_show_form( + step_id="reconfig_storage", + data_schema=_get_schema_step_storage(user_input, self._data), + errors=self._errors, + ) diff --git a/custom_components/mail_and_packages/const.py b/custom_components/mail_and_packages/const.py new file mode 100644 index 0000000..26e07bd --- /dev/null +++ b/custom_components/mail_and_packages/const.py @@ -0,0 +1,1812 @@ +"""Constants for Mail and Packages.""" + +from __future__ import annotations + +from typing import Final + +from homeassistant.components.binary_sensor import BinarySensorDeviceClass +from homeassistant.components.sensor import SensorDeviceClass, SensorEntityDescription +from homeassistant.helpers.entity import EntityCategory + +from .entity import MailandPackagesBinarySensorEntityDescription + +DOMAIN = "mail_and_packages" +DOMAIN_DATA = f"{DOMAIN}_data" +VERSION = "0.5.9" +ISSUE_URL = "http://github.com/moralmunky/Home-Assistant-Mail-And-Packages" +PLATFORM = "sensor" +PLATFORMS = ["binary_sensor", "camera", "sensor"] +DATA = "data" +COORDINATOR = "coordinator_mail" +OVERLAY = ["overlay.png", "vignette.png", "white.png"] +SERVICE_UPDATE_FILE_PATH = "update_file_path" +CAMERA = "cameras" +CONFIG_VER = 19 + +# Attributes +ATTR_AMAZON_IMAGE = "amazon_image" +ATTR_COUNT = "count" +ATTR_CODE = "code" +ATTR_GRID_IMAGE_NAME = "grid_image" +ATTR_ORDER = "order" +ATTR_TRACKING = "tracking" +ATTR_TRACKING_NUM = "tracking_#" +ATTR_IMAGE = "image" +ATTR_IMAGE_PATH = "image_path" +ATTR_SERVER = "server" +ATTR_IMAGE_NAME = "image_name" +ATTR_EMAIL = "email" +ATTR_SUBJECT = "subject" +ATTR_BODY = "body" +ATTR_BODY_COUNT = "body_count" +ATTR_PATTERN = "pattern" +ATTR_USPS_MAIL = "usps_mail" +ATTR_UPS_IMAGE = "ups_image" +ATTR_WALMART_IMAGE = "walmart_image" +ATTR_FEDEX_IMAGE = "fedex_image" +ATTR_GENERIC_IMAGE = "generic_image" +ATTR_USPS_IMAGE = "usps_image" +ATTR_POST_DE_IMAGE = "post_de_image" + +# Configuration Properties +CONF_ALLOW_EXTERNAL = "allow_external" +CONF_CAMERA_NAME = "camera_name" +CONF_CUSTOM_IMG = "custom_img" +CONF_CUSTOM_IMG_FILE = "custom_img_file" +CONF_AMAZON_CUSTOM_IMG = "amazon_custom_img" +CONF_AMAZON_CUSTOM_IMG_FILE = "amazon_custom_img_file" +CONF_UPS_CUSTOM_IMG = "ups_custom_img" +CONF_UPS_CUSTOM_IMG_FILE = "ups_custom_img_file" +CONF_WALMART_CUSTOM_IMG = "walmart_custom_img" +CONF_WALMART_CUSTOM_IMG_FILE = "walmart_custom_img_file" +CONF_FEDEX_CUSTOM_IMG = "fedex_custom_img" +CONF_FEDEX_CUSTOM_IMG_FILE = "fedex_custom_img_file" +CONF_GENERIC_CUSTOM_IMG = "generic_custom_img" +CONF_GENERIC_CUSTOM_IMG_FILE = "generic_custom_img_file" +CONF_POST_DE_CUSTOM_IMG = "post_de_custom_img" +CONF_POST_DE_CUSTOM_IMG_FILE = "post_de_custom_img_file" +CONF_STORAGE = "storage" +CONF_FOLDER = "folder" +CONF_PATH = "image_path" +CONF_DURATION = "gif_duration" +CONF_SCAN_INTERVAL = "scan_interval" +CONF_IMAGE_SECURITY = "image_security" +CONF_IMAP_TIMEOUT = "imap_timeout" +CONF_GENERATE_GRID = "generate_grid" +CONF_GENERATE_MP4 = "generate_mp4" +CONF_AMAZON_FWDS = "amazon_fwds" +CONF_AMAZON_DAYS = "amazon_days" +CONF_VERIFY_SSL = "verify_ssl" +CONF_IMAP_SECURITY = "imap_security" +CONF_AMAZON_DOMAIN = "amazon_domain" +CONF_ALLOW_FORWARDED_EMAILS = "allow_forwarded_emails" +CONF_FORWARDED_EMAILS = "forwarded_emails" +CONF_FORWARDING_HEADER = "forwarding_header" +CONF_CUSTOM_DAYS = "custom_days" + +# Defaults +DEFAULT_CAMERA_NAME = "Mail USPS Camera" +DEFAULT_NAME = "Mail And Packages" +DEFAULT_PORT = "993" +DEFAULT_FOLDER = "INBOX" +DEFAULT_PATH = "custom_components/mail_and_packages/images/" +DEFAULT_IMAGE_SECURITY = True +DEFAULT_IMAP_TIMEOUT = 60 +DEFAULT_GIF_DURATION = 5 +DEFAULT_SCAN_INTERVAL = 30 +DEFAULT_CUSTOM_DAYS = 3 +MAX_TRACKING_AGE_DAYS = 14 +DEFAULT_GIF_FILE_NAME = "mail_today.gif" +DEFAULT_AMAZON_FWDS = "(none)" +DEFAULT_ALLOW_EXTERNAL = False +DEFAULT_CUSTOM_IMG = False +DEFAULT_CUSTOM_IMG_FILE = "custom_components/mail_and_packages/mail_none.gif" +DEFAULT_AMAZON_CUSTOM_IMG = False +DEFAULT_AMAZON_CUSTOM_IMG_FILE = ( + "custom_components/mail_and_packages/no_deliveries_amazon.jpg" +) +DEFAULT_UPS_CUSTOM_IMG = False +DEFAULT_UPS_CUSTOM_IMG_FILE = ( + "custom_components/mail_and_packages/no_deliveries_ups.jpg" +) +DEFAULT_WALMART_CUSTOM_IMG = False +DEFAULT_WALMART_CUSTOM_IMG_FILE = ( + "custom_components/mail_and_packages/no_deliveries_walmart.jpg" +) +DEFAULT_FEDEX_CUSTOM_IMG = False +DEFAULT_FEDEX_CUSTOM_IMG_FILE = ( + "custom_components/mail_and_packages/no_deliveries_fedex.jpg" +) +DEFAULT_GENERIC_CUSTOM_IMG = False +DEFAULT_GENERIC_CUSTOM_IMG_FILE = ( + "custom_components/mail_and_packages/no_deliveries_generic.jpg" +) +DEFAULT_POST_DE_CUSTOM_IMG = False +DEFAULT_POST_DE_CUSTOM_IMG_FILE = "custom_components/mail_and_packages/mail_none.gif" +DEFAULT_AMAZON_DAYS = 3 +DEFAULT_AMAZON_DOMAIN = "amazon.com" +DEFAULT_STORAGE = "custom_components/mail_and_packages/images/" + +DEFAULT_ALLOW_FORWARDED_EMAILS = False +DEFAULT_FORWARDED_EMAILS = "(none)" +DEFAULT_FORWARDING_HEADER = "(none)" + +# Amazon +AMAZON_DOMAINS = [ + "amazon.com", + "amazon.ca", + "amazon.co.uk", + "amazon.in", + "amazon.de", + "amazon.it", + "amazon.com.au", + "amazon.pl", + "amazon.es", + "amazon.fr", + "amazon.ae", + "amazon.nl", +] +AMAZON_DELIVERED_SUBJECT = [ + "Delivered: ", + "Your Amazon order has arrived!", + "Consegna effettuata:", + "Dostarczono:", + "Geliefert:", + "Livré", + "Entregado:", + "Bezorgd:", + "Livraison : Votre", + "Zugestellt:", +] +AMAZON_SHIPMENT_TRACKING = [ + "auto-confirm", + "shipment-tracking", + "order-update", + "conferma-spedizione", + "confirmar-envio", + "versandbestaetigung", + "confirmation-commande", + "verzending-volgen", + "update-bestelling", +] +AMAZON_SHIPMENT_SUBJECT = [ + "Shipped:", + "Enviado:", + "Out for delivery:", +] +AMAZON_ORDERED_SUBJECT = ["Ordered:", "Pedido efetuado:"] +AMAZON_EMAIL = [ + "order-update@", + "update-bestelling@", + "versandbestaetigung@", + "verzending-volgen@", + "auto-bevestiging@", +] +AMAZON_PACKAGES = "amazon_packages" +AMAZON_ORDER = "amazon_order" +AMAZON_DELIVERED = "amazon_delivered" +AMAZON_IMG_LIST = [ + "us-prod-temp.s3.amazonaws.com", + "gb-prod-temp.s3.eu-west-1.amazonaws.com", +] +AMAZON_IMG_PATTERN = ( + "(https://)([\\w_-]+(?:(?:\\.[\\w_-]+)+))([\\w.,@?^=%&:/~+#-;]*[\\w@?^=%&/~+#-;])?" +) +AMAZON_HUB = "amazon_hub" +AMAZON_HUB_CODE = "amazon_hub_code" +AMAZON_HUB_EMAIL = [ + "thehub@amazon.com", + "order-update@amazon.com", + "amazonlockers@amazon.com", + "versandbestaetigung@amazon.de", +] +AMAZON_HUB_SUBJECT = ["ready for pickup from Amazon Hub Locker"] +AMAZON_HUB_SUBJECT_SEARCH = "(a package to pick up)(.*)(\\d{6})" +AMAZON_HUB_BODY = "(Your pickup code is )(\\d{6})" +AMAZON_TIME_PATTERN = [ + "will arrive:", + "estimated delivery date is:", + "guaranteed delivery date is:", + "Arriving:", + "Arriverà:", + "arriving:", + "Arriving ", + "Dostawa:", + "Entrega:", + "A chegar:", + "Arrivée :", + "Chega ", + "Verwachte bezorgdatum:", + "Votre date de livraison prévue est :", +] +AMAZON_TIME_PATTERN_END = [ + "Previously expected:", + "This contains", + "Track your", + "Per tracciare il tuo pacco", + "View or manage order", + "Acompanhar", + "Seguimiento", + "Verfolge deine(n) Artikel", + "Lieferung verfolgen", + "Ihr Paket verfolgen", + "Suivre", + "Volg je pakket", + "Je pakket volgen", +] +AMAZON_TIME_PATTERN_REGEX = [ + "Arriving (\\w+ \\d+) - (\\w+ \\d+)", + "Arriving (\\w+ \\d+)", + "Arriving (\\w+ ?\\d*)", + "Arriving (\\w+)", + "Zustellung (\\w+ \\d+) - (\\w+ \\d+)", + "Zustellung (\\w+ \\d+)", + "Zustellung (\\w+ \\d*)", + "Arriverà (\\w+ \\d+) - (\\w+ \\d+)", + "Arriverà (\\w+ \\d+)", + "Arriverà (\\w+ \\d*)", + "Arrivée (\\w+ \\d+) - (\\w+ \\d+)", + "Arrivée (\\w+ \\d+)", + "Arrivée (\\w+ \\d*)", + "Chega ((\\w+(-\\w+)?))", + "Wordt bezorgd op (\\w+ \\d+ \\w+)", + "Wordt bezorgd op (\\w+ \\d+)", + "Wordt (\\w+) bezorgd", +] +AMAZON_EXCEPTION_SUBJECT = "Delivery update:" +AMAZON_EXCEPTION_BODY = "running late" +AMAZON_EXCEPTION = "amazon_exception" +AMAZON_EXCEPTION_ORDER = "amazon_exception_order" +AMAZON_PATTERN = "[0-9]{3}-[0-9]{7}-[0-9]{7}" +AMAZON_LANGS = [ + "it_IT", + "it_IT.UTF-8", + "pl_PL", + "pl_PL.UTF-8", + "de_DE", + "de_DE.UTF-8", + "es_ES", + "es_ES.UTF-8", + "pt_PT", + "pt_PT.UTF-8", + "pt_BR", + "pt_BR.UTF-8", + "fr_CA", + "fr_CA.UTF-8", + "", +] +AMAZON_OTP = "amazon_otp" +AMAZON_OTP_CODE = "amazon_otp_code" +AMAZON_OTP_REGEX = "(\n)(\\d{6})(\n)" +AMAZON_OTP_SUBJECT = "A one-time password is required for your Amazon delivery" + +AMAZON_DELIEVERED_BY_OTHERS_SEARCH_TEXT = ["AMAZON"] + +# Sensor Data +SENSOR_DATA = { + # USPS + "usps_delivered": { + "email": ["auto-reply@usps.com", "auto-reply@tracking.usps.com"], + "subject": ["Item Delivered"], + }, + "usps_delivering": { + "email": ["auto-reply@usps.com", "auto-reply@tracking.usps.com"], + "subject": ["Expected Delivery on", "Out for Delivery"], + "body": ["Your item is out for delivery"], + }, + "usps_exception": { + "email": ["auto-reply@usps.com", "auto-reply@tracking.usps.com"], + "subject": ["Delivery Exception"], + }, + "usps_packages": { + "email": ["auto-reply@usps.com", "auto-reply@tracking.usps.com"], + "subject": ["Expected Delivery by"], + }, + "usps_tracking": {"pattern": ["9[2345]\\d{15,26}"]}, + "usps_mail": { + "email": [ + "USPSInformedDelivery@usps.gov", + "USPSInformeddelivery@email.informeddelivery.usps.com", + "USPSInformeddelivery@informeddelivery.usps.com", + "USPS Informed Delivery", + ], + "subject": ["Your Daily Digest"], + }, + "usps_mail_delivered": { + "email": [ + "USPSInformedDelivery@usps.gov", + "USPSInformeddelivery@email.informeddelivery.usps.com", + "USPSInformeddelivery@informeddelivery.usps.com", + "USPS Informed Delivery", + ], + "subject": ["Your Mail Was Delivered"], + }, + # UPS + "ups_delivered": { + "email": ["mcinfo@ups.com", "pkginfo@ups.com"], + "subject": [ + "Your UPS Package was delivered", + "Your UPS Packages were delivered", + "Your UPS Parcel was delivered", + "Your UPS Parcels were delivered", + "Votre colis UPS a été livré", + "Paket wurde zugestellt", + ], + }, + "ups_delivering": { + "email": ["mcinfo@ups.com", "pkginfo@ups.com"], + "subject": [ + "UPS Update: Package Scheduled for Delivery Today", + "UPS Update: Follow Your Delivery on a Live Map", + "UPS Pre-Arrival: Your Driver is Arriving Soon! Follow on a Live Map", + "UPS Update: Parcel Scheduled for Delivery Today", + "Mise à jour UPS : Livraison du colis prévue demain", + "Mise à jour UPS : Livraison du colis prévue aujourd'hui", + ], + }, + "ups_exception": { + "email": ["mcinfo@ups.com"], + "subject": ["UPS Update: New Scheduled Delivery Date"], + }, + "ups_packages": { + "email": ["mcinfo@ups.com", "pkginfo@ups.com"], + "subject": ["UPS Ship Notification"], + }, + "ups_tracking": {"pattern": ["1Z?[0-9A-Z]{16}"]}, + # FedEx + "fedex_delivered": { + "email": [ + "TrackingUpdates@fedex.com", + "fedexcanada@fedex.com", + "noreply@fedex.com", + ], + "subject": [ + "Your package has been delivered", + "Your packages have been delivered", + "Your shipment was delivered", + ], + }, + "fedex_delivering": { + "email": [ + "TrackingUpdates@fedex.com", + "fedexcanada@fedex.com", + "noreply@fedex.com", + ], + "subject": [ + "Delivery scheduled for today", + "Your package is scheduled for delivery today", + "Your package is now out for delivery", + "Your shipment is out for delivery today", + "out for delivery today", + "Ihre Sendung wird voraussichtlich heute zugestellt", + ], + }, + "fedex_packages": { + "email": [ + "TrackingUpdates@fedex.com", + "fedexcanada@fedex.com", + "noreply@fedex.com", + ], + "subject": ["Your shipment is on the way"], + }, + "fedex_exception": { + "email": [ + "TrackingUpdates@fedex.com", + "fedexcanada@fedex.com", + "noreply@fedex.com", + ], + # Subject confirmed against a real FedEx delivery-exception + # notification (From: trackingupdates@fedex.com, Subject: + # "FedEx Delivery Exception"). IMAP SUBJECT search is a + # case-insensitive substring match, mirroring usps_exception's + # "Delivery Exception" fragment. + "subject": ["FedEx Delivery Exception"], + }, + "fedex_tracking": {"pattern": ["\\d{12,20}"]}, + # Canada Post + "capost_delivered": { + "email": [ + "donotreply@canadapost.postescanada.ca", + "donotreply-nepasrepondre@notifications.canadapost-postescanada.ca", + ], + "subject": [ + "Delivery Notification", + ], + }, + "capost_delivering": { + "email": [ + "donotreply-nepasrepondre@notifications.canadapost-postescanada.ca", + ], + "subject": [ + "Your parcel is out for delivery", + ], + }, + "capost_packages": {}, + "capost_tracking": {"pattern": ["\\d{16}"]}, + "capost_mail": { + "email": ["donotreply-nepasrepondre@communications.canadapost-postescanada.ca"], + "subject": ["You have mail on the way"], + "body": ["\\sYou have (\\d) piece|pieces of mail\\s"], + "body_count": True, + }, + # DHL + "dhl_delivered": { + "email": [ + "donotreply_odd@dhl.com", + "NoReply.ODD@dhl.com", + "noreply@dhl.de", + "pl.no.reply@dhl.com", + "support@dhl.com", + "noreply@dhlecommerce.nl", + "noreply@dhl.nl", + ], + "subject": [ + "DHL On Demand Delivery", + "Powiadomienie o przesyłce", + "wurde zugestellt", + "DHL Shipment Notification", + "liegt am gewünschten Ablageort", + "Ihre Sendung liegt im Briefkasten", + "Zustellung an Ablageort", + "Sendung zugestellt", + "Paket wurde zugestellt", + "Ihre AliExpress Sendung liegt im Briefkasten", + "succesvol bezorgd", + "is bezorgd", + ], + "body": [ + "has been delivered", + "została doręczona", + "ist angekommen", + 'Notification for shipment event group "Delivered', + " - Delivered - ", + "liegt im Briefkasten", + "zugestellt", + "Zustellung", + "wurde zugestellt", + "succesvol bezorgd", + "is bezorgd", + "pakket is afgeleverd", + ], + }, + "dhl_delivering": { + "email": [ + "donotreply_odd@dhl.com", + "NoReply.ODD@dhl.com", + "noreply@dhl.de", + "pl.no.reply@dhl.com", + "support@dhl.com", + "noreply@dhlecommerce.nl", + "noreply@dhl.nl", + ], + "subject": [ + "DHL On Demand Delivery", + "Paket kommt heute", + "kommt heute", + "wird gleich zugestellt", + "Powiadomienie o przesyłce", + "DHL Shipment Notification", + "ist unterwegs", + "Jetzt Live verfolgen", + "vanavond voor de deur", + "vandaag voor de deur", + "pakket onderweg", + "bezorging vandaag", + "staan vandaag voor de deur", + "staan vanavond voor de deur", + "komen we bij je langs", + ], + "body": [ + "scheduled for delivery TODAY", + "zostanie dziś do Państwa doręczona", + "wird Ihnen heute", + "heute zwischen", + " - Shipment is out with courier for delivery - ", + "Shipment is scheduled for delivery", + "voraussichtlich innerhalb", + "staan vandaag voor de deur", + "staan vanavond voor de deur", + "wordt vandaag bezorgd", + "bezorger onderweg", + "komen we bij je langs", + ], + }, + "dhl_packages": {}, + "dhl_tracking": { + "pattern": [ + "(?:JJD\\d{18}|JVGL\\d{20}|MDP[A-Z0-9]{5,15}|00\\d{18}|(? dict: + """Process emails and update sensors.""" + # Initialize defaults and image paths + data = self._initialize_data() + config = await self._setup_image_config(hass, config) + + # Connect to IMAP + account = await self._get_imap_connection(config) + try: + cache = EmailCache(account) + now = datetime.datetime.now() + today = now.strftime("%d-%b-%Y") + today_iso = now.date().isoformat() + days = config.get(CONF_CUSTOM_DAYS, DEFAULT_CUSTOM_DAYS) + since_date = (now - datetime.timedelta(days=days)).strftime("%d-%b-%Y") + + # Process logic + shipper_data = await self._update_shippers( + account, config, today, since_date, cache + ) + tracking_details = shipper_data.pop("_tracking_details", {}) + data.update(shipper_data) + self._apply_tracking_state(data, tracking_details, today_iso) + + # Aggregate global transit and delivered sensors + self._aggregate_package_counts(data) + finally: + await logout(account) + + # Post-process external images + if config.get(CONF_ALLOW_EXTERNAL): + try: + await hass.async_add_executor_job(copy_images, hass, config) + except (OSError, ValueError) as err: + _LOGGER.error("Problem creating: %s", err) + + return data + + def _initialize_data(self) -> dict: + """Initialize core data structure with default values.""" + data = { + "mail_updated": datetime.datetime.now(datetime.UTC).isoformat(), + "amazon_delivered_by_others": 0, + } + resources = self.config.get(CONF_RESOURCES, []) + for sensor in resources: + if sensor not in data: + data[sensor] = 0 + return data + + async def _setup_image_config(self, hass: HomeAssistant, config: dict) -> dict: + """Configure image paths and filenames for all shippers.""" + image_path = default_image_path(hass, config) + config["image_path"] = image_path + + shipper_images = { + "amazon_image": (True, False, False, False), + "ups_image": (False, True, False, False), + "walmart_image": (False, False, True, False), + "fedex_image": (False, False, False, True), + "usps_image": (False, False, False, False), + "post_de_image": (False, False, False, False), + } + + for key, params in shipper_images.items(): + config[key] = await hass.async_add_executor_job( + image_file_name, hass, config, *params + ) + return config + + async def _get_imap_connection(self, config: dict) -> IMAP4_SSL: + """Establish and return an authenticated IMAP connection.""" + try: + account = await login( + self.hass, + config.get(CONF_HOST), + config.get(CONF_PORT), + config.get(CONF_USERNAME), + config.get(CONF_PASSWORD), + config.get(CONF_IMAP_SECURITY), + config.get(CONF_VERIFY_SSL), + config.get("oauth_token"), + timeout=self.timeout, + ) + except InvalidAuth as err: + _LOGGER.error("Authentication failed: %s", err) + raise ConfigEntryAuthFailed from err + except Exception as err: + _LOGGER.error("Error logging into IMAP: %s", err) + raise UpdateFailed(f"Login failed: {err}") from err + + folders = config.get(CONF_FOLDER) + if not folders: + folders = ["INBOX"] + elif isinstance(folders, str): + folders = [folders] + elif isinstance(folders, (list, tuple, set)): + folders = [f for f in folders if isinstance(f, str) and f] + if not folders: + folders = ["INBOX"] + else: + folders = ["INBOX"] + account._folders = folders # noqa: SLF001 + account._current_folder = None # noqa: SLF001 + + if folders: + try: + folder_ok = await selectfolder(account, folders[0]) + except Exception as err: + await logout(account) + raise UpdateFailed(f"Folder selection failed: {err}") from err + + if not folder_ok: + _LOGGER.error("Error selecting folder: %s", folders[0]) + await logout(account) + raise UpdateFailed(f"Folder selection failed: {folders[0]}") + + return account + + async def _update_shippers( + self, + account: IMAP4_SSL, + config: dict, + today: str, + since_date: str, + cache: EmailCache, + ) -> dict: + """Group and process sensors by shipper.""" + data = {} + resources = config.get(CONF_RESOURCES, []) + sensors_by_shipper = {} + + for sensor in resources: + shipper = get_shipper_for_sensor(self.hass, config, sensor) + if shipper: + sensors_by_shipper.setdefault(shipper.name, []).append( + (shipper, sensor) + ) + + for shipper_name, shipper_group in sensors_by_shipper.items(): + shipper_instance = shipper_group[0][0] + sensors = [s[1] for s in shipper_group] + + shipper_start = monotonic() + success = False + try: + results = await shipper_instance.process_batch( + account, today, sensors, cache, since_date=since_date + ) + if isinstance(results, dict): + if "_tracking_details" in results: + data.setdefault("_tracking_details", {}).update( + results.pop("_tracking_details") + ) + data.update(results) + success = True + except Exception as err: # noqa: BLE001 + _LOGGER.error("Error processing shipper %s: %s", shipper_name, err) + finally: + _LOGGER.debug( + "Shipper %s %s in %.1fs", + shipper_name, + "processed" if success else "failed", + monotonic() - shipper_start, + ) + + return data + + def _apply_tracking_state( + self, + data: dict, + tracking_details: dict[str, list[str]], + today_iso: str, + ) -> None: + """Update in-transit tracking state and override sensor counts.""" + prefixes: set[str] = set(self._in_transit_tracking.keys()) + for sensor_key in tracking_details: + prefix = "_".join(sensor_key.split("_")[:-1]) + if prefix: + prefixes.add(prefix) + + for prefix in prefixes: + if prefix in self._in_transit_tracking and not ( + f"{prefix}_delivering" in tracking_details + or f"{prefix}_exception" in tracking_details + or f"{prefix}_delivered" in tracking_details + ): + _LOGGER.debug( + "Prefix '%s' has no tracking_details entries — " + "may be a removed carrier; tracking will persist until TTL expiry", + prefix, + ) + + delivering = list(tracking_details.get(f"{prefix}_delivering", [])) + delivering += list(tracking_details.get(f"{prefix}_exception", [])) + delivered = list(tracking_details.get(f"{prefix}_delivered", [])) + + self._update_tracking_for_prefix( + prefix, delivering, delivered, today_iso, MAX_TRACKING_AGE_DAYS + ) + + in_transit = self._in_transit_tracking.get(prefix, {}) + if in_transit: + data[f"{prefix}_tracking"] = list(in_transit.keys()) + data[f"{prefix}_delivering"] = len(in_transit) + delivered_count = data.get(f"{prefix}_delivered", 0) + data[f"{prefix}_packages"] = len(in_transit) + ( + delivered_count if isinstance(delivered_count, int) else 0 + ) + + def _update_tracking_for_prefix( + self, + prefix: str, + delivering: list[str], + delivered: list[str], + today_iso: str, + ttl_days: int, + ) -> None: + """Add/expire delivering tracking numbers and remove delivered ones.""" + if prefix not in self._in_transit_tracking: + self._in_transit_tracking[prefix] = {} + + in_transit = self._in_transit_tracking[prefix] + + # Add new delivering tracking numbers (record first-seen date) + for tid in delivering: + if tid and tid not in in_transit: + in_transit[tid] = today_iso + + # Remove delivered tracking numbers + for tid in delivered: + in_transit.pop(tid, None) + + # Expire entries older than TTL + cutoff = ( + datetime.date.fromisoformat(today_iso) - datetime.timedelta(days=ttl_days) + ).isoformat() + expired = [tid for tid, seen in in_transit.items() if seen < cutoff] + for tid in expired: + del in_transit[tid] + + def _aggregate_package_counts(self, data: dict) -> None: + """Aggregate global transit and delivered counts from all shippers.""" + # Only update if sensors were requested in initialize_data + if "zpackages_transit" in data: + data["zpackages_transit"] = self._sum_transit_counts(data) + if "zpackages_delivered" in data: + data["zpackages_delivered"] = self._sum_delivered_counts(data) + + def _sum_delivered_counts(self, data: dict) -> int: + """Sum delivered packages from all shippers.""" + delivered = 0 + exclude_keys = ( + "zpackages_delivered", + "amazon_delivered_by_others", + "usps_mail_delivered", + ) + + for key, value in data.items(): + if ( + isinstance(value, int) + and value > 0 + and key.endswith("_delivered") + and key not in exclude_keys + ): + delivered += value + return delivered + + def _sum_transit_counts(self, data: dict) -> int: + """Sum transit and exception packages from all shippers.""" + transit = 0 + shippers_counted = set() + + # Amazon is special as it uses amazon_packages for total arriving + if data.get("amazon_packages", 0) > 0: + transit += data["amazon_packages"] + shippers_counted.add("amazon") + + for key, value in data.items(): + if not isinstance(value, int) or value <= 0: + continue + + # Add exceptions for all shippers + if key.endswith("_exception") and key != "zpackages_exception": + transit += value + continue + + # Match shipper prefix + shipper = next((s for s in const.SHIPPERS if key.startswith(s)), None) + if not shipper or shipper in shippers_counted: + continue + + # Priority: _delivering (preferred generic state) or _packages + if key.endswith(("_delivering", "_packages")): + transit += value + shippers_counted.add(shipper) + + return transit + + async def _binary_sensor_update(self): # noqa: C901 + """Update binary sensor states.""" + # USPS uses ATTR_USPS_IMAGE instead of the old ATTR_IMAGE_NAME + _LOGGER.debug("Data: %s", self._data) + image = self._data.get(ATTR_USPS_IMAGE) + if image: + path = default_image_path(self.hass, self.config) + usps_image = f"{path}/{image}" + usps_none = f"{Path(__file__).parent}/mail_none.gif" + usps_check = await anyio.Path(usps_image).exists() + _LOGGER.debug("USPS Check: %s", usps_check) + if usps_check: + # Optimized: Use _get_file_hash_if_changed + image_hash = await self._get_file_hash_if_changed(usps_image) + none_hash = await self._get_file_hash_if_changed(usps_none) + + _LOGGER.debug("USPS Image hash: %s", image_hash) + _LOGGER.debug("USPS None hash: %s", none_hash) + + if image_hash != none_hash: + self._data["usps_update"] = True + else: + self._data["usps_update"] = False + + # Handle generic delivery cameras (Amazon, UPS, Walmart, FedEx, Generic) with unified logic + # Derive camera list dynamically from CAMERA_DATA, excluding usps_camera and generic_camera + delivery_cameras = [ + camera_type.replace("_camera", "") + for camera_type in const.CAMERA_DATA + if camera_type not in ("usps_camera", "generic_camera") + ] + + for base_name in delivery_cameras: + # Derive attribute and config keys dynamically + image_attr_name = f"ATTR_{base_name.upper()}_IMAGE" + image_attr = getattr(const, image_attr_name, None) + if not image_attr: + continue + + custom_img_key = getattr( + const, + f"CONF_{base_name.upper()}_CUSTOM_IMG", + None, + ) + custom_img_file_key = getattr( + const, + f"CONF_{base_name.upper()}_CUSTOM_IMG_FILE", + None, + ) + update_key = f"{base_name}_update" + + image = self._data.get(image_attr) + _LOGGER.debug("%s image from data: %s", base_name.title(), image) + if image: + # Normalize path to avoid double slashes + image_path = ( + default_image_path(self.hass, self.config).rstrip("/") + "/" + ) + path = f"{image_path}{base_name}/" + # Use absolute path for file existence check + delivery_image_relative = f"{path}{image}" + delivery_image = f"{self.hass.config.path()}/{delivery_image_relative}" + _LOGGER.debug( + "Full %s image path: %s", + base_name.title(), + delivery_image, + ) + + if custom_img_key and self.config.get(custom_img_key): + none_image = self.config.get(custom_img_file_key) + elif base_name == "post_de": + none_image = f"{Path(__file__).parent}/mail_none.gif" + else: + none_image = ( + f"{Path(__file__).parent}/no_deliveries_{base_name}.jpg" + ) + + image_check = await anyio.Path(delivery_image).exists() + _LOGGER.debug("%s Check: %s", base_name.title(), image_check) + if image_check: + # Optimized: Use _get_file_hash_if_changed + image_hash = await self._get_file_hash_if_changed(delivery_image) + none_hash = await self._get_file_hash_if_changed(none_image) + + _LOGGER.debug("%s Image hash: %s", base_name.title(), image_hash) + _LOGGER.debug("%s None hash: %s", base_name.title(), none_hash) + + if image_hash != none_hash: + self._data[update_key] = True + else: + self._data[update_key] = False diff --git a/custom_components/mail_and_packages/diagnostics.py b/custom_components/mail_and_packages/diagnostics.py new file mode 100644 index 0000000..8ead48d --- /dev/null +++ b/custom_components/mail_and_packages/diagnostics.py @@ -0,0 +1,47 @@ +"""Provide diagnostics for Mail and Packages.""" + +from __future__ import annotations + +import logging +from typing import Any + +from homeassistant.components.diagnostics import async_redact_data +from homeassistant.const import CONF_PASSWORD, CONF_USERNAME +from homeassistant.core import HomeAssistant +from homeassistant.helpers.device_registry import DeviceEntry + +from . import MailAndPackagesConfigEntry +from .const import CONF_AMAZON_FWDS, CONF_FORWARDED_EMAILS + +_LOGGER = logging.getLogger(__name__) +REDACT_KEYS = {CONF_PASSWORD, CONF_USERNAME, CONF_AMAZON_FWDS, CONF_FORWARDED_EMAILS} + + +async def async_get_config_entry_diagnostics( + hass: HomeAssistant, + config_entry: MailAndPackagesConfigEntry, # pylint: disable=unused-argument +) -> dict[str, Any]: + """Return diagnostics for a config entry.""" + diag: dict[str, Any] = {} + diag["config"] = config_entry.as_dict() + return async_redact_data(diag, REDACT_KEYS) + + +async def async_get_device_diagnostics( + hass: HomeAssistant, + config_entry: MailAndPackagesConfigEntry, + device: DeviceEntry, # pylint: disable=unused-argument +) -> dict[str, Any]: + """Return diagnostics for a device.""" + coordinator = config_entry.runtime_data.coordinator + + dynamic_keys = { + variable + for variable in coordinator.data + if "tracking" in variable or "order" in variable + } + redact_keys = REDACT_KEYS | dynamic_keys + + _LOGGER.debug("Redacted keys: %s", redact_keys) + + return async_redact_data(coordinator.data, redact_keys) diff --git a/custom_components/mail_and_packages/entity.py b/custom_components/mail_and_packages/entity.py new file mode 100644 index 0000000..3e3bf5c --- /dev/null +++ b/custom_components/mail_and_packages/entity.py @@ -0,0 +1,14 @@ +"""Support for Mail and Packages entities.""" + +from __future__ import annotations + +from dataclasses import dataclass + +from homeassistant.components.binary_sensor import BinarySensorEntityDescription + + +@dataclass +class MailandPackagesBinarySensorEntityDescription(BinarySensorEntityDescription): + """Class describing Mail and Packages binary sensor entities.""" + + selectable: bool = False diff --git a/custom_components/mail_and_packages/helpers.py b/custom_components/mail_and_packages/helpers.py new file mode 100644 index 0000000..cef33cf --- /dev/null +++ b/custom_components/mail_and_packages/helpers.py @@ -0,0 +1,131 @@ +"""Helper functions for Mail and Packages.""" + +from __future__ import annotations + +import datetime +import logging +import os +from pathlib import Path +from shutil import copyfile +from typing import Any + +from aioimaplib import IMAP4_SSL +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant + +from .const import ( + AMAZON_DELIVERED_SUBJECT, + AMAZON_EXCEPTION_SUBJECT, + AMAZON_HUB_SUBJECT, + AMAZON_OTP_SUBJECT, + ATTR_COUNT, + ATTR_TRACKING, + BINARY_SENSORS, + CONF_PATH, + SENSOR_TYPES, +) +from .shippers import SHIPPER_REGISTRY +from .shippers.usps import USPSShipper +from .utils.image import ( + default_image_path, +) + +_LOGGER = logging.getLogger(__name__) + +# Legacy constants for tests + +amazon_exception = AMAZON_EXCEPTION_SUBJECT +amazon_hub = AMAZON_HUB_SUBJECT +amazon_otp = AMAZON_OTP_SUBJECT +amazon_search_legacy = AMAZON_DELIVERED_SUBJECT +image_file_name = "mail_today.gif" + + +async def get_count( + account: IMAP4_SSL, + sensor_type: str, + body_count: bool, + image_path: str, + hass: HomeAssistant, +) -> dict[str, Any]: + """Legacy get_count wrapper for tests.""" + shipper_class = SHIPPER_REGISTRY.get(sensor_type) + if not shipper_class: + _LOGGER.error("No shipper found for %s", sensor_type) + return {ATTR_COUNT: 0, ATTR_TRACKING: []} + + shipper = shipper_class(hass, {CONF_PATH: image_path}) + today = datetime.datetime.now().strftime("%d-%b-%Y") + return await shipper.process(account, today, sensor_type) + + +async def get_mails( + account: IMAP4_SSL, + address_list: list[str], + hass: HomeAssistant, + config: dict[str, Any], +) -> int: + """Legacy get_mails wrapper for tests.""" + shipper = USPSShipper(hass, config) + today = datetime.datetime.now().strftime("%d-%b-%Y") + result = await shipper.process(account, today, "usps_mail") + return result.get(ATTR_COUNT, 0) + + +async def fetch( + hass: HomeAssistant, + config: dict[str, Any], + account: IMAP4_SSL, + sensor: str, +) -> int: + """Legacy fetch wrapper for tests.""" + shipper_class = SHIPPER_REGISTRY.get(sensor) + if not shipper_class: + return 0 + + shipper = shipper_class(hass, config) + today = datetime.datetime.now().strftime("%d-%b-%Y") + data = await shipper.process(account, today, sensor) + return data.get(ATTR_COUNT, 0) + + +async def get_items( + hass: HomeAssistant, + config: dict[str, Any], + account: IMAP4_SSL, + sensor: str, +) -> dict[str, Any]: + """Legacy get_items wrapper for tests.""" + shipper_class = SHIPPER_REGISTRY.get(sensor) + if not shipper_class: + return {ATTR_COUNT: 0, ATTR_TRACKING: []} + + shipper = shipper_class(hass, config) + today = datetime.datetime.now().strftime("%d-%b-%Y") + return await shipper.process(account, today, sensor) + + +def get_resources(hass: HomeAssistant | None = None) -> dict: + """Return resources from const.""" + resources = {k: v.name for k, v in SENSOR_TYPES.items()} + resources.update({k: v.name for k, v in BINARY_SENSORS.items() if v.selectable}) + return resources + + +def copy_images(hass: HomeAssistant, config: ConfigEntry) -> None: + """Copy processed images to www directory.""" + image_path = Path(hass.config.path()) / default_image_path(hass, config) + www_path = Path(hass.config.path()) / "www" / "mail_and_packages" + + if not www_path.is_dir(): + www_path.mkdir(parents=True, exist_ok=True) + + for root, _, files in os.walk(image_path): + for file in files: + if file.endswith((".gif", ".jpg", ".png")): + src = Path(root) / file + dest = www_path / file + try: + copyfile(str(src), str(dest)) + except OSError as err: + _LOGGER.error("Error copying image: %s", err) diff --git a/custom_components/mail_and_packages/image-no-mailpieces700.jpg b/custom_components/mail_and_packages/image-no-mailpieces700.jpg new file mode 100644 index 0000000000000000000000000000000000000000..794ee8cf2fb2c98832f790c5af20e763abc4bbae GIT binary patch literal 44385 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�p6pDo-TcsYYTmWnN}UsOm)mZTmc1Jj$#Nl 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.0", + "dateparser", + "aioimaplib" + ], + "version": "0.5.9" +} diff --git a/custom_components/mail_and_packages/no_deliveries_amazon.jpg b/custom_components/mail_and_packages/no_deliveries_amazon.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a445a39a81ae10c3755c3714659b711ae7885b6f GIT binary patch literal 35660 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 literal 0 HcmV?d00001 diff --git a/custom_components/mail_and_packages/no_deliveries_generic.jpg b/custom_components/mail_and_packages/no_deliveries_generic.jpg new file mode 100644 index 0000000000000000000000000000000000000000..800184e5588f750e80d76c9b1c9b68ab22e7fc8c GIT binary patch literal 27660 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 DYr$)m literal 0 HcmV?d00001 diff --git a/custom_components/mail_and_packages/no_deliveries_ups.jpg b/custom_components/mail_and_packages/no_deliveries_ups.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a37a3b6080136e1ce6c054e2706ba15405ae7c30 GIT binary patch literal 34834 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 DbRq9> literal 0 HcmV?d00001 diff --git a/custom_components/mail_and_packages/no_deliveries_walmart.jpg b/custom_components/mail_and_packages/no_deliveries_walmart.jpg new file mode 100644 index 0000000000000000000000000000000000000000..83228c93898d327d091cca4965c5b23ae554f46d GIT binary patch literal 47455 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 IFMrMbFKPxv-~a#s literal 0 HcmV?d00001 diff --git a/custom_components/mail_and_packages/overlay.png b/custom_components/mail_and_packages/overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..6a6c9b1d5b3edfdd30427871739340698f8f185b GIT binary patch literal 8764 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 bcuT%1h2*70kj4XF^08EvUMW_}L&E 1: + prefix = "_".join(parts[:-1]) + if parts[-1] in DELIVERED_SUFFIXES: + self._tracking_key = f"{prefix}_delivered_tracking" + else: + self._tracking_key = f"{prefix}_tracking" + else: + self._tracking_key = f"{self.type}_tracking" + + @property + def device_info(self) -> dict: + """Return device information about the mailbox.""" + return { + "connections": {(DOMAIN, self._unique_id)}, + "name": self._host, + "manufacturer": "IMAP E-Mail", + "sw_version": VERSION, + } + + @property + def unique_id(self) -> str: + """Return a unique, Home Assistant friendly identifier for this entity.""" + return f"sensor_{self._host}_{self.type}_{self._unique_id}" + + @property + def name(self) -> str: + """Return the name of the sensor.""" + return self._name + + @property + def native_value(self) -> Any: + """Return the state of the sensor.""" + value = self.coordinator.data.get(self.type) + + if self.type == "mail_updated": + # Safely handle string vs datetime to prevent ValueError + if isinstance(value, str): + try: + value = datetime.datetime.fromisoformat(value) + except ValueError: + value = datetime.datetime.now(datetime.UTC) + elif value is None: + value = datetime.datetime.now(datetime.UTC) + return value + + @property + def should_poll(self) -> bool: + """No need to poll. Coordinator notifies entity of updates.""" + return False + + @property + def available(self) -> bool: + """Return if entity is available.""" + return self.coordinator.data is not None + + @property + def extra_state_attributes(self) -> str | None: + """Return device specific state attributes.""" + attr = {} + data = self.coordinator.data + + if any( + sensor in self.type + for sensor in ["_delivering", "_delivered", "_packages", "_exception"] + ): + if tracking := data.get(self._tracking_key): + attr[ATTR_TRACKING_NUM] = tracking + + # Catch no data entries + if self.data is None: + return attr + + if "Amazon" in self._name: + self._add_amazon_attributes(attr, data) + elif self._name == "Mail USPS Mail": + if image_name := data.get(ATTR_IMAGE_NAME): + attr[ATTR_IMAGE] = image_name + + return attr + + def _add_amazon_attributes(self, attr: dict, data: dict) -> None: + """Add Amazon specific attributes to the sensor.""" + if self.type == AMAZON_EXCEPTION: + if order := data.get(AMAZON_EXCEPTION_ORDER, data.get(ATTR_ORDER)): + attr[ATTR_ORDER] = order + elif order := data.get(AMAZON_ORDER): + attr[ATTR_ORDER] = order + elif self.type == AMAZON_HUB: + if code := data.get(AMAZON_HUB_CODE, data.get(ATTR_CODE)): + attr[ATTR_CODE] = code + elif self.type == AMAZON_OTP: + if code := data.get(AMAZON_OTP_CODE, data.get(ATTR_CODE)): + attr[ATTR_CODE] = code + + +class ImagePathSensors(CoordinatorEntity, SensorEntity): + """Representation of a sensor.""" + + def __init__( + self, + hass: HomeAssistant, + config: ConfigEntry, + sensor_description: SensorEntityDescription, + coordinator: Any, + ): + """Initialize the sensor.""" + super().__init__(coordinator) + self.entity_description = sensor_description + self.hass = hass + self.coordinator = coordinator + self._config = config + self._name = sensor_description.name + self.type = sensor_description.key + self._host = config.data[CONF_HOST] + self._unique_id = self._config.entry_id + + @property + def device_info(self) -> dict: + """Return device information about the mailbox.""" + return { + "connections": {(DOMAIN, self._unique_id)}, + "name": self._host, + "manufacturer": "IMAP E-Mail", + "sw_version": VERSION, + } + + @property + def unique_id(self) -> str: + """Return a unique, Home Assistant friendly identifier for this entity.""" + return f"sensor_{self._host}_{self.type}_{self._unique_id}" + + @property + def name(self) -> str: + """Return the name of the sensor.""" + return self._name + + @property + def native_value(self) -> str | None: + """Return the state of the sensor.""" + image = "" + the_path = None + + image = self.coordinator.data.get(ATTR_USPS_IMAGE) + + grid_image = self.coordinator.data.get(ATTR_GRID_IMAGE_NAME) + + path = self.coordinator.data.get( + ATTR_IMAGE_PATH, + self._config.data.get(CONF_PATH), + ) + + if self.type == "usps_mail_image_system_path" and image: + _LOGGER.debug("Updating system image path to: %s", path) + the_path = f"{self.hass.config.path()}/{path}{image}" + elif self.type == "usps_mail_grid_image_path" and grid_image: + _LOGGER.debug("Updating grid image path to: %s", path) + the_path = f"{self.hass.config.path()}/{path}{grid_image}" + elif self.type == "usps_mail_image_url" and image: + url = self._get_base_url() + if url: + the_path = f"{url.rstrip('/')}/local/mail_and_packages/{image}" + return the_path + + def _get_base_url(self) -> str | None: + """Return the best available base URL for building image links. + + Priority: explicit external URL → HA Cloud remote URL → internal URL. + """ + if self.hass.config.external_url: + return self.hass.config.external_url + + # Try Home Assistant Cloud (Nabu Casa) — its remote URL is not exposed via + # hass.config.external_url when "Use Home Assistant Cloud" is selected. + try: + from homeassistant.components.cloud import ( # noqa: PLC0415 + CloudNotAvailable, + async_remote_ui_url, + ) + except ImportError: + pass + else: + try: + return async_remote_ui_url(self.hass) + except (CloudNotAvailable, KeyError): + _LOGGER.debug("HA Cloud remote URL not available.") + + if self.hass.config.internal_url: + _LOGGER.debug("Falling back to internal URL for image link.") + return self.hass.config.internal_url + + return None + + @property + def should_poll(self) -> bool: + """No need to poll. Coordinator notifies entity of updates.""" + return False + + @property + def available(self) -> bool: + """Return if entity is available.""" + return self.coordinator.data is not None diff --git a/custom_components/mail_and_packages/services.yaml b/custom_components/mail_and_packages/services.yaml new file mode 100644 index 0000000..7878411 --- /dev/null +++ b/custom_components/mail_and_packages/services.yaml @@ -0,0 +1,13 @@ +update_image: + name: Refresh the Mail Camera(s) + description: Refreshes the Mail Camera specified or all of them at once. Leave blank to refresh them all. + fields: + entity_id: + name: Camera Entity + description: The camera entity to refresh. + example: camera.mail_usps_camera + required: false + selector: + entity: + domain: camera + integration: mail_and_packages diff --git a/custom_components/mail_and_packages/shippers/__init__.py b/custom_components/mail_and_packages/shippers/__init__.py new file mode 100644 index 0000000..a8ab9f4 --- /dev/null +++ b/custom_components/mail_and_packages/shippers/__init__.py @@ -0,0 +1,42 @@ +"""Shippers for Mail and Packages.""" + +from __future__ import annotations + +from typing import TYPE_CHECKING + +from .amazon import AmazonShipper +from .generic import GenericShipper +from .post_de import PostDEShipper +from .usps import USPSShipper + +if TYPE_CHECKING: + from homeassistant.core import HomeAssistant + + from .base import Shipper + +SHIPPER_REGISTRY = { + "amazon": AmazonShipper, + "generic": GenericShipper, + "post_de": PostDEShipper, + "usps": USPSShipper, +} + + +def get_shipper_for_sensor( + hass: HomeAssistant, + config: dict, + sensor_type: str, +) -> Shipper | None: + """Return the appropriate shipper for the given sensor type.""" + # Check specialized shippers first + for name, shipper_class in SHIPPER_REGISTRY.items(): + if name == "generic": + continue + if shipper_class.handles_sensor(sensor_type): + return shipper_class(hass, config) + + # Fallback to generic + if GenericShipper.handles_sensor(sensor_type): + return GenericShipper(hass, config) + + return None diff --git a/custom_components/mail_and_packages/shippers/__pycache__/__init__.cpython-314.pyc b/custom_components/mail_and_packages/shippers/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3d34363609ff47225bbc2d399cff35cbfbff0c7f GIT binary patch literal 1498 zcmZWp&2Jk;6n|^4cWtjfHXkGf61+)DLKMkPB}b$ZLR2MlU5{IH4-0+P;ZWc)GKe+c7tG~ee>qc+uzLoe(&u^aKiPw4Ce0RazyC{?8r6S0EyW7T*?6)O4)iB}U9O=yv?R`p6! zBqKjjO;yq&9r;?-sANQ@0Nd(Z|CD+bU_xT))odjva#3Egny;9`EC5MuYb3p$B*u1{ zWVSOURSc2rIFQ^p?3!Yjs+$(G}y>{DW+}a74^^xuETDD)eYPR!*-EetvUI`7` z_XA-IFYq}ov-j@TR_N`@%I&r4`l<}vYT0{%-v`1#Zq@Z&<~di9Y%Sp8!WL1!N} z;X!QqJAgXICg85pRER=iBu-S4AR5t0vZNvhsTVO!57nm4Ig=2f<^=wZ*9g_R=ZMhY zuFnHT#iO1Ngn1C z%*2TeNi%{bRDHYUhS~ms)Y-+d<1%%2cGj}kHJLNka0MM?U_lKKr*Jcp{~7X7t3kc5KWY8goAz$42>?Q9d299*;g9DIR5t z7b&oo@%7}`v3~tXzyA2MWBtaFe&cz5^2hqq{KAvu!tX|&y@AK9&yR#UrS-s}G)z;v z)4|%8wI~G(HRQ(g8%)*0oU~aGR z)Q2{ASxP2ONF%?OjY%VK(&HxiUMr|~cHQ@xEG1c0{0^FKTv3!$c>5ft&%ru}sWX^4 wgXuGv{3~vrsf*|8B=$rid(b*jvj^Ww^UaBxK3MCf5~HyvV7@f5MWS>50XBqVwEzGB literal 0 HcmV?d00001 diff --git a/custom_components/mail_and_packages/shippers/__pycache__/amazon.cpython-314.pyc b/custom_components/mail_and_packages/shippers/__pycache__/amazon.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..82845863195f6d39b91741e72f9fe2baaada1395 GIT binary patch literal 32673 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îU-@_ouG^=z@PdmcMg3f9GNtal)_`<-6wk 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 SKCb7x`SV@>n_~!@*#8%-Dk{_f literal 0 HcmV?d00001 diff --git a/custom_components/mail_and_packages/shippers/__pycache__/base.cpython-314.pyc b/custom_components/mail_and_packages/shippers/__pycache__/base.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..298dff1a9416460d729ac589f587c318c4093916 GIT binary patch literal 3187 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 F{r_v?2X_Df literal 0 HcmV?d00001 diff --git a/custom_components/mail_and_packages/shippers/__pycache__/post_de.cpython-314.pyc b/custom_components/mail_and_packages/shippers/__pycache__/post_de.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9cac74816c238c2fa6b4e2bd7511371945cf78ec GIT binary patch literal 18872 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 V8!kfnn9%cemm2?(qbKX#{|9dDBOU+% literal 0 HcmV?d00001 diff --git a/custom_components/mail_and_packages/shippers/amazon.py b/custom_components/mail_and_packages/shippers/amazon.py new file mode 100644 index 0000000..1d8bc7d --- /dev/null +++ b/custom_components/mail_and_packages/shippers/amazon.py @@ -0,0 +1,612 @@ +"""Base Shipper class.""" + +from __future__ import annotations + +import datetime +import email +import logging +import re +from pathlib import Path +from shutil import copyfile +from typing import Any + +import anyio +import dateparser +import homeassistant.helpers.config_validation as cv +from aioimaplib import IMAP4_SSL + +from custom_components.mail_and_packages import const +from custom_components.mail_and_packages.const import ( + AMAZON_DELIVERED, + AMAZON_DELIVERED_SUBJECT, + AMAZON_EXCEPTION, + AMAZON_EXCEPTION_BODY, + AMAZON_EXCEPTION_ORDER, + AMAZON_EXCEPTION_SUBJECT, + AMAZON_HUB, + AMAZON_HUB_BODY, + AMAZON_HUB_CODE, + AMAZON_HUB_SUBJECT, + AMAZON_HUB_SUBJECT_SEARCH, + AMAZON_ORDER, + AMAZON_ORDERED_SUBJECT, + AMAZON_OTP, + AMAZON_OTP_CODE, + AMAZON_OTP_REGEX, + AMAZON_OTP_SUBJECT, + AMAZON_PACKAGES, + AMAZON_SHIPMENT_SUBJECT, + ATTR_COUNT, + CONF_AMAZON_DAYS, + CONF_AMAZON_DOMAIN, + CONF_AMAZON_FWDS, + CONF_DURATION, + CONF_FORWARDING_HEADER, + DEFAULT_AMAZON_DAYS, +) +from custom_components.mail_and_packages.utils.amazon import ( + _extract_hub_code, + amazon_email_addresses, + download_amazon_img, + extract_order_numbers, + filter_amazon_strings, + get_decoded_subject, + get_email_body, + parse_amazon_arrival_date, + search_amazon_emails, +) +from custom_components.mail_and_packages.utils.cache import EmailCache +from custom_components.mail_and_packages.utils.date import get_today +from custom_components.mail_and_packages.utils.image import ( + cleanup_images, + generate_delivery_gif, + random_filename, + resize_images, +) +from custom_components.mail_and_packages.utils.imap import ( + email_fetch, + email_search, +) + +from .base import Shipper + +_LOGGER = logging.getLogger(__name__) + + +class AmazonShipper(Shipper): + """Amazon shipper implementation.""" + + @property + def name(self) -> str: + """Return shipper name.""" + return "amazon" + + @classmethod + def handles_sensor(cls, sensor_type: str) -> bool: + """Return True if this shipper handles the given sensor type.""" + return sensor_type.startswith("amazon_") or sensor_type == AMAZON_PACKAGES + + async def process( + self, + account: IMAP4_SSL, + date: str, + sensor_type: str, + cache: EmailCache | None = None, + ) -> dict[str, Any]: + """Process Amazon-specific emails.""" + forwarding_header = self.config.get(CONF_FORWARDING_HEADER, "") + if forwarding_header and forwarding_header != "(none)": + # Header mode: use native Amazon addresses; fwds not needed + fwds = None + else: + forwarding_header = "" + fwds = cv.ensure_list_csv(self.config.get(CONF_AMAZON_FWDS)) + days = self.config.get(CONF_AMAZON_DAYS, DEFAULT_AMAZON_DAYS) + domain = self.config.get(CONF_AMAZON_DOMAIN) + + if sensor_type in [AMAZON_PACKAGES, AMAZON_ORDER]: + param = "count" if sensor_type == AMAZON_PACKAGES else "order" + result = await self._parse_amazon_emails( + account, param, fwds, days, domain, cache, forwarding_header + ) + return {sensor_type: result} + + if sensor_type == AMAZON_HUB: + return await self._amazon_hub(account, fwds, cache, forwarding_header) + + if sensor_type == AMAZON_OTP: + result = await self._amazon_otp(account, fwds, cache, forwarding_header) + return {sensor_type: result} + + if sensor_type == AMAZON_EXCEPTION: + return await self._amazon_exception( + account, fwds, domain, cache, forwarding_header + ) + + if sensor_type == AMAZON_DELIVERED: + image_path = self.config.get("image_path") + image_name = self.config.get("amazon_image") + result = await self._amazon_search( + account, + image_path, + image_name, + domain, + fwds, + cache, + forwarding_header, + ) + return { + sensor_type: result, + const.ATTR_AMAZON_IMAGE: image_name, + const.ATTR_IMAGE_PATH: image_path, + } + + return {ATTR_COUNT: 0} + + async def process_batch( + self, + account: IMAP4_SSL, + date: str, + sensors: list[str], + cache: EmailCache, + since_date: str | None = None, + ) -> dict[str, Any]: + """Process multiple Amazon sensors in batch.""" + res = {} + for sensor in sensors: + sensor_res = await self.process(account, date, sensor, cache) + res.update(sensor_res) + # Replicate coordinator dictionary logic + if sensor not in sensor_res: + if ATTR_COUNT in sensor_res: + res[sensor] = sensor_res[ATTR_COUNT] + return res + + # Internal helper methods (migrated from helpers.py) + + async def _parse_amazon_emails( + self, + account: IMAP4_SSL, + param: str, + fwds: list[str] | None = None, + days: int = DEFAULT_AMAZON_DAYS, + domain: str | None = None, + cache: EmailCache | None = None, + forwarding_header: str = "", + ) -> list[str] | int: + """Parse Amazon emails for delivery date and order number.""" + today_date = get_today() + address_list = amazon_email_addresses(fwds, domain) + unique_emails = await search_amazon_emails( + account, address_list, days, domain, cache, forwarding_header + ) + order_pattern = re.compile(r"[0-9]{3}-[0-9]{7}-[0-9]{7}") + + context = { + "today": today_date, + "packages_arriving_today": {}, + "delivered_packages": {}, + "amazon_delivered": [], + "deliveries_today": [], + "all_shipped_orders": set(), + "order_pattern": order_pattern, + } + + for email_id in unique_emails: + await self._process_amazon_email(account, email_id, context, cache) + + final_count = self._calculate_final_count(context) + + if param == "count": + return final_count + return list(context["all_shipped_orders"]) + + async def _process_amazon_email( + self, + account: IMAP4_SSL, + email_id: bytes | str, + ctx: dict, + cache: EmailCache | None = None, + ): + """Process a single Amazon email.""" + fetch_id = email_id.decode() if isinstance(email_id, bytes) else email_id + if cache: + data = (await cache.fetch(fetch_id, "(RFC822)"))[1] + else: + data = (await email_fetch(account, fetch_id, "(RFC822)"))[1] + + for response_part in data: + if not isinstance(response_part, (bytes, bytearray)): + continue + + msg = email.message_from_bytes(response_part) + email_date = await self._parse_email_date(msg) + email_subject = get_decoded_subject(msg) + + if any(s.lower() in email_subject.lower() for s in AMAZON_ORDERED_SUBJECT): + continue + + email_msg = get_email_body(msg) + if any( + s.lower() in email_subject.lower() for s in AMAZON_DELIVERED_SUBJECT + ): + self._handle_delivered_email(email_subject, email_msg, ctx) + continue + + await self._handle_shipping_email(email_subject, email_msg, email_date, ctx) + + async def _parse_email_date( + self, + msg: email.message.Message, + ) -> datetime.date | None: + """Parse the date from an email message.""" + date_str = msg.get("Date") + if not date_str: + return None + parsed = await self.hass.async_add_executor_job(dateparser.parse, date_str) + return parsed.date() if parsed else None + + def _handle_delivered_email(self, subject: str, body: str | None, ctx: dict): + """Handle an Amazon 'delivered' email.""" + orders = extract_order_numbers(subject, ctx["order_pattern"]) + if not orders and body: + orders = extract_order_numbers(body, ctx["order_pattern"]) + for o in orders: + ctx["delivered_packages"][o] = ctx["delivered_packages"].get(o, 0) + 1 + if o not in ctx["amazon_delivered"]: + ctx["amazon_delivered"].append(o) + + async def _handle_shipping_email( + self, + subject: str, + body: str | None, + date: datetime.date | None, + ctx: dict, + ): + """Handle an Amazon 'shipping' or 'arriving' email.""" + order_id = self._extract_first_order_id(subject, body, ctx["order_pattern"]) + if order_id: + ctx["all_shipped_orders"].add(order_id) + + if body: + parsed_arrival = await parse_amazon_arrival_date(self.hass, body, date) + if parsed_arrival == ctx["today"]: + if order_id: + ctx["packages_arriving_today"][order_id] = ( + ctx["packages_arriving_today"].get(order_id, 0) + 1 + ) + else: + ctx["deliveries_today"].append("Amazon Order") + + def _extract_first_order_id( + self, + subject: str, + body: str | None, + pattern: re.Pattern, + ) -> str | None: + """Extract the first order number found in subject or body.""" + orders = extract_order_numbers(subject, pattern) + if orders: + return orders[0] + if body: + orders = extract_order_numbers(body, pattern) + if orders: + return orders[0] + return None + + def _calculate_final_count(self, ctx: dict) -> int: + """Calculate the final count of packages arriving today.""" + deliveries_today = [ + item + for item in ctx["deliveries_today"] + if item not in ctx["amazon_delivered"] + ] + final_count = 0 + for order_id, arriving_count in ctx["packages_arriving_today"].items(): + delivered_count = ctx["delivered_packages"].get(order_id, 0) + final_count += max(0, arriving_count - delivered_count) + return final_count + len(deliveries_today) + + async def _amazon_search( + self, + account: IMAP4_SSL, + image_path: str, + amazon_image_name: str, + amazon_domain: str, + fwds: list[str] | None = None, + cache: EmailCache | None = None, + forwarding_header: str = "", + ) -> int: + """Find Amazon Delivered email and handle images.""" + _LOGGER.debug("=== AMAZON DELIVERED SEARCH START ===") + subjects = AMAZON_DELIVERED_SUBJECT + today = get_today().strftime("%d-%b-%Y") + count = 0 + all_image_urls = [] + + await self.hass.async_add_executor_job( + cleanup_images, + f"{image_path or ''}amazon/", + ) + + address_list = amazon_email_addresses(fwds, amazon_domain) + _LOGGER.debug("Amazon email search addresses: %s", address_list) + if amazon_domain: + subjects = filter_amazon_strings(subjects, amazon_domain) + + (server_response, data) = await email_search( + account=account, + address=address_list, + date=today, + subject=subjects, + header=forwarding_header, + ) + if server_response == "OK" and data[0]: + for email_id in data[0].split(): + fetch_id = ( + email_id.decode() if isinstance(email_id, bytes) else email_id + ) + if cache: + msg_data = (await cache.fetch(fetch_id, "(RFC822)"))[1] + else: + msg_data = (await email_fetch(account, fetch_id, "(RFC822)"))[1] + + is_delivered, urls = self._is_amazon_delivered(msg_data, subjects) + if is_delivered: + count += 1 + for url in urls: + if url not in all_image_urls: + all_image_urls.append(url) + + await self._process_amazon_images( + all_image_urls, image_path, amazon_image_name, count + ) + + return count + + def _is_amazon_delivered( + self, msg_data: list, subjects: list[str] + ) -> tuple[bool, list[str]]: + """Verify if email is a delivered notification and return image URLs.""" + for response_part in msg_data: + if not isinstance(response_part, (bytes, bytearray)): + continue + msg = email.message_from_bytes(response_part) + subject = get_decoded_subject(msg) + if not subject: + continue + + # Check if subject contains any delivered keyword (case-insensitive) + has_delivered = any(s.lower() in subject.lower() for s in subjects) + # Check if subject contains ordered or shipped keywords (case-insensitive) + has_ordered = any( + s.lower() in subject.lower() for s in AMAZON_ORDERED_SUBJECT + ) + has_shipped = any( + s.lower() in subject.lower() for s in AMAZON_SHIPMENT_SUBJECT + ) + + if has_delivered and not has_ordered and not has_shipped: + urls = self._extract_amazon_image_urls(msg) + return True, urls + return False, [] + + def _extract_amazon_image_urls(self, msg: email.message.Message) -> list[str]: + """Extract image URLs from Amazon email body.""" + urls = [] + pattern = re.compile(rf"{const.AMAZON_IMG_PATTERN}") + for part in msg.walk(): + if part.get_content_type() != "text/html": + continue + part_payload = part.get_payload(decode=True) + if part_payload: + part_content = part_payload.decode("utf-8", "ignore") + found = pattern.findall(part_content) + for url in found: + if url[1] not in const.AMAZON_IMG_LIST: + continue + full_url = url[0] + url[1] + url[2] + if full_url not in urls: + urls.append(full_url) + return urls + + async def _process_amazon_images( + self, + image_urls: list[str], + image_base_path: str, + image_name: str, + email_count: int, + ) -> None: + """Process and save Amazon delivery images.""" + if not image_base_path or not image_name: + return + + amazon_path = Path(image_base_path) / "amazon" + image_files = await self._download_all_images(image_urls, image_base_path) + + if len(image_files) > 1: + await self._create_amazon_gif(image_files, amazon_path, image_name) + elif len(image_files) == 1: + await self._save_single_amazon_image( + image_files[0], amazon_path, image_name + ) + else: + await self._copy_amazon_placeholder(amazon_path, image_name) + + async def _download_all_images(self, urls: list[str], base_path: str) -> list[str]: + """Download all image URLs to temporary files.""" + image_files = [] + amazon_path = Path(base_path) / "amazon" + for url in urls: + temp_filename = random_filename() + await download_amazon_img(url, base_path, temp_filename, self.hass) + full_temp_path = amazon_path / temp_filename + if await anyio.Path(full_temp_path).exists(): + image_files.append(str(full_temp_path)) + return image_files + + async def _create_amazon_gif( + self, image_files: list[str], amazon_path: Path, image_name: str + ) -> None: + """Create animated GIF from multiple images.""" + _LOGGER.debug("Combining %d Amazon images into GIF", len(image_files)) + resized_images = await self.hass.async_add_executor_job( + resize_images, image_files, 724, 320 + ) + gif_path = str(amazon_path / image_name) + duration = self.config.get(CONF_DURATION, 5) * 1000 + await self.hass.async_add_executor_job( + generate_delivery_gif, resized_images, gif_path, duration + ) + # Cleanup + for img in image_files + resized_images: + if await anyio.Path(img).exists(): + await self.hass.async_add_executor_job( + cleanup_images, str(Path(img).parent) + "/", Path(img).name + ) + + async def _save_single_amazon_image( + self, image_file: str, amazon_path: Path, image_name: str + ) -> None: + """Save a single image by renaming it to the final name.""" + final_path = amazon_path / image_name + if await anyio.Path(final_path).exists(): + await anyio.Path(final_path).unlink() + await self.hass.async_add_executor_job(Path(image_file).rename, final_path) + _LOGGER.debug("Single Amazon image saved: %s", image_name) + + async def _copy_amazon_placeholder( + self, amazon_path: Path, image_name: str + ) -> None: + """Copy the Amazon no-delivery placeholder.""" + nomail = f"{Path(__file__).parent.parent}/no_deliveries_amazon.jpg" + _LOGGER.debug("No Amazon images found in emails, using placeholder") + try: + await self.hass.async_add_executor_job( + copyfile, nomail, str(amazon_path / image_name) + ) + except OSError as err: + _LOGGER.error("Error attempting to copy image: %s", err) + + async def _amazon_hub( + self, + account: IMAP4_SSL, + fwds: list[str] | None = None, + cache: EmailCache | None = None, + forwarding_header: str = "", + ) -> dict[str, Any]: + """Find Amazon Hub code.""" + _LOGGER.debug("=== AMAZON HUB SEARCH START ===") + count = 0 + code = [] + processed_ids = [] + today = get_today().strftime("%d-%b-%Y") + address_list = amazon_email_addresses(fwds, "amazon.com") + for search_subject in AMAZON_HUB_SUBJECT: + (server_response, data) = await email_search( + account, + address_list, + today, + search_subject, + body=AMAZON_HUB_BODY, + header=forwarding_header, + ) + if server_response == "OK" and data[0] is not None: + for num in data[0].split(): + if num in processed_ids: + continue + processed_ids.append(num) + if cache: + msg_parts = (await cache.fetch(num, "(RFC822)"))[1] + else: + msg_parts = (await email_fetch(account, num, "(RFC822)"))[1] + for response_part in msg_parts: + if isinstance(response_part, (bytes, bytearray)): + msg = email.message_from_bytes(response_part) + actual_subject = get_decoded_subject(msg) + body = get_email_body(msg) + if hub_code := _extract_hub_code( + body, + AMAZON_HUB_BODY, + actual_subject, + AMAZON_HUB_SUBJECT_SEARCH, + ): + count += 1 + if hub_code not in code: + code.append(hub_code) + return {AMAZON_HUB: count, AMAZON_HUB_CODE: code} + + async def _amazon_otp( + self, + account: IMAP4_SSL, + fwds: list[str] | None = None, + cache: EmailCache | None = None, + forwarding_header: str = "", + ) -> dict[str, Any]: + """Find Amazon OTP code.""" + code = [] + today = get_today().strftime("%d-%b-%Y") + address_list = amazon_email_addresses(fwds, "amazon.com") + (server_response, data) = await email_search( + account, + address_list, + today, + AMAZON_OTP_SUBJECT, + body=AMAZON_OTP_REGEX, + header=forwarding_header, + ) + if server_response == "OK" and data[0] is not None: + for num in data[0].split(): + if cache: + msg_parts = (await cache.fetch(num, "(RFC822)"))[1] + else: + msg_parts = (await email_fetch(account, num, "(RFC822)"))[1] + for response_part in msg_parts: + if isinstance(response_part, (bytes, bytearray)): + msg = email.message_from_bytes(response_part) + body = get_email_body(msg) + if ( + found := re.compile(AMAZON_OTP_REGEX).search(body) + ) is not None: + code.append(found.group(2)) + return {AMAZON_OTP: len(code), AMAZON_OTP_CODE: code} + + async def _amazon_exception( + self, + account: IMAP4_SSL, + fwds: list[str] | None = None, + domain: str | None = None, + cache: EmailCache | None = None, + forwarding_header: str = "", + ) -> dict[str, Any]: + """Find Amazon exception emails.""" + count = 0 + orders = [] + today = get_today().strftime("%d-%b-%Y") + address_list = amazon_email_addresses(fwds, domain) + (server_response, data) = await email_search( + account=account, + address=address_list, + date=today, + subject=AMAZON_EXCEPTION_SUBJECT, + header=forwarding_header, + ) + if server_response == "OK" and data[0] is not None: + order_pattern = re.compile(r"[0-9]{3}-[0-9]{7}-[0-9]{7}") + for num in data[0].split(): + if cache: + msg_parts = (await cache.fetch(num, "(RFC822)"))[1] + else: + msg_parts = (await email_fetch(account, num, "(RFC822)"))[1] + for response_part in msg_parts: + if isinstance(response_part, (bytes, bytearray)): + msg = email.message_from_bytes(response_part) + body = get_email_body(msg) + subject = get_decoded_subject(msg) + if AMAZON_EXCEPTION_BODY in body: + count += 1 + if found := order_pattern.findall(body): + orders.extend(found) + if found := order_pattern.findall(subject): + orders.extend(found) + return {AMAZON_EXCEPTION: count, AMAZON_EXCEPTION_ORDER: orders} diff --git a/custom_components/mail_and_packages/shippers/base.py b/custom_components/mail_and_packages/shippers/base.py new file mode 100644 index 0000000..36b91d0 --- /dev/null +++ b/custom_components/mail_and_packages/shippers/base.py @@ -0,0 +1,54 @@ +"""Base Shipper class.""" + +from __future__ import annotations + +from abc import ABC, abstractmethod +from typing import Any + +from aioimaplib import IMAP4_SSL +from homeassistant.core import HomeAssistant + +from custom_components.mail_and_packages.utils.cache import EmailCache + + +class Shipper(ABC): + """Base class for shipper-specific parsing logic.""" + + def __init__(self, hass: HomeAssistant, config: dict[str, Any]) -> None: + """Initialize the shipper.""" + self.hass = hass + self.config = config + + @property + @abstractmethod + def name(self) -> str: + """Return the internal name of the shipper.""" + + @classmethod + @abstractmethod + def handles_sensor(cls, sensor_type: str) -> bool: + """Return True if this shipper handles the given sensor type.""" + + @abstractmethod + async def process( + self, + account: IMAP4_SSL, + date: str, + sensor_type: str, + ) -> dict[str, Any]: + """Process emails for this shipper on the given date for a specific sensor.""" + + @abstractmethod + async def process_batch( + self, + account: IMAP4_SSL, + date: str, + sensors: list[str], + cache: EmailCache, + since_date: str | None = None, + ) -> dict[str, Any]: + """Process multiple sensors for this shipper using batched fetching/searching. + + since_date: earliest IMAP SINCE date for _delivering/_exception/_delivered + sensors. Defaults to date (today) if not provided. + """ diff --git a/custom_components/mail_and_packages/shippers/generic.py b/custom_components/mail_and_packages/shippers/generic.py new file mode 100644 index 0000000..c0f7c2e --- /dev/null +++ b/custom_components/mail_and_packages/shippers/generic.py @@ -0,0 +1,697 @@ +"""Generic Shipper class.""" + +from __future__ import annotations + +import email +import logging +from email.header import decode_header +from pathlib import Path +from shutil import copyfile +from typing import Any + +import anyio +from aioimaplib import IMAP4_SSL + +from custom_components.mail_and_packages.const import ( + AMAZON_DELIEVERED_BY_OTHERS_SEARCH_TEXT, + AMAZON_DELIVERED, + ATTR_BODY, + ATTR_BODY_COUNT, + ATTR_COUNT, + ATTR_EMAIL, + ATTR_PATTERN, + ATTR_SUBJECT, + ATTR_TRACKING, + CAMERA_DATA, + CAMERA_EXTRACTION_CONFIG, + CONF_FORWARDING_HEADER, + SENSOR_DATA, +) +from custom_components.mail_and_packages.utils.cache import EmailCache +from custom_components.mail_and_packages.utils.email import find_text, find_text_matches +from custom_components.mail_and_packages.utils.imap import ( + email_fetch, + email_fetch_headers, + email_search, +) +from custom_components.mail_and_packages.utils.shipper import ( + generic_delivery_image_extraction, + get_tracking, +) + +from .base import Shipper + +_LOGGER = logging.getLogger(__name__) + + +class GenericShipper(Shipper): + """Generic Shipper class for UPS, FedEx, Walmart, etc.""" + + @property + def name(self) -> str: + """Return the internal name of the shipper.""" + return "generic" + + @classmethod + def handles_sensor(cls, sensor_type: str) -> bool: + """Return True if this shipper handles the given sensor type.""" + return sensor_type in SENSOR_DATA + + async def process( + self, + account: IMAP4_SSL, + date: str, + sensor_type: str, + cache: EmailCache | None = None, + since_date: str | None = None, + ) -> dict[str, Any]: + """Process emails for this shipper on the given date. + + since_date: if provided, used instead of date for _delivering and + _exception sensors so that emails from previous days are included. + """ + _LOGGER.debug("Processing generic sensor: %s", sensor_type) + + if sensor_type not in SENSOR_DATA: + _LOGGER.error("Sensor %s not found in SENSOR_DATA", sensor_type) + return {ATTR_COUNT: 0} + + config = SENSOR_DATA[sensor_type] + email_addresses = config.get(ATTR_EMAIL, []) + subjects = config.get(ATTR_SUBJECT, []) + + # _packages sensors with no email/subject are computed in process_batch + # as delivering + delivered; skip IMAP search here. + if sensor_type.endswith("_packages") and not email_addresses and not subjects: + _LOGGER.debug( + "Skipping email search for %s: no email addresses configured", + sensor_type, + ) + return {ATTR_COUNT: 0, ATTR_TRACKING: []} + + forwarding_header, email_addresses = self._resolve_forwarding(email_addresses) + + # _delivering/_exception/_packages use the extended window so in-transit + # packages remain visible across the midnight boundary. + # _delivered uses today's date for the sensor count (resets at midnight) + # but also searches the extended window to obtain tracking numbers for + # deduplication — without those, a package delivered yesterday would still + # appear as "delivering" today because the delivering email is in the window + # but the delivered email is not. + is_delivered = sensor_type.endswith("_delivered") + search_date = date + if ( + since_date + and sensor_type.endswith( + ("_delivering", "_exception", "_delivered", "_packages") + ) + and sensor_type != "post_de_delivering" + ): + search_date = since_date + + result = {ATTR_COUNT: 0, ATTR_TRACKING: []} + + # Skip email search for sensors with no email addresses configured + # (e.g. *_packages sensors that are empty dicts in SENSOR_DATA) + if not email_addresses: + _LOGGER.debug( + "Skipping email search for %s: no email addresses configured", + sensor_type, + ) + return result + + image_path = self.config.get("image_path") + # Setup image extraction + shipper_cfg = await self._setup_image_extraction(sensor_type, image_path) + image_found = False + + count, found_data, image_found = await self._search_for_emails( + account, + email_addresses, + search_date, + subjects, + config, + shipper_cfg, + sensor_type, + result, + cache, + forwarding_header, + ) + + # Process tracking numbers + result[ATTR_TRACKING] = await self._process_tracking_numbers( + sensor_type, + found_data, + account, + cache, + ) + if result[ATTR_TRACKING]: + count = len(result[ATTR_TRACKING]) + + if is_delivered: + result["pre_filtered_tracking"] = result.get(ATTR_TRACKING, []) + + # For _delivered sensors, the extended-window search gives us tracking + # numbers needed for deduplication (above), but the count must reflect + # only today's deliveries so the sensor resets at midnight. + if is_delivered and since_date and search_date != date: + today_result: dict[str, Any] = {ATTR_COUNT: 0, ATTR_TRACKING: []} + today_count, today_found, _ = await self._search_for_emails( + account, + email_addresses, + date, + subjects, + config, + shipper_cfg, + sensor_type, + today_result, + cache, + forwarding_header, + ) + today_tracking = await self._process_tracking_numbers( + sensor_type, today_found, account, cache + ) + count = len(today_tracking) if today_tracking else today_count + result[ATTR_TRACKING] = today_tracking + + result[ATTR_COUNT] = count + if shipper_cfg: + image_attr = f"{shipper_cfg['name']}_image" + result[image_attr] = shipper_cfg["image_name"] + result["image_path"] = image_path + + if not image_found: + await self._copy_generic_placeholder(shipper_cfg) + + return result + + def _resolve_forwarding(self, email_addresses: list[str]) -> tuple[str, list[str]]: + """Return (forwarding_header, resolved_email_addresses). + + Header mode: uses original-sender header for matching; address list + is passed as-is so IMAP can match via HEADER substring. + Address-list mode: prepends the user's forwarded addresses so that + emails arriving through a forwarding service are also matched. + """ + forwarding_header = self.config.get(CONF_FORWARDING_HEADER, "") + if forwarding_header and forwarding_header != "(none)": + return forwarding_header, email_addresses + forwarding_header = "" + forwarded_emails = self.config.get("forwarded_emails", []) + if isinstance(forwarded_emails, str): + forwarded_emails = [ + e.strip() for e in forwarded_emails.split(",") if e.strip() + ] + if forwarded_emails: + email_addresses = forwarded_emails + email_addresses + return forwarding_header, email_addresses + + async def process_batch( + self, + account: IMAP4_SSL, + date: str, + sensors: list[str], + cache: EmailCache, + since_date: str | None = None, + ) -> dict[str, Any]: + """Process multiple generic sensors in batch.""" + batch_results, all_tracking = await self._process_individual_sensors( + account, date, sensors, cache, since_date + ) + + self._deduplicate_batch_tracking(batch_results) + self._compute_package_totals(batch_results) + + # Merge results and aggregate global tracking + res = {} + for sensor, sensor_res in batch_results: + tracking = ( + sensor_res.pop("pre_filtered_tracking", []) + if sensor.endswith("_delivered") + else sensor_res.get(ATTR_TRACKING) + ) + res.update(sensor_res) + # Expose per-sensor raw tracking for coordinator state management. + # Keyed as "_tracking_details" to distinguish from the public data dict. + if tracking and sensor.endswith( + ("_delivering", "_delivered", "_exception") + ): + res.setdefault("_tracking_details", {})[sensor] = list(tracking) + + if all_tracking: + res[ATTR_TRACKING] = list(all_tracking) + + return res + + async def _process_individual_sensors( + self, + account: IMAP4_SSL, + date: str, + sensors: list[str], + cache: EmailCache, + since_date: str | None = None, + ) -> tuple[list[tuple[str, dict[str, Any]]], set[str]]: + """Process each sensor independently and aggregate tracking.""" + batch_results = [] + all_tracking = set() + + for sensor in sensors: + sensor_res = await self.process( + account, date, sensor, cache, since_date=since_date + ) + # Replicate coordinator dictionary logic for local sensor counts + if sensor not in sensor_res and ATTR_COUNT in sensor_res: + sensor_res[sensor] = sensor_res[ATTR_COUNT] + + # Capture today-only tracking for _delivered sensors BEFORE + # _deduplicate_batch_tracking runs (which currently only modifies + # _delivering and _packages sensor results). + if sensor_res.get(ATTR_TRACKING) and sensor.endswith("_delivered"): + sensor_res[f"{sensor}_tracking"] = sensor_res[ATTR_TRACKING] + + # Record results for post-processing + batch_results.append((sensor, sensor_res)) + + # Aggregate all tracking numbers found + if sensor_res.get(ATTR_TRACKING): + all_tracking.update(sensor_res[ATTR_TRACKING]) + + return batch_results, all_tracking + + def _deduplicate_batch_tracking( + self, + batch_results: list[tuple[str, dict[str, Any]]], + ) -> None: + """Deduplicate tracking numbers across sensors based on shipper prefix.""" + shippers = {} + for sensor, sensor_res in batch_results: + # Prefix is everything before the last underscore (e.g., 'ups', 'fedex') + prefix = "_".join(sensor.split("_")[:-1]) + if prefix not in shippers: + shippers[prefix] = { + "delivered": set(), + "delivering": set(), + "update_targets": [], + "package_targets": [], + } + + tracking = set(sensor_res.get(ATTR_TRACKING, [])) + if sensor.endswith("_delivered"): + shippers[prefix]["delivered"].update(tracking) + elif sensor.endswith(("_delivering", "_exception")): + shippers[prefix]["delivering"].update(tracking) + shippers[prefix]["update_targets"].append((sensor, sensor_res)) + elif sensor.endswith("_packages"): + shippers[prefix]["package_targets"].append((sensor, sensor_res)) + + for data in shippers.values(): + # Remove "delivered" tracking numbers from in-transit sensors + self._apply_deduplication(data["update_targets"], data["delivered"]) + # Remove "delivering" and "delivered" tracking numbers from _packages + # so _packages only shows packages not yet out for delivery or delivered + in_pipeline = data["delivering"] | data["delivered"] + self._apply_deduplication(data["package_targets"], in_pipeline) + + def _apply_deduplication( + self, + targets: list[tuple[str, dict[str, Any]]], + delivered_ids: set[str], + ) -> None: + """Apply deduplication logic to a list of target sensors.""" + if not delivered_ids: + return + + for sensor, sensor_res in targets: + original_tracking = sensor_res.get(ATTR_TRACKING, []) + new_tracking = [ + tid for tid in original_tracking if tid not in delivered_ids + ] + + if len(new_tracking) != len(original_tracking): + sensor_res[ATTR_TRACKING] = new_tracking + sensor_res[sensor] = len(new_tracking) + if ATTR_COUNT in sensor_res: + sensor_res[ATTR_COUNT] = len(new_tracking) + + def _compute_package_totals( + self, + batch_results: list[tuple[str, dict[str, Any]]], + ) -> None: + """Compute _packages sensors with empty config as delivering + delivered. + + These sensors have no IMAP search of their own; their value is the + sum of the shipper's _delivering and _delivered counts (matching the + original pre-refactor behaviour in helpers.py). + """ + sensor_counts = { + sensor: sensor_res.get(sensor, sensor_res.get(ATTR_COUNT, 0)) + for sensor, sensor_res in batch_results + } + + for sensor, sensor_res in batch_results: + if not sensor.endswith("_packages"): + continue + config = SENSOR_DATA.get(sensor, {}) + if config.get(ATTR_EMAIL) or config.get(ATTR_SUBJECT): + continue # sensor has its own IMAP search config + prefix = sensor.replace("_packages", "") + computed = sensor_counts.get(f"{prefix}_delivering", 0) + sensor_counts.get( + f"{prefix}_delivered", 0 + ) + sensor_res[sensor] = computed + sensor_res[ATTR_COUNT] = computed + + async def _copy_generic_placeholder(self, shipper_cfg: dict[str, Any]) -> None: + """Copy the generic placeholder for the shipper.""" + shipper_name = shipper_cfg["name"] + # Try to find courier-specific placeholder + placeholder = Path(__file__).parent.parent / f"no_deliveries_{shipper_name}.jpg" + if not await anyio.Path(placeholder).exists(): + placeholder = Path(__file__).parent.parent / "mail_none.gif" + + target = ( + Path(shipper_cfg["image_path"]) / shipper_name / shipper_cfg["image_name"] + ) + _LOGGER.debug( + "No %s images found in emails, using placeholder: %s", + shipper_name, + placeholder.name, + ) + try: + await self.hass.async_add_executor_job( + copyfile, str(placeholder), str(target) + ) + except OSError as err: + _LOGGER.error("Error attempting to copy placeholder: %s", err) + + async def _search_for_emails( + self, + account: IMAP4_SSL, + email_addresses: list[str], + date: str, + subjects: list[str], + config: dict[str, Any], + shipper_cfg: dict[str, Any] | None, + sensor_type: str, + result: dict[str, Any], + cache: EmailCache | None = None, + forwarding_header: str = "", + ) -> tuple[int, list[bytes], bool]: + """Search for and process emails.""" + count = 0 + unique_email_ids = set() + found_data = [] + image_found = False + + (server_response, sdata) = await email_search( + account=account, + address=email_addresses, + date=date, + subject=subjects, + body=config.get(ATTR_BODY, ""), + header=forwarding_header, + ) + + if server_response == "OK" and sdata[0]: + raw_ids = sdata[0].split() + _LOGGER.debug( + "Found %d matching email IDs for %s: %s", + len(raw_ids), + sensor_type, + [eid.decode() if isinstance(eid, bytes) else eid for eid in raw_ids], + ) + verified_ids = await self._verify_matched_subjects( + account, raw_ids, sensor_type, subjects, cache + ) + filtered_new_ids = self._filter_unique_ids(verified_ids, unique_email_ids) + + if filtered_new_ids: + count, img_found = await self._process_matched_emails( + account, + config, + filtered_new_ids, + count, + cache, + shipper_cfg, + sensor_type, + result, + found_data, + ) + if img_found: + image_found = True + + return count, found_data, image_found + + def _decode_subject(self, header_part: bytes | bytearray) -> str | None: + """Decode MIME encoded subject from email header part.""" + msg = email.message_from_bytes(header_part) + header_val = msg.get("subject") + if not header_val: + return None + + decoded = decode_header(header_val)[0] + subject_bytes, encoding = decoded + if encoding: + try: + if isinstance(subject_bytes, bytes): + return subject_bytes.decode(encoding, "ignore").strip() + return str(subject_bytes).strip() + except (LookupError, UnicodeError): + pass + + if isinstance(subject_bytes, bytes): + return subject_bytes.decode("utf-8", "ignore").strip() + return str(subject_bytes).strip() + + async def _verify_matched_subjects( + self, + account: IMAP4_SSL, + email_ids: list[bytes], + sensor_type: str, + expected_subjects: list[str], + cache: EmailCache | None = None, + ) -> list[bytes]: + """Verify the subject of each matched email locally and log for debugging.""" + if not expected_subjects: + return email_ids + + verified_ids = [] + expected_subjects_lower = [s.lower() for s in expected_subjects] + + for eid in email_ids: + try: + if cache: + header_data = ( + await cache.fetch(eid, "(BODY[HEADER.FIELDS (SUBJECT)])") + )[1] + else: + header_data = (await email_fetch_headers(account, eid))[1] + + subject_found = False + for part in header_data: + if isinstance(part, (bytes, bytearray)): + subject = self._decode_subject(part) + if not subject: + continue + + _LOGGER.debug( + "Matched email for %s (ID %s): %s", + sensor_type, + eid.decode() if isinstance(eid, bytes) else eid, + subject, + ) + subject_lower = subject.lower() + if any( + expected in subject_lower + for expected in expected_subjects_lower + ): + subject_found = True + + if subject_found: + verified_ids.append(eid) + else: + _LOGGER.debug( + "Email ID %s rejected for %s: Subject did not match any expected subjects.", + eid.decode() if isinstance(eid, bytes) else eid, + sensor_type, + ) + except (OSError, AttributeError) as err: + _LOGGER.debug("Could not fetch subject for email %s: %s", eid, err) + + return verified_ids + + def _filter_unique_ids( + self, email_ids: list[bytes], unique_email_ids: set + ) -> list[bytes]: + """Filter out already processed email IDs.""" + new_ids = [] + for eid in email_ids: + eid_str = eid.decode() if isinstance(eid, bytes) else str(eid) + if eid_str not in unique_email_ids: + unique_email_ids.add(eid_str) + new_ids.append(eid) + return new_ids + + async def _process_matched_emails( + self, + account: IMAP4_SSL, + config: dict[str, Any], + new_ids: list[bytes], + current_count: int, + cache: EmailCache | None, + shipper_cfg: dict[str, Any] | None, + sensor_type: str, + result: dict[str, Any], + found_data: list[bytes], + ) -> tuple[int, bool]: + """Process a batch of matched unique emails.""" + image_found = False + count, matched_ids = await self._process_emails_by_type( + account, config, new_ids, current_count, cache + ) + if matched_ids: + found_data.append(b" ".join(matched_ids)) + + if shipper_cfg: + if await self._extract_images_for_shipper( + account, matched_ids, shipper_cfg, cache + ): + image_found = True + + if sensor_type.endswith("_delivered") and sensor_type != AMAZON_DELIVERED: + await self._check_amazon_mentions(account, matched_ids, result, cache) + + return count, image_found + + async def _process_tracking_numbers( + self, + sensor_type: str, + found_data: list, + account: IMAP4_SSL, + cache: EmailCache | None = None, + ) -> list: + """Process tracking numbers for the sensor.""" + tracking_key = f"{'_'.join(sensor_type.split('_')[:-1])}_tracking" + if ( + tracking_key not in SENSOR_DATA + or ATTR_PATTERN not in SENSOR_DATA[tracking_key] + ): + return [] + + pattern = SENSOR_DATA[tracking_key][ATTR_PATTERN][0] + tracking_nums = [] + for sdata in found_data: + tracking_nums.extend( + await get_tracking(sdata.decode(), account, pattern, cache) + ) + + return list(dict.fromkeys(tracking_nums)) + + async def _setup_image_extraction( + self, + sensor_type: str, + image_path: str, + ) -> dict | None: + """Set up image extraction configuration.""" + if not sensor_type.endswith("_delivered"): + return None + + shipper_name = sensor_type.replace("_delivered", "") + camera_key = f"{shipper_name}_camera" + if camera_key not in CAMERA_DATA or camera_key in ( + "usps_camera", + "generic_camera", + ): + return None + + extraction_config = CAMERA_EXTRACTION_CONFIG.get(shipper_name, {}) + absolute_image_path = image_path.rstrip("/") + "/" + + def _create_dir(): + path = Path(absolute_image_path) / shipper_name + if not path.exists(): + path.mkdir(parents=True, exist_ok=True) + + await self.hass.async_add_executor_job(_create_dir) + + return { + "name": shipper_name, + "image_path": absolute_image_path, + "image_name": self.config.get(f"{shipper_name}_image") + or f"{shipper_name}_delivery.jpg", + "image_type": extraction_config.get("image_type", "jpeg"), + "cid_name": extraction_config.get("cid_name"), + "pattern": extraction_config.get("attachment_filename_pattern"), + } + + async def _process_emails_by_type( + self, + account: IMAP4_SSL, + config: dict, + ids: list, + current_count: int, + cache: EmailCache | None = None, + ) -> tuple[int, list]: + """Process emails based on body search or just count.""" + if ATTR_BODY in config: + body_count = config.get(ATTR_BODY_COUNT, False) + mock_data = (b" ".join(ids),) + count, matched_ids = await find_text_matches( + mock_data, + account, + config[ATTR_BODY], + body_count, + cache, + ) + return current_count + count, matched_ids + return current_count + len(ids), list(ids) + + async def _extract_images_for_shipper( + self, + account: IMAP4_SSL, + ids: list, + s_config: dict, + cache: EmailCache | None = None, + ) -> bool: + """Extract delivery images from emails.""" + image_found = False + for eid in ids: + if cache: + msg_parts = (await cache.fetch(eid, "(RFC822)"))[1] + else: + msg_parts = (await email_fetch(account, eid, "(RFC822)"))[1] + for response_part in msg_parts: + if isinstance(response_part, (bytes, bytearray)): + if generic_delivery_image_extraction( + response_part, + s_config["image_path"], + s_config["image_name"], + s_config["name"], + s_config["image_type"], + s_config["cid_name"], + s_config["pattern"], + ): + _LOGGER.debug("Extracted image for %s", s_config["name"]) + image_found = True + return image_found + + async def _check_amazon_mentions( + self, + account: IMAP4_SSL, + ids: list, + result: dict, + cache: EmailCache | None = None, + ): + """Check for Amazon mentions in emails.""" + mock_data = (b" ".join(ids),) + amazon_mentions = await find_text( + mock_data, + account, + AMAZON_DELIEVERED_BY_OTHERS_SEARCH_TEXT, + False, + cache, + ) + if amazon_mentions > 0: + result["amazon_delivered_by_others"] = ( + result.get("amazon_delivered_by_others", 0) + amazon_mentions + ) diff --git a/custom_components/mail_and_packages/shippers/post_de.py b/custom_components/mail_and_packages/shippers/post_de.py new file mode 100644 index 0000000..924e97c --- /dev/null +++ b/custom_components/mail_and_packages/shippers/post_de.py @@ -0,0 +1,370 @@ +"""Post DE Shipper class.""" + +from __future__ import annotations + +import email +import io +import logging +import shutil +from pathlib import Path +from typing import Any + +import anyio +from aioimaplib import IMAP4_SSL +from PIL import Image, UnidentifiedImageError + +from custom_components.mail_and_packages.const import ( + ATTR_IMAGE_PATH, + CONF_CUSTOM_IMG_FILE, + CONF_DURATION, + CONF_FORWARDING_HEADER, + CONF_GENERATE_GRID, + CONF_GENERATE_MP4, + CONF_POST_DE_CUSTOM_IMG_FILE, + DEFAULT_CUSTOM_IMG_FILE, + SENSOR_DATA, +) +from custom_components.mail_and_packages.utils.cache import EmailCache +from custom_components.mail_and_packages.utils.date import get_formatted_date +from custom_components.mail_and_packages.utils.image import ( + _generate_mp4, + cleanup_images, + generate_delivery_gif, + generate_grid_img, + random_filename, + resize_images, +) +from custom_components.mail_and_packages.utils.imap import email_fetch, email_search + +from .base import Shipper + +_LOGGER = logging.getLogger(__name__) + + +class PostDEShipper(Shipper): + """Post DE Briefankündigung shipper.""" + + @property + def name(self) -> str: + """Return shipper name.""" + return "post_de" + + @classmethod + def handles_sensor(cls, sensor_type: str) -> bool: + """Return True if this shipper handles the given sensor type.""" + return sensor_type == "post_de_mail" + + async def process( + self, + account: IMAP4_SSL, + date: str, + sensor_type: str, + cache: EmailCache | None = None, + ) -> dict[str, Any]: + """Process Post DE Briefankündigung emails.""" + if sensor_type != "post_de_mail": + return {sensor_type: 0} + + config = self._get_config() + image_count = 0 + images = [] + images_delete = [] + + (server_response, data) = await self._search_emails(account) + + # Bail out on error + if server_response != "OK" or data[0] is None: + return {sensor_type: image_count} + + # Setup image directory + post_de_dir = Path(config["image_output_path"]) / "post_de" + if not await self._setup_image_directory(str(post_de_dir)): + return {sensor_type: image_count} + + _LOGGER.debug("Post DE Briefankündigung email found processing...") + for num in data[0].split(): + (image_count, images) = await self._process_post_de_email( + account, + num, + str(post_de_dir), + image_count, + images, + cache, + ) + + image_count = len(images) + + if image_count > 0: + await self._generate_mail_image( + images, + str(post_de_dir), + config["image_name"], + config["gif_duration"], + images_delete, + ) + elif image_count == 0: + await self._copy_nomail_image( + str(post_de_dir), + config["image_name"], + config["custom_img"], + ) + + if config["gen_mp4"]: + await self._generate_mp4_video( + str(post_de_dir), + config["image_name"], + ) + if config["gen_grid"]: + await self._generate_grid_image( + str(post_de_dir), + config["image_name"], + image_count, + ) + + return { + sensor_type: image_count, + "post_de_image": config["image_name"], + ATTR_IMAGE_PATH: config["image_output_path"], + "post_de_grid_image_name": config["image_name"].replace( + ".gif", "_grid.png" + ), + } + + async def process_batch( + self, + account: IMAP4_SSL, + date: str, + sensors: list[str], + cache: EmailCache, + since_date: str | None = None, + ) -> dict[str, Any]: + """Process multiple Post DE sensors in batch.""" + res = {} + for sensor in sensors: + res.update(await self.process(account, date, sensor, cache)) + + # Replicate coordinator dict structure + if sensor not in res: + res[sensor] = res.get(sensor, 0) + + return res + + async def _generate_mp4_video(self, path: str, name: str): + """Generate MP4 video from images.""" + await self.hass.async_add_executor_job(_generate_mp4, path + "/", name) + + async def _generate_grid_image(self, path: str, name: str, count: int): + """Generate grid image from images.""" + await self.hass.async_add_executor_job( + generate_grid_img, path + "/", name, count + ) + + async def _generate_mail_image( + self, + images: list, + path: str, + name: str, + duration: int, + delete_list: list, + ): + """Generate animated GIF from mail images.""" + try: + _LOGGER.debug("Resizing Post DE images to 724x320...") + all_images = await self.hass.async_add_executor_job( + resize_images, + images, + 724, + 320, + ) + delete_list.extend(all_images) + + _LOGGER.debug("Generating animated GIF for Post DE") + gif_path = str(Path(path) / name) + await self.hass.async_add_executor_job( + generate_delivery_gif, + all_images, + gif_path, + duration * 1000, + ) + _LOGGER.debug("Post DE mail image generated.") + except (OSError, ValueError) as err: + _LOGGER.error("Error attempting to generate Post DE image: %s", err) + + for image in delete_list: + await self.hass.async_add_executor_job( + cleanup_images, + f"{Path(image).parent}/", + Path(image).name, + ) + + async def _copy_nomail_image(self, path: str, name: str, custom_img: str | None): + """Copy the 'no mail' placeholder image.""" + + def _prepare(): + if not Path(path).exists(): + Path(path).mkdir(parents=True, exist_ok=True) + target = Path(path) / name + if target.is_file(): + cleanup_images(path + "/", name) + src = custom_img or str(Path(__file__).parent.parent / "mail_none.gif") + shutil.copyfile(src, str(target)) + + _LOGGER.debug("No Post DE mail found.") + try: + await self.hass.async_add_executor_job(_prepare) + except OSError as err: + _LOGGER.error("Error attempting to copy Post DE image: %s", err) + + def _get_config(self) -> dict: + """Get Post DE specific configuration.""" + + image_path = self.config.get("image_path") + return { + "image_output_path": image_path, + "gif_duration": self.config.get(CONF_DURATION), + "image_name": self.config.get("post_de_image") or "post_de_deliveries.gif", + "gen_mp4": self.config.get(CONF_GENERATE_MP4), + "custom_img": self.config.get(CONF_POST_DE_CUSTOM_IMG_FILE) + or self.config.get(CONF_CUSTOM_IMG_FILE) + or DEFAULT_CUSTOM_IMG_FILE, + "gen_grid": self.config.get(CONF_GENERATE_GRID), + } + + async def _search_emails(self, account: IMAP4_SSL) -> tuple: + """Search for Post DE Briefankündigung emails.""" + _LOGGER.debug("Attempting to find Post DE Briefankündigung mail") + _LOGGER.debug("Post DE search date: %s", get_formatted_date()) + + config = SENSOR_DATA["post_de_mail"] + email_addresses = config.get("email", []) + subjects = config.get("subject", []) + + forwarding_header = self.config.get(CONF_FORWARDING_HEADER, "") + if forwarding_header and forwarding_header != "(none)": + pass + else: + forwarding_header = "" + forwarded_emails = self.config.get("forwarded_emails", []) + if isinstance(forwarded_emails, str): + forwarded_emails = [ + e.strip() for e in forwarded_emails.split(",") if e.strip() + ] + if forwarded_emails: + email_addresses = forwarded_emails + email_addresses + + return await email_search( + account=account, + address=email_addresses, + date=get_formatted_date(), + subject=subjects, + header=forwarding_header, + ) + + async def _setup_image_directory(self, path: str) -> bool: + """Ensure image directory exists and is prepared.""" + if not await anyio.Path(path).is_dir(): + try: + await anyio.Path(path).mkdir(parents=True, exist_ok=True) + except OSError as err: + _LOGGER.error("Error creating directory: %s", err) + return False + + # Clean up + await self.hass.async_add_executor_job(cleanup_images, path + "/") + return True + + async def _process_post_de_email( # noqa: C901 + self, + account: IMAP4_SSL, + num: str, + image_output_path: str, + image_count: int, + images: list, + cache: EmailCache | None = None, + ) -> tuple[int, list]: + """Process a single Post DE email and extract envelope scans. + + Expected email payload format is HTML containing inline tags + referencing base64-encoded PNG/JPEG images. + """ + if cache: + msg_parts = (await cache.fetch(num, "(RFC822)"))[1] + else: + msg_parts = (await email_fetch(account, num, "(RFC822)"))[1] + _LOGGER.debug("Processing Post DE email number: %s", num) + for response_part in msg_parts: + if isinstance(response_part, (bytes, bytearray)): + msg = email.message_from_bytes(response_part) + for part in msg.walk(): + if part.get_content_type() in ("image/png", "image/jpeg"): + payload = part.get_payload(decode=True) + if not payload: + continue + + # Check image dimensions to skip logos/icons + def _check_and_save( + img_bytes: bytes, + out_path: str, + content_type: str, + ) -> str | None: + try: + img = Image.open(io.BytesIO(img_bytes)) + if img.format is None: + _LOGGER.debug( + "Post DE image format is unidentified (None)" + ) + return None + + # Validate format against expected content type + if content_type == "image/png" and img.format != "PNG": + _LOGGER.debug( + "Post DE image format mismatch: expected PNG, got %s", + img.format, + ) + return None + if ( + content_type == "image/jpeg" + and img.format != "JPEG" + ): + _LOGGER.debug( + "Post DE image format mismatch: expected JPEG, got %s", + img.format, + ) + return None + + width, height = img.size + if width > 150 and height > 100: + ext = ( + ".png" + if content_type == "image/png" + else ".jpg" + ) + filename = random_filename(ext=ext) + target = Path(out_path) / filename + with target.open("wb") as f: + f.write(img_bytes) + return str(target) + except UnidentifiedImageError as err: + _LOGGER.warning( + "Unidentified image found in Post DE email: %s", err + ) + except (OSError, ValueError, TypeError) as err: + _LOGGER.debug( + "Error checking/saving Post DE image: %s", err + ) + return None + + saved_path = await self.hass.async_add_executor_job( + _check_and_save, + payload, + image_output_path, + part.get_content_type(), + ) + if saved_path: + images.append(saved_path) + image_count += 1 + _LOGGER.debug( + "Extracted Post DE mail image: %s", saved_path + ) + + return image_count, images diff --git a/custom_components/mail_and_packages/shippers/usps.py b/custom_components/mail_and_packages/shippers/usps.py new file mode 100644 index 0000000..b88c1d3 --- /dev/null +++ b/custom_components/mail_and_packages/shippers/usps.py @@ -0,0 +1,425 @@ +"""USPS Shipper class.""" + +from __future__ import annotations + +import base64 +import email +import logging +import re +import shutil +from pathlib import Path +from typing import Any + +import anyio +from aioimaplib import IMAP4_SSL +from bs4 import BeautifulSoup + +from custom_components.mail_and_packages.const import ( + ATTR_COUNT, + ATTR_EMAIL, + ATTR_GRID_IMAGE_NAME, + ATTR_IMAGE_PATH, + ATTR_SUBJECT, + ATTR_USPS_IMAGE, + ATTR_USPS_MAIL, + CONF_CUSTOM_IMG_FILE, + CONF_DURATION, + CONF_FORWARDING_HEADER, + CONF_GENERATE_GRID, + CONF_GENERATE_MP4, + DEFAULT_CUSTOM_IMG_FILE, + SENSOR_DATA, +) +from custom_components.mail_and_packages.utils.cache import EmailCache +from custom_components.mail_and_packages.utils.date import get_formatted_date +from custom_components.mail_and_packages.utils.image import ( + _generate_mp4, + cleanup_images, + copy_overlays, + generate_delivery_gif, + generate_grid_img, + io_save_file, + random_filename, + resize_images, +) +from custom_components.mail_and_packages.utils.imap import email_fetch, email_search + +from .base import Shipper + +_LOGGER = logging.getLogger(__name__) + + +class USPSShipper(Shipper): + """USPS Informed Delivery shipper.""" + + @property + def name(self) -> str: + """Return shipper name.""" + return "usps" + + @classmethod + def handles_sensor(cls, sensor_type: str) -> bool: + """Return True if this shipper handles the given sensor type.""" + return sensor_type == "usps_mail" + + async def process( + self, + account: IMAP4_SSL, + date: str, + sensor_type: str, + cache: EmailCache | None = None, + ) -> dict[str, Any]: + """Process USPS Informed Delivery emails.""" + config = self._get_usps_config() + image_count = 0 + images = [] + images_delete = [] + + (server_response, data) = await self._search_informed_delivery(account) + + # Bail out on error + if server_response != "OK" or data[0] is None: + return {ATTR_COUNT: image_count} + + # Setup image directory and overlays + if not await self._setup_image_directory(config["image_output_path"]): + return {ATTR_COUNT: image_count} + + all_msg_content = "" + if server_response == "OK": + _LOGGER.debug("Informed Delivery email found processing...") + for num in data[0].split(): + (image_count, images, email_content) = await self._process_usps_email( + account, + num, + config["image_output_path"], + image_count, + images, + cache, + ) + all_msg_content += email_content + + # Process images + images = await self._process_usps_images(all_msg_content, images) + image_count = len(images) + + if image_count > 0: + await self._generate_mail_image( + images, + config["image_output_path"], + config["image_name"], + config["gif_duration"], + images_delete, + ) + elif image_count == 0: + await self._copy_nomail_image( + config["image_output_path"], + config["image_name"], + config["custom_img"], + ) + + if config["gen_mp4"]: + await self._generate_mp4_video( + config["image_output_path"], + config["image_name"], + ) + if config["gen_grid"]: + await self._generate_grid_image( + config["image_output_path"], + config["image_name"], + image_count, + ) + + return { + ATTR_COUNT: image_count, + ATTR_USPS_IMAGE: config["image_name"], + ATTR_IMAGE_PATH: config["image_output_path"], + ATTR_GRID_IMAGE_NAME: config["image_name"].replace(".gif", "_grid.png"), + } + + async def process_batch( + self, + account: IMAP4_SSL, + date: str, + sensors: list[str], + cache: EmailCache, + since_date: str | None = None, + ) -> dict[str, Any]: + """Process multiple USPS sensors in batch.""" + res = {} + for sensor in sensors: + res.update(await self.process(account, date, sensor, cache)) + + # Replicatecoordinator dict structure + if sensor not in res: + if ATTR_COUNT in res: + res[sensor] = res[ATTR_COUNT] + # Don't pop ATTR_COUNT because other things might need it, actually + # coordinator used to pop it via explicit assignment + + return res + + async def _generate_mp4_video(self, path: str, name: str): + """Generate MP4 video from images.""" + await self.hass.async_add_executor_job(_generate_mp4, path, name) + + async def _generate_grid_image(self, path: str, name: str, count: int): + """Generate grid image from images.""" + await self.hass.async_add_executor_job(generate_grid_img, path, name, count) + + async def _process_usps_images(self, content: str, images: list) -> list: + """Process USPS images (placeholder and filtering).""" + # Old USPS format: plain-text email body contained the filename as a reference. + # New format is handled in _extract_usps_images on properly decoded HTML. + if re.compile(r"\bimage-no-mailpieces?700\.jpg\b").search(content) is not None: + placeholder = Path(__file__).parent.parent / "image-no-mailpieces700.jpg" + placeholder_str = str(placeholder) + if placeholder.exists() and placeholder_str not in images: + images.append(placeholder_str) + _LOGGER.debug( + "Placeholder image found using: image-no-mailpieces700.jpg.", + ) + + # Announcement images removal + return self._remove_announcement_images(images) + + def _remove_announcement_images(self, images: list) -> list: + """Remove announcement images.""" + return [ + el + for el in images + if not any( + ignore in el + for ignore in ["mailerProvidedImage", "ra_0", "Mail Attachment.txt"] + ) + ] + + async def _generate_mail_image( + self, + images: list, + path: str, + name: str, + duration: int, + delete_list: list, + ): + """Generate animated GIF from mail images.""" + _LOGGER.debug("Resizing images to 724x320...") + all_images = await self.hass.async_add_executor_job( + resize_images, + images, + 724, + 320, + ) + delete_list.extend(all_images) + + try: + _LOGGER.debug("Generating animated GIF") + gif_path = str(Path(path) / name) + await self.hass.async_add_executor_job( + generate_delivery_gif, + all_images, + gif_path, + duration * 1000, + ) + _LOGGER.debug("Mail image generated.") + except (OSError, ValueError) as err: + _LOGGER.error("Error attempting to generate image: %s", err) + + for image in delete_list: + await self.hass.async_add_executor_job( + cleanup_images, + f"{Path(image).parent}/", + Path(image).name, + ) + + async def _copy_nomail_image(self, path: str, name: str, custom_img: str | None): + """Copy the 'no mail' placeholder image.""" + + def _prepare(): + if not Path(path).exists(): + Path(path).mkdir(parents=True, exist_ok=True) + target = Path(path) / name + if target.is_file(): + cleanup_images(path, name) + src = custom_img or str(Path(__file__).parent.parent / "mail_none.gif") + shutil.copyfile(src, str(target)) + + _LOGGER.debug("No mail found.") + try: + await self.hass.async_add_executor_job(_prepare) + except OSError as err: + _LOGGER.error("Error attempting to copy image: %s", err) + + def _get_usps_config(self) -> dict: + """Get USPS specific configuration.""" + return { + "image_output_path": self.config.get("image_path"), + "gif_duration": self.config.get(CONF_DURATION), + "image_name": self.config.get("usps_image"), + "gen_mp4": self.config.get(CONF_GENERATE_MP4), + "custom_img": self.config.get(CONF_CUSTOM_IMG_FILE) + or DEFAULT_CUSTOM_IMG_FILE, + "gen_grid": self.config.get(CONF_GENERATE_GRID), + } + + async def _search_informed_delivery(self, account: IMAP4_SSL) -> tuple: + """Search for USPS Informed Delivery emails.""" + _LOGGER.debug("Attempting to find Informed Delivery mail") + _LOGGER.debug("Informed delivery search date: %s", get_formatted_date()) + + forwarding_header = self.config.get(CONF_FORWARDING_HEADER, "") + if forwarding_header and forwarding_header != "(none)": + email_addresses = SENSOR_DATA[ATTR_USPS_MAIL][ATTR_EMAIL] + else: + forwarding_header = "" + forwarded_emails = self.config.get("forwarded_emails", []) + if isinstance(forwarded_emails, str): + forwarded_emails = [ + e.strip() for e in forwarded_emails.split(",") if e.strip() + ] + if forwarded_emails: + email_addresses = ( + forwarded_emails + SENSOR_DATA[ATTR_USPS_MAIL][ATTR_EMAIL] + ) + else: + email_addresses = SENSOR_DATA[ATTR_USPS_MAIL][ATTR_EMAIL] + + return await email_search( + account=account, + address=email_addresses, + date=get_formatted_date(), + subject=SENSOR_DATA[ATTR_USPS_MAIL][ATTR_SUBJECT][0], + header=forwarding_header, + ) + + async def _setup_image_directory(self, path: str) -> bool: + """Ensure image directory exists and is prepared.""" + if not await anyio.Path(path).is_dir(): + try: + await anyio.Path(path).mkdir(parents=True, exist_ok=True) + except OSError as err: + _LOGGER.error("Error creating directory: %s", err) + return False + + # Clean up and setup overlays + await self.hass.async_add_executor_job(cleanup_images, path) + await self.hass.async_add_executor_job(copy_overlays, path) + return True + + async def _process_usps_email( + self, + account: IMAP4_SSL, + num: str, + image_output_path: str, + image_count: int, + images: list, + cache: EmailCache | None = None, + ) -> tuple[int, list, str]: + """Process a single USPS Informed Delivery email.""" + if cache: + msg_parts = (await cache.fetch(num, "(RFC822)"))[1] + else: + msg_parts = (await email_fetch(account, num, "(RFC822)"))[1] + _LOGGER.debug("Processing email number: %s", num) + all_content = "" + for response_part in msg_parts: + if isinstance(response_part, (bytes, bytearray)): + all_content += str(response_part, "utf-8", errors="ignore") + msg = email.message_from_bytes(response_part) + for part in msg.walk(): + if part.get_content_type() == "text/html": + (image_count, images) = await self._extract_usps_images( + part, + image_output_path, + image_count, + images, + ) + elif part.get_content_type() == "image/jpeg": + (image_count, images) = await self._extract_jpeg_attachment( + part, + image_output_path, + image_count, + images, + ) + return image_count, images, all_content + + async def _extract_usps_images( + self, + part: email.message.Message, + image_output_path: str, + image_count: int, + images: list, + ) -> tuple[int, list]: + """Extract images from an email part (HTML/Base64).""" + payload = part.get_payload(decode=True) + content = ( + payload.decode("utf-8", "ignore") + if isinstance(payload, (bytes, bytearray)) + else str(payload) + ) + + # New USPS format: unscanned mailpieces use a div with a specific id. + # Check here on properly decoded HTML — raw RFC822 content is + # quoted-printable encoded and soft line breaks could split the string. + if "mailpiece-with-no-image-id" in content: + placeholder = Path(__file__).parent.parent / "image-no-mailpieces700.jpg" + placeholder_str = str(placeholder) + if placeholder.exists() and placeholder_str not in images: + images.append(placeholder_str) + image_count += 1 + _LOGGER.debug( + "Placeholder image found using: image-no-mailpieces700.jpg.", + ) + + if "data:image/jpeg;base64" not in content: + return image_count, images + + soup = BeautifulSoup(content, "html.parser") + found_images = soup.find_all(id="mailpiece-image-src-id") + + for image in found_images: + filename = random_filename() + img_data = str(image["src"]).split(",")[1] + try: + target_path = Path(image_output_path) / filename + await self.hass.async_add_executor_job( + io_save_file, + target_path, + base64.b64decode(img_data), + ) + images.append(str(target_path)) + image_count += 1 + except (OSError, ValueError, TypeError) as err: + _LOGGER.error("Error extracting image: %s", err) + + return image_count, images + + async def _extract_jpeg_attachment( + self, + part: email.message.Message, + image_output_path: str, + image_count: int, + images: list, + ) -> tuple[int, list]: + """Extract image from JPEG attachment.""" + _LOGGER.debug("Extracting image from email attachment") + filename = part.get_filename() + junkmail = ["mailer", "content", "package"] + if filename is None: + return image_count, images + if any(junk in filename for junk in junkmail): + return image_count, images + + try: + target_path = Path(image_output_path) / filename + await self.hass.async_add_executor_job( + io_save_file, + target_path, + part.get_payload(decode=True), + ) + images.append(str(target_path)) + image_count += 1 + except OSError as err: + _LOGGER.critical("Error opening filepath: %s", err) + + return image_count, images diff --git a/custom_components/mail_and_packages/strings.json b/custom_components/mail_and_packages/strings.json new file mode 100644 index 0000000..9928637 --- /dev/null +++ b/custom_components/mail_and_packages/strings.json @@ -0,0 +1,199 @@ +{ + "config": { + "abort": { + "single_instance_allowed": "Only a single configuration of Mail and Packages is allowed.", + "reconfigure_successful": "Reconfigure Successful" + }, + "error": { + "cannot_connect": "Unable to connect or login to the mail server. Please check the log for details.", + "invalid_path": "Please store the images in another directory.", + "ffmpeg_not_found": "Generate MP4 requires ffmpeg", + "amazon_domain": "Invalid forwarding email address.", + "file_not_found": "Image file not found", + "invalid_email_format": "Invalid email address format.", + "missing_forwarded_emails": "Missing forwarded email addresses. You may enter '(none)' to clear this setting.", + "path_not_found": "Directory not found", + "invalid_auth": "Invalid authentication details. Please check your username and password.", + "ssl_error": "An SSL error occurred. Change SSL cipher list and try again." + }, + "step": { + "user": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "imap_config": { + "description": "Please enter the connection information of your mail server.", + "data": { + "host": "Host", + "password": "Password", + "port": "Port", + "username": "Username", + "verify_ssl": "Verify SSL Cert", + "imap_security": "IMAP Security" + }, + "title": "Mail and Packages (Step 1 of 2)" + }, + "config_2": { + "data": { + "folder": "Mail Folder", + "resources": "Sensors List", + "scan_interval": "Scanning Interval (minutes, minimum 5)", + "image_path": "Image Path", + "gif_duration": "Image Duration (seconds)", + "image_security": "Random Image Filename", + "imap_timeout": "Mailbox scan time limit (seconds, minimum 10)", + "generate_grid": "Create image grid for LLM vision models", + "generate_mp4": "Create mp4 from images", + "allow_external": "Create image for notification apps", + "custom_img": "Use custom USPS 'no mail' image?", + "amazon_custom_img": "Use custom 'no Amazon delivery' image?", + "ups_custom_img": "Use custom 'no UPS delivery' image?", + "walmart_custom_img": "Use custom 'no Walmart delivery' image?", + "fedex_custom_img": "Use custom 'no FedEx delivery' image?", + "post_de_custom_img": "Use custom Post DE 'no mail' image?", + "allow_forwarded_emails": "Allow forwarded emails in addition to a service's default (e.g. no-reply@usps.com)" + }, + "data_description": { + "imap_timeout": "Covers the entire scan — login plus every per-carrier IMAP search — not just connecting. Raise this if large mailboxes time out; lower it to fail faster." + }, + "description": "Finish the configuration by customizing the following based on your email structure and Home Assistant installation.\n\nIf using Amazon forwarded emails please separate each address with a comma.", + "title": "Mail and Packages (Step 2 of 2)" + }, + "config_3": { + "data": { + "custom_img_file": "Path to custom USPS image: (ie: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (ie: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (ie: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (ie: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (ie: images/my_custom_no_fedex.jpg)", + "post_de_custom_img_file": "Path to custom Post DE image: (ie: images/my_custom_no_post_de.gif)" + }, + "description": "Enter the path and file name to your custom no delivery images below.\n\nExample: images/custom_nomail.gif", + "title": "Mail and Packages (Step 3 of 3)" + }, + "config_amazon": { + "data": { + "amazon_domain": "Amazon domain", + "amazon_fwds": "Amazon forwarded email addresses", + "amazon_days": "Days back to check for Amazon emails" + }, + "description": "Please enter the domain Amazon sends email's from (ie: amazon.com or amazon.de)\n\nIf using Amazon forwarded emails please separate each address with a comma or enter (none) to clear this setting.", + "title": "Amazon Settings" + }, + "config_forwarded_emails": { + "data": { + "forwarded_emails": "Forwarded Email Addresses" + }, + "description": "By default, the Mail and Packages integration only searches for messages matching a service's address.\n\nIf you want to use forwarded emails, please separate each address messages will be coming from with a comma or enter '(none)' to clear this setting.", + "title": "Forwarded Email Addresses" + }, + "reconfigure": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reconfig_imap": { + "data": { + "host": "Host", + "password": "Password", + "port": "Port", + "username": "Username", + "imap_security": "IMAP Security", + "verify_ssl": "Verify SSL Cert" + }, + "description": "Please enter the connection information of your mail server.", + "title": "Mail and Packages (Step 1 of 2)" + }, + "reconfig_2": { + "data": { + "folder": "Mail Folder", + "scan_interval": "Scanning Interval (minutes, minimum 5)", + "image_path": "Image Path", + "gif_duration": "Image Duration (seconds)", + "image_security": "Random Image Filename", + "generate_grid": "Create image grid for LLM vision models", + "generate_mp4": "Create mp4 from images", + "resources": "Sensors List", + "imap_timeout": "Mailbox scan time limit (seconds, minimum 10)", + "allow_external": "Create image for notification apps", + "custom_img": "Use custom USPS 'no mail' image?", + "amazon_custom_img": "Use custom 'no Amazon delivery' image?", + "ups_custom_img": "Use custom 'no UPS delivery' image?", + "walmart_custom_img": "Use custom 'no Walmart delivery' image?", + "fedex_custom_img": "Use custom 'no FedEx delivery' image?", + "post_de_custom_img": "Use custom Post DE 'no mail' image?", + "allow_forwarded_emails": "Allow forwarded emails in addition to a service's default (e.g. no-reply@usps.com)" + }, + "data_description": { + "imap_timeout": "Covers the entire scan — login plus every per-carrier IMAP search — not just connecting. Raise this if large mailboxes time out; lower it to fail faster." + }, + "description": "Finish the configuration by customizing the following based on your email structure and Home Assistant installation.\n\nIf using Amazon forwarded emails please separate each address with a comma or enter (none) to clear this setting.", + "title": "Mail and Packages (Step 2 of 2)" + }, + "reconfig_3": { + "data": { + "custom_img_file": "Path to custom USPS image: (i.e.: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (i.e.: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (i.e.: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (i.e.: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (i.e.: images/my_custom_no_fedex.jpg)", + "post_de_custom_img_file": "Path to custom Post DE image: (i.e.: images/my_custom_no_post_de.gif)" + }, + "description": "Enter the path and file name to your custom no delivery images below.\n\nExample: images/custom_nomail.gif", + "title": "Mail and Packages (Step 3 of 3)" + }, + "reconfig_amazon": { + "data": { + "amazon_domain": "Amazon domain", + "amazon_fwds": "Amazon forwarded email addresses", + "amazon_days": "Days back to check for Amazon emails" + }, + "description": "Please enter the domain Amazon sends email's from (ie: amazon.com or amazon.de)\n\nIf using Amazon forwarded emails please separate each address with a comma or enter (none) to clear this setting.", + "title": "Amazon Settings" + }, + "config_storage": { + "data": { + "storage": "Directory to store images" + }, + "description": "Please enter the directory you'd like your images to be stored in.\nThe default is auto populated.", + "title": "Image storage location" + }, + "reconfig_storage": { + "data": { + "storage": "Directory to store images" + }, + "description": "Please enter the directory you'd like your images to be stored in.\nThe default is auto populated.", + "title": "Image storage location" + }, + "reconfig_forwarded_emails": { + "data": { + "forwarded_emails": "Forwarded Email Addresses" + }, + "description": "By default, the Mail and Packages integration only searches for messages matching a service's address.\n\nIf you want to use forwarded emails, please separate each address messages will be coming from with a comma or enter '(none)' to clear this setting.", + "title": "Forwarded Email Addresses" + }, + "reauth_confirm": { + "description": "The authentication for your mail server has expired or is invalid. Please re-authenticate to continue.", + "data": { + "username": "Username", + "password": "Password" + }, + "title": "Re-authenticate Mail Server" + } + } + }, + "selector": { + "auth_type": { + "options": { + "password": "Password", + "oauth2_microsoft": "OAuth2 - Microsoft (Outlook/Exchange)", + "oauth2_google": "OAuth2 - Google (Gmail)" + } + } + } +} diff --git a/custom_components/mail_and_packages/translations/ca.json b/custom_components/mail_and_packages/translations/ca.json new file mode 100644 index 0000000..a22a5d8 --- /dev/null +++ b/custom_components/mail_and_packages/translations/ca.json @@ -0,0 +1,203 @@ +{ + "config": { + "abort": { + "single_instance_allowed": "Només es permet una única configuració de correu i paquets.", + "reconfigure_successful": "Reconfiguració exitosa" + }, + "error": { + "cannot_connect": "No es pot connectar o iniciar sessió al servidor de correu. Consulteu el registre per obtenir més detalls.", + "invalid_path": "Deseu les imatges en un altre directori.", + "ffmpeg_not_found": "Generar MP4 requereix ffmpeg", + "amazon_domain": "Adreça de correu electrònic de reenviament no vàlida.", + "file_not_found": "No s'ha trobat el fitxer d'imatge", + "invalid_email_format": "Format d'adreça de correu electrònic no vàlid.", + "path_not_found": "Directori no trobat", + "missing_forwarded_emails": "Falten les adreces de correu electrònic reenviades. Podeu introduir \"(none)\" per esborrar aquesta configuració.", + "invalid_auth": "Invalid authentication details. Please check your username and password.", + "ssl_error": "An SSL error occurred. Change SSL cipher list and try again." + }, + "step": { + "config_2": { + "data": { + "folder": "Carpeta de correu", + "resources": "Llista de sensors", + "scan_interval": "Interval d'exploració (minuts)", + "image_path": "Camí de la imatge", + "gif_duration": "Durada de la imatge (segons)", + "image_security": "Nom del fitxer d'imatge aleatòria", + "imap_timeout": "Temps en segons abans de l'expiració de la connexió (segons, mínim 10)", + "generate_mp4": "Crea mp4 a partir d'imatges", + "allow_external": "Crea una imatge per a aplicacions de notificacions", + "custom_img": "Utilitza la imatge personalitzada USPS 'no hi ha correu'?", + "amazon_custom_img": "Utilitza la imatge personalitzada Amazon 'no hi ha lliurament'?", + "ups_custom_img": "Utilitza la imatge personalitzada UPS 'no hi ha lliurament'?", + "walmart_custom_img": "Utilitza la imatge personalitzada Walmart 'no hi ha lliurament'?", + "fedex_custom_img": "Utilitza la imatge personalitzada FedEx 'no hi ha lliurament'?", + "generic_custom_img": "Utilitza la imatge personalitzada genèrica 'no hi ha lliurament'?", + "generate_grid": "Crea una quadrícula d'imatges per a models de visió LLM", + "allow_forwarded_emails": "Permet els correus electrònics reenviats a més del valor predeterminat d'un servei (p. ex., no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Finalitzeu la configuració personalitzant la següent en funció de la vostra instal·lació de correu electrònic i la instal·lació d'assistència a casa. \n\n Per obtenir més informació sobre les opcions [Integració de paquets i correus] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration), reviseu les opcions [configuració, plantilles , secció i automatitzacions] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) a GitHub.", + "title": "Correu i paquets (pas 2 de 2)" + }, + "config_3": { + "data": { + "custom_img_file": "Camí a la imatge personalitzada: (és a dir: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (ie: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (ie: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (ie: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (ie: images/my_custom_no_fedex.jpg)" + }, + "description": "Introduïu el camí i el nom del fitxer de la vostra imatge personalitzada de no correu a continuació.\n\nExemple: imatges/custom_nomail.gif", + "title": "Correu i paquets (Pas 3 de 3)" + }, + "config_amazon": { + "data": { + "amazon_domain": "Domini d'Amazon", + "amazon_fwds": "Amazon ha reenviat les adreces de correu electrònic", + "amazon_days": "Dies per comprovar els correus electrònics d'Amazon" + }, + "description": "Introduïu el domini des d'on Amazon envia correus electrònics (és a dir: amazon.com o amazon.de)\n\nSi utilitzeu correus electrònics reenviats d'Amazon, separeu cada adreça amb una coma o introduïu (none) per esborrar aquesta configuració.\n\nNota: si heu configurat una capçalera de reenviament en el pas anterior, el camp d'adreça de reenviament no apareixerà — la capçalera gestiona la correspondència de correus electrònics d'Amazon automàticament.", + "title": "Configuració d'Amazon" + }, + "reconfig_2": { + "data": { + "folder": "Carpeta de correu", + "scan_interval": "Interval d'exploració (minuts)", + "image_path": "Camí de la imatge", + "gif_duration": "Durada de la imatge (segons)", + "image_security": "Nom del fitxer d'imatge aleatòria", + "generate_mp4": "Crea mp4 a partir d'imatges", + "resources": "Llista de sensors", + "imap_timeout": "Temps en segons abans de l'expiració de la connexió (segons, mínim 10)", + "allow_external": "Crea una imatge per a aplicacions de notificacions", + "custom_img": "Utilitza la imatge personalitzada USPS 'no hi ha correu'?", + "amazon_custom_img": "Utilitza la imatge personalitzada Amazon 'no hi ha lliurament'?", + "ups_custom_img": "Utilitza la imatge personalitzada UPS 'no hi ha lliurament'?", + "walmart_custom_img": "Utilitza la imatge personalitzada Walmart 'no hi ha lliurament'?", + "fedex_custom_img": "Utilitza la imatge personalitzada FedEx 'no hi ha lliurament'?", + "generic_custom_img": "Utilitza la imatge personalitzada genèrica 'no hi ha lliurament'?", + "generate_grid": "Crea una quadrícula d'imatges per a models de visió LLM", + "allow_forwarded_emails": "Permet els correus electrònics reenviats a més del valor predeterminat d'un servei (p. ex., no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Acabeu la configuració personalitzant el següent en funció de l'estructura del vostre correu electrònic i de la instal·lació de Home Assistant.\n\nPer obtenir més detalls sobre les opcions d'[integració de correu i paquets](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration), consulteu la [secció de configuració, plantilles i automatitzacions](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) a GitHub.\n\nSi utilitzeu correus electrònics reenviats d'Amazon, separeu cada adreça amb una coma o introduïu (none) per esborrar aquesta configuració.", + "title": "Correu i paquets (pas 2 de 2)" + }, + "reconfig_3": { + "data": { + "custom_img_file": "Camí a la imatge personalitzada: (p. ex.: imatges/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (i.e.: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (i.e.: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (i.e.: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (i.e.: images/my_custom_no_fedex.jpg)" + }, + "description": "Introduïu el camí i el nom del fitxer de la vostra imatge personalitzada de no correu a continuació.\n\nExemple: imatges/custom_nomail.gif", + "title": "Correu i paquets (Pas 3 de 3)" + }, + "reconfig_amazon": { + "data": { + "amazon_domain": "Domini d'Amazon", + "amazon_fwds": "Amazon ha reenviat les adreces de correu electrònic", + "amazon_days": "Dies per comprovar els correus electrònics d'Amazon" + }, + "description": "Introduïu el domini des d'on Amazon envia correus electrònics (és a dir: amazon.com o amazon.de)\n\nSi utilitzeu correus electrònics reenviats d'Amazon, separeu cada adreça amb una coma o introduïu (none) per esborrar aquesta configuració.\n\nNota: si heu configurat una capçalera de reenviament en el pas anterior, el camp d'adreça de reenviament no apareixerà — la capçalera gestiona la correspondència de correus electrònics d'Amazon automàticament.", + "title": "Configuració d'Amazon" + }, + "config_storage": { + "data": { + "storage": "Directori per emmagatzemar imatges" + }, + "description": "Introduïu el directori on voleu que es desin les vostres imatges.\nPer defecte, es completa automàticament.", + "title": "Ubicació de l'emmagatzematge d'imatges" + }, + "reconfig_storage": { + "data": { + "storage": "Directori per emmagatzemar imatges" + }, + "description": "Introduïu el directori on voleu que es desin les vostres imatges.\nPer defecte, es completa automàticament.", + "title": "Ubicació de l'emmagatzematge d'imatges" + }, + "config_forwarded_emails": { + "data": { + "forwarding_header": "Capçalera de reenviament (p. ex. X-SimpleLogin-Original-From)", + "forwarded_emails": "Adreces de correu electrònic reenviades" + }, + "data_description": { + "forwarding_header": "Si el vostre servei de reenviament inclou el remitent original en una capçalera, introduïu aquí el nom de la capçalera. Això té prioritat sobre la llista d'adreces a continuació. Introduïu '(none)' o deixeu-ho en blanc per utilitzar la llista d'adreces.", + "forwarded_emails": "Llista d'adreces de reenviament separades per comes des de les quals arribaran els missatges. Deixeu '(none)' si feu servir la capçalera de reenviament de dalt." + }, + "description": "Trieu com fer coincidir els correus electrònics reenviats.\n\n**Opció 1 — Capçalera de reenviament**: Si el vostre servei (p. ex. SimpleLogin) inclou el remitent original en una capçalera personalitzada, introduïu el nom d'aquesta capçalera. Mail and Packages l'utilitzarà per fer coincidir automàticament les adreces dels transportistes.\n\n**Opció 2 — Llista d'adreces**: Introduïu les adreces de reenviament que el vostre servei ha assignat a cada transportista, separades per comes.", + "title": "Configuració dels correus electrònics reenviats" + }, + "reconfig_forwarded_emails": { + "data": { + "forwarding_header": "Capçalera de reenviament (p. ex. X-SimpleLogin-Original-From)", + "forwarded_emails": "Adreces de correu electrònic reenviades" + }, + "data_description": { + "forwarding_header": "Si el vostre servei de reenviament inclou el remitent original en una capçalera, introduïu aquí el nom de la capçalera. Això té prioritat sobre la llista d'adreces a continuació. Introduïu '(none)' o deixeu-ho en blanc per utilitzar la llista d'adreces.", + "forwarded_emails": "Llista d'adreces de reenviament separades per comes des de les quals arribaran els missatges. Deixeu '(none)' si feu servir la capçalera de reenviament de dalt." + }, + "description": "Trieu com fer coincidir els correus electrònics reenviats.\n\n**Opció 1 — Capçalera de reenviament**: Si el vostre servei (p. ex. SimpleLogin) inclou el remitent original en una capçalera personalitzada, introduïu el nom d'aquesta capçalera. Mail and Packages l'utilitzarà per fer coincidir automàticament les adreces dels transportistes.\n\n**Opció 2 — Llista d'adreces**: Introduïu les adreces de reenviament que el vostre servei ha assignat a cada transportista, separades per comes.", + "title": "Configuració dels correus electrònics reenviats" + }, + "imap_config": { + "description": "Introduïu la informació de connexió del vostre servidor de correu.", + "data": { + "host": "Amfitrió", + "password": "Contrasenya", + "port": "Port", + "username": "Nom d'usuari", + "verify_ssl": "Verifica el certificat SSL", + "imap_security": "Seguretat IMAP" + }, + "title": "Correu i paquets (pas 1 de 2)" + }, + "user": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reconfig_imap": { + "data": { + "host": "Amfitrió", + "password": "Contrasenya", + "port": "Port", + "username": "Nom d'usuari", + "imap_security": "Seguretat IMAP", + "verify_ssl": "Verifica el certificat SSL" + }, + "description": "Introduïu la informació de connexió del vostre servidor de correu.", + "title": "Correu i paquets (pas 1 de 2)" + }, + "reconfigure": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reauth_confirm": { + "description": "The authentication for your mail server has expired or is invalid. Please re-authenticate to continue.", + "data": { + "username": "Username", + "password": "Password" + }, + "title": "Re-authenticate Mail Server" + } + } + }, + "selector": { + "auth_type": { + "options": { + "password": "Password", + "oauth2_microsoft": "OAuth2 - Microsoft (Outlook/Exchange)", + "oauth2_google": "OAuth2 - Google (Gmail)" + } + } + } +} diff --git a/custom_components/mail_and_packages/translations/cs.json b/custom_components/mail_and_packages/translations/cs.json new file mode 100644 index 0000000..383d4cd --- /dev/null +++ b/custom_components/mail_and_packages/translations/cs.json @@ -0,0 +1,269 @@ +{ + "config": { + "abort": { + "single_instance_allowed": "Je povolena pouze jedna konfigurace Mail and Packages.", + "reconfigure_successful": "Rekonfigurace úspěšná" + }, + "error": { + "cannot_connect": "Nelze se připojit nebo přihlásit k poštovnímu serveru. Podrobnosti naleznete v logu.", + "invalid_path": "Prosím uložte obrázky do jiného adresáře.", + "ffmpeg_not_found": "Generování MP4 vyžaduje ffmpeg", + "amazon_domain": "Neplatná e-mailová adresa pro přeposílání.", + "file_not_found": "Soubor obrázku nebyl nalezen", + "missing_forwarded_emails": "Chybí přeposílané e-mailové adresy. Můžete zadat '(none)' pro vymazání tohoto nastavení.", + "scan_too_low": "Interval skenování je příliš nízký (minimum 5)", + "timeout_too_low": "IMAP timeout je příliš nízký (minimum 10)", + "invalid_email_format": "Invalid email address format.", + "path_not_found": "Directory not found", + "invalid_auth": "Invalid authentication details. Please check your username and password.", + "ssl_error": "An SSL error occurred. Change SSL cipher list and try again." + }, + "step": { + "config_2": { + "data": { + "folder": "Poštovní složka", + "scan_interval": "Interval skenování (minuty)", + "image_path": "Cesta obrázku", + "gif_duration": "Trvání obrázku (sekund)", + "image_security": "Jméno náhodného obrázku", + "generate_mp4": "Vytvořit mp4 z obrázku", + "resources": "Seznam senzorů", + "imap_timeout": "Čas v sekundách před vypršením časového limitu připojení (sekund, minimum 10)", + "amazon_fwds": "Amazon předal e-mailové adresy", + "allow_external": "Vytvořte obrázek pro oznamovací aplikaci", + "amazon_days": "Dny zpět ke kontrole e-mailů Amazon", + "custom_img": "Použít vlastní obrázek USPS 'bez pošty'?", + "amazon_custom_img": "Použít vlastní obrázek Amazon 'bez dodání'?", + "ups_custom_img": "Použít vlastní obrázek UPS 'bez dodání'?", + "walmart_custom_img": "Použít vlastní obrázek Walmart 'bez dodání'?", + "fedex_custom_img": "Použít vlastní obrázek FedEx 'bez dodání'?", + "generic_custom_img": "Použít vlastní obrázek obecný 'bez dodání'?", + "allow_forwarded_emails": "Povolit přeposílané e-maily kromě výchozí hodnoty služby (např. no-reply@usps.com)", + "generate_grid": "Create image grid for LLM vision models", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Dokončete konfiguraci přizpůsobením následujících položek na základě struktury e-mailu a instalace Home Assistant.\n\nPodrobnosti o [Mail and Packages integration](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) můžete zkontrolovat na [configurace, styly a automatizace](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) na GitHubu.", + "title": "Mail and Packages (Krok 2 ze 3)" + }, + "options_3": { + "data": { + "custom_img_file": "Cesta k vlastnímu obrázku: (např.: images/my_custom_no_mail.jpg)" + }, + "description": "Níže zadejte cestu a název souboru k vlastnímu obrázku bez pošty.\n\nPříklad: images/custom_nomail.gif", + "title": "Mail and Packages (Krok 3 ze 3)" + }, + "config_forwarded_emails": { + "data": { + "forwarding_header": "Hlavička přesměrování (např. X-SimpleLogin-Original-From)", + "forwarded_emails": "Přeposílané e-mailové adresy" + }, + "data_description": { + "forwarding_header": "Pokud vaše přeposílací služba zahrnuje původního odesílatele do záhlaví, zadejte zde název záhlaví. To má přednost před níže uvedeným seznamem adres. Zadejte '(none)' nebo nechte prázdné, chcete-li místo toho použít seznam adres.", + "forwarded_emails": "Seznam přeposílacích adres oddělených čárkami, ze kterých budou přicházet zprávy. Ponechejte '(none)', pokud používáte výše uvedenou hlavičku přesměrování." + }, + "description": "Vyberte způsob porovnávání přeposlaných e-mailů.\n\n**Možnost 1 — Hlavička přesměrování**: Pokud vaše služba (např. SimpleLogin) zahrnuje původního odesílatele do vlastního záhlaví, zadejte název tohoto záhlaví. Mail and Packages ho použije k automatickému přiřazení adres dopravců.\n\n**Možnost 2 — Seznam adres**: Zadejte přeposílací adresy, které vaše služba přidělila každému dopravci, oddělené čárkami.", + "title": "Nastavení přeposlaných e-mailů" + }, + "reconfig_forwarded_emails": { + "data": { + "forwarding_header": "Hlavička přesměrování (např. X-SimpleLogin-Original-From)", + "forwarded_emails": "Přeposílané e-mailové adresy" + }, + "data_description": { + "forwarding_header": "Pokud vaše přeposílací služba zahrnuje původního odesílatele do záhlaví, zadejte zde název záhlaví. To má přednost před níže uvedeným seznamem adres. Zadejte '(none)' nebo nechte prázdné, chcete-li místo toho použít seznam adres.", + "forwarded_emails": "Seznam přeposílacích adres oddělených čárkami, ze kterých budou přicházet zprávy. Ponechejte '(none)', pokud používáte výše uvedenou hlavičku přesměrování." + }, + "description": "Vyberte způsob porovnávání přeposlaných e-mailů.\n\n**Možnost 1 — Hlavička přesměrování**: Pokud vaše služba (např. SimpleLogin) zahrnuje původního odesílatele do vlastního záhlaví, zadejte název tohoto záhlaví. Mail and Packages ho použije k automatickému přiřazení adres dopravců.\n\n**Možnost 2 — Seznam adres**: Zadejte přeposílací adresy, které vaše služba přidělila každému dopravci, oddělené čárkami.", + "title": "Nastavení přeposlaných e-mailů" + }, + "imap_config": { + "data": { + "host": "Host", + "password": "Heslo", + "port": "Port", + "username": "Uživatelské jméno", + "verify_ssl": "Verify SSL Cert", + "imap_security": "IMAP Security" + }, + "description": "Zadejte prosím informace o připojení vašeho poštovního serveru.", + "title": "Mail and Packages (Krok 1 ze 3)" + }, + "user": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reconfigure": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "config_3": { + "data": { + "custom_img_file": "Path to custom USPS image: (ie: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (ie: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (ie: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (ie: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (ie: images/my_custom_no_fedex.jpg)" + }, + "description": "Enter the path and file name to your custom no delivery images below.\n\nExample: images/custom_nomail.gif", + "title": "Mail and Packages (Step 3 of 3)" + }, + "config_amazon": { + "data": { + "amazon_domain": "Amazon domain", + "amazon_fwds": "Amazon forwarded email addresses", + "amazon_days": "Days back to check for Amazon emails" + }, + "description": "Please enter the domain Amazon sends email's from (ie: amazon.com or amazon.de)\n\nIf using Amazon forwarded emails please separate each address with a comma or enter (none) to clear this setting.\n\nNote: if you configured a forwarding header in the previous step, the forwarding address field will not appear — the header handles Amazon email matching automatically.", + "title": "Amazon Settings" + }, + "reconfig_imap": { + "data": { + "host": "Host", + "password": "Password", + "port": "Port", + "username": "Username", + "imap_security": "IMAP Security", + "verify_ssl": "Verify SSL Cert" + }, + "description": "Please enter the connection information of your mail server.", + "title": "Mail and Packages (Step 1 of 2)" + }, + "reconfig_2": { + "data": { + "folder": "Mail Folder", + "scan_interval": "Scanning Interval (minutes, minimum 5)", + "image_path": "Image Path", + "gif_duration": "Image Duration (seconds)", + "image_security": "Random Image Filename", + "generate_grid": "Create image grid for LLM vision models", + "generate_mp4": "Create mp4 from images", + "resources": "Sensors List", + "imap_timeout": "Time in seconds before connection timeout (seconds, minimum 10)", + "allow_external": "Create image for notification apps", + "custom_img": "Use custom USPS 'no mail' image?", + "amazon_custom_img": "Use custom 'no Amazon delivery' image?", + "ups_custom_img": "Use custom 'no UPS delivery' image?", + "walmart_custom_img": "Use custom 'no Walmart delivery' image?", + "fedex_custom_img": "Use custom 'no FedEx delivery' image?", + "allow_forwarded_emails": "Allow forwarded emails in addition to a service's default (e.g. no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Finish the configuration by customizing the following based on your email structure and Home Assistant installation.\n\nIf using Amazon forwarded emails please separate each address with a comma or enter (none) to clear this setting.", + "title": "Mail and Packages (Step 2 of 2)" + }, + "reconfig_3": { + "data": { + "custom_img_file": "Path to custom USPS image: (i.e.: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (i.e.: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (i.e.: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (i.e.: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (i.e.: images/my_custom_no_fedex.jpg)" + }, + "description": "Enter the path and file name to your custom no delivery images below.\n\nExample: images/custom_nomail.gif", + "title": "Mail and Packages (Step 3 of 3)" + }, + "reconfig_amazon": { + "data": { + "amazon_domain": "Amazon domain", + "amazon_fwds": "Amazon forwarded email addresses", + "amazon_days": "Days back to check for Amazon emails" + }, + "description": "Please enter the domain Amazon sends email's from (ie: amazon.com or amazon.de)\n\nIf using Amazon forwarded emails please separate each address with a comma or enter (none) to clear this setting.\n\nNote: if you configured a forwarding header in the previous step, the forwarding address field will not appear — the header handles Amazon email matching automatically.", + "title": "Amazon Settings" + }, + "config_storage": { + "data": { + "storage": "Directory to store images" + }, + "description": "Please enter the directory you'd like your images to be stored in.\nThe default is auto populated.", + "title": "Image storage location" + }, + "reconfig_storage": { + "data": { + "storage": "Directory to store images" + }, + "description": "Please enter the directory you'd like your images to be stored in.\nThe default is auto populated.", + "title": "Image storage location" + }, + "reauth_confirm": { + "description": "The authentication for your mail server has expired or is invalid. Please re-authenticate to continue.", + "data": { + "username": "Username", + "password": "Password" + }, + "title": "Re-authenticate Mail Server" + } + }, + "title": "Mail and Packages" + }, + "options": { + "error": { + "cannot_connect": "Nelze se připojit nebo přihlásit k poštovnímu serveru. Podrobnosti naleznete v logu.", + "invalid_path": "Prosím uložte obrázky do jiného adresáře.", + "ffmpeg_not_found": "Generování MP4 vyžaduje ffmpeg", + "amazon_domain": "Neplatná e-mailová adresa pro přeposílání.", + "file_not_found": "Soubor obrázku nebyl nalezen", + "missing_forwarded_emails": "Chybí přeposílané e-mailové adresy. Můžete zadat '(none)' pro vymazání tohoto nastavení.", + "scan_too_low": "Interval skenování je příliš nízký (minimum 5)", + "timeout_too_low": "IMAP timeout je příliš nízký (minimum 10)" + }, + "step": { + "init": { + "data": { + "host": "Host", + "password": "Heslo", + "port": "Port", + "username": "Uživatelské jméno" + }, + "description": "Zadejte prosím informace o připojení vašeho poštovního serveru.", + "title": "Mail and Packages (Krok 1 ze 3)" + }, + "options_2": { + "data": { + "folder": "Poštovní složka", + "scan_interval": "Interval skenování (minuty)", + "image_path": "Cesta obrázku", + "gif_duration": "Trvání obrázku (sekund)", + "image_security": "Jméno náhodného obrázku", + "generate_mp4": "Vytvořit mp4 z obrázku", + "resources": "Seznam senzorů", + "imap_timeout": "Čas v sekundách před vypršením časového limitu připojení (sekund, minimum 10)", + "amazon_fwds": "Amazon předal e-mailové adresy", + "allow_external": "Vytvořte obrázek pro oznamovací aplikaci", + "amazon_days": "Dny zpět ke kontrole e-mailů Amazon", + "custom_img": "Použít vlastní obrázek USPS 'bez pošty'?", + "amazon_custom_img": "Použít vlastní obrázek Amazon 'bez dodání'?", + "ups_custom_img": "Použít vlastní obrázek UPS 'bez dodání'?", + "walmart_custom_img": "Použít vlastní obrázek Walmart 'bez dodání'?", + "generic_custom_img": "Použít vlastní obrázek obecný 'bez dodání'?", + "allow_forwarded_emails": "Povolit přeposílané e-maily kromě výchozí hodnoty služby (např. no-reply@usps.com)" + }, + "description": "Dokončete konfiguraci přizpůsobením následujících položek na základě struktury e-mailu a instalace Home Assistant.\n\nPodrobnosti o [Mail and Packages integration](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) můžete zkontrolovat na [configurace, styly a automatizace](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) na GitHubu.", + "title": "Mail and Packages (Krok 2 ze 3)" + }, + "options_3": { + "data": { + "custom_img_file": "Cesta k vlastnímu obrázku: (např.: images/my_custom_no_mail.jpg)" + }, + "description": "Níže zadejte cestu a název souboru k vlastnímu obrázku bez pošty.\n\nPříklad: images/custom_nomail.gif", + "title": "Mail and Packages (Krok 3 ze 3)" + } + } + }, + "title": "Mail and Packages", + "selector": { + "auth_type": { + "options": { + "password": "Password", + "oauth2_microsoft": "OAuth2 - Microsoft (Outlook/Exchange)", + "oauth2_google": "OAuth2 - Google (Gmail)" + } + } + } +} diff --git a/custom_components/mail_and_packages/translations/de.json b/custom_components/mail_and_packages/translations/de.json new file mode 100644 index 0000000..697a1e9 --- /dev/null +++ b/custom_components/mail_and_packages/translations/de.json @@ -0,0 +1,207 @@ +{ + "config": { + "abort": { + "single_instance_allowed": "Es ist nur eine einzige Konfiguration von Mail und Paketen zulässig.", + "reconfigure_successful": "Neukonfiguration erfolgreich" + }, + "error": { + "cannot_connect": "Es kann keine Verbindung zum Mailserver hergestellt oder angemeldet werden. Bitte überprüfen Sie das Protokoll für Details.", + "invalid_path": "Bitte speichern Sie die Bilder in einem anderen Verzeichnis.", + "ffmpeg_not_found": "MP4 erstellen erfordert ffmpeg", + "amazon_domain": "Ungültige Weiterleitungs-E-Mail-Adresse.", + "file_not_found": "Bilddatei nicht gefunden", + "invalid_email_format": "Ungültiges E-Mail-Adressformat.", + "missing_forwarded_emails": "Fehlende weitergeleitete E-Mail-Adressen. Sie können '(none)' eingeben, um diese Einstellung zu löschen.", + "path_not_found": "Verzeichnis nicht gefunden", + "invalid_auth": "Invalid authentication details. Please check your username and password.", + "ssl_error": "An SSL error occurred. Change SSL cipher list and try again." + }, + "step": { + "config_2": { + "data": { + "folder": "E-Mail-Ordner", + "resources": "Sensoren Liste", + "scan_interval": "Scanintervall (Minuten)", + "image_path": "Bildpfad", + "gif_duration": "Bilddauer (Sekunden)", + "image_security": "Zufälliger Bilddateiname", + "imap_timeout": "Zeit in Sekunden bis zum Timeout der Verbindung (Sekunden, mindestens 10)", + "generate_mp4": "Erstellen Sie mp4 aus Bildern", + "allow_external": "Bild für Benachrichtigungs-Apps erstellen", + "custom_img": "Benutzerdefiniertes USPS 'keine Post' Bild verwenden?", + "amazon_custom_img": "Benutzerdefiniertes Amazon 'keine Lieferung' Bild verwenden?", + "ups_custom_img": "Benutzerdefiniertes UPS 'keine Lieferung' Bild verwenden?", + "walmart_custom_img": "Benutzerdefiniertes Walmart 'keine Lieferung' Bild verwenden?", + "fedex_custom_img": "Benutzerdefiniertes FedEx 'keine Lieferung' Bild verwenden?", + "generic_custom_img": "Benutzerdefiniertes generisches 'keine Lieferung' Bild verwenden?", + "post_de_custom_img": "Benutzerdefiniertes Post DE 'keine Post' Bild verwenden?", + "generate_grid": "Erstellen Sie ein Bildraster für LLM-Vision-Modelle", + "allow_forwarded_emails": "Weitergeleitete E-Mails zusätzlich zu den Standardwerten eines Dienstes zulassen (z. B. no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Beenden Sie die Konfiguration, indem Sie Folgendes basierend auf Ihrer E-Mail-Struktur und der Installation von Home Assistant anpassen. \n\n Weitere Informationen zu den Optionen [Mail- und Paketintegration] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) finden Sie in den [Konfiguration, Vorlagen und Abschnitt Automatisierungen] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) auf GitHub.", + "title": "Briefe und Pakete (Schritt 2 von 2)" + }, + "config_3": { + "data": { + "custom_img_file": "Pfad zum benutzerdefinierten Bild: (z. B.: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (ie: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (ie: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (ie: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (ie: images/my_custom_no_fedex.jpg)", + "post_de_custom_img_file": "Pfad zum benutzerdefinierten Post DE-Bild: (z. B.: images/my_custom_no_post_de.gif)" + }, + "description": "Geben Sie unten den Pfad und den Dateinamen zu Ihrem benutzerdefinierten Keine-Mail-Bild ein.\n\nBeispiel: images/custom_nomail.gif", + "title": "Post und Pakete (Schritt 3 von 3)" + }, + "config_amazon": { + "data": { + "amazon_domain": "Amazon-Domain", + "amazon_fwds": "Amazon hat E-Mail-Adressen weitergeleitet", + "amazon_days": "Tage zurück, um nach Amazon-E-Mails zu suchen" + }, + "description": "Bitte geben Sie die Domain ein, von der Amazon E-Mails sendet (z.B.: amazon.com oder amazon.de)\n\nWenn Sie weitergeleitete E-Mails von Amazon verwenden, trennen Sie bitte jede Adresse mit einem Komma oder geben Sie (keine) ein, um diese Einstellung zu löschen.\n\nHinweis: Wenn Sie im vorherigen Schritt einen Weiterleitungs-Header konfiguriert haben, wird das Feld für die Weiterleitungsadresse nicht angezeigt — der Header übernimmt die Zuordnung von Amazon-E-Mails automatisch.", + "title": "Amazon Einstellungen" + }, + "reconfig_2": { + "data": { + "folder": "E-Mail-Ordner", + "scan_interval": "Scanintervall (Minuten)", + "image_path": "Bildpfad", + "gif_duration": "Bilddauer (Sekunden)", + "image_security": "Zufälliger Bilddateiname", + "generate_mp4": "Erstellen Sie mp4 aus Bildern", + "resources": "Sensoren Liste", + "imap_timeout": "Zeit in Sekunden bis zum Timeout der Verbindung (Sekunden, mindestens 10)", + "allow_external": "Bild für Benachrichtigungs-Apps erstellen", + "custom_img": "Benutzerdefiniertes USPS 'keine Post' Bild verwenden?", + "amazon_custom_img": "Benutzerdefiniertes Amazon 'keine Lieferung' Bild verwenden?", + "ups_custom_img": "Benutzerdefiniertes UPS 'keine Lieferung' Bild verwenden?", + "walmart_custom_img": "Benutzerdefiniertes Walmart 'keine Lieferung' Bild verwenden?", + "fedex_custom_img": "Benutzerdefiniertes FedEx 'keine Lieferung' Bild verwenden?", + "generic_custom_img": "Benutzerdefiniertes generisches 'keine Lieferung' Bild verwenden?", + "post_de_custom_img": "Benutzerdefiniertes Post DE 'keine Post' Bild verwenden?", + "generate_grid": "Erstellen Sie ein Bildraster für LLM-Vision-Modelle", + "allow_forwarded_emails": "Weitergeleitete E-Mails zusätzlich zu den Standardwerten eines Dienstes zulassen (z. B. no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Schließen Sie die Konfiguration ab, indem Sie das Folgende an Ihre E-Mail-Struktur und Home Assistant-Installation anpassen.\n\nWeitere Informationen zu den [Mail und Packages Integration](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) Optionen finden Sie im [Konfigurations-, Vorlagen- und Automatisierungsabschnitt](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) auf GitHub.\n\nWenn Sie weitergeleitete E-Mails von Amazon verwenden, trennen Sie bitte jede Adresse durch ein Komma oder geben Sie (keine) ein, um diese Einstellung zu löschen.", + "title": "Briefe und Pakete (Schritt 2 von 2)" + }, + "reconfig_3": { + "data": { + "custom_img_file": "Pfad zum benutzerdefinierten Bild: (z.B.: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (i.e.: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (i.e.: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (i.e.: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (i.e.: images/my_custom_no_fedex.jpg)", + "post_de_custom_img_file": "Pfad zum benutzerdefinierten Post DE-Bild: (z. B.: images/my_custom_no_post_de.gif)" + }, + "description": "Geben Sie unten den Pfad und den Dateinamen zu Ihrem benutzerdefinierten Keine-Mail-Bild ein.\n\nBeispiel: images/custom_nomail.gif", + "title": "Post und Pakete (Schritt 3 von 3)" + }, + "reconfig_amazon": { + "data": { + "amazon_domain": "Amazon-Domain", + "amazon_fwds": "Amazon hat E-Mail-Adressen weitergeleitet", + "amazon_days": "Tage zurück, um nach Amazon-E-Mails zu suchen" + }, + "description": "Bitte geben Sie die Domain ein, von der Amazon E-Mails sendet (z.B.: amazon.com oder amazon.de)\n\nWenn Sie weitergeleitete E-Mails von Amazon verwenden, trennen Sie bitte jede Adresse mit einem Komma oder geben Sie (keine) ein, um diese Einstellung zu löschen.\n\nHinweis: Wenn Sie im vorherigen Schritt einen Weiterleitungs-Header konfiguriert haben, wird das Feld für die Weiterleitungsadresse nicht angezeigt — der Header übernimmt die Zuordnung von Amazon-E-Mails automatisch.", + "title": "Amazon Einstellungen" + }, + "config_storage": { + "data": { + "storage": "Verzeichnis zum Speichern von Bildern" + }, + "description": "Bitte geben Sie das Verzeichnis ein, in dem Ihre Bilder gespeichert werden sollen.\nStandardmäßig ist es automatisch ausgefüllt.", + "title": "Speicherort für Bilder" + }, + "reconfig_storage": { + "data": { + "storage": "Verzeichnis zum Speichern von Bildern" + }, + "description": "Bitte geben Sie das Verzeichnis ein, in dem Ihre Bilder gespeichert werden sollen.\nStandardmäßig ist es automatisch ausgefüllt.", + "title": "Speicherort für Bilder" + }, + "config_forwarded_emails": { + "data": { + "forwarding_header": "Weiterleitungs-Header (z.B. X-SimpleLogin-Original-From)", + "forwarded_emails": "Weitergeleitete E-Mail-Adressen" + }, + "data_description": { + "forwarding_header": "Wenn Ihr Weiterleitungsdienst den ursprünglichen Absender in einem Header enthält, geben Sie hier den Header-Namen ein. Dies hat Vorrang vor der Adressliste unten. Geben Sie '(none)' ein oder lassen Sie das Feld leer, um stattdessen die Adressliste zu verwenden.", + "forwarded_emails": "Kommagetrennte Liste der Weiterleitungsadressen, von denen Nachrichten eingehen. Lassen Sie '(none)' stehen, wenn Sie den Weiterleitungs-Header oben verwenden." + }, + "description": "Wählen Sie, wie weitergeleitete E-Mails abgeglichen werden sollen.\n\n**Option 1 — Weiterleitungs-Header**: Wenn Ihr Dienst (z.B. SimpleLogin) den ursprünglichen Absender in einem benutzerdefinierten Header enthält, geben Sie diesen Header-Namen ein. Mail and Packages verwendet ihn, um Zustell-Adressen automatisch abzugleichen.\n\n**Option 2 — Adressliste**: Geben Sie die Weiterleitungsadressen ein, die Ihr Dienst jedem Zusteller zugewiesen hat, getrennt durch Kommas.", + "title": "Einstellungen für weitergeleitete E-Mails" + }, + "reconfig_forwarded_emails": { + "data": { + "forwarding_header": "Weiterleitungs-Header (z.B. X-SimpleLogin-Original-From)", + "forwarded_emails": "Weitergeleitete E-Mail-Adressen" + }, + "data_description": { + "forwarding_header": "Wenn Ihr Weiterleitungsdienst den ursprünglichen Absender in einem Header enthält, geben Sie hier den Header-Namen ein. Dies hat Vorrang vor der Adressliste unten. Geben Sie '(none)' ein oder lassen Sie das Feld leer, um stattdessen die Adressliste zu verwenden.", + "forwarded_emails": "Kommagetrennte Liste der Weiterleitungsadressen, von denen Nachrichten eingehen. Lassen Sie '(none)' stehen, wenn Sie den Weiterleitungs-Header oben verwenden." + }, + "description": "Wählen Sie, wie weitergeleitete E-Mails abgeglichen werden sollen.\n\n**Option 1 — Weiterleitungs-Header**: Wenn Ihr Dienst (z.B. SimpleLogin) den ursprünglichen Absender in einem benutzerdefinierten Header enthält, geben Sie diesen Header-Namen ein. Mail and Packages verwendet ihn, um Zustell-Adressen automatisch abzugleichen.\n\n**Option 2 — Adressliste**: Geben Sie die Weiterleitungsadressen ein, die Ihr Dienst jedem Zusteller zugewiesen hat, getrennt durch Kommas.", + "title": "Einstellungen für weitergeleitete E-Mails" + }, + "imap_config": { + "description": "Bitte geben Sie die Verbindungsinformationen Ihres Mail-Servers ein.", + "data": { + "host": "Host", + "password": "Passwort", + "port": "Port", + "username": "Nutzername", + "verify_ssl": "SSL-Zertifikat überprüfen", + "imap_security": "IMAP-Sicherheit" + }, + "title": "Briefe und Pakete (Schritt 1 von 2)" + }, + "user": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reconfig_imap": { + "data": { + "host": "Host", + "password": "Passwort", + "port": "Port", + "username": "Nutzername", + "imap_security": "IMAP-Sicherheit", + "verify_ssl": "SSL-Zertifikat überprüfen" + }, + "description": "Bitte geben Sie die Verbindungsinformationen Ihres Mail-Servers ein.", + "title": "Briefe und Pakete (Schritt 1 von 2)" + }, + "reconfigure": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reauth_confirm": { + "description": "The authentication for your mail server has expired or is invalid. Please re-authenticate to continue.", + "data": { + "username": "Username", + "password": "Password" + }, + "title": "Re-authenticate Mail Server" + } + } + }, + "selector": { + "auth_type": { + "options": { + "password": "Password", + "oauth2_microsoft": "OAuth2 - Microsoft (Outlook/Exchange)", + "oauth2_google": "OAuth2 - Google (Gmail)" + } + } + } +} diff --git a/custom_components/mail_and_packages/translations/en.json b/custom_components/mail_and_packages/translations/en.json new file mode 100644 index 0000000..41ea4a0 --- /dev/null +++ b/custom_components/mail_and_packages/translations/en.json @@ -0,0 +1,213 @@ +{ + "config": { + "abort": { + "single_instance_allowed": "Only a single configuration of Mail and Packages is allowed.", + "reconfigure_successful": "Reconfigure Successful" + }, + "error": { + "cannot_connect": "Unable to connect or login to the mail server. Please check the log for details.", + "invalid_path": "Please store the images in another directory.", + "ffmpeg_not_found": "Generate MP4 requires ffmpeg", + "amazon_domain": "Invalid forwarding email address.", + "file_not_found": "Image file not found", + "invalid_email_format": "Invalid email address format.", + "missing_forwarded_emails": "Missing forwarded email addresses. You may enter '(none)' to clear this setting.", + "path_not_found": "Directory not found", + "invalid_auth": "Invalid authentication details. Please check your username and password.", + "ssl_error": "An SSL error occurred. Change SSL cipher list and try again." + }, + "step": { + "user": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "imap_config": { + "description": "Please enter the connection information of your mail server.", + "data": { + "host": "Host", + "password": "Password", + "port": "Port", + "username": "Username", + "verify_ssl": "Verify SSL Cert", + "imap_security": "IMAP Security" + }, + "title": "Mail and Packages (Step 1 of 2)" + }, + "config_2": { + "data": { + "folder": "Mail Folder", + "resources": "Sensors List", + "scan_interval": "Scanning Interval (minutes, minimum 5)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)", + "image_path": "Image Path", + "gif_duration": "Image Duration (seconds)", + "image_security": "Random Image Filename", + "imap_timeout": "Mailbox scan time limit (seconds, minimum 10)", + "generate_mp4": "Create mp4 from images", + "allow_external": "Create image for notification apps", + "custom_img": "Use custom USPS 'no mail' image?", + "amazon_custom_img": "Use custom 'no Amazon delivery' image?", + "ups_custom_img": "Use custom 'no UPS delivery' image?", + "walmart_custom_img": "Use custom 'no Walmart delivery' image?", + "fedex_custom_img": "Use custom 'no FedEx delivery' image?", + "generic_custom_img": "Use custom 'no Generic delivery' image?", + "post_de_custom_img": "Use custom Post DE 'no mail' image?", + "generate_grid": "Create image grid for LLM vision models", + "allow_forwarded_emails": "Allow forwarded emails in addition to a service's default (e.g. no-reply@usps.com)" + }, + "data_description": { + "imap_timeout": "Covers the entire scan — login plus every per-carrier IMAP search — not just connecting. Raise this if large mailboxes time out; lower it to fail faster." + }, + "description": "Finish the configuration by customizing the following based on your email structure and Home Assistant installation.\n\nIf using Amazon forwarded emails please separate each address with a comma.", + "title": "Mail and Packages (Step 2 of 2)" + }, + "config_3": { + "data": { + "custom_img_file": "Path to custom image: (ie: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (ie: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (ie: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (ie: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (ie: images/my_custom_no_fedex.jpg)", + "post_de_custom_img_file": "Path to custom Post DE image: (ie: images/my_custom_no_post_de.gif)" + }, + "description": "Enter the path and file name to your custom no mail image below.\n\nExample: images/custom_nomail.gif", + "title": "Mail and Packages (Step 3 of 3)" + }, + "config_amazon": { + "data": { + "amazon_domain": "Amazon domain", + "amazon_fwds": "Amazon forwarded email addresses", + "amazon_days": "Days back to check for Amazon emails" + }, + "description": "Please enter the domain Amazon sends email's from (ie: amazon.com or amazon.de)\n\nIf using Amazon forwarded emails please separate each address with a comma or enter (none) to clear this setting.\n\nNote: if you configured a forwarding header in the previous step, the forwarding address field will not appear — the header handles Amazon email matching automatically.", + "title": "Amazon Settings" + }, + "reconfigure": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reconfig_imap": { + "data": { + "host": "Host", + "password": "Password", + "port": "Port", + "username": "Username", + "imap_security": "IMAP Security", + "verify_ssl": "Verify SSL Cert" + }, + "description": "Please enter the connection information of your mail server.", + "title": "Mail and Packages (Step 1 of 2)" + }, + "reconfig_2": { + "data": { + "folder": "Mail Folder", + "scan_interval": "Scanning Interval (minutes, minimum 5)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)", + "image_path": "Image Path", + "gif_duration": "Image Duration (seconds)", + "image_security": "Random Image Filename", + "generate_mp4": "Create mp4 from images", + "resources": "Sensors List", + "imap_timeout": "Mailbox scan time limit (seconds, minimum 10)", + "allow_external": "Create image for notification apps", + "custom_img": "Use custom USPS 'no mail' image?", + "amazon_custom_img": "Use custom 'no Amazon delivery' image?", + "ups_custom_img": "Use custom 'no UPS delivery' image?", + "walmart_custom_img": "Use custom 'no Walmart delivery' image?", + "fedex_custom_img": "Use custom 'no FedEx delivery' image?", + "generic_custom_img": "Use custom 'no Generic delivery' image?", + "post_de_custom_img": "Use custom Post DE 'no mail' image?", + "generate_grid": "Create image grid for LLM vision models", + "allow_forwarded_emails": "Allow forwarded emails in addition to a service's default (e.g. no-reply@usps.com)" + }, + "data_description": { + "imap_timeout": "Covers the entire scan — login plus every per-carrier IMAP search — not just connecting. Raise this if large mailboxes time out; lower it to fail faster." + }, + "description": "Finish the configuration by customizing the following based on your email structure and Home Assistant installation.\n\nIf using Amazon forwarded emails please separate each address with a comma or enter (none) to clear this setting.", + "title": "Mail and Packages (Step 2 of 2)" + }, + "reconfig_3": { + "data": { + "custom_img_file": "Path to custom image: (i.e.: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (i.e.: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (i.e.: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (i.e.: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (i.e.: images/my_custom_no_fedex.jpg)", + "post_de_custom_img_file": "Path to custom Post DE image: (i.e.: images/my_custom_no_post_de.gif)" + }, + "description": "Enter the path and file name to your custom no mail image below.\n\nExample: images/custom_nomail.gif", + "title": "Mail and Packages (Step 3 of 3)" + }, + "reconfig_amazon": { + "data": { + "amazon_domain": "Amazon domain", + "amazon_fwds": "Amazon forwarded email addresses", + "amazon_days": "Days back to check for Amazon emails" + }, + "description": "Please enter the domain Amazon sends email's from (ie: amazon.com or amazon.de)\n\nIf using Amazon forwarded emails please separate each address with a comma or enter (none) to clear this setting.\n\nNote: if you configured a forwarding header in the previous step, the forwarding address field will not appear — the header handles Amazon email matching automatically.", + "title": "Amazon Settings" + }, + "config_storage": { + "data": { + "storage": "Directory to store images" + }, + "description": "Please enter the directory you'd like your images to be stored in.\nThe default is auto populated.", + "title": "Image storage location" + }, + "reconfig_storage": { + "data": { + "storage": "Directory to store images" + }, + "description": "Please enter the directory you'd like your images to be stored in.\nThe default is auto populated.", + "title": "Image storage location" + }, + "config_forwarded_emails": { + "data": { + "forwarding_header": "Forwarding Header (e.g. X-SimpleLogin-Original-From)", + "forwarded_emails": "Forwarded Email Addresses" + }, + "data_description": { + "forwarding_header": "If your forwarding service includes the original sender in a header, enter the header name here. This takes precedence over the address list below. Enter '(none)' or leave blank to use the address list instead.", + "forwarded_emails": "Comma-separated list of forwarded addresses messages will arrive from. Leave as '(none)' if using the forwarding header above." + }, + "description": "Choose how to match forwarded emails.\n\n**Option 1 — Forwarding header**: If your service (e.g. SimpleLogin) includes the original sender in a custom header, enter that header name. Mail and Packages will use it to match carrier addresses automatically.\n\n**Option 2 — Address list**: Enter the forwarding addresses your service assigned to each carrier, separated by commas.", + "title": "Forwarded Email Settings" + }, + "reconfig_forwarded_emails": { + "data": { + "forwarding_header": "Forwarding Header (e.g. X-SimpleLogin-Original-From)", + "forwarded_emails": "Forwarded Email Addresses" + }, + "data_description": { + "forwarding_header": "If your forwarding service includes the original sender in a header, enter the header name here. This takes precedence over the address list below. Enter '(none)' or leave blank to use the address list instead.", + "forwarded_emails": "Comma-separated list of forwarded addresses messages will arrive from. Leave as '(none)' if using the forwarding header above." + }, + "description": "Choose how to match forwarded emails.\n\n**Option 1 — Forwarding header**: If your service (e.g. SimpleLogin) includes the original sender in a custom header, enter that header name. Mail and Packages will use it to match carrier addresses automatically.\n\n**Option 2 — Address list**: Enter the forwarding addresses your service assigned to each carrier, separated by commas.", + "title": "Forwarded Email Settings" + }, + "reauth_confirm": { + "description": "The authentication for your mail server has expired or is invalid. Please re-authenticate to continue.", + "data": { + "username": "Username", + "password": "Password" + }, + "title": "Re-authenticate Mail Server" + } + } + }, + "selector": { + "auth_type": { + "options": { + "password": "Password", + "oauth2_microsoft": "OAuth2 - Microsoft (Outlook/Exchange)", + "oauth2_google": "OAuth2 - Google (Gmail)" + } + } + } +} diff --git a/custom_components/mail_and_packages/translations/es.json b/custom_components/mail_and_packages/translations/es.json new file mode 100644 index 0000000..f0fae70 --- /dev/null +++ b/custom_components/mail_and_packages/translations/es.json @@ -0,0 +1,203 @@ +{ + "config": { + "abort": { + "single_instance_allowed": "Solo se permite una única configuración de correo y paquetes.", + "reconfigure_successful": "Reconfiguración Exitosa" + }, + "error": { + "cannot_connect": "No se puede conectar o iniciar sesión en el servidor de correo. Por favor, consulte el registro para más detalles.", + "invalid_path": "Guarde las imágenes en otro directorio.", + "ffmpeg_not_found": "Generar MP4 requiere ffmpeg", + "amazon_domain": "Dirección de correo electrónico de reenvío no válida.", + "file_not_found": "Archivo de imagen no encontrado", + "invalid_email_format": "Formato de dirección de correo electrónico no válido.", + "missing_forwarded_emails": "Faltan direcciones de correo electrónico reenviadas. Puede introducir '(none)' para borrar esta configuración.", + "path_not_found": "Directorio no encontrado", + "invalid_auth": "Invalid authentication details. Please check your username and password.", + "ssl_error": "An SSL error occurred. Change SSL cipher list and try again." + }, + "step": { + "config_2": { + "data": { + "folder": "Carpeta de correo", + "resources": "Lista de Sensores", + "scan_interval": "Intervalo de escaneo (minutos)", + "image_path": "Ruta de la imagen", + "gif_duration": "Duración de la imagen (segundos)", + "image_security": "Nombre de archivo de imagen aleatoria", + "imap_timeout": "Tiempo en segundos antes del tiempo de espera de la conexión (segundos, mínimo 10)", + "generate_mp4": "Crea mp4 a partir de imágenes", + "allow_external": "Crea imagen para aplicaciones de notificación", + "custom_img": "¿Usar imagen personalizada de USPS 'sin correo'?", + "amazon_custom_img": "¿Usar imagen personalizada de Amazon 'sin entrega'?", + "ups_custom_img": "¿Usar imagen personalizada de UPS 'sin entrega'?", + "walmart_custom_img": "¿Usar imagen personalizada de Walmart 'sin entrega'?", + "fedex_custom_img": "¿Usar imagen personalizada de FedEx 'sin entrega'?", + "generic_custom_img": "¿Usar imagen personalizada genérica 'sin entrega'?", + "generate_grid": "Crear cuadrícula de imágenes para modelos de visión LLM", + "allow_forwarded_emails": "Permitir correos electrónicos reenviados además del valor predeterminado de un servicio (p. ej., no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Termine la configuración personalizando lo siguiente según su estructura de correo electrónico y la instalación de Home Assistant. \n\n Para obtener detalles sobre las opciones [Integración de correo y paquetes] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) revise las [configuración, plantillas , y la sección de automatizaciones] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) en GitHub.", + "title": "Correo y paquetes (Paso 2 de 2)" + }, + "config_3": { + "data": { + "custom_img_file": "Ruta a la imagen personalizada: (es decir: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (ie: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (ie: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (ie: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (ie: images/my_custom_no_fedex.jpg)" + }, + "description": "Ingrese la ruta y el nombre del archivo de su imagen personalizada de no correo a continuación.\n\nEjemplo: images/custom_nomail.gif", + "title": "Correo y Paquetes (Paso 3 de 3)" + }, + "config_amazon": { + "data": { + "amazon_domain": "Dominio de Amazon", + "amazon_fwds": "Amazon reenvió direcciones de correo electrónico", + "amazon_days": "Días atrás para verificar los correos electrónicos de Amazon" + }, + "description": "Por favor, introduzca el dominio desde el cual Amazon envía correos electrónicos (es decir: amazon.com o amazon.de)\n\nSi utiliza correos electrónicos reenviados por Amazon, separe cada dirección con una coma o introduzca (ninguno) para borrar esta configuración.\n\nNota: si configuró un encabezado de reenvío en el paso anterior, el campo de dirección de reenvío no aparecerá — el encabezado gestiona la coincidencia de correos electrónicos de Amazon automáticamente.", + "title": "Configuración de Amazon" + }, + "reconfig_2": { + "data": { + "folder": "Carpeta de correo", + "scan_interval": "Intervalo de escaneo (minutos)", + "image_path": "Ruta de la imagen", + "gif_duration": "Duración de la imagen (segundos)", + "image_security": "Nombre de archivo de imagen aleatoria", + "generate_mp4": "Crea mp4 a partir de imágenes", + "resources": "Lista de Sensores", + "imap_timeout": "Tiempo en segundos antes del tiempo de espera de la conexión (segundos, mínimo 10)", + "allow_external": "Crea imagen para aplicaciones de notificación", + "custom_img": "¿Usar imagen personalizada de USPS 'sin correo'?", + "amazon_custom_img": "¿Usar imagen personalizada de Amazon 'sin entrega'?", + "ups_custom_img": "¿Usar imagen personalizada de UPS 'sin entrega'?", + "walmart_custom_img": "¿Usar imagen personalizada de Walmart 'sin entrega'?", + "fedex_custom_img": "¿Usar imagen personalizada de FedEx 'sin entrega'?", + "generic_custom_img": "¿Usar imagen personalizada genérica 'sin entrega'?", + "generate_grid": "Crear cuadrícula de imágenes para modelos de visión LLM", + "allow_forwarded_emails": "Permitir correos electrónicos reenviados además del valor predeterminado de un servicio (p. ej., no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Finalice la configuración personalizando lo siguiente en función de la estructura de su correo electrónico y la instalación de Home Assistant.\n\nPara obtener detalles sobre las opciones de [integración de correo y paquetes](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration), revise la [sección de configuración, plantillas y automatizaciones](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) en GitHub.\n\nSi utiliza correos electrónicos reenviados de Amazon, separe cada dirección con una coma o ingrese (ninguno) para borrar esta configuración.", + "title": "Correo y paquetes (Paso 2 de 2)" + }, + "reconfig_3": { + "data": { + "custom_img_file": "Ruta a la imagen personalizada: (es decir: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (i.e.: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (i.e.: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (i.e.: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (i.e.: images/my_custom_no_fedex.jpg)" + }, + "description": "Ingrese la ruta y el nombre del archivo de su imagen personalizada de no correo a continuación.\n\nEjemplo: images/custom_nomail.gif", + "title": "Correo y Paquetes (Paso 3 de 3)" + }, + "reconfig_amazon": { + "data": { + "amazon_domain": "Dominio de Amazon", + "amazon_fwds": "Amazon reenvió direcciones de correo electrónico", + "amazon_days": "Días atrás para verificar los correos electrónicos de Amazon" + }, + "description": "Por favor, introduzca el dominio desde el cual Amazon envía correos electrónicos (es decir: amazon.com o amazon.de)\n\nSi utiliza correos electrónicos reenviados por Amazon, separe cada dirección con una coma o introduzca (ninguno) para borrar esta configuración.\n\nNota: si configuró un encabezado de reenvío en el paso anterior, el campo de dirección de reenvío no aparecerá — el encabezado gestiona la coincidencia de correos electrónicos de Amazon automáticamente.", + "title": "Configuración de Amazon" + }, + "config_storage": { + "data": { + "storage": "Directorio para almacenar imágenes" + }, + "description": "Por favor, introduzca el directorio en el que le gustaría almacenar sus imágenes. \nEl valor predeterminado se rellena automáticamente.", + "title": "Ubicación de almacenamiento de imágenes" + }, + "reconfig_storage": { + "data": { + "storage": "Directorio para almacenar imágenes" + }, + "description": "Por favor, introduzca el directorio en el que le gustaría almacenar sus imágenes. \nEl valor predeterminado se rellena automáticamente.", + "title": "Ubicación de almacenamiento de imágenes" + }, + "config_forwarded_emails": { + "data": { + "forwarding_header": "Cabecera de reenvío (p. ej. X-SimpleLogin-Original-From)", + "forwarded_emails": "Direcciones de correo electrónico reenviadas" + }, + "data_description": { + "forwarding_header": "Si su servicio de reenvío incluye el remitente original en una cabecera, ingrese el nombre de la cabecera aquí. Esto tiene prioridad sobre la lista de direcciones a continuación. Ingrese '(none)' o deje en blanco para usar la lista de direcciones en su lugar.", + "forwarded_emails": "Lista separada por comas de las direcciones de reenvío de las que llegarán los mensajes. Deje '(none)' si usa la cabecera de reenvío de arriba." + }, + "description": "Elija cómo hacer coincidir los correos electrónicos reenviados.\n\n**Opción 1 — Cabecera de reenvío**: Si su servicio (p. ej. SimpleLogin) incluye el remitente original en una cabecera personalizada, ingrese ese nombre de cabecera. Mail and Packages lo usará para hacer coincidir las direcciones de los transportistas automáticamente.\n\n**Opción 2 — Lista de direcciones**: Ingrese las direcciones de reenvío que su servicio asignó a cada transportista, separadas por comas.", + "title": "Configuración de correos electrónicos reenviados" + }, + "reconfig_forwarded_emails": { + "data": { + "forwarding_header": "Cabecera de reenvío (p. ej. X-SimpleLogin-Original-From)", + "forwarded_emails": "Direcciones de correo electrónico reenviadas" + }, + "data_description": { + "forwarding_header": "Si su servicio de reenvío incluye el remitente original en una cabecera, ingrese el nombre de la cabecera aquí. Esto tiene prioridad sobre la lista de direcciones a continuación. Ingrese '(none)' o deje en blanco para usar la lista de direcciones en su lugar.", + "forwarded_emails": "Lista separada por comas de las direcciones de reenvío de las que llegarán los mensajes. Deje '(none)' si usa la cabecera de reenvío de arriba." + }, + "description": "Elija cómo hacer coincidir los correos electrónicos reenviados.\n\n**Opción 1 — Cabecera de reenvío**: Si su servicio (p. ej. SimpleLogin) incluye el remitente original en una cabecera personalizada, ingrese ese nombre de cabecera. Mail and Packages lo usará para hacer coincidir las direcciones de los transportistas automáticamente.\n\n**Opción 2 — Lista de direcciones**: Ingrese las direcciones de reenvío que su servicio asignó a cada transportista, separadas por comas.", + "title": "Configuración de correos electrónicos reenviados" + }, + "imap_config": { + "description": "Por favor, ingrese la información de conexión de su servidor de correo.", + "data": { + "host": "Anfitrión", + "password": "Contraseña", + "port": "Puerto", + "username": "Nombre de usuario", + "verify_ssl": "Verificar Certificado SSL", + "imap_security": "Seguridad IMAP" + }, + "title": "Correo y paquetes (Paso 1 de 2)" + }, + "user": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reconfig_imap": { + "data": { + "host": "Anfitrión", + "password": "Contraseña", + "port": "Puerto", + "username": "Nombre de usuario", + "imap_security": "Seguridad IMAP", + "verify_ssl": "Verificar Certificado SSL" + }, + "description": "Por favor, ingrese la información de conexión de su servidor de correo.", + "title": "Correo y paquetes (Paso 1 de 2)" + }, + "reconfigure": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reauth_confirm": { + "description": "The authentication for your mail server has expired or is invalid. Please re-authenticate to continue.", + "data": { + "username": "Username", + "password": "Password" + }, + "title": "Re-authenticate Mail Server" + } + } + }, + "selector": { + "auth_type": { + "options": { + "password": "Password", + "oauth2_microsoft": "OAuth2 - Microsoft (Outlook/Exchange)", + "oauth2_google": "OAuth2 - Google (Gmail)" + } + } + } +} diff --git a/custom_components/mail_and_packages/translations/es_419.json b/custom_components/mail_and_packages/translations/es_419.json new file mode 100644 index 0000000..b0e7251 --- /dev/null +++ b/custom_components/mail_and_packages/translations/es_419.json @@ -0,0 +1,203 @@ +{ + "config": { + "abort": { + "single_instance_allowed": "Solo se permite una única configuración de correo y paquetes.", + "reconfigure_successful": "Reconfiguración Exitosa" + }, + "error": { + "cannot_connect": "No se puede conectar o iniciar sesión en el servidor de correo. Por favor, consulte el registro para más detalles.", + "invalid_path": "Guarde las imágenes en otro directorio.", + "ffmpeg_not_found": "Generar MP4 requiere ffmpeg", + "amazon_domain": "Dirección de correo electrónico de reenvío no válida.", + "file_not_found": "Archivo de imagen no encontrado", + "invalid_email_format": "Formato de dirección de correo electrónico inválido.", + "missing_forwarded_emails": "Faltan direcciones de correo electrónico reenviadas. Puede introducir '(none)' para borrar esta configuración.", + "path_not_found": "Directorio no encontrado", + "invalid_auth": "Invalid authentication details. Please check your username and password.", + "ssl_error": "An SSL error occurred. Change SSL cipher list and try again." + }, + "step": { + "config_2": { + "data": { + "folder": "Carpeta de correo", + "resources": "Lista de Sensores", + "scan_interval": "Intervalo de escaneo (minutos)", + "image_path": "Ruta de la imagen", + "gif_duration": "Duración de la imagen (segundos)", + "image_security": "Nombre de archivo de imagen aleatoria", + "imap_timeout": "Tiempo en segundos antes del tiempo de espera de la conexión (segundos, mínimo 10)", + "generate_mp4": "Crea mp4 a partir de imágenes", + "allow_external": "Crea imagen para aplicaciones de notificación", + "custom_img": "¿Usar imagen personalizada de USPS 'sin correo'?", + "amazon_custom_img": "¿Usar imagen personalizada de Amazon 'sin entrega'?", + "ups_custom_img": "¿Usar imagen personalizada de UPS 'sin entrega'?", + "walmart_custom_img": "¿Usar imagen personalizada de Walmart 'sin entrega'?", + "fedex_custom_img": "¿Usar imagen personalizada de FedEx 'sin entrega'?", + "generic_custom_img": "¿Usar imagen personalizada genérica 'sin entrega'?", + "generate_grid": "Crear cuadrícula de imágenes para modelos de visión LLM", + "allow_forwarded_emails": "Permitir correos electrónicos reenviados además del valor predeterminado de un servicio (p. ej., no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Termine la configuración personalizando lo siguiente según su estructura de correo electrónico y la instalación de Home Assistant. \n\n Para obtener detalles sobre las opciones [Integración de correo y paquetes] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) revise las [configuración, plantillas , y la sección de automatizaciones] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) en GitHub.", + "title": "Correo y paquetes (Paso 2 de 2)" + }, + "config_3": { + "data": { + "custom_img_file": "Ruta a la imagen personalizada: (es decir: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (ie: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (ie: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (ie: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (ie: images/my_custom_no_fedex.jpg)" + }, + "description": "Ingrese la ruta y el nombre del archivo de su imagen personalizada de no correo a continuación.\n\nEjemplo: images/custom_nomail.gif", + "title": "Correo y paquetes (Paso 3 de 3)" + }, + "config_amazon": { + "data": { + "amazon_domain": "Dominio de Amazon", + "amazon_fwds": "Amazon reenvió direcciones de correo electrónico", + "amazon_days": "Días atrás para verificar los correos electrónicos de Amazon" + }, + "description": "Por favor, ingrese el dominio desde el cual Amazon envía correos electrónicos (es decir: amazon.com o amazon.de)\n\nSi utiliza correos electrónicos reenviados por Amazon, separe cada dirección con una coma o ingrese (ninguno) para borrar esta configuración.\n\nNota: si configuró un encabezado de reenvío en el paso anterior, el campo de dirección de reenvío no aparecerá — el encabezado gestiona la coincidencia de correos electrónicos de Amazon automáticamente.", + "title": "Configuración de Amazon" + }, + "reconfig_2": { + "data": { + "folder": "Carpeta de correo", + "scan_interval": "Intervalo de escaneo (minutos)", + "image_path": "Ruta de la imagen", + "gif_duration": "Duración de la imagen (segundos)", + "image_security": "Nombre de archivo de imagen aleatoria", + "generate_mp4": "Crea mp4 a partir de imágenes", + "resources": "Lista de Sensores", + "imap_timeout": "Tiempo en segundos antes del tiempo de espera de la conexión (segundos, mínimo 10)", + "allow_external": "Crea imagen para aplicaciones de notificación", + "custom_img": "¿Usar imagen personalizada de USPS 'sin correo'?", + "amazon_custom_img": "¿Usar imagen personalizada de Amazon 'sin entrega'?", + "ups_custom_img": "¿Usar imagen personalizada de UPS 'sin entrega'?", + "walmart_custom_img": "¿Usar imagen personalizada de Walmart 'sin entrega'?", + "fedex_custom_img": "¿Usar imagen personalizada de FedEx 'sin entrega'?", + "generic_custom_img": "¿Usar imagen personalizada genérica 'sin entrega'?", + "generate_grid": "Crear cuadrícula de imágenes para modelos de visión LLM", + "allow_forwarded_emails": "Permitir correos electrónicos reenviados además del valor predeterminado de un servicio (p. ej., no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Finalice la configuración personalizando lo siguiente en función de la estructura de su correo electrónico y la instalación de Home Assistant.\n\nPara obtener detalles sobre las opciones de [integración de correo y paquetes](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration), revise la [sección de configuración, plantillas y automatizaciones](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) en GitHub.\n\nSi utiliza correos electrónicos reenviados de Amazon, separe cada dirección con una coma o ingrese (ninguno) para borrar esta configuración.", + "title": "Correo y paquetes (Paso 2 de 2)" + }, + "reconfig_3": { + "data": { + "custom_img_file": "Ruta a la imagen personalizada: (es decir: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (i.e.: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (i.e.: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (i.e.: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (i.e.: images/my_custom_no_fedex.jpg)" + }, + "description": "Ingrese la ruta y el nombre del archivo de su imagen personalizada de no correo a continuación.\n\nEjemplo: images/custom_nomail.gif", + "title": "Correo y paquetes (Paso 3 de 3)" + }, + "reconfig_amazon": { + "data": { + "amazon_domain": "Dominio de Amazon", + "amazon_fwds": "Amazon reenvió direcciones de correo electrónico", + "amazon_days": "Días atrás para verificar los correos electrónicos de Amazon" + }, + "description": "Por favor, ingrese el dominio desde el cual Amazon envía correos electrónicos (es decir: amazon.com o amazon.de)\n\nSi utiliza correos electrónicos reenviados por Amazon, separe cada dirección con una coma o ingrese (ninguno) para borrar esta configuración.\n\nNota: si configuró un encabezado de reenvío en el paso anterior, el campo de dirección de reenvío no aparecerá — el encabezado gestiona la coincidencia de correos electrónicos de Amazon automáticamente.", + "title": "Configuración de Amazon" + }, + "config_storage": { + "data": { + "storage": "Directorio para almacenar imágenes" + }, + "description": "Por favor, ingrese el directorio en el que le gustaría almacenar sus imágenes.\nEl predeterminado se llena automáticamente.", + "title": "Ubicación de almacenamiento de imágenes" + }, + "reconfig_storage": { + "data": { + "storage": "Directorio para almacenar imágenes" + }, + "description": "Por favor, ingrese el directorio en el que le gustaría almacenar sus imágenes.\nEl predeterminado se llena automáticamente.", + "title": "Ubicación de almacenamiento de imágenes" + }, + "config_forwarded_emails": { + "data": { + "forwarding_header": "Cabecera de reenvío (p. ej. X-SimpleLogin-Original-From)", + "forwarded_emails": "Direcciones de correo electrónico reenviadas" + }, + "data_description": { + "forwarding_header": "Si su servicio de reenvío incluye el remitente original en una cabecera, ingrese el nombre de la cabecera aquí. Esto tiene prioridad sobre la lista de direcciones a continuación. Ingrese '(none)' o deje en blanco para usar la lista de direcciones en su lugar.", + "forwarded_emails": "Lista separada por comas de las direcciones de reenvío de las que llegarán los mensajes. Deje '(none)' si usa la cabecera de reenvío de arriba." + }, + "description": "Elija cómo hacer coincidir los correos electrónicos reenviados.\n\n**Opción 1 — Cabecera de reenvío**: Si su servicio (p. ej. SimpleLogin) incluye el remitente original en una cabecera personalizada, ingrese ese nombre de cabecera. Mail and Packages lo usará para hacer coincidir las direcciones de los transportistas automáticamente.\n\n**Opción 2 — Lista de direcciones**: Ingrese las direcciones de reenvío que su servicio asignó a cada transportista, separadas por comas.", + "title": "Configuración de correos electrónicos reenviados" + }, + "reconfig_forwarded_emails": { + "data": { + "forwarding_header": "Cabecera de reenvío (p. ej. X-SimpleLogin-Original-From)", + "forwarded_emails": "Direcciones de correo electrónico reenviadas" + }, + "data_description": { + "forwarding_header": "Si su servicio de reenvío incluye el remitente original en una cabecera, ingrese el nombre de la cabecera aquí. Esto tiene prioridad sobre la lista de direcciones a continuación. Ingrese '(none)' o deje en blanco para usar la lista de direcciones en su lugar.", + "forwarded_emails": "Lista separada por comas de las direcciones de reenvío de las que llegarán los mensajes. Deje '(none)' si usa la cabecera de reenvío de arriba." + }, + "description": "Elija cómo hacer coincidir los correos electrónicos reenviados.\n\n**Opción 1 — Cabecera de reenvío**: Si su servicio (p. ej. SimpleLogin) incluye el remitente original en una cabecera personalizada, ingrese ese nombre de cabecera. Mail and Packages lo usará para hacer coincidir las direcciones de los transportistas automáticamente.\n\n**Opción 2 — Lista de direcciones**: Ingrese las direcciones de reenvío que su servicio asignó a cada transportista, separadas por comas.", + "title": "Configuración de correos electrónicos reenviados" + }, + "imap_config": { + "description": "Por favor, ingrese la información de conexión de su servidor de correo.", + "data": { + "host": "Anfitrión", + "password": "Contraseña", + "port": "Puerto", + "username": "Nombre de usuario", + "verify_ssl": "Verificar Certificado SSL", + "imap_security": "Seguridad IMAP" + }, + "title": "Correo y paquetes (Paso 1 de 2)" + }, + "user": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reconfig_imap": { + "data": { + "host": "Anfitrión", + "password": "Contraseña", + "port": "Puerto", + "username": "Nombre de usuario", + "imap_security": "Seguridad IMAP", + "verify_ssl": "Verificar Certificado SSL" + }, + "description": "Por favor, ingrese la información de conexión de su servidor de correo.", + "title": "Correo y paquetes (Paso 1 de 2)" + }, + "reconfigure": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reauth_confirm": { + "description": "The authentication for your mail server has expired or is invalid. Please re-authenticate to continue.", + "data": { + "username": "Username", + "password": "Password" + }, + "title": "Re-authenticate Mail Server" + } + } + }, + "selector": { + "auth_type": { + "options": { + "password": "Password", + "oauth2_microsoft": "OAuth2 - Microsoft (Outlook/Exchange)", + "oauth2_google": "OAuth2 - Google (Gmail)" + } + } + } +} diff --git a/custom_components/mail_and_packages/translations/fi.json b/custom_components/mail_and_packages/translations/fi.json new file mode 100644 index 0000000..0205650 --- /dev/null +++ b/custom_components/mail_and_packages/translations/fi.json @@ -0,0 +1,203 @@ +{ + "config": { + "abort": { + "single_instance_allowed": "Vain yksi posti- ja pakettien kokoonpano on sallittu.", + "reconfigure_successful": "Uudelleenmääritys onnistui" + }, + "error": { + "cannot_connect": "Ei voida muodostaa yhteyttä tai kirjautua sisään postipalvelimeen. Tarkista lokista yksityiskohdat.", + "invalid_path": "Tallenna kuvat toiseen hakemistoon.", + "ffmpeg_not_found": "MP4:n luominen vaatii ffmpeg:n", + "amazon_domain": "Virheellinen edelleenlähetettävä sähköpostiosoite.", + "file_not_found": "Kuvatiedostoa ei löydy", + "invalid_email_format": "Virheellinen sähköpostiosoitteen muoto.", + "missing_forwarded_emails": "Puuttuvat edelleenlähetetyt sähköpostiosoitteet. Voit syöttää '(none)' tyhjentääksesi tämän asetuksen.", + "path_not_found": "Hakemistoa ei löydy", + "invalid_auth": "Invalid authentication details. Please check your username and password.", + "ssl_error": "An SSL error occurred. Change SSL cipher list and try again." + }, + "step": { + "config_2": { + "data": { + "folder": "Mail-kansio", + "resources": "Anturiluettelo", + "scan_interval": "Skannausväli (minuutit)", + "image_path": "Kuvan polku", + "gif_duration": "Kuvan kesto (sekunteina)", + "image_security": "Satunnainen kuvatiedostonimi", + "imap_timeout": "Aika sekunneissa ennen yhteyden aikakatkaisua (sekuntia, vähintään 10)", + "generate_mp4": "Luo mp4 kuvista", + "allow_external": "Luo kuva ilmoitussovelluksille", + "custom_img": "Käytä mukautettua USPS 'ei postia' kuvaa?", + "amazon_custom_img": "Käytä mukautettua Amazon 'ei toimituksia' kuvaa?", + "ups_custom_img": "Käytä mukautettua UPS 'ei toimituksia' kuvaa?", + "walmart_custom_img": "Käytä mukautettua Walmart 'ei toimituksia' kuvaa?", + "fedex_custom_img": "Käytä mukautettua FedEx 'ei toimituksia' kuvaa?", + "generic_custom_img": "Käytä mukautettua yleistä 'ei toimituksia' kuvaa?", + "generate_grid": "Luo kuvaverkko LLM-näkömalleille", + "allow_forwarded_emails": "Salli edelleenlähetetyt sähköpostit palvelun oletusarvon lisäksi (esim. no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Viimeistele kokoonpano mukauttamalla seuraava sähköpostirakenteen ja Home Assistant -asennuksen perusteella. \n\n Lisätietoja [Posti ja paketit-integroinnista] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) -asetuksista on [kokoonpano, mallit , ja automaatiot-osio] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) GitHubissa.", + "title": "Posti ja paketit (vaihe 2/2)" + }, + "config_3": { + "data": { + "custom_img_file": "Polku mukautettuun kuvaan: (esim: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (ie: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (ie: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (ie: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (ie: images/my_custom_no_fedex.jpg)" + }, + "description": "Syötä alla olevaan kenttään polku ja tiedostonimi mukautetulle ei-postia -kuvallesi.\n\nEsimerkki: kuvat/mukautettu_eipostia.gif", + "title": "Posti ja paketit (vaihe 3/3)" + }, + "config_amazon": { + "data": { + "amazon_domain": "Amazonin verkkotunnus", + "amazon_fwds": "Amazon välitti sähköpostiosoitteet", + "amazon_days": "Päiviä, joiden aikana tarkistetaan Amazonin sähköpostit" + }, + "description": "Anna domaini, josta Amazon lähettää sähköposteja (esim: amazon.com tai amazon.de)\n\nJos käytät Amazonin välittämiä sähköposteja, erottele jokainen osoite pilkulla tai kirjoita (none) tyhjentääksesi tämän asetuksen.\n\nHuomio: jos määritit edelleenlähetyksen otsikon edellisessä vaiheessa, edelleenlähetysosoite-kenttä ei näy — otsikko käsittelee Amazon-sähköpostien täsmäytyksen automaattisesti.", + "title": "Amazonin asetukset" + }, + "reconfig_2": { + "data": { + "folder": "Mail-kansio", + "scan_interval": "Skannausväli (minuutit)", + "image_path": "Kuvan polku", + "gif_duration": "Kuvan kesto (sekunteina)", + "image_security": "Satunnainen kuvatiedostonimi", + "generate_mp4": "Luo mp4 kuvista", + "resources": "Anturiluettelo", + "imap_timeout": "Aika sekunneissa ennen yhteyden aikakatkaisua (sekuntia, vähintään 10)", + "allow_external": "Luo kuva ilmoitussovelluksille", + "custom_img": "Käytä mukautettua USPS 'ei postia' kuvaa?", + "amazon_custom_img": "Käytä mukautettua Amazon 'ei toimituksia' kuvaa?", + "ups_custom_img": "Käytä mukautettua UPS 'ei toimituksia' kuvaa?", + "walmart_custom_img": "Käytä mukautettua Walmart 'ei toimituksia' kuvaa?", + "fedex_custom_img": "Käytä mukautettua FedEx 'ei toimituksia' kuvaa?", + "generic_custom_img": "Käytä mukautettua yleistä 'ei toimituksia' kuvaa?", + "generate_grid": "Luo kuvaverkko LLM-näkömalleille", + "allow_forwarded_emails": "Salli edelleenlähetetyt sähköpostit palvelun oletusarvon lisäksi (esim. no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Suorita määritys loppuun mukauttamalla seuraavat sähköpostirakenteeseesi ja Home Assistant -asennukseesi perustuen.\n\nLisätietoja [Mail and Packages -integraation](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) vaihtoehdoista löydät GitHubista [määritys-, mallit- ja automaatiot-osiossa](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration).\n\nJos käytät Amazonin välittämiä sähköposteja, erottele jokainen osoite pilkulla tai syötä (none) tyhjentääksesi tämän asetuksen.", + "title": "Posti ja paketit (vaihe 2/2)" + }, + "reconfig_3": { + "data": { + "custom_img_file": "Polku mukautettuun kuvaan: (esim.: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (i.e.: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (i.e.: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (i.e.: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (i.e.: images/my_custom_no_fedex.jpg)" + }, + "description": "Syötä alla olevaan kenttään polku ja tiedostonimi mukautetulle ei-postia -kuvallesi.\n\nEsimerkki: kuvat/mukautettu_eipostia.gif", + "title": "Posti ja paketit (vaihe 3/3)" + }, + "reconfig_amazon": { + "data": { + "amazon_domain": "Amazonin verkkotunnus", + "amazon_fwds": "Amazon välitti sähköpostiosoitteet", + "amazon_days": "Päiviä, joiden aikana tarkistetaan Amazonin sähköpostit" + }, + "description": "Anna domaini, josta Amazon lähettää sähköposteja (esim: amazon.com tai amazon.de)\n\nJos käytät Amazonin välittämiä sähköposteja, erottele jokainen osoite pilkulla tai kirjoita (none) tyhjentääksesi tämän asetuksen.\n\nHuomio: jos määritit edelleenlähetyksen otsikon edellisessä vaiheessa, edelleenlähetysosoite-kenttä ei näy — otsikko käsittelee Amazon-sähköpostien täsmäytyksen automaattisesti.", + "title": "Amazonin asetukset" + }, + "config_storage": { + "data": { + "storage": "Hakemisto kuvien tallentamiseen" + }, + "description": "Anna hakemisto, johon haluat kuviesi tallentuvan.\nOletusarvo täytetään automaattisesti.", + "title": "Kuvien tallennuspaikka" + }, + "reconfig_storage": { + "data": { + "storage": "Hakemisto kuvien tallentamiseen" + }, + "description": "Anna hakemisto, johon haluat kuviesi tallentuvan.\nOletusarvo täytetään automaattisesti.", + "title": "Kuvien tallennuspaikka" + }, + "config_forwarded_emails": { + "data": { + "forwarding_header": "Välitysotsake (esim. X-SimpleLogin-Original-From)", + "forwarded_emails": "Edelleenlähetetyt sähköpostiosoitteet" + }, + "data_description": { + "forwarding_header": "Jos välityspalvelusi sisältää alkuperäisen lähettäjän otsikossa, syötä otsikon nimi tähän. Tämä ohittaa alla olevan osoitelistan. Syötä '(none)' tai jätä tyhjäksi käyttääksesi osoitelistaa.", + "forwarded_emails": "Pilkuilla eroteltu lista välitysosoitteista, joista viestit saapuvat. Jätä '(none)', jos käytät yllä olevaa välitysotsiketta." + }, + "description": "Valitse, miten välitetyt sähköpostit yhdistetään.\n\n**Vaihtoehto 1 — Välitysotsake**: Jos palvelusi (esim. SimpleLogin) sisältää alkuperäisen lähettäjän mukautetussa otsakkeessa, syötä kyseinen otsakkeen nimi. Mail and Packages käyttää sitä kuriiriosoitteiden automaattiseen yhdistämiseen.\n\n**Vaihtoehto 2 — Osoitelista**: Syötä välitysosoitteet, jotka palvelusi on määrittänyt kullekin kuriirille, pilkuilla eroteltuna.", + "title": "Välitettyjen sähköpostien asetukset" + }, + "reconfig_forwarded_emails": { + "data": { + "forwarding_header": "Välitysotsake (esim. X-SimpleLogin-Original-From)", + "forwarded_emails": "Edelleenlähetetyt sähköpostiosoitteet" + }, + "data_description": { + "forwarding_header": "Jos välityspalvelusi sisältää alkuperäisen lähettäjän otsikossa, syötä otsikon nimi tähän. Tämä ohittaa alla olevan osoitelistan. Syötä '(none)' tai jätä tyhjäksi käyttääksesi osoitelistaa.", + "forwarded_emails": "Pilkuilla eroteltu lista välitysosoitteista, joista viestit saapuvat. Jätä '(none)', jos käytät yllä olevaa välitysotsiketta." + }, + "description": "Valitse, miten välitetyt sähköpostit yhdistetään.\n\n**Vaihtoehto 1 — Välitysotsake**: Jos palvelusi (esim. SimpleLogin) sisältää alkuperäisen lähettäjän mukautetussa otsakkeessa, syötä kyseinen otsakkeen nimi. Mail and Packages käyttää sitä kuriiriosoitteiden automaattiseen yhdistämiseen.\n\n**Vaihtoehto 2 — Osoitelista**: Syötä välitysosoitteet, jotka palvelusi on määrittänyt kullekin kuriirille, pilkuilla eroteltuna.", + "title": "Välitettyjen sähköpostien asetukset" + }, + "imap_config": { + "description": "Anna postipalvelimesi yhteystiedot.", + "data": { + "host": "isäntä", + "password": "Salasana", + "port": "portti", + "username": "Käyttäjätunnus", + "verify_ssl": "Varmenna SSL-sertifikaatti", + "imap_security": "IMAP-tietoturva" + }, + "title": "Posti ja paketit (vaihe 1/2)" + }, + "user": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reconfig_imap": { + "data": { + "host": "isäntä", + "password": "Salasana", + "port": "portti", + "username": "Käyttäjätunnus", + "imap_security": "IMAP-tietoturva", + "verify_ssl": "Varmenna SSL-sertifikaatti" + }, + "description": "Anna postipalvelimesi yhteystiedot.", + "title": "Posti ja paketit (vaihe 1/2)" + }, + "reconfigure": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reauth_confirm": { + "description": "The authentication for your mail server has expired or is invalid. Please re-authenticate to continue.", + "data": { + "username": "Username", + "password": "Password" + }, + "title": "Re-authenticate Mail Server" + } + } + }, + "selector": { + "auth_type": { + "options": { + "password": "Password", + "oauth2_microsoft": "OAuth2 - Microsoft (Outlook/Exchange)", + "oauth2_google": "OAuth2 - Google (Gmail)" + } + } + } +} diff --git a/custom_components/mail_and_packages/translations/fr.json b/custom_components/mail_and_packages/translations/fr.json new file mode 100644 index 0000000..c18b76d --- /dev/null +++ b/custom_components/mail_and_packages/translations/fr.json @@ -0,0 +1,203 @@ +{ + "config": { + "abort": { + "single_instance_allowed": "Une seule configuration de Mail et Packages est autorisée.", + "reconfigure_successful": "Reconfiguration réussie" + }, + "error": { + "cannot_connect": "Impossible de se connecter ou de se connecter au serveur de messagerie. Veuillez consulter le journal pour plus de détails.", + "invalid_path": "Veuillez stocker les images dans un autre répertoire.", + "ffmpeg_not_found": "Générer MP4 nécessite ffmpeg", + "amazon_domain": "Adresse e-mail de transfert invalide.", + "file_not_found": "Fichier image non trouvé", + "invalid_email_format": "Format d'adresse e-mail invalide.", + "missing_forwarded_emails": "Adresses e-mail de transfert manquantes. Vous pouvez entrer '(none)' pour effacer ce paramètre.", + "path_not_found": "Répertoire non trouvé", + "invalid_auth": "Invalid authentication details. Please check your username and password.", + "ssl_error": "An SSL error occurred. Change SSL cipher list and try again." + }, + "step": { + "config_2": { + "data": { + "folder": "Dossier de messagerie", + "resources": "Liste des capteurs", + "scan_interval": "Intervalle de numérisation (minutes)", + "image_path": "Chemin de l'image", + "gif_duration": "Durée de l'image (secondes)", + "image_security": "Nom de fichier d'image aléatoire", + "imap_timeout": "Temps en secondes avant la fin de la connexion (secondes, minimum 10)", + "generate_mp4": "Créer mp4 à partir d'images", + "allow_external": "Créer une image pour les applications de notification", + "custom_img": "Utiliser une image personnalisée USPS 'pas de courrier' ?", + "amazon_custom_img": "Utiliser une image personnalisée Amazon 'pas de livraison' ?", + "ups_custom_img": "Utiliser une image personnalisée UPS 'pas de livraison' ?", + "walmart_custom_img": "Utiliser une image personnalisée Walmart 'pas de livraison' ?", + "fedex_custom_img": "Utiliser une image personnalisée FedEx 'pas de livraison' ?", + "generic_custom_img": "Utiliser une image personnalisée générique 'pas de livraison' ?", + "generate_grid": "Créer une grille d'images pour les modèles de vision LLM", + "allow_forwarded_emails": "Autoriser les e-mails transférés en plus de la valeur par défaut d'un service (par ex. no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Terminez la configuration en personnalisant les éléments suivants en fonction de votre structure de messagerie et de l'installation de Home Assistant. \n\n Pour plus de détails sur les [Intégration de messagerie et de packages] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration), passez en revue les [configuration, modèles et section automatisations] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) sur GitHub.", + "title": "Courrier et colis (étape 2 sur 2)" + }, + "config_3": { + "data": { + "custom_img_file": "Chemin vers l'image personnalisée : (par exemple : images/mon_image_personnalisée_pas_de_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (ie: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (ie: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (ie: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (ie: images/my_custom_no_fedex.jpg)" + }, + "description": "Entrez le chemin et le nom de fichier de votre image personnalisée de non-réception de courrier ci-dessous.\n\nExemple : images/custom_nomail.gif", + "title": "Courrier et colis (Étape 3 sur 3)" + }, + "config_amazon": { + "data": { + "amazon_domain": "Domaine Amazon", + "amazon_fwds": "Amazon a transmis des adresses e-mail", + "amazon_days": "Jours en arrière pour vérifier les emails Amazon" + }, + "description": "Veuillez entrer le domaine à partir duquel Amazon envoie des emails (par exemple : amazon.com ou amazon.de)\n\nSi vous utilisez des emails transférés par Amazon, veuillez séparer chaque adresse par une virgule ou entrer (aucun) pour effacer ce paramètre.\n\nRemarque : si vous avez configuré un en-tête de transfert dans l'étape précédente, le champ d'adresse de transfert n'apparaîtra pas — l'en-tête gère automatiquement la correspondance des e-mails Amazon.", + "title": "Paramètres Amazon" + }, + "reconfig_2": { + "data": { + "folder": "Dossier de messagerie", + "scan_interval": "Intervalle de numérisation (minutes)", + "image_path": "Chemin de l'image", + "gif_duration": "Durée de l'image (secondes)", + "image_security": "Nom de fichier d'image aléatoire", + "generate_mp4": "Créer mp4 à partir d'images", + "resources": "Liste des capteurs", + "imap_timeout": "Temps en secondes avant la fin de la connexion (secondes, minimum 10)", + "allow_external": "Créer une image pour les applications de notification", + "custom_img": "Utiliser une image personnalisée USPS 'pas de courrier' ?", + "amazon_custom_img": "Utiliser une image personnalisée Amazon 'pas de livraison' ?", + "ups_custom_img": "Utiliser une image personnalisée UPS 'pas de livraison' ?", + "walmart_custom_img": "Utiliser une image personnalisée Walmart 'pas de livraison' ?", + "fedex_custom_img": "Utiliser une image personnalisée FedEx 'pas de livraison' ?", + "generic_custom_img": "Utiliser une image personnalisée générique 'pas de livraison' ?", + "generate_grid": "Créer une grille d'images pour les modèles de vision LLM", + "allow_forwarded_emails": "Autoriser les e-mails transférés en plus de la valeur par défaut d'un service (par ex. no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Terminez la configuration en personnalisant ce qui suit en fonction de la structure de votre courrier électronique et de l'installation de Home Assistant.\n\nPour plus de détails sur les options d'[intégration de courrier et de colis](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration), consultez la [section configuration, modèles et automatisations](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) sur GitHub.\n\nSi vous utilisez des courriels transférés par Amazon, veuillez séparer chaque adresse par une virgule ou entrer (aucun) pour effacer ce paramètre.", + "title": "Courrier et colis (étape 2 sur 2)" + }, + "reconfig_3": { + "data": { + "custom_img_file": "Chemin vers l'image personnalisée : (par exemple : images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (i.e.: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (i.e.: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (i.e.: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (i.e.: images/my_custom_no_fedex.jpg)" + }, + "description": "Entrez le chemin et le nom de fichier de votre image personnalisée de non-réception de courrier ci-dessous.\n\nExemple : images/custom_nomail.gif", + "title": "Courrier et colis (Étape 3 sur 3)" + }, + "reconfig_amazon": { + "data": { + "amazon_domain": "Domaine Amazon", + "amazon_fwds": "Amazon a transmis des adresses e-mail", + "amazon_days": "Jours en arrière pour vérifier les emails Amazon" + }, + "description": "Veuillez entrer le domaine à partir duquel Amazon envoie des emails (par exemple : amazon.com ou amazon.de)\n\nSi vous utilisez des emails transférés par Amazon, veuillez séparer chaque adresse par une virgule ou entrer (aucun) pour effacer ce paramètre.\n\nRemarque : si vous avez configuré un en-tête de transfert dans l'étape précédente, le champ d'adresse de transfert n'apparaîtra pas — l'en-tête gère automatiquement la correspondance des e-mails Amazon.", + "title": "Paramètres Amazon" + }, + "config_storage": { + "data": { + "storage": "Répertoire pour stocker les images" + }, + "description": "Veuillez entrer le répertoire dans lequel vous souhaitez que vos images soient stockées.\nLa valeur par défaut est automatiquement remplie.", + "title": "Emplacement de stockage des images" + }, + "reconfig_storage": { + "data": { + "storage": "Répertoire pour stocker les images" + }, + "description": "Veuillez entrer le répertoire dans lequel vous souhaitez que vos images soient stockées.\nLa valeur par défaut est automatiquement remplie.", + "title": "Emplacement de stockage des images" + }, + "config_forwarded_emails": { + "data": { + "forwarding_header": "En-tête de transfert (ex. X-SimpleLogin-Original-From)", + "forwarded_emails": "Adresses e-mail transférées" + }, + "data_description": { + "forwarding_header": "Si votre service de transfert inclut l'expéditeur original dans un en-tête, entrez le nom de l'en-tête ici. Cela a la priorité sur la liste d'adresses ci-dessous. Entrez '(none)' ou laissez vide pour utiliser la liste d'adresses à la place.", + "forwarded_emails": "Liste séparée par des virgules des adresses de transfert dont proviendront les messages. Laissez '(none)' si vous utilisez l'en-tête de transfert ci-dessus." + }, + "description": "Choisissez comment faire correspondre les e-mails transférés.\n\n**Option 1 — En-tête de transfert** : Si votre service (ex. SimpleLogin) inclut l'expéditeur original dans un en-tête personnalisé, entrez ce nom d'en-tête. Mail and Packages l'utilisera pour faire correspondre automatiquement les adresses des transporteurs.\n\n**Option 2 — Liste d'adresses** : Entrez les adresses de transfert que votre service a attribuées à chaque transporteur, séparées par des virgules.", + "title": "Paramètres des e-mails transférés" + }, + "reconfig_forwarded_emails": { + "data": { + "forwarding_header": "En-tête de transfert (ex. X-SimpleLogin-Original-From)", + "forwarded_emails": "Adresses e-mail transférées" + }, + "data_description": { + "forwarding_header": "Si votre service de transfert inclut l'expéditeur original dans un en-tête, entrez le nom de l'en-tête ici. Cela a la priorité sur la liste d'adresses ci-dessous. Entrez '(none)' ou laissez vide pour utiliser la liste d'adresses à la place.", + "forwarded_emails": "Liste séparée par des virgules des adresses de transfert dont proviendront les messages. Laissez '(none)' si vous utilisez l'en-tête de transfert ci-dessus." + }, + "description": "Choisissez comment faire correspondre les e-mails transférés.\n\n**Option 1 — En-tête de transfert** : Si votre service (ex. SimpleLogin) inclut l'expéditeur original dans un en-tête personnalisé, entrez ce nom d'en-tête. Mail and Packages l'utilisera pour faire correspondre automatiquement les adresses des transporteurs.\n\n**Option 2 — Liste d'adresses** : Entrez les adresses de transfert que votre service a attribuées à chaque transporteur, séparées par des virgules.", + "title": "Paramètres des e-mails transférés" + }, + "imap_config": { + "description": "Veuillez entrer les informations de connexion de votre serveur de messagerie.", + "data": { + "host": "Hôte", + "password": "Mot de passe", + "port": "Port", + "username": "Nom d'utilisateur", + "verify_ssl": "Vérifier le certificat SSL", + "imap_security": "Sécurité IMAP" + }, + "title": "Courrier et colis (étape 1 sur 2)" + }, + "user": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reconfig_imap": { + "data": { + "host": "Hôte", + "password": "Mot de passe", + "port": "Port", + "username": "Nom d'utilisateur", + "imap_security": "Sécurité IMAP", + "verify_ssl": "Vérifier le certificat SSL" + }, + "description": "Veuillez entrer les informations de connexion de votre serveur de messagerie.", + "title": "Courrier et colis (étape 1 sur 2)" + }, + "reconfigure": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reauth_confirm": { + "description": "The authentication for your mail server has expired or is invalid. Please re-authenticate to continue.", + "data": { + "username": "Username", + "password": "Password" + }, + "title": "Re-authenticate Mail Server" + } + } + }, + "selector": { + "auth_type": { + "options": { + "password": "Password", + "oauth2_microsoft": "OAuth2 - Microsoft (Outlook/Exchange)", + "oauth2_google": "OAuth2 - Google (Gmail)" + } + } + } +} diff --git a/custom_components/mail_and_packages/translations/hu.json b/custom_components/mail_and_packages/translations/hu.json new file mode 100644 index 0000000..94ed0dc --- /dev/null +++ b/custom_components/mail_and_packages/translations/hu.json @@ -0,0 +1,203 @@ +{ + "config": { + "abort": { + "single_instance_allowed": "Csak a Levelek és a Csomagok egyetlen konfigurációja megengedett.", + "reconfigure_successful": "Újrakonfigurálás sikeres" + }, + "error": { + "cannot_connect": "Nem lehet csatlakozni vagy bejelentkezni az e-mail szerverhez. Kérjük, ellenőrizze a naplót a részletekért.", + "invalid_path": "Tárolja a képeket egy másik könyvtárban.", + "ffmpeg_not_found": "Az MP4 generálása ffmpeg-et igényel", + "amazon_domain": "Érvénytelen továbbítási e-mail cím.", + "file_not_found": "Képfájl nem található", + "invalid_email_format": "Érvénytelen e-mail cím formátum.", + "missing_forwarded_emails": "Hiányzó továbbított e-mail címek. Megadhatja a '(none)' értéket a beállítás törléséhez.", + "path_not_found": "Könyvtár nem található", + "invalid_auth": "Invalid authentication details. Please check your username and password.", + "ssl_error": "An SSL error occurred. Change SSL cipher list and try again." + }, + "step": { + "config_2": { + "data": { + "folder": "Mail mappa", + "resources": "Érzékelők listája", + "scan_interval": "Beolvasási időköz (perc)", + "image_path": "Kép elérési útja", + "gif_duration": "Kép időtartama (másodpercben)", + "image_security": "Véletlen képfájlnév", + "imap_timeout": "A kapcsolat időtúllépése előtti idő másodpercben (másodperc, minimum 10)", + "generate_mp4": "Készítsen mp4-et a képekből", + "allow_external": "Kép létrehozása értesítési alkalmazásokhoz", + "custom_img": "Használjon egyéni USPS 'nincs posta' képet?", + "amazon_custom_img": "Használjon egyéni Amazon 'nincs szállítás' képet?", + "ups_custom_img": "Használjon egyéni UPS 'nincs szállítás' képet?", + "walmart_custom_img": "Használjon egyéni Walmart 'nincs szállítás' képet?", + "fedex_custom_img": "Használjon egyéni FedEx 'nincs szállítás' képet?", + "generic_custom_img": "Használjon egyéni általános 'nincs szállítás' képet?", + "generate_grid": "Kép rács létrehozása LLM látásmodellekhez", + "allow_forwarded_emails": "Engedélyezze a továbbított e-maileket a szolgáltatás alapértelmezett értékén kívül (pl. no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Végezze el a konfigurációt az alábbiak testreszabásával az e-mail struktúrája és a Home Assistant telepítése alapján. \n\n A [Levelek és csomagok integrációja] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) opciókkal kapcsolatban tekintse meg a [konfiguráció, sablonok , és az automatizálás szakasz] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) a GitHubon.", + "title": "Levél és csomagok (2. lépés a 2-ből)" + }, + "config_3": { + "data": { + "custom_img_file": "Egyéni kép elérési útja: (pl.: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (ie: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (ie: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (ie: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (ie: images/my_custom_no_fedex.jpg)" + }, + "description": "Adja meg az egyéni \"nincs levél\" kép útvonalát és fájlnevét alább.\n\nPélda: images/custom_nomail.gif", + "title": "Levelek és csomagok (3. lépés a 3-ból)" + }, + "config_amazon": { + "data": { + "amazon_domain": "Amazon domain", + "amazon_fwds": "Amazon továbbított e-mail címek", + "amazon_days": "Napok visszamenőleg az Amazon e-mailek ellenőrzéséhez" + }, + "description": "Kérjük, adja meg azt a domain-t, ahonnan az Amazon e-maileket küld (pl.: amazon.com vagy amazon.de)\n\nHa az Amazon továbbított e-maileket használ, kérjük, válassza el minden címet vesszővel, vagy írja be, hogy (nincs), hogy törölje ezt a beállítást.\n\nMegjegyzés: ha az előző lépésben beállított egy továbbítási fejlécet, a továbbítási cím mező nem jelenik meg — a fejléc automatikusan kezeli az Amazon e-mailek egyeztetését.", + "title": "Amazon beállítások" + }, + "reconfig_2": { + "data": { + "folder": "Mail mappa", + "scan_interval": "Beolvasási időköz (perc)", + "image_path": "Kép elérési útja", + "gif_duration": "Kép időtartama (másodpercben)", + "image_security": "Véletlen képfájlnév", + "generate_mp4": "Készítsen mp4-et a képekből", + "resources": "Érzékelők listája", + "imap_timeout": "A kapcsolat időtúllépése előtti idő másodpercben (másodperc, minimum 10)", + "allow_external": "Kép létrehozása értesítési alkalmazásokhoz", + "custom_img": "Használjon egyéni USPS 'nincs posta' képet?", + "amazon_custom_img": "Használjon egyéni Amazon 'nincs szállítás' képet?", + "ups_custom_img": "Használjon egyéni UPS 'nincs szállítás' képet?", + "walmart_custom_img": "Használjon egyéni Walmart 'nincs szállítás' képet?", + "fedex_custom_img": "Használjon egyéni FedEx 'nincs szállítás' képet?", + "generic_custom_img": "Használjon egyéni általános 'nincs szállítás' képet?", + "generate_grid": "Kép rács létrehozása LLM látásmodellekhez", + "allow_forwarded_emails": "Engedélyezze a továbbított e-maileket a szolgáltatás alapértelmezett értékén kívül (pl. no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Fejezze be a konfigurációt a következők testreszabásával az e-mail struktúrája és a Home Assistant telepítése alapján.\n\nA [Mail and Packages integráció](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) lehetőségeinek részleteiről a GitHub-on található [konfiguráció, sablonok és automatizálások szekcióban](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) található információkat.\n\nHa Amazon továbbított e-maileket használ, kérjük, válassza el minden címet vesszővel, vagy írja be a (none) opciót, hogy törölje ezt a beállítást.", + "title": "Levél és csomagok (2. lépés a 2-ből)" + }, + "reconfig_3": { + "data": { + "custom_img_file": "Egyéni kép elérési útja: (pl.: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (i.e.: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (i.e.: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (i.e.: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (i.e.: images/my_custom_no_fedex.jpg)" + }, + "description": "Adja meg az egyéni \"nincs levél\" kép útvonalát és fájlnevét alább.\n\nPélda: images/custom_nomail.gif", + "title": "Levelek és csomagok (3. lépés a 3-ból)" + }, + "reconfig_amazon": { + "data": { + "amazon_domain": "Amazon domain", + "amazon_fwds": "Amazon továbbított e-mail címek", + "amazon_days": "Napok visszamenőleg az Amazon e-mailek ellenőrzéséhez" + }, + "description": "Kérjük, adja meg azt a domain-t, ahonnan az Amazon e-maileket küld (pl.: amazon.com vagy amazon.de)\n\nHa az Amazon továbbított e-maileket használ, kérjük, válassza el minden címet vesszővel, vagy írja be, hogy (nincs), hogy törölje ezt a beállítást.\n\nMegjegyzés: ha az előző lépésben beállított egy továbbítási fejlécet, a továbbítási cím mező nem jelenik meg — a fejléc automatikusan kezeli az Amazon e-mailek egyeztetését.", + "title": "Amazon beállítások" + }, + "config_storage": { + "data": { + "storage": "Képek tárolására szolgáló könyvtár" + }, + "description": "Kérjük, adja meg azt a könyvtárat, ahová a képeit szeretné tárolni.\nAz alapértelmezett automatikusan kitöltődik.", + "title": "Képtárolási hely" + }, + "reconfig_storage": { + "data": { + "storage": "Képek tárolására szolgáló könyvtár" + }, + "description": "Kérjük, adja meg azt a könyvtárat, ahová a képeit szeretné tárolni.\nAz alapértelmezett automatikusan kitöltődik.", + "title": "Képtárolási hely" + }, + "config_forwarded_emails": { + "data": { + "forwarding_header": "Továbbítási fejléc (pl. X-SimpleLogin-Original-From)", + "forwarded_emails": "Továbbított e-mail címek" + }, + "data_description": { + "forwarding_header": "Ha a továbbítási szolgáltatása tartalmazza az eredeti feladót egy fejlécben, adja meg itt a fejléc nevét. Ez elsőbbséget élvez az alábbi címlistával szemben. Írja be a '(none)' értéket, vagy hagyja üresen a címlista használatához.", + "forwarded_emails": "Vesszővel elválasztott lista a továbbítási címekről, ahonnan az üzenetek érkeznek. Hagyja '(none)' értéken, ha a fenti továbbítási fejlécet használja." + }, + "description": "Válassza ki, hogyan egyezzen meg a továbbított e-mailekkel.\n\n**1. lehetőség — Továbbítási fejléc**: Ha a szolgáltatása (pl. SimpleLogin) tartalmazza az eredeti feladót egy egyéni fejlécben, adja meg azt a fejlécnevet. A Mail and Packages ezt fogja használni a szállítói címek automatikus egyeztetéséhez.\n\n**2. lehetőség — Címlista**: Adja meg a továbbítási címeket, amelyeket a szolgáltatása minden szállítóhoz hozzárendelt, vesszővel elválasztva.", + "title": "Továbbított e-mailek beállításai" + }, + "reconfig_forwarded_emails": { + "data": { + "forwarding_header": "Továbbítási fejléc (pl. X-SimpleLogin-Original-From)", + "forwarded_emails": "Továbbított e-mail címek" + }, + "data_description": { + "forwarding_header": "Ha a továbbítási szolgáltatása tartalmazza az eredeti feladót egy fejlécben, adja meg itt a fejléc nevét. Ez elsőbbséget élvez az alábbi címlistával szemben. Írja be a '(none)' értéket, vagy hagyja üresen a címlista használatához.", + "forwarded_emails": "Vesszővel elválasztott lista a továbbítási címekről, ahonnan az üzenetek érkeznek. Hagyja '(none)' értéken, ha a fenti továbbítási fejlécet használja." + }, + "description": "Válassza ki, hogyan egyezzen meg a továbbított e-mailekkel.\n\n**1. lehetőség — Továbbítási fejléc**: Ha a szolgáltatása (pl. SimpleLogin) tartalmazza az eredeti feladót egy egyéni fejlécben, adja meg azt a fejlécnevet. A Mail and Packages ezt fogja használni a szállítói címek automatikus egyeztetéséhez.\n\n**2. lehetőség — Címlista**: Adja meg a továbbítási címeket, amelyeket a szolgáltatása minden szállítóhoz hozzárendelt, vesszővel elválasztva.", + "title": "Továbbított e-mailek beállításai" + }, + "imap_config": { + "description": "Kérjük, adja meg a levelezőszervere kapcsolati adatait.", + "data": { + "host": "Házigazda", + "password": "Jelszó", + "port": "Kikötő", + "username": "Felhasználónév", + "verify_ssl": "Ellenőrizze az SSL tanúsítványt", + "imap_security": "IMAP Biztonság" + }, + "title": "Levél és csomagok (1. lépés a 2-ből)" + }, + "user": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reconfig_imap": { + "data": { + "host": "Házigazda", + "password": "Jelszó", + "port": "Kikötő", + "username": "Felhasználónév", + "imap_security": "IMAP Biztonság", + "verify_ssl": "Ellenőrizze az SSL tanúsítványt" + }, + "description": "Kérjük, adja meg a levelezőszervere kapcsolati adatait.", + "title": "Levél és csomagok (1. lépés a 2-ből)" + }, + "reconfigure": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reauth_confirm": { + "description": "The authentication for your mail server has expired or is invalid. Please re-authenticate to continue.", + "data": { + "username": "Username", + "password": "Password" + }, + "title": "Re-authenticate Mail Server" + } + } + }, + "selector": { + "auth_type": { + "options": { + "password": "Password", + "oauth2_microsoft": "OAuth2 - Microsoft (Outlook/Exchange)", + "oauth2_google": "OAuth2 - Google (Gmail)" + } + } + } +} diff --git a/custom_components/mail_and_packages/translations/it.json b/custom_components/mail_and_packages/translations/it.json new file mode 100644 index 0000000..6651e26 --- /dev/null +++ b/custom_components/mail_and_packages/translations/it.json @@ -0,0 +1,203 @@ +{ + "config": { + "abort": { + "single_instance_allowed": "È consentita una sola configurazione di posta e pacchetti.", + "reconfigure_successful": "Riconfigurazione Riuscita" + }, + "error": { + "cannot_connect": "Impossibile connettersi o accedere al server di posta. Si prega di controllare il registro per i dettagli.", + "invalid_path": "Conservare le immagini in un'altra directory.", + "ffmpeg_not_found": "Generare MP4 richiede ffmpeg", + "amazon_domain": "Indirizzo email di inoltro non valido.", + "file_not_found": "File immagine non trovato", + "invalid_email_format": "Formato dell'indirizzo email non valido.", + "missing_forwarded_emails": "Indirizzi email inoltrati mancanti. Puoi inserire '(none)' per cancellare questa impostazione.", + "path_not_found": "Directory non trovato", + "invalid_auth": "Invalid authentication details. Please check your username and password.", + "ssl_error": "An SSL error occurred. Change SSL cipher list and try again." + }, + "step": { + "config_2": { + "data": { + "folder": "Cartella posta", + "resources": "Elenco dei sensori", + "scan_interval": "Intervallo di scansione (minuti)", + "image_path": "Percorso immagine", + "gif_duration": "Durata immagine (secondi)", + "image_security": "Nome file immagine casuale", + "imap_timeout": "Tempo in secondi prima del timeout di connessione (secondi, minimo 10)", + "generate_mp4": "Crea mp4 dalle immagini", + "allow_external": "Crea immagine per le app di notifica", + "custom_img": "Usare l'immagine personalizzata USPS 'nessuna posta'?", + "amazon_custom_img": "Usare l'immagine personalizzata Amazon 'nessuna consegna'?", + "ups_custom_img": "Usare l'immagine personalizzata UPS 'nessuna consegna'?", + "walmart_custom_img": "Usare l'immagine personalizzata Walmart 'nessuna consegna'?", + "fedex_custom_img": "Usare l'immagine personalizzata FedEx 'nessuna consegna'?", + "generic_custom_img": "Usare l'immagine personalizzata generica 'nessuna consegna'?", + "generate_grid": "Crea una griglia di immagini per i modelli di visione LLM", + "allow_forwarded_emails": "Consenti email inoltrate oltre al valore predefinito di un servizio (ad es. no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Termina la configurazione personalizzando quanto segue in base alla struttura della tua e-mail e all'installazione di Home Assistant. \n\n Per i dettagli sulle opzioni [Integrazione posta e pacchetti] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) rivedere le [configurazione, modelli e sezione automazioni] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) su GitHub.", + "title": "Posta e pacchi (passaggio 2 di 2)" + }, + "config_3": { + "data": { + "custom_img_file": "Percorso per l'immagine personalizzata: (es: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (ie: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (ie: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (ie: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (ie: images/my_custom_no_fedex.jpg)" + }, + "description": "Inserisci il percorso e il nome del file per la tua immagine personalizzata di nessuna mail qui sotto.\n\nEsempio: images/custom_nomail.gif", + "title": "Posta e Pacchetti (Passaggio 3 di 3)" + }, + "config_amazon": { + "data": { + "amazon_domain": "Dominio Amazon", + "amazon_fwds": "Amazon ha inoltrato gli indirizzi email", + "amazon_days": "Giorni precedenti da controllare per le email di Amazon" + }, + "description": "Inserisci il dominio da cui Amazon invia le email (ad esempio: amazon.com o amazon.de)\n\nSe stai utilizzando email inoltrate da Amazon, separa ogni indirizzo con una virgola o inserisci (nessuno) per cancellare questa impostazione.\n\nNota: se hai configurato un'intestazione di inoltro nel passaggio precedente, il campo dell'indirizzo di inoltro non apparirà — l'intestazione gestisce automaticamente la corrispondenza delle email Amazon.", + "title": "Impostazioni Amazon" + }, + "reconfig_2": { + "data": { + "folder": "Cartella posta", + "scan_interval": "Intervallo di scansione (minuti)", + "image_path": "Percorso immagine", + "gif_duration": "Durata immagine (secondi)", + "image_security": "Nome file immagine casuale", + "generate_mp4": "Crea mp4 dalle immagini", + "resources": "Elenco dei sensori", + "imap_timeout": "Tempo in secondi prima del timeout di connessione (secondi, minimo 10)", + "allow_external": "Crea immagine per le app di notifica", + "custom_img": "Usare l'immagine personalizzata USPS 'nessuna posta'?", + "amazon_custom_img": "Usare l'immagine personalizzata Amazon 'nessuna consegna'?", + "ups_custom_img": "Usare l'immagine personalizzata UPS 'nessuna consegna'?", + "walmart_custom_img": "Usare l'immagine personalizzata Walmart 'nessuna consegna'?", + "fedex_custom_img": "Usare l'immagine personalizzata FedEx 'nessuna consegna'?", + "generic_custom_img": "Usare l'immagine personalizzata generica 'nessuna consegna'?", + "generate_grid": "Crea una griglia di immagini per i modelli di visione LLM", + "allow_forwarded_emails": "Consenti email inoltrate oltre al valore predefinito di un servizio (ad es. no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Termina la configurazione personalizzando quanto segue in base alla struttura della tua email e all'installazione di Home Assistant.\n\nPer i dettagli sulle opzioni di [integrazione Mail e Pacchetti](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) consulta la [sezione configurazione, modelli e automazioni](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) su GitHub.\n\nSe utilizzi email inoltrate da Amazon, separa ogni indirizzo con una virgola o inserisci (nessuno) per cancellare questa impostazione.", + "title": "Posta e pacchi (passaggio 2 di 2)" + }, + "reconfig_3": { + "data": { + "custom_img_file": "Percorso per l'immagine personalizzata: (ad es.: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (i.e.: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (i.e.: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (i.e.: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (i.e.: images/my_custom_no_fedex.jpg)" + }, + "description": "Inserisci il percorso e il nome del file per la tua immagine personalizzata di nessuna mail qui sotto.\n\nEsempio: images/custom_nomail.gif", + "title": "Posta e Pacchetti (Passaggio 3 di 3)" + }, + "reconfig_amazon": { + "data": { + "amazon_domain": "Dominio Amazon", + "amazon_fwds": "Amazon ha inoltrato gli indirizzi email", + "amazon_days": "Giorni precedenti da controllare per le email di Amazon" + }, + "description": "Inserisci il dominio da cui Amazon invia le email (ad esempio: amazon.com o amazon.de)\n\nSe stai utilizzando email inoltrate da Amazon, separa ogni indirizzo con una virgola o inserisci (nessuno) per cancellare questa impostazione.\n\nNota: se hai configurato un'intestazione di inoltro nel passaggio precedente, il campo dell'indirizzo di inoltro non apparirà — l'intestazione gestisce automaticamente la corrispondenza delle email Amazon.", + "title": "Impostazioni Amazon" + }, + "config_storage": { + "data": { + "storage": "Cartella per memorizzare le immagini" + }, + "description": "Inserisci la directory in cui desideri che le tue immagini vengano memorizzate.\nIl valore predefinito viene popolato automaticamente.", + "title": "Posizione di archiviazione delle immagini" + }, + "reconfig_storage": { + "data": { + "storage": "Cartella per memorizzare le immagini" + }, + "description": "Inserisci la directory in cui desideri che le tue immagini vengano memorizzate.\nIl valore predefinito viene popolato automaticamente.", + "title": "Posizione di archiviazione delle immagini" + }, + "config_forwarded_emails": { + "data": { + "forwarding_header": "Intestazione di inoltro (es. X-SimpleLogin-Original-From)", + "forwarded_emails": "Indirizzi email inoltrati" + }, + "data_description": { + "forwarding_header": "Se il tuo servizio di inoltro include il mittente originale in un'intestazione, inserisci qui il nome dell'intestazione. Questo ha la precedenza sull'elenco di indirizzi seguente. Inserisci '(none)' o lascia vuoto per usare l'elenco di indirizzi.", + "forwarded_emails": "Elenco separato da virgole degli indirizzi di inoltro da cui arriveranno i messaggi. Lascia '(none)' se stai usando l'intestazione di inoltro sopra." + }, + "description": "Scegli come abbinare le email inoltrate.\n\n**Opzione 1 — Intestazione di inoltro**: Se il tuo servizio (es. SimpleLogin) include il mittente originale in un'intestazione personalizzata, inserisci il nome di quell'intestazione. Mail and Packages lo utilizzerà per abbinare automaticamente gli indirizzi dei corrieri.\n\n**Opzione 2 — Elenco di indirizzi**: Inserisci gli indirizzi di inoltro che il tuo servizio ha assegnato a ciascun corriere, separati da virgole.", + "title": "Impostazioni email inoltrate" + }, + "reconfig_forwarded_emails": { + "data": { + "forwarding_header": "Intestazione di inoltro (es. X-SimpleLogin-Original-From)", + "forwarded_emails": "Indirizzi email inoltrati" + }, + "data_description": { + "forwarding_header": "Se il tuo servizio di inoltro include il mittente originale in un'intestazione, inserisci qui il nome dell'intestazione. Questo ha la precedenza sull'elenco di indirizzi seguente. Inserisci '(none)' o lascia vuoto per usare l'elenco di indirizzi.", + "forwarded_emails": "Elenco separato da virgole degli indirizzi di inoltro da cui arriveranno i messaggi. Lascia '(none)' se stai usando l'intestazione di inoltro sopra." + }, + "description": "Scegli come abbinare le email inoltrate.\n\n**Opzione 1 — Intestazione di inoltro**: Se il tuo servizio (es. SimpleLogin) include il mittente originale in un'intestazione personalizzata, inserisci il nome di quell'intestazione. Mail and Packages lo utilizzerà per abbinare automaticamente gli indirizzi dei corrieri.\n\n**Opzione 2 — Elenco di indirizzi**: Inserisci gli indirizzi di inoltro che il tuo servizio ha assegnato a ciascun corriere, separati da virgole.", + "title": "Impostazioni email inoltrate" + }, + "imap_config": { + "description": "Inserisci le informazioni di connessione del tuo server di posta.", + "data": { + "host": "Ospite", + "password": "Parola d'ordine", + "port": "Porta", + "username": "Nome utente", + "verify_ssl": "Verifica Certificato SSL", + "imap_security": "Sicurezza IMAP" + }, + "title": "Posta e pacchi (passaggio 1 di 2)" + }, + "user": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reconfig_imap": { + "data": { + "host": "Ospite", + "password": "Parola d'ordine", + "port": "Porta", + "username": "Nome utente", + "imap_security": "Sicurezza IMAP", + "verify_ssl": "Verifica Certificato SSL" + }, + "description": "Inserisci le informazioni di connessione del tuo server di posta.", + "title": "Posta e pacchi (passaggio 1 di 2)" + }, + "reconfigure": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reauth_confirm": { + "description": "The authentication for your mail server has expired or is invalid. Please re-authenticate to continue.", + "data": { + "username": "Username", + "password": "Password" + }, + "title": "Re-authenticate Mail Server" + } + } + }, + "selector": { + "auth_type": { + "options": { + "password": "Password", + "oauth2_microsoft": "OAuth2 - Microsoft (Outlook/Exchange)", + "oauth2_google": "OAuth2 - Google (Gmail)" + } + } + } +} diff --git a/custom_components/mail_and_packages/translations/ko.json b/custom_components/mail_and_packages/translations/ko.json new file mode 100644 index 0000000..59f2e93 --- /dev/null +++ b/custom_components/mail_and_packages/translations/ko.json @@ -0,0 +1,203 @@ +{ + "config": { + "abort": { + "single_instance_allowed": "메일 및 패키지의 단일 구성 만 허용됩니다.", + "reconfigure_successful": "재구성 성공" + }, + "error": { + "cannot_connect": "메일 서버에 연결하거나 로그인 할 수 없습니다. 자세한 내용은 로그를 확인하십시오.", + "invalid_path": "이미지를 다른 디렉토리에 저장하십시오.", + "ffmpeg_not_found": "MP4 생성은 ffmpeg가 필요합니다", + "amazon_domain": "잘못된 전달 이메일 주소입니다.", + "file_not_found": "이미지 파일을 찾을 수 없습니다", + "invalid_email_format": "잘못된 이메일 주소 형식입니다.", + "missing_forwarded_emails": "전달된 이메일 주소가 없습니다. 이 설정을 지우려면 '(none)'을 입력할 수 있습니다.", + "path_not_found": "디렉토리를 찾을 수 없습니다", + "invalid_auth": "Invalid authentication details. Please check your username and password.", + "ssl_error": "An SSL error occurred. Change SSL cipher list and try again." + }, + "step": { + "config_2": { + "data": { + "folder": "메일 폴더", + "resources": "센서 목록", + "scan_interval": "스캔 간격 (분)", + "image_path": "이미지 경로", + "gif_duration": "이미지 지속 시간 (초)", + "image_security": "임의의 이미지 파일 이름", + "imap_timeout": "연결 시간 초과 전 시간(초, 최소 10)", + "generate_mp4": "이미지에서 mp4 만들기", + "allow_external": "알림 앱용 이미지 생성", + "custom_img": "사용자 정의 USPS '우편 없음' 이미지를 사용하시겠습니까?", + "amazon_custom_img": "사용자 정의 Amazon '배송 없음' 이미지를 사용하시겠습니까?", + "ups_custom_img": "사용자 정의 UPS '배송 없음' 이미지를 사용하시겠습니까?", + "walmart_custom_img": "사용자 정의 Walmart '배송 없음' 이미지를 사용하시겠습니까?", + "fedex_custom_img": "사용자 정의 FedEx '배송 없음' 이미지를 사용하시겠습니까?", + "generic_custom_img": "사용자 정의 일반 '배송 없음' 이미지를 사용하시겠습니까?", + "generate_grid": "LLM 비전 모델을 위한 이미지 그리드 생성", + "allow_forwarded_emails": "서비스 기본값 외에 전달된 이메일 허용 (예: no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "이메일 구조 및 Home Assistant 설치에 따라 다음을 사용자 정의하여 구성을 완료하십시오. \n\n [메일 및 패키지 통합] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) 옵션에 대한 자세한 내용은 [구성, 템플릿 및 자동화 섹션] (https://github.com/moralmunky/Home-Assistant-Mail-and-Packages/wiki/Configuration-and-Email-Settings#configuration)", + "title": "메일 및 패키지 (2/2 단계)" + }, + "config_3": { + "data": { + "custom_img_file": "사용자 정의 이미지 경로: (예: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (ie: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (ie: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (ie: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (ie: images/my_custom_no_fedex.jpg)" + }, + "description": "아래에 사용자 정의 '메일 없음' 이미지의 경로와 파일 이름을 입력하세요.\n\n예시: images/custom_nomail.gif", + "title": "우편 및 패키지 (3단계 중 3단계)" + }, + "config_amazon": { + "data": { + "amazon_domain": "아마존 도메인", + "amazon_fwds": "Amazon이 전달한 이메일 주소", + "amazon_days": "Amazon 이메일을 확인하기 위해 돌아가야 할 날짜" + }, + "description": "Amazon이 이메일을 보내는 도메인을 입력해 주세요 (예: amazon.com 또는 amazon.de)\n\nAmazon에서 전달된 이메일을 사용하는 경우 각 주소를 쉼표로 구분하거나 이 설정을 지우려면 (none)을 입력하세요.\n\n참고: 이전 단계에서 전달 헤더를 구성한 경우 전달 주소 필드가 표시되지 않습니다 — 헤더가 Amazon 이메일 매칭을 자동으로 처리합니다.", + "title": "아마존 설정" + }, + "reconfig_2": { + "data": { + "folder": "메일 폴더", + "scan_interval": "스캔 간격 (분)", + "image_path": "이미지 경로", + "gif_duration": "이미지 지속 시간 (초)", + "image_security": "임의의 이미지 파일 이름", + "generate_mp4": "이미지에서 mp4 만들기", + "resources": "센서 목록", + "imap_timeout": "연결 시간 초과 전 시간(초, 최소 10)", + "allow_external": "알림 앱용 이미지 생성", + "custom_img": "사용자 정의 USPS '우편 없음' 이미지를 사용하시겠습니까?", + "amazon_custom_img": "사용자 정의 Amazon '배송 없음' 이미지를 사용하시겠습니까?", + "ups_custom_img": "사용자 정의 UPS '배송 없음' 이미지를 사용하시겠습니까?", + "walmart_custom_img": "사용자 정의 Walmart '배송 없음' 이미지를 사용하시겠습니까?", + "fedex_custom_img": "사용자 정의 FedEx '배송 없음' 이미지를 사용하시겠습니까?", + "generic_custom_img": "사용자 정의 일반 '배송 없음' 이미지를 사용하시겠습니까?", + "generate_grid": "LLM 비전 모델을 위한 이미지 그리드 생성", + "allow_forwarded_emails": "서비스 기본값 외에 전달된 이메일 허용 (예: no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "이메일 구조와 Home Assistant 설치에 따라 다음을 사용자 정의하여 구성을 완료하십시오.\n\n[Mail and Packages 통합](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) 옵션에 대한 자세한 내용은 GitHub의 [구성, 템플릿, 자동화 섹션](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration)을 참조하십시오.\n\nAmazon에서 전달된 이메일을 사용하는 경우 각 주소를 쉼표로 구분하거나 이 설정을 지우려면 (none)을 입력하십시오.", + "title": "메일 및 패키지 (2/2 단계)" + }, + "reconfig_3": { + "data": { + "custom_img_file": "사용자 정의 이미지 경로: (예: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (i.e.: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (i.e.: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (i.e.: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (i.e.: images/my_custom_no_fedex.jpg)" + }, + "description": "아래에 사용자 정의 '메일 없음' 이미지의 경로와 파일 이름을 입력하세요.\n\n예시: images/custom_nomail.gif", + "title": "우편 및 패키지 (3단계 중 3단계)" + }, + "reconfig_amazon": { + "data": { + "amazon_domain": "아마존 도메인", + "amazon_fwds": "Amazon이 전달한 이메일 주소", + "amazon_days": "Amazon 이메일을 확인하기 위해 돌아가야 할 날짜" + }, + "description": "Amazon이 이메일을 보내는 도메인을 입력해 주세요 (예: amazon.com 또는 amazon.de)\n\nAmazon에서 전달된 이메일을 사용하는 경우 각 주소를 쉼표로 구분하거나 이 설정을 지우려면 (none)을 입력하세요.\n\n참고: 이전 단계에서 전달 헤더를 구성한 경우 전달 주소 필드가 표시되지 않습니다 — 헤더가 Amazon 이메일 매칭을 자동으로 처리합니다.", + "title": "아마존 설정" + }, + "config_storage": { + "data": { + "storage": "이미지를 저장할 디렉토리" + }, + "description": "이미지를 저장할 디렉토리를 입력해 주세요.\n기본값은 자동으로 채워집니다.", + "title": "이미지 저장 위치" + }, + "reconfig_storage": { + "data": { + "storage": "이미지를 저장할 디렉토리" + }, + "description": "이미지를 저장할 디렉토리를 입력해 주세요.\n기본값은 자동으로 채워집니다.", + "title": "이미지 저장 위치" + }, + "config_forwarded_emails": { + "data": { + "forwarding_header": "전달 헤더 (예: X-SimpleLogin-Original-From)", + "forwarded_emails": "전달된 이메일 주소" + }, + "data_description": { + "forwarding_header": "전달 서비스가 헤더에 원래 발신자를 포함하는 경우, 여기에 헤더 이름을 입력하세요. 이는 아래 주소 목록보다 우선합니다. 주소 목록을 사용하려면 '(none)'을 입력하거나 비워두세요.", + "forwarded_emails": "메시지가 도착할 전달 주소의 쉼표로 구분된 목록입니다. 위의 전달 헤더를 사용하는 경우 '(none)'으로 두세요." + }, + "description": "전달된 이메일을 일치시키는 방법을 선택하세요.\n\n**옵션 1 — 전달 헤더**: 서비스(예: SimpleLogin)가 사용자 지정 헤더에 원래 발신자를 포함하는 경우, 해당 헤더 이름을 입력하세요. Mail and Packages가 이를 사용하여 배송사 주소를 자동으로 일치시킵니다.\n\n**옵션 2 — 주소 목록**: 서비스가 각 배송사에 할당한 전달 주소를 쉼표로 구분하여 입력하세요.", + "title": "전달 이메일 설정" + }, + "reconfig_forwarded_emails": { + "data": { + "forwarding_header": "전달 헤더 (예: X-SimpleLogin-Original-From)", + "forwarded_emails": "전달된 이메일 주소" + }, + "data_description": { + "forwarding_header": "전달 서비스가 헤더에 원래 발신자를 포함하는 경우, 여기에 헤더 이름을 입력하세요. 이는 아래 주소 목록보다 우선합니다. 주소 목록을 사용하려면 '(none)'을 입력하거나 비워두세요.", + "forwarded_emails": "메시지가 도착할 전달 주소의 쉼표로 구분된 목록입니다. 위의 전달 헤더를 사용하는 경우 '(none)'으로 두세요." + }, + "description": "전달된 이메일을 일치시키는 방법을 선택하세요.\n\n**옵션 1 — 전달 헤더**: 서비스(예: SimpleLogin)가 사용자 지정 헤더에 원래 발신자를 포함하는 경우, 해당 헤더 이름을 입력하세요. Mail and Packages가 이를 사용하여 배송사 주소를 자동으로 일치시킵니다.\n\n**옵션 2 — 주소 목록**: 서비스가 각 배송사에 할당한 전달 주소를 쉼표로 구분하여 입력하세요.", + "title": "전달 이메일 설정" + }, + "imap_config": { + "description": "메일 서버의 연결 정보를 입력해 주세요.", + "data": { + "host": "주최자", + "password": "암호", + "port": "포트", + "username": "사용자 이름", + "verify_ssl": "SSL 인증서 확인", + "imap_security": "IMAP 보안" + }, + "title": "메일 및 패키지 (1/2 단계)" + }, + "user": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reconfig_imap": { + "data": { + "host": "주최자", + "password": "암호", + "port": "포트", + "username": "사용자 이름", + "imap_security": "IMAP 보안", + "verify_ssl": "SSL 인증서 확인" + }, + "description": "메일 서버의 연결 정보를 입력해 주세요.", + "title": "메일 및 패키지 (1/2 단계)" + }, + "reconfigure": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reauth_confirm": { + "description": "The authentication for your mail server has expired or is invalid. Please re-authenticate to continue.", + "data": { + "username": "Username", + "password": "Password" + }, + "title": "Re-authenticate Mail Server" + } + } + }, + "selector": { + "auth_type": { + "options": { + "password": "Password", + "oauth2_microsoft": "OAuth2 - Microsoft (Outlook/Exchange)", + "oauth2_google": "OAuth2 - Google (Gmail)" + } + } + } +} diff --git a/custom_components/mail_and_packages/translations/nl.json b/custom_components/mail_and_packages/translations/nl.json new file mode 100644 index 0000000..768ab51 --- /dev/null +++ b/custom_components/mail_and_packages/translations/nl.json @@ -0,0 +1,203 @@ +{ + "config": { + "abort": { + "single_instance_allowed": "Slechts een enkele configuratie van Mail en pakketten is toegestaan.", + "reconfigure_successful": "Herconfiguratie succesvol" + }, + "error": { + "cannot_connect": "Kan geen verbinding maken met of inloggen op de mailserver. Controleer het logboek voor details.", + "invalid_path": "Bewaar de afbeeldingen in een andere map.", + "ffmpeg_not_found": "MP4 genereren vereist ffmpeg", + "amazon_domain": "Ongeldig doorstuur e-mailadres.", + "file_not_found": "Afbeeldingsbestand niet gevonden", + "invalid_email_format": "Ongeldig e-mailadres formaat.", + "missing_forwarded_emails": "Ontbrekende doorgestuurde e-mailadressen. U kunt '(none)' invoeren om deze instelling te wissen.", + "path_not_found": "Map niet gevonden", + "invalid_auth": "Invalid authentication details. Please check your username and password.", + "ssl_error": "An SSL error occurred. Change SSL cipher list and try again." + }, + "step": { + "config_2": { + "data": { + "folder": "E-mailmap", + "resources": "Lijst van sensoren", + "scan_interval": "Scaninterval (minuten)", + "image_path": "Afbeeldingspad", + "gif_duration": "Beeldduur (seconden)", + "image_security": "Bestandsnaam willekeurige afbeelding", + "imap_timeout": "Tijd in seconden voordat de verbinding verloopt (seconden, minimaal 10)", + "generate_mp4": "Maak mp4 van afbeeldingen", + "allow_external": "Maak afbeelding voor meldingsapps", + "custom_img": "Gebruik aangepaste USPS 'geen post' afbeelding?", + "amazon_custom_img": "Gebruik aangepaste Amazon 'geen levering' afbeelding?", + "ups_custom_img": "Gebruik aangepaste UPS 'geen levering' afbeelding?", + "walmart_custom_img": "Gebruik aangepaste Walmart 'geen levering' afbeelding?", + "fedex_custom_img": "Gebruik aangepaste FedEx 'geen levering' afbeelding?", + "generic_custom_img": "Gebruik aangepaste generieke 'geen levering' afbeelding?", + "generate_grid": "Maak een afbeeldingsraster voor LLM-visiemodellen", + "allow_forwarded_emails": "Doorgestuurde e-mails toestaan naast de standaardwaarde van een service (bijv. no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Voltooi de configuratie door het volgende aan te passen op basis van uw e-mailstructuur en Home Assistant-installatie. \n\n Voor meer informatie over de [E-mail en pakketten integratie] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) opties bekijk de [configuratie, sjablonen , en automatisering sectie] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) op GitHub.", + "title": "Mail en pakketten (stap 2 van 2)" + }, + "config_3": { + "data": { + "custom_img_file": "Pad naar aangepaste afbeelding: (bijv: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (ie: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (ie: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (ie: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (ie: images/my_custom_no_fedex.jpg)" + }, + "description": "Voer hieronder het pad en de bestandsnaam in voor uw aangepaste afbeelding voor geen mail.\n\nVoorbeeld: images/custom_nomail.gif", + "title": "Mail en Pakketten (Stap 3 van 3)" + }, + "config_amazon": { + "data": { + "amazon_domain": "Amazon domein", + "amazon_fwds": "Amazon stuurde e-mailadressen door", + "amazon_days": "Dagen terug om te controleren op Amazon e-mails" + }, + "description": "Voer het domein in waarvan Amazon e-mails verstuurt (bijv: amazon.com of amazon.de)\n\nAls u doorgestuurde e-mails van Amazon gebruikt, scheid dan elk adres met een komma of voer (geen) in om deze instelling te wissen.\n\nOpmerking: als u in de vorige stap een doorstuurheader hebt geconfigureerd, verschijnt het doorstuuradresveld niet — de header verwerkt de Amazon e-mailkoppeling automatisch.", + "title": "Amazon Instellingen" + }, + "reconfig_2": { + "data": { + "folder": "E-mailmap", + "scan_interval": "Scaninterval (minuten)", + "image_path": "Afbeeldingspad", + "gif_duration": "Beeldduur (seconden)", + "image_security": "Bestandsnaam willekeurige afbeelding", + "generate_mp4": "Maak mp4 van afbeeldingen", + "resources": "Lijst van sensoren", + "imap_timeout": "Tijd in seconden voordat de verbinding verloopt (seconden, minimaal 10)", + "allow_external": "Maak afbeelding voor meldingsapps", + "custom_img": "Gebruik aangepaste USPS 'geen post' afbeelding?", + "amazon_custom_img": "Gebruik aangepaste Amazon 'geen levering' afbeelding?", + "ups_custom_img": "Gebruik aangepaste UPS 'geen levering' afbeelding?", + "walmart_custom_img": "Gebruik aangepaste Walmart 'geen levering' afbeelding?", + "fedex_custom_img": "Gebruik aangepaste FedEx 'geen levering' afbeelding?", + "generic_custom_img": "Gebruik aangepaste generieke 'geen levering' afbeelding?", + "generate_grid": "Maak een afbeeldingsraster voor LLM-visiemodellen", + "allow_forwarded_emails": "Doorgestuurde e-mails toestaan naast de standaardwaarde van een service (bijv. no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Rond de configuratie af door het volgende aan te passen op basis van uw e-mailstructuur en Home Assistant-installatie.\n\nVoor details over de [Mail en Packages integratie](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) opties, bekijk de [configuratie, sjablonen en automatiseringen sectie](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) op GitHub.\n\nAls u doorgestuurde e-mails van Amazon gebruikt, scheid dan elk adres met een komma of voer (geen) in om deze instelling te wissen.", + "title": "Mail en pakketten (stap 2 van 2)" + }, + "reconfig_3": { + "data": { + "custom_img_file": "Pad naar aangepaste afbeelding: (bijv.: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (i.e.: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (i.e.: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (i.e.: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (i.e.: images/my_custom_no_fedex.jpg)" + }, + "description": "Voer hieronder het pad en de bestandsnaam in voor uw aangepaste afbeelding voor geen mail.\n\nVoorbeeld: images/custom_nomail.gif", + "title": "Mail en Pakketten (Stap 3 van 3)" + }, + "reconfig_amazon": { + "data": { + "amazon_domain": "Amazon domein", + "amazon_fwds": "Amazon stuurde e-mailadressen door", + "amazon_days": "Dagen terug om te controleren op Amazon e-mails" + }, + "description": "Voer het domein in waarvan Amazon e-mails verstuurt (bijv: amazon.com of amazon.de)\n\nAls u doorgestuurde e-mails van Amazon gebruikt, scheid dan elk adres met een komma of voer (geen) in om deze instelling te wissen.\n\nOpmerking: als u in de vorige stap een doorstuurheader hebt geconfigureerd, verschijnt het doorstuuradresveld niet — de header verwerkt de Amazon e-mailkoppeling automatisch.", + "title": "Amazon Instellingen" + }, + "config_storage": { + "data": { + "storage": "Map om afbeeldingen op te slaan" + }, + "description": "Voer de map in waar u uw afbeeldingen wilt opslaan.\nDe standaard is automatisch ingevuld.", + "title": "Locatie voor afbeeldingsopslag" + }, + "reconfig_storage": { + "data": { + "storage": "Map om afbeeldingen op te slaan" + }, + "description": "Voer de map in waar u uw afbeeldingen wilt opslaan.\nDe standaard is automatisch ingevuld.", + "title": "Locatie voor afbeeldingsopslag" + }, + "config_forwarded_emails": { + "data": { + "forwarding_header": "Doorstuurkoptekst (bijv. X-SimpleLogin-Original-From)", + "forwarded_emails": "Doorgestuurde e-mailadressen" + }, + "data_description": { + "forwarding_header": "Als uw doorstuurdienst de oorspronkelijke afzender in een koptekst opneemt, voer dan hier de naam van de koptekst in. Dit heeft voorrang op de onderstaande adreslijst. Voer '(none)' in of laat leeg om de adreslijst te gebruiken.", + "forwarded_emails": "Kommagescheiden lijst van doorstuuradressen waarvan berichten zullen aankomen. Laat '(none)' staan als u de bovenstaande doorstuurkoptekst gebruikt." + }, + "description": "Kies hoe doorgestuurde e-mails worden gekoppeld.\n\n**Optie 1 — Doorstuurkoptekst**: Als uw dienst (bijv. SimpleLogin) de oorspronkelijke afzender in een aangepaste koptekst opneemt, voer dan die koptekstnaam in. Mail and Packages zal die gebruiken om vervoerdersadressen automatisch te koppelen.\n\n**Optie 2 — Adreslijst**: Voer de doorstuuradressen in die uw dienst aan elke vervoerder heeft toegewezen, gescheiden door komma's.", + "title": "Instellingen doorgestuurde e-mails" + }, + "reconfig_forwarded_emails": { + "data": { + "forwarding_header": "Doorstuurkoptekst (bijv. X-SimpleLogin-Original-From)", + "forwarded_emails": "Doorgestuurde e-mailadressen" + }, + "data_description": { + "forwarding_header": "Als uw doorstuurdienst de oorspronkelijke afzender in een koptekst opneemt, voer dan hier de naam van de koptekst in. Dit heeft voorrang op de onderstaande adreslijst. Voer '(none)' in of laat leeg om de adreslijst te gebruiken.", + "forwarded_emails": "Kommagescheiden lijst van doorstuuradressen waarvan berichten zullen aankomen. Laat '(none)' staan als u de bovenstaande doorstuurkoptekst gebruikt." + }, + "description": "Kies hoe doorgestuurde e-mails worden gekoppeld.\n\n**Optie 1 — Doorstuurkoptekst**: Als uw dienst (bijv. SimpleLogin) de oorspronkelijke afzender in een aangepaste koptekst opneemt, voer dan die koptekstnaam in. Mail and Packages zal die gebruiken om vervoerdersadressen automatisch te koppelen.\n\n**Optie 2 — Adreslijst**: Voer de doorstuuradressen in die uw dienst aan elke vervoerder heeft toegewezen, gescheiden door komma's.", + "title": "Instellingen doorgestuurde e-mails" + }, + "imap_config": { + "description": "Vul de verbindingsinformatie van uw mailserver in.", + "data": { + "host": "Gastheer", + "password": "Wachtwoord", + "port": "Haven", + "username": "Gebruikersnaam", + "verify_ssl": "SSL Certificaat Verifiëren", + "imap_security": "IMAP-beveiliging" + }, + "title": "Mail en pakketten (stap 1 van 2)" + }, + "user": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reconfig_imap": { + "data": { + "host": "Gastheer", + "password": "Wachtwoord", + "port": "Haven", + "username": "Gebruikersnaam", + "imap_security": "IMAP-beveiliging", + "verify_ssl": "SSL Certificaat Verifiëren" + }, + "description": "Vul de verbindingsinformatie van uw mailserver in.", + "title": "Mail en pakketten (stap 1 van 2)" + }, + "reconfigure": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reauth_confirm": { + "description": "The authentication for your mail server has expired or is invalid. Please re-authenticate to continue.", + "data": { + "username": "Username", + "password": "Password" + }, + "title": "Re-authenticate Mail Server" + } + } + }, + "selector": { + "auth_type": { + "options": { + "password": "Password", + "oauth2_microsoft": "OAuth2 - Microsoft (Outlook/Exchange)", + "oauth2_google": "OAuth2 - Google (Gmail)" + } + } + } +} diff --git a/custom_components/mail_and_packages/translations/no.json b/custom_components/mail_and_packages/translations/no.json new file mode 100644 index 0000000..bc704cc --- /dev/null +++ b/custom_components/mail_and_packages/translations/no.json @@ -0,0 +1,203 @@ +{ + "config": { + "abort": { + "single_instance_allowed": "Bare en enkelt konfigurasjon av e-post og pakker er tillatt.", + "reconfigure_successful": "Omkonfigurering vellykket" + }, + "error": { + "cannot_connect": "Kan ikke koble til eller logge inn på postserveren. Vennligst sjekk loggen for detaljer.", + "invalid_path": "Lagre bildene i en annen katalog.", + "ffmpeg_not_found": "Generer MP4 krever ffmpeg", + "amazon_domain": "Ugyldig videresendings e-postadresse.", + "file_not_found": "Bildefil ikke funnet", + "invalid_email_format": "Ugyldig e-postadresseformat.", + "missing_forwarded_emails": "Manglende videresendte e-postadresser. Du kan skrive inn '(none)' for å tømme denne innstillingen.", + "path_not_found": "Mappen ble ikke funnet", + "invalid_auth": "Invalid authentication details. Please check your username and password.", + "ssl_error": "An SSL error occurred. Change SSL cipher list and try again." + }, + "step": { + "config_2": { + "data": { + "folder": "E-postmappe", + "resources": "Sensorliste", + "scan_interval": "Skanneintervall (minutter)", + "image_path": "Bildevei", + "gif_duration": "Bildets varighet (sekunder)", + "image_security": "Tilfeldig bilde filnavn", + "imap_timeout": "Tid i sekunder før tilkoblingen tidsavbrudd (sekunder, minimum 10)", + "generate_mp4": "Lag mp4 fra bilder", + "allow_external": "Lag bilde for varslingsapper", + "custom_img": "Bruk tilpasset USPS 'ingen post' bilde?", + "amazon_custom_img": "Bruk tilpasset Amazon 'ingen levering' bilde?", + "ups_custom_img": "Bruk tilpasset UPS 'ingen levering' bilde?", + "walmart_custom_img": "Bruk tilpasset Walmart 'ingen levering' bilde?", + "fedex_custom_img": "Bruk tilpasset FedEx 'ingen levering' bilde?", + "generic_custom_img": "Bruk tilpasset generisk 'ingen levering' bilde?", + "generate_grid": "Opprett bildegitter for LLM-visjonsmodeller", + "allow_forwarded_emails": "Tillat videresendte e-poster i tillegg til en tjenestes standardverdi (f.eks. no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Fullfør konfigurasjonen ved å tilpasse følgende basert på e-poststrukturen og Home Assistant-installasjonen. \n\n For detaljer om alternativene [Mail and Packages] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration), les gjennom [konfigurasjon, maler , og automatiseringsdel] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) på GitHub.", + "title": "E-post og pakker (trinn 2 av 2)" + }, + "config_3": { + "data": { + "custom_img_file": "Sti til tilpasset bilde: (f.eks: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (ie: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (ie: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (ie: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (ie: images/my_custom_no_fedex.jpg)" + }, + "description": "Skriv inn stien og filnavnet til ditt tilpassede ingen post-bilde nedenfor.\n\nEksempel: bilder/tilpasset_ingenpost.gif", + "title": "Post og pakker (Trinn 3 av 3)" + }, + "config_amazon": { + "data": { + "amazon_domain": "Amazon-domene", + "amazon_fwds": "Amazon videresendte e-postadresser", + "amazon_days": "Dager tilbake for å sjekke Amazon-e-poster" + }, + "description": "Vennligst skriv inn domenet amazon sender e-poster fra (f.eks: amazon.com eller amazon.de)\n\nHvis du bruker Amazon videresendte e-poster, vennligst skill hver adresse med et komma, eller skriv inn (ingen) for å tømme denne innstillingen.\n\nMerk: hvis du konfigurerte et videresendingshode i forrige trinn, vil feltet for videresendingsadresse ikke vises — hodet håndterer Amazon e-postkoblingen automatisk.", + "title": "Amazon-innstillinger" + }, + "reconfig_2": { + "data": { + "folder": "E-postmappe", + "scan_interval": "Skanneintervall (minutter)", + "image_path": "Bildevei", + "gif_duration": "Bildets varighet (sekunder)", + "image_security": "Tilfeldig bilde filnavn", + "generate_mp4": "Lag mp4 fra bilder", + "resources": "Sensorliste", + "imap_timeout": "Tid i sekunder før tilkoblingen tidsavbrudd (sekunder, minimum 10)", + "allow_external": "Lag bilde for varslingsapper", + "custom_img": "Bruk tilpasset USPS 'ingen post' bilde?", + "amazon_custom_img": "Bruk tilpasset Amazon 'ingen levering' bilde?", + "ups_custom_img": "Bruk tilpasset UPS 'ingen levering' bilde?", + "walmart_custom_img": "Bruk tilpasset Walmart 'ingen levering' bilde?", + "fedex_custom_img": "Bruk tilpasset FedEx 'ingen levering' bilde?", + "generic_custom_img": "Bruk tilpasset generisk 'ingen levering' bilde?", + "generate_grid": "Opprett bildegitter for LLM-visjonsmodeller", + "allow_forwarded_emails": "Tillat videresendte e-poster i tillegg til en tjenestes standardverdi (f.eks. no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Fullfør konfigurasjonen ved å tilpasse følgende basert på din e-poststruktur og Home Assistant-installasjon.\n\nFor detaljer om [Mail and Packages-integrasjonen](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) alternativene, se gjennom [konfigurasjon, maler og automatiseringsseksjonen](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) på GitHub.\n\nHvis du bruker Amazon videresendte e-poster, vennligst skill hver adresse med et komma eller skriv inn (ingen) for å tømme denne innstillingen.", + "title": "E-post og pakker (trinn 2 av 2)" + }, + "reconfig_3": { + "data": { + "custom_img_file": "Sti til tilpasset bilde: (dvs.: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (i.e.: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (i.e.: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (i.e.: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (i.e.: images/my_custom_no_fedex.jpg)" + }, + "description": "Skriv inn stien og filnavnet til ditt tilpassede ingen post-bilde nedenfor.\n\nEksempel: bilder/tilpasset_ingenpost.gif", + "title": "Post og pakker (Trinn 3 av 3)" + }, + "reconfig_amazon": { + "data": { + "amazon_domain": "Amazon-domene", + "amazon_fwds": "Amazon videresendte e-postadresser", + "amazon_days": "Dager tilbake for å sjekke Amazon-e-poster" + }, + "description": "Vennligst skriv inn domenet amazon sender e-poster fra (f.eks: amazon.com eller amazon.de)\n\nHvis du bruker Amazon videresendte e-poster, vennligst skill hver adresse med et komma, eller skriv inn (ingen) for å tømme denne innstillingen.\n\nMerk: hvis du konfigurerte et videresendingshode i forrige trinn, vil feltet for videresendingsadresse ikke vises — hodet håndterer Amazon e-postkoblingen automatisk.", + "title": "Amazon-innstillinger" + }, + "config_storage": { + "data": { + "storage": "Katalog for å lagre bilder" + }, + "description": "Vennligst oppgi mappen du vil at bildene dine skal lagres i.\nStandard er automatisk fylt ut.", + "title": "Bildelagringssted" + }, + "reconfig_storage": { + "data": { + "storage": "Katalog for å lagre bilder" + }, + "description": "Vennligst oppgi mappen du vil at bildene dine skal lagres i.\nStandard er automatisk fylt ut.", + "title": "Bildelagringssted" + }, + "config_forwarded_emails": { + "data": { + "forwarding_header": "Videresendingshode (f.eks. X-SimpleLogin-Original-From)", + "forwarded_emails": "Videresendte e-postadresser" + }, + "data_description": { + "forwarding_header": "Hvis videresendingstjenesten din inkluderer den opprinnelige avsenderen i en topptekst, skriv inn topptekstnavnet her. Dette har forrang over adresselisten nedenfor. Skriv inn '(none)' eller la det stå tomt for å bruke adresselisten i stedet.", + "forwarded_emails": "Kommaseparert liste over videresendingsadresser meldinger vil komme fra. La '(none)' stå hvis du bruker videresendingshodet ovenfor." + }, + "description": "Velg hvordan videresendte e-poster skal matches.\n\n**Alternativ 1 — Videresendingshode**: Hvis tjenesten din (f.eks. SimpleLogin) inkluderer den opprinnelige avsenderen i et tilpasset hode, skriv inn det hodet. Mail and Packages vil bruke det til å matche fraktadresser automatisk.\n\n**Alternativ 2 — Adresseliste**: Skriv inn videresendingsadressene tjenesten din har tildelt hver fraktfører, atskilt med komma.", + "title": "Innstillinger for videresendte e-poster" + }, + "reconfig_forwarded_emails": { + "data": { + "forwarding_header": "Videresendingshode (f.eks. X-SimpleLogin-Original-From)", + "forwarded_emails": "Videresendte e-postadresser" + }, + "data_description": { + "forwarding_header": "Hvis videresendingstjenesten din inkluderer den opprinnelige avsenderen i en topptekst, skriv inn topptekstnavnet her. Dette har forrang over adresselisten nedenfor. Skriv inn '(none)' eller la det stå tomt for å bruke adresselisten i stedet.", + "forwarded_emails": "Kommaseparert liste over videresendingsadresser meldinger vil komme fra. La '(none)' stå hvis du bruker videresendingshodet ovenfor." + }, + "description": "Velg hvordan videresendte e-poster skal matches.\n\n**Alternativ 1 — Videresendingshode**: Hvis tjenesten din (f.eks. SimpleLogin) inkluderer den opprinnelige avsenderen i et tilpasset hode, skriv inn det hodet. Mail and Packages vil bruke det til å matche fraktadresser automatisk.\n\n**Alternativ 2 — Adresseliste**: Skriv inn videresendingsadressene tjenesten din har tildelt hver fraktfører, atskilt med komma.", + "title": "Innstillinger for videresendte e-poster" + }, + "imap_config": { + "description": "Vennligst oppgi tilkoblingsinformasjonen til din e-postserver.", + "data": { + "host": "Vert", + "password": "Passord", + "port": "Havn", + "username": "Brukernavn", + "verify_ssl": "Bekreft SSL-sertifikat", + "imap_security": "IMAP-sikkerhet" + }, + "title": "E-post og pakker (trinn 1 av 2)" + }, + "user": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reconfig_imap": { + "data": { + "host": "Vert", + "password": "Passord", + "port": "Havn", + "username": "Brukernavn", + "imap_security": "IMAP-sikkerhet", + "verify_ssl": "Bekreft SSL-sertifikat" + }, + "description": "Vennligst oppgi tilkoblingsinformasjonen til din e-postserver.", + "title": "E-post og pakker (trinn 1 av 2)" + }, + "reconfigure": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reauth_confirm": { + "description": "The authentication for your mail server has expired or is invalid. Please re-authenticate to continue.", + "data": { + "username": "Username", + "password": "Password" + }, + "title": "Re-authenticate Mail Server" + } + } + }, + "selector": { + "auth_type": { + "options": { + "password": "Password", + "oauth2_microsoft": "OAuth2 - Microsoft (Outlook/Exchange)", + "oauth2_google": "OAuth2 - Google (Gmail)" + } + } + } +} diff --git a/custom_components/mail_and_packages/translations/pl.json b/custom_components/mail_and_packages/translations/pl.json new file mode 100644 index 0000000..efcfe9d --- /dev/null +++ b/custom_components/mail_and_packages/translations/pl.json @@ -0,0 +1,203 @@ +{ + "config": { + "abort": { + "single_instance_allowed": "Dozwolona jest tylko jedna konfiguracja poczty i pakietów.", + "reconfigure_successful": "Pomyślnie przekonfigurowano" + }, + "error": { + "cannot_connect": "Nie można połączyć się lub zalogować do serwera pocztowego. Sprawdź szczegóły w dzienniku.", + "invalid_path": "Proszę przechowywać obrazy w innym katalogu.", + "ffmpeg_not_found": "Generowanie MP4 wymaga ffmpeg", + "amazon_domain": "Nieprawidłowy adres e-mail do przekierowania.", + "file_not_found": "Nie znaleziono pliku obrazu", + "invalid_email_format": "Nieprawidłowy format adresu e-mail.", + "missing_forwarded_emails": "Brak przekierowanych adresów e-mail. Możesz wprowadzić '(none)', aby wyczyścić to ustawienie.", + "path_not_found": "Katalog nie został znaleziony", + "invalid_auth": "Invalid authentication details. Please check your username and password.", + "ssl_error": "An SSL error occurred. Change SSL cipher list and try again." + }, + "step": { + "config_2": { + "data": { + "folder": "Folder poczty", + "resources": "Lista czujników", + "scan_interval": "Interwał skanowania (minuty)", + "image_path": "Ścieżka obrazu", + "gif_duration": "Czas trwania obrazu (sekundy)", + "image_security": "Losowa nazwa pliku obrazu", + "imap_timeout": "Czas w sekundach przed wygaśnięciem połączenia (sekundy, minimum 10)", + "generate_mp4": "Utwórz mp4 z obrazów", + "allow_external": "Utwórz obraz dla aplikacji powiadomień", + "custom_img": "Użyć niestandardowego obrazu USPS 'brak poczty'?", + "amazon_custom_img": "Użyć niestandardowego obrazu Amazon 'brak dostawy'?", + "ups_custom_img": "Użyć niestandardowego obrazu UPS 'brak dostawy'?", + "walmart_custom_img": "Użyć niestandardowego obrazu Walmart 'brak dostawy'?", + "fedex_custom_img": "Użyć niestandardowego obrazu FedEx 'brak dostawy'?", + "generic_custom_img": "Użyć niestandardowego obrazu ogólnego 'brak dostawy'?", + "generate_grid": "Utwórz siatkę obrazów dla modeli wizji LLM", + "allow_forwarded_emails": "Zezwalaj na przekierowane e-maile oprócz wartości domyślnej usługi (np. no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Zakończ konfigurację, dostosowując następujące elementy w oparciu o strukturę poczty e-mail i instalację Home Assistant. \n\n Aby uzyskać szczegółowe informacje na temat opcji [Integracja poczty i pakietów] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) sprawdź opcje [konfiguracja, szablony i sekcja automatyzacji] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) na GitHub.", + "title": "Poczta i paczki (krok 2 z 2)" + }, + "config_3": { + "data": { + "custom_img_file": "Ścieżka do niestandardowego obrazu: (np.: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (ie: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (ie: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (ie: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (ie: images/my_custom_no_fedex.jpg)" + }, + "description": "Wprowadź ścieżkę i nazwę pliku do swojego niestandardowego obrazu bez maila poniżej.\n\nPrzykład: images/custom_nomail.gif", + "title": "Poczta i paczki (Krok 3 z 3)" + }, + "config_amazon": { + "data": { + "amazon_domain": "Domena Amazon", + "amazon_fwds": "Amazon przekazał adresy e-mail", + "amazon_days": "Dni do sprawdzenia dla wiadomości e-mail od Amazon" + }, + "description": "Wprowadź domenę, z której Amazon wysyła e-maile (np. amazon.com lub amazon.de)\n\nJeśli korzystasz z przekierowanych e-maili od Amazon, oddziel każdy adres przecinkiem lub wpisz (brak), aby wyczyścić to ustawienie.\n\nUwaga: jeśli w poprzednim kroku skonfigurowałeś nagłówek przekierowania, pole adresu przekierowania nie pojawi się — nagłówek automatycznie obsługuje dopasowywanie e-maili Amazon.", + "title": "Ustawienia Amazon" + }, + "reconfig_2": { + "data": { + "folder": "Folder poczty", + "scan_interval": "Interwał skanowania (minuty)", + "image_path": "Ścieżka obrazu", + "gif_duration": "Czas trwania obrazu (sekundy)", + "image_security": "Losowa nazwa pliku obrazu", + "generate_mp4": "Utwórz mp4 z obrazów", + "resources": "Lista czujników", + "imap_timeout": "Czas w sekundach przed wygaśnięciem połączenia (sekundy, minimum 10)", + "allow_external": "Utwórz obraz dla aplikacji powiadomień", + "custom_img": "Użyć niestandardowego obrazu USPS 'brak poczty'?", + "amazon_custom_img": "Użyć niestandardowego obrazu Amazon 'brak dostawy'?", + "ups_custom_img": "Użyć niestandardowego obrazu UPS 'brak dostawy'?", + "walmart_custom_img": "Użyć niestandardowego obrazu Walmart 'brak dostawy'?", + "fedex_custom_img": "Użyć niestandardowego obrazu FedEx 'brak dostawy'?", + "generic_custom_img": "Użyć niestandardowego obrazu ogólnego 'brak dostawy'?", + "generate_grid": "Utwórz siatkę obrazów dla modeli wizji LLM", + "allow_forwarded_emails": "Zezwalaj na przekierowane e-maile oprócz wartości domyślnej usługi (np. no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Zakończ konfigurację, dostosowując następujące elementy do struktury swojego e-maila i instalacji Home Assistant.\n\nAby uzyskać szczegółowe informacje na temat opcji [integracji Mail and Packages](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration), zapoznaj się z [sekcją konfiguracji, szablonów i automatyzacji](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) na GitHubie.\n\nJeśli korzystasz z przekierowanych e-maili Amazon, oddziel każdy adres przecinkiem lub wprowadź (brak), aby wyczyścić to ustawienie.", + "title": "Poczta i paczki (krok 2 z 2)" + }, + "reconfig_3": { + "data": { + "custom_img_file": "Ścieżka do niestandardowego obrazu: (np.: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (i.e.: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (i.e.: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (i.e.: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (i.e.: images/my_custom_no_fedex.jpg)" + }, + "description": "Wprowadź ścieżkę i nazwę pliku do swojego niestandardowego obrazu bez maila poniżej.\n\nPrzykład: images/custom_nomail.gif", + "title": "Poczta i paczki (Krok 3 z 3)" + }, + "reconfig_amazon": { + "data": { + "amazon_domain": "Domena Amazon", + "amazon_fwds": "Amazon przekazał adresy e-mail", + "amazon_days": "Dni do sprawdzenia dla wiadomości e-mail od Amazon" + }, + "description": "Wprowadź domenę, z której Amazon wysyła e-maile (np. amazon.com lub amazon.de)\n\nJeśli korzystasz z przekierowanych e-maili od Amazon, oddziel każdy adres przecinkiem lub wpisz (brak), aby wyczyścić to ustawienie.\n\nUwaga: jeśli w poprzednim kroku skonfigurowałeś nagłówek przekierowania, pole adresu przekierowania nie pojawi się — nagłówek automatycznie obsługuje dopasowywanie e-maili Amazon.", + "title": "Ustawienia Amazon" + }, + "config_storage": { + "data": { + "storage": "Katalog do przechowywania obrazów" + }, + "description": "Wprowadź katalog, w którym chciałbyś przechowywać swoje obrazy.\nDomyślnie jest on automatycznie wypełniany.", + "title": "Lokalizacja przechowywania obrazów" + }, + "reconfig_storage": { + "data": { + "storage": "Katalog do przechowywania obrazów" + }, + "description": "Wprowadź katalog, w którym chciałbyś przechowywać swoje obrazy.\nDomyślnie jest on automatycznie wypełniany.", + "title": "Lokalizacja przechowywania obrazów" + }, + "config_forwarded_emails": { + "data": { + "forwarding_header": "Nagłówek przekierowania (np. X-SimpleLogin-Original-From)", + "forwarded_emails": "Przekierowane adresy e-mail" + }, + "data_description": { + "forwarding_header": "Jeśli Twoja usługa przekierowania zawiera oryginalnego nadawcę w nagłówku, wprowadź tutaj nazwę nagłówka. Ma to pierwszeństwo przed poniższą listą adresów. Wprowadź '(none)' lub pozostaw puste, aby zamiast tego użyć listy adresów.", + "forwarded_emails": "Lista oddzielona przecinkami adresów przekierowania, z których będą przychodziły wiadomości. Pozostaw '(none)', jeśli używasz powyższego nagłówka przekierowania." + }, + "description": "Wybierz sposób dopasowywania przekierowanych wiadomości e-mail.\n\n**Opcja 1 — Nagłówek przekierowania**: Jeśli Twoja usługa (np. SimpleLogin) zawiera oryginalnego nadawcę w niestandardowym nagłówku, wprowadź nazwę tego nagłówka. Mail and Packages użyje go do automatycznego dopasowywania adresów przewoźników.\n\n**Opcja 2 — Lista adresów**: Wprowadź adresy przekierowania przypisane przez usługę do każdego przewoźnika, oddzielone przecinkami.", + "title": "Ustawienia przekierowanych wiadomości e-mail" + }, + "reconfig_forwarded_emails": { + "data": { + "forwarding_header": "Nagłówek przekierowania (np. X-SimpleLogin-Original-From)", + "forwarded_emails": "Przekierowane adresy e-mail" + }, + "data_description": { + "forwarding_header": "Jeśli Twoja usługa przekierowania zawiera oryginalnego nadawcę w nagłówku, wprowadź tutaj nazwę nagłówka. Ma to pierwszeństwo przed poniższą listą adresów. Wprowadź '(none)' lub pozostaw puste, aby zamiast tego użyć listy adresów.", + "forwarded_emails": "Lista oddzielona przecinkami adresów przekierowania, z których będą przychodziły wiadomości. Pozostaw '(none)', jeśli używasz powyższego nagłówka przekierowania." + }, + "description": "Wybierz sposób dopasowywania przekierowanych wiadomości e-mail.\n\n**Opcja 1 — Nagłówek przekierowania**: Jeśli Twoja usługa (np. SimpleLogin) zawiera oryginalnego nadawcę w niestandardowym nagłówku, wprowadź nazwę tego nagłówka. Mail and Packages użyje go do automatycznego dopasowywania adresów przewoźników.\n\n**Opcja 2 — Lista adresów**: Wprowadź adresy przekierowania przypisane przez usługę do każdego przewoźnika, oddzielone przecinkami.", + "title": "Ustawienia przekierowanych wiadomości e-mail" + }, + "imap_config": { + "description": "Proszę wprowadzić informacje o połączeniu z serwerem pocztowym.", + "data": { + "host": "Gospodarz", + "password": "Hasło", + "port": "Port", + "username": "Nazwa Użytkownika", + "verify_ssl": "Sprawdź certyfikat SSL", + "imap_security": "Bezpieczeństwo IMAP" + }, + "title": "Poczta i paczki (krok 1 z 2)" + }, + "user": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reconfig_imap": { + "data": { + "host": "Gospodarz", + "password": "Hasło", + "port": "Port", + "username": "Nazwa Użytkownika", + "imap_security": "Bezpieczeństwo IMAP", + "verify_ssl": "Sprawdź certyfikat SSL" + }, + "description": "Proszę wprowadzić informacje o połączeniu z serwerem pocztowym.", + "title": "Poczta i paczki (krok 1 z 2)" + }, + "reconfigure": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reauth_confirm": { + "description": "The authentication for your mail server has expired or is invalid. Please re-authenticate to continue.", + "data": { + "username": "Username", + "password": "Password" + }, + "title": "Re-authenticate Mail Server" + } + } + }, + "selector": { + "auth_type": { + "options": { + "password": "Password", + "oauth2_microsoft": "OAuth2 - Microsoft (Outlook/Exchange)", + "oauth2_google": "OAuth2 - Google (Gmail)" + } + } + } +} diff --git a/custom_components/mail_and_packages/translations/pt.json b/custom_components/mail_and_packages/translations/pt.json new file mode 100644 index 0000000..d21820b --- /dev/null +++ b/custom_components/mail_and_packages/translations/pt.json @@ -0,0 +1,203 @@ +{ + "config": { + "abort": { + "single_instance_allowed": "Somente uma única configuração de correio e pacotes é permitida.", + "reconfigure_successful": "Reconfiguração bem-sucedida" + }, + "error": { + "cannot_connect": "Não foi possível conectar ou fazer login no servidor de email. Por favor, verifique o log para obter detalhes.", + "invalid_path": "Por favor, guarde as imagens em outro diretório.", + "ffmpeg_not_found": "Gerar MP4 requer ffmpeg", + "amazon_domain": "Endereço de encaminhamento de email inválido.", + "file_not_found": "Arquivo de imagem não encontrado", + "invalid_email_format": "Formato de endereço de email inválido.", + "missing_forwarded_emails": "Endereços de email encaminhados em falta. Pode introduzir '(none)' para limpar esta configuração.", + "path_not_found": "Diretório não encontrado", + "invalid_auth": "Invalid authentication details. Please check your username and password.", + "ssl_error": "An SSL error occurred. Change SSL cipher list and try again." + }, + "step": { + "config_2": { + "data": { + "folder": "Pasta de Correio", + "resources": "Lista de Sensores", + "scan_interval": "Intervalo de digitalização (minutos)", + "image_path": "Caminho da imagem", + "gif_duration": "Duração da imagem (segundos)", + "image_security": "Nome da imagem aleatória", + "imap_timeout": "Tempo em segundos antes do tempo limite de conexão (segundos, mínimo 10)", + "generate_mp4": "Crie mp4 a partir de imagens", + "allow_external": "Crie imagem para aplicativos de notificação", + "custom_img": "Usar imagem personalizada USPS 'sem correio'?", + "amazon_custom_img": "Usar imagem personalizada Amazon 'sem entrega'?", + "ups_custom_img": "Usar imagem personalizada UPS 'sem entrega'?", + "walmart_custom_img": "Usar imagem personalizada Walmart 'sem entrega'?", + "fedex_custom_img": "Usar imagem personalizada FedEx 'sem entrega'?", + "generic_custom_img": "Usar imagem personalizada genérica 'sem entrega'?", + "generate_grid": "Criar grade de imagens para modelos de visão LLM", + "allow_forwarded_emails": "Permitir emails encaminhados além do padrão de um serviço (ex: no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Conclua a configuração, personalizando o seguinte com base na sua estrutura de email e instalação do Home Assistant. \n\n Para obter detalhes sobre as opções [integração de Mail e Pacotes] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration), revise as opções de [configuração, modelos e seção de automações] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) no GitHub.", + "title": "Correio e pacotes (Etapa 2 de 2)" + }, + "config_3": { + "data": { + "custom_img_file": "Caminho para imagem personalizada: (ex: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (ie: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (ie: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (ie: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (ie: images/my_custom_no_fedex.jpg)" + }, + "description": "Insira o caminho e o nome do arquivo para a sua imagem personalizada de sem correio abaixo.\n\nExemplo: images/custom_nomail.gif", + "title": "Correio e Pacotes (Etapa 3 de 3)" + }, + "config_amazon": { + "data": { + "amazon_domain": "Domínio da Amazon", + "amazon_fwds": "A Amazon encaminhou endereços de email", + "amazon_days": "Dias atrás para verificar emails da Amazon" + }, + "description": "Por favor, insira o domínio de onde a Amazon envia e-mails (por exemplo: amazon.com ou amazon.de)\n\nSe estiver usando e-mails encaminhados pela Amazon, separe cada endereço com uma vírgula ou insira (nenhum) para limpar essa configuração.\n\nNota: se configurou um cabeçalho de reencaminhamento no passo anterior, o campo de endereço de reencaminhamento não aparecerá — o cabeçalho trata automaticamente da correspondência de e-mails da Amazon.", + "title": "Configurações da Amazon" + }, + "reconfig_2": { + "data": { + "folder": "Pasta de Correio", + "scan_interval": "Intervalo de digitalização (minutos)", + "image_path": "Caminho da imagem", + "gif_duration": "Duração da imagem (segundos)", + "image_security": "Nome da imagem aleatória", + "generate_mp4": "Crie mp4 a partir de imagens", + "resources": "Lista de Sensores", + "imap_timeout": "Tempo em segundos antes do tempo limite de conexão (segundos, mínimo 10)", + "allow_external": "Crie imagem para aplicativos de notificação", + "custom_img": "Usar imagem personalizada USPS 'sem correio'?", + "amazon_custom_img": "Usar imagem personalizada Amazon 'sem entrega'?", + "ups_custom_img": "Usar imagem personalizada UPS 'sem entrega'?", + "walmart_custom_img": "Usar imagem personalizada Walmart 'sem entrega'?", + "fedex_custom_img": "Usar imagem personalizada FedEx 'sem entrega'?", + "generic_custom_img": "Usar imagem personalizada genérica 'sem entrega'?", + "generate_grid": "Criar grade de imagens para modelos de visão LLM", + "allow_forwarded_emails": "Permitir emails encaminhados além do padrão de um serviço (ex: no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Conclua a configuração personalizando o seguinte com base na estrutura do seu email e na instalação do Home Assistant.\n\nPara detalhes sobre as opções de [integração de Correio e Pacotes](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration), consulte a [seção de configuração, modelos e automações](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) no GitHub.\n\nSe estiver usando emails encaminhados da Amazon, separe cada endereço com uma vírgula ou insira (nenhum) para limpar essa configuração.", + "title": "Correio e pacotes (Etapa 2 de 2)" + }, + "reconfig_3": { + "data": { + "custom_img_file": "Caminho para imagem personalizada: (ex.: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (i.e.: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (i.e.: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (i.e.: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (i.e.: images/my_custom_no_fedex.jpg)" + }, + "description": "Insira o caminho e o nome do arquivo para a sua imagem personalizada de sem correio abaixo.\n\nExemplo: images/custom_nomail.gif", + "title": "Correio e Pacotes (Etapa 3 de 3)" + }, + "reconfig_amazon": { + "data": { + "amazon_domain": "Domínio da Amazon", + "amazon_fwds": "A Amazon encaminhou endereços de email", + "amazon_days": "Dias atrás para verificar emails da Amazon" + }, + "description": "Por favor, insira o domínio de onde a Amazon envia e-mails (por exemplo: amazon.com ou amazon.de)\n\nSe estiver usando e-mails encaminhados pela Amazon, separe cada endereço com uma vírgula ou insira (nenhum) para limpar essa configuração.\n\nNota: se configurou um cabeçalho de reencaminhamento no passo anterior, o campo de endereço de reencaminhamento não aparecerá — o cabeçalho trata automaticamente da correspondência de e-mails da Amazon.", + "title": "Configurações da Amazon" + }, + "config_storage": { + "data": { + "storage": "Diretório para armazenar imagens" + }, + "description": "Por favor, insira o diretório em que você gostaria que suas imagens fossem armazenadas.\nO padrão é preenchido automaticamente.", + "title": "Local de armazenamento de imagens" + }, + "reconfig_storage": { + "data": { + "storage": "Diretório para armazenar imagens" + }, + "description": "Por favor, insira o diretório em que você gostaria que suas imagens fossem armazenadas.\nO padrão é preenchido automaticamente.", + "title": "Local de armazenamento de imagens" + }, + "config_forwarded_emails": { + "data": { + "forwarding_header": "Cabeçalho de reencaminhamento (ex. X-SimpleLogin-Original-From)", + "forwarded_emails": "Endereços de email encaminhados" + }, + "data_description": { + "forwarding_header": "Se o seu serviço de reencaminhamento inclui o remetente original num cabeçalho, introduza aqui o nome do cabeçalho. Isto tem prioridade sobre a lista de endereços abaixo. Introduza '(none)' ou deixe em branco para usar a lista de endereços.", + "forwarded_emails": "Lista separada por vírgulas dos endereços de reencaminhamento de onde chegarão as mensagens. Deixe '(none)' se estiver a usar o cabeçalho de reencaminhamento acima." + }, + "description": "Escolha como fazer a correspondência dos e-mails reencaminhados.\n\n**Opção 1 — Cabeçalho de reencaminhamento**: Se o seu serviço (ex. SimpleLogin) inclui o remetente original num cabeçalho personalizado, introduza esse nome de cabeçalho. O Mail and Packages irá utilizá-lo para fazer a correspondência automática dos endereços das transportadoras.\n\n**Opção 2 — Lista de endereços**: Introduza os endereços de reencaminhamento que o seu serviço atribuiu a cada transportadora, separados por vírgulas.", + "title": "Definições de e-mails reencaminhados" + }, + "reconfig_forwarded_emails": { + "data": { + "forwarding_header": "Cabeçalho de reencaminhamento (ex. X-SimpleLogin-Original-From)", + "forwarded_emails": "Endereços de email encaminhados" + }, + "data_description": { + "forwarding_header": "Se o seu serviço de reencaminhamento inclui o remetente original num cabeçalho, introduza aqui o nome do cabeçalho. Isto tem prioridade sobre a lista de endereços abaixo. Introduza '(none)' ou deixe em branco para usar a lista de endereços.", + "forwarded_emails": "Lista separada por vírgulas dos endereços de reencaminhamento de onde chegarão as mensagens. Deixe '(none)' se estiver a usar o cabeçalho de reencaminhamento acima." + }, + "description": "Escolha como fazer a correspondência dos e-mails reencaminhados.\n\n**Opção 1 — Cabeçalho de reencaminhamento**: Se o seu serviço (ex. SimpleLogin) inclui o remetente original num cabeçalho personalizado, introduza esse nome de cabeçalho. O Mail and Packages irá utilizá-lo para fazer a correspondência automática dos endereços das transportadoras.\n\n**Opção 2 — Lista de endereços**: Introduza os endereços de reencaminhamento que o seu serviço atribuiu a cada transportadora, separados por vírgulas.", + "title": "Definições de e-mails reencaminhados" + }, + "imap_config": { + "description": "Por favor, insira as informações de conexão do seu servidor de email.", + "data": { + "host": "Hospedeiro", + "password": "Senha", + "port": "Porta", + "username": "Nome do usuário", + "verify_ssl": "Verificar Certificado SSL", + "imap_security": "Segurança IMAP" + }, + "title": "Correio e pacotes (Etapa 1 de 2)" + }, + "user": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reconfig_imap": { + "data": { + "host": "Hospedeiro", + "password": "Senha", + "port": "Porta", + "username": "Nome do usuário", + "imap_security": "Segurança IMAP", + "verify_ssl": "Verificar Certificado SSL" + }, + "description": "Por favor, insira as informações de conexão do seu servidor de email.", + "title": "Correio e pacotes (Etapa 1 de 2)" + }, + "reconfigure": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reauth_confirm": { + "description": "The authentication for your mail server has expired or is invalid. Please re-authenticate to continue.", + "data": { + "username": "Username", + "password": "Password" + }, + "title": "Re-authenticate Mail Server" + } + } + }, + "selector": { + "auth_type": { + "options": { + "password": "Password", + "oauth2_microsoft": "OAuth2 - Microsoft (Outlook/Exchange)", + "oauth2_google": "OAuth2 - Google (Gmail)" + } + } + } +} diff --git a/custom_components/mail_and_packages/translations/pt_BR.json b/custom_components/mail_and_packages/translations/pt_BR.json new file mode 100644 index 0000000..ad19de1 --- /dev/null +++ b/custom_components/mail_and_packages/translations/pt_BR.json @@ -0,0 +1,203 @@ +{ + "config": { + "abort": { + "single_instance_allowed": "Somente uma única configuração de correio e pacotes é permitida.", + "reconfigure_successful": "Reconfiguração bem-sucedida" + }, + "error": { + "cannot_connect": "Não foi possível conectar ou fazer login no servidor de email. Por favor, verifique o log para obter detalhes.", + "invalid_path": "Por favor, guarde as imagens em outro diretório.", + "ffmpeg_not_found": "Gerar MP4 requer ffmpeg", + "amazon_domain": "Endereço de encaminhamento de email inválido.", + "file_not_found": "Arquivo de imagem não encontrado", + "invalid_email_format": "Formato de endereço de email inválido.", + "missing_forwarded_emails": "Endereços de email encaminhados em falta. Você pode inserir '(none)' para limpar esta configuração.", + "path_not_found": "Diretório não encontrado", + "invalid_auth": "Invalid authentication details. Please check your username and password.", + "ssl_error": "An SSL error occurred. Change SSL cipher list and try again." + }, + "step": { + "config_2": { + "data": { + "folder": "Pasta de Correio", + "resources": "Lista de Sensores", + "scan_interval": "Intervalo de digitalização (minutos)", + "image_path": "Caminho da imagem", + "gif_duration": "Duração da imagem (segundos)", + "image_security": "Nome da imagem aleatória", + "imap_timeout": "Tempo em segundos antes do tempo limite de conexão (segundos, mínimo 10)", + "generate_mp4": "Crie mp4 a partir de imagens", + "allow_external": "Crie imagem para aplicativos de notificação", + "custom_img": "Usar imagem personalizada USPS 'sem correio'?", + "amazon_custom_img": "Usar imagem personalizada Amazon 'sem entrega'?", + "ups_custom_img": "Usar imagem personalizada UPS 'sem entrega'?", + "walmart_custom_img": "Usar imagem personalizada Walmart 'sem entrega'?", + "fedex_custom_img": "Usar imagem personalizada FedEx 'sem entrega'?", + "generic_custom_img": "Usar imagem personalizada genérica 'sem entrega'?", + "generate_grid": "Criar grade de imagens para modelos de visão LLM", + "allow_forwarded_emails": "Permitir e-mails encaminhados além do padrão de um serviço (ex: no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Conclua a configuração, personalizando o seguinte com base na sua estrutura de email e instalação do Home Assistant. \n\n Para obter detalhes sobre as opções [integração de Mail e Pacotes] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration), revise as opções de [configuração, modelos e seção de automações] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) no GitHub.", + "title": "Correio e pacotes (Etapa 2 de 2)" + }, + "config_3": { + "data": { + "custom_img_file": "Caminho para imagem personalizada: (ex: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (ie: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (ie: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (ie: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (ie: images/my_custom_no_fedex.jpg)" + }, + "description": "Insira o caminho e o nome do arquivo para a sua imagem personalizada de sem correio abaixo.\n\nExemplo: images/custom_nomail.gif", + "title": "Correio e Pacotes (Etapa 3 de 3)" + }, + "config_amazon": { + "data": { + "amazon_domain": "Domínio da Amazon", + "amazon_fwds": "A Amazon encaminhou endereços de email", + "amazon_days": "Dias atrás para verificar os emails da Amazon" + }, + "description": "Por favor, insira o domínio do qual a Amazon envia e-mails (por exemplo: amazon.com ou amazon.de)\n\nSe estiver usando e-mails encaminhados pela Amazon, separe cada endereço com uma vírgula ou insira (nenhum) para limpar essa configuração.\n\nNota: se você configurou um cabeçalho de encaminhamento na etapa anterior, o campo de endereço de encaminhamento não aparecerá — o cabeçalho trata automaticamente da correspondência de e-mails da Amazon.", + "title": "Configurações da Amazon" + }, + "reconfig_2": { + "data": { + "folder": "Pasta de Correio", + "scan_interval": "Intervalo de digitalização (minutos)", + "image_path": "Caminho da imagem", + "gif_duration": "Duração da imagem (segundos)", + "image_security": "Nome da imagem aleatória", + "generate_mp4": "Crie mp4 a partir de imagens", + "resources": "Lista de Sensores", + "imap_timeout": "Tempo em segundos antes do tempo limite de conexão (segundos, mínimo 10)", + "allow_external": "Crie imagem para aplicativos de notificação", + "custom_img": "Usar imagem personalizada USPS 'sem correio'?", + "amazon_custom_img": "Usar imagem personalizada Amazon 'sem entrega'?", + "ups_custom_img": "Usar imagem personalizada UPS 'sem entrega'?", + "walmart_custom_img": "Usar imagem personalizada Walmart 'sem entrega'?", + "fedex_custom_img": "Usar imagem personalizada FedEx 'sem entrega'?", + "generic_custom_img": "Usar imagem personalizada genérica 'sem entrega'?", + "generate_grid": "Criar grade de imagens para modelos de visão LLM", + "allow_forwarded_emails": "Permitir e-mails encaminhados além do padrão de um serviço (ex: no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Conclua a configuração personalizando o seguinte com base na estrutura do seu email e na instalação do Home Assistant.\n\nPara detalhes sobre as opções de [integração de Mail e Pacotes](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration), consulte a [seção de configuração, modelos e automações](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) no GitHub.\n\nSe estiver usando emails encaminhados da Amazon, separe cada endereço com uma vírgula ou insira (nenhum) para limpar essa configuração.", + "title": "Correio e pacotes (Etapa 2 de 2)" + }, + "reconfig_3": { + "data": { + "custom_img_file": "Caminho para imagem personalizada: (ex.: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (i.e.: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (i.e.: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (i.e.: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (i.e.: images/my_custom_no_fedex.jpg)" + }, + "description": "Insira o caminho e o nome do arquivo para a sua imagem personalizada de sem correio abaixo.\n\nExemplo: images/custom_nomail.gif", + "title": "Correio e Pacotes (Etapa 3 de 3)" + }, + "reconfig_amazon": { + "data": { + "amazon_domain": "Domínio da Amazon", + "amazon_fwds": "A Amazon encaminhou endereços de email", + "amazon_days": "Dias atrás para verificar os emails da Amazon" + }, + "description": "Por favor, insira o domínio do qual a Amazon envia e-mails (por exemplo: amazon.com ou amazon.de)\n\nSe estiver usando e-mails encaminhados pela Amazon, separe cada endereço com uma vírgula ou insira (nenhum) para limpar essa configuração.\n\nNota: se você configurou um cabeçalho de encaminhamento na etapa anterior, o campo de endereço de encaminhamento não aparecerá — o cabeçalho trata automaticamente da correspondência de e-mails da Amazon.", + "title": "Configurações da Amazon" + }, + "config_storage": { + "data": { + "storage": "Diretório para armazenar imagens" + }, + "description": "Por favor, insira o diretório em que você gostaria que suas imagens fossem armazenadas.\nO padrão é preenchido automaticamente.", + "title": "Local de armazenamento de imagens" + }, + "reconfig_storage": { + "data": { + "storage": "Diretório para armazenar imagens" + }, + "description": "Por favor, insira o diretório em que você gostaria que suas imagens fossem armazenadas.\nO padrão é preenchido automaticamente.", + "title": "Local de armazenamento de imagens" + }, + "config_forwarded_emails": { + "data": { + "forwarding_header": "Cabeçalho de encaminhamento (ex. X-SimpleLogin-Original-From)", + "forwarded_emails": "Endereços de e-mail encaminhados" + }, + "data_description": { + "forwarding_header": "Se o seu serviço de encaminhamento inclui o remetente original em um cabeçalho, insira o nome do cabeçalho aqui. Isso tem precedência sobre a lista de endereços abaixo. Insira '(none)' ou deixe em branco para usar a lista de endereços.", + "forwarded_emails": "Lista separada por vírgulas dos endereços de encaminhamento dos quais as mensagens chegarão. Deixe '(none)' se estiver usando o cabeçalho de encaminhamento acima." + }, + "description": "Escolha como corresponder os e-mails encaminhados.\n\n**Opção 1 — Cabeçalho de encaminhamento**: Se o seu serviço (ex. SimpleLogin) inclui o remetente original em um cabeçalho personalizado, insira esse nome de cabeçalho. O Mail and Packages o usará para corresponder os endereços das transportadoras automaticamente.\n\n**Opção 2 — Lista de endereços**: Insira os endereços de encaminhamento que seu serviço atribuiu a cada transportadora, separados por vírgulas.", + "title": "Configurações de e-mails encaminhados" + }, + "reconfig_forwarded_emails": { + "data": { + "forwarding_header": "Cabeçalho de encaminhamento (ex. X-SimpleLogin-Original-From)", + "forwarded_emails": "Endereços de e-mail encaminhados" + }, + "data_description": { + "forwarding_header": "Se o seu serviço de encaminhamento inclui o remetente original em um cabeçalho, insira o nome do cabeçalho aqui. Isso tem precedência sobre a lista de endereços abaixo. Insira '(none)' ou deixe em branco para usar a lista de endereços.", + "forwarded_emails": "Lista separada por vírgulas dos endereços de encaminhamento dos quais as mensagens chegarão. Deixe '(none)' se estiver usando o cabeçalho de encaminhamento acima." + }, + "description": "Escolha como corresponder os e-mails encaminhados.\n\n**Opção 1 — Cabeçalho de encaminhamento**: Se o seu serviço (ex. SimpleLogin) inclui o remetente original em um cabeçalho personalizado, insira esse nome de cabeçalho. O Mail and Packages o usará para corresponder os endereços das transportadoras automaticamente.\n\n**Opção 2 — Lista de endereços**: Insira os endereços de encaminhamento que seu serviço atribuiu a cada transportadora, separados por vírgulas.", + "title": "Configurações de e-mails encaminhados" + }, + "imap_config": { + "description": "Por favor, insira as informações de conexão do seu servidor de e-mail.", + "data": { + "host": "Hospedeiro", + "password": "Senha", + "port": "Porta", + "username": "Nome do usuário", + "verify_ssl": "Verificar Certificado SSL", + "imap_security": "Segurança IMAP" + }, + "title": "Correio e pacotes (Etapa 1 de 2)" + }, + "user": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reconfig_imap": { + "data": { + "host": "Hospedeiro", + "password": "Senha", + "port": "Porta", + "username": "Nome do usuário", + "imap_security": "Segurança IMAP", + "verify_ssl": "Verificar Certificado SSL" + }, + "description": "Por favor, insira as informações de conexão do seu servidor de e-mail.", + "title": "Correio e pacotes (Etapa 1 de 2)" + }, + "reconfigure": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reauth_confirm": { + "description": "The authentication for your mail server has expired or is invalid. Please re-authenticate to continue.", + "data": { + "username": "Username", + "password": "Password" + }, + "title": "Re-authenticate Mail Server" + } + } + }, + "selector": { + "auth_type": { + "options": { + "password": "Password", + "oauth2_microsoft": "OAuth2 - Microsoft (Outlook/Exchange)", + "oauth2_google": "OAuth2 - Google (Gmail)" + } + } + } +} diff --git a/custom_components/mail_and_packages/translations/ru.json b/custom_components/mail_and_packages/translations/ru.json new file mode 100644 index 0000000..32f9d3c --- /dev/null +++ b/custom_components/mail_and_packages/translations/ru.json @@ -0,0 +1,203 @@ +{ + "config": { + "abort": { + "single_instance_allowed": "Разрешена только одна конфигурация Почты и Пакетов.", + "reconfigure_successful": "Перенастройка успешно завершена" + }, + "error": { + "cannot_connect": "Невозможно подключиться или войти на почтовый сервер. Пожалуйста, проверьте журнал для деталей.", + "invalid_path": "Пожалуйста, храните изображения в другом каталоге.", + "ffmpeg_not_found": "Для создания MP4 требуется ffmpeg", + "amazon_domain": "Недействительный адрес электронной почты для переадресации.", + "file_not_found": "Файл изображения не найден", + "invalid_email_format": "Неверный формат адреса электронной почты.", + "missing_forwarded_emails": "Отсутствуют переадресованные адреса электронной почты. Вы можете ввести '(none)', чтобы очистить этот параметр.", + "path_not_found": "Директория не найдена", + "invalid_auth": "Invalid authentication details. Please check your username and password.", + "ssl_error": "An SSL error occurred. Change SSL cipher list and try again." + }, + "step": { + "config_2": { + "data": { + "folder": "Папка почты", + "resources": "Список датчиков", + "scan_interval": "Интервал сканирования (минуты)", + "image_path": "Путь к изображению", + "gif_duration": "Длительность изображения (секунды)", + "image_security": "Случайное изображение Имя файла", + "imap_timeout": "Время в секундах до тайм-аута соединения (секунды, минимум 10)", + "generate_mp4": "Создать mp4 из изображений", + "allow_external": "Создать изображение для приложений уведомлений", + "custom_img": "Использовать пользовательское изображение USPS 'нет почты'?", + "amazon_custom_img": "Использовать пользовательское изображение Amazon 'нет доставки'?", + "ups_custom_img": "Использовать пользовательское изображение UPS 'нет доставки'?", + "walmart_custom_img": "Использовать пользовательское изображение Walmart 'нет доставки'?", + "fedex_custom_img": "Использовать пользовательское изображение FedEx 'нет доставки'?", + "generic_custom_img": "Использовать пользовательское изображение общее 'нет доставки'?", + "generate_grid": "Создать сетку изображений для моделей зрения LLM", + "allow_forwarded_emails": "Разрешить переадресованные электронные письма в дополнение к значениям по умолчанию службы (например, no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Завершите настройку, настроив следующие параметры в зависимости от структуры электронной почты и установки Home Assistant. \n\n Подробнее о параметрах [Интеграция с почтой и пакетами] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) см. В разделе [конфигурация, шаблоны и раздел автоматизации] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) на GitHub.", + "title": "Почта и пакеты (шаг 2 из 2)" + }, + "config_3": { + "data": { + "custom_img_file": "Путь к пользовательскому изображению: (например: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (ie: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (ie: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (ie: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (ie: images/my_custom_no_fedex.jpg)" + }, + "description": "Введите путь и имя файла к вашему пользовательскому изображению без почты ниже.\n\nПример: images/custom_nomail.gif", + "title": "Почта и посылки (Шаг 3 из 3)" + }, + "config_amazon": { + "data": { + "amazon_domain": "Домен Amazon", + "amazon_fwds": "Amazon переслал адреса электронной почты", + "amazon_days": "Дни для проверки электронных писем от Amazon" + }, + "description": "Пожалуйста, введите домен, с которого Amazon отправляет электронные письма (например: amazon.com или amazon.de)\n\nЕсли вы используете переадресованные электронные письма от Amazon, разделите каждый адрес запятой или введите (none), чтобы очистить эту настройку.\n\nПримечание: если вы настроили заголовок переадресации на предыдущем шаге, поле адреса переадресации не появится — заголовок автоматически обрабатывает сопоставление писем Amazon.", + "title": "Настройки Amazon" + }, + "reconfig_2": { + "data": { + "folder": "Папка почты", + "scan_interval": "Интервал сканирования (минуты)", + "image_path": "Путь к изображению", + "gif_duration": "Длительность изображения (секунды)", + "image_security": "Случайное изображение Имя файла", + "generate_mp4": "Создать mp4 из изображений", + "resources": "Список датчиков", + "imap_timeout": "Время в секундах до тайм-аута соединения (секунды, минимум 10)", + "allow_external": "Создать изображение для приложений уведомлений", + "custom_img": "Использовать пользовательское изображение USPS 'нет почты'?", + "amazon_custom_img": "Использовать пользовательское изображение Amazon 'нет доставки'?", + "ups_custom_img": "Использовать пользовательское изображение UPS 'нет доставки'?", + "walmart_custom_img": "Использовать пользовательское изображение Walmart 'нет доставки'?", + "fedex_custom_img": "Использовать пользовательское изображение FedEx 'нет доставки'?", + "generic_custom_img": "Использовать пользовательское изображение общее 'нет доставки'?", + "generate_grid": "Создать сетку изображений для моделей зрения LLM", + "allow_forwarded_emails": "Разрешить переадресованные электронные письма в дополнение к значениям по умолчанию службы (например, no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Завершите настройку, настроив следующее в соответствии со структурой вашей электронной почты и установкой Home Assistant.\n\nДля получения подробной информации о вариантах [интеграции Почта и Пакеты](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) ознакомьтесь с [разделом конфигурации, шаблонов и автоматизации](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) на GitHub.\n\nЕсли вы используете переадресованные электронные письма Amazon, разделите каждый адрес запятой или введите (none), чтобы очистить эту настройку.", + "title": "Почта и пакеты (шаг 2 из 2)" + }, + "reconfig_3": { + "data": { + "custom_img_file": "Путь к пользовательскому изображению: (например: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (i.e.: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (i.e.: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (i.e.: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (i.e.: images/my_custom_no_fedex.jpg)" + }, + "description": "Введите путь и имя файла к вашему пользовательскому изображению без почты ниже.\n\nПример: images/custom_nomail.gif", + "title": "Почта и посылки (Шаг 3 из 3)" + }, + "reconfig_amazon": { + "data": { + "amazon_domain": "Домен Amazon", + "amazon_fwds": "Amazon переслал адреса электронной почты", + "amazon_days": "Дни для проверки электронных писем от Amazon" + }, + "description": "Пожалуйста, введите домен, с которого Amazon отправляет электронные письма (например: amazon.com или amazon.de)\n\nЕсли вы используете переадресованные электронные письма от Amazon, разделите каждый адрес запятой или введите (none), чтобы очистить эту настройку.\n\nПримечание: если вы настроили заголовок переадресации на предыдущем шаге, поле адреса переадресации не появится — заголовок автоматически обрабатывает сопоставление писем Amazon.", + "title": "Настройки Amazon" + }, + "config_storage": { + "data": { + "storage": "Каталог для хранения изображений" + }, + "description": "Пожалуйста, введите директорию, в которой вы хотите хранить свои изображения. \nПо умолчанию она заполняется автоматически.", + "title": "Место хранения изображения" + }, + "reconfig_storage": { + "data": { + "storage": "Каталог для хранения изображений" + }, + "description": "Пожалуйста, введите директорию, в которой вы хотите хранить свои изображения. \nПо умолчанию она заполняется автоматически.", + "title": "Место хранения изображения" + }, + "config_forwarded_emails": { + "data": { + "forwarding_header": "Заголовок переадресации (например, X-SimpleLogin-Original-From)", + "forwarded_emails": "Переадресованные адреса электронной почты" + }, + "data_description": { + "forwarding_header": "Если ваш сервис переадресации включает оригинального отправителя в заголовок, введите здесь название заголовка. Это имеет приоритет над списком адресов ниже. Введите '(none)' или оставьте пустым, чтобы использовать список адресов.", + "forwarded_emails": "Список адресов переадресации, разделённых запятыми, с которых будут приходить сообщения. Оставьте '(none)', если используете заголовок переадресации выше." + }, + "description": "Выберите способ сопоставления переадресованных писем.\n\n**Вариант 1 — Заголовок переадресации**: Если ваш сервис (например, SimpleLogin) включает оригинального отправителя в пользовательский заголовок, введите это название заголовка. Mail and Packages будет использовать его для автоматического сопоставления адресов перевозчиков.\n\n**Вариант 2 — Список адресов**: Введите адреса переадресации, которые ваш сервис назначил каждому перевозчику, через запятую.", + "title": "Настройки переадресованных писем" + }, + "reconfig_forwarded_emails": { + "data": { + "forwarding_header": "Заголовок переадресации (например, X-SimpleLogin-Original-From)", + "forwarded_emails": "Переадресованные адреса электронной почты" + }, + "data_description": { + "forwarding_header": "Если ваш сервис переадресации включает оригинального отправителя в заголовок, введите здесь название заголовка. Это имеет приоритет над списком адресов ниже. Введите '(none)' или оставьте пустым, чтобы использовать список адресов.", + "forwarded_emails": "Список адресов переадресации, разделённых запятыми, с которых будут приходить сообщения. Оставьте '(none)', если используете заголовок переадресации выше." + }, + "description": "Выберите способ сопоставления переадресованных писем.\n\n**Вариант 1 — Заголовок переадресации**: Если ваш сервис (например, SimpleLogin) включает оригинального отправителя в пользовательский заголовок, введите это название заголовка. Mail and Packages будет использовать его для автоматического сопоставления адресов перевозчиков.\n\n**Вариант 2 — Список адресов**: Введите адреса переадресации, которые ваш сервис назначил каждому перевозчику, через запятую.", + "title": "Настройки переадресованных писем" + }, + "imap_config": { + "description": "Пожалуйста, введите информацию о подключении к вашему почтовому серверу.", + "data": { + "host": "хозяин", + "password": "пароль", + "port": "порт", + "username": "имя пользователя", + "verify_ssl": "Проверить SSL-сертификат", + "imap_security": "Безопасность IMAP" + }, + "title": "Почта и Пакеты (Шаг 1 из 2)" + }, + "user": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reconfig_imap": { + "data": { + "host": "хозяин", + "password": "пароль", + "port": "порт", + "username": "имя пользователя", + "imap_security": "Безопасность IMAP", + "verify_ssl": "Проверить SSL-сертификат" + }, + "description": "Пожалуйста, введите информацию о подключении к вашему почтовому серверу.", + "title": "Почта и Пакеты (Шаг 1 из 2)" + }, + "reconfigure": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reauth_confirm": { + "description": "The authentication for your mail server has expired or is invalid. Please re-authenticate to continue.", + "data": { + "username": "Username", + "password": "Password" + }, + "title": "Re-authenticate Mail Server" + } + } + }, + "selector": { + "auth_type": { + "options": { + "password": "Password", + "oauth2_microsoft": "OAuth2 - Microsoft (Outlook/Exchange)", + "oauth2_google": "OAuth2 - Google (Gmail)" + } + } + } +} diff --git a/custom_components/mail_and_packages/translations/sk.json b/custom_components/mail_and_packages/translations/sk.json new file mode 100644 index 0000000..373dfb2 --- /dev/null +++ b/custom_components/mail_and_packages/translations/sk.json @@ -0,0 +1,203 @@ +{ + "config": { + "abort": { + "single_instance_allowed": "Je povolená iba jedna konfigurácia pošty a balíkov.", + "reconfigure_successful": "Rekonfigurácia úspešná" + }, + "error": { + "cannot_connect": "Nedá sa pripojiť alebo prihlásiť na poštový server. Podrobnosti nájdete v protokole.", + "invalid_path": "Uložte obrázky do iného adresára.", + "ffmpeg_not_found": "Vytvorenie MP4 vyžaduje ffmpeg", + "amazon_domain": "Neplatná adresa pre presmerovanie e-mailov.", + "file_not_found": "Obrázokový súbor nebol nájdený", + "invalid_email_format": "Neplatný formát e-mailovej adresy.", + "missing_forwarded_emails": "Chýbajú preposielané e-mailové adresy. Môžete zadať '(none)' na vymazanie tohto nastavenia.", + "path_not_found": "Adresár nebol nájdený", + "invalid_auth": "Invalid authentication details. Please check your username and password.", + "ssl_error": "An SSL error occurred. Change SSL cipher list and try again." + }, + "step": { + "config_2": { + "data": { + "folder": "Priečinok pošty", + "resources": "Zoznam senzorov", + "scan_interval": "Interval skenovania (minúty)", + "image_path": "Cesta obrázka", + "gif_duration": "Trvanie obrázka (sekundy)", + "image_security": "Náhodný názov súboru obrázka", + "imap_timeout": "Čas v sekundách pred časovým limitom pripojenia (sekundy, minimálne 10)", + "generate_mp4": "Vytvorte mp4 z obrázkov", + "allow_external": "Vytvorte obrázok pre aplikácie upozornení", + "custom_img": "Použiť vlastný obrázok USPS 'bez pošty'?", + "amazon_custom_img": "Použiť vlastný obrázok Amazon 'bez dodávky'?", + "ups_custom_img": "Použiť vlastný obrázok UPS 'bez dodávky'?", + "walmart_custom_img": "Použiť vlastný obrázok Walmart 'bez dodávky'?", + "fedex_custom_img": "Použiť vlastný obrázok FedEx 'bez dodávky'?", + "generic_custom_img": "Použiť vlastný obrázok všeobecný 'bez dodávky'?", + "generate_grid": "Vytvoriť mriežku obrázkov pre modely videnia LLM", + "allow_forwarded_emails": "Povoliť preposielané e-maily okrem predvolenej hodnoty služby (napr. no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Dokončite konfiguráciu prispôsobením nasledujúcich položiek na základe štruktúry e-mailu a inštalácie Home Assistant.\n\nPodrobnosti nájdete na [Pošta a balíky integrácia](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) možnosti si pozrite v časti [konfigurácia, šablóny a automatizácie](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) na GitHube.", + "title": "Pošta a balíky (krok 2 z 2)" + }, + "config_3": { + "data": { + "custom_img_file": "Cesta k vlastnému obrázku: (napr.: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (ie: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (ie: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (ie: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (ie: images/my_custom_no_fedex.jpg)" + }, + "description": "Zadajte cestu a názov súboru k vášmu vlastnému obrázku bez pošty nižšie.\n\nPríklad: images/custom_nomail.gif", + "title": "Pošta a balíky (Krok 3 z 3)" + }, + "config_amazon": { + "data": { + "amazon_domain": "Doména Amazon", + "amazon_fwds": "Amazon preposlal emailové adresy", + "amazon_days": "Dni späť na kontrolu e-mailov od Amazonu" + }, + "description": "Prosím, zadajte doménu, z ktorej Amazon posiela e-maily (napríklad: amazon.com alebo amazon.de)\n\nAk používate preposlané e-maily od Amazonu, oddelte každú adresu čiarkou alebo zadajte (žiadne) na vymazanie tohto nastavenia.\n\nPoznámka: ak ste v predchádzajúcom kroku nakonfigurovali hlavičku presmerovania, pole s adresou presmerovania sa nezobrazí — hlavička automaticky spracúva zhodu e-mailov Amazon.", + "title": "Nastavenia Amazon" + }, + "reconfig_2": { + "data": { + "folder": "Priečinok pošty", + "scan_interval": "Interval skenovania (minúty)", + "image_path": "Cesta obrázka", + "gif_duration": "Trvanie obrázka (sekundy)", + "image_security": "Náhodný názov súboru obrázka", + "generate_mp4": "Vytvorte mp4 z obrázkov", + "resources": "Zoznam senzorov", + "imap_timeout": "Čas v sekundách pred časovým limitom pripojenia (sekundy, minimálne 10)", + "allow_external": "Vytvorte obrázok pre aplikácie upozornení", + "custom_img": "Použiť vlastný obrázok USPS 'bez pošty'?", + "amazon_custom_img": "Použiť vlastný obrázok Amazon 'bez dodávky'?", + "ups_custom_img": "Použiť vlastný obrázok UPS 'bez dodávky'?", + "walmart_custom_img": "Použiť vlastný obrázok Walmart 'bez dodávky'?", + "fedex_custom_img": "Použiť vlastný obrázok FedEx 'bez dodávky'?", + "generic_custom_img": "Použiť vlastný obrázok všeobecný 'bez dodávky'?", + "generate_grid": "Vytvoriť mriežku obrázkov pre modely videnia LLM", + "allow_forwarded_emails": "Povoliť preposielané e-maily okrem predvolenej hodnoty služby (napr. no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Dokončite konfiguráciu prispôsobením nasledujúceho na základe štruktúry vášho e-mailu a inštalácie Home Assistant.\n\nPre podrobnosti o možnostiach [integrácie Mail a Packages](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) si prečítajte [sekciu o konfigurácii, šablónach a automatizáciách](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) na GitHub.\n\nAk používate preposlané e-maily od Amazonu, oddelte každú adresu čiarkou alebo zadajte (none) na vymazanie tohto nastavenia.", + "title": "Pošta a balíky (krok 2 z 2)" + }, + "reconfig_3": { + "data": { + "custom_img_file": "Cesta k vlastnému obrázku: (napr.: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (i.e.: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (i.e.: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (i.e.: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (i.e.: images/my_custom_no_fedex.jpg)" + }, + "description": "Zadajte cestu a názov súboru k vášmu vlastnému obrázku bez pošty nižšie.\n\nPríklad: images/custom_nomail.gif", + "title": "Pošta a balíky (Krok 3 z 3)" + }, + "reconfig_amazon": { + "data": { + "amazon_domain": "Doména Amazon", + "amazon_fwds": "Amazon preposlal emailové adresy", + "amazon_days": "Dni späť na kontrolu e-mailov od Amazonu" + }, + "description": "Prosím, zadajte doménu, z ktorej Amazon posiela e-maily (napríklad: amazon.com alebo amazon.de)\n\nAk používate preposlané e-maily od Amazonu, oddelte každú adresu čiarkou alebo zadajte (žiadne) na vymazanie tohto nastavenia.\n\nPoznámka: ak ste v predchádzajúcom kroku nakonfigurovali hlavičku presmerovania, pole s adresou presmerovania sa nezobrazí — hlavička automaticky spracúva zhodu e-mailov Amazon.", + "title": "Nastavenia Amazon" + }, + "config_storage": { + "data": { + "storage": "Adresár na ukladanie obrázkov" + }, + "description": "Prosím, zadajte adresár, v ktorom chcete ukladať svoje obrázky.\nPredvolená hodnota je automaticky vyplnená.", + "title": "Miesto ukladania obrázkov" + }, + "reconfig_storage": { + "data": { + "storage": "Adresár na ukladanie obrázkov" + }, + "description": "Prosím, zadajte adresár, v ktorom chcete ukladať svoje obrázky.\nPredvolená hodnota je automaticky vyplnená.", + "title": "Miesto ukladania obrázkov" + }, + "config_forwarded_emails": { + "data": { + "forwarding_header": "Hlavička presmerovania (napr. X-SimpleLogin-Original-From)", + "forwarded_emails": "Preposielané e-mailové adresy" + }, + "data_description": { + "forwarding_header": "Ak vaša služba presmerovania zahŕňa pôvodného odosielateľa v hlavičke, zadajte tu názov hlavičky. Toto má prednosť pred zoznamom adries nižšie. Zadajte '(none)' alebo nechajte prázdne, aby ste namiesto toho použili zoznam adries.", + "forwarded_emails": "Zoznam presmerovacích adries oddelených čiarkami, z ktorých budú prichádzať správy. Ponechajte '(none)', ak používate vyššie uvedenú hlavičku presmerovania." + }, + "description": "Vyberte spôsob porovnávania presmerovaných e-mailov.\n\n**Možnosť 1 — Hlavička presmerovania**: Ak vaša služba (napr. SimpleLogin) zahŕňa pôvodného odosielateľa do vlastnej hlavičky, zadajte názov tej hlavičky. Mail and Packages ho použije na automatické priradenie adries dopravcov.\n\n**Možnosť 2 — Zoznam adries**: Zadajte presmerovavacie adresy, ktoré vaša služba priradila každému dopravcovi, oddelené čiarkami.", + "title": "Nastavenia presmerovaných e-mailov" + }, + "reconfig_forwarded_emails": { + "data": { + "forwarding_header": "Hlavička presmerovania (napr. X-SimpleLogin-Original-From)", + "forwarded_emails": "Preposielané e-mailové adresy" + }, + "data_description": { + "forwarding_header": "Ak vaša služba presmerovania zahŕňa pôvodného odosielateľa v hlavičke, zadajte tu názov hlavičky. Toto má prednosť pred zoznamom adries nižšie. Zadajte '(none)' alebo nechajte prázdne, aby ste namiesto toho použili zoznam adries.", + "forwarded_emails": "Zoznam presmerovacích adries oddelených čiarkami, z ktorých budú prichádzať správy. Ponechajte '(none)', ak používate vyššie uvedenú hlavičku presmerovania." + }, + "description": "Vyberte spôsob porovnávania presmerovaných e-mailov.\n\n**Možnosť 1 — Hlavička presmerovania**: Ak vaša služba (napr. SimpleLogin) zahŕňa pôvodného odosielateľa do vlastnej hlavičky, zadajte názov tej hlavičky. Mail and Packages ho použije na automatické priradenie adries dopravcov.\n\n**Možnosť 2 — Zoznam adries**: Zadajte presmerovavacie adresy, ktoré vaša služba priradila každému dopravcovi, oddelené čiarkami.", + "title": "Nastavenia presmerovaných e-mailov" + }, + "imap_config": { + "description": "Prosím, zadajte informácie o pripojení k vášmu mailovému serveru.", + "data": { + "host": "Host", + "password": "Heslo", + "port": "Port", + "username": "Užívateľské meno", + "verify_ssl": "Overiť SSL certifikát", + "imap_security": "Bezpečnosť IMAP" + }, + "title": "Pošta a balíky (1. krok z 2)" + }, + "user": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reconfig_imap": { + "data": { + "host": "Host", + "password": "Heslo", + "port": "Port", + "username": "Užívateľské meno", + "imap_security": "Bezpečnosť IMAP", + "verify_ssl": "Overiť SSL certifikát" + }, + "description": "Prosím, zadajte informácie o pripojení k vášmu mailovému serveru.", + "title": "Pošta a balíky (1. krok z 2)" + }, + "reconfigure": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reauth_confirm": { + "description": "The authentication for your mail server has expired or is invalid. Please re-authenticate to continue.", + "data": { + "username": "Username", + "password": "Password" + }, + "title": "Re-authenticate Mail Server" + } + } + }, + "selector": { + "auth_type": { + "options": { + "password": "Password", + "oauth2_microsoft": "OAuth2 - Microsoft (Outlook/Exchange)", + "oauth2_google": "OAuth2 - Google (Gmail)" + } + } + } +} diff --git a/custom_components/mail_and_packages/translations/sl.json b/custom_components/mail_and_packages/translations/sl.json new file mode 100644 index 0000000..f203fb1 --- /dev/null +++ b/custom_components/mail_and_packages/translations/sl.json @@ -0,0 +1,203 @@ +{ + "config": { + "abort": { + "single_instance_allowed": "Dovoljena je samo ena konfiguracija pošte in paketov.", + "reconfigure_successful": "Prekonfiguracija uspešna" + }, + "error": { + "cannot_connect": "Poštnega strežnika ni mogoče povezati ali prijaviti. Za podrobnosti preverite dnevnik.", + "invalid_path": "Shranite slike v drugem imeniku.", + "ffmpeg_not_found": "Ustvarjanje MP4 zahteva ffmpeg", + "amazon_domain": "Neveljaven naslov za preusmerjanje e-pošte.", + "file_not_found": "Slikovna datoteka ni najdena", + "invalid_email_format": "Neveljaven format e-poštnega naslova.", + "missing_forwarded_emails": "Manjkajo posredovani e-poštni naslovi. Vnesete lahko '(none)' za izbris te nastavitve.", + "path_not_found": "Mapa ni najdena", + "invalid_auth": "Invalid authentication details. Please check your username and password.", + "ssl_error": "An SSL error occurred. Change SSL cipher list and try again." + }, + "step": { + "config_2": { + "data": { + "folder": "Mapa mape", + "resources": "Seznam senzorjev", + "scan_interval": "Interval optičnega branja (minute)", + "image_path": "Pot slike", + "gif_duration": "Trajanje slike (sekunde)", + "image_security": "Naključno ime datoteke", + "imap_timeout": "Čas v sekundah pred prekinitvijo povezave (sekunde, najmanj 10)", + "generate_mp4": "Ustvari mp4 iz slik", + "allow_external": "Ustvari sliko za aplikacije za obvestila", + "custom_img": "Uporabite prilagojeno sliko USPS 'brez pošte'?", + "amazon_custom_img": "Uporabite prilagojeno sliko Amazon 'brez dostave'?", + "ups_custom_img": "Uporabite prilagojeno sliko UPS 'brez dostave'?", + "walmart_custom_img": "Uporabite prilagojeno sliko Walmart 'brez dostave'?", + "fedex_custom_img": "Uporabite prilagojeno sliko FedEx 'brez dostave'?", + "generic_custom_img": "Uporabite prilagojeno splošno sliko 'brez dostave'?", + "generate_grid": "Ustvari mrežo slik za vizualne modele LLM", + "allow_forwarded_emails": "Dovoli posredovane e-poštne sporočila poleg privzete vrednosti storitve (npr. no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Končajte konfiguracijo s prilagoditvijo naslednjih na podlagi strukture e-pošte in namestitve Home Assistant. \n\n Za podrobnosti o možnostih [Integracija pošte in paketov] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) preglejte [konfiguracijo, predloge in oddelku za avtomatizacije] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) na GitHubu.", + "title": "Pošta in paketi (2. korak od 2)" + }, + "config_3": { + "data": { + "custom_img_file": "Pot do prilagojene slike: (npr.: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (ie: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (ie: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (ie: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (ie: images/my_custom_no_fedex.jpg)" + }, + "description": "V spodnje polje vnesite pot in ime datoteke do vaše prilagojene slike brez pošte.\n\nPrimer: images/custom_nomail.gif", + "title": "Pošta in paketi (Korak 3 od 3)" + }, + "config_amazon": { + "data": { + "amazon_domain": "Amazon domena", + "amazon_fwds": "Amazon je posredoval e-poštne naslove", + "amazon_days": "Dnevi nazaj za preverjanje Amazonovih e-poštnih sporočil" + }, + "description": "Prosimo, vnesite domeno, s katere Amazon pošilja e-pošto (npr.: amazon.com ali amazon.de)\n\nČe uporabljate preusmerjena e-poštna sporočila Amazon, ločite vsak naslov z vejico ali vnesite (noben) za izbris te nastavitve.\n\nOpomba: če ste v prejšnjem koraku konfigurirali glavo posredovanja, polje z naslovom posredovanja ne bo prikazano — glava samodejno obravnava ujemanje Amazonovih e-poštnih sporočil.", + "title": "Nastavitve Amazon" + }, + "reconfig_2": { + "data": { + "folder": "Mapa mape", + "scan_interval": "Interval optičnega branja (minute)", + "image_path": "Pot slike", + "gif_duration": "Trajanje slike (sekunde)", + "image_security": "Naključno ime datoteke", + "generate_mp4": "Ustvari mp4 iz slik", + "resources": "Seznam senzorjev", + "imap_timeout": "Čas v sekundah pred prekinitvijo povezave (sekunde, najmanj 10)", + "allow_external": "Ustvari sliko za aplikacije za obvestila", + "custom_img": "Uporabite prilagojeno sliko USPS 'brez pošte'?", + "amazon_custom_img": "Uporabite prilagojeno sliko Amazon 'brez dostave'?", + "ups_custom_img": "Uporabite prilagojeno sliko UPS 'brez dostave'?", + "walmart_custom_img": "Uporabite prilagojeno sliko Walmart 'brez dostave'?", + "fedex_custom_img": "Uporabite prilagojeno sliko FedEx 'brez dostave'?", + "generic_custom_img": "Uporabite prilagojeno splošno sliko 'brez dostave'?", + "generate_grid": "Ustvari mrežo slik za vizualne modele LLM", + "allow_forwarded_emails": "Dovoli posredovane e-poštne sporočila poleg privzete vrednosti storitve (npr. no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Konfiguracijo dokončajte z prilagajanjem naslednjega glede na strukturo vašega e-poštnega sporočila in namestitev Home Assistant.\n\nZa podrobnosti o možnostih [integracije Mail and Packages](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) si oglejte [razdelek o konfiguraciji, predlogah in avtomatizacijah](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) na GitHubu.\n\nČe uporabljate preusmerjena e-poštna sporočila Amazon, ločite vsak naslov z vejico ali vnesite (noben) za izbris te nastavitve.", + "title": "Pošta in paketi (2. korak od 2)" + }, + "reconfig_3": { + "data": { + "custom_img_file": "Pot do prilagojene slike: (npr.: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (i.e.: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (i.e.: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (i.e.: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (i.e.: images/my_custom_no_fedex.jpg)" + }, + "description": "V spodnje polje vnesite pot in ime datoteke do vaše prilagojene slike brez pošte.\n\nPrimer: images/custom_nomail.gif", + "title": "Pošta in paketi (korak 3 od 3)" + }, + "reconfig_amazon": { + "data": { + "amazon_domain": "Amazon domena", + "amazon_fwds": "Amazon je posredoval e-poštne naslove", + "amazon_days": "Dnevi nazaj za preverjanje Amazonovih e-poštnih sporočil" + }, + "description": "Prosimo, vnesite domeno, s katere Amazon pošilja e-pošto (npr.: amazon.com ali amazon.de)\n\nČe uporabljate preusmerjena e-poštna sporočila Amazon, ločite vsak naslov z vejico ali vnesite (noben) za izbris te nastavitve.\n\nOpomba: če ste v prejšnjem koraku konfigurirali glavo posredovanja, polje z naslovom posredovanja ne bo prikazano — glava samodejno obravnava ujemanje Amazonovih e-poštnih sporočil.", + "title": "Nastavitve Amazon" + }, + "config_storage": { + "data": { + "storage": "Mapa za shranjevanje slik" + }, + "description": "Prosimo, vnesite imenik, v katerem želite shraniti svoje slike.\nPrivzeto je samodejno izpolnjeno.", + "title": "Lokacija shranjevanja slik" + }, + "reconfig_storage": { + "data": { + "storage": "Mapa za shranjevanje slik" + }, + "description": "Prosimo, vnesite imenik, v katerem želite shraniti svoje slike.\nPrivzeto je samodejno izpolnjeno.", + "title": "Lokacija shranjevanja slik" + }, + "config_forwarded_emails": { + "data": { + "forwarding_header": "Glava za posredovanje (npr. X-SimpleLogin-Original-From)", + "forwarded_emails": "Posredovani e-poštni naslovi" + }, + "data_description": { + "forwarding_header": "Če vaša storitev posredovanja vključuje izvirnega pošiljatelja v glavi, vnesite tukaj ime glave. To ima prednost pred spodnjim seznamom naslovov. Vnesite '(none)' ali pustite prazno, da namesto tega uporabite seznam naslovov.", + "forwarded_emails": "Z vejicami ločen seznam naslovov za posredovanje, od katerih bodo prihajala sporočila. Pustite '(none)', če uporabljate zgornjo glavo za posredovanje." + }, + "description": "Izberite, kako ujemati posredovana e-poštna sporočila.\n\n**Možnost 1 — Glava za posredovanje**: Če vaša storitev (npr. SimpleLogin) vključuje izvirnega pošiljatelja v glavo po meri, vnesite ime te glave. Mail and Packages jo bo uporabil za samodejno ujemanje naslovov prevoznikov.\n\n**Možnost 2 — Seznam naslovov**: Vnesite naslove za posredovanje, ki jih je vaša storitev dodelila vsakemu prevozniku, ločene z vejicami.", + "title": "Nastavitve posredovane e-pošte" + }, + "reconfig_forwarded_emails": { + "data": { + "forwarding_header": "Glava za posredovanje (npr. X-SimpleLogin-Original-From)", + "forwarded_emails": "Posredovani e-poštni naslovi" + }, + "data_description": { + "forwarding_header": "Če vaša storitev posredovanja vključuje izvirnega pošiljatelja v glavi, vnesite tukaj ime glave. To ima prednost pred spodnjim seznamom naslovov. Vnesite '(none)' ali pustite prazno, da namesto tega uporabite seznam naslovov.", + "forwarded_emails": "Z vejicami ločen seznam naslovov za posredovanje, od katerih bodo prihajala sporočila. Pustite '(none)', če uporabljate zgornjo glavo za posredovanje." + }, + "description": "Izberite, kako ujemati posredovana e-poštna sporočila.\n\n**Možnost 1 — Glava za posredovanje**: Če vaša storitev (npr. SimpleLogin) vključuje izvirnega pošiljatelja v glavo po meri, vnesite ime te glave. Mail and Packages jo bo uporabil za samodejno ujemanje naslovov prevoznikov.\n\n**Možnost 2 — Seznam naslovov**: Vnesite naslove za posredovanje, ki jih je vaša storitev dodelila vsakemu prevozniku, ločene z vejicami.", + "title": "Nastavitve posredovane e-pošte" + }, + "imap_config": { + "description": "Prosimo, vnesite podatke o povezavi vašega poštnega strežnika.", + "data": { + "host": "Gostitelj", + "password": "Geslo", + "port": "Pristanišče", + "username": "Uporabniško ime", + "verify_ssl": "Preveri SSL certifikat", + "imap_security": "Varnost IMAP" + }, + "title": "Pošta in paketi (1. korak od 2)" + }, + "user": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reconfig_imap": { + "data": { + "host": "Gostitelj", + "password": "Geslo", + "port": "Pristanišče", + "username": "Uporabniško ime", + "imap_security": "Varnost IMAP", + "verify_ssl": "Preveri SSL certifikat" + }, + "description": "Prosimo, vnesite podatke o povezavi vašega poštnega strežnika.", + "title": "Pošta in paketi (1. korak od 2)" + }, + "reconfigure": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reauth_confirm": { + "description": "The authentication for your mail server has expired or is invalid. Please re-authenticate to continue.", + "data": { + "username": "Username", + "password": "Password" + }, + "title": "Re-authenticate Mail Server" + } + } + }, + "selector": { + "auth_type": { + "options": { + "password": "Password", + "oauth2_microsoft": "OAuth2 - Microsoft (Outlook/Exchange)", + "oauth2_google": "OAuth2 - Google (Gmail)" + } + } + } +} diff --git a/custom_components/mail_and_packages/translations/sv.json b/custom_components/mail_and_packages/translations/sv.json new file mode 100644 index 0000000..77ae548 --- /dev/null +++ b/custom_components/mail_and_packages/translations/sv.json @@ -0,0 +1,203 @@ +{ + "config": { + "abort": { + "single_instance_allowed": "Endast en enda konfiguration av post och paket är tillåten.", + "reconfigure_successful": "Omkonfigurering lyckades" + }, + "error": { + "cannot_connect": "Det går inte att ansluta eller logga in på e-postservern. Kontrollera loggen för mer information.", + "invalid_path": "Förvara bilderna i en annan katalog.", + "ffmpeg_not_found": "Generera MP4 kräver ffmpeg", + "amazon_domain": "Ogiltig vidarebefordrings e-postadress.", + "file_not_found": "Bildfilen hittades inte", + "invalid_email_format": "Ogiltigt format för e-postadress.", + "missing_forwarded_emails": "Saknade vidarebefordrade e-postadresser. Du kan ange '(none)' för att rensa denna inställning.", + "path_not_found": "Katalogen hittades inte", + "invalid_auth": "Invalid authentication details. Please check your username and password.", + "ssl_error": "An SSL error occurred. Change SSL cipher list and try again." + }, + "step": { + "config_2": { + "data": { + "folder": "E-postmapp", + "resources": "Sensorlista", + "scan_interval": "Skanningsintervall (minuter)", + "image_path": "Bildväg", + "gif_duration": "Bildens längd (sekunder)", + "image_security": "Slumpmässig bildfilnamn", + "imap_timeout": "Tid i sekunder innan anslutningen kopplas från (sekunder, minst 10)", + "generate_mp4": "Skapa mp4 från bilder", + "allow_external": "Skapa bild för notifikationsappar", + "custom_img": "Använd anpassad USPS 'inget post' bild?", + "amazon_custom_img": "Använd anpassad Amazon 'ingen leverans' bild?", + "ups_custom_img": "Använd anpassad UPS 'ingen leverans' bild?", + "walmart_custom_img": "Använd anpassad Walmart 'ingen leverans' bild?", + "fedex_custom_img": "Använd anpassad FedEx 'ingen leverans' bild?", + "generic_custom_img": "Använd anpassad generisk 'ingen leverans' bild?", + "generate_grid": "Skapa bildrutnät för LLM-visionsmodeller", + "allow_forwarded_emails": "Tillåt vidarebefordrade e-postmeddelanden utöver en tjänsts standardvärde (t.ex. no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Avsluta konfigurationen genom att anpassa följande baserat på din e-poststruktur och installation av hemassistent. \n\n Mer information om alternativen [Mail and Packages] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) läser [konfiguration, mallar , och automatiseringsavsnitt] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) på GitHub.", + "title": "Mail och paket (steg 2 av 2)" + }, + "config_3": { + "data": { + "custom_img_file": "Sökväg till anpassad bild: (t.ex: bilder/min_anpassade_ingen_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (ie: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (ie: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (ie: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (ie: images/my_custom_no_fedex.jpg)" + }, + "description": "Ange sökvägen och filnamnet till din anpassade ingen post-bild nedan.\n\nExempel: bilder/anpassad_nomail.gif", + "title": "Post och paket (Steg 3 av 3)" + }, + "config_amazon": { + "data": { + "amazon_domain": "Amazon domän", + "amazon_fwds": "Amazon vidarebefordrade e-postadresser", + "amazon_days": "Dagar tillbaka för att kontrollera Amazon-e-postmeddelanden" + }, + "description": "Vänligen ange domänen som Amazon skickar e-postmeddelanden från (t.ex: amazon.com eller amazon.de)\n\nOm du använder Amazon vidarebefordrade e-postmeddelanden, vänligen separera varje adress med ett kommatecken eller ange (ingen) för att rensa denna inställning.\n\nObs: om du konfigurerade ett vidarebefordringshuvud i föregående steg kommer fältet för vidarebefordringsadress inte att visas — huvudet hanterar Amazon e-postkopplingen automatiskt.", + "title": "Amazon-inställningar" + }, + "reconfig_2": { + "data": { + "folder": "E-postmapp", + "scan_interval": "Skanningsintervall (minuter)", + "image_path": "Bildväg", + "gif_duration": "Bildens längd (sekunder)", + "image_security": "Slumpmässig bildfilnamn", + "generate_mp4": "Skapa mp4 från bilder", + "resources": "Sensorlista", + "imap_timeout": "Tid i sekunder innan anslutningen kopplas från (sekunder, minst 10)", + "allow_external": "Skapa bild för notifikationsappar", + "custom_img": "Använd anpassad USPS 'inget post' bild?", + "amazon_custom_img": "Använd anpassad Amazon 'ingen leverans' bild?", + "ups_custom_img": "Använd anpassad UPS 'ingen leverans' bild?", + "walmart_custom_img": "Använd anpassad Walmart 'ingen leverans' bild?", + "fedex_custom_img": "Använd anpassad FedEx 'ingen leverans' bild?", + "generic_custom_img": "Använd anpassad generisk 'ingen leverans' bild?", + "generate_grid": "Skapa bildrutnät för LLM-visionsmodeller", + "allow_forwarded_emails": "Tillåt vidarebefordrade e-postmeddelanden utöver en tjänsts standardvärde (t.ex. no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "Slutför konfigurationen genom att anpassa följande baserat på din e-poststruktur och Home Assistant-installation.\n\nFör detaljer om [Mail and Packages integration](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) alternativen granska [konfiguration, mallar och automatiseringssektionen](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) på GitHub.\n\nOm du använder vidarebefordrade e-postmeddelanden från Amazon, separera varje adress med ett kommatecken eller ange (ingen) för att rensa denna inställning.", + "title": "Mail och paket (steg 2 av 2)" + }, + "reconfig_3": { + "data": { + "custom_img_file": "Sökväg till anpassad bild: (t.ex.: bilder/min_anpassade_ingen_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (i.e.: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (i.e.: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (i.e.: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (i.e.: images/my_custom_no_fedex.jpg)" + }, + "description": "Ange sökvägen och filnamnet till din anpassade ingen post-bild nedan.\n\nExempel: bilder/anpassad_nomail.gif", + "title": "Post och paket (Steg 3 av 3)" + }, + "reconfig_amazon": { + "data": { + "amazon_domain": "Amazon domän", + "amazon_fwds": "Amazon vidarebefordrade e-postadresser", + "amazon_days": "Dagar tillbaka för att kontrollera Amazon-e-postmeddelanden" + }, + "description": "Vänligen ange domänen som Amazon skickar e-postmeddelanden från (t.ex: amazon.com eller amazon.de)\n\nOm du använder Amazon vidarebefordrade e-postmeddelanden, vänligen separera varje adress med ett kommatecken eller ange (ingen) för att rensa denna inställning.\n\nObs: om du konfigurerade ett vidarebefordringshuvud i föregående steg kommer fältet för vidarebefordringsadress inte att visas — huvudet hanterar Amazon e-postkopplingen automatiskt.", + "title": "Amazon-inställningar" + }, + "config_storage": { + "data": { + "storage": "Katalog för att lagra bilder" + }, + "description": "Vänligen ange den katalog du vill att dina bilder ska lagras i.\nStandardinställningen är automatiskt ifylld.", + "title": "Bildlagringsplats" + }, + "reconfig_storage": { + "data": { + "storage": "Katalog för att lagra bilder" + }, + "description": "Vänligen ange den katalog du vill att dina bilder ska lagras i.\nStandardinställningen är automatiskt ifylld.", + "title": "Bildlagringsplats" + }, + "config_forwarded_emails": { + "data": { + "forwarding_header": "Vidarebefordringshuvud (t.ex. X-SimpleLogin-Original-From)", + "forwarded_emails": "Vidarebefordrade e-postadresser" + }, + "data_description": { + "forwarding_header": "Om din vidarebefordringstjänst inkluderar den ursprungliga avsändaren i ett huvud, ange huvud-namnet här. Detta har företräde framför adresslistan nedan. Ange '(none)' eller lämna tomt för att använda adresslistan istället.", + "forwarded_emails": "Kommaseparerad lista över vidarebefordringsadresser som meddelanden kommer att anlända från. Lämna '(none)' om du använder vidarebefordringshuvudet ovan." + }, + "description": "Välj hur vidarebefordrade e-postmeddelanden ska matchas.\n\n**Alternativ 1 — Vidarebefordringshuvud**: Om din tjänst (t.ex. SimpleLogin) inkluderar den ursprungliga avsändaren i ett anpassat huvud, ange det huvud-namnet. Mail and Packages kommer att använda det för att automatiskt matcha transportörernas adresser.\n\n**Alternativ 2 — Adresslista**: Ange de vidarebefordringsadresser som din tjänst har tilldelat varje transportör, separerade med kommatecken.", + "title": "Inställningar för vidarebefordrade e-postmeddelanden" + }, + "reconfig_forwarded_emails": { + "data": { + "forwarding_header": "Vidarebefordringshuvud (t.ex. X-SimpleLogin-Original-From)", + "forwarded_emails": "Vidarebefordrade e-postadresser" + }, + "data_description": { + "forwarding_header": "Om din vidarebefordringstjänst inkluderar den ursprungliga avsändaren i ett huvud, ange huvud-namnet här. Detta har företräde framför adresslistan nedan. Ange '(none)' eller lämna tomt för att använda adresslistan istället.", + "forwarded_emails": "Kommaseparerad lista över vidarebefordringsadresser som meddelanden kommer att anlända från. Lämna '(none)' om du använder vidarebefordringshuvudet ovan." + }, + "description": "Välj hur vidarebefordrade e-postmeddelanden ska matchas.\n\n**Alternativ 1 — Vidarebefordringshuvud**: Om din tjänst (t.ex. SimpleLogin) inkluderar den ursprungliga avsändaren i ett anpassat huvud, ange det huvud-namnet. Mail and Packages kommer att använda det för att automatiskt matcha transportörernas adresser.\n\n**Alternativ 2 — Adresslista**: Ange de vidarebefordringsadresser som din tjänst har tilldelat varje transportör, separerade med kommatecken.", + "title": "Inställningar för vidarebefordrade e-postmeddelanden" + }, + "imap_config": { + "description": "Vänligen ange anslutningsinformationen för din e-postserver.", + "data": { + "host": "Värd", + "password": "Lösenord", + "port": "Hamn", + "username": "Användarnamn", + "verify_ssl": "Verifiera SSL-certifikat", + "imap_security": "IMAP-säkerhet" + }, + "title": "Mail och paket (steg 1 av 2)" + }, + "user": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reconfig_imap": { + "data": { + "host": "Värd", + "password": "Lösenord", + "port": "Hamn", + "username": "Användarnamn", + "imap_security": "IMAP-säkerhet", + "verify_ssl": "Verifiera SSL-certifikat" + }, + "description": "Vänligen ange anslutningsinformationen för din e-postserver.", + "title": "Mail och paket (steg 1 av 2)" + }, + "reconfigure": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reauth_confirm": { + "description": "The authentication for your mail server has expired or is invalid. Please re-authenticate to continue.", + "data": { + "username": "Username", + "password": "Password" + }, + "title": "Re-authenticate Mail Server" + } + } + }, + "selector": { + "auth_type": { + "options": { + "password": "Password", + "oauth2_microsoft": "OAuth2 - Microsoft (Outlook/Exchange)", + "oauth2_google": "OAuth2 - Google (Gmail)" + } + } + } +} diff --git a/custom_components/mail_and_packages/translations/zh_Hant_HK.json b/custom_components/mail_and_packages/translations/zh_Hant_HK.json new file mode 100644 index 0000000..27df481 --- /dev/null +++ b/custom_components/mail_and_packages/translations/zh_Hant_HK.json @@ -0,0 +1,203 @@ +{ + "config": { + "abort": { + "single_instance_allowed": "僅允許郵件和軟件包的單個配置。", + "reconfigure_successful": "重新配置成功" + }, + "error": { + "cannot_connect": "無法連接或登錄到郵件服務器。請檢查日誌以獲取詳細信息。", + "invalid_path": "請將圖像存儲在另一個目錄中。", + "ffmpeg_not_found": "生成MP4需要ffmpeg", + "amazon_domain": "無效的轉發電郵地址。", + "file_not_found": "找不到圖像檔案", + "invalid_email_format": "無效的電郵地址格式。", + "missing_forwarded_emails": "缺少轉發的電郵地址。您可以輸入 '(none)' 來清除此設定。", + "path_not_found": "找不到目錄", + "invalid_auth": "Invalid authentication details. Please check your username and password.", + "ssl_error": "An SSL error occurred. Change SSL cipher list and try again." + }, + "step": { + "config_2": { + "data": { + "folder": "郵件文件夾", + "resources": "感應器列表", + "scan_interval": "掃描間隔(分鐘)", + "image_path": "圖像路徑", + "gif_duration": "圖像持續時間(秒)", + "image_security": "隨機圖像文件名", + "imap_timeout": "連接超時前的時間(秒,最少10秒)", + "generate_mp4": "從圖像創建mp4", + "allow_external": "為通知應用程式創建圖像", + "custom_img": "使用自訂的 USPS「無郵件」圖像?", + "amazon_custom_img": "使用自訂的 Amazon「無送貨」圖像?", + "ups_custom_img": "使用自訂的 UPS「無送貨」圖像?", + "walmart_custom_img": "使用自訂的 Walmart「無送貨」圖像?", + "fedex_custom_img": "使用自訂的 FedEx「無送貨」圖像?", + "generic_custom_img": "使用自訂的通用「無送貨」圖像?", + "generate_grid": "為LLM視覺模型創建圖像網格", + "allow_forwarded_emails": "允許轉發的電郵,除了服務的預設值(例如 no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "通過根據您的電子郵件結構和Home Assistant安裝自定義以下內容來完成配置。 \n\n有關[郵件和軟件包集成](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration)選項的詳細信息,請查看[配置,模板和自動化部分](GitHub上的https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration)。", + "title": "郵件和包裹(第2步,共2步)" + }, + "config_3": { + "data": { + "custom_img_file": "自訂圖片的路徑:(例如:images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (ie: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (ie: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (ie: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (ie: images/my_custom_no_fedex.jpg)" + }, + "description": "在下方輸入您的自訂無郵件圖像的路徑和檔案名稱。\n\n例如:images/custom_nomail.gif", + "title": "郵件和包裹(第3步,共3步)" + }, + "config_amazon": { + "data": { + "amazon_domain": "Amazon 域名", + "amazon_fwds": "Amazon 轉發的電郵地址", + "amazon_days": "檢查Amazon電郵的天數" + }, + "description": "請輸入亞馬遜發送電子郵件的域名(例如:amazon.com或amazon.de)\n\n如果使用亞馬遜轉發的電子郵件,請用逗號分隔每個地址,或輸入(無)以清除此設定。\n\n注意:如果您在上一步中設定了轉寄標頭,轉寄地址欄位將不會顯示 — 標頭會自動處理 Amazon 電郵的配對。", + "title": "Amazon 設定" + }, + "reconfig_2": { + "data": { + "folder": "郵件文件夾", + "scan_interval": "掃描間隔(分鐘)", + "image_path": "圖像路徑", + "gif_duration": "圖像持續時間(秒)", + "image_security": "隨機圖像文件名", + "generate_mp4": "從圖像創建mp4", + "resources": "感應器列表", + "imap_timeout": "連接超時前的時間(秒,最少10秒)", + "allow_external": "為通知應用程式創建圖像", + "custom_img": "使用自訂的 USPS「無郵件」圖像?", + "amazon_custom_img": "使用自訂的 Amazon「無送貨」圖像?", + "ups_custom_img": "使用自訂的 UPS「無送貨」圖像?", + "walmart_custom_img": "使用自訂的 Walmart「無送貨」圖像?", + "fedex_custom_img": "使用自訂的 FedEx「無送貨」圖像?", + "generic_custom_img": "使用自訂的通用「無送貨」圖像?", + "generate_grid": "為LLM視覺模型創建圖像網格", + "allow_forwarded_emails": "允許轉發的電郵,除了服務的預設值(例如 no-reply@usps.com)", + "custom_days": "Days back to check for package emails (minimum 1, default 3)" + }, + "description": "根據您的電郵結構和Home Assistant安裝來完成配置。\n\n有關[郵件和包裹整合](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration)選項的詳情,請查閱GitHub上的[配置、模板和自動化部分](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration)。\n\n如果使用Amazon轉發的電郵,請用逗號分隔每個地址,或輸入(none)以清除此設定。", + "title": "郵件和包裹(第2步,共2步)" + }, + "reconfig_3": { + "data": { + "custom_img_file": "Path to custom image: (i.e.: images/my_custom_no_mail.jpg)", + "amazon_custom_img_file": "Path to custom Amazon image: (i.e.: images/my_custom_no_amazon.jpg)", + "ups_custom_img_file": "Path to custom UPS image: (i.e.: images/my_custom_no_ups.jpg)", + "walmart_custom_img_file": "Path to custom Walmart image: (i.e.: images/my_custom_no_walmart.jpg)", + "fedex_custom_img_file": "Path to custom FedEx image: (i.e.: images/my_custom_no_fedex.jpg)" + }, + "description": "在下方輸入您的自訂無郵件圖像的路徑和檔案名稱。\n\n例如:images/custom_nomail.gif", + "title": "郵件和包裹(第3步,共3步)" + }, + "reconfig_amazon": { + "data": { + "amazon_domain": "Amazon 域名", + "amazon_fwds": "Amazon 轉發的電郵地址", + "amazon_days": "檢查Amazon電郵的天數" + }, + "description": "請輸入亞馬遜發送電子郵件的域名(例如:amazon.com或amazon.de)\n\n如果使用亞馬遜轉發的電子郵件,請用逗號分隔每個地址,或輸入(無)以清除此設定。\n\n注意:如果您在上一步中設定了轉寄標頭,轉寄地址欄位將不會顯示 — 標頭會自動處理 Amazon 電郵的配對。", + "title": "Amazon 設定" + }, + "config_storage": { + "data": { + "storage": "儲存圖片的目錄" + }, + "description": "請輸入您希望存儲圖像的目錄。\n預設值會自動填充。", + "title": "圖像儲存位置" + }, + "reconfig_storage": { + "data": { + "storage": "儲存圖片的目錄" + }, + "description": "請輸入您希望存儲圖像的目錄。\n預設值會自動填充。", + "title": "圖像儲存位置" + }, + "config_forwarded_emails": { + "data": { + "forwarding_header": "轉寄標頭 (例如 X-SimpleLogin-Original-From)", + "forwarded_emails": "轉發的電郵地址" + }, + "data_description": { + "forwarding_header": "如果您的轉寄服務在標頭中包含原始寄件者,請在此輸入標頭名稱。這優先於下方的地址清單。輸入「(none)」或留空以改用地址清單。", + "forwarded_emails": "以逗號分隔的轉寄地址清單,訊息將從這些地址發送。如果使用上方的轉寄標頭,請保留「(none)」。" + }, + "description": "選擇如何匹配轉寄的電子郵件。\n\n**選項 1 — 轉寄標頭**:如果您的服務(例如 SimpleLogin)在自訂標頭中包含原始寄件者,請輸入該標頭名稱。Mail and Packages 將使用它自動匹配快遞公司地址。\n\n**選項 2 — 地址清單**:輸入您的服務為每個快遞公司分配的轉寄地址,以逗號分隔。", + "title": "轉寄電子郵件設定" + }, + "reconfig_forwarded_emails": { + "data": { + "forwarding_header": "轉寄標頭 (例如 X-SimpleLogin-Original-From)", + "forwarded_emails": "轉發的電郵地址" + }, + "data_description": { + "forwarding_header": "如果您的轉寄服務在標頭中包含原始寄件者,請在此輸入標頭名稱。這優先於下方的地址清單。輸入「(none)」或留空以改用地址清單。", + "forwarded_emails": "以逗號分隔的轉寄地址清單,訊息將從這些地址發送。如果使用上方的轉寄標頭,請保留「(none)」。" + }, + "description": "選擇如何匹配轉寄的電子郵件。\n\n**選項 1 — 轉寄標頭**:如果您的服務(例如 SimpleLogin)在自訂標頭中包含原始寄件者,請輸入該標頭名稱。Mail and Packages 將使用它自動匹配快遞公司地址。\n\n**選項 2 — 地址清單**:輸入您的服務為每個快遞公司分配的轉寄地址,以逗號分隔。", + "title": "轉寄電子郵件設定" + }, + "imap_config": { + "description": "請輸入您的郵件伺服器的連接資訊。", + "data": { + "host": "主辦", + "password": "密碼", + "port": "港口", + "username": "用戶名", + "verify_ssl": "驗證 SSL 證書", + "imap_security": "IMAP 安全性" + }, + "title": "郵件和包裹(第1步,共2步)" + }, + "user": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reconfig_imap": { + "data": { + "host": "主辦", + "password": "密碼", + "port": "港口", + "username": "用戶名", + "imap_security": "IMAP 安全性", + "verify_ssl": "驗證 SSL 證書" + }, + "description": "請輸入您的郵件伺服器的連接資訊。", + "title": "郵件和包裹(第1步,共2步)" + }, + "reconfigure": { + "description": "Select the authentication method for your mail server.", + "data": { + "auth_type": "Authentication Type" + }, + "title": "Authentication Method" + }, + "reauth_confirm": { + "description": "The authentication for your mail server has expired or is invalid. Please re-authenticate to continue.", + "data": { + "username": "Username", + "password": "Password" + }, + "title": "Re-authenticate Mail Server" + } + } + }, + "selector": { + "auth_type": { + "options": { + "password": "Password", + "oauth2_microsoft": "OAuth2 - Microsoft (Outlook/Exchange)", + "oauth2_google": "OAuth2 - Google (Gmail)" + } + } + } +} diff --git a/custom_components/mail_and_packages/utils/__init__.py b/custom_components/mail_and_packages/utils/__init__.py new file mode 100644 index 0000000..3d48004 --- /dev/null +++ b/custom_components/mail_and_packages/utils/__init__.py @@ -0,0 +1 @@ +"""Utility functions for Mail and Packages.""" diff --git a/custom_components/mail_and_packages/utils/__pycache__/__init__.cpython-314.pyc b/custom_components/mail_and_packages/utils/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..18928d11ef1c94c81714152590be504d507ea863 GIT binary patch literal 215 zcmdPqrf zlFaX%p8TpycC6i#N_P6^weTKKTXD4?D6p_`N{F|D;Yk647_ElpPZkU zmYJ@fTv}X`pBtZ?pIeZhmzq~nte*=sARcHyd;!z|{ZgPs#rpB_nR%Hd@$q^EmA5!- ha`RJ4b5iY!*np;i+*r&3Bt9@RGBVy~&?{mAasZwJI~M=| literal 0 HcmV?d00001 diff --git a/custom_components/mail_and_packages/utils/__pycache__/amazon.cpython-314.pyc b/custom_components/mail_and_packages/utils/__pycache__/amazon.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..da501e339557860b6ab502d906435a749f7e73f0 GIT binary patch literal 20354 zcmch9dvsIxo#(xJKP}1f`zc$U8yn(p9CGmUd5osyl*mU-jQkWy3I5Jqp5rDtAD7^c zaX!AA_bL*KdP*z0l?f$_RS6Y~)d@9=H3#jn|cMv9zhX$-6eO z*4vzDuIHXs_xt26$j1%b)9bciALvP}_q8Tkd}a^l^Bm!QMTpxFTM%zRY(=~gu`L@H zBi@9(-B;q_+q8*RUuik#D=X(ltqG5>9O(*{Zu3Ez)%?y~(%P zSC5>7a-)1=vu}&90r|#kev8kE+!|JQt8c5%gmfj1KBE_9ZwEmQw&{W!N}@)xe2xV)&$Jk}~mdP#8X$)Cbv_c|ze_GLpz8$47I? z6T;_m-Qi%aG#t+*W1~q^XEdHbw*Z3Z&SAO$*-OA_kX9mlXAKgQoS!?U*!~@k3!$ur zdyGHH`*@$ir}U|OYM-J_32@TqjH;#Mh8}TGWK1SkJhqL{8KQ z;lzY6{yK+sYfeOkv0x%jqc)1W+J>X!Cn6(l!xQmDbSy9&9g9WB!{do~8{3ZHcqkAH z4u3s35{|bKsK(o}n-M!BngW3=yoLh-foA(Uk}* zyn{;IFil^6v`Ap7>N`Cs4XT2=NzTJXbwl!dt{-n#K3lQ{R_;Iv$Hf!_x_ZZl&Wm zT#Q~-eG0j^m^!BNa50Ua&(C)UT7-_%;pNNxd`ne+ele{yW>6mWAjd^jLj(xy*~LGm zI>d$QsgHV$huJD=wtlUZlUIJg#BuW6Mi{6ZHgdE+Rc{Gfr@Gfl>sYPr%C%+NcX8YR zt*u+yshB3Fx^G=gG$%jr(`-M5Rk9fl>E(G3F&ap@ezRPbkNp~XTsd}f58L*rza`%h zC%2blCr+*&e=$|0Am!F3w;YI!Cc=V)?uR3K!jZi&j^n|2IOG62PMi!oq#NTH4UUgY z0Ny>zE~g5^+UasSkodC8*+zI?EmWhL$j1fj3@1<y`IAB=A{k@l<21M>TOFDOb;wlG&9I@f(x(NA`r7D zw}>RNyZIm*=RtD?uyFtwj(}}|e+XdXozkVk;sI={w#^@sTe)mjbgjWE@ptHGck_(^ z^+|4!I{D<$G#pu6L;%{8oU(hsD_^Icz~)2?Nmr$Bbo>q z$cH2rN!TElw@IK80QC$=uY|2=6(^k6)Z}pdp2OjIL;|_eRS#0=M9oL3$$vqBqq|*M zJ*O(WRk|i!x_-WN{ms(WDSbv)mDV-P>l$X=H+3ybO0LXvPlFrHuJw|JbF59-cfE9K zrr}cL3jedwiyhM)FP)m~nX~V@U0Ocbm(iMkSihik+^SiB>A;Pe&2zfS4_qw^l}BGa zI?Ml!@-LMOY=2Xm{ePqU8|7c*v*``~R~lv-UOhThG*@|aQN!tqSVyz|OV2O3cHXks zf7p4k_d@TiCsndBW!W^R+w^Or<%g<^<_qST(HnKUQr6uml;!@d$8{u1QNFz}OfJcPLksaEmLOBBr2Zd#=Ha-3!FzeYL6Wg0h|NP}-V zk>~xqOrS$QC9(-dK`})97km7?j2Xeie23#sp%-Dx5M55`y>dt;r?(L9z?16_*9T-+ zmCFO=*KpNfc>1+c&BD;H?9Y+te7RrcQ^@_wGXbtWNNm%?_X56jwO*e2qF#n9@(lb+ zc~m*Z=>Iy4=~ewUxn4fbvvXh^>~gt3#}35Qezm+K5=-M#p(a>5>FEaxxbkV>d}vir zr($IduCRv!CQh!`Qn2G&vZn`zP;>uG{F?q+xm7+smV<+SVj5OFGP~#G99*8g8Upht zJ)0F8E(ACsMzNOb`Ogt(cqeA#| z^+e)C>voY#R_{(k5~Ja-9ozf#y1mU`JGT4j_3qtmtZc8_D$v?QLnIyC2^y?F`ECF$@G)|rf%}k$68yaqH4-~YwecHPu*Pm$h^rp)qBfQIn(+^Y1-0u-O~24y?Rlh zDy_{_xY89Z^A#D6lkmuge4Z8xpkmrA+j4t}wWvlgE}b?(&kH&YhZoX+)YW95u9 zWvrX*{Mcyuz+$^qTyoL<19wK(bV>Eb@t=*oKK37u|6Sy7BR4z;?1g zv;q*T?;K|c8|aej&!Jnc;$*wBDyjG?D_DlgbMm^A&SsVMe6^l|GIPj(D2M!qawvW%ht4;vfJPf>MKR?N zF^ue44I%q9gGzZX2<7^;G37p`Pv^|0B76=7>yz%T(+MFsoNz#&;*jtO6FDW6Oo+%4 z51t5*p7A6N3GlLQu~8^*24Cj|;*W*H6dXd3Z0r}J$4A3sQYS!TS*)Jrd3HKn@jjsk zHQiQdxFFC>j3y$42u0PY;ON&yD}M6T3rbnBiby5IGjG%YFyBNp4YPQ5R>7MQLO8ystJlw0ufM!yu6li{dV9Kh-+cAH zH?`L)Qq{ieCB7v!SLs~TaphGPqZgvH!BkoE)Iq}CYhT;?(><^5NjtaCJGZATJFZ)H zWXkK(tdHHYmrb8~ard05{o=CV$= z@*TGt>18N5i}@Z(#i(H_My;gDP!Uv0WE*FdfR_y(y|Bu<-Hn+GE9 z@1jy1_Y7xwk5lmtOBBp17b%+a>}BzrJ6NfNzq5=lT5ue}2gBdrKmsa^9PWmeDpyaw zn>jpHPPaPGO83)VtazZh$T49Ihp)yi=P)VsJbcn2-|VOmf`Vy$V(fTWh&xE^bkLr8 zpbMf4B?%ypBPD7{$qJ>js67!G4?#fyWdXsq08JXlv;$2|SxJ&M9cUxKIuB$!7oJBw zwt=KDndE-0wN0;md2?D@e_dNoRDRtL*3BGE6}zUi8DsJJedqSgY)Kg%b1Fxk6v|ts zLl4+W{tk)2B)fcx&ROHr`gCpJq#;W)^_J>nFdi3ZA4R>y!9fa>fW#o>L%~EiX{Im{ z84G(T!GI)LvaAf?(+92d1EJ;uhKjedncm|L^SpJ5g&Bi+QAt@`w?#E27z?$iWl0^U zsan!gQd&Nin|nwI`8II^HGnBe@sx)qnOcJqaXd~iDCKCbNi=VeU&lY(bJ3%a#9~h zPZ!)x?B>d+fjb6mv&;_>cWbNc@ZggDS$u;mO$*dK=uEEEBeSwaF02wo3k?jg} z9PRLRk(yW+4<{02w(ENx##|UBgf^V@-m@zfL+OcVnx>PhX zMQVOll!_jIMl`ZvLQ-{ou9D!Vt{~47m#Q8>;r3 zgdd>+qYfY9B9V&zu8AwIezAJ;&|M8z;+lOjWpA6)woRT+Yuj#BIMNmF`3iTsV&i

fZCW#DS~IimmZ{`??{|B@cjS&*S!tLuFPgZ@+H}R{`HIcAO!iyWs z6}L;AvrlJAJeSprYGqaNU9Hw!bVsSLG~DC#cEgnRUI}NiXQ~=rX?dyTN1my}nTp1A z#fG_x4YSWobrW@}S+F)|>~(LPOnV-=?s??R;DX0{qtUxy_uejVoU=Bf&KC~7_EJSA zKfYE)%He#!r*)iN{9P|qvoY%y^rR*>xx@zUUYSmR69ANmXwG|Y$cQhb+r=0id zRPR*Ki+9#Mx*O4Z4&H0fyw{+obXz&XYdW4n1BJgMPWi;CP&`>i#sy}Hmsn$&!y)s- z=LXyoxxj$};h|XOk5Mz;gn(G)8s4@`Hdum>>CD@|~J+NAI+h*W0LI@mYpsB=t?+y5 z7(u^!wOI}14Bwa!&U`4RUdh^C86yNkzXrBf71>^gNUg@6hp@q_dn=fARMT4mLFP;Q zkoRTz866(M&Z+x}(5!e^Z(8PhfSr;VJGmFE<~!0J`9VDMCV00l={N}Ms{jJv=#c!L z7@>54CJC_4!0D+kX~;U1Kq?aXN7yBlM+db0c9!A1fzquM+R%&0pAeOFGpS42I4qee z-C2?;@ z0}2ALtZ5q*uh6u;$^yc|AJh2vEkJk;#h=qFNVwUl)$IE7=1Y&w#Ai3py8h^Ef7$#Q z)2V#BxRiGr3&hbqXdtQ+6S2{-KsQbxc}O@yK_>-t&;rT80+gCCzzTmvX=Xyz#f0#Q z$Z4qk`Izu0C>GVs7As9sivo#!XKkWot8cRKr>Mvf+g&7n1F~)4bj8zaURI{HHP^K@ z8EeVZbLUjI%;htxmlLl&J~Ng!w_G>3WGwb6)orc$g|iu3?UV*I-dgg*o|L6w()+R5 zHN|I&EK>v1{M5FY=9|XG49NPCb4O;Lof)3B%^bXGS_5@YQPW)=XLZd!0qgjr_wQY; zDU;{bCuaGn_;mYp^Y@Ou`ov_{oXPXC*7%{ld}@EjQanBU{ba^kdeL;jG&6A1+VHWh z$eUc*uIcjyczA3`wq>3s&D(P#3ReMN1MgWMKLNY@63hockY34zW; zG-csiGJZ3<^RK8}89@y?SmDQ%RS%QP+~>BgocmmsUWqmsz)uAQvY=$W5+%)s1I>~~ zM)jDX<>?0s^Zy$y;(Z8+o;C6{OB7_xWs6G0w~MP6)rdjQj75uDO6fRr`J$du*uUCE zBc)7SMfIYYQbnA`wq!v{qIUM~1J|?nh zl9dC@fztt)T}FT69^pIaJgIYqT3yFmT~9(u_h%>&wb|<-oJUURrXr1GTI>@QM-Jmo z_0o%>JV4}$!SfdgnT8hr z9R+k3rE7SZQh$L!)W?Ex7$HeEQzcG}B}7XWmuBseanS-H?m764fuzEDGY*4n9Mywy z0#Ha%vLGc1Q6-XXRhFU{)r$*1M^$zq(?~G+shBgBO^06IpEf$K8y$-ZrG72xwG%Jy znCb-Pv{k)meEDR$Zo~Du4VOa;b-Qj@cTIL@j3rRU&l_uJo=F+qlbyfTIToBdZ|HU| z>>0SB8(36w>JmsIx}sZEZI>;nD({r#*RG8jYk9_st8dF#>oXR|U8AN+bC1(FH1n#O z$-ttO)0NMxSL*2(8V>?)zKNcha+PUJMb$%TNS#0!Y@LKu8~A-o6lBcSMJ3|fMYcsXVjxv0 zO0|^I5qi~A%D`z1OGcz51e&{im<27CAy7XM!hHxdr!j}yOAaLhW${Ogm*rJ?MB883 zJ36Na`n@`zLPn1G_dk&Rt(ReLS* zYAYVn*~u%3>3n*>j_DeIhjST%)>C@E!mL0pChY+T4V?nY?{V%CiBDPU~2_Aj2Q~Zr$JuLij_b%eBeqS9tH{@ypK$e`gbfm&%ziBhgrCRg-(#`|AfDvFOSe?MvLGX1d zegiG;NaAF2TZbf!O9LgMQ8>K|7%~xs6MS|O&90Dxaq{jKNBrxNSPUG0a_6#!;nTz6 za47DGN0MQ<){jNt-*AE~d~zo(j!+~%EJ+K=nw;xGb_nubfU9hnoEF^00x_Flz#`F; zi9}2^?;nl8M`2J}rkovs(g5E^iAp#vh*}{GHwpNkX`nk!OvFX4#Hz&^e-{FZe~W^v z6cAyCV=-n<6kB+YvRdde*v!yvJSNIVA-Pz{+aHj&pDEg*>_$6T(Vf$DOFWug-awg4 z1A8FcLVZTw?}6$u7OeUcEX|YNjHUdBrE$`GtEe7wwRNujz%@SQI+SWSJYAHrH@tRa z!M^!cN%h4e7mj2q9?MiT-Bl|~nJT&ZUgiBAF4l2%jjufU(vv^>TDrV>T9xHhU;Y;6 zkn3jfu2O+MG+b%*J=ZFItmDe7(`6gy%QpU1%bU7X*^#vM$ei`ay|pXqE?BnyV|m9X zv$mv{X0-Db{Op0+g3TN;U1-3RN! z`QCHAb5+}~IMb%R^QOK3Oq}b!&+oNLJB`gwS+@SK`1?5f7dlE0x%s!C-Y(OzP*-ezP*X}HtOEqOf}!$Mm672@Lred9VOL#N8h1E)pxB__1$XT+pK%HhN`~n zpsMe#=e_Gx@3v6YcQ?`Szfkku7Sk^@9!hVaR=?QCdp)}MIBNBtidwyA;k_GF?^&tU zdu5fV`Cc3E-DG-igNo9u)q7~QMR$$0y2e^vv+#!us%us)T3xH;(c85e7S{7r(#X;- zmTqS0bu5jIXxCr!u#yd|1PeyV7FN=(>9&}!VQcmkU)y6q`hA^(LIchA{UX}v_bs%! z?-!RI(rVvdTXsmHeSeP{<-b&@QSwWzlF|n1`Ijcmp(gz=i}^#PMZdHgC|#$Z(4oiM zWfBF6iAWc1V8E&*p#iKm`d|6T zY!%!r@qdJzsASQq#gPV zMIj4*Y`OowwzoR3>p5D6c32TT4{ArB=^gkKbJFDW0B<@#%%sAW@GRhR&y_qYx$H+Siu@=xWjOaMD3irL4IT~f9jmD zX7n3ZV>Ag){HoR5DE&F6H)i&mF~i3(!ydDsq7EGk&W+3aTibDPLML6tRala zUB^NjWAt>%H3wi(cfjvU)=9zI9)bSmOqTI`+}9KLBz4Wc1N*mc+T`v_>X}RE$;8;` zpb)~8^8TP;o32m+HjNX`P+&qJs@Ye}0!d4f!ivgjDSu4f- z@da!RCkXVy1Z#fI^E8{w@~Kz=RMzl1Ku_SbCh!d%^=U;jS(&xmGoX~5ShH#|#?-R< z!hc5thSKP4iDiPq*j9GYc)|Fhd9wRfk@fsD-+gAGwr#FvL#k-gR(y^()!uprK(ibmUPLM%fTD=?dLjwUFDh`xx6k_wI^M&=gPA;>>X2`AJ#U= zuKupSs+@E0N?Ud>Sa#nk13TflUgo*<%~aW*X=SFS{uS>_-X9;D?#zJGC~uiBZ%LJV zF0WrG-vh`0jB{<;xq05X`O20#=Vq{C(>)nyTiS__4cjlD0z=~LMoEqHl_M`5xzv-Y z*)iSqVf~sJWv04r=Gi}Lf1`e(diw`8YckHJ*=K*!erf+@{?88lWZ&h1E4IJ(-*E1l z(PgTgH>=w+HI7#fzjXML?qQ*WT5Ffm$+hMdgdlu)I$m{=~(VZvBUn zJ)gxlVjExRupLnHZ`t{-J({;lswv&ZAK)}^ZEz!fweHb&MDJF*5dMPW5iTQcUsYYE z0P0Y*k-ALsKNSL)f}|=lo}4&Nsxoprl{B;#`3n!Z)IpVjIlq+DjQ}KanzACkXo*9> zJP8rwn~p^_VvsuM%(Rr!ab=Z@dP+f4re885b-$*J2m}7qcm5|5lLa5w_UA|&USuDj z?%bzOt9>ny|ICSe4Z|=6gP5uMwQ~D>d@R=wyvuUMUod7)U$^R*Il}tDF>}TVc)asC zDMfO#>*%E2?X>IYRbM^d(yv~BaeZS&=W zDckNj-R>#%b!~UXQgZ(JbI;Fg{NC9)T`eq%+3JT=w&t|0ZQj;)S(UPFozrcl>W?n3 z{(;df0Rw>QxB5MYLT78q!KxlTiMlLE$3M3gI+QR~umcq&OT>df{WO7kBdQZurz22D zFzZ~TXl`Q%i?0o^QfU>1z^Xz!2GSwc0emB?vdeCSBQlO}D3*Wpz&@&we&NCqNyJeFA0c@D z>Hpw?XEiA&g$oD(WM?V;2?dN$saZ|wbAu-Nlds||86ks9K(dtx_t1oGBD8qe#M@fS zb#3`A`?@LJuk6+EvM#N=cD8L4iDfY zU?a^z(&{SzLhEb)Dr$b2dt8-+FGN*J$+PJ29)hRUT%l#|b}eR2PZs`wc2M6el@*5h zuQBg~&h9UU&Ix=JIpSb`nT1eEzbQ}c>0e_Kvifs2(C7KA}l0!CXG)`;P+z^;nC5=PPZ~?2b+f% zW5HJZ3Q{PNghnr%EZI+{%aQS*BYXnvYhnTx%$*Y?xpk1YZCH4F)~!m~CSr6kTWKhC zM>-4@qkf&aSBQ9BM^IsFLo{a55^4gm$8jQW`!&KZ1jSTj6#z zhPj6)2>f~?&k1k8p0rUMjKuN7AUhrYXhH~25C_91^7iXt$4<98X_0#oTEpYdMWRVV z7hEX9Bf(H~XHwUNB9^lDV}+q87KNYSVI`XVCsE7cR`m6`m3`9JTFl+Yy;IZ%@Z$o* zfq-ZT1SH2_{ICw)A<44L*mmt`bcEK#NM`nziae6$Q~ESle_~>M7)ssIxa8_fAMBhQ zjU1OWtQu&CsWmNE_$39uk3cj)@e0lv7U|=Xr-=K$Uj*{p_lrOt>;dfDI_iZ^N^&A% zq5{bwlEJ%(Qp~Z4_;(2(GoZI4E8hRZL#qtKet5{kd{P9Gfkn^5OipS=;3D}>e}$o# z3?Zq6zrs+of0EF}?ECa{Q$08st_j5lR)O=@o!H%?kW0-E%_l%iT|#@fp~sMfAj4d zF?NkH%0?gW9q$&OdMXm)47ZG}#YtI@UodvvyzqyZY8i;*rSYV(sMA7w#$b$ir9b+Aa#*-@8dbcdyN zP_5I_I_Z}@)s>-6=c6vYEJk!!)D57N8?HfIRzF}O&z+zz3J9)TppzHqie*jE(}MJJ zT1g0r*_osgmvmW3q%WnCX(^#~#L)nj5eS+Y*S4__#7SnJ#K?KuvF{R+0Br+#lDWu4 znWvcNz~oUjY=e1lpP{h~rxcH;XH&Z2P-T5qO^vCj4%rL`7-?G4jdD?pCnZfwC~;jB zHLPu#H%^4(>C~h$6^_qpdU{%nr>AGqDLJKUVQMoltTOp)yPd16&-nEY6YS|jTmJ+nI0o5dKIUVK+=3&L2jgyd> zClg+DdozUrlT-mOLQ7jMX{q2F-~)h zQJst*>+Ce#RuNs!*ku(grvx}TO-@eIh7`i)W)=QaV(_Ai-zMChj z{ylGa^5Me^T$ZoP9}MF=kU!M9z}@ES)oS==n?E=}LHz-7xSv0OPcZFH_{d688}$+v zq%F*%pQvuAGI;8lqLMJ|Gm@%nYB^{_tifu!YS=Hls>_;T*TGHYkWJkMbt;{_=`M7w zY9(qhn$*IhHG`n0ZL&YIPC#7kzqbEpr`It1E0(@KIYTSV)oob^+S%dx4qEv=&^D1q zz~}6iWn;|QExQ&1QVTS|lz=%jkQg(LJ?u!`R{3$)*)2R`Od-t8urXWIaU8x$Jdb@$ z92)0$bO1$K@1tXoQuQ&mz3yJCAUTWJ(i9`(=v6z?L}$0P?qTrC7a;!%GtWlsE;7T# zxbvjAx2WydGcY@V9cK4v>CqAN7#Ac_SPh*kph(w(7Tb}wt))c$&b53^h@h9yR2q>O zTd?VWj7Z5fY$3v#h)jW1!9#3OJ4LgAPYDv-hEIw5{}Vnn_s8dd@R*WoDB$zoduot4 z$siN?rjtZg;2DI+eS}q*kaI3Hgw$@49uSHS1R}uRz@#E!QcX`6qOM_k;wuWm#+A69dmaclccBn(a%zH9FJ}aX2*RpxSdGx8YJWC8g<7DlV%SMGZ$n zj;CRlum=h%0;zH+@W)gAC>$s-JgFE0LUuKP`34jZfiRr1k`OWCv8t?T7(|+zn+3s) z<#uzU;w=i~R71nv4ATs|ce(ZL@SEXmRqzk&??!%KzTjMS zdzXD}S$A8$qBd98o~dikR-m((t%~ka- z^ye$8E+78E%U67Fd^_K9IOlE3c$*fFX1oXT)wK(ct-7l(&t}~XwAX`~x`Ww@gS6MS zjK6K^=q-QOvbSsX{zD#E8hAHyE%F`=*_W&8+dgEtGv^IvyurocjJMqyvhwnoHy*hn zFMcb#r;`rcmZ@vYRwp=Ix(2duSq$@gx$Pm{TXkF4*YiqsolHid#B-Q!_uXdnp3%oQ_K9RyGKcNAG2Ods{5IBAE_Q@);+}g z$QRmUV8hpYj||r_A0B0fE4dGk_3==+L6~75cZ2DxfWk*!X1JF7sPbXRf9zp~1Kh{u zcFg-2l(kd_P?qN42#oO{4o1E$=Hcy;9a%bxoXi$;a#?|sHR_!vC36OsRKP{4kE7SC z0*D8b@(K7#>jFVZxz!E`5tMg!KlG#c)xjUXcx!jt8cQ`@J!a<5WxLkxsQFih#@`2G zr)T3e;9`@ZI|y(n<0WUfSz8C0wG9E`&TvJ%%{`E}xv$LIT!FX8Y^Qq&DI4*zVzWOH_Wi>YB{R*E?aqcoD!2MIYHCcx4bvmUeh zEy3!v->++21;%|5o@p4{wu8f1%3+0>l;FRwbtXTDSzL$b7qG{8FkZhktrBBfEHo3~ zDGj8aoGsn~l;EU^s-is+SG*?*f>$-dGs7vsIgv8TGLE?+lVzr7lez-?Q+pd!!>MlY%ru4_+6Na)%m(iK_ch><2NXA~l9wYAb5!j~2q*7PlA< zXe_4^CbLjdLBgPH6LOl&0uEy_i+ftpfUTxrhpicm4Et@9X*9JBzR~c1qEu5L8#kpE z>mXdalX6Tw{iXL?#Ixoi{@n}iJCQRh)v-@TKX~b-a zc3t+Js&dbhm?)`KwZ%~s;^uX#y%B~n7m zqW;cnS6{pS>`Kj0u3~7JANu0%AVYi;%=!RByu-{F8rt`D=fFwk`zHpDa38Y$Rgk|? zTZi%xGjM{tao7dyCXpyrl}Fza62lY_`o)}Yub_S-^My% zd;62Jr0zIdHGvEt$nkqJ{GKc?P)&V?ug~#&GyLA$e30S_hhDlJq+3M#=VBBegIQp( zf}JHC+f&jsUSGIGaXOutO=2D{HeQ;Ql2%QHC{8M>rY9A+7fD04Qxp^FxG1W-p%b+o z1yB<)S5gCaD{v#C#6?MmSae|)4%E=5vgr0DE+> z5R(j-q@8pj&36Y)aN6&`egfEgHhVCii~TH zW8Qw8G_gCSjzR^lNIL{#jb#|-4(a@q?D{Ja{zfKN$i%9vGUuwl>8ignvf|o5@7#2p OWte>%aPDW!ng0`Es~G?Q literal 0 HcmV?d00001 diff --git a/custom_components/mail_and_packages/utils/__pycache__/date.cpython-314.pyc b/custom_components/mail_and_packages/utils/__pycache__/date.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..86f0359bc3750cf64278a385931c5142e1f3e8df GIT binary patch literal 1646 zcma)6-D?v;5Z}#R(wNgKTCLh(*J{zwniFZIqAiNz$Ac0N6$J6P-d)?%?Lh1rFCFuXLn}jX683@Bfa}_1ZaHe-m{k} zLe}umAvh~)U4(6cSVWSi#G-eoq*kh*SXw_RACM_a2RW@|&B}n>qh#Hpr$`}NAHCs7 zpE;q&WKi+hoL{c`T(Fslv%5}ER+^IIK6hq)QM~6;_!cfC3_yd`ngF&y9+9W1iPwa9 zaF-|d=^VA_6VN17>V(_5fZc=;mQ(Afi8I`nH69jHan^%~Fql|JsX*flL{o93zz+|_ zmrOSbXM$PNtqB=bY&WV@qtFkfFe?zT4Y}CWcEn~)24!KQpJH`B-fM$4j3gXwn`3D+ zutYzw1@fDu>B%3+mL@(-zMoWL3sl5K)}eORdTR=97Rb&SmeQSPoBLQ>g!0q+;w@h? z8F|k98No12Rue%u%f!5peub4I*C{Jx>X0HkdpiP*t_cwc>4XxVV4YA^DCTmOs$knq zH2utXW!sya^V=Tb$-h2}xq`;A3cLqcoK~?c6K>$u9=zH!>q}c*^Zjt{s@TsQ+1vMS z^37z^IMFaptQu@ZXX@qleR3L}@75>S6CAq=aMy(71L0}FC(fns z+1Mhy4@^|aq8iNgE@KbKp7+KLrc7Wl(#&t^_@Yn^7>X@CNIRf_L7_eln zOvJ?eIMEy!Z44-!%Ihx?c7S!g(7R0A;wG5mT0mj`uHyXF zs%rAE{JQ~&hG@r<`P!JCSPP>UvG(x6^{oIJiFaFpixp9&83JJ)5>zA9H1Z82-!xdm zU|)`Y&413X8pRd8_(xz0i^cP_kdAw7+lyTIZK+|!NmPBn(dE`}X0KEtuU7V__yB0J ffyHrP-!)3C1CsorsqY; literal 0 HcmV?d00001 diff --git a/custom_components/mail_and_packages/utils/__pycache__/email.cpython-314.pyc b/custom_components/mail_and_packages/utils/__pycache__/email.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0a94b88f3eec62cd652f48d7c12ad9a24d1f51a4 GIT binary patch literal 8731 zcmc&(X>c6Jb?(`n+1dNR4dNOQ2e}juNdQa=qD6uS4&flQfEJbnakbnXfGaF^S2MGc ziIU}wWS2l6B|@YExa^9V#7U?`Kd6{-l$7EUBmMB7RDlFRtVVE5m#A_%zW{+MN-F=z zdp)xUK!~)HAMUE{c|FtJ+tdBt_r3S#KBvP= zapGh87=@u%gJPgpqhf@sp^xq56s`vQ82e1UyuwqN?KAgU6icsFvG&>&8@lR^3Qmf0%aE5*ja{)*aIy3ab`7@& zMn(p_MwO$ps;_Vqc6-s+vYZC&lR?bhnKh9U3|23moYh?SiJ24mccy$M_KX zM52KSQ3;(4;V$SqL0FLStTyh4Dnd^rl%XnWwp{kIA2< z3M{6MM99O&DiUG5+{`chnudvja#BRif_)a^6QEiG-84Zznii|IOPZ8Btpb!yhbHWX zqw;nNqcDEc5J8D&^jC!8K6C%p#Aj!#W8H60lbr%{kRc&|h^RWYz>ccgN7NOkNn z5K?5Vh~tV^J*7Y4e$1b(nKgZAcFun5nz`zhm2mb~2mfMlv7q&0)iw6OZ*8v6Z#js) z;ubN$2(#-o$7#o6$08y(2Hif5^Aez3r+`T;<3QQ3t?Guz#RY^HX4x?FkVrSoOp+k+;Gthm+lj_ zIa+z~K{Zrpcn+p;9ji<18eZNle0StO%IF;lH*b^i@obbC3KlM}#l67HaC0+ULL zvTB?ZL8kzSyqpA>M^q!IoXYD90c#XvGT11uLzRp=--tM+S!VU5{+0p#<#Y?x$4jV) zR2jbyLW-ue*dL~;EGFFbO~?vr+OBh z-KzyvD+Tpe3+k^IG|rmRrB(AYb2I06U3l<%Y0GR++EuWy>zb?fLw8x)Uie!7>HY=& zr;Z;v&WD!D_FQ;ixvcrRy=8+ZWv%N*Qn+i)O6-NHp)Wpl5LXW)qmT4m%b_y%Y$a5i z%o+_4w3}@F4PEp9#jJ<3^&X z8-5i*$j@zO!Z}~yVJ2b9j)>xjoFCyg4WmYHDO+r$G6e1gL};g(2{J z0bzI383OT%0C;cUn#fH;cBTLYQLoiHG*jITh87lfH^^QXuX{+~cSB&%DKyA4RoguW zze$NqLww=2Akqe<&`H%86=SMtQi>-NvQ!KQDV0K{^7{Kq4`7R<&sBaR5(@{TQLya$ zuxAri&Dg;fjfa9!&H7c>mIX^+qjOB)ie#>PBIcWEyQZoam`(thYctv(F`cv&T+ zuqf4^F4>Vf_HkjwEdLu@ak^aiY4wk)FR)AH&5Q2lGu(A|^QE?n$$x$E?H7Ok(o$RZ zuRPb<9$j^p&O7ED>7w>@QN{eRxnt>~^7(u*7*;ct`!>0WX%5lJL?Wpr%A8p_jq@1q-?glp#l0&C{?NtKYgExuDAB*Kk4CSaE#UI9HDbtFvv0o{B5N1a^!NG?1XNW<@!0vU(InO4TjGE$oX(gLva zm=>ra{V9?S^*f9Z?we<#BO!?Fg90X)q8V2l^GV>3P0L$-_^;#}1u`hn9N9#JvJ%(= z;FNL9yM5h<_dWQacNDWYVKEdBi!)qOnP}dpnj(|2xFmWFGZy5=)|1L~bjC`>L=>V9 zuT$k{)=9#UNVP^_&9V{%!c@5vrxb__EO-e@Qt*@{V3z`*DH(EM0Ss3HS|9d>V021# zLj(at6H_2d6hKf=ZFnaUJQa-x!_r|K?d(z%DRLsIh(~G2Z+|=%!S&J>B^a+$dIWk( z2e8WWm~;?FJ2q{JYNcC3saItoffrOAK(vsil12De3Bs9ac~WJmXwiTSZ}2*QtDF}4 zAeI90Y1D@ijULhz1!Oo!J&u9n3*fd%-+e1iv_H;?b z{M6jk`P~;DT`JkT;@JMtYpy;Bd~TFgu9WS*QnvddyI8h+sjOqRZ_QwIl&32jRw|pWR5o20yLfV` z^1vAjfMj*^g(u$Ivs5*BdI+K?d-<}xes(bJDuNI!UA6Od>qZ4Bt^vZ`QN6Z@*vl7f z^^0u%`UAwX@3-!QpWmt^#dSX$SS)2-iQz1F$nM?>th@{ERvLb@uNn zK)Otr!w1;Q%pn4e_YDO{820_5Qk3s^Vts&t`UA#uq=f&Vz=(1&gK`PVn_@Ah`Vwz7?;Dv&14DGn#IXhpvpIOs^nzUJgT#*U31+)QNYfr z|3&pyr%GM|NFq`fR`@D3{>tM=bm;CzjjzIUc@Qe3#!AMsj@7Eoxn_jxO`Re+kbxQt zOV@amG)6=zj}fs6jA&VRfOIDb;%2;pBsc^bu909a$2^QH-%=pOV#uSSZ0@O};` z3Z_q3a#7V-`PeIdwp}Mspj<;fRa5f#C%-X6n_&p7A-=SU6!u4LKpcA@&H{KEdv+7S znEJt`#{cz$is)$|K7xdDA0-FlOkH;*3i?66FUSco6q$&Ggcssc7*eNtxX|)t?Ffwl z@B;<%Mkbh`R|;e@2JzXTK*GI~YOzAcOXV?JABl<-th{y!@k&EgJjk44sur5dr|Cpa zbNC>6AWc);Rhfw7$L?cL$*BAJAgN`2EEsoaxEO{GR73wB1jNN#?rgHPrtA7qwX2jAX*q5Yg;-uk+AL0Oo%?rwa0 zf2w!Ub?{?H$t<&4(*_Bi1@i@Q!)Oq!w~1kg^|W)AzikF@?}n@BD&SXH)$1IjdEB*Y zX5uJVwpV`d=z1w}mI6xKJ*j~&KCL0{E@s^XL%)!#V5u)Za;O1tN;p)_UKUDG-pd@S zGhN=-1o9>b%Ekfj!mvL#1mz-tJjXBV`{&!*onF55B)ovvat}Dly6aL8cE3xK8BbhB z9YbKMV`|p1qQC^#EHHtr0~1ObFrkzOOxV<2b@trjZ`c-X70X=Zx&!Xt1*ZP$&j?d3 z08A9B%z02{z9&?fw}mQ8!c3v+3G}A(plZk1*?U0MyFO#Wkq1}c+XGzLb-1!8Og=W@ z81(pUdIF2W+1S)(=)yjJM+WlrNTC-zb$&bV-*3&t2ap4Y!$;5?n?&zfhdncey~il* zaWg&lhQ0j6jqak+TU16U>^ma2NXJ3XhPp=~QvE9Ulfb7Z6#7(CFp&^rVel!x3Ie5P zuyYV9)t>pIKm@+EoWT14@I(q>l|{mg`xutL%5U^!K{4aJOV7d-)Jm>`@TY=fy0ADk z@c%vEnxM(T^0|^>-L@NbqJ!30HTYw>P5Eti%;*%1JZhUt(UvVVFz>BARIQamv@$;{19{4X1d(j z3i5xpR734$hP)N<-7gT1hv3t&0K-&18lRkmb>Jbbqgi8{14SF5S_s15+3Ki^TYNw{ppA87Mky%ISiG> zA#Pw-W8BEDe4J-jQ{2R^=D3+%EpZF3#sO=;5ErVcE#vX3qb-9Z z3^epN#v7}-U+0I1)S+tE8t&Jd_G7#h;(p0i%t`iQZpIzoDLIgKvUIbQhjczm?~+_d zyIHzL@*wSH=~l@v72ubTe$5!-yQM<>Dq?wiq++B?SbDFtQ!2%;vP`*sQaOHAu)H>@ z66q?I-Y-=nEwc0hsadMQui8wVXQVp(s%Lozr3R!MS-M@?CGEhkrcAkKB|{zOZ%Mo` zFgrdK5~FftA{2{-=cdH*xu7^ZK8L%rp}Dv?9}mxj-pcO@^m>=Hl{2{LJf*%!WGgpjdo- zE{-Z@_WZQKE+?Zgzb9SPb#kb8taGsQb0>$!y3U*)IXO5sFxZza&wYQaci==%+Ql+; zrG49OD8&ld-QJ$=o)`5^m*u>zRB^IA^g`q!@|UuT9->#LXKxT#bwW;tg&PYiZS zBl;>8za&GcR@L3p+j-{1$m6q+X;#hG2CQUMsu|mdsAQL`*;@yoWLB%0k9SuoU_BY= zkxq1;!+Z2jh2mpa5VPa)cqlj)9FK=4Xscwl3ui={h{k3;q6IF%y<}|vD#rzJuYx;e zm^Mg;QRFCLH!Vfu-%*{kMGnR1Y^L7nz=x&KsMc z#>SKqawG1s&U=vfJ9OlMopXAwl)QFi*;MuqF{=I*XTD*}JF(y<4Po;zqNlwR$v8^y zg9V8nr3P8p&Es8}g}*(PI8bj`mL;I5=n71I~~sSGVG=d-KFy@7}Lj zH+bCqG)7(hYGDKS?b=Q||BlUoc*~m3ynJqxy6_p+G)gI9H(oJD%hs_#kTo|x8)B>X zErYxhWuCNVyOAHGH%)8SYY^{Kbe-Rz%bPs=rL0r^8nmK3Tc<~H7nB1(l`yPd&6#^O z-2O}|Y8a(`#6o~m*X=O1wk>EB=sClfVcs~;k7=!dKa27KUNW{{02ywe)f_Mm+qN}< zpAxS=1LY0Fj>k&`vL&jyWFA>HFN5&o5JWTxUjLB zt3*xu!ybEL?aY2MC#1}NqFr*jzq4hp2!b@NZY+AK*iSLqFyXm)L=4AuJ4-FeN{z=v zP$@7!_Owwx&t6@aGjZII-FMp4XcCmR(QqkQ=YDzTOI6(m5>ot(S) z@^5_YH(vYFLO%$gJ%4ffwW_48V#QXmG?KK{uGwmD1V46r7R{;rf-AA#nfcgPa&6%1 zz*6uVCl`BCPT%E|mrgGAeCVv*uyU^QM^?^Wx8dcSzNDja#ZkHHs9rWzKPtf84{f!N zWqcZ=SAV;;^N9JKBaWk0wk`YapBzhUGzE;Bq^$syc<9x*iX}AVY)i^jNIhv^oZXFwar7|qd`y3^8A+a76w*=`dENfE%hmC)U}dh8%w5hUhS!soMes~ zj~FGirli7#EOc2D{_fCBC>|2WMUoM)vDm)35C$ZL2tKg$=7KZGYE4u&#Kacy^!x+~ z6qEBaGZ#fUG#mLsD0oP0h>avFSbi_<&R_&$1sF0h^eO}b%1-QLXe1I_IU9|WJc6C8 z)XzX`<@YlD4p_F>J#*JpPrmb?n5+zP=tQZ4QRc&rhYTCr>N*W@h~a$?wEO z$wv{TdED9xZqBhF8>g}%kE0MNHIvmW8Bz}HpYjz)Id;(XGI4jni zRqM`z%Y&B&m&=~LeQ?b=^ie_ay5PE;cPVeVX#cILHDTbs1x(r}56qmifIv?&Wb=={ z-Io+jEeoeUa=3r7VWzxKV|b0+R|-2zxTQu!?{GyFmpG1^_;>1xI*;)095ExkWnY?5 zg;wGw!T8hhP~r&(-%|NG2Ij=U4aseYpS0B`ksqV|NL#JK&}+EQ;_Ih3*!2c@XuA72 z3=){3ho(&@Vm$+`12-DMwxI4Mb>B^u(i+#T@SK2%Hi>#5R5PZoT*t8Mo|gj#)#tgn zGl0@oZr<3N&vBpk3^OH((xw^@8IQX;&c;SD((Ux9X_WXU76Js&*||7=Sm|#o7d7W<=SkE|?MVLvXS*xyEgecc^H_NzyCj5aj}VXc^q!P@)Q1pZ zP3Lc|mpHKXH=diLozC8o9!cL!j%r$WGmsz#=ZWvyQf-F<0W*LE%F0d#Q$S^ULf!P6 zJ~g#Yg(nfuM)xCrIXaavwMOTr{0@arvxH+~s4n;7eaL-?($;W1B;!`vMErhQ2+aj! zgkmz$`m~3JH57^WM&{>&tQT@WRUJU&7i7{ArVX#Aos%?+W9LKAOoZePx@#k#Q`i@W zk~=<$C#4OO@-gJc2%U-PqmYrK#?(p84p4pxr5IstV?4+`hwF;zwL?iq#fqaM>8QHn zsLBFH&)e}e;lxKm{)VZ@+-q2G+I4f}yY^($p_QgXYfXn&i#t}D4&T`OhUK~iiACpf zaYv?Z%GsTAmOL=?Hv6W)71k_vr(6Y>zj*13%at8T*Yj(x=hrL58@_KIyXm`I(Q?JM z?ygumx7^hJq5IkUR+QhcbH$~Lj`bX!YuC%c zpFv{r_;T3`_Y_1-IlEHM;{Q#Z_=mr*AutAqMPv6}C?a#5~ZLqnx z^EjKEh2QsB8(K$mk$lN;)}XP7dO38ICWHl*xMg7hPauZ)0>DN#1Pq}X1`}CG(1Dd< z3s@OPv(ObVLJG}-6(hV^iBPMrK)T zw+FvGxa=h|U^;!z>bX*X-JG;m-LY1sipnlI7EK>pop-Dy>%NjD-#3okD7@=yT(qqV zzANXJ#XW1nUQmvErlKqH4^0&skEUX|36CKj>{sF<iWHgLRr;`(~y6kLqw_* zTyB`yFRec)%R*-NnKu6vJsjut%99AMDc_zmoZ^ph!Dnc}K?%XPLCXwthoE1$DnFHr zH`91NHP!3nvWf~tJ$M|8vRZ{@d$azU?W%3* z#Sh&LtNVHtwft|ER~dRo5(P9F#NH6MfLUPV!*7!z)<7_Yg+L(_XYf;_CNj-MS{P&E z>DXA>5*?SJc89`=u_k6_B47-O{4#Zi_A$7Q7nITDZ5e|6d1SKP_&Z2^vcTPQ6)p7t z-06C)Yt7a7C-t}D|7mA(U-!zs?zMfrtFFGwU6;GQmOE?J*|*U1h-BNJ`YIN?vtsb> zTfYBXzUJ&$cly@dzSm#;Mt;)Wu;Ok=x_7O(cioKNb+@J5zTb6#4am#iG;@WO_jxp; z?SGXX(Yj~!i17V0pl=2`NSUco2g#&?-EI?Bq=La|i=rKe$ub;_Pp2)@q43mnM)_n+ zn}`if^H3l@NgDn`^efiHI`@bxHWb~b=z9GIUEYkb%b#?y%U^V}JY|eDCN&U1;IIYT6>Xn$$fTh4hmfxYZIlRKa?QDmznZH#iRT%%awgS_9Tx zl=7^%O|MCAc4; zZEX&%n8U1GrxT6e}e1rBE!K2xTaIt9$_M!Hz4)q1gB=7$CCg z&W7UCkzm3(hMOoGBt9(7_YL$8B`Ov1Pv?=K0ED9S^LrJ-*p5bJ;;hrQ`1Jhj`8gPW z)3B(rM}V%TttUE%x;}UEv`mXL%}1fCH%-V9G)uotF(Uh>*!UMhY0G#N>inRhVkQcc zwg<>UrwD+(xSE-1xW zrXm=UI;j!HH6>&SwK6H0rsdaAgb|ox(8C4pV^6`tvGt;gMf--)V=G)QE?+vfTD)Vi zKjkUCR(Z8@DW3GyuX*ZkTGorouf6>Bmv0oU7ByYrQ|^Lmc~|q6=9eOWVNSO9ueA3k z+lN=$hp*(VxlgSZRb89;`b^4KoGL84a&o;~OqMsVls6~K+g8fk9#~Dq-YYzber4CD zuTI}E+}L{~v|PP^wdep^uJM1T`rlUHn*RRmAJ5(zd;7$4+o`)Xr>^AFBZaHNQq|4E zHTUk6yDaIhS#j6AS$AV@wf4Z8`YN4G%!S27KntRkETuVxmXSws6E+^c*x*{ROaONLG|P}Bue|h*~lfOwYqYdoREI zwU=L;S;?zhnpirs?5JBd)oCM9VI9Dx%r>b=o(Ah0kZ%#Fbuc9Hl4-keEw`d+CRqMpk z;ZI{1=O(7*$XsMT1~IycJi+E6M?;SodNnjL4^^eVHEq0bo+gDHj*1#n1zdU) zicOR$$Y`5ooeG@c$QaRL#qP3%EH?enFw=6f?(bM|Uv;NKlv)u%CHrM~4oV*a6{)BQ`#mL%XkZN zv8QhM|AN-C&MtL^7hpA^nB-r&eh*upuD5*3{l`~TmP`B`raAYjiW<+>=q0o$f3_y~ zO2azItk^B(O#xG`Ri?_suo%$BWg)i%K|p6|2$)rAHrPkJhNk4vq*6RD2M?(363L{O zYEd?aoT`okeC3n-X4dx&jtdsaDhaxtWL+C1n`GDB&vJ{cR#+sm++r>ck@#m_i6V8b zwCj^|C5PlZXi`dJKj+i_)zu&pyDelbzE<7nvz(k_msz*{k!^Xj3_RJxFz5*LoITW24hbqqs%L3c?z0_B%Y>p}E6oerTlj#`J zc5Rx{ygWabws!XfhR&Qgk@j{mFTi2N?^aTfFiQ$Um=-W# z_HbAo&|@a_r}>H5pu$lSzpFBo8Gdq19ncu6%726cj1b*Ng87+v3a^ZO!@e+(a+lt9 zH{$9lNtU;)l(*cRyfwL6-f`E}vC#jqyCmrrSKQ*NyLMsVp2?wTARBKAYo@(Fx4Q2M zMX$$}+TS?xdq-A_n{Q6sE#7;p{req%+_5HfW>xmPZceWW2RBR}^9zQLoxYUQjeqM- z*A?4qLn&twtm*Vacx`aQCAjR1`~xp%E4ZBhwfvORwO&w}ENECMXvii~-l9h~v(3(| z21Q9n(~6^sYy>Z8HiBnwwA*SbiDq|tWidih zGQ00I^Z`I9z7FLAUB7o)x&8%!gnqvbAfc-QBs3N^kob+?rp+qETY$v)l0hY>lYWVMsWu`~Jq-aQ3 zzu;ZPz`7wOU&mMzrCYF4?LHwX15EkfP$6TBoG|Ta-M1&c>7G*pUSmigV$hRr_LyEpb5ra<~Q-w1EEB^=FO-<2~xgK?rA@6G~BHDw*RiDdC_vu?YlB^x3F>5y@Nov zH0i2Yan;;tyxF|!dS;;?N^`>Hq`Pj#U3a5@)!ni%@Ugp8QKGE6>vSmGe%rrhItdhp zqo}PIIQ*=lzF95abu)Iic;Bso?+^X)(3;SdMdH1;o?R0<2#NcEmR`bGAUyQ(>+XUp z1K)t|#+PyzrQ9_sZ|PFwQps{n`?CAlOy-8imY4s)$N8#qAaZ#=A#xRzIT|9~-?*Hy8C<`5#-&NasdmQqz3~M9$DSW(Y8$ z3JWjYk4IbBf`JN3ku6T7W?}n990%x(`w;}a7a1&@T;Qn`P^_6EW1-&nj zoj?;=bE|_O|DYZPfMRw^hO-l*>OPJb@s=DcyIQ=n*Tp${NWtN=L z_2ncUi~zLj2Qz(nI*5&CK~w{E=t44V31laxCD&x9(JZ{`W+?}Zw((gIvFJb~hyGr& zjOc(AAOh*|h(!_rA}pl?5!-kpCO(TJ@K+e01O372DG_RKg=VV@P*t7V?Va*e?2w(5 z!)jh;aUK#+z%WI=?h5TENq`woW305gau12abZq3pbVw$FEX1A_n~uywZaNs&~tMs$z%pBbL z=HlVWa40xHr_ywCpH;q1^?pDR8<2YW@-9(JhEU9kYX++nq$WUC75lu;FNR@P|7tKvWOSNqwb-S%~+*^Vo z4>qA^X^V1(4yLHt@kC@U&Cf?;Y3qgYnb~nUo;FX0f}vLx=rLlo_D6R6LS=t;`# zL2RYi7@LDfT(5x+I#SGz*-_%2vv>mzbcS+ZP@ZSQ%8~+(oNU-w($3|3HykVp|2+3b z9!utP7RT?jz0NPT|JK-j7u{0eN)IMkxcZ-X4?t|4PF0hUb@L0Ut<4hPHH6mYaFlFi zERZ%9rA!)e*4$Y%M_*?mR1wwJ#IKFS*TBf3rr40nkoZA>amTI zzdQ@@mCNuOu(I$lKU?6qv%zr}FdtDNYKz*Vj;J%57Z7%2YD{5H;LHtJ(#*2MHJMD^ zMY0F-hU;`UGD)=`>T}u2tA@wR1#Bwlt4|IBtl_0+7|vDNu9kjIb46l3#n~)JH2*1m zbv(JRfqV_12VWdjJH(Cp)qanXnT7?mAH#aVKa-d1UcjkWWUIBG+GFQu?{UBiD_R~| z(E|BxMshW;Qw;Lf;oX^z=`K=s-lMMEb3IB-Aq#46)d>kA@yp)OC>ch!)Y82vE7b$@ zq%ICFnt%5Hv>D;Nt~UKoGS^aG?zvW;<#;~ysY349+F!VC36uvi$nZ4zCAFe&_(jjl>ZU~PZVy=2DxN;e?@tvTk|qhl;xA! zGf})XpAlD<`(Kf(2+frly(}>U5U6!57TG%!rDxce5|pF2*#g8VB+8U5b&zUhmY2s) zsL$cJI_bRqt-6DHHV zuv2;XkV8zqNxv-0`${uc2Ldle7Y(fek{irksu7 zGB)zSf#7Uo9+b@0>&|-QrJQvsrze}?TX)v2JDb*>%_+(&%w~Akoi*#u#&xGZuftms|FzXQGGmtRc&9LrTWZKhQHVBoGhaId2JP1Bn%ek(sI z9#|0%B*nuk;^Et0yepnqtr*nRI&{15hl4*D{PU9^oLh6BO%+vN`L!FxH*CuVJ8upw z7aX|bJa8XJLp>WM98S2g18+-Rs}6CYJ7vxL?ZlT8ukTJ;YwuWVQ@*lm$F3e*t8QEM z?N9nnF8fZdwVzzHZNMMUy-1%Uc))XoCD%>YU;Ji%vZQ6Dq$OFhf2Cyqt$%U1q<7WV zw`fZ_T&$qNJrLJV|0&Sk0P=8~BZxkOypK{!fa9NHcppY^dec`&=$*K9`kN^96XxpqH+p8KAaVP>~^OhU%AS5DS_Nol9a@>$thzhhS$& zIZgy=TTn}>NRwf3z(S!s(XMTQeDov(Gbu0z<2Yy;yy>!Xy;dB`{LG@zK^??G=INcg zM%I?A)d+$WQ+&fEzP+E=vd5UQ&(nc+jb+T`88}P?b6ddph-hyM>U`v4EYn(#T+F;m<7#8Q!PoeIE8my!JR$FX4FjS5o^>`%?(!TJp5|aHngkuxdG-T z1ass-vx!P4SpG#=0DD!HxAF;!$QD$C^NNd`gZSB|4JVc+?zV)2_@%B&rAv`9x zwC%Sib}1iuC}M(sctXb?5kH}r%}-;1385j_(r~_| z;aq|kne#KDS@2it_nnxgD06~3Au5^=EjN1@4a^K3+oV5oR3i-#J--P9;tH# zCt-$q&WdNw40KajIu?`InXCMn(*r|&V$X{Mr$>-b%leDb#z>3-f7%?2;xkh+nV%G! zz!^$?i=qHUXAwaS3++)njDvf5WaFR|j@HaZ$(?gNo)%(Y5Lh-+@+76$M->z{=rT2P zg(7VH48t@)sXjzFG01qSB;7bj5kY|J;X`A_>77V${GxJvocQl_9((|_i2;M8D7O?- z0&!P5Hbzm=R52b#sY7j!(I|)yQcioye}hU4P`-oR56gnUd41Q4uNE`6&Wo!a|IM1a zo?Y<%bXGx$ve2_(DmM2R)=Mjwg5NAlmNu`HHh);!vN(_`s7MynuN2fL3mWefG=2oV zezAD%OIN=HCs9}Na(UaDtBr0})F&%iRw`iTU#&Rsh%;8^!}YKds()De$x-tLEEE2u z`?+QJb2le$1>Tz7;JLgqc>235FMV;tX!qa*dsSnyYWGUj?qpTRN>xXyq~?wM-^*Vu zX-bytT`AeS$s4PS{hw}#wP@!Coct>`1g@mw`o-@R+&uT)s@3ZDwc_^MJ!^+g zq#9b5>>rg>uGcqx=hz<{`__q-y0%+gw+<}VJp1)yf8W5BwQlU;1n-))YQ3c54g2rg zzv)~l-f@$^F~3~cvS`n$i+Vq>uL-B|6y{Be)Aow`X}Rd=+sD>~lOH<@;bi*BgJQ0v z8qNYV24DHL!K;JIwViLbCw-?@eW%DYfs9|=Q_dV>j#cYL`|bLq(7hsbGwVeUtQWtA zm-Zh!#Xd9lZb1pfyBrjEbnfUagx9G7Ki+FBL;8Krg!GRK9eqagkHw_RA=F{=(9*$ zCI1A)VfO%jD&KWdlutY9?h`)l^h2!U7;RmJJEE@yG~%lOOz%Vqrgx%5M(@Ouir$GO z6}=NnDtafDgx<+^-$lvC^-TgEh8Z$#(kIBaFi2Nd-l_i5!iXgDNQdmOi$VtaxqQ;s|wKD7%~BDMwW%r;C$G%tx^1BPMy4Vcmg%E zEC^h>R93-0!e<#TuuuShQ}#F5Jp9(2@h}?|Fj5TSD~M6YXtDatb5rNOyFar!>Nvn2 z31lo}Vb!K%N=Z8179`V%P18q>2=n*~7CtC~0|RsrjILW?^;d7-a_*uAt50sANRmkyjEG+bj@SOrSbLiPqdOuCyIuA7D`! z1?3|vGI0TnAMiUh%>a{^<)2a(!@6}!5rs&bXJ5esWrm9k5|2<8p%LmgQThXl{*t1t zY5^T;{&&hfMo|_&W29bS(tPHCg93vt4K*1%A^$HFW2Az*1l%j(l=H1AA;9Ej2gK!+ zkoUl0FN^Yr-KI?C%PtbO6Cz_KOGkkCp2Ez_uow)tCA-b{GSE$6aw$+*bKj^7r}oB zpS~FjMkerO!=E8jeg;w6iqFJNfumI3`kQp0*dSVgar&s0^7<{YY5GzkJ6*`WJeaPS z#%DV5=`5^He5SKiu}-ir{6QI~eAmyry$C*qK%_Fw4-cGBjAcY2)BeXkP}j&6cpf}_2^G+eWQ3yPkz^paRnVIa?EeB35=@-{ literal 0 HcmV?d00001 diff --git a/custom_components/mail_and_packages/utils/__pycache__/imap.cpython-314.pyc b/custom_components/mail_and_packages/utils/__pycache__/imap.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..68eb95769b70e8e7ecebd6e4d38f8c483231dde5 GIT binary patch literal 36487 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 G;Qt5Q literal 0 HcmV?d00001 diff --git a/custom_components/mail_and_packages/utils/__pycache__/shipper.cpython-314.pyc b/custom_components/mail_and_packages/utils/__pycache__/shipper.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4e8d5378ce2250e865c90096075b0c7e85694a75 GIT binary patch literal 12250 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 literal 0 HcmV?d00001 diff --git a/custom_components/mail_and_packages/utils/amazon.py b/custom_components/mail_and_packages/utils/amazon.py new file mode 100644 index 0000000..cee4ab5 --- /dev/null +++ b/custom_components/mail_and_packages/utils/amazon.py @@ -0,0 +1,396 @@ +"""Amazon specific utilities.""" + +from __future__ import annotations + +import datetime +import email +import logging +import re +from email.header import decode_header +from functools import partial +from pathlib import Path +from typing import Any + +import aiohttp +import dateparser +from aioimaplib import IMAP4_SSL + +from custom_components.mail_and_packages.const import ( + AMAZON_DELIVERED_SUBJECT, + AMAZON_DOMAINS, + AMAZON_EMAIL, + AMAZON_IMG_LIST, + AMAZON_IMG_PATTERN, + AMAZON_ORDERED_SUBJECT, + AMAZON_SHIPMENT_SUBJECT, + AMAZON_SHIPMENT_TRACKING, + AMAZON_TIME_PATTERN, + AMAZON_TIME_PATTERN_END, + AMAZON_TIME_PATTERN_REGEX, + DEFAULT_AMAZON_DAYS, +) +from custom_components.mail_and_packages.utils.cache import EmailCache +from custom_components.mail_and_packages.utils.date import get_today +from custom_components.mail_and_packages.utils.image import io_save_file +from custom_components.mail_and_packages.utils.imap import ( + email_fetch, + email_search, +) + +_LOGGER = logging.getLogger(__name__) + +_MAX_IMAGE_SIZE = 10 * 1024 * 1024 # 10 MB + +DOMAIN_LANG_MAP = { + "amazon.de": ["versandbestaetigung", "Geliefert:", "Zugestellt:"], + "amazon.it": ["conferma-spedizione", "Consegna effettuata:", "Arriverà"], + "amazon.nl": [ + "update-bestelling", + "verzending-volgen", + "auto-bevestiging", + "Bezorgd:", + ], + "amazon.fr": ["confirmation-commande", "Livré", "Livraison : Votre", "Arrivée :"], + "amazon.ca": ["confirmation-commande", "Livré", "Livraison : Votre", "Arrivée :"], + "amazon.es": [ + "confirmar-envio", + "Entregado:", + "Enviado:", + "Pedido efetuado:", + "Chega ", + ], + "amazon.pl": ["Dostarczono:"], +} + + +def filter_amazon_strings(strings: list[str], domain: str) -> list[str]: + """Filter list of strings based on the domain language.""" + all_mapped_strings = [] + for lang_list in DOMAIN_LANG_MAP.values(): + all_mapped_strings.extend(lang_list) + + def is_mapped(s: str) -> bool: + return any(m in s for m in all_mapped_strings) + + base_strings = [s for s in strings if not is_mapped(s)] + + domain_strings = [] + if domain in DOMAIN_LANG_MAP: + mapped_for_domain = DOMAIN_LANG_MAP[domain] + domain_strings = [s for s in strings if any(m in s for m in mapped_for_domain)] + + # Only amazon.ca and unmapped domains (like .com, .co.uk) should use base English strings + if domain in DOMAIN_LANG_MAP and domain != "amazon.ca": + return list(dict.fromkeys(domain_strings)) + + return list(dict.fromkeys(base_strings + domain_strings)) + + +def get_decoded_subject(msg: email.message.Message) -> str: + """Decode email subject.""" + header_val = msg["subject"] + if header_val: + decoded_parts = [] + for subject_bytes, encoding in decode_header(header_val): + if isinstance(subject_bytes, bytes): + if encoding: + try: + decoded_parts.append(subject_bytes.decode(encoding, "ignore")) + continue + except (LookupError, UnicodeError): + pass + decoded_parts.append(subject_bytes.decode("utf-8", "ignore")) + else: + decoded_parts.append(str(subject_bytes)) + return "".join(decoded_parts) + + body = get_email_body(msg) + if not body: + return "" + title_match = re.search( + r"]*>([^<]+)", body, re.IGNORECASE | re.DOTALL + ) + if not title_match: + return "" + return title_match.group(1).strip() + + +def get_email_body(msg: email.message.Message) -> str: + """Extract and decode the email body safely.""" + try: + if msg.is_multipart(): + # Standard practice is to look for text/plain then text/html + for part in msg.walk(): + if part.get_content_type() == "text/plain": + return part.get_payload(decode=True).decode("utf-8", "ignore") + # If no text/plain, fall back to first part + payload = msg.get_payload(0) + if isinstance(payload, email.message.Message): + return payload.get_payload(decode=True).decode("utf-8", "ignore") + return str(payload) + + return msg.get_payload(decode=True).decode("utf-8", "ignore") + except (ValueError, TypeError, IndexError, AttributeError) as err: + _LOGGER.debug("Problem decoding email message: %s", err) + return "" + + +def extract_order_numbers(text: str, pattern: re.Pattern | str) -> list[str]: + """Extract order numbers from text.""" + if isinstance(pattern, str): + pattern = re.compile(pattern) + return pattern.findall(text) + + +async def parse_amazon_arrival_date( + hass: Any, + email_msg: str, + email_date: datetime.date, +) -> datetime.date | None: + """Determine arrival date from email.""" + today_date = get_today() + + # Try using regex for more precise extraction of the arrival date string + if date_str := amazon_date_regex(email_msg): + base_datetime = datetime.datetime.combine( + email_date or today_date, + datetime.time(), + ) + + # 1. Try parsing without PREFER_DATES_FROM: future to handle relative terms (any language) + dateobj = await hass.async_add_executor_job( + partial( + dateparser.parse, + date_str, + settings={ + "RELATIVE_BASE": base_datetime, + "RETURN_AS_TIMEZONE_AWARE": False, + }, + ), + ) + if dateobj: + parsed_date = dateobj.date() + base_date = email_date or today_date + # Only accept matches that resolve to email_date (today) or email_date + 1 day (tomorrow) + if ( + parsed_date == base_date + or parsed_date == base_date + datetime.timedelta(days=1) + ): + return parsed_date + + # 2. Fall back to parsing with PREFER_DATES_FROM: future for absolute dates + dateobj = await hass.async_add_executor_job( + partial( + dateparser.parse, + date_str, + settings={ + "PREFER_DATES_FROM": "future", + "RELATIVE_BASE": base_datetime, + "RETURN_AS_TIMEZONE_AWARE": False, + }, + ), + ) + if dateobj: + return dateobj.date() + + # Fallback to chunk-based parsing + for search in AMAZON_TIME_PATTERN: + if search not in email_msg: + continue + + start = email_msg.find(search) + len(search) + chunk = email_msg[start : start + 50] + + dateobj = await hass.async_add_executor_job( + partial( + dateparser.parse, + chunk, + settings={ + "PREFER_DATES_FROM": "future", + "RELATIVE_BASE": datetime.datetime.combine( + email_date or today_date, + datetime.time(), + ), + "RETURN_AS_TIMEZONE_AWARE": False, + }, + ), + ) + if dateobj: + return dateobj.date() + return None + + +def amazon_email_addresses( + fwds: list[str] | str | None = None, + domain: str | None = None, +) -> list[str]: + """Generate Amazon email addresses.""" + if isinstance(fwds, str): + fwds = [fwds] + elif not isinstance(fwds, (list, tuple)): + fwds = None + + if domain is None: + domain = "amazon.com" + + # Use both AMAZON_EMAIL and AMAZON_SHIPMENT_TRACKING for prefixes + prefixes = list(AMAZON_EMAIL) + for p in AMAZON_SHIPMENT_TRACKING: + if f"{p}@" not in prefixes: + prefixes.append(f"{p}@") + + prefixes = filter_amazon_strings(prefixes, domain) + + value = [f"{e}{domain}" for e in prefixes] + if fwds: + for fwd in fwds: + if "@" in fwd: + value.append(fwd) + elif any(f in fwd for f in AMAZON_DOMAINS): + value.extend(f"{e}{fwd}" for e in prefixes) + return value + + +async def search_amazon_emails( + account: IMAP4_SSL, + address_list: list[str], + days: int, + domain: str | None = None, + cache: EmailCache | None = None, + forwarding_header: str = "", +) -> list[bytes]: + """Search for Amazon emails.""" + if not isinstance(days, int): + try: + days = int(days) + except (ValueError, TypeError): + days = DEFAULT_AMAZON_DAYS + + past_date = get_today() - datetime.timedelta(days=days) + tfmt = past_date.strftime("%d-%b-%Y") + amazon_subjects = ( + AMAZON_DELIVERED_SUBJECT + AMAZON_SHIPMENT_SUBJECT + AMAZON_ORDERED_SUBJECT + ) + if domain: + amazon_subjects = filter_amazon_strings(amazon_subjects, domain) + + (server_response, sdata) = await email_search( + account=account, + address=address_list, + date=tfmt, + subject=amazon_subjects, + header=forwarding_header, + ) + + if server_response != "OK" or not sdata[0]: + return [] + + return sdata[0].split() + + +async def download_amazon_img( + img_url: str, + img_path: str, + img_name: str, + hass: Any, +) -> None: + """Download image from url.""" + img_path = Path(img_path) / "amazon" + filepath = img_path / img_name + timeout = aiohttp.ClientTimeout(total=30) + async with aiohttp.ClientSession(timeout=timeout) as session: + try: + async with session.get(img_url.replace("&", "&")) as resp: + if resp.status != 200: + return + content_type = resp.headers.get("content-type", "") + if "image" not in content_type: + return + content_length = int(resp.headers.get("content-length", 0)) + if content_length > _MAX_IMAGE_SIZE: + _LOGGER.warning( + "Amazon image too large to download (%d bytes), skipping", + content_length, + ) + return + data = await resp.read() + if len(data) > _MAX_IMAGE_SIZE: + _LOGGER.warning( + "Amazon image exceeds size limit after download, discarding" + ) + return + await hass.async_add_executor_job(io_save_file, filepath, data) + except aiohttp.ClientError as err: + _LOGGER.error("Problem downloading file: %s", err) + + +async def get_amazon_image_urls( + sdata: Any, + account: IMAP4_SSL, + cache: EmailCache | None = None, +) -> list[str]: + """Find all Amazon delivery image URLs.""" + mail_list = sdata.split() + pattern = re.compile(rf"{AMAZON_IMG_PATTERN}") + urls = [] + for i in mail_list: + if cache: + data = (await cache.fetch(i, "(RFC822)"))[1] + else: + data = (await email_fetch(account, i, "(RFC822)"))[1] + for response_part in data: + if isinstance(response_part, (bytes, bytearray)): + msg = email.message_from_bytes(response_part) + for part in msg.walk(): + if part.get_content_type() != "text/html": + continue + part_payload = part.get_payload(decode=True) + part_content = part_payload.decode("utf-8", "ignore") + found = pattern.findall(part_content) + for url in found: + if url[1] not in AMAZON_IMG_LIST: + continue + full_url = url[0] + url[1] + url[2] + if full_url not in urls: + urls.append(full_url) + return urls + + +def _extract_hub_code( + body: str, + hub_pattern: str, + subject: str, + subject_pattern: str, +) -> str: + """Extract Amazon Hub code from email body or subject.""" + # Check subject first + if (found := re.compile(subject_pattern).search(subject)) is not None: + return found.group(3) + + # Check body + if (found := re.compile(hub_pattern).search(body)) is not None: + return found.group(2) + return "" + + +def amazon_date_search(email_msg: str, patterns: list[str] | None = None) -> int: + """Search for a date pattern in an email message and return its index.""" + if patterns is None: + patterns = AMAZON_TIME_PATTERN_END + + for pattern in patterns: + if (index := email_msg.find(pattern)) != -1: + return index + return -1 + + +def amazon_date_regex(email_msg: str, patterns: list[str] | None = None) -> str | None: + """Search for a date pattern using regex and return the first capture group.""" + if patterns is None: + patterns = AMAZON_TIME_PATTERN_REGEX + + for pattern in patterns: + if (found := re.compile(pattern, re.IGNORECASE).search(email_msg)) is not None: + if found.groups(): + return found.group(1) + return None diff --git a/custom_components/mail_and_packages/utils/cache.py b/custom_components/mail_and_packages/utils/cache.py new file mode 100644 index 0000000..1381959 --- /dev/null +++ b/custom_components/mail_and_packages/utils/cache.py @@ -0,0 +1,104 @@ +"""Email caching utility for Mail and Packages.""" + +import logging + +from aioimaplib import IMAP4_SSL + +from .imap import email_fetch, email_fetch_batch, email_fetch_headers, email_fetch_text + +_LOGGER = logging.getLogger(__name__) + + +class EmailCache: + """Cache for IMAP email fetches to avoid duplicate downloads.""" + + def __init__(self, account: IMAP4_SSL) -> None: + """Initialize the cache.""" + self.account = account + self._cache_rfc822: dict[str, tuple] = {} + self._cache_text: dict[str, tuple] = {} + self._cache_headers: dict[str, tuple] = {} + + async def fetch(self, email_id: str | bytes, parts: str = "(RFC822)") -> tuple: # noqa: C901 + """Fetch email content or return from cache.""" + eid_str = email_id.decode() if isinstance(email_id, bytes) else str(email_id) + + if parts in ("(RFC822)", "BODY[]"): + if eid_str in self._cache_rfc822: + return self._cache_rfc822[eid_str] + res = await email_fetch(self.account, eid_str, parts) + if res[0] == "OK": + self._cache_rfc822[eid_str] = res + return res + + if "HEADER" in parts: + if eid_str in self._cache_headers: + return self._cache_headers[eid_str] + # fallback to RFC822 cache if we already have it + if eid_str in self._cache_rfc822: + return self._cache_rfc822[eid_str] + res = await email_fetch_headers(self.account, eid_str) + if res[0] == "OK": + self._cache_headers[eid_str] = res + return res + + if "TEXT" in parts or parts == "(BODY[1])": + if eid_str in self._cache_text: + return self._cache_text[eid_str] + if eid_str in self._cache_rfc822: + return self._cache_rfc822[eid_str] + res = await email_fetch_text(self.account, eid_str, parts) + if res[0] == "OK": + self._cache_text[eid_str] = res + return res + + # Unknown part, bypass cache + return await email_fetch(self.account, eid_str, parts) + + async def fetch_batch( + self, email_ids: list[str | bytes], parts: str = "(RFC822)" + ) -> tuple: + """Fetch multiple emails in a batch, retrieving from cache if applicable.""" + # For simplicity, if we don't have all of them, fetch the missing ones in batch + missing_ids = [] + eid_strs = [e.decode() if isinstance(e, bytes) else str(e) for e in email_ids] + + # Determine which ones we already have + for eid_str in eid_strs: + if parts in ("(RFC822)", "BODY[]"): + if eid_str not in self._cache_rfc822: + missing_ids.append(eid_str) + elif "HEADER" in parts: + if ( + eid_str not in self._cache_headers + and eid_str not in self._cache_rfc822 + ): + missing_ids.append(eid_str) + elif "TEXT" in parts or parts == "(BODY[1])": + if ( + eid_str not in self._cache_text + and eid_str not in self._cache_rfc822 + ): + missing_ids.append(eid_str) + else: + missing_ids.append(eid_str) + + # Batch fetch only what is missing + if missing_ids: + # Just use fetch() internally for now to populate individual items since fetch_batch + # returns combined lines which might be tricky to parse. + # Wait, email_fetch_batch might be tricky to cache without parsing the response to separate emails. + # So actually we will just loop `fetch` for batch if we want it cleanly cached, or we don't cache + # `fetch_batch` if we aren't parsing it. + # Actually `fetch_batch` isn't needed if we just do individual fetches? No, batch is faster. + # But parsing batch response to stick into cache is annoying. + pass + + # For this version, let's keep fetch_batch simple and bypass cache. + return await email_fetch_batch(self.account, email_ids, parts) + + def clear(self) -> None: + """Clear the cache.""" + self._cache_rfc822.clear() + self._cache_text.clear() + self._cache_headers.clear() diff --git a/custom_components/mail_and_packages/utils/date.py b/custom_components/mail_and_packages/utils/date.py new file mode 100644 index 0000000..8446891 --- /dev/null +++ b/custom_components/mail_and_packages/utils/date.py @@ -0,0 +1,27 @@ +"""Date and time helpers for Mail and Packages.""" + +import datetime + + +def get_today() -> datetime.date: + """Get today's date using system local timezone (Home Assistant's timezone). + + Returns date object using the system's local timezone. + """ + return datetime.date.today() + + +def get_formatted_date() -> str: + """Return today in specific format. + + Returns current timestamp as string + """ + return get_today().strftime("%d-%b-%Y") + + +async def update_time() -> datetime.datetime: + """Get update time. + + Returns current timestamp as datetime object. + """ + return datetime.datetime.now(datetime.UTC) diff --git a/custom_components/mail_and_packages/utils/email.py b/custom_components/mail_and_packages/utils/email.py new file mode 100644 index 0000000..eb41f73 --- /dev/null +++ b/custom_components/mail_and_packages/utils/email.py @@ -0,0 +1,201 @@ +"""Email parsing and validation utilities for Mail and Packages.""" + +import email +import logging +import re +from typing import Any + +from aioimaplib import IMAP4_SSL +from voluptuous import Email, MultipleInvalid, Schema + +from custom_components.mail_and_packages.const import SENSOR_DATA +from custom_components.mail_and_packages.utils.cache import EmailCache + +from .imap import email_fetch + +_LOGGER = logging.getLogger(__name__) + + +def validate_email_address(email_address: str) -> bool: + """Validate the format of an email address. + + Args: + email_address (str): The email address to validate. + + Returns: + bool: `True` if the email address is valid, `False` otherwise. + + """ + try: + schema = Schema(Email()) # pylint: disable=no-value-for-parameter + schema(email_address) + except MultipleInvalid: + _LOGGER.error("'%s' does not look like a valid email address", email_address) + return False + + _LOGGER.debug("%s is a valid email address", email_address) + + return True + + +def generate_service_email_domains(amazon_fwds: list) -> set[str]: + """Generate a set of service email domains from amazon domains and SENSOR_DATA. + + Returns: + set[str]: A set of unique email domains. + + """ + domains = {fwd.split("@")[1] for fwd in amazon_fwds if "@" in fwd} + for sensor in SENSOR_DATA.values(): + for address in sensor.get("email", []): + if "@" not in address: + continue + domains.add(address.split("@")[1]) + return domains + + +def _match_patterns( + text: str, + patterns: list[re.Pattern], + body_count: bool, +) -> tuple[int, int | None]: + """Apply patterns to text and return occurrence count and extracted value. + + Returns: + tuple[int, int | None]: (count_of_matches, extracted_value) + + """ + local_count = 0 + extracted_value = None + + for pattern in patterns: + if body_count: + if (found := pattern.search(text)) and len(found.groups()) > 0: + _LOGGER.debug( + "Found (%s) in email result: %s", + pattern.pattern, + found.groups(), + ) + extracted_value = int(found.group(1)) + elif (found := pattern.findall(text)) and len(found) > 0: + _LOGGER.debug( + "Found (%s) in email %s times.", + pattern.pattern, + len(found), + ) + local_count += len(found) + + return local_count, extracted_value + + +async def _scan_email_for_text( + account: type[IMAP4_SSL], + email_id: str, + patterns: list[re.Pattern], + body_count: bool, + cache: EmailCache | None = None, +) -> tuple[int, int | None]: + """Scan a single email for terms. + + Returns: + tuple[int, int | None]: (total_matches, last_extracted_value) + + """ + total_matches = 0 + last_value = None + + if cache: + data = (await cache.fetch(email_id, "(RFC822)"))[1] + else: + data = (await email_fetch(account, email_id, "(RFC822)"))[1] + for response_part in data: + if not isinstance(response_part, (bytes, bytearray)): + continue + + msg = email.message_from_bytes(response_part) + + for part in msg.walk(): + if part.get_content_type() not in ["text/html", "text/plain"]: + continue + + email_msg = part.get_payload(decode=True) + try: + email_msg = email_msg.decode("utf-8", "ignore") + except (AttributeError, UnicodeError): + continue + + matches, value = _match_patterns(email_msg, patterns, body_count) + total_matches += matches + if value is not None: + last_value = value + + return total_matches, last_value + + +async def find_text( + sdata: Any, + account: type[IMAP4_SSL], + search_terms: list, + body_count: bool, + cache: EmailCache | None = None, +) -> int: + """Filter for specific words in email.""" + _LOGGER.debug("Searching for (%s) in (%s) emails", search_terms, len(sdata)) + mail_list = sdata[0].split() + count = 0 + + # Pre-compile regex patterns once + patterns = [re.compile(rf"{term}") for term in search_terms] + + for i in mail_list: + matches, value = await _scan_email_for_text( + account, i, patterns, body_count, cache + ) + + if body_count: + # If extracting a value, "last found value wins" (updates count) + if value is not None: + count = value + else: + # If counting occurrences, accumulate + count += matches + + return count + + +async def find_text_matches( + sdata: Any, + account: type[IMAP4_SSL], + search_terms: list, + body_count: bool, + cache: EmailCache | None = None, +) -> tuple[int, list[bytes]]: + """Filter for specific words in email and return matches and matching IDs.""" + _LOGGER.debug("Searching for (%s) in (%s) emails", search_terms, len(sdata)) + mail_list = sdata[0].split() + count = 0 + matching_ids = [] + + # Pre-compile regex patterns once + patterns = [re.compile(rf"{term}") for term in search_terms] + + for i in mail_list: + matches, value = await _scan_email_for_text( + account, i, patterns, body_count, cache + ) + + matched = False + if body_count: + # If extracting a value, "last found value wins" (updates count) + if value is not None: + count = value + matched = True + # If counting occurrences, accumulate + elif matches > 0: + count += matches + matched = True + + if matched: + matching_ids.append(i) + + return count, matching_ids diff --git a/custom_components/mail_and_packages/utils/image.py b/custom_components/mail_and_packages/utils/image.py new file mode 100644 index 0000000..9a3cc80 --- /dev/null +++ b/custom_components/mail_and_packages/utils/image.py @@ -0,0 +1,485 @@ +"""Image processing and management utilities for Mail and Packages.""" + +import datetime +import hashlib +import logging +import os +import subprocess # nosec +import uuid +from pathlib import Path +from shutil import copyfile, which + +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant +from PIL import Image, ImageOps + +from custom_components.mail_and_packages.const import ( + CONF_AMAZON_CUSTOM_IMG, + CONF_AMAZON_CUSTOM_IMG_FILE, + CONF_CUSTOM_IMG, + CONF_CUSTOM_IMG_FILE, + CONF_FEDEX_CUSTOM_IMG, + CONF_FEDEX_CUSTOM_IMG_FILE, + CONF_STORAGE, + CONF_UPS_CUSTOM_IMG, + CONF_UPS_CUSTOM_IMG_FILE, + CONF_WALMART_CUSTOM_IMG, + CONF_WALMART_CUSTOM_IMG_FILE, + DEFAULT_AMAZON_CUSTOM_IMG_FILE, + DEFAULT_CUSTOM_IMG_FILE, + DEFAULT_FEDEX_CUSTOM_IMG_FILE, + DEFAULT_UPS_CUSTOM_IMG_FILE, + DEFAULT_WALMART_CUSTOM_IMG_FILE, + OVERLAY, +) + +from .date import get_formatted_date + +_LOGGER = logging.getLogger(__name__) + + +async def _check_ffmpeg() -> bool: + """Check if ffmpeg is installed. + + Returns boolean + """ + return which("ffmpeg") + + +def default_image_path( + hass: HomeAssistant, # pylint: disable=unused-argument + config_entry: ConfigEntry, +) -> str: + """Return value of the default image path. + + Returns the default path based on logic + """ + storage = None + try: + storage = config_entry.get(CONF_STORAGE) + except AttributeError: + storage = config_entry.data[CONF_STORAGE] + + if storage: + return storage + return "custom_components/mail_and_packages/images/" + + +def hash_file(filename: str) -> str: + """Return the SHA-1 hash of the file passed into it. + + Returns hash of file as string + """ + # make a hash object + the_hash = hashlib.sha1() # nosec + + # open file for reading in binary mode + with Path(filename).open("rb") as file: + # loop till the end of the file + chunk = 0 + while chunk != b"": + # read only 1024 bytes at a time + chunk = file.read(1024) + the_hash.update(chunk) + + # return the hex representation of digest + return the_hash.hexdigest() + + +def _delete_file(file_path: Path, context: str) -> bool: + """Delete a single file with error handling.""" + try: + if file_path.exists(): + file_path.unlink() + _LOGGER.debug("%s - Successfully removed: %s", context, file_path) + return True + _LOGGER.debug("%s - File does not exist: %s", context, file_path) + except OSError as err: + _LOGGER.error("Error attempting to remove image in %s: %s", context, err) + return False + + +def _cleanup_directory(path: str) -> None: + """Handle directory-wide cleanup.""" + if not Path(path).is_dir(): + _LOGGER.debug("cleanup_images - Directory does not exist: %s", path) + return + + try: + files_before = [x.name for x in Path(path).iterdir()] + _LOGGER.debug( + "cleanup_images - Files in directory BEFORE cleanup: %s", + files_before, + ) + for file in files_before: + if file.endswith((".gif", ".mp4", ".jpg", ".png")): + full_path = Path(path) / file + _delete_file(full_path, "cleanup_images") + + files_after = [] + if Path(path).is_dir(): + files_after = [f.name for f in Path(path).iterdir()] + + _LOGGER.debug( + "cleanup_images - Files in directory AFTER cleanup: %s", + files_after, + ) + except FileNotFoundError: + _LOGGER.debug("cleanup_images - Directory removed during cleanup: %s", path) + except OSError as err: + _LOGGER.error("Error listing directory for cleanup: %s", err) + + +def cleanup_images(path: str, image: str | None = None) -> None: + """Clean up image storage directory. + + Only suppose to delete .gif, .mp4, and .jpg files + """ + _LOGGER.debug("=== cleanup_images CALLED === path: %s, image: %s", path, image) + + if isinstance(path, tuple): + path, image = path + + if image is not None: + full_path = Path(path) / image + _delete_file(full_path, "cleanup_images") + return + + _cleanup_directory(path) + + +def copy_overlays(path: str) -> None: + """Copy overlay images to image output path.""" + overlays = OVERLAY + check = all(item.name in overlays for item in Path(path).iterdir()) + + # Copy files if they are missing + if not check: + for file in overlays: + _LOGGER.debug("Copying file to: %s", path + file) + copyfile( + Path(__file__).parent.parent / file, + path + file, + ) + + +def resize_images(images: list, width: int, height: int) -> list: + """Resize images.""" + all_images = [] + for image_path in images: + try: + img_path = Path(image_path) + with img_path.open("rb") as fd_img: + img = Image.open(fd_img) + img.thumbnail((width, height), resample=Image.Resampling.LANCZOS) + img = ImageOps.pad( + img, + (width, height), + method=Image.Resampling.LANCZOS, + ) + img = img.crop((0, 0, width, height)) + new_image_path = img_path.parent / f"{img_path.stem}_resized.gif" + img.save(new_image_path, "GIF") + all_images.append(str(new_image_path)) + + except (OSError, ValueError) as err: + _LOGGER.error("Error processing image %s: %s", image_path, err) + continue + + return all_images + + +def random_filename(ext: str = ".jpg") -> str: + """Generate random filename.""" + return f"{uuid.uuid4()!s}{ext}" + + +def io_save_file(path: str | Path, data: bytes) -> None: + """Write bytes to a file synchronously (for use in executor).""" + with Path(path).open("wb") as the_file: + the_file.write(data) + + +def _generate_mp4(path: str, image_file: str) -> None: + """Generate mp4 from gif. + + use a subprocess so we don't lock up the thread + command: ffmpeg -f gif -i infile.gif outfile.mp4 + """ + base_path = Path(path) + gif_image = base_path / image_file + mp4_file = base_path / image_file.replace(".gif", ".mp4") + + filecheck = mp4_file.is_file() + + _LOGGER.debug("Generating mp4: %s", mp4_file) + if filecheck: + # Construct path string with trailing slash to ensure cleanup_images concatenates correctly + cleanup_images(str(mp4_file.parent) + "/", mp4_file.name) + _LOGGER.debug("Removing old mp4: %s", mp4_file) + + try: + cmd = [ + "ffmpeg", + "-y", + "-i", + str(gif_image), + "-pix_fmt", + "yuv420p", + str(mp4_file), + ] + subprocess.run( + cmd, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + check=True, + ) + except subprocess.CalledProcessError as err: + _LOGGER.error("FFmpeg failed to generate MP4: %s", err) + + +def generate_grid_img(path: str, image_file: str, count: int) -> None: + """Generate png grid from gif. + + use a subprocess so we don't lock up the thread + command: ffmpeg -f gif -i infile.gif outfile.mp4 + """ + count = max(count, 1) + if count % 2 == 0: + length = int(count / 2) + else: + length = int(count / 2) + count % 2 + + gif_image = Path(path + image_file) + png_file = image_file.replace(".gif", "_grid.png") + png_image = Path(path).joinpath(png_file) + + filecheck = png_image.is_file() + + _LOGGER.debug("Generating png image grid %s from %s", png_image, gif_image) + if filecheck: + # cleanup_images expects a tuple or string path, so we use string parts here + # or we could update cleanup_images to handle Path objects natively later. + cleanup_images(str(png_image.parent) + "/", png_image.name) + _LOGGER.debug("Removing old png grid: %s", png_image) + + try: + subprocess.run( + [ + "ffmpeg", + "-i", + str(gif_image), + "-r", + "0.20", + "-filter_complex", + f"tile=2x{length}:padding=10:color=black", + str(png_image), + ], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + check=True, + ) + except subprocess.CalledProcessError as err: + _LOGGER.error("FFmpeg failed to generate grid image: %s", err) + + +def generate_delivery_gif( + delivery_images: list, + gif_path: str, + duration: int = 3000, +) -> bool: + """Generate an animated GIF from delivery images. + + Args: + delivery_images: List of image file paths + gif_path: Path where the GIF should be saved + duration: Duration for each frame in milliseconds (default: 3000) + + Returns: + bool: True if GIF was created successfully, False otherwise + + """ + try: + # Open all images + corrected_images = [] + for img_path in delivery_images: + img = Image.open(img_path) + img = ImageOps.exif_transpose(img) # auto-rotates according to EXIF + corrected_images.append(img) + + # Create animated GIF + corrected_images[0].save( + gif_path, + format="GIF", + append_images=corrected_images[1:], + save_all=True, + duration=duration, + loop=0, # Infinite loop + ) + + _LOGGER.debug( + "Generated animated GIF with %d delivery images at %s", + len(delivery_images), + gif_path, + ) + + except (OSError, ValueError, Image.UnidentifiedImageError) as e: + _LOGGER.error("Error creating animated GIF: %s", e) + return False + else: + return True + + +def _get_courier_info( + hass: HomeAssistant, + config: ConfigEntry, + amazon: bool, + ups: bool, + walmart: bool, + fedex: bool, +) -> tuple[str, str]: + """Determine the path and default image for the active courier.""" + configs = [ + ( + amazon, + CONF_AMAZON_CUSTOM_IMG, + CONF_AMAZON_CUSTOM_IMG_FILE, + DEFAULT_AMAZON_CUSTOM_IMG_FILE, + "no_deliveries_amazon.jpg", + "amazon", + ), + ( + ups, + CONF_UPS_CUSTOM_IMG, + CONF_UPS_CUSTOM_IMG_FILE, + DEFAULT_UPS_CUSTOM_IMG_FILE, + "no_deliveries_ups.jpg", + "ups", + ), + ( + walmart, + CONF_WALMART_CUSTOM_IMG, + CONF_WALMART_CUSTOM_IMG_FILE, + DEFAULT_WALMART_CUSTOM_IMG_FILE, + "no_deliveries_walmart.jpg", + "walmart", + ), + ( + fedex, + CONF_FEDEX_CUSTOM_IMG, + CONF_FEDEX_CUSTOM_IMG_FILE, + DEFAULT_FEDEX_CUSTOM_IMG_FILE, + "no_deliveries_fedex.jpg", + "fedex", + ), + ] + + base_path = f"{hass.config.path()}/{default_image_path(hass, config)}" + + for ( + active, + img_conf, + file_conf, + default_file_conf, + local_default, + sub_dir, + ) in configs: + if active: + _LOGGER.debug("Processing %s image file name", sub_dir.title()) + if config.get(img_conf): + mail_none = config.get(file_conf) or default_file_conf + _LOGGER.debug("Using custom %s image: %s", sub_dir.title(), mail_none) + else: + mail_none = str(Path(__file__).parent.parent / local_default) + _LOGGER.debug("Using default %s image: %s", sub_dir.title(), mail_none) + return f"{base_path}{sub_dir}", mail_none + + # Standard mail case + path = base_path.rstrip("/") + if config.get(CONF_CUSTOM_IMG): + mail_none = config.get(CONF_CUSTOM_IMG_FILE) or DEFAULT_CUSTOM_IMG_FILE + else: + mail_none = str(Path(__file__).parent.parent / "mail_none.gif") + return path, mail_none + + +def _get_image_name_from_directory( + path: str, mail_none: str, sha1: str, ext: str +) -> str: + """Check existing images and return a filename.""" + image_name = os.path.split(mail_none)[1] + today = get_formatted_date() + + try: + for file_path in Path(path).iterdir(): + if not file_path.is_file(): + continue + filename = file_path.name + if filename == "generic_deliveries.gif": + continue + is_image_file = filename.endswith(".gif") or ( + filename.endswith(".jpg") and ext == ".jpg" + ) + if is_image_file: + try: + created = datetime.datetime.fromtimestamp( + file_path.stat().st_ctime, + ).strftime("%d-%b-%Y") + # If it's the correct hash OR created today, we can reuse it + if sha1 == hash_file(str(file_path)) or today == created: + image_name = filename + break + image_name = f"{uuid.uuid4()!s}{ext}" + except OSError as err: + _LOGGER.error("Problem accessing file %s: %s", filename, err) + except OSError as err: + _LOGGER.error("Error accessing directory %s: %s", path, err) + + if image_name in mail_none: + image_name = f"{uuid.uuid4()!s}{ext}" + _LOGGER.debug("=== image_file_name GENERATED NEW UUID: %s ===", image_name) + else: + _LOGGER.debug("=== image_file_name USING EXISTING: %s ===", image_name) + + return image_name + + +def image_file_name( + hass: HomeAssistant, + config: ConfigEntry, + amazon: bool = False, + ups: bool = False, + walmart: bool = False, + fedex: bool = False, +) -> str: + """Determine if filename is to be changed or not. + + Returns filename + """ + _LOGGER.debug( + "=== image_file_name CALLED === - amazon: %s, ups: %s, walmart: %s, fedex: %s", + amazon, + ups, + walmart, + fedex, + ) + + path, mail_none = _get_courier_info(hass, config, amazon, ups, walmart, fedex) + image_name = os.path.split(mail_none)[1] + + # Path check + try: + Path(path).mkdir(parents=True, exist_ok=True) + except OSError as err: + _LOGGER.error("Error creating directory: %s", err) + return image_name + + # SHA1 file hash check + try: + sha1 = hash_file(mail_none) + except OSError as err: + _LOGGER.error("Problem accessing file: %s, error returned: %s", mail_none, err) + return image_name + + ext = ".jpg" if ups or walmart or fedex else ".gif" + return _get_image_name_from_directory(path, mail_none, sha1, ext) diff --git a/custom_components/mail_and_packages/utils/imap.py b/custom_components/mail_and_packages/utils/imap.py new file mode 100644 index 0000000..36d8061 --- /dev/null +++ b/custom_components/mail_and_packages/utils/imap.py @@ -0,0 +1,722 @@ +"""IMAP connection and search utilities for Mail and Packages.""" + +import asyncio +import binascii +import logging +import re +import unicodedata + +import aioimaplib +from aioimaplib import ( + AUTH, + IMAP4, + IMAP4_SSL, + NONAUTH, + SELECTED, + AioImapException, + Cmd, + Command, + Exec, +) +from homeassistant.core import HomeAssistant +from homeassistant.exceptions import HomeAssistantError +from homeassistant.util import ssl + +from custom_components.mail_and_packages.const import DEFAULT_IMAP_TIMEOUT + +_LOGGER = logging.getLogger(__name__) + +# Register ESEARCH command if not already present in aioimaplib +if "ESEARCH" not in aioimaplib.Commands: + aioimaplib.Commands["ESEARCH"] = Cmd("ESEARCH", (AUTH, SELECTED), Exec.is_async) + + +def encode_imap_utf7(s: str) -> str: + """Encode a string into IMAP modified UTF-7.""" + res = [] + unicode_buffer = [] + + def flush_unicode(): + if unicode_buffer: + u_str = "".join(unicode_buffer) + encoded_bytes = u_str.encode("utf-16be") + b64 = ( + binascii.b2a_base64(encoded_bytes) + .decode("ascii") + .rstrip("\n=") + .replace("/", ",") + ) + res.append(f"&{b64}-") + unicode_buffer.clear() + + for char in s: + ord_c = ord(char) + if 0x20 <= ord_c <= 0x7E: + if char == "&": + flush_unicode() + res.append("&-") + else: + if unicode_buffer: + flush_unicode() + res.append(char) + else: + unicode_buffer.append(char) + + flush_unicode() + return "".join(res) + + +def decode_imap_utf7(s: str) -> str: + """Decode a string from IMAP modified UTF-7.""" + res = [] + i = 0 + n = len(s) + while i < n: + char = s[i] + if char == "&": + end = s.find("-", i + 1) + if end == -1: + res.append("&") + i += 1 + elif end == i + 1: + res.append("&") + i += 2 + else: + b64_part = s[i + 1 : end] + b64_part = b64_part.replace(",", "/") + pad = len(b64_part) % 4 + if pad: + b64_part += "=" * (4 - pad) + try: + decoded_bytes = binascii.a2b_base64(b64_part) + res.append(decoded_bytes.decode("utf-16be")) + except (binascii.Error, UnicodeDecodeError, ValueError): + res.append(s[i : end + 1]) + i = end + 1 + else: + res.append(char) + i += 1 + + return "".join(res) + + +_ATOM_SPECIALS = frozenset('(){%*"\\] ') + + +def _is_imap_atom(s: str) -> bool: + """Check if the string is a valid IMAP atom.""" + return bool(s) and all(0x20 < ord(c) < 0x7F and c not in _ATOM_SPECIALS for c in s) + + +def quote_folder(folder: str) -> str: + """Ensure folder name is properly quoted for IMAP commands.""" + if folder.startswith('"') and folder.endswith('"'): + return folder + return folder if _is_imap_atom(folder) else f'"{folder}"' + + +class InvalidAuth(HomeAssistantError): + """Raise exception for invalid credentials.""" + + +async def login( + hass: HomeAssistant, + host: str, + port: int, + user: str, + pwd: str, + security: str, + verify: bool = True, + oauth_token: str | None = None, + timeout: float = DEFAULT_IMAP_TIMEOUT, +) -> IMAP4_SSL | IMAP4: + """Login to IMAP server asynchronously. + + Supports both password and OAuth2 (XOAUTH2) authentication. + If oauth_token is provided, uses XOAUTH2 SASL mechanism. + Otherwise falls back to standard LOGIN command. + """ + ssl_context = ( + ssl.client_context(ssl.SSLCipherList.PYTHON_DEFAULT) + if verify + else ssl.create_no_verify_ssl_context() + ) + if security == "SSL": + account = IMAP4_SSL( + host=host, port=port, ssl_context=ssl_context, timeout=timeout + ) + else: + account = IMAP4(host=host, port=port, timeout=timeout) + + await account.wait_hello_from_server() + + if account.protocol.state == NONAUTH: + try: + if oauth_token: + await account.xoauth2(user, oauth_token) + else: + await account.login(user, pwd) + except TimeoutError: + raise + except (AioImapException, OSError) as err: + _LOGGER.error("Error logging in to IMAP Server: %s", err) + raise InvalidAuth from err + + if account.protocol.state not in {AUTH, SELECTED}: + _LOGGER.error("Error logging in to IMAP Server") + raise InvalidAuth + return account + + +async def selectfolder(account: IMAP4_SSL, folder: str) -> bool: + """Select folder inside the mailbox asynchronously.""" + if getattr(account, "_current_folder", None) == folder: + return True + + encoded_folder = encode_imap_utf7(folder) + quoted_folder = quote_folder(encoded_folder) + + try: + await account.select(quoted_folder) + except TimeoutError: + raise + except (AioImapException, OSError) as err: + _LOGGER.error("Error selecting folder %s: %s", folder, err) + return False + else: + account._current_folder = folder # noqa: SLF001 + return True + + +def clean_search_string(val: str) -> str: + """Clean search string for IMAP search compatibility. + + Normalizes Unicode characters to NFKD decomposed form, strips non-ASCII + characters to ensure compatibility with US-ASCII only IMAP servers, + and removes any double quotes to prevent syntax corruption. + """ + if not val: + return "" + normalized = unicodedata.normalize("NFKD", val) + cleaned = normalized.encode("ascii", "ignore").decode("ascii") + return cleaned.replace('"', "") + + +def build_search( # noqa: C901 + address: list, + date: str, + subject: str | list[str] = "", + body: str | list[str] = "", + header: str = "", + is_yahoo: bool = False, +) -> tuple: + """Build IMAP search query. + + Return tuple of utf8 flag and search query. + Non-ASCII characters are stripped from subject to ensure compatibility + with servers that only support US-ASCII charset (e.g. Microsoft Exchange). + IMAP SUBJECT performs substring matching, so stripping non-ASCII chars + still matches the original subject (e.g. 'Livr' matches 'Livré'). + + When `header` is provided, each address is matched as either a forwarded + email (via HEADER substring match) OR a direct email (via FROM), so the + same config works for carriers that are forwarded through a service like + SimpleLogin AND carriers whose emails arrive directly in the mailbox. + IMAP HEADER does substring matching, so "mcinfo@ups.com" will match a + header value of "UPS ". + """ + the_date = f"SINCE {date}" + + if not address: + raise ValueError("address list must not be empty") + + # Build the address/header clause + if header: + # Each address matches via header (forwarded) OR FROM (direct), so + # users with mixed setups (some carriers forwarded, others direct) + # don't need separate configurations. + parts = [f'OR HEADER "{header}" "{a}" FROM "{a}"' for a in address] + if len(parts) == 1: + addr_clause = f"({parts[0]})" if is_yahoo else parts[0] + else: + or_prefix = " ".join(["OR"] * (len(parts) - 1)) + addr_clause = ( + f"({or_prefix} {' '.join(parts)})" + if is_yahoo + else f"{or_prefix} {' '.join(parts)}" + ) + elif len(address) == 1: + addr_clause = f'FROM "{address[0]}"' + else: + joined = '" FROM "'.join(address) + or_prefix = " ".join(["OR"] * (len(address) - 1)) + addr_clause = ( + f'({or_prefix} FROM "{joined}")' + if is_yahoo + else f'{or_prefix} FROM "{joined}"' + ) + + # Handle multiple subjects + subject_part = "" + if subject: + subjects = [subject] if isinstance(subject, str) else subject + safe_subjects = [clean_search_string(s) for s in subjects] + safe_subjects = [s for s in safe_subjects if s] + + if len(safe_subjects) == 1: + subject_part = f'SUBJECT "{safe_subjects[0]}"' + elif len(safe_subjects) > 1: + subject_prefix = " ".join(["OR"] * (len(safe_subjects) - 1)) + subject_joined = '" SUBJECT "'.join(safe_subjects) + subject_part = ( + f'({subject_prefix} SUBJECT "{subject_joined}")' + if is_yahoo + else f'{subject_prefix} SUBJECT "{subject_joined}"' + ) + + # Handle multiple bodies + body_part = "" + if body: + bodies = [body] if isinstance(body, str) else body + safe_bodies = [clean_search_string(b) for b in bodies] + safe_bodies = [b for b in safe_bodies if b] + + if len(safe_bodies) == 1: + body_part = f'BODY "{safe_bodies[0]}"' + elif len(safe_bodies) > 1: + body_prefix = " ".join(["OR"] * (len(safe_bodies) - 1)) + body_joined = '" BODY "'.join(safe_bodies) + body_part = ( + f'({body_prefix} BODY "{body_joined}")' + if is_yahoo + else f'{body_prefix} BODY "{body_joined}"' + ) + + if is_yahoo: + if subject_part or body_part: + search_criteria = f"{subject_part} {body_part}".strip() + imap_search = f"({addr_clause} {search_criteria} {the_date})" + else: + imap_search = f"({addr_clause} {the_date})" + elif subject_part or body_part: + search_criteria = f"{subject_part} {body_part}".strip() + imap_search = f"{addr_clause} {search_criteria} {the_date}" + else: + imap_search = f"{addr_clause} {the_date}" + + _LOGGER.debug("DEBUG imap_search: %s", imap_search) + + return (False, imap_search) + + +def parse_search_response(lines: list[bytes]) -> list[bytes]: + """Parse IMAP SEARCH response lines and return list of UID/ID bytes. + + Handles both standard server responses (prefixed with b"SEARCH") + and mocked test inputs (which often contain raw UIDs directly). + Filters out the SEARCH keyword, tagged OK/status responses, + and any non-numeric tokens. + """ + uids = [] + for line in lines: + if not line: + continue + parts = line.split() + if not parts: + continue + + if parts[0] == b"SEARCH": + # Check if this is a search result line, e.g. b"SEARCH 1001 1002" + # (as opposed to b"SEARCH completed") + if len(parts) > 1 and parts[1].isdigit(): + uids.extend(parts[1:]) + # Check if this line is just a list of numeric UIDs (mock/test compatibility) + # and ignore status/existence responses like b"23 EXISTS" + elif all(p.isdigit() for p in parts): + uids.extend(parts) + + return uids + + +def _parse_esearch_line(line_bytes: bytes) -> list[bytes]: + """Parse a single ESEARCH line and return list of formatted UID bytes: b'folder/uid'.""" + line_str = line_bytes.decode("utf-8", "ignore") + + # Extract the correlator inside parentheses + start_paren = line_str.find("(") + end_paren = line_str.find(")", start_paren) if start_paren != -1 else -1 + if start_paren == -1 or end_paren == -1: + return [] + + correlator = line_str[start_paren + 1 : end_paren] + + # Extract mailbox name (could be quoted or unquoted) + mailbox_match = re.search(r'MAILBOX\s+"([^"]+)"', correlator) + if not mailbox_match: + mailbox_match = re.search(r"MAILBOX\s+(\S+)", correlator) + if not mailbox_match: + return [] + mailbox = mailbox_match.group(1) + mailbox = decode_imap_utf7(mailbox) + + # Extract the sequence set after 'UID ALL' anywhere in the line + seq_match = re.search(r"UID\s+ALL\s+(\S+)", line_str) + if not seq_match: + return [] + seq_set = seq_match.group(1) + + uids = [] + for part in seq_set.split(","): + part = part.strip() + if not part: + continue + if ":" in part: + try: + start_str, end_str = part.split(":", 1) + start, end = int(start_str), int(end_str) + if start <= end: + uids.extend(str(x) for x in range(start, end + 1)) + else: + uids.extend(str(x) for x in range(end, start + 1)) + except ValueError: + pass + else: + uids.append(part) + return [f"{mailbox}/{uid}".encode() for uid in uids] + + +async def _execute_single_search(account: IMAP4_SSL, search_query: str) -> list[bytes]: # noqa: C901 + """Execute search query. If single folder, use standard search. If multiple, use hybrid ESEARCH/fallback.""" + folders = getattr(account, "_folders", ["INBOX"]) + + if len(folders) <= 1: + res = await account.search(search_query, charset=None) + if res.result == "OK" and res.lines: + return parse_search_response(res.lines) + return [] + + all_uids = [] + + # Check for MULTISEARCH capability safely (handling mock/AsyncMock in tests) + is_multisearch = False + if hasattr(account, "has_capability"): + try: + res = account.has_capability("MULTISEARCH") + if asyncio.iscoroutine(res): + res.close() + is_multisearch = False + else: + is_multisearch = bool(res) + except Exception: # noqa: BLE001 + pass + + if is_multisearch: + # ESEARCH IN ("folder1" "folder2") query - encode and quote folders + folder_list = " ".join([quote_folder(encode_imap_utf7(f)) for f in folders]) + args = ("IN", f"({folder_list})", search_query) + try: + timeout = getattr(account, "timeout", None) + if not isinstance(timeout, (int, float)): + timeout = None + res = await account.protocol.execute( + Command( + "ESEARCH", + account.protocol.new_tag(), + *args, + loop=account.protocol.loop, + timeout=timeout, + ) + ) + if res.result == "OK": + for line in res.lines: + if line: + all_uids.extend(_parse_esearch_line(line)) + except TimeoutError: + raise + except (AioImapException, OSError) as err: + _LOGGER.error("Error executing ESEARCH: %s", err) + else: + # Sequential select and search fallback - no limits on configured folders + for folder in folders: + select_ok = await selectfolder(account, folder) + if not select_ok: + continue + try: + res = await account.uid_search(search_query, charset=None) + if res.result == "OK" and res.lines: + parsed = parse_search_response(res.lines) + all_uids.extend( + f"{folder}/{uid.decode()}".encode() for uid in parsed + ) + except TimeoutError: + raise + except (AioImapException, OSError) as err: + _LOGGER.error("Error searching folder %s: %s", folder, err) + + return all_uids + + +async def email_search( # noqa: C901 + account: IMAP4_SSL, + address: list, + date: str, + subject: str | list[str] = "", + body: str | list[str] = "", + header: str = "", +) -> tuple: + """Search emails with from/header, subject, and date asynchronously. + + Always uses charset=None to avoid sending CHARSET in the IMAP SEARCH + command, ensuring compatibility with servers like Microsoft Exchange + that only support US-ASCII. + + When `header` is provided, searches via HEADER criterion instead of FROM, + matching the original sender in forwarding-service headers. + + If multiple subjects are provided, they are searched in batches of 10 + to keep the search query length safe. + """ + folders = getattr(account, "_folders", ["INBOX"]) + is_yahoo = False + if hasattr(account, "host") and isinstance(account.host, str): + host_lower = account.host.lower() + is_yahoo = "yahoo" in host_lower or "aol" in host_lower + + # If there are more than 2 body patterns, do not search them server-side + # to prevent slow query execution and timeouts on standard IMAP servers. + # Instead, we let the shipper's client-side text filtering handle it. + body_search = body + if body: + bodies = [body] if isinstance(body, str) else body + if len(bodies) > 2: + body_search = "" + + if len(folders) <= 1: + if not isinstance(subject, list) or len(subject) <= 10: + _unused, search = build_search( + address, date, subject, body_search, header, is_yahoo=is_yahoo + ) + try: + res = await account.search(search, charset=None) + except TimeoutError: + raise + except (AioImapException, OSError) as err: + _LOGGER.error("Error searching emails: %s", err) + return ("BAD", str(err)) + else: + parsed = parse_search_response(res.lines) + return (res.result, [b" ".join(parsed)]) + + # Batch subjects in groups of 10 + all_matched_ids = [] + for i in range(0, len(subject), 10): + batch = subject[i : i + 10] + _unused, search = build_search( + address, date, batch, body_search, header, is_yahoo=is_yahoo + ) + try: + res = await account.search(search, charset=None) + if res.result == "OK" and res.lines: + parsed = parse_search_response(res.lines) + all_matched_ids.extend(parsed) + except TimeoutError: + raise + except (AioImapException, OSError) as err: + _LOGGER.error("Error searching emails batch: %s", err) + + # Deduplicate and return in same format as individual search + unique_ids = list(dict.fromkeys(all_matched_ids)) + return ("OK", [b" ".join(unique_ids)]) + + # Multi-folder search logic + if not isinstance(subject, list) or len(subject) <= 10: + _unused, search = build_search( + address, date, subject, body_search, header, is_yahoo=is_yahoo + ) + try: + uids = await _execute_single_search(account, search) + except TimeoutError: + raise + except (AioImapException, OSError) as err: + _LOGGER.error("Error searching emails: %s", err) + return ("BAD", str(err)) + return ("OK", [b" ".join(uids)]) + + # Batch subjects in groups of 10 + all_matched_ids = [] + for i in range(0, len(subject), 10): + batch = subject[i : i + 10] + _unused, search = build_search( + address, date, batch, body_search, header, is_yahoo=is_yahoo + ) + try: + uids = await _execute_single_search(account, search) + all_matched_ids.extend(uids) + except TimeoutError: + raise + except (AioImapException, OSError) as err: + _LOGGER.error("Error searching emails batch: %s", err) + + # Deduplicate and return in same format as individual search + unique_ids = list(dict.fromkeys(all_matched_ids)) + return ("OK", [b" ".join(unique_ids)]) + + +async def email_fetch(account: IMAP4_SSL, num, parts: str = "(RFC822)") -> tuple: + """Download specified email for parsing asynchronously.""" + if account.host == "imap.mail.me.com": + parts = "BODY[]" + + num_str = num.decode() if isinstance(num, bytes) else str(num) + if "/" in num_str: + folder, num_str = num_str.rsplit("/", 1) + await selectfolder(account, folder) + try: + res = await account.uid("FETCH", num_str, parts) + except TimeoutError: + raise + except (AioImapException, OSError) as err: + _LOGGER.error("Error fetching email %s: %s", num_str, err) + return ("BAD", str(err)) + else: + return (res.result, res.lines) + + try: + res = await account.fetch(num_str, parts) + except TimeoutError: + raise + except (AioImapException, OSError) as err: + _LOGGER.error("Error fetching email %s: %s", num_str, err) + return ("BAD", str(err)) + else: + return (res.result, res.lines) + + +async def email_fetch_headers(account: IMAP4_SSL, num) -> tuple: + """Download only the subject header of an email asynchronously.""" + num_str = num.decode() if isinstance(num, bytes) else str(num) + if "/" in num_str: + folder, num_str = num_str.rsplit("/", 1) + await selectfolder(account, folder) + try: + res = await account.uid("FETCH", num_str, "(BODY[HEADER.FIELDS (SUBJECT)])") + except TimeoutError: + raise + except (AioImapException, OSError) as err: + _LOGGER.error("Error fetching email headers %s: %s", num_str, err) + return ("BAD", str(err)) + else: + return (res.result, res.lines) + + try: + res = await account.fetch(num_str, "(BODY[HEADER.FIELDS (SUBJECT)])") + except TimeoutError: + raise + except (AioImapException, OSError) as err: + _LOGGER.error("Error fetching email headers %s: %s", num_str, err) + return ("BAD", str(err)) + else: + return (res.result, res.lines) + + +async def email_fetch_text(account: IMAP4_SSL, num, parts: str = "(BODY[1])") -> tuple: + """Download the specific part of the email body asynchronously.""" + if account.host == "imap.mail.me.com": + parts = "BODY[]" + + num_str = num.decode() if isinstance(num, bytes) else str(num) + if "/" in num_str: + folder, num_str = num_str.rsplit("/", 1) + await selectfolder(account, folder) + try: + res = await account.uid("FETCH", num_str, parts) + except TimeoutError: + raise + except (AioImapException, OSError) as err: + _LOGGER.error("Error fetching email text %s: %s", num_str, err) + return ("BAD", str(err)) + else: + return (res.result, res.lines) + + try: + res = await account.fetch(num_str, parts) + except TimeoutError: + raise + except (AioImapException, OSError) as err: + _LOGGER.error("Error fetching email text %s: %s", num_str, err) + return ("BAD", str(err)) + else: + return (res.result, res.lines) + + +async def email_fetch_batch( # noqa: C901 + account: IMAP4_SSL, nums: list[str | bytes], parts: str = "(RFC822)" +) -> tuple: + """Download specified emails for parsing asynchronously in a batch.""" + if not nums: + return ("OK", []) + + if account.host == "imap.mail.me.com": + parts = "BODY[]" + + # Check if any ID contains a folder prefix + has_folder_prefix = False + for num in nums: + num_str = num.decode() if isinstance(num, bytes) else str(num) + if "/" in num_str: + has_folder_prefix = True + break + + if not has_folder_prefix: + num_strs = [ + num.decode() if isinstance(num, bytes) else str(num) for num in nums + ] + num_list_str = ",".join(num_strs) + try: + res = await account.fetch(num_list_str, parts) + except TimeoutError: + raise + except (AioImapException, OSError) as err: + _LOGGER.error("Error fetching emails batch %s: %s", num_list_str, err) + return ("BAD", str(err)) + else: + return (res.result, res.lines) + + # Group nums by their folder prefix + folder_to_nums = {} + for num in nums: + num_str = num.decode() if isinstance(num, bytes) else str(num) + if "/" in num_str: + folder, actual_num = num_str.rsplit("/", 1) + else: + folder, actual_num = None, num_str + folder_to_nums.setdefault(folder, []).append(actual_num) + + all_results = [] + overall_result = "OK" + + for folder, folder_nums in folder_to_nums.items(): + if folder is not None: + await selectfolder(account, folder) + + num_list_str = ",".join(folder_nums) + try: + res = await account.uid("FETCH", num_list_str, parts) + if res.result != "OK": + overall_result = res.result + all_results.extend(res.lines) + except TimeoutError: + raise + except (AioImapException, OSError) as err: + _LOGGER.error("Error fetching emails batch %s: %s", num_list_str, err) + return ("BAD", str(err)) + + return (overall_result, all_results) + + +async def logout(account: IMAP4_SSL | IMAP4) -> None: + """Logout from IMAP server asynchronously.""" + try: + await account.logout() + except (TimeoutError, AioImapException, OSError, asyncio.CancelledError) as err: + _LOGGER.debug("Error logging out of IMAP Server: %s", err) diff --git a/custom_components/mail_and_packages/utils/shipper.py b/custom_components/mail_and_packages/utils/shipper.py new file mode 100644 index 0000000..d4dba5e --- /dev/null +++ b/custom_components/mail_and_packages/utils/shipper.py @@ -0,0 +1,294 @@ +"""Shipper utility functions for Mail and Packages.""" + +from __future__ import annotations + +import base64 +import email +import logging +import re +from pathlib import Path +from typing import Any + +from aioimaplib import IMAP4_SSL + +from custom_components.mail_and_packages.utils.cache import EmailCache + +from .imap import email_fetch + +_LOGGER = logging.getLogger(__name__) + + +async def get_tracking( + sdata: Any, + account: type[IMAP4_SSL], + the_format: str | None = None, + cache: EmailCache | None = None, +) -> list: + """Parse tracking numbers from email. + + Returns list of tracking numbers + """ + tracking = [] + pattern = re.compile(rf"{the_format}") + mail_list = sdata.split() + _LOGGER.debug("Searching for tracking numbers in %s messages...", len(mail_list)) + + for i in mail_list: + if cache: + data = (await cache.fetch(i, "(RFC822)"))[1] + else: + data = (await email_fetch(account, i, "(RFC822)"))[1] + + for response_part in data: + if not isinstance(response_part, (bytes, bytearray)): + continue + + msg = email.message_from_bytes(response_part) + + # 1. Search subject + if found := _find_tracking_in_subject(msg, pattern): + if found not in tracking: + tracking.append(found) + continue + + # 2. Search body + if the_format == "1Z?[0-9A-Z]{16}": + found = _find_ups_tracking_in_raw(response_part, pattern) + else: + found = _find_tracking_in_body(msg, pattern, the_format) + + if found and found not in tracking: + tracking.append(found) + + return tracking + + +def _find_tracking_in_subject( + msg: email.message.Message, + pattern: re.Pattern, +) -> str | None: + """Find tracking number in email subject.""" + email_subject = msg["subject"] + if email_subject: + email_subject = str(email_subject) + if (found := pattern.findall(email_subject)) and len(found) > 0: + _LOGGER.debug("Found tracking number in email subject: %s", found[0]) + return found[0] + return None + + +def _find_ups_tracking_in_raw( + response_part: bytes | bytearray, + pattern: re.Pattern, +) -> str | None: + """UPS specific tracking search in raw email bytes.""" + try: + email_content = str(response_part, "utf-8", errors="ignore") + if (found := pattern.findall(email_content)) and len(found) > 0: + _LOGGER.debug("Found tracking number in email: %s", found[0]) + return found[0] + except (TypeError, UnicodeError) as err: + _LOGGER.debug("Error processing email content: %s", err) + return None + + +def _find_tracking_in_body( + msg: email.message.Message, + pattern: re.Pattern, + the_format: str, +) -> str | None: + """Search for tracking number in email body parts.""" + for part in msg.walk(): + if part.get_content_type() not in ["text/html", "text/plain"]: + continue + email_msg = part.get_payload(decode=True) + email_msg = email_msg.decode("utf-8", "ignore") + if (found := pattern.findall(email_msg)) and len(found) > 0: + tracking_num = found[0] + # DHL is special + if " " in the_format: + tracking_num = tracking_num.split(" ")[1] + + _LOGGER.debug("Found tracking number in email body: %s", tracking_num) + return tracking_num + return None + + +def save_image_data_to_disk(shipper_name: str, path: str, image_data: bytes) -> bool: + """Write image bytes to disk and verify.""" + try: + # Ensure directory exists + directory = Path(path).parent + if not directory.is_dir(): + _LOGGER.debug("%s - Creating directory: %s", shipper_name, directory) + try: + directory.mkdir(parents=True, exist_ok=True) + except OSError as err: + _LOGGER.error("Error creating directory: %s", err) + return False + + _LOGGER.debug( + "%s - Writing %d bytes to file: %s", + shipper_name, + len(image_data), + path, + ) + with Path(path).open("wb") as the_file: + the_file.write(image_data) + + except OSError as err: + _LOGGER.error( + "Error saving %s delivery photo to %s: %s", + shipper_name, + path, + err, + ) + return False + else: + if Path(path).exists(): + return True + + _LOGGER.error( + "%s - ERROR: File write reported success but file doesn't exist: %s", + shipper_name, + path, + ) + return False + + +def generic_delivery_image_extraction( + sdata: Any, + image_path: str, + image_name: str, + shipper_name: str, + image_type: str, + cid_name: str | None = None, + attachment_filename_pattern: str | None = None, +) -> bool: + """Extract delivery photos from email.""" + _LOGGER.debug("Attempting to extract %s delivery photo", shipper_name) + + msg = ( + email.message_from_bytes(sdata) + if isinstance(sdata, (bytes, bytearray)) + else email.message_from_string(sdata) + ) + + normalized_image_path = image_path.rstrip("/") + "/" + shipper_path = f"{normalized_image_path}{shipper_name}/" + full_path = shipper_path + image_name + + # Pass 1: CID search + if cid_name and ( + found := _extract_from_cid(msg, cid_name, shipper_name, full_path, image_type) + ): + return found + + # Pass 2: HTML/Base64 search + if found := _extract_from_html(msg, cid_name, shipper_name, full_path, image_type): + return found + + # Pass 3: Attachment search + return _extract_from_attachments( + msg, + attachment_filename_pattern, + shipper_name, + full_path, + image_type, + ) + + +def _extract_from_cid( + msg: email.message.Message, + cid_name: str, + shipper_name: str, + full_path: str, + image_type: str, +) -> bool: + """Pass 1: Look for CID embedded images.""" + content_type = f"image/{image_type}" + for part in msg.walk(): + if part.get_content_type() == content_type: + content_id = part.get("Content-ID") + if content_id and content_id.strip("<>") == cid_name: + return save_image_data_to_disk( + shipper_name, + full_path, + part.get_payload(decode=True), + ) + return False + + +def _extract_from_html( + msg: email.message.Message, + cid_name: str | None, + shipper_name: str, + full_path: str, + image_type: str, +) -> bool: + """Pass 2: Look for HTML content with CID references or base64.""" + base64_pattern = rf"data:image/{image_type};base64,((?:[A-Za-z0-9+/]{{4}})*(?:[A-Za-z0-9+/]{{2}}==|[A-Za-z0-9+/]{{3}}=)?)" + + for part in msg.walk(): + if part.get_content_type() != "text/html": + continue + + payload = part.get_payload(decode=True) + content = ( + payload.decode("utf-8", "ignore") + if isinstance(payload, bytes) + else str(payload) + ) + + # Base64 check + if matches := re.findall(base64_pattern, content): + try: + base64_data = matches[0].replace(" ", "").replace("=3D", "=") + return save_image_data_to_disk( + shipper_name, + full_path, + base64.b64decode(base64_data), + ) + except (OSError, ValueError, TypeError) as err: + _LOGGER.error( + "Error saving %s delivery photo from base64: %s", + shipper_name, + err, + ) + return False + + return False + + +def _extract_from_attachments( + msg: email.message.Message, + pattern: str | None, + shipper_name: str, + full_path: str, + image_type: str, +) -> bool: + """Pass 3: Look for attachments.""" + content_type = f"image/{image_type}" + for part in msg.walk(): + if part.get_content_type() == content_type: + filename = part.get_filename() + if not filename: + continue + if pattern and pattern.lower() not in filename.lower(): + continue + + try: + return save_image_data_to_disk( + shipper_name, + full_path, + part.get_payload(decode=True), + ) + except (OSError, ValueError, TypeError) as err: + _LOGGER.error( + "Error saving %s delivery photo to %s: %s", + shipper_name, + full_path, + err, + ) + return False + return False diff --git a/custom_components/mail_and_packages/vignette.png b/custom_components/mail_and_packages/vignette.png new file mode 100644 index 0000000000000000000000000000000000000000..a5365ce05adeee6a3cc873db0c566ba979774846 GIT binary patch literal 38527 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ΠklJ4rA-Y+UH3d8RD*{&s~bR@AT!UM=o%9 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 XHtp2D6#oC=Kl`j~EptCVc;f#6hRkuo literal 0 HcmV?d00001 diff --git a/custom_components/mail_and_packages/white.png b/custom_components/mail_and_packages/white.png new file mode 100644 index 0000000000000000000000000000000000000000..a12ccffbcb5a56f87278b7dac5f20ab0f8539517 GIT binary patch literal 171 zcmeAS@N?(olHy`uVBq!ia0y~yV4A_ez-Yn93=}!aE%*~iF%}28J29*~C-V}>VM%xN zb!1@J*w6hZkrl{i4)6(a{r~^}@*~nGfLzW3kH}&M2EM}}%y>M1MG8>R(9^{+q~g}w qgNBSi-k}9w{d0Nw6@X0afbS|pS^@*(xs}c8AO)VTelF{r5}E*RI48^i literal 0 HcmV?d00001 diff --git a/custom_components/maintenance_supporter/__init__.py b/custom_components/maintenance_supporter/__init__.py index e9eb79b..0e2bd97 100644 --- a/custom_components/maintenance_supporter/__init__.py +++ b/custom_components/maintenance_supporter/__init__.py @@ -894,6 +894,10 @@ async def _async_setup_shared(hass: HomeAssistant) -> bool: unsub_digest, ] + # Once HA has started (all entries loaded), flag object entries that were + # orphaned by a deleted global entry as a fixable repair issue (#86). + async_at_started(hass, _sync_missing_global_entry_issue) + return True @@ -1058,6 +1062,11 @@ async def async_setup_entry(hass: HomeAssistant, entry: MaintenanceSupporterConf # HA-started so the store has finished loading. entry.async_on_unload(async_at_started(hass, _check_document_storage_issues)) + # A global entry now exists — clear the orphan repair issue immediately + # (e.g. right after the repair flow recreated it, when HA is already + # started and the async_at_started check above won't fire again). + _sync_missing_global_entry_issue(hass) + _LOGGER.debug("Global config entry set up: %s", entry.entry_id) else: # Maintenance object entry: create Store + coordinator @@ -1188,6 +1197,39 @@ async def _check_document_storage_issues(hass: HomeAssistant) -> None: ir.async_delete_issue(hass, DOMAIN, _DOC_STORAGE_ISSUE_ID) +_MISSING_GLOBAL_ISSUE_ID = "missing_global_entry" + + +@callback +def _sync_missing_global_entry_issue(hass: HomeAssistant) -> None: + """Surface "object entries exist but the global entry is gone" as a repair. + + The config flow always creates the global "Maintenance Supporter" entry + before the first object, but a user can later delete just that entry from + Settings → Devices & Services, leaving orphan object entries behind. That + strips the summary sensors, the sidebar panel and the digests — and the + dashboard KPI chips read "unknown" (#86, 2nd report). The fixable issue's + flow recreates the global entry with default settings; it clears itself once + a global entry is present again. + """ + from homeassistant.helpers import issue_registry as ir + + entries = hass.config_entries.async_entries(DOMAIN) + has_global = any(e.unique_id == GLOBAL_UNIQUE_ID for e in entries) + has_objects = any(e.unique_id != GLOBAL_UNIQUE_ID for e in entries) + if has_objects and not has_global: + ir.async_create_issue( + hass, + DOMAIN, + _MISSING_GLOBAL_ISSUE_ID, + is_fixable=True, + severity=ir.IssueSeverity.ERROR, + translation_key=_MISSING_GLOBAL_ISSUE_ID, + ) + else: + ir.async_delete_issue(hass, DOMAIN, _MISSING_GLOBAL_ISSUE_ID) + + async def _async_global_options_updated(hass: HomeAssistant, entry: ConfigEntry) -> None: """React to global options changes (panel toggle / sidebar title).""" panel_enabled = entry.options.get(CONF_PANEL_ENABLED, DEFAULT_PANEL_ENABLED) @@ -1349,6 +1391,10 @@ async def async_unload_entry(hass: HomeAssistant, entry: MaintenanceSupporterCon async def async_remove_entry(hass: HomeAssistant, entry: ConfigEntry) -> None: """Clean up store file when a config entry is permanently deleted.""" if entry.unique_id == GLOBAL_UNIQUE_ID: + # Deleting the global entry while object entries remain is a broken + # state (no summary sensors / panel / digests) — surface it right away + # as a fixable repair issue so the user can restore it (#86). + _sync_missing_global_entry_issue(hass) return store = MaintenanceStore(hass, entry.entry_id) await store.async_remove() diff --git a/custom_components/maintenance_supporter/__pycache__/__init__.cpython-314.pyc b/custom_components/maintenance_supporter/__pycache__/__init__.cpython-314.pyc index 12fbc7560c72e17d32a53d1358de3775456ea2ba..62c594a8e51b9418dcebe39c3d1ff1945ff51c50 100644 GIT binary patch delta 3928 zcmbVPYj9LW7VdNB&LcO;m}F*>0D0UzNHQ=a2$PTn1QL@Fo)d-`U!&tBbCV1VGvmDz zlk6*z)h*psc{J?ogDoxhgC>mX&%Lmd|HVPxJk^{k5d6+L=#Pq^Dr*1=@aC*7UVr`!SLS84n@ z_iChr8ol1V2I-JSZ*Yf^j%f5o_k&2w8cp2_(ov1x0HFx=`3dZkcQ z?)9RqOHx1Ist0&M9eZw_&T}c7=xytpk4~C%l%IPh`IZZJrxE>>3kU@l+$N$gzM@p2 z)kkME&4vMJx|QEvlZ51MfF>uun_DCx^G*sh&Enrlt)Gm{pc5F*LZrLqub?F_EP=;V z`Gv1|*iR$s0vMt%sb2j_jKyQB?PV(msyb!cMiYEQUw!Qmd`O>o-K8JFURC|@^{ZUP zMI9kZ8M@FYF6qw61K|~yHIbg& zpFH7jTB0}+xurcC)@kTeukW`5IH~;rg_HEv1Lyf&7!&%ZgIi#X)*g}(|8dA62$*|X z^e3vH9eNyuO9DxX*O9^KdElDC@10*;hRnWFa8>gA z%4(+}bHE0!YW_f`6X}BjxMuSQlWVQW9L@*VT>h{))5sV*Fmz~Gq2UY-(GiqaYdBlO zxrmsa^XcVx8{mF*-jOHuf)3X!Gq_*<=ke_TkE%}%Kh6o)Fg7xSM`*#ReXvRW?9>}N zc#gh!rV7MZ&;W%r>1;N;G3^vi{&%Tv8Z2hidNT&@yQ1UX5d7X#*%kp|6 zG{C5aTW=fD+U?C6Pt!igO2rePzjzLf_LKVw{gEuvh-9VHdoubWoJYGYS(?m&75rl2 z&mkm-;B~=ekrpnEByPio6hcbJv#A3O=8z@Hgya#oZdrN~Yx!lV1>YK#I4cp|ch1wt zCer_36MbXUjfwacKH;XnmbuxYOYj}DH6EH$$Jaq<_@qD&old>QoRGM6cq-E9ih9fD znP8#QokE7&Fv}3{MrVyhqy^}Dr z717Jb2PU#}us+hoZXMT z6^dm=)m09023o;@hUKW8c_E4IfgWFLP{Nqwn^vj_T4ZJEJ7TK6ePVYY+KC}*_jLuM z=x#h5bHqSYY{Rw73Q~#`Y!}0!wlYcZeQRSQvV@C_ioOnCAXF~M`IsW~bw{ST0TZVX zQ>ULalZGtnD=bQGB&3J*>+{Ky2{db;BVWIOBD*Sp;=w>*{WBgC$kf64|sSch@^NDT{}K4rX8 z8BS(&Jo^+ykGdrye)38-ioH`BsB8^eQPfYyu!5QMp*iE2xnRg#aLimWWUhGGaKt>T zf8ptLE42)<&>gWh#4NEs%f=h*k@SZC#iuiDv}lNh;D~KutSDBr@dkG!V`2Z2)5eUa zXCF5S$4t3HrrhHxY44|Gyq{8hJZsW%Th=k#|2Pjc)$fAzWo7 zgCX^uk8=Rds^>ldflKG8@5edRINAfB(*98gd`_PqEfl_D+6>OBCq_?j+)bt{)Z>?~ z@+Ow1%bSO@X!w&Xdf|%gu0j;ZMGQt*NJklLL9l1uwAH_3(%&=4WN?td$84^N3~Jfv z+Zm)Y_z9Cuquwv=jZ+!VazfjAnO&oD2nXBE@onG13~76x!Y(gwz^`~^U$Ra zNN%8mU*1O#k0wEdI_v6Wj=KOiLUxb3_N(p~6=4}Zv<#oYhnBV5C&k;httgM(r-MAMildQjc{JQ2%&5ML5I;T> zImE+KQTuK#A>B|!JjO&17Ko-B<)b0OwQxtzP>C>l^vTrX#I~=U)i^cNc}9=1ovuU`yYZ&|#M_R@ab2dgn<1ra%_J-v>A|3~(rZB@J4! z$xVkElzP))GQh85k7mF*C>{t|;0u7x0m%kwu$29#$n0-KX4SA(9cs0pT*g?f+N)%g zb}?y3cLig$W2qf#mY*_=6Uugi9Q&6tO7hgb|G#n;qMc3*tnU$zu&*WR2AV#g`q$ Jkf!}~{s+}cD5U@Z delta 2157 zcmY+Fdr(wW9LLY^?7h3o71o7az~!;)0S^+%QuAj!{WdB0xj zl=^l{j**TOg0eLQb)?9bTp0@0A~Qng4^GM z<>smF*Ca@=Z_EjBl;wUrM?MLJEH_&}c2n44zP@v<9nLWIvo1Kze*Y{iU&PWKX8q?^ z>6D8WLRyNj`)9~yG7tEKIX9K|i2Uf7hU+3Wcc4VqFnAtC3?@5@X9)vwI;_AX*6wr3aug!Bvdw)i<8&(6*!hFDl)Aw-8va}4Y_`U3|6j?} zIv1-sw2_Ujb3>T*9;$!{8Z^Um1N zj!c+0;Egr0aUCN)o5l94NLv4(;8;P`Z0%41D%kr+7@TC|JI}JxuJv$6@8X7dP+9OyHTaBU4#;C~o*4$m zn0cmE`HKg0tYkGm9Au&GH5PpcWpfMjVXK*cZYNl;issnq^Cik3TyktR(=X%zw3(wX zftp5nfd#x@FSt;!uEI076+ z9E-5F>d>F&jeNpUjNX&U54X(M=PYb$nWHy8s^7?6_Cc3E#>le3U5Z!<4msXxff1DU zf>@~X_z@XaTcFywD+yxqG^|`6|1=5Sfa`NEn7xJ2O$S0L$BbbaXlh$%O1!N zxd;4g^0{m}oU(6rdfB);6yxF$kkj!^$sro#lNdHOkQ#t}zs_x(N(H;rOrwpez!3fS4`zg@=dDWHOvOAkjMGVhEskGt9aXo!0t*VTfw`&xY0V zIs>shsGSF0GD1T^^~TU47JEO&oWO=K zRTjk?UC;&4WR#~v5t=j8AroMEd~pWEDY{h;+>P1G9tfhh%L5|-))|+w;3vq7f13@z z0nCaY&jlxh_&1~T-$duHn7H8LI_rhp6c<)p#9O#2E}1x({MhMy{(7TP?t_4`4mGwy zT4=n{2dk_e{^|BFbrylOKMLbePoVr;>aRDF3L!xI#~6`981CWcv%kj1>2^WE<&pw$ HiVx}^8P86x diff --git a/custom_components/maintenance_supporter/__pycache__/binary_sensor.cpython-314.pyc b/custom_components/maintenance_supporter/__pycache__/binary_sensor.cpython-314.pyc index 37ea107e3d0ea37dc24b6ebf757cb83b0a062017..0a628434bfa787710feaca46b33553252f20e3a7 100644 GIT binary patch delta 20 acmX@=e$<^?n~#@^0SI2~@ZZS2OBnz?7X|zP delta 20 acmX@=e$<^?n~#@^0SMZP{Wfy%QU(Ax#syRW diff --git a/custom_components/maintenance_supporter/__pycache__/button.cpython-314.pyc b/custom_components/maintenance_supporter/__pycache__/button.cpython-314.pyc index 070caf77c39a7169f866ef7dbd8e89e8af11b749..cd0bae055426a863ed06202ee0de9de3abcef995 100644 GIT binary patch delta 20 acmca)e#x9$n~#@^0SI2~@ZZRNTp9p8*9H3k delta 20 acmca)e#x9$n~#@^0SMZP{WfwRmj(bhh6Pgq diff --git a/custom_components/maintenance_supporter/__pycache__/calendar.cpython-314.pyc b/custom_components/maintenance_supporter/__pycache__/calendar.cpython-314.pyc index 572f7459f72726b4bb7293cfea422fc4db3bb60f..9b6a5bea8f0402d2a9ea080294627867453aba8c 100644 GIT binary patch delta 22 ccmbQei*fcYMs96BUM>b8c(KEOBey^-07?@EAOHXW delta 22 ccmbQei*fcYMs96BUM>b8Xe;*H$Sn{H07b$DcmMzZ diff --git a/custom_components/maintenance_supporter/__pycache__/condition.cpython-314.pyc b/custom_components/maintenance_supporter/__pycache__/condition.cpython-314.pyc index c2ef1143eae85f3203ed2feba50f40c5b4c5aa02..2a5eac704a90c290f95a238d80722a8bd08f7f72 100644 GIT binary patch delta 20 acmbOrI6;tGn~#@^0SI2~@ZZSY$^if^90b+? delta 20 acmbOrI6;tGn~#@^0SMZP{Wfy9asU7*%LFa} diff --git a/custom_components/maintenance_supporter/__pycache__/config_flow.cpython-314.pyc b/custom_components/maintenance_supporter/__pycache__/config_flow.cpython-314.pyc index 0d42c8067761b9e4a2ccd5ee6371bf22f40b9928..d6aca48875fc05030a5bc9feceddb5cd281323f2 100644 GIT binary patch delta 6627 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 delta 22 ccmcb6jOp$%CT?v$UM>b8Xe;*H$Q`s808b8c(KEOBlp7H09U*RtpET3 delta 22 ccmZ4UooUT?CT?v$UM>b8Xe;*H$h~kk08?uR1poj5 diff --git a/custom_components/maintenance_supporter/__pycache__/const.cpython-314.pyc b/custom_components/maintenance_supporter/__pycache__/const.cpython-314.pyc index 2d54776a3daa6ac92c44aa93f5e8bd5850fec616..74a2e81b399e755b07e6dce2c0b0603346a17318 100644 GIT binary patch delta 22 ccmdnj%($b8c(KEOBe&XT099EBQ~&?~ delta 22 ccmdn^jCtcTW^QdhUM>b8Xe;*H$gTDn08t1AtN;K2 diff --git a/custom_components/maintenance_supporter/__pycache__/diagnostics.cpython-314.pyc b/custom_components/maintenance_supporter/__pycache__/diagnostics.cpython-314.pyc index 161f039b20b1aaf05c3b7755a56ca43afe136aa1..13801a088d9f4bfe288dd3bf37b7ec4da80f5a28 100644 GIT binary patch delta 20 acmX>Ua43LVn~#@^0SI2~@ZZR7t^oi%=mm-Z delta 20 acmX>Ua43LVn~#@^0SMZP{Wfx&YXAT^mjvPf diff --git a/custom_components/maintenance_supporter/__pycache__/logbook.cpython-314.pyc b/custom_components/maintenance_supporter/__pycache__/logbook.cpython-314.pyc index 1101ab65c7bf2941c83a05f8dc6052d8098cb37d..66e0f332d2bbdf5e7e80b34d9bebe34088156f4e 100644 GIT binary patch delta 20 acmdm-vN?rYn~#@^0SI2~@ZZR-VFUm@Y6Xt~ delta 20 acmdm-vN?rYn~#@^0SMZP{WfxI7y$q|83gA5 diff --git a/custom_components/maintenance_supporter/__pycache__/panel.cpython-314.pyc b/custom_components/maintenance_supporter/__pycache__/panel.cpython-314.pyc index 950b5490e27e39aabe4b8eb7438ef78ed43de408..a97cc6d0e305012d311b7c20d1b29b8d6662d749 100644 GIT binary patch delta 1624 zcmah}T})F~96#sww!Qss@1?dvwTwETR6r+M(1Kh9v4dc9g)S`Z8V2RV)z;mX5tcAP z9>`vt^(GCUTGMn(scqp}N!%g_}2`xO(mWZFPYtV5)p{VtOCP$z^RwduUFb!UU(@?cdAQRpqYI%sN2Pqnq?YL@? z^dJHOdaBgHAD8}7o@Dw;3qb%HcJe`G;{*UhT>v;h5Cj~>{GJXt_w1q-A_t)oREAvW zYp%y0+HGBl6CwRh9w4pC136^ZID~r8z!btwSPdP-d!lEm+ER&?I4}7(u{c49tfvyF zzM(ExNtz%NszK*8Kj{wdX6g~A^(fz0gYFkgjaokxzK5Hpi2*qt85@p_$3KcECgSKz z-2-SxVf}mMWEQdx!=^P75PLehBNuwbUjLa$pVS@c>gY$m=-n29sGkeb~R$}M=0q7Ul`v==h z*jcTGek;3LC%UlnP=Exj7}2tRiD;N(MyR>qUgNVt(V<+P0v}GP#j&e)J1eM=_?;6 zaDo6iolH(FvjkcQcnLHTXeA(Ga4YCjv#B1A4UCLLhc#2_a=G3p8@efv?XPu8&XNFz8xbpS} zd+xDMoNk}<&-nAKJTVEBM&RF4HpST|@w*#g5GI$W(;UD^1aaKM>fL>vG z`N*j$Ln*xq&oAe@lo%S1MO)+`&Jsc;KR|bcrrIqta8!I%y;gB-&EBvEtS?k5C~Wcg R(Ol`H@94{RhESLG`VT#NJ}v+N delta 1201 zcmah|%WGU^6#u@N`<%zUnMWp__O_GEB$JFo(??!?%!EuRB}yHVOC1+Y3DaaKDbpFb zcZy^YYa6tP3kgS1R4_vE9|*y0N-H%rZX{_6sk4xRZrmk^6v2h(eA5cL@q_z2&+mMf z^E>C8>{6eRHG)2d=Y6+$t;<+84)7nBd%rqq>mAJYb+Bq%M2|t9s;3dR zO|;rX{Gjbgu}lag{xjs{F&OeJ$uX=LS-t1^np-BSP8&i~ovqgzm0H8~qLof}I_+>% zipfdJh0mm4ZW@#-@>SAO2u5FTFFJdM6)Z2{BU1H2) zB{q2wxE|q$p{z!NiPmMtO7e6Ue4-U$M$M>N8r{=L$mkXvQw_MU%RCJm`kKG*W&UIq z-t%SUS5$UkZFSA}DvvZnGjEk^mFkS!C^zP3XKpxE2n9BI44Q#Ab?TDiM}VndMhcVi zVQ@eZ-AciC!81|OhO?ALAlh&b!p8UA8q)%I7H%!vS-iFQap_ZgNA28IySLTut)5dm z>gn~%Pt@07&*+bjz5bE@fxfF*+nV)7X~o{r`nEE;Z7mO%%y%vxW#-6!fa!I4A=jfV``G#lf{0jr+9H@-Q~3!IyeRTQ7xf;=2c81JtL?TJhXmE%U!R}-KbVZok@(+nz==oYCnDW4@KdTy)f?TgEz$bKCg0O HR^0s?cKq=` diff --git a/custom_components/maintenance_supporter/__pycache__/repairs.cpython-314.pyc b/custom_components/maintenance_supporter/__pycache__/repairs.cpython-314.pyc index e4f89cae850f1ef51dce3c845449f72b76f95049..b6ffb294726e45fd3067b848d1473bc5ea15bc57 100644 GIT binary patch delta 1559 zcmZWpO-vg{6rMHyiw&kM5D;;a!BoHo8$uO+MAAr*(gqO&k+o5LZ){h-osk0HaqBw3s@zyKB6II*;A-gLc zft|J{WV~iaMopU*;v}c)^ligh)R$cdslQ7I#Yu`1)h5`^5IieCNZ#TYFN`}39}hi4FlFp&E*K#xrJx1sVtMU zRI1_esj(tXW%L{iKyez54u_`S>3jQ9ykdprhyYYuczi2w$f=4 zEoGT$eO6dH7}m3#gaETiE{Yd3dMX2DRhVPKeV@7tMT@#Un*napYTmFhBjP58JApJc z32|5;qtdKF7&8i3Ph-m@P!mtJfXR{$B|?rDEo=~Vfp-S-grdboz&|BXoM!}|9qwQO z=i0S`th~}|r**dZ@=a(m!=Rt*Xb<^4Q_`-$((%!q%HsTdWrv2rDFxmyh8I?=2-Q55 zK_d}#6hb5a zV;l0ZExBhy?%9%uHsqn7`+q%KN~B8TT1g(-l*v{#DOD3kTIoyIq^0LfhDa;Jo)Mq) zz$cA(+zS5_G=iAlq zPbEM%gP<=BI1Que0}xA$6Z>-;n&xba@!y_MjK^U&?B;Sqw(`N7sXRr|#e(8>p4=$SJ=6B7{qV>|0^wr5{ Mh|habphGbE51!n%e*gdg delta 320 zcmbO|m#KLI6Q4F8FBbz4v=#ehX=G01lVGgcsGiFx6r>=|5Tq#1kRwo{9mJ%}psBQZ z4`XaSqvmF*#xO=k&B=vLDU-i;Obe}HVqhpX0GiOi@STB&QRgFwxWOgotvG8f zg~5)En7pSuQ2GwH=4Ec}3oP0{i$MXd9kdl$*S+SC&f$s0)Y~ QiZ@KY+PjYHyAI6d01vuL%K!iX diff --git a/custom_components/maintenance_supporter/__pycache__/sensor.cpython-314.pyc b/custom_components/maintenance_supporter/__pycache__/sensor.cpython-314.pyc index 1e33d919dd49192bdf21bfc83635149674d65317..87623dd40a856ca1d6bd5e98e41296298a3edd9a 100644 GIT binary patch delta 22 ccmX^0i}BPiMs96BUM>b8c(KEOBe#7m09)7xO#lD@ delta 22 ccmX^0i}BPiMs96BUM>b8Xe;*H$ZcN>09S_wr2qf` diff --git a/custom_components/maintenance_supporter/__pycache__/storage.cpython-314.pyc b/custom_components/maintenance_supporter/__pycache__/storage.cpython-314.pyc index 7a91072f0f4772a2860ce6f734050b53c6e9e713..6ac0afb51b4b6b58ee5d427faf01d6367971340b 100644 GIT binary patch delta 22 ccmcb#nDNqLMs96BUM>b8c(KEOBlqz@08qmR3jhEB delta 22 ccmcb#nDNqLMs96BUM>b8Xe;*H$bCEz08DZQV*mgE diff --git a/custom_components/maintenance_supporter/__pycache__/templates.cpython-314.pyc b/custom_components/maintenance_supporter/__pycache__/templates.cpython-314.pyc index 74edda27b9dd08a5ac650bb026a214ed45a26575..63dc46613958f1ee08222fed5ab91d65aa2fc461 100644 GIT binary patch delta 20 acmbR3Iop$4n~#@^0SI2~@ZZQiK?MLd&;^44 delta 20 acmbR3Iop$4n~#@^0SMZP{Wfw>Pyqlke+1hA diff --git a/custom_components/maintenance_supporter/__pycache__/templates_i18n.cpython-314.pyc b/custom_components/maintenance_supporter/__pycache__/templates_i18n.cpython-314.pyc index 30c5a42e3ca8797788c11b37be564121948d747b..ecd6e891708eabf9c4e3d62cc42311ed05bb174a 100644 GIT binary patch delta 22 ccmeBq!qoGGiCdeGmx}=iUhMGS$j!J308VZOo&W#< delta 22 ccmeBq!qoGGiCdeGmx}=i+KT-)ax-oM07@MN_5c6? diff --git a/custom_components/maintenance_supporter/__pycache__/todo.cpython-314.pyc b/custom_components/maintenance_supporter/__pycache__/todo.cpython-314.pyc index b37ec284937a562f6d9590d6bfa827b41db7864b..3c6331abdbeca2082dc4386019705b99397c8714 100644 GIT binary patch delta 20 acmZ4Cxx$lMn~#@^0SI2~@ZZQiR|Nn#*afNp delta 20 acmZ4Cxx$lMn~#@^0SMZP{WfyXRRI7rhXn!v diff --git a/custom_components/maintenance_supporter/__pycache__/trigger.cpython-314.pyc b/custom_components/maintenance_supporter/__pycache__/trigger.cpython-314.pyc index a0b3ec6ca86c3b94d14801001196c7990c21b9f7..f86b625d74307a1c9ccede52cd9d74b6e5ec5af4 100644 GIT binary patch delta 20 acmeAY?-J+M=HumJ0D>1g{5Nvfa{~Y^2L#gq delta 20 ZcmeAY?-J+M=HumJ0D`t+zm44W+yE%H1S

xj@&Et; delta 22 bcmeBgX6$cf ConfigFlowResult: + """Programmatically (re)create the global entry with default settings. + + Used by the missing-global-entry repair flow to restore the global + "Maintenance Supporter" configuration after it was deleted while object + entries remained (which strips the summary sensors + panel). Aborts if a + global entry already exists, so it's safe to trigger unconditionally. + """ + await self.async_set_unique_id(GLOBAL_UNIQUE_ID) + self._abort_if_unique_id_configured() + return self.async_create_entry( + title="Maintenance Supporter", + data={ + CONF_DEFAULT_WARNING_DAYS: DEFAULT_WARNING_DAYS, + CONF_NOTIFICATIONS_ENABLED: False, + CONF_NOTIFY_SERVICE: "", + }, + ) + async def async_step_create_from_template(self, user_input: dict[str, Any] | None = None) -> ConfigFlowResult: """Step 1: Select a template category.""" if user_input is not None: diff --git a/custom_components/maintenance_supporter/entity/__pycache__/__init__.cpython-314.pyc b/custom_components/maintenance_supporter/entity/__pycache__/__init__.cpython-314.pyc index 591f9bc4b42d424bdb81c067bbae3a6858db134b..92cd3302287c7a5651840379859a169753ee7823 100644 GIT binary patch delta 20 acmaFM^p=TRn~#@^0SI2~@ZZRt#0UU5fdxna delta 20 acmaFM^p=TRn~#@^0SMZP{WfwZF#-TIFa)3g diff --git a/custom_components/maintenance_supporter/entity/__pycache__/entity_base.cpython-314.pyc b/custom_components/maintenance_supporter/entity/__pycache__/entity_base.cpython-314.pyc index 7136304b7f767e7d6e0f3ab6b98da8eaaad8b450..0173390323a8baf6b9f296301af0bc3715e8794d 100644 GIT binary patch delta 20 acmeyY@mYggn~#@^0SI2~@ZZRtAp!tC+y%J+ delta 20 acmeyY@mYggn~#@^0SMZP{WfxEhyVaOiv9gV1=HumJ0D>1g{5Ntl%K-o}?gYF5 delta 20 ZcmeCP>9gV1=HumJ0D`t+zm43?asVxz1QY-O diff --git a/custom_components/maintenance_supporter/entity/triggers/__pycache__/__init__.cpython-314.pyc b/custom_components/maintenance_supporter/entity/triggers/__pycache__/__init__.cpython-314.pyc index 50f61c771200ee5f235ec4c933d8503802d765c4..c28b8a7c0b93daf0f438a8ac3c4272744617c190 100644 GIT binary patch delta 20 acmaFw@ZN!2n~#@^0SI2~@ZZRtq5uFvs0HZ& delta 20 acmaFw@ZN!2n~#@^0SMZP{Wfx^C;$LGR|P=; diff --git a/custom_components/maintenance_supporter/entity/triggers/__pycache__/base_trigger.cpython-314.pyc b/custom_components/maintenance_supporter/entity/triggers/__pycache__/base_trigger.cpython-314.pyc index 3e1b864cfa952a5aa6013cad5d5e5c00ca300384..8f540407cf98e9c35f8bde671e99655e5fb20907 100644 GIT binary patch delta 20 acmca#c)yTan~#@^0SI2~@ZZRN#R33FBnGnp delta 20 acmca#c)yTan~#@^0SMZP{Wfx6u>b%<(*_Fw diff --git a/custom_components/maintenance_supporter/entity/triggers/__pycache__/compound.cpython-314.pyc b/custom_components/maintenance_supporter/entity/triggers/__pycache__/compound.cpython-314.pyc index 2f47bafe06fd9a63ceb5f388bdbbc5d3d32fa7a0..f7ad5cdb7dcb3dec462687712dae7b05a46fa792 100644 GIT binary patch delta 20 acmZ2jyRep9n~#@^0SI2~@ZZQi%?vjYG+*#&O^ diff --git a/custom_components/maintenance_supporter/entity/triggers/__pycache__/counter.cpython-314.pyc b/custom_components/maintenance_supporter/entity/triggers/__pycache__/counter.cpython-314.pyc index 469ef8351137b13d62aefe4f55d851861993ddd8..50495c2286bf7ad66a904b147bc410006060bbb0 100644 GIT binary patch delta 20 acmca&f5o0#n~#@^0SI2~@ZZRNQXT+4O9mAH delta 20 acmca&f5o0#n~#@^0SMZP{Wfx+lm`Gg`UPzO diff --git a/custom_components/maintenance_supporter/entity/triggers/__pycache__/runtime.cpython-314.pyc b/custom_components/maintenance_supporter/entity/triggers/__pycache__/runtime.cpython-314.pyc index 06126fb6a2a378e51b658993d59980e8406b3885..7eee2299bdced773a26be56f5b492ed61aeb2f3b 100644 GIT binary patch delta 22 ccmccA%y_Apkz1ROmx}=iUhMGS$bH-q087&by8r+H delta 22 ccmccA%y_Apkz1ROmx}=i+KT-)avygD07rrb6951J diff --git a/custom_components/maintenance_supporter/entity/triggers/__pycache__/state_change.cpython-314.pyc b/custom_components/maintenance_supporter/entity/triggers/__pycache__/state_change.cpython-314.pyc index ae10ec3c84bc8956ddfa38fefc2e5eb5a13d8586..b592eac6f343d7353d26797472bccedaf5bb86e5 100644 GIT binary patch delta 20 acmZ4Cv%-g4n~#@^0SI2~@ZZQSs|El#Mg=ke delta 20 acmZ4Cv%-g4n~#@^0SMZP{WfyTssR8q^#qCl diff --git a/custom_components/maintenance_supporter/entity/triggers/__pycache__/threshold.cpython-314.pyc b/custom_components/maintenance_supporter/entity/triggers/__pycache__/threshold.cpython-314.pyc index 4bf19de9de7cde07e78f31ad69638212de22718f..1aff80c802fde7e4d4ffaab566afb13e211733bf 100644 GIT binary patch delta 20 acmbQ^J;$3{n~#@^0SI2~@ZZQiQ566;K?REd delta 20 acmbQ^J;$3{n~#@^0SMZP{Wfw>R0RMs@C4%k diff --git a/custom_components/maintenance_supporter/frontend-src/__tests__/dashboard-kpi-chips.test.ts b/custom_components/maintenance_supporter/frontend-src/__tests__/dashboard-kpi-chips.test.ts new file mode 100644 index 0000000..618f92d --- /dev/null +++ b/custom_components/maintenance_supporter/frontend-src/__tests__/dashboard-kpi-chips.test.ts @@ -0,0 +1,54 @@ +/** + * #86 (2nd report): the dashboard KPI chips must never read "unknown" when the + * summary sensors are absent (orphan object entries after the global entry was + * deleted). The chips prefer the live summary sensor when its entity id + * resolves, but fall back to the literal count from the statistics WS payload + * otherwise. + */ +import { expect } from "@open-wc/testing"; +import { kpiMarkdownCard } from "../maintenance-dashboard-strategy"; + +function contentOf(card: unknown): string { + return (card as { content: string }).content; +} + +describe("dashboard KPI chips (#86)", () => { + it("uses live sensor templates when the summary entity ids resolve", () => { + const content = contentOf( + kpiMarkdownCard( + { + overdue: "sensor.maintenance_supporter_overdue", + triggered: "sensor.maintenance_supporter_triggered", + due_soon: "sensor.maintenance_supporter_due_soon", + ok: "sensor.maintenance_supporter_ok", + }, + { overdue: 2, triggered: 1, due_soon: 3, ok: 4 }, + ), + ); + // Reactive template, not the literal number. + expect(content).to.include("{{ states('sensor.maintenance_supporter_overdue') }}"); + expect(content).to.include("overdue"); + }); + + it("falls back to the literal WS counts when no summary sensor exists", () => { + const content = contentOf( + kpiMarkdownCard( + { overdue: null, triggered: null, due_soon: null, ok: null }, + { overdue: 2, triggered: 1, due_soon: 3, ok: 4 }, + ), + ); + // No entity templates at all — the counts are baked in as real numbers. + expect(content).to.not.include("states("); + expect(content).to.not.include("unknown"); + expect(content).to.include("**2** overdue"); + expect(content).to.include("**1** triggered"); + expect(content).to.include("**3** due soon"); + expect(content).to.include("**4** ok"); + }); + + it("shows an em dash rather than a template when neither id nor count is available", () => { + const content = contentOf(kpiMarkdownCard({}, {})); + expect(content).to.not.include("states("); + expect(content).to.include("**—** overdue"); + }); +}); diff --git a/custom_components/maintenance_supporter/frontend-src/maintenance-dashboard-strategy.ts b/custom_components/maintenance_supporter/frontend-src/maintenance-dashboard-strategy.ts index 75ccb2d..6c3bb53 100644 --- a/custom_components/maintenance_supporter/frontend-src/maintenance-dashboard-strategy.ts +++ b/custom_components/maintenance_supporter/frontend-src/maintenance-dashboard-strategy.ts @@ -204,18 +204,32 @@ const SMALL_SCREEN_CONDITION: ViewColumnsCondition = { // documented sensor.maintenance_supporter_ ids are NOT guaranteed — // a user rename, a _2 collision suffix, or a pre-pinning install that // registered localized ids all made the hardcoded templates read "unknown". -type SummaryEntityIds = Partial>; +type SummaryKey = "overdue" | "triggered" | "due_soon" | "ok"; +type SummaryEntityIds = Partial>; +type SummaryCounts = Partial>; -function kpiMarkdownCard(ids: SummaryEntityIds = {}): CardConfig { - const eid = (key: keyof SummaryEntityIds) => ids[key] || `sensor.maintenance_supporter_${key}`; +// One chip's value: prefer the live summary sensor (reactive template) when its +// entity exists, but fall back to the literal count from the statistics WS when +// it doesn't. The summary sensors only exist while the global "Maintenance +// Supporter" entry is set up; if it was deleted (orphan object entries — #86, +// 2nd report) the templated `states()` reads "unknown". The count from the WS +// is always authoritative, so the chips stay correct either way. +function kpiValue(key: SummaryKey, ids: SummaryEntityIds, counts: SummaryCounts): string { + const id = ids[key]; + if (id) return `{{ states('${id}') }}`; + const n = counts[key]; + return n === undefined || n === null ? "—" : String(n); +} + +export function kpiMarkdownCard(ids: SummaryEntityIds = {}, counts: SummaryCounts = {}): CardConfig { return { type: "markdown", text_only: true, content: [ - `🔴 **{{ states('${eid("overdue")}') }}** overdue`, - `⚡ **{{ states('${eid("triggered")}') }}** triggered`, - `🟡 **{{ states('${eid("due_soon")}') }}** due soon`, - `🟢 **{{ states('${eid("ok")}') }}** ok`, + `🔴 **${kpiValue("overdue", ids, counts)}** overdue`, + `⚡ **${kpiValue("triggered", ids, counts)}** triggered`, + `🟡 **${kpiValue("due_soon", ids, counts)}** due soon`, + `🟢 **${kpiValue("ok", ids, counts)}** ok`, ].join(" · "), }; } @@ -270,8 +284,8 @@ function emptyStateView(): ViewConfig { }; } -function overviewView(summaryIds: SummaryEntityIds = {}): ViewConfig { - const kpiCard = kpiMarkdownCard(summaryIds); +function overviewView(summaryIds: SummaryEntityIds = {}, counts: SummaryCounts = {}): ViewConfig { + const kpiCard = kpiMarkdownCard(summaryIds, counts); return { title: "Overview", icon: "mdi:wrench-clock", @@ -621,19 +635,31 @@ export class MaintenanceDashboardStrategy extends HTMLElement { calendar: () => viewsByCalendar(objects), }; - // Registry-resolved summary-sensor ids (#86); tolerate older backends. + // Registry-resolved summary-sensor ids + live counts (#86); tolerate older + // backends. The counts are the fallback the chips render when the summary + // sensors don't exist (orphan object entries after the global entry was + // deleted), so they never read "unknown". let summaryIds: SummaryEntityIds = {}; + let counts: SummaryCounts = {}; try { - const stats = await hass.connection.sendMessagePromise<{ summary_entity_ids?: SummaryEntityIds }>({ + const stats = await hass.connection.sendMessagePromise< + { summary_entity_ids?: SummaryEntityIds } & SummaryCounts + >({ type: "maintenance_supporter/statistics", }); summaryIds = stats.summary_entity_ids || {}; + counts = { + overdue: stats.overdue, + triggered: stats.triggered, + due_soon: stats.due_soon, + ok: stats.ok, + }; } catch { /* fall back to the documented default ids */ } return { title: "Maintenance", views: [ - overviewView(summaryIds), + overviewView(summaryIds, counts), ...(viewBuilders[groupBy] ?? viewBuilders.area)(), ], }; diff --git a/custom_components/maintenance_supporter/frontend/__pycache__/__init__.cpython-314.pyc b/custom_components/maintenance_supporter/frontend/__pycache__/__init__.cpython-314.pyc index 860dd6ecd15cf303f836f82c2a042d7b3bd340bf..38fa98e5d057e424cc0fd4023d3d0fac985b7562 100644 GIT binary patch delta 20 acmbOyJ5QEdn~#@^0SI2~@ZZQinGXOl0tFrb delta 20 acmbOyJ5QEdn~#@^0SMZP{Wfw><^upMu>^Ji diff --git a/custom_components/maintenance_supporter/frontend/strategy/maintenance-dashboard-strategy.js b/custom_components/maintenance_supporter/frontend/strategy/maintenance-dashboard-strategy.js index b1d7bfa..20daa5b 100644 --- a/custom_components/maintenance_supporter/frontend/strategy/maintenance-dashboard-strategy.js +++ b/custom_components/maintenance_supporter/frontend/strategy/maintenance-dashboard-strategy.js @@ -1,4 +1,4 @@ -import"./chunks/chunk-LO2NM3CE.js";var A="maintenance-supporter",I=`ll-strategy-dashboard-${A}`,L="hui-maintenance-supporter-strategy-editor",P="NOT_RUNNING",G=[{status:"overdue",title:"Overdue",icon:"mdi:alert-circle",path:"overdue"},{status:"triggered",title:"Triggered",icon:"mdi:flash",path:"triggered"},{status:"due_soon",title:"Due Soon",icon:"mdi:clock-alert-outline",path:"due-soon"},{status:"ok",title:"OK",icon:"mdi:check-circle-outline",path:"ok"}],C=[{title:"Overdue",icon:"mdi:alert-circle",path:"overdue",filter:{filter_due_max_days:-1},matches:i=>i<=-1},{title:"Today",icon:"mdi:calendar-today",path:"today",filter:{filter_due_min_days:0,filter_due_max_days:0},matches:i=>i===0},{title:"This Week",icon:"mdi:calendar-week",path:"this-week",filter:{filter_due_min_days:1,filter_due_max_days:7},matches:i=>i>=1&&i<=7},{title:"This Month",icon:"mdi:calendar-month",path:"this-month",filter:{filter_due_min_days:8,filter_due_max_days:30},matches:i=>i>=8&&i<=30},{title:"Later",icon:"mdi:calendar-clock",path:"later",filter:{filter_due_min_days:31},matches:i=>i>=31}];function u(i){return{type:"grid",cards:[i]}}var H={condition:"view_columns",min:2};function V(i={}){let n=e=>i[e]||`sensor.maintenance_supporter_${e}`;return{type:"markdown",text_only:!0,content:[`\u{1F534} **{{ states('${n("overdue")}') }}** overdue`,`\u26A1 **{{ states('${n("triggered")}') }}** triggered`,`\u{1F7E1} **{{ states('${n("due_soon")}') }}** due soon`,`\u{1F7E2} **{{ states('${n("ok")}') }}** ok`].join(" \xB7 ")}}function N(){return{title:"Maintenance",type:"panel",cards:[{type:"empty-state",icon:"mdi:wrench-clock",icon_color:"primary",content_only:!0,title:"No maintenance objects yet",content:"Open the Maintenance panel to add your first object \u2014 pool pump, HVAC filter, vehicle, anything that needs scheduled care.",buttons:[{icon:"mdi:wrench",text:"Open Maintenance panel",appearance:"filled",variant:"brand",tap_action:{action:"navigate",navigation_path:"/maintenance-supporter"}},{icon:"mdi:plus",text:"Add object",appearance:"outlined",variant:"brand",tap_action:{action:"fire-dom-event",ll_custom:{type:"maintenance-supporter:add-object"}}}]}]}}function B(i={}){let n=V(i);return{title:"Overview",icon:"mdi:wrench-clock",path:"overview",type:"sections",header:{layout:"responsive",card:n},sidebar:{sections:[{type:"grid",cards:[{type:"heading",heading:"Status",heading_style:"title"},n]}],visibility:[H],content_label:"Tasks",sidebar_label:"Status"},sections:[u({type:"custom:maintenance-supporter-card",show_header:!1,filter_status:["overdue","triggered","due_soon"]})]}}function $(i,n){let e=new Map;for(let r of i){let a=r.object.area_id||null;e.has(a)||e.set(a,[]),e.get(a).push(r)}let s=Array.from(e.keys()).filter(r=>r!==null);s.sort((r,a)=>{let c=n[r]?.name||r,d=n[a]?.name||a;return c.localeCompare(d)});let t=[];for(let r of s){let a=e.get(r);if(a.length===0)continue;let c=n[r];t.push({title:c?.name||r,icon:c?.icon||"mdi:floor-plan",path:`area-${r}`,type:"sections",sections:[u({type:"custom:maintenance-supporter-card",show_header:!1,filter_objects:a.map(d=>d.object.name)})]})}let o=e.get(null);return o&&o.length>0&&t.push({title:"Unassigned",icon:"mdi:help-circle-outline",path:"unassigned",type:"sections",sections:[u({type:"custom:maintenance-supporter-card",show_header:!1,filter_objects:o.map(r=>r.object.name)})]}),t}function U(i){let n=new Set;for(let s of i)for(let t of s.tasks||[])t.status&&n.add(t.status);let e=[];for(let s of G)n.has(s.status)&&e.push({title:s.title,icon:s.icon,path:s.path,type:"sections",sections:[u({type:"custom:maintenance-supporter-card",show_header:!1,filter_status:[s.status]})]});return e}function W(i,n,e){let s=new Map;for(let a of i){let c=a.object.area_id,d=c&&n[c]?.floor_id||null;s.has(d)||s.set(d,[]),s.get(d).push(a)}let t=Array.from(s.keys()).filter(a=>a!==null);t.sort((a,c)=>{let d=e[a],g=e[c],l=d?.level??0,p=g?.level??0;return l!==p?l-p:(d?.name||a).localeCompare(g?.name||c)});let o=[];for(let a of t){let c=s.get(a);if(c.length===0)continue;let d=e[a];o.push({title:d?.name||a,icon:d?.icon||"mdi:home-floor-1",path:`floor-${a}`,type:"sections",sections:[u({type:"custom:maintenance-supporter-card",show_header:!1,filter_objects:c.map(g=>g.object.name)})]})}let r=s.get(null);return r&&r.length>0&&o.push({title:"Other",icon:"mdi:help-circle-outline",path:"other",type:"sections",sections:[u({type:"custom:maintenance-supporter-card",show_header:!1,filter_objects:r.map(a=>a.object.name)})]}),o}function Y(i){return[{title:"Week",icon:"mdi:calendar-week",path:"cal-7",window_days:7},{title:"Fortnight",icon:"mdi:calendar-week-begin",path:"cal-14",window_days:14},{title:"Month",icon:"mdi:calendar-month",path:"cal-30",window_days:30},{title:"Year",icon:"mdi:calendar-clock",path:"cal-365",window_days:365}].map(e=>({title:e.title,icon:e.icon,path:e.path,type:"panel",cards:[{type:"custom:maintenance-supporter-calendar-card",window_days:e.window_days,show_window_chips:!1,show_user_filter:!0}]}))}function F(i){let n=new Set;for(let s of i)for(let t of s.tasks||[]){let o=t.days_until_due;o!=null&&C.forEach((r,a)=>{r.matches(o)&&n.add(a)})}let e=[];return C.forEach((s,t)=>{n.has(t)&&e.push({title:s.title,icon:s.icon,path:s.path,type:"sections",sections:[u({type:"custom:maintenance-supporter-card",show_header:!1,...s.filter})]})}),e}var E=class extends HTMLElement{static getCreateSuggestions(n){return{title:"Maintenance Supporter",icon:"mdi:wrench-clock"}}static async getConfigElement(){return document.createElement(L)}static async generate(n,e){if(e.config?.state===P)return{views:[{type:"sections",sections:[{cards:[{type:"starting"}]}]}]};if(e.config?.recovery_mode)return{views:[{type:"sections",sections:[{cards:[{type:"recovery-mode"}]}]}]};let s;try{s=await e.connection.sendMessagePromise({type:"maintenance_supporter/objects"})}catch{return{title:"Maintenance",views:[{title:"Maintenance",cards:[{type:"markdown",content:"**Maintenance Supporter** is not loaded. Install/enable the integration first."}]}]}}let t=s.objects||[];if(t.length===0)return{title:"Maintenance",views:[N()]};let o=n?.group_by??"area",r={area:()=>$(t,e.areas||{}),status:()=>U(t),floor:()=>W(t,e.areas||{},e.floors||{}),due_date:()=>F(t),calendar:()=>Y(t)},a={};try{a=(await e.connection.sendMessagePromise({type:"maintenance_supporter/statistics"})).summary_entity_ids||{}}catch{}return{title:"Maintenance",views:[B(a),...(r[o]??r.area)()]}}},q=[{value:"area",label:"By area (default)"},{value:"status",label:"By status (Overdue / Triggered / Due Soon / OK)"},{value:"floor",label:"By floor (uses HA floors)"},{value:"due_date",label:"By due date (Overdue / Today / Week / Month / Later)"},{value:"calendar",label:"Rolling calendar (Week / Fortnight / Month / Year)"}],h=class extends HTMLElement{constructor(){super(...arguments);this._config={type:"custom:maintenance-supporter"}}set hass(e){this._hass=e}setConfig(e){this._config=e,this._render()}connectedCallback(){this._render()}_render(){let e=this._config.group_by??"area",s=q.map(o=>``).join("");this.innerHTML=` +import"./chunks/chunk-LO2NM3CE.js";var L="maintenance-supporter",P=`ll-strategy-dashboard-${L}`,O="hui-maintenance-supporter-strategy-editor",G="NOT_RUNNING",V=[{status:"overdue",title:"Overdue",icon:"mdi:alert-circle",path:"overdue"},{status:"triggered",title:"Triggered",icon:"mdi:flash",path:"triggered"},{status:"due_soon",title:"Due Soon",icon:"mdi:clock-alert-outline",path:"due-soon"},{status:"ok",title:"OK",icon:"mdi:check-circle-outline",path:"ok"}],S=[{title:"Overdue",icon:"mdi:alert-circle",path:"overdue",filter:{filter_due_max_days:-1},matches:n=>n<=-1},{title:"Today",icon:"mdi:calendar-today",path:"today",filter:{filter_due_min_days:0,filter_due_max_days:0},matches:n=>n===0},{title:"This Week",icon:"mdi:calendar-week",path:"this-week",filter:{filter_due_min_days:1,filter_due_max_days:7},matches:n=>n>=1&&n<=7},{title:"This Month",icon:"mdi:calendar-month",path:"this-month",filter:{filter_due_min_days:8,filter_due_max_days:30},matches:n=>n>=8&&n<=30},{title:"Later",icon:"mdi:calendar-clock",path:"later",filter:{filter_due_min_days:31},matches:n=>n>=31}];function u(n){return{type:"grid",cards:[n]}}var H={condition:"view_columns",min:2};function f(n,i,e){let s=i[n];if(s)return`{{ states('${s}') }}`;let t=e[n];return t==null?"\u2014":String(t)}function N(n={},i={}){return{type:"markdown",text_only:!0,content:[`\u{1F534} **${f("overdue",n,i)}** overdue`,`\u26A1 **${f("triggered",n,i)}** triggered`,`\u{1F7E1} **${f("due_soon",n,i)}** due soon`,`\u{1F7E2} **${f("ok",n,i)}** ok`].join(" \xB7 ")}}function B(){return{title:"Maintenance",type:"panel",cards:[{type:"empty-state",icon:"mdi:wrench-clock",icon_color:"primary",content_only:!0,title:"No maintenance objects yet",content:"Open the Maintenance panel to add your first object \u2014 pool pump, HVAC filter, vehicle, anything that needs scheduled care.",buttons:[{icon:"mdi:wrench",text:"Open Maintenance panel",appearance:"filled",variant:"brand",tap_action:{action:"navigate",navigation_path:"/maintenance-supporter"}},{icon:"mdi:plus",text:"Add object",appearance:"outlined",variant:"brand",tap_action:{action:"fire-dom-event",ll_custom:{type:"maintenance-supporter:add-object"}}}]}]}}function $(n={},i={}){let e=N(n,i);return{title:"Overview",icon:"mdi:wrench-clock",path:"overview",type:"sections",header:{layout:"responsive",card:e},sidebar:{sections:[{type:"grid",cards:[{type:"heading",heading:"Status",heading_style:"title"},e]}],visibility:[H],content_label:"Tasks",sidebar_label:"Status"},sections:[u({type:"custom:maintenance-supporter-card",show_header:!1,filter_status:["overdue","triggered","due_soon"]})]}}function U(n,i){let e=new Map;for(let a of n){let r=a.object.area_id||null;e.has(r)||e.set(r,[]),e.get(r).push(a)}let s=Array.from(e.keys()).filter(a=>a!==null);s.sort((a,r)=>{let d=i[a]?.name||a,c=i[r]?.name||r;return d.localeCompare(c)});let t=[];for(let a of s){let r=e.get(a);if(r.length===0)continue;let d=i[a];t.push({title:d?.name||a,icon:d?.icon||"mdi:floor-plan",path:`area-${a}`,type:"sections",sections:[u({type:"custom:maintenance-supporter-card",show_header:!1,filter_objects:r.map(c=>c.object.name)})]})}let o=e.get(null);return o&&o.length>0&&t.push({title:"Unassigned",icon:"mdi:help-circle-outline",path:"unassigned",type:"sections",sections:[u({type:"custom:maintenance-supporter-card",show_header:!1,filter_objects:o.map(a=>a.object.name)})]}),t}function W(n){let i=new Set;for(let s of n)for(let t of s.tasks||[])t.status&&i.add(t.status);let e=[];for(let s of V)i.has(s.status)&&e.push({title:s.title,icon:s.icon,path:s.path,type:"sections",sections:[u({type:"custom:maintenance-supporter-card",show_header:!1,filter_status:[s.status]})]});return e}function Y(n,i,e){let s=new Map;for(let r of n){let d=r.object.area_id,c=d&&i[d]?.floor_id||null;s.has(c)||s.set(c,[]),s.get(c).push(r)}let t=Array.from(s.keys()).filter(r=>r!==null);t.sort((r,d)=>{let c=e[r],g=e[d],l=c?.level??0,p=g?.level??0;return l!==p?l-p:(c?.name||r).localeCompare(g?.name||d)});let o=[];for(let r of t){let d=s.get(r);if(d.length===0)continue;let c=e[r];o.push({title:c?.name||r,icon:c?.icon||"mdi:home-floor-1",path:`floor-${r}`,type:"sections",sections:[u({type:"custom:maintenance-supporter-card",show_header:!1,filter_objects:d.map(g=>g.object.name)})]})}let a=s.get(null);return a&&a.length>0&&o.push({title:"Other",icon:"mdi:help-circle-outline",path:"other",type:"sections",sections:[u({type:"custom:maintenance-supporter-card",show_header:!1,filter_objects:a.map(r=>r.object.name)})]}),o}function F(n){return[{title:"Week",icon:"mdi:calendar-week",path:"cal-7",window_days:7},{title:"Fortnight",icon:"mdi:calendar-week-begin",path:"cal-14",window_days:14},{title:"Month",icon:"mdi:calendar-month",path:"cal-30",window_days:30},{title:"Year",icon:"mdi:calendar-clock",path:"cal-365",window_days:365}].map(e=>({title:e.title,icon:e.icon,path:e.path,type:"panel",cards:[{type:"custom:maintenance-supporter-calendar-card",window_days:e.window_days,show_window_chips:!1,show_user_filter:!0}]}))}function K(n){let i=new Set;for(let s of n)for(let t of s.tasks||[]){let o=t.days_until_due;o!=null&&S.forEach((a,r)=>{a.matches(o)&&i.add(r)})}let e=[];return S.forEach((s,t)=>{i.has(t)&&e.push({title:s.title,icon:s.icon,path:s.path,type:"sections",sections:[u({type:"custom:maintenance-supporter-card",show_header:!1,...s.filter})]})}),e}var E=class extends HTMLElement{static getCreateSuggestions(i){return{title:"Maintenance Supporter",icon:"mdi:wrench-clock"}}static async getConfigElement(){return document.createElement(O)}static async generate(i,e){if(e.config?.state===G)return{views:[{type:"sections",sections:[{cards:[{type:"starting"}]}]}]};if(e.config?.recovery_mode)return{views:[{type:"sections",sections:[{cards:[{type:"recovery-mode"}]}]}]};let s;try{s=await e.connection.sendMessagePromise({type:"maintenance_supporter/objects"})}catch{return{title:"Maintenance",views:[{title:"Maintenance",cards:[{type:"markdown",content:"**Maintenance Supporter** is not loaded. Install/enable the integration first."}]}]}}let t=s.objects||[];if(t.length===0)return{title:"Maintenance",views:[B()]};let o=i?.group_by??"area",a={area:()=>U(t,e.areas||{}),status:()=>W(t),floor:()=>Y(t,e.areas||{},e.floors||{}),due_date:()=>K(t),calendar:()=>F(t)},r={},d={};try{let c=await e.connection.sendMessagePromise({type:"maintenance_supporter/statistics"});r=c.summary_entity_ids||{},d={overdue:c.overdue,triggered:c.triggered,due_soon:c.due_soon,ok:c.ok}}catch{}return{title:"Maintenance",views:[$(r,d),...(a[o]??a.area)()]}}},q=[{value:"area",label:"By area (default)"},{value:"status",label:"By status (Overdue / Triggered / Due Soon / OK)"},{value:"floor",label:"By floor (uses HA floors)"},{value:"due_date",label:"By due date (Overdue / Today / Week / Month / Later)"},{value:"calendar",label:"Rolling calendar (Week / Fortnight / Month / Year)"}],b=class extends HTMLElement{constructor(){super(...arguments);this._config={type:"custom:maintenance-supporter"}}set hass(e){this._hass=e}setConfig(e){this._config=e,this._render()}connectedCallback(){this._render()}_render(){let e=this._config.group_by??"area",s=q.map(o=>``).join("");this.innerHTML=` ','Custom\x20color\x20for\x20X-axis\x20labels.\x20Accepts\x20any\x20CSS\x20color\x20or\x20CSS\x20variable.\x20Leave\x20empty\x20to\x20use\x20theme\x20--primary-text-color.','firstChild','Position\x20and\x20alignment\x20of\x20this\x20entity\x20state\x20row.','Tooltip','dampResetBoundaryMax','.e-needle_color-picker','','className','y2_axis_format','DD-MM-YYYY','\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20Entity','error','#888','stable','radialbar','\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20','fire-dom-event','click','\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20','sgc-hours:','_onQueryPick','#16a085','rgba(','#e91e63','Mois\x20précédent','block','Select\x20end\x20date','statistic_id','toggle','No\x20annotations\x20yet','','\x22\x20height=\x22','180天','Wczoraj','_cacheCleanupTimer','Sidste\x20uge','fill:','[data-intlabel]','No\x20numeric\x20data\x20for\x20box\x20plot.','numeric','Juokseva\x20summa','\x22\x20data-hours=\x22','Ostatni','padding:','_resolveCanvasColor','Median','linearGradient','Yhteensä','\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20','sgc:compiled_transform','show_range_band','diff','Milliseconds','Diff','row','\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20','pointerEvents','\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20','stats','never','External\x20statistic\x20—\x20only\x20published\x20to\x20the\x20statistics\x20database.','config','Últimas\x2024\x20horas','middle','_sgcIcon','closest','\x22\x20aria-label=\x22Open\x20calendar\x22\x20title=\x22Open\x20calendar\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20','customEnd','Time\x20span','Campioni','_attachTooltip','\x22\x20is\x20not\x20implemented\x20in\x20Phase\x201.\x0a\x20\x20\x20\x20\x20\x20\x20\x20Phase\x201\x20supports\x20timeline.\x20YAML\x20for\x20other\x20modes\x20is\x20accepted\x20and\x20preserved.\x0a\x20\x20\x20\x20\x20\x20','#26a69a','_onDatePickerSyncRequest','isInteger','_querySyncHandler','Português','_cache','','clientX','d\x20h:mm','unexpected\x20character\x20\x22','day_of_year','getDate','\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20Graph\x20','\x20selected','_renderCalendarGrid','index','ohlc','How\x20numbers\x20on\x20the\x20Y\x20axis\x20are\x20formatted.\x20System\x20=\x20follow\x20HA\x20locale\x20setting.\x20Comma\x20=\x20European\x20style\x20(1.234,56).\x20Dot\x20=\x20American\x20style\x20(1,234.56).\x20Independent\x20from\x20per-entity\x20Number\x20Format,\x20which\x20still\x20drives\x20state\x20row,\x20tooltip\x20and\x20data\x20labels.','Son\x207\x20Gün','slice','Colour\x20of\x20the\x20━\x20(stable)\x20trend\x20icon.\x20Leave\x20empty\x20to\x20follow\x20the\x20theme\x20secondary\x20text\x20colour\x20(grey).','Color\x20Thresholds\x20','','Questo\x20mese','Son\x2015\x20gün','show_points','px','Poslední\x203\x20dny','Delta','long','24sa','e-entity','mtab','>Adaptive\x20Color\x20','Statistics\x20Graph\x20Chart\x20Card','Grid\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20','localeCompare','pie_label_color','_quantile','--primary-font-family','baselineByIdx','Последние\x20180\x20дней','_read','>X\x20Ticks\x20','Snaps\x20the\x20start\x20of\x20the\x20graph\x20window\x20to\x20a\x20calendar\x20boundary.\x20Today\x20=\x20start\x20from\x20today\x2000:00\x20(ideal\x20for\x20showing\x20a\x20full\x2024h\x20of\x20today,\x20e.g.\x20Nord\x20Pool\x20hourly\x20prices\x20with\x20today_hourly\x20attribute\x20—\x20use\x20with\x20Show\x20Full\x20Period).\x20Tomorrow\x20=\x20start\x20from\x20tomorrow\x2000:00\x20(for\x20forecast\x20data).\x20Week\x20=\x20Monday\x2000:00.\x20Month\x20=\x201st\x20of\x20the\x20month.\x20Year\x20=\x20January\x201st.\x20Overrides\x20hours_to_show.\x20When\x20the\x20interval\x20picker\x20is\x20active,\x20this\x20setting\x20is\x20ignored.','Sem\x20entidades\x20para\x20classificar.','http://www.w3.org/2000/svg','pie_label_format','sgc-ann-band','.e-value_transform','\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20','_drawAverageLines','_showExtremaOnClick','\x22>×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 baCp5pa-fgURn~NzP(cxqA;qeO|dgJF3uQH!j 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

mfMdx@{#ZQJSP^X@3v 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

_?9t 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�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"use strict";const t=globalThis,e=t.ShadowRoot&&(void 0===t.ShadyCSS||t.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,i=Symbol(),n=new WeakMap;class r{constructor(t,e,n){if(this._$cssResult$=!0,n!==i)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e}get styleSheet(){let t=this.o;const i=this.t;if(e&&void 0===t){const e=void 0!==i&&1===i.length;e&&(t=n.get(i)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),e&&n.set(i,t))}return t}toString(){return this.cssText}}const o=(t,...e)=>{const n=1===t.length?t[0]:e.reduce((e,i,n)=>e+(t=>{if(!0===t._$cssResult$)return t.cssText;if("number"==typeof t)return t;throw Error("Value passed to 'css' function must be a 'css' function result: "+t+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(i)+t[n+1],t[0]);return new r(n,t,i)},s=(i,n)=>{if(e)i.adoptedStyleSheets=n.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet);else for(const e of n){const n=document.createElement("style"),r=t.litNonce;void 0!==r&&n.setAttribute("nonce",r),n.textContent=e.cssText,i.appendChild(n)}},a=e?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new r("string"==typeof t?t:t+"",void 0,i))(e)})(t):t,{is:c,defineProperty:u,getOwnPropertyDescriptor:l,getOwnPropertyNames:h,getOwnPropertySymbols:f,getPrototypeOf:d}=Object,p=globalThis,m=p.trustedTypes,y=m?m.emptyScript:"",b=p.reactiveElementPolyfillSupport,_=(t,e)=>t,v={toAttribute(t,e){switch(e){case Boolean:t=t?y:null;break;case Object:case Array:t=null==t?t:JSON.stringify(t)}return t},fromAttribute(t,e){let i=t;switch(e){case Boolean:i=null!==t;break;case Number:i=null===t?null:Number(t);break;case Object:case Array:try{i=JSON.parse(t)}catch(t){i=null}}return i}},g=(t,e)=>!c(t,e),$={attribute:!0,type:String,converter:v,reflect:!1,useDefault:!1,hasChanged:g};Symbol.metadata??=Symbol("metadata"),p.litPropertyMetadata??=new WeakMap;class w extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,e=$){if(e.state&&(e.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(t)&&((e=Object.create(e)).wrapped=!0),this.elementProperties.set(t,e),!e.noAccessor){const i=Symbol(),n=this.getPropertyDescriptor(t,i,e);void 0!==n&&u(this.prototype,t,n)}}static getPropertyDescriptor(t,e,i){const{get:n,set:r}=l(this.prototype,t)??{get(){return this[e]},set(t){this[e]=t}};return{get:n,set(e){const o=n?.call(this);r?.call(this,e),this.requestUpdate(t,o,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??$}static _$Ei(){if(this.hasOwnProperty(_("elementProperties")))return;const t=d(this);t.finalize(),void 0!==t.l&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(_("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(_("properties"))){const t=this.properties,e=[...h(t),...f(t)];for(const i of e)this.createProperty(i,t[i])}const t=this[Symbol.metadata];if(null!==t){const e=litPropertyMetadata.get(t);if(void 0!==e)for(const[t,i]of e)this.elementProperties.set(t,i)}this._$Eh=new Map;for(const[t,e]of this.elementProperties){const i=this._$Eu(t,e);void 0!==i&&this._$Eh.set(i,t)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(t){const e=[];if(Array.isArray(t)){const i=new Set(t.flat(1/0).reverse());for(const t of i)e.unshift(a(t))}else void 0!==t&&e.push(a(t));return e}static _$Eu(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(t=>t(this))}addController(t){(this._$EO??=new Set).add(t),void 0!==this.renderRoot&&this.isConnected&&t.hostConnected?.()}removeController(t){this._$EO?.delete(t)}_$E_(){const t=new Map,e=this.constructor.elementProperties;for(const i of e.keys())this.hasOwnProperty(i)&&(t.set(i,this[i]),delete this[i]);t.size>0&&(this._$Ep=t)}createRenderRoot(){const t=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return s(t,this.constructor.elementStyles),t}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(t=>t.hostConnected?.())}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach(t=>t.hostDisconnected?.())}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$ET(t,e){const i=this.constructor.elementProperties.get(t),n=this.constructor._$Eu(t,i);if(void 0!==n&&!0===i.reflect){const r=(void 0!==i.converter?.toAttribute?i.converter:v).toAttribute(e,i.type);this._$Em=t,null==r?this.removeAttribute(n):this.setAttribute(n,r),this._$Em=null}}_$AK(t,e){const i=this.constructor,n=i._$Eh.get(t);if(void 0!==n&&this._$Em!==n){const t=i.getPropertyOptions(n),r="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==t.converter?.fromAttribute?t.converter:v;this._$Em=n;const o=r.fromAttribute(e,t.type);this[n]=o??this._$Ej?.get(n)??o,this._$Em=null}}requestUpdate(t,e,i,n=!1,r){if(void 0!==t){const o=this.constructor;if(!1===n&&(r=this[t]),i??=o.getPropertyOptions(t),!((i.hasChanged??g)(r,e)||i.useDefault&&i.reflect&&r===this._$Ej?.get(t)&&!this.hasAttribute(o._$Eu(t,i))))return;this.C(t,e,i)}!1===this.isUpdatePending&&(this._$ES=this._$EP())}C(t,e,{useDefault:i,reflect:n,wrapped:r},o){i&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,o??e??this[t]),!0!==r||void 0!==o)||(this._$AL.has(t)||(this.hasUpdated||i||(e=void 0),this._$AL.set(t,e)),!0===n&&this._$Em!==t&&(this._$Eq??=new Set).add(t))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[t,e]of this._$Ep)this[t]=e;this._$Ep=void 0}const t=this.constructor.elementProperties;if(t.size>0)for(const[e,i]of t){const{wrapped:t}=i,n=this[e];!0!==t||this._$AL.has(e)||void 0===n||this.C(e,void 0,i,n)}}let t=!1;const e=this._$AL;try{t=this.shouldUpdate(e),t?(this.willUpdate(e),this._$EO?.forEach(t=>t.hostUpdate?.()),this.update(e)):this._$EM()}catch(e){throw t=!1,this._$EM(),e}t&&this._$AE(e)}willUpdate(t){}_$AE(t){this._$EO?.forEach(t=>t.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return!0}update(t){this._$Eq&&=this._$Eq.forEach(t=>this._$ET(t,this[t])),this._$EM()}updated(t){}firstUpdated(t){}}w.elementStyles=[],w.shadowRootOptions={mode:"open"},w[_("elementProperties")]=new Map,w[_("finalized")]=new Map,b?.({ReactiveElement:w}),(p.reactiveElementVersions??=[]).push("2.1.2");const A=globalThis,O=t=>t,S=A.trustedTypes,E=S?S.createPolicy("lit-html",{createHTML:t=>t}):void 0,P="$lit$",j=`lit$${Math.random().toFixed(9).slice(2)}$`,x="?"+j,k=`<${x}>`,C=document,D=()=>C.createComment(""),N=t=>null===t||"object"!=typeof t&&"function"!=typeof t,T=Array.isArray,M="[ \t\n\f\r]",U=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,H=/-->/g,R=/>/g,I=RegExp(`>|${M}(?:([^\\s"'>=/]+)(${M}*=${M}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),F=/'/g,z=/"/g,L=/^(?:script|style|textarea|title)$/i,B=t=>(e,...i)=>({_$litType$:t,strings:e,values:i}),W=B(1),V=(B(2),B(3),Symbol.for("lit-noChange")),q=Symbol.for("lit-nothing"),Z=new WeakMap,J=C.createTreeWalker(C,129);function K(t,e){if(!T(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==E?E.createHTML(e):e}const Y=(t,e)=>{const i=t.length-1,n=[];let r,o=2===e?"":3===e?"":"",s=U;for(let e=0;e"===c[0]?(s=r??U,u=-1):void 0===c[1]?u=-2:(u=s.lastIndex-c[2].length,a=c[1],s=void 0===c[3]?I:'"'===c[3]?z:F):s===z||s===F?s=I:s===H||s===R?s=U:(s=I,r=void 0);const h=s===I&&t[e+1].startsWith("/>")?" ":"";o+=s===U?i+k:u>=0?(n.push(a),i.slice(0,u)+P+i.slice(u)+j+h):i+j+(-2===u?e:h)}return[K(t,o+(t[i]||"")+(2===e?"":3===e?"":"")),n]};class G{constructor({strings:t,_$litType$:e},i){let n;this.parts=[];let r=0,o=0;const s=t.length-1,a=this.parts,[c,u]=Y(t,e);if(this.el=G.createElement(c,i),J.currentNode=this.el.content,2===e||3===e){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes)}for(;null!==(n=J.nextNode())&&a.length0){n.textContent=S?S.emptyScript:"";for(let i=0;iT(t)||"function"==typeof t?.[Symbol.iterator])(t)?this.k(t):this._(t)}O(t){return this._$AA.parentNode.insertBefore(t,this._$AB)}T(t){this._$AH!==t&&(this._$AR(),this._$AH=this.O(t))}_(t){this._$AH!==q&&N(this._$AH)?this._$AA.nextSibling.data=t:this.T(C.createTextNode(t)),this._$AH=t}$(t){const{values:e,_$litType$:i}=t,n="number"==typeof i?this._$AC(t):(void 0===i.el&&(i.el=G.createElement(K(i.h,i.h[0]),this.options)),i);if(this._$AH?._$AD===n)this._$AH.p(e);else{const t=new X(n,this),i=t.u(this.options);t.p(e),this.T(i),this._$AH=t}}_$AC(t){let e=Z.get(t.strings);return void 0===e&&Z.set(t.strings,e=new G(t)),e}k(t){T(this._$AH)||(this._$AH=[],this._$AR());const e=this._$AH;let i,n=0;for(const r of t)n===e.length?e.push(i=new tt(this.O(D()),this.O(D()),this,this.options)):i=e[n],i._$AI(r),n++;n2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=q}_$AI(t,e=this,i,n){const r=this.strings;let o=!1;if(void 0===r)t=Q(this,t,e,0),o=!N(t)||t!==this._$AH&&t!==V,o&&(this._$AH=t);else{const n=t;let s,a;for(t=r[0],s=0;s{const n=i?.renderBefore??e;let r=n._$litPart$;if(void 0===r){const t=i?.renderBefore??null;n._$litPart$=r=new tt(e.insertBefore(D(),t),t,void 0,i??{})}return r._$AI(t),r})(e,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return V}}ct._$litElement$=!0,ct.finalized=!0,at.litElementHydrateSupport?.({LitElement:ct});const ut=at.litElementPolyfillSupport;var lt,ht;ut?.({LitElement:ct}),(at.litElementVersions??=[]).push("4.2.2"),function(t){t.language="language",t.system="system",t.comma_decimal="comma_decimal",t.decimal_comma="decimal_comma",t.space_comma="space_comma",t.none="none"}(lt||(lt={})),function(t){t.language="language",t.system="system",t.am_pm="12",t.twenty_four="24"}(ht||(ht={}));const ft=["closed","locked","off"],dt=(new Set(["fan","input_boolean","light","switch","group","automation"]),(t,e,i,n)=>{n=n||{},i=i??{};const r=new Event(e,{bubbles:void 0===n.bubbles||n.bubbles,cancelable:Boolean(n.cancelable),composed:void 0===n.composed||n.composed});return r.detail=i,t.dispatchEvent(r),r});new Set(["call-service","divider","section","weblink","cast","select"]);const pt=t=>{dt(window,"haptic",t)};var mt="unavailable",yt="unknown",bt=[mt,yt],_t="last-changed",vt="last-updated",gt=["relative","total","date","time","datetime"],$t=["entity-id","last-changed","last-updated","last-triggered","position","tilt-position","brightness"],wt="language",At=function(t){return t<10?"0".concat(t):t};function Ot(t){var e=Math.floor(t/3600),i=Math.floor(t%3600/60),n=Math.floor(t%3600%60);return e>0?"".concat(e,":").concat(At(i),":").concat(At(n)):i>0?"".concat(i,":").concat(At(n)):n>0?""+n:null}function St(t){return St="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},St(t)}function Et(t,e){var i=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),i.push.apply(i,n)}return i}function Pt(t,e,i){return(e=function(t){var e=function(t){if("object"!=St(t)||!t)return t;var e=t[Symbol.toPrimitive];if(void 0!==e){var i=e.call(t,"string");if("object"!=St(i))return i;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(t)}(t);return"symbol"==St(e)?e:e+""}(e))in t?Object.defineProperty(t,e,{value:i,enumerable:!0,configurable:!0,writable:!0}):t[e]=i,t}var jt=function(t,e,i){var n=e?function(t){switch(t.number_format){case"comma_decimal":return["en-US","en"];case"decimal_comma":return["de","es","it"];case"space_comma":return["fr","sv","cs"];case"system":return;default:return t.language}}(e):void 0;if(Number.isNaN=Number.isNaN||function t(e){return"number"==typeof e&&t(e)},"none"!==(null==e?void 0:e.number_format)&&!Number.isNaN(Number(t))&&Intl)try{return new Intl.NumberFormat(n,xt(t,i)).format(Number(t))}catch(e){return console.error(e),new Intl.NumberFormat(void 0,xt(t,i)).format(Number(t))}return"string"==typeof t?t:"".concat(function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:2;return Math.round(t*Math.pow(10,e))/Math.pow(10,e)}(t,null==i?void 0:i.maximumFractionDigits).toString()).concat("currency"===(null==i?void 0:i.style)?" ".concat(i.currency):"")},xt=function(t,e){var i=function(t){for(var e=1;e-1?t.split(".")[1].length:0;i.minimumFractionDigits=n,i.maximumFractionDigits=n}return i},kt=Number.isNaN||function(t){return"number"==typeof t&&t!=t};function Ct(t,e){return t===e||!(!kt(t)||!kt(e))}function Dt(t,e){if(t.length!==e.length)return!1;for(var i=0;ie.hide_if.above)return!0;e.hide_if.value&&(n=n.concat(e.hide_if.value))}else n=n.concat(e.hide_if);return n.some(function(t){return"number"==typeof t?t===+i:t===i})},Vt=["formatEntityName","formatEntityState","formatEntityAttributeValue"];function qt(t){return qt="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},qt(t)}function Zt(t,e){var i=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),i.push.apply(i,n)}return i}function Jt(t){for(var e=1;e\n
\n ',"","\n
\n "])),this._hass,this.config,this.renderSecondaryInfo(),!1,this.config.column?"entities-column":"entities-row",this.entities.map(function(e){return t.renderEntity(e.stateObj,e)}),this.renderMainEntity()):this.renderWarning():W(Gt||(Gt=ye([""])))}},{key:"renderSecondaryInfo",value:function(){if(!this.config.secondary_info||"string"==typeof(t=this.config.secondary_info)&&$t.includes(t)||Wt(this.info,this.config.secondary_info))return null;var t;if("string"==typeof this.config.secondary_info)return W(Xt||(Xt=ye(["",""])),this.config.secondary_info);var e=de(this.info,this.config.secondary_info);return W(te||(te=ye([""," ",""])),e,this.renderValue(this.info,this.config.secondary_info))}},{key:"renderMainEntity",value:function(){return!1===this.config.show_state?null:W(ee||(ee=ye(['
\n ',"\n
","
\n
"])),pe(this.config),this.onRowClick,this.config.state_header&&W(ie||(ie=ye(["",""])),this.config.state_header),this.renderValue(this.stateObj,this.config))}},{key:"renderEntity",value:function(t,e){if(!t||Wt(t,e))return e.default?W(ne||(ne=ye(['
\n ',"\n
","
\n
"])),pe(e),e.name,e.default):null;var i=this.clickHandler(t.entity_id,e.tap_action);return W(re||(re=ye(['
\n ',"\n
","
\n
"])),pe(e),i,de(t,e),e.icon?this.renderIcon(t,e):this.renderValue(t,e))}},{key:"renderValue",value:function(t,e){if(!0===e.toggle)return W(oe||(oe=ye([''])),t,this._hass);var i;if(e.attribute&&[_t,vt].includes(e.attribute))return W(se||(se=ye([""])),this._hass,t[null===(i=e.attribute)||void 0===i?void 0:i.replace("-","_")]);if(e.format&>.includes(e.format)){var n,r=e.attribute?null!==(n=t.attributes[e.attribute])&&void 0!==n?n:t[e.attribute]:t.state,o=new Date(r);return o instanceof Date&&!isNaN(o.getTime())?W(ae||(ae=ye([""])),this._hass,o,e.format):r}return function(t,e,i){var n="function"==typeof t.formatEntityState,r="function"==typeof t.formatEntityAttributeValue;if(Bt(e))return n?t.formatEntityState(e):t.localize("state.default.".concat(e.state));var o=i.attribute?e.attributes[i.attribute]:e.state,s=!1===i.unit?void 0:void 0!==i.attribute?i.unit:i.unit||e.attributes.unit_of_measurement;if(i.format){if(null==o&&(o=0),isNaN(parseFloat(o))||!isFinite(o));else if("brightness"===i.format)o=Math.round(o/255*100),s="%";else if("duration"===i.format){var a;o=null!==(a=Ot(o))&&void 0!==a?a:"0",s=void 0}else if("duration-m"===i.format){var c;o=null!==(c=Ot(o/1e3))&&void 0!==c?c:"0",s=void 0}else if("duration-h"===i.format){var u;o=null!==(u=Ot(3600*o))&&void 0!==u?u:"0",s=void 0}else if(i.format.startsWith("precision")){var l=parseInt(i.format.slice(-1),10);o=jt(parseFloat(o),t.locale,{minimumFractionDigits:l,maximumFractionDigits:l})}else if(i.format.startsWith("kilo"))o=fe(o,1e3,i.format.slice(4),t.locale);else if(i.format.startsWith("mega"))o=fe(o,1e6,i.format.slice(4),t.locale);else if(i.format.startsWith("milli"))o=fe(o,.001,i.format.slice(5),t.locale);else if("invert"===i.format){var h=he(o);o=jt(o-2*o,t.locale,void 0!==h?{minimumFractionDigits:h,maximumFractionDigits:h}:void 0)}else if("position"===i.format){var f=he(o);o=jt(100-o,t.locale,void 0!==f?{minimumFractionDigits:f,maximumFractionDigits:f}:void 0)}else"celsius_to_fahrenheit"===i.format?o=jt(1.8*o+32,t.locale,{maximumFractionDigits:0}):"fahrenheit_to_celsius"===i.format&&(o=jt(5*(o-32)/9,t.locale,{maximumFractionDigits:1}));return"".concat(o).concat(s?" ".concat(s):"")}var d=Jt(Jt({},e),{},{attributes:Jt(Jt({},e.attributes),{},{unit_of_measurement:s})});if(i.attribute){if(r)return t.formatEntityAttributeValue(d,i.attribute);var p=null==o?"":isNaN(o)?o:jt(o,t.locale);return"".concat(p).concat(s?" ".concat(s):"")}return n?t.formatEntityState(d):function(t,e,i,n){var r=e.state;if(r===yt||r===mt)return t("state.default.".concat(r));if(function(t){return!!t.attributes.unit_of_measurement||!!t.attributes.state_class}(e)){if("monetary"===e.attributes.device_class&&/^[A-Za-z]{3}$/.test(e.attributes.unit_of_measurement))try{return jt(r,i,{style:"currency",currency:e.attributes.unit_of_measurement})}catch(t){}return"".concat(jt(r,i)).concat(e.attributes.unit_of_measurement?" "+e.attributes.unit_of_measurement:"")}var o,s=function(t){return t.entity_id.substr(0,t.entity_id.indexOf("."))}(e);if("input_datetime"===s)return e.attributes.has_date&&e.attributes.has_time?(o=new Date(e.attributes.year,e.attributes.month-1,e.attributes.day,e.attributes.hour,e.attributes.minute),Ht(o,i)):e.attributes.has_date?(o=new Date(e.attributes.year,e.attributes.month-1,e.attributes.day),Tt(o,i)):e.attributes.has_time?((o=new Date).setHours(e.attributes.hour,e.attributes.minute),It(o,i)):e.state;if("humidifier"===s&&"on"===r&&e.attributes.humidity)return"".concat(e.attributes.humidity," %");if("counter"===s||"number"===s||"input_number"===s)return jt(r,i);if("button"===s||"sensor"===s&&"timestamp"===e.attributes.device_class)return Ht(new Date(r),i);var a=n&&n[e.entity_id];return(null==a?void 0:a.translation_key)&&t("component.".concat(a.platform,".entity.").concat(s,".").concat(a.translation_key,".state.").concat(r))||e.attributes.device_class&&t("component.".concat(s,".entity_component.").concat(e.attributes.device_class,".state.").concat(r))||t("component.".concat(s,".entity_component._.state.").concat(r))||r}(t.localize,d,t.locale,t.entities)}(this._hass,t,e)}},{key:"renderIcon",value:function(t,e){return W(ce||(ce=ye([''])),this._hass,t,!0===e.icon?t.attributes.icon||null:e.icon,e.state_color)}},{key:"renderWarning",value:function(){return W(ue||(ue=ye(["\n ","\n "])),this._hass.localize("ui.panel.lovelace.warning.entity_not_found","entity",this.config.entity))}},{key:"clickHandler",value:function(t,e){var i=this;return function(){return((t,e,i)=>{let n;if(i.tap_action&&(n=i.tap_action),n||(n={action:"more-info"}),!n.confirmation||n.confirmation.exemptions&&n.confirmation.exemptions.some(t=>t.user===e.user.id)||confirm(n.confirmation.text||`Are you sure you want to ${n.action}?`))switch(n.action){case"more-info":(n.entity||i.entity||i.camera_image)&&(dt(t,"hass-more-info",{entityId:n.entity?n.entity:i.entity?i.entity:i.camera_image}),n.haptic&&pt(n.haptic));break;case"navigate":n.navigation_path&&(((t,e,i=!1)=>{i?history.replaceState(null,"",e):history.pushState(null,"",e),dt(window,"location-changed",{replace:i})})(0,n.navigation_path),n.haptic&&pt(n.haptic));break;case"url":n.url_path&&window.open(n.url_path),n.haptic&&pt(n.haptic);break;case"toggle":i.entity&&(((t,e)=>{((t,e,i=!0)=>{const n=function(t){return t.substr(0,t.indexOf("."))}(e),r="group"===n?"homeassistant":n;let o;switch(n){case"lock":o=i?"unlock":"lock";break;case"cover":o=i?"open_cover":"close_cover";break;default:o=i?"turn_on":"turn_off"}t.callService(r,o,{entity_id:e})})(t,e,ft.includes(t.states[e].state))})(e,i.entity),n.haptic&&pt(n.haptic));break;case"call-service":{if(!n.service)return;const[t,r]=n.service.split(".",2),o=Object.assign({},n.service_data);"entity"===o.entity_id&&(o.entity_id=i.entity),e.callService(t,r,o,n.target),n.haptic&&pt(n.haptic);break}case"fire-dom-event":dt(t,"ll-custom",n),n.haptic&&pt(n.haptic)}})(i,i._hass,{entity:t,tap_action:e})}}}],[{key:"properties",get:function(){return{_hass:Object,config:Object,stateObj:Object}}},{key:"styles",get:function(){return o(Yt||(Yt=function(t,e){return e||(e=t.slice(0)),Object.freeze(Object.defineProperties(t,{raw:{value:Object.freeze(e)}}))}(["\n .icon-small {\n width: auto;\n }\n .entity {\n text-align: center;\n cursor: pointer;\n }\n .entity span {\n font-size: 10px;\n color: var(--secondary-text-color);\n }\n .entities-row {\n flex-direction: row;\n display: inline-flex;\n justify-content: space-between;\n align-items: center;\n }\n .entities-row .entity {\n margin-right: 16px;\n }\n .entities-row .entity:last-of-type {\n margin-right: 0;\n }\n .entities-column {\n flex-direction: column;\n display: flex;\n align-items: flex-end;\n justify-content: space-evenly;\n }\n .entities-column .entity div {\n display: inline-block;\n vertical-align: middle;\n }\n"])))}}])}(ct);customElements.define("multiple-entity-row",Se)})(); \ No newline at end of file +(()=>{"use strict";const t=globalThis,e=t.ShadowRoot&&(void 0===t.ShadyCSS||t.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,n=Symbol(),i=new WeakMap;class o{constructor(t,e,i){if(this._$cssResult$=!0,i!==n)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e}get styleSheet(){let t=this.o;const n=this.t;if(e&&void 0===t){const e=void 0!==n&&1===n.length;e&&(t=i.get(n)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),e&&i.set(n,t))}return t}toString(){return this.cssText}}const r=(t,...e)=>{const i=1===t.length?t[0]:e.reduce((e,n,i)=>e+(t=>{if(!0===t._$cssResult$)return t.cssText;if("number"==typeof t)return t;throw Error("Value passed to 'css' function must be a 'css' function result: "+t+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(n)+t[i+1],t[0]);return new o(i,t,n)},a=(n,i)=>{if(e)n.adoptedStyleSheets=i.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet);else for(const e of i){const i=document.createElement("style"),o=t.litNonce;void 0!==o&&i.setAttribute("nonce",o),i.textContent=e.cssText,n.appendChild(i)}},s=e?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const n of t.cssRules)e+=n.cssText;return(t=>new o("string"==typeof t?t:t+"",void 0,n))(e)})(t):t,{is:c,defineProperty:l,getOwnPropertyDescriptor:u,getOwnPropertyNames:d,getOwnPropertySymbols:f,getPrototypeOf:h}=Object,p=globalThis,m=p.trustedTypes,v=m?m.emptyScript:"",y=p.reactiveElementPolyfillSupport,b=(t,e)=>t,_={toAttribute(t,e){switch(e){case Boolean:t=t?v:null;break;case Object:case Array:t=null==t?t:JSON.stringify(t)}return t},fromAttribute(t,e){let n=t;switch(e){case Boolean:n=null!==t;break;case Number:n=null===t?null:Number(t);break;case Object:case Array:try{n=JSON.parse(t)}catch(t){n=null}}return n}},g=(t,e)=>!c(t,e),w={attribute:!0,type:String,converter:_,reflect:!1,useDefault:!1,hasChanged:g};Symbol.metadata??=Symbol("metadata"),p.litPropertyMetadata??=new WeakMap;class A extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,e=w){if(e.state&&(e.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(t)&&((e=Object.create(e)).wrapped=!0),this.elementProperties.set(t,e),!e.noAccessor){const n=Symbol(),i=this.getPropertyDescriptor(t,n,e);void 0!==i&&l(this.prototype,t,i)}}static getPropertyDescriptor(t,e,n){const{get:i,set:o}=u(this.prototype,t)??{get(){return this[e]},set(t){this[e]=t}};return{get:i,set(e){const r=i?.call(this);o?.call(this,e),this.requestUpdate(t,r,n)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??w}static _$Ei(){if(this.hasOwnProperty(b("elementProperties")))return;const t=h(this);t.finalize(),void 0!==t.l&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(b("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(b("properties"))){const t=this.properties,e=[...d(t),...f(t)];for(const n of e)this.createProperty(n,t[n])}const t=this[Symbol.metadata];if(null!==t){const e=litPropertyMetadata.get(t);if(void 0!==e)for(const[t,n]of e)this.elementProperties.set(t,n)}this._$Eh=new Map;for(const[t,e]of this.elementProperties){const n=this._$Eu(t,e);void 0!==n&&this._$Eh.set(n,t)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(t){const e=[];if(Array.isArray(t)){const n=new Set(t.flat(1/0).reverse());for(const t of n)e.unshift(s(t))}else void 0!==t&&e.push(s(t));return e}static _$Eu(t,e){const n=e.attribute;return!1===n?void 0:"string"==typeof n?n:"string"==typeof t?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(t=>t(this))}addController(t){(this._$EO??=new Set).add(t),void 0!==this.renderRoot&&this.isConnected&&t.hostConnected?.()}removeController(t){this._$EO?.delete(t)}_$E_(){const t=new Map,e=this.constructor.elementProperties;for(const n of e.keys())this.hasOwnProperty(n)&&(t.set(n,this[n]),delete this[n]);t.size>0&&(this._$Ep=t)}createRenderRoot(){const t=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return a(t,this.constructor.elementStyles),t}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(t=>t.hostConnected?.())}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach(t=>t.hostDisconnected?.())}attributeChangedCallback(t,e,n){this._$AK(t,n)}_$ET(t,e){const n=this.constructor.elementProperties.get(t),i=this.constructor._$Eu(t,n);if(void 0!==i&&!0===n.reflect){const o=(void 0!==n.converter?.toAttribute?n.converter:_).toAttribute(e,n.type);this._$Em=t,null==o?this.removeAttribute(i):this.setAttribute(i,o),this._$Em=null}}_$AK(t,e){const n=this.constructor,i=n._$Eh.get(t);if(void 0!==i&&this._$Em!==i){const t=n.getPropertyOptions(i),o="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==t.converter?.fromAttribute?t.converter:_;this._$Em=i;const r=o.fromAttribute(e,t.type);this[i]=r??this._$Ej?.get(i)??r,this._$Em=null}}requestUpdate(t,e,n,i=!1,o){if(void 0!==t){const r=this.constructor;if(!1===i&&(o=this[t]),n??=r.getPropertyOptions(t),!((n.hasChanged??g)(o,e)||n.useDefault&&n.reflect&&o===this._$Ej?.get(t)&&!this.hasAttribute(r._$Eu(t,n))))return;this.C(t,e,n)}!1===this.isUpdatePending&&(this._$ES=this._$EP())}C(t,e,{useDefault:n,reflect:i,wrapped:o},r){n&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,r??e??this[t]),!0!==o||void 0!==r)||(this._$AL.has(t)||(this.hasUpdated||n||(e=void 0),this._$AL.set(t,e)),!0===i&&this._$Em!==t&&(this._$Eq??=new Set).add(t))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[t,e]of this._$Ep)this[t]=e;this._$Ep=void 0}const t=this.constructor.elementProperties;if(t.size>0)for(const[e,n]of t){const{wrapped:t}=n,i=this[e];!0!==t||this._$AL.has(e)||void 0===i||this.C(e,void 0,n,i)}}let t=!1;const e=this._$AL;try{t=this.shouldUpdate(e),t?(this.willUpdate(e),this._$EO?.forEach(t=>t.hostUpdate?.()),this.update(e)):this._$EM()}catch(e){throw t=!1,this._$EM(),e}t&&this._$AE(e)}willUpdate(t){}_$AE(t){this._$EO?.forEach(t=>t.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return!0}update(t){this._$Eq&&=this._$Eq.forEach(t=>this._$ET(t,this[t])),this._$EM()}updated(t){}firstUpdated(t){}}A.elementStyles=[],A.shadowRootOptions={mode:"open"},A[b("elementProperties")]=new Map,A[b("finalized")]=new Map,y?.({ReactiveElement:A}),(p.reactiveElementVersions??=[]).push("2.1.2");const $=globalThis,S=t=>t,O=$.trustedTypes,x=O?O.createPolicy("lit-html",{createHTML:t=>t}):void 0,E="$lit$",C=`lit$${Math.random().toFixed(9).slice(2)}$`,j="?"+C,k=`<${j}>`,P=document,T=()=>P.createComment(""),M=t=>null===t||"object"!=typeof t&&"function"!=typeof t,I=Array.isArray,H=t=>I(t)||"function"==typeof t?.[Symbol.iterator],F="[ \t\n\f\r]",D=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,R=/-->/g,N=/>/g,U=RegExp(`>|${F}(?:([^\\s"'>=/]+)(${F}*=${F}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),L=/'/g,V=/"/g,z=/^(?:script|style|textarea|title)$/i,B=t=>(e,...n)=>({_$litType$:t,strings:e,values:n}),W=B(1),Z=(B(2),B(3),Symbol.for("lit-noChange")),q=Symbol.for("lit-nothing"),J=new WeakMap,G=P.createTreeWalker(P,129);function K(t,e){if(!I(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==x?x.createHTML(e):e}const Y=(t,e)=>{const n=t.length-1,i=[];let o,r=2===e?"":3===e?"":"",a=D;for(let e=0;e"===c[0]?(a=o??D,l=-1):void 0===c[1]?l=-2:(l=a.lastIndex-c[2].length,s=c[1],a=void 0===c[3]?U:'"'===c[3]?V:L):a===V||a===L?a=U:a===R||a===N?a=D:(a=U,o=void 0);const d=a===U&&t[e+1].startsWith("/>")?" ":"";r+=a===D?n+k:l>=0?(i.push(s),n.slice(0,l)+E+n.slice(l)+C+d):n+C+(-2===l?e:d)}return[K(t,r+(t[n]||"")+(2===e?"":3===e?"":"")),i]};class Q{constructor({strings:t,_$litType$:e},n){let i;this.parts=[];let o=0,r=0;const a=t.length-1,s=this.parts,[c,l]=Y(t,e);if(this.el=Q.createElement(c,n),G.currentNode=this.el.content,2===e||3===e){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes)}for(;null!==(i=G.nextNode())&&s.length0){i.textContent=O?O.emptyScript:"";for(let n=0;n2||""!==n[0]||""!==n[1]?(this._$AH=Array(n.length-1).fill(new String),this.strings=n):this._$AH=q}_$AI(t,e=this,n,i){const o=this.strings;let r=!1;if(void 0===o)t=X(this,t,e,0),r=!M(t)||t!==this._$AH&&t!==Z,r&&(this._$AH=t);else{const i=t;let a,s;for(t=o[0],a=0;a{const i=n?.renderBefore??e;let o=i._$litPart$;if(void 0===o){const t=n?.renderBefore??null;i._$litPart$=o=new et(e.insertBefore(T(),t),t,void 0,n??{})}return o._$AI(t),o})(e,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return Z}}ut._$litElement$=!0,ut.finalized=!0,lt.litElementHydrateSupport?.({LitElement:ut});const dt=lt.litElementPolyfillSupport;dt?.({LitElement:ut}),(lt.litElementVersions??=[]).push("4.2.2");var ft=["unavailable","unknown"],ht="last-changed",pt="last-updated",mt=["relative","total","date","time","datetime"],vt=["entity-id","last-changed","last-updated","last-triggered","position","tilt-position","brightness"],yt=function(t){return t<10?"0".concat(t):t};function bt(t){var e=Math.floor(t/3600),n=Math.floor(t%3600/60),i=Math.floor(t%3600%60);return e>0?"".concat(e,":").concat(yt(n),":").concat(yt(i)):n>0?"".concat(n,":").concat(yt(i)):i>0?""+i:null}function _t(t){return _t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},_t(t)}function gt(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);e&&(i=i.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),n.push.apply(n,i)}return n}function wt(t,e,n){return(e=function(t){var e=function(t){if("object"!=_t(t)||!t)return t;var e=t[Symbol.toPrimitive];if(void 0!==e){var n=e.call(t,"string");if("object"!=_t(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(t)}(t);return"symbol"==_t(e)?e:e+""}(e))in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var At=function(t,e,n){var i=e?function(t){switch(t.number_format){case"comma_decimal":return["en-US","en"];case"decimal_comma":return["de","es","it"];case"space_comma":return["fr","sv","cs"];case"system":return;default:return t.language}}(e):void 0;if(Number.isNaN=Number.isNaN||function t(e){return"number"==typeof e&&t(e)},"none"!==(null==e?void 0:e.number_format)&&!Number.isNaN(Number(t))&&Intl)try{return new Intl.NumberFormat(i,$t(t,n)).format(Number(t))}catch(e){return console.error(e),new Intl.NumberFormat(void 0,$t(t,n)).format(Number(t))}return"string"==typeof t?t:"".concat(function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:2;return Math.round(t*Math.pow(10,e))/Math.pow(10,e)}(t,null==n?void 0:n.maximumFractionDigits).toString()).concat("currency"===(null==n?void 0:n.style)?" ".concat(n.currency):"")},$t=function(t,e){var n=function(t){for(var e=1;e-1?t.split(".")[1].length:0;n.minimumFractionDigits=i,n.maximumFractionDigits=i}return n};function St(t){return St="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},St(t)}var Ot=function(t){return"object"===St(t)&&!Array.isArray(t)&&!!t},xt=function(t,e,n){var i=new Event(e,{bubbles:!0,composed:!0});i.detail=n,t.dispatchEvent(i)},Et=function(t){return!t||ft.includes(t.state)},Ct=function(t,e,n){if(function(t,e){return e.hide_unavailable&&(Et(t)||e.attribute&&![ht,pt].includes(e.attribute)&&void 0===t.attributes[e.attribute])}(t,e))return!0;if(void 0===e.hide_if)return!1;var i;if(Ot(e.hide_if)&&(e.hide_if.entity||e.hide_if.attribute)){var o=e.hide_if.entity?null==n?void 0:n.states[e.hide_if.entity]:t;i=e.hide_if.attribute?null==o?void 0:o.attributes[e.hide_if.attribute]:null==o?void 0:o.state}else i=e.attribute?t.attributes[e.attribute]:t.state;var r=[];if(Ot(e.hide_if)){if(e.hide_if.below&&ie.hide_if.above)return!0;e.hide_if.value&&(r=r.concat(e.hide_if.value))}else r=r.concat(e.hide_if);return r.some(function(t){return"number"==typeof t?t===+i:t===i})},jt=["formatEntityName","formatEntityState","formatEntityAttributeValue"];function kt(t){return kt="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},kt(t)}function Pt(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);e&&(i=i.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),n.push.apply(n,i)}return n}function Tt(t){for(var e=1;et.length)&&(e=t.length);for(var n=0,i=Array(e);n1&&a.every(function(t){return Vt.test(t)})){var s=o??0;return!isNaN(parseFloat(s))&&isFinite(s)?function(t,e,n,i){var o,r,a=parseFloat(e),s=Rt(e),c=!1,l=function(t){c||(s=void 0,o=t)},u=function(t){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(!e){if(Array.isArray(t)||(e=It(t))){e&&(t=e);var n=0,i=function(){};return{s:i,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,r=!0,a=!1;return{s:function(){e=e.call(t)},n:function(){var t=e.next();return r=t.done,t},e:function(t){a=!0,o=t},f:function(){try{r||null==e.return||e.return()}finally{if(a)throw o}}}}(t);try{for(u.s();!(r=u.n()).done;){var d=r.value,f=Ut.exec(d);if(f&&"precision"===f[1])s=parseInt(f[2],10),o=void 0,c=!0;else if(f)a/={kilo:1e3,mega:1e6,milli:.001}[f[1]],void 0!==f[2]?(s=parseInt(f[2],10),o=void 0,c=!0):l(2);else switch(d){case"brightness":a=Math.round(a/255*100),n="%",l(0);break;case"percent":a*=100,n="%",l(2);break;case"invert":a=-a;break;case"position":a=100-a;break;case"celsius_to_fahrenheit":a=1.8*a+32,l(0);break;case"fahrenheit_to_celsius":a=5*(a-32)/9,l(1)}}}catch(t){u.e(t)}finally{u.f()}return"".concat(At(a,i,void 0!==s?{minimumFractionDigits:s,maximumFractionDigits:s}:void 0!==o?{maximumFractionDigits:o}:void 0)).concat(n?" ".concat(n):"")}(a,s,r,t.locale):"".concat(s).concat(r?" ".concat(r):"")}if(n.format&&!function(t){return Nt.some(function(e){return null==t?void 0:t.startsWith(e)})&&!Lt(t)}(n.format)){if(null==o&&(o=zt.includes(n.format)?"":0),zt.includes(n.format))return"".concat(function(t,e){switch(t){case"upper":return e.toUpperCase();case"lower":return e.toLowerCase();case"capitalize":return e.charAt(0).toUpperCase()+e.slice(1);case"title":return e.split(/(\s+)/).map(function(t){return t.charAt(0).toUpperCase()+t.slice(1)}).join("")}}(n.format,String(o))).concat(r?" ".concat(r):"");if(isNaN(parseFloat(o))||!isFinite(o));else if("brightness"===n.format)o=Math.round(o/255*100),r="%";else if("percent"===n.format)o=At(100*o,t.locale,{maximumFractionDigits:2}),r="%";else if("duration"===n.format){var c;o=null!==(c=bt(o))&&void 0!==c?c:"0",r=void 0}else if("duration-m"===n.format){var l;o=null!==(l=bt(o/1e3))&&void 0!==l?l:"0",r=void 0}else if("duration-h"===n.format){var u;o=null!==(u=bt(3600*o))&&void 0!==u?u:"0",r=void 0}else if(Lt(n.format)){var d=function(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){var n=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=n){var i,o,r,a,s=[],c=!0,l=!1;try{if(r=(n=n.call(t)).next,0===e){if(Object(n)!==n)return;c=!1}else for(;!(c=(i=r.call(n)).done)&&(s.push(i.value),s.length!==e);c=!0);}catch(t){l=!0,o=t}finally{try{if(!c&&null!=n.return&&(a=n.return(),Object(a)!==a))return}finally{if(l)throw o}}return s}}(t,e)||It(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}(Lt(n.format),3),f=d[1],h=d[2];if("precision"===f){var p=parseInt(h,10);o=At(parseFloat(o),t.locale,{minimumFractionDigits:p,maximumFractionDigits:p})}else o=function(t,e,n,i){if(void 0===n)return At(t/e,i,{maximumFractionDigits:2});var o=parseInt(n,10);return At(t/e,i,{minimumFractionDigits:o,maximumFractionDigits:o})}(o,{kilo:1e3,mega:1e6,milli:.001}[f],h,t.locale)}else if("invert"===n.format){var m=Rt(o);o=At(o-2*o,t.locale,void 0!==m?{minimumFractionDigits:m,maximumFractionDigits:m}:void 0)}else if("position"===n.format){var v=Rt(o);o=At(100-o,t.locale,void 0!==v?{minimumFractionDigits:v,maximumFractionDigits:v}:void 0)}else"celsius_to_fahrenheit"===n.format?o=At(1.8*o+32,t.locale,{maximumFractionDigits:0}):"fahrenheit_to_celsius"===n.format&&(o=At(5*(o-32)/9,t.locale,{maximumFractionDigits:1}));return"".concat(o).concat(r?" ".concat(r):"")}var y=Tt(Tt({},e),{},{attributes:Tt(Tt({},e.attributes),{},{unit_of_measurement:r})});return n.attribute?t.formatEntityAttributeValue(y,n.attribute):t.formatEntityState(y)},Jt=function(t){return Ot(null==t?void 0:t.styles)?Object.keys(t.styles).map(function(e){return"".concat(e,": ").concat(t.styles[e],";")}).join(""):""};class Gt{constructor(t){}get _$AU(){return this._$AM._$AU}_$AT(t,e,n){this._$Ct=t,this._$AM=e,this._$Ci=n}_$AS(t,e){return this.update(t,e)}update(t,e){return this.render(...e)}}const{I:Kt}=st,Yt={},Qt=(t=>(...e)=>({_$litDirective$:t,values:e}))(class extends Gt{constructor(){super(...arguments),this.key=q}render(t,e){return this.key=t,e}update(t,[e,n]){return e!==this.key&&(((t,e=Yt)=>{t._$AH=e})(t),this.key=e),n}});var Xt,te,ee,ne,ie,oe,re,ae,se,ce,le,ue,de,fe,he,pe,me,ve="__custom__",ye=[{value:"",label:"No format"},{value:"brightness",label:"Brightness (0-255 → %)"},{value:"percent",label:"Percent (value × 100 → x %)"},{value:"duration",label:"Duration (seconds → h:mm:ss)"},{value:"duration-m",label:"Duration (milliseconds)"},{value:"duration-h",label:"Duration (hours)"},{value:"precision0",label:"Precision 0 decimals"},{value:"precision1",label:"Precision 1 decimal"},{value:"precision2",label:"Precision 2 decimals"},{value:"precision3",label:"Precision 3 decimals"},{value:"kilo",label:"Kilo (value / 1,000)"},{value:"mega",label:"Mega (value / 1,000,000)"},{value:"milli",label:"Milli (value × 1,000)"},{value:"invert",label:"Invert (value × -1)"},{value:"position",label:"Position (100 - value)"},{value:"celsius_to_fahrenheit",label:"°C → °F"},{value:"fahrenheit_to_celsius",label:"°F → °C"},{value:"upper",label:"Text: UPPERCASE"},{value:"lower",label:"Text: lowercase"},{value:"capitalize",label:"Text: Capitalize first letter"},{value:"title",label:"Text: Title Case"},{value:"relative",label:"Timestamp: relative"},{value:"total",label:"Timestamp: total"},{value:"date",label:"Timestamp: date"},{value:"time",label:"Timestamp: time"},{value:"datetime",label:"Timestamp: date + time"},{value:ve,label:"Custom…"}],be=new Set(ye.map(function(t){return t.value}).filter(function(t){return t&&t!==ve})),_e=[{name:"entity",required:!0,selector:{entity:{}}},{type:"grid",schema:[{name:"name",selector:{text:{}}},{name:"attribute",selector:{text:{}}}]},{type:"grid",schema:[{name:"unit",selector:{text:{}}},{name:"icon",selector:{icon:{}}}]},{name:"icon_color",selector:{text:{}}},{type:"grid",schema:[{name:"show_state",default:!0,selector:{boolean:{}}},{name:"state_color",selector:{boolean:{}}}]},{type:"grid",schema:[{name:"toggle",selector:{boolean:{}}},{name:"column",selector:{boolean:{}}}]},{type:"grid",schema:[{name:"show_state_first",selector:{boolean:{}}},{name:"hide_unavailable",selector:{boolean:{}}}]},{name:"state_header",selector:{text:{}}},{name:"image",selector:{text:{}}},{name:"format",selector:{select:{mode:"dropdown",options:ye}}}],ge=[{name:"tap_action",selector:{ui_action:{default_action:"more-info"}}},{name:"hold_action",selector:{ui_action:{default_action:"none"}}},{name:"double_tap_action",selector:{ui_action:{default_action:"none"}}}],we=[{name:"entity",selector:{entity:{}}},{type:"grid",schema:[{name:"name",selector:{text:{}}},{name:"attribute",selector:{text:{}}}]},{type:"grid",schema:[{name:"unit",selector:{text:{}}},{name:"icon",selector:{icon:{}}}]},{name:"icon_color",selector:{text:{}}},{type:"grid",schema:[{name:"state_color",selector:{boolean:{}}},{name:"toggle",selector:{boolean:{}}}]},{name:"hide_unavailable",selector:{boolean:{}}},{name:"format",selector:{select:{mode:"dropdown",options:ye}}}],Ae={entity:"Entity",attribute:"Attribute",name:"Name override",unit:"Unit",icon:"Icon",icon_color:"Icon color (CSS value, e.g. red, #ff0000, var(--my-color))",image:"Image URL",format:"Format",show_state:"Show main entity state",show_state_first:"State before entities",state_header:"State header label",state_color:"State color",column:"Column layout",toggle:"Show as toggle",hide_unavailable:"Hide if unavailable",tap_action:"Tap action",hold_action:"Hold action",double_tap_action:"Double-tap action"};function $e(t,e){return e||(e=t.slice(0)),Object.freeze(Object.defineProperties(t,{raw:{value:Object.freeze(e)}}))}function Se(t){return function(t){if(Array.isArray(t))return Fe(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||He(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function Oe(t,e){for(var n=0;n=t.length?{done:!0}:{done:!1,value:t[i++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,a=!0,s=!1;return{s:function(){n=n.call(t)},n:function(){var t=n.next();return a=t.done,t},e:function(t){s=!0,r=t},f:function(){try{a||null==n.return||n.return()}finally{if(s)throw r}}}}function Ie(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){var n=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=n){var i,o,r,a,s=[],c=!0,l=!1;try{if(r=(n=n.call(t)).next,0===e){if(Object(n)!==n)return;c=!1}else for(;!(c=(i=r.call(n)).done)&&(s.push(i.value),s.length!==e);c=!0);}catch(t){l=!0,o=t}finally{try{if(!c&&null!=n.return&&(a=n.return(),Object(a)!==a))return}finally{if(l)throw o}}return s}}(t,e)||He(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function He(t,e){if(t){if("string"==typeof t)return Fe(t,e);var n={}.toString.call(t).slice(8,-1);return"Object"===n&&t.constructor&&(n=t.constructor.name),"Map"===n||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Fe(t,e):void 0}}function Fe(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,i=Array(e);ni.length&&(t._selectedTab=i.length),t._keys.clear(),t._updateConfig({entities:i.length?i:void 0})}}),Pe(t,"_moveAdditional",function(e,n){var i;if(t._config){var o=Se(null!==(i=t._config.entities)&&void 0!==i?i:[]),r=e+n;if(!(r<0||r>=o.length)){var a=[o[r],o[e]];o[e]=a[0],o[r]=a[1],t._selectedTab=r+1,t._keys.clear(),t._updateConfig({entities:o})}}}),Pe(t,"_copyAdditional",function(e){var n,i=null===(n=t._config)||void 0===n||null===(n=n.entities)||void 0===n?void 0:n[e];null!=i&&t._writeClipboard("string"==typeof i?{entity:i}:ke({},i))}),Pe(t,"_cutAdditional",function(e){t._copyAdditional(e),t._deleteAdditional(e)}),Pe(t,"_copyMainAsTemplate",function(){if(t._config){var e,n={},i=Me(pn);try{for(i.s();!(e=i.n()).done;){var o=e.value,r=t._config[o];void 0!==r&&(n[o]=r)}}catch(t){i.e(t)}finally{i.f()}t._writeClipboard(n)}}),Pe(t,"_pasteEntity",function(){var e;if(t._config){var n=t._readClipboard();if(n){var i=[].concat(Se(null!==(e=t._config.entities)&&void 0!==e?e:[]),[n]);t._selectedTab=i.length,t._keys.clear(),t._updateConfig({entities:i})}}}),Pe(t,"_secondaryModeChanged",function(e){if(t._config){var n=e.detail.value.mode;if(n!==t._secondaryInfoMode()){var i;switch(n){case"none":i=void 0;break;case"text":i="";break;case"generic":i="last-changed";break;case"entity":i={entity:t._config.entity}}t._updateConfig({secondary_info:i})}}}),Pe(t,"_secondaryTextChanged",function(e){t._updateConfig({secondary_info:e.detail.value.text})}),Pe(t,"_secondaryTokenChanged",function(e){t._updateConfig({secondary_info:e.detail.value.token})}),Pe(t,"_secondaryEntityChanged",function(e){var n,i=Ot(null===(n=t._config)||void 0===n?void 0:n.secondary_info)?t._config.secondary_info.format:void 0;t._updateConfig({secondary_info:t._formatFromForm("secondary",fn(e.detail.value),i)})}),t._selectedTab=0,t._entitiesExpanded=!0,t._stateIconRowsMain=[],t._stateIconRowsAdditional=new Map,t._customFormatScopes=new Set,t}return function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),Object.defineProperty(t,"prototype",{writable:!1}),e&&Ce(t,e)}(e,t),function(t,e,n){return e&&Oe(t.prototype,e),n&&Oe(t,n),Object.defineProperty(t,"prototype",{writable:!1}),t}(e,[{key:"setConfig",value:function(t){var e,n,i,o=this;this._config=t;var r,a=null!==(e=null===(n=t.entities)||void 0===n?void 0:n.length)&&void 0!==e?e:0;this._selectedTab>a&&(this._selectedTab=a),this._clipboardEntity=this._readClipboard(),this._stateIconRowsMatch(this._stateIconRowsMain,t.state_icon)||(this._stateIconRowsMain=Object.entries(null!==(r=t.state_icon)&&void 0!==r?r:{}));var s=new Map;null===(i=t.entities)||void 0===i||i.forEach(function(t,e){var n=Ot(t)?t.state_icon:void 0,i=o._stateIconRowsAdditional.get(e);i&&o._stateIconRowsMatch(i,n)?s.set(e,i):n&&s.set(e,Object.entries(n))}),this._stateIconRowsAdditional=s}},{key:"_stateIconRowsMatch",value:function(t,e){var n,i={},o=Me(t);try{for(o.s();!(n=o.n()).done;){var r=Ie(n.value,2),a=r[0],s=r[1];a.trim()&&s.trim()&&(i[a.trim()]=s.trim())}}catch(t){o.e(t)}finally{o.f()}var c=null!=e?e:{},l=Object.keys(i);return l.length===Object.keys(c).length&&l.every(function(t){return i[t]===c[t]})}},{key:"_readClipboard",value:function(){try{var t=sessionStorage.getItem(hn);if(!t)return;var e=JSON.parse(t);if(e&&"object"===De(e))return e}catch(t){}}},{key:"_writeClipboard",value:function(t){try{sessionStorage.setItem(hn,JSON.stringify(t)),this._clipboardEntity=t}catch(t){}}},{key:"_hasNativeTabs",get:function(){return!!customElements.get("ha-tab-group")&&!!customElements.get("ha-tab-group-tab")}},{key:"render",value:function(){return this.hass&&this._config?W(Xt||(Xt=$e(["\n \n ",'\n \n\n \n "])),"Entities",this._entitiesExpanded,this._onEntitiesExpandedChanged,this._renderEntitiesPanel(),"4.7.0","2026-07-08T23:41:43.781Z"):q}},{key:"_isCustomFormat",value:function(t,e){return this._customFormatScopes.has(t)||!!e&&!be.has(e)}},{key:"_setCustomFormatScope",value:function(t,e){if(e!==this._customFormatScopes.has(t)){var n=new Set(this._customFormatScopes);e?n.add(t):n.delete(t),this._customFormatScopes=n}}},{key:"_formatToForm",value:function(t,e){return this._isCustomFormat(t,e.format)?ke(ke({},e),{},{format:ve}):e}},{key:"_formatFromForm",value:function(t,e,n){if(e.format===ve){this._setCustomFormatScope(t,!0);var i=ke({},e);return void 0!==n?i.format=n:delete i.format,i}return this._setCustomFormatScope(t,!1),e}},{key:"_renderCustomFormatField",value:function(t,e,n){return this._isCustomFormat(t,e)?W(te||(te=$e(["\n \n "])),this.hass,{custom_format:null!=e?e:""},[{name:"custom_format",selector:{text:{}}}],function(){return"Custom format (e.g. invert, precision3)"},function(t){var e,i=(null!==(e=t.detail.value.custom_format)&&void 0!==e?e:"").trim();n(i||void 0)}):q}},{key:"_keyFor",value:function(t){return this._keys.has(t)||this._keys.set(t,"".concat(t,"-").concat(Math.random().toString(36).slice(2,10))),this._keys.get(t)}},{key:"_renderEntitiesPanel",value:function(){var t,e,n=this,i=null!==(t=null===(e=this._config)||void 0===e?void 0:e.entities)&&void 0!==t?t:[],o=Math.min(this._selectedTab,i.length);return W(ee||(ee=$e(['\n
\n
\n ','\n \n
\n\n
\n ',"\n
\n
\n "])),this._hasNativeTabs?W(ne||(ne=$e(['\n \n \n \n \n \n
\n
\n \n \n ','\n \n ','\n \n ',"\n \n "])),"Copy main as template",nn,this._copyMainAsTemplate,"Paste as new entity",on,!this._clipboardEntity,this._pasteEntity,this.hass,this._mainFormData(),_e,this._computeLabel,this._mainValueChanged,this._renderCustomFormatField("main",null===(t=this._config)||void 0===t?void 0:t.format,function(t){return n._updateConfig({format:t})}),this.hass,this._mainFormData(),ge,this._computeLabel,this._mainValueChanged,this._renderSecondaryInfoBlock(),this._renderStateIconRows("main"),this._renderStylesBlock(null===(e=this._config)||void 0===e?void 0:e.styles,function(t){return n._mainStylesChanged(t)}))}},{key:"_renderStylesBlock",value:function(t,e){return W(se||(se=$e(['\n \n ','\n \n \n \n \n
\n
\n \n \n ','\n \n ',"\n \n "])),"Move before","M15.41,16.58L10.83,12L15.41,7.41L14,6L8,12L14,18L15.41,16.58Z",0===t,function(){return i._moveAdditional(t,-1)},"Move after","M8.59,16.58L13.17,12L8.59,7.41L10,6L16,12L10,18L8.59,16.58Z",t===a,function(){return i._moveAdditional(t,1)},"Copy entity",nn,function(){return i._copyAdditional(t)},"Cut entity","M19,3L13,9L15,11L22,4V3M12,12.5A0.5,0.5 0 0,1 11.5,12A0.5,0.5 0 0,1 12,11.5A0.5,0.5 0 0,1 12.5,12A0.5,0.5 0 0,1 12,12.5M6,20A2,2 0 0,1 4,18C4,16.89 4.9,16 6,16A2,2 0 0,1 8,18C8,19.11 7.1,20 6,20M6,8A2,2 0 0,1 4,6C4,4.89 4.9,4 6,4A2,2 0 0,1 8,6C8,7.11 7.1,8 6,8M9.64,7.64C9.87,7.14 10,6.59 10,6A4,4 0 0,0 6,2A4,4 0 0,0 2,6A4,4 0 0,0 6,10C6.59,10 7.14,9.87 7.64,9.64L10,12L7.64,14.36C7.14,14.13 6.59,14 6,14A4,4 0 0,0 2,18A4,4 0 0,0 6,22A4,4 0 0,0 10,18C10,17.41 9.87,16.86 9.64,16.36L12,14L19,21H22V20L9.64,7.64Z",function(){return i._cutAdditional(t)},"Paste from clipboard",on,!this._clipboardEntity,this._pasteEntity,"Delete entity",en,function(){return i._deleteAdditional(t)},this.hass,this._formatToForm("sub-".concat(t),dn(r)),we,this._computeLabel,function(e){return i._additionalValueChanged(e,t)},this._renderCustomFormatField("sub-".concat(t),r.format,function(e){return i._setAdditionalFormat(t,e)}),this.hass,this._formatToForm("sub-".concat(t),dn(r)),ge,this._computeLabel,function(e){return i._additionalValueChanged(e,t)},this._renderStateIconRows(t),this._renderStylesBlock(r.styles,function(e){return i._additionalStylesChanged(e,t)}))}},{key:"_mainFormData",value:function(){return this._formatToForm("main",dn(ke({show_state:!0},this._config)))}},{key:"_setAdditionalFormat",value:function(t,e){var n;if(this._config){var i=Se(null!==(n=this._config.entities)&&void 0!==n?n:[]),o=i[t],r="string"==typeof o?{entity:o}:ke({},o);e?r.format=e:delete r.format,i[t]=r,this._updateConfig({entities:i})}}},{key:"_secondaryInfoMode",value:function(){var t,e=null===(t=this._config)||void 0===t?void 0:t.secondary_info;return null==e?"none":"object"===De(e)?"entity":vt.includes(e)?"generic":"text"}},{key:"_renderSecondaryInfoBlock",value:function(){var t,e=this,n=this._secondaryInfoMode(),i=null===(t=this._config)||void 0===t?void 0:t.secondary_info;return W(de||(de=$e(["\n
\n \n ","\n ","\n ","\n
\n "])),this.hass,{mode:n},rn,function(){return"Mode"},this._secondaryModeChanged,"text"===n?W(fe||(fe=$e(['
\n \n \n \n
\n ',"\n
\n "])),Bt(this.config.icon_color),this._hass,n,this.renderSecondaryInfo(),!0,this.config.column?"entities-column":"entities-row",this.config.show_state_first?W(Ue||(Ue=yn(["","",""])),this.renderMainEntity(),this.entities.map(function(e,n){return t.renderEntity(e.stateObj,e,n)})):W(Le||(Le=yn(["","",""])),this.entities.map(function(e,n){return t.renderEntity(e.stateObj,e,n)}),this.renderMainEntity()))}},{key:"renderSecondaryInfo",value:function(){if(!this.config.secondary_info||"string"==typeof(t=this.config.secondary_info)&&vt.includes(t)||Ct(this.info,this.config.secondary_info,this._hass))return null;var t;if("string"==typeof this.config.secondary_info)return W(Ve||(Ve=yn(["",""])),this.config.secondary_info);var e=Zt(this.info,this.config.secondary_info);return W(ze||(ze=yn([""," ",""])),e,this.renderValue(this.info,this.config.secondary_info))}},{key:"renderMainEntity",value:function(){if(!1===this.config.show_state)return null;if(Ct(this.stateObj,this.config,this._hass))return this.config.default?W(Be||(Be=yn(['
\n ',"\n
","
\n
"])),Jt(this.config),this.config.state_header&&W(We||(We=yn(["",""])),this.config.state_header),this.config.default):null;var t=this.getGestureHandlers("main",this.config.entity,this.config);return W(Ze||(Ze=yn(['\n ',"\n
","
\n
"])),Jt(this.config),null==t?void 0:t.onDown,null==t?void 0:t.onUp,null==t?void 0:t.onCancel,xn,xn,xn,xn,xn,xn,this.config.state_header&&W(qe||(qe=yn(["",""])),this.config.state_header),this.renderValue(this.stateObj,this.config))}},{key:"renderEntity",value:function(t,e,n){if(!t||Ct(t,e,this._hass))return e.default?W(Je||(Je=yn(['
\n ',"\n
","
\n
"])),Jt(e),e.name,e.default):null;var i=this.getGestureHandlers("sub-".concat(n),t.entity_id,e);return W(Ge||(Ge=yn(['\n ',"\n
\n ","\n
\n "])),Jt(e),null==i?void 0:i.onDown,null==i?void 0:i.onUp,null==i?void 0:i.onCancel,xn,xn,xn,xn,xn,xn,Zt(t,e),e.icon||Ot(e.state_icon)?this.renderIcon(t,e):this.renderValue(t,e))}},{key:"renderValue",value:function(t,e){if(!0===e.toggle)return W(Ke||(Ke=yn([''])),t,this._hass);var n;if(e.attribute&&[ht,pt].includes(e.attribute))return W(Ye||(Ye=yn([""])),this._hass,t[null===(n=e.attribute)||void 0===n?void 0:n.replace("-","_")]);if(e.format&&mt.includes(e.format)){var i,o=e.attribute?null!==(i=t.attributes[e.attribute])&&void 0!==i?i:t[e.attribute]:t.state,r=new Date(o);return r instanceof Date&&!isNaN(r.getTime())?W(Qe||(Qe=yn([""])),this._hass,r,e.format):o}return qt(this._hass,t,e)}},{key:"renderIcon",value:function(t,e){var n,i=null!==(n=Wt(t,e))&&void 0!==n?n:!0===e.icon?t.attributes.icon||null:e.icon;return W(Xe||(Xe=yn([''])),Bt(e.icon_color),this._hass,t,i,e.state_color)}},{key:"renderWarning",value:function(){return W(tn||(tn=yn(["\n ","\n "])),this._hass.localize("ui.panel.lovelace.warning.entity_not_found","entity",this.config.entity))}},{key:"getGestureHandlers",value:function(t,e,n){var i,o,r,a,s,c,l,u=this;return!0===n.toggle?null:(this._actionHandlers.has(t)||this._actionHandlers.set(t,(i=function(t,i){return u.dispatchAction(e,n,t,i)},o={hasHold:!!n.hold_action,hasDoubleTap:!!n.double_tap_action},s=o.hasHold,c=o.hasDoubleTap,l=!1,{onDown:function(){l=!1,s&&(r=setTimeout(function(){l=!0},500))},onUp:function(){if(clearTimeout(r),l)return l=!1,void i(!0,!1);c?a?(clearTimeout(a),a=void 0,i(!1,!0)):a=setTimeout(function(){a=void 0,i(!1,!1)},250):i(!1,!1)},onCancel:function(){clearTimeout(r)}})),this._actionHandlers.get(t))}},{key:"dispatchAction",value:function(t,e,n,i){var o,r=i?e.double_tap_action:n?e.hold_action:null!==(o=e.tap_action)&&void 0!==o?o:{action:"more-info"};if(r&&"none"!==r.action){var a=i?"double_tap":n?"hold":"tap";xt(this,"hass-action",{config:gn({entity:r.entity||t},"".concat(a,"_action"),r),action:a})}}}],[{key:"getConfigElement",value:function(){return document.createElement("multiple-entity-row-editor")}},{key:"getStubConfig",value:function(t,e){var n,i,o=null!==(n=null!==(i=null==e?void 0:e.find(function(t){return t.startsWith("sensor.")}))&&void 0!==i?i:null==e?void 0:e[0])&&void 0!==n?n:"";return{entity:o}}},{key:"properties",get:function(){return{_hass:Object,config:Object,stateObj:Object}}},{key:"styles",get:function(){return r(Ft||(Ft=function(t,e){return e||(e=t.slice(0)),Object.freeze(Object.defineProperties(t,{raw:{value:Object.freeze(e)}}))}(["\n .icon-small {\n width: auto;\n }\n .entity {\n text-align: center;\n cursor: pointer;\n }\n .entity span {\n font-size: 10px;\n color: var(--multiple-entity-row-header-color, var(--secondary-text-color));\n }\n .entities-row {\n flex-direction: row;\n display: inline-flex;\n justify-content: space-between;\n align-items: center;\n }\n .entities-row .entity {\n margin-right: 16px;\n }\n .entities-row .entity:last-of-type {\n margin-right: 0;\n }\n .entities-column {\n flex-direction: column;\n display: flex;\n align-items: flex-end;\n justify-content: space-evenly;\n }\n .entities-column .entity div {\n display: inline-block;\n vertical-align: middle;\n }\n"])))}}])}(ut);customElements.define("multiple-entity-row",En),window.customCards=window.customCards||[],window.customCards.push({type:"multiple-entity-row",name:"Multiple Entity Row",description:"Show multiple entity states and attributes on a single entity row"})})(); \ No newline at end of file diff --git a/www/community/lovelace-multiple-entity-row/multiple-entity-row.js.gz b/www/community/lovelace-multiple-entity-row/multiple-entity-row.js.gz index f3fb1bf498585ac8cc870d0257820ebfba34e91e..4818e2e4f1df8171e598c72362f89fee75a276ca 100644 GIT binary patch literal 19518 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 mC_k&e;!^T!U#yD2|KB3sag_F5=9bJ) diff --git a/zigbee2mqtt/coordinator_backup.json b/zigbee2mqtt/coordinator_backup.json index 83fb9c4..f899ca4 100644 --- a/zigbee2mqtt/coordinator_backup.json +++ b/zigbee2mqtt/coordinator_backup.json @@ -4,7 +4,7 @@ "version": 1, "source": "zigbee-herdsman@10.6.1", "internal": { - "date": "2026-07-07T17:46:32.639Z", + "date": "2026-07-08T20:34:42.178Z", "znpVersion": 1 } }, @@ -25,7 +25,7 @@ "network_key": { "key": "0a7ed3caf6adb653119697df9d04ec25", "sequence_number": 0, - "frame_counter": 2037561 + "frame_counter": 2066839 }, "devices": [ { @@ -35,7 +35,7 @@ "link_key": { "key": "a59c7f704c547dca7033b287b04ffc4b", "rx_counter": 0, - "tx_counter": 661 + "tx_counter": 672 } }, { @@ -45,7 +45,7 @@ "link_key": { "key": "91fa9ab38f0a04fc102f357e78f61f7d", "rx_counter": 0, - "tx_counter": 638 + "tx_counter": 649 } }, { @@ -55,7 +55,7 @@ "link_key": { "key": "a59a9f9bbb354104241b4a3476c2bd1f", "rx_counter": 0, - "tx_counter": 638 + "tx_counter": 649 } }, { @@ -65,7 +65,7 @@ "link_key": { "key": "d6d47144ee36ca67791986b8f5b74bb2", "rx_counter": 0, - "tx_counter": 638 + "tx_counter": 649 } }, { @@ -75,7 +75,7 @@ "link_key": { "key": "9b47a21f8d33962956b05e040cb24386", "rx_counter": 0, - "tx_counter": 638 + "tx_counter": 649 } }, { @@ -85,7 +85,7 @@ "link_key": { "key": "3537b9fd0d00b2cdf8c045e68c816762", "rx_counter": 0, - "tx_counter": 702 + "tx_counter": 713 } }, { @@ -95,7 +95,7 @@ "link_key": { "key": "85676341f405baf92aaa94bdef843b2c", "rx_counter": 0, - "tx_counter": 605 + "tx_counter": 616 } }, { @@ -105,7 +105,7 @@ "link_key": { "key": "fea770704c547dca2b08bd87b04ffc4b", "rx_counter": 0, - "tx_counter": 627 + "tx_counter": 638 } }, { @@ -115,7 +115,7 @@ "link_key": { "key": "facb3a7e78f61f7d7b1e95b38f0a04fc", "rx_counter": 0, - "tx_counter": 627 + "tx_counter": 638 } }, { @@ -125,7 +125,7 @@ "link_key": { "key": "452689b8f5b74bb2eaeb7e44ee36ca67", "rx_counter": 0, - "tx_counter": 621 + "tx_counter": 632 } }, { @@ -135,15 +135,15 @@ "link_key": { "key": "89bd998438a05c117e418205b975f3dc", "rx_counter": 0, - "tx_counter": 0 + "tx_counter": 11 } }, { - "nwk_address": "2ff8", + "nwk_address": "ebf6", "ieee_address": "54ef4410014f65c1", "is_child": false, "link_key": { - "key": "7f9e4cb55d7697228385cd3488d95ad5", + "key": "f31d3943f0c6dacc5cd0cebfeb475b19", "rx_counter": 0, "tx_counter": 0 }