package steamplaying import ( "fmt" "log" "regexp" "strings" "time" "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}}, } // action.ActionManager.SendMsg(msg) log.Println(msg.ReplyMsg) } } // 更新playingMap playingMap = make(map[string]string) for _, player := range players { if player.GameID != "" { playingMap[player.SteamID] = player.GameID } } once = false }) }