165 lines
4.8 KiB
Go
165 lines
4.8 KiB
Go
package teamspeak
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/go-telegram/bot"
|
|
"github.com/go-telegram/bot/models"
|
|
"github.com/reugn/go-quartz/job"
|
|
"github.com/reugn/go-quartz/quartz"
|
|
"github.com/rs/zerolog"
|
|
"trle5.xyz/trbot/utils"
|
|
"trle5.xyz/trbot/utils/flaterr"
|
|
"trle5.xyz/trbot/utils/task"
|
|
)
|
|
|
|
// CheckClient 检查 TeamSpeak 服务器的状态和用户数量,根据配置通知用户或尝试重连
|
|
func (sc *ServerConfig) CheckClient(ctx context.Context) {
|
|
if sc.rw.TryRLock() {
|
|
defer sc.rw.RUnlock()
|
|
} else {
|
|
return
|
|
}
|
|
|
|
logger := zerolog.Ctx(ctx).
|
|
With().
|
|
Str("pluginName", "teamspeak3").
|
|
Str(utils.GetCurrentFuncName()).
|
|
Logger()
|
|
|
|
onlineClients, err := sc.c.ClientList()
|
|
if err != nil {
|
|
sc.s.CheckFailedCount++
|
|
logger.Error().
|
|
Err(err).
|
|
Int("failedCount", sc.s.CheckFailedCount).
|
|
Msg("Failed to get online client")
|
|
if sc.s.CheckFailedCount > 5 {
|
|
// 累积失败五次后再重连
|
|
sc.PauseCheckClientTask(ctx, true)
|
|
if sc.SendMessageMode {
|
|
botMessage, err := botInstance.SendMessage(ctx, &bot.SendMessageParams{
|
|
ChatID: sc.GroupID,
|
|
Text: "已连续五次检查在线客户端失败,开始尝试自动重连",
|
|
})
|
|
if err != nil {
|
|
logger.Error().
|
|
Err(err).
|
|
Int64("chatID", sc.GroupID).
|
|
Str("content", "failed to check online client 5 times, start auto reconnect").
|
|
Msg(flaterr.SendMessage.Str())
|
|
} else {
|
|
sc.s.RetryMsgID = botMessage.ID
|
|
}
|
|
}
|
|
if sc.PinMessageMode && sc.PinnedMessageID != 0 {
|
|
_, err := botInstance.EditMessageText(ctx, &bot.EditMessageTextParams{
|
|
ChatID: sc.GroupID,
|
|
MessageID: sc.PinnedMessageID,
|
|
Text: fmt.Sprintf("%s | 已与服务器断开连接...", time.Now().Format("15:04")),
|
|
ParseMode: models.ParseModeHTML,
|
|
})
|
|
if err != nil {
|
|
logger.Error().
|
|
Err(err).
|
|
Int64("chatID", sc.GroupID).
|
|
Str("content", "teamspeak pinned message server disconnect").
|
|
Msg(flaterr.EditMessageText.Str())
|
|
}
|
|
}
|
|
}
|
|
} else if onlineClients != nil {
|
|
sc.s.CheckFailedCount = 0 // 重置失败计数
|
|
var nowOnlineClient []Client
|
|
for _, client := range *onlineClients {
|
|
if client.ClientNickname == botNickName { continue }
|
|
|
|
var isExist bool
|
|
for _, user := range sc.s.BeforeOnlineClient {
|
|
if user.DatabaseID == client.ClientDatabaseId {
|
|
user.Username = client.ClientNickname // 用户昵称可能会变动
|
|
nowOnlineClient = append(nowOnlineClient, user)
|
|
isExist = true
|
|
break
|
|
}
|
|
}
|
|
if !isExist {
|
|
nowOnlineClient = append(nowOnlineClient, Client{
|
|
Username: client.ClientNickname,
|
|
DatabaseID: client.ClientDatabaseId,
|
|
JoinTime: time.Now(),
|
|
})
|
|
}
|
|
}
|
|
added, removed := diffSlices(sc.s.BeforeOnlineClient, nowOnlineClient)
|
|
if sc.SendMessageMode && len(added) + len(removed) > 0 {
|
|
logger.Debug().
|
|
Int("clientJoin", len(added)).
|
|
Int("clientLeave", len(removed)).
|
|
Msg("online client change detected")
|
|
sc.NotifyClientChange(ctx, added, removed)
|
|
}
|
|
if sc.PinMessageMode {
|
|
sc.NewPinnedMessage(ctx)
|
|
sc.ChangePinnedMessage(ctx, nowOnlineClient, added, removed)
|
|
}
|
|
sc.s.BeforeOnlineClient = nowOnlineClient
|
|
}
|
|
}
|
|
|
|
// ScheduleOrResumeCheckClientTask 创建检查客户端任务
|
|
func (sc *ServerConfig) ScheduleCheckClientTask(ctx context.Context) error {
|
|
err := task.ScheduleTask(ctx, task.Task{
|
|
Name: fmt.Sprintf("check_client_%d", sc.GroupID),
|
|
Group: "teamspeak3",
|
|
Job: job.NewFunctionJobWithDesc(
|
|
func(ctx context.Context) (int, error) {
|
|
sc.CheckClient(ctx)
|
|
return 0, nil
|
|
},
|
|
"check teamspeak client changes",
|
|
),
|
|
Trigger: quartz.NewSimpleTrigger(time.Second * time.Duration(sc.PollingInterval)),
|
|
})
|
|
if err != nil {
|
|
zerolog.Ctx(ctx).Error().Err(err).Msg("Failed to schedule check client job")
|
|
return err
|
|
}
|
|
|
|
sc.s.IsCheckClientTaskScheduled = true
|
|
sc.s.IsCheckClientTaskRunning = true
|
|
|
|
return nil
|
|
}
|
|
|
|
// ResumeCheckClientTask 恢复检查客户端任务
|
|
func (sc *ServerConfig) ResumeCheckClientTask(ctx context.Context) {
|
|
if !sc.s.IsCheckClientTaskRunning {
|
|
err := task.ResumeTask(ctx, fmt.Sprintf("check_client_%d", sc.GroupID), "teamspeak3")
|
|
if err != nil {
|
|
zerolog.Ctx(ctx).Error().Err(err).Msg("Failed to resume check client task")
|
|
} else {
|
|
sc.s.IsCheckClientTaskRunning = true
|
|
}
|
|
}
|
|
}
|
|
|
|
// PauseCheckClientTask 暂停检查客户端任务,可选是否开始重试
|
|
func (sc *ServerConfig) PauseCheckClientTask(ctx context.Context, retry bool) {
|
|
if sc.s.IsCheckClientTaskRunning {
|
|
err := task.PauseTask(ctx, fmt.Sprintf("check_client_%d", sc.GroupID), "teamspeak3")
|
|
if err != nil {
|
|
zerolog.Ctx(ctx).Error().Err(err).Msg("Failed to pause check client task")
|
|
} else {
|
|
sc.s.IsCheckClientTaskRunning = false
|
|
}
|
|
}
|
|
|
|
if retry && !sc.s.IsInRetryLoop {
|
|
go sc.RetryLoop(ctx)
|
|
zerolog.Ctx(ctx).Warn().Msg("Start retry connect loop")
|
|
}
|
|
}
|