304 lines
8.7 KiB
Go
304 lines
8.7 KiB
Go
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
|
||
})
|
||
}
|