🍱 更新基础资源, 提高加载速度
@ -1,12 +1,28 @@
|
|||||||
import json
|
import json
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
path = Path(__file__).parent
|
import aiofiles
|
||||||
with open(path / 'all_achi.json', "r", encoding='UTF-8') as f:
|
from gsuid_core.server import on_core_start
|
||||||
all_achi = json.load(f)
|
|
||||||
|
path = Path(__file__).parent
|
||||||
|
all_achi = {}
|
||||||
|
daily_achi = {}
|
||||||
|
|
||||||
|
|
||||||
|
@on_core_start
|
||||||
|
async def load_data():
|
||||||
|
global all_achi, daily_achi
|
||||||
|
|
||||||
|
async with aiofiles.open(
|
||||||
|
path / 'all_achi.json', "r", encoding='UTF-8'
|
||||||
|
) as f:
|
||||||
|
all_achi = json.loads(await f.read())
|
||||||
|
|
||||||
|
async with aiofiles.open(
|
||||||
|
path / 'daily_achi.json', "r", encoding='UTF-8'
|
||||||
|
) as f:
|
||||||
|
daily_achi = json.loads(await f.read())
|
||||||
|
|
||||||
with open(path / 'daily_achi.json', "r", encoding='UTF-8') as f:
|
|
||||||
daily_achi = json.load(f)
|
|
||||||
|
|
||||||
daily_template = '''任务:【{}】
|
daily_template = '''任务:【{}】
|
||||||
成就:【{}】
|
成就:【{}】
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import re
|
import re
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
from PIL import Image, ImageOps, ImageDraw
|
from PIL import Image, ImageOps, ImageDraw
|
||||||
@ -18,13 +19,22 @@ from ..utils.image.image_tools import (
|
|||||||
|
|
||||||
assets_dir = Path(__file__).parent / 'assets'
|
assets_dir = Path(__file__).parent / 'assets'
|
||||||
|
|
||||||
list_head = Image.open(assets_dir / 'list.png')
|
list_head: Optional[Image.Image] = None
|
||||||
list_item = (
|
list_item: Optional[Image.Image] = None
|
||||||
Image.open(assets_dir / 'item.png').resize((384, 96)).convert('RGBA')
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def ann_list_card() -> bytes:
|
async def ann_list_card() -> bytes:
|
||||||
|
global list_head, list_item
|
||||||
|
if not list_head:
|
||||||
|
list_head = Image.open(assets_dir / 'list.png')
|
||||||
|
|
||||||
|
if not list_item:
|
||||||
|
list_item = (
|
||||||
|
Image.open(assets_dir / 'item.png')
|
||||||
|
.resize((384, 96))
|
||||||
|
.convert('RGBA')
|
||||||
|
)
|
||||||
|
|
||||||
ann_list = await ann().get_ann_list()
|
ann_list = await ann().get_ann_list()
|
||||||
if not ann_list:
|
if not ann_list:
|
||||||
raise Exception('获取游戏公告失败,请检查接口是否正常')
|
raise Exception('获取游戏公告失败,请检查接口是否正常')
|
||||||
@ -159,7 +169,7 @@ async def ann_detail_card(ann_id):
|
|||||||
bbox = gs_font_26.getbbox('囗')
|
bbox = gs_font_26.getbbox('囗')
|
||||||
_x, _y = bbox[2] - bbox[0], bbox[3] - bbox[1]
|
_x, _y = bbox[2] - bbox[0], bbox[3] - bbox[1]
|
||||||
|
|
||||||
padding = (_x, _y, _x, _y)
|
padding = (int(_x), int(_y), int(_x), int(_y))
|
||||||
im = ImageOps.expand(im, padding, '#f9f6f2')
|
im = ImageOps.expand(im, padding, '#f9f6f2')
|
||||||
|
|
||||||
return await convert_img(im)
|
return await convert_img(im)
|
||||||
|
@ -14,17 +14,17 @@ yyy_data = {
|
|||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
# 5.5影月月数据
|
# 5.7影月月数据
|
||||||
# 2025.3.27
|
# 2025.5.18
|
||||||
yyy_data = {
|
yyy_data = {
|
||||||
'成就': 1458,
|
'成就': 1458,
|
||||||
'华丽的宝箱': 325,
|
'华丽的宝箱': 325,
|
||||||
'珍贵的宝箱': 851,
|
'珍贵的宝箱': 851,
|
||||||
'精致的宝箱': 2714,
|
'精致的宝箱': 2717,
|
||||||
'普通的宝箱': 3317,
|
'普通的宝箱': 3318,
|
||||||
'奇馈宝箱': 316,
|
'奇馈宝箱': 316,
|
||||||
'解锁传送点': 580,
|
'解锁传送点': 584,
|
||||||
'解锁秘境': 63,
|
'解锁秘境': 64,
|
||||||
}
|
}
|
||||||
|
|
||||||
# 影月月没收集到的数据
|
# 影月月没收集到的数据
|
||||||
|
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 1.7 MiB |
Before Width: | Height: | Size: 160 KiB After Width: | Height: | Size: 505 KiB |
Before Width: | Height: | Size: 142 KiB After Width: | Height: | Size: 460 KiB |
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 1.7 MiB |
@ -1,7 +1,5 @@
|
|||||||
import asyncio
|
|
||||||
import threading
|
|
||||||
|
|
||||||
from gsuid_core.logger import logger
|
from gsuid_core.logger import logger
|
||||||
|
from gsuid_core.server import on_core_start
|
||||||
|
|
||||||
from ..genshinuid_resource import startup
|
from ..genshinuid_resource import startup
|
||||||
|
|
||||||
@ -11,12 +9,16 @@ from ..genshinuid_guide.get_new_abyss_data import download_Oceanid
|
|||||||
# from ..genshinuid_enka.start import check_artifacts_list
|
# from ..genshinuid_enka.start import check_artifacts_list
|
||||||
# from ..genshinuid_guide.get_abyss_data import generate_data
|
# from ..genshinuid_guide.get_abyss_data import generate_data
|
||||||
from ..utils.resource.generate_char_card import create_all_char_card
|
from ..utils.resource.generate_char_card import create_all_char_card
|
||||||
|
|
||||||
|
'''
|
||||||
from ..genshinuid_xkdata.get_all_char_data import (
|
from ..genshinuid_xkdata.get_all_char_data import (
|
||||||
save_all_char_info,
|
save_all_char_info,
|
||||||
save_all_abyss_rank,
|
save_all_abyss_rank,
|
||||||
)
|
)
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
@on_core_start
|
||||||
async def all_start():
|
async def all_start():
|
||||||
try:
|
try:
|
||||||
await download_Oceanid()
|
await download_Oceanid()
|
||||||
@ -25,10 +27,7 @@ async def all_start():
|
|||||||
await create_all_char_card()
|
await create_all_char_card()
|
||||||
# await draw_teyvat_abyss_img()
|
# await draw_teyvat_abyss_img()
|
||||||
# await generate_data()
|
# await generate_data()
|
||||||
await save_all_char_info()
|
# await save_all_char_info()
|
||||||
await save_all_abyss_rank()
|
# await save_all_abyss_rank()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(e)
|
logger.exception(e)
|
||||||
|
|
||||||
|
|
||||||
threading.Thread(target=lambda: asyncio.run(all_start()), daemon=True).start()
|
|
||||||
|
@ -134,5 +134,5 @@ def download_namecard_pic(start: int = 10000002):
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# download_namecard_pic(10000063)
|
download_namecard_pic(10000063)
|
||||||
main()
|
# main()
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict, List, TypedDict
|
from typing import Dict, List, TypedDict
|
||||||
|
|
||||||
|
import aiofiles
|
||||||
from msgspec import json as msgjson
|
from msgspec import json as msgjson
|
||||||
from gsuid_core.logger import logger
|
from gsuid_core.logger import logger
|
||||||
|
from gsuid_core.server import on_core_start
|
||||||
|
|
||||||
from ...version import Genshin_version
|
from ...version import Genshin_version
|
||||||
|
|
||||||
@ -38,89 +40,194 @@ class TS(TypedDict):
|
|||||||
Icon: Dict[str, str]
|
Icon: Dict[str, str]
|
||||||
|
|
||||||
|
|
||||||
try:
|
charList: Dict[str, str] = {}
|
||||||
with open(MAP / charList_fileName, 'r', encoding='UTF-8') as f:
|
weaponList: Dict[str, str] = {}
|
||||||
charList = msgjson.decode(f.read(), type=Dict)
|
avatarId2Name: Dict[str, str] = {}
|
||||||
|
icon2Name: Dict[str, str] = {}
|
||||||
|
artifact2attr: Dict[str, str] = {}
|
||||||
|
name2Icon: Dict[str, str] = {}
|
||||||
|
avatarName2Element: Dict[str, str] = {}
|
||||||
|
avatarName2Weapon: Dict[str, str] = {}
|
||||||
|
mysData: Dict = {}
|
||||||
|
propId2Name: Dict[str, str] = {}
|
||||||
|
Id2PropId: Dict[str, str] = {}
|
||||||
|
artifactId2Piece: Dict[str, List[str]] = {}
|
||||||
|
skillId2Name: TS = TS(Name={}, Icon={})
|
||||||
|
talentId2Name: TS = TS(Name={}, Icon={})
|
||||||
|
weaponHash2Name: Dict[str, str] = {}
|
||||||
|
weaponHash2Type: Dict[str, str] = {}
|
||||||
|
alias_data: Dict[str, List[str]] = {}
|
||||||
|
avatarId2Star_data: Dict[str, str] = {}
|
||||||
|
enName_to_avatarId_data: Dict[str, str] = {}
|
||||||
|
ex_monster_data: Dict[str, Dict] = {}
|
||||||
|
monster2entry_data: Dict[str, Dict] = {}
|
||||||
|
avatarId2SkillList_data: Dict[str, Dict[str, str]] = {}
|
||||||
|
weaponId2Name_data: Dict[str, str] = {}
|
||||||
|
CharId2TalentIcon_data: Dict[str, List[str]] = {}
|
||||||
|
|
||||||
with open(MAP / weaponList_fileName, 'r', encoding='UTF-8') as f:
|
|
||||||
weaponList = msgjson.decode(f.read(), type=Dict)
|
|
||||||
|
|
||||||
with open(MAP / avatarId2Name_fileName, 'r', encoding='UTF-8') as f:
|
@on_core_start
|
||||||
avatarId2Name = msgjson.decode(f.read(), type=Dict[str, str])
|
async def load_map():
|
||||||
|
global charList, weaponList, avatarId2Name, icon2Name
|
||||||
|
global artifact2attr, name2Icon, avatarName2Element
|
||||||
|
global avatarName2Weapon, mysData, talentId2Name
|
||||||
|
global propId2Name, Id2PropId, artifactId2Piece, skillId2Name
|
||||||
|
global weaponHash2Name, weaponHash2Type, alias_data, avatarId2Star_data
|
||||||
|
global enName_to_avatarId_data, ex_monster_data, monster2entry_data
|
||||||
|
global avatarId2SkillList_data, weaponId2Name_data, CharId2TalentIcon_data
|
||||||
|
logger.info('[GenshinUID MAP] 正在加载资源文件...')
|
||||||
|
|
||||||
with open(MAP / icon2Name_fileName, 'r', encoding='UTF-8') as f:
|
try:
|
||||||
icon2Name = msgjson.decode(f.read(), type=Dict[str, str])
|
async with aiofiles.open(
|
||||||
|
MAP / charList_fileName, 'r', encoding='UTF-8'
|
||||||
|
) as f:
|
||||||
|
charList = msgjson.decode(await f.read(), type=Dict)
|
||||||
|
|
||||||
with open(MAP / artifact2attr_fileName, 'r', encoding='UTF-8') as f:
|
async with aiofiles.open(
|
||||||
artifact2attr = msgjson.decode(f.read(), type=Dict[str, str])
|
MAP / weaponList_fileName, 'r', encoding='UTF-8'
|
||||||
|
) as f:
|
||||||
|
weaponList = msgjson.decode(await f.read(), type=Dict)
|
||||||
|
|
||||||
with open(MAP / icon2Name_fileName, 'r', encoding='UTF-8') as f:
|
async with aiofiles.open(
|
||||||
icon2Name = msgjson.decode(f.read(), type=Dict[str, str])
|
MAP / avatarId2Name_fileName, 'r', encoding='UTF-8'
|
||||||
|
) as f:
|
||||||
|
avatarId2Name = msgjson.decode(await f.read(), type=Dict[str, str])
|
||||||
|
|
||||||
with open(MAP / name2Icon_fileName, 'r', encoding='UTF-8') as f:
|
async with aiofiles.open(
|
||||||
name2Icon = msgjson.decode(f.read(), type=Dict[str, str])
|
MAP / icon2Name_fileName, 'r', encoding='UTF-8'
|
||||||
|
) as f:
|
||||||
|
icon2Name = msgjson.decode(await f.read(), type=Dict[str, str])
|
||||||
|
|
||||||
with open(MAP / 'propId2Name_mapping.json', 'r', encoding='UTF-8') as f:
|
async with aiofiles.open(
|
||||||
propId2Name = msgjson.decode(f.read(), type=Dict[str, str])
|
MAP / artifact2attr_fileName, 'r', encoding='UTF-8'
|
||||||
|
) as f:
|
||||||
|
artifact2attr = msgjson.decode(await f.read(), type=Dict[str, str])
|
||||||
|
|
||||||
with open(MAP / 'Id2propId_mapping.json', 'r', encoding='UTF-8') as f:
|
async with aiofiles.open(
|
||||||
Id2PropId = msgjson.decode(f.read(), type=Dict[str, str])
|
MAP / icon2Name_fileName, 'r', encoding='UTF-8'
|
||||||
|
) as f:
|
||||||
|
icon2Name = msgjson.decode(await f.read(), type=Dict[str, str])
|
||||||
|
|
||||||
with open(MAP / weaponHash2Name_fileName, 'r', encoding='UTF-8') as f:
|
async with aiofiles.open(
|
||||||
weaponHash2Name = msgjson.decode(f.read(), type=Dict[str, str])
|
MAP / name2Icon_fileName, 'r', encoding='UTF-8'
|
||||||
|
) as f:
|
||||||
|
name2Icon = msgjson.decode(await f.read(), type=Dict[str, str])
|
||||||
|
|
||||||
with open(MAP / weaponHash2Type_fileName, 'r', encoding='UTF-8') as f:
|
async with aiofiles.open(
|
||||||
weaponHash2Type = msgjson.decode(f.read(), type=Dict[str, str])
|
MAP / 'propId2Name_mapping.json', 'r', encoding='UTF-8'
|
||||||
|
) as f:
|
||||||
|
propId2Name = msgjson.decode(await f.read(), type=Dict[str, str])
|
||||||
|
|
||||||
with open(
|
async with aiofiles.open(
|
||||||
MAP / 'artifactId2Piece_mapping.json', 'r', encoding='UTF-8'
|
MAP / 'Id2propId_mapping.json', 'r', encoding='UTF-8'
|
||||||
) as f:
|
) as f:
|
||||||
artifactId2Piece = msgjson.decode(f.read(), type=Dict[str, List[str]])
|
Id2PropId = msgjson.decode(await f.read(), type=Dict[str, str])
|
||||||
|
|
||||||
with open(MAP / skillId2Name_fileName, 'r', encoding='UTF-8') as f:
|
async with aiofiles.open(
|
||||||
skillId2Name = msgjson.decode(f.read(), type=TS)
|
MAP / weaponHash2Name_fileName, 'r', encoding='UTF-8'
|
||||||
|
) as f:
|
||||||
|
weaponHash2Name = msgjson.decode(
|
||||||
|
await f.read(), type=Dict[str, str]
|
||||||
|
)
|
||||||
|
|
||||||
with open(MAP / talentId2Name_fileName, 'r', encoding='UTF-8') as f:
|
async with aiofiles.open(
|
||||||
talentId2Name = msgjson.decode(f.read(), type=TS)
|
MAP / weaponHash2Type_fileName, 'r', encoding='UTF-8'
|
||||||
|
) as f:
|
||||||
|
weaponHash2Type = msgjson.decode(
|
||||||
|
await f.read(), type=Dict[str, str]
|
||||||
|
)
|
||||||
|
|
||||||
with open(MAP / avatarName2Element_fileName, 'r', encoding='UTF-8') as f:
|
async with aiofiles.open(
|
||||||
avatarName2Element = msgjson.decode(f.read(), type=Dict[str, str])
|
MAP / 'artifactId2Piece_mapping.json', 'r', encoding='UTF-8'
|
||||||
|
) as f:
|
||||||
|
artifactId2Piece = msgjson.decode(
|
||||||
|
await f.read(), type=Dict[str, List[str]]
|
||||||
|
)
|
||||||
|
|
||||||
with open(MAP / avatarName2Weapon_fileName, 'r', encoding='UTF-8') as f:
|
async with aiofiles.open(
|
||||||
avatarName2Weapon = msgjson.decode(f.read(), type=Dict[str, str])
|
MAP / skillId2Name_fileName, 'r', encoding='UTF-8'
|
||||||
|
) as f:
|
||||||
|
skillId2Name = msgjson.decode(await f.read(), type=TS)
|
||||||
|
|
||||||
with open(MAP / 'char_alias.json', 'r', encoding='UTF-8') as f:
|
async with aiofiles.open(
|
||||||
alias_data = msgjson.decode(f.read(), type=Dict[str, List[str]])
|
MAP / talentId2Name_fileName, 'r', encoding='UTF-8'
|
||||||
|
) as f:
|
||||||
|
talentId2Name = msgjson.decode(await f.read(), type=TS)
|
||||||
|
|
||||||
with open(MAP / avatarId2Star_fileName, 'r', encoding='utf8') as f:
|
async with aiofiles.open(
|
||||||
avatarId2Star_data = msgjson.decode(f.read(), type=Dict[str, str])
|
MAP / avatarName2Element_fileName, 'r', encoding='UTF-8'
|
||||||
|
) as f:
|
||||||
|
avatarName2Element = msgjson.decode(
|
||||||
|
await f.read(), type=Dict[str, str]
|
||||||
|
)
|
||||||
|
|
||||||
with open(MAP / avatarId2Star_fileName, 'r', encoding='utf8') as f:
|
async with aiofiles.open(
|
||||||
avatarId2Star_data = msgjson.decode(f.read(), type=Dict[str, str])
|
MAP / avatarName2Weapon_fileName, 'r', encoding='UTF-8'
|
||||||
|
) as f:
|
||||||
|
avatarName2Weapon = msgjson.decode(
|
||||||
|
await f.read(), type=Dict[str, str]
|
||||||
|
)
|
||||||
|
|
||||||
with open(MAP / enName2Id_fileName, 'r', encoding='utf8') as f:
|
async with aiofiles.open(
|
||||||
enName_to_avatarId_data = msgjson.decode(f.read(), type=Dict[str, str])
|
MAP / 'char_alias.json', 'r', encoding='UTF-8'
|
||||||
|
) as f:
|
||||||
|
alias_data = msgjson.decode(
|
||||||
|
await f.read(), type=Dict[str, List[str]]
|
||||||
|
)
|
||||||
|
|
||||||
with open(MAP / EXMonster_fileName, 'r', encoding='utf8') as f:
|
async with aiofiles.open(
|
||||||
ex_monster_data = msgjson.decode(f.read(), type=Dict[str, Dict])
|
MAP / avatarId2Star_fileName, 'r', encoding='utf8'
|
||||||
|
) as f:
|
||||||
|
avatarId2Star_data = msgjson.decode(
|
||||||
|
await f.read(), type=Dict[str, str]
|
||||||
|
)
|
||||||
|
|
||||||
with open(MAP / monster2entry_fileName, 'r', encoding='utf8') as f:
|
async with aiofiles.open(
|
||||||
monster2entry_data = msgjson.decode(f.read(), type=Dict[str, Dict])
|
MAP / enName2Id_fileName, 'r', encoding='utf8'
|
||||||
|
) as f:
|
||||||
|
enName_to_avatarId_data = msgjson.decode(
|
||||||
|
await f.read(), type=Dict[str, str]
|
||||||
|
)
|
||||||
|
|
||||||
with open(MAP / avatarId2SkillList_fileName, 'r', encoding='utf8') as f:
|
async with aiofiles.open(
|
||||||
avatarId2SkillList_data = msgjson.decode(
|
MAP / EXMonster_fileName, 'r', encoding='utf8'
|
||||||
f.read(), type=Dict[str, Dict[str, str]]
|
) as f:
|
||||||
)
|
ex_monster_data = msgjson.decode(
|
||||||
|
await f.read(), type=Dict[str, Dict]
|
||||||
|
)
|
||||||
|
|
||||||
with open(MAP / weaponId2Name_fileName, 'r', encoding='utf8') as f:
|
async with aiofiles.open(
|
||||||
weaponId2Name_data = msgjson.decode(f.read(), type=Dict[str, str])
|
MAP / monster2entry_fileName, 'r', encoding='utf8'
|
||||||
|
) as f:
|
||||||
|
monster2entry_data = msgjson.decode(
|
||||||
|
await f.read(), type=Dict[str, Dict]
|
||||||
|
)
|
||||||
|
|
||||||
with open(MAP / mysData_fileName, 'r', encoding='utf8') as f:
|
async with aiofiles.open(
|
||||||
mysData = msgjson.decode(f.read(), type=Dict)
|
MAP / avatarId2SkillList_fileName, 'r', encoding='utf8'
|
||||||
|
) as f:
|
||||||
|
avatarId2SkillList_data = msgjson.decode(
|
||||||
|
await f.read(), type=Dict[str, Dict[str, str]]
|
||||||
|
)
|
||||||
|
|
||||||
with open(MAP / CharId2TalentIcon_fileName, 'r', encoding='utf8') as f:
|
async with aiofiles.open(
|
||||||
CharId2TalentIcon_data = msgjson.decode(
|
MAP / weaponId2Name_fileName, 'r', encoding='utf8'
|
||||||
f.read(), type=Dict[str, List[str]]
|
) as f:
|
||||||
)
|
weaponId2Name_data = msgjson.decode(
|
||||||
except FileNotFoundError:
|
await f.read(), type=Dict[str, str]
|
||||||
logger.error('[GenshinUID] 未找到对应版本的映射文件')
|
)
|
||||||
|
|
||||||
|
async with aiofiles.open(
|
||||||
|
MAP / mysData_fileName, 'r', encoding='utf8'
|
||||||
|
) as f:
|
||||||
|
mysData = msgjson.decode(await f.read(), type=Dict)
|
||||||
|
|
||||||
|
async with aiofiles.open(
|
||||||
|
MAP / CharId2TalentIcon_fileName, 'r', encoding='utf8'
|
||||||
|
) as f:
|
||||||
|
CharId2TalentIcon_data = msgjson.decode(
|
||||||
|
await f.read(), type=Dict[str, List[str]]
|
||||||
|
)
|
||||||
|
logger.success('[GenshinUID MAP] 资源文件加载完成')
|
||||||
|
except FileNotFoundError:
|
||||||
|
logger.error('[GenshinUID] 未找到对应版本的映射文件')
|
||||||
|
@ -1,11 +1,6 @@
|
|||||||
import asyncio
|
|
||||||
|
|
||||||
from .download_from_miniggicu import download_all_file_from_miniggicu
|
from .download_from_miniggicu import download_all_file_from_miniggicu
|
||||||
|
|
||||||
|
|
||||||
async def download_all_resource():
|
async def download_all_resource():
|
||||||
ret = await asyncio.gather(download_all_file_from_miniggicu())
|
await download_all_file_from_miniggicu()
|
||||||
ret = [str(x) for x in ret if x]
|
|
||||||
if ret:
|
|
||||||
return '\n'.join(ret)
|
|
||||||
return 'Genshin全部资源下载完成!'
|
return 'Genshin全部资源下载完成!'
|
||||||
|