优化管理员帮助,超级用户帮助图片,重新移植gamedraw,修复pil帮助私聊时无法生成

This commit is contained in:
HibiKier
2022-12-24 00:16:17 +08:00
parent 0dc11b7edb
commit b25b9ca928
33 changed files with 869 additions and 695 deletions
+85 -51
View File
@@ -1,11 +1,12 @@
import asyncio
import traceback
from cn2an import cn2an
from dataclasses import dataclass
from typing import Optional, Set, Tuple
from typing import Optional, Set, Tuple, Any
import nonebot
from nonebot import on_regex, on_keyword
from cn2an import cn2an
from configs.config import Config
from nonebot import on_keyword, on_regex
from nonebot.adapters.onebot.v11 import MessageEvent
from nonebot.log import logger
from nonebot.matcher import Matcher
@@ -14,8 +15,9 @@ from nonebot.permission import SUPERUSER
from nonebot.typing import T_Handler
from nonebot_plugin_apscheduler import scheduler
from .handles.base_handle import BaseHandle
from .handles.azur_handle import AzurHandle
from .handles.ba_handle import BaHandle
from .handles.base_handle import BaseHandle
from .handles.fgo_handle import FgoHandle
from .handles.genshin_handle import GenshinHandle
from .handles.guardian_handle import GuardianHandle
@@ -23,10 +25,6 @@ from .handles.onmyoji_handle import OnmyojiHandle
from .handles.pcr_handle import PcrHandle
from .handles.pretty_handle import PrettyHandle
from .handles.prts_handle import PrtsHandle
from .handles.ba_handle import BaHandle
from .config import draw_config
__zx_plugin_name__ = "游戏抽卡"
__plugin_usage__ = """
@@ -35,6 +33,7 @@ usage:
指令:
原神[1-180]抽: 原神常驻池
原神角色[1-180]抽: 原神角色UP池子
原神角色2池[1-180]抽: 原神角色UP池子
原神武器[1-180]抽: 原神武器UP池子
重置原神抽卡: 清空当前卡池的抽卡次数[即从0开始计算UP概率]
方舟[1-300]抽: 方舟卡池,当有当期UP时指向UP池
@@ -106,48 +105,18 @@ class Game:
flag: bool
max_count: int = 300 # 一次最大抽卡数
reload_time: Optional[int] = None # 重载UP池时间(小时)
has_other_pool: bool = False
games = (
Game({"azur", "碧蓝航线"}, AzurHandle(), draw_config.AZUR_FLAG),
Game({"fgo", "命运冠位指定"}, FgoHandle(), draw_config.FGO_FLAG),
Game(
{"genshin", "原神"},
GenshinHandle(),
draw_config.GENSHIN_FLAG,
max_count=180,
reload_time=18,
),
Game(
{"guardian", "坎公骑冠剑"},
GuardianHandle(),
draw_config.GUARDIAN_FLAG,
reload_time=4,
),
Game({"onmyoji", "阴阳师"}, OnmyojiHandle(), draw_config.ONMYOJI_FLAG),
Game({"pcr", "公主连结", "公主连接", "公主链接", "公主焊接"}, PcrHandle(), draw_config.PCR_FLAG),
Game(
{"pretty", "马娘", "赛马娘"},
PrettyHandle(),
draw_config.PRETTY_FLAG,
max_count=200,
reload_time=4,
),
Game({"prts", "方舟", "明日方舟"}, PrtsHandle(), draw_config.PRTS_FLAG, reload_time=4),
Game(
{"ba","碧蓝档案"},BaHandle(),
draw_config.BA_FLAG,
max_count=200,
),
)
games = None
def create_matchers():
def draw_handler(game: Game) -> T_Handler:
async def handler(
matcher: Matcher, event: MessageEvent, args: Tuple[str, ...] = RegexGroup()
matcher: Matcher, event: MessageEvent, args: Tuple[Any, ...] = RegexGroup()
):
pool_name, num, unit = args
pool_name, pool_type_, num, unit = args
if num == "单":
num = 1
else:
@@ -168,8 +137,11 @@ def create_matchers():
.replace("卡牌", "card")
.replace("卡", "card")
)
try:
res = await game.handle.draw(num, pool_name=pool_name, user_id=event.user_id)
if pool_type_ in ["2池", "二池"]:
pool_name = pool_name + "1"
res = game.handle.draw(num, pool_name=pool_name, user_id=event.user_id)
except:
logger.warning(traceback.format_exc())
await matcher.finish("出错了...")
@@ -209,8 +181,11 @@ def create_matchers():
pool_pattern = r"([^\s单0-9零一二三四五六七八九百十]{0,3})"
num_pattern = r"(单|[0-9零一二三四五六七八九百十]{1,3})"
unit_pattern = r"([抽|井|连])"
draw_regex = r".*?(?:{})\s*{}\s*{}\s*{}".format(
"|".join(game.keywords), pool_pattern, num_pattern, unit_pattern
pool_type = "()"
if game.has_other_pool:
pool_type = r"([2二]池)?"
draw_regex = r".*?(?:{})\s*{}\s*{}\s*{}\s*{}".format(
"|".join(game.keywords), pool_pattern, pool_type, num_pattern, unit_pattern
)
update_keywords = {f"更新{keyword}信息" for keyword in game.keywords}
reload_keywords = {f"重载{keyword}卡池" for keyword in game.keywords}
@@ -220,12 +195,12 @@ def create_matchers():
draw_handler(game)
)
on_keyword(
update_keywords, permission=SUPERUSER, priority=1, block=True
update_keywords, priority=1, block=True, permission=SUPERUSER
).append_handler(update_handler(game))
on_keyword(reload_keywords, priority=1, block=True).append_handler(
reload_handler(game)
)
on_keyword(reset_keywords, priority=1, block=True).append_handler(
on_keyword(
reload_keywords, priority=1, block=True, permission=SUPERUSER
).append_handler(reload_handler(game))
on_keyword(reset_keywords, priority=5, block=True).append_handler(
reset_handler(game)
)
if game.reload_time:
@@ -234,7 +209,7 @@ def create_matchers():
)
create_matchers()
# create_matchers()
# 更新资源
@@ -256,6 +231,65 @@ driver = nonebot.get_driver()
@driver.on_startup
async def _():
global games
if not games:
from .config import draw_config
games = (
Game(
{"azur", "碧蓝航线"},
AzurHandle(),
Config.get_config("draw_card", "AZUR_FLAG", True),
),
Game(
{"fgo", "命运冠位指定"},
FgoHandle(),
Config.get_config("draw_card", "FGO_FLAG", True),
),
Game(
{"genshin", "原神"},
GenshinHandle(),
Config.get_config("draw_card", "GENSHIN_FLAG", True),
max_count=180,
reload_time=18,
has_other_pool=True,
),
Game(
{"guardian", "坎公骑冠剑"},
GuardianHandle(),
Config.get_config("draw_card", "GUARDIAN_FLAG", True),
reload_time=4,
),
Game(
{"onmyoji", "阴阳师"},
OnmyojiHandle(),
Config.get_config("draw_card", "ONMYOJI_FLAG", True),
),
Game(
{"pcr", "公主连结", "公主连接", "公主链接", "公主焊接"},
PcrHandle(),
Config.get_config("draw_card", "PCR_FLAG", True),
),
Game(
{"pretty", "马娘", "赛马娘"},
PrettyHandle(),
Config.get_config("draw_card", "PRETTY_FLAG", True),
max_count=200,
reload_time=4,
),
Game(
{"prts", "方舟", "明日方舟"},
PrtsHandle(),
Config.get_config("draw_card", "PRTS_FLAG", True),
reload_time=4,
),
Game(
{"ba", "碧蓝档案"},
BaHandle(),
Config.get_config("draw_card", "BA_FLAG", True),
),
)
create_matchers()
tasks = []
for game in games:
if game.flag:
+33 -19
View File
@@ -1,9 +1,9 @@
import nonebot
from pathlib import Path
from nonebot.log import logger
from pydantic import BaseModel, Extra
from pydantic import BaseModel, Extra, ValidationError
from configs.config import Config as AConfig
from configs.path_config import DATA_PATH
from configs.path_config import IMAGE_PATH, DATA_PATH
try:
import ujson as json
@@ -87,28 +87,30 @@ class OnmyojiConfig(BaseModel, extra=Extra.ignore):
ONMYOJI_SR: float = 0.2
ONMYOJI_R: float = 0.7875
#碧蓝档案
# 碧蓝档案
class BaConfig(BaseModel, extra=Extra.ignore):
BA_THREE_P: float = 0.025
BA_TWO_P: float = 0.185
BA_ONE_P: float = 0.79
BA_G_TWO_P: float = 0.975
class Config(BaseModel, extra=Extra.ignore):
# 开关
PRTS_FLAG: bool = AConfig.get_config("draw_card", "PRTS_FLAG")
GENSHIN_FLAG: bool = AConfig.get_config("draw_card", "GENSHIN_FLAG")
PRETTY_FLAG: bool = AConfig.get_config("draw_card", "PRETTY_FLAG")
GUARDIAN_FLAG: bool = AConfig.get_config("draw_card", "GUARDIAN_FLAG")
PCR_FLAG: bool = AConfig.get_config("draw_card", "PCR_FLAG")
AZUR_FLAG: bool = AConfig.get_config("draw_card", "AZUR_FLAG")
FGO_FLAG: bool = AConfig.get_config("draw_card", "FGO_FLAG")
ONMYOJI_FLAG: bool = AConfig.get_config("draw_card", "ONMYOJI_FLAG")
BA_FLAG: bool = AConfig.get_config("draw_card", "BA_FLAG")
PRTS_FLAG: bool = True
GENSHIN_FLAG: bool = True
PRETTY_FLAG: bool = True
GUARDIAN_FLAG: bool = True
PCR_FLAG: bool = True
AZUR_FLAG: bool = True
FGO_FLAG: bool = True
ONMYOJI_FLAG: bool = True
BA_FLAG: bool = True
# 其他配置
PCR_TAI: bool = AConfig.get_config("draw_card", "PCR_TAI")
SEMAPHORE: int = AConfig.get_config("draw_card", "SEMAPHORE")
PCR_TAI: bool = True
SEMAPHORE: int = 5
# 抽卡概率
prts: PrtsConfig = PrtsConfig()
@@ -124,12 +126,16 @@ class Config(BaseModel, extra=Extra.ignore):
driver = nonebot.get_driver()
DRAW_PATH = DATA_PATH / "draw_card"
config_path = DRAW_PATH / "draw_card_config" / "draw_card_config.json"
# DRAW_PATH = Path("data/draw_card").absolute()
DRAW_PATH = IMAGE_PATH / "draw_card"
# try:
# DRAW_PATH = Path(global_config.draw_path).absolute()
# except:
# pass
config_path = DATA_PATH / "draw_card" / "draw_card_config" / "draw_card_config.json"
draw_config: Config = Config()
for game_flag, game_name in zip(
[
"PRTS_FLAG",
@@ -143,7 +149,7 @@ for game_flag, game_name in zip(
"PCR_TAI",
"BA_FLAG"
],
["明日方舟", "原神", "赛马娘", "坎公骑冠剑", "公主连结", "碧蓝航线", "命运-冠位指定(FGO)", "阴阳师", "pcr台服卡池","碧蓝档案"],
["明日方舟", "原神", "赛马娘", "坎公骑冠剑", "公主连结", "碧蓝航线", "命运-冠位指定(FGO)", "阴阳师", "pcr台服卡池", "碧蓝档案"],
):
AConfig.add_plugin_config(
"draw_card",
@@ -161,11 +167,19 @@ AConfig.add_plugin_config(
@driver.on_startup
def check_config():
global draw_config
draw_config = Config()
if not config_path.exists():
config_path.parent.mkdir(parents=True, exist_ok=True)
draw_config = Config()
logger.warning("draw_card:配置文件不存在,已重新生成配置文件.....")
else:
with config_path.open("r", encoding="utf8") as fp:
data = json.load(fp)
try:
draw_config = Config.parse_obj({**data})
except ValidationError:
draw_config = Config()
logger.warning("draw_card:配置文件格式错误,已重新生成配置文件.....")
with config_path.open("w", encoding="utf8") as fp:
json.dump(
+44 -64
View File
@@ -1,15 +1,16 @@
from typing import Optional
from typing import Optional, TypeVar, Generic
from pydantic import BaseModel
import time
from cachetools import TTLCache
class BaseUserCount(BaseModel):
count: int = 1 # 当前抽卡次数
time_: int = time.time() # 抽卡时间,当超过一定时间时将重置抽卡次数
timeout: int = 60 # 超时时间60秒
count: int = 0 # 当前抽卡次数
class DrawCountManager:
TCount = TypeVar("TCount", bound="BaseUserCount")
class DrawCountManager(Generic[TCount]):
"""
抽卡统计保底
"""
@@ -30,19 +31,28 @@ class DrawCountManager:
"""
# 只有保底
self._data = {}
# 超过60秒重置抽卡次数
self._data: TTLCache[int, TCount] = TTLCache(maxsize=1000, ttl=60)
self._guarantee_tuple = game_draw_count_rule
self._star2name = star2name
self._max_draw_count = max_draw_count
@classmethod
def get_count_class(cls) -> TCount:
raise NotImplementedError
def _get_count(self, key: int) -> TCount:
if self._data.get(key) is None:
self._data[key] = self.get_count_class()
else:
self._data[key] = self._data[key]
return self._data[key]
def increase(self, key: int, value: int = 1):
"""
用户抽卡次数加1
"""
if self._data.get(key) is None:
self._data[key] = BaseUserCount()
else:
self._data[key].count += 1
self._get_count(key).count += value
def get_max_guarantee(self):
"""
@@ -54,103 +64,74 @@ class DrawCountManager:
"""
获取当前抽卡次数
"""
return self._data[key].count
def update_time(self, key: int):
"""
更新抽卡时间
"""
self._data[key].time_ = time.time()
return self._get_count(key).count
def reset(self, key: int):
"""
清空记录
"""
del self._data[key]
self._data.pop(key, None)
class GenshinCountManager(DrawCountManager):
class UserCount(BaseUserCount):
five_index: int = 0 # 获取五星时的抽卡次数
four_index: int = 0 # 获取四星时的抽卡次数
is_up: bool = False # 下次五星是否必定为up
class GenshinUserCount(BaseUserCount):
five_index: int = 0 # 获取五星时的抽卡次数
four_index: int = 0 # 获取四星时的抽卡次数
is_up: bool = False # 下次五星是否必定为up
def increase(self, key: int, value: int = 1):
"""
用户抽卡次数加1
"""
if self._data.get(key) is None:
self._data[key] = self.UserCount()
else:
self._data[key].count += 1
class GenshinCountManager(DrawCountManager[GenshinUserCount]):
@classmethod
def get_count_class(cls) -> GenshinUserCount:
return GenshinUserCount()
def set_is_up(self, key: int, value: bool):
"""
设置下次是否必定up
"""
self._data[key].is_up = value
self._get_count(key).is_up = value
def is_up(self, key: int) -> bool:
"""
判断该次保底是否必定为up
"""
return self._data[key].is_up
return self._get_count(key).is_up
def get_user_five_index(self, key: int) -> int:
"""
获取用户上次获取五星的次数
"""
return self._data[key].five_index
return self._get_count(key).five_index
def get_user_four_index(self, key: int) -> int:
"""
获取用户上次获取四星的次数
"""
return self._data[key].four_index
return self._get_count(key).four_index
def mark_five_index(self, key: int):
"""
标记用户该次次数为五星
"""
self._data[key].five_index = self._data[key].count
self._get_count(key).five_index = self._get_count(key).count
def mark_four_index(self, key: int):
"""
标记用户该次次数为四星
"""
self._data[key].four_index = self._data[key].count
def check_timeout(self, key: int):
"""
检查用户距离上次抽卡是否超时
"""
if key in self._data.keys() and self._is_timeout(key):
del self._data[key]
self._get_count(key).four_index = self._get_count(key).count
def check_count(self, key: int, count: int):
"""
检查用户该次抽卡次数累计是否超过最大限制次数
"""
if (
key in self._data.keys()
and self._data[key].count + count > self._max_draw_count
):
del self._data[key]
def _is_timeout(self, key: int) -> bool:
return time.time() - self._data[key].time_ > self._data[key].timeout
if self._get_count(key).count + count > self._max_draw_count:
self._data.pop(key, None)
def get_user_guarantee_count(self, key: int) -> int:
user = self._get_count(key)
return (
self.get_max_guarantee()
- (
(
self._data[key].count % self.get_max_guarantee()
if self._data[key].count > 0
else 0
)
- self._data[key].five_index
)
- (user.count % self.get_max_guarantee() - user.five_index)
) % self.get_max_guarantee() or self.get_max_guarantee()
def check(self, key: int) -> Optional[int]:
@@ -158,12 +139,11 @@ class GenshinCountManager(DrawCountManager):
是否保底
"""
# print(self._data)
user: GenshinCountManager.UserCount = self._data[key]
user = self._get_count(key)
if user.count - user.five_index == 90:
user.five_index = 90
user.five_index = user.count
return 5
if user.count - user.four_index == 10:
user.four_index = user.count
return 4
return None
+44 -27
View File
@@ -1,17 +1,17 @@
import contextlib
import random
import dateparser
from lxml import etree
from typing import List, Optional, Tuple
from PIL import ImageDraw
from urllib.parse import unquote
from pydantic import ValidationError
from nonebot.log import logger
from nonebot.adapters.onebot.v11 import Message
from utils.message_builder import image
from nonebot.adapters.onebot.v11 import Message, MessageSegment
from utils.message_builder import image
from .base_handle import BaseHandle, BaseData, UpEvent as _UpEvent, UpChar as _UpChar
from ..config import draw_config
from ..util import remove_prohibited_str, cn2py
from ..util import remove_prohibited_str, cn2py, load_font
from utils.image_utils import BuildImage
try:
@@ -59,19 +59,25 @@ class AzurHandle(BaseHandle[AzurChar]):
# print(up_ship)
acquire_char = None
if up_ship and up_pool_flag:
up_zoom = [(0, up_ship[0].zoom / 100)]
up_zoom: List[Tuple[float, float]] = [(0, up_ship[0].zoom / 100)]
# 初始化概率
cur_ = up_ship[0].zoom / 100
for i in range(len(up_ship)):
with contextlib.suppress(IndexError):
try:
up_zoom.append((cur_, cur_ + up_ship[i + 1].zoom / 100))
cur_ += up_ship[i + 1].zoom / 100
except IndexError:
pass
rand = random.random()
# 抽取up
for i, zoom in enumerate(up_zoom):
if zoom[0] <= rand <= zoom[1]:
with contextlib.suppress(IndexError):
acquire_char = [x for x in self.ALL_CHAR if x.name == up_ship[i].name][0]
try:
acquire_char = [
x for x in self.ALL_CHAR if x.name == up_ship[i].name
][0]
except IndexError:
pass
# 没有up或者未抽取到up
if not acquire_char:
star = self.get_star(
@@ -83,17 +89,19 @@ class AzurHandle(BaseHandle[AzurChar]):
self.config.AZUR_ONE_P,
],
)
acquire_char = random.choice([
x
for x in self.ALL_CHAR
if x.star == star and x.type_ in type_ and not x.limited
])
acquire_char = random.choice(
[
x
for x in self.ALL_CHAR
if x.star == star and x.type_ in type_ and not x.limited
]
)
return acquire_char
async def draw(self, count: int, **kwargs) -> Message:
def draw(self, count: int, **kwargs) -> Message:
index2card = self.get_cards(count, **kwargs)
cards = [card[0] for card in index2card]
up_list = [x.name for x in self.UP_EVENT.up_char] if self.UP_EVENT.up_char else []
up_list = [x.name for x in self.UP_EVENT.up_char] if self.UP_EVENT else []
result = self.format_result(index2card, **{**kwargs, "up_list": up_list})
return image(b64=self.generate_img(cards).pic2bs4()) + result
@@ -103,22 +111,25 @@ class AzurHandle(BaseHandle[AzurChar]):
sep_b = 20
w = 100
h = 100
bg = BuildImage(w + sep_w * 2, h + sep_t + sep_b, font="msyh.ttf")
frame_path = self.img_path / f"{card.star}_star.png"
bg = BuildImage(w + sep_w * 2, h + sep_t + sep_b)
frame_path = str(self.img_path / f"{card.star}_star.png")
frame = BuildImage(w, h, background=frame_path)
img_path = self.img_path / f"{cn2py(card.name)}.png"
img_path = str(self.img_path / f"{cn2py(card.name)}.png")
img = BuildImage(w, h, background=img_path)
# 加圆角
frame.circle_corner(6)
img.circle_corner(6)
bg.paste(img, (sep_w, sep_t), alpha=True)
bg.paste(frame, (sep_w, sep_t), alpha=True)
bg.circle_corner(6)
# 加名字
text = card.name[:6] + "..." if len(card.name) > 7 else card.name
text_w, text_h = bg.getsize(text)
bg.text(
font = load_font(fontsize=14)
text_w, text_h = font.getsize(text)
draw = ImageDraw.Draw(bg.markImg)
draw.text(
(sep_w + (w - text_w) / 2, h + sep_t + (sep_b - text_h) / 2),
text,
font=font,
fill=["#808080", "#3b8bff", "#8000ff", "#c90", "#ee494c"][card.star - 1],
)
return bg
@@ -146,6 +157,7 @@ class AzurHandle(BaseHandle[AzurChar]):
if self.UP_EVENT:
data = {"char": json.loads(self.UP_EVENT.json())}
self.dump_data(data, f"draw_card_up/{self.game_name}_up_char.json")
self.dump_data(data, f"draw_card_up/{self.game_name}_up_char.json")
async def _update_info(self):
info = {}
@@ -220,17 +232,22 @@ class AzurHandle(BaseHandle[AzurChar]):
@staticmethod
def parse_star(star: str) -> int:
if star in {"舰娘头像外框普通.png", "舰娘头像外框白色.png"}:
if star in ["舰娘头像外框普通.png", "舰娘头像外框白色.png"]:
return 1
elif star in {"舰娘头像外框稀有.png", "舰娘头像外框蓝色.png"}:
elif star in ["舰娘头像外框稀有.png", "舰娘头像外框蓝色.png"]:
return 2
elif star in {"舰娘头像外框精锐.png", "舰娘头像外框紫色.png"}:
elif star in ["舰娘头像外框精锐.png", "舰娘头像外框紫色.png"]:
return 3
elif star in {"舰娘头像外框超稀有.png", "舰娘头像外框金色.png"}:
elif star in ["舰娘头像外框超稀有.png", "舰娘头像外框金色.png"]:
return 4
elif star in {"舰娘头像外框海上传奇.png", "舰娘头像外框彩色.png"}:
elif star in ["舰娘头像外框海上传奇.png", "舰娘头像外框彩色.png"]:
return 5
elif star in {"舰娘头像外框最高方案.png", "舰娘头像外框决战方案.png", "舰娘头像外框超稀有META.png", "舰娘头像外框精锐META.png"}:
elif star in [
"舰娘头像外框最高方案.png",
"舰娘头像外框决战方案.png",
"舰娘头像外框超稀有META.png",
"舰娘头像外框精锐META.png",
]:
return 6
else:
return 6
+29 -69
View File
@@ -1,17 +1,17 @@
import random
import json
from utils.http_utils import AsyncHttpx
from lxml import etree
from typing import List, Tuple
from PIL import ImageDraw
from urllib.parse import unquote
from nonebot.log import logger
from .base_handle import BaseHandle, BaseData
from ..config import draw_config
from ..util import remove_prohibited_str, cn2py, load_font
from lxml import etree
from nonebot.log import logger
from PIL import ImageDraw
from utils.http_utils import AsyncHttpx
from utils.image_utils import BuildImage
from ..config import draw_config
from ..util import cn2py, load_font, remove_prohibited_str
from .base_handle import BaseData, BaseHandle
class BaChar(BaseData):
pass
@@ -68,17 +68,19 @@ class BaHandle(BaseHandle[BaChar]):
bar = BuildImage(bar_w, bar_h, color="#6495ED")
bg.paste(img, (sep_w, sep_h), alpha=True)
bg.paste(bar, (sep_w, img_h - bar_h + sep_h), alpha=True)
if (card.star == 1):
if card.star == 1:
star_path = str(self.img_path / "star-1.png")
star_w = 15
elif (card.star == 2):
elif card.star == 2:
star_path = str(self.img_path / "star-2.png")
star_w = 30
else:
star_path = str(self.img_path / "star-3.png")
star_w = 45
star = BuildImage(star_w, star_h, background=star_path)
bg.paste(star, (img_w // 2 - 15 * (card.star - 1) // 2, img_h - star_h), alpha=True)
bg.paste(
star, (img_w // 2 - 15 * (card.star - 1) // 2, img_h - star_h), alpha=True
)
text = card.name[:5] + "..." if len(card.name) > 6 else card.name
font = load_font(fontsize=14)
text_w, text_h = font.getsize(text)
@@ -100,78 +102,37 @@ class BaHandle(BaseHandle[BaChar]):
)
for key, value in self.load_data().items()
]
def title2star(self, title: int):
if title == 'Star-3.png':
if title == "Star-3.png":
return 3
elif title == 'Star-2.png':
elif title == "Star-2.png":
return 2
else:
return 1
# Bwiki 待恢复
# async def _update_info(self):
# info = {}
# url = "https://wiki.biligame.com/bluearchive/学生筛选"
# result = await self.get_url(url)
# if not result:
# logger.warning(f"更新 {self.game_name_cn} 出错")
# return
# else:
# dom = etree.HTML(result, etree.HTMLParser())
# char_list = dom.xpath("//div[@class='filters']/table[2]/tbody/tr")
# for char in char_list:
# try:
# name = char.xpath("./td[2]/a/div/text()")[0]
# avatar = char.xpath("./td[1]/div/div/a/img/@data-src")[0]
# star_pic = char.xpath("./td[4]/img/@alt")[0]
# except IndexError:
# continue
# member_dict = {
# "头像": unquote(str(avatar)),
# "名称": remove_prohibited_str(name),
# "星级": self.title2star(star_pic),
# }
# info[member_dict["名称"]] = member_dict
# self.dump_data(info)
# logger.info(f"{self.game_name_cn} 更新成功")
# # 下载头像
# for value in info.values():
# await self.download_img(value["头像"], value["名称"])
# # 下载星星
# await self.download_img(
# "https://patchwiki.biligame.com/images/bluearchive/thumb/e/e0/82nj2x9sxko473g7782r14fztd4zyky.png/15px-Star-1.png",
# "star-1",
# )
# await self.download_img(
# "https://patchwiki.biligame.com/images/bluearchive/thumb/0/0b/msaff2g0zk6nlyl1rrn7n1ri4yobcqc.png/30px-Star-2.png",
# "star-2",
# )
# await self.download_img(
# "https://patchwiki.biligame.com/images/bluearchive/thumb/8/8a/577yv79x1rwxk8efdccpblo0lozl158.png/46px-Star-3.png",
# "star-3"
# )
# 数据来源:SCHALE DB
async def _update_info(self):
info = {}
url = "https://lonqie.github.io/SchaleDB/data/cn/students.min.json?v=49"
result = await AsyncHttpx.get(url)
if result.status_code != 200:
result = (await AsyncHttpx.get(url)).json()
if not result:
logger.warning(f"更新 {self.game_name_cn} 出错")
return
else:
char_list = json.loads(result.text)
for char in char_list:
for char in result:
try:
name = char.get("Name")
avatar = "https://lonqie.github.io/SchaleDB/images/student/icon/"+char.get("CollectionTexture")+".png"
star = char.get("StarGrade")
name = char["Name"]
avatar = (
"https://github.com/lonqie/SchaleDB/raw/main/images/student/icon/"
+ char["CollectionTexture"]
+ ".png"
)
star = char["StarGrade"]
except IndexError:
continue
member_dict = {
"头像": unquote(str(avatar)),
"名称": remove_prohibited_str(name),
"头像": avatar,
"名称": name,
"星级": star,
}
info[member_dict["名称"]] = member_dict
@@ -191,6 +152,5 @@ class BaHandle(BaseHandle[BaChar]):
)
await self.download_img(
"https://patchwiki.biligame.com/images/bluearchive/thumb/8/8a/577yv79x1rwxk8efdccpblo0lozl158.png/46px-Star-3.png",
"star-3"
"star-3",
)
+12 -17
View File
@@ -1,18 +1,18 @@
import math
import anyio
import random
import aiohttp
import asyncio
import aiofiles
from PIL import Image
from datetime import datetime
from pydantic import BaseModel, Extra
from asyncio.exceptions import TimeoutError
from typing import Dict, List, Optional, TypeVar, Generic, Tuple
from nonebot.adapters.onebot.v11 import Message
from configs.path_config import IMAGE_PATH
from utils.message_builder import image
from nonebot.adapters.onebot.v11 import Message, MessageSegment
from nonebot.log import logger
import asyncio
from configs.path_config import DATA_PATH
from utils.message_builder import image
try:
import ujson as json
@@ -50,29 +50,25 @@ class UpEvent(BaseModel):
start_time: Optional[datetime] # 开始时间
end_time: Optional[datetime] # 结束时间
up_char: List[UpChar] # up对象
up_name: str = "" # up名称
TC = TypeVar("TC", bound="BaseData")
class BaseHandle(Generic[TC]):
def __init__(self, game_name: str, game_name_cn: str, game_card_color: str = "#ffffff"):
def __init__(self, game_name: str, game_name_cn: str):
self.game_name = game_name
self.game_name_cn = game_name_cn
self.max_star = 1 # 最大星级
self.data_path = DRAW_PATH
self.img_path = IMAGE_PATH / f"draw_card/{self.game_name}"
self.up_path = DRAW_PATH / "draw_card_up"
self.game_card_color: str = "#ffffff"
self.data_path = DATA_PATH / "draw_card"
self.img_path = DRAW_PATH / f"{self.game_name}"
self.up_path = DATA_PATH / "draw_card" / "draw_card_up"
self.img_path.mkdir(parents=True, exist_ok=True)
self.up_path.mkdir(parents=True, exist_ok=True)
self.data_files: List[str] = [f"{self.game_name}.json"]
self.game_card_color: str = game_card_color
async def draw(self, count: int, **kwargs) -> Message:
return await asyncio.get_event_loop().run_in_executor(None, self._draw, count)
def _draw(self, count: int, **kwargs) -> Message:
def draw(self, count: int, **kwargs) -> Message:
index2card = self.get_cards(count, **kwargs)
cards = [card[0] for card in index2card]
result = self.format_result(index2card)
@@ -173,7 +169,6 @@ class BaseHandle(Generic[TC]):
card_imgs: List[BuildImage] = []
for card, num in zip(card_list, num_list):
card_img = self.generate_card_img(card)
# 数量 > 1 时加数字上标
if num > 1:
label = circled_number(num)
@@ -274,7 +269,7 @@ class BaseHandle(Generic[TC]):
return True
try:
async with self.session.get(url, timeout=10) as response:
async with aiofiles.open(str(img_path), "wb") as f:
async with await anyio.open_file(img_path, "wb") as f:
await f.write(await response.read())
return True
except TimeoutError:
+52 -33
View File
@@ -6,10 +6,10 @@ from urllib.parse import unquote
from typing import List, Optional, Tuple
from pydantic import ValidationError
from datetime import datetime, timedelta
from nonebot.adapters.onebot.v11 import Message
from utils.message_builder import image
from nonebot.adapters.onebot.v11 import Message, MessageSegment
from nonebot.log import logger
import asyncio
from utils.message_builder import image
try:
import ujson as json
@@ -37,21 +37,23 @@ class GenshinArms(GenshinData):
class GenshinHandle(BaseHandle[GenshinData]):
def __init__(self):
super().__init__("genshin", "原神", "#ebebeb")
super().__init__("genshin", "原神")
self.data_files.append("genshin_arms.json")
self.max_star = 5
self.game_card_color = "#ebebeb"
self.config = draw_config.genshin
self.ALL_CHAR: List[GenshinData] = []
self.ALL_ARMS: List[GenshinData] = []
self.UP_CHAR: Optional[UpEvent] = None
self.UP_CHAR_LIST: Optional[UpEvent] = []
self.UP_ARMS: Optional[UpEvent] = None
self.count_manager = GenshinCountManager((10, 90), ("4", "5"), 180)
# 抽取卡池
def get_card(
self, pool_name: str, mode: int = 1, add: float = 0.0, is_up: bool = False
self, pool_name: str, mode: int = 1, add: float = 0.0, is_up: bool = False, card_index: int = 0
):
"""
mode 1:普通抽 2:四星保底 3:五星保底
@@ -74,7 +76,7 @@ class GenshinHandle(BaseHandle[GenshinData]):
star = 5
if pool_name == "char":
up_event = self.UP_CHAR
up_event = self.UP_CHAR_LIST[card_index]
all_list = self.ALL_CHAR + [
x for x in self.ALL_ARMS if x.star == star and x.star < 5
]
@@ -105,14 +107,13 @@ class GenshinHandle(BaseHandle[GenshinData]):
return acquire_char
def get_cards(
self, count: int, user_id: int, pool_name: str
self, count: int, user_id: int, pool_name: str, card_index: int = 0
) -> List[Tuple[GenshinData, int]]:
card_list = [] # 获取角色列表
add = 0.0
count_manager = self.count_manager
count_manager.check_timeout(user_id) # 检查上次抽卡次数是否超时
count_manager.check_count(user_id, count) # 检查次数累计
pool = self.UP_CHAR if pool_name == "char" else self.UP_ARMS
pool = self.UP_CHAR_LIST[card_index] if pool_name == "char" else self.UP_ARMS
for i in range(count):
count_manager.increase(user_id)
star = count_manager.check(user_id) # 是否有四星或五星保底
@@ -123,13 +124,13 @@ class GenshinHandle(BaseHandle[GenshinData]):
add += draw_config.genshin.I72_ADD
if star:
if star == 4:
card = self.get_card(pool_name, 2, add=add)
card = self.get_card(pool_name, 2, add=add, card_index=card_index)
else:
card = self.get_card(
pool_name, 3, add, count_manager.is_up(user_id)
pool_name, 3, add, count_manager.is_up(user_id), card_index=card_index
)
else:
card = self.get_card(pool_name, 1, add, count_manager.is_up(user_id))
card = self.get_card(pool_name, 1, add, count_manager.is_up(user_id), card_index=card_index)
# print(f"{count_manager.get_user_count(user_id)}:",
# count_manager.get_user_five_index(user_id), star, card.star, add)
# 四星角色
@@ -147,7 +148,6 @@ class GenshinHandle(BaseHandle[GenshinData]):
else:
count_manager.set_is_up(user_id, False)
card_list.append((card, count_manager.get_user_count(user_id)))
count_manager.update_time(user_id)
return card_list
def generate_card_img(self, card: GenshinData) -> BuildImage:
@@ -188,11 +188,11 @@ class GenshinHandle(BaseHandle[GenshinData]):
bg.paste(star, (sep_w + int((frame_w - star.width) / 2), sep_h - 6), alpha=True)
return bg
def format_pool_info(self, pool_name: str) -> str:
def format_pool_info(self, pool_name: str, card_index: int = 0) -> str:
info = ""
up_event = None
if pool_name == "char":
up_event = self.UP_CHAR
up_event = self.UP_CHAR_LIST[card_index]
elif pool_name == "arms":
up_event = self.UP_ARMS
if up_event:
@@ -205,15 +205,18 @@ class GenshinHandle(BaseHandle[GenshinData]):
info = f"当前up池:{up_event.title}\n{info}"
return info.strip()
async def draw(self, count: int, user_id: int, pool_name: str = "", **kwargs) -> Message:
return await asyncio.get_event_loop().run_in_executor(None, self._draw, count, user_id, pool_name)
def _draw(self, count: int, user_id: int, pool_name: str = "", **kwargs) -> Message:
index2cards = self.get_cards(count, user_id, pool_name)
def draw(self, count: int, user_id: int, pool_name: str = "", **kwargs) -> Message:
card_index = 0
if "1" in pool_name:
card_index = 1
pool_name = pool_name.replace("1", "")
index2cards = self.get_cards(count, user_id, pool_name, card_index)
cards = [card[0] for card in index2cards]
up_event = None
if pool_name == "char":
up_event = self.UP_CHAR
if card_index == 1 and len(self.UP_CHAR_LIST) == 1:
return Message("当前没有第二个角色UP池")
up_event = self.UP_CHAR_LIST[card_index]
elif pool_name == "arms":
up_event = self.UP_ARMS
up_list = [x.name for x in up_event.up_char] if up_event else []
@@ -225,7 +228,7 @@ class GenshinHandle(BaseHandle[GenshinData]):
)
result += f"\n距离保底发还剩 {self.count_manager.get_user_guarantee_count(user_id)} 抽"
# result += "\n【五星:0.6%,四星:5.1%,第72抽开始五星概率每抽加0.585%】"
pool_info = self.format_pool_info(pool_name)
pool_info = self.format_pool_info(pool_name, card_index)
img = self.generate_img(cards)
bk = BuildImage(img.w, img.h + 50, font_size=20, color="#ebebeb")
bk.paste(img)
@@ -255,17 +258,20 @@ class GenshinHandle(BaseHandle[GenshinData]):
def load_up_char(self):
try:
data = self.load_data(f"draw_card_up/{self.game_name}_up_char.json")
self.UP_CHAR = UpEvent.parse_obj(data.get("char", {}))
self.UP_CHAR_LIST.append(UpEvent.parse_obj(data.get("char", {})))
self.UP_CHAR_LIST.append(UpEvent.parse_obj(data.get("char1", {})))
self.UP_ARMS = UpEvent.parse_obj(data.get("arms", {}))
except ValidationError:
logger.warning(f"{self.game_name}_up_char 解析出错")
def dump_up_char(self):
if self.UP_CHAR and self.UP_ARMS:
if self.UP_CHAR_LIST and self.UP_ARMS:
data = {
"char": json.loads(self.UP_CHAR.json()),
"char": json.loads(self.UP_CHAR_LIST[0].json()),
"arms": json.loads(self.UP_ARMS.json()),
}
if len(self.UP_CHAR_LIST) > 1:
data['char1'] = json.loads(self.UP_CHAR_LIST[1].json())
self.dump_data(data, f"draw_card_up/{self.game_name}_up_char.json")
async def _update_info(self):
@@ -359,6 +365,7 @@ class GenshinHandle(BaseHandle[GenshinData]):
await self.update_up_char()
async def update_up_char(self):
self.UP_CHAR_LIST = []
url = "https://wiki.biligame.com/ys/祈愿"
result = await self.get_url(url)
if not result:
@@ -399,14 +406,15 @@ class GenshinHandle(BaseHandle[GenshinData]):
for name in star4_list
],
)
if index == 0:
self.UP_CHAR = up_event
elif index == 1:
if '神铸赋形' not in title:
self.UP_CHAR_LIST.append(up_event)
else:
self.UP_ARMS = up_event
if self.UP_CHAR and self.UP_ARMS:
if self.UP_CHAR_LIST and self.UP_ARMS:
self.dump_up_char()
char_title = " & ".join([x.title for x in self.UP_CHAR_LIST])
logger.info(
f"成功获取{self.game_name_cn}当前up信息...当前up池: {self.UP_CHAR.title} & {self.UP_ARMS.title}"
f"成功获取{self.game_name_cn}当前up信息...当前up池: {char_title} & {self.UP_ARMS.title}"
)
except Exception as e:
logger.warning(f"{self.game_name_cn}UP更新出错 {type(e)}:{e}")
@@ -418,12 +426,23 @@ class GenshinHandle(BaseHandle[GenshinData]):
async def _reload_pool(self) -> Optional[Message]:
await self.update_up_char()
self.load_up_char()
if self.UP_CHAR and self.UP_ARMS:
if self.UP_CHAR_LIST and self.UP_ARMS:
if len(self.UP_CHAR_LIST) > 1:
return Message(
Message.template("重载成功!\n当前UP池子:{} & {} & {}{:image}{:image}{:image}").format(
self.UP_CHAR_LIST[0].title,
self.UP_CHAR_LIST[1].title,
self.UP_ARMS.title,
self.UP_CHAR_LIST[0].pool_img,
self.UP_CHAR_LIST[1].pool_img,
self.UP_ARMS.pool_img,
)
)
return Message(
Message.template("重载成功!\n当前UP池子:{} & {}{:image}{:image}").format(
self.UP_CHAR.title,
char_title,
self.UP_ARMS.title,
self.UP_CHAR.pool_img,
self.UP_CHAR_LIST[0].pool_img,
self.UP_ARMS.pool_img,
)
)
+10 -10
View File
@@ -7,10 +7,10 @@ from datetime import datetime
from urllib.parse import unquote
from typing import List, Optional, Tuple
from pydantic import ValidationError
from nonebot.adapters.onebot.v11 import Message
from utils.message_builder import image
from nonebot.adapters.onebot.v11 import Message, MessageSegment
from nonebot.log import logger
import asyncio
from utils.message_builder import image
try:
import ujson as json
@@ -137,10 +137,7 @@ class GuardianHandle(BaseHandle[GuardianData]):
info = f"当前up池:{up_event.title}\n{info}"
return info.strip()
async def draw(self, count: int, pool_name: str, **kwargs) -> Message:
return await asyncio.get_event_loop().run_in_executor(None, self._draw, count, pool_name)
def _draw(self, count: int, pool_name: str, **kwargs) -> Message:
def draw(self, count: int, pool_name: str, **kwargs) -> Message:
index2card = self.get_cards(count, pool_name)
cards = [card[0] for card in index2card]
up_event = self.UP_CHAR if pool_name == "char" else self.UP_ARMS
@@ -238,9 +235,12 @@ class GuardianHandle(BaseHandle[GuardianData]):
char_list = dom.xpath("//table[@id='CardSelectTr']/tbody/tr")
for char in char_list:
try:
name = char.xpath("./td[1]/a/@title")[0]
avatar = char.xpath("./td[1]/a/img/@src")[0]
star = char.xpath("./td[1]/span/img/@alt")[0]
# name = char.xpath("./td[1]/a/@title")[0]
# avatar = char.xpath("./td[1]/a/img/@src")[0]
# star = char.xpath("./td[1]/span/img/@alt")[0]
name = char.xpath("./th[1]/a[1]/@title")[0]
avatar = char.xpath("./th[1]/a/img/@src")[0]
star = char.xpath("./th[1]/span/img/@alt")[0]
except IndexError:
continue
member_dict = {
+33 -35
View File
@@ -8,10 +8,10 @@ from datetime import datetime
from urllib.parse import unquote
from typing import List, Optional, Tuple
from pydantic import ValidationError
from nonebot.adapters.onebot.v11 import Message
from utils.message_builder import image
from nonebot.adapters.onebot.v11 import Message, MessageSegment
from nonebot.log import logger
import asyncio
from utils.message_builder import image
try:
import ujson as json
@@ -40,9 +40,10 @@ class PrettyCard(PrettyData):
class PrettyHandle(BaseHandle[PrettyData]):
def __init__(self):
super().__init__("pretty", "赛马娘", "#eff2f5")
super().__init__("pretty", "赛马娘")
self.data_files.append("pretty_card.json")
self.max_star = 3
self.game_card_color = "#eff2f5"
self.config = draw_config.pretty
self.ALL_CHAR: List[PrettyChar] = []
@@ -129,10 +130,7 @@ class PrettyHandle(BaseHandle[PrettyData]):
info = f"当前up池:{up_event.title}\n{info}"
return info.strip()
async def draw(self, count: int, pool_name: str, **kwargs) -> Message:
return await asyncio.get_event_loop().run_in_executor(None, self._draw, count, pool_name)
def _draw(self, count: int, pool_name: str, **kwargs) -> Message:
def draw(self, count: int, pool_name: str, **kwargs) -> Message:
pool_name = "char" if not pool_name else pool_name
index2card = self.get_cards(count, pool_name)
cards = [card[0] for card in index2card]
@@ -331,7 +329,9 @@ class PrettyHandle(BaseHandle[PrettyData]):
try:
title = announcement.xpath("./@title")[0]
url = "https://wiki.biligame.com/" + announcement.xpath("./@href")[0]
if "卡池" in title:
if re.match(r".*?\d{8}$", title) or re.match(
r"^\d{1,2}月\d{1,2}日.*?", title
):
break
except IndexError:
continue
@@ -348,49 +348,48 @@ class PrettyHandle(BaseHandle[PrettyData]):
char_img = ""
card_img = ""
up_chars = []
up_chars_name = []
up_cards = []
up_cards_name = []
dom = etree.HTML(result, etree.HTMLParser())
content = dom.xpath('//*[@id="mw-content-text"]/div/div/div[1]/div')[0]
heads = content.xpath("./div")
soup = BeautifulSoup(result, "lxml")
heads = soup.find_all("span", {"class": "mw-headline"})
for head in heads:
if "时间" in head.find("./img").tail or "期间" in head.find("./img").tail:
time = content.xpath("./p")[1].text.split("\n")[0]
if "时间" in head.text:
time = head.find_next("p").text.split("\n")[0]
if "~" in time:
start, end = time.split("~")
start_time = dateparser.parse(start)
end_time = dateparser.parse(end)
elif "赛马娘" in head.find("./img").tail:
char_img = content.xpath("./center")[1].find("./a/img").get("src")
lines = content.xpath("./p")[2].xpath("string(.)").split("\n")
elif "赛马娘" in head.text:
char_img = head.find_next("a", {"class": "image"}).find("img")[
"src"
]
lines = str(head.find_next("p").text).split("\n")
chars = [
line
for line in lines
if "★" in line and "[" in line and "]" in line
if "★" in line and "(" in line and ")" in line
]
for char in set(chars): # list去重
for char in chars:
star = char.count("★")
name = re.split("[ ]",char)[-1]
name = re.split(r"[()]", char)[-2].strip()
up_chars.append(
UpChar(name=name, star=star, limited=False, zoom=70)
)
up_chars_name.append(name)
elif "支援卡" in head.find("./img").tail:
card_img = content.xpath("./center")[2].find("./a/img").get("src")
lines = content.xpath("./p")[3].xpath("string(.)").split("\n")
elif "支援卡" in head.text:
card_img = head.find_next("a", {"class": "image"}).find("img")[
"src"
]
lines = str(head.find_next("p").text).split("\n")
cards = [
line
for line in lines
if "R" in line and "[" in line and "]" in line
if "R" in line and "(" in line and ")" in line
]
for card in set(cards):
for card in cards:
star = 3 if "SSR" in card else 2 if "SR" in card else 1
name = re.split("[ ]",card)[-1]
name = re.split(r"[()]", card)[-2].strip()
up_cards.append(
UpChar(name=name, star=star, limited=False, zoom=70)
)
up_cards_name.append(name)
if start_time and end_time:
if start_time <= datetime.now() <= end_time:
self.UP_CHAR = UpEvent(
@@ -399,7 +398,6 @@ class PrettyHandle(BaseHandle[PrettyData]):
start_time=start_time,
end_time=end_time,
up_char=up_chars,
up_name=",".join(up_chars_name),
)
self.UP_CARD = UpEvent(
title=title,
@@ -407,7 +405,6 @@ class PrettyHandle(BaseHandle[PrettyData]):
start_time=start_time,
end_time=end_time,
up_char=up_cards,
up_name=",".join(up_cards_name),
)
self.dump_up_char()
logger.info(f"成功获取{self.game_name_cn}当前up信息...当前up池: {title}")
@@ -419,8 +416,9 @@ class PrettyHandle(BaseHandle[PrettyData]):
self.load_up_char()
if self.UP_CHAR and self.UP_CARD:
return Message(
Message.template("重载成功!\n当前UP池子:{}\n当前支援卡池子:{}").format(
self.UP_CHAR.up_name,
self.UP_CARD.up_name,
Message.template("重载成功!\n当前UP池子:{}{:image}{:image}").format(
self.UP_CHAR.title,
self.UP_CHAR.pool_img,
self.UP_CARD.pool_img,
)
)
+19 -19
View File
@@ -1,16 +1,17 @@
import re
import random
import dateparser
from lxml import etree
from PIL import ImageDraw
import re
from datetime import datetime
from urllib.parse import unquote
from typing import List, Optional, Tuple
from pydantic import ValidationError
from nonebot.adapters.onebot.v11 import Message
from utils.message_builder import image
from urllib.parse import unquote
import dateparser
from PIL import ImageDraw
from lxml import etree
from nonebot.adapters.onebot.v11 import Message, MessageSegment
from nonebot.log import logger
import asyncio
from pydantic import ValidationError
from utils.message_builder import image
try:
import ujson as json
@@ -104,17 +105,18 @@ class PrtsHandle(BaseHandle[Operator]):
info = f"当前up池: {self.UP_EVENT.title}\n{info}"
return info.strip()
async def draw(self, count: int, **kwargs) -> Message:
return await asyncio.get_event_loop().run_in_executor(None, self._draw, count)
def _draw(self, count: int, **kwargs) -> Message:
def draw(self, count: int, **kwargs) -> Message:
index2card = self.get_cards(count)
"""这里cards修复了抽卡图文不符的bug"""
cards = [card[0] for card in index2card]
up_list = [x.name for x in self.UP_EVENT.up_char] if self.UP_EVENT else []
result = self.format_result(index2card, up_list=up_list)
pool_info = self.format_pool_info()
return pool_info + image(b64=self.generate_img(cards).pic2bs4()) + result
return (
pool_info
+ image(b64=self.generate_img(cards).pic2bs4())
+ result
)
def generate_card_img(self, card: Operator) -> BuildImage:
sep_w = 5
@@ -177,6 +179,7 @@ class PrtsHandle(BaseHandle[Operator]):
self.dump_data(data, f"draw_card_up/{self.game_name}_up_char.json")
async def _update_info(self):
"""更新信息"""
info = {}
url = "https://wiki.biligame.com/arknights/干员数据表"
result = await self.get_url(url)
@@ -288,10 +291,7 @@ class PrtsHandle(BaseHandle[Operator]):
up_chars.append(
UpChar(name=name, star=star, limited=False, zoom=zoom)
)
if start_time <= datetime.now() <= end_time: # 跳过过时的卡池
break # 这里break会导致个问题:如果一个公告里有两个池子,会漏掉下面的池子,比如 5.19 的定向寻访。但目前我也没啥好想法解决
chars: List[str] = [] # 查找下一个卡池之前清空 chars
up_chars = [] # 查找下一个卡池之前清空 up_chars
break # 这里break会导致个问题:如果一个公告里有两个池子,会漏掉下面的池子,比如 5.19 的定向寻访。但目前我也没啥好想法解决
if title and start_time and end_time:
if start_time <= datetime.now() <= end_time:
self.UP_EVENT = UpEvent(
@@ -309,6 +309,6 @@ class PrtsHandle(BaseHandle[Operator]):
await self.update_up_char()
self.load_up_char()
if self.UP_EVENT:
return f"重载成功!\n当前UP池子:{self.UP_EVENT.title}" + image(
return f"重载成功!\n当前UP池子:{self.UP_EVENT.title}" + MessageSegment.image(
self.UP_EVENT.pool_img
)
View File
+8 -3
View File
@@ -1,14 +1,19 @@
import platform
import pypinyin
from pathlib import Path
from PIL.ImageFont import FreeTypeFont
from PIL import Image, ImageDraw, ImageFont
from PIL.Image import Image as IMG
from configs.path_config import FONT_PATH
dir_path = Path(__file__).parent.absolute()
def cn2py(word) -> str:
"""保存声调,防止出现类似方舟干员红与吽拼音相同声调不同导致红照片无法保存的问题"""
temp = ""
for i in pypinyin.pinyin(word, style=pypinyin.NORMAL):
for i in pypinyin.pinyin(word, style=pypinyin.Style.TONE3):
temp += "".join(i)
return temp
@@ -26,9 +31,9 @@ def remove_prohibited_str(name: str) -> str:
return name
def load_font(font_name: str = "msyh.ttf", fontsize: int = 16) -> FreeTypeFont:
def load_font(fontname: str = "msyh.ttf", fontsize: int = 16) -> FreeTypeFont:
return ImageFont.truetype(
str(FONT_PATH / f"{font_name}"), fontsize, encoding="utf-8"
str(FONT_PATH / f"{fontname}"), fontsize, encoding="utf-8"
)