mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2026-10-11 15:00:00 +08:00
优化管理员帮助,超级用户帮助图片,重新移植gamedraw,修复pil帮助私聊时无法生成
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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",
|
||||
)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user