Skip to content

Commit

Permalink
Adds support GUI setup
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexxIT committed Jun 8, 2021
1 parent e6a0492 commit 3d766c4
Show file tree
Hide file tree
Showing 5 changed files with 233 additions and 63 deletions.
51 changes: 32 additions & 19 deletions custom_components/yandex_dialogs/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import asyncio
import logging

import voluptuous as vol
from aiohttp import web
from homeassistant.components.http import HomeAssistantView
from homeassistant.const import CONF_NAME
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
from homeassistant.core import Event
from homeassistant.helpers import config_validation as cv, intent
from homeassistant.helpers import intent
from homeassistant.helpers.typing import HomeAssistantType

from . import utils
Expand All @@ -15,20 +14,26 @@

DOMAIN = 'yandex_dialogs'

CONF_USER_IDS = 'allowed_user_ids'

CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({
vol.Optional(CONF_NAME): cv.string,
vol.Optional(CONF_USER_IDS, default=[]): cv.ensure_list,
}, extra=vol.ALLOW_EXTRA),
}, extra=vol.ALLOW_EXTRA)
CONF_USER_IDS = 'user_ids'


async def async_setup(hass: HomeAssistantType, hass_config: dict):
config = hass_config[DOMAIN]
if DOMAIN in hass_config:
hass.async_create_task(hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_IMPORT}
))
return True


async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry):
user_ids = entry.options.get(CONF_USER_IDS, [])

if DOMAIN in hass.data:
dialog: YandexDialog = hass.data[DOMAIN]
dialog.user_ids = user_ids
return True

dialog = YandexDialog(hass, config[CONF_USER_IDS])
hass.data[DOMAIN] = dialog = YandexDialog(hass, user_ids)
hass.http.register_view(dialog)

async def listener(event: Event):
Expand All @@ -38,10 +43,18 @@ async def listener(event: Event):

hass.bus.async_listen('yandex_intent_response', listener)

if 'name' in config:
coro = utils.create_dialog(hass, config['name'])
asyncio.create_task(coro)
# add options handler
if not entry.update_listeners:
entry.add_update_listener(async_update_options)

return True


async def async_update_options(hass: HomeAssistantType, entry):
await hass.config_entries.async_reload(entry.entry_id)


async def async_unload_entry(hass: HomeAssistantType, entry):
return True


Expand All @@ -56,7 +69,7 @@ class YandexDialog(HomeAssistantView):

def __init__(self, hass: HomeAssistantType, user_ids: list):
self.hass = hass
self.allowed_user_ids = user_ids
self.user_ids = user_ids

@staticmethod
def empty(text='', end_session=False):
Expand All @@ -81,10 +94,10 @@ async def post(self, request: web.Request) -> web.Response:
return self.empty()

user_id = data['session']['user']['user_id']
if user_id not in self.allowed_user_ids:
if user_id not in self.user_ids:
if request['command'] == 'привет':
self.hass.components.persistent_notification.async_create(
f"Новый пользователь: {user_id}",
f"Новый пользователь: `{user_id}`",
title="Yandex Dialogs")
return self.empty(text="Умный дом на связи")

Expand Down
113 changes: 113 additions & 0 deletions custom_components/yandex_dialogs/config_flow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import re
from urllib.parse import urlparse

import homeassistant.helpers.config_validation as cv
import voluptuous as vol
from homeassistant.config_entries import ConfigFlow, OptionsFlow, ConfigEntry
from homeassistant.core import callback
from homeassistant.helpers.network import get_url, NoURLAvailableError

from . import DOMAIN, utils, CONF_USER_IDS


class ConfigFlowHandler(ConfigFlow, domain=DOMAIN):
async def async_step_import(self, user_input=None):
return await self.async_step_user()

async def async_step_user(self, user_input=None):
if self._async_current_entries():
return await self.async_step_create()

return self.async_create_entry(title="Yandex Dialogs", data={})

async def async_step_create(self, user_input=None, desc=''):
if user_input:
p = urlparse(user_input['url'])
if p.scheme != 'https':
desc = "Обязательно использование HTTPS"
return self.async_step_create(desc=desc)

hass_url = f"{p.scheme}://{p.netloc}"

entry_id = user_input['account']
entry = self.hass.config_entries.async_get_entry(entry_id)

resp = await utils.create_dialog(
self.hass, user_input['name'], hass_url, entry.data['cookie']
)
if 'error' in resp:
error = resp['error']
if 'url' in resp:
error += f"\n[ссылка на диалог]({resp['url']})"
return await self.async_step_create(desc=error)

await self._update_allowed_users(resp['user_id'])

return self.async_abort(
reason="success",
description_placeholders={'url': resp['url']}
)

entries = self.hass.config_entries.async_entries('yandex_station')
if not entries:
return self.async_abort(reason="yandex_station")

entries = {
entry.entry_id: entry.title
for entry in entries
}

try:
hass_url = get_url(self.hass, require_ssl=True,
allow_internal=False)
except NoURLAvailableError:
hass_url = None

return self.async_show_form(
step_id='create',
data_schema=vol.Schema({
vol.Required('account'): vol.In(entries),
vol.Required('url', default=hass_url): str,
vol.Required('name'): str
}),
description_placeholders={'description': desc}
)

async def _update_allowed_users(self, user_id: str):
entry = self._async_current_entries()[0]

user_ids = entry.options.get(CONF_USER_IDS, [])
if user_id in user_ids:
return

self.hass.config_entries.async_update_entry(entry, data={}, options={
CONF_USER_IDS: user_ids + [user_id]
})
await self.hass.config_entries.async_reload(entry.entry_id)

@staticmethod
@callback
def async_get_options_flow(config_entry):
return OptionsFlowHandler(config_entry)


class OptionsFlowHandler(OptionsFlow):
def __init__(self, config_entry: ConfigEntry):
self.config_entry = config_entry

async def async_step_init(self, user_input=None):
user_ids = self.config_entry.options.get(CONF_USER_IDS)
user_ids = ','.join(user_ids) if user_ids else ''
return self.async_show_form(
step_id='user',
data_schema=vol.Schema({
vol.Optional(CONF_USER_IDS, default=user_ids): cv.string,
})
)

async def async_step_user(self, user_input: dict = None):
user_ids = user_input[CONF_USER_IDS].strip()
user_ids = re.split(r"\s*,\s*", user_ids)
return self.async_create_entry(title='', data={
CONF_USER_IDS: user_ids
})
10 changes: 6 additions & 4 deletions custom_components/yandex_dialogs/manifest.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
{
"domain": "yandex_dialogs",
"name": "Yandex Dialogs",
"config_flow": true,
"documentation": "https://github.com/AlexxIT/YandexDialogs",
"issue_tracker": "https://github.com/AlexxIT/YandexDialogs/issues",
"codeowners": ["@AlexxIT"],
"dependencies": [],
"codeowners": [
"@AlexxIT"
],
"requirements": []
"requirements": [],
"version": "1.1.0",
"iot_class": "cloud_push"
}
30 changes: 30 additions & 0 deletions custom_components/yandex_dialogs/translations/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"config": {
"abort": {
"yandex_station": "Для автоматического создания диалога необходимо установить и настроить интеграцию [Yandex.Station](https://github.com/AlexxIT/YandexStation)",
"success": "Диалог успешно создан: [ссылка]({url})"
},
"step": {
"create": {
"title": "Создание Яндекс Диалога",
"data": {
"account": "Акаунт Яндекса",
"url": "HTTPS-адрес Home Assistant",
"name": "Название диалога"
},
"description": "{description}"
}
}
},
"options": {
"step": {
"user": {
"title": "Настройки Яндекс Диалога",
"data": {
"user_ids": "ID пользователей"
},
"description": "Введите идентификаторы пользователей через запятую"
}
}
}
}
Loading

0 comments on commit 3d766c4

Please sign in to comment.