新增深渊配队,将深渊相关指令统一到一个插件,修改设置别名命令

This commit is contained in:
CMHopeSunshine 2022-10-02 19:20:07 +08:00
parent b40535e45f
commit 24d4ac595a
8 changed files with 256 additions and 64 deletions

View File

@ -0,0 +1,83 @@
from nonebot import on_command
from nonebot.adapters.onebot.v11 import Message, MessageEvent, GroupMessageEvent
from nonebot.params import Arg
from nonebot.plugin import PluginMetadata
from LittlePaimon.utils import logger
from LittlePaimon.utils.genshin import GenshinInfoManager
from LittlePaimon.utils.message import CommandPlayer
from .abyss_statistics import get_statistics
from .draw_abyss import draw_abyss_card
from .youchuang import draw_team
__plugin_meta__ = PluginMetadata(
name='原神深渊查询',
description='原神深渊查询',
usage='...',
extra={
'author': '惜月',
'version': '3.0',
'priority': 2,
}
)
sy = on_command('sy', aliases={'深渊战报', '深渊信息'}, priority=10, block=True, state={
'pm_name': 'sy',
'pm_description': '查看本期|上期的深渊战报',
'pm_usage': 'sy(uid)(本期|上期)',
'pm_priority': 1
})
abyss_stat = on_command('深渊统计', aliases={'深渊群数据', '深渊群排行'}, priority=10, block=True, state={
'pm_name': '深渊统计',
'pm_description': '查看本群深渊统计,仅群可用',
'pm_usage': '深渊统计',
'pm_priority': 2
})
abyss_team = on_command('深渊配队', aliases={'配队推荐', '深渊阵容'}, priority=10, block=True, state={
'pm_name': '深渊配队',
'pm_description': '查看深渊配队推荐,数据来源于游创工坊',
'pm_usage': '深渊配队',
'pm_priority': 3
})
@sy.handle()
async def _(event: MessageEvent, players=CommandPlayer(), msg: str = Arg('msg')):
logger.info('原神深渊战报', '开始执行')
abyss_index = 2 if any(i in msg for i in ['', 'last']) else 1
msg = Message()
for player in players:
logger.info('原神深渊战报', '', {'用户': players[0].user_id, 'UID': players[0].uid})
gim = GenshinInfoManager(player.user_id, player.uid)
abyss_info = await gim.get_abyss_info(abyss_index)
if isinstance(abyss_info, str):
logger.info('原神深渊战报', '➤➤', {}, abyss_info, False)
msg += f'UID{player.uid}{abyss_info}\n'
else:
logger.info('原神深渊战报', '➤➤', {}, '数据获取成功', True)
try:
img = await draw_abyss_card(abyss_info)
logger.info('原神深渊战报', '➤➤➤', {}, '制图完成', True)
msg += img
except Exception as e:
logger.info('原神深渊战报', '➤➤➤', {}, f'制图出错:{e}', False)
msg += F'UID{player.uid}制图时出错:{e}\n'
await sy.finish(msg, at_sender=True)
@abyss_stat.handle()
async def _(event: GroupMessageEvent):
try:
result = await get_statistics(event.group_id)
except Exception as e:
result = f'制作深渊统计时出错:{e}'
await abyss_stat.finish(result)
@abyss_team.handle()
async def _(event: MessageEvent):
try:
result = await draw_team(str(event.user_id))
except Exception as e:
result = f'制作深渊配队时出错:{e}'
await abyss_team.finish(result)

View File

@ -0,0 +1 @@
from .draw import draw_team

View File

@ -0,0 +1,39 @@
from typing import List, Tuple
from pydantic import parse_obj_as
from LittlePaimon.utils.requests import aiorequests
from .models import TeamRateResult, TeamRate
# API均来自微信公众号`原神创意工坊`感谢坊主提供的API
BASE_API = 'https://www.youchuang.fun'
TEAM_RATE_API = f'{BASE_API}/gamerole/formationRate'
VERSION_API = 'https://api-cloudgame-static.mihoyo.com/hk4e_cg_cn/gamer/api/getFunctionShieldNew?client_type=1'
HEADERS = {
'Host': 'www.youchuang.fun',
'Referer': 'https://servicewechat.com/wxce4dbe0cb0f764b3/91/page-frame.html',
'User-Agent': 'Mozilla/5.0 (iPad; CPU OS 15_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) '
'Mobile/15E148 MicroMessenger/8.0.20(0x1800142f) NetType/WIFI Language/zh_CN',
'content-type': 'application/json'
}
async def get_game_version() -> float:
data = await aiorequests.get(VERSION_API)
data = data.json()
return float(data['data']['config']['cg.key_function_queue_news']['versions'][0].replace('.0', ''))
async def get_team_rate() -> Tuple[TeamRateResult, float]:
version = await get_game_version()
data_up = (await aiorequests.post(TEAM_RATE_API, json={
'version': version,
'layer': 1
}, headers=HEADERS)).json()['result']
data_down = (await aiorequests.post(TEAM_RATE_API, json={
'version': version,
'layer': 2
}, headers=HEADERS)).json()['result']
return TeamRateResult(rateListUp=parse_obj_as(List[TeamRate], data_up['rateList']),
rateListDown=parse_obj_as(List[TeamRate], data_down['rateList']),
userCount=data_up['userCount']), version

View File

@ -0,0 +1,60 @@
import asyncio
from typing import List
from LittlePaimon.database.models import Character, LastQuery
from LittlePaimon.config import RESOURCE_BASE_PATH
from LittlePaimon.utils.files import load_image
from LittlePaimon.utils.alias import get_chara_icon
from LittlePaimon.utils.image import PMImage, font_manager as fm
from LittlePaimon.utils.message import MessageBuild
from .api import get_team_rate
from .models import TeamRate
async def draw_team_line(up: TeamRate, down: TeamRate, characters: List[str]) -> PMImage:
img = PMImage(size=(1013, 127), mode='RGBA', color=(0, 0, 0, 0))
for i, member in enumerate(up.formation):
owned = member.name in characters if characters else True
await img.paste(await load_image(RESOURCE_BASE_PATH / 'icon' / f'{member.star}starbox.png'), (110 * i, 0))
await img.paste(
await load_image(RESOURCE_BASE_PATH / 'avatar' / f'{get_chara_icon(name=member.name)}.png', size=(100, 100)),
(110 * i, 1))
await img.text(member.name if owned else '未拥有', (110 * i, 110 * i + 100), 103, fm.get('hywh', 18), '#33231a',
'center')
if not owned:
await img.paste(await load_image(RESOURCE_BASE_PATH / 'icon' / 'grey_box.png'), (110 * i, 0))
await img.text(f'{round(up.rate * 100, 2)}%', 439, 30, fm.get('bahnschrift_bold', 30), '#33231a')
for i, member in enumerate(down.formation):
owned = member.name in characters if characters else True
await img.paste(await load_image(RESOURCE_BASE_PATH / 'icon' / f'{member.star}starbox.png'), (583 + 110 * i, 0))
await img.paste(
await load_image(RESOURCE_BASE_PATH / 'avatar' / f'{get_chara_icon(name=member.name)}.png', size=(100, 100)),
(583 + 110 * i, 1))
await img.text(member.name if owned else '未拥有', (583 + 110 * i, 110 * i + 683), 103, fm.get('hywh', 18), '#33231a',
'center')
if not owned:
await img.paste(await load_image(RESOURCE_BASE_PATH / 'icon' / 'grey_box.png'), (583 + 110 * i, 0))
await img.text(f'{round(down.rate * 100, 2)}%', 574, 59, fm.get('bahnschrift_bold', 30), '#33231a', 'right')
return img
async def draw_team(user_id: str):
if last_query := await LastQuery.get_or_none(user_id=user_id):
charas = await Character.filter(user_id=user_id, uid=last_query.uid)
else:
charas = await Character.filter(user_id=user_id)
characters = [chara.name for chara in charas if chara is not None]
team_data, version = await get_team_rate()
if characters:
team_data.sort_by_own(characters)
img = PMImage(RESOURCE_BASE_PATH / 'abyss' / 'team_bg.png')
await img.text('深境螺旋十二层配队', 36, 29, fm.get('优设标题黑', 72), '#40342d')
await img.paste(await load_image(RESOURCE_BASE_PATH / 'general' / 'bubble.png'), (625, 35))
await img.text(f'{version}版本', (625, 625 + 147), 38, fm.get('SourceHanSansCN-Bold.otf', 30), 'white', 'center')
await img.text('CREATED BY LITTLEPAIMON | DATA FROM YOU-CHUANG',
1025, 158, fm.get('bahnschrift_regular.ttf', 30), '#8c4c2e', 'right')
await asyncio.gather(*[img.paste(await draw_team_line(team_data.rateListUp[i], team_data.rateListDown[i], characters), (33, 222 + 153 * i)) for i in range(15)])
return MessageBuild.Image(img, mode='RGB', quality=80)

View File

@ -0,0 +1,33 @@
from typing import List, Optional
from pydantic import BaseModel, validator
class Member(BaseModel):
star: int
attr: str
name: str
class TeamRate(BaseModel):
rate: float
formation: List[Member]
ownerNum: Optional[int]
@validator('rate', pre=True)
def str2float(cls, v):
return float(v.replace('%', '')) / 100.0 if isinstance(v, str) else v
class TeamRateResult(BaseModel):
rateListUp: List[TeamRate]
rateListDown: List[TeamRate]
userCount: int
def sort_by_own(self, characters: List[str]):
for team in self.rateListUp:
team.ownerNum = len(set(characters) & {member.name for member in team.formation})
for team in self.rateListDown:
team.ownerNum = len(set(characters) & {member.name for member in team.formation})
self.rateListUp.sort(key=lambda x: (x.ownerNum / 4 * x.rate), reverse=True)
self.rateListDown.sort(key=lambda x: (x.ownerNum / 4 * x.rate), reverse=True)

View File

@ -1,7 +1,8 @@
from nonebot import on_command, on_regex from nonebot import on_command
from nonebot.adapters.onebot.v11 import Message, MessageEvent, MessageSegment, GroupMessageEvent from nonebot.adapters.onebot.v11 import Message, MessageEvent, MessageSegment
from nonebot.params import Arg, RegexDict, CommandArg from nonebot.params import Arg, ArgPlainText, CommandArg
from nonebot.plugin import PluginMetadata from nonebot.plugin import PluginMetadata
from nonebot.typing import T_State
from LittlePaimon import NICKNAME from LittlePaimon import NICKNAME
from LittlePaimon.database.models import PlayerAlias from LittlePaimon.database.models import PlayerAlias
@ -9,14 +10,12 @@ from LittlePaimon.utils import logger
from LittlePaimon.utils.message import CommandPlayer, CommandCharacter, CommandUID from LittlePaimon.utils.message import CommandPlayer, CommandCharacter, CommandUID
from LittlePaimon.utils.genshin import GenshinInfoManager from LittlePaimon.utils.genshin import GenshinInfoManager
from LittlePaimon.utils.tool import freq_limiter from LittlePaimon.utils.tool import freq_limiter
from LittlePaimon.utils.typing import CHARA_RE from LittlePaimon.utils.typing import CHARACTERS
from .draw_player_card import draw_player_card from .draw_player_card import draw_player_card
from .draw_character_bag import draw_chara_bag from .draw_character_bag import draw_chara_bag
from .draw_character_detail import draw_chara_detail from .draw_character_detail import draw_chara_detail
from .draw_character_card import draw_chara_card from .draw_character_card import draw_chara_card
from .draw_abyss import draw_abyss_card
from .abyss_statistics import get_statistics
__plugin_meta__ = PluginMetadata( __plugin_meta__ = PluginMetadata(
name='原神信息查询', name='原神信息查询',
@ -41,12 +40,6 @@ ysa = on_command('ysa', aliases={'角色背包', '练度统计'}, priority=10, b
'pm_usage': 'ysa(uid)', 'pm_usage': 'ysa(uid)',
'pm_priority': 2 'pm_priority': 2
}) })
sy = on_command('sy', aliases={'深渊战报', '深渊信息'}, priority=10, block=True, state={
'pm_name': 'sy',
'pm_description': '查看本期|上期的深渊战报',
'pm_usage': 'sy(uid)(本期|上期)',
'pm_priority': 3
})
ysc = on_command('ysc', aliases={'角色图', '角色卡片'}, priority=10, block=True, state={ ysc = on_command('ysc', aliases={'角色图', '角色卡片'}, priority=10, block=True, state={
'pm_name': 'ysc', 'pm_name': 'ysc',
'pm_description': '随机角色同人图+角色信息卡片', 'pm_description': '随机角色同人图+角色信息卡片',
@ -65,14 +58,12 @@ update_info = on_command('udi', aliases={'更新角色信息', '更新面板', '
'pm_usage': '更新角色信息[天赋](uid)', 'pm_usage': '更新角色信息[天赋](uid)',
'pm_priority': 6 'pm_priority': 6
}) })
add_alias = on_regex( add_alias = on_command('设置别名', priority=10, block=True, state={
rf'((?P<chara>{CHARA_RE})是[我俺咱]的?(?P<alias>\w+))|([我俺咱]的?(?P<alias2>\w+)[是叫名](?P<chara2>{CHARA_RE}))', priority=10,
block=True, state={
'pm_name': '角色别名设置', 'pm_name': '角色别名设置',
'pm_description': '设置专属于你的角色别名', 'pm_description': '设置专属于你的角色别名,例如【设置别名钟离 老公】',
'pm_usage': '<角色名>是我<别名>', 'pm_usage': '设置别名<角色> <别名>',
'pm_priority': 7 'pm_priority': 7
}) })
delete_alias = on_command('删除别名', priority=10, block=True, state={ delete_alias = on_command('删除别名', priority=10, block=True, state={
'pm_name': '角色别名删除', 'pm_name': '角色别名删除',
'pm_description': '删除你已设置的角色别名', 'pm_description': '删除你已设置的角色别名',
@ -85,12 +76,6 @@ show_alias = on_command('查看别名', priority=10, block=True, state={
'pm_usage': '查看别名', 'pm_usage': '查看别名',
'pm_priority': 9 'pm_priority': 9
}) })
show_abyss = on_command('深渊统计', priority=10, block=True, state={
'pm_name': '深渊统计',
'pm_description': '查看本群深渊统计,仅群可用',
'pm_usage': '深渊统计',
'pm_priority': 10
})
@ys.handle() @ys.handle()
@ -149,30 +134,6 @@ async def _(event: MessageEvent, players=CommandPlayer(2)):
await ysa.finish(msg, at_sender=True) await ysa.finish(msg, at_sender=True)
@sy.handle()
async def _(event: MessageEvent, players=CommandPlayer(), msg: str = Arg('msg')):
logger.info('原神深渊战报', '开始执行')
abyss_index = 2 if any(i in msg for i in ['', 'last']) else 1
msg = Message()
for player in players:
logger.info('原神深渊战报', '', {'用户': players[0].user_id, 'UID': players[0].uid})
gim = GenshinInfoManager(player.user_id, player.uid)
abyss_info = await gim.get_abyss_info(abyss_index)
if isinstance(abyss_info, str):
logger.info('原神深渊战报', '➤➤', {}, abyss_info, False)
msg += f'UID{player.uid}{abyss_info}\n'
else:
logger.info('原神深渊战报', '➤➤', {}, '数据获取成功', True)
try:
img = await draw_abyss_card(abyss_info)
logger.info('原神深渊战报', '➤➤➤', {}, '制图完成', True)
msg += img
except Exception as e:
logger.info('原神深渊战报', '➤➤➤', {}, f'制图出错:{e}', False)
msg += F'UID{player.uid}制图时出错:{e}\n'
await ysa.finish(msg, at_sender=True)
@ysc.handle() @ysc.handle()
async def _(event: MessageEvent, players=CommandPlayer(only_cn=False), characters=CommandCharacter()): async def _(event: MessageEvent, players=CommandPlayer(only_cn=False), characters=CommandCharacter()):
logger.info('原神角色卡片', '开始执行') logger.info('原神角色卡片', '开始执行')
@ -267,21 +228,42 @@ async def _(event: MessageEvent, uid=CommandUID(), msg: str = Arg('msg')):
@add_alias.handle() @add_alias.handle()
async def _(event: MessageEvent, regex_dict: dict = RegexDict()): async def _(event: MessageEvent, state: T_State, msg: Message = CommandArg()):
chara = regex_dict['chara'] or regex_dict['chara2'] msg = msg.extract_plain_text().strip().split(' ')
alias = regex_dict['alias'] or regex_dict['alias2'] if msg[0] in CHARACTERS:
state['chara'] = Message(msg[0])
else:
await add_alias.finish(f'{NICKNAME}不认识{msg[0]}哦,请使用角色全称', at_sender=True)
if len(msg) > 1:
state['alias'] = Message(msg[1])
@add_alias.got('alias', prompt=Message.template('你想把{chara}设置为你的谁呢?'))
async def _(event: MessageEvent, chara: str = ArgPlainText('chara'), alias: str = ArgPlainText('alias')):
await PlayerAlias.update_or_create(user_id=str(event.user_id), alias=alias, defaults={'character': chara}) await PlayerAlias.update_or_create(user_id=str(event.user_id), alias=alias, defaults={'character': chara})
await add_alias.finish(f'{NICKNAME}知道{chara}是你的{alias}啦..') await add_alias.finish(f'设置成功,{NICKNAME}知道{chara}是你的{alias}啦..')
@delete_alias.handle() @delete_alias.handle()
async def _(event: MessageEvent, msg: Message = CommandArg()): async def _(event: MessageEvent, state: T_State, msg: Message = CommandArg()):
msg = msg.extract_plain_text().strip() if msg:
if alias := await PlayerAlias.get_or_none(user_id=str(event.user_id), alias=msg): state['alias'] = msg
elif aliases := await PlayerAlias.filter(user_id=str(event.user_id)).all():
state['msg'] = '你已设置以下别名:\n' + '\n'.join([f'{i.alias} -> {i.character}' for i in aliases]) + '\n请输入你想删除的别名或发送"全部"删除全部别名'
else:
await delete_alias.finish('你还没有设置任何别名哦')
@delete_alias.got('alias', prompt=Message.template('{msg}'))
async def _(event: MessageEvent, msg: str = ArgPlainText('alias')):
if msg == '全部':
await PlayerAlias.filter(user_id=str(event.user_id)).delete()
await delete_alias.finish('已删除你设置的全部别名')
elif alias := await PlayerAlias.get_or_none(user_id=str(event.user_id), alias=msg):
await alias.delete() await alias.delete()
await delete_alias.finish(f'别名{msg}删除成功!', at_sender=True) await delete_alias.finish(f'别名{msg}删除成功!', at_sender=True)
else: else:
await delete_alias.finish(f'你并没有将{msg}设置为某个角色的别名', at_sender=True) await delete_alias.reject(f'你并没有将{msg}设置为某个角色的别名', at_sender=True)
@show_alias.handle() @show_alias.handle()
@ -291,9 +273,3 @@ async def _(event: MessageEvent):
at_sender=True) at_sender=True)
else: else:
await show_alias.finish('你还没有设置过角色别名哦', at_sender=True) await show_alias.finish('你还没有设置过角色别名哦', at_sender=True)
@show_abyss.handle()
async def _(event: GroupMessageEvent):
result = await get_statistics(event.group_id)
await show_abyss.finish(result)