mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 08:47:57 +00:00
Remove Google Chat/Hangouts integration (#82645)
This commit is contained in:
parent
8577310e6d
commit
285aff154d
@ -483,11 +483,6 @@ omit =
|
||||
homeassistant/components/habitica/__init__.py
|
||||
homeassistant/components/habitica/const.py
|
||||
homeassistant/components/habitica/sensor.py
|
||||
homeassistant/components/hangouts/__init__.py
|
||||
homeassistant/components/hangouts/hangouts_bot.py
|
||||
homeassistant/components/hangouts/hangups_utils.py
|
||||
homeassistant/components/hangouts/intents.py
|
||||
homeassistant/components/hangouts/notify.py
|
||||
homeassistant/components/harman_kardon_avr/media_player.py
|
||||
homeassistant/components/harmony/const.py
|
||||
homeassistant/components/harmony/data.py
|
||||
|
@ -14,7 +14,6 @@
|
||||
"google",
|
||||
"nest",
|
||||
"cast",
|
||||
"hangouts",
|
||||
"dialogflow"
|
||||
]
|
||||
}
|
||||
|
@ -1,160 +0,0 @@
|
||||
"""Support for Hangouts."""
|
||||
import logging
|
||||
|
||||
from hangups.auth import GoogleAuthError
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components.conversation.util import create_matcher
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import dispatcher, intent
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
|
||||
# We need an import from .config_flow, without it .config_flow is never loaded.
|
||||
from .config_flow import HangoutsFlowHandler # noqa: F401
|
||||
from .const import (
|
||||
CONF_BOT,
|
||||
CONF_DEFAULT_CONVERSATIONS,
|
||||
CONF_ERROR_SUPPRESSED_CONVERSATIONS,
|
||||
CONF_INTENTS,
|
||||
CONF_MATCHERS,
|
||||
CONF_REFRESH_TOKEN,
|
||||
CONF_SENTENCES,
|
||||
DOMAIN,
|
||||
EVENT_HANGOUTS_CONNECTED,
|
||||
EVENT_HANGOUTS_CONVERSATIONS_CHANGED,
|
||||
EVENT_HANGOUTS_CONVERSATIONS_RESOLVED,
|
||||
INTENT_HELP,
|
||||
INTENT_SCHEMA,
|
||||
MESSAGE_SCHEMA,
|
||||
SERVICE_RECONNECT,
|
||||
SERVICE_SEND_MESSAGE,
|
||||
SERVICE_UPDATE,
|
||||
TARGETS_SCHEMA,
|
||||
)
|
||||
from .hangouts_bot import HangoutsBot
|
||||
from .intents import HelpIntent
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema(
|
||||
{
|
||||
DOMAIN: vol.Schema(
|
||||
{
|
||||
vol.Optional(CONF_INTENTS, default={}): vol.Schema(
|
||||
{cv.string: INTENT_SCHEMA}
|
||||
),
|
||||
vol.Optional(CONF_DEFAULT_CONVERSATIONS, default=[]): [TARGETS_SCHEMA],
|
||||
vol.Optional(CONF_ERROR_SUPPRESSED_CONVERSATIONS, default=[]): [
|
||||
TARGETS_SCHEMA
|
||||
],
|
||||
}
|
||||
)
|
||||
},
|
||||
extra=vol.ALLOW_EXTRA,
|
||||
)
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
"""Set up the Hangouts bot component."""
|
||||
if (conf := config.get(DOMAIN)) is None:
|
||||
hass.data[DOMAIN] = {
|
||||
CONF_INTENTS: {},
|
||||
CONF_DEFAULT_CONVERSATIONS: [],
|
||||
CONF_ERROR_SUPPRESSED_CONVERSATIONS: [],
|
||||
}
|
||||
return True
|
||||
|
||||
hass.data[DOMAIN] = {
|
||||
CONF_INTENTS: conf[CONF_INTENTS],
|
||||
CONF_DEFAULT_CONVERSATIONS: conf[CONF_DEFAULT_CONVERSATIONS],
|
||||
CONF_ERROR_SUPPRESSED_CONVERSATIONS: conf[CONF_ERROR_SUPPRESSED_CONVERSATIONS],
|
||||
}
|
||||
|
||||
if (
|
||||
hass.data[DOMAIN][CONF_INTENTS]
|
||||
and INTENT_HELP not in hass.data[DOMAIN][CONF_INTENTS]
|
||||
):
|
||||
hass.data[DOMAIN][CONF_INTENTS][INTENT_HELP] = {CONF_SENTENCES: ["HELP"]}
|
||||
|
||||
for data in hass.data[DOMAIN][CONF_INTENTS].values():
|
||||
matchers = []
|
||||
for sentence in data[CONF_SENTENCES]:
|
||||
matchers.append(create_matcher(sentence))
|
||||
|
||||
data[CONF_MATCHERS] = matchers
|
||||
|
||||
hass.async_create_task(
|
||||
hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_IMPORT}
|
||||
)
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, config: ConfigEntry) -> bool:
|
||||
"""Set up a config entry."""
|
||||
try:
|
||||
bot = HangoutsBot(
|
||||
hass,
|
||||
config.data.get(CONF_REFRESH_TOKEN),
|
||||
hass.data[DOMAIN][CONF_INTENTS],
|
||||
hass.data[DOMAIN][CONF_DEFAULT_CONVERSATIONS],
|
||||
hass.data[DOMAIN][CONF_ERROR_SUPPRESSED_CONVERSATIONS],
|
||||
)
|
||||
hass.data[DOMAIN][CONF_BOT] = bot
|
||||
except GoogleAuthError as exception:
|
||||
_LOGGER.error("Hangouts failed to log in: %s", str(exception))
|
||||
return False
|
||||
|
||||
dispatcher.async_dispatcher_connect(
|
||||
hass, EVENT_HANGOUTS_CONNECTED, bot.async_handle_update_users_and_conversations
|
||||
)
|
||||
|
||||
dispatcher.async_dispatcher_connect(
|
||||
hass, EVENT_HANGOUTS_CONVERSATIONS_CHANGED, bot.async_resolve_conversations
|
||||
)
|
||||
|
||||
dispatcher.async_dispatcher_connect(
|
||||
hass,
|
||||
EVENT_HANGOUTS_CONVERSATIONS_RESOLVED,
|
||||
bot.async_update_conversation_commands,
|
||||
)
|
||||
|
||||
config.async_on_unload(
|
||||
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, bot.async_handle_hass_stop)
|
||||
)
|
||||
|
||||
await bot.async_connect()
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
SERVICE_SEND_MESSAGE,
|
||||
bot.async_handle_send_message,
|
||||
schema=MESSAGE_SCHEMA,
|
||||
)
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
SERVICE_UPDATE,
|
||||
bot.async_handle_update_users_and_conversations,
|
||||
schema=vol.Schema({}),
|
||||
)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_RECONNECT, bot.async_handle_reconnect, schema=vol.Schema({})
|
||||
)
|
||||
|
||||
intent.async_register(hass, HelpIntent(hass))
|
||||
|
||||
return True
|
||||
|
||||
|
||||
async def async_unload_entry(hass: HomeAssistant, _: ConfigEntry) -> bool:
|
||||
"""Unload a config entry."""
|
||||
bot = hass.data[DOMAIN].pop(CONF_BOT)
|
||||
await bot.async_disconnect()
|
||||
return True
|
@ -1,111 +0,0 @@
|
||||
"""Config flow to configure Google Hangouts."""
|
||||
import functools
|
||||
|
||||
from hangups import get_auth
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.const import CONF_EMAIL, CONF_PASSWORD
|
||||
|
||||
from .const import CONF_2FA, CONF_AUTH_CODE, CONF_REFRESH_TOKEN, DOMAIN
|
||||
from .hangups_utils import (
|
||||
Google2FAError,
|
||||
GoogleAuthError,
|
||||
HangoutsCredentials,
|
||||
HangoutsRefreshToken,
|
||||
)
|
||||
|
||||
|
||||
class HangoutsFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
"""Config flow Google Hangouts."""
|
||||
|
||||
VERSION = 1
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize Google Hangouts config flow."""
|
||||
self._credentials = None
|
||||
self._refresh_token = None
|
||||
|
||||
async def async_step_user(self, user_input=None):
|
||||
"""Handle a flow start."""
|
||||
errors = {}
|
||||
|
||||
self._async_abort_entries_match()
|
||||
|
||||
if user_input is not None:
|
||||
user_email = user_input[CONF_EMAIL]
|
||||
user_password = user_input[CONF_PASSWORD]
|
||||
user_auth_code = user_input.get(CONF_AUTH_CODE)
|
||||
manual_login = user_auth_code is not None
|
||||
|
||||
user_pin = None
|
||||
self._credentials = HangoutsCredentials(
|
||||
user_email, user_password, user_pin, user_auth_code
|
||||
)
|
||||
self._refresh_token = HangoutsRefreshToken(None)
|
||||
try:
|
||||
await self.hass.async_add_executor_job(
|
||||
functools.partial(
|
||||
get_auth,
|
||||
self._credentials,
|
||||
self._refresh_token,
|
||||
manual_login=manual_login,
|
||||
)
|
||||
)
|
||||
|
||||
return await self.async_step_final()
|
||||
except GoogleAuthError as err:
|
||||
if isinstance(err, Google2FAError):
|
||||
return await self.async_step_2fa()
|
||||
msg = str(err)
|
||||
if msg == "Unknown verification code input":
|
||||
errors["base"] = "invalid_2fa_method"
|
||||
else:
|
||||
errors["base"] = "invalid_login"
|
||||
|
||||
return self.async_show_form(
|
||||
step_id="user",
|
||||
data_schema=vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_EMAIL): str,
|
||||
vol.Required(CONF_PASSWORD): str,
|
||||
vol.Optional(CONF_AUTH_CODE): str,
|
||||
}
|
||||
),
|
||||
errors=errors,
|
||||
)
|
||||
|
||||
async def async_step_2fa(self, user_input=None):
|
||||
"""Handle the 2fa step, if needed."""
|
||||
errors = {}
|
||||
|
||||
if user_input is not None:
|
||||
self._credentials.set_verification_code(user_input[CONF_2FA])
|
||||
try:
|
||||
await self.hass.async_add_executor_job(
|
||||
get_auth, self._credentials, self._refresh_token
|
||||
)
|
||||
|
||||
return await self.async_step_final()
|
||||
except GoogleAuthError:
|
||||
errors["base"] = "invalid_2fa"
|
||||
|
||||
return self.async_show_form(
|
||||
step_id=CONF_2FA,
|
||||
data_schema=vol.Schema({vol.Required(CONF_2FA): str}),
|
||||
errors=errors,
|
||||
)
|
||||
|
||||
async def async_step_final(self):
|
||||
"""Handle the final step, create the config entry."""
|
||||
return self.async_create_entry(
|
||||
title=self._credentials.get_email(),
|
||||
data={
|
||||
CONF_EMAIL: self._credentials.get_email(),
|
||||
CONF_REFRESH_TOKEN: self._refresh_token.get(),
|
||||
},
|
||||
)
|
||||
|
||||
async def async_step_import(self, _):
|
||||
"""Handle a flow import."""
|
||||
return await self.async_step_user()
|
@ -1,80 +0,0 @@
|
||||
"""Constants for Google Hangouts Component."""
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.notify import ATTR_DATA, ATTR_MESSAGE, ATTR_TARGET
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
DOMAIN = "hangouts"
|
||||
|
||||
CONF_2FA = "2fa"
|
||||
CONF_AUTH_CODE = "authorization_code"
|
||||
CONF_REFRESH_TOKEN = "refresh_token"
|
||||
CONF_BOT = "bot"
|
||||
|
||||
CONF_CONVERSATIONS = "conversations"
|
||||
CONF_DEFAULT_CONVERSATIONS = "default_conversations"
|
||||
CONF_ERROR_SUPPRESSED_CONVERSATIONS = "error_suppressed_conversations"
|
||||
|
||||
CONF_INTENTS = "intents"
|
||||
CONF_INTENT_TYPE = "intent_type"
|
||||
CONF_SENTENCES = "sentences"
|
||||
CONF_MATCHERS = "matchers"
|
||||
|
||||
INTENT_HELP = "HangoutsHelp"
|
||||
|
||||
EVENT_HANGOUTS_CONNECTED = "hangouts_connected"
|
||||
EVENT_HANGOUTS_DISCONNECTED = "hangouts_disconnected"
|
||||
EVENT_HANGOUTS_USERS_CHANGED = "hangouts_users_changed"
|
||||
EVENT_HANGOUTS_CONVERSATIONS_CHANGED = "hangouts_conversations_changed"
|
||||
EVENT_HANGOUTS_CONVERSATIONS_RESOLVED = "hangouts_conversations_resolved"
|
||||
EVENT_HANGOUTS_MESSAGE_RECEIVED = "hangouts_message_received"
|
||||
|
||||
CONF_CONVERSATION_ID = "id"
|
||||
CONF_CONVERSATION_NAME = "name"
|
||||
|
||||
SERVICE_SEND_MESSAGE = "send_message"
|
||||
SERVICE_UPDATE = "update"
|
||||
SERVICE_RECONNECT = "reconnect"
|
||||
|
||||
|
||||
TARGETS_SCHEMA = vol.All(
|
||||
vol.Schema(
|
||||
{
|
||||
vol.Exclusive(CONF_CONVERSATION_ID, "id or name"): cv.string,
|
||||
vol.Exclusive(CONF_CONVERSATION_NAME, "id or name"): cv.string,
|
||||
}
|
||||
),
|
||||
cv.has_at_least_one_key(CONF_CONVERSATION_ID, CONF_CONVERSATION_NAME),
|
||||
)
|
||||
MESSAGE_SEGMENT_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required("text"): cv.string,
|
||||
vol.Optional("is_bold"): cv.boolean,
|
||||
vol.Optional("is_italic"): cv.boolean,
|
||||
vol.Optional("is_strikethrough"): cv.boolean,
|
||||
vol.Optional("is_underline"): cv.boolean,
|
||||
vol.Optional("parse_str"): cv.boolean,
|
||||
vol.Optional("link_target"): cv.string,
|
||||
}
|
||||
)
|
||||
MESSAGE_DATA_SCHEMA = vol.Schema(
|
||||
{vol.Optional("image_file"): cv.string, vol.Optional("image_url"): cv.string}
|
||||
)
|
||||
|
||||
MESSAGE_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required(ATTR_TARGET): [TARGETS_SCHEMA],
|
||||
vol.Required(ATTR_MESSAGE): [MESSAGE_SEGMENT_SCHEMA],
|
||||
vol.Optional(ATTR_DATA): MESSAGE_DATA_SCHEMA,
|
||||
}
|
||||
)
|
||||
|
||||
INTENT_SCHEMA = vol.All(
|
||||
# Basic Schema
|
||||
vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_SENTENCES): vol.All(cv.ensure_list, [cv.string]),
|
||||
vol.Optional(CONF_CONVERSATIONS): [TARGETS_SCHEMA],
|
||||
}
|
||||
)
|
||||
)
|
@ -1,361 +0,0 @@
|
||||
"""The Hangouts Bot."""
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from contextlib import suppress
|
||||
from http import HTTPStatus
|
||||
import io
|
||||
import logging
|
||||
|
||||
import aiohttp
|
||||
import hangups
|
||||
from hangups import ChatMessageEvent, ChatMessageSegment, Client, get_auth, hangouts_pb2
|
||||
|
||||
from homeassistant.core import ServiceCall, callback
|
||||
from homeassistant.helpers import dispatcher, intent
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
|
||||
from .const import (
|
||||
ATTR_DATA,
|
||||
ATTR_MESSAGE,
|
||||
ATTR_TARGET,
|
||||
CONF_CONVERSATION_ID,
|
||||
CONF_CONVERSATION_NAME,
|
||||
CONF_CONVERSATIONS,
|
||||
CONF_MATCHERS,
|
||||
DOMAIN,
|
||||
EVENT_HANGOUTS_CONNECTED,
|
||||
EVENT_HANGOUTS_CONVERSATIONS_CHANGED,
|
||||
EVENT_HANGOUTS_CONVERSATIONS_RESOLVED,
|
||||
EVENT_HANGOUTS_DISCONNECTED,
|
||||
EVENT_HANGOUTS_MESSAGE_RECEIVED,
|
||||
INTENT_HELP,
|
||||
)
|
||||
from .hangups_utils import HangoutsCredentials, HangoutsRefreshToken
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class HangoutsBot:
|
||||
"""The Hangouts Bot."""
|
||||
|
||||
def __init__(
|
||||
self, hass, refresh_token, intents, default_convs, error_suppressed_convs
|
||||
):
|
||||
"""Set up the client."""
|
||||
self.hass = hass
|
||||
self._connected = False
|
||||
|
||||
self._refresh_token = refresh_token
|
||||
|
||||
self._intents = intents
|
||||
self._conversation_intents = None
|
||||
|
||||
self._client = None
|
||||
self._user_list = None
|
||||
self._conversation_list = None
|
||||
self._default_convs = default_convs
|
||||
self._default_conv_ids = None
|
||||
self._error_suppressed_convs = error_suppressed_convs
|
||||
self._error_suppressed_conv_ids = None
|
||||
|
||||
dispatcher.async_dispatcher_connect(
|
||||
self.hass,
|
||||
EVENT_HANGOUTS_MESSAGE_RECEIVED,
|
||||
self._async_handle_conversation_message,
|
||||
)
|
||||
|
||||
def _resolve_conversation_id(self, obj):
|
||||
if CONF_CONVERSATION_ID in obj:
|
||||
return obj[CONF_CONVERSATION_ID]
|
||||
if CONF_CONVERSATION_NAME in obj:
|
||||
conv = self._resolve_conversation_name(obj[CONF_CONVERSATION_NAME])
|
||||
if conv is not None:
|
||||
return conv.id_
|
||||
return None
|
||||
|
||||
def _resolve_conversation_name(self, name):
|
||||
for conv in self._conversation_list.get_all():
|
||||
if conv.name == name:
|
||||
return conv
|
||||
return None
|
||||
|
||||
@callback
|
||||
def async_update_conversation_commands(self):
|
||||
"""Refresh the commands for every conversation."""
|
||||
self._conversation_intents = {}
|
||||
|
||||
for intent_type, data in self._intents.items():
|
||||
if data.get(CONF_CONVERSATIONS):
|
||||
conversations = []
|
||||
for conversation in data.get(CONF_CONVERSATIONS):
|
||||
conv_id = self._resolve_conversation_id(conversation)
|
||||
if conv_id is not None:
|
||||
conversations.append(conv_id)
|
||||
data[f"_{CONF_CONVERSATIONS}"] = conversations
|
||||
elif self._default_conv_ids:
|
||||
data[f"_{CONF_CONVERSATIONS}"] = self._default_conv_ids
|
||||
else:
|
||||
data[f"_{CONF_CONVERSATIONS}"] = [
|
||||
conv.id_ for conv in self._conversation_list.get_all()
|
||||
]
|
||||
|
||||
for conv_id in data[f"_{CONF_CONVERSATIONS}"]:
|
||||
if conv_id not in self._conversation_intents:
|
||||
self._conversation_intents[conv_id] = {}
|
||||
|
||||
self._conversation_intents[conv_id][intent_type] = data
|
||||
|
||||
with suppress(ValueError):
|
||||
self._conversation_list.on_event.remove_observer(
|
||||
self._async_handle_conversation_event
|
||||
)
|
||||
self._conversation_list.on_event.add_observer(
|
||||
self._async_handle_conversation_event
|
||||
)
|
||||
|
||||
@callback
|
||||
def async_resolve_conversations(self, _):
|
||||
"""Resolve the list of default and error suppressed conversations."""
|
||||
self._default_conv_ids = []
|
||||
self._error_suppressed_conv_ids = []
|
||||
|
||||
for conversation in self._default_convs:
|
||||
conv_id = self._resolve_conversation_id(conversation)
|
||||
if conv_id is not None:
|
||||
self._default_conv_ids.append(conv_id)
|
||||
|
||||
for conversation in self._error_suppressed_convs:
|
||||
conv_id = self._resolve_conversation_id(conversation)
|
||||
if conv_id is not None:
|
||||
self._error_suppressed_conv_ids.append(conv_id)
|
||||
dispatcher.async_dispatcher_send(
|
||||
self.hass, EVENT_HANGOUTS_CONVERSATIONS_RESOLVED
|
||||
)
|
||||
|
||||
async def _async_handle_conversation_event(self, event):
|
||||
if isinstance(event, ChatMessageEvent):
|
||||
dispatcher.async_dispatcher_send(
|
||||
self.hass,
|
||||
EVENT_HANGOUTS_MESSAGE_RECEIVED,
|
||||
event.conversation_id,
|
||||
event.user_id,
|
||||
event,
|
||||
)
|
||||
|
||||
async def _async_handle_conversation_message(self, conv_id, user_id, event):
|
||||
"""Handle a message sent to a conversation."""
|
||||
user = self._user_list.get_user(user_id)
|
||||
if user.is_self:
|
||||
return
|
||||
message = event.text
|
||||
|
||||
_LOGGER.debug("Handling message '%s' from %s", message, user.full_name)
|
||||
|
||||
intents = self._conversation_intents.get(conv_id)
|
||||
if intents is not None:
|
||||
is_error = False
|
||||
try:
|
||||
intent_result = await self._async_process(intents, message, conv_id)
|
||||
except (intent.UnknownIntent, intent.IntentHandleError) as err:
|
||||
is_error = True
|
||||
intent_result = intent.IntentResponse()
|
||||
intent_result.async_set_speech(str(err))
|
||||
|
||||
if intent_result is None:
|
||||
is_error = True
|
||||
intent_result = intent.IntentResponse()
|
||||
intent_result.async_set_speech("Sorry, I didn't understand that")
|
||||
|
||||
message = (
|
||||
intent_result.as_dict().get("speech", {}).get("plain", {}).get("speech")
|
||||
)
|
||||
|
||||
if (message is not None) and not (
|
||||
is_error and conv_id in self._error_suppressed_conv_ids
|
||||
):
|
||||
await self._async_send_message(
|
||||
[{"text": message, "parse_str": True}],
|
||||
[{CONF_CONVERSATION_ID: conv_id}],
|
||||
None,
|
||||
)
|
||||
|
||||
async def _async_process(self, intents, text, conv_id):
|
||||
"""Detect a matching intent."""
|
||||
for intent_type, data in intents.items():
|
||||
for matcher in data.get(CONF_MATCHERS, []):
|
||||
if not (match := matcher.match(text)):
|
||||
continue
|
||||
if intent_type == INTENT_HELP:
|
||||
return await intent.async_handle(
|
||||
self.hass,
|
||||
DOMAIN,
|
||||
intent_type,
|
||||
{"conv_id": {"value": conv_id}},
|
||||
text,
|
||||
)
|
||||
|
||||
return await intent.async_handle(
|
||||
self.hass,
|
||||
DOMAIN,
|
||||
intent_type,
|
||||
{"conv_id": {"value": conv_id}}
|
||||
| {
|
||||
key: {"value": value}
|
||||
for key, value in match.groupdict().items()
|
||||
},
|
||||
text,
|
||||
)
|
||||
|
||||
async def async_connect(self):
|
||||
"""Login to the Google Hangouts."""
|
||||
session = await self.hass.async_add_executor_job(
|
||||
get_auth,
|
||||
HangoutsCredentials(None, None, None),
|
||||
HangoutsRefreshToken(self._refresh_token),
|
||||
)
|
||||
|
||||
self._client = Client(session)
|
||||
self._client.on_connect.add_observer(self._on_connect)
|
||||
self._client.on_disconnect.add_observer(self._on_disconnect)
|
||||
|
||||
self.hass.loop.create_task(self._client.connect())
|
||||
|
||||
def _on_connect(self):
|
||||
_LOGGER.debug("Connected!")
|
||||
self._connected = True
|
||||
dispatcher.async_dispatcher_send(self.hass, EVENT_HANGOUTS_CONNECTED)
|
||||
|
||||
async def _on_disconnect(self):
|
||||
"""Handle disconnecting."""
|
||||
if self._connected:
|
||||
_LOGGER.debug("Connection lost! Reconnect")
|
||||
await self.async_connect()
|
||||
else:
|
||||
dispatcher.async_dispatcher_send(self.hass, EVENT_HANGOUTS_DISCONNECTED)
|
||||
|
||||
async def async_disconnect(self):
|
||||
"""Disconnect the client if it is connected."""
|
||||
if self._connected:
|
||||
self._connected = False
|
||||
await self._client.disconnect()
|
||||
|
||||
async def async_handle_hass_stop(self, _):
|
||||
"""Run once when Home Assistant stops."""
|
||||
await self.async_disconnect()
|
||||
|
||||
async def _async_send_message(self, message, targets, data):
|
||||
conversations = []
|
||||
for target in targets:
|
||||
conversation = None
|
||||
if CONF_CONVERSATION_ID in target:
|
||||
conversation = self._conversation_list.get(target[CONF_CONVERSATION_ID])
|
||||
elif CONF_CONVERSATION_NAME in target:
|
||||
conversation = self._resolve_conversation_name(
|
||||
target[CONF_CONVERSATION_NAME]
|
||||
)
|
||||
if conversation is not None:
|
||||
conversations.append(conversation)
|
||||
|
||||
if not conversations:
|
||||
return False
|
||||
|
||||
messages = []
|
||||
for segment in message:
|
||||
if messages:
|
||||
messages.append(
|
||||
ChatMessageSegment(
|
||||
"", segment_type=hangouts_pb2.SEGMENT_TYPE_LINE_BREAK
|
||||
)
|
||||
)
|
||||
if "parse_str" in segment and segment["parse_str"]:
|
||||
messages.extend(ChatMessageSegment.from_str(segment["text"]))
|
||||
else:
|
||||
if "parse_str" in segment:
|
||||
del segment["parse_str"]
|
||||
messages.append(ChatMessageSegment(**segment))
|
||||
|
||||
image_file = None
|
||||
if data:
|
||||
if data.get("image_url"):
|
||||
uri = data.get("image_url")
|
||||
try:
|
||||
websession = async_get_clientsession(self.hass)
|
||||
async with websession.get(uri, timeout=5) as response:
|
||||
if response.status != HTTPStatus.OK:
|
||||
_LOGGER.error(
|
||||
"Fetch image failed, %s, %s", response.status, response
|
||||
)
|
||||
image_file = None
|
||||
else:
|
||||
image_data = await response.read()
|
||||
image_file = io.BytesIO(image_data)
|
||||
image_file.name = "image.png"
|
||||
except (asyncio.TimeoutError, aiohttp.ClientError) as error:
|
||||
_LOGGER.error("Failed to fetch image, %s", type(error))
|
||||
image_file = None
|
||||
elif data.get("image_file"):
|
||||
uri = data.get("image_file")
|
||||
if self.hass.config.is_allowed_path(uri):
|
||||
try:
|
||||
# pylint: disable=consider-using-with
|
||||
image_file = open(uri, "rb")
|
||||
except OSError as error:
|
||||
_LOGGER.error(
|
||||
"Image file I/O error(%s): %s", error.errno, error.strerror
|
||||
)
|
||||
else:
|
||||
_LOGGER.error('Path "%s" not allowed', uri)
|
||||
|
||||
if not messages:
|
||||
return False
|
||||
for conv in conversations:
|
||||
await conv.send_message(messages, image_file)
|
||||
|
||||
async def _async_list_conversations(self):
|
||||
(
|
||||
self._user_list,
|
||||
self._conversation_list,
|
||||
) = await hangups.build_user_conversation_list(self._client)
|
||||
conversations = {}
|
||||
for i, conv in enumerate(self._conversation_list.get_all()):
|
||||
users_in_conversation = []
|
||||
for user in conv.users:
|
||||
users_in_conversation.append(user.full_name)
|
||||
conversations[str(i)] = {
|
||||
CONF_CONVERSATION_ID: str(conv.id_),
|
||||
CONF_CONVERSATION_NAME: conv.name,
|
||||
"users": users_in_conversation,
|
||||
}
|
||||
|
||||
self.hass.states.async_set(
|
||||
f"{DOMAIN}.conversations",
|
||||
len(self._conversation_list.get_all()),
|
||||
attributes=conversations,
|
||||
)
|
||||
dispatcher.async_dispatcher_send(
|
||||
self.hass, EVENT_HANGOUTS_CONVERSATIONS_CHANGED, conversations
|
||||
)
|
||||
|
||||
async def async_handle_send_message(self, service: ServiceCall) -> None:
|
||||
"""Handle the send_message service."""
|
||||
await self._async_send_message(
|
||||
service.data[ATTR_MESSAGE],
|
||||
service.data[ATTR_TARGET],
|
||||
service.data.get(ATTR_DATA, {}),
|
||||
)
|
||||
|
||||
async def async_handle_update_users_and_conversations(
|
||||
self, service: ServiceCall | None = None
|
||||
) -> None:
|
||||
"""Handle the update_users_and_conversations service."""
|
||||
await self._async_list_conversations()
|
||||
|
||||
async def async_handle_reconnect(self, service: ServiceCall | None = None) -> None:
|
||||
"""Handle the reconnect service."""
|
||||
await self.async_disconnect()
|
||||
await self.async_connect()
|
||||
|
||||
def get_intents(self, conv_id):
|
||||
"""Return the intents for a specific conversation."""
|
||||
return self._conversation_intents.get(conv_id)
|
@ -1,96 +0,0 @@
|
||||
"""Utils needed for Google Hangouts."""
|
||||
|
||||
from hangups import CredentialsPrompt, GoogleAuthError, RefreshTokenCache
|
||||
|
||||
|
||||
class Google2FAError(GoogleAuthError):
|
||||
"""A Google authentication request failed."""
|
||||
|
||||
|
||||
class HangoutsCredentials(CredentialsPrompt):
|
||||
"""Google account credentials.
|
||||
|
||||
This implementation gets the user data as params.
|
||||
"""
|
||||
|
||||
def __init__(self, email, password, pin=None, auth_code=None):
|
||||
"""Google account credentials.
|
||||
|
||||
:param email: Google account email address.
|
||||
:param password: Google account password.
|
||||
:param pin: Google account verification code.
|
||||
"""
|
||||
self._email = email
|
||||
self._password = password
|
||||
self._pin = pin
|
||||
self._auth_code = auth_code
|
||||
|
||||
def get_email(self):
|
||||
"""Return email.
|
||||
|
||||
:return: Google account email address.
|
||||
"""
|
||||
return self._email
|
||||
|
||||
def get_password(self):
|
||||
"""Return password.
|
||||
|
||||
:return: Google account password.
|
||||
"""
|
||||
return self._password
|
||||
|
||||
def get_verification_code(self):
|
||||
"""Return the verification code.
|
||||
|
||||
:return: Google account verification code.
|
||||
"""
|
||||
if self._pin is None:
|
||||
raise Google2FAError()
|
||||
return self._pin
|
||||
|
||||
def set_verification_code(self, pin):
|
||||
"""Set the verification code.
|
||||
|
||||
:param pin: Google account verification code.
|
||||
"""
|
||||
self._pin = pin
|
||||
|
||||
def get_authorization_code(self):
|
||||
"""Return the oauth authorization code.
|
||||
|
||||
:return: Google oauth code.
|
||||
"""
|
||||
return self._auth_code
|
||||
|
||||
def set_authorization_code(self, code):
|
||||
"""Set the google oauth authorization code.
|
||||
|
||||
:param code: Oauth code returned after authentication with google.
|
||||
"""
|
||||
self._auth_code = code
|
||||
|
||||
|
||||
class HangoutsRefreshToken(RefreshTokenCache):
|
||||
"""Memory-based cache for refresh token."""
|
||||
|
||||
def __init__(self, token):
|
||||
"""Memory-based cache for refresh token.
|
||||
|
||||
:param token: Initial refresh token.
|
||||
"""
|
||||
super().__init__("")
|
||||
self._token = token
|
||||
|
||||
def get(self):
|
||||
"""Get cached refresh token.
|
||||
|
||||
:return: Cached refresh token.
|
||||
"""
|
||||
return self._token
|
||||
|
||||
def set(self, refresh_token):
|
||||
"""Cache a refresh token.
|
||||
|
||||
:param refresh_token: Refresh token to cache.
|
||||
"""
|
||||
self._token = refresh_token
|
@ -1,31 +0,0 @@
|
||||
"""Intents for the Hangouts component."""
|
||||
from homeassistant.helpers import intent
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
from .const import CONF_BOT, DOMAIN, INTENT_HELP
|
||||
|
||||
|
||||
class HelpIntent(intent.IntentHandler):
|
||||
"""Handle Help intents."""
|
||||
|
||||
intent_type = INTENT_HELP
|
||||
slot_schema = {"conv_id": cv.string}
|
||||
|
||||
def __init__(self, hass):
|
||||
"""Set up the intent."""
|
||||
self.hass = hass
|
||||
|
||||
async def async_handle(self, intent_obj):
|
||||
"""Handle the intent."""
|
||||
slots = self.async_validate_slots(intent_obj.slots)
|
||||
conv_id = slots["conv_id"]["value"]
|
||||
|
||||
intents = self.hass.data[DOMAIN][CONF_BOT].get_intents(conv_id)
|
||||
response = intent_obj.create_response()
|
||||
help_text = "I understand the following sentences:"
|
||||
for intent_data in intents.values():
|
||||
for sentence in intent_data["sentences"]:
|
||||
help_text += f"\n'{sentence}'"
|
||||
response.async_set_speech(help_text)
|
||||
|
||||
return response
|
@ -1,10 +0,0 @@
|
||||
{
|
||||
"domain": "hangouts",
|
||||
"name": "Google Chat",
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/hangouts",
|
||||
"requirements": ["hangups==0.4.18"],
|
||||
"codeowners": [],
|
||||
"iot_class": "cloud_push",
|
||||
"loggers": ["hangups", "urwid"]
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
"""Support for Hangouts notifications."""
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.notify import (
|
||||
ATTR_DATA,
|
||||
ATTR_MESSAGE,
|
||||
ATTR_TARGET,
|
||||
PLATFORM_SCHEMA,
|
||||
BaseNotificationService,
|
||||
)
|
||||
|
||||
from .const import (
|
||||
CONF_DEFAULT_CONVERSATIONS,
|
||||
DOMAIN,
|
||||
SERVICE_SEND_MESSAGE,
|
||||
TARGETS_SCHEMA,
|
||||
)
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||
{vol.Required(CONF_DEFAULT_CONVERSATIONS): [TARGETS_SCHEMA]}
|
||||
)
|
||||
|
||||
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the Hangouts notification service."""
|
||||
return HangoutsNotificationService(config.get(CONF_DEFAULT_CONVERSATIONS))
|
||||
|
||||
|
||||
class HangoutsNotificationService(BaseNotificationService):
|
||||
"""Send Notifications to Hangouts conversations."""
|
||||
|
||||
def __init__(self, default_conversations):
|
||||
"""Set up the notification service."""
|
||||
self._default_conversations = default_conversations
|
||||
|
||||
def send_message(self, message="", **kwargs):
|
||||
"""Send the message to the Google Hangouts server."""
|
||||
target_conversations = None
|
||||
if ATTR_TARGET in kwargs:
|
||||
target_conversations = []
|
||||
for target in kwargs.get(ATTR_TARGET):
|
||||
target_conversations.append({"id": target})
|
||||
else:
|
||||
target_conversations = self._default_conversations
|
||||
|
||||
messages = []
|
||||
if "title" in kwargs:
|
||||
messages.append({"text": kwargs["title"], "is_bold": True})
|
||||
|
||||
messages.append({"text": message, "parse_str": True})
|
||||
service_data = {ATTR_TARGET: target_conversations, ATTR_MESSAGE: messages}
|
||||
if kwargs[ATTR_DATA]:
|
||||
service_data[ATTR_DATA] = kwargs[ATTR_DATA]
|
||||
|
||||
return self.hass.services.call(
|
||||
DOMAIN, SERVICE_SEND_MESSAGE, service_data=service_data
|
||||
)
|
@ -1,32 +0,0 @@
|
||||
update:
|
||||
name: Update
|
||||
description: Updates the list of conversations.
|
||||
|
||||
send_message:
|
||||
name: Send message
|
||||
description: Send a notification to a specific target.
|
||||
fields:
|
||||
target:
|
||||
name: Target
|
||||
description: List of targets with id or name.
|
||||
required: true
|
||||
example: '[{"id": "UgxrXzVrARmjx_C6AZx4AaABAagBo-6UCw"}, {"name": "Test Conversation"}]'
|
||||
selector:
|
||||
object:
|
||||
message:
|
||||
name: Message
|
||||
description: List of message segments, only the "text" field is required in every segment.
|
||||
required: true
|
||||
example: '[{"text":"test", "is_bold": false, "is_italic": false, "is_strikethrough": false, "is_underline": false, "parse_str": false, "link_target": "http://google.com"}]'
|
||||
selector:
|
||||
object:
|
||||
data:
|
||||
name: Data
|
||||
description: Other options ['image_file' / 'image_url']
|
||||
example: '{ "image_file": "file" }'
|
||||
selector:
|
||||
object:
|
||||
|
||||
reconnect:
|
||||
name: Reconnect
|
||||
description: Reconnect the bot.
|
@ -1,29 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_service%]",
|
||||
"unknown": "[%key:common::config_flow::error::unknown%]"
|
||||
},
|
||||
"error": {
|
||||
"invalid_login": "Invalid Login, please try again.",
|
||||
"invalid_2fa": "Invalid 2 Factor Authentication, please try again.",
|
||||
"invalid_2fa_method": "Invalid 2FA Method (verify on Phone)."
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"email": "[%key:common::config_flow::data::email%]",
|
||||
"password": "[%key:common::config_flow::data::password%]",
|
||||
"authorization_code": "Authorization Code (required for manual authentication)"
|
||||
},
|
||||
"title": "Google Chat Login"
|
||||
},
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "2FA PIN"
|
||||
},
|
||||
"title": "2-Factor-Authentication"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Google Hangouts \u0432\u0435\u0447\u0435 \u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u043d",
|
||||
"unknown": "\u0412\u044a\u0437\u043d\u0438\u043a\u043d\u0430 \u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u0430 \u0433\u0440\u0435\u0448\u043a\u0430."
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u0430 2-\u0444\u0430\u043a\u0442\u043e\u0440\u043d\u0430 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u043a\u0430\u0446\u0438\u044f, \u043c\u043e\u043b\u044f, \u043e\u043f\u0438\u0442\u0430\u0439\u0442\u0435 \u043e\u0442\u043d\u043e\u0432\u043e.",
|
||||
"invalid_2fa_method": "\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u0435\u043d \u043c\u0435\u0442\u043e\u0434 2FA (\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0430).",
|
||||
"invalid_login": "\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u043e \u0432\u043b\u0438\u0437\u0430\u043d\u0435, \u043c\u043e\u043b\u044f, \u043e\u043f\u0438\u0442\u0430\u0439\u0442\u0435 \u043e\u0442\u043d\u043e\u0432\u043e."
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "2FA PIN"
|
||||
},
|
||||
"title": "\u0414\u0432\u0443-\u0444\u0430\u043a\u0442\u043e\u0440\u043d\u0430 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u043a\u0430\u0446\u0438\u044f"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"authorization_code": "\u041a\u043e\u0434 \u0437\u0430 \u043e\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f (\u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0437\u0430 \u0440\u044a\u0447\u043d\u043e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u043a\u0438\u0440\u0430\u043d\u0435)",
|
||||
"email": "\u0418\u043c\u0435\u0439\u043b",
|
||||
"password": "\u041f\u0430\u0440\u043e\u043b\u0430"
|
||||
},
|
||||
"title": "\u0412\u0445\u043e\u0434 \u0432 Google Hangouts"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "El servei ja est\u00e0 configurat",
|
||||
"unknown": "Error inesperat"
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "La verificaci\u00f3 en dos passos no \u00e9s v\u00e0lida, torna-ho a provar.",
|
||||
"invalid_2fa_method": "M\u00e8tode 2FA inv\u00e0lid (verifica-ho al m\u00f2bil).",
|
||||
"invalid_login": "L'inici de sessi\u00f3 no \u00e9s v\u00e0lid, torna-ho a provar."
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "PIN 2FA"
|
||||
},
|
||||
"description": "Buit",
|
||||
"title": "Verificaci\u00f3 en dos passos"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"authorization_code": "Codi d'autoritzaci\u00f3 (necessari per a l'autenticaci\u00f3 manual)",
|
||||
"email": "Correu electr\u00f2nic",
|
||||
"password": "Contrasenya"
|
||||
},
|
||||
"description": "Buit",
|
||||
"title": "Inici de sessi\u00f3 de Google Chat"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Slu\u017eba je ji\u017e nastavena",
|
||||
"unknown": "Neo\u010dek\u00e1van\u00e1 chyba"
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "Dfoufaktorov\u00e9 ov\u011b\u0159en\u00ed se nezda\u0159ilo. Zkuste to znovu.",
|
||||
"invalid_2fa_method": "Neplatn\u00e1 metoda 2FA (ov\u011b\u0159en\u00ed na telefonu).",
|
||||
"invalid_login": "Neplatn\u00e9 p\u0159ihla\u0161ovac\u00ed jm\u00e9no, pros\u00edm zkuste to znovu."
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "Dvoufaktorov\u00fd ov\u011b\u0159ovac\u00ed k\u00f3d"
|
||||
},
|
||||
"description": "Pr\u00e1zdn\u00e9",
|
||||
"title": "Dvoufaktorov\u00e9 ov\u011b\u0159en\u00ed"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"authorization_code": "Autoriza\u010dn\u00ed k\u00f3d (vy\u017eadov\u00e1n pro ru\u010dn\u00ed ov\u011b\u0159en\u00ed)",
|
||||
"email": "E-mail",
|
||||
"password": "Heslo"
|
||||
},
|
||||
"description": "Pr\u00e1zdn\u00e9",
|
||||
"title": "P\u0159ihl\u00e1\u0161en\u00ed do slu\u017eby Google Hangouts"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Google Hangouts er allerede konfigureret",
|
||||
"unknown": "Ukendt fejl opstod"
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "Ugyldig tofaktor-godkendelse, pr\u00f8v igen.",
|
||||
"invalid_2fa_method": "Ugyldig 2FA-metode (Bekr\u00e6ft p\u00e5 telefon).",
|
||||
"invalid_login": "Ugyldig login, pr\u00f8v venligst igen."
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "2FA pin"
|
||||
},
|
||||
"title": "Tofaktor-godkendelse"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"authorization_code": "Godkendelseskode (kr\u00e6vet til manuel godkendelse)",
|
||||
"email": "Emailadresse",
|
||||
"password": "Adgangskode"
|
||||
},
|
||||
"title": "Google Hangouts login"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Der Dienst ist bereits konfiguriert",
|
||||
"unknown": "Unerwarteter Fehler"
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "Ung\u00fcltige 2-Faktor Authentifizierung, bitte versuche es erneut.",
|
||||
"invalid_2fa_method": "Ung\u00fcltige 2FA Methode (mit Telefon verifizieren)",
|
||||
"invalid_login": "Ung\u00fcltiges Login, bitte versuche es erneut."
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "2FA PIN"
|
||||
},
|
||||
"description": "Leer",
|
||||
"title": "2-Faktor-Authentifizierung"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"authorization_code": "Autorisierungscode (f\u00fcr die manuelle Authentifizierung erforderlich)",
|
||||
"email": "E-Mail",
|
||||
"password": "Passwort"
|
||||
},
|
||||
"description": "Leer",
|
||||
"title": "Google Chat Anmeldung"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "\u0397 \u03c5\u03c0\u03b7\u03c1\u03b5\u03c3\u03af\u03b1 \u03ad\u03c7\u03b5\u03b9 \u03ae\u03b4\u03b7 \u03c1\u03c5\u03b8\u03bc\u03b9\u03c3\u03c4\u03b5\u03af",
|
||||
"unknown": "\u0391\u03c0\u03c1\u03cc\u03c3\u03bc\u03b5\u03bd\u03bf \u03c3\u03c6\u03ac\u03bb\u03bc\u03b1"
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "\u039c\u03b7 \u03ad\u03b3\u03ba\u03c5\u03c1\u03bf\u03c2 \u03ad\u03bb\u03b5\u03b3\u03c7\u03bf\u03c2 \u03c4\u03b1\u03c5\u03c4\u03cc\u03c4\u03b7\u03c4\u03b1\u03c2 2 \u03c0\u03b1\u03c1\u03b1\u03b3\u03cc\u03bd\u03c4\u03c9\u03bd, \u03b4\u03bf\u03ba\u03b9\u03bc\u03ac\u03c3\u03c4\u03b5 \u03be\u03b1\u03bd\u03ac.",
|
||||
"invalid_2fa_method": "\u039c\u03b7 \u03ad\u03b3\u03ba\u03c5\u03c1\u03b7 \u03bc\u03ad\u03b8\u03bf\u03b4\u03bf\u03c2 2FA (\u03b5\u03c0\u03b1\u03bb\u03ae\u03b8\u03b5\u03c5\u03c3\u03b7 \u03c3\u03c4\u03bf \u03c4\u03b7\u03bb\u03ad\u03c6\u03c9\u03bd\u03bf).",
|
||||
"invalid_login": "\u039c\u03b7 \u03ad\u03b3\u03ba\u03c5\u03c1\u03b7 \u03c3\u03cd\u03bd\u03b4\u03b5\u03c3\u03b7, \u03b4\u03bf\u03ba\u03b9\u03bc\u03ac\u03c3\u03c4\u03b5 \u03be\u03b1\u03bd\u03ac."
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "\u039a\u03c9\u03b4\u03b9\u03ba\u03cc\u03c2 PIN \u03c0\u03b9\u03c3\u03c4\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7\u03c2 2 \u03c0\u03b1\u03c1\u03b1\u03b3\u03cc\u03bd\u03c4\u03c9\u03bd"
|
||||
},
|
||||
"description": "\u039a\u03b5\u03bd\u03cc",
|
||||
"title": "\u03a0\u03b9\u03c3\u03c4\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 2 \u03c0\u03b1\u03c1\u03b1\u03b3\u03cc\u03bd\u03c4\u03c9\u03bd"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"authorization_code": "\u039a\u03c9\u03b4\u03b9\u03ba\u03cc\u03c2 \u03b5\u03be\u03bf\u03c5\u03c3\u03b9\u03bf\u03b4\u03cc\u03c4\u03b7\u03c3\u03b7\u03c2 (\u03b1\u03c0\u03b1\u03b9\u03c4\u03b5\u03af\u03c4\u03b1\u03b9 \u03b3\u03b9\u03b1 \u03c7\u03b5\u03b9\u03c1\u03bf\u03ba\u03af\u03bd\u03b7\u03c4\u03bf \u03ad\u03bb\u03b5\u03b3\u03c7\u03bf \u03c4\u03b1\u03c5\u03c4\u03cc\u03c4\u03b7\u03c4\u03b1\u03c2)",
|
||||
"email": "Email",
|
||||
"password": "\u039a\u03c9\u03b4\u03b9\u03ba\u03cc\u03c2 \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7\u03c2"
|
||||
},
|
||||
"description": "\u039a\u03b5\u03bd\u03cc",
|
||||
"title": "\u03a3\u03cd\u03bd\u03b4\u03b5\u03c3\u03b7 Google Hangouts"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Service is already configured",
|
||||
"unknown": "Unexpected error"
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "Invalid 2 Factor Authentication, please try again.",
|
||||
"invalid_2fa_method": "Invalid 2FA Method (verify on Phone).",
|
||||
"invalid_login": "Invalid Login, please try again."
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "2FA PIN"
|
||||
},
|
||||
"title": "2-Factor-Authentication"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"authorization_code": "Authorization Code (required for manual authentication)",
|
||||
"email": "Email",
|
||||
"password": "Password"
|
||||
},
|
||||
"title": "Google Chat Login"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Google Hangouts ya est\u00e1 configurado",
|
||||
"unknown": "Se produjo un error desconocido."
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "Autenticaci\u00f3n de 2 factores no v\u00e1lida, intente nuevamente.",
|
||||
"invalid_2fa_method": "M\u00e9todo 2FA no v\u00e1lido (verificar en el tel\u00e9fono).",
|
||||
"invalid_login": "Inicio de sesi\u00f3n no v\u00e1lido, por favor, int\u00e9ntalo de nuevo."
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "Pin 2FA"
|
||||
},
|
||||
"title": "Autenticaci\u00f3n de 2 factores"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"authorization_code": "C\u00f3digo de autorizaci\u00f3n (requerido para la autenticaci\u00f3n manual)",
|
||||
"email": "Direcci\u00f3n de correo electr\u00f3nico",
|
||||
"password": "Contrase\u00f1a"
|
||||
},
|
||||
"title": "Inicio de sesi\u00f3n de Google Hangouts"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "El servicio ya est\u00e1 configurado",
|
||||
"unknown": "Error inesperado"
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "Autenticaci\u00f3n de 2 factores no v\u00e1lida, por favor, int\u00e9ntalo de nuevo.",
|
||||
"invalid_2fa_method": "M\u00e9todo 2FA no v\u00e1lido (verificar en el tel\u00e9fono).",
|
||||
"invalid_login": "Inicio de sesi\u00f3n no v\u00e1lido, por favor, int\u00e9ntalo de nuevo."
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "PIN 2FA"
|
||||
},
|
||||
"title": "Autenticaci\u00f3n de 2 factores"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"authorization_code": "C\u00f3digo de autorizaci\u00f3n (requerido para la autenticaci\u00f3n manual)",
|
||||
"email": "Correo electr\u00f3nico",
|
||||
"password": "Contrase\u00f1a"
|
||||
},
|
||||
"title": "Inicio de sesi\u00f3n de Google Chat"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Teenus on juba seadistatud",
|
||||
"unknown": "Tundmatu viga"
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "Vale 2-teguriline autentimine, proovi uuesti.",
|
||||
"invalid_2fa_method": "Kehtetu kaheastmelise tuvastuse meetod (kontrolli telefonistl).",
|
||||
"invalid_login": "Vale kasutajanimi, palun proovi uuesti."
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "Kaheastmelise tuvastuse PIN"
|
||||
},
|
||||
"description": "",
|
||||
"title": "Kaheastmeline autentimine"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"authorization_code": "Autoriseerimiskood (vajalik k\u00e4sitsi autentimiseks)",
|
||||
"email": "E-posti aadress",
|
||||
"password": "Salas\u00f5na"
|
||||
},
|
||||
"description": "",
|
||||
"title": "Google Chat'i sisselogimine"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"unknown": "Tapahtui tuntematon virhe."
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "Virheellinen kaksitekij\u00e4todennus, yrit\u00e4 uudelleen.",
|
||||
"invalid_2fa_method": "Virheellinen 2FA-menetelm\u00e4 (tarkista puhelimessa).",
|
||||
"invalid_login": "Virheellinen kirjautuminen, yrit\u00e4 uudelleen."
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "2FA-pin"
|
||||
},
|
||||
"description": "Tyhj\u00e4",
|
||||
"title": "Kaksivaiheinen tunnistus"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"email": "S\u00e4hk\u00f6postiosoite",
|
||||
"password": "Salasana"
|
||||
},
|
||||
"description": "Tyhj\u00e4",
|
||||
"title": "Google Hangouts -kirjautuminen"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Le service est d\u00e9j\u00e0 configur\u00e9",
|
||||
"unknown": "Erreur inattendue"
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "Authentification \u00e0 deux facteurs non valide, veuillez r\u00e9essayer.",
|
||||
"invalid_2fa_method": "M\u00e9thode 2FA non valide (v\u00e9rifiez sur le t\u00e9l\u00e9phone).",
|
||||
"invalid_login": "Identifiant non valide, veuillez r\u00e9essayer."
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "Code NIP d'authentification \u00e0 2 facteurs"
|
||||
},
|
||||
"description": "Vide",
|
||||
"title": "Authentification \u00e0 2 facteurs"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"authorization_code": "Code d'autorisation (requis pour l'authentification manuelle)",
|
||||
"email": "Courriel",
|
||||
"password": "Mot de passe"
|
||||
},
|
||||
"description": "Vide",
|
||||
"title": "Connexion \u00e0 Google Chat"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "\u05e9\u05d9\u05e8\u05d5\u05ea \u05d6\u05d4 \u05db\u05d1\u05e8 \u05de\u05d5\u05d2\u05d3\u05e8",
|
||||
"unknown": "\u05e9\u05d2\u05d9\u05d0\u05d4 \u05d1\u05dc\u05ea\u05d9 \u05e6\u05e4\u05d5\u05d9\u05d4"
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "\u05d0\u05d9\u05de\u05d5\u05ea \u05d3\u05d5 \u05e9\u05dc\u05d1\u05d9 \u05dc\u05d0 \u05d7\u05d5\u05e7\u05d9, \u05d1\u05d1\u05e7\u05e9\u05d4 \u05e0\u05e1\u05d4 \u05e9\u05d5\u05d1.",
|
||||
"invalid_2fa_method": "\u05d3\u05e8\u05da \u05dc\u05d0\u05d9\u05de\u05d5\u05ea \u05d3\u05d5 \u05e9\u05dc\u05d1\u05d9 \u05dc\u05d0 \u05d7\u05d5\u05e7\u05d9\u05ea (\u05d0\u05de\u05ea \u05d1\u05d8\u05dc\u05e4\u05d5\u05df).",
|
||||
"invalid_login": "\u05db\u05e0\u05d9\u05e1\u05d4 \u05dc\u05d0 \u05d7\u05d5\u05e7\u05d9\u05ea, \u05e0\u05e1\u05d4 \u05e9\u05d5\u05d1."
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "\u05e7\u05d5\u05d3 \u05d0\u05d9\u05de\u05d5\u05ea \u05d3\u05d5 \u05e9\u05dc\u05d1\u05d9"
|
||||
},
|
||||
"title": "\u05d0\u05d9\u05de\u05d5\u05ea \u05d3\u05d5 \u05e9\u05dc\u05d1\u05d9"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"email": "\u05d3\u05d5\u05d0\"\u05dc",
|
||||
"password": "\u05e1\u05d9\u05e1\u05de\u05d4"
|
||||
},
|
||||
"title": "\u05d4\u05ea\u05d7\u05d1\u05e8\u05d5\u05ea \u05dc\u05e6'\u05d0\u05d8 \u05e9\u05dc \u05d2\u05d5\u05d2\u05dc"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"email": "Email",
|
||||
"password": "Lozinka"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "A szolg\u00e1ltat\u00e1s m\u00e1r konfigur\u00e1lva van",
|
||||
"unknown": "V\u00e1ratlan hiba t\u00f6rt\u00e9nt"
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "\u00c9rv\u00e9nytelen K\u00e9tfaktoros hiteles\u00edt\u00e9s, pr\u00f3b\u00e1ld \u00fajra.",
|
||||
"invalid_2fa_method": "\u00c9rv\u00e9nytelen 2FA M\u00f3dszer (Ellen\u0151rz\u00e9s a Telefonon).",
|
||||
"invalid_login": "\u00c9rv\u00e9nytelen bejelentkez\u00e9s, pr\u00f3b\u00e1ld \u00fajra."
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "2FA PIN"
|
||||
},
|
||||
"description": "\u00dcres",
|
||||
"title": "K\u00e9tfaktoros Hiteles\u00edt\u00e9s"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"authorization_code": "Enged\u00e9lyez\u00e9si k\u00f3d (k\u00e9zi hiteles\u00edt\u00e9shez sz\u00fcks\u00e9ges)",
|
||||
"email": "E-mail",
|
||||
"password": "Jelsz\u00f3"
|
||||
},
|
||||
"description": "\u00dcres",
|
||||
"title": "Google Chat bejelentkez\u00e9s"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Layanan sudah dikonfigurasi",
|
||||
"unknown": "Kesalahan yang tidak diharapkan"
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "Autentikasi 2 Faktor Tidak Valid, coba lagi.",
|
||||
"invalid_2fa_method": "Metode 2FA Tidak Valid (Verifikasikan di Ponsel).",
|
||||
"invalid_login": "Info Masuk Tidak Valid, coba lagi."
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "PIN 2FA"
|
||||
},
|
||||
"description": "Kosong",
|
||||
"title": "Autentikasi Dua Faktor"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"authorization_code": "Kode Otorisasi (diperlukan untuk autentikasi manual)",
|
||||
"email": "Email",
|
||||
"password": "Kata Sandi"
|
||||
},
|
||||
"description": "Kosong",
|
||||
"title": "Info Masuk Google Chat"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Il servizio \u00e8 gi\u00e0 configurato",
|
||||
"unknown": "Errore imprevisto"
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "Autenticazione a 2 fattori non valida, riprova.",
|
||||
"invalid_2fa_method": "Metodo 2FA non valido (verifica sul telefono).",
|
||||
"invalid_login": "Accesso non valido, riprova."
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "2FA PIN"
|
||||
},
|
||||
"description": "Vuoto",
|
||||
"title": "Autenticazione a due fattori"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"authorization_code": "Codice di autorizzazione (necessario per l'autenticazione manuale)",
|
||||
"email": "Email",
|
||||
"password": "Password"
|
||||
},
|
||||
"description": "Vuoto",
|
||||
"title": "Accesso a Google Chat"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "\u30b5\u30fc\u30d3\u30b9\u306f\u3059\u3067\u306b\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u3059",
|
||||
"unknown": "\u4e88\u671f\u3057\u306a\u3044\u30a8\u30e9\u30fc"
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "2\u8981\u7d20\u8a8d\u8a3c\u304c\u7121\u52b9\u3067\u3059\u3002\u3082\u3046\u4e00\u5ea6\u304a\u8a66\u3057\u304f\u3060\u3055\u3044\u3002",
|
||||
"invalid_2fa_method": "2\u8981\u7d20\u8a8d\u8a3c\u304c\u7121\u52b9(\u96fb\u8a71\u3067\u78ba\u8a8d)",
|
||||
"invalid_login": "\u30ed\u30b0\u30a4\u30f3\u3067\u304d\u307e\u305b\u3093\u3001\u3082\u3046\u4e00\u5ea6\u304a\u8a66\u3057\u304f\u3060\u3055\u3044\u3002"
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "2\u8981\u7d20 PIN"
|
||||
},
|
||||
"description": "\u7a7a",
|
||||
"title": "2\u8981\u7d20\u8a8d\u8a3c"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"authorization_code": "\u8a8d\u8a3c\u30b3\u30fc\u30c9(\u624b\u52d5\u8a8d\u8a3c\u6642\u306b\u5fc5\u8981)",
|
||||
"email": "E\u30e1\u30fc\u30eb",
|
||||
"password": "\u30d1\u30b9\u30ef\u30fc\u30c9"
|
||||
},
|
||||
"description": "\u7a7a",
|
||||
"title": "Google \u30cf\u30f3\u30b0\u30a2\u30a6\u30c8 \u30ed\u30b0\u30a4\u30f3"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "\uc11c\ube44\uc2a4\uac00 \uc774\ubbf8 \uad6c\uc131\ub418\uc5c8\uc2b5\ub2c8\ub2e4",
|
||||
"unknown": "\uc608\uc0c1\uce58 \ubabb\ud55c \uc624\ub958\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4"
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "2\ub2e8\uacc4 \uc778\uc99d\uc774 \uc798\ubabb\ub418\uc5c8\uc2b5\ub2c8\ub2e4. \ub2e4\uc2dc \uc2dc\ub3c4\ud574\uc8fc\uc138\uc694.",
|
||||
"invalid_2fa_method": "2\ub2e8\uacc4 \uc778\uc99d \ubc29\ubc95\uc774 \uc798\ubabb\ub418\uc5c8\uc2b5\ub2c8\ub2e4. (\uc804\ud654\uae30\uc5d0\uc11c \ud655\uc778)",
|
||||
"invalid_login": "\ub85c\uadf8\uc778\uc774 \uc798\ubabb\ub418\uc5c8\uc2b5\ub2c8\ub2e4. \ub2e4\uc2dc \uc2dc\ub3c4\ud574\uc8fc\uc138\uc694."
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "2\ub2e8\uacc4 \uc778\uc99d PIN"
|
||||
},
|
||||
"description": "\uc8c4\uc1a1\ud569\ub2c8\ub2e4. \uad00\ub828 \ub0b4\uc6a9\uc774 \uc544\uc9c1 \uc5c5\ub370\uc774\ud2b8 \ub418\uc9c0 \uc54a\uc558\uc2b5\ub2c8\ub2e4. \ucd94\ud6c4\uc5d0 \ubc18\uc601\ub420 \uc608\uc815\uc774\ub2c8 \uc870\uae08\ub9cc \uae30\ub2e4\ub824\uc8fc\uc138\uc694.",
|
||||
"title": "2\ub2e8\uacc4 \uc778\uc99d"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"authorization_code": "\uc778\uc99d \ucf54\ub4dc (\uc218\ub3d9 \uc778\uc99d\uc5d0 \ud544\uc694)",
|
||||
"email": "\uc774\uba54\uc77c",
|
||||
"password": "\ube44\ubc00\ubc88\ud638"
|
||||
},
|
||||
"description": "\uc8c4\uc1a1\ud569\ub2c8\ub2e4. \uad00\ub828 \ub0b4\uc6a9\uc774 \uc544\uc9c1 \uc5c5\ub370\uc774\ud2b8 \ub418\uc9c0 \uc54a\uc558\uc2b5\ub2c8\ub2e4. \ucd94\ud6c4\uc5d0 \ubc18\uc601\ub420 \uc608\uc815\uc774\ub2c8 \uc870\uae08\ub9cc \uae30\ub2e4\ub824\uc8fc\uc138\uc694.",
|
||||
"title": "Google \ud589\uc544\uc6c3 \ub85c\uadf8\uc778"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Service ass scho konfigur\u00e9iert",
|
||||
"unknown": "Onerwaarte Feeler"
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "Ong\u00eblteg 2-Faktor Authentifikatioun, prob\u00e9iert w.e.g. nach emol.",
|
||||
"invalid_2fa_method": "Ong\u00eblteg 2FA Methode (Iwwerpr\u00e9ift et um Telefon)",
|
||||
"invalid_login": "Ong\u00ebltege Login, prob\u00e9iert w.e.g. nach emol."
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "2FA Pin"
|
||||
},
|
||||
"description": "Eidel",
|
||||
"title": "2-Faktor-Authentifikatioun"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"authorization_code": "Autorisatioun's Code (n\u00e9ideg fir eng manuell Authentifikatioun)",
|
||||
"email": "E-Mail",
|
||||
"password": "Passwuert"
|
||||
},
|
||||
"description": "Eidel",
|
||||
"title": "Google Hangouts Login"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "2FA PIN"
|
||||
},
|
||||
"title": "2 veiksni\u0173 autentifikavimas"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"unknown": "Uventet feil"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Dienst is al geconfigureerd",
|
||||
"unknown": "Onverwachte fout"
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "Ongeldige twee-factor-authenticatie, probeer het opnieuw.",
|
||||
"invalid_2fa_method": "Ongeldige 2FA-methode (verifi\u00ebren op telefoon).",
|
||||
"invalid_login": "Ongeldige aanmelding, probeer het opnieuw."
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "2FA pin"
|
||||
},
|
||||
"description": "Leeg",
|
||||
"title": "Twee-factor-authenticatie"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"authorization_code": "Autorisatiecode (vereist voor handmatige authenticatie)",
|
||||
"email": "E-mail",
|
||||
"password": "Wachtwoord"
|
||||
},
|
||||
"description": "Leeg",
|
||||
"title": "Google Chat-login"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Google Hangouts er allereie konfigurert",
|
||||
"unknown": "Det hende ein ukjent feil"
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "Ugyldig to-faktor-autentisering. Ver vennleg og pr\u00f8v igjen.",
|
||||
"invalid_2fa_method": "Ugyldig 2FA-metode (godkjenn p\u00e5 telefonen).",
|
||||
"invalid_login": "Ugyldig innlogging. Pr\u00f8v igjen."
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "2FA PIN"
|
||||
},
|
||||
"title": "To-faktor-autentisering"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"email": "Epostadresse",
|
||||
"password": "Passord"
|
||||
},
|
||||
"title": "Google Hangouts Login"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Tjenesten er allerede konfigurert",
|
||||
"unknown": "Uventet feil"
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "Ugyldig totrinnsbekreftelse, vennligst pr\u00f8v igjen.",
|
||||
"invalid_2fa_method": "Ugyldig 2FA-metode (bekreft p\u00e5 telefon).",
|
||||
"invalid_login": "Ugyldig innlogging, vennligst pr\u00f8v igjen."
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "2FA PIN"
|
||||
},
|
||||
"description": "",
|
||||
"title": "Totrinnsbekreftelse"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"authorization_code": "Godkjenningskode (kreves for manuell godkjenning)",
|
||||
"email": "E-post",
|
||||
"password": "Passord"
|
||||
},
|
||||
"description": "",
|
||||
"title": "Google Chat-p\u00e5logging"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Us\u0142uga jest ju\u017c skonfigurowana",
|
||||
"unknown": "Nieoczekiwany b\u0142\u0105d"
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "Nieprawid\u0142owe uwierzytelnienie dwusk\u0142adnikowe, spr\u00f3buj ponownie",
|
||||
"invalid_2fa_method": "Nieprawid\u0142owa metoda uwierzytelniania dwusk\u0142adnikowego (u\u017cyj weryfikacji przez telefon)",
|
||||
"invalid_login": "Nieprawid\u0142owy login, spr\u00f3buj ponownie"
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "Kod uwierzytelniania dwusk\u0142adnikowego"
|
||||
},
|
||||
"description": "Pusty",
|
||||
"title": "Uwierzytelnianie dwusk\u0142adnikowe"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"authorization_code": "Kod autoryzacji (wymagany do r\u0119cznego uwierzytelnienia)",
|
||||
"email": "Adres e-mail",
|
||||
"password": "Has\u0142o"
|
||||
},
|
||||
"description": "Pusty",
|
||||
"title": "Logowanie do Google Chat"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "O servi\u00e7o j\u00e1 est\u00e1 configurado",
|
||||
"unknown": "Erro inesperado"
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "Autentica\u00e7\u00e3o de 2 fatores inv\u00e1lida, por favor, tente novamente.",
|
||||
"invalid_2fa_method": "M\u00e9todo 2FA inv\u00e1lido (verificar no telefone).",
|
||||
"invalid_login": "Login inv\u00e1lido, por favor, tente novamente."
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "C\u00f3digo 2FA"
|
||||
},
|
||||
"description": "Vazio",
|
||||
"title": "Autentica\u00e7\u00e3o de 2 Fatores"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"authorization_code": "C\u00f3digo de Autoriza\u00e7\u00e3o (requerido para autentica\u00e7\u00e3o manual)",
|
||||
"email": "Email",
|
||||
"password": "Senha"
|
||||
},
|
||||
"description": "Vazio",
|
||||
"title": "Login no Google Chat"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Google Hangouts j\u00e1 est\u00e1 configurado",
|
||||
"unknown": "Erro inesperado"
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "Autentica\u00e7\u00e3o por 2 fatores inv\u00e1lida, por favor, tente novamente.",
|
||||
"invalid_2fa_method": "M\u00e9todo 2FA inv\u00e1lido (verificar no telefone).",
|
||||
"invalid_login": "Login inv\u00e1lido, por favor, tente novamente."
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "Pin 2FA"
|
||||
},
|
||||
"description": "Vazio",
|
||||
"title": "Autentica\u00e7\u00e3o de 2 Fatores"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"email": "E-mail",
|
||||
"password": "Palavra-passe"
|
||||
},
|
||||
"description": "Vazio",
|
||||
"title": "Login Google Hangouts"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Google Hangouts este deja configurat",
|
||||
"unknown": "Sa produs o eroare necunoscut\u0103."
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa_method": "Metoda 2FA invalid\u0103 (Verifica\u021bi pe telefon).",
|
||||
"invalid_login": "Conectare invalid\u0103, \u00eencerca\u021bi din nou."
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "2FA Pin"
|
||||
}
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"email": "Adresa de email",
|
||||
"password": "Parol\u0103"
|
||||
},
|
||||
"description": "Gol",
|
||||
"title": "Conectare Google Hangouts"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "\u042d\u0442\u0430 \u0441\u043b\u0443\u0436\u0431\u0430 \u0443\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0430 \u0432 Home Assistant.",
|
||||
"unknown": "\u041d\u0435\u043f\u0440\u0435\u0434\u0432\u0438\u0434\u0435\u043d\u043d\u0430\u044f \u043e\u0448\u0438\u0431\u043a\u0430."
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "\u041d\u0435\u0432\u0435\u0440\u043d\u0430\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0441\u043d\u043e\u0432\u0430.",
|
||||
"invalid_2fa_method": "\u041d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0434\u0432\u0443\u0445\u0444\u0430\u043a\u0442\u043e\u0440\u043d\u043e\u0439 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 (\u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043d\u0430 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0435).",
|
||||
"invalid_login": "\u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u043b\u043e\u0433\u0438\u043d, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0441\u043d\u043e\u0432\u0430."
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "\u041f\u0438\u043d-\u043a\u043e\u0434 \u0434\u043b\u044f \u0434\u0432\u0443\u0445\u0444\u0430\u043a\u0442\u043e\u0440\u043d\u043e\u0439 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438"
|
||||
},
|
||||
"description": "\u043f\u0443\u0441\u0442\u043e",
|
||||
"title": "\u0414\u0432\u0443\u0445\u0444\u0430\u043a\u0442\u043e\u0440\u043d\u0430\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"authorization_code": "\u041a\u043e\u0434 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 (\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0440\u0443\u0447\u043d\u043e\u0439 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438)",
|
||||
"email": "\u0410\u0434\u0440\u0435\u0441 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b",
|
||||
"password": "\u041f\u0430\u0440\u043e\u043b\u044c"
|
||||
},
|
||||
"description": "\u043f\u0443\u0441\u0442\u043e",
|
||||
"title": "Google Chat"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"email": "Email",
|
||||
"password": "Heslo"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Google Hangouts je \u017ee konfiguriran",
|
||||
"unknown": "Pri\u0161lo je do neznane napake"
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "Neveljavna 2FA avtorizacija, prosimo, poskusite znova.",
|
||||
"invalid_2fa_method": "Neveljavna 2FA Metoda (Preverite na Telefonu).",
|
||||
"invalid_login": "Neveljavna Prijava, prosimo, poskusite znova."
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "2FA Pin"
|
||||
},
|
||||
"description": "prazno",
|
||||
"title": "Dvofaktorska avtorizacija"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"authorization_code": "Koda pooblastila (potrebna za ro\u010dno overjanje)",
|
||||
"email": "E-po\u0161tni naslov",
|
||||
"password": "Geslo"
|
||||
},
|
||||
"description": "prazno",
|
||||
"title": "Prijava za Google Hangouts"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Google Hangouts \u00e4r redan inst\u00e4llt",
|
||||
"unknown": "Ett ok\u00e4nt fel intr\u00e4ffade"
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "Ogiltig 2FA autentisering, f\u00f6rs\u00f6k igen.",
|
||||
"invalid_2fa_method": "Ogiltig 2FA-metod (Verifiera med telefon).",
|
||||
"invalid_login": "Ogiltig inloggning, f\u00f6rs\u00f6k igen."
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "2FA Pinkod"
|
||||
},
|
||||
"description": "Missing english translation",
|
||||
"title": "Tv\u00e5faktorsautentisering"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"authorization_code": "Auktoriseringskod (kr\u00e4vs vid manuell verifiering)",
|
||||
"email": "E-postadress",
|
||||
"password": "L\u00f6senord"
|
||||
},
|
||||
"description": "Missing english translation",
|
||||
"title": "Google Hangouts-inloggning"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"2fa": {
|
||||
"title": "\u0e23\u0e2b\u0e31\u0e2a\u0e23\u0e31\u0e1a\u0e23\u0e2d\u0e07\u0e04\u0e27\u0e32\u0e21\u0e16\u0e39\u0e01\u0e15\u0e49\u0e2d\u0e07\u0e2a\u0e2d\u0e07\u0e1b\u0e31\u0e08\u0e08\u0e31\u0e22"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"email": "\u0e17\u0e35\u0e48\u0e2d\u0e22\u0e39\u0e48\u0e2d\u0e35\u0e40\u0e21\u0e25",
|
||||
"password": "\u0e23\u0e2b\u0e31\u0e2a\u0e1c\u0e48\u0e32\u0e19"
|
||||
},
|
||||
"description": "\u0e27\u0e48\u0e32\u0e07\u0e40\u0e1b\u0e25\u0e48\u0e32"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Hizmet zaten yap\u0131land\u0131r\u0131lm\u0131\u015f",
|
||||
"unknown": "Beklenmeyen hata"
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "Ge\u00e7ersiz 2 Fakt\u00f6rl\u00fc Kimlik Do\u011frulama, l\u00fctfen tekrar deneyin.",
|
||||
"invalid_2fa_method": "Ge\u00e7ersiz 2FA Y\u00f6ntemi (Telefonda do\u011frulay\u0131n).",
|
||||
"invalid_login": "Ge\u00e7ersiz Giri\u015f, l\u00fctfen tekrar deneyin."
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "2FA PIN'i"
|
||||
},
|
||||
"description": "Bo\u015f",
|
||||
"title": "2-Fakt\u00f6rl\u00fc Kimlik Do\u011frulama"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"authorization_code": "Yetkilendirme Kodu (manuel kimlik do\u011frulama i\u00e7in gereklidir)",
|
||||
"email": "E-posta",
|
||||
"password": "Parola"
|
||||
},
|
||||
"description": "Bo\u015f",
|
||||
"title": "Google Sohbet Giri\u015fi"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "\u0426\u044f \u0441\u043b\u0443\u0436\u0431\u0430 \u0432\u0436\u0435 \u0434\u043e\u0434\u0430\u043d\u0430 \u0432 Home Assistant.",
|
||||
"unknown": "\u041d\u0435\u043e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430"
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "\u041d\u0435\u0432\u0456\u0440\u043d\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0456\u044f, \u0431\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u0441\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0437\u043d\u043e\u0432\u0443.",
|
||||
"invalid_2fa_method": "\u041d\u0435\u043f\u0440\u0438\u043f\u0443\u0441\u0442\u0438\u043c\u0438\u0439 \u0441\u043f\u043e\u0441\u0456\u0431 \u0434\u0432\u043e\u0444\u0430\u043a\u0442\u043e\u0440\u043d\u043e\u0457 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0456\u043a\u0430\u0446\u0456\u0457 (\u043f\u0435\u0440\u0435\u0432\u0456\u0440\u0438\u0442\u0438 \u043d\u0430 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0456).",
|
||||
"invalid_login": "\u041d\u0435\u0432\u0456\u0440\u043d\u0438\u0439 \u043b\u043e\u0433\u0456\u043d, \u0431\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u0441\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0437\u043d\u043e\u0432\u0443."
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "\u041f\u0456\u043d-\u043a\u043e\u0434 \u0434\u043b\u044f \u0434\u0432\u043e\u0444\u0430\u043a\u0442\u043e\u0440\u043d\u043e\u0457 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0456\u043a\u0430\u0446\u0456\u0457"
|
||||
},
|
||||
"description": "\u043f\u043e\u0440\u043e\u0436\u043d\u044c\u043e",
|
||||
"title": "\u0414\u0432\u043e\u0444\u0430\u043a\u0442\u043e\u0440\u043d\u0430 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0456\u043a\u0430\u0446\u0456\u044f"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"authorization_code": "\u041a\u043e\u0434 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0456\u0457 (\u0432\u0438\u043c\u0430\u0433\u0430\u0454\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0440\u0443\u0447\u043d\u043e\u0457 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0456\u043a\u0430\u0446\u0456\u0457)",
|
||||
"email": "\u0410\u0434\u0440\u0435\u0441\u0430 \u0435\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0457 \u043f\u043e\u0448\u0442\u0438",
|
||||
"password": "\u041f\u0430\u0440\u043e\u043b\u044c"
|
||||
},
|
||||
"description": "\u043f\u043e\u0440\u043e\u0436\u043d\u044c\u043e",
|
||||
"title": "Google Hangouts"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"error": {
|
||||
"invalid_2fa_method": "Ph\u01b0\u01a1ng ph\u00e1p 2FA kh\u00f4ng h\u1ee3p l\u1ec7 (X\u00e1c minh tr\u00ean \u0111i\u1ec7n tho\u1ea1i)."
|
||||
}
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Google Hangouts \u5df2\u914d\u7f6e\u5b8c\u6210",
|
||||
"unknown": "\u53d1\u751f\u672a\u77e5\u9519\u8bef\u3002"
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "\u53cc\u91cd\u8ba4\u8bc1\u5931\u8d25\uff0c\u8bf7\u91cd\u8bd5\u3002",
|
||||
"invalid_2fa_method": "\u65e0\u6548\u7684\u53cc\u91cd\u8ba4\u8bc1\u65b9\u6cd5\uff08\u7535\u8bdd\u9a8c\u8bc1\uff09\u3002",
|
||||
"invalid_login": "\u767b\u9646\u5931\u8d25\uff0c\u8bf7\u518d\u8bd5\u4e00\u6b21\u3002"
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "2FA Pin"
|
||||
},
|
||||
"description": "\u65e0",
|
||||
"title": "\u53cc\u91cd\u8ba4\u8bc1"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"email": "\u7535\u5b50\u90ae\u4ef6\u5730\u5740",
|
||||
"password": "\u5bc6\u7801"
|
||||
},
|
||||
"description": "\u65e0",
|
||||
"title": "\u767b\u5f55 Google Hangouts"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "\u670d\u52d9\u5df2\u7d93\u8a2d\u5b9a\u5b8c\u6210",
|
||||
"unknown": "\u672a\u9810\u671f\u932f\u8aa4"
|
||||
},
|
||||
"error": {
|
||||
"invalid_2fa": "\u96d9\u91cd\u8a8d\u8b49\u7121\u6548\uff0c\u8acb\u518d\u8a66\u4e00\u6b21\u3002",
|
||||
"invalid_2fa_method": "\u5169\u968e\u6bb5\u8a8d\u8b49\u65b9\u5f0f\u7121\u6548\uff08\u65bc\u96fb\u8a71\u4e0a\u9a57\u8b49\uff09\u3002",
|
||||
"invalid_login": "\u767b\u5165\u5931\u6557\uff0c\u8acb\u518d\u8a66\u4e00\u6b21\u3002"
|
||||
},
|
||||
"step": {
|
||||
"2fa": {
|
||||
"data": {
|
||||
"2fa": "\u5169\u968e\u6bb5\u8a8d\u8b49\u78bc"
|
||||
},
|
||||
"description": "\u7a7a\u767d",
|
||||
"title": "\u96d9\u91cd\u8a8d\u8b49"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"authorization_code": "\u9a57\u8b49\u78bc\uff08\u624b\u52d5\u9a57\u8b49\u5fc5\u9808\uff09",
|
||||
"email": "\u96fb\u5b50\u90f5\u4ef6",
|
||||
"password": "\u5bc6\u78bc"
|
||||
},
|
||||
"description": "\u7a7a\u767d",
|
||||
"title": "\u767b\u5165 Google Chat"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -162,7 +162,6 @@ FLOWS = {
|
||||
"growatt_server",
|
||||
"guardian",
|
||||
"habitica",
|
||||
"hangouts",
|
||||
"harmony",
|
||||
"heos",
|
||||
"here_travel_time",
|
||||
|
@ -2022,12 +2022,6 @@
|
||||
"iot_class": "local_polling",
|
||||
"name": "Google Cast"
|
||||
},
|
||||
"hangouts": {
|
||||
"integration_type": "hub",
|
||||
"config_flow": true,
|
||||
"iot_class": "cloud_push",
|
||||
"name": "Google Chat"
|
||||
},
|
||||
"dialogflow": {
|
||||
"integration_type": "hub",
|
||||
"config_flow": true,
|
||||
|
@ -847,9 +847,6 @@ ha-philipsjs==2.9.0
|
||||
# homeassistant.components.habitica
|
||||
habitipy==0.2.0
|
||||
|
||||
# homeassistant.components.hangouts
|
||||
hangups==0.4.18
|
||||
|
||||
# homeassistant.components.cloud
|
||||
hass-nabucasa==0.56.0
|
||||
|
||||
|
@ -639,9 +639,6 @@ ha-philipsjs==2.9.0
|
||||
# homeassistant.components.habitica
|
||||
habitipy==0.2.0
|
||||
|
||||
# homeassistant.components.hangouts
|
||||
hangups==0.4.18
|
||||
|
||||
# homeassistant.components.cloud
|
||||
hass-nabucasa==0.56.0
|
||||
|
||||
|
@ -1 +0,0 @@
|
||||
"""Tests for the Hangouts Component."""
|
@ -1,132 +0,0 @@
|
||||
"""Tests for the Google Hangouts config flow."""
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
from homeassistant import data_entry_flow
|
||||
from homeassistant.components.hangouts import config_flow
|
||||
from homeassistant.const import CONF_EMAIL, CONF_PASSWORD
|
||||
|
||||
EMAIL = "test@test.com"
|
||||
PASSWORD = "1232456"
|
||||
|
||||
|
||||
async def test_flow_works(hass, aioclient_mock):
|
||||
"""Test config flow without 2fa."""
|
||||
flow = config_flow.HangoutsFlowHandler()
|
||||
|
||||
flow.hass = hass
|
||||
|
||||
with patch("homeassistant.components.hangouts.config_flow.get_auth"):
|
||||
result = await flow.async_step_user(
|
||||
{CONF_EMAIL: EMAIL, CONF_PASSWORD: PASSWORD}
|
||||
)
|
||||
assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == EMAIL
|
||||
|
||||
|
||||
async def test_flow_works_with_authcode(hass, aioclient_mock):
|
||||
"""Test config flow without 2fa."""
|
||||
flow = config_flow.HangoutsFlowHandler()
|
||||
|
||||
flow.hass = hass
|
||||
|
||||
with patch("homeassistant.components.hangouts.config_flow.get_auth"):
|
||||
result = await flow.async_step_user(
|
||||
{
|
||||
CONF_EMAIL: EMAIL,
|
||||
CONF_PASSWORD: PASSWORD,
|
||||
"authorization_code": "c29tZXJhbmRvbXN0cmluZw==",
|
||||
}
|
||||
)
|
||||
assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == EMAIL
|
||||
|
||||
|
||||
async def test_flow_works_with_2fa(hass, aioclient_mock):
|
||||
"""Test config flow with 2fa."""
|
||||
from homeassistant.components.hangouts.hangups_utils import Google2FAError
|
||||
|
||||
flow = config_flow.HangoutsFlowHandler()
|
||||
|
||||
flow.hass = hass
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.hangouts.config_flow.get_auth",
|
||||
side_effect=Google2FAError,
|
||||
):
|
||||
result = await flow.async_step_user(
|
||||
{CONF_EMAIL: EMAIL, CONF_PASSWORD: PASSWORD}
|
||||
)
|
||||
assert result["type"] == data_entry_flow.FlowResultType.FORM
|
||||
assert result["step_id"] == "2fa"
|
||||
|
||||
with patch("homeassistant.components.hangouts.config_flow.get_auth"):
|
||||
result = await flow.async_step_2fa({"2fa": 123456})
|
||||
assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == EMAIL
|
||||
|
||||
|
||||
async def test_flow_with_unknown_2fa(hass, aioclient_mock):
|
||||
"""Test config flow with invalid 2fa method."""
|
||||
from homeassistant.components.hangouts.hangups_utils import GoogleAuthError
|
||||
|
||||
flow = config_flow.HangoutsFlowHandler()
|
||||
|
||||
flow.hass = hass
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.hangouts.config_flow.get_auth",
|
||||
side_effect=GoogleAuthError("Unknown verification code input"),
|
||||
):
|
||||
result = await flow.async_step_user(
|
||||
{CONF_EMAIL: EMAIL, CONF_PASSWORD: PASSWORD}
|
||||
)
|
||||
assert result["type"] == data_entry_flow.FlowResultType.FORM
|
||||
assert result["errors"]["base"] == "invalid_2fa_method"
|
||||
|
||||
|
||||
async def test_flow_invalid_login(hass, aioclient_mock):
|
||||
"""Test config flow with invalid 2fa method."""
|
||||
from homeassistant.components.hangouts.hangups_utils import GoogleAuthError
|
||||
|
||||
flow = config_flow.HangoutsFlowHandler()
|
||||
|
||||
flow.hass = hass
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.hangouts.config_flow.get_auth",
|
||||
side_effect=GoogleAuthError,
|
||||
):
|
||||
result = await flow.async_step_user(
|
||||
{CONF_EMAIL: EMAIL, CONF_PASSWORD: PASSWORD}
|
||||
)
|
||||
assert result["type"] == data_entry_flow.FlowResultType.FORM
|
||||
assert result["errors"]["base"] == "invalid_login"
|
||||
|
||||
|
||||
async def test_flow_invalid_2fa(hass, aioclient_mock):
|
||||
"""Test config flow with 2fa."""
|
||||
from homeassistant.components.hangouts.hangups_utils import Google2FAError
|
||||
|
||||
flow = config_flow.HangoutsFlowHandler()
|
||||
|
||||
flow.hass = hass
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.hangouts.config_flow.get_auth",
|
||||
side_effect=Google2FAError,
|
||||
):
|
||||
result = await flow.async_step_user(
|
||||
{CONF_EMAIL: EMAIL, CONF_PASSWORD: PASSWORD}
|
||||
)
|
||||
assert result["type"] == data_entry_flow.FlowResultType.FORM
|
||||
assert result["step_id"] == "2fa"
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.hangouts.config_flow.get_auth",
|
||||
side_effect=Google2FAError,
|
||||
):
|
||||
result = await flow.async_step_2fa({"2fa": 123456})
|
||||
|
||||
assert result["type"] == data_entry_flow.FlowResultType.FORM
|
||||
assert result["errors"]["base"] == "invalid_2fa"
|
Loading…
x
Reference in New Issue
Block a user