Files
trbot/plugins/teamspeak/check_client.go
2026-03-09 16:14:43 +08:00

168 lines
4.6 KiB
Go

package teamspeak
import (
"context"
"fmt"
"time"
"github.com/go-telegram/bot"
"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) {
logger := zerolog.Ctx(ctx).
With().
Str("pluginName", "teamspeak3").
Str(utils.GetCurrentFuncName()).
Logger()
// 仅在能立即锁定时继续操作,否则直接退出
if sc.rw.TryLock() {
defer sc.rw.Unlock()
} else {
return
}
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 err.Error() == "not connected" {
// 连不上服务器直接暂停人物为并尝试重连
sc.PauseCheckClientTask(ctx, true)
} else if sc.s.CheckFailedCount >= 5 {
// 不是连不上服务器,则累积到五次后再重连
sc.PauseCheckClientTask(ctx, true)
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
}
}
return
} else if onlineClients != nil {
var nowOnlineClient []OnlineClient
sc.s.CheckFailedCount = 0 // 重置失败计数
for _, client := range *onlineClients {
if client.ClientNickname == botNickName { continue }
var isExist bool
for _, user := range sc.s.BeforeOnlineClient {
if user.DatabaseID == client.ClientDatabaseId {
nowOnlineClient = append(nowOnlineClient, user)
isExist = true
}
}
if !isExist {
nowOnlineClient = append(nowOnlineClient, OnlineClient{
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 {
logger := zerolog.Ctx(ctx).
With().
Str("pluginName", "teamspeak3").
Str(utils.GetCurrentFuncName()).
Logger()
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 {
logger.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) {
logger := zerolog.Ctx(ctx).
With().
Str("pluginName", "teamspeak3").
Str(utils.GetCurrentFuncName()).
Logger()
if !sc.s.IsCheckClientTaskRunning {
err := task.ResumeTask(ctx, fmt.Sprintf("check_client_%d", sc.GroupID), "teamspeak3")
if err != nil {
logger.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) {
logger := zerolog.Ctx(ctx).
With().
Str("pluginName", "teamspeak3").
Str(utils.GetCurrentFuncName()).
Logger()
if sc.s.IsCheckClientTaskRunning {
err := task.PauseTask(ctx, fmt.Sprintf("check_client_%d", sc.GroupID), "teamspeak3")
if err != nil {
logger.Error().Err(err).Msg("Failed to pause check client task")
} else {
sc.s.IsCheckClientTaskRunning = false
}
}
if retry && !sc.s.IsInRetryLoop {
go sc.RetryLoop(ctx)
logger.Warn().Msg("Start retry connect loop")
}
}