Skip to content
This repository has been archived by the owner on Aug 24, 2022. It is now read-only.

Commit

Permalink
Add service to select synchronized list.
Browse files Browse the repository at this point in the history
  • Loading branch information
vlebourl committed Nov 18, 2020
1 parent ff96b19 commit 071a91f
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 12 deletions.
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.vscode/settings.json
custom_components/shopping_list/__pycache__/bring.cpython-38.pyc
.vscode/
custom_components/shopping_list/__pycache__/
custom_components/shopping_list/scratch.py
venv/
Config/
33 changes: 28 additions & 5 deletions custom_components/shopping_list/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
"""Support to manage a shopping list."""
import asyncio
import logging
import uuid

import homeassistant.helpers.config_validation as cv
import voluptuous as vol
Expand All @@ -21,6 +19,7 @@
CONF_BRING_USERNAME = "bring_username"
CONF_BRING_PASSWORD = "bring_password"
CONF_BRING_LANGUAGE = "bring_language"
CONF_BRING_LIST_NAME = "bring_list_name"

_LOGGER = logging.getLogger(__name__)
CONFIG_SCHEMA = vol.Schema(
Expand All @@ -29,19 +28,23 @@
vol.Required(CONF_BRING_USERNAME): str,
vol.Required(CONF_BRING_PASSWORD): str,
vol.Optional(CONF_BRING_LANGUAGE, default="en-EN"): str,
vol.Optional(CONF_BRING_LIST_NAME, default=""): str,
}
},
extra=vol.ALLOW_EXTRA,
)

EVENT = "shopping_list_updated"
ITEM_UPDATE_SCHEMA = vol.Schema({"complete": bool, ATTR_NAME: str})
PERSISTENCE = ".shopping_list.json"

SERVICE_ADD_ITEM = "add_item"
SERVICE_COMPLETE_ITEM = "complete_item"
SERVICE_SYNC_BRING = "sync_bring"
SERVICE_BRING_SYNC = "bring_sync"
SERVICE_BRING_SELECT_LIST = "bring_select_list"

SERVICE_ITEM_SCHEMA = vol.Schema({vol.Required(ATTR_NAME): vol.Any(None, cv.string)})
SERVICE_BRING_SELECT_LIST_SCHEMA = vol.Schema({vol.Required(ATTR_NAME): str})

WS_TYPE_SHOPPING_LIST_ITEMS = "shopping_list/items"
WS_TYPE_SHOPPING_LIST_ADD_ITEM = "shopping_list/items/add"
Expand Down Expand Up @@ -82,13 +85,15 @@ async def async_setup(hass, config):
CONF_BRING_USERNAME: "",
CONF_BRING_PASSWORD: "",
CONF_BRING_LANGUAGE: "",
CONF_BRING_LIST_NAME: "",
}
return True

hass.data[DOMAIN] = {
CONF_BRING_USERNAME: config[CONF_BRING_USERNAME],
CONF_BRING_PASSWORD: config[CONF_BRING_PASSWORD],
CONF_BRING_LANGUAGE: config[CONF_BRING_LANGUAGE],
CONF_BRING_LIST_NAME: config[CONF_BRING_LIST_NAME],
}

hass.async_create_task(
Expand Down Expand Up @@ -123,13 +128,23 @@ async def complete_item_service(call):
else:
await data.async_update(item["id"], {"name": name, "complete": True})

async def sync_bring_service(call):
async def bring_sync_service(call):
"""Sync with Bring List"""
await hass.data[DOMAIN].sync_bring()

async def bring_select_list_service(call):
"""Select which Bring List HA should synchronize with"""
data = hass.data[DOMAIN]
name = call.data.get(ATTR_NAME)

await data.switch_list(name)

username = hass.data[DOMAIN][CONF_BRING_USERNAME]
password = hass.data[DOMAIN][CONF_BRING_PASSWORD]
language = hass.data[DOMAIN][CONF_BRING_LANGUAGE]
list_name = hass.data[DOMAIN][CONF_BRING_LIST_NAME]

_LOGGER.debug("Selected list: %s", list_name)

session = aiohttp_client.async_create_clientsession(hass)
bring_data = BringData(username, password, language, session)
Expand All @@ -148,7 +163,10 @@ async def sync_bring_service(call):
DOMAIN, SERVICE_COMPLETE_ITEM, complete_item_service, schema=SERVICE_ITEM_SCHEMA
)
hass.services.async_register(
DOMAIN, SERVICE_SYNC_BRING, sync_bring_service, schema={}
DOMAIN, SERVICE_BRING_SYNC, bring_sync_service, schema={}
)
hass.services.async_register(
DOMAIN, SERVICE_BRING_SELECT_LIST, bring_select_list_service, schema=SERVICE_BRING_SELECT_LIST_SCHEMA
)

hass.http.register_view(ShoppingListView)
Expand Down Expand Up @@ -376,6 +394,11 @@ async def async_clear_completed(self):
await self.sync_bring()
await self.hass.async_add_executor_job(self.save)

async def switch_list(self, list_name):
self.map_items = {}
await self.bring.api.select_list(list_name)
await self.sync_bring()

async def sync_bring(self):
await self.bring.update_lists(self.map_items)

Expand Down
20 changes: 17 additions & 3 deletions custom_components/shopping_list/bring.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,12 @@ def __init__(
self._translations = None
self.bringUUID = ""
self.bringListUUID = ""
self.lists = []
self.headers = {}
self.addheaders = {}
self.session = session if session else ClientSession()
self.logged = False
self.selected_list = "Default"

async def __aenter__(self) -> BringApi:
return self
Expand All @@ -76,6 +78,7 @@ async def check_response(response: ClientResponse) -> None:
result = await response.text()
if not result:
print("none")
message = None
if result.get("errorCode"):
message = result.get("error")

Expand Down Expand Up @@ -144,11 +147,22 @@ async def close(self) -> None:
"""Close the session."""
await self.session.close()

async def get_lists(self) -> None:
lists = await self.__get(
BRING_URL, f"bringusers/{self.bringUUID}/lists", headers=self.headers
)
self.lists = lists.get("lists")

async def select_list(self, name):
await self.get_lists()
selected = next((_list for _list in self.lists if _list.get("name") == name), None)
if not selected:
raise ValueError(f"List {name} does not exist")
self.bringListUUID = selected.get("listUuid")
self.selected_list = selected.get("name")

# return list of items from current list as well as recent items - translated if requested
async def get_items(self, locale=None) -> dict:
if not self.logged:
await self.login()

items = await self.__get(
BRING_URL, f"bringlists/{self.bringListUUID}", headers=self.headers
)
Expand Down
2 changes: 1 addition & 1 deletion custom_components/shopping_list/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
aiohttp==3.7.1
voluptuous==0.12.0
pip>=8.0.3
pip>=8.0.3
8 changes: 7 additions & 1 deletion custom_components/shopping_list/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,11 @@ complete_item:
name:
description: The name of the item to mark as completed.
example: Beer
sync_bring:
bring_sync:
description: Syncs with Bring Shopping List.
bring_select_list:
description: Select which list Bring should synchronize with.
fields:
name:
description: The name of the Bring list.
example: Shopping
34 changes: 34 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[flake8]
exclude = .venv,.git,.tox,docs,venv,bin,lib,deps,build
doctests = True
# To work with Black
max-line-length = 88
# E501: line too long
# W503: Line break occurred before a binary operator
# E203: Whitespace before ':'
# D202 No blank lines allowed after function docstring
# W504 line break after binary operator
ignore =
E501,
W503,
E203,
D202,
W504

[isort]
# https://github.com/timothycrosley/isort
# https://github.com/timothycrosley/isort/wiki/isort-Settings
# splits long import on multiple lines indented by 4 spaces
multi_line_output = 3
include_trailing_comma=True
force_grid_wrap=0
use_parentheses=True
line_length=88
indent = " "
# by default isort don't check module indexes
not_skip = __init__.py
# will group `import x` and `from x import` of the same module.
force_sort_within_sections = true
sections = FUTURE,STDLIB,INBETWEENS,THIRDPARTY,FIRSTPARTY,LOCALFOLDER
default_section = THIRDPARTY
combine_as_imports = true

0 comments on commit 071a91f

Please sign in to comment.