Wiki增加材料特产,并优化指令使用方法,支持了大范围查询,如火元素角色图鉴长枪武器图鉴圣遗物图鉴

This commit is contained in:
CMHopeSunshine 2022-12-24 00:11:38 +08:00
parent 89f6b15d1f
commit 33c2f83606
9 changed files with 473 additions and 67 deletions

View File

@ -0,0 +1,324 @@
{
"角色": {
"武器类型": {
"单手剑": [
"神里绫华",
"琴",
"凯亚",
"行秋",
"班尼特",
"七七",
"阿贝多",
"刻晴",
"枫原万叶",
"久岐忍",
"神里绫人",
"妮露",
"莱依拉",
"艾尔海森",
"旅行者"
],
"法器": [
"丽莎",
"芭芭拉",
"凝光",
"可莉",
"莫娜",
"砂糖",
"烟绯",
"珊瑚宫心海",
"八重神子",
"鹿野院平藏",
"纳西妲",
"流浪者"
],
"双手剑": [
"迪卢克",
"雷泽",
"北斗",
"诺艾尔",
"重云",
"辛焱",
"优菈",
"早柚",
"荒泷一斗",
"多莉"
],
"弓": [
"安柏",
"温迪",
"菲谢尔",
"达达利亚",
"甘雨",
"迪奥娜",
"宵宫",
"五郎",
"九条裟罗",
"夜兰",
"埃洛伊",
"柯莱",
"提纳里",
"珐露珊"
],
"长柄武器": [
"香菱",
"魈",
"钟离",
"罗莎莉亚",
"胡桃",
"托马",
"雷电将军",
"申鹤",
"云堇",
"赛诺",
"坎蒂丝",
"瑶瑶"
]
},
"元素类型": {
"冰": [
"神里绫华",
"凯亚",
"七七",
"重云",
"甘雨",
"迪奥娜",
"罗莎莉亚",
"优菈",
"埃洛伊",
"申鹤",
"莱依拉"
],
"风": [
"琴",
"温迪",
"魈",
"砂糖",
"枫原万叶",
"早柚",
"鹿野院平藏",
"流浪者",
"珐露珊",
"旅行者"
],
"雷": [
"丽莎",
"雷泽",
"北斗",
"菲谢尔",
"刻晴",
"雷电将军",
"九条裟罗",
"八重神子",
"久岐忍",
"多莉",
"赛诺",
"旅行者"
],
"水": [
"芭芭拉",
"行秋",
"达达利亚",
"莫娜",
"珊瑚宫心海",
"夜兰",
"神里绫人",
"妮露",
"坎蒂丝"
],
"火": [
"迪卢克",
"安柏",
"香菱",
"可莉",
"班尼特",
"辛焱",
"胡桃",
"烟绯",
"宵宫",
"托马"
],
"岩": [
"凝光",
"钟离",
"诺艾尔",
"阿贝多",
"五郎",
"荒泷一斗",
"云堇",
"旅行者"
],
"草": [
"柯莱",
"提纳里",
"纳西妲",
"瑶瑶",
"艾尔海森",
"旅行者"
]
}
},
"武器": {
"单手剑": [
"无锋剑",
"银剑",
"冷刃",
"黎明神剑",
"旅行剑",
"暗铁剑",
"吃虎鱼刀",
"飞天御剑",
"西风剑",
"笛剑",
"祭礼剑",
"宗室长剑",
"匣里龙吟",
"试作斩岩",
"铁蜂刺",
"黑岩长剑",
"黑剑",
"暗巷闪光",
"降临之剑",
"腐殖之剑",
"天目影打刀",
"辰砂之纺锤",
"笼钓瓶一心",
"原木刀",
"西福斯的月光",
"东花坊时雨",
"风鹰剑",
"天空之刃",
"苍古自由之誓",
"斫峰之刃",
"磐岩结绿",
"雾切之回光",
"波乱月白经津",
"圣显之钥",
"裁叶萃光"
],
"双手剑": [
"训练大剑",
"佣兵重剑",
"铁影阔剑",
"沐浴龙血的剑",
"白铁大剑",
"以理服人",
"飞天大御剑",
"西风大剑",
"钟剑",
"祭礼大剑",
"宗室大剑",
"雨裁",
"试作古华",
"白影剑",
"黑岩斩刀",
"螭骨剑",
"千岩古剑",
"雪葬的星银",
"衔珠海皇",
"桂木斩长正",
"玛海菈的水色",
"恶王丸",
"森林王器",
"天空之傲",
"狼的末路",
"松籁响起之时",
"无工之剑",
"赤角石溃杵"
],
"长柄武器": [
"新手长枪",
"铁尖枪",
"白缨枪",
"钺矛",
"黑缨枪",
"匣里灭辰",
"试作星镰",
"流月针",
"黑岩刺枪",
"决斗之枪",
"千岩长枪",
"西风长枪",
"宗室猎枪",
"龙脊长枪",
"喜多院十文字",
"「渔获」",
"断浪长鳍",
"贯月矢",
"风信之锋",
"护摩之杖",
"天空之脊",
"贯虹之槊",
"和璞鸢",
"息灾",
"薙草之稻光",
"赤沙之杖"
],
"法器": [
"学徒笔记",
"口袋魔导书",
"魔导绪论",
"讨龙英杰谭",
"异世界行记",
"翡玉法球",
"甲级宝珏",
"西风秘典",
"流浪乐章",
"祭礼残章",
"宗室秘法录",
"匣里日月",
"试作金珀",
"万国诸海图谱",
"黑岩绯玉",
"昭心",
"暗巷的酒与诗",
"忍冬之果",
"嘟嘟可故事集",
"白辰之环",
"证誓之明瞳",
"流浪的晚星",
"盈满之实",
"天空之卷",
"四风原典",
"尘世之锁",
"不灭月华",
"神乐之真意",
"千夜浮梦",
"图莱杜拉的回忆"
],
"弓": [
"猎弓",
"历练的猎弓",
"鸦羽弓",
"神射手之誓",
"反曲弓",
"弹弓",
"信使",
"西风猎弓",
"绝弦",
"祭礼弓",
"宗室长弓",
"弓藏",
"试作澹月",
"钢轮弓",
"黑岩战弓",
"苍翠猎弓",
"暗巷猎手",
"落霞",
"幽夜华尔兹",
"风花之颂",
"破魔之弓",
"掠食者",
"曚云之月",
"王下近侍",
"竭泽",
"天空之翼",
"阿莫斯之弓",
"终末嗟叹之诗",
"冬极白星",
"若水",
"飞雷之弦振",
"猎人之径"
]
}
}

View File

@ -18,6 +18,7 @@ from LittlePaimon.utils.api import get_bind_game_info, get_stoken_by_login_ticke
try:
from .get_cookie import *
except ImportError:
logger.info('原神绑定', '导入扫码绑定功能<r>失败</r>,请检查是否已安装<m>qrcode</m>库(运行<m>poetry run pip install qrcode</m>)')
bind_tips = '获取cookie的教程\ndocs.qq.com/doc/DQ3JLWk1vQVllZ2Z1\n获取后,使用[ysb cookie]指令绑定'
bind_tips_web = '获取cookie的教程\ndocs.qq.com/doc/DQ3JLWk1vQVllZ2Z1\n获取后,使用[ysb cookie]指令绑定或前往{cookie_web_url}网页添加绑定'

View File

@ -0,0 +1 @@
from .api import get_card_resources, get_match_card, CARD_API, get_all_specialty, get_match_specialty

View File

@ -8,6 +8,7 @@ from LittlePaimon.utils.requests import aiorequests
CARD_RESOURCES_API = '{proxy}https://raw.githubusercontent.com/Nwflower/Atlas/master/resource/text/card.yaml'
CARD_API = '{proxy}https://raw.githubusercontent.com/Nwflower/genshin-atlas/master/card/{name}.png'
SPECIALTY_RESOURCES_API = '{proxy}https://raw.githubusercontent.com/Nwflower/genshin-atlas/master/path.json'
async def get_card_resources() -> Optional[dict]:
@ -19,10 +20,31 @@ async def get_card_resources() -> Optional[dict]:
return None
async def get_match_card(name: str):
async def get_match_card(name: str) -> Optional[list]:
if not (data := await get_card_resources()):
return None
matches = []
if name == '全部':
return data
for cards in data.values():
matches.extend(difflib.get_close_matches(name, cards, cutoff=0.6, n=10))
return matches
async def get_all_specialty() -> Optional[list]:
with contextlib.suppress(Exception):
resp = await aiorequests.get(SPECIALTY_RESOURCES_API.format(proxy=config.github_proxy))
return resp.json()['specialty'].keys()
return None
async def get_match_specialty(name: str) -> Optional[list]:
with contextlib.suppress(Exception):
resp = await aiorequests.get(SPECIALTY_RESOURCES_API.format(proxy=config.github_proxy))
data = resp.json()['specialty']
return (
difflib.get_close_matches(name, data, cutoff=0.6, n=10)
if name != '全部'
else list(data.keys())
)
return None

View File

@ -14,7 +14,7 @@ from nonebot.typing import T_State
from LittlePaimon.database import PlayerAlias
from LittlePaimon.utils import NICKNAME
from LittlePaimon.config import config
from LittlePaimon.utils.alias import get_match_alias
from LittlePaimon.utils.alias import get_match_alias, WEAPON_TYPE_ALIAS, type_file, alias_file
from LittlePaimon.utils.message import MessageBuild, fullmatch_rule
from LittlePaimon.utils.path import RESOURCE_BASE_PATH
from LittlePaimon.utils.tool import freq_limiter
@ -22,10 +22,9 @@ from LittlePaimon.utils.typing import COMMAND_START_RE
from .draw_daily_material import draw_material
from .draw_map import init_map, draw_map, get_full_map
from .SereniteaPot import draw_pot_materials
from .card import get_match_card, get_card_resources
from .Atlas import get_match_card, get_card_resources, get_match_specialty, get_all_specialty
from .wiki_api import API
__plugin_meta__ = PluginMetadata(
name='原神Wiki',
description='原神WIKI百科',
@ -38,9 +37,16 @@ __plugin_meta__ = PluginMetadata(
)
cancel = [HandleCancellation(f'好吧,有需要再找{NICKNAME}')]
BASE_TYPE = ['角色', '天赋', '培养', '命座', '技能', '武器', '圣遗物', '原魔', '怪物', '七圣召唤', '原牌', '卡牌',
'特产', '材料']
BASE_TYPE_RE = '(' + '|'.join(BASE_TYPE) + ')'
IMG_TYPE = ['图鉴', '攻略', '材料', '参考面板', '收益曲线']
IMG_TYPE_RE = '(' + '|'.join(IMG_TYPE) + ')'
WIKI_RE = fr'{COMMAND_START_RE}(?P<name1>\w{{0,7}}?)(?P<type>{BASE_TYPE_RE}?{IMG_TYPE_RE})(?P<name2>\w{{0,7}})'
total_wiki = on_regex(
COMMAND_START_RE + r'(?P<name1>\w{0,7})(?P<type>(材料|图鉴|攻略|参考面板|收益曲线))(?P<name2>\w{0,7})',
WIKI_RE,
priority=12,
block=True,
state={
@ -176,41 +182,27 @@ async def _(event: MessageEvent, msg: Message = CommandArg()):
async def _(state: T_State, regex_dict: dict = RegexDict()):
if regex_dict['name1'] and regex_dict['name2']:
await total_wiki.finish()
name = regex_dict['name1'] or regex_dict['name2'] or ''
type = regex_dict.get('type')
if type == '材料':
if name.endswith(('角色', '天赋', '培养')):
state['type'] = '角色材料'
name = name[:-2]
elif name.endswith('武器'):
state['type'] = '武器图鉴'
name = name[:-2]
elif re.match(r'现在|[今明后][天日]|周[一二三四五六日]', name):
state['type'] = '每日材料'
else:
state['type'] = '材料'
elif type in {'图鉴', '攻略'}:
if name.endswith(('角色', '天赋', '命座', '技能')):
state['type'] = f'角色{type}'
name = name[:-2]
elif name.endswith('武器'):
state['type'] = '武器图鉴'
name = name[:-2]
elif name.endswith(('原魔', '怪物')):
state['type'] = '原魔图鉴'
name = name[:-2]
elif name.endswith('圣遗物'):
state['type'] = '圣遗物图鉴'
name = name[:-3]
elif name.endswith(('七圣召唤', '原牌', '卡牌', '七圣')):
state['type'] = '七圣召唤图鉴'
name = name.replace('七圣召唤', '').replace('原牌', '').replace('卡牌', '')
else:
state['type'] = type
else:
state['type'] = type
name: str = regex_dict['name1'] or regex_dict['name2'] or ''
type: str = regex_dict.get('type')
if type.startswith(('角色', '天赋', '培养', '命座', '技能')):
type = f'角色{type[2:]}'
elif type.startswith('武器'):
type = '武器图鉴'
elif type.startswith(('材料', '特产')) and type != '材料':
type = '特产图鉴'
elif type.startswith(('原魔', '怪物')):
type = '原魔图鉴'
elif type.startswith(('七圣召唤', '原牌', '卡牌')):
type = '七圣召唤图鉴'
if type.endswith('材料') and re.match(r'现在|[今明后][天日]|周[一二三四五六日]', name):
type = '每日材料'
elif type.endswith(('参考面板', '收益曲线')):
type = type[-4:]
state['type'] = type
if name:
state['name'] = Message(name)
elif type not in {'图鉴', '攻略', '材料'}:
state['name'] = Message('全部')
state['times'] = 1
@ -243,8 +235,17 @@ async def _(bot: Bot, event: MessageEvent, state: T_State, type: str = Arg('type
await total_wiki.send('开始获取每日材料,请稍候...')
await total_wiki.finish(await draw_material(str(event.user_id), week_str[day]), at_sender=True)
else:
if type.startswith('角色') or type in {'参考面板', '收益曲线'}:
if alias := await PlayerAlias.get_or_none(user_id=str(event.user_id), alias=name):
matches = {}
if type == '参考面板' and name in {'', '', '', '', '', '', ''}:
await total_wiki.finish(MessageSegment.image(API[type].format(proxy=config.github_proxy, name=name)))
elif type.startswith('角色') or type in {'参考面板', '收益曲线'}:
if name == '全部':
matches = type_file['角色']['元素类型']
elif re.match('[火水冰雷风岩草](元素|属性)?', name):
matches = {'角色': type_file['角色']['元素类型'][name[0]]}
elif re.match('|'.join(WEAPON_TYPE_ALIAS.keys()), name):
matches = {'角色': type_file['角色']['武器类型'][WEAPON_TYPE_ALIAS[name]]}
elif alias := await PlayerAlias.get_or_none(user_id=str(event.user_id), alias=name):
final_name = alias.character
matches = {}
try:
@ -254,15 +255,32 @@ async def _(bot: Bot, event: MessageEvent, state: T_State, type: str = Arg('type
await total_wiki.finish(
MessageBuild.Text(f'{final_name}{type}发送失败,可能是网络问题或者不存在该资源'))
else:
matches = get_match_alias(name, ['角色'])
elif type.startswith(('武器', '原魔')):
matches = get_match_alias(name, [type[:2]])
matches = get_match_alias(name, '角色')
elif type.startswith('武器'):
if name == '全部':
matches = type_file['武器']
elif re.match('|'.join(WEAPON_TYPE_ALIAS.keys()), name):
matches = {'武器': type_file['武器'][WEAPON_TYPE_ALIAS[name]]}
else:
matches = get_match_alias(name, '武器')
elif type.startswith('原魔'):
matches = {'原魔': alias_file['原魔']} if name == '全部' else get_match_alias(name, '原魔')
elif type.startswith('圣遗物'):
matches = get_match_alias(name, ['圣遗物'])
matches = {'圣遗物': list(alias_file['圣遗物'].keys())} if name == '全部' else get_match_alias(name, '圣遗物')
elif type.startswith('七圣召唤'):
matches = await get_match_card(name)
if name == '全部':
matches = await get_match_card(name)
else:
matches = {'七圣召唤': await get_match_card(name)}
elif type == '特产图鉴':
matches = {'特产': await get_match_specialty(name)}
else:
if alias := await PlayerAlias.get_or_none(user_id=str(event.user_id), alias=name):
if re.match('[火水冰雷风岩草](元素|属性)?', name):
matches = {'角色': type_file['角色']['元素类型'][name[0]]}
elif re.match('|'.join(WEAPON_TYPE_ALIAS.keys()), name):
matches = {'角色': type_file['角色']['武器类型'][WEAPON_TYPE_ALIAS[name]],
'武器': type_file['武器'][WEAPON_TYPE_ALIAS[name]]}
elif alias := await PlayerAlias.get_or_none(user_id=str(event.user_id), alias=name):
final_name = alias.character
if type in {'材料', '攻略', '图鉴'}:
type = f'角色{type}'
@ -271,9 +289,12 @@ async def _(bot: Bot, event: MessageEvent, state: T_State, type: str = Arg('type
MessageSegment.image(API[type].format(proxy=config.github_proxy, name=final_name)))
except ActionFailed:
await total_wiki.finish(f'{final_name}{type}发送失败,可能是网络问题或者不存在该资源')
matches = get_match_alias(name, ['角色', '武器', '原魔', '圣遗物'])
if m := await get_match_card(name):
matches['七圣召唤'] = m
else:
matches = get_match_alias(name, ['角色', '武器', '原魔', '圣遗物'])
if m := await get_match_card(name):
matches['七圣召唤'] = m
if s := await get_match_specialty(name):
matches['特产'] = s
if not matches:
await total_wiki.finish(MessageBuild.Text(f'没有名为{name}{type}哦,是不是打错了~'), at_sender=True)
elif len(matches) == 1 and len(list(matches.values())[0]) == 1:
@ -288,13 +309,23 @@ async def _(bot: Bot, event: MessageEvent, state: T_State, type: str = Arg('type
await total_wiki.finish(f'{final_name}{type}发送失败,可能是网络问题或者不存在该资源')
else:
send_flag = False
if sum(len(value) for value in matches.values()) >= 15 and isinstance(event, (PrivateMessageEvent, GroupMessageEvent)):
msg = [
{'type': 'node',
'data': {'name': NICKNAME, 'uin': event.self_id, 'content': f'{type}\n' + '\n'.join(names)}}
for type, names in matches.items()]
msg.insert(0, {'type': 'node', 'data': {'name': NICKNAME, 'uin': event.self_id, 'content': f'你要查询哪个的{type}呢?'}})
msg.append({'type': 'node', 'data': {'name': NICKNAME, 'uin': event.self_id, 'content': '回答\"序号\"查询或回答\"取消\"取消查询'}})
if sum(len(value) for value in matches.values()) >= 15 and isinstance(event, (
PrivateMessageEvent, GroupMessageEvent)):
if len(matches) == 1:
matches = {i: matches[list(matches.keys())[0]][i:i + 5] for i in
range(0, len(matches[list(matches.keys())[0]]), 5)}
index = 1
msg = []
for key, value in matches.items():
temp_msg = f'{key}:\n' if not isinstance(key, int) else ''
for v in value:
temp_msg += f'{index}.{v}\n'
index += 1
msg.append({'type': 'node', 'data': {'name': NICKNAME, 'uin': event.self_id, 'content': temp_msg}})
msg.insert(0, {'type': 'node',
'data': {'name': NICKNAME, 'uin': event.self_id, 'content': f'你要查询哪个的{type}呢?'}})
msg.append({'type': 'node', 'data': {'name': NICKNAME, 'uin': event.self_id,
'content': '回答\"序号\"查询或回答\"取消\"取消查询'}})
try:
send_flag = True
if isinstance(event, GroupMessageEvent):

View File

@ -1 +0,0 @@
from .api import get_card_resources, get_match_card, CARD_API

View File

@ -1,5 +1,5 @@
from typing import Dict
from .card import CARD_API
from .Atlas import CARD_API
API: Dict[str, str] = {
'角色图鉴': '{proxy}https://raw.githubusercontent.com/CMHopeSunshine/GenshinWikiMap/master/results/character_map/{name}.jpg',
@ -10,5 +10,6 @@ API: Dict[str, str] = {
'武器图鉴': '{proxy}https://raw.githubusercontent.com/Nwflower/genshin-atlas/master/weapon/{name}.png',
'圣遗物图鉴': '{proxy}https://raw.githubusercontent.com/Nwflower/genshin-atlas/master/artifact/{name}.png',
'原魔图鉴': 'https://static.cherishmoon.fun/LittlePaimon/MonsterMaps/{name}.jpg',
'特产图鉴': '{proxy}https://raw.githubusercontent.com/Nwflower/genshin-atlas/master/specialty/{name}.png',
'七圣召唤图鉴': CARD_API
}

View File

@ -1,12 +1,30 @@
import re
from difflib import get_close_matches
from typing import Union, Literal, List, Optional, Dict
from .files import load_json
from .path import JSON_DATA
from .path import JSON_DATA, GACHA_RES
alias_file = load_json(JSON_DATA / 'alias.json')
info_file = load_json(JSON_DATA / 'genshin_info.json')
weapon_file = load_json(JSON_DATA / 'weapon.json')
item_type_file = load_json(GACHA_RES / 'type.json')
type_file = load_json(JSON_DATA / '类型.json')
WEAPON_TYPE_ALIAS = {
'单手剑': '单手剑',
'双手剑': '双手剑',
'大剑': '双手剑',
'长柄武器': '长柄武器',
'': '长柄武器',
'长枪': '长柄武器',
'长柄': '长柄武器',
'法器': '法器',
'法书': '法器',
'': '法器',
'': '',
'弓箭': ''
}
def get_id_by_name(name: str) -> Optional[str]:
@ -43,7 +61,10 @@ def get_alias_by_name(name: str) -> Optional[List[str]]:
return next((r for r in name_list.values() if name in r), None)
def get_match_alias(name: str, types: List[Literal['角色', '武器', '原魔', '圣遗物']] = None,
ALIAS_TYPE = Literal['角色', '武器', '原魔', '圣遗物']
def get_match_alias(name: str, types: Union[List[ALIAS_TYPE], ALIAS_TYPE] = None,
one_to_list: bool = False) -> Union[
Dict[str, List[str]], List[str]]:
"""
@ -55,6 +76,8 @@ def get_match_alias(name: str, types: List[Literal['角色', '武器', '原魔',
"""
if types is None:
types = ['角色']
elif isinstance(types, str):
types = [types]
matches = {}
for type in types:
alias_list = alias_file[type]
@ -63,13 +86,15 @@ def get_match_alias(name: str, types: List[Literal['角色', '武器', '原魔',
if name.startswith(('', '', '', '', '', '', '')) and name.endswith(
('', '主角', '', '', '旅行者')):
matches[type].append(name if name.endswith(('', '')) else f'{name[0]}')
continue
for alias in alias_list.values():
if name in alias:
matches[type].append(alias[0])
break
if get_close_matches(name, alias, cutoff=0.6, n=3):
matches[type].append(alias[0])
else:
for alias in alias_list.values():
if name in alias:
if len(types) == 1 and one_to_list:
return [name]
matches[type].append(alias[0])
break
if get_close_matches(name, alias, cutoff=0.6, n=3):
matches[type].append(alias[0])
elif type in {'武器', '圣遗物'}:
for raw_name, alias in alias_list.items():
if name in alias:
@ -103,6 +128,7 @@ def get_chara_icon(name: Optional[str] = None, chara_id: Optional[int] = None,
side_icon = info['SideIconName']
else:
return None
# UI_AvatarIcon_Side_Wanderer
if icon_type == 'side':
return side_icon
elif icon_type == 'avatar':

View File

@ -35,6 +35,7 @@ amis-python = "^1.0.5"
psutil = "^5.9.3"
nonebot-plugin-apscheduler = "^0.2.0"
playwright = "^1.27.1"
qrcode = "^7.3.1"
[tool.poetry.dev-dependencies]
nb-cli = "^0.6.7"