def test_create_matcher(): """Test the create matcher method.""" # Basic sentence pattern = create_matcher("Hello world") assert pattern.match("Hello world") is not None # Match a part pattern = create_matcher("Hello {name}") match = pattern.match("hello world") assert match is not None assert match.groupdict()["name"] == "world" no_match = pattern.match("Hello world, how are you?") assert no_match is None # Optional and matching part pattern = create_matcher("Turn on [the] {name}") match = pattern.match("turn on the kitchen lights") assert match is not None assert match.groupdict()["name"] == "kitchen lights" match = pattern.match("turn on kitchen lights") assert match is not None assert match.groupdict()["name"] == "kitchen lights" match = pattern.match("turn off kitchen lights") assert match is None # Two different optional parts, 1 matching part pattern = create_matcher("Turn on [the] [a] {name}") match = pattern.match("turn on the kitchen lights") assert match is not None assert match.groupdict()["name"] == "kitchen lights" match = pattern.match("turn on kitchen lights") assert match is not None assert match.groupdict()["name"] == "kitchen lights" match = pattern.match("turn on a kitchen light") assert match is not None assert match.groupdict()["name"] == "kitchen light" # Strip plural pattern = create_matcher("Turn {name}[s] on") match = pattern.match("turn kitchen lights on") assert match is not None assert match.groupdict()["name"] == "kitchen light" # Optional 2 words pattern = create_matcher("Turn [the great] {name} on") match = pattern.match("turn the great kitchen lights on") assert match is not None assert match.groupdict()["name"] == "kitchen lights" match = pattern.match("turn kitchen lights on") assert match is not None assert match.groupdict()["name"] == "kitchen lights"
def async_register(hass, intent_type, utterances): """Register utterances and any custom intents. Registrations don't require conversations to be loaded. They will become active once the conversation component is loaded. """ intents = hass.data.get(DOMAIN) if intents is None: intents = hass.data[DOMAIN] = {} conf = intents.get(intent_type) if conf is None: conf = intents[intent_type] = [] for utterance in utterances: if isinstance(utterance, REGEX_TYPE): conf.append(utterance) else: conf.append(create_matcher(utterance))
async def async_setup(hass, config): """Set up the Hangouts bot component.""" config = config.get(DOMAIN) if config is None: hass.data[DOMAIN] = { CONF_INTENTS: {}, CONF_DEFAULT_CONVERSATIONS: [], CONF_ERROR_SUPPRESSED_CONVERSATIONS: [], } return True hass.data[DOMAIN] = { CONF_INTENTS: config[CONF_INTENTS], CONF_DEFAULT_CONVERSATIONS: config[CONF_DEFAULT_CONVERSATIONS], CONF_ERROR_SUPPRESSED_CONVERSATIONS: config[ 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(hass, config): """Register the process service.""" config = config.get(DOMAIN, {}) intents = hass.data.get(DOMAIN) if intents is None: intents = hass.data[DOMAIN] = {} for intent_type, utterances in config.get('intents', {}).items(): conf = intents.get(intent_type) if conf is None: conf = intents[intent_type] = [] conf.extend(create_matcher(utterance) for utterance in utterances) async def process(service): """Parse text into commands.""" text = service.data[ATTR_TEXT] _LOGGER.debug('Processing: <%s>', text) try: await _process(hass, text) except intent.IntentHandleError as err: _LOGGER.error('Error processing %s: %s', text, err) hass.services.async_register(DOMAIN, SERVICE_PROCESS, process, schema=SERVICE_PROCESS_SCHEMA) hass.http.register_view(ConversationProcessView) # We strip trailing 's' from name because our state matcher will fail # if a letter is not there. By removing 's' we can match singular and # plural names. async_register(hass, intent.INTENT_TURN_ON, [ 'Turn [the] [a] {name}[s] on', 'Turn on [the] [a] [an] {name}[s]', ]) async_register(hass, intent.INTENT_TURN_OFF, [ 'Turn [the] [a] [an] {name}[s] off', 'Turn off [the] [a] [an] {name}[s]', ]) async_register(hass, intent.INTENT_TOGGLE, [ 'Toggle [the] [a] [an] {name}[s]', '[the] [a] [an] {name}[s] toggle', ]) @callback def register_utterances(component): """Register utterances for a component.""" if component not in UTTERANCES: return for intent_type, sentences in UTTERANCES[component].items(): async_register(hass, intent_type, sentences) @callback def component_loaded(event): """Handle a new component loaded.""" register_utterances(event.data[ATTR_COMPONENT]) hass.bus.async_listen(EVENT_COMPONENT_LOADED, component_loaded) # Check already loaded components. for component in hass.config.components: register_utterances(component) return True
async def async_setup(hass, config): """Register the process service.""" config = config.get(DOMAIN, {}) intents = hass.data.get(DOMAIN) if intents is None: intents = hass.data[DOMAIN] = {} for intent_type, utterances in config.get('intents', {}).items(): conf = intents.get(intent_type) if conf is None: conf = intents[intent_type] = [] conf.extend(create_matcher(utterance) for utterance in utterances) async def process(service): """Parse text into commands.""" text = service.data[ATTR_TEXT] _LOGGER.debug('Processing: <%s>', text) try: await _process(hass, text) except intent.IntentHandleError as err: _LOGGER.error('Error processing %s: %s', text, err) hass.services.async_register( DOMAIN, SERVICE_PROCESS, process, schema=SERVICE_PROCESS_SCHEMA) hass.http.register_view(ConversationProcessView) # We strip trailing 's' from name because our state matcher will fail # if a letter is not there. By removing 's' we can match singular and # plural names. async_register(hass, intent.INTENT_TURN_ON, [ 'Turn [the] [a] {name}[s] on', 'Turn on [the] [a] [an] {name}[s]', ]) async_register(hass, intent.INTENT_TURN_OFF, [ 'Turn [the] [a] [an] {name}[s] off', 'Turn off [the] [a] [an] {name}[s]', ]) async_register(hass, intent.INTENT_TOGGLE, [ 'Toggle [the] [a] [an] {name}[s]', '[the] [a] [an] {name}[s] toggle', ]) @callback def register_utterances(component): """Register utterances for a component.""" if component not in UTTERANCES: return for intent_type, sentences in UTTERANCES[component].items(): async_register(hass, intent_type, sentences) @callback def component_loaded(event): """Handle a new component loaded.""" register_utterances(event.data[ATTR_COMPONENT]) hass.bus.async_listen(EVENT_COMPONENT_LOADED, component_loaded) # Check already loaded components. for component in hass.config.components: register_utterances(component) return True
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,