11
This commit is contained in:
@@ -0,0 +1,70 @@
|
|||||||
|
# core/request.py
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
from astrbot.api import logger
|
||||||
|
|
||||||
|
def api_data(api_url, json_data=None, outdata="data"):
|
||||||
|
"""
|
||||||
|
获取数据的POST请求函数
|
||||||
|
|
||||||
|
Args:
|
||||||
|
api_url: API地址
|
||||||
|
json_data: POST请求的JSON数据
|
||||||
|
outdata: 返回数据中要提取的字段,默认为"data"
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
成功时返回outdata字段的数据,失败返回None
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
response = requests.post(
|
||||||
|
api_url,
|
||||||
|
json=json_data, # JSON body数据
|
||||||
|
timeout=10,
|
||||||
|
verify=False
|
||||||
|
)
|
||||||
|
|
||||||
|
response.raise_for_status()
|
||||||
|
data = response.json()
|
||||||
|
|
||||||
|
if data.get('code') not in [200, "0"]:
|
||||||
|
logger.error(f"API返回错误: {data.get('msg', '未知错误')}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
return data.get(outdata, {})
|
||||||
|
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
logger.error(f"请求出错: {e}")
|
||||||
|
return None
|
||||||
|
except json.JSONDecodeError as e:
|
||||||
|
logger.error(f"JSON解析错误: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def fetch_jx3_data(api_url=None,outdata="data", **params):
|
||||||
|
"""
|
||||||
|
获取数据的GET请求函数
|
||||||
|
|
||||||
|
Args:
|
||||||
|
api_url: API地址
|
||||||
|
outdata: 返回数据中要提取的字段,默认为"data"
|
||||||
|
**params: 其他查询参数
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
成功时返回outdata字段的数据,失败返回None
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
response = requests.get(api_url, params=params, timeout=10, verify=False)
|
||||||
|
response.raise_for_status()
|
||||||
|
data = response.json()
|
||||||
|
|
||||||
|
if data.get('code') != 200:
|
||||||
|
logger.error(f"API返回错误: {data.get('msg', '未知错误')}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
return data.get(outdata, {})
|
||||||
|
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
logger.error(f"请求出错: {e}")
|
||||||
|
return None
|
||||||
|
except json.JSONDecodeError as e:
|
||||||
|
logger.error(f"JSON解析错误: {e}")
|
||||||
|
return None
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
# core/request.py
|
|
||||||
import requests
|
|
||||||
import json
|
|
||||||
from astrbot.api import logger
|
|
||||||
|
|
||||||
def fetch_jx3_data(api_url=None,outdata="data", **params):
|
|
||||||
# 函数实现
|
|
||||||
try:
|
|
||||||
response = requests.get(api_url, params=params, timeout=10, verify=False)
|
|
||||||
response.raise_for_status()
|
|
||||||
data = response.json()
|
|
||||||
|
|
||||||
if data.get('code') != 200:
|
|
||||||
logger.error(f"API返回错误: {data.get('msg', '未知错误')}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
return data.get(outdata, {})
|
|
||||||
|
|
||||||
except requests.exceptions.RequestException as e:
|
|
||||||
logger.error(f"请求出错: {e}")
|
|
||||||
return None
|
|
||||||
except json.JSONDecodeError as e:
|
|
||||||
logger.error(f"JSON解析错误: {e}")
|
|
||||||
return None
|
|
||||||
@@ -5,11 +5,9 @@ from astrbot.api.star import Context, Star, register
|
|||||||
from astrbot.api import logger
|
from astrbot.api import logger
|
||||||
from astrbot.api import AstrBotConfig
|
from astrbot.api import AstrBotConfig
|
||||||
|
|
||||||
from .core.request import fetch_jx3_data
|
|
||||||
from .core.jx3jiaoyihang import fetch_jx3_jiaoyihang
|
from .core.jx3jiaoyihang import fetch_jx3_jiaoyihang
|
||||||
from .core.load_template import load_template
|
from .core.load_template import load_template
|
||||||
|
from .core.api_data import api_data, fetch_jx3_data
|
||||||
from jinja2 import Template
|
|
||||||
|
|
||||||
# 禁用 SSL 警告
|
# 禁用 SSL 警告
|
||||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||||
@@ -28,7 +26,7 @@ class Jx3ApiPlugin(Star):
|
|||||||
|
|
||||||
@filter.command("剑三日常")
|
@filter.command("剑三日常")
|
||||||
async def jx3_richang(self, event: AstrMessageEvent):
|
async def jx3_richang(self, event: AstrMessageEvent):
|
||||||
"""获取剑网3日常活动信息"""
|
"""剑三日常"""
|
||||||
# 接口URL
|
# 接口URL
|
||||||
custom_url = "https://www.jx3api.com/data/active/calendar"
|
custom_url = "https://www.jx3api.com/data/active/calendar"
|
||||||
# 接口参数
|
# 接口参数
|
||||||
@@ -77,13 +75,10 @@ class Jx3ApiPlugin(Star):
|
|||||||
logger.error(f"处理数据时出错: {e}")
|
logger.error(f"处理数据时出错: {e}")
|
||||||
yield event.plain_result("处理接口返回信息时出错")
|
yield event.plain_result("处理接口返回信息时出错")
|
||||||
|
|
||||||
async def terminate(self):
|
|
||||||
"""可选择实现异步的插件销毁方法,当插件被卸载/停用时会调用。"""
|
|
||||||
|
|
||||||
|
|
||||||
@filter.command("剑三骚话")
|
@filter.command("剑三骚话")
|
||||||
async def jx3_shaohua(self, event: AstrMessageEvent):
|
async def jx3_shaohua(self, event: AstrMessageEvent):
|
||||||
"""随机获取一条与万花门派相关的骚话"""
|
"""剑三骚话"""
|
||||||
# 接口URL
|
# 接口URL
|
||||||
custom_url = "https://www.jx3api.com/data/saohua/random"
|
custom_url = "https://www.jx3api.com/data/saohua/random"
|
||||||
# 接口参数
|
# 接口参数
|
||||||
@@ -113,13 +108,10 @@ class Jx3ApiPlugin(Star):
|
|||||||
logger.error(f"处理数据时出错: {e}")
|
logger.error(f"处理数据时出错: {e}")
|
||||||
yield event.plain_result("处理接口返回信息时出错")
|
yield event.plain_result("处理接口返回信息时出错")
|
||||||
|
|
||||||
async def terminate(self):
|
|
||||||
"""可选择实现异步的插件销毁方法,当插件被卸载/停用时会调用。"""
|
|
||||||
|
|
||||||
|
|
||||||
@filter.command("剑三技改")
|
@filter.command("剑三技改")
|
||||||
async def jx3_jigai(self, event: AstrMessageEvent):
|
async def jx3_jigai(self, event: AstrMessageEvent):
|
||||||
"""查询技能的历史修改记录,包括资料片更新、技能调整等信息"""
|
"""剑三技改"""
|
||||||
# 接口URL
|
# 接口URL
|
||||||
custom_url = "https://www.jx3api.com/data/skills/records"
|
custom_url = "https://www.jx3api.com/data/skills/records"
|
||||||
# 接口参数
|
# 接口参数
|
||||||
@@ -153,13 +145,10 @@ class Jx3ApiPlugin(Star):
|
|||||||
logger.error(f"处理数据时出错: {e}")
|
logger.error(f"处理数据时出错: {e}")
|
||||||
yield event.plain_result("处理接口返回信息时出错")
|
yield event.plain_result("处理接口返回信息时出错")
|
||||||
|
|
||||||
async def terminate(self):
|
|
||||||
"""可选择实现异步的插件销毁方法,当插件被卸载/停用时会调用。"""
|
|
||||||
|
|
||||||
|
|
||||||
@filter.command("剑三交易行")
|
@filter.command("剑三交易行")
|
||||||
async def jx3_jiaoyihang(self, event: AstrMessageEvent):
|
async def jx3_jiaoyihang(self, event: AstrMessageEvent):
|
||||||
"""获取剑网3交易行信息 区服+物品名称"""
|
"""剑三交易行 服务器 物品名称"""
|
||||||
|
|
||||||
# 接口参数
|
# 接口参数
|
||||||
params = {
|
params = {
|
||||||
@@ -207,21 +196,6 @@ class Jx3ApiPlugin(Star):
|
|||||||
|
|
||||||
# 调整渲染图片的尺寸
|
# 调整渲染图片的尺寸
|
||||||
options = {
|
options = {
|
||||||
"viewport": {
|
|
||||||
"width": 800,
|
|
||||||
"height": 600,
|
|
||||||
"device_scale_factor": 1 # 明确设置设备缩放因子
|
|
||||||
},
|
|
||||||
"clip": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"width": 800,
|
|
||||||
"height": 600
|
|
||||||
},
|
|
||||||
"full_page": False,
|
|
||||||
"type": "jpeg",
|
|
||||||
"quality": 85,
|
|
||||||
"scale": "device" # 尝试使用设备缩放
|
|
||||||
}
|
}
|
||||||
|
|
||||||
url = await self.html_render(template_content, render_data, options)
|
url = await self.html_render(template_content, render_data, options)
|
||||||
@@ -231,7 +205,86 @@ class Jx3ApiPlugin(Star):
|
|||||||
logger.error(f"交易行查询出错: {e}")
|
logger.error(f"交易行查询出错: {e}")
|
||||||
yield event.plain_result("查询交易行数据时出错,请稍后再试")
|
yield event.plain_result("查询交易行数据时出错,请稍后再试")
|
||||||
|
|
||||||
async def terminate(self):
|
|
||||||
"""可选择实现异步的插件销毁方法,当插件被卸载/停用时会调用。"""
|
|
||||||
|
|
||||||
|
@filter.command("剑三沙盘")
|
||||||
|
async def jx3_shapan(self, event: AstrMessageEvent):
|
||||||
|
"""剑三沙盘 服务器"""
|
||||||
|
# 接口URL
|
||||||
|
custom_url = "https://www.jianxiachaguan.cn/api2/aijx3-jxcg/game/get-sand-table-img"
|
||||||
|
# 接口参数
|
||||||
|
params = {
|
||||||
|
"serverName": "眉间雪" # 默认服务器
|
||||||
|
}
|
||||||
|
# 获取消息内容
|
||||||
|
message_str = event.message_str.strip()
|
||||||
|
parts = message_str.split()
|
||||||
|
# 解析消息内容
|
||||||
|
if len(parts) > 1:
|
||||||
|
params["serverName"] = parts[1] # 第二个参数为服务器
|
||||||
|
# 获取数据
|
||||||
|
data = api_data(custom_url,params)
|
||||||
|
|
||||||
|
if not data:
|
||||||
|
yield event.plain_result("获取获取接口信息失败,请稍后再试")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 格式化返回消息
|
||||||
|
try:
|
||||||
|
# 构建回复消息
|
||||||
|
yield event.image_result(data.get("picUrl"))
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"处理数据时出错: {e}")
|
||||||
|
yield event.plain_result("处理接口返回信息时出错")
|
||||||
|
|
||||||
|
@filter.command("剑三金价")
|
||||||
|
async def jx3_jinjia(self, event: AstrMessageEvent):
|
||||||
|
"""剑三金价 服务器"""
|
||||||
|
# 接口URL
|
||||||
|
custom_url = "https://www.jianxiachaguan.cn/api2/aijx3-jxcg/game/get-gold"
|
||||||
|
# 接口参数
|
||||||
|
params = {
|
||||||
|
"serverName": "眉间雪" # 默认服务器
|
||||||
|
}
|
||||||
|
# 获取消息内容
|
||||||
|
message_str = event.message_str.strip()
|
||||||
|
parts = message_str.split()
|
||||||
|
# 解析消息内容
|
||||||
|
if len(parts) > 1:
|
||||||
|
params["serverName"] = parts[1] # 第二个参数为服务器
|
||||||
|
# 获取数据
|
||||||
|
data = api_data(custom_url,params)
|
||||||
|
|
||||||
|
if not data:
|
||||||
|
yield event.plain_result("获取获取接口信息失败,请稍后再试")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 格式化返回消息
|
||||||
|
try:
|
||||||
|
# 加载模板
|
||||||
|
try:
|
||||||
|
template_content = load_template("jinjia.html")
|
||||||
|
except FileNotFoundError as e:
|
||||||
|
logger.error(f"加载模板失败: {e}")
|
||||||
|
yield event.plain_result("系统错误:模板文件不存在")
|
||||||
|
return
|
||||||
|
# 准备模板渲染数据
|
||||||
|
render_data = {
|
||||||
|
"items": data,
|
||||||
|
"server": params["serverName"],
|
||||||
|
"update_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
}
|
||||||
|
# 调整渲染图片的尺寸
|
||||||
|
options = {
|
||||||
|
}
|
||||||
|
|
||||||
|
url = await self.html_render(template_content, render_data, options)
|
||||||
|
yield event.image_result(url)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"处理数据时出错: {e}")
|
||||||
|
yield event.plain_result("处理接口返回信息时出错")
|
||||||
|
|
||||||
|
|
||||||
|
async def terminate(self):
|
||||||
|
"""可选择实现异步的插件销毁方法,当插件被卸载/停用时会调用。"""
|
||||||
@@ -0,0 +1,186 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>剑网3各平台金价查询</title>
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
font-family: 'Microsoft YaHei', sans-serif;
|
||||||
|
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
|
||||||
|
padding: 20px;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
width: 1280px;
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
background: linear-gradient(135deg, #4a90e2 0%, #2a5298 100%);
|
||||||
|
color: white;
|
||||||
|
padding: 25px 30px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.header h1 {
|
||||||
|
font-size: 32px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
.server-info {
|
||||||
|
font-size: 18px;
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
.summary {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
padding: 15px 30px;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #495057;
|
||||||
|
border-bottom: 1px solid #e9ecef;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.items-count {
|
||||||
|
font-weight: 600;
|
||||||
|
color: #4a90e2;
|
||||||
|
}
|
||||||
|
.update-time {
|
||||||
|
color: #6c757d;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.table-container {
|
||||||
|
padding: 0 30px 30px 30px;
|
||||||
|
overflow-x: auto;
|
||||||
|
text-align: center
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin-top: 20px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
th {
|
||||||
|
background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
|
||||||
|
color: white;
|
||||||
|
padding: 16px 20px;
|
||||||
|
text-align: left;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 16px;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
th:first-child {
|
||||||
|
border-top-left-radius: 8px;
|
||||||
|
}
|
||||||
|
th:last-child {
|
||||||
|
border-top-right-radius: 8px;
|
||||||
|
}
|
||||||
|
td {
|
||||||
|
padding: 14px 20px;
|
||||||
|
border-bottom: 1px solid #e9ecef;
|
||||||
|
font-size: 15px;
|
||||||
|
color: #495057;
|
||||||
|
}
|
||||||
|
tr:nth-child(even) {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
}
|
||||||
|
tr:hover {
|
||||||
|
background-color: #e9f7fe;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
.item-name {
|
||||||
|
font-weight: 500;
|
||||||
|
color: #2c3e50;
|
||||||
|
max-width: 500px;
|
||||||
|
}
|
||||||
|
.price {
|
||||||
|
text-align: right;
|
||||||
|
color: #e74c3c;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
.sample {
|
||||||
|
text-align: center;
|
||||||
|
color: #6c757d;
|
||||||
|
}
|
||||||
|
.footer {
|
||||||
|
background-color: #343a40;
|
||||||
|
color: #f8f9fa;
|
||||||
|
padding: 15px 30px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.highlight {
|
||||||
|
background-color: #fff3cd;
|
||||||
|
}
|
||||||
|
@media (max-width: 1320px) {
|
||||||
|
body {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 1280px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="header">
|
||||||
|
<h1>剑网3各平台金价查询</h1>
|
||||||
|
<div class="server-info">服务器: {{ server }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="summary">
|
||||||
|
<div class="items-count">共找到 <strong>{{ items|length }}</strong> 条数据</div>
|
||||||
|
<div class="update-time">数据更新时间: {{ update_time }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="table-container">
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="width: 28%; text-align: center;">时间</th>
|
||||||
|
<th style="width: 12%; text-align: center;">贴吧</th>
|
||||||
|
<th style="width: 12%; text-align: center;">万宝楼</th>
|
||||||
|
<th style="width: 12%; text-align: center;">DD373</th>
|
||||||
|
<th style="width: 12%; text-align: center;">UU898</th>
|
||||||
|
<th style="width: 12%; text-align: center;">5173</th>
|
||||||
|
<th style="width: 12%; text-align: center;">7881</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for item in items %}
|
||||||
|
<tr {% if loop.index <= 3 %}class="highlight"{% endif %}>
|
||||||
|
<td class="date">{{ item.date }}</td>
|
||||||
|
<td class="priceTieba">{{ item.priceTieba }}</td>
|
||||||
|
<td class="priceWanbaolou">{{ item.priceWanbaolou }}</td>
|
||||||
|
<td class="priceDd373">{{ item.priceDd373 }}</td>
|
||||||
|
<td class="priceUu898">{{ item.priceUu898 }}</td>
|
||||||
|
<td class="price5173">{{ item.price5173 }}</td>
|
||||||
|
<td class="priceDd373">{{ item.price7881 }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer">
|
||||||
|
© 2025 剑网3金价查询系统 | 数据仅供参考,以游戏内实际价格为准
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user