11
This commit is contained in:
@@ -86,5 +86,24 @@
|
||||
"size": 10,
|
||||
"tradeStatus": ""
|
||||
}
|
||||
},
|
||||
"jx3box_item":{
|
||||
"url":"https://node.jx3box.com/api/node/item/search",
|
||||
"method":"GET",
|
||||
"description":"魔盒中模糊查找剑网三的物品数据",
|
||||
"params":{
|
||||
"keyword": "守缺式",
|
||||
"page": "1",
|
||||
"per": "50"
|
||||
}
|
||||
},
|
||||
"jx3box_itemprice":{
|
||||
"url":"https://next2.jx3box.com/api/item-price/list",
|
||||
"method":"GET",
|
||||
"description":"交易行中在售物品数据",
|
||||
"params":{
|
||||
"server": "眉间雪",
|
||||
"itemIds": ["5_76650"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -181,6 +181,49 @@ class APIClient:
|
||||
return data.get(outdata, {})
|
||||
|
||||
|
||||
async def all_pages(self,http, api_url, params_data = None, outdata: str = "",listdata: str = "list", max_pages: int = 10):
|
||||
"""
|
||||
分页获取所有数据
|
||||
|
||||
Args:
|
||||
http: 请求方法 ('GET' 或 'POST')
|
||||
api_url: API地址
|
||||
params_data: 参数字典,如 {"name": "万花"}
|
||||
outdata: 返回数据中要提取的字段
|
||||
max_pages: 最大页数限制,0表示不限制
|
||||
listdata: 返回数据中包含列表数据的字段名,默认为"list"
|
||||
Returns:
|
||||
成功时返回所有页数据的列表,失败返回None
|
||||
"""
|
||||
all_data = []
|
||||
current_page = 1
|
||||
|
||||
while True:
|
||||
# 设置当前页码
|
||||
params = params_data.copy() if params_data else {}
|
||||
params["page"] = str(current_page)
|
||||
|
||||
# 请求数据
|
||||
if http.upper() == "POST":
|
||||
data = await self.post(api_url, params, outdata)
|
||||
else:
|
||||
data = await self.get(api_url, params, outdata)
|
||||
|
||||
if not data[listdata]:
|
||||
break
|
||||
|
||||
# 添加当前页数据到总列表
|
||||
all_data.extend(data[listdata])
|
||||
|
||||
# 检查是否达到最大页数限制
|
||||
if max_pages and current_page >= max_pages:
|
||||
break
|
||||
|
||||
current_page += 1
|
||||
logger.info(f"已获取第 {current_page} 页数据")
|
||||
return all_data
|
||||
|
||||
|
||||
# 保持原有函数接口的兼容性
|
||||
async def api_data_post(api_url, params_data=None, outdata=None):
|
||||
"""兼容原有函数的POST请求"""
|
||||
|
||||
+44
-3
@@ -4,7 +4,7 @@ from astrbot.api import logger
|
||||
|
||||
from .class_reqsest import APIClient
|
||||
from .cless_mysql import AsyncMySQL
|
||||
from .function_basic import load_template, extract_field
|
||||
from .function_basic import load_template, extract_field,flatten_field,extract_fields
|
||||
|
||||
class JX3Function:
|
||||
def __init__(self, api_config,db: AsyncMySQL ):
|
||||
@@ -219,7 +219,7 @@ class JX3Function:
|
||||
return return_data
|
||||
# 提取数据
|
||||
try:
|
||||
extracted_data = extract_field(data, "dataModels")
|
||||
extracted_data = flatten_field(data, "dataModels")
|
||||
except FileNotFoundError as e:
|
||||
logger.error(f"提取数据失败: {e}")
|
||||
return_data["msg"] = "提取指定数据字段失败"
|
||||
@@ -381,4 +381,45 @@ class JX3Function:
|
||||
logger.error(f"处理万宝楼记录出错: {e}")
|
||||
continue
|
||||
|
||||
return processed
|
||||
return processed
|
||||
|
||||
async def jiaoyihang(self,Name: str = "守缺式",server: str = "眉间雪"):
|
||||
return_data = {
|
||||
"code": 0,
|
||||
"msg": "功能函数未执行",
|
||||
"data": {}
|
||||
}
|
||||
#在配置文件中获取接口配置
|
||||
api_config = self.__api_config["jx3box_item"]
|
||||
#更新参数
|
||||
api_config["params"]["keyword"] = Name
|
||||
# 获取多页查找信息
|
||||
data = await self.__api.all_pages("GET",api_config["url"],api_config["params"],"data","data")
|
||||
if not data:
|
||||
logger.error(f"获取多页数据失败")
|
||||
return_data["msg"] = "未找到该物品"
|
||||
return return_data
|
||||
# 提取指定字段
|
||||
fields = ["IconID", "Name","id"]
|
||||
result = extract_fields(data, fields)
|
||||
if not data:
|
||||
logger.error(f"提取字段失败")
|
||||
return_data["msg"] = "未找到该物品"
|
||||
return return_data
|
||||
# 提取id列表
|
||||
lists_id = extract_field(result, "id")
|
||||
strlists_id = ",".join(str(x) for x in lists_id)
|
||||
logger.info(f"{strlists_id}")
|
||||
#在配置文件中获取接口配置
|
||||
api_config = self.__api_config["jx3box_itemprice"]
|
||||
#更新参数
|
||||
api_config["params"]["itemIds"] = strlists_id
|
||||
api_config["params"]["server"] = server
|
||||
# 获取数据
|
||||
data = await self.__api.get(api_config["url"],api_config["params"],"data")
|
||||
if not data:
|
||||
return_data["msg"] = "未找到在售物品"
|
||||
return return_data
|
||||
return_data["data"]=data
|
||||
return_data["code"] = 200
|
||||
return return_data
|
||||
|
||||
+49
-9
@@ -24,6 +24,54 @@ def load_template(template_name):
|
||||
return f.read()
|
||||
|
||||
|
||||
def flatten_field(data_list, field_name):
|
||||
"""
|
||||
提取并扁平化指定字段的值
|
||||
|
||||
从一个字典列表中,收集指定字段的所有值。
|
||||
如果字段的值是列表,则会被展开(扁平化)加入结果;
|
||||
如果字段的值是单个元素,则直接加入结果。
|
||||
|
||||
Args:
|
||||
data_list (list[dict]): 数据列表,每个元素是字典
|
||||
field_name (str): 要提取的字段名
|
||||
|
||||
Returns:
|
||||
list: 扁平化后的字段值列表
|
||||
"""
|
||||
extracted_data = []
|
||||
for item in data_list:
|
||||
if field_name in item and item[field_name]:
|
||||
# 如果是 list,展开
|
||||
if isinstance(item[field_name], list):
|
||||
extracted_data.extend(item[field_name])
|
||||
else:
|
||||
extracted_data.append(item[field_name])
|
||||
return extracted_data
|
||||
|
||||
|
||||
def extract_fields(data_list, fields):
|
||||
"""
|
||||
从字典列表中提取多个字段
|
||||
|
||||
Args:
|
||||
data_list (list[dict]): 包含字典的列表
|
||||
fields (list[str]): 要提取的字段名列表
|
||||
|
||||
Returns:
|
||||
list[dict]: 只包含指定字段的新字典列表
|
||||
"""
|
||||
result = []
|
||||
try:
|
||||
for item in data_list:
|
||||
extracted = {field: item.get(field) for field in fields}
|
||||
result.append(extracted)
|
||||
except Exception as e:
|
||||
print(f"提取字段时出错: {e}")
|
||||
return []
|
||||
return result
|
||||
|
||||
|
||||
def extract_field(data_list, field_name):
|
||||
"""
|
||||
从列表中的字典提取指定字段的所有值
|
||||
@@ -35,12 +83,4 @@ def extract_field(data_list, field_name):
|
||||
Returns:
|
||||
list: 提取出来的字段值列表
|
||||
"""
|
||||
extracted_data = []
|
||||
for item in data_list:
|
||||
if field_name in item and item[field_name]:
|
||||
# 如果是 list,展开
|
||||
if isinstance(item[field_name], list):
|
||||
extracted_data.extend(item[field_name])
|
||||
else:
|
||||
extracted_data.append(item[field_name])
|
||||
return extracted_data
|
||||
return [item[field_name] for item in data_list if field_name in item]
|
||||
+1
-131
@@ -182,134 +182,4 @@ def jx3_data_jiaoyihang(inserver="眉间雪", inname="武技殊影图"):
|
||||
result_items.sort(key=lambda x: x["avg_price"])
|
||||
|
||||
return result_items
|
||||
|
||||
|
||||
def jx3_data_wujia(inname="秃盒"):
|
||||
"""
|
||||
获取剑三外观物品价格数据
|
||||
|
||||
Args:
|
||||
inname: 物品名称
|
||||
|
||||
Returns:
|
||||
dict: 包含价格和名称信息的字典
|
||||
"""
|
||||
# 初始化返回数据结构
|
||||
datas = {
|
||||
"code": 0,
|
||||
"msg": "未获取数据",
|
||||
"data": {}
|
||||
}
|
||||
|
||||
try:
|
||||
# 1. 获取物品ID和名称
|
||||
idname = api_data_get(inname)
|
||||
if not idname:
|
||||
datas.update({"code": 201, "msg": "未找到该外观信息"})
|
||||
return datas
|
||||
|
||||
# 更新基础信息
|
||||
datas.update({
|
||||
"code": 1,
|
||||
"msg": "获取外观名称ID完成",
|
||||
"data": {
|
||||
"showName": idname.get("showName", "未知物品"),
|
||||
"searchId": idname.get("searchId", "未知ID"),
|
||||
"Name": inname
|
||||
}
|
||||
})
|
||||
|
||||
# 2. 查询爱剑三获取外观数据
|
||||
aj3_data = get_aj3_goods_data(datas["data"]["showName"])
|
||||
if aj3_data:
|
||||
datas["data"].update(aj3_data)
|
||||
datas.update({"code": 2, "msg": "获取外观数据完成"})
|
||||
|
||||
# 3. 查询万宝楼数据(公示和在售)
|
||||
wbl_data = get_wbl_data(idname['searchId'])
|
||||
if wbl_data:
|
||||
datas["data"].update(wbl_data)
|
||||
datas.update({"code": 200, "msg": "获取万宝楼数据完成"})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"物价查询出错: {e}")
|
||||
datas.update({"code": 500, "msg": f"查询过程中出错: {e}"})
|
||||
|
||||
return datas
|
||||
|
||||
|
||||
def get_aj3_goods_data(goods_name):
|
||||
"""获取爱剑三商品数据"""
|
||||
try:
|
||||
aj3_url = "https://www.aijx3.cn/api2/aijx3-wj/goods/getGoodsDetail"
|
||||
aj3_params = {"goodsName": goods_name}
|
||||
|
||||
dataaj3 = api_data_post(aj3_url, aj3_params, "data")
|
||||
if not dataaj3:
|
||||
return None
|
||||
|
||||
imgs = dataaj3.get("imgs", [])
|
||||
return {
|
||||
"goodsDesc": dataaj3.get("goodsDesc", "无描述"),
|
||||
"publishTime": dataaj3.get("publishTime", "无数据"),
|
||||
"priceNum": dataaj3.get("priceNum", 0),
|
||||
"imgs": imgs[0] if imgs else "",
|
||||
"goodsId": dataaj3.get("goodsId", "无数据")
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"获取爱剑三数据出错: {e}")
|
||||
return None
|
||||
|
||||
|
||||
def get_wbl_data(search_id):
|
||||
"""获取万宝楼数据(公示和在售)"""
|
||||
try:
|
||||
wbl_url = "https://www.aijx3.cn/api2/aijx3-wblwg/record/queryByCondition"
|
||||
base_params = {
|
||||
"accoSeq": "",
|
||||
"orderMode": 1,
|
||||
"orderBy": "price_num",
|
||||
"searchId": [search_id],
|
||||
"current": 1,
|
||||
"size": 10
|
||||
}
|
||||
|
||||
# 获取公示数据
|
||||
gs_params = base_params.copy()
|
||||
gs_params["tradeStatus"] = "3"
|
||||
datawblgs = api_data_post(wbl_url, gs_params, "data")
|
||||
|
||||
# 获取在售数据
|
||||
zs_params = base_params.copy()
|
||||
zs_params["tradeStatus"] = "5"
|
||||
datawblzs = api_data_post(wbl_url, zs_params, "data")
|
||||
|
||||
return {
|
||||
"wblgs": process_wbl_records(datawblgs.get("records", [])),
|
||||
"wblzs": process_wbl_records(datawblzs.get("records", []))
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"获取万宝楼数据出错: {e}")
|
||||
return None
|
||||
|
||||
|
||||
def process_wbl_records(records):
|
||||
"""处理万宝楼记录数据"""
|
||||
processed = []
|
||||
for record in records:
|
||||
try:
|
||||
# 转换时间戳为可读格式
|
||||
timestamp = record.get("replyTime", 0)
|
||||
dt = datetime.fromtimestamp(timestamp / 1000) if timestamp else datetime.now()
|
||||
|
||||
processed.append({
|
||||
"priceNum": record.get("priceNum", 0),
|
||||
"belongQf2": record.get("belongQf2", "无数据"),
|
||||
"replyTime": dt.strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"discountRate": record.get("discountRate", 0.0),
|
||||
})
|
||||
except Exception as e:
|
||||
logger.error(f"处理万宝楼记录出错: {e}")
|
||||
continue
|
||||
|
||||
return processed
|
||||
|
||||
@@ -8,7 +8,7 @@ from astrbot.api import logger
|
||||
from astrbot.api import AstrBotConfig
|
||||
|
||||
from .core.function_basic import load_template
|
||||
from .core.jx3_data import jx3_data_jiaoyihang,jx3_data_wujia
|
||||
from .core.jx3_data import jx3_data_jiaoyihang
|
||||
from .core.cless_mysql import AsyncMySQL
|
||||
from .core.cless_jx3 import JX3Function
|
||||
|
||||
@@ -165,6 +165,23 @@ class Jx3ApiPlugin(Star):
|
||||
yield event.plain_result("猪脑过载,请稍后再试")
|
||||
|
||||
|
||||
@jx3.command("交易行")
|
||||
async def jx3_jiaoyihang(self, event: AstrMessageEvent,Name: str = "守缺式",server: str = "眉间雪"):
|
||||
"""剑三 外观名称"""
|
||||
try:
|
||||
data=await self.jx3fun.jiaoyihang(Name,server)
|
||||
if data["code"] == 200:
|
||||
#url = await self.html_render(data["temp"], data["data"], options={})
|
||||
#yield event.image_result(url)
|
||||
yield event.plain_result(f"{data['data']}")
|
||||
else:
|
||||
yield event.plain_result(data["msg"])
|
||||
return
|
||||
except Exception as e:
|
||||
logger.error(f"功能函数执行错误: {e}")
|
||||
yield event.plain_result("猪脑过载,请稍后再试")
|
||||
|
||||
|
||||
@filter.permission_type(filter.PermissionType.ADMIN)
|
||||
@jx3.command("外观数据同步")
|
||||
async def jx3_SearchData(self, event: AstrMessageEvent):
|
||||
|
||||
Reference in New Issue
Block a user