qq_bot/handler/steamplaying/steam_playing.go

304 lines
8.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package steamplaying
import (
"fmt"
"log"
"regexp"
"strings"
"time"
"git.lxtend.com/qqbot/action"
"git.lxtend.com/qqbot/config"
"git.lxtend.com/qqbot/constants"
"git.lxtend.com/qqbot/handler"
"git.lxtend.com/qqbot/model"
"git.lxtend.com/qqbot/util"
)
// 用于记录玩家退出游戏的信息
type GameExitInfo struct {
GameID string // 游戏ID
ExitTime time.Time // 退出时间
}
func init() {
// Register the handler with the server
handler.RegisterHandler("绑steam", bindSteam, constants.LEVEL_USER)
handler.RegisterHelpInform("绑steam", "steam", "输入steamID绑定您的steam账号。可以通过客户端右上角-账户明细 https://store.steampowered.com/account/ 查看steamID位于页面左上角")
handler.RegisterHandler("启用上号通知", bindSteamInGroup, constants.LEVEL_USER)
handler.RegisterHelpInform("启用上号通知", "steam", "在群内启用您的steam上号通知")
handler.RegisterHandler("解绑steam", unbindSteam, constants.LEVEL_USER)
handler.RegisterHelpInform("解绑steam", "steam", "解绑您的steam账号并解绑所有群监听")
handler.RegisterHandler("禁用上号通知", unbindSteamInGroup, constants.LEVEL_USER)
handler.RegisterHelpInform("禁用上号通知", "steam", "禁用您在本群的steam上号通知")
handler.RegisterHandler("查房", checkSteamPlaying, constants.LEVEL_USER)
handler.RegisterHelpInform("查房", "steam", "查看群内成员的steam游戏状态")
go RoundCheckSteamPlaying()
}
func bindSteam(msg model.Message) *model.Reply {
token := util.SplitN(msg.RawMsg, 2)
if len(token) < 2 {
return &model.Reply{
ReplyMsg: "请输入steamID",
ReferOriginMsg: true,
FromMsg: msg,
}
} else {
re := regexp.MustCompile(`https://steamcommunity\.com/profiles/([0-9]+)`)
steamIdInUrl := re.FindStringSubmatch(token[1])
if steamIdInUrl != nil {
token[1] = steamIdInUrl[1]
}
if valid, err := checkSteamIDValid(token[1]); !valid {
return &model.Reply{
ReplyMsg: fmt.Sprintf("steamID无效: %v", err),
ReferOriginMsg: true,
FromMsg: msg,
}
} else if err != nil {
return &model.Reply{
ReplyMsg: fmt.Sprintf("steamID验证失败: %v", err),
ReferOriginMsg: true,
FromMsg: msg,
}
}
if err := bindSteamUser(msg.UserId, token[1]); err != nil {
return &model.Reply{
ReplyMsg: fmt.Sprintf("绑定失败: %v", err),
ReferOriginMsg: true,
FromMsg: msg,
}
}
}
return &model.Reply{
ReplyMsg: fmt.Sprintf("绑定steam用户%s成功如果需要开启群内上号通知请输入 启用上号通知", token[1]),
ReferOriginMsg: true,
FromMsg: msg,
}
}
func bindSteamInGroup(msg model.Message) *model.Reply {
if user, err := getSteamUser(msg.UserId); err != nil {
return &model.Reply{
ReplyMsg: fmt.Sprintf("查询steam绑定失败: %v", err),
ReferOriginMsg: true,
FromMsg: msg,
}
} else if err := bindUserInGroup(msg.GroupInfo.GroupId, user.SteamID); err != nil {
return &model.Reply{
ReplyMsg: fmt.Sprintf("绑定至群监听列表失败: %v", err),
ReferOriginMsg: true,
FromMsg: msg,
}
}
return &model.Reply{
ReplyMsg: "绑定至群监听列表成功",
ReferOriginMsg: true,
FromMsg: msg,
}
}
func unbindSteam(msg model.Message) *model.Reply {
if user, err := getSteamUser(msg.UserId); err != nil {
return &model.Reply{
ReplyMsg: fmt.Sprintf("解绑失败: %v", err),
ReferOriginMsg: true,
FromMsg: msg,
}
} else {
if err := unbindUserInAllGroup(user.SteamID); err != nil {
return &model.Reply{
ReplyMsg: fmt.Sprintf("解绑所有群监听列表失败: %v", err),
ReferOriginMsg: true,
FromMsg: msg,
}
}
if err := unbindSteamUser(msg.UserId); err != nil {
return &model.Reply{
ReplyMsg: fmt.Sprintf("解绑失败: %v", err),
ReferOriginMsg: true,
FromMsg: msg,
}
}
}
return &model.Reply{
ReplyMsg: "解绑成功",
ReferOriginMsg: true,
FromMsg: msg,
}
}
func unbindSteamInGroup(msg model.Message) *model.Reply {
if user, err := getSteamUser(msg.UserId); err != nil {
return &model.Reply{
ReplyMsg: fmt.Sprintf("群监听解绑失败: %v", err),
ReferOriginMsg: true,
FromMsg: msg,
}
} else {
if err := unbindUserInGroup(msg.GroupInfo.GroupId, user.SteamID); err != nil {
return &model.Reply{
ReplyMsg: fmt.Sprintf("群监听解绑失败: %v", err),
ReferOriginMsg: true,
FromMsg: msg,
}
}
}
return &model.Reply{
ReplyMsg: "群监听解绑成功本群内将不再查询你的steam游戏状态",
ReferOriginMsg: true,
FromMsg: msg,
}
}
func checkSteamPlaying(msg model.Message) *model.Reply {
users, err := getSteamUsersInGroup(msg.GroupInfo.GroupId)
if err != nil {
return &model.Reply{
ReplyMsg: fmt.Sprintf("获取群成员steam列表失败: %v", err),
ReferOriginMsg: true,
FromMsg: msg,
}
}
var steamIds []string
for _, user := range users {
steamIds = append(steamIds, user.SteamID)
}
gameList, err := checkSteamGameStatus(steamIds)
if err != nil {
return &model.Reply{
ReplyMsg: fmt.Sprintf("获取游戏列表失败: %v", err),
ReferOriginMsg: true,
FromMsg: msg,
}
}
return &model.Reply{
ReplyMsg: gameList,
ReferOriginMsg: true,
FromMsg: msg,
}
}
func RoundCheckSteamPlaying() {
once := true
playingMap := map[string]string{}
// 记录玩家退出游戏的信息
exitInfoMap := map[string]GameExitInfo{}
util.AddCycleTask("checkSteamPlaying", 15*time.Second, 15*time.Second, func() {
// 检查当前时间是否在凌晨1点至早上8点之间
now := time.Now()
hour := now.Hour()
if hour >= 1 && hour < 8 {
return
}
allSteamIDs, err := getAllSteamID()
if err != nil {
fmt.Println("获取所有steamID失败: ", err)
return
}
groups, err := getAllGroupID()
if err != nil {
fmt.Println("获取群列表失败: ", err)
return
}
gamePlayingMap, players, err := checkDiffSteamGameStatus(allSteamIDs, playingMap)
if err != nil {
fmt.Println("获取游戏列表失败: ", err)
return
}
// 更新退出游戏信息
for steamId := range playingMap {
var currentGameID string
for _, player := range players {
if player.SteamID == steamId {
currentGameID = player.GameID
break
}
}
if currentGameID == "" { // 玩家退出游戏
// 从API响应中获取玩家之前的游戏信息
for _, player := range players {
if player.SteamID == steamId {
exitInfoMap[steamId] = GameExitInfo{
GameID: player.GameID,
ExitTime: time.Now(),
}
break
}
}
} else { // 玩家在玩游戏
if oldStatus, exists := playingMap[steamId]; exists && oldStatus != currentGameID {
// 玩家切换了游戏,清除退出记录
delete(exitInfoMap, steamId)
}
}
}
for _, group := range groups {
time.Sleep(15 * time.Second)
users, err := getSteamUsersInGroup(group)
if err != nil {
log.Println("获取群成员steam列表失败: ", err)
continue
}
var steamIds []string
for _, user := range users {
steamIds = append(steamIds, user.SteamID)
}
var gameList []string
for _, steamId := range steamIds {
if gameStatus, ok := gamePlayingMap[steamId]; ok {
// 检查是否是30分钟内重新登录同一游戏
if exitInfo, exists := exitInfoMap[steamId]; exists {
// 从API响应中获取当前游戏ID
var currentGameID string
for _, player := range players {
if player.SteamID == steamId {
currentGameID = player.GameID
break
}
}
if exitInfo.GameID == currentGameID && time.Since(exitInfo.ExitTime) <= 30*time.Minute {
// 30分钟内重新登录同一游戏更新退出时间并跳过通知
exitInfoMap[steamId] = GameExitInfo{
GameID: currentGameID,
ExitTime: time.Now(),
}
continue
}
// 清除退出记录
delete(exitInfoMap, steamId)
}
gameList = append(gameList, gameStatus)
}
}
if len(gameList) > 0 && !once {
msg := model.Reply{
ReplyMsg: "速报:\n" + strings.Join(gameList, "\n"),
ReferOriginMsg: false,
// FromMsg: model.Message{GroupInfo: model.GroupInfo{GroupId: group}},
FromMsg: model.Message{GroupInfo: model.GroupInfo{GroupId: config.ConfigManager.GetConfig().Management.ReportGroup}},
}
action.ActionManager.SendMsg(&msg)
}
}
// 更新playingMap
playingMap = make(map[string]string)
for _, player := range players {
if player.GameID != "" {
playingMap[player.SteamID] = player.GameID
}
}
once = false
})
}