mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-15 16:56:56 +08:00
log: add logrus log lib and add telegram notification push as an option
This commit is contained in:
120
logger/telegram_sender.go
Normal file
120
logger/telegram_sender.go
Normal file
@@ -0,0 +1,120 @@
|
||||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||
)
|
||||
|
||||
// TelegramSender Telegram消息发送器(异步)
|
||||
type TelegramSender struct {
|
||||
bot *tgbotapi.BotAPI
|
||||
chatID int64
|
||||
msgChan chan string
|
||||
retryCount int
|
||||
retryInterval time.Duration
|
||||
wg sync.WaitGroup
|
||||
stopChan chan struct{}
|
||||
once sync.Once
|
||||
}
|
||||
|
||||
// NewTelegramSender 创建Telegram发送器(使用默认参数)
|
||||
func NewTelegramSender(botToken string, chatID int64) (*TelegramSender, error) {
|
||||
bot, err := tgbotapi.NewBotAPI(botToken)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("创建telegram bot失败: %w", err)
|
||||
}
|
||||
|
||||
// 设置为静默模式(不打印bot信息)
|
||||
bot.Debug = false
|
||||
|
||||
sender := &TelegramSender{
|
||||
bot: bot,
|
||||
chatID: chatID,
|
||||
msgChan: make(chan string, 20), // 固定缓冲区大小: 20
|
||||
retryCount: 3, // 固定重试次数: 3
|
||||
retryInterval: 3 * time.Second, // 固定重试间隔: 3秒
|
||||
stopChan: make(chan struct{}),
|
||||
}
|
||||
|
||||
// 启动异步发送协程
|
||||
sender.Start()
|
||||
|
||||
return sender, nil
|
||||
}
|
||||
|
||||
// Start 启动异步发送协程
|
||||
func (s *TelegramSender) Start() {
|
||||
s.wg.Add(1)
|
||||
go s.listenAndSend()
|
||||
}
|
||||
|
||||
// SendAsync 异步发送消息(非阻塞)
|
||||
func (s *TelegramSender) SendAsync(message string) {
|
||||
select {
|
||||
case s.msgChan <- message:
|
||||
// 成功写入缓冲区
|
||||
default:
|
||||
// 缓冲区满,丢弃消息(不阻塞主流程)
|
||||
fmt.Printf("[Telegram] 消息缓冲区已满,消息被丢弃\n")
|
||||
}
|
||||
}
|
||||
|
||||
// listenAndSend 监听channel并发送消息
|
||||
func (s *TelegramSender) listenAndSend() {
|
||||
defer s.wg.Done()
|
||||
|
||||
for {
|
||||
select {
|
||||
case msg := <-s.msgChan:
|
||||
s.sendWithRetry(msg)
|
||||
case <-s.stopChan:
|
||||
// 清空缓冲区后退出
|
||||
for len(s.msgChan) > 0 {
|
||||
msg := <-s.msgChan
|
||||
s.sendWithRetry(msg)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sendWithRetry 发送消息(带重试)
|
||||
func (s *TelegramSender) sendWithRetry(message string) {
|
||||
var err error
|
||||
for i := 0; i < s.retryCount; i++ {
|
||||
err = s.send(message)
|
||||
if err == nil {
|
||||
return // 发送成功
|
||||
}
|
||||
|
||||
// 重试前等待
|
||||
if i < s.retryCount-1 {
|
||||
time.Sleep(s.retryInterval)
|
||||
}
|
||||
}
|
||||
|
||||
// 所有重试都失败
|
||||
if err != nil {
|
||||
fmt.Printf("[Telegram] 发送消息失败(已重试%d次): %v\n", s.retryCount, err)
|
||||
}
|
||||
}
|
||||
|
||||
// send 发送单条消息
|
||||
func (s *TelegramSender) send(message string) error {
|
||||
msg := tgbotapi.NewMessage(s.chatID, message)
|
||||
msg.ParseMode = tgbotapi.ModeMarkdown
|
||||
|
||||
_, err := s.bot.Send(msg)
|
||||
return err
|
||||
}
|
||||
|
||||
// Stop 停止发送器(优雅关闭)
|
||||
func (s *TelegramSender) Stop() {
|
||||
s.once.Do(func() {
|
||||
close(s.stopChan)
|
||||
s.wg.Wait()
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user