11
This commit is contained in:
+10
-1
@@ -126,6 +126,15 @@
|
|||||||
"goods_type": "3",
|
"goods_type": "3",
|
||||||
"sort[price]": "1"
|
"sort[price]": "1"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"wzry_zhanji":{
|
||||||
|
"url":"https://api.t1qq.com/api/tool/wzrr/morebattle",
|
||||||
|
"method":"GET",
|
||||||
|
"description":"魔盒中模糊查找剑网三的物品数据",
|
||||||
|
"params":{
|
||||||
|
"key": "vBpEzoiC9z5A9c9Nn83IhLn6M9",
|
||||||
|
"id": "489048724",
|
||||||
|
"option": "1"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+22
-19
@@ -73,39 +73,42 @@ class APIClient:
|
|||||||
|
|
||||||
async def _handle_response(self, response):
|
async def _handle_response(self, response):
|
||||||
"""
|
"""
|
||||||
处理HTTP响应
|
处理HTTP响应(增强版:兼容 text/json 和非标准 JSON)
|
||||||
|
|
||||||
Args:
|
|
||||||
response: aiohttp响应对象
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
解析后的数据或None
|
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
# 添加响应日志
|
|
||||||
logger.debug(f"响应状态: {response.status}")
|
logger.debug(f"响应状态: {response.status}")
|
||||||
|
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
data = await response.json()
|
|
||||||
|
# ----------------------
|
||||||
|
# 强制兼容 text/json 类型
|
||||||
|
# ----------------------
|
||||||
|
try:
|
||||||
|
# content_type=None 忽略 MIME 类型检查
|
||||||
|
data = await response.json(content_type=None)
|
||||||
|
except Exception:
|
||||||
|
# 响应不是 JSON,尝试手动解析
|
||||||
|
text = await response.text()
|
||||||
|
logger.debug(f"原始文本响应: {text}")
|
||||||
|
|
||||||
|
# 尝试解析 JSON 字符串
|
||||||
|
try:
|
||||||
|
data = json.loads(text)
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
logger.error("无法解析为 JSON 数据")
|
||||||
|
return None
|
||||||
|
|
||||||
logger.debug(f"响应数据: {data}")
|
logger.debug(f"响应数据: {data}")
|
||||||
|
|
||||||
# 检查API响应状态
|
|
||||||
return self._check_response_data(data)
|
return self._check_response_data(data)
|
||||||
|
|
||||||
except aiohttp.ClientError as e:
|
except aiohttp.ClientError as e:
|
||||||
logger.error(f"HTTP错误: {e}")
|
logger.error(f"HTTP错误: {e}")
|
||||||
return None
|
return None
|
||||||
except json.JSONDecodeError as e:
|
except Exception as e:
|
||||||
logger.error(f"JSON解析错误: {e}")
|
logger.error(f"未知错误: {e}")
|
||||||
# 尝试读取原始文本内容
|
|
||||||
try:
|
|
||||||
text_content = await response.text()
|
|
||||||
logger.error(f"原始响应内容: {text_content}")
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def _check_response_data(self, data):
|
def _check_response_data(self, data):
|
||||||
"""
|
"""
|
||||||
检查API响应数据的通用逻辑
|
检查API响应数据的通用逻辑
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from astrbot.api import logger
|
||||||
|
|
||||||
|
from .class_reqsest import APIClient
|
||||||
|
from .cless_mysql import AsyncMySQL
|
||||||
|
from .function_basic import load_template,extract_field,flatten_field,extract_fields,gold_to_string,plot_line_chart_base64
|
||||||
|
|
||||||
|
class WZRYFunction:
|
||||||
|
def __init__(self, api_config,db: AsyncMySQL ):
|
||||||
|
self.__api = APIClient()
|
||||||
|
self.__db = db
|
||||||
|
self.__api_config = api_config
|
||||||
|
|
||||||
|
async def zhanji(self,id: str ,option: str):
|
||||||
|
"""
|
||||||
|
战绩查询
|
||||||
|
"""
|
||||||
|
return_data = {
|
||||||
|
"code": 0,
|
||||||
|
"msg": "功能函数未执行",
|
||||||
|
"data": {}
|
||||||
|
}
|
||||||
|
#在配置文件中获取接口配置
|
||||||
|
api_config = self.__api_config["wzry_zhanji"]
|
||||||
|
#更新参数
|
||||||
|
api_config["params"]["id"] = id
|
||||||
|
api_config["params"]["option"] = option
|
||||||
|
fields = ["gametime","killcnt","deadcnt","assistcnt","gameresult","mvpcnt","losemvp","mapName",
|
||||||
|
"oldMasterMatchScore","newMasterMatchScore","usedTime","winNum","failNum","roleJobName","stars","desc",
|
||||||
|
"gradeGame","heroIcon"]
|
||||||
|
# 处理返回数据
|
||||||
|
try:
|
||||||
|
# 获取数据
|
||||||
|
data = await self.__api.get(api_config["url"],api_config["params"],"data")
|
||||||
|
if not data:
|
||||||
|
return_data["msg"] = "获取接口信息失败"
|
||||||
|
return return_data
|
||||||
|
result = extract_fields(data["list"], fields)
|
||||||
|
result = result[:15]
|
||||||
|
# 数据处理
|
||||||
|
for m in result:
|
||||||
|
minutes = m["usedTime"] // 60
|
||||||
|
seconds = m["usedTime"] % 60
|
||||||
|
m["time_str"] = f"{minutes}:{seconds:02d}"
|
||||||
|
# 可选:提前转义 gameresult
|
||||||
|
if m["gameresult"] == 1:
|
||||||
|
m["gameresult_label"] = "胜利"
|
||||||
|
m["gameresult_bg"] = "#e6fbf1"
|
||||||
|
m["gameresult_color"] = "#056a3a"
|
||||||
|
elif m["gameresult"] == 2:
|
||||||
|
m["gameresult_label"] = "失败"
|
||||||
|
m["gameresult_bg"] = "#fff0f0"
|
||||||
|
m["gameresult_color"] = "#9c1f1f"
|
||||||
|
else:
|
||||||
|
m["gameresult_label"] = "平局"
|
||||||
|
m["gameresult_bg"] = "#eee"
|
||||||
|
m["gameresult_color"] = "#555"
|
||||||
|
m["MVP"] = "混子"
|
||||||
|
if m["mvpcnt"] ==1:
|
||||||
|
m["MVP"] = "胜方MVP"
|
||||||
|
if m["mvpcnt"] ==1:
|
||||||
|
m["MVP"] = "败方MVP"
|
||||||
|
|
||||||
|
return_data["data"] = result
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"处理数据时出错: {e}")
|
||||||
|
return_data["msg"] = "处理接口返回信息时出错"
|
||||||
|
# 加载模板
|
||||||
|
try:
|
||||||
|
return_data["temp"] = load_template("temp_test.html")
|
||||||
|
except FileNotFoundError as e:
|
||||||
|
logger.error(f"加载模板失败: {e}")
|
||||||
|
return_data["msg"] = "系统错误:模板文件不存在"
|
||||||
|
return return_data
|
||||||
|
return_data["code"] = 200
|
||||||
|
return return_data
|
||||||
|
|
||||||
|
|
||||||
+9
-15
@@ -1,20 +1,14 @@
|
|||||||
import aiohttp
|
import http.client
|
||||||
import asyncio
|
|
||||||
|
|
||||||
async def fetch_data():
|
conn = http.client.HTTPSConnection("api.t1qq.com")
|
||||||
url = "https://trade-api.seasunwbl.com/api/buyer/goods/list?filter%255Bstate%255D=1&page=1&size=10&goods_type=3&sort%255Bprice%255D=1&filter%255Brole_appearance%255D=%25E6%25BB%2587%25E6%259E%2597%25E9%259B%25A8%25C2%25B7%25E7%259F%25A5%25E5%258D%2597%25C2%25B7%25E6%25A0%2587%25E5%2587%2586"
|
payload = ''
|
||||||
headers = {
|
headers = {
|
||||||
'User-Agent': 'Apifox/1.0.0 (https://apifox.com)',
|
'User-Agent': 'Apifox/1.0.0 (https://apifox.com)',
|
||||||
'Accept': '*/*',
|
'Accept': '*/*',
|
||||||
'Host': 'trade-api.seasunwbl.com',
|
'Host': 'api.t1qq.com',
|
||||||
'Connection': 'keep-alive',
|
'Connection': 'keep-alive'
|
||||||
'Cookie': 'ts_session_id=AqvN1gha8NDXTjdauL6ApVT4KgbJLvPv0Dnd9uid; ts_session_id_=AqvN1gha8NDXTjdauL6ApVT4KgbJLvPv0Dnd9uid'
|
|
||||||
}
|
}
|
||||||
|
conn.request("GET", "/api/tool/wzrr/morebattle?key=vBpEzoiC9z5A9c9Nn83IhLn6M9&id=489048724&option=1", payload, headers)
|
||||||
async with aiohttp.ClientSession() as session:
|
res = conn.getresponse()
|
||||||
async with session.get(url, headers=headers) as response:
|
data = res.read()
|
||||||
data = await response.text()
|
print(data.decode("utf-8"))
|
||||||
print(data)
|
|
||||||
|
|
||||||
# Run the async function
|
|
||||||
asyncio.run(fetch_data())
|
|
||||||
@@ -10,6 +10,7 @@ from astrbot.api import AstrBotConfig
|
|||||||
|
|
||||||
from .core.cless_mysql import AsyncMySQL
|
from .core.cless_mysql import AsyncMySQL
|
||||||
from .core.cless_jx3 import JX3Function
|
from .core.cless_jx3 import JX3Function
|
||||||
|
from .core.cless_wzry import WZRYFunction
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -52,6 +53,7 @@ class Jx3ApiPlugin(Star):
|
|||||||
#创建类实例
|
#创建类实例
|
||||||
self.db = AsyncMySQL(db_config)
|
self.db = AsyncMySQL(db_config)
|
||||||
self.jx3fun = JX3Function(self.api_config,self.db)
|
self.jx3fun = JX3Function(self.api_config,self.db)
|
||||||
|
self.wzry = WZRYFunction(self.api_config,self.db)
|
||||||
# 周期函数调用
|
# 周期函数调用
|
||||||
|
|
||||||
|
|
||||||
@@ -285,6 +287,28 @@ class Jx3ApiPlugin(Star):
|
|||||||
|
|
||||||
yield event.plain_result(f"测试值:{self.test_server}")
|
yield event.plain_result(f"测试值:{self.test_server}")
|
||||||
|
|
||||||
|
|
||||||
|
@filter.command_group("王者")
|
||||||
|
def wz(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@wz.command("战绩")
|
||||||
|
async def wz_zhanji(self, event: AstrMessageEvent,ID: str = "489048724",option: str = "1"):
|
||||||
|
"""王者 战绩 服务器 天数"""
|
||||||
|
try:
|
||||||
|
data = await self.wzry.zhanji(ID,option)
|
||||||
|
# logger.info(f"王者荣耀战绩查询结果{data}")
|
||||||
|
if data["code"] == 200:
|
||||||
|
url = await self.html_render(data["temp"],{"data": data["data"]}, options={})
|
||||||
|
yield event.image_result(url)
|
||||||
|
else:
|
||||||
|
yield event.plain_result(data["msg"])
|
||||||
|
return
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"功能函数执行错误: {e}")
|
||||||
|
yield event.plain_result("猪脑过载,请稍后再试")
|
||||||
|
|
||||||
|
|
||||||
async def terminate(self):
|
async def terminate(self):
|
||||||
"""可选择实现异步的插件销毁方法,当插件被卸载/停用时会调用。"""
|
"""可选择实现异步的插件销毁方法,当插件被卸载/停用时会调用。"""
|
||||||
await self.db.close_pool()
|
await self.db.close_pool()
|
||||||
|
|||||||
+49
-22
@@ -1,30 +1,57 @@
|
|||||||
<div style="width: 1220px; margin: 0 auto;">
|
<div style="font-family: 'Microsoft YaHei', Arial, sans-serif; padding:20px; background:#f5f7fa; max-width:900px; margin:0 auto;">
|
||||||
<h1 style="text-align: center;">剑网3交易行价格查询</h1>
|
<h1 style="text-align:center; font-size:28px; margin-bottom:20px;">王者荣耀 — 对局列表</h1>
|
||||||
<p style="text-align: center;">服务器: {{ server }}</p>
|
|
||||||
|
|
||||||
<div style="overflow-x: auto; overflow-y: hidden;">
|
<table style="width:100%; border-collapse: collapse; position:relative;">
|
||||||
<table style="width: 100%; border-collapse: collapse; margin: 0 auto;">
|
|
||||||
<thead>
|
|
||||||
<tr style="height: 50px; text-align: center;">
|
|
||||||
<th style="border:1px solid #000; padding:4px;">物品名称</th>
|
|
||||||
<th style="border:1px solid #000; padding:4px;">最低价</th>
|
|
||||||
<th style="border:1px solid #000; padding:4px;">总数量</th>
|
|
||||||
<th style="border:1px solid #000; padding:4px;">数据更新时间</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for item in items %}
|
{% for m in data %}
|
||||||
<tr style="height: 45px; text-align: center;">
|
<tr style="background:#fff; border-radius:10px; margin-bottom:12px; position:relative;">
|
||||||
<td style="border:1px solid #000; padding:4px; text-align: left;">
|
<td style="width:64px; padding:8px; vertical-align:top;">
|
||||||
<img src="{{ item.IconID }}" alt="icon" style="width:20px; height:20px; vertical-align:middle; border-radius:4px; margin-right:6px;">
|
<img src="{{ m.heroIcon }}" style="width:64px; height:64px; object-fit:cover; border-radius:8px;">
|
||||||
{{ item.Name }}
|
<!-- 对局描述 -->
|
||||||
|
<div style="margin-top:6px; font-size:16px; color:#444; font-weight:bold; text-align:center;">
|
||||||
|
{{ m.desc }}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td style="padding:8px; vertical-align:top; position:relative;">
|
||||||
|
<!-- 胜负+MVP右上角 -->
|
||||||
|
<div style="position:absolute; top:8px; right:8px; display:flex; gap:6px; align-items:center;">
|
||||||
|
<!-- MVP -->
|
||||||
|
<div style="background:#b69f1c; color:#fff; font-weight:bold; padding:4px 8px; border-radius:6px; font-size:12px; box-shadow:0 2px 4px rgba(0,0,0,0.2);">
|
||||||
|
{{ m.MVP }}
|
||||||
|
</div>
|
||||||
|
<!-- 胜负 -->
|
||||||
|
<div style="background: {{ m.gameresult_bg }};
|
||||||
|
color: {{ m.gameresult_color }};
|
||||||
|
padding:6px 10px; border-radius:8px; font-weight:bold; font-size:14px;
|
||||||
|
box-shadow:0 2px 4px rgba(0,0,0,0.1);">
|
||||||
|
{{ m.gameresult_label }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 第一行:时间、地图、角色、星数 -->
|
||||||
|
<div style="margin-bottom:6px; color:#607785;">
|
||||||
|
{{ m.gametime }} · {{ m.mapName }}<br>
|
||||||
|
{{ m.roleJobName }} · ⭐{{ m.stars }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 第二行:击杀/死亡/助攻/时长 -->
|
||||||
|
<div style="margin-bottom:6px; font-size:14px; color:#333;">
|
||||||
|
击杀 {{ m.killcnt }} 死亡 {{ m.deadcnt }} 助攻 {{ m.assistcnt }} 时长 {{ m.time_str }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 第三行:评分 -->
|
||||||
|
<div style="font-size:15px; color:#000000; font-weight:bold; margin-bottom:6px;">
|
||||||
|
评分 {{ m.gradeGame }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 隐藏分右下角 -->
|
||||||
|
<div style="position:absolute; bottom:8px; right:8px; font-size:14px; color:#056a3a; font-weight:bold;">
|
||||||
|
巅峰赛积分 {{ m.oldMasterMatchScore }} → {{ m.newMasterMatchScore }}
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td style="border:1px solid #000; padding:4px;">{{ item.AvgPrice }}</td>
|
|
||||||
<td style="border:1px solid #000; padding:4px;">{{ item.SampleSize }}</td>
|
|
||||||
<td style="border:1px solid #000; padding:4px;">{{ item.Date }}</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr style="height:12px;"><td colspan="2"></td></tr> <!-- 间距 -->
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
<div style="font-family: 'Microsoft YaHei', Arial, sans-serif; padding:20px; background:#f5f7fa; max-width:900px; margin:0 auto;">
|
||||||
|
<h1 style="text-align:center; font-size:28px; margin-bottom:20px;">王者荣耀 — 对局列表</h1>
|
||||||
|
|
||||||
|
<table style="width:100%; border-collapse: collapse;">
|
||||||
|
<tbody>
|
||||||
|
{% for m in data %}
|
||||||
|
<tr style="background:#fff; border-radius:10px; margin-bottom:12px;">
|
||||||
|
<td style="width:64px; padding:8px; vertical-align:top;">
|
||||||
|
<img src="{{ m.heroIcon }}" style="width:64px; height:64px; object-fit:cover; border-radius:8px;">
|
||||||
|
</td>
|
||||||
|
<td style="padding:8px; vertical-align:top;">
|
||||||
|
<!-- 第一行:时间、地图、角色、星数、结果 -->
|
||||||
|
<div style="margin-bottom:6px;">
|
||||||
|
<span>{{ m.gametime }} · {{ m.mapName }}</span><br>
|
||||||
|
<span style="color:#607785;">{{ m.roleJobName }} · ⭐{{ m.stars }}</span><br>
|
||||||
|
<span style="padding: 2px 6px; border-radius:6px; font-size:13px;">
|
||||||
|
{{ m.gameresult_label }}
|
||||||
|
</span>
|
||||||
|
<span style="font-size:13px; color:#7b8b96; margin-left:6px;">评分 {{ m.gradeGame }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 第二行:击杀/死亡/助攻/时长 -->
|
||||||
|
<div style="margin-bottom:6px; font-size:14px; color:#333;">
|
||||||
|
击杀 {{ m.killcnt }} 死亡 {{ m.deadcnt }} 助攻 {{ m.assistcnt }} 时长 {{ m.time_str }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 第三行:描述/隐分 -->
|
||||||
|
<div style="font-size:13px; color:#61707a;">
|
||||||
|
<span>{{ m.desc }}</span>
|
||||||
|
<span style="float:right;">巅峰赛积分 {{ m.oldMasterMatchScore }} → {{ m.newMasterMatchScore }}</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="height:12px;"><td colspan="2"></td></tr> <!-- 间距 -->
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
Reference in New Issue
Block a user