Skip to content

Commit

Permalink
Merge pull request #23 from LeslieLeung/dev
Browse files Browse the repository at this point in the history
  • Loading branch information
LeslieLeung authored Jan 30, 2024
2 parents db4645e + c0f50e8 commit d0ec2f2
Show file tree
Hide file tree
Showing 11 changed files with 112 additions and 86 deletions.
8 changes: 6 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,11 @@ channel_9_TYPE=telegram
channel_9_TELEGRAM_TOKEN=<YOUR_TELEGRAM_TOKEN>
channel_9_TELEGRAM_CHAT_ID=<YOUR_TELEGRAM_CHAT_ID>

# channel_10(Ntfy)
# channel_10(ntfy)
channel_10_TYPE=ntfy
channel_10_NTFY_HOST=<YOUR_NTFY_HOST>
channel_10_NTFY_TOPIC=<YOUR_NTFY_TOPIC>
channel_10_NTFY_TOPIC=<YOUR_NTFY_TOPIC>

# channel_11(lark)
channel_11_TYPE=lark_webhook
channel_11_LARK_TOKEN=<YOUR_LARK_TOKEN>
20 changes: 0 additions & 20 deletions .github/workflows/sonarqube-scan.yml

This file was deleted.

3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,11 @@ Heimdallr 是一个非常轻量的通知网关,可以聚合各种推送渠道
- [Discord(webhook)](https://discord.com/developers/docs/resources/webhook#execute-webhook)
- [Telegram Bot](https://core.telegram.org/bots/api#sendmessage)
- [ntfy](https://docs.ntfy.sh/)
- [飞书/Lark](https://open.feishu.cn/document/client-docs/bot-v3/add-custom-bot)


### 可能会支持的推送方式
- [ ] 钉钉
- [ ] 飞书/Lark
- [ ] ...

> 如果有需要的通知方式,请提交 [issue](https://github.com/LeslieLeung/heimdallr/issues/new?assignees=LeslieLeung&labels=enhancement&template=feature_request.md&title=)
Expand Down
2 changes: 2 additions & 0 deletions docs/Changelog.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# 更新日志
## v2.0.2
- 通知渠道新增 飞书/Lark Webhook
## v2.0.1
- 通知渠道新增 ntfy
- 新增 `/push/form` 接口,支持 form-data
Expand Down
79 changes: 41 additions & 38 deletions docs/Config.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,47 +62,50 @@ channel_3_WECOM_WEBHOOK_KEY=<YOUR_WECOM_WEBHOOK_KEY>

#### 通知渠道类型

| 渠道名称 | 渠道类型(上面的`<CHANNEL_NAME>_TYPE` |
| ---------------- | ------------------------------------- |
| Bark | bark |
| 企业微信 Webhook | wecom_webhook |
| 企业微信应用 | wecom_app |
| Pushover | pushover |
| PushDeer | pushdeer |
| Chanify | chanify |
| SMTP(邮件) | email |
| Discord | discord_webhook |
| Telegram | telegram |
| ntfy | ntfy |
| 渠道名称 | 渠道类型(上面的`<CHANNEL_NAME>_TYPE` |
| ----------------- | ------------------------------------- |
| Bark | bark |
| 企业微信 Webhook | wecom_webhook |
| 企业微信应用 | wecom_app |
| Pushover | pushover |
| PushDeer | pushdeer |
| Chanify | chanify |
| SMTP(邮件) | email |
| Discord | discord_webhook |
| Telegram | telegram |
| ntfy | ntfy |
| 飞书/Lark Webhook | lark_webhook |


#### 渠道配置后缀
| 后缀名 | 通知渠道 | 后缀说明 |
| ----------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `BARK_URL` | Bark | Bark服务器地址,如`https://api.day.app` |
| `BARK_KEY` | Bark | Bark的推送 key,如 `qy7s8qnhjhphuNDHJNFxQE` |
| `WECOM_KEY` | 企业微信 | 企业微信机器人的 key,见 [企业微信机器人webhook](https://developer.work.weixin.qq.com/document/path/91770) |
| `WECOM_CORP_ID` | 企业微信 | 企业微信应用的 corp_id,见 [企业微信应用消息](https://developer.work.weixin.qq.com/document/path/90236) |
| `WECOM_AGENT_ID` | 企业微信 | 企业微信应用的 agent_id |
| `WECOM_SECRET` | 企业微信 | 企业微信应用的 secret |
| `PUSHOVER_TOKEN` | Pushover | Pushover 的 token,见 [Pushover API](https://pushover.net/api) |
| `PUSHOVER_USER` | Pushover | Pushover 的 user |
| `PUSHDEER_TOKEN` | PushDeer | PushDeer 的 token,见 [Pushdeer API](http://pushdeer.com) |
| `CHANIFY_ENDPOINT` | Chanify | Chanify 的 endpoint,见 [Chanify](https://github.com/chanify/chanify#as-sender-client),可不填,默认为 `https://api.chanify.net` |
| `CHANIFY_TOKEN` | Chanify | Chanify 的 token |
| `EMAIL_HOST` | Email | Email 服务器地址,如 `smtp.gmail.com` |
| `EMAIL_PORT` | Email | Email 服务器端口,如 `465` |
| `EMAIL_USER` | Email | Email 用户名 |
| `EMAIL_PASSWORD` | Email | Email 密码 |
| `EMAIL_SENDER` | Email | Email 发件人名称 |
| `EMAIL_TO` | Email | Email 收件人 |
| `EMAIL_STARTTLS` | Email | Email 是否使用 TLS |
| `DISCORD_WEBHOOK_ID` | Discord | Discord 的 Webhook ID,见 [Discord 文档](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks) |
| `DISCORD_WEBHOOK_TOKEN` | Discord | Discord 的 Webhook Token |
| `TELEGRAM_TOKEN` | Telegram | Telegram 的 Token,见 [这里](https://github.com/pppscn/SmsForwarder/wiki/2.%E5%8F%91%E9%80%81%E9%80%9A%E9%81%93#tele%E6%9C%BA%E5%99%A8%E4%BA%BA%E7%A7%91%E5%AD%A6%E4%B8%8A%E7%BD%91) |
| `TELEGRAM_CHAT_ID` | Telegram | Telegram 的 Chat ID,见 [这里](https://github.com/pppscn/SmsForwarder/issues/319) |
| `NTFY_HOST` | ntfy | ntfy 的服务端地址 |
| `NTFY_TOPIC` | ntfy | ntfy 的 topic,见 [这里](https://docs.ntfy.sh/) |
| 后缀名 | 通知渠道 | 后缀说明 |
| ----------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `BARK_URL` | Bark | Bark服务器地址,如`https://api.day.app` |
| `BARK_KEY` | Bark | Bark的推送 key,如 `qy7s8qnhjhphuNDHJNFxQE` |
| `WECOM_KEY` | 企业微信 | 企业微信机器人的 key,见 [企业微信机器人webhook](https://developer.work.weixin.qq.com/document/path/91770) |
| `WECOM_CORP_ID` | 企业微信 | 企业微信应用的 corp_id,见 [企业微信应用消息](https://developer.work.weixin.qq.com/document/path/90236) |
| `WECOM_AGENT_ID` | 企业微信 | 企业微信应用的 agent_id |
| `WECOM_SECRET` | 企业微信 | 企业微信应用的 secret |
| `PUSHOVER_TOKEN` | Pushover | Pushover 的 token,见 [Pushover API](https://pushover.net/api) |
| `PUSHOVER_USER` | Pushover | Pushover 的 user |
| `PUSHDEER_TOKEN` | PushDeer | PushDeer 的 token,见 [Pushdeer API](http://pushdeer.com) |
| `CHANIFY_ENDPOINT` | Chanify | Chanify 的 endpoint,见 [Chanify](https://github.com/chanify/chanify#as-sender-client),可不填,默认为 `https://api.chanify.net` |
| `CHANIFY_TOKEN` | Chanify | Chanify 的 token |
| `EMAIL_HOST` | Email | Email 服务器地址,如 `smtp.gmail.com` |
| `EMAIL_PORT` | Email | Email 服务器端口,如 `465` |
| `EMAIL_USER` | Email | Email 用户名 |
| `EMAIL_PASSWORD` | Email | Email 密码 |
| `EMAIL_SENDER` | Email | Email 发件人名称 |
| `EMAIL_TO` | Email | Email 收件人 |
| `EMAIL_STARTTLS` | Email | Email 是否使用 TLS |
| `DISCORD_WEBHOOK_ID` | Discord | Discord 的 Webhook ID,见 [Discord 文档](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks) |
| `DISCORD_WEBHOOK_TOKEN` | Discord | Discord 的 Webhook Token |
| `TELEGRAM_TOKEN` | Telegram | Telegram 的 Token,见 [这里](https://github.com/pppscn/SmsForwarder/wiki/2.%E5%8F%91%E9%80%81%E9%80%9A%E9%81%93#tele%E6%9C%BA%E5%99%A8%E4%BA%BA%E7%A7%91%E5%AD%A6%E4%B8%8A%E7%BD%91) |
| `TELEGRAM_CHAT_ID` | Telegram | Telegram 的 Chat ID,见 [这里](https://github.com/pppscn/SmsForwarder/issues/319) |
| `NTFY_HOST` | ntfy | ntfy 的服务端地址 |
| `NTFY_TOPIC` | ntfy | ntfy 的 topic,见 [这里](https://docs.ntfy.sh/) |
| `LARK_HOST` | 飞书/Lark | 飞书/Lark 的接口地址,默认可以留空。如果使用 Lark, 则为 https://open.larksuite.com/open-apis/bot/v2/hook/ |
| `LARK_TOKEN` | 飞书/Lark | 飞书/Lark 的 Token |


## 腾讯云 Serverless 环境变量设置
Expand Down
22 changes: 0 additions & 22 deletions heimdallr/api/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,6 @@
logger = logging.getLogger(__name__)


def serve(key: str, title: str = "", body: str = "", **kwargs):
try:
group = config.get_group(key)
except AuthException as e:
return Response(code=-1, message=str(e)).render()
logger.info(f"group: {group.name}, token: {group.token}")
errors = {}
for chan in group.channels:
logger.info(f"channel: {chan.get_name()}, channel_type: {chan.get_type()}")
message = build_message(chan.get_name(), title, body, **kwargs)
rs, msg = chan.send(message)
if not rs:
errors[chan.get_name()] = msg

if len(errors) == 0:
return success()
err_msg = ""
for err in errors.items():
err_msg += f"{err[0]} return: {err[1]}."
return Response(code=1, message=err_msg).render()


async def serve_channels_async(key: str, title: str = "", body: str = "", **kwargs):
try:
group = config.get_group(key)
Expand Down
6 changes: 6 additions & 0 deletions heimdallr/channel/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from heimdallr.channel.chanify import Chanify, ChanifyMessage
from heimdallr.channel.discord import DiscordWebhook, DiscordWebhookMessage
from heimdallr.channel.email import Email, EmailMessage
from heimdallr.channel.lark import LarkWebhook, LarkWebhookMessage
from heimdallr.channel.ntfy import Ntfy, NtfyMessage
from heimdallr.channel.pushdeer import PushDeer, PushDeerMessage
from heimdallr.channel.pushover import Pushover, PushoverMessage
Expand Down Expand Up @@ -32,6 +33,7 @@
CHANNEL_DISCORD_WEBHOOK = "discord_webhook"
CHANNEL_TELEGRAM = "telegram"
CHANNEL_NTFY = "ntfy"
CHANNEL_LARK_WEBHOOK = "lark_webhook"


def _get_channel_type_by_name(name: str) -> str:
Expand Down Expand Up @@ -69,6 +71,8 @@ def build_channel(name: str) -> Channel:
return Telegram(name, channel_type)
elif channel_type == CHANNEL_NTFY:
return Ntfy(name, channel_type)
elif channel_type == CHANNEL_LARK_WEBHOOK:
return LarkWebhook(name, channel_type)
else:
raise ParamException(f"Channel {name} type {channel_type} not supported.")

Expand Down Expand Up @@ -99,5 +103,7 @@ def build_message(name: str, title: str, body: str, **kwargs) -> Message:
return TelegramMessage(title, body, **kwargs)
elif channel_type == CHANNEL_NTFY:
return NtfyMessage(title, body, **kwargs)
elif channel_type == CHANNEL_LARK_WEBHOOK:
return LarkWebhookMessage(title, body, **kwargs)
else:
raise ParamException(f"Channel type {channel_type} not supported.")
49 changes: 49 additions & 0 deletions heimdallr/channel/lark.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import logging
from typing import Any, Tuple

import requests

from heimdallr.channel.base import Channel, Message
from heimdallr.config.config import get_config_str
from heimdallr.config.definition import SUFFIX_LARK_HOST, SUFFIX_LARK_TOKEN
from heimdallr.exception import ParamException

logger = logging.getLogger(__name__)


class LarkWebhookMessage(Message):
def __init__(self, title: str, body: str, **kwargs) -> None:
super().__init__(title, body)

def render_message(self) -> Any:
return {"msg_type": "text", "content": {"text": f"{self.title}\n{self.body}"}}


class LarkWebhook(Channel):
def __init__(self, name: str, type: str) -> None:
super().__init__(name, type)
self.base_url: str = "https://open.feishu.cn/open-apis/bot/v2/hook/"
self.token: str = ""
self._build_channel()

def _build_channel(self) -> None:
self.base_url = get_config_str(self.get_name(), SUFFIX_LARK_HOST, self.base_url)
self.token = get_config_str(self.get_name(), SUFFIX_LARK_TOKEN, "")
if self.token == "":
raise ParamException("LarkWebhook key not set")

def send(self, message: Message) -> Tuple[bool, str]:
if not isinstance(message, LarkWebhookMessage):
raise ParamException("Invalid message type")

url = f"{self.base_url}{self.token}"
rs = requests.post(
url,
json=message.render_message(),
headers={"Content-Type": "application/json"},
).json()
logger.debug(f"LarkWebhook response: {rs}")
if rs["code"] != 0:
logger.error(f"LarkWebhook error: {rs['msg']}")
return False, rs["msg"]
return True, rs["msg"]
Loading

0 comments on commit d0ec2f2

Please sign in to comment.