Support starrail material light_cone

This commit is contained in:
xtaodada 2023-05-03 00:16:14 +08:00
parent 26e9f6dcbb
commit b7396a7171
Signed by: xtaodada
GPG Key ID: 4CBB3F4FA8C85659
12 changed files with 356 additions and 124 deletions

View File

@ -3,7 +3,7 @@ from typing import List
from core.base_service import BaseService
from core.dependence.redisdb import RedisDB
__all__ = ["GameCache", "GameCacheForStrategy"]
__all__ = ["GameCache", "GameCacheForStrategy", "GameCacheForMaterial", "GameCacheForLightCone"]
class GameCache:
@ -24,10 +24,6 @@ class GameCache:
await self.client.expire(qname, self.ttl)
return await self.client.llen(qname)
class GameCacheForStrategy(BaseService.Component, GameCache):
qname = "game:strategy"
async def get_file(self, character_name: str):
qname = f"{self.qname}:{character_name}"
return await self.client.get(qname)
@ -36,3 +32,15 @@ class GameCacheForStrategy(BaseService.Component, GameCache):
qname = f"{self.qname}:{character_name}"
await self.client.set(qname, file)
await self.client.expire(qname, self.ttl)
class GameCacheForStrategy(BaseService.Component, GameCache):
qname = "game:strategy"
class GameCacheForMaterial(BaseService.Component, GameCache):
qname = "game:material"
class GameCacheForLightCone(BaseService.Component, GameCache):
qname = "game:lightcone"

View File

@ -1,17 +1,40 @@
from core.base_service import BaseService
from core.services.game.cache import GameCacheForStrategy
from core.services.game.cache import GameCacheForStrategy, GameCacheForMaterial, GameCacheForLightCone
__all__ = "GameStrategyService"
__all__ = "GameCacheService"
class GameStrategyService(BaseService):
def __init__(self, cache: GameCacheForStrategy):
self._cache = cache
class GameCacheService(BaseService):
def __init__(
self,
strategy_cache: GameCacheForStrategy,
material_cache: GameCacheForMaterial,
light_cone_cache: GameCacheForLightCone,
):
self.strategy_cache = strategy_cache
self.material_cache = material_cache
self.light_cone_cache = light_cone_cache
async def get_strategy_cache(self, character_name: str) -> str:
cache = await self._cache.get_file(character_name)
cache = await self.strategy_cache.get_file(character_name)
if cache is not None:
return cache
async def set_strategy_cache(self, character_name: str, file: str) -> None:
await self._cache.set_file(character_name, file)
await self.strategy_cache.set_file(character_name, file)
async def get_material_cache(self, character_name: str) -> str:
cache = await self.material_cache.get_file(character_name)
if cache is not None:
return cache
async def set_material_cache(self, character_name: str, file: str) -> None:
await self.material_cache.set_file(character_name, file)
async def get_light_cone_cache(self, light_cone_name: str) -> str:
cache = await self.light_cone_cache.get_file(light_cone_name)
if cache is not None:
return cache
async def set_light_cone_cache(self, light_cone_name: str, file: str) -> None:
await self.light_cone_cache.set_file(light_cone_name, file)

View File

@ -147,3 +147,10 @@ def roleToTag(role_name: str) -> List[str]:
"""通过角色名获取TAG"""
role_name = str.casefold(role_name)
return next((value for value in roles.values() if value[0] == role_name), [role_name])
@functools.lru_cache()
def lightConeToTag(name: str) -> List[str]:
"""通过光锥名获取TAG"""
name = str.casefold(name)
return next((value for value in light_cones.values() if value[0] == name), [name])

View File

@ -16,55 +16,33 @@ if TYPE_CHECKING:
class Calendar:
"""原神活动日历"""
"""活动日历"""
ANNOUNCEMENT_LIST = "https://hk4e-api.mihoyo.com/common/hk4e_cn/announcement/api/getAnnList"
ANNOUNCEMENT_CONTENT = "https://hk4e-api.mihoyo.com/common/hk4e_cn/announcement/api/getAnnContent"
ANNOUNCEMENT_LIST = "https://hkrpg-api.mihoyo.com/common/hkrpg_cn/announcement/api/getAnnList"
ANNOUNCEMENT_CONTENT = "https://hkrpg-api-static.mihoyo.com/common/hkrpg_cn/announcement/api/getAnnContent"
ANNOUNCEMENT_PARAMS = {
"game": "hk4e",
"game_biz": "hk4e_cn",
"game": "hkrpg",
"game_biz": "hkrpg_cn",
"lang": "zh-cn",
"bundle_id": "hk4e_cn",
"bundle_id": "hkrpg_cn",
"platform": "pc",
"region": "cn_gf01",
"region": "prod_gf_cn",
"level": "55",
"uid": "100000000",
}
MIAO_API = "http://miaoapi.cn/api/calendar"
IGNORE_IDS = [
495, # 有奖问卷调查开启!
1263, # 米游社《原神》专属工具一览
423, # 《原神》玩家社区一览
422, # 《原神》防沉迷系统说明
762, # 《原神》公平运营声明
762, # 《原神》公平运营声明
194, # 有奖问卷调查开启!
183, # 官方社群一览
171, # 米游社《崩坏:星穹铁道》专属工具一览
187, # 《崩坏:星穹铁道》防沉迷系统公告
185, # 《崩坏:星穹铁道》公平运营声明
]
IGNORE_RE = re.compile(r"(内容专题页|版本更新说明|调研|防沉迷|米游社|专项意见|更新修复与优化|问卷调查|版本更新通知|更新时间说明|预下载功能|周边限时|周边上新|角色演示)")
IGNORE_RE = re.compile(r"(内容专题页|版本更新说明|调研|防沉迷|米游社|专项意见|游戏优化及已知问题说明|问卷调查|版本更新通知|更新时间说明|预下载功能|周边限时|周边上新|角色演示)")
FULL_TIME_RE = re.compile(r"(魔神任务)")
def __init__(self):
self.client = AsyncClient()
@staticmethod
async def async_gen_birthday_list() -> Dict[str, List[str]]:
"""生成生日列表并且合并云端生日列表"""
birthday_list = Calendar.gen_birthday_list()
remote_data = await Remote.get_remote_birthday()
if remote_data:
birthday_list.update(remote_data)
return birthday_list
@staticmethod
def gen_birthday_list() -> Dict[str, List[str]]:
"""生成生日列表"""
birthday_list = {}
for value in AVATAR_DATA.values():
key = "_".join([str(i) for i in value["birthday"]])
data = birthday_list.get(key, [])
data.append(value["name"])
birthday_list[key] = data
return birthday_list
@staticmethod
def get_now_hour() -> datetime:
"""获取当前时间"""

View File

@ -1,46 +1,54 @@
import asyncio
from typing import List
from typing import List, Dict
from modules.wiki.base import WikiModel
class Raider(WikiModel):
raider_url = WikiModel.BASE_URL + "raiders/"
raider_url = "https://raw.githubusercontent.com/PaiGramTeam/star-rail-atlas/master"
raider_path = WikiModel.BASE_PATH / "raiders"
raider_info_path = WikiModel.BASE_PATH / "raiders" / "info.json"
raider_path.mkdir(parents=True, exist_ok=True)
raider_role_path = WikiModel.BASE_PATH / "raiders" / "role"
raider_light_cone_path = WikiModel.BASE_PATH / "raiders" / "light_cone"
raider_role_material_path = WikiModel.BASE_PATH / "raiders" / "role_material"
raider_info_path = WikiModel.BASE_PATH / "raiders" / "path.json"
raider_role_path.mkdir(parents=True, exist_ok=True)
raider_light_cone_path.mkdir(parents=True, exist_ok=True)
raider_role_material_path.mkdir(parents=True, exist_ok=True)
name_map = {"role": "role", "lightcone": "light_cone", "material for role": "role_material"}
def __init__(self):
super().__init__()
self.all_raiders: List[str] = []
self.all_role_raiders: List[str] = []
self.all_light_cone_raiders: List[str] = []
self.all_role_material_raiders: List[str] = []
def clear_class_data(self) -> None:
self.all_raiders.clear()
self.all_role_raiders.clear()
self.all_light_cone_raiders.clear()
self.all_role_material_raiders.clear()
async def refresh_task(self, name: str):
photo = await self.remote_get(f"{self.raider_url}{name}.png")
await self.save_file(photo.content, self.raider_path / f"{name}.png")
async def refresh_task(self, name: str, path: str = "", start: str = ""):
photo = await self.remote_get(f"{self.raider_url}{path}")
await self.save_file(photo.content, self.raider_path / start / f"{name}.png")
async def refresh(self):
datas = await self.remote_get(self.raider_url + "info.json")
datas = await self.remote_get(self.raider_url + "/path.json")
data = datas.json()
tasks = []
for name in data:
tasks.append(self.refresh_task(name))
await asyncio.gather(*tasks)
await self.dump(data, self.raider_info_path)
new_data = {}
for key, start in self.name_map.items():
new_data[start] = list(data[key].keys())
tasks = []
for name, path in data[key].items():
tasks.append(self.refresh_task(name, path, start))
await asyncio.gather(*tasks)
await self.dump(new_data, self.raider_info_path)
await self.read()
async def read(self):
if not self.raider_info_path.exists():
await self.refresh()
return
datas = await WikiModel.read(self.raider_info_path)
datas: Dict[str, List] = await WikiModel.read(self.raider_info_path)
self.clear_class_data()
for data in datas:
self.all_raiders.append(data)
def get_name_list(self) -> List[str]:
return self.all_raiders.copy()
def get_item_id(self, name: str) -> int:
return self.all_raiders.index(name)
self.all_role_raiders.extend(datas["role"])
self.all_light_cone_raiders.extend(datas["light_cone"])
self.all_role_material_raiders.extend(datas["role_material"])

View File

@ -15,6 +15,7 @@ from telegram.error import BadRequest
from telegram.ext import CallbackContext, InlineQueryHandler
from core.plugin import Plugin, handler
from core.dependence.assets import AssetsService
from core.services.search.services import SearchServices
from core.services.wiki.services import WikiService
from utils.log import logger
@ -25,25 +26,40 @@ class Inline(Plugin):
def __init__(
self,
wiki_service: WikiService,
asset_service: AssetsService,
search_service: SearchServices,
wiki_service: WikiService,
):
self.asset_service = asset_service
self.wiki_service = wiki_service
self.weapons_list: List[Dict[str, str]] = []
self.characters_list: List[Dict[str, str]] = []
self.characters_material_list: List[Dict[str, str]] = []
self.light_cone_list: List[Dict[str, str]] = []
self.refresh_task: List[Awaitable] = []
self.search_service = search_service
async def initialize(self):
async def task_light_cone():
logger.info("Inline 模块正在获取光锥列表")
light_cone_datas: Dict[str, str] = {}
for light_cone in self.asset_service.light_cone.data:
light_cone_datas[light_cone.name] = light_cone.icon_
# 光锥列表
for light_cone in self.wiki_service.raider.all_light_cone_raiders:
if light_cone in light_cone_datas:
self.light_cone_list.append({"name": light_cone, "icon": light_cone_datas[light_cone]})
else:
logger.warning(f"未找到光锥 {light_cone} 的图标inline 不显示此光锥")
logger.success("Inline 模块获取光锥列表完成")
async def task_characters():
logger.info("Inline 模块正在获取角色列表")
datas: Dict[str, str] = {}
for character in self.wiki_service.character.all_avatars:
if not character.icon:
logger.warning(f"角色 {character.name} 无图标")
continue
datas[character.name] = character.icon
for character in self.wiki_service.raider.get_name_list():
for character in self.asset_service.avatar.data:
datas[character.name] = character.square or character.normal
# 角色攻略
for character in self.wiki_service.raider.all_role_raiders:
if character in datas:
self.characters_list.append({"name": character, "icon": datas[character]})
else:
@ -51,11 +67,21 @@ class Inline(Plugin):
if character.startswith(key):
self.characters_list.append({"name": character, "icon": value})
break
# 角色培养素材
for character in self.wiki_service.raider.all_role_material_raiders:
if character in datas:
self.characters_material_list.append({"name": character, "icon": datas[character]})
else:
for key, value in datas.items():
if character.startswith(key):
self.characters_material_list.append({"name": character, "icon": value})
break
logger.success("Inline 模块获取角色列表成功")
self.refresh_task.append(asyncio.create_task(task_characters()))
self.refresh_task.append(asyncio.create_task(task_light_cone()))
@handler(InlineQueryHandler, block=False)
@handler.inline_query(block=False)
async def inline_query(self, update: Update, _: CallbackContext) -> None:
user = update.effective_user
ilq = cast(InlineQuery, update.inline_query)
@ -65,27 +91,34 @@ class Inline(Plugin):
results_list = []
args = query.split(" ")
if args[0] == "":
results_list.append(
InlineQueryResultArticle(
id=str(uuid4()),
title="角色攻略查询",
description="输入角色名即可查询角色攻略",
input_message_content=InputTextMessageContent("角色攻略查询"),
temp_data = [("光锥图鉴查询", "输入光锥名称即可查询光锥图鉴"), ("角色攻略查询", "输入角色名即可查询角色攻略图鉴")]
for i in temp_data:
results_list.append(
InlineQueryResultArticle(
id=str(uuid4()),
title=i[0],
description=i[1],
input_message_content=InputTextMessageContent(i[0]),
)
)
)
else:
if args[0] == "查看角色攻略列表并查询":
for character in self.characters_list:
if args[0] in ["查看角色攻略列表并查询", "查看角色培养素材列表并查询", "查看光锥列表并查询"]:
temp_data = {
"查看角色攻略列表并查询": (self.characters_list, "角色攻略查询"),
"查看角色培养素材列表并查询": (self.characters_material_list, "角色培养素材查询"),
"查看光锥列表并查询": (self.light_cone_list, "光锥查询"),
}[args[0]]
for character in temp_data[0]:
name = character["name"]
icon = character["icon"]
results_list.append(
InlineQueryResultArticle(
id=str(uuid4()),
title=name,
description=f"查看角色攻略列表并查询 {name}",
description=f"{args[0]} {name}",
thumb_url=icon,
input_message_content=InputTextMessageContent(
f"角色攻略查询{name}", parse_mode=ParseMode.MARKDOWN_V2
f"{temp_data[1]}{name}", parse_mode=ParseMode.MARKDOWN_V2
),
)
)

View File

@ -58,7 +58,7 @@ class DailyNotePlugin(Plugin):
"expeditions": bool(daily_info.expeditions),
"remained_time": remained_time,
"current_expeditions": len(daily_info.expeditions),
"max_expeditions": daily_info.accepted_epedition_num,
"max_expeditions": daily_info.total_expedition_num,
}
render_result = await self.template_service.render(
"starrail/daily_note/daily_note.html",

View File

@ -0,0 +1,88 @@
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
from telegram.constants import ChatAction, ParseMode
from telegram.ext import CallbackContext, filters
from core.plugin import Plugin, handler
from core.services.game.services import GameCacheService
from core.services.search.models import StrategyEntry
from core.services.search.services import SearchServices
from core.services.wiki.services import WikiService
from metadata.shortname import lightConeToTag, lightConeToName
from utils.log import logger
class LightConePlugin(Plugin):
"""光锥图鉴查询"""
KEYBOARD = [[InlineKeyboardButton(text="查看光锥列表并查询", switch_inline_query_current_chat="查看光锥列表并查询")]]
def __init__(
self,
cache_service: GameCacheService = None,
wiki_service: WikiService = None,
search_service: SearchServices = None,
):
self.cache_service = cache_service
self.wiki_service = wiki_service
self.search_service = search_service
@handler.command(command="light_cone", block=False)
@handler.message(filters=filters.Regex("^光锥查询(.*)"), block=False)
async def command_start(self, update: Update, context: CallbackContext) -> None:
message = update.effective_message
user = update.effective_user
args = self.get_args(context)
if len(args) >= 1:
light_cone_name = args[0]
else:
reply_message = await message.reply_text(
"请回复你要查询的光锥名称",
reply_markup=InlineKeyboardMarkup(self.KEYBOARD)
)
if filters.ChatType.GROUPS.filter(reply_message):
self.add_delete_message_job(message)
self.add_delete_message_job(reply_message)
return
light_cone_name = lightConeToName(light_cone_name)
file_path = self.wiki_service.raider.raider_light_cone_path / f"{light_cone_name}.png"
if not file_path.exists():
reply_message = await message.reply_text(
f"没有找到 {light_cone_name} 的光锥图鉴", reply_markup=InlineKeyboardMarkup(self.KEYBOARD)
)
if filters.ChatType.GROUPS.filter(reply_message):
self.add_delete_message_job(message)
self.add_delete_message_job(reply_message)
return
logger.info("用户 %s[%s] 查询光锥图鉴命令请求 || 参数 %s", user.full_name, user.id, light_cone_name)
await message.reply_chat_action(ChatAction.UPLOAD_PHOTO)
caption = "From 米游社@听语惊花"
if file_id := await self.cache_service.get_light_cone_cache(light_cone_name):
await message.reply_photo(
photo=file_id,
caption=caption,
filename=f"{light_cone_name}.png",
allow_sending_without_reply=True,
parse_mode=ParseMode.HTML,
)
else:
reply_photo = await message.reply_photo(
photo=open(file_path, "rb"),
caption=caption,
filename=f"{light_cone_name}.png",
allow_sending_without_reply=True,
parse_mode=ParseMode.HTML,
)
if reply_photo.photo:
tags = lightConeToTag(light_cone_name)
photo_file_id = reply_photo.photo[0].file_id
await self.cache_service.set_light_cone_cache(light_cone_name, photo_file_id)
entry = StrategyEntry(
key=f"plugin:strategy:{light_cone_name}",
title=light_cone_name,
description=f"{light_cone_name} 光锥图鉴",
tags=tags,
caption=caption,
parse_mode="HTML",
photo_file_id=photo_file_id,
)
await self.search_service.add_entry(entry)

View File

@ -0,0 +1,88 @@
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
from telegram.constants import ChatAction, ParseMode
from telegram.ext import CallbackContext, filters
from core.plugin import Plugin, handler
from core.services.game.services import GameCacheService
from core.services.search.models import StrategyEntry
from core.services.search.services import SearchServices
from core.services.wiki.services import WikiService
from metadata.shortname import roleToName, roleToTag
from utils.log import logger
class MaterialPlugin(Plugin):
"""角色培养素材查询"""
KEYBOARD = [[InlineKeyboardButton(text="查看角色培养素材列表并查询", switch_inline_query_current_chat="查看角色培养素材列表并查询")]]
def __init__(
self,
cache_service: GameCacheService = None,
wiki_service: WikiService = None,
search_service: SearchServices = None,
):
self.cache_service = cache_service
self.wiki_service = wiki_service
self.search_service = search_service
@handler.command(command="material", block=False)
@handler.message(filters=filters.Regex("^角色培养素材查询(.*)"), block=False)
async def command_start(self, update: Update, context: CallbackContext) -> None:
message = update.effective_message
user = update.effective_user
args = self.get_args(context)
if len(args) >= 1:
character_name = args[0]
else:
reply_message = await message.reply_text(
"请回复你要查询的角色培养素材图鉴的角色名",
reply_markup=InlineKeyboardMarkup(self.KEYBOARD)
)
if filters.ChatType.GROUPS.filter(reply_message):
self.add_delete_message_job(message)
self.add_delete_message_job(reply_message)
return
character_name = roleToName(character_name)
file_path = self.wiki_service.raider.raider_role_material_path / f"{character_name}.png"
if not file_path.exists():
reply_message = await message.reply_text(
f"没有找到 {character_name} 的角色培养素材图鉴", reply_markup=InlineKeyboardMarkup(self.KEYBOARD)
)
if filters.ChatType.GROUPS.filter(reply_message):
self.add_delete_message_job(message)
self.add_delete_message_job(reply_message)
return
logger.info("用户 %s[%s] 查询角色培养素材命令请求 || 参数 %s", user.full_name, user.id, character_name)
await message.reply_chat_action(ChatAction.UPLOAD_PHOTO)
caption = "From 米游社@听语惊花"
if file_id := await self.cache_service.get_material_cache(character_name):
await message.reply_photo(
photo=file_id,
caption=caption,
filename=f"{character_name}.png",
allow_sending_without_reply=True,
parse_mode=ParseMode.HTML,
)
else:
reply_photo = await message.reply_photo(
photo=open(file_path, "rb"),
caption=caption,
filename=f"{character_name}.png",
allow_sending_without_reply=True,
parse_mode=ParseMode.HTML,
)
if reply_photo.photo:
tags = roleToTag(character_name)
photo_file_id = reply_photo.photo[0].file_id
await self.cache_service.set_material_cache(character_name, photo_file_id)
entry = StrategyEntry(
key=f"plugin:strategy:{character_name}",
title=character_name,
description=f"{character_name} 角色攻略",
tags=tags,
caption=caption,
parse_mode="HTML",
photo_file_id=photo_file_id,
)
await self.search_service.add_entry(entry)

View File

@ -3,7 +3,7 @@ from telegram.constants import ChatAction, ParseMode
from telegram.ext import CallbackContext, filters
from core.plugin import Plugin, handler
from core.services.game.services import GameStrategyService
from core.services.game.services import GameCacheService
from core.services.search.models import StrategyEntry
from core.services.search.services import SearchServices
from core.services.wiki.services import WikiService
@ -18,7 +18,7 @@ class StrategyPlugin(Plugin):
def __init__(
self,
cache_service: GameStrategyService = None,
cache_service: GameCacheService = None,
wiki_service: WikiService = None,
search_service: SearchServices = None,
):
@ -41,7 +41,7 @@ class StrategyPlugin(Plugin):
self.add_delete_message_job(reply_message)
return
character_name = roleToName(character_name)
file_path = self.wiki_service.raider.raider_path / f"{character_name}.png"
file_path = self.wiki_service.raider.raider_role_path / f"{character_name}.png"
if not file_path.exists():
reply_message = await message.reply_text(
f"没有找到 {character_name} 的攻略", reply_markup=InlineKeyboardMarkup(self.KEYBOARD)
@ -52,28 +52,27 @@ class StrategyPlugin(Plugin):
return
logger.info("用户 %s[%s] 查询角色攻略命令请求 || 参数 %s", user.full_name, user.id, character_name)
await message.reply_chat_action(ChatAction.UPLOAD_PHOTO)
caption = "From 米游社"
caption = "From 米游社@听语惊花"
if file_id := await self.cache_service.get_strategy_cache(character_name):
await message.reply_document(
document=file_id,
await message.reply_photo(
photo=file_id,
caption=caption,
filename=f"{character_name}.png",
allow_sending_without_reply=True,
parse_mode=ParseMode.HTML,
)
else:
reply_document = await message.reply_document(
document=open(file_path, "rb"),
reply_photo = await message.reply_photo(
photo=open(file_path, "rb"),
caption=caption,
filename=f"{character_name}.png",
allow_sending_without_reply=True,
parse_mode=ParseMode.HTML,
)
if reply_document.document:
if reply_photo.photo:
tags = roleToTag(character_name)
photo_file_id = reply_document.document.file_id
cid = self.wiki_service.raider.get_item_id(character_name)
await self.cache_service.set_strategy_cache(cid, photo_file_id)
photo_file_id = reply_photo.photo[0].file_id
await self.cache_service.set_strategy_cache(character_name, photo_file_id)
entry = StrategyEntry(
key=f"plugin:strategy:{character_name}",
title=character_name,
@ -81,6 +80,6 @@ class StrategyPlugin(Plugin):
tags=tags,
caption=caption,
parse_mode="HTML",
document_file_id=photo_file_id,
photo_file_id=photo_file_id,
)
await self.search_service.add_entry(entry)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

View File

@ -26,25 +26,25 @@
<div class="box pt-4 rounded-xl space-y-4 overflow-hidden">
<div>
<div class="command-background pointer-events-none">
<img src="background/starrail.png" alt=""/>
<img src="../../img/logo.png" alt=""/>
</div>
<div class="command-title text-2xl mx-1">
<h1>查询命令</h1>
</div>
<div class="grid grid-cols-4 py-4 px-2">
<!-- WIKI类 -->
<!-- <div class="command">-->
<!-- <div class="command-name">/weapon</div>-->
<!-- <div class="command-description">查询武器</div>-->
<!-- </div>-->
<div class="command">
<div class="command-name">/light_cone</div>
<div class="command-description">查询光锥图鉴</div>
</div>
<div class="command rounded-xl flex-1">
<div class="command-name">/strategy</div>
<div class="command-description">查询角色攻略</div>
</div>
<!-- <div class="command">-->
<!-- <div class="command-name">/material</div>-->
<!-- <div class="command-description">角色培养素材查询</div>-->
<!-- </div>-->
<div class="command">
<div class="command-name">/material</div>
<div class="command-description">角色培养素材查询</div>
</div>
<!-- UID 查询类 -->
<div class="command">
<div class="command-name">
@ -89,13 +89,13 @@
<!-- </div>-->
<!-- <div class="command-description">查询深渊推荐配队</div>-->
<!-- </div>-->
<!-- <div class="command">-->
<!-- <div class="command-name">-->
<!-- /avatars-->
<!-- <i class="fa fa-id-card-o ml-2"></i>-->
<!-- </div>-->
<!-- <div class="command-description">查询角色练度</div>-->
<!-- </div>-->
<div class="command">
<div class="command-name">
/avatars
<i class="fa fa-id-card-o ml-2"></i>
</div>
<div class="command-description">查询角色练度</div>
</div>
<!-- <div class="command">-->
<!-- <div class="command-name">-->
<!-- /reg_time-->
@ -239,10 +239,10 @@
<div class="command-name">@{{bot_username}} 角色名</div>
<div class="command-description">查询角色攻略</div>
</div>
<!-- <div class="command">-->
<!-- <div class="command-name">@{{bot_username}} 武器名</div>-->
<!-- <div class="command-description">查询武器信息</div>-->
<!-- </div>-->
<div class="command">
<div class="command-name">@{{bot_username}} 光锥名</div>
<div class="command-description">查询光锥信息</div>
</div>
</div>
</div>