168 lines
4.6 KiB
Go
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")
|
|
}
|
|
}
|