async def handle(app: Ariadne, message: MessageChain, group: Group, member: Member, content: RegexResult, image: ElementResult): msg = content.result.asDisplay() img = await image.result.get_bytes() msg = await get_translate(msg) w2b = BuildImage(0, 0, background=BytesIO(img)) w2b.convert("L") msg_sp = msg.split("<|>") w, h = w2b.size add_h, font_size = init_h_font_size(h) bg = BuildImage(w, h + add_h, color="black", font_size=font_size) bg.paste(w2b) chinese_msg = formalization_msg(msg) if not bg.check_font_size(chinese_msg): if len(msg_sp) == 1: centered_text(bg, chinese_msg, add_h) else: centered_text(bg, chinese_msg + "<|>" + msg_sp[1], add_h) elif not bg.check_font_size(msg_sp[0]): centered_text(bg, msg, add_h) else: ratio = (bg.getsize(msg_sp[0])[0] + 20) / bg.w add_h = add_h * ratio bg.resize(ratio) centered_text(bg, msg, add_h) return MessageItem( MessageChain.create([Image(data_bytes=bg.pic2bytes())]), QuoteSource())
def gen_icon(icon: str): A = BuildImage(0, 0, background=f"{icon_path}/box.png") B = BuildImage(0, 0, background=f"{icon_path}/box_alpha.png") icon_ = icon_path / f"{icon}" icon_img = BuildImage(115, 115, background=icon_) icon_img.circle() B.paste(icon_img, (17, 10), True) B.paste(A, alpha=True) B.save(icon) logger.info(f"生成图片成功 file:{str(icon)}")
def get_background_height(weapons_imgs: List[str]) -> int: height = 0 for weapons in weapons_imgs: height += BuildImage(0, 0, background=weapons).size[1] last_weapon = BuildImage(0, 0, background=weapons_imgs[-1]) w, h = last_weapon.size last_weapon.crop((0, 0, w, h - 10)) last_weapon.save(weapons_imgs[-1]) return height
def _get_icon_image(self, id_: int) -> "BuildImage": icon = icon_path / f"{id_}.png" if icon.exists(): return BuildImage(int(50 * self.ratio), int(50 * self.ratio), background=icon) return BuildImage( int(50 * self.ratio), int(50 * self.ratio), background=f"{icon_path}/box.png", )
async def download_map_init(semaphore: Semaphore, flag: bool = False): global CENTER_POINT, MAP_RATIO map_path.mkdir(exist_ok=True, parents=True) _map = map_path / "map.png" if _map.exists() and os.path.getsize(_map) > 1024 * 1024 * 30: _map.unlink() try: async with aiohttp.ClientSession() as session: async with session.get(MAP_URL) as resp: if resp.status == 200: data = await resp.json() if data["message"] == "OK": data = json.loads(data["data"]["info"]["detail"]) CENTER_POINT = (data["origin"][0], data["origin"][1]) if not _map.exists(): data = data["slices"] idx = 0 for _map_data in data[0]: map_url = _map_data['url'] await download_image( map_url, f"{map_path}/{idx}.png", semaphore, force_flag=flag, ) BuildImage(0, 0, background=f"{map_path}/{idx}.png", ratio=MAP_RATIO).save() idx += 1 _w, h = BuildImage( 0, 0, background=f"{map_path}/0.png").size w = _w * len(os.listdir(map_path)) map_file = BuildImage(w, h, _w, h, ratio=MAP_RATIO) for i in range(idx): map_file.paste( BuildImage( 0, 0, background=f"{map_path}/{i}.png")) map_file.save(f"{map_path}/map.png") else: logger.warning(f'获取原神地图失败 msg: {data["message"]}') else: logger.warning(f"获取原神地图失败 code:{resp.status}") except TimeoutError: logger.warning("下载原神地图数据超时....") except Exception as e: logger.error(f"下载原神地图数据超时 {type(e)}:{e}")
async def i_have_a_friend(app: Ariadne, message: MessageChain, group: Group, member: Member, content: RegexResult, target: ElementResult, dark: RegexResult): if content.matched and content.result.asDisplay().strip(): content = content.result.asDisplay() if target.matched: target = target.result.target member = await app.getMember(group, target) if not member: await app.sendGroupMessage(group, MessageChain("获取成员信息失败!"), quote=message.getFirst(Source)) return else: target = member if avatar := await get_avatar(target, 160): avatar = BuildImage(200, 100, background=BytesIO(avatar)) else: avatar = BuildImage(200, 100, color=(0, 0, 0)) avatar.circle_new() text = BuildImage(300, 30, font_size=30, color="white" if not dark.matched else "black") text.text((0, 0), member.name, (0, 0, 0) if not dark.matched else (141, 141, 146)) A = BuildImage(700, 150, font_size=25, color="white" if not dark.matched else "black") A.paste(avatar, (30, 25), True) A.paste(text, (150, 38)) A.text((150, 85), content.strip(), (125, 125, 125) if not dark.matched else (255, 255, 255)) await app.sendGroupMessage(group, MessageChain( [Image(data_bytes=A.pic2bytes())]), quote=message.getFirst(Source))
def __init__( self, resource_name: str, center_point: Tuple[int, int], deviation: Tuple[int, int] = (25, 51), padding: int = 100, planning_route: bool = False, ratio: float = 1, ): """ 参数: :param resource_name: 资源名称 :param center_point: 中心点 :param deviation: 坐标误差 :param padding: 截图外边距 :param planning_route: 是否规划最佳线路 :param ratio: 压缩比率 """ self.map = BuildImage(0, 0, background=map_path) self.resource_name = resource_name self.center_x = center_point[0] self.center_y = center_point[1] self.deviation = deviation self.padding = int(padding * ratio) self.planning_route = planning_route self.ratio = ratio self.deviation = ( int(self.deviation[0] * ratio), int(self.deviation[1] * ratio), ) data = json.load(open(resource_label_file, "r", encoding="utf8")) # 资源 id self.resource_id = [ data[x]["id"] for x in data if x != "CENTER_POINT" and data[x]["name"] == resource_name ][0] # 传送锚点 id self.teleport_anchor_id = [ data[x]["id"] for x in data if x != "CENTER_POINT" and data[x]["name"] == "传送锚点" ][0] # 神像 id self.teleport_god_id = [ data[x]["id"] for x in data if x != "CENTER_POINT" and data[x]["name"] == "七天神像" ][0] # 资源坐标 data = json.load(open(resource_point_file, "r", encoding="utf8")) self.resource_point = [ Resources( int((self.center_x + data[x]["x_pos"]) * ratio), int((self.center_y + data[x]["y_pos"]) * ratio), ) for x in data if x != "CENTER_POINT" and data[x]["label_id"] == self.resource_id ] # 传送锚点坐标 self.teleport_anchor_point = [ Resources( int((self.center_x + data[x]["x_pos"]) * ratio), int((self.center_y + data[x]["y_pos"]) * ratio), ) for x in data if x != "CENTER_POINT" and data[x]["label_id"] == self.teleport_anchor_id ] # 神像坐标 self.teleport_god_point = [ Resources( int((self.center_x + data[x]["x_pos"]) * ratio), int((self.center_y + data[x]["y_pos"]) * ratio), ) for x in data if x != "CENTER_POINT" and data[x]["label_id"] == self.teleport_god_id ]
async def update_image(): # try: if not os.path.exists(str(IMAGE_PATH)): os.makedirs(str(IMAGE_PATH)) for file in os.listdir(str(IMAGE_PATH)): os.remove(str(IMAGE_PATH / file)) browser = await get_browser() if not browser: raise ValueError("获取browser失败!") url = "https://genshin.pub/daily" page = await browser.new_page() await page.goto(url, wait_until="networkidle", timeout=100000) await page.set_viewport_size({"width": 2560, "height": 1080}) await page.evaluate(""" document.getElementsByClassName('GSTitleBar_gs_titlebar__2IJqy')[0].remove(); e = document.getElementsByClassName('GSContainer_gs_container__2FbUz')[0]; e.setAttribute("style", "height:880px"); """) await page.click("button") div = await page.query_selector(".GSContainer_content_box__1sIXz") for i, card in enumerate( await page.query_selector_all(".GSTraitCotainer_trait_section__1f3bc")): index = 0 type_ = "char" if not i else "weapons" for x in await card.query_selector_all("xpath=child::*"): await x.screenshot( path=f"{IMAGE_PATH}/{type_}_{index}.png", timeout=100000, ) # 下滑两次 for _ in range(3): await div.press("PageDown") index += 1 # 结束后上滑至顶 for _ in range(index * 3): await div.press("PageUp") file_list = os.listdir(str(IMAGE_PATH)) char_imgs = [ f"{IMAGE_PATH}/{x}" for x in file_list if x.startswith("char") ] weapons_imgs = [ f"{IMAGE_PATH}/{x}" for x in file_list if x.startswith("weapons") ] char_imgs.sort() weapons_imgs.sort() height = await asyncio.get_event_loop().run_in_executor( None, get_background_height, weapons_imgs) background_img = BuildImage(1200, height + 100, color="#f6f2ee") current_width = 50 for imgs in [char_imgs, weapons_imgs]: current_height = 20 for img in imgs: x = BuildImage(0, 0, background=img) background_img.paste(x, (current_width, current_height)) current_height += x.size[1] current_width += 600 file_name = str((datetime.now() - timedelta(hours=4)).date()) background_img.save(f"{IMAGE_PATH}/{file_name}.png") await page.close() return True