monsterxcn / nonebot-plugin-gspanel

🤖 NoneBot2 原神游戏内角色展柜数据展示插件,参考 @yoimiya-kokomi/miao-plugin
https://pypi.python.org/pypi/nonebot-plugin-gspanel
MIT License
97 stars 8 forks source link

编写脚本自动更新喵喵的评分规则 #59

Closed forchannot closed 1 year ago

forchannot commented 1 year ago

功能请求

实现代码如下

import asyncio
import aiohttp
import re
import json

from collections import OrderedDict

miao_artis_mark_url = "https://gitee.com/yoimiya-kokomi/miao-plugin/raw/master/resources/meta-gs/artifact/artis-mark.js"

github_url = "https://api.github.com/repos/yoimiya-kokomi/miao-plugin/contents/resources/meta-gs/character/"

gitee_url = "https://gitee.com/yoimiya-kokomi/miao-plugin/raw/master/resources/meta-gs/character/"

trans_table = {
    "hp": "生命值百分比",
    "atk": "攻击力百分比",
    "def": "防御力百分比",
    "cpct": "暴击率",
    "cdmg": "暴击伤害",
    "mastery": "元素精通",
    "dmg": "元素伤害加成",
    "phy": "物理伤害加成",
    "heal": "治疗加成",
    "recharge": "元素充能效率",
}

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ",
    "Authorization": "Bearer your own fine-grained personal access token",
}

def insert_keys(original_data, new_data):
    ordered_data = OrderedDict(original_data)
    for key, value in new_data.items():
        if '-' in key:
            main_key, _ = key.split('-')
            keys = list(ordered_data.keys())
            if main_key in keys:
                position = keys.index(main_key)
                keys.insert(position + 1, key)
                ordered_data = OrderedDict((k, ordered_data.get(k, value)) for k in keys)
    return ordered_data

async def get_data(session, url, pattern, headers=None):
    async with session.get(url, headers=headers) as response:
        text = await response.text()
    data = {}
    for line in text.split("\n"):
        match = re.match(pattern, line.strip())
        if match:
            character = match.group(1).strip()
            attributes_str = match.group(2).strip()
            attributes = {}
            for attr_str in attributes_str.split(","):
                key, value = attr_str.split(":")
                key = key.strip()
                value = int(value.strip())
                if key in trans_table:
                    key = trans_table[key]
                if value != 0:
                    attributes[key] = value
            data[character] = attributes
    return data

async def get_special_characters(session, url, headers, name):
    async with session.get(url, headers=headers) as response:
        items = await response.json()
    list = []
    for item in items:
        if "artis.js" == item["name"]:
            list.append(name)
    return list

async def main():
    async with aiohttp.ClientSession() as session:
        all_data = await get_data(session, miao_artis_mark_url, r"(.+?)\s*:\s*\{(.+?)\},")
        special_characters_tasks = [
            get_special_characters(session, github_url + name, headers, name)
            for name in all_data.keys()
        ]
        special_characters_nested = await asyncio.gather(*special_characters_tasks)
        special_characters = [
            item for sublist in special_characters_nested for item in sublist
        ]
        special_data_tasks = [
            get_data(
                session,
                gitee_url + f"{name}/artis.js",
                r"return rule\('(.+?)', \{(.+?)\}\)",
            )
            for name in special_characters
        ]
        special_data = await asyncio.gather(*special_data_tasks)
        for data in special_data:
            all_data = insert_keys(all_data, data)
            all_data.update(all_data)
    with open("artis-mark.json", "w", encoding="utf-8") as f:
        f.write(json.dumps(all_data, indent=2, ensure_ascii=False))

if __name__ == "__main__":
    asyncio.run(main())

生成结果如下 artis-mark.json

代码存在改进,但初步实现了,不过发现本仓库规则是和喵喵不完全一致,可以考虑使用喵喵新规则 改进的地方:不用github api,改为请求后验证status_code

- github_url = "https://api.github.com/repos/yoimiya-kokomi/miao-plugin/contents/resources/meta-gs/character/"

- headers = {
-   "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ",
-   "Authorization": "Bearer your own fine-grained personal access token",
-}
-           get_special_characters(session, github_url + name, headers, name)
+           get_special_characters(session, gitee_url + f"{name}/artis.js, name)

-async def get_special_characters(session, url, headers, name):
-   async with session.get(url, headers=headers) as response:
-       items = await response.json()
-   list = []
-   for item in items:
-       if "artis.js" == item["name"]:
-           list.append(name)
-   return list
+async def get_special_characters(session, url, name):
+   special_name = []
+   async with session.get(url) as response:
+       if response.status == 200:
+           special_name.append(name)
+   return special_name
forchannot commented 1 year ago

理论上别名也可以这样干,代码如下,不过好像本仓库用的别名不同于喵喵

import json
import re
from pathlib import Path

import requests

urls = {
    "角色": "https://raw.githubusercontent.com/yoimiya-kokomi/miao-plugin/master/resources/meta-gs/character/alias.js",
    # "武器": "https://raw.githubusercontent.com/yoimiya-kokomi/miao-plugin/master/resources/meta-gs/weapon/alias.js",
}

result_dict = {"角色": {}}

for alias_type, url in urls.items():
    js_text = requests.get(url).text
    match = re.search(r"export const alias = {(.*?)}", js_text, re.DOTALL)
    if match:
        js_text = match.group(1)
        lines = js_text.split("\n")
        for line in lines:
            line = line.strip()
            if line.startswith("/") or not line:
                continue
            key, value = line.split(":")
            key = key.strip()
            value = value.strip().strip(",").strip("'")
            result_dict[alias_type][key] = value.split(",")
        #for k, v in result_dict[alias_type].items():
            #v.insert(0, k)

with open(
    Path("./alias.json"), "w", encoding="utf-8"
) as f:
    json.dump(result_dict, f, indent=2, ensure_ascii=False)

输出 alias.json

monsterxcn commented 1 year ago

感谢。

以前写过用 GitHub Actions 更新评分规则,这个不是很麻烦。但是后来发现喵喵仓库的 artis-mark.js 不全,那个时候 miao-plugin 才刚开始做多流派评分,角色的评分规则放到单独的 .js 文件里去了。现在已经很久不关注面板和评分了,不知道现在 artis-mark.js 是否还能保证是最合适的评分规则?

forchannot commented 1 year ago

看了下,基本上都算比较符合,然后一些特殊的流派放在了character/${name}/artis.js里面,在这里也是全部收在一起了的,不过要完全适配喵喵的话可能得适当更改一些流派的识别,比如宵宫的话他默认是通用流派,然后加上了蒸发流派和纯火流派

monsterxcn commented 1 year ago

感谢您提供的关于提取特殊评分规则的思路,虽然这些规则现在还没什么用,但是总归有点什么用。

关于自动更新最终能否发挥作用还是要看喵喵の脸色,谢谢喵

鉴于版本更新时间不定,目前仍保持旧的更新资源方式:手动触发 GitHub Action 来更新 CDN 上的 JSON 资源,本地重启 NoneBot2 后自动更新 JSON 资源。

现隆重邀请您加入此仓库合作者身份(主要用于在版本更新后及时手动触发 GitHub Action),以使我正式进入冬眠,感谢!