feat(push): add telegram bot push notification channel

Implement TelegramPusher in pkg/push, register config schema in channels_definition.go, add validation in model/push_channel.go, update task routing, and update settings-tab.tsx UI validation.
This commit is contained in:
ryan
2026-06-15 14:42:49 +08:00
parent cb018b3b60
commit de58b118b4
18 changed files with 394 additions and 60 deletions
+9 -1
View File
@@ -20,7 +20,7 @@ import (
// ListChannelDefinitions 获取各种消息通道的表单配置定义列表
// @Summary 获取所有消息通道配置字段定义
// @Description 返回系统支持的所有消息通道类型(如飞书、邮件、自定义)的动态表单定义,需要管理员权限
// @Description 返回系统支持的所有消息通道类型(如飞书、邮件、自定义、Telegram)的动态表单定义,需要管理员权限
// @Tags admin-push
// @Produce json
// @Security SessionCookie
@@ -279,6 +279,7 @@ func TestChannel(c *gin.Context) {
c.JSON(http.StatusBadRequest, util.Err(err.Error()))
return
}
url = tempChannel.URL
var config pkgpush.Config
var renderedJSON string
@@ -298,6 +299,13 @@ func TestChannel(c *gin.Context) {
Key: token,
Secret: other,
}
case channelTelegram:
config = pkgpush.Config{
Channel: channelTelegram,
URL: url,
Secret: token,
Key: other,
}
default:
config = pkgpush.Config{
Channel: channelCustom,
@@ -56,8 +56,8 @@ func ListDefinitions() []Definition {
defMu.RLock()
defer defMu.RUnlock()
// We want a stable order: custom, lark, email
order := []string{channelCustom, channelLark, channelEmail}
// We want a stable order: custom, lark, telegram, email
order := []string{channelCustom, channelLark, channelTelegram, channelEmail}
res := make([]Definition, 0, len(definitions))
for _, t := range order {
if d, ok := definitions[t]; ok {
@@ -140,6 +140,39 @@ func init() {
},
})
// Register Telegram channel
RegisterChannelDefinition(Definition{
Type: channelTelegram,
Name: "Telegram 机器人",
Description: "配置 Telegram 机器人推送消息。",
Fields: []Field{
{
Key: KeyURL,
Label: "API 基础地址 (可选)",
Type: TypeText,
Required: false,
Placeholder: "https://api.telegram.org",
Description: "接口请求的 HTTPS 基础地址,留空默认为 https://api.telegram.org",
},
{
Key: KeyToken,
Label: "机器人 Token (Bot Token)",
Type: TypePassword,
Required: true,
Placeholder: "在此输入 Telegram 机器人的 Bot Token",
Description: "通过 BotFather 申请到的机器人 Access Token",
},
{
Key: KeyOther,
Label: "默认会话 ID (Chat ID) (可选)",
Type: TypeText,
Required: false,
Placeholder: "例如 -100123456789 或 @channel_name",
Description: "默认的消息接收 Chat ID。如果通知事件中未配置 targets,将推送到此 ID",
},
},
})
// Register Email channel
RegisterChannelDefinition(Definition{
Type: channelEmail,
+1
View File
@@ -7,6 +7,7 @@ const (
channelCustom = "custom"
channelEmail = "email"
channelLark = "lark"
channelTelegram = "telegram"
defaultLevelInfo = "INFO"
keyTitle = "title"
keyContent = "content"
+7
View File
@@ -362,6 +362,13 @@ func (t *EventTrigger) enqueueSingleCustomPushChannelTask(ctx context.Context, m
Key: token, // SMTP Username
Secret: other, // SMTP Password
}
case channelTelegram:
config = pkgpush.Config{
Channel: channelTelegram,
URL: channel.URL,
Secret: channel.Token, // Telegram Bot Token
Key: channel.Other, // Default Chat ID
}
default: // custom
config = pkgpush.Config{
Channel: channelCustom,
+11
View File
@@ -620,6 +620,17 @@ func TestPushChannelAPI(t *testing.T) {
c6 := &model.PushChannel{Name: "lark_channel", Type: "lark", URL: "https://open.feishu.cn", Other: ""}
assert.NoError(t, c6.Validate())
// Telegram 渠道校验
cTelegramErr := &model.PushChannel{Name: "tg_channel", Type: "telegram", URL: "https://api.telegram.org", Token: "", Other: ""}
assert.Error(t, cTelegramErr.Validate())
cTelegramErr2 := &model.PushChannel{Name: "tg_channel", Type: "telegram", URL: "http://api.telegram.org", Token: "123:abc", Other: ""}
assert.Error(t, cTelegramErr2.Validate())
cTelegramOk := &model.PushChannel{Name: "tg_channel", Type: "telegram", URL: "", Token: "123:abc", Other: "-100123"}
assert.NoError(t, cTelegramOk.Validate())
assert.Equal(t, "https://api.telegram.org", cTelegramOk.URL)
// 邮件配置校验:允许空配置以复用系统全局设置
c7 := &model.PushChannel{Name: "email_channel", Type: "email", URL: "", Token: "", Other: ""}
assert.NoError(t, c7.Validate())