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

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.adapters.onebot.v11 import Message, MessageEvent, MessageSegment, GroupMessageEvent
from nonebot.params import Arg, RegexDict, CommandArg
from nonebot import on_command
from nonebot.adapters.onebot.v11 import Message, MessageEvent, MessageSegment
from nonebot.params import Arg, ArgPlainText, CommandArg
from nonebot.plugin import PluginMetadata
from nonebot.typing import T_State
from LittlePaimon import NICKNAME
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.genshin import GenshinInfoManager
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_character_bag import draw_chara_bag
from .draw_character_detail import draw_chara_detail
from .draw_character_card import draw_chara_card
from .draw_abyss import draw_abyss_card
from .abyss_statistics import get_statistics
__plugin_meta__ = PluginMetadata(
name='原神信息查询',
@ -41,12 +40,6 @@ ysa = on_command('ysa', aliases={'角色背包', '练度统计'}, priority=10, b
'pm_usage': 'ysa(uid)',
'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={
'pm_name': 'ysc',
'pm_description': '随机角色同人图+角色信息卡片',
@ -65,12 +58,10 @@ update_info = on_command('udi', aliases={'更新角色信息', '更新面板', '
'pm_usage': '更新角色信息[天赋](uid)',
'pm_priority': 6
})
add_alias = on_regex(
rf'((?P<chara>{CHARA_RE})是[我俺咱]的?(?P<alias>\w+))|([我俺咱]的?(?P<alias2>\w+)[是叫名](?P<chara2>{CHARA_RE}))', priority=10,
block=True, state={
add_alias = on_command('设置别名', priority=10, block=True, state={
'pm_name': '角色别名设置',
'pm_description': '设置专属于你的角色别名',
'pm_usage': '<角色名>是我<别名>',
'pm_description': '设置专属于你的角色别名,例如【设置别名钟离 老公】',
'pm_usage': '设置别名<角色> <别名>',
'pm_priority': 7
})
delete_alias = on_command('删除别名', priority=10, block=True, state={
@ -85,12 +76,6 @@ show_alias = on_command('查看别名', priority=10, block=True, state={
'pm_usage': '查看别名',
'pm_priority': 9
})
show_abyss = on_command('深渊统计', priority=10, block=True, state={
'pm_name': '深渊统计',
'pm_description': '查看本群深渊统计,仅群可用',
'pm_usage': '深渊统计',
'pm_priority': 10
})
@ys.handle()
@ -149,30 +134,6 @@ async def _(event: MessageEvent, players=CommandPlayer(2)):
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()
async def _(event: MessageEvent, players=CommandPlayer(only_cn=False), characters=CommandCharacter()):
logger.info('原神角色卡片', '开始执行')
@ -267,21 +228,42 @@ async def _(event: MessageEvent, uid=CommandUID(), msg: str = Arg('msg')):
@add_alias.handle()
async def _(event: MessageEvent, regex_dict: dict = RegexDict()):
chara = regex_dict['chara'] or regex_dict['chara2']
alias = regex_dict['alias'] or regex_dict['alias2']
async def _(event: MessageEvent, state: T_State, msg: Message = CommandArg()):
msg = msg.extract_plain_text().strip().split(' ')
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 add_alias.finish(f'{NICKNAME}知道{chara}是你的{alias}啦..')
await add_alias.finish(f'设置成功,{NICKNAME}知道{chara}是你的{alias}啦..')
@delete_alias.handle()
async def _(event: MessageEvent, msg: Message = CommandArg()):
msg = msg.extract_plain_text().strip()
if alias := await PlayerAlias.get_or_none(user_id=str(event.user_id), alias=msg):
async def _(event: MessageEvent, state: T_State, msg: Message = CommandArg()):
if 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 delete_alias.finish(f'别名{msg}删除成功!', at_sender=True)
else:
await delete_alias.finish(f'你并没有将{msg}设置为某个角色的别名', at_sender=True)
await delete_alias.reject(f'你并没有将{msg}设置为某个角色的别名', at_sender=True)
@show_alias.handle()
@ -291,9 +273,3 @@ async def _(event: MessageEvent):
at_sender=True)
else:
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)