另一种实现方案
使用Vgtime的检索后,这个插件仍然存在几个问题:
- Vgtime本身的搜索功能就比较垃圾(这是编辑老师说的..)
- 游戏范围限定在了Steam平台,这对于主机群来说太致命了
- 据使用者反馈,Steam的官方API在国内访问十分缓慢,时常出现请求失败
想解决它们,必须换一种思路。
不仅白嫖搜索框,还要白嫖游戏库!
其实在我的手机上,二柄的游戏检索功能可能是体验最好的,它可以实现中英文搜索、词汇联想,甚至是拼写纠正。但在使用app的搜索功能时,貌似需要登陆账号,尝试对其进行抓包:
>> 本文件内容为 https://v2.diershoubing.com/eb/combine_game/versions/?src=ios&version=9.54&auth=//&game_id=104808&plat_name=psn&platform_info=1 的请求抓包详情,供您分析和定位问题。
1. 请求内容 Request:
GET /eb/combine_game/versions/?src=ios&version=9.54&auth=c930cae3aa14cbae19a688c3f70d7b12&game_id=104808&plat_name=psn&platform_info=1 HTTP/1.1
Host: v2.diershoubing.com
Accept: */*
Cookie: //
User-Agent: erbinghd/9.54 (com.diershoubing.erbing; build:187; iOS 16.3.0) Alamofire/5.6.2
Accept-Language: zh-Hans-CN;q=1.0
Accept-Encoding: br;q=1.0, gzip;q=0.9, deflate;q=0.8
Connection: keep-alive
Markdown惊讶地发现,调用其搜索功能时并不需要加上Cookie,于是事情就容易多了
const response = await axios.get(`https://v2.diershoubing.com/eb/combine_game/search/?src=ios&version=9.54&search_name=${text}`);
const gamedata = response.data.combine_games
const chinese_name = gamedata[0].name
const game_id = gamedata[0].game_id
signal = true;
session.send(`\n猜你想搜:${chinese_name}\n\n如果您对搜索结果不满意,请回复“错误的”`);
session.execute(`id ${game_id}`);
signal = false;
session.prompt((session) => {
const appid = session.content;
if (appid == "错误的") {
const games = gamedata.slice(0, 10).map((game) => `游戏名称:${game.name},name_id:${game.game_id}`).join('\n')
session.send(games + "\n\n请输入您需要的name_id");
session.prompt((session) => {
const appid = session.content.match(/\d+/);
if (appid) {
session.execute(`id ${appid}`);
signal = false;
} else {
return session.send("请输入正确的name_id");
}
});
} else {
return;
}
});
});
JavaScript首先调用搜索功能,默认获取第一个游戏的ID,并执行下一个命令“id”查询具体信息,如果错误再显示全部搜索结果。下面定义ID命令:
ctx
.command("id <appid>", "检索游戏的game_id")
.alias('id:', 'ID' , 'game_id')
.action(async ({ session }, appid) => {
let response;
const link = `https://v2.diershoubing.com/eb/combine_game/detail/${appid}/?src=ios&version=9.54&pf=1`;
response = await axios.get(link)
if (response.ret === "-1") {
return 'name_id不存在!';
}else{
const data = response.data.combine_game;
const values = [];
if (data.name) {
values.push(`名称:${data.name}`);
}
if (data.desc && config.desc) {
values.push(`简介:${data.desc}`);
}
if (config.is_cn) {
if(data.is_cn){
values.push(`中文支持:True`);
}else{
values.push(`中文支持:False`);
}
}
if (data.release_date && config.date) {
let dateString = data.release_date;
let date = new Date(dateString);
let formattedDate = date.toLocaleDateString("zh-cn", {year: 'numeric', month: 'long', day: 'numeric'});
values.push(`发售日期:${formattedDate}`);
}
if (data.tag && config.tag) {
values.push(`标签:${data.tag}`);
}
if (data.price_detail && config.price ) {
let priceDetails = data.price_detail.map(price =>
`平台名称: ${price.platform_name},史低:${price.history_price},原价:${price.origin_price},现价: ${price.price}\n`
);
values.push(`全区售价:${priceDetails.join('')
}`);
}
if (data.played_rating && config.played_rating) {
values.push(`玩家评分:${data.played_rating}`);
}
if (response.data.medium_ratings && config.medium_ratings ) {
const ratings = response.data.medium_ratings.map(rating =>
`媒体: ${rating.source_name},评分:${rating.rating}\n`
);
values.push(`\n${ratings.join('')}`);
}
let imageData = null;
let image1 = null;
if (data.game_photo) {
imageData = await ctx.http.get(data.game_photo, { responseType: 'arraybuffer' });
}
if (data.img) {
image1 = await ctx.http.get(data.img, { responseType: 'arraybuffer' });
}
// 将图片数据拼接在返回的字符串中
let result = values.join('\n');
if (imageData) {
result += koishi_1.segment.image(imageData);
}
if (image1) {
result += koishi_1.segment.image(image1);
}
return result;
}
JavaScript到了这里,实现了全平台游戏、强大的中文检索、无需科学环境三个目标!
还有更多
进一步抓包可以发现,二柄app内似乎所有的内容未经加密,甚至不需要cookie,那意味着它们全部可以为己所用。
if (config.comments) {
const link = `https://v2.diershoubing.com/eb/combine_comment/list/game/${appid}/?src=ios&version=9.54&has_filter=1&is_load_steam_review=1&pn=0&rn=20`;
response = await axios.get(link)
if(response.data.combine_comments){
const data_comments = response.data.combine_comments;
const comments = data_comments.splice(0, 3).map(comment =>
`“${comment.content}”\n`
);
values.push(`评论:${comments.join('')}`);
}
JavaScript以上代码调用了评论的接口,在返回游戏信息上加上评论!
ctx
.command("打折游戏", "查询精选的打折作品")
.action(async ({ session }) => {
const url = (`https://v2.diershoubing.com/eb/combine_game/discount/?src=ios&version=9.54&rn=20`);
const response = await axios.get(url);
const ratings = response.data.combine_games.slice(0,config.limit).map(game =>
`【名称: 《${game.name}》,平台:${game.plat_name},原价: ${game.origin_price},折后价: ${game.price},优惠期截至: ${game.price_expired}】\n\n`
);
const values = [];
let imageData = null;
let image1 = null;
values.push(`近期优惠一览:${ratings.join('')}`);
if (response.data.combine_games[0].img) {
imageData = await ctx.http.get(response.data.combine_games[0].img, { responseType: 'arraybuffer' });
}
if (response.data.combine_games[1].img) {
image1 = await ctx.http.get(response.data.combine_games[1].img, { responseType: 'arraybuffer' });
}
let result = values.join('\n');
if (imageData) {
result += koishi_1.segment.image(imageData);
}
if (image1) {
result += koishi_1.segment.image(image1);
}
return result;
JavaScript又或者是调出二柄整理好的打折清单,可以做到的事情太多了。
总结与未来
插件上线一周内,它的下载了已经突破了一千,我也收到不少用户反馈,这篇文章中的代码已是多次迭代后的结果,未来一定会更加完善。
既然游戏查询完成了,那么一个查询用户的插件如何?当群内发现逆天言论时,不妨查查他的成分,若是看见某款开发时间RPG游戏,那一切可能就顺理成章了~
但无论是Steam、Xbox、PS还是NS,官方都没有提供任何有关用户信息的接口,需要自己想办法实现。我也发现了一个可能成功的库。