import random 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 utils.image_utils import BuildImage class PcrChar(BaseData): pass class PcrHandle(BaseHandle[PcrChar]): def __init__(self): super().__init__("pcr", "公主连结") self.max_star = 3 self.config = draw_config.pcr self.ALL_CHAR: List[PcrChar] = [] def get_card(self, mode: int = 1) -> PcrChar: if mode == 2: star = self.get_star( [3, 2], [self.config.PCR_G_THREE_P, self.config.PCR_G_TWO_P] ) else: star = self.get_star( [3, 2, 1], [self.config.PCR_THREE_P, self.config.PCR_TWO_P, self.config.PCR_ONE_P], ) chars = [x for x in self.ALL_CHAR if x.star == star and not x.limited] return random.choice(chars) def get_cards(self, count: int, **kwargs) -> List[Tuple[PcrChar, int]]: card_list = [] card_count = 0 # 保底计算 for i in range(count): card_count += 1 # 十连保底 if card_count == 10: card = self.get_card(2) card_count = 0 else: card = self.get_card(1) if card.star > self.max_star - 2: card_count = 0 card_list.append((card, i + 1)) return card_list def generate_card_img(self, card: PcrChar) -> BuildImage: sep_w = 5 sep_h = 5 star_h = 15 img_w = 90 img_h = 90 font_h = 20 bg = BuildImage(img_w + sep_w * 2, img_h + font_h + sep_h * 2, color="#EFF2F5") star_path = str(self.img_path / "star.png") star = BuildImage(star_h, star_h, background=star_path) img_path = str(self.img_path / f"{cn2py(card.name)}.png") img = BuildImage(img_w, img_h, background=img_path) bg.paste(img, (sep_w, sep_h), alpha=True) for i in range(card.star): bg.paste(star, (sep_w + img_w - star_h * (i + 1), sep_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) draw = ImageDraw.Draw(bg.markImg) draw.text( (sep_w + (img_w - text_w) / 2, sep_h + img_h + (font_h - text_h) / 2), text, font=font, fill="gray", ) return bg def _init_data(self): self.ALL_CHAR = [ PcrChar( name=value["名称"], star=int(value["星级"]), limited=True if "(" in key else False, ) for key, value in self.load_data().items() ] async def _update_info(self): info = {} if draw_config.PCR_TAI: url = "https://wiki.biligame.com/pcr/角色图鉴" result = await self.get_url(url) if not result: logger.warning(f"更新 {self.game_name_cn} 出错") return dom = etree.HTML(result, etree.HTMLParser()) char_list = dom.xpath( "//div[@class='resp-tab-content']/div[@class='unit-icon']" ) for char in char_list: try: name = char.xpath("./a/@title")[0] avatar = char.xpath("./a/img/@srcset")[0] star = len(char.xpath("./div[1]/img")) except IndexError: continue member_dict = { "头像": unquote(str(avatar).split(" ")[-2]), "名称": remove_prohibited_str(name), "星级": star, } info[member_dict["名称"]] = member_dict else: url = "https://wiki.biligame.com/pcr/角色筛选表" result = await self.get_url(url) if not result: logger.warning(f"更新 {self.game_name_cn} 出错") return dom = etree.HTML(result, etree.HTMLParser()) 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/@srcset")[0] star = char.xpath("./td[4]/text()")[0] except IndexError: continue member_dict = { "头像": unquote(str(avatar).split(" ")[-2]), "名称": remove_prohibited_str(name), "星级": int(str(star).strip()), } 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/pcr/0/02/s75ys2ecqhu2xbdw1wf1v9ccscnvi5g.png", "star", )