optimize check client logic show network message at pinned message determine the user by database id track user's username use strings.Builder to combine messages
289 lines
10 KiB
Go
289 lines
10 KiB
Go
package teamspeak
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/go-telegram/bot"
|
|
"github.com/go-telegram/bot/models"
|
|
"github.com/rs/zerolog"
|
|
"trle5.xyz/trbot/utils"
|
|
"trle5.xyz/trbot/utils/configs"
|
|
"trle5.xyz/trbot/utils/flaterr"
|
|
"trle5.xyz/trbot/utils/handler_params"
|
|
"trle5.xyz/trbot/utils/type/contain"
|
|
)
|
|
|
|
// showStatus 响应 `/ts3` 命令,显示用户列表或触发手动连接,可显示连接错误信息
|
|
func showStatus(opts *handler_params.Message) error {
|
|
logger := zerolog.Ctx(opts.Ctx).
|
|
With().
|
|
Str("pluginName", "teamspeak3").
|
|
Str(utils.GetCurrentFuncName()).
|
|
Logger()
|
|
|
|
var handlerErr flaterr.MultErr
|
|
var pm strings.Builder
|
|
|
|
getOnlineList := func() {
|
|
onlineClients, err := tsConfig.c.ClientList()
|
|
if err != nil {
|
|
logger.Error().
|
|
Err(err).
|
|
Msg("Failed to get online client")
|
|
handlerErr.Addf("failed to get online client: %w", err)
|
|
fmt.Fprintf(&pm, "获取服务器用户列表时发生了一些错误:\n<blockquote expandable>%s</blockquote>", utils.IgnoreHTMLTags(err.Error()))
|
|
} else if onlineClients != nil {
|
|
if len(*onlineClients) > 1 {
|
|
pm.WriteString("在线用户:\n")
|
|
for _, client := range *onlineClients {
|
|
if client.ClientNickname == botNickName {
|
|
continue
|
|
}
|
|
fmt.Fprintf(&pm, "用户 [ %s ]\n", client.ClientNickname)
|
|
}
|
|
} else {
|
|
pm.WriteString("当前无用户在线")
|
|
}
|
|
}
|
|
}
|
|
|
|
// 正常运行就输出用户列表,否则发送错误信息
|
|
if tsConfig.s.IsCheckClientTaskScheduled && tsConfig.s.IsCheckClientTaskRunning {
|
|
getOnlineList()
|
|
} else {
|
|
err := tsConfig.Connect(opts.Ctx)
|
|
if err != nil {
|
|
fmt.Fprintf(&pm, "teamspeak 插件发生了一些错误:\n<blockquote expandable>%s</blockquote>\n\n", err)
|
|
if tsConfig.s.IsCheckClientTaskScheduled{
|
|
pm.WriteString("您可以使用 /ts3 命令来尝试重新连接或等待自动重连")
|
|
} else {
|
|
pm.WriteString("尝试重新初始化失败,由于检查任务未在运行,您需要手动使用 /ts3 命令来尝试重新连接")
|
|
}
|
|
handlerErr.Addf("failed to reinit teamspeak plugin: %w", err)
|
|
} else {
|
|
if tsConfig.s.IsInRetryLoop {
|
|
tsConfig.s.ResetTicker <- true
|
|
}
|
|
getOnlineList()
|
|
}
|
|
}
|
|
|
|
var buttons models.ReplyMarkup
|
|
// 显示管理按钮
|
|
if opts.Message.Chat.ID == tsConfig.GroupID && contain.Int64(opts.Message.From.ID, utils.GetChatAdminIDs(opts.Ctx, opts.Thebot, tsConfig.GroupID)...) || contain.Int64(opts.Message.From.ID, configs.BotConfig.AdminIDs...) {
|
|
buttons = &models.InlineKeyboardMarkup{ InlineKeyboard: [][]models.InlineKeyboardButton{
|
|
{{
|
|
Text: "管理此功能",
|
|
CallbackData: "teamspeak",
|
|
}},
|
|
{{
|
|
Text: "清理通知消息",
|
|
CallbackData: "teamspeak_clear",
|
|
}},
|
|
}}
|
|
}
|
|
|
|
// 发送消息
|
|
_, err := opts.Thebot.SendMessage(opts.Ctx, &bot.SendMessageParams{
|
|
ChatID: opts.Message.Chat.ID,
|
|
Text: pm.String(),
|
|
ParseMode: models.ParseModeHTML,
|
|
ReplyParameters: &models.ReplyParameters{ MessageID: opts.Message.ID },
|
|
ReplyMarkup: buttons,
|
|
})
|
|
if err != nil {
|
|
logger.Error().
|
|
Err(err).
|
|
Int64("chatID", opts.Message.Chat.ID).
|
|
Str("content", "teamspeak online client status").
|
|
Msg(flaterr.SendMessage.Str())
|
|
handlerErr.Addt(flaterr.SendMessage, "teamspeak online client status", err)
|
|
}
|
|
|
|
return handlerErr.Flat()
|
|
}
|
|
|
|
// teamspeakCallbackHandler 响应前缀为 "teamspeak" 的 callbackQuery 请求
|
|
func teamspeakCallbackHandler(opts *handler_params.CallbackQuery) error {
|
|
logger := zerolog.Ctx(opts.Ctx).
|
|
With().
|
|
Str("pluginName", "teamspeak3").
|
|
Str(utils.GetCurrentFuncName()).
|
|
Str("callbackQueryData", opts.CallbackQuery.Data).
|
|
Logger()
|
|
|
|
wrap := flaterr.NewWrapper(logger.Error())
|
|
|
|
if contain.Int64(opts.CallbackQuery.From.ID, utils.GetChatAdminIDs(opts.Ctx, opts.Thebot, tsConfig.GroupID)...) || contain.Int64(opts.CallbackQuery.From.ID, configs.BotConfig.AdminIDs...) {
|
|
var needEdit bool = true
|
|
var needSave bool = false
|
|
var needEditTask bool = false
|
|
|
|
switch opts.CallbackQuery.Data {
|
|
case "teamspeak_pinmessage":
|
|
if tsConfig.PinMessageMode && !tsConfig.SendMessageMode {
|
|
needEdit = false
|
|
_, err := opts.Thebot.AnswerCallbackQuery(opts.Ctx, &bot.AnswerCallbackQueryParams{
|
|
CallbackQueryID: opts.CallbackQuery.ID,
|
|
Text: "您至少要保留一个检测用户变动的方式",
|
|
ShowAlert: true,
|
|
})
|
|
wrap.ErrIf(err).MsgT(flaterr.AnswerCallbackQuery, "at least need one notice method")
|
|
} else {
|
|
tsConfig.PinMessageMode = !tsConfig.PinMessageMode
|
|
needSave = true
|
|
if tsConfig.PinMessageMode {
|
|
if tsConfig.PinnedMessageID != 0 {
|
|
// 机器人启动时没有使用置顶模式,但后续开了,而且消息 ID 不为零,就假设已经成功置顶了
|
|
tsConfig.s.IsMessagePinned = true
|
|
}
|
|
} else {
|
|
// 关闭时解除当前消息的置顶
|
|
tsConfig.RemovePinnedMessage(opts.Ctx, true)
|
|
}
|
|
}
|
|
case "teamspeak_pinmessage_deletepinedmessage":
|
|
tsConfig.DeleteOldPinnedMessage = !tsConfig.DeleteOldPinnedMessage
|
|
needSave = true
|
|
case "teamspeak_sendmessage":
|
|
if tsConfig.SendMessageMode && !tsConfig.PinMessageMode {
|
|
needEdit = false
|
|
_, err := opts.Thebot.AnswerCallbackQuery(opts.Ctx, &bot.AnswerCallbackQueryParams{
|
|
CallbackQueryID: opts.CallbackQuery.ID,
|
|
Text: "您至少要保留一个检测用户变动的方式",
|
|
ShowAlert: true,
|
|
})
|
|
wrap.ErrIf(err).MsgT(flaterr.AnswerCallbackQuery, "at least need one notice method")
|
|
} else {
|
|
tsConfig.SendMessageMode = !tsConfig.SendMessageMode
|
|
needSave = true
|
|
needEditTask = true
|
|
}
|
|
case "teamspeak_sendmessage_autodelete":
|
|
tsConfig.AutoDeleteMessage = !tsConfig.AutoDeleteMessage
|
|
needSave = true
|
|
needEditTask = true
|
|
case "teamspeak_clear":
|
|
needEdit = false
|
|
var needDelMsgIDs []int
|
|
|
|
for _, msg := range tsConfig.s.OldMessageID {
|
|
needDelMsgIDs = append(needDelMsgIDs, msg.ID)
|
|
}
|
|
|
|
if len(needDelMsgIDs) > 0 {
|
|
_, err := botInstance.DeleteMessages(opts.Ctx, &bot.DeleteMessagesParams{
|
|
ChatID: tsConfig.GroupID,
|
|
MessageIDs: needDelMsgIDs,
|
|
})
|
|
if err != nil {
|
|
_, err = opts.Thebot.AnswerCallbackQuery(opts.Ctx, &bot.AnswerCallbackQueryParams{
|
|
CallbackQueryID: opts.CallbackQuery.ID,
|
|
Text: fmt.Sprintln("删除旧的通知消息发生错误", err.Error()),
|
|
ShowAlert: true,
|
|
})
|
|
wrap.ErrIf(err).MsgT(flaterr.AnswerCallbackQuery, "delete old message failed notice")
|
|
} else {
|
|
_, err = opts.Thebot.AnswerCallbackQuery(opts.Ctx, &bot.AnswerCallbackQueryParams{
|
|
CallbackQueryID: opts.CallbackQuery.ID,
|
|
Text: fmt.Sprintf("已删除 %d 条旧的通知消息", len(needDelMsgIDs)),
|
|
})
|
|
wrap.ErrIf(err).MsgT(flaterr.AnswerCallbackQuery, "delete old message success notice")
|
|
}
|
|
} else {
|
|
_, err := opts.Thebot.AnswerCallbackQuery(opts.Ctx, &bot.AnswerCallbackQueryParams{
|
|
CallbackQueryID: opts.CallbackQuery.ID,
|
|
Text: "没有旧的通知消息",
|
|
ShowAlert: true,
|
|
})
|
|
wrap.ErrIf(err).MsgT(flaterr.AnswerCallbackQuery, "no old messages notice")
|
|
}
|
|
}
|
|
|
|
if needEditTask {
|
|
if tsConfig.s.IsDeleteMessageTaskScheduled {
|
|
if tsConfig.SendMessageMode && tsConfig.AutoDeleteMessage {
|
|
tsConfig.ResumeDeleteMessageTask(opts.Ctx)
|
|
} else {
|
|
tsConfig.PauseDeleteMessageTask(opts.Ctx)
|
|
tsConfig.s.OldMessageID = []OldMessageID{}
|
|
}
|
|
} else {
|
|
_, err := opts.Thebot.AnswerCallbackQuery(opts.Ctx, &bot.AnswerCallbackQueryParams{
|
|
CallbackQueryID: opts.CallbackQuery.ID,
|
|
Text: "您的操作已保存,但因为删除消息的任务没有添加成功,无法自动删除消息,请尝试重启机器人",
|
|
ShowAlert: true,
|
|
})
|
|
wrap.ErrIf(err).MsgT(flaterr.AnswerCallbackQuery, "delete message task not scheduled")
|
|
}
|
|
}
|
|
|
|
if needEdit {
|
|
var buttons [][]models.InlineKeyboardButton
|
|
|
|
if tsConfig.SendMessageMode {
|
|
buttons = append(buttons, []models.InlineKeyboardButton{
|
|
{
|
|
Text: utils.TextForTrueOrFalse(tsConfig.SendMessageMode, "✅ ", "") + "发送消息通知",
|
|
CallbackData: "teamspeak_sendmessage",
|
|
},
|
|
{
|
|
Text: utils.TextForTrueOrFalse(tsConfig.AutoDeleteMessage, "✅ ", "") + "自动删除旧消息",
|
|
CallbackData: "teamspeak_sendmessage_autodelete",
|
|
},
|
|
})
|
|
} else {
|
|
buttons = append(buttons, []models.InlineKeyboardButton{{
|
|
Text: utils.TextForTrueOrFalse(tsConfig.SendMessageMode, "✅ ", "") + "发送消息通知",
|
|
CallbackData: "teamspeak_sendmessage",
|
|
}})
|
|
}
|
|
|
|
if tsConfig.PinMessageMode {
|
|
buttons = append(buttons, []models.InlineKeyboardButton{
|
|
{
|
|
Text: utils.TextForTrueOrFalse(tsConfig.PinMessageMode, "✅ ", "") + "显示在置顶消息",
|
|
CallbackData: "teamspeak_pinmessage",
|
|
},
|
|
{
|
|
Text: utils.TextForTrueOrFalse(tsConfig.DeleteOldPinnedMessage, "✅ ", "") + "删除旧的置顶消息",
|
|
CallbackData: "teamspeak_pinmessage_deletepinedmessage",
|
|
},
|
|
})
|
|
} else {
|
|
buttons = append(buttons, []models.InlineKeyboardButton{{
|
|
Text: utils.TextForTrueOrFalse(tsConfig.PinMessageMode, "✅ ", "") + "显示在置顶消息",
|
|
CallbackData: "teamspeak_pinmessage",
|
|
}})
|
|
}
|
|
buttons = append(buttons, []models.InlineKeyboardButton{{
|
|
Text: "关闭菜单",
|
|
CallbackData: "delete_this_message",
|
|
}},)
|
|
|
|
_, err := opts.Thebot.EditMessageText(opts.Ctx, &bot.EditMessageTextParams{
|
|
ChatID: opts.CallbackQuery.Message.Message.Chat.ID,
|
|
MessageID: opts.CallbackQuery.Message.Message.ID,
|
|
Text: "选择通知用户变动的方式",
|
|
ReplyMarkup: &models.InlineKeyboardMarkup{ InlineKeyboard: buttons },
|
|
})
|
|
wrap.ErrIf(err).MsgT(flaterr.EditMessageText, "teamspeak manage keyboard")
|
|
}
|
|
|
|
if needSave {
|
|
err := saveTeamspeakData(opts.Ctx)
|
|
wrap.ErrIf(err).Msg("failed to save teamspeak data")
|
|
}
|
|
} else {
|
|
_, err := opts.Thebot.AnswerCallbackQuery(opts.Ctx, &bot.AnswerCallbackQueryParams{
|
|
CallbackQueryID: opts.CallbackQuery.ID,
|
|
Text: "您没有权限修改此内容",
|
|
ShowAlert: true,
|
|
})
|
|
wrap.ErrIf(err).MsgT(flaterr.AnswerCallbackQuery, "no permission to change teamspeak config")
|
|
}
|
|
|
|
return wrap.Flat()
|
|
}
|