-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
428 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
package steam | ||
|
||
import ( | ||
"fmt" | ||
"strconv" | ||
"strings" | ||
"time" | ||
|
||
"github.com/FloatTech/floatbox/binary" | ||
"github.com/FloatTech/floatbox/web" | ||
ctrl "github.com/FloatTech/zbpctrl" | ||
"github.com/tidwall/gjson" | ||
zero "github.com/wdvxdr1123/ZeroBot" | ||
"github.com/wdvxdr1123/ZeroBot/message" | ||
) | ||
|
||
// ----------------------- 远程调用 ---------------------- | ||
const ( | ||
URL = "https://api.steampowered.com/" // steam API 调用地址 | ||
StatusURL = "ISteamUser/GetPlayerSummaries/v2/?key=%+v&steamids=%+v" // 根据用户steamID获取用户状态 | ||
steamapikeygid = 3 | ||
) | ||
|
||
var apiKey string | ||
|
||
func init() { | ||
engine.OnRegex(`^steam绑定\s*api\s*key\s*(.*)$`, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) { | ||
apiKey = ctx.State["regex_matched"].([]string)[1] | ||
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx]) | ||
_ = m.Manager.Response(steamapikeygid) | ||
err := m.Manager.SetExtra(steamapikeygid, apiKey) | ||
if err != nil { | ||
ctx.SendChain(message.Text("[steam] ERROR: 保存apikey失败!")) | ||
return | ||
} | ||
ctx.SendChain(message.Text("保存apikey成功!")) | ||
}) | ||
engine.OnFullMatch("查看apikey", zero.OnlyPrivate, zero.SuperUserPermission, getDB).SetBlock(true).Handle(func(ctx *zero.Ctx) { | ||
ctx.SendChain(message.Text("apikey为: ", apiKey)) | ||
}) | ||
engine.OnFullMatch("拉取steam订阅", getDB).SetBlock(true).Handle(func(ctx *zero.Ctx) { | ||
su := zero.BotConfig.SuperUsers[0] | ||
// 获取所有处于监听状态的用户信息 | ||
infos, err := database.findAll() | ||
if err != nil { | ||
// 挂了就给管理员发消息 | ||
ctx.SendPrivateMessage(su, message.Text("[steam] ERROR: ", err)) | ||
return | ||
} | ||
if len(infos) == 0 { | ||
return | ||
} | ||
// 收集这波用户的streamId,然后查当前的状态,并建立信息映射表 | ||
streamIds := make([]string, len(infos)) | ||
localPlayerMap := make(map[int64]*player) | ||
for i, info := range infos { | ||
streamIds[i] = strconv.FormatInt(info.SteamID, 10) | ||
localPlayerMap[info.SteamID] = info | ||
} | ||
// 将所有用户状态查一遍 | ||
playerStatus, err := getPlayerStatus(streamIds...) | ||
if err != nil { | ||
// 出错就发消息 | ||
ctx.SendPrivateMessage(su, message.Text("[steam] ERROR: ", err)) | ||
return | ||
} | ||
// 遍历返回的信息做对比,假如信息有变化则发消息 | ||
now := time.Now() | ||
msg := make(message.Message, 0, len(playerStatus)) | ||
for _, playerInfo := range playerStatus { | ||
msg = msg[:0] | ||
localInfo := localPlayerMap[playerInfo.SteamID] | ||
// 排除不需要处理的情况 | ||
if localInfo.GameID == 0 && playerInfo.GameID == 0 { | ||
continue | ||
} | ||
// 打开游戏 | ||
if localInfo.GameID == 0 && playerInfo.GameID != 0 { | ||
msg = append(msg, message.Text(playerInfo.PersonaName, "正在玩", playerInfo.GameExtraInfo)) | ||
localInfo.LastUpdate = now.Unix() | ||
} | ||
// 更换游戏 | ||
if localInfo.GameID != 0 && playerInfo.GameID != localInfo.GameID && playerInfo.GameID != 0 { | ||
msg = append(msg, message.Text(playerInfo.PersonaName, "玩了", (now.Unix()-localInfo.LastUpdate)/60, "分钟后, 丢下了", localInfo.GameExtraInfo, ", 转头去玩", playerInfo.GameExtraInfo)) | ||
localInfo.LastUpdate = now.Unix() | ||
} | ||
// 关闭游戏 | ||
if playerInfo.GameID != localInfo.GameID && playerInfo.GameID == 0 { | ||
msg = append(msg, message.Text(playerInfo.PersonaName, "玩了", (now.Unix()-localInfo.LastUpdate)/60, "分钟后, 关掉了", localInfo.GameExtraInfo)) | ||
localInfo.LastUpdate = 0 | ||
} | ||
if len(msg) != 0 { | ||
groups := strings.Split(localInfo.Target, ",") | ||
for _, groupString := range groups { | ||
group, err := strconv.ParseInt(groupString, 10, 64) | ||
if err != nil { | ||
ctx.SendPrivateMessage(su, message.Text("[steam] ERROR: ", err, "\nOTHER: SteamID ", localInfo.SteamID)) | ||
continue | ||
} | ||
ctx.SendGroupMessage(group, msg) | ||
} | ||
} | ||
// 更新数据 | ||
localInfo.GameID = playerInfo.GameID | ||
localInfo.GameExtraInfo = playerInfo.GameExtraInfo | ||
if err = database.update(localInfo); err != nil { | ||
ctx.SendPrivateMessage(su, message.Text("[steam] ERROR: ", err, "\nEXP: 更新数据失败\nOTHER: SteamID ", localInfo.SteamID)) | ||
} | ||
} | ||
}) | ||
} | ||
|
||
// getPlayerStatus 获取用户状态 | ||
func getPlayerStatus(streamIds ...string) ([]*player, error) { | ||
players := make([]*player, 0) | ||
// 拼接请求地址 | ||
url := fmt.Sprintf(URL+StatusURL, apiKey, strings.Join(streamIds, ",")) | ||
// 拉取并解析数据 | ||
data, err := web.GetData(url) | ||
if err != nil { | ||
return players, err | ||
} | ||
dataStr := binary.BytesToString(data) | ||
index := gjson.Get(dataStr, "response.players.#").Uint() | ||
for i := uint64(0); i < index; i++ { | ||
players = append(players, &player{ | ||
SteamID: gjson.Get(dataStr, fmt.Sprintf("response.players.%d.steamid", i)).Int(), | ||
PersonaName: gjson.Get(dataStr, fmt.Sprintf("response.players.%d.personaname", i)).String(), | ||
GameID: gjson.Get(dataStr, fmt.Sprintf("response.players.%d.gameid", i)).Int(), | ||
GameExtraInfo: gjson.Get(dataStr, fmt.Sprintf("response.players.%d.gameextrainfo", i)).String(), | ||
}) | ||
} | ||
return players, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
// Package steam 获取steam用户状态 | ||
package steam | ||
|
||
import ( | ||
"strconv" | ||
"strings" | ||
"time" | ||
|
||
"github.com/FloatTech/floatbox/binary" | ||
"github.com/FloatTech/floatbox/math" | ||
ctrl "github.com/FloatTech/zbpctrl" | ||
"github.com/FloatTech/zbputils/control" | ||
"github.com/FloatTech/zbputils/ctxext" | ||
"github.com/FloatTech/zbputils/img/text" | ||
zero "github.com/wdvxdr1123/ZeroBot" | ||
"github.com/wdvxdr1123/ZeroBot/message" | ||
) | ||
|
||
var ( | ||
engine = control.Register("steam", &ctrl.Options[*zero.Ctx]{ | ||
DisableOnDefault: false, | ||
Brief: "steam相关插件", | ||
Help: "- steam添加订阅 xxxxxxx (可输入需要绑定的 steamid)\n" + | ||
"- steam删除订阅 xxxxxxx (删除你创建的对于 steamid 的绑定)\n" + | ||
"- steam查询订阅 (查询本群内所有的绑定对象)\n" + | ||
"-----------------------\n" + | ||
"- steam绑定 api key xxxxxxx (密钥在steam网站申请, 申请地址: https://steamcommunity.com/dev/registerkey)\n" + | ||
"- 查看apikey (查询已经绑定的密钥)\n" + | ||
"- 拉取steam订阅 (使用插件定时任务开始)\n" + | ||
"-----------------------\n" + | ||
"Tips: steamID在用户资料页的链接上面, 形如7656119820673xxxx\n" + | ||
"需要先私聊绑定apikey, 订阅用户之后使用job插件设置定时, 例: \n" + | ||
"记录在\"@every 1m\"触发的指令\n" + | ||
"拉取steam订阅", | ||
PrivateDataFolder: "steam", | ||
}).ApplySingle(ctxext.DefaultSingle) | ||
) | ||
|
||
func init() { | ||
// 创建绑定流程 | ||
engine.OnRegex(`^steam添加订阅\s*(\d+)$`, zero.OnlyGroup, getDB).SetBlock(true).Handle(func(ctx *zero.Ctx) { | ||
steamidstr := ctx.State["regex_matched"].([]string)[1] | ||
steamID := math.Str2Int64(steamidstr) | ||
// 获取用户状态 | ||
playerStatus, err := getPlayerStatus(steamidstr) | ||
if err != nil { | ||
ctx.SendChain(message.Text("[steam] ERROR: ", err, "\nEXP: 添加失败, 获取用户信息错误")) | ||
return | ||
} | ||
if len(playerStatus) == 0 { | ||
ctx.SendChain(message.Text("[steam] ERROR: 需要添加的用户不存在, 请检查id或url")) | ||
return | ||
} | ||
playerData := playerStatus[0] | ||
// 判断用户是否已经初始化:若未初始化,通过用户的steamID获取当前状态并初始化;若已经初始化则更新用户信息 | ||
info, err := database.find(steamID) | ||
if err != nil { | ||
ctx.SendChain(message.Text("[steam] ERROR: ", err, "\nEXP: 添加失败,数据库错误")) | ||
return | ||
} | ||
// 处理数据 | ||
groupID := strconv.FormatInt(ctx.Event.GroupID, 10) | ||
if info.Target == "" { | ||
info = player{ | ||
SteamID: steamID, | ||
PersonaName: playerData.PersonaName, | ||
Target: groupID, | ||
GameID: playerData.GameID, | ||
GameExtraInfo: playerData.GameExtraInfo, | ||
LastUpdate: time.Now().Unix(), | ||
} | ||
} else if !strings.Contains(info.Target, groupID) { | ||
info.Target = strings.Join([]string{info.Target, groupID}, ",") | ||
} | ||
// 更新数据库 | ||
if err = database.update(&info); err != nil { | ||
ctx.SendChain(message.Text("[steam] ERROR: ", err, "\nEXP: 更新数据库失败")) | ||
return | ||
} | ||
ctx.SendChain(message.Text("添加成功")) | ||
}) | ||
// 删除绑定流程 | ||
engine.OnRegex(`^steam删除订阅\s*(\d+)$`, zero.OnlyGroup, getDB).SetBlock(true).Handle(func(ctx *zero.Ctx) { | ||
steamID := math.Str2Int64(ctx.State["regex_matched"].([]string)[1]) | ||
groupID := strconv.FormatInt(ctx.Event.GroupID, 10) | ||
// 判断是否已经绑定该steamID,若已绑定就将群列表从推送群列表钟去除 | ||
info, err := database.findWithGroupID(steamID, groupID) | ||
if err != nil { | ||
ctx.SendChain(message.Text("[steam] ERROR: ", err, "\nEXP: 删除失败,数据库错误")) | ||
return | ||
} | ||
if info.SteamID == 0 { | ||
ctx.SendChain(message.Text("[steam] ERROR: 所需要删除的用户不存在。")) | ||
return | ||
} | ||
// 从绑定列表中剔除需要删除的对象 | ||
targets := strings.Split(info.Target, ",") | ||
newTargets := make([]string, 0) | ||
for _, target := range targets { | ||
if target == groupID { | ||
continue | ||
} | ||
newTargets = append(newTargets, target) | ||
} | ||
if len(newTargets) == 0 { | ||
if err = database.del(steamID); err != nil { | ||
ctx.SendChain(message.Text("[steam] ERROR: ", err, "\nEXP: 删除失败,数据库错误")) | ||
return | ||
} | ||
} else { | ||
info.Target = strings.Join(newTargets, ",") | ||
if err = database.update(&info); err != nil { | ||
ctx.SendChain(message.Text("[steam] ERROR: ", err, "\nEXP: 删除失败,数据库错误")) | ||
return | ||
} | ||
} | ||
ctx.SendChain(message.Text("删除成功")) | ||
}) | ||
// 查询当前群绑定信息 | ||
engine.OnFullMatch("steam查询订阅", zero.OnlyGroup, getDB).SetBlock(true).Handle(func(ctx *zero.Ctx) { | ||
// 获取群信息 | ||
groupID := strconv.FormatInt(ctx.Event.GroupID, 10) | ||
// 获取所有绑定信息 | ||
infos, err := database.findAll() | ||
if err != nil { | ||
ctx.SendChain(message.Text("[steam] ERROR: ", err, "\nEXP: 查询订阅失败, 数据库错误")) | ||
return | ||
} | ||
if len(infos) == 0 { | ||
ctx.SendChain(message.Text("[steam] ERROR: 还未订阅过用户关系!")) | ||
return | ||
} | ||
// 遍历所有信息,如果包含该群就收集对应的steamID | ||
var sb strings.Builder | ||
head := " 查询steam订阅成功, 该群订阅的用户有: \n" | ||
sb.WriteString(head) | ||
for _, info := range infos { | ||
if strings.Contains(info.Target, groupID) { | ||
sb.WriteString(" ") | ||
sb.WriteString(info.PersonaName) | ||
sb.WriteString(":") | ||
sb.WriteString(strconv.FormatInt(info.SteamID, 10)) | ||
sb.WriteString("\n") | ||
} | ||
} | ||
if sb.String() == head { | ||
ctx.SendChain(message.Text("查询成功,该群暂时还没有被绑定的用户!")) | ||
return | ||
} | ||
// 组装并返回结果 | ||
data, err := text.RenderToBase64(sb.String(), text.FontFile, 400, 18) | ||
if err != nil { | ||
ctx.SendChain(message.Text("[steam] ERROR: ", err)) | ||
return | ||
} | ||
ctx.SendChain(message.Image("base64://" + binary.BytesToString(data))) | ||
}) | ||
} |
Oops, something went wrong.