初步适配Yunzai V3
170
CHANGELOG.md
@ -1,3 +1,7 @@
|
||||
# 1.9.0
|
||||
|
||||
* 初步适配Yunzai V3
|
||||
|
||||
# 1.8.9
|
||||
|
||||
* 增加提纳里、柯莱、多莉的资料及角色图像
|
||||
@ -12,138 +16,138 @@
|
||||
# 1.8.1~1.8.7
|
||||
|
||||
* 新增`#上传深渊数据`命令
|
||||
* 上传自己角色的深渊挑战数据及角色列表,并展示在本期深渊中伤害与承伤排名
|
||||
* 上传数据用于`#角色持有率 #深渊出场率`等统计,可使统计更加及时准确
|
||||
* 数据统计及服务来自SG团队胡桃API
|
||||
* 上传自己角色的深渊挑战数据及角色列表,并展示在本期深渊中伤害与承伤排名
|
||||
* 上传数据用于`#角色持有率 #深渊出场率`等统计,可使统计更加及时准确
|
||||
* 数据统计及服务来自SG团队胡桃API
|
||||
* 增加`#深渊使用率`命令,数据源自SG团队胡桃API
|
||||
* `#刻晴` 角色卡片功能升级
|
||||
* `#老婆设置刻晴,心海`不再检查是否具有角色或展示在米游社展柜
|
||||
* `#刻晴` 角色卡片优先使用面板数据进行展示,无面板数据时使用米游社数据
|
||||
* 在未能获取到角色数据时也会展示角色卡片
|
||||
* `#老婆设置刻晴,心海`不再检查是否具有角色或展示在米游社展柜
|
||||
* `#刻晴` 角色卡片优先使用面板数据进行展示,无面板数据时使用米游社数据
|
||||
* 在未能获取到角色数据时也会展示角色卡片
|
||||
* 支持戳一戳返回喵喵版角色卡片
|
||||
* 需要使用喵喵分支Yunzai以支持此能力,如需切换可在Yunzai根目录输入下方命令后更新重启
|
||||
* `git remote set-url origin https://gitee.com/yoimiya-kokomi/Yunzai-Bot`
|
||||
* 可通过`#喵喵设置` 关闭戳一戳
|
||||
* 需要使用喵喵分支Yunzai以支持此能力,如需切换可在Yunzai根目录输入下方命令后更新重启
|
||||
* `git remote set-url origin https://gitee.com/yoimiya-kokomi/Yunzai-Bot`
|
||||
* 可通过`#喵喵设置` 关闭戳一戳
|
||||
* 支持定义新角色及别名
|
||||
* 新增角色 派蒙、瑶瑶、白术、伐难、应达、散兵、女士、萍儿 的角色配置及图片
|
||||
* 自定义角色可使用`#派蒙` `#派蒙图片`触发图片查看,`#女儿设置派蒙`进行设置。后续会支持更多场景
|
||||
* 如需扩展可在喵喵config/character.js中定义
|
||||
* 新增角色 派蒙、瑶瑶、白术、伐难、应达、散兵、女士、萍儿 的角色配置及图片
|
||||
* 自定义角色可使用`#派蒙` `#派蒙图片`触发图片查看,`#女儿设置派蒙`进行设置。后续会支持更多场景
|
||||
* 如需扩展可在喵喵config/character.js中定义
|
||||
* `#喵喵帮助`增加对自定义配置文件的支持
|
||||
* 已有配置文件可更名为help-cfg.js,防止后续更新冲突,后续会支持更多配置项
|
||||
* 在默认配置中增加部分新的帮助命令
|
||||
* 已有配置文件可更名为help-cfg.js,防止后续更新冲突,后续会支持更多配置项
|
||||
* 在默认配置中增加部分新的帮助命令
|
||||
* 增加`#添加刻晴图像`命令,感谢 **@叶**
|
||||
* 可通过命令上传添加指定角色图片,上传至 **resources/character-img/刻晴/upload**
|
||||
* 请将图像与命令一同发送,后续会支持at图像及命令后发送图像
|
||||
* 可通过命令上传添加指定角色图片,上传至 **resources/character-img/刻晴/upload**
|
||||
* 请将图像与命令一同发送,后续会支持at图像及命令后发送图像
|
||||
* `#喵喵日历`现在可通过`#日历 #日历列表`触发
|
||||
|
||||
# 1.8.0
|
||||
|
||||
* `#角色面板`、`#圣遗物列表` 使用新的圣遗物评分逻辑计算评分
|
||||
* 新的圣遗物评分规针对不同角色进行了细化,对不同角色的评分进行了拉齐
|
||||
* 不同角色基于不同词条权重进行计算。感谢 **@糖炒栗子 @秋声 @49631073**等的权重梳理
|
||||
* 新的圣遗物评分规针对不同角色进行了细化,对不同角色的评分进行了拉齐
|
||||
* 不同角色基于不同词条权重进行计算。感谢 **@糖炒栗子 @秋声 @49631073**等的权重梳理
|
||||
* 增加`#雷神圣遗物`命令
|
||||
* 展示指定角色圣遗物及评分计算详情
|
||||
* 展示新版圣遗物评分逻辑与计算规则
|
||||
* 展示指定角色圣遗物及评分计算详情
|
||||
* 展示新版圣遗物评分逻辑与计算规则
|
||||
* 增加`#原图`命令,可获取喵喵角色卡片原图,感谢 **@牧星长** 提供功能
|
||||
* 对由`#老婆 #刻晴`发出的角色卡片图回复`#原图`可获取对应图像
|
||||
* 对由`#老婆 #刻晴`发出的角色卡片图回复`#原图`可获取对应图像
|
||||
* `#角色面板`现在支持B服角色数据获取
|
||||
* 数据来自喵喵API,目前开放调用无需Token,仅限喵喵插件用户使用
|
||||
* 已知问题:角色天赋的皇冠及命座加成效果显示可能有问题,后期fix
|
||||
* 数据来自喵喵API,目前开放调用无需Token,仅限喵喵插件用户使用
|
||||
* 已知问题:角色天赋的皇冠及命座加成效果显示可能有问题,后期fix
|
||||
* `#录入角色面板` 功能恢复
|
||||
* 可对已有面板数据的角色手工输入更改面板属性,用于伤害测算
|
||||
* 例如`#录入雷神面板 暴击80,暴伤250`
|
||||
* 暂不支持设置武器、圣遗物、命座、天赋。后续会增加支持
|
||||
* 可对已有面板数据的角色手工输入更改面板属性,用于伤害测算
|
||||
* 例如`#录入雷神面板 暴击80,暴伤250`
|
||||
* 暂不支持设置武器、圣遗物、命座、天赋。后续会增加支持
|
||||
* 部分页面样式调整及功能优化
|
||||
* `#角色持有率` 等增加提示说明
|
||||
* `#圣遗物列表` 展示个数提升至28,且根据新版圣遗物评分规则进行词条高亮
|
||||
* `#喵喵更新` 的自动重启功能适配node app方式启动的Yunzai-Bot,感谢 **@SirlyDreamer**
|
||||
* `#角色持有率` 等增加提示说明
|
||||
* `#圣遗物列表` 展示个数提升至28,且根据新版圣遗物评分规则进行词条高亮
|
||||
* `#喵喵更新` 的自动重启功能适配node app方式启动的Yunzai-Bot,感谢 **@SirlyDreamer**
|
||||
* 角色图像增加小清新开关,默认关闭
|
||||
* 对增量包内的角色图像进行分级,较为清凉的图像独立管理
|
||||
* 勇士们可使用 `#喵喵设置小清新开启` 启用
|
||||
* 对增量包内的角色图像进行分级,较为清凉的图像独立管理
|
||||
* 勇士们可使用 `#喵喵设置小清新开启` 启用
|
||||
* 伤害计算增加扩散、感电的计算逻辑,感谢 **@49631073**的逻辑梳理
|
||||
* `#角色面板` 伤害计算增加部分角色,目前支持
|
||||
* 长柄武器:雷神、胡桃、魈、钟离、香菱
|
||||
* 法器:神子、心海、可莉、凝光、芭芭拉、莫娜
|
||||
* 弓:甘雨、宵宫、公子,九条,迪奥娜、安柏、皇女、温迪、夜兰
|
||||
* 单手剑:绫人、绫华、刻晴、阿贝多、行秋、班尼特、七七、凯亚、琴、万叶ⁿᵉʷ、久岐忍ⁿᵉʷ
|
||||
* 双手剑:一斗、优菈、迪卢克、诺艾尔、重云
|
||||
* 长柄武器:雷神、胡桃、魈、钟离、香菱
|
||||
* 法器:神子、心海、可莉、凝光、芭芭拉、莫娜
|
||||
* 弓:甘雨、宵宫、公子,九条,迪奥娜、安柏、皇女、温迪、夜兰
|
||||
* 单手剑:绫人、绫华、刻晴、阿贝多、行秋、班尼特、七七、凯亚、琴、万叶ⁿᵉʷ、久岐忍ⁿᵉʷ
|
||||
* 双手剑:一斗、优菈、迪卢克、诺艾尔、重云
|
||||
|
||||
# 1.7.0
|
||||
|
||||
* `#更新面板` 功能升级
|
||||
* 该功能可直接使用,不再需要token
|
||||
* 在查询新用户时会自动使用,自动使用的CD 12小时
|
||||
* 支持国际服UID,目前暂不支持2及5开头的UID
|
||||
* 服务来自enka api,部分网络可能无法请求,请科学处理,后续会增加转发服务。
|
||||
* 由于服务逻辑与之前数据不一致,部分角色的属性及伤害计算可能会不准确,如有发现请反馈给喵喵
|
||||
* 该功能可直接使用,不再需要token
|
||||
* 在查询新用户时会自动使用,自动使用的CD 12小时
|
||||
* 支持国际服UID,目前暂不支持2及5开头的UID
|
||||
* 服务来自enka api,部分网络可能无法请求,请科学处理,后续会增加转发服务。
|
||||
* 由于服务逻辑与之前数据不一致,部分角色的属性及伤害计算可能会不准确,如有发现请反馈给喵喵
|
||||
* `#面板`、`#更新面板`、`#角色面板`、`#角色伤害`、`#圣遗物列表`不再需要绑定cookie,支持查他人
|
||||
* 使用`#面板`命令可查看已获取面板数据的角色列表
|
||||
* 默认查询自己UID,同时也可通过命令+uid方式指定查询对象
|
||||
* 由于整体逻辑变化,喵喵1.6.0之前更新的面板数据无法查看,需要重新更新数据
|
||||
* 使用`#面板`命令可查看已获取面板数据的角色列表
|
||||
* 默认查询自己UID,同时也可通过命令+uid方式指定查询对象
|
||||
* 由于整体逻辑变化,喵喵1.6.0之前更新的面板数据无法查看,需要重新更新数据
|
||||
* 增加`#喵喵面板设置`命令,可更精细的设置是否允许好友/临时对话/群使用面板功能
|
||||
* 由`#录入xx面板` 录入的数据暂时屏蔽
|
||||
* `#角色面板`、`#喵喵日历` 部分细节样式调整
|
||||
* `#角色面板` 伤害计算增加部分角色,目前支持
|
||||
* 长柄武器:雷神、胡桃、魈、钟离、香菱
|
||||
* 法器:神子、心海、可莉、凝光、芭芭拉、莫娜ⁿᵉʷ
|
||||
* 弓:甘雨、宵宫、公子,九条,迪奥娜、安柏、皇女ⁿᵉʷ、温迪ⁿᵉʷ、夜兰ⁿᵉʷ
|
||||
* 单手剑:绫人、绫华、刻晴、阿贝多、行秋、班尼特、七七、凯亚、琴ⁿᵉʷ
|
||||
* 双手剑:一斗、优菈、迪卢克、诺艾尔、重云
|
||||
* 长柄武器:雷神、胡桃、魈、钟离、香菱
|
||||
* 法器:神子、心海、可莉、凝光、芭芭拉、莫娜ⁿᵉʷ
|
||||
* 弓:甘雨、宵宫、公子,九条,迪奥娜、安柏、皇女ⁿᵉʷ、温迪ⁿᵉʷ、夜兰ⁿᵉʷ
|
||||
* 单手剑:绫人、绫华、刻晴、阿贝多、行秋、班尼特、七七、凯亚、琴ⁿᵉʷ
|
||||
* 双手剑:一斗、优菈、迪卢克、诺艾尔、重云
|
||||
|
||||
# 1.6.0
|
||||
|
||||
* `#喵喵设置` 支持设置 面板查询 的功能开关
|
||||
* `#喵喵版本` 使用图片展示更新信息
|
||||
* `#喵喵日历` 升级
|
||||
* 增加 `#喵喵日历列表`命令,以列表形式展示活动信息
|
||||
* 增加从活动详情信息中解析活动日期的逻辑,使一些活动日期更加准确
|
||||
* 增加 `#喵喵日历列表`命令,以列表形式展示活动信息
|
||||
* 增加从活动详情信息中解析活动日期的逻辑,使一些活动日期更加准确
|
||||
* 增加鹿野院平藏的角色信息,可通过`#平藏天赋`、`#平藏命座`查看信息
|
||||
* 其他升级调整
|
||||
* `#深渊出场率`、`#角色持有率` 等页面功能及样式微调
|
||||
* `#角色面板` 伤害计算增加双手剑计算逻辑,增加物伤计算逻辑
|
||||
* 页面版权信息展示Yunzai及喵喵版本号
|
||||
* `#深渊出场率`、`#角色持有率` 等页面功能及样式微调
|
||||
* `#角色面板` 伤害计算增加双手剑计算逻辑,增加物伤计算逻辑
|
||||
* 页面版权信息展示Yunzai及喵喵版本号
|
||||
* `#角色面板` 伤害计算增加部分角色,目前支持
|
||||
* 长柄武器:雷神、胡桃、魈、钟离、香菱
|
||||
* 法器:神子、心海、可莉ⁿᵉʷ、凝光ⁿᵉʷ、芭芭拉ⁿᵉʷ
|
||||
* 弓:甘雨、宵宫、公子,九条ⁿᵉʷ,迪奥娜ⁿᵉʷ、安柏ⁿᵉʷ
|
||||
* 单手剑:绫人、绫华、刻晴、阿贝多、行秋、班尼特、七七ⁿᵉʷ、凯亚ⁿᵉʷ
|
||||
* 双手剑:一斗ⁿᵉʷ、优菈ⁿᵉʷ、迪卢克ⁿᵉʷ、诺艾尔ⁿᵉʷ、重云ⁿᵉʷ
|
||||
* 长柄武器:雷神、胡桃、魈、钟离、香菱
|
||||
* 法器:神子、心海、可莉ⁿᵉʷ、凝光ⁿᵉʷ、芭芭拉ⁿᵉʷ
|
||||
* 弓:甘雨、宵宫、公子,九条ⁿᵉʷ,迪奥娜ⁿᵉʷ、安柏ⁿᵉʷ
|
||||
* 单手剑:绫人、绫华、刻晴、阿贝多、行秋、班尼特、七七ⁿᵉʷ、凯亚ⁿᵉʷ
|
||||
* 双手剑:一斗ⁿᵉʷ、优菈ⁿᵉʷ、迪卢克ⁿᵉʷ、诺艾尔ⁿᵉʷ、重云ⁿᵉʷ
|
||||
|
||||
# 1.5.0
|
||||
|
||||
* 增加`#喵喵日历` 功能
|
||||
* 【!请注意!】此功能需要安装moment库,请在Yunzai安装目录下运行`npm install moment`后再进行升级
|
||||
* 展示当前进行中及即将开始的活动,包括深境螺旋
|
||||
* 【!请注意!】此功能需要安装moment库,请在Yunzai安装目录下运行`npm install moment`后再进行升级
|
||||
* 展示当前进行中及即将开始的活动,包括深境螺旋
|
||||
* `#角色面板` 伤害计算目前支持
|
||||
* 长柄武器:雷神、胡桃、魈、钟离、香菱ⁿᵉʷ
|
||||
* 法器:神子、心海
|
||||
* 弓:甘雨、宵宫、公子
|
||||
* 单手剑:绫人、绫华、刻晴、阿贝多ⁿᵉʷ、行秋ⁿᵉʷ、班尼特ⁿᵉʷ
|
||||
* 长柄武器:雷神、胡桃、魈、钟离、香菱ⁿᵉʷ
|
||||
* 法器:神子、心海
|
||||
* 弓:甘雨、宵宫、公子
|
||||
* 单手剑:绫人、绫华、刻晴、阿贝多ⁿᵉʷ、行秋ⁿᵉʷ、班尼特ⁿᵉʷ
|
||||
* 底层升级:抽象了部分公共组件为tpl模板以提高复用度,css改为less处理
|
||||
|
||||
# 1.4.0
|
||||
|
||||
* 增加 `#深渊配队` 功能
|
||||
* 根据当前账号的角色练度及本期深渊出场数据,推荐较匹配的配队方案
|
||||
* 深渊出场数据来自胡桃API,为Snap Genshin用户自主上传的深渊挑战记录,感谢SG团队
|
||||
* 配队方案仅供参考
|
||||
* 根据当前账号的角色练度及本期深渊出场数据,推荐较匹配的配队方案
|
||||
* 深渊出场数据来自胡桃API,为Snap Genshin用户自主上传的深渊挑战记录,感谢SG团队
|
||||
* 配队方案仅供参考
|
||||
* `#角色面板` 伤害计算新增部分角色
|
||||
* 目前支持:雷神、胡桃、魈、神子、甘雨、宵宫、公子、绫人、绫华、心海、钟离
|
||||
* 目前支持:雷神、胡桃、魈、神子、甘雨、宵宫、公子、绫人、绫华、心海、钟离
|
||||
* `#角色面板` 一些功能升级与调整
|
||||
* 支持对治疗量、护盾量的计算与展示
|
||||
* 修复冰融化、少女4等buff等buff遗漏或错误导致的伤害计算偏差
|
||||
* 支持对治疗量、护盾量的计算与展示
|
||||
* 修复冰融化、少女4等buff等buff遗漏或错误导致的伤害计算偏差
|
||||
* `#老婆` 功能支持对jpeg格式的图片格式识别
|
||||
|
||||
# 1.3.0
|
||||
|
||||
* 增加 `#雷神伤害` 功能
|
||||
* 可计算圣遗物副词条置换带来的伤害变化,可用于圣遗物副词条侧重方向的参考
|
||||
* 可以查看指定角色伤害计算的Buff列表
|
||||
* 可计算圣遗物副词条置换带来的伤害变化,可用于圣遗物副词条侧重方向的参考
|
||||
* 可以查看指定角色伤害计算的Buff列表
|
||||
* `#角色面板` 伤害计算新增部分角色
|
||||
* 目前支持:雷神、胡桃、魈、神子、甘雨、宵宫、公子、绫人、绫华
|
||||
* 目前支持:雷神、胡桃、魈、神子、甘雨、宵宫、公子、绫人、绫华
|
||||
* `#角色面板` 功能升级
|
||||
* 优化无角色面板数据时的引导
|
||||
* 优化返回的图像格式及分辨率,平衡响应速度及显示效果
|
||||
* 优化无角色面板数据时的引导
|
||||
* 优化返回的图像格式及分辨率,平衡响应速度及显示效果
|
||||
* 增加 `#圣遗物列表` 功能,对已经获取面板的所有角色圣遗物进行评分,并展示高评分的圣遗物列表
|
||||
* 增加 `#角色面板列表` / `#角色面板帮助` 命令
|
||||
* 增加 `#更新胡桃面板` 命令,获取单个角色面板数据,每天可更新5次
|
||||
@ -152,15 +156,15 @@
|
||||
# 1.2.0
|
||||
|
||||
* `#角色面板` 增加伤害计算功能
|
||||
* 目前支持角色:雷神、胡桃、魈、神子、甘雨
|
||||
* 可通过 `#怪物等级85` 命令设定怪物等级,以获得更准确的计算结果
|
||||
* 计算伤害为满Buff情况,后续会出更详细的Buff及计算展示
|
||||
* 目前支持角色:雷神、胡桃、魈、神子、甘雨
|
||||
* 可通过 `#怪物等级85` 命令设定怪物等级,以获得更准确的计算结果
|
||||
* 计算伤害为满Buff情况,后续会出更详细的Buff及计算展示
|
||||
* `#获取游戏角色详情`命令在服务侧增加基于UID的天频度限制
|
||||
* 增加 `#喵喵更新` 功能
|
||||
* 感谢 @碎月 @清秋 的代码支持
|
||||
* 若更新成功会重启Yunzai,需要Yunzai以 npm run start 模式启动
|
||||
* 尚未经充分测试,请有一定容错能力的勇士尝试
|
||||
* 增加`#喵喵版本`命令查询版本信息
|
||||
* 感谢 @碎月 @清秋 的代码支持
|
||||
* 若更新成功会重启Yunzai,需要Yunzai以 npm run start 模式启动
|
||||
* 尚未经充分测试,请有一定容错能力的勇士尝试
|
||||
* 增加`#喵喵版本`命令查询版本信息
|
||||
|
||||
# 1.1.0
|
||||
|
||||
|
44
adapter/index.js
Normal file
@ -0,0 +1,44 @@
|
||||
import plugin from '../../../lib/plugins/plugin.js'
|
||||
import * as Miao from '../apps/index.js'
|
||||
import { render } from './render.js'
|
||||
import { checkAuth, getMysApi } from './mys.js'
|
||||
|
||||
export class miao extends plugin {
|
||||
constructor () {
|
||||
super({
|
||||
name: 'miao-plugin',
|
||||
desc: '喵喵插件',
|
||||
event: 'message',
|
||||
priority: 50,
|
||||
rule: [{
|
||||
reg: '.+',
|
||||
fnc: 'dispatch'
|
||||
}]
|
||||
})
|
||||
}
|
||||
|
||||
async dispatch (e) {
|
||||
let msg = e.raw_message
|
||||
e.checkAuth = async function (cfg) {
|
||||
return await checkAuth(e, cfg)
|
||||
}
|
||||
e.getMysApi = async function (cfg) {
|
||||
return await getMysApi(e, cfg)
|
||||
}
|
||||
msg = '#' + msg.replace('#', '')
|
||||
for (let fn in Miao.rule) {
|
||||
let cfg = Miao.rule[fn]
|
||||
if (Miao[fn] && new RegExp(cfg.reg).test(msg)) {
|
||||
let ret = await Miao[fn](e, {
|
||||
render
|
||||
})
|
||||
if (ret === true) {
|
||||
console.log('ret true')
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
114
adapter/mys.js
Normal file
@ -0,0 +1,114 @@
|
||||
import MysInfo from '../../genshin/model/mys/mysInfo.js'
|
||||
import lodash from 'lodash'
|
||||
|
||||
class User {
|
||||
constructor (cfg) {
|
||||
this.id = cfg.id
|
||||
this.uid = cfg.uid
|
||||
this.cookie = ''
|
||||
}
|
||||
|
||||
// 保存用户配置
|
||||
async setCfg (path, value) {
|
||||
console.log(this.id)
|
||||
let userCfg = await redis.get(`genshin:user-cfg:${this.id}`)
|
||||
userCfg = userCfg ? JSON.parse(userCfg) : {}
|
||||
lodash.set(userCfg, path, value)
|
||||
await redis.set(`genshin:user-cfg:${this.id}`, JSON.stringify(userCfg))
|
||||
}
|
||||
|
||||
/* 获取用户配置 */
|
||||
async getCfg (path, defaultValue) {
|
||||
let userCfg = await redis.get(`genshin:user-cfg:${this.id}`)
|
||||
userCfg = userCfg ? JSON.parse(userCfg) : {}
|
||||
return lodash.get(userCfg, path, defaultValue)
|
||||
}
|
||||
|
||||
async getMysUser () {
|
||||
return {
|
||||
uid: this.uid
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Mys {
|
||||
constructor (e, uid, MysApi) {
|
||||
this.selfUser = new User({ id: e.user_id, uid })
|
||||
this.targetUser = {
|
||||
uid
|
||||
}
|
||||
this.e = e
|
||||
this.MysApi = MysApi
|
||||
e.targetUser = this.targetUser
|
||||
e.selfUser = this.selfUser
|
||||
}
|
||||
|
||||
async getData (api, data) {
|
||||
if (!this.MysApi) {
|
||||
return false
|
||||
}
|
||||
let ret = await MysInfo.get(this.e, api, data)
|
||||
if (!ret) {
|
||||
return false
|
||||
}
|
||||
return ret.data || ret
|
||||
}
|
||||
|
||||
// 获取角色信息
|
||||
async getCharacter () {
|
||||
return await this.getData('character')
|
||||
}
|
||||
|
||||
// 获取角色详情
|
||||
async getAvatar (id) {
|
||||
return await this.getData('detail', { avatar_id: id })
|
||||
}
|
||||
|
||||
// 首页宝箱信息
|
||||
async getIndex () {
|
||||
return await this.getData('index')
|
||||
}
|
||||
|
||||
// 获取深渊信息
|
||||
async getSpiralAbyss (type = 1) {
|
||||
return await this.getData('spiralAbyss', { schedule_type: type })
|
||||
}
|
||||
|
||||
async getDetail (id) {
|
||||
return await this.getData('detail', { avatar_id: id })
|
||||
}
|
||||
|
||||
async getCompute (data) {
|
||||
return await this.getData('compute', data)
|
||||
}
|
||||
|
||||
async getAvatarSkill (id) {
|
||||
return await this.getData('avatarSkill', { avatar_id: id })
|
||||
}
|
||||
|
||||
get isSelfCookie () {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
export async function getMysApi (e, cfg) {
|
||||
let { auth = 'all' } = cfg
|
||||
let uid = await MysInfo.getUid(e)
|
||||
if (!uid) return false
|
||||
|
||||
/* 检查user ck */
|
||||
let isCookieUser = await MysInfo.checkUidBing(uid)
|
||||
if (auth === 'cookie' && !isCookieUser) {
|
||||
e.reply('尚未绑定Cookie...')
|
||||
return false
|
||||
}
|
||||
let MysApi = await MysInfo.init(e, 'roleIndex')
|
||||
if (!MysApi) {
|
||||
return false
|
||||
}
|
||||
return new Mys(e, uid, MysApi)
|
||||
}
|
||||
|
||||
export async function checkAuth (e, cfg) {
|
||||
return new User({ id: e.user_id })
|
||||
}
|
21
adapter/render.js
Normal file
@ -0,0 +1,21 @@
|
||||
import lodash from 'lodash'
|
||||
import Data from '../components/Data.js'
|
||||
import puppeteer from '../../../lib/puppeteer/puppeteer.js'
|
||||
|
||||
const plugin = 'miao-plugin'
|
||||
|
||||
const _path = process.cwd()
|
||||
|
||||
export async function render (app = '', tpl = '', data = {}, imgType = 'jpeg') {
|
||||
// 在data中保存plugin信息
|
||||
data._plugin = plugin
|
||||
|
||||
if (lodash.isUndefined(data._res_path)) {
|
||||
data._res_path = `../../../../../plugins/${plugin}/resources/`
|
||||
}
|
||||
Data.createDir(_path + '/data/', `html/${plugin}/${app}/${tpl}`)
|
||||
data.saveId = data.saveId || data.save_id || tpl
|
||||
data.tplFile = `./plugins/${plugin}/resources/${app}/${tpl}.html`
|
||||
data.pluResPath = data._res_path
|
||||
return await puppeteer.screenshot(`miao-plugin/${app}/${tpl}`, data)
|
||||
}
|
269
apps/admin.js
@ -1,242 +1,235 @@
|
||||
import { segment } from "oicq";
|
||||
import fs from "fs";
|
||||
import lodash from "lodash";
|
||||
import { createRequire } from "module";
|
||||
import { exec } from "child_process";
|
||||
import { Cfg } from "../components/index.js";
|
||||
import Common from "../components/Common.js";
|
||||
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
import fs from 'fs'
|
||||
import lodash from 'lodash'
|
||||
import { exec } from 'child_process'
|
||||
import { Cfg } from '../components/index.js'
|
||||
import Common from '../components/Common.js'
|
||||
|
||||
let cfgMap = {
|
||||
"角色": "char.char",
|
||||
"面板": "char.profile-data",
|
||||
"老婆": "char.wife",
|
||||
"戳一戳": "char.poke",
|
||||
"小清新": "char.se",
|
||||
"查他人": "char.queryOther",
|
||||
"图鉴": "wiki.wiki",
|
||||
"图片": "wiki.pic",
|
||||
"深渊": "wiki.abyss",
|
||||
"渲染": "sys.scale",
|
||||
"帮助": "sys.help",
|
||||
};
|
||||
let sysCfgReg = `^#喵喵设置\s*(${lodash.keys(cfgMap).join("|")})?\s*(.*)$`;
|
||||
角色: 'char.char',
|
||||
面板: 'char.profile-data',
|
||||
老婆: 'char.wife',
|
||||
戳一戳: 'char.poke',
|
||||
小清新: 'char.se',
|
||||
查他人: 'char.queryOther',
|
||||
图鉴: 'wiki.wiki',
|
||||
图片: 'wiki.pic',
|
||||
深渊: 'wiki.abyss',
|
||||
渲染: 'sys.scale',
|
||||
帮助: 'sys.help'
|
||||
}
|
||||
let sysCfgReg = `^#喵喵设置\\s*(${lodash.keys(cfgMap).join('|')})?\\s*(.*)$`
|
||||
export const rule = {
|
||||
updateRes: {
|
||||
hashMark: true,
|
||||
reg: "^#喵喵(更新图像|图像更新)$",
|
||||
describe: "【#管理】更新素材",
|
||||
reg: '^#喵喵(更新图像|图像更新)$',
|
||||
describe: '【#管理】更新素材'
|
||||
},
|
||||
updateMiaoPlugin: {
|
||||
hashMark: true,
|
||||
reg: "^#喵喵(强制)?更新",
|
||||
describe: "【#管理】喵喵更新",
|
||||
reg: '^#喵喵(强制)?更新',
|
||||
describe: '【#管理】喵喵更新'
|
||||
},
|
||||
sysCfg: {
|
||||
hashMark: true,
|
||||
reg: sysCfgReg,
|
||||
describe: "【#管理】系统设置"
|
||||
describe: '【#管理】系统设置'
|
||||
},
|
||||
profileCfg: {
|
||||
hashMark: true,
|
||||
reg: "^#喵喵面板(?:设置)?.*",
|
||||
describe: "【#管理】面板设置"
|
||||
reg: '^#喵喵面板(?:设置)?.*',
|
||||
describe: '【#管理】面板设置'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
const _path = process.cwd();
|
||||
const resPath = `${_path}/plugins/miao-plugin/resources/`;
|
||||
const plusPath = `${resPath}/miao-res-plus/`;
|
||||
const _path = process.cwd()
|
||||
const resPath = `${_path}/plugins/miao-plugin/resources/`
|
||||
const plusPath = `${resPath}/miao-res-plus/`
|
||||
|
||||
const checkAuth = async function (e) {
|
||||
return await e.checkAuth({
|
||||
auth: "master",
|
||||
auth: 'master',
|
||||
replyMsg: `只有主人才能命令喵喵哦~
|
||||
(*/ω\*)`
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
export async function sysCfg(e, { render }) {
|
||||
export async function sysCfg (e, { render }) {
|
||||
if (!await checkAuth(e)) {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
|
||||
let cfgReg = new RegExp(sysCfgReg);
|
||||
let regRet = cfgReg.exec(e.msg);
|
||||
let cfgReg = new RegExp(sysCfgReg)
|
||||
let regRet = cfgReg.exec(e.msg)
|
||||
|
||||
if (!regRet) {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
|
||||
if (regRet[1]) {
|
||||
// 设置模式
|
||||
let val = regRet[2] || "";
|
||||
let val = regRet[2] || ''
|
||||
|
||||
let cfgKey = cfgMap[regRet[1]];
|
||||
if (cfgKey === "sys.scale") {
|
||||
val = Math.min(200, Math.max(50, val * 1 || 100));
|
||||
let cfgKey = cfgMap[regRet[1]]
|
||||
if (cfgKey === 'sys.scale') {
|
||||
val = Math.min(200, Math.max(50, val * 1 || 100))
|
||||
} else {
|
||||
val = !/关闭/.test(val);
|
||||
val = !/关闭/.test(val)
|
||||
}
|
||||
|
||||
if (cfgKey) {
|
||||
Cfg.set(cfgKey, val);
|
||||
Cfg.set(cfgKey, val)
|
||||
}
|
||||
}
|
||||
|
||||
let cfg = {
|
||||
chars: getStatus("char.char"),
|
||||
profile: getStatus("char.profile-data"),
|
||||
wife: getStatus("char.wife"),
|
||||
poke: getStatus("char.poke"),
|
||||
se: getStatus("char.se", false),
|
||||
other: getStatus("char.queryOther"),
|
||||
wiki: getStatus("wiki.wiki"),
|
||||
pic: getStatus("wiki.pic"),
|
||||
abyss: getStatus("wiki.abyss"),
|
||||
chars: getStatus('char.char'),
|
||||
profile: getStatus('char.profile-data'),
|
||||
wife: getStatus('char.wife'),
|
||||
poke: getStatus('char.poke'),
|
||||
se: getStatus('char.se', false),
|
||||
other: getStatus('char.queryOther'),
|
||||
wiki: getStatus('wiki.wiki'),
|
||||
pic: getStatus('wiki.pic'),
|
||||
abyss: getStatus('wiki.abyss'),
|
||||
imgPlus: fs.existsSync(plusPath),
|
||||
help: getStatus("sys.help", false),
|
||||
scale: Cfg.get("sys.scale", 100)
|
||||
help: getStatus('sys.help', false),
|
||||
scale: Cfg.get('sys.scale', 100)
|
||||
}
|
||||
|
||||
//渲染图像
|
||||
return await Common.render("admin/index", {
|
||||
...cfg,
|
||||
}, { e, render, scale: 1.4 });
|
||||
// 渲染图像
|
||||
return await Common.render('admin/index', {
|
||||
...cfg
|
||||
}, { e, render, scale: 1.4 })
|
||||
}
|
||||
|
||||
const getStatus = function (rote, def = true) {
|
||||
if (Cfg.get(rote, def)) {
|
||||
return `<div class="cfg-status" >已开启</div>`;
|
||||
return '<div class="cfg-status" >已开启</div>'
|
||||
} else {
|
||||
return `<div class="cfg-status status-off">已关闭</div>`;
|
||||
return '<div class="cfg-status status-off">已关闭</div>'
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateRes(e) {
|
||||
export async function updateRes (e) {
|
||||
if (!await checkAuth(e)) {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
let command = "";
|
||||
let command = ''
|
||||
if (fs.existsSync(`${resPath}/miao-res-plus/`)) {
|
||||
e.reply("开始尝试更新,请耐心等待~");
|
||||
command = `git pull`;
|
||||
e.reply('开始尝试更新,请耐心等待~')
|
||||
command = 'git pull'
|
||||
exec(command, { cwd: `${resPath}/miao-res-plus/` }, function (error, stdout, stderr) {
|
||||
console.log(stdout);
|
||||
console.log(stdout)
|
||||
if (/(Already up[ -]to[ -]date|已经是最新的)/.test(stdout)) {
|
||||
e.reply("目前所有图片都已经是最新了~");
|
||||
return true;
|
||||
e.reply('目前所有图片都已经是最新了~')
|
||||
return true
|
||||
}
|
||||
let numRet = /(\d*) files changed,/.exec(stdout);
|
||||
let numRet = /(\d*) files changed,/.exec(stdout)
|
||||
if (numRet && numRet[1]) {
|
||||
e.reply(`报告主人,更新成功,此次更新了${numRet[1]}个图片~`);
|
||||
return true;
|
||||
e.reply(`报告主人,更新成功,此次更新了${numRet[1]}个图片~`)
|
||||
return true
|
||||
}
|
||||
if (error) {
|
||||
e.reply("更新失败!\nError code: " + error.code + "\n" + error.stack + "\n 请稍后重试。");
|
||||
e.reply('更新失败!\nError code: ' + error.code + '\n' + error.stack + '\n 请稍后重试。')
|
||||
} else {
|
||||
e.reply("图片加量包更新成功~");
|
||||
e.reply('图片加量包更新成功~')
|
||||
}
|
||||
});
|
||||
})
|
||||
} else {
|
||||
command = `git clone https://gitee.com/yoimiya-kokomi/miao-res-plus.git "${resPath}/miao-res-plus/"`;
|
||||
e.reply("开始尝试安装图片加量包,可能会需要一段时间,请耐心等待~");
|
||||
command = `git clone https://gitee.com/yoimiya-kokomi/miao-res-plus.git "${resPath}/miao-res-plus/"`
|
||||
e.reply('开始尝试安装图片加量包,可能会需要一段时间,请耐心等待~')
|
||||
exec(command, function (error, stdout, stderr) {
|
||||
if (error) {
|
||||
e.reply("角色图片加量包安装失败!\nError code: " + error.code + "\n" + error.stack + "\n 请稍后重试。");
|
||||
e.reply('角色图片加量包安装失败!\nError code: ' + error.code + '\n' + error.stack + '\n 请稍后重试。')
|
||||
} else {
|
||||
e.reply("角色图片加量包安装成功!您后续也可以通过 #喵喵更新图像 命令来更新图像");
|
||||
e.reply('角色图片加量包安装成功!您后续也可以通过 #喵喵更新图像 命令来更新图像')
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
|
||||
let timer;
|
||||
let timer
|
||||
|
||||
export async function updateMiaoPlugin(e) {
|
||||
export async function updateMiaoPlugin (e) {
|
||||
if (!await checkAuth(e)) {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
let isForce = e.msg.includes("强制");
|
||||
let command = "git pull";
|
||||
let isForce = e.msg.includes('强制')
|
||||
let command = 'git pull'
|
||||
if (isForce) {
|
||||
command = "git checkout . && git pull";
|
||||
e.reply("正在执行强制更新操作,请稍等");
|
||||
command = 'git checkout . && git pull'
|
||||
e.reply('正在执行强制更新操作,请稍等')
|
||||
} else {
|
||||
e.reply("正在执行更新操作,请稍等");
|
||||
e.reply('正在执行更新操作,请稍等')
|
||||
}
|
||||
exec(command, { cwd: `${_path}/plugins/miao-plugin/` }, function (error, stdout, stderr) {
|
||||
if (/(Already up[ -]to[ -]date|已经是最新的)/.test(stdout)) {
|
||||
e.reply("目前已经是最新版喵喵了~");
|
||||
return true;
|
||||
e.reply('目前已经是最新版喵喵了~')
|
||||
return true
|
||||
}
|
||||
if (error) {
|
||||
e.reply("喵喵更新失败!\nError code: " + error.code + "\n" + error.stack + "\n 请稍后重试。");
|
||||
return true;
|
||||
e.reply('喵喵更新失败!\nError code: ' + error.code + '\n' + error.stack + '\n 请稍后重试。')
|
||||
return true
|
||||
}
|
||||
e.reply("喵喵更新成功,正在尝试重新启动Yunzai以应用更新...");
|
||||
timer && clearTimeout(timer);
|
||||
redis.set("miao:restart-msg", JSON.stringify({
|
||||
msg: "重启成功,新版喵喵已经生效",
|
||||
e.reply('喵喵更新成功,正在尝试重新启动Yunzai以应用更新...')
|
||||
timer && clearTimeout(timer)
|
||||
redis.set('miao:restart-msg', JSON.stringify({
|
||||
msg: '重启成功,新版喵喵已经生效',
|
||||
qq: e.user_id
|
||||
}), { EX: 30 });
|
||||
}), { EX: 30 })
|
||||
timer = setTimeout(function () {
|
||||
let command = `npm run start`;
|
||||
if (process.argv[1].includes("pm2")) {
|
||||
command = `npm run restart`;
|
||||
let command = 'npm run start'
|
||||
if (process.argv[1].includes('pm2')) {
|
||||
command = 'npm run restart'
|
||||
}
|
||||
exec(command, function (error, stdout, stderr) {
|
||||
if (error) {
|
||||
e.reply("自动重启失败,请手动重启以应用新版喵喵。\nError code: " + error.code + "\n" + error.stack + "\n");
|
||||
Bot.logger.error('重启失败\n${error.stack}');
|
||||
return true;
|
||||
e.reply('自动重启失败,请手动重启以应用新版喵喵。\nError code: ' + error.code + '\n' + error.stack + '\n')
|
||||
Bot.logger.error(`重启失败\n${error.stack}`)
|
||||
return true
|
||||
} else if (stdout) {
|
||||
Bot.logger.mark("重启成功,运行已转为后台,查看日志请用命令:npm run log");
|
||||
Bot.logger.mark("停止后台运行命令:npm stop");
|
||||
process.exit();
|
||||
Bot.logger.mark('重启成功,运行已转为后台,查看日志请用命令:npm run log')
|
||||
Bot.logger.mark('停止后台运行命令:npm stop')
|
||||
process.exit()
|
||||
}
|
||||
})
|
||||
}, 1000);
|
||||
|
||||
});
|
||||
return true;
|
||||
}, 1000)
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
export async function profileCfg(e, { render }) {
|
||||
export async function profileCfg (e, { render }) {
|
||||
if (!await checkAuth(e)) {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
|
||||
let keyMap = {
|
||||
"好友": "friend",
|
||||
"群": "group",
|
||||
"陌生人": "stranger"
|
||||
好友: 'friend',
|
||||
群: 'group',
|
||||
陌生人: 'stranger'
|
||||
}
|
||||
|
||||
let regRet = /喵喵面板(?:设置)?\s*(好友|群|群聊|陌生人)?\s*(\d*)\s*(开启|关闭|删除)?\s*$/.exec(e.msg);
|
||||
let regRet = /喵喵面板(?:设置)?\s*(好友|群|群聊|陌生人)?\s*(\d*)\s*(开启|关闭|删除)?\s*$/.exec(e.msg)
|
||||
|
||||
if (!regRet) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
let [, target, groupId, actionType] = regRet;
|
||||
if (target === "群聊") {
|
||||
target = "群";
|
||||
let [, target, groupId, actionType] = regRet
|
||||
if (target === '群聊') {
|
||||
target = '群'
|
||||
}
|
||||
|
||||
if (target) {
|
||||
if (groupId && (target === "群" || !target)) {
|
||||
if (actionType === "删除") {
|
||||
Cfg.del(`profile.groups.群${groupId}`);
|
||||
if (groupId && (target === '群' || !target)) {
|
||||
if (actionType === '删除') {
|
||||
Cfg.del(`profile.groups.群${groupId}`)
|
||||
} else {
|
||||
Cfg.set(`profile.groups.群${groupId}.status`, actionType !== "关闭");
|
||||
Cfg.set(`profile.groups.群${groupId}.status`, actionType !== '关闭')
|
||||
}
|
||||
} else {
|
||||
Cfg.set(`profile.${keyMap[target]}.status`, actionType !== "关闭");
|
||||
Cfg.set(`profile.${keyMap[target]}.status`, actionType !== '关闭')
|
||||
}
|
||||
}
|
||||
|
||||
@ -246,13 +239,12 @@ export async function profileCfg(e, { render }) {
|
||||
|
||||
lodash.forEach(['friend', 'group', 'stranger'], (key) => {
|
||||
cfg[key] = getStatus(`profile.${key}.status`, true)
|
||||
});
|
||||
})
|
||||
|
||||
let groups = Cfg.get('profile-data.groups', {});
|
||||
let groups = Cfg.get('profile-data.groups', {})
|
||||
lodash.forEach(lodash.keys(groups), (group, idx) => {
|
||||
|
||||
if (lodash.isUndefined(groups[group])) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
cfg.groups.push({
|
||||
group,
|
||||
@ -261,9 +253,8 @@ export async function profileCfg(e, { render }) {
|
||||
})
|
||||
})
|
||||
|
||||
//渲染图像
|
||||
return await Common.render("admin/profile", {
|
||||
...cfg,
|
||||
}, { e, render, scale: 1.4 });
|
||||
|
||||
// 渲染图像
|
||||
return await Common.render('admin/profile', {
|
||||
...cfg
|
||||
}, { e, render, scale: 1.4 })
|
||||
}
|
||||
|
@ -1,133 +1,119 @@
|
||||
import lodash from "lodash";
|
||||
import { Common, Cfg } from "../components/index.js";
|
||||
import { renderAvatar } from "./character/avatar-card.js";
|
||||
import { getTargetUid, getProfile, profileHelp, getProfileAll } from "./character/profile-common.js";
|
||||
import { Common, Cfg } from '../components/index.js'
|
||||
import { renderAvatar } from './character/avatar-card.js'
|
||||
import { getTargetUid, getProfile, profileHelp, getProfileAll } from './character/profile-common.js'
|
||||
|
||||
import { profileArtis } from "./character/profile-artis.js"
|
||||
import { renderProfile } from "./character/profile-detail.js";
|
||||
import { profileArtis } from './character/profile-artis.js'
|
||||
import { renderProfile } from './character/profile-detail.js'
|
||||
|
||||
export { enemyLv, getOriginalPicture } from "./character/utils.js";
|
||||
import { Character } from '../components/models.js'
|
||||
|
||||
export { enemyLv, getOriginalPicture } from './character/utils.js'
|
||||
|
||||
// 角色图像上传
|
||||
export { uploadCharacterImg } from "./character/character-img-upload.js";
|
||||
export { uploadCharacterImg } from './character/character-img-upload.js'
|
||||
|
||||
//
|
||||
export { getProfileAll, getProfile, profileHelp };
|
||||
export { getProfileAll, getProfile, profileHelp }
|
||||
|
||||
// 圣遗物列表
|
||||
export { profileArtisList } from "./character/profile-artis.js";
|
||||
export { profileArtisList } from './character/profile-artis.js'
|
||||
|
||||
// 老婆
|
||||
export { wife, pokeWife, wifeReg } from "./character/avatar-wife.js";
|
||||
|
||||
import { Character } from "../components/models.js";
|
||||
export { wife, pokeWife, wifeReg } from './character/avatar-wife.js'
|
||||
|
||||
// 查看当前角色
|
||||
export async function character(e, { render, User }) {
|
||||
let msg = e.msg;
|
||||
export async function character (e, { render }) {
|
||||
let msg = e.raw_message || e.msg
|
||||
if (!msg) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
let mode = 'card';
|
||||
let uidRet = /[0-9]{9}/.exec(msg);
|
||||
let mode = 'card'
|
||||
let uidRet = /[0-9]{9}/.exec(msg)
|
||||
if (uidRet) {
|
||||
e.uid = uidRet[0];
|
||||
msg = msg.replace(uidRet[0], "");
|
||||
e.uid = uidRet[0]
|
||||
msg = msg.replace(uidRet[0], '')
|
||||
}
|
||||
let name = msg.replace(/#|老婆|老公/g, "").trim();
|
||||
msg = msg.replace("面版", "面板")
|
||||
let dmgRet = /伤害(\d?)$/.exec(name), dmgIdx = 0;
|
||||
let name = msg.replace(/#|老婆|老公/g, '').trim()
|
||||
msg = msg.replace('面版', '面板')
|
||||
let dmgRet = /伤害(\d?)$/.exec(name);
|
||||
let dmgIdx = 0
|
||||
if (/(详情|详细|面板|面版)\s*$/.test(msg) && !/更新|录入|输入/.test(msg)) {
|
||||
mode = 'profile';
|
||||
name = name.replace(/(详情|详细|面板)/, "").trim();
|
||||
mode = 'profile'
|
||||
name = name.replace(/(详情|详细|面板)/, '').trim()
|
||||
} else if (dmgRet) {
|
||||
mode = 'dmg';
|
||||
name = name.replace(/伤害[0-5]?/, "").trim();
|
||||
mode = 'dmg'
|
||||
name = name.replace(/伤害[0-5]?/, '').trim()
|
||||
if (dmgRet[1]) {
|
||||
dmgIdx = dmgRet[1] * 1;
|
||||
dmgIdx = dmgRet[1] * 1
|
||||
}
|
||||
} else if (/(详情|详细|面板)更新$/.test(msg) || (/更新/.test(msg) && /(详情|详细|面板)$/.test(msg))) {
|
||||
mode = "refresh";
|
||||
name = name.replace(/详情|详细|面板|更新/g, "").trim();
|
||||
mode = 'refresh'
|
||||
name = name.replace(/详情|详细|面板|更新/g, '').trim()
|
||||
} else if (/(录入|输入)/.test(msg) && /(详情|详细|面板)/.test(msg)) {
|
||||
mode = "input";
|
||||
let nameRet = /(?:录入|输入)(.+)(?:面板|详细|详情|数据)+/.exec(name);
|
||||
mode = 'input'
|
||||
let nameRet = /(?:录入|输入)(.+)(?:面板|详细|详情|数据)+/.exec(name)
|
||||
if (nameRet) {
|
||||
name = nameRet[1];
|
||||
e.inputData = msg.replace(nameRet[0], "");
|
||||
name = nameRet[1]
|
||||
e.inputData = msg.replace(nameRet[0], '')
|
||||
}
|
||||
name = name.replace(/录入|输入|详情|详细|面板|数据|[0-9]|\.|\+/g, "").trim()
|
||||
name = name.replace(/录入|输入|详情|详细|面板|数据|[0-9]|\.|\+/g, '').trim()
|
||||
} else if (/圣遗物/.test(msg)) {
|
||||
mode = "artis";
|
||||
name = name.replace("圣遗物", "").trim();
|
||||
mode = 'artis'
|
||||
name = name.replace('圣遗物', '').trim()
|
||||
}
|
||||
|
||||
if (mode === "card" && Common.isDisable(e, "char.char")) {
|
||||
return;
|
||||
if (mode === 'card' && Common.isDisable(e, 'char.char')) {
|
||||
return
|
||||
}
|
||||
|
||||
if (mode !== "card" && !e.isMaster) {
|
||||
if (Common.isDisable(e, "char.profile")) {
|
||||
if (mode !== 'card' && !e.isMaster) {
|
||||
if (Common.isDisable(e, 'char.profile')) {
|
||||
// 面板开关关闭
|
||||
return;
|
||||
return
|
||||
}
|
||||
if (e.isPrivate) {
|
||||
if ((e.sub_type === "friend" && Cfg.get("profile.friend.status") === false) ||
|
||||
(e.sub_type === "group" && Cfg.get("profile.stranger.status") === false)) {
|
||||
return;
|
||||
if ((e.sub_type === 'friend' && Cfg.get('profile.friend.status') === false) ||
|
||||
(e.sub_type === 'group' && Cfg.get('profile.stranger.status') === false)) {
|
||||
return
|
||||
}
|
||||
} else if (e.isGroup) {
|
||||
let groupCfg = Cfg.get(`profile.groups.群${e.group_id}.status`);
|
||||
if (groupCfg === false || (groupCfg !== true && Cfg.get(`profile.group.status`) === false)) {
|
||||
return;
|
||||
let groupCfg = Cfg.get(`profile.groups.群${e.group_id}.status`)
|
||||
if (groupCfg === false || (groupCfg !== true && Cfg.get('profile.group.status') === false)) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let char = Character.get(name.trim());
|
||||
let char = Character.get(name.trim())
|
||||
|
||||
if (!char) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
|
||||
if (mode === "card") {
|
||||
return renderAvatar(e, char.name, render);
|
||||
if (mode === 'card') {
|
||||
return renderAvatar(e, char.name, render)
|
||||
}
|
||||
|
||||
let uid = await getTargetUid(e);
|
||||
let uid = await getTargetUid(e)
|
||||
if (!uid) {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
e.uid = uid;
|
||||
e.avatar = char.id;
|
||||
e.uid = uid
|
||||
e.avatar = char.id
|
||||
|
||||
if (char.isCustom) {
|
||||
e.reply("自定义角色暂不支持此功能");
|
||||
return true;
|
||||
e.reply('自定义角色暂不支持此功能')
|
||||
return true
|
||||
}
|
||||
|
||||
if (mode === "profile" || mode === "dmg") {
|
||||
return renderProfile(e, char, render, mode, { dmgIdx });
|
||||
} else if (mode === "refresh" || mode === "input") {
|
||||
await getProfile(e, mode);
|
||||
return true;
|
||||
} else if (mode === "artis") {
|
||||
return profileArtis(e, { render });
|
||||
if (mode === 'profile' || mode === 'dmg') {
|
||||
return renderProfile(e, char, render, mode, { dmgIdx })
|
||||
} else if (mode === 'refresh' || mode === 'input') {
|
||||
await getProfile(e, mode)
|
||||
return true
|
||||
} else if (mode === 'artis') {
|
||||
return profileArtis(e, { render })
|
||||
}
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,240 +1,227 @@
|
||||
import { Artifact, Character } from "../../components/models.js";
|
||||
import { Cfg, Data, Common, Profile } from "../../components/index.js";
|
||||
import lodash from "lodash";
|
||||
import { segment } from "oicq";
|
||||
import { Artifact, Character } from '../../components/models.js'
|
||||
import { Cfg, Data, Common, Profile } from '../../components/index.js'
|
||||
import lodash from 'lodash'
|
||||
import { segment } from 'oicq'
|
||||
|
||||
//角色昵称
|
||||
let nameID = "";
|
||||
let genshin = {};
|
||||
await init();
|
||||
// 角色昵称
|
||||
|
||||
export async function init(isUpdate = false) {
|
||||
let _path = "file://" + process.cwd();
|
||||
let version = isUpdate ? new Date().getTime() : 0;
|
||||
genshin = await import(_path + `/config/genshin/roleId.js?version=${version}`);
|
||||
nameID = "";
|
||||
}
|
||||
|
||||
|
||||
export async function renderAvatar(e, avatar, render, renderType = "card") {
|
||||
let abbr = Character.getAbbr()
|
||||
|
||||
export async function renderAvatar (e, avatar, render, renderType = 'card') {
|
||||
// 如果传递的是名字,则获取
|
||||
if (typeof (avatar) === "string") {
|
||||
let char = Character.get(avatar);
|
||||
if (typeof (avatar) === 'string') {
|
||||
let char = Character.get(avatar)
|
||||
if (!char) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
|
||||
let MysApi = await e.getMysApi({
|
||||
auth: "all",
|
||||
targetType: Cfg.get("char.queryOther", true) ? "all" : "self",
|
||||
cookieType: "all",
|
||||
actionName: "查询信息"
|
||||
});
|
||||
auth: 'all',
|
||||
targetType: Cfg.get('char.queryOther', true) ? 'all' : 'self',
|
||||
cookieType: 'all',
|
||||
actionName: '查询信息'
|
||||
})
|
||||
|
||||
if (!MysApi) return true;
|
||||
if (!MysApi) return true
|
||||
|
||||
let uid = e.targetUser.uid;
|
||||
let uid = MysApi.targetUser.uid
|
||||
|
||||
if (char.isCustom) {
|
||||
avatar = { id: char.id, name: char.name, detail: false }
|
||||
} else {
|
||||
let profile = await Profile.get(uid, char.id, true);
|
||||
let profile = await Profile.get(uid, char.id, true)
|
||||
if (profile) {
|
||||
// 优先使用Profile数据
|
||||
avatar = profile;
|
||||
avatar = profile
|
||||
} else {
|
||||
// 使用Mys数据兜底
|
||||
let charData = await MysApi.getCharacter();
|
||||
if (!charData) return true;
|
||||
let charData = await MysApi.getCharacter()
|
||||
if (!charData) return true
|
||||
|
||||
let avatars = charData.avatars;
|
||||
let length = avatars.length;
|
||||
char.checkAvatars(avatars);
|
||||
avatars = lodash.keyBy(avatars, "id");
|
||||
avatar = avatars[char.id] || { id: char.id, name: char.name, detail: false };
|
||||
let avatars = charData.avatars
|
||||
char.checkAvatars(avatars)
|
||||
avatars = lodash.keyBy(avatars, 'id')
|
||||
avatar = avatars[char.id] || { id: char.id, name: char.name, detail: false }
|
||||
}
|
||||
}
|
||||
}
|
||||
return await renderCard(e, avatar, render, renderType);
|
||||
return await renderCard(e, avatar, render, renderType)
|
||||
}
|
||||
|
||||
// 渲染角色卡片
|
||||
async function renderCard(e, avatar, render, renderType = "card") {
|
||||
|
||||
let char = Character.get(avatar);
|
||||
async function renderCard (e, avatar, render, renderType = 'card') {
|
||||
let char = Character.get(avatar)
|
||||
|
||||
if (!char) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
let uid = e.uid || (e.targetUser && e.targetUser.uid);
|
||||
let uid = e.uid || (e.targetUser && e.targetUser.uid)
|
||||
|
||||
let crownNum = 0, talent = {};
|
||||
let crownNum = 0;
|
||||
let talent = {}
|
||||
if (!char.isCustom) {
|
||||
talent = await getTalent(e, avatar);
|
||||
talent = await getTalent(e, avatar)
|
||||
// 计算皇冠个数
|
||||
crownNum = lodash.filter(lodash.map(talent, (d) => d.original), (d) => d >= 10).length;
|
||||
crownNum = lodash.filter(lodash.map(talent, (d) => d.original), (d) => d >= 10).length
|
||||
}
|
||||
let bg = char.getCardImg(Cfg.get("char.se", false));
|
||||
if (renderType === "photo") {
|
||||
e.reply(segment.image(process.cwd() + "/plugins/miao-plugin/resources/" + bg.img));
|
||||
let bg = char.getCardImg(Cfg.get('char.se', false))
|
||||
if (renderType === 'photo') {
|
||||
e.reply(segment.image(process.cwd() + '/plugins/miao-plugin/resources/' + bg.img))
|
||||
} else {
|
||||
//渲染图像
|
||||
let msgRes = await Common.render("character/card", {
|
||||
// 渲染图像
|
||||
let msgRes = await Common.render('character/card', {
|
||||
save_id: uid,
|
||||
uid,
|
||||
talent,
|
||||
crownNum,
|
||||
talentMap: { a: "普攻", e: "战技", q: "爆发" },
|
||||
talentMap: { a: '普攻', e: '战技', q: '爆发' },
|
||||
bg,
|
||||
custom: char.isCustom,
|
||||
...getCharacterData(avatar),
|
||||
ds: char.getData("name,id,title,desc"),
|
||||
}, { e, render, scale: 1.6 });
|
||||
ds: char.getData('name,id,title,desc')
|
||||
}, { e, render, scale: 1.6 })
|
||||
if (msgRes && msgRes.message_id) {
|
||||
// 如果消息发送成功,就将message_id和图片路径存起来,1小时过期
|
||||
await redis.set(`miao:original-picture:${msgRes.message_id}`, bg.img, { EX: 3600 });
|
||||
await redis.set(`miao:original-picture:${msgRes.message_id}`, bg.img, { EX: 3600 })
|
||||
}
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
|
||||
//获取角色技能数据
|
||||
async function getTalent(e, avatars) {
|
||||
let talent = {}, cons = 0, char = Character.get(avatars.id), mode = "level";
|
||||
// 获取角色技能数据
|
||||
async function getTalent (e, avatars) {
|
||||
let talent = {};
|
||||
let cons = 0;
|
||||
let char = Character.get(avatars.id);
|
||||
let mode = 'level'
|
||||
if (char.isCustom) {
|
||||
return {}
|
||||
}
|
||||
if (avatars.dataSource && avatars.talent) {
|
||||
// profile模式
|
||||
talent = avatars.talent || {};
|
||||
cons = avatars.cons || 0;
|
||||
talent = avatars.talent || {}
|
||||
cons = avatars.cons || 0
|
||||
} else {
|
||||
let MysApi = await e.getMysApi({
|
||||
auth: "all",
|
||||
targetType: Cfg.get("char.queryOther", true) ? "all" : "self",
|
||||
cookieType: "all",
|
||||
actionName: "查询信息"
|
||||
});
|
||||
if (!MysApi && !MysApi.isSelfCookie) return {};
|
||||
let skillRes = await MysApi.getAvatar(avatars.id);
|
||||
auth: 'all',
|
||||
targetType: Cfg.get('char.queryOther', true) ? 'all' : 'self',
|
||||
cookieType: 'all',
|
||||
actionName: '查询信息'
|
||||
})
|
||||
if (!MysApi && !MysApi.isSelfCookie) return {}
|
||||
let skillRes = await MysApi.getAvatar(avatars.id)
|
||||
cons = avatars.actived_constellation_num
|
||||
mode = "original";
|
||||
mode = 'original'
|
||||
if (skillRes && skillRes.skill_list) {
|
||||
let skill_list = lodash.orderBy(skillRes.skill_list, ["id"], ["asc"]);
|
||||
for (let val of skill_list) {
|
||||
if (val.name.includes("普通攻击")) {
|
||||
talent.a = val;
|
||||
continue;
|
||||
let skillList = lodash.orderBy(skillRes.skill_list, ['id'], ['asc'])
|
||||
for (let val of skillList) {
|
||||
if (val.name.includes('普通攻击')) {
|
||||
talent.a = val
|
||||
continue
|
||||
}
|
||||
if (val.max_level >= 10 && !talent.e) {
|
||||
talent.e = val;
|
||||
continue;
|
||||
talent.e = val
|
||||
continue
|
||||
}
|
||||
if (val.max_level >= 10 && !talent.q) {
|
||||
talent.q = val;
|
||||
talent.q = val
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return char.getAvatarTalent(talent, cons, mode);
|
||||
return char.getAvatarTalent(talent, cons, mode)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 获取角色数据
|
||||
* */
|
||||
function getCharacterData(avatars) {
|
||||
let list = [];
|
||||
let set = {};
|
||||
let artiEffect = [];
|
||||
let w = avatars.weapon || {};
|
||||
function getCharacterData (avatars) {
|
||||
let list = []
|
||||
let set = {}
|
||||
let artiEffect = []
|
||||
let w = avatars.weapon || {}
|
||||
let weapon = {
|
||||
type: "weapon",
|
||||
name: w.name || "",
|
||||
showName: genshin.abbr[w.name] || w.name || "",
|
||||
type: 'weapon',
|
||||
name: w.name || '',
|
||||
showName: abbr[w.name] || w.name || '',
|
||||
level: w.level || 1,
|
||||
affix: w.affix || w.affix_level || 0
|
||||
}
|
||||
|
||||
let artis = avatars.artis || avatars.reliquaries;
|
||||
let artis = avatars.artis || avatars.reliquaries
|
||||
|
||||
if (artis) {
|
||||
lodash.forEach(artis, (val) => {
|
||||
let setCfg = Artifact.getSetByArti(val.name);
|
||||
let setCfg = Artifact.getSetByArti(val.name)
|
||||
if (!setCfg) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
let setName = setCfg.name;
|
||||
let setName = setCfg.name
|
||||
if (set[setName]) {
|
||||
set[setName]++;
|
||||
set[setName]++
|
||||
if (set[setName] === 2) {
|
||||
artiEffect.push("2件套:" + setCfg.effect['2'])
|
||||
artiEffect.push('2件套:' + setCfg.effect['2'])
|
||||
}
|
||||
if (set[setName] === 4) {
|
||||
artiEffect.push("4件套:" + setCfg.name);
|
||||
artiEffect.push('4件套:' + setCfg.name)
|
||||
}
|
||||
} else {
|
||||
set[setName] = 1;
|
||||
set[setName] = 1
|
||||
}
|
||||
})
|
||||
|
||||
if (artiEffect.length === 0) {
|
||||
artiEffect = ["无套装效果"];
|
||||
artiEffect = ['无套装效果']
|
||||
}
|
||||
}
|
||||
|
||||
if (avatars.id == "10000005") {
|
||||
avatars.name = "空";
|
||||
} else if (avatars.id == "10000007") {
|
||||
avatars.name = "荧";
|
||||
if (avatars.id == '10000005') {
|
||||
avatars.name = '空'
|
||||
} else if (avatars.id == '10000007') {
|
||||
avatars.name = '荧'
|
||||
}
|
||||
|
||||
let reliquaries = list[0];
|
||||
let reliquaries = list[0]
|
||||
return {
|
||||
name: avatars.name,
|
||||
showName: genshin.abbr[avatars.name] ? genshin.abbr[avatars.name] : avatars.name,
|
||||
showName: abbr[avatars.name] ? abbr[avatars.name] : avatars.name,
|
||||
level: Data.def(avatars.lv, avatars.level),
|
||||
fetter: avatars.fetter,
|
||||
cons: Data.def(avatars.cons, avatars.actived_constellation_num),
|
||||
weapon,
|
||||
artiEffect,
|
||||
reliquaries
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function getAvatarList(e, type, MysApi) {
|
||||
let data = await MysApi.getCharacter();
|
||||
if (!data) return false;
|
||||
export async function getAvatarList (e, type, MysApi) {
|
||||
let data = await MysApi.getCharacter()
|
||||
if (!data) return false
|
||||
|
||||
let avatars = data.avatars;
|
||||
let avatars = data.avatars
|
||||
|
||||
if (avatars.length <= 0) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
let list = [];
|
||||
let list = []
|
||||
for (let val of avatars) {
|
||||
if (type !== false) {
|
||||
if (!genshin.wifeData[type].includes(Number(val.id))) {
|
||||
continue;
|
||||
if (!Character.checkWifeType(val.id, type)) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if (val.rarity > 5) {
|
||||
val.rarity = 5;
|
||||
val.rarity = 5
|
||||
}
|
||||
list.push(val);
|
||||
list.push(val)
|
||||
}
|
||||
|
||||
if (list.length <= 0) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
let sortKey = "level,fetter,weapon_level,rarity,weapon_rarity,cons,weapon_affix_level";
|
||||
list = lodash.orderBy(list, sortKey, lodash.repeat("desc,", sortKey.length).split(","));
|
||||
return list;
|
||||
}
|
||||
|
||||
export function checkWifeType(id, type) {
|
||||
return Chargenshin.wifeData[type].includes(Number(id));
|
||||
let sortKey = 'level,fetter,weapon_level,rarity,weapon_rarity,cons,weapon_affix_level'
|
||||
list = lodash.orderBy(list, sortKey, lodash.repeat('desc,', sortKey.length).split(','))
|
||||
return list
|
||||
}
|
@ -1,189 +1,190 @@
|
||||
//#老婆
|
||||
import lodash from "lodash";
|
||||
import { Cfg } from "../../components/index.js";
|
||||
import { Character } from "../../components/models.js";
|
||||
import { checkWifeType, getAvatarList, renderAvatar } from "./avatar-card.js";
|
||||
// #老婆
|
||||
import lodash from 'lodash'
|
||||
import { Cfg } from '../../components/index.js'
|
||||
import { Character } from '../../components/models.js'
|
||||
import { getAvatarList, renderAvatar } from './avatar-card.js'
|
||||
|
||||
const relationMap = {
|
||||
wife: {
|
||||
keyword: "老婆,媳妇,妻子,娘子".split(","),
|
||||
keyword: '老婆,媳妇,妻子,娘子'.split(','),
|
||||
type: 0
|
||||
},
|
||||
husband: {
|
||||
keyword: "老公,丈夫,夫君,郎君".split(","),
|
||||
keyword: '老公,丈夫,夫君,郎君'.split(','),
|
||||
type: 1
|
||||
},
|
||||
gf: {
|
||||
keyword: "女朋友,女友,女神".split(","),
|
||||
keyword: '女朋友,女友,女神'.split(','),
|
||||
type: 0
|
||||
},
|
||||
bf: {
|
||||
keyword: "男朋友,男友,男神".split(","),
|
||||
keyword: '男朋友,男友,男神'.split(','),
|
||||
type: 1
|
||||
},
|
||||
daughter: {
|
||||
keyword: "女儿".split(","),
|
||||
keyword: '女儿'.split(','),
|
||||
type: 2
|
||||
},
|
||||
son: {
|
||||
keyword: "儿子".split(","),
|
||||
keyword: '儿子'.split(','),
|
||||
type: 3
|
||||
}
|
||||
}
|
||||
|
||||
const relation = lodash.flatMap(relationMap, (d) => d.keyword);
|
||||
export const wifeReg = `^#?\\s*(${relation.join("|")})\\s*(设置|选择|指定|列表|查询|列表|是|是谁|照片|相片|图片|写真|图像)?\\s*([^\\d]*)\\s*(\\d*)$`;
|
||||
const relation = lodash.flatMap(relationMap, (d) => d.keyword)
|
||||
export const wifeReg = `^#?\\s*(${relation.join('|')})\\s*(设置|选择|指定|列表|查询|列表|是|是谁|照片|相片|图片|写真|图像)?\\s*([^\\d]*)\\s*(\\d*)$`
|
||||
|
||||
|
||||
export async function wife(e, { render, User }) {
|
||||
let msg = e.msg || "";
|
||||
if (!msg && !e.isPoke) return false;
|
||||
export async function wife (e, { render, User }) {
|
||||
let msg = e.msg || ''
|
||||
if (!msg && !e.isPoke) return false
|
||||
|
||||
if (e.isPoke) {
|
||||
if (Cfg.isDisable(e, "char.poke")) {
|
||||
return false;
|
||||
if (Cfg.isDisable(e, 'char.poke')) {
|
||||
return false
|
||||
}
|
||||
} else if (Cfg.isDisable(e, "char.wife")) {
|
||||
return false;
|
||||
} else if (Cfg.isDisable(e, 'char.wife')) {
|
||||
return false
|
||||
}
|
||||
|
||||
let msgRet = (new RegExp(wifeReg)).exec(msg);
|
||||
let msgRet = (new RegExp(wifeReg)).exec(msg)
|
||||
if (e.isPoke) {
|
||||
msgRet = [];
|
||||
msgRet = []
|
||||
} else if (!msgRet) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
let target = msgRet[1],
|
||||
action = msgRet[2] || "卡片",
|
||||
actionParam = msgRet[3] || "";
|
||||
let target = msgRet[1]
|
||||
let action = msgRet[2] || '卡片'
|
||||
let actionParam = msgRet[3] || ''
|
||||
|
||||
if (!"设置,选择,挑选,指定".split(",").includes(action) && actionParam) {
|
||||
return false;
|
||||
if (!'设置,选择,挑选,指定'.split(',').includes(action) && actionParam) {
|
||||
return false
|
||||
}
|
||||
|
||||
let targetCfg = lodash.find(relationMap, (cfg, key) => {
|
||||
cfg.key = key;
|
||||
return cfg.keyword.includes(target);
|
||||
});
|
||||
if (!targetCfg && !e.isPoke) return true;
|
||||
cfg.key = key
|
||||
return cfg.keyword.includes(target)
|
||||
})
|
||||
if (!targetCfg && !e.isPoke) return true
|
||||
|
||||
let avatarList = [], avatar = {}, wifeList = [];
|
||||
let avatarList = [];
|
||||
let avatar = {};
|
||||
let wifeList = []
|
||||
|
||||
let MysApi = await e.getMysApi({
|
||||
auth: "all",
|
||||
targetType: Cfg.get("char.queryOther", true) ? "all" : "self",
|
||||
cookieType: "all",
|
||||
actionName: "查询信息"
|
||||
});
|
||||
auth: 'all',
|
||||
targetType: Cfg.get('char.queryOther', true) ? 'all' : 'self',
|
||||
cookieType: 'all',
|
||||
actionName: '查询信息'
|
||||
})
|
||||
if (!MysApi || !MysApi.selfUser) {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
let selfUser = MysApi.selfUser;
|
||||
let selfMysUser = await selfUser.getMysUser();
|
||||
let isSelf = true;
|
||||
let selfUser = MysApi.selfUser
|
||||
let selfMysUser = await selfUser.getMysUser()
|
||||
let isSelf = true
|
||||
if (!selfMysUser || selfMysUser.uid !== MysApi.targetUser.uid) {
|
||||
isSelf = false;
|
||||
isSelf = false
|
||||
}
|
||||
|
||||
switch (action) {
|
||||
case "卡片":
|
||||
case "照片":
|
||||
case "相片":
|
||||
case "图片":
|
||||
case "写真":
|
||||
case '卡片':
|
||||
case '照片':
|
||||
case '相片':
|
||||
case '图片':
|
||||
case '写真':
|
||||
// 展示老婆卡片
|
||||
|
||||
// 如果选择过,则进行展示
|
||||
let renderType = action === "卡片" ? "card" : "photo";
|
||||
let renderType = action === '卡片' ? 'card' : 'photo'
|
||||
if (!e.isPoke) {
|
||||
wifeList = await selfUser.getCfg(`wife.${targetCfg.key}`, []);
|
||||
wifeList = await selfUser.getCfg(`wife.${targetCfg.key}`, [])
|
||||
// 存在设置
|
||||
if (wifeList && wifeList.length > 0 && isSelf && !e.isPoke) {
|
||||
if (wifeList[0] === "随机") {
|
||||
if (wifeList[0] === '随机') {
|
||||
// 如果选择为全部,则从列表中随机选择一个
|
||||
avatarList = await getAvatarList(e, targetCfg.type, MysApi);
|
||||
let avatar = lodash.sample(avatarList);
|
||||
return renderAvatar(e, avatar, render, renderType);
|
||||
avatarList = await getAvatarList(e, targetCfg.type, MysApi)
|
||||
let avatar = lodash.sample(avatarList)
|
||||
return renderAvatar(e, avatar, render, renderType)
|
||||
} else {
|
||||
// 如果指定过,则展示指定角色
|
||||
return renderAvatar(e, lodash.sample(wifeList), render, renderType);
|
||||
return renderAvatar(e, lodash.sample(wifeList), render, renderType)
|
||||
}
|
||||
}
|
||||
}
|
||||
// 如果未指定过,则从列表中排序并随机选择前5个
|
||||
if (e.isPoke) {
|
||||
avatarList = await getAvatarList(e, false, MysApi);
|
||||
avatarList = await getAvatarList(e, false, MysApi)
|
||||
if (avatarList && avatarList.length > 0) {
|
||||
avatar = lodash.sample(avatarList);
|
||||
return await renderAvatar(e, avatar, render, renderType);
|
||||
avatar = lodash.sample(avatarList)
|
||||
return await renderAvatar(e, avatar, render, renderType)
|
||||
}
|
||||
} else {
|
||||
avatarList = await getAvatarList(e, targetCfg.type, MysApi);
|
||||
avatarList = await getAvatarList(e, targetCfg.type, MysApi)
|
||||
if (avatarList && avatarList.length > 0) {
|
||||
avatar = lodash.sample(avatarList.slice(0, 5));
|
||||
return await renderAvatar(e, avatar, render, renderType);
|
||||
avatar = lodash.sample(avatarList.slice(0, 5))
|
||||
return await renderAvatar(e, avatar, render, renderType)
|
||||
}
|
||||
}
|
||||
e.reply(`在当前米游社公开展示的角色中未能找到适合展示的角色..`);
|
||||
return true;
|
||||
break;
|
||||
case "设置":
|
||||
case "选择":
|
||||
case "挑选":
|
||||
case "指定":
|
||||
e.reply('在当前米游社公开展示的角色中未能找到适合展示的角色..')
|
||||
return true
|
||||
break
|
||||
case '设置':
|
||||
case '选择':
|
||||
case '挑选':
|
||||
case '指定':
|
||||
if (!isSelf) {
|
||||
e.reply("只能指定自己的哦~");
|
||||
return true;
|
||||
e.reply('只能指定自己的哦~')
|
||||
return true
|
||||
}
|
||||
// 选择老婆
|
||||
actionParam = actionParam.replace(/(,|、|;|;)/g, ",");
|
||||
wifeList = actionParam.split(",");
|
||||
let addRet = [];
|
||||
if (lodash.intersection(["全部", "任意", "随机", "全都要"], wifeList).length > 0) {
|
||||
addRet = ['随机'];
|
||||
actionParam = actionParam.replace(/(,|、|;|;)/g, ',')
|
||||
wifeList = actionParam.split(',')
|
||||
let addRet = []
|
||||
if (lodash.intersection(['全部', '任意', '随机', '全都要'], wifeList).length > 0) {
|
||||
addRet = ['随机']
|
||||
} else {
|
||||
wifeList = lodash.map(wifeList, (name) => {
|
||||
let char = Character.get(name);
|
||||
let char = Character.get(name)
|
||||
if (char && char.checkWifeType(targetCfg.type)) {
|
||||
return char.name;
|
||||
return char.name
|
||||
}
|
||||
});
|
||||
wifeList = lodash.filter(lodash.uniq(wifeList), (d) => !!d);
|
||||
})
|
||||
wifeList = lodash.filter(lodash.uniq(wifeList), (d) => !!d)
|
||||
/*
|
||||
avatarList = await getAvatarList(e, targetCfg.type, MysApi);
|
||||
avatarList = lodash.map(avatarList, (avatar) => avatar.name);
|
||||
avatarList = lodash.filter(avatarList, (d) => !!d);
|
||||
addRet = lodash.intersection(avatarList, wifeList);
|
||||
*/
|
||||
addRet = wifeList;
|
||||
addRet = wifeList
|
||||
if (addRet.length === 0) {
|
||||
e.reply(`在可选的${targetCfg.keyword[0]}列表中未能找到 ${actionParam} ~`);
|
||||
return true;
|
||||
e.reply(`在可选的${targetCfg.keyword[0]}列表中未能找到 ${actionParam} ~`)
|
||||
return true
|
||||
}
|
||||
}
|
||||
await selfUser.setCfg(`wife.${targetCfg.key}`, addRet);
|
||||
e.reply(`${targetCfg.keyword[0]}已经设置:${addRet.join(",")}`);
|
||||
return true;
|
||||
break;
|
||||
case "列表":
|
||||
case "是":
|
||||
case "是谁":
|
||||
await selfUser.setCfg(`wife.${targetCfg.key}`, addRet)
|
||||
e.reply(`${targetCfg.keyword[0]}已经设置:${addRet.join(',')}`)
|
||||
return true
|
||||
break
|
||||
case '列表':
|
||||
case '是':
|
||||
case '是谁':
|
||||
// 查看当前选择老婆
|
||||
if (!isSelf) {
|
||||
e.reply("只能查看自己的哦~");
|
||||
return true;
|
||||
e.reply('只能查看自己的哦~')
|
||||
return true
|
||||
}
|
||||
wifeList = await selfUser.getCfg(`wife.${targetCfg.key}`, []);
|
||||
wifeList = await selfUser.getCfg(`wife.${targetCfg.key}`, [])
|
||||
if (wifeList && wifeList.length > 0) {
|
||||
e.reply(`你的${targetCfg.keyword[0]}是:${wifeList.join(",")}`);
|
||||
e.reply(`你的${targetCfg.keyword[0]}是:${wifeList.join(',')}`)
|
||||
} else {
|
||||
e.reply(`尚未设置,回复#${targetCfg.keyword[0]}设置+角色名 来设置,如果设置多位请用逗号间隔`)
|
||||
}
|
||||
break;
|
||||
break
|
||||
}
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
|
||||
export async function pokeWife(e, components) {
|
||||
return await wife(e, components);
|
||||
}
|
||||
export async function pokeWife (e, components) {
|
||||
return await wife(e, components)
|
||||
}
|
||||
|
@ -1,252 +1,247 @@
|
||||
/*
|
||||
* 面板公共方法及处理
|
||||
* */
|
||||
import lodash from "lodash";
|
||||
import { segment } from "oicq";
|
||||
import Profile from "../../components/Profile.js";
|
||||
import { Character } from "../../components/models.js";
|
||||
import lodash from 'lodash'
|
||||
import { segment } from 'oicq'
|
||||
import Profile from '../../components/Profile.js'
|
||||
import { Character } from '../../components/models.js'
|
||||
|
||||
/*
|
||||
* 获取面板查询的 目标uid
|
||||
* */
|
||||
export async function getTargetUid(e) {
|
||||
let uidReg = /[1-9][0-9]{8}/;
|
||||
export async function getTargetUid (e) {
|
||||
let uidReg = /[1-9][0-9]{8}/
|
||||
|
||||
if (e.uid && uidReg.test(e.uid)) {
|
||||
return e.uid;
|
||||
return e.uid
|
||||
}
|
||||
|
||||
let uidRet = uidReg.exec(e.msg);
|
||||
let uidRet = uidReg.exec(e.msg)
|
||||
if (uidRet) {
|
||||
return uidRet[0]
|
||||
}
|
||||
let uid = false;
|
||||
let uid = false
|
||||
let getUid = async function (qq) {
|
||||
if (NoteCookie && NoteCookie[qq]) {
|
||||
let nc = NoteCookie[qq];
|
||||
let nCookie = global.NoteCookie || false
|
||||
if (nCookie && nCookie[qq]) {
|
||||
let nc = nCookie[qq]
|
||||
if (nc.uid && uidReg.test(nc.uid)) {
|
||||
return nc.uid;
|
||||
return nc.uid
|
||||
}
|
||||
}
|
||||
uid = await redis.get(`genshin:id-uid:${qq}`) || await redis.get(`genshin:uid:${qq}`);
|
||||
uid = await redis.get(`genshin:id-uid:${qq}`) || await redis.get(`genshin:uid:${qq}`)
|
||||
if (uid && uidReg.test(uid)) {
|
||||
return uid;
|
||||
return uid
|
||||
}
|
||||
}
|
||||
|
||||
if (e.at && e.at != BotConfig.account.qq) {
|
||||
uid = await getUid(e.at);
|
||||
if (e.at && e.at != global?.BotConfig?.account?.qq) {
|
||||
uid = await getUid(e.at)
|
||||
if (uid) {
|
||||
return uid;
|
||||
return uid
|
||||
}
|
||||
}
|
||||
|
||||
uid = await getUid(e.user_id);
|
||||
uid = await getUid(e.user_id)
|
||||
if (uid) {
|
||||
return uid;
|
||||
return uid
|
||||
}
|
||||
|
||||
try {
|
||||
let MysApi = await e.getMysApi({
|
||||
auth: "all",
|
||||
targetType: "all",
|
||||
cookieType: "all"
|
||||
});
|
||||
auth: 'all',
|
||||
targetType: 'all',
|
||||
cookieType: 'all'
|
||||
})
|
||||
|
||||
if (!MysApi || !e.targetUser) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
|
||||
uid = e.targetUser.uid;
|
||||
uid = e.targetUser.uid
|
||||
if (!uid || !uidReg.test(uid)) {
|
||||
e.reply("请先发送【#绑定+你的UID】来绑定查询目标")
|
||||
return false;
|
||||
e.reply('请先发送【#绑定+你的UID】来绑定查询目标')
|
||||
return false
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
console.log(err)
|
||||
}
|
||||
return uid || false;
|
||||
return uid || false
|
||||
}
|
||||
|
||||
/*
|
||||
* 自动更新面板数据
|
||||
* */
|
||||
export async function autoRefresh(e) {
|
||||
|
||||
let uid = await getTargetUid(e);
|
||||
export async function autoRefresh (e) {
|
||||
let uid = await getTargetUid(e)
|
||||
if (!uid || e.isRefreshed) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
|
||||
let refreshMark = await redis.get(`miao:profile-refresh-cd:${uid}`);
|
||||
let inCd = await redis.get(`miao:role-all:${uid}`);
|
||||
let refreshMark = await redis.get(`miao:profile-refresh-cd:${uid}`)
|
||||
let inCd = await redis.get(`miao:role-all:${uid}`)
|
||||
|
||||
if (refreshMark || inCd) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
|
||||
await redis.set(`miao:profile-refresh-cd:${uid}`, "TRUE", { EX: 3600 * 12 });
|
||||
e.isRefreshed = true;
|
||||
await redis.set(`miao:profile-refresh-cd:${uid}`, 'TRUE', { EX: 3600 * 12 })
|
||||
e.isRefreshed = true
|
||||
|
||||
// 数据更新
|
||||
let data = await Profile.request(uid, e);
|
||||
let data = await Profile.request(uid, e)
|
||||
if (!data) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
|
||||
if (!data.chars) {
|
||||
e.reply("请确认角色已在【游戏内】橱窗展示并开放了查看详情。请在设置完毕5分钟后使用 #面板更新 重新获取");
|
||||
return false;
|
||||
e.reply('请确认角色已在【游戏内】橱窗展示并开放了查看详情。请在设置完毕5分钟后使用 #面板更新 重新获取')
|
||||
return false
|
||||
} else {
|
||||
let ret = [];
|
||||
let ret = []
|
||||
lodash.forEach(data.chars, (ds) => {
|
||||
let char = Character.get(ds.id);
|
||||
let char = Character.get(ds.id)
|
||||
if (char) {
|
||||
ret.push(char.name);
|
||||
ret.push(char.name)
|
||||
}
|
||||
})
|
||||
if (ret.length === 0) {
|
||||
e.reply("请确认角色已在【游戏内】橱窗展示并开放了查看详情。请在设置完毕5分钟后使用 #面板更新 重新获取")
|
||||
return false;
|
||||
e.reply('请确认角色已在【游戏内】橱窗展示并开放了查看详情。请在设置完毕5分钟后使用 #面板更新 重新获取')
|
||||
return false
|
||||
} else {
|
||||
// e.reply(`本次获取成功角色: ${ret.join(", ")} `)
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
|
||||
export async function autoGetProfile(e, uid, avatar, callback) {
|
||||
|
||||
export async function autoGetProfile (e, uid, avatar, callback) {
|
||||
let refresh = async () => {
|
||||
let refreshRet = await autoRefresh(e);
|
||||
let refreshRet = await autoRefresh(e)
|
||||
if (refreshRet) {
|
||||
await callback();
|
||||
await callback()
|
||||
}
|
||||
return refreshRet;
|
||||
return refreshRet
|
||||
}
|
||||
|
||||
let char = Character.get(avatar);
|
||||
let char = Character.get(avatar)
|
||||
if (!char) {
|
||||
return { err: true };
|
||||
return { err: true }
|
||||
}
|
||||
|
||||
let profile = await Profile.get(uid, char.id);
|
||||
let profile = await Profile.get(uid, char.id)
|
||||
if (!profile) {
|
||||
if (await refresh()) {
|
||||
return { err: true };
|
||||
return { err: true }
|
||||
} else {
|
||||
e.reply(`请确认${char.name}已展示在【游戏内】的角色展柜中,并打开了“显示角色详情”。然后请使用 #更新面板\n命令来获取${char.name}的面板详情`);
|
||||
e.reply(`请确认${char.name}已展示在【游戏内】的角色展柜中,并打开了“显示角色详情”。然后请使用 #更新面板\n命令来获取${char.name}的面板详情`)
|
||||
}
|
||||
return { err: true };
|
||||
return { err: true }
|
||||
} else if (!['enka', 'input2', 'miao', 'miao-pre'].includes(profile.dataSource)) {
|
||||
if (!await refresh()) {
|
||||
e.reply(`由于数据格式升级,请重新获取面板信息后查看`);
|
||||
e.reply('由于数据格式升级,请重新获取面板信息后查看')
|
||||
}
|
||||
return { err: true };
|
||||
return { err: true }
|
||||
}
|
||||
|
||||
return { profile, char, refresh }
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* 面板数据更新
|
||||
* */
|
||||
export async function getProfile(e, mode = "refresh") {
|
||||
let uid = await getTargetUid(e);
|
||||
export async function getProfile (e, mode = 'refresh') {
|
||||
let uid = await getTargetUid(e)
|
||||
if (!uid) {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
|
||||
if (mode === "input") {
|
||||
if (mode === 'input') {
|
||||
if (e.inputData.trim().length < 5) {
|
||||
e.reply(`【输入示例】\n#录入夜兰面板 生命14450+25469, 攻击652+444, 防御548+144, 元素精通84, 暴击76.3, 爆伤194.2, 治疗0,充能112.3,元素伤害61.6,物伤0`)
|
||||
return true;
|
||||
//await profileHelp(e);
|
||||
e.reply('【输入示例】\n#录入夜兰面板 生命14450+25469, 攻击652+444, 防御548+144, 元素精通84, 暴击76.3, 爆伤194.2, 治疗0,充能112.3,元素伤害61.6,物伤0')
|
||||
return true
|
||||
// await profileHelp(e);
|
||||
}
|
||||
|
||||
|
||||
let ret = Profile.inputProfile(uid, e);
|
||||
let char = Character.get(e.avatar);
|
||||
let ret = Profile.inputProfile(uid, e)
|
||||
let char = Character.get(e.avatar)
|
||||
if (lodash.isString(ret)) {
|
||||
e.reply(ret);
|
||||
return true;
|
||||
e.reply(ret)
|
||||
return true
|
||||
} else if (ret) {
|
||||
e.reply(`${char.name}信息手工录入完成,你可以使用 #角色名+面板 / #角色名+伤害 来查看详细角色面板属性了`)
|
||||
} else {
|
||||
e.reply(`${char.name}信息手工录入失败,请检查录入格式。回复 #角色面板帮助 可查看录入提示`);
|
||||
e.reply(`【输入示例】\n#录入夜兰面板 生命14450+25469, 攻击652+444, 防御548+144, 元素精通84, 暴击76.3, 爆伤194.2, 治疗0,充能112.3,元素伤害61.6,物伤0`)
|
||||
e.reply(`${char.name}信息手工录入失败,请检查录入格式。回复 #角色面板帮助 可查看录入提示`)
|
||||
e.reply('【输入示例】\n#录入夜兰面板 生命14450+25469, 攻击652+444, 防御548+144, 元素精通84, 暴击76.3, 爆伤194.2, 治疗0,充能112.3,元素伤害61.6,物伤0')
|
||||
}
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
|
||||
// 数据更新
|
||||
let data = await Profile.request(uid, e);
|
||||
let data = await Profile.request(uid, e)
|
||||
if (!data) {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
|
||||
if (!data.chars) {
|
||||
e.reply("获取角色面板数据失败,请确认角色已在游戏内橱窗展示,并开放了查看详情。设置完毕后请5分钟后再进行请求~");
|
||||
e.reply('获取角色面板数据失败,请确认角色已在游戏内橱窗展示,并开放了查看详情。设置完毕后请5分钟后再进行请求~')
|
||||
} else {
|
||||
let ret = [];
|
||||
let ret = []
|
||||
lodash.forEach(data.chars, (ds) => {
|
||||
let char = Character.get(ds.id);
|
||||
let char = Character.get(ds.id)
|
||||
if (char) {
|
||||
ret.push(char.name);
|
||||
ret.push(char.name)
|
||||
}
|
||||
})
|
||||
if (ret.length === 0) {
|
||||
e.reply("获取角色面板数据失败,未能请求到角色数据。请确认角色已在游戏内橱窗展示,并开放了查看详情。设置完毕后请5分钟后再进行请求~")
|
||||
e.reply('获取角色面板数据失败,未能请求到角色数据。请确认角色已在游戏内橱窗展示,并开放了查看详情。设置完毕后请5分钟后再进行请求~')
|
||||
} else {
|
||||
e.reply(`获取角色面板数据成功!\n${ret.length > 8 ? "所有已获取" : "本次获取成功"}角色: ${ret.join(", ")} 。\n你可以使用 #角色名+面板 来查看详细角色面板属性了。`)
|
||||
e.reply(`获取角色面板数据成功!\n${ret.length > 8 ? '所有已获取' : '本次获取成功'}角色: ${ret.join(', ')} 。\n你可以使用 #角色名+面板 来查看详细角色面板属性了。`)
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
|
||||
/*
|
||||
* 获取面板列表
|
||||
* */
|
||||
export async function getProfileAll(e) {
|
||||
|
||||
let uid = await getTargetUid(e);
|
||||
export async function getProfileAll (e) {
|
||||
let uid = await getTargetUid(e)
|
||||
if (!uid) {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
|
||||
let profiles = Profile.getAll(uid) || {};
|
||||
let profiles = Profile.getAll(uid) || {}
|
||||
|
||||
let chars = [];
|
||||
let chars = []
|
||||
lodash.forEach(profiles || [], (ds) => {
|
||||
if (!['enka', 'input2', 'miao-pre', 'miao'].includes(ds.dataSource)) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
ds.name && chars.push(ds.name)
|
||||
});
|
||||
|
||||
})
|
||||
|
||||
if (chars.length === 0) {
|
||||
if (await autoRefresh(e)) {
|
||||
await getProfileAll(e);
|
||||
return true;
|
||||
await getProfileAll(e)
|
||||
return true
|
||||
} else {
|
||||
e.reply("尚未获取任何角色数据");
|
||||
await profileHelp(e);
|
||||
e.reply('尚未获取任何角色数据')
|
||||
await profileHelp(e)
|
||||
}
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
|
||||
e.reply(`uid${uid} 已获取面板角色: ` + chars.join(", "));
|
||||
e.reply(`uid${uid} 已获取面板角色: ` + chars.join(', '))
|
||||
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
|
||||
/*
|
||||
* 面板帮助
|
||||
* */
|
||||
export async function profileHelp(e) {
|
||||
export async function profileHelp (e) {
|
||||
e.reply(segment.image(`file://${process.cwd()}/plugins/miao-plugin/resources/character/imgs/help.jpg`))
|
||||
return true;
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@ -1,59 +1,56 @@
|
||||
import lodash from "lodash";
|
||||
import { autoRefresh } from "./profile-common.js";
|
||||
import { Calc, Common, Format, Models, Profile } from "../../components/index.js";
|
||||
import { getArtis } from "./profile-artis.js";
|
||||
|
||||
const { Character } = Models;
|
||||
|
||||
export async function renderProfile(e, char, render, mode = "profile", params = {}) {
|
||||
import lodash from 'lodash'
|
||||
import { autoRefresh } from './profile-common.js'
|
||||
import { Calc, Common, Format, Profile } from '../../components/index.js'
|
||||
import { getArtis } from './profile-artis.js'
|
||||
|
||||
export async function renderProfile (e, char, render, mode = 'profile', params = {}) {
|
||||
let selfUser = await e.checkAuth({
|
||||
auth: "self"
|
||||
auth: 'self'
|
||||
})
|
||||
|
||||
let { uid } = e;
|
||||
let { uid } = e
|
||||
|
||||
if (['荧', '空', '主角', '旅行者'].includes(char.name)) {
|
||||
e.reply("暂不支持主角的面板信息查看");
|
||||
return true;
|
||||
e.reply('暂不支持主角的面板信息查看')
|
||||
return true
|
||||
}
|
||||
if (char.isCustom) {
|
||||
e.reply(`暂不支持自定义角色${char.name}的面板信息查看`);
|
||||
return true;
|
||||
e.reply(`暂不支持自定义角色${char.name}的面板信息查看`)
|
||||
return true
|
||||
}
|
||||
|
||||
let refresh = async () => {
|
||||
let refreshRet = await autoRefresh(e);
|
||||
let refreshRet = await autoRefresh(e)
|
||||
if (refreshRet) {
|
||||
await renderProfile(e, char, render, mode, params);
|
||||
await renderProfile(e, char, render, mode, params)
|
||||
}
|
||||
return refreshRet;
|
||||
return refreshRet
|
||||
}
|
||||
|
||||
let profile = await Profile.get(uid, char.id);
|
||||
let profile = await Profile.get(uid, char.id)
|
||||
|
||||
if (!profile) {
|
||||
if (await refresh()) {
|
||||
return true;
|
||||
return true
|
||||
} else {
|
||||
e.reply(`请确认${char.name}已展示在【游戏内】的角色展柜中,并打开了“显示角色详情”。然后请使用 #更新面板\n命令来获取${char.name}的面板详情`);
|
||||
e.reply(`请确认${char.name}已展示在【游戏内】的角色展柜中,并打开了“显示角色详情”。然后请使用 #更新面板\n命令来获取${char.name}的面板详情`)
|
||||
}
|
||||
return true;
|
||||
return true
|
||||
} else if (!profile.attr) {
|
||||
if (!await refresh()) {
|
||||
e.reply(`由于数据Api变更,请重新获取面板信息后查看`);
|
||||
e.reply('由于数据Api变更,请重新获取面板信息后查看')
|
||||
}
|
||||
return true;
|
||||
return true
|
||||
} else if (!['enka', 'input2', 'miao', 'miao-pre'].includes(profile.dataSource)) {
|
||||
if (!await refresh()) {
|
||||
e.reply(`由于数据格式升级,请重新获取面板信息后查看`);
|
||||
e.reply('由于数据格式升级,请重新获取面板信息后查看')
|
||||
}
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
|
||||
let a = profile.attr;
|
||||
let c = Format.comma,
|
||||
p = Format.pct;
|
||||
let a = profile.attr
|
||||
let c = Format.comma
|
||||
let p = Format.pct
|
||||
let attr = {
|
||||
hp: c(a.hp),
|
||||
hpPlus: c(a.hp - a.hpBase),
|
||||
@ -66,50 +63,48 @@ export async function renderProfile(e, char, render, mode = "profile", params =
|
||||
mastery: c(a.mastery),
|
||||
recharge: p(a.recharge),
|
||||
dmgBonus: p(Math.max(a.dmgBonus * 1 || 0, a.phyBonus * 1 || 0))
|
||||
};
|
||||
}
|
||||
|
||||
let { artis, totalMark, totalMarkClass, usefulMark } = getArtis(char.name, profile.artis)
|
||||
|
||||
let { artis, totalMark, totalMarkClass, usefulMark } = getArtis(char.name, profile.artis);
|
||||
|
||||
|
||||
let enemyLv = await selfUser.getCfg(`char.enemyLv`, 91);
|
||||
let dmgMsg = [], dmgData = [];
|
||||
let enemyLv = await selfUser.getCfg('char.enemyLv', 91)
|
||||
let dmgMsg = []
|
||||
let dmgData = []
|
||||
let dmgCalc = await Calc.calcData({
|
||||
profile,
|
||||
char,
|
||||
enemyLv,
|
||||
mode,
|
||||
...params
|
||||
});
|
||||
})
|
||||
if (dmgCalc && dmgCalc.ret) {
|
||||
lodash.forEach(dmgCalc.ret, (ds) => {
|
||||
ds.dmg = Format.comma(ds.dmg, 0);
|
||||
ds.avg = Format.comma(ds.avg, 0);
|
||||
dmgData.push(ds);
|
||||
ds.dmg = Format.comma(ds.dmg, 0)
|
||||
ds.avg = Format.comma(ds.avg, 0)
|
||||
dmgData.push(ds)
|
||||
})
|
||||
lodash.forEach(dmgCalc.msg, (msg) => {
|
||||
msg.replace(":", ":");
|
||||
dmgMsg.push(msg.split(":"))
|
||||
msg.replace(':', ':')
|
||||
dmgMsg.push(msg.split(':'))
|
||||
})
|
||||
}
|
||||
|
||||
if (mode === "dmg") {
|
||||
let basic = dmgCalc.dmgCfg.basicRet;
|
||||
if (mode === 'dmg') {
|
||||
let basic = dmgCalc.dmgCfg.basicRet
|
||||
lodash.forEach(dmgCalc.dmgRet, (row) => {
|
||||
lodash.forEach(row, (ds) => {
|
||||
ds.val = (ds.avg > basic.avg ? "+" : "") + Format.comma(ds.avg - basic.avg);
|
||||
ds.dmg = Format.comma(ds.dmg, 0);
|
||||
ds.avg = Format.comma(ds.avg, 0);
|
||||
|
||||
ds.val = (ds.avg > basic.avg ? '+' : '') + Format.comma(ds.avg - basic.avg)
|
||||
ds.dmg = Format.comma(ds.dmg, 0)
|
||||
ds.avg = Format.comma(ds.avg, 0)
|
||||
})
|
||||
});
|
||||
basic.dmg = Format.comma(basic.dmg);
|
||||
basic.avg = Format.comma(basic.avg);
|
||||
})
|
||||
basic.dmg = Format.comma(basic.dmg)
|
||||
basic.avg = Format.comma(basic.avg)
|
||||
}
|
||||
//渲染图像
|
||||
return await Common.render("character/detail", {
|
||||
// 渲染图像
|
||||
return await Common.render('character/detail', {
|
||||
save_id: uid,
|
||||
uid: uid,
|
||||
uid,
|
||||
data: profile,
|
||||
attr,
|
||||
cons: char.cons,
|
||||
@ -122,12 +117,12 @@ export async function renderProfile(e, char, render, mode = "profile", params =
|
||||
dmgCfg: dmgCalc.dmgCfg,
|
||||
artis,
|
||||
enemyLv,
|
||||
enemyName: dmgCalc.enemyName || "小宝",
|
||||
enemyName: dmgCalc.enemyName || '小宝',
|
||||
totalMark: c(totalMark, 1),
|
||||
totalMarkClass,
|
||||
usefulMark,
|
||||
talentMap: { a: "普攻", e: "战技", q: "爆发" },
|
||||
talentMap: { a: '普攻', e: '战技', q: '爆发' },
|
||||
bodyClass: `char-${char.name}`,
|
||||
mode,
|
||||
}, { e, render, scale: 1.6 });
|
||||
}
|
||||
mode
|
||||
}, { e, render, scale: 1.6 })
|
||||
}
|
||||
|
69
apps/help.js
@ -1,24 +1,22 @@
|
||||
import { Cfg } from "../components/index.js";
|
||||
import { segment } from "oicq";
|
||||
import lodash from "lodash";
|
||||
import { currentVersion, changelogs } from "../components/Changelog.js";
|
||||
import Common from "../components/Common.js";
|
||||
import fs from "fs";
|
||||
import { Cfg } from '../components/index.js'
|
||||
import lodash from 'lodash'
|
||||
import { currentVersion, changelogs } from '../components/Changelog.js'
|
||||
import Common from '../components/Common.js'
|
||||
import fs from 'fs'
|
||||
|
||||
const _path = process.cwd();
|
||||
const helpPath = `${_path}/plugins/miao-plugin/resources/help`;
|
||||
const _path = process.cwd()
|
||||
const helpPath = `${_path}/plugins/miao-plugin/resources/help`
|
||||
|
||||
export async function help(e, { render }) {
|
||||
|
||||
if (!/喵喵/.test(e.msg) && !Cfg.get("sys.help", false)) {
|
||||
return false;
|
||||
export async function help (e, { render }) {
|
||||
if (!/喵喵/.test(e.msg) && !Cfg.get('sys.help', false)) {
|
||||
return false
|
||||
}
|
||||
|
||||
let custom = {}, help = {};
|
||||
let custom = {}; let help = {}
|
||||
if (fs.existsSync(`${helpPath}/help-cfg.js`)) {
|
||||
help = await import(`file://${helpPath}/help-cfg.js?version=${new Date().getTime()}`);
|
||||
help = await import(`file://${helpPath}/help-cfg.js?version=${new Date().getTime()}`)
|
||||
} else if (fs.existsSync(`${helpPath}/help-list.js`)) {
|
||||
help = await import(`file://${helpPath}/help-list.js?version=${new Date().getTime()}`);
|
||||
help = await import(`file://${helpPath}/help-list.js?version=${new Date().getTime()}`)
|
||||
}
|
||||
|
||||
// 兼容一下旧字段
|
||||
@ -26,48 +24,47 @@ export async function help(e, { render }) {
|
||||
custom = {
|
||||
helpList: help.helpCfg,
|
||||
helpCfg: {}
|
||||
};
|
||||
}
|
||||
} else {
|
||||
custom = help;
|
||||
custom = help
|
||||
}
|
||||
|
||||
let def = await import(`file://${helpPath}/help-cfg_default.js?version=${new Date().getTime()}`);
|
||||
let def = await import(`file://${helpPath}/help-cfg_default.js?version=${new Date().getTime()}`)
|
||||
|
||||
let helpCfg = lodash.defaults(custom.helpCfg, def.helpCfg);
|
||||
let helpList = custom.helpList || def.helpList;
|
||||
let helpCfg = lodash.defaults(custom.helpCfg, def.helpCfg)
|
||||
let helpList = custom.helpList || def.helpList
|
||||
|
||||
let helpGroup = [];
|
||||
let helpGroup = []
|
||||
|
||||
lodash.forEach(helpList, (group) => {
|
||||
if (group.auth && group.auth === "master" && !e.isMaster) {
|
||||
return;
|
||||
if (group.auth && group.auth === 'master' && !e.isMaster) {
|
||||
return
|
||||
}
|
||||
|
||||
lodash.forEach(group.list, (help) => {
|
||||
let icon = help.icon * 1;
|
||||
let icon = help.icon * 1
|
||||
if (!icon) {
|
||||
help.css = `display:none`;
|
||||
help.css = 'display:none'
|
||||
} else {
|
||||
let x = (icon - 1) % 10, y = (icon - x - 1) / 10;
|
||||
help.css = `background-position:-${x * 50}px -${y * 50}px`;
|
||||
let x = (icon - 1) % 10; let y = (icon - x - 1) / 10
|
||||
help.css = `background-position:-${x * 50}px -${y * 50}px`
|
||||
}
|
||||
})
|
||||
|
||||
});
|
||||
helpGroup.push(group)
|
||||
})
|
||||
|
||||
helpGroup.push(group);
|
||||
});
|
||||
|
||||
return await Common.render("help/index", {
|
||||
return await Common.render('help/index', {
|
||||
helpCfg,
|
||||
helpGroup,
|
||||
element: 'default'
|
||||
}, { e, render, scale: 1.2 })
|
||||
}
|
||||
|
||||
export async function versionInfo(e, { render }) {
|
||||
return await Common.render("help/version-info", {
|
||||
export async function versionInfo (e, { render }) {
|
||||
return await Common.render('help/version-info', {
|
||||
currentVersion,
|
||||
changelogs,
|
||||
elem: "cryo",
|
||||
elem: 'cryo'
|
||||
}, { e, render, scale: 1.2 })
|
||||
}
|
||||
}
|
||||
|
119
apps/index.js
Normal file
@ -0,0 +1,119 @@
|
||||
import { wifeReg } from './character.js'
|
||||
|
||||
import { consStat, abyssPct, abyssTeam, uploadData } from './stat.js'
|
||||
import { wiki, calendar } from './wiki.js'
|
||||
import { help, versionInfo } from './help.js'
|
||||
import lodash from 'lodash'
|
||||
import { rule as adminRule, updateRes, sysCfg, updateMiaoPlugin, profileCfg } from './admin.js'
|
||||
|
||||
export {
|
||||
character,
|
||||
getProfile,
|
||||
wife,
|
||||
pokeWife,
|
||||
enemyLv,
|
||||
profileArtisList,
|
||||
getProfileAll,
|
||||
profileHelp,
|
||||
getOriginalPicture,
|
||||
uploadCharacterImg
|
||||
} from './character.js'
|
||||
|
||||
export {
|
||||
consStat,
|
||||
abyssPct,
|
||||
abyssTeam,
|
||||
wiki,
|
||||
updateRes,
|
||||
updateMiaoPlugin,
|
||||
sysCfg,
|
||||
help,
|
||||
versionInfo,
|
||||
calendar,
|
||||
profileCfg,
|
||||
uploadData
|
||||
}
|
||||
|
||||
let rule = {
|
||||
character: {
|
||||
reg: '^(#(.*)|#*(更新|录入)?(.*)(详细|详情|面板|面版|伤害[1-7]?)(更新)?)$',
|
||||
// reg: "noCheck",
|
||||
describe: '【#角色】角色详情'
|
||||
},
|
||||
uploadCharacterImg: {
|
||||
reg: '^#*(喵喵)?(上传|添加)(.+)(照片|写真|图片|图像)\\s*$',
|
||||
describe: '喵喵上传角色写真'
|
||||
},
|
||||
profileArtisList: {
|
||||
reg: '^#圣遗物列表\\s*(\\d{9})?$',
|
||||
describe: '【#角色】圣遗物列表'
|
||||
},
|
||||
getProfileAll: {
|
||||
reg: '^#(面板角色|角色面板|面板)(列表)?\\s*(\\d{9})?$',
|
||||
describe: '【#角色】查看当前已获取面板数据的角色列表'
|
||||
},
|
||||
profileHelp: {
|
||||
reg: '^#角色面板帮助$',
|
||||
describe: '【#角色】查看当前已获取面板数据的角色列表'
|
||||
},
|
||||
wife: {
|
||||
reg: wifeReg,
|
||||
describe: '【#角色】#老公 #老婆 查询'
|
||||
},
|
||||
pokeWife: {
|
||||
reg: '#poke#',
|
||||
describe: '【#角色】戳一戳'
|
||||
},
|
||||
getOriginalPicture: {
|
||||
reg: '^#?(获取|给我|我要|求|发|发下|发个|发一下)?原图(吧|呗)?$',
|
||||
describe: '【#原图】 回复角色卡片,可获取原图'
|
||||
},
|
||||
consStat: {
|
||||
reg: '^#(喵喵)?角色(持有|持有率|命座|命之座|.命)(分布|统计|持有|持有率)?$',
|
||||
describe: '【#统计】 #角色持有率 #角色5命统计'
|
||||
},
|
||||
abyssPct: {
|
||||
reg: '^#(喵喵)?深渊(第?.{1,2}层)?(角色)?(出场|使用)(率|统计)*$',
|
||||
describe: '【#统计】 #深渊出场率 #深渊12层出场率'
|
||||
},
|
||||
abyssTeam: {
|
||||
reg: '#深渊(组队|配队)',
|
||||
describe: '【#角色】 #深渊组队'
|
||||
},
|
||||
wiki: {
|
||||
reg: '^(#|喵喵)?.*(天赋|技能|命座|命之座|资料|照片|写真|图片|图像)$',
|
||||
describe: '【#资料】 #神里天赋 #夜兰命座'
|
||||
},
|
||||
help: {
|
||||
reg: '^#?(喵喵)?(命令|帮助|菜单|help|说明|功能|指令|使用说明)$',
|
||||
describe: '【#帮助】 #喵喵帮助'
|
||||
},
|
||||
getProfile: {
|
||||
reg: '^#(全部面板更新|更新全部面板|获取游戏角色详情|更新面板|面板更新)\\s*(\\d{9})?$',
|
||||
describe: '【#角色】 获取游戏橱窗详情数据'
|
||||
},
|
||||
enemyLv: {
|
||||
reg: '^#(敌人|怪物)等级\\s*\\d{1,3}\\s*$',
|
||||
describe: '【#角色】 设置伤害计算中目标敌人的等级'
|
||||
},
|
||||
versionInfo: {
|
||||
reg: '^#?喵喵版本$',
|
||||
describe: '【#帮助】 喵喵版本介绍'
|
||||
},
|
||||
calendar: {
|
||||
reg: '^(#|喵喵)+(日历|日历列表)$',
|
||||
describe: '【#日历】 活动日历'
|
||||
},
|
||||
uploadData: {
|
||||
reg: '^#上传(深渊|数据)+$'
|
||||
},
|
||||
...adminRule
|
||||
}
|
||||
|
||||
lodash.forEach(rule, (r) => {
|
||||
r.priority = r.priority || 50
|
||||
r.prehash = true
|
||||
r.hashMark = true
|
||||
})
|
||||
|
||||
export { rule }
|
413
apps/stat.js
@ -2,146 +2,144 @@
|
||||
* 胡桃数据库的统计
|
||||
*
|
||||
* */
|
||||
import { HutaoApi, Character } from "../components/models.js";
|
||||
import { Cfg, Data } from "../components/index.js";
|
||||
import lodash from "lodash";
|
||||
import fs from "fs";
|
||||
import Common from "../components/Common.js";
|
||||
import { HutaoApi, Character } from '../components/models.js'
|
||||
import { Cfg } from '../components/index.js'
|
||||
import lodash from 'lodash'
|
||||
import fs from 'fs'
|
||||
import Common from '../components/Common.js'
|
||||
|
||||
export async function consStat(e, { render }) {
|
||||
if (Cfg.isDisable(e, "wiki.abyss")) {
|
||||
return;
|
||||
export async function consStat (e, { render }) {
|
||||
if (Cfg.isDisable(e, 'wiki.abyss')) {
|
||||
return
|
||||
}
|
||||
|
||||
let consData = await HutaoApi.getCons();
|
||||
let consData = await HutaoApi.getCons()
|
||||
|
||||
if (!consData) {
|
||||
e.reply("角色持有数据获取失败,请稍后重试~");
|
||||
return true;
|
||||
e.reply('角色持有数据获取失败,请稍后重试~')
|
||||
return true
|
||||
}
|
||||
|
||||
let msg = e.msg;
|
||||
let msg = e.msg
|
||||
|
||||
let mode = /持有/.test(msg) ? "char" : "cons";
|
||||
let mode = /持有/.test(msg) ? 'char' : 'cons'
|
||||
|
||||
let conNum = -1;
|
||||
if (mode === "cons") {
|
||||
let conNum = -1
|
||||
if (mode === 'cons') {
|
||||
lodash.forEach([/0|零/, /1|一/, /2|二/, /3|三/, /4|四/, /5|五/, /6|六|满/], (reg, idx) => {
|
||||
if (reg.test(msg)) {
|
||||
conNum = idx;
|
||||
return false;
|
||||
conNum = idx
|
||||
return false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (!consData && !consData.data) {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
|
||||
let data = consData.data;
|
||||
let data = consData.data
|
||||
|
||||
let Lumine = lodash.filter(data, (ds) => ds.avatar === 10000007)[0] || {},
|
||||
Aether = lodash.filter(data, (ds) => ds.avatar === 10000005)[0] || {};
|
||||
let Lumine = lodash.filter(data, (ds) => ds.avatar === 10000007)[0] || {}
|
||||
let Aether = lodash.filter(data, (ds) => ds.avatar === 10000005)[0] || {}
|
||||
|
||||
Lumine.holdingRate = (1 - Aether.holdingRate) || Lumine.holdingRate;
|
||||
Lumine.holdingRate = (1 - Aether.holdingRate) || Lumine.holdingRate
|
||||
|
||||
let ret = [];
|
||||
let ret = []
|
||||
|
||||
lodash.forEach(data, (ds) => {
|
||||
let char = Character.get(ds.avatar);
|
||||
let char = Character.get(ds.avatar)
|
||||
|
||||
let data = {
|
||||
name: char.name || ds.avatar,
|
||||
star: char.star || 3,
|
||||
hold: ds.holdingRate
|
||||
};
|
||||
}
|
||||
|
||||
if (mode === "char") {
|
||||
if (mode === 'char') {
|
||||
data.cons = lodash.map(ds.rate, (c) => {
|
||||
c.value = c.value * ds.holdingRate;
|
||||
return c;
|
||||
});
|
||||
c.value = c.value * ds.holdingRate
|
||||
return c
|
||||
})
|
||||
} else {
|
||||
data.cons = ds.rate
|
||||
}
|
||||
data.cons = lodash.sortBy(data.cons, ['id'])
|
||||
|
||||
|
||||
ret.push(data);
|
||||
});
|
||||
ret.push(data)
|
||||
})
|
||||
|
||||
if (conNum > -1) {
|
||||
ret = lodash.sortBy(ret, [`cons[${conNum}].value`]);
|
||||
ret.reverse();
|
||||
ret = lodash.sortBy(ret, [`cons[${conNum}].value`])
|
||||
ret.reverse()
|
||||
} else {
|
||||
ret = lodash.sortBy(ret, ['hold']);
|
||||
ret = lodash.sortBy(ret, ['hold'])
|
||||
}
|
||||
//渲染图像
|
||||
return await Common.render("stat/character", {
|
||||
// 渲染图像
|
||||
return await Common.render('stat/character', {
|
||||
chars: ret,
|
||||
abbr: Character.getAbbr(),
|
||||
mode: mode,
|
||||
mode,
|
||||
conNum,
|
||||
lastUpdate: consData.lastUpdate,
|
||||
pct: function (num) {
|
||||
return (num * 100).toFixed(2);
|
||||
},
|
||||
}, { e, render, scale: 1.5 });
|
||||
return (num * 100).toFixed(2)
|
||||
}
|
||||
}, { e, render, scale: 1.5 })
|
||||
}
|
||||
|
||||
export async function abyssPct(e, { render }) {
|
||||
|
||||
if (Cfg.isDisable(e, "wiki.abyss")) {
|
||||
return;
|
||||
export async function abyssPct (e, { render }) {
|
||||
if (Cfg.isDisable(e, 'wiki.abyss')) {
|
||||
return
|
||||
}
|
||||
|
||||
let mode = /使用/.test(e.msg) ? "use" : "pct",
|
||||
modeName, abyssData, modeMulti = 1;
|
||||
let mode = /使用/.test(e.msg) ? 'use' : 'pct'
|
||||
let modeName
|
||||
let abyssData
|
||||
let modeMulti = 1
|
||||
|
||||
if (mode === "use") {
|
||||
modeName = "使用率";
|
||||
abyssData = await HutaoApi.getAbyssUse();
|
||||
if (mode === 'use') {
|
||||
modeName = '使用率'
|
||||
abyssData = await HutaoApi.getAbyssUse()
|
||||
} else {
|
||||
modeName = "出场率";
|
||||
abyssData = await HutaoApi.getAbyssPct();
|
||||
modeMulti = 8;
|
||||
modeName = '出场率'
|
||||
abyssData = await HutaoApi.getAbyssPct()
|
||||
modeMulti = 8
|
||||
}
|
||||
|
||||
|
||||
if (!abyssData) {
|
||||
e.reply(`深渊${modeName}数据获取失败,请稍后重试~`);
|
||||
return true;
|
||||
e.reply(`深渊${modeName}数据获取失败,请稍后重试~`)
|
||||
return true
|
||||
}
|
||||
|
||||
let ret = [], chooseFloor = -1, msg = e.msg;
|
||||
let ret = []
|
||||
let chooseFloor = -1
|
||||
let msg = e.msg
|
||||
|
||||
const floorName = {
|
||||
"12": "十二层",
|
||||
"11": "十一层",
|
||||
"10": "十层",
|
||||
"9": "九层"
|
||||
};
|
||||
12: '十二层',
|
||||
11: '十一层',
|
||||
10: '十层',
|
||||
9: '九层'
|
||||
}
|
||||
|
||||
// 匹配深渊楼层信息
|
||||
lodash.forEach(floorName, (cn, num) => {
|
||||
let reg = new RegExp(`${cn}|${num}`);
|
||||
let reg = new RegExp(`${cn}|${num}`)
|
||||
if (reg.test(msg)) {
|
||||
chooseFloor = num;
|
||||
return false;
|
||||
chooseFloor = num
|
||||
return false
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
let data = abyssData.data;
|
||||
data = lodash.sortBy(data, "floor");
|
||||
data = data.reverse();
|
||||
let data = abyssData.data
|
||||
data = lodash.sortBy(data, 'floor')
|
||||
data = data.reverse()
|
||||
|
||||
lodash.forEach(data, (floorData) => {
|
||||
let floor = {
|
||||
floor: floorData.floor,
|
||||
};
|
||||
let avatars = [];
|
||||
let avatars = []
|
||||
lodash.forEach(floorData.avatarUsage, (ds) => {
|
||||
let char = Character.get(ds.id);
|
||||
let char = Character.get(ds.id)
|
||||
if (char) {
|
||||
avatars.push({
|
||||
name: char.name,
|
||||
@ -150,155 +148,155 @@ export async function abyssPct(e, { render }) {
|
||||
})
|
||||
}
|
||||
})
|
||||
avatars = lodash.sortBy(avatars, "value", ["asc"]);
|
||||
avatars.reverse();
|
||||
avatars = lodash.sortBy(avatars, 'value', ['asc'])
|
||||
avatars.reverse()
|
||||
if (chooseFloor === -1) {
|
||||
avatars = avatars.slice(0, 14);
|
||||
avatars = avatars.slice(0, 14)
|
||||
}
|
||||
|
||||
ret.push({
|
||||
floor: floorData.floor,
|
||||
avatars
|
||||
});
|
||||
})
|
||||
})
|
||||
|
||||
return await Common.render("stat/abyss-pct", {
|
||||
return await Common.render('stat/abyss-pct', {
|
||||
abyss: ret,
|
||||
floorName,
|
||||
chooseFloor,
|
||||
mode,
|
||||
modeName,
|
||||
lastUpdate: abyssData.lastUpdate
|
||||
}, { e, render, scale: 1.5 });
|
||||
}, { e, render, scale: 1.5 })
|
||||
}
|
||||
|
||||
async function getTalentData(e, isUpdate = false) {
|
||||
|
||||
async function getTalentData (e, isUpdate = false) {
|
||||
// 技能查询缓存
|
||||
let cachePath = `./data/cache/`;
|
||||
let cachePath = './data/cache/'
|
||||
if (!fs.existsSync(cachePath)) {
|
||||
fs.mkdirSync(cachePath);
|
||||
fs.mkdirSync(cachePath)
|
||||
}
|
||||
cachePath += "talentList/";
|
||||
cachePath += 'talentList/'
|
||||
if (!fs.existsSync(cachePath)) {
|
||||
fs.mkdirSync(cachePath);
|
||||
fs.mkdirSync(cachePath)
|
||||
}
|
||||
|
||||
let avatarRet = [];
|
||||
let uid = e.selfUser.uid;
|
||||
let avatarRet = []
|
||||
let uid = e.selfUser.uid
|
||||
|
||||
let hasCache = await redis.get(`cache:uid-talent-new:${uid}`);
|
||||
let hasCache = await redis.get(`cache:uid-talent-new:${uid}`)
|
||||
if (hasCache) {
|
||||
// 有缓存优先使用缓存
|
||||
let jsonRet = fs.readFileSync(cachePath + `${uid}.json`, "utf8");
|
||||
avatarRet = JSON.parse(jsonRet);
|
||||
return avatarRet;
|
||||
let jsonRet = fs.readFileSync(cachePath + `${uid}.json`, 'utf8')
|
||||
avatarRet = JSON.parse(jsonRet)
|
||||
return avatarRet
|
||||
} else if (!isUpdate) {
|
||||
e.noReplyTalentList = true;
|
||||
await YunzaiApps.mysInfo.talentList(e);
|
||||
return await getTalentData(e, true);
|
||||
e.noReplyTalentList = true
|
||||
await global.YunzaiApps.mysInfo.talentList(e)
|
||||
return await getTalentData(e, true)
|
||||
}
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
|
||||
export async function abyssTeam(e, { render }) {
|
||||
|
||||
export async function abyssTeam (e, { render }) {
|
||||
if (Common.todoV3(e)) {
|
||||
return true
|
||||
}
|
||||
let MysApi = await e.getMysApi({
|
||||
auth: "cookie", // 所有用户均可查询
|
||||
targetType: "self", // 被查询用户可以是任意用户
|
||||
cookieType: "self" // cookie可以是任意可用cookie
|
||||
});
|
||||
auth: 'cookie', // 所有用户均可查询
|
||||
targetType: 'self', // 被查询用户可以是任意用户
|
||||
cookieType: 'self' // cookie可以是任意可用cookie
|
||||
})
|
||||
|
||||
if (!MysApi || !MysApi.selfUser || !MysApi.selfUser.uid) {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
|
||||
let abyssData = await HutaoApi.getAbyssTeam();
|
||||
let abyssData = await HutaoApi.getAbyssTeam()
|
||||
if (!abyssData || !abyssData.data) {
|
||||
e.reply("深渊组队数据获取失败,请稍后重试~");
|
||||
return true;
|
||||
e.reply('深渊组队数据获取失败,请稍后重试~')
|
||||
return true
|
||||
}
|
||||
abyssData = abyssData.data;
|
||||
let talentData = await getTalentData(e);
|
||||
abyssData = abyssData.data
|
||||
let talentData = await getTalentData(e)
|
||||
if (!talentData || talentData.length === 0) {
|
||||
e.reply("暂时未能获得角色的练度信息,请使用【#练度统计】命令尝试手工获取...");
|
||||
return true;
|
||||
e.reply('暂时未能获得角色的练度信息,请使用【#练度统计】命令尝试手工获取...')
|
||||
return true
|
||||
}
|
||||
|
||||
let avatarRet = {};
|
||||
let data = {};
|
||||
let avatarRet = {}
|
||||
let data = {}
|
||||
|
||||
let noAvatar = {};
|
||||
let noAvatar = {}
|
||||
|
||||
lodash.forEach(talentData, (avatar) => {
|
||||
avatarRet[avatar.id] = Math.min(avatar.level, avatar.weapon_level) * 100 + Math.max(avatar.a_original, avatar.e_original, avatar.q_original) * 1000
|
||||
});
|
||||
})
|
||||
|
||||
let getTeamCfg = (str) => {
|
||||
let teams = str.split(",");
|
||||
teams.sort();
|
||||
let teamMark = 0;
|
||||
let teams = str.split(',')
|
||||
teams.sort()
|
||||
let teamMark = 0
|
||||
lodash.forEach(teams, (a) => {
|
||||
if (!avatarRet[a]) {
|
||||
teamMark = -1;
|
||||
noAvatar[a] = true;
|
||||
teamMark = -1
|
||||
noAvatar[a] = true
|
||||
}
|
||||
if (teamMark !== -1) {
|
||||
teamMark += avatarRet[a] * 1;
|
||||
teamMark += avatarRet[a] * 1
|
||||
}
|
||||
})
|
||||
if (teamMark === -1) {
|
||||
teamMark = 1;
|
||||
teamMark = 1
|
||||
}
|
||||
|
||||
return {
|
||||
key: teams.join(","),
|
||||
key: teams.join(','),
|
||||
mark: teamMark
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
let hasSame = function (team1, team2) {
|
||||
for (let idx = 0; idx < team1.length; idx++) {
|
||||
if (team2.includes(team1[idx])) {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
|
||||
lodash.forEach(abyssData, (ds) => {
|
||||
let floor = ds.level.floor;
|
||||
let floor = ds.level.floor
|
||||
if (!data[floor]) {
|
||||
data[floor] = {
|
||||
up: {},
|
||||
down: {},
|
||||
teams: []
|
||||
};
|
||||
}
|
||||
}
|
||||
lodash.forEach(ds.teams, (ds) => {
|
||||
lodash.forEach(['up', 'down'], (halfKey) => {
|
||||
let teamCfg = getTeamCfg(ds.id[`${halfKey}Half`]);
|
||||
let teamCfg = getTeamCfg(ds.id[`${halfKey}Half`])
|
||||
if (teamCfg) {
|
||||
if (!data[floor][halfKey][teamCfg.key]) {
|
||||
data[floor][halfKey][teamCfg.key] = {
|
||||
count: 0,
|
||||
mark: 0,
|
||||
hasTeam: teamCfg.mark > 1
|
||||
};
|
||||
}
|
||||
}
|
||||
data[floor][halfKey][teamCfg.key].count += ds.value;
|
||||
data[floor][halfKey][teamCfg.key].mark += ds.value * teamCfg.mark;
|
||||
data[floor][halfKey][teamCfg.key].count += ds.value
|
||||
data[floor][halfKey][teamCfg.key].mark += ds.value * teamCfg.mark
|
||||
}
|
||||
|
||||
})
|
||||
});
|
||||
})
|
||||
|
||||
let temp = [];
|
||||
let temp = []
|
||||
lodash.forEach(['up', 'down'], (halfKey) => {
|
||||
lodash.forEach(data[floor][halfKey], (ds, team) => {
|
||||
temp.push({
|
||||
team,
|
||||
teamArr: team.split(","),
|
||||
teamArr: team.split(','),
|
||||
half: halfKey,
|
||||
count: ds.count,
|
||||
mark: ds.mark,
|
||||
@ -306,67 +304,66 @@ export async function abyssTeam(e, { render }) {
|
||||
hasTeam: ds.hasTeam
|
||||
})
|
||||
})
|
||||
temp = lodash.sortBy(temp, "mark")
|
||||
data[floor].teams = temp.reverse();
|
||||
});
|
||||
});
|
||||
temp = lodash.sortBy(temp, 'mark')
|
||||
data[floor].teams = temp.reverse()
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
let ret = {};
|
||||
let ret = {}
|
||||
|
||||
lodash.forEach(data, (floorData, floor) => {
|
||||
ret[floor] = {}
|
||||
let ds = ret[floor];
|
||||
let ds = ret[floor]
|
||||
lodash.forEach(floorData.teams, (t1) => {
|
||||
if (t1.mark2 <= 0) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
lodash.forEach(floorData.teams, (t2) => {
|
||||
if (t1.mark2 <= 0) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
if (t1.half === t2.half || t2.mark2 <= 0) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
let teamKey = t1.half === "up" ? (t1.team + "+" + t2.team) : (t2.team + "+" + t1.team);
|
||||
let teamKey = t1.half === 'up' ? (t1.team + '+' + t2.team) : (t2.team + '+' + t1.team)
|
||||
if (ds[teamKey]) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
if (hasSame(t1.teamArr, t2.teamArr)) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
ds[teamKey] = {
|
||||
up: t1.half === "up" ? t1 : t2,
|
||||
down: t1.half === "up" ? t2 : t1,
|
||||
up: t1.half === 'up' ? t1 : t2,
|
||||
down: t1.half === 'up' ? t2 : t1,
|
||||
count: Math.min(t1.count, t2.count),
|
||||
mark: t1.hasTeam && t2.hasTeam ? t1.mark + t2.mark : t1.count + t2.count // 如果不存在组队则进行评分惩罚
|
||||
}
|
||||
t1.mark2--;
|
||||
t2.mark2--;
|
||||
return false;
|
||||
});
|
||||
t1.mark2--
|
||||
t2.mark2--
|
||||
return false
|
||||
})
|
||||
if (lodash.keys(ds).length >= 20) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
lodash.forEach(ret, (ds, floor) => {
|
||||
ds = lodash.sortBy(lodash.values(ds), 'mark');
|
||||
ds = ds.reverse();
|
||||
ds = ds.slice(0, 4);
|
||||
|
||||
lodash.forEach(ds, (team) => {
|
||||
team.up.teamArr = Character.sortIds(team.up.teamArr);
|
||||
team.down.teamArr = Character.sortIds(team.down.teamArr);
|
||||
})
|
||||
|
||||
ret[floor] = ds;
|
||||
})
|
||||
|
||||
let avatarMap = {};
|
||||
lodash.forEach(ret, (ds, floor) => {
|
||||
ds = lodash.sortBy(lodash.values(ds), 'mark')
|
||||
ds = ds.reverse()
|
||||
ds = ds.slice(0, 4)
|
||||
|
||||
lodash.forEach(ds, (team) => {
|
||||
team.up.teamArr = Character.sortIds(team.up.teamArr)
|
||||
team.down.teamArr = Character.sortIds(team.down.teamArr)
|
||||
})
|
||||
|
||||
ret[floor] = ds
|
||||
})
|
||||
|
||||
let avatarMap = {}
|
||||
|
||||
lodash.forEach(talentData, (ds) => {
|
||||
avatarMap[ds.id] = {
|
||||
@ -379,79 +376,79 @@ export async function abyssTeam(e, { render }) {
|
||||
})
|
||||
|
||||
lodash.forEach(noAvatar, (d, id) => {
|
||||
let char = Character.get(id);
|
||||
let char = Character.get(id)
|
||||
avatarMap[id] = {
|
||||
id,
|
||||
name: char.name,
|
||||
star: char.star,
|
||||
level: 0,
|
||||
cons: 0,
|
||||
cons: 0
|
||||
}
|
||||
})
|
||||
|
||||
return await Common.render("stat/abyss-team", {
|
||||
return await Common.render('stat/abyss-team', {
|
||||
teams: ret,
|
||||
avatars: avatarMap,
|
||||
}, { e, render, scale: 1.5 });
|
||||
avatars: avatarMap
|
||||
}, { e, render, scale: 1.5 })
|
||||
}
|
||||
|
||||
export async function uploadData(e) {
|
||||
export async function uploadData (e) {
|
||||
let MysApi = await e.getMysApi({
|
||||
auth: "cookie",
|
||||
targetType: "self",
|
||||
cookieType: "self",
|
||||
action: "获取信息"
|
||||
});
|
||||
if (!MysApi) return;
|
||||
let ret = {};
|
||||
let uid = e.selfUser.uid;
|
||||
auth: 'cookie',
|
||||
targetType: 'self',
|
||||
cookieType: 'self',
|
||||
action: '获取信息'
|
||||
})
|
||||
if (!MysApi) return
|
||||
let ret = {}
|
||||
let uid = e.selfUser.uid
|
||||
try {
|
||||
let resDetail = await MysApi.getCharacter();
|
||||
let resAbyss = await MysApi.getSpiralAbyss(1);
|
||||
//Data.writeJson('/test-data', 'abyss.json', resAbyss);
|
||||
let resDetail = await MysApi.getCharacter()
|
||||
let resAbyss = await MysApi.getSpiralAbyss(1)
|
||||
// Data.writeJson('/test-data', 'abyss.json', resAbyss);
|
||||
if (!resDetail || !resAbyss || !resDetail.avatars || resDetail.avatars.length <= 3) {
|
||||
e.reply("角色信息获取失败");
|
||||
return true;
|
||||
e.reply('角色信息获取失败')
|
||||
return true
|
||||
}
|
||||
delete resDetail._res;
|
||||
delete resAbyss._res;
|
||||
delete resDetail._res
|
||||
delete resAbyss._res
|
||||
ret = await HutaoApi.uploadData({
|
||||
uid,
|
||||
resDetail,
|
||||
resAbyss
|
||||
});
|
||||
})
|
||||
} catch (err) {
|
||||
// console.log(err);
|
||||
}
|
||||
if (ret && ret.retcode === 0) {
|
||||
let msg = [`uid:${uid}本次深渊记录上传成功~ \n多谢支持,φ(>ω<*) 喵~`];
|
||||
let msg = [`uid:${uid}本次深渊记录上传成功~ \n多谢支持,φ(>ω<*) 喵~`]
|
||||
if (ret.data) {
|
||||
let addMsg = function (title, ds) {
|
||||
if (!ds && !ds.avatarId && !ds.percent) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
let char = Character.get(ds.avatarId);
|
||||
title = `${title}:${char.name}(${(ds.value / 10000).toFixed(1)}W)`;
|
||||
let char = Character.get(ds.avatarId)
|
||||
title = `${title}:${char.name}(${(ds.value / 10000).toFixed(1)}W)`
|
||||
|
||||
let pct = (percent, name) => {
|
||||
if (percent < 0.2) {
|
||||
title += `,少于${(Math.max(0.1, 100 - percent * 100)).toFixed(1)}%的${name}`;
|
||||
title += `,少于${(Math.max(0.1, 100 - percent * 100)).toFixed(1)}%的${name}`
|
||||
} else {
|
||||
title += `,超过${(Math.min(99.9, percent * 100)).toFixed(1)}%的${name}`;
|
||||
title += `,超过${(Math.min(99.9, percent * 100)).toFixed(1)}%的${name}`
|
||||
}
|
||||
}
|
||||
pct(ds.percent, char.name);
|
||||
pct(ds.percentTotal, "总记录");
|
||||
msg.push(title);
|
||||
pct(ds.percent, char.name)
|
||||
pct(ds.percentTotal, '总记录')
|
||||
msg.push(title)
|
||||
}
|
||||
msg.push("当前数据记录:");
|
||||
addMsg("【最强一击】", ret.data.damage || {});
|
||||
addMsg("【承受伤害】", ret.data.takeDamage || {});
|
||||
msg.push("排行会随时间而更新,数据仅供参考~");
|
||||
msg.push('当前数据记录:')
|
||||
addMsg('【最强一击】', ret.data.damage || {})
|
||||
addMsg('【承受伤害】', ret.data.takeDamage || {})
|
||||
msg.push('排行会随时间而更新,数据仅供参考~')
|
||||
}
|
||||
e.reply(msg.join("\n"))
|
||||
e.reply(msg.join('\n'))
|
||||
} else {
|
||||
e.reply(`${ret.message || "上传失败"},请稍后重试...`);
|
||||
e.reply(`${ret.message || '上传失败'},请稍后重试...`)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
88
apps/wiki.js
@ -1,93 +1,91 @@
|
||||
import { segment } from "oicq";
|
||||
import { Character } from "../components/models.js";
|
||||
import lodash from "lodash";
|
||||
import Calendar from "../components/Calendar.js";
|
||||
import Common from "../components/Common.js";
|
||||
import { Cfg } from "../components/index.js";
|
||||
|
||||
import { segment } from 'oicq'
|
||||
import { Character } from '../components/models.js'
|
||||
import lodash from 'lodash'
|
||||
import Calendar from '../components/Calendar.js'
|
||||
import Common from '../components/Common.js'
|
||||
import { Cfg } from '../components/index.js'
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
let action = {
|
||||
wiki: {
|
||||
keyword: "命座|天赋|技能|资料|照片|写真|图片|插画"
|
||||
keyword: '命座|天赋|技能|资料|照片|写真|图片|插画'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export async function wiki(e, { render }) {
|
||||
|
||||
export async function wiki (e, { render }) {
|
||||
if (!e.msg) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
|
||||
let reg = /#?(.+)(命座|命之座|天赋|技能|资料|照片|写真|图片|图像)$/, msg = e.msg;
|
||||
let ret = reg.exec(msg);
|
||||
let reg = /#?(.+)(命座|命之座|天赋|技能|资料|照片|写真|图片|图像)$/; let msg = e.msg
|
||||
let ret = reg.exec(msg)
|
||||
|
||||
if (!ret || !ret[1] || !ret[2]) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
|
||||
let mode = "talent";
|
||||
let mode = 'talent'
|
||||
if (/命/.test(ret[2])) {
|
||||
mode = "cons";
|
||||
mode = 'cons'
|
||||
} else if (/图|画|写真|照片/.test(ret[2])) {
|
||||
mode = "pic";
|
||||
mode = 'pic'
|
||||
}
|
||||
|
||||
if ((mode === "pic" && Common.isDisable(e, "wiki.pic"))
|
||||
|| (mode !== "pic" && Common.isDisable("wiki.wiki"))) {
|
||||
return;
|
||||
if ((mode === 'pic' && Common.isDisable(e, 'wiki.pic')) ||
|
||||
(mode !== 'pic' && Common.isDisable('wiki.wiki'))) {
|
||||
return
|
||||
}
|
||||
|
||||
let char = Character.get(ret[1]);
|
||||
let char = Character.get(ret[1])
|
||||
if (!char) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
|
||||
if (mode === "pic") {
|
||||
let img = char.getCardImg(Cfg.get("char.se", false), false);
|
||||
if (mode === 'pic') {
|
||||
let img = char.getCardImg(Cfg.get('char.se', false), false)
|
||||
if (img && img.img) {
|
||||
e.reply(segment.image(process.cwd() + "/plugins/miao-plugin/resources/" + img.img));
|
||||
e.reply(segment.image(process.cwd() + '/plugins/miao-plugin/resources/' + img.img))
|
||||
} else {
|
||||
e.reply("暂无图片");
|
||||
e.reply('暂无图片')
|
||||
}
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
|
||||
if (char.isCustom) {
|
||||
e.reply("暂不支持自定义角色");
|
||||
return true;
|
||||
e.reply('暂不支持自定义角色')
|
||||
return true
|
||||
}
|
||||
|
||||
return await Common.render("wiki/character", {
|
||||
save_id: "天赋" + char.name,
|
||||
return await Common.render('wiki/character', {
|
||||
save_id: '天赋' + char.name,
|
||||
...char,
|
||||
mode,
|
||||
line: getLineData(char),
|
||||
_char: `/meta/character/${char.name}/`,
|
||||
}, { e, render, scale: 1 });
|
||||
_char: `/meta/character/${char.name}/`
|
||||
}, { e, render, scale: 1 })
|
||||
}
|
||||
|
||||
const getLineData = function (data) {
|
||||
let ret = [];
|
||||
lodash.forEach(data.lvStat.detail["90"], (num, idx) => {
|
||||
let ret = []
|
||||
lodash.forEach(data.lvStat.detail['90'], (num, idx) => {
|
||||
ret.push({
|
||||
num,
|
||||
label: data.lvStat.stat[idx]
|
||||
})
|
||||
})
|
||||
|
||||
return ret;
|
||||
return ret
|
||||
}
|
||||
|
||||
export async function calendar(e, { render }) {
|
||||
let calData = await Calendar.get();
|
||||
let mode = "calendar";
|
||||
export async function calendar (e, { render }) {
|
||||
let calData = await Calendar.get()
|
||||
let mode = 'calendar'
|
||||
if (/(日历列表|活动)$/.test(e.msg)) {
|
||||
mode = "list";
|
||||
mode = 'list'
|
||||
}
|
||||
|
||||
return await Common.render("wiki/calendar", {
|
||||
return await Common.render('wiki/calendar', {
|
||||
...calData,
|
||||
displayMode: mode,
|
||||
}, { e, render, scale: 1.1 });
|
||||
}
|
||||
displayMode: mode
|
||||
}, { e, render, scale: 1.1 })
|
||||
}
|
||||
|
@ -1,195 +0,0 @@
|
||||
//技能列表,配置了cookie能查
|
||||
import fs from "fs";
|
||||
import lodash from "lodash";
|
||||
import common from "../../../lib/common.js";
|
||||
|
||||
import { segment } from "oicq";
|
||||
|
||||
export async function talentList(e, { render }) {
|
||||
//缓存时间,单位小时
|
||||
let cacheCd = 6;
|
||||
|
||||
let msg = e.msg.replace("#", "").trim();
|
||||
if (msg === "角色统计" || msg === "武器统计") {
|
||||
//暂时避让一下抽卡分析的关键词
|
||||
return false;
|
||||
}
|
||||
|
||||
let MysApi = await getMysApi(e);
|
||||
if (!MysApi) return true;
|
||||
let uid = MysApi.targetUid;
|
||||
|
||||
//禁止重复获取
|
||||
if (skillLoading[e.user_id]) {
|
||||
e.reply("角色数据获取中,请耐心等待...");
|
||||
setTimeout(() => {
|
||||
if (skillLoading[e.user_id]) delete skillLoading[e.user_id];
|
||||
}, 60000);
|
||||
return;
|
||||
}
|
||||
|
||||
const displayMode = /(角色|武器|练度)/.test(e.msg) ? "weapon" : "talent";
|
||||
|
||||
//四星五星
|
||||
let star = 0;
|
||||
if (/(四|4)/.test(msg)) star = 4;
|
||||
if (/(五|5)/.test(msg)) star = 5;
|
||||
|
||||
// 技能查询缓存
|
||||
let cachePath = `./data/cache/`;
|
||||
if (!fs.existsSync(cachePath)) {
|
||||
fs.mkdirSync(cachePath);
|
||||
}
|
||||
cachePath += "talentList/";
|
||||
if (!fs.existsSync(cachePath)) {
|
||||
fs.mkdirSync(cachePath);
|
||||
}
|
||||
|
||||
let avatarRet = [];
|
||||
|
||||
let hasCache = await redis.get(`cache:uid-talent-new:${uid}`); // 由于数据结构改变,临时修改一下键值,防止命中历史缓存导致展示错误
|
||||
if (hasCache && !/force/.test(e.msg)) {
|
||||
// 有缓存优先使用缓存
|
||||
let jsonRet = fs.readFileSync(cachePath + `${uid}.json`, "utf8");
|
||||
avatarRet = JSON.parse(jsonRet);
|
||||
} else {
|
||||
|
||||
skillLoading[e.user_id] = true;
|
||||
let resIndex = await MysApi.getCharacter();
|
||||
if (!resIndex) {
|
||||
delete skillLoading[e.user_id];
|
||||
return true;
|
||||
}
|
||||
|
||||
let avatarData = resIndex && resIndex.avatars || [];
|
||||
|
||||
// let skillRet = [], skill = [];
|
||||
//配置了cookie的才去获取技能
|
||||
// if (NoteCookie[e.user_id]) {
|
||||
|
||||
let skillRet = [], skill = [];
|
||||
//配置了完整cookie的才去获取技能
|
||||
if (NoteCookie[e.user_id] && NoteCookie[e.user_id].cookie.includes("cookie_token")) {
|
||||
e.reply("角色数据获取中,请耐心等待...");
|
||||
//批量获取技能数据,分组10个id一次,延迟100ms
|
||||
let num = 10, ms = 100;
|
||||
let avatarArr = lodash.chunk(avatarData, num);
|
||||
for (let val of avatarArr) {
|
||||
for (let avatar of val) {
|
||||
skillRet.push(getSkill(e, uid, avatar, MysApi));
|
||||
}
|
||||
skillRet = await Promise.all(skillRet);
|
||||
//过滤没有获取成功的
|
||||
skillRet.filter(item => item.a);
|
||||
skillRet = skillRet.filter(item => item.a);
|
||||
|
||||
await common.sleep(ms);
|
||||
}
|
||||
skill = lodash.keyBy(skillRet, "id");
|
||||
}
|
||||
|
||||
// 天赋等级背景
|
||||
const talentLvMap = '0,1,1,1,2,2,3,3,3,4,5'.split(',')
|
||||
|
||||
// 根据每日素材构建 角色->素材的映射关系
|
||||
let charTalentMap = {};
|
||||
daily.forEach((weekCfg, week) => {
|
||||
lodash.forIn(weekCfg[0], (talentCfg, talentName) => {
|
||||
talentCfg[1].forEach((charName) => {
|
||||
charTalentMap[charName] = { name: talentName, week: [3, 1, 2][week] };
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
for (let idx in avatarData) {
|
||||
let curr = avatarData[idx];
|
||||
let avatar = lodash.pick(curr, "id,name,rarity,level,rarity,fetter".split(","));
|
||||
// 埃洛伊rarity是105...
|
||||
avatar.rarity = avatar.rarity > 5 ? 5 : avatar.rarity;
|
||||
let weapon = curr.weapon || {};
|
||||
"name,level,rarity,affix_level".split(",").forEach((idx) => {
|
||||
avatar[`weapon_${idx}`] = curr.weapon[idx];
|
||||
});
|
||||
avatar.cons = curr.actived_constellation_num;
|
||||
if (avatar.id == 10000007) {
|
||||
avatar.name = "荧";
|
||||
} else if (avatar.id == 10000005) {
|
||||
avatar.name = "空";
|
||||
} else {
|
||||
let talent = charTalentMap[avatar.name] || {};
|
||||
avatar.talent = talent.name;
|
||||
avatar.talentWeek = talent.week; //`${talent.week}${talent.week + 3}`;
|
||||
}
|
||||
|
||||
let skillRet = skill[avatar.id] || {};
|
||||
const talentConsCfg = { a: 0, e: 3, q: 5 };
|
||||
|
||||
lodash.forIn(talentConsCfg, (consLevel, key) => {
|
||||
let talent = skillRet[key] || {};
|
||||
// 天赋等级
|
||||
avatar[key] = talent.level_current || '-';
|
||||
// 是否有命座加成
|
||||
avatar[`${key}_plus`] = talent.level_current > talent.level_original;
|
||||
// 天赋书星级
|
||||
avatar[`${key}_lvl`] = talentLvMap[talent.level_original * 1];
|
||||
avatar[`${key}_original`] = talent.level_original * 1;
|
||||
})
|
||||
avatar.aeq = avatar.a * 1 + avatar.e + avatar.q;
|
||||
avatarRet.push(avatar);
|
||||
}
|
||||
|
||||
fs.writeFileSync(cachePath + `${uid}.json`, JSON.stringify(avatarRet));
|
||||
//缓存
|
||||
await redis.set(`cache:uid-talent-new:${uid}`, uid, { EX: 3600 * cacheCd });
|
||||
delete skillLoading[e.user_id];
|
||||
// }
|
||||
|
||||
}
|
||||
//超过八个角色才分类四星五星
|
||||
if (star >= 4 && avatarRet.length > 8) {
|
||||
avatarRet = avatarRet.filter(item => item.rarity == star);
|
||||
}
|
||||
|
||||
let sortKey = ({
|
||||
talent: "aeq,rarity,level,star,fetter,talentWeek",
|
||||
weapon: "level,rarity,aeq,cons,weapon_level,weapon_rarity,weapon_affix_level,fetter"
|
||||
})[displayMode].split(",");
|
||||
|
||||
avatarRet = lodash.orderBy(avatarRet, sortKey, lodash.repeat("desc,", sortKey.length).split(","));
|
||||
|
||||
let noTalent = avatarRet.length == 0 || /^\-+$/.test(avatarRet.map((d) => d.a).join(""));
|
||||
|
||||
let talentNotice = `技能列表每${cacheCd}小时更新一次`;
|
||||
if (noTalent) {
|
||||
talentNotice = "未绑定体力Cookie,无法获取天赋列表。请回复 #体力 获取配置教程";
|
||||
}
|
||||
|
||||
let week = new Date().getDay();
|
||||
if (new Date().getHours() < 4) {
|
||||
week--;
|
||||
}
|
||||
|
||||
let base64 = await render("genshin", "talentList", {
|
||||
save_id: uid,
|
||||
uid: uid,
|
||||
avatars: avatarRet,
|
||||
bgType: Math.ceil(Math.random() * 3),
|
||||
abbr: genshin.abbr,
|
||||
displayMode,
|
||||
isSelf: e.isSelf,
|
||||
week: [3, 1, 2][week % 3],
|
||||
talentNotice
|
||||
|
||||
});
|
||||
|
||||
if (base64) {
|
||||
let msg = [];
|
||||
if (e.isGroup) {
|
||||
let name = lodash.truncate(e.sender.card, { length: 8 });
|
||||
msg.push(segment.at(e.user_id, name));
|
||||
}
|
||||
msg.push(segment.image(`base64://${base64}`));
|
||||
e.reply(msg);
|
||||
}
|
||||
return true; //事件结束不再往下
|
||||
}
|
@ -1,47 +1,48 @@
|
||||
import fs from "fs";
|
||||
import lodash from "lodash";
|
||||
import fs from 'fs'
|
||||
import lodash from 'lodash'
|
||||
|
||||
const _path = process.cwd();
|
||||
const _logPath = `${_path}/plugins/miao-plugin/CHANGELOG.md`;
|
||||
const _path = process.cwd()
|
||||
const _logPath = `${_path}/plugins/miao-plugin/CHANGELOG.md`
|
||||
|
||||
let logs = {};
|
||||
let changelogs = [];
|
||||
let currentVersion;
|
||||
let versionCount = 4;
|
||||
let logs = {}
|
||||
let changelogs = []
|
||||
let currentVersion
|
||||
let versionCount = 4
|
||||
|
||||
let packageJson = JSON.parse(fs.readFileSync("package.json", "utf8"));
|
||||
let packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'))
|
||||
|
||||
const getLine = function (line) {
|
||||
line = line.replace(/(^\s*\*|\r)/g, '');
|
||||
line = line.replace(/\s*`([^`]+`)/g, '<span class="cmd">$1');
|
||||
line = line.replace(/`\s*/g, '</span>');
|
||||
line = line.replace(/\s*\*\*([^\*]+\*\*)/g, '<span class="strong">$1')
|
||||
line = line.replace(/\*\*\s*/g, '</span>');
|
||||
line = line.replace(/ⁿᵉʷ/g, '<span class="new"></span>');
|
||||
return line;
|
||||
line = line.replace(/(^\s*\*|\r)/g, '')
|
||||
line = line.replace(/\s*`([^`]+`)/g, '<span class="cmd">$1')
|
||||
line = line.replace(/`\s*/g, '</span>')
|
||||
line = line.replace(/\s*\*\*([^\\*]+\*\*)/g, '<span class="strong">$1')
|
||||
line = line.replace(/\*\*\s*/g, '</span>')
|
||||
line = line.replace(/ⁿᵉʷ/g, '<span class="new"></span>')
|
||||
return line
|
||||
}
|
||||
|
||||
try {
|
||||
if (fs.existsSync(_logPath)) {
|
||||
logs = fs.readFileSync(_logPath, "utf8") || "";
|
||||
logs = logs.split("\n");
|
||||
logs = fs.readFileSync(_logPath, 'utf8') || ''
|
||||
logs = logs.split('\n')
|
||||
|
||||
let temp = {}, lastLine = {};
|
||||
let temp = {};
|
||||
let lastLine = {}
|
||||
lodash.forEach(logs, (line) => {
|
||||
if (versionCount <= -1) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
let versionRet = /^#\s*([0-9\\.~\s]+?)\s*$/.exec(line);
|
||||
let versionRet = /^#\s*([0-9\\.~\s]+?)\s*$/.exec(line)
|
||||
if (versionRet && versionRet[1]) {
|
||||
let v = versionRet[1].trim();
|
||||
let v = versionRet[1].trim()
|
||||
if (!currentVersion) {
|
||||
currentVersion = v;
|
||||
currentVersion = v
|
||||
} else {
|
||||
changelogs.push(temp);
|
||||
changelogs.push(temp)
|
||||
if (/0\s*$/.test(v) && versionCount > 0) {
|
||||
versionCount = 0;
|
||||
versionCount = 0
|
||||
} else {
|
||||
versionCount--;
|
||||
versionCount--
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,24 +52,25 @@ try {
|
||||
}
|
||||
} else {
|
||||
if (!line.trim()) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
if (/^\*/.test(line)) {
|
||||
lastLine = {
|
||||
title: getLine(line),
|
||||
logs: []
|
||||
}
|
||||
temp.logs.push(lastLine);
|
||||
temp.logs.push(lastLine)
|
||||
} else if (/^\s{3,}\*/.test(line)) {
|
||||
lastLine.logs.push(getLine(line));
|
||||
lastLine.logs.push(getLine(line))
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
} catch (e) {
|
||||
// do nth
|
||||
}
|
||||
|
||||
const yunzaiVersion = packageJson.version;
|
||||
const yunzaiVersion = packageJson.version
|
||||
const isV3 = yunzaiVersion[0] === '3'
|
||||
|
||||
export { currentVersion, yunzaiVersion, changelogs };
|
||||
export { currentVersion, yunzaiVersion, isV3, changelogs }
|
||||
|
@ -1,32 +1,40 @@
|
||||
import { Cfg } from "./index.js";
|
||||
import { segment } from "oicq";
|
||||
import { currentVersion, yunzaiVersion } from "./Changelog.js";
|
||||
import { Cfg } from './index.js'
|
||||
import { segment } from 'oicq'
|
||||
import { currentVersion, yunzaiVersion, isV3 } from './Changelog.js'
|
||||
|
||||
export const render = async function (path, params, cfg) {
|
||||
let paths = path.split("/");
|
||||
let { render, e } = cfg;
|
||||
let _layout_path = process.cwd() + "/plugins/miao-plugin/resources/common/layout/";
|
||||
let paths = path.split('/')
|
||||
let { render, e } = cfg
|
||||
let layoutPath = process.cwd() + '/plugins/miao-plugin/resources/common/layout/'
|
||||
let base64 = await render(paths[0], paths[1], {
|
||||
...params,
|
||||
_layout_path,
|
||||
defaultLayout: _layout_path + "default.html",
|
||||
elemLayout: _layout_path + "elem.html",
|
||||
_layout_path: layoutPath,
|
||||
defaultLayout: layoutPath + 'default.html',
|
||||
elemLayout: layoutPath + 'elem.html',
|
||||
sys: {
|
||||
scale: Cfg.scale(cfg.scale || 1),
|
||||
copyright: `Created By Yunzai-Bot<span class="version">${yunzaiVersion}</span> & Miao-Plugin<span class="version">${currentVersion}</span>`
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
if (base64) {
|
||||
return await e.reply(segment.image(`base64://${base64}`));
|
||||
return isV3 ? await e.reply(base64) : await e.reply(segment.image(`base64://${base64}`))
|
||||
}
|
||||
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
|
||||
export const todoV3 = function (e) {
|
||||
if (isV3) {
|
||||
e.reply('本功能暂时不支持V3版Yunzai...')
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
export default {
|
||||
render,
|
||||
cfg: Cfg.get,
|
||||
isDisable: Cfg.isDisable
|
||||
};
|
||||
isDisable: Cfg.isDisable,
|
||||
todoV3
|
||||
}
|
||||
|
@ -1,24 +1,23 @@
|
||||
import lodash from "lodash";
|
||||
import fs from "fs";
|
||||
import request from "request";
|
||||
import lodash from 'lodash'
|
||||
import fs from 'fs'
|
||||
|
||||
const _path = process.cwd();
|
||||
const _path = process.cwd()
|
||||
|
||||
let Data = {
|
||||
|
||||
/*
|
||||
* 根据指定的path依次检查与创建目录
|
||||
* */
|
||||
createDir(rootPath = "", path = "", includeFile = false) {
|
||||
let pathList = path.split("/"),
|
||||
nowPath = rootPath;
|
||||
createDir (rootPath = '', path = '', includeFile = false) {
|
||||
let pathList = path.split('/')
|
||||
let nowPath = rootPath
|
||||
pathList.forEach((name, idx) => {
|
||||
name = name.trim();
|
||||
name = name.trim()
|
||||
if (!includeFile && idx <= pathList.length - 1) {
|
||||
nowPath += name + "/";
|
||||
nowPath += name + '/'
|
||||
if (name) {
|
||||
if (!fs.existsSync(nowPath)) {
|
||||
fs.mkdirSync(nowPath);
|
||||
fs.mkdirSync(nowPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -28,15 +27,15 @@ let Data = {
|
||||
/*
|
||||
* 读取json
|
||||
* */
|
||||
readJSON(root, path) {
|
||||
readJSON (root, path) {
|
||||
if (!/\.json$/.test(path)) {
|
||||
path = path + ".json";
|
||||
path = path + '.json'
|
||||
}
|
||||
// 检查并创建目录
|
||||
Data.createDir(root, path, true);
|
||||
Data.createDir(root, path, true)
|
||||
if (fs.existsSync(`${root}/${path}`)) {
|
||||
let jsonRet = fs.readFileSync(`${root}/${path}`, "utf8");
|
||||
return JSON.parse(jsonRet);
|
||||
let jsonRet = fs.readFileSync(`${root}/${path}`, 'utf8')
|
||||
return JSON.parse(jsonRet)
|
||||
}
|
||||
return {}
|
||||
},
|
||||
@ -44,27 +43,27 @@ let Data = {
|
||||
/*
|
||||
* 写JSON
|
||||
* */
|
||||
writeJson(path, file, data, space = "\t") {
|
||||
writeJson (path, file, data, space = '\t') {
|
||||
if (!/\.json$/.test(file)) {
|
||||
file = file + ".json";
|
||||
file = file + '.json'
|
||||
}
|
||||
|
||||
// 检查并创建目录
|
||||
Data.createDir(_path, path, false);
|
||||
console.log(data);
|
||||
delete data._res;
|
||||
return fs.writeFileSync(`${_path}/${path}/${file}`, JSON.stringify(data, null, space));
|
||||
Data.createDir(_path, path, false)
|
||||
console.log(data)
|
||||
delete data._res
|
||||
return fs.writeFileSync(`${_path}/${path}/${file}`, JSON.stringify(data, null, space))
|
||||
},
|
||||
|
||||
async importModule(path, file, rootPath = _path) {
|
||||
async importModule (path, file, rootPath = _path) {
|
||||
if (!/\.js$/.test(file)) {
|
||||
file = file + ".js";
|
||||
file = file + '.js'
|
||||
}
|
||||
// 检查并创建目录
|
||||
Data.createDir(_path, path, true);
|
||||
Data.createDir(_path, path, true)
|
||||
if (fs.existsSync(`${_path}/${path}/${file}`)) {
|
||||
let data = await import (`file://${_path}/${path}/${file}`);
|
||||
return data || {};
|
||||
let data = await import(`file://${_path}/${path}/${file}`)
|
||||
return data || {}
|
||||
}
|
||||
return {}
|
||||
},
|
||||
@ -80,42 +79,42 @@ let Data = {
|
||||
*
|
||||
* */
|
||||
|
||||
getData(target, keyList = "", cfg = {}) {
|
||||
target = target || {};
|
||||
let defaultData = cfg.defaultData || {};
|
||||
let ret = {};
|
||||
getData (target, keyList = '', cfg = {}) {
|
||||
target = target || {}
|
||||
let defaultData = cfg.defaultData || {}
|
||||
let ret = {}
|
||||
// 分割逗号
|
||||
if (typeof (keyList) === "string") {
|
||||
keyList = keyList.split(",");
|
||||
if (typeof (keyList) === 'string') {
|
||||
keyList = keyList.split(',')
|
||||
}
|
||||
|
||||
lodash.forEach(keyList, (keyCfg) => {
|
||||
// 处理通过:指定 toKey & fromKey
|
||||
let _keyCfg = keyCfg.split(":");
|
||||
let keyTo = _keyCfg[0].trim(),
|
||||
keyFrom = (_keyCfg[1] || _keyCfg[0]).trim(),
|
||||
keyRet = keyTo;
|
||||
let _keyCfg = keyCfg.split(':')
|
||||
let keyTo = _keyCfg[0].trim()
|
||||
let keyFrom = (_keyCfg[1] || _keyCfg[0]).trim()
|
||||
let keyRet = keyTo
|
||||
if (cfg.lowerFirstKey) {
|
||||
keyRet = lodash.lowerFirst(keyRet);
|
||||
keyRet = lodash.lowerFirst(keyRet)
|
||||
}
|
||||
if (cfg.keyPrefix) {
|
||||
keyRet = cfg.keyPrefix + keyRet;
|
||||
keyRet = cfg.keyPrefix + keyRet
|
||||
}
|
||||
// 通过Data.getVal获取数据
|
||||
ret[keyRet] = Data.getVal(target, keyFrom, defaultData[keyTo], cfg);
|
||||
ret[keyRet] = Data.getVal(target, keyFrom, defaultData[keyTo], cfg)
|
||||
})
|
||||
return ret;
|
||||
return ret
|
||||
},
|
||||
|
||||
getVal(target, keyFrom, defaultValue) {
|
||||
return lodash.get(target, keyFrom, defaultValue);
|
||||
getVal (target, keyFrom, defaultValue) {
|
||||
return lodash.get(target, keyFrom, defaultValue)
|
||||
},
|
||||
|
||||
getUrlPath(url) {
|
||||
let reg = /^https*:\/\/(.*)\/(\w+\.(png|jpg|jpeg|webp))(\?.*)?$/;
|
||||
let ret = reg.exec(url);
|
||||
getUrlPath (url) {
|
||||
let reg = /^https*:\/\/(.*)\/(\w+\.(png|jpg|jpeg|webp))(\?.*)?$/
|
||||
let ret = reg.exec(url)
|
||||
if (!ret) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
return {
|
||||
path: ret[1],
|
||||
@ -124,91 +123,68 @@ let Data = {
|
||||
url
|
||||
}
|
||||
},
|
||||
pathExists(root, path) {
|
||||
if (fs.existsSync(root + "/" + path)) {
|
||||
return true;
|
||||
pathExists (root, path) {
|
||||
if (fs.existsSync(root + '/' + path)) {
|
||||
return true
|
||||
}
|
||||
path = path.replace("\\", "/");
|
||||
const dirList = path.split("/");
|
||||
let currentDir = root;
|
||||
path = path.replace('\\', '/')
|
||||
const dirList = path.split('/')
|
||||
let currentDir = root
|
||||
|
||||
for (let dir of dirList) {
|
||||
currentDir = currentDir + "/" + dir;
|
||||
currentDir = currentDir + '/' + dir
|
||||
if (!fs.existsSync(currentDir)) {
|
||||
fs.mkdirSync(currentDir);
|
||||
fs.mkdirSync(currentDir)
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return true
|
||||
},
|
||||
async asyncPool(poolLimit, array, iteratorFn) {
|
||||
const ret = []; // 存储所有的异步任务
|
||||
const executing = []; // 存储正在执行的异步任务
|
||||
async asyncPool (poolLimit, array, iteratorFn) {
|
||||
const ret = [] // 存储所有的异步任务
|
||||
const executing = [] // 存储正在执行的异步任务
|
||||
for (const item of array) {
|
||||
// 调用iteratorFn函数创建异步任务
|
||||
const p = Promise.resolve().then(() => iteratorFn(item, array));
|
||||
const p = Promise.resolve().then(() => iteratorFn(item, array))
|
||||
// 保存新的异步任务
|
||||
ret.push(p);
|
||||
ret.push(p)
|
||||
|
||||
// 当poolLimit值小于或等于总任务个数时,进行并发控制
|
||||
if (poolLimit <= array.length) {
|
||||
// 当任务完成后,从正在执行的任务数组中移除已完成的任务
|
||||
const e = p.then(() => executing.splice(executing.indexOf(e), 1));
|
||||
executing.push(e); // 保存正在执行的异步任务
|
||||
const e = p.then(() => executing.splice(executing.indexOf(e), 1))
|
||||
executing.push(e) // 保存正在执行的异步任务
|
||||
if (executing.length >= poolLimit) {
|
||||
// 等待较快的任务执行完成
|
||||
await Promise.race(executing);
|
||||
await Promise.race(executing)
|
||||
}
|
||||
}
|
||||
}
|
||||
return Promise.all(ret);
|
||||
return Promise.all(ret)
|
||||
},
|
||||
|
||||
async cacheFile(fileList, cacheRoot) {
|
||||
|
||||
let ret = {};
|
||||
let cacheFn = async function (url) {
|
||||
let path = Data.getUrlPath(url);
|
||||
if (fs.existsSync(`${cacheRoot}/${path.path}/${path.filename}`)) {
|
||||
console.log("已存在,跳过 " + path.path + "/" + path.filename);
|
||||
ret[url] = `${path.path}/${path.filename}`;
|
||||
return true;
|
||||
}
|
||||
|
||||
Data.pathExists(cacheRoot, path.path);
|
||||
await request(url).pipe(fs.createWriteStream(`${cacheRoot}/${path.path}/` + path.filename));
|
||||
console.log("下载成功: " + path.path + "/" + path.filname);
|
||||
ret[url] = `${path.path}/${path.filename}`;
|
||||
return true;
|
||||
};
|
||||
|
||||
await Data.asyncPool(10, fileList, cacheFn);
|
||||
return ret;
|
||||
|
||||
sleep (ms) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms))
|
||||
},
|
||||
|
||||
sleep(ms) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
},
|
||||
|
||||
def() {
|
||||
def () {
|
||||
for (let idx in arguments) {
|
||||
if (!lodash.isUndefined(arguments[idx])) {
|
||||
return arguments[idx];
|
||||
return arguments[idx]
|
||||
}
|
||||
}
|
||||
},
|
||||
eachStr: (arr, fn) => {
|
||||
if (lodash.isString(arr)) {
|
||||
arr = arr.replace(/\s*(;|;|、|,)\s*/, ",");
|
||||
arr = arr.split(",");
|
||||
arr = arr.replace(/\s*(;|;|、|,)\s*/, ',')
|
||||
arr = arr.split(',')
|
||||
}
|
||||
lodash.forEach(arr, (str, idx) => {
|
||||
if (!lodash.isUndefined(str)) {
|
||||
fn(str.trim ? str.trim() : str, idx)
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Data;
|
||||
export default Data
|
||||
|
@ -1,158 +0,0 @@
|
||||
import md5 from "md5";
|
||||
import lodash from 'lodash';
|
||||
import fetch from "node-fetch";
|
||||
|
||||
let MysApi = {
|
||||
getUrl(type, uid, data = {}) {
|
||||
let url = "https://api-takumi.mihoyo.com";
|
||||
let game_record = "/game_record/app/genshin/api/";
|
||||
let server = MysApi.getServer(uid);
|
||||
let query, body;
|
||||
|
||||
switch (type) {
|
||||
//首页宝箱
|
||||
case "index":
|
||||
url += game_record + "index";
|
||||
query = `role_id=${uid}&server=${server}`;
|
||||
break;
|
||||
//深渊
|
||||
case "spiralAbyss":
|
||||
url += game_record + "spiralAbyss";
|
||||
query = `role_id=${uid}&schedule_type=${data.schedule_type}&server=${server}`;
|
||||
break;
|
||||
//角色详情
|
||||
case "character":
|
||||
url += game_record + "character";
|
||||
body = JSON.stringify(data);
|
||||
break;
|
||||
//树脂每日任务(只能当前id)
|
||||
case "dailyNote":
|
||||
url += game_record + "dailyNote";
|
||||
query = `role_id=${uid}&server=${server}`;
|
||||
break;
|
||||
case "detail":
|
||||
url += "/event/e20200928calculate/v1/sync/avatar/detail";
|
||||
query = `uid=${uid}®ion=${server}&avatar_id=${data.avatar_id}`;
|
||||
break;
|
||||
case "getAnnouncement":
|
||||
url += "/game_record/card/wapi/getAnnouncement";
|
||||
break;
|
||||
case "getGameRecordCard":
|
||||
url += "/game_record/card/wapi/getGameRecordCard";
|
||||
query = `uid=${uid}`;//米游社id
|
||||
break;
|
||||
case "bbs_sign_info":
|
||||
url += "/event/bbs_sign_reward/info";
|
||||
query = `act_id=e202009291139501®ion=${server}&uid=${uid}`;
|
||||
break;
|
||||
case "bbs_sign_home":
|
||||
url += "/event/bbs_sign_reward/home";
|
||||
query = `act_id=e202009291139501®ion=${server}&uid=${uid}`;
|
||||
break;
|
||||
case "bbs_sign":
|
||||
url += "/event/bbs_sign_reward/sign";
|
||||
body = JSON.stringify({ act_id: "e202009291139501", region: server, uid: uid, });
|
||||
break;
|
||||
case "ys_ledger":
|
||||
url = "https://hk4e-api.mihoyo.com/event/ys_ledger/monthInfo";
|
||||
query = `month=${data.month}&bind_uid=${uid}&bind_region=${server}`;
|
||||
break;
|
||||
}
|
||||
|
||||
if (query) {
|
||||
url += "?" + query;
|
||||
}
|
||||
|
||||
let headers;
|
||||
if (type === "bbs_sign") {
|
||||
headers = MysApi.getHeaders_sign();
|
||||
} else {
|
||||
headers = MysApi.getHeaders(query, body);
|
||||
}
|
||||
|
||||
return { url, headers, query, body };
|
||||
},
|
||||
|
||||
getServer(uid) {
|
||||
switch (uid.toString()[0]) {
|
||||
case "1":
|
||||
case "2":
|
||||
return "cn_gf01"; //官服
|
||||
case "5":
|
||||
return "cn_qd01"; //B服
|
||||
}
|
||||
return "cn_gf01"; //官服
|
||||
},
|
||||
|
||||
//# Github-@lulu666lulu
|
||||
getDs(q = "", b = "") {
|
||||
let n = "xV8v4Qu54lUKrEYFZkJhB8cuOh9Asafs";
|
||||
let t = Math.round(new Date().getTime() / 1000);
|
||||
let r = Math.floor(Math.random() * 900000 + 100000);
|
||||
let DS = md5(`salt=${n}&t=${t}&r=${r}&b=${b}&q=${q}`);
|
||||
return `${t},${r},${DS}`;
|
||||
},
|
||||
|
||||
//签到ds
|
||||
getDS_sign() {
|
||||
const n = "h8w582wxwgqvahcdkpvdhbh2w9casgfl";
|
||||
const t = Math.round(new Date().getTime() / 1000);
|
||||
const r = lodash.sampleSize("abcdefghijklmnopqrstuvwxyz0123456789", 6).join("");
|
||||
const DS = md5(`salt=${n}&t=${t}&r=${r}`);
|
||||
return `${t},${r},${DS}`;
|
||||
},
|
||||
|
||||
getHeaders(q = "", b = "") {
|
||||
return {
|
||||
"x-rpc-app_version": "2.20.1",
|
||||
"x-rpc-client_type": 5,
|
||||
DS: MysApi.getDs(q, b),
|
||||
};
|
||||
},
|
||||
|
||||
getHeaders_sign() {
|
||||
return {
|
||||
"x-rpc-app_version": "2.3.0",
|
||||
"x-rpc-client_type": 5,
|
||||
"x-rpc-device_id": MysApi.guid(),
|
||||
"User-Agent": " miHoYoBBS/2.3.0",
|
||||
DS: MysApi.getDS_sign(),
|
||||
};
|
||||
},
|
||||
|
||||
guid() {
|
||||
function S4() {
|
||||
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
|
||||
}
|
||||
|
||||
return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
|
||||
},
|
||||
|
||||
// 按type请求
|
||||
request: async function (type, cfg) {
|
||||
let { uid } = cfg;
|
||||
let { url, headers } = MysApi.getUrl(type, uid);
|
||||
return await MysApi.fetch(url, headers, cfg);
|
||||
},
|
||||
|
||||
// 发送请求
|
||||
fetch: async function (url, cfg) {
|
||||
let { cookie, error, success, headers, method } = cfg;
|
||||
headers = headers || {};
|
||||
method = method || "get";
|
||||
headers.Cookie = cookie;
|
||||
let response = await fetch(url, { method, headers });
|
||||
if (!response.ok) {
|
||||
return await error(-1, {
|
||||
msg: "米游社接口错误"
|
||||
})
|
||||
}
|
||||
let res = await response.json();
|
||||
if (res.retcode * 1 !== 0) {
|
||||
return await error(res.retcode * 1, res)
|
||||
}
|
||||
return await success(res.data, res)
|
||||
}
|
||||
}
|
||||
|
||||
export default MysApi;
|
@ -1,252 +1,249 @@
|
||||
import Base from "./Base.js";
|
||||
import lodash from "lodash";
|
||||
import fs from "fs";
|
||||
import Data from "../Data.js";
|
||||
import sizeOf from "image-size";
|
||||
import { customCharacters } from "../../config/character_default.js";
|
||||
import Base from './Base.js'
|
||||
import lodash from 'lodash'
|
||||
import fs from 'fs'
|
||||
import Data from '../Data.js'
|
||||
import sizeOf from 'image-size'
|
||||
|
||||
|
||||
let aliasMap = {}, idMap = {}, abbrMap = {}, wifeMap = {};
|
||||
const _path = process.cwd();
|
||||
let aliasMap = {};
|
||||
let idMap = {};
|
||||
let abbrMap = {};
|
||||
let wifeMap = {}
|
||||
const _path = process.cwd()
|
||||
const metaPath = `${_path}/plugins/miao-plugin/resources/meta/character/`
|
||||
|
||||
async function init() {
|
||||
let sysCfg = await Data.importModule(`config/genshin`, 'roleId.js'),
|
||||
charCfg = await Data.importModule(`plugins/miao-plugin/config`, 'character_default.js'),
|
||||
custom = await Data.importModule(`plugins/miao-plugin/config`, 'character.js');
|
||||
async function init () {
|
||||
let sysCfg = await Data.importModule('plugins/miao-plugin/config/system', 'character.js')
|
||||
let custom = await Data.importModule('plugins/miao-plugin/config', 'character.js')
|
||||
|
||||
lodash.forEach([custom.customCharacters, charCfg.customCharacters, sysCfg.roleId], (roleIds) => {
|
||||
lodash.forEach([custom.customCharacters, sysCfg.characters], (roleIds) => {
|
||||
lodash.forEach(roleIds || {}, (aliases, id) => {
|
||||
aliases = aliases || [];
|
||||
aliases = aliases || []
|
||||
if (aliases.length === 0) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
// 建立别名映射
|
||||
lodash.forEach(aliases || [], (alias) => {
|
||||
aliasMap[alias] = id;
|
||||
alias = alias.toLowerCase()
|
||||
aliasMap[alias] = id
|
||||
})
|
||||
aliasMap[id] = id;
|
||||
idMap[id] = aliases[0];
|
||||
aliasMap[id] = id
|
||||
idMap[id] = aliases[0]
|
||||
})
|
||||
})
|
||||
|
||||
lodash.forEach([sysCfg.wifeData, charCfg.wifeData, custom.wifeData], (wifeData) => {
|
||||
lodash.forEach([sysCfg.wifeData, custom.wifeData], (wifeData) => {
|
||||
lodash.forEach(wifeData || {}, (ids, type) => {
|
||||
type = Data.def({ girlfriend: 0, boyfriend: 1, daughter: 2, son: 3 }[type], type);
|
||||
type = Data.def({ girlfriend: 0, boyfriend: 1, daughter: 2, son: 3 }[type], type)
|
||||
if (!wifeMap[type]) {
|
||||
wifeMap[type] = {};
|
||||
wifeMap[type] = {}
|
||||
}
|
||||
Data.eachStr(ids, (id) => {
|
||||
id = aliasMap[id];
|
||||
id = aliasMap[id]
|
||||
if (id) {
|
||||
wifeMap[type][id] = true;
|
||||
wifeMap[type][id] = true
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
abbrMap = sysCfg.abbr;
|
||||
abbrMap = sysCfg.abbr
|
||||
}
|
||||
|
||||
await init();
|
||||
|
||||
await init()
|
||||
|
||||
class Character extends Base {
|
||||
constructor(name, id) {
|
||||
super();
|
||||
constructor (name, id) {
|
||||
super()
|
||||
|
||||
if (id * 1 === 10000005) {
|
||||
name = "空";
|
||||
name = '空'
|
||||
} else if (id * 1 === 10000007) {
|
||||
name = "荧";
|
||||
name = '荧'
|
||||
}
|
||||
this.name = name;
|
||||
lodash.extend(this, getMeta(name));
|
||||
if (name === "主角" || name === "旅行者" || /.主/.test(name)) {
|
||||
this.id = 20000000;
|
||||
this.name = name
|
||||
lodash.extend(this, getMeta(name))
|
||||
if (name === '主角' || name === '旅行者' || /.主/.test(name)) {
|
||||
this.id = 20000000
|
||||
}
|
||||
this.id = id;
|
||||
this.id = id
|
||||
}
|
||||
|
||||
|
||||
getCardImg(se = false, def = true) {
|
||||
let name = this.name;
|
||||
const charImgPath = `./plugins/miao-plugin/resources/character-img/${name}/`;
|
||||
let list = [];
|
||||
getCardImg (se = false, def = true) {
|
||||
let name = this.name
|
||||
let list = []
|
||||
let addImg = function (charImgPath, disable = false) {
|
||||
let dirPath = `./plugins/miao-plugin/resources/${charImgPath}`;
|
||||
let dirPath = `./plugins/miao-plugin/resources/${charImgPath}`
|
||||
|
||||
if (!fs.existsSync(dirPath)) {
|
||||
fs.mkdirSync(dirPath);
|
||||
fs.mkdirSync(dirPath)
|
||||
}
|
||||
if (disable) {
|
||||
return
|
||||
}
|
||||
|
||||
let imgs = fs.readdirSync(dirPath);
|
||||
imgs = imgs.filter((img) => /\.(png|jpg|webp|jpeg)/i.test(img));
|
||||
let imgs = fs.readdirSync(dirPath)
|
||||
imgs = imgs.filter((img) => /\.(png|jpg|webp|jpeg)/i.test(img))
|
||||
lodash.forEach(imgs, (img) => {
|
||||
list.push(`${charImgPath}/${img}`);
|
||||
});
|
||||
list.push(`${charImgPath}/${img}`)
|
||||
})
|
||||
}
|
||||
addImg(`character-img/${name}`);
|
||||
addImg(`character-img/${name}/upload`);
|
||||
addImg(`character-img/${name}`)
|
||||
addImg(`character-img/${name}/upload`)
|
||||
addImg(`character-img/${name}/se`, !se)
|
||||
|
||||
const plusPath = `./plugins/miao-plugin/resources/miao-res-plus/`;
|
||||
const plusPath = './plugins/miao-plugin/resources/miao-res-plus/'
|
||||
if (fs.existsSync(plusPath)) {
|
||||
addImg(`miao-res-plus/character-img/${name}`);
|
||||
addImg(`miao-res-plus/character-img/${name}/se`, !se);
|
||||
addImg(`miao-res-plus/character-img/${name}`)
|
||||
addImg(`miao-res-plus/character-img/${name}/se`, !se)
|
||||
}
|
||||
|
||||
let img = lodash.sample(list);
|
||||
let img = lodash.sample(list)
|
||||
|
||||
if (!img) {
|
||||
if (def) {
|
||||
img = "/character-img/default/01.jpg";
|
||||
img = '/character-img/default/01.jpg'
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
let ret = sizeOf(`./plugins/miao-plugin/resources/${img}`);
|
||||
ret.img = img;
|
||||
ret.mode = ret.width > ret.height ? "left" : "bottom";
|
||||
return ret;
|
||||
let ret = sizeOf(`./plugins/miao-plugin/resources/${img}`)
|
||||
ret.img = img
|
||||
ret.mode = ret.width > ret.height ? 'left' : 'bottom'
|
||||
return ret
|
||||
}
|
||||
|
||||
checkAvatars(avatars) {
|
||||
checkAvatars (avatars) {
|
||||
if (!lodash.includes([20000000, 10000005, 10000007], this.id * 1)) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
let avatarIds = [];
|
||||
let avatarIds = []
|
||||
if (lodash.isArray(avatars)) {
|
||||
avatarIds = lodash.map(avatars, (a) => a.id * 1);
|
||||
avatarIds = lodash.map(avatars, (a) => a.id * 1)
|
||||
} else {
|
||||
avatarIds = [avatars.id];
|
||||
avatarIds = [avatars.id]
|
||||
}
|
||||
|
||||
if (lodash.includes(avatarIds, 10000005)) {
|
||||
// 空
|
||||
lodash.extend(this, getMeta('空'));
|
||||
lodash.extend(this, getMeta('空'))
|
||||
} else if (lodash.includes(avatarIds, 10000007)) {
|
||||
// 荧
|
||||
lodash.extend(this, getMeta('荧'));
|
||||
lodash.extend(this, getMeta('荧'))
|
||||
}
|
||||
}
|
||||
|
||||
getAvatarTalent(talent = {}, cons = 0, mode = "level") {
|
||||
let ret = {};
|
||||
let consTalent = this.getConsTalent();
|
||||
getAvatarTalent (talent = {}, cons = 0, mode = 'level') {
|
||||
let ret = {}
|
||||
let consTalent = this.getConsTalent()
|
||||
lodash.forEach(['a', 'e', 'q'], (key) => {
|
||||
let ds = talent[key];
|
||||
let ds = talent[key]
|
||||
if (ds) {
|
||||
let level;
|
||||
let level
|
||||
if (lodash.isNumber(ds)) {
|
||||
level = ds;
|
||||
level = ds
|
||||
} else {
|
||||
level = mode === "level" ? ds.level || ds.level_current || ds.original || ds.level_original :
|
||||
ds.original || ds.level_original || ds.level || ds.level_current;
|
||||
level = mode === 'level' ? ds.level || ds.level_current || ds.original || ds.level_original : ds.original || ds.level_original || ds.level || ds.level_current
|
||||
}
|
||||
if (mode === "level") {
|
||||
if (mode === 'level') {
|
||||
// 基于level计算original
|
||||
ret[key] = {
|
||||
level,
|
||||
original: (key !== "a" && cons >= consTalent[key]) ? (level - 3) : level
|
||||
original: (key !== 'a' && cons >= consTalent[key]) ? (level - 3) : level
|
||||
}
|
||||
} else {
|
||||
// 基于original计算level
|
||||
ret[key] = {
|
||||
original: level,
|
||||
level: (key !== "a" && cons >= consTalent[key]) ? (level + 3) : level
|
||||
level: (key !== 'a' && cons >= consTalent[key]) ? (level + 3) : level
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
})
|
||||
return ret;
|
||||
return ret
|
||||
}
|
||||
|
||||
getConsTalent() {
|
||||
let talent = this.talent || false;
|
||||
getConsTalent () {
|
||||
let talent = this.talent || false
|
||||
if (!talent) {
|
||||
return { e: 3, q: 5 }
|
||||
}
|
||||
let e = talent.e.name,
|
||||
q = talent.q.name;
|
||||
let c3 = this.cons['3'].desc,
|
||||
c5 = this.cons['5'].desc;
|
||||
let e = talent.e.name
|
||||
let q = talent.q.name
|
||||
let c3 = this.cons['3'].desc
|
||||
let c5 = this.cons['5'].desc
|
||||
return {
|
||||
e: c3.includes(e) ? 3 : 5,
|
||||
q: c5.includes(q) ? 5 : 3,
|
||||
q: c5.includes(q) ? 5 : 3
|
||||
}
|
||||
}
|
||||
|
||||
get weaponType() {
|
||||
get weaponType () {
|
||||
const map = {
|
||||
sword: "单手剑",
|
||||
catalyst: "法器",
|
||||
bow: "弓",
|
||||
claymore: "双手剑",
|
||||
polearm: "长柄武器"
|
||||
sword: '单手剑',
|
||||
catalyst: '法器',
|
||||
bow: '弓',
|
||||
claymore: '双手剑',
|
||||
polearm: '长柄武器'
|
||||
}
|
||||
let weaponType = this.weapon || "";
|
||||
return map[weaponType.toLowerCase()] || "";
|
||||
let weaponType = this.weapon || ''
|
||||
return map[weaponType.toLowerCase()] || ''
|
||||
}
|
||||
|
||||
get isCustom() {
|
||||
return !/10\d{6}/.test(this.id);
|
||||
get isCustom () {
|
||||
return !/10\d{6}/.test(this.id)
|
||||
}
|
||||
|
||||
checkWifeType(type) {
|
||||
return !!wifeMap[type][this.id];
|
||||
checkWifeType (type) {
|
||||
return !!wifeMap[type][this.id]
|
||||
}
|
||||
}
|
||||
|
||||
let getMeta = function (name) {
|
||||
return Data.readJSON(`${_path}/plugins/miao-plugin/resources/meta/character/${name}/`, "data.json") || {};
|
||||
return Data.readJSON(`${_path}/plugins/miao-plugin/resources/meta/character/${name}/`, 'data.json') || {}
|
||||
}
|
||||
|
||||
Character.get = function (val) {
|
||||
let id, name;
|
||||
let id, name
|
||||
if (!val) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
if (typeof (val) === "number" || /^\d*$/.test(val)) {
|
||||
id = val;
|
||||
if (typeof (val) === 'number' || /^\d*$/.test(val)) {
|
||||
id = val
|
||||
} else if (val.id) {
|
||||
id = val.id;
|
||||
name = val.name || idMap[id];
|
||||
id = val.id
|
||||
name = val.name || idMap[id]
|
||||
} else {
|
||||
id = aliasMap[val];
|
||||
id = aliasMap[val]
|
||||
}
|
||||
if (!name) {
|
||||
name = idMap[id];
|
||||
name = idMap[id]
|
||||
}
|
||||
if (!name) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
return new Character(name, id);
|
||||
};
|
||||
|
||||
return new Character(name, id)
|
||||
}
|
||||
|
||||
Character.getAbbr = function () {
|
||||
return abbrMap;
|
||||
return abbrMap
|
||||
}
|
||||
|
||||
Character.checkWifeType = function (charid, type) {
|
||||
return !!wifeMap[type][charid];
|
||||
}
|
||||
|
||||
Character.getRandomImg = function (type) {
|
||||
let chars = fs.readdirSync(metaPath);
|
||||
let ret = [];
|
||||
type = type === "party" ? "party" : "profile";
|
||||
let chars = fs.readdirSync(metaPath)
|
||||
let ret = []
|
||||
type = type === 'party' ? 'party' : 'profile'
|
||||
lodash.forEach(chars, (char) => {
|
||||
if (fs.existsSync(`${metaPath}/${char}/${type}.png`)) {
|
||||
ret.push(`/meta/character/${char}/${type}.png`);
|
||||
ret.push(`/meta/character/${char}/${type}.png`)
|
||||
}
|
||||
});
|
||||
return lodash.sample(ret);
|
||||
})
|
||||
return lodash.sample(ret)
|
||||
}
|
||||
|
||||
|
||||
let charPosIdx = {
|
||||
1: '宵宫,雷神,胡桃,甘雨,优菈,一斗,公子,绫人,魈,可莉,迪卢克,凝光,刻晴,辛焱,烟绯,雷泽',
|
||||
2: '夜兰,八重,九条,行秋,香菱,安柏,凯亚,丽莎,北斗,菲谢尔,重云,罗莎莉亚,埃洛伊',
|
||||
@ -254,20 +251,19 @@ let charPosIdx = {
|
||||
4: '班尼特,心海,琴,芭芭拉,七七,迪奥娜,托马,空,荧,阿贝多,钟离'
|
||||
}
|
||||
|
||||
let idSort = {};
|
||||
let idSort = {}
|
||||
lodash.forEach(charPosIdx, (chars, pos) => {
|
||||
chars = chars.split(",");
|
||||
chars = chars.split(',')
|
||||
lodash.forEach(chars, (name, idx) => {
|
||||
let id = aliasMap[name];
|
||||
let id = aliasMap[name]
|
||||
if (id) {
|
||||
idSort[id] = pos * 100 + idx;
|
||||
idSort[id] = pos * 100 + idx
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
Character.sortIds = function (arr) {
|
||||
return arr.sort((a, b) => (idSort[a] || 300) - (idSort[b] || 300));
|
||||
return arr.sort((a, b) => (idSort[a] || 300) - (idSort[b] || 300))
|
||||
}
|
||||
|
||||
export default Character;
|
||||
export default Character
|
||||
|
@ -15,31 +15,10 @@ export const customCharacters = {
|
||||
|
||||
// 已有角色添加别名示例:为魈增加新的别名
|
||||
// roleid请参见Yunzai roleId.js
|
||||
10000026: ["魈", "风夜叉"],
|
||||
10000059: ["鹿野院平藏", "小鹿"],
|
||||
|
||||
// ID暂无,使用临时ID代替
|
||||
10000100: ["提纳里", "提那里", "驴"],
|
||||
10000101: ["柯莱", "柯来", "科莱", "科来", "小天使"],
|
||||
10000102: ["多莉", "多利", "多力"],
|
||||
10000026: ['魈', '风夜叉'],
|
||||
|
||||
// 以下为新增自定义角色,角色id请以小写英文定义
|
||||
paimon: ["派蒙", "应急食物", "应急食品", "吉祥物", "宠物", "外置器官", "会说话的动物", "矮堇瓜", "飞行矮堇瓜", "最好的伙伴"],
|
||||
sb: ["散兵", "国崩", "雷电国崩", "大炮", "雷电大炮", "雷大炮", "伞兵"],
|
||||
nvshi: ["女士", "炽热的炎之魔女", "炎之魔女"],
|
||||
baizhu: ["白术", "长生"],
|
||||
yaoyao: ["瑶瑶", "遥遥", "遥遥无期"],
|
||||
fanan: ["伐难", "水夜叉"],
|
||||
yingda: ["应达", "火夜叉", "火鼠大将"],
|
||||
ping: ["萍姥姥", "歌尘浪市真君", "歌尘浪市", "萍儿"],
|
||||
|
||||
puren: ["阿蕾奇诺", "仆人", "黑优菈", "黑暗优菈"],
|
||||
shaonv: ["哥伦比娅", "少女"],
|
||||
furen: ["潘塔罗涅", "富人", "黑白术", "黑术"],
|
||||
boshi: ["多托雷", "博士"],
|
||||
muou: ["桑多涅", "木偶"]
|
||||
|
||||
|
||||
sb: ['散兵', '国崩']
|
||||
}
|
||||
|
||||
/*
|
||||
@ -48,13 +27,13 @@ export const customCharacters = {
|
||||
* */
|
||||
export const wifeData = {
|
||||
// 老婆&女朋友:成女、少女
|
||||
girlfriend: "伐难, 女士, 萍姥姥, 柯莱, 多莉",
|
||||
girlfriend: '雷神',
|
||||
|
||||
// 老公&男朋友:成男、少男
|
||||
boyfriend: "散兵, 白术, 提纳里",
|
||||
boyfriend: '散兵, 魈',
|
||||
|
||||
// 女儿:萝莉
|
||||
daughter: "派蒙, 瑶瑶",
|
||||
daughter: '派蒙, 瑶瑶',
|
||||
// 儿子:正太
|
||||
son: ""
|
||||
son: ''
|
||||
}
|
159
config/system/character.js
Normal file
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* 请不要直接修改此或删除此文件,防止后续更新冲突
|
||||
* 如需新增自定义角色可【复制】此文件,改名为character.js
|
||||
* 复制的character.js中可按格式及自己需求进行配置
|
||||
* 最终character.js character_default.js两份配置会叠加生效
|
||||
*
|
||||
* 暂未做热更新,修改完毕请重启yunzai
|
||||
* */
|
||||
|
||||
/*
|
||||
* 角色列表,别名的第一个是标准名字,后面的为别名
|
||||
* 实装的角色需要以数字roleid为key,自定义的角色及非实装角色请以英文为key
|
||||
* */
|
||||
export const characters = {
|
||||
10000003: ['琴', 'Jean', '团长', '代理团长', '琴团长', '蒲公英骑士'],
|
||||
10000006: ['丽莎', 'Lisa', '图书管理员', '图书馆管理员', '蔷薇魔女', '阿姨'],
|
||||
10000005: ['空', '男主', '男主角', '龙哥', '空哥', '男爷'],
|
||||
10000007: ['荧', '女主', '女主角', '莹', '萤', '黄毛阿姨', '荧妹', '女爷', '包包', '宴宁'],
|
||||
20000000: ['主角', '旅行者', '卑鄙的外乡人', '荣誉骑士', '爷', '风主', '岩主', '雷主', '履刑者', '抽卡不歪真君'],
|
||||
10000014: ['芭芭拉', 'Barbara', '巴巴拉', '拉粑粑', '拉巴巴', '内鬼', '加湿器', '肉身解咒', '肉身解咒真君', '闪耀偶像', '偶像'],
|
||||
10000015: ['凯亚', 'Kaeya', '盖亚', '凯子哥', '凯鸭', '矿工', '矿工头子', '骑兵队长', '凯子', '凝冰渡海真君'],
|
||||
10000016: ['迪卢克', 'Diluc', '卢姥爷', '姥爷', '卢老爷', '卢锅巴', '正义人', '正e人', '正E人', '卢本伟', '暗夜英雄', '卢卢伯爵', '落魄了', '落魄了家人们'],
|
||||
10000020: ['雷泽', 'Razor', '狼少年', '狼崽子', '狼崽', '卢皮卡', '小狼', '小狼狗', '狼孩'],
|
||||
10000021: ['安柏', 'Amber', '安伯', '兔兔伯爵', '飞行冠军', '侦查骑士', '点火姬', '点火机', '打火机', '打火姬'],
|
||||
10000022: ['温迪', 'Venti', '温蒂', '风神', '卖唱的', '巴巴托斯', '巴巴脱丝', '芭芭托斯', '芭芭脱丝', '干点正事', '不干正事', '吟游诗人', '诶嘿', '唉嘿', '摸鱼'],
|
||||
10000023: ['香菱', 'Xiangling', '香玲', '锅巴', '厨师', '万民堂厨师', '香师傅'],
|
||||
10000024: ['北斗', 'Beidou', '大姐头', '大姐', '无冕的龙王', '龙王'],
|
||||
10000025: ['行秋', 'Xingqiu', '秋秋人', '秋妹妹', '书呆子', '水神', '飞云商会二少爷'],
|
||||
10000026: ['魈', 'Xiao', '打桩机', '插秧', '三眼五显仙人', '三眼五显真人', '降魔大圣', '护法夜叉', '快乐风男', '无聊', '靖妖傩舞', '矮子仙人', '三点五尺仙人', '跳跳虎', '风夜叉'],
|
||||
10000027: ['凝光', 'Ningguang', '富婆', '天权星', '天权'],
|
||||
10000029: ['可莉', '逃跑的太阳', 'Klee', '嘟嘟可', '火花骑士', '蹦蹦炸弹', '炸鱼', '放火烧山', '放火烧山真君', '蒙德最强战力', '逃跑的太阳', '啦啦啦', '哒哒哒', '炸弹人', '禁闭室', '太阳', '小太阳'],
|
||||
10000030: ['钟离', 'Zhongli', '摩拉克斯', '岩王爷', '岩神', '钟师傅', '天动万象', '岩王帝君', '未来可期', '帝君', '拒收病婿'],
|
||||
10000031: ['菲谢尔', 'Fischl', '皇女', '小艾米', '小艾咪', '奥兹', '断罪皇女', '中二病', '中二少女', '中二皇女', '奥兹发射器'],
|
||||
10000032: ['班尼特', 'Bennett', '点赞哥', '点赞', '倒霉少年', '倒霉蛋', '霹雳闪雷真君', '班神', '班爷', '倒霉', '火神', '六星真神'],
|
||||
10000033: ['达达利亚', 'Tartaglia', 'Childe', 'Ajax', '达达鸭', '达达利鸭', '公子', '玩具销售员', '玩具推销员', '钱包', '鸭鸭', '愚人众末席'],
|
||||
10000034: ['诺艾尔', 'Noelle', '女仆', '高达', '岩王帝姬'],
|
||||
10000035: ['七七', 'Qiqi', '僵尸', '肚饿真君', '度厄真君', '77'],
|
||||
10000036: ['重云', 'Chongyun', '纯阳之体', '冰棍'],
|
||||
10000037: ['甘雨', 'Ganyu', '椰羊', '椰奶', '王小美'],
|
||||
10000038: ['阿贝多', 'Albedo', '可莉哥哥', '升降机', '升降台', '电梯', '白垩之子', '贝爷', '白垩', '阿贝少', '花呗多', '阿贝夕', '阿师傅'],
|
||||
10000039: ['迪奥娜', 'Diona', '迪欧娜', 'dio娜', '冰猫', '猫猫', '猫娘', '喵喵', '调酒师'],
|
||||
10000041: ['莫娜', 'Mona', '穷鬼', '穷光蛋', '穷', '莫纳', '占星术士', '占星师', '讨龙真君', '半部讨龙真君', '阿斯托洛吉斯·莫娜·梅姬斯图斯', '梅姬斯图斯', '梅姬斯图斯姬'],
|
||||
10000042: ['刻晴', 'Keqing', '刻情', '氪晴', '刻师傅', '刻师父', '牛杂', '牛杂师傅', '斩尽牛杂', '免疫', '免疫免疫', '屁斜剑法', '玉衡星', '阿晴', '啊晴', '璃月雷神'],
|
||||
10000043: ['砂糖', 'Sucrose', 'sucrose'],
|
||||
10000044: ['辛焱', 'Xinyan', '辛炎', '黑妹', '摇滚'],
|
||||
10000045: ['罗莎莉亚', 'Rosaria', '罗莎莉娅', '白色史莱姆', '白史莱姆', '修女', '罗莎利亚', '罗莎利娅', '罗沙莉亚', '罗沙莉娅', '罗沙利亚', '罗沙利娅', '萝莎莉亚', '萝莎莉娅', '萝莎利亚', '萝莎利娅', '萝沙莉亚', '萝沙莉娅', '萝沙利亚', '萝沙利娅'],
|
||||
10000046: ['胡桃', 'Hu Tao', 'HuTao', 'Hutao', '胡淘', '往生堂堂主', '火化', '抬棺的', '蝴蝶', '核桃', '堂主', '胡堂主', '雪霁梅香', '桃子', '桃'],
|
||||
10000047: ['枫原万叶', 'Kaedehara Kazuha', 'Kazuha', '万叶', '叶天帝', '天帝', '叶师傅'],
|
||||
10000048: ['烟绯', 'Yanfei', '烟老师', '律师', '罗翔'],
|
||||
10000051: ['优菈', 'Eula', '优拉', '尤拉', '尤菈', '浪花骑士', '记仇', '劳伦斯'],
|
||||
|
||||
// 2.0
|
||||
10000002: ['神里绫华', 'Kamisato Ayaka', 'Ayaka', '神里', '绫华', '神里凌华', '凌华', '白鹭公主', '神里大小姐', '龟', '龟龟', '乌龟'],
|
||||
10000049: ['宵宫', 'Yoimiya', '霄宫', '烟花', '肖宫', '肖工', '绷带女孩'],
|
||||
10000052: ['雷电将军', 'Raiden Shogun', 'Raiden', '雷神', '将军', '雷军', '巴尔', '阿影', '影', '巴尔泽布', '煮饭婆', '奶香一刀', '无想一刀', '宅女'],
|
||||
10000053: ['早柚', 'Sayu', '小狸猫', '狸猫', '忍者', '貉'],
|
||||
10000054: ['珊瑚宫心海', 'Sangonomiya Kokomi', 'Kokomi', '心海', '军师', '珊瑚宫', '书记', '观赏鱼', '水母', '鱼', '美人鱼'],
|
||||
10000056: ['九条裟罗', 'Kujou Sara', 'Sara', '九条', '九条沙罗', '裟罗', '沙罗', '天狗'],
|
||||
10000062: ['埃洛伊', 'Aloy'],
|
||||
10000050: ['托马', 'Thoma', '家政官', '太郎丸', '地头蛇', '男仆', '拖马'],
|
||||
10000055: ['五郎', 'Gorou', '柴犬', '土狗', '希娜', '希娜小姐'],
|
||||
10000057: ['荒泷一斗', 'Arataki Itto', 'Itto', '荒龙一斗', '荒泷天下第一斗', '一斗', '一抖', '荒泷', '1斗', '牛牛', '斗子哥', '牛子哥', '牛子', '孩子王', '斗虫', '巧乐兹', '放牛的'],
|
||||
10000058: ['八重神子', 'Yae Miko', 'Miko', '八重', '神子', '狐狸', '想得美哦', '巫女', '屑狐狸', '骚狐狸', '八重宫司', '婶子', '小八', '八重寄子', '寄子', '八神虫子', '八神重子'],
|
||||
10000059: ['鹿野院平藏', 'shikanoin heizou', 'Heizou', '鹿野苑', '鹿野院', '平藏', '鹿野苑平藏', '小鹿'],
|
||||
10000060: ['夜兰', 'Yelan', '夜阑', '叶澜', '腋兰', '夜天后'],
|
||||
10000063: ['申鹤', 'Shenhe', '神鹤', '小姨', '小姨子', '审鹤'],
|
||||
10000064: ['云堇', 'Yun Jin', 'yun jin', '云瑾', '云先生', '云锦', '神女劈观'],
|
||||
10000065: ['久岐忍', 'Kuki Shinobu', 'Kuki', 'Shinobu', '97忍', '小忍', '久歧忍', '97', '茄忍', '茄子', '紫茄子', '阿忍', '忍姐'],
|
||||
10000066: ['神里绫人', 'Kamisato Ayato', 'Ayato', '绫人', '神里凌人', '凌人', '0人', '神人', '零人', '大舅哥'],
|
||||
|
||||
// 3.0
|
||||
// ID暂无,使用临时ID代替
|
||||
10000100: ['提纳里', '提那里', '驴'],
|
||||
10000101: ['柯莱', '柯来', '科莱', '科来', '小天使'],
|
||||
10000102: ['多莉', '多利', '多力'],
|
||||
|
||||
// 以下为Miao新增自定义角色
|
||||
paimon: ['派蒙', '应急食物', '应急食品', '吉祥物', '宠物', '外置器官', '会说话的动物', '矮堇瓜', '飞行矮堇瓜', '最好的伙伴'],
|
||||
sb: ['散兵', '国崩', '雷电国崩', '大炮', '雷电大炮', '雷大炮', '伞兵'],
|
||||
nvshi: ['女士', '炽热的炎之魔女', '炎之魔女'],
|
||||
baizhu: ['白术', '长生'],
|
||||
yaoyao: ['瑶瑶', '遥遥', '遥遥无期'],
|
||||
fanan: ['伐难', '水夜叉'],
|
||||
yingda: ['应达', '火夜叉', '火鼠大将'],
|
||||
ping: ['萍姥姥', '歌尘浪市真君', '歌尘浪市', '萍儿'],
|
||||
puren: ['阿蕾奇诺', '仆人', '黑优菈', '黑暗优菈'],
|
||||
shaonv: ['哥伦比娅', '少女'],
|
||||
furen: ['潘塔罗涅', '富人', '黑白术', '黑术'],
|
||||
boshi: ['多托雷', '博士'],
|
||||
muou: ['桑多涅', '木偶']
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* 追加设置每个关系的可选角色,会与yunzai的设置同时起作用
|
||||
* 一个角色可以在多个关系中
|
||||
* */
|
||||
export const wifeData = {
|
||||
// 老婆&女朋友:成女、少女
|
||||
girlfriend: `琴,丽莎,荧,芭芭拉,安柏,香菱,北斗,凝光,菲谢尔,诺艾尔,甘雨,莫娜,刻晴,砂糖,辛焱,罗莎莉亚,胡桃,烟绯,优菈,神里绫华
|
||||
宵宫,雷电将军,珊瑚宫心海,九条裟罗,八重神子,埃洛伊,申鹤,云堇,夜兰,久岐忍,柯莱,多莉,伐难, 女士,萍姥姥,柯莱,多莉`,
|
||||
|
||||
// 老公&男朋友:成男、少男
|
||||
boyfriend: `空,凯亚,迪卢克,雷泽,温迪,行秋,魈,钟离,班尼特,达达利亚,重云,阿贝多,枫原万叶,托马,五郎,荒泷一斗,鹿野院平藏,神里绫人
|
||||
提纳里,散兵,白术,提纳里`,
|
||||
|
||||
// 女儿:萝莉
|
||||
daughter: '可莉,七七,迪奥娜,早柚,派蒙,瑶瑶',
|
||||
|
||||
// 儿子:正太
|
||||
son: ''
|
||||
}
|
||||
|
||||
export const abbr = {
|
||||
达达利亚: '公子',
|
||||
神里绫华: '绫华',
|
||||
神里绫人: '绫人',
|
||||
枫原万叶: '万叶',
|
||||
雷电将军: '雷神',
|
||||
珊瑚宫心海: '心海',
|
||||
荒泷一斗: '一斗',
|
||||
八重神子: '八重',
|
||||
九条裟罗: '九条',
|
||||
罗莎莉亚: '罗莎',
|
||||
鹿野院平藏: '平藏',
|
||||
|
||||
松籁响起之时: '松籁',
|
||||
无工之剑: '无工',
|
||||
狼的末路: '狼末',
|
||||
苍古自由之誓: '苍古',
|
||||
雾切之回光: '雾切',
|
||||
终末嗟叹之诗: '终末',
|
||||
阿莫斯之弓: '阿莫斯',
|
||||
冬极白星: '冬极',
|
||||
飞雷之弦振: '飞雷',
|
||||
护摩之杖: '护摩',
|
||||
薙草之稻光: '薙刀',
|
||||
赤角石溃杵: '赤角',
|
||||
嘟嘟可故事集: '嘟嘟可',
|
||||
讨龙英杰谭: '讨龙',
|
||||
'「渔获」': '渔获',
|
||||
天目影打刀: '天目刀',
|
||||
喜多院十文字: '喜多院',
|
||||
雪葬的星银: '雪葬星银',
|
||||
辰砂之纺锤: '辰砂纺锤',
|
||||
万国诸海图谱: '万国图谱',
|
||||
神乐之真意: '神乐',
|
||||
证誓之明瞳: '证誓明瞳',
|
||||
波乱月白经津: '波乱',
|
||||
笼钓瓶一心: '笼钓瓶',
|
||||
|
||||
角斗士的终幕礼: '角斗士',
|
||||
流浪大地的乐团: '流浪乐团',
|
||||
华馆梦醒形骸记: '华馆梦醒',
|
||||
平息鸣雷的尊者: '平雷尊者',
|
||||
炽烈的炎之魔女: '炽烈魔女',
|
||||
渡过烈火的贤人: '渡火贤人',
|
||||
冰风迷途的勇士: '冰风勇士'
|
||||
}
|
0
config/system/目录说明.txt
Normal file
@ -1,12 +0,0 @@
|
||||
/*
|
||||
* 请将此文件复制一份,命名为 config.js 放置在miao-plugin的根目录
|
||||
* 由于服务侧压力过大,目前已经暂停 #角色面板 token的发放,请见谅~
|
||||
* */
|
||||
|
||||
export const config = {
|
||||
/*miaoApi: {
|
||||
api: "http://49.232.91.210:88/miaoPlugin/getRoleAll", // Miao APi 地址
|
||||
qq: "", // 申请的主人qq
|
||||
token: "" // 申请的token,申请API Token请在Bot群内联系 @喵喵 或者 @九章
|
||||
}*/
|
||||
}
|
152
index.js
@ -1,136 +1,26 @@
|
||||
export {
|
||||
character,
|
||||
getProfile,
|
||||
wife,
|
||||
pokeWife,
|
||||
enemyLv,
|
||||
profileArtisList,
|
||||
getProfileAll,
|
||||
profileHelp,
|
||||
getOriginalPicture,
|
||||
uploadCharacterImg
|
||||
} from "./apps/character.js";
|
||||
// 适配V3 Yunzai,将index.js移至app/index.js
|
||||
import { currentVersion, isV3 } from './components/Changelog.js'
|
||||
import Data from './components/Data.js'
|
||||
|
||||
import { wifeReg } from "./apps/character.js";
|
||||
export * from './apps/index.js'
|
||||
let index = { miao: {} }
|
||||
if (isV3) {
|
||||
index = await Data.importModule('/plugins/miao-plugin/adapter', 'index.js')
|
||||
console.log(index)
|
||||
}
|
||||
export const miao = index.miao || {}
|
||||
|
||||
import { consStat, abyssPct, abyssTeam, uploadData } from "./apps/stat.js";
|
||||
import { wiki, calendar } from "./apps/wiki.js";
|
||||
import { help, versionInfo } from "./apps/help.js";
|
||||
import lodash from "lodash";
|
||||
import common from "../../lib/common.js";
|
||||
import { rule as adminRule, updateRes, sysCfg, updateMiaoPlugin, profileCfg } from "./apps/admin.js";
|
||||
import { currentVersion } from "./components/Changelog.js";
|
||||
|
||||
|
||||
export {
|
||||
consStat,
|
||||
abyssPct,
|
||||
abyssTeam,
|
||||
wiki,
|
||||
updateRes,
|
||||
updateMiaoPlugin,
|
||||
sysCfg,
|
||||
help,
|
||||
versionInfo,
|
||||
calendar,
|
||||
profileCfg,
|
||||
uploadData
|
||||
};
|
||||
|
||||
|
||||
let rule = {
|
||||
character: {
|
||||
reg: "^(#(.*)|#*(更新|录入)?(.*)(详细|详情|面板|面版|伤害[1-7]?)(更新)?)$",
|
||||
//reg: "noCheck",
|
||||
describe: "【#角色】角色详情",
|
||||
},
|
||||
uploadCharacterImg: {
|
||||
reg: "^#*(喵喵)?(上传|添加)(.+)(照片|写真|图片|图像)\\s*$",
|
||||
describe: "喵喵上传角色写真",
|
||||
},
|
||||
profileArtisList: {
|
||||
reg: "^#圣遗物列表\\s*(\\d{9})?$",
|
||||
describe: "【#角色】圣遗物列表",
|
||||
},
|
||||
getProfileAll: {
|
||||
reg: "^#(面板角色|角色面板|面板)(列表)?\\s*(\\d{9})?$",
|
||||
describe: "【#角色】查看当前已获取面板数据的角色列表",
|
||||
},
|
||||
profileHelp: {
|
||||
reg: "^#角色面板帮助$",
|
||||
describe: "【#角色】查看当前已获取面板数据的角色列表",
|
||||
},
|
||||
wife: {
|
||||
reg: wifeReg,
|
||||
describe: "【#角色】#老公 #老婆 查询",
|
||||
},
|
||||
pokeWife: {
|
||||
reg: "#poke#",
|
||||
describe: "【#角色】戳一戳",
|
||||
},
|
||||
getOriginalPicture: {
|
||||
reg: "^#?(获取|给我|我要|求|发|发下|发个|发一下)?原图(吧|呗)?$",
|
||||
describe: "【#原图】 回复角色卡片,可获取原图",
|
||||
},
|
||||
consStat: {
|
||||
reg: "^#(喵喵)?角色(持有|持有率|命座|命之座|.命)(分布|统计|持有|持有率)?$",
|
||||
describe: "【#统计】 #角色持有率 #角色5命统计",
|
||||
},
|
||||
abyssPct: {
|
||||
reg: "^#(喵喵)?深渊(第?.{1,2}层)?(角色)?(出场|使用)(率|统计)*$",
|
||||
describe: "【#统计】 #深渊出场率 #深渊12层出场率",
|
||||
},
|
||||
abyssTeam: {
|
||||
reg: "#深渊(组队|配队)",
|
||||
describe: "【#角色】 #深渊组队",
|
||||
},
|
||||
wiki: {
|
||||
reg: "^(#|喵喵)?.*(天赋|技能|命座|命之座|资料|照片|写真|图片|图像)$",
|
||||
describe: "【#资料】 #神里天赋 #夜兰命座",
|
||||
},
|
||||
help: {
|
||||
reg: "^#?(喵喵)?(命令|帮助|菜单|help|说明|功能|指令|使用说明)$",
|
||||
describe: "【#帮助】 #喵喵帮助",
|
||||
},
|
||||
getProfile: {
|
||||
reg: "^#(全部面板更新|更新全部面板|获取游戏角色详情|更新面板|面板更新)\\s*(\\d{9})?$",
|
||||
describe: "【#角色】 获取游戏橱窗详情数据",
|
||||
},
|
||||
enemyLv: {
|
||||
reg: "^#(敌人|怪物)等级\\s*\\d{1,3}\\s*$",
|
||||
describe: "【#角色】 设置伤害计算中目标敌人的等级",
|
||||
},
|
||||
versionInfo: {
|
||||
reg: "^#?喵喵版本$",
|
||||
describe: "【#帮助】 喵喵版本介绍",
|
||||
},
|
||||
calendar: {
|
||||
reg: "^(#|喵喵)+(日历|日历列表)$",
|
||||
describe: "【#日历】 活动日历",
|
||||
},
|
||||
uploadData: {
|
||||
reg: "^#上传(深渊|数据)+$"
|
||||
},
|
||||
...adminRule
|
||||
};
|
||||
|
||||
lodash.forEach(rule, (r) => {
|
||||
r.priority = r.priority || 50;
|
||||
r.prehash = true;
|
||||
r.hashMark = true;
|
||||
});
|
||||
|
||||
export { rule };
|
||||
|
||||
console.log(`喵喵插件${currentVersion}初始化~`);
|
||||
console.log(`喵喵插件${currentVersion}初始化~`)
|
||||
|
||||
setTimeout(async function () {
|
||||
let msgStr = await redis.get("miao:restart-msg");
|
||||
if (msgStr) {
|
||||
let msg = JSON.parse(msgStr);
|
||||
await common.relpyPrivate(msg.qq, msg.msg);
|
||||
await redis.del("miao:restart-msg");
|
||||
let msgs = [`当前喵喵版本: ${currentVersion}`, `您可使用 #喵喵版本 命令查看更新信息`];
|
||||
await common.relpyPrivate(msg.qq, msgs.join("\n"));
|
||||
let msgStr = await redis.get('miao:restart-msg')
|
||||
let relpyPrivate = async function () {
|
||||
}
|
||||
}, 1000);
|
||||
if (msgStr) {
|
||||
let msg = JSON.parse(msgStr)
|
||||
await relpyPrivate(msg.qq, msg.msg)
|
||||
await redis.del('miao:restart-msg')
|
||||
let msgs = [`当前喵喵版本: ${currentVersion}`, '您可使用 #喵喵版本 命令查看更新信息']
|
||||
await relpyPrivate(msg.qq, msgs.join('\n'))
|
||||
}
|
||||
}, 1000)
|
||||
|
@ -38,7 +38,7 @@
|
||||
<div class="item arti">
|
||||
{{if ds && ds.name && ds.main && ds.main.title && ds.main.title!="undefined"}}
|
||||
<div class="arti-icon">
|
||||
<img src="{{_sys_res_path}}/genshin/logo/reliquaries/{{ds.name}}.png"/>
|
||||
<img src="{{_res_path}}/meta/reliquaries/icon/{{ds.name}}.png"/>
|
||||
<span>+{{ds.level}}</span>
|
||||
</div>
|
||||
<div class="head">
|
||||
|
@ -17,7 +17,7 @@
|
||||
<img src="{{_res_path}}meta/character/{{ds.avatar}}/side.png" onerror="whenError(this)"/>
|
||||
</div>
|
||||
<div class="arti-icon">
|
||||
<img src="{{_sys_res_path}}/genshin/logo/reliquaries/{{ds.name}}.png"/>
|
||||
<img src="{{_res_path}}/meta/reliquaries/icon/{{ds.name}}.png"/>
|
||||
</div>
|
||||
<div class="head">
|
||||
<strong>{{ds.name}}</strong>
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
<div class="weapon">
|
||||
<div class="weapon_cont">
|
||||
<img title="{{weapon.name}}" src="{{_sys_res_path}}/genshin/logo/weapon/{{weapon.name}}.png"/>
|
||||
<img title="{{weapon.name}}" src="{{_res_path}}/meta/weapons/icon/{{weapon.name}}.png"/>
|
||||
|
||||
<p class="weapon_lv">Lv.{{weapon.level}}</p>
|
||||
<p class="weapon_affix">{{weapon.affix}}</p>
|
||||
|
@ -56,7 +56,7 @@
|
||||
<div class="artis">
|
||||
<div>
|
||||
<div class="item weapon">
|
||||
<img src="{{_sys_res_path}}/genshin/logo/weapon/{{weapon.name}}.png"/>
|
||||
<img src="{{_res_path}}/meta/weapons/icon/{{weapon.name}}.png"/>
|
||||
<div class="head">
|
||||
<strong>{{weapon.name}}</strong>
|
||||
<div class="star star-{{weapon.star}}"></div>
|
||||
@ -73,7 +73,7 @@
|
||||
<div class="item arti">
|
||||
{{if ds && ds.name && ds.main && ds.main.title && ds.main.title!="undefined"}}
|
||||
<div class="arti-icon">
|
||||
<img src="{{_sys_res_path}}/genshin/logo/reliquaries/{{ds.name}}.png"/>
|
||||
<img src="{{_res_path}}/meta/reliquaries/icon/{{ds.name}}.png"/>
|
||||
<span>+{{ds.level}}</span>
|
||||
</div>
|
||||
<div class="head">
|
||||
@ -114,7 +114,7 @@
|
||||
<div class="artis input-mode">
|
||||
|
||||
<div class="item weapon">
|
||||
<img src="{{_sys_res_path}}/genshin/logo/weapon/{{weapon.name}}.png"/>
|
||||
<img src="{{_res_path}}/meta/weapons/icon/{{weapon.name}}.png"/>
|
||||
<div class="head">
|
||||
<strong>{{weapon.name}}</strong>
|
||||
<div class="star star-{{weapon.star}}"></div>
|
||||
@ -127,7 +127,7 @@
|
||||
<div class="item arti">
|
||||
{{if ds && ds.name }}
|
||||
<div class="arti-icon">
|
||||
<img src="{{_sys_res_path}}/genshin/logo/reliquaries/{{ds.name}}.png"/>
|
||||
<img src="{{_res_path}}/meta/reliquaries/icon/{{ds.name}}.png"/>
|
||||
<span>+{{ds.level}}</span>
|
||||
</div>
|
||||
<div class="head">
|
||||
|
BIN
resources/common/cont/logo.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
@ -1,12 +1,12 @@
|
||||
{{set ds = $data[0]}}
|
||||
{{set {_res_path,_char,_sys_res_path} = $data[1]}}
|
||||
{{set {_res_path,_char} = $data[1]}}
|
||||
{{if ds.name && ds.main && ds.main[0] && ds.main[0]!="undefined"}}
|
||||
<div class="item arti-detail">
|
||||
<div class="avatar-icon">
|
||||
<img src="{{_res_path}}/meta/character/{{ds.avatar}}/side.png" onerror="whenError(this)"/>
|
||||
</div>
|
||||
<div class="arti-icon">
|
||||
<img src="{{_sys_res_path}}/genshin/logo/reliquaries/{{ds.name}}.png"/>
|
||||
<img src="{{_res_path}}/meta/reliquaries/icon/{{ds.name}}.png"/>
|
||||
</div>
|
||||
<div class="head">
|
||||
<strong>{{ds.name}}</strong>
|
||||
|
@ -1,9 +1,9 @@
|
||||
{{set ds = $data[0]}}
|
||||
{{set {_res_path,_char,_sys_res_path} = $data[1]}}
|
||||
{{set {_res_path,_char} = $data[1]}}
|
||||
|
||||
<div class="item-card">
|
||||
<span class="badge">
|
||||
<img src="{{_sys_res_path}}/genshin/logo/side/{{ds.avatar==`旅行者`?`荧`:ds.avatar}}.png"/>
|
||||
<img src="{{_res_path}}/meta/character/{{ds.avatar==`旅行者`?`荧`:ds.avatar}}/side.png"/>
|
||||
</span>
|
||||
<div class="box">
|
||||
{{ if ds.affix_level>1}}
|
||||
@ -12,7 +12,7 @@
|
||||
</span>
|
||||
{{/if}}
|
||||
<div class="item-bg bg{{ds.rarity}}"></div>
|
||||
<img class="item-img" src="{{_sys_res_path}}/genshin/logo/reliquaries/{{ds.name}}.png"/>
|
||||
<img class="item-img" src="{{_res_path}}/meta/reliquaries/icon/{{ds.name}}.png"/>
|
||||
<div class="item-desc artis-lvl">Lv.{{ds.level}}</div>
|
||||
<div class="item-desc artis-name">{{ds.name}}</div>
|
||||
</div>
|
||||
|
@ -1,5 +1,5 @@
|
||||
{{set ds = $data[0]}}
|
||||
{{set {_res_path, _char, _sys_res_path, uid} = $data[1]}}
|
||||
{{set {_res_path, _char, uid} = $data[1]}}
|
||||
{{set {attr} = ds}}
|
||||
|
||||
<div class="profile">
|
||||
|
@ -1,16 +1,15 @@
|
||||
{{ set weapon = $data[0] }}
|
||||
{{ set {_sys_res_path} = $data[1] }}
|
||||
|
||||
<div class="item-card">
|
||||
<span class="badge">
|
||||
<img src="{{_sys_res_path}}/genshin/logo/side/{{weapon.avatar==`旅行者`?`荧`:weapon.avatar}}.png"/>
|
||||
<img src="{{_res_path}}/meta/character/{{weapon.avatar==`旅行者`?`荧`:weapon.avatar}}/side.png"/>
|
||||
</span>
|
||||
<div class="box">
|
||||
{{ if weapon.affix_level>1}}
|
||||
<span class="item-life life{{weapon.affix_level}}">{{weapon.affix_level}}</span>
|
||||
{{/if}}
|
||||
<div class="item-bg bg{{weapon.rarity}}"></div>
|
||||
<img class="item-img" src="{{_sys_res_path}}genshin/logo/weapon/{{weapon.name}}.png"/>
|
||||
<img class="item-img" src="{{_res_path}}/meta/weapons/icon//{{weapon.name}}.png"/>
|
||||
<div class="item-desc weapon-lv">Lv.{{weapon.level}}</div>
|
||||
<div class="item-desc weapon-name">{{weapon.showName || weapon.name}}</div>
|
||||
</div>
|
||||
|
BIN
resources/meta/reliquaries/icon/不动玄石之相.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
resources/meta/reliquaries/icon/乐团的晨光.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
resources/meta/reliquaries/icon/众生之谣.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
resources/meta/reliquaries/icon/停摆之刻.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
resources/meta/reliquaries/icon/冒险家之花.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
resources/meta/reliquaries/icon/冒险家头带.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
resources/meta/reliquaries/icon/冒险家尾羽.png
Normal file
After Width: | Height: | Size: 9.7 KiB |
BIN
resources/meta/reliquaries/icon/冒险家怀表.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
resources/meta/reliquaries/icon/冒险家金杯.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
resources/meta/reliquaries/icon/冰雪故园的终期.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
resources/meta/reliquaries/icon/切落之羽.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
resources/meta/reliquaries/icon/勇士的冠冕.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
resources/meta/reliquaries/icon/勇士的勋章.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
resources/meta/reliquaries/icon/勇士的坚毅.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
resources/meta/reliquaries/icon/勇士的壮行.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
resources/meta/reliquaries/icon/勇士的期许.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
resources/meta/reliquaries/icon/勋绩之花.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
resources/meta/reliquaries/icon/华饰之兜.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
resources/meta/reliquaries/icon/华馆之羽.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
resources/meta/reliquaries/icon/历经风雪的思念.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
resources/meta/reliquaries/icon/吟游者之壶.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
resources/meta/reliquaries/icon/唤雷的头冠.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
resources/meta/reliquaries/icon/嗤笑之面.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
resources/meta/reliquaries/icon/坚铜罗盘.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
resources/meta/reliquaries/icon/垂玉之叶.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
resources/meta/reliquaries/icon/夏祭之刻.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
resources/meta/reliquaries/icon/夏祭之花.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
resources/meta/reliquaries/icon/夏祭之面.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
resources/meta/reliquaries/icon/夏祭水玉.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
resources/meta/reliquaries/icon/夏祭终末.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
resources/meta/reliquaries/icon/奇迹之杯.png
Normal file
After Width: | Height: | Size: 9.5 KiB |
BIN
resources/meta/reliquaries/icon/奇迹之沙.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
resources/meta/reliquaries/icon/奇迹之羽.png
Normal file
After Width: | Height: | Size: 9.7 KiB |
BIN
resources/meta/reliquaries/icon/奇迹之花.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
resources/meta/reliquaries/icon/奇迹耳坠.png
Normal file
After Width: | Height: | Size: 8.4 KiB |
BIN
resources/meta/reliquaries/icon/学士的书签.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
resources/meta/reliquaries/icon/学士的墨杯.png
Normal file
After Width: | Height: | Size: 9.3 KiB |
BIN
resources/meta/reliquaries/icon/学士的时钟.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
resources/meta/reliquaries/icon/学士的羽笔.png
Normal file
After Width: | Height: | Size: 9.2 KiB |
BIN
resources/meta/reliquaries/icon/学士的镜片.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
resources/meta/reliquaries/icon/守护之皿.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
resources/meta/reliquaries/icon/守护之花.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
resources/meta/reliquaries/icon/守护座钟.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
resources/meta/reliquaries/icon/守护徽印.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
resources/meta/reliquaries/icon/守护束带.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
resources/meta/reliquaries/icon/宗室之翎.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
resources/meta/reliquaries/icon/宗室之花.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
resources/meta/reliquaries/icon/宗室时计.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
resources/meta/reliquaries/icon/宗室银瓮.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
resources/meta/reliquaries/icon/宗室面具.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
resources/meta/reliquaries/icon/将帅兜鍪.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
resources/meta/reliquaries/icon/少女易逝的芳颜.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
resources/meta/reliquaries/icon/少女片刻的闲暇.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
resources/meta/reliquaries/icon/少女苦短的良辰.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
resources/meta/reliquaries/icon/少女飘摇的思念.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
resources/meta/reliquaries/icon/嵯峨群峰之翼.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
resources/meta/reliquaries/icon/巉岩琢塑之樽.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
resources/meta/reliquaries/icon/平雷之冠.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
resources/meta/reliquaries/icon/平雷之刻.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
resources/meta/reliquaries/icon/平雷之器.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
resources/meta/reliquaries/icon/平雷之心.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
resources/meta/reliquaries/icon/平雷之羽.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
resources/meta/reliquaries/icon/幸运儿之杯.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
resources/meta/reliquaries/icon/幸运儿沙漏.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
resources/meta/reliquaries/icon/幸运儿绿花.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
resources/meta/reliquaries/icon/幸运儿银冠.png
Normal file
After Width: | Height: | Size: 10 KiB |