Skip to content

Commit

Permalink
Merge pull request #3 from jekalmin/v0.0.2
Browse files Browse the repository at this point in the history
0.0.2
  • Loading branch information
jekalmin authored Dec 22, 2024
2 parents 67d93e7 + 2926b34 commit 61870ee
Show file tree
Hide file tree
Showing 14 changed files with 784 additions and 232 deletions.
68 changes: 25 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# HASS-Line-Bot
# Line Bot
Home Assistant custom component for notifying message via Line Messaging API (https://developers.line.biz/en/docs/messaging-api/overview/)

## Usage
Expand All @@ -16,57 +16,39 @@ data:
- Follow instructions from the [link](https://developers.line.biz/en/docs/messaging-api/getting-started/) to create a new channel.

## Installation
1. Copy
```
/custom_components/line_bot/
```
into
```
<config directory>/custom_components/line_bot/
```

1. Install via custom component of HACS.

[![Open your Home Assistant instance and open a repository inside the Home Assistant Community Store.](https://my.home-assistant.io/badges/hacs_repository.svg)](https://my.home-assistant.io/redirect/hacs_repository/?owner=jekalmin&repository=line_bot&category=integration)
2. Go to https://developers.line.biz/console
3. Select "Provider", and then "Channel" created from [prequisite](#prequisite).
4. Set configuration.yaml as below (retrieve "Channel access token" and "Channel secret" from Line Console)
```yaml
line_bot:
token: !secret line_bot_token
secret: !secret line_bot_secret
```
5. Restart HomeAssistant
6. Set "Webhook URL" from "Messaging API" tab of Line Console as below
3. Retrieve "Channel access token" and "Channel secret" from Line Console

4. Install integration
- [Settings] > [Devices and Services] > [Add Integration] > [Line Bot]
- Use "Channel access token" and "Channel secret" retrieved from above (#3).
<img width="302" alt="스크린샷 2024-12-22 오후 9 00 33" src="https://github.com/user-attachments/assets/b5a8fc74-d2f7-415a-8c03-10f3fab4e46f" />


5. Set "Webhook URL" from "Messaging API" tab of Line Console as below
- Webhook URL is base_url + "/api/line/callback"
- Your HomeAssistant URL has to support https

![10](https://user-images.githubusercontent.com/2917984/69878412-3b132d00-1308-11ea-926a-d0029eb96b9a.png)
7. Click "Verify" button to verify URL is valid. It has to return "Success"
<img width="300" alt="스크린샷 2024-12-22 오후 9 13 12" src="https://github.com/user-attachments/assets/7c1de92c-e44d-492e-950a-5e11946bb5a2" />


6. Click "Verify" button to verify URL is valid. It has to return "Success"

![11](https://user-images.githubusercontent.com/2917984/69878717-081d6900-1309-11ea-8b08-c319bd4b333a.png)

8. Add a bot as a friend by either QR code or Bot ID
9. Send any message to a bot
10. Get chat_id from HomeAssistant notification
7. Add a bot as a friend by either QR code or Bot ID
8. Send any message to a bot
9. Go to [Configure > Add a chat] and follow the directions.

![12](https://user-images.githubusercontent.com/2917984/69880905-a4963a00-130e-11ea-8ab8-f1caaa748a4d.png)
11. Set "chat_id" into "allowed_chat_ids" of configuration.yaml
12. Restart HomeAssistant and try [examples](https://github.com/jekalmin/HASS-line-bot/tree/master/examples)
## Configuration
#### Example configuration.yaml:
```yaml
line_bot:
token: !secret line_bot_token
secret: !secret line_bot_secret
allowed_chat_ids:
me: !secret line_chat_id
```
#### Configuration variables:
configure | add a chat | configure a chat
--|--|--
<img width="442" src="https://github.com/user-attachments/assets/63ddeb48-6248-4488-813a-429b8f993a85" /> | <img width="400" src="https://github.com/user-attachments/assets/20475b4b-c2d1-4ee2-bc8a-0ede595f7da7" /> | <img width="400" src="https://github.com/user-attachments/assets/f581c3c7-139a-44ec-8707-5badc4c00f4b" />

| key | required | default | dataType | description
| --- | --- | --- | --- | ---
| **token** | yes | | string | channel access token (to issue a channel access token, click Issue on the "Channel settings" page on the [console](https://developers.line.biz/console/).)
| **secret** | no | | string | channel secret. Only required to use webhook.
| **allowed_chat_ids** | yes | | dictionary | any name as a key, ID of target recipient as a value. Do not use the LINE ID found on LINE (see [API Documentation](https://developers.line.biz/en/reference/messaging-api/#send-push-message))
10. Try [examples](https://github.com/jekalmin/HASS-line-bot/tree/master/examples)

## Services
### line_bot.send_message
Expand Down
132 changes: 35 additions & 97 deletions custom_components/line_bot/__init__.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,32 @@
"""The line_bot component."""

import logging
import requests
import voluptuous as vol
from typing import Any, Dict
import homeassistant.helpers.config_validation as cv
from homeassistant.core import HomeAssistant, callback
from homeassistant.const import CONF_TOKEN
from urllib.parse import urlencode

from .http import async_register_http
from .const import (
DOMAIN, CONF_ALLOWED_CHAT_IDS, CONF_SECRET
)
from linebot import (
LineBotApi
)
from linebot.models import (
TextSendMessage,
ImageSendMessage,
StickerSendMessage,
TemplateSendMessage,
LocationSendMessage,
FlexSendMessage,
AudioSendMessage,
ButtonsTemplate,
ConfirmTemplate,
FlexSendMessage,
ImageSendMessage,
LocationSendMessage,
MessageAction,
PostbackAction,
StickerSendMessage,
TemplateSendMessage,
TextSendMessage,
URIAction,
MessageAction,
)

from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_ACCESS_TOKEN
from homeassistant.core import HomeAssistant
from homeassistant.helpers.typing import ConfigType

from .const import DOMAIN
from .helpers import get_quota
from .http import async_register_http
from .services import async_setup_services

_LOGGER = logging.getLogger(__name__)

MESSAGES = {
Expand All @@ -38,89 +36,29 @@
"template": TemplateSendMessage,
"location": LocationSendMessage,
"flex": FlexSendMessage,
"audio": AudioSendMessage
"audio": AudioSendMessage,
}

CONFIG_SCHEMA = vol.Schema(
{
DOMAIN: vol.All(
vol.Schema(
{
vol.Required(CONF_TOKEN): cv.string,
vol.Optional(CONF_SECRET): cv.string,
vol.Optional(CONF_ALLOWED_CHAT_IDS): dict,
}
)
)
},
extra=vol.ALLOW_EXTRA,
)

def setup(hass: HomeAssistant, config: Dict[str, Any]):
if config[DOMAIN].get(CONF_SECRET):
async_register_http(hass, config)

lineClient = LineNotificationService(config[DOMAIN].get(CONF_TOKEN), config[DOMAIN].get(CONF_ALLOWED_CHAT_IDS, {}))
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up OpenAI Conversation."""
await async_setup_services(hass, config)
return True

def send_message(call):
to = call.data.get("to")
reply_token = call.data.get("reply_token")
message = call.data.get("message")
message_type = message.get("type")
lineClient.send_message(MESSAGES[message_type].new_from_json_dict(message), to=to, reply_token=reply_token)

def send_button_message(call):
to = call.data.get("to")
reply_token = call.data.get("reply_token")
text = call.data.get("text")
alt_text = call.data.get("alt_text", text)
buttons = call.data.get("buttons")
button_template = ButtonsTemplate(text=text, actions=to_actions(buttons))
lineClient.send_message(TemplateSendMessage(alt_text=alt_text, template=button_template), to=to, reply_token=reply_token)
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up OpenAI Conversation from a config entry."""

def send_confirm_message(call):
to = call.data.get("to")
reply_token = call.data.get("reply_token")
text = call.data.get("text")
alt_text = call.data.get("altText", text)
buttons = call.data.get("buttons")
confirm_template = ConfirmTemplate(text=text, actions=to_actions(buttons))
lineClient.send_message(TemplateSendMessage(alt_text=alt_text, template=confirm_template), to=to, reply_token=reply_token)
await get_quota(hass, entry.data[CONF_ACCESS_TOKEN])
hass.data.setdefault(DOMAIN, {}).setdefault("entry", {}).setdefault(
entry.entry_id, {}
)

hass.services.register(DOMAIN, 'send_message', send_message)
hass.services.register(DOMAIN, 'send_button_message', send_button_message)
hass.services.register(DOMAIN, 'send_confirm_message', send_confirm_message)
async_register_http(hass)
return True

class LineNotificationService:
def __init__(self, token, allowed_chat_ids):
"""Initialize the service."""
self.allowed_chat_ids = allowed_chat_ids
self.line_bot_api = LineBotApi(token)

def send_message(self, message, **kwargs):
reply_token = kwargs.get("reply_token")
if reply_token:
self.line_bot_api.reply_message(reply_token, message)
else:
to = self.allowed_chat_ids.get(kwargs.get("to"))
self.line_bot_api.push_message(to, message)

def to_actions(buttons):
actions = []
for button in buttons:
action = None
text = button.get("text")
data = button.get("data")
uri = button.get("uri")
if data is not None:
label = button.get("label", text)
action = PostbackAction(label=label, data=data)
elif uri is not None:
label = button.get("label", text)
action = URIAction(label=label, uri=uri)
else:
label = button.get("label", text)
action = MessageAction(label=label, text=text)
actions.append(action)
return actions
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload OpenAI."""
hass.data[DOMAIN]["entry"].pop(entry.entry_id)
return True
Loading

0 comments on commit 61870ee

Please sign in to comment.