async def delete_keyword(app: GraiaMiraiApplication, group: Group, member: Member, message_serialization: str) -> MessageItem: _, keyword = message_serialization.split("#") if re.match(r"\[mirai:image:{.*}\..*]", keyword): keyword = re.findall(r"\[mirai:image:{(.*?)}\..*]", keyword, re.S)[0] if record := await orm.fetchone( select(TriggerKeyword.function).where( TriggerKeyword.keyword == keyword)): await app.sendGroupMessage( group, MessageChain.create([ Plain( text=f"查找到以下信息:\n{keyword} -> {record[0]}\n是否删除?(是/否)") ])) inc = InterruptControl(AppCore.get_core_instance().get_bcc()) @Waiter.create_using_function([GroupMessage]) def confirm_waiter(waiter_group: Group, waiter_member: Member, waiter_message: MessageChain): if all([ waiter_group.id == group.id, waiter_member.id == member.id ]): if re.match(r"[是否]", waiter_message.asDisplay()): return waiter_message.asDisplay() else: return "" result = await inc.wait(confirm_waiter) if not result: return MessageItem( MessageChain.create([Plain(text="非预期回复,进程退出")]), Normal(GroupStrategy())) elif result == "是": try: await orm.delete(TriggerKeyword, [TriggerKeyword.keyword == keyword]) except: logger.error(traceback.format_exc()) return MessageItem( MessageChain.create([Plain(text="发生错误!请查看日志!")]), QuoteSource(GroupStrategy())) return MessageItem( MessageChain.create([Plain(text=f"关键词 {keyword} 删除成功")]), Normal(GroupStrategy())) else: return MessageItem(MessageChain.create([Plain(text="进程退出")]), Normal(GroupStrategy()))
async def handle(app: GraiaMiraiApplication, message: MessageChain, group: Group, member: Member): legal_type = ("setu", "setu18", "real", "realHighq", "wallpaper", "sketch") if re.match( r"添加(setu|setu18|real|realHighq|wallpaper|sketch)图片(\[图片])+", message.asDisplay()): if not user_permission_require(group, member, 2): return MessageItem( MessageChain.create([Plain(text="你没有权限,爬!")]), Normal(GroupStrategy())) image_type = re.findall(r"添加(.*?)图片(\[图片])+", message.asDisplay(), re.S)[0][0] if image_type not in legal_type: return MessageItem( MessageChain.create([ Plain( text=f"非法图片类型!\n合法image_type:{'、'.join(legal_type)}" ) ]), QuoteSource(GroupStrategy())) if path := get_config(f"{image_type}Path"): if os.path.exists(path): try: await ImageAdderHandler.add_image( path, message.get(Image)) except Exception as e: logger.error(traceback.format_exc()) return MessageItem( MessageChain.create( [Plain(text="出错了呐~请查看日志/控制台输出!")]), Normal(GroupStrategy())) return MessageItem( MessageChain.create([ Plain( text=f"保存成功!共保存了{len(message.get(Image))}张图片!") ]), Normal(GroupStrategy())) else: return MessageItem( MessageChain.create([ Image.fromLocalFile( f"{os.getcwd()}/statics/error/path_not_exists.png" ) ]), QuoteSource(GroupStrategy())) else: return MessageItem( MessageChain.create( [Plain(text=f"无{image_type}Path项!请检查配置!")]), QuoteSource(GroupStrategy()))
async def rub(operator_image: Union[int, str], target_image: Union[int, str]) -> MessageItem: user_locs = [(39, 91, 75, 75, 0), (49, 101, 75, 75, 0), (67, 98, 75, 75, 0), (55, 86, 75, 75, 0), (61, 109, 75, 75, 0), (65, 101, 75, 75, 0)] self_locs = [(102, 95, 70, 80, 0), (108, 60, 50, 100, 0), (97, 18, 65, 95, 0), (65, 5, 75, 75, -20), (95, 57, 100, 55, -70), (109, 107, 65, 75, 0)] frames = [] self_img = await AvatarFunPicHandler.get_pil_avatar(operator_image) user_img = await AvatarFunPicHandler.get_pil_avatar(target_image) for i in range(6): frame = IMG.open(f'{os.getcwd()}/statics/RubFrames/frame{i}.png' ).convert('RGBA') x, y, w, h, angle = user_locs[i] user_img_new = (await AvatarFunPicHandler.resize_img( user_img, w, h, angle)).convert("RGBA") frame.paste(user_img_new, (x, y), mask=user_img_new) x, y, w, h, angle = self_locs[i] self_img_new = (await AvatarFunPicHandler.resize_img( self_img, w, h, angle)).convert("RGBA") frame.paste(self_img_new, (x, y), mask=self_img_new) frames.append(frame) output = BytesIO() imageio.mimsave(output, frames, format='gif', duration=0.05) return MessageItem( MessageChain.create([Image.fromUnsafeBytes(output.getvalue())]), Normal(GroupStrategy()))
async def handle(self, app: GraiaMiraiApplication, message: MessageChain, group: Group, member: Member): if apps := message.get(App): app_json = json.loads(apps[0].content) if app_json[ "prompt"] == "[QQ小程序]哔哩哔哩" or "meta" in app_json and "detail_1" in app_json[ "meta"] and app_json["meta"]["detail_1"][ "title"] == "哔哩哔哩": short_url = app_json["meta"]["detail_1"]["qqdocurl"] async with aiohttp.ClientSession() as session: async with session.get(url=short_url, allow_redirects=False) as resp: result = (await resp.read()).decode("utf-8") bv_url = result.split("\"")[1].split("?")[0].split( "/")[-1].strip() print(bv_url) bilibili_video_api_url = f"http://api.bilibili.com/x/web-interface/view?aid={self.bv_to_av(bv_url)}" async with aiohttp.ClientSession() as session: async with session.get(url=bilibili_video_api_url) as resp: result = (await resp.read()).decode('utf-8') result = json.loads(result) return MessageItem(await self.generate_messagechain(result), Normal(GroupStrategy())) else: return await super().handle(app, message, group, member)
async def get_github_trending(group: Group, member: Member) -> MessageItem: url = "https://github.com/trending" headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36" } async with aiohttp.ClientSession() as session: async with session.get(url=url, headers=headers) as resp: html = await resp.read() soup = BeautifulSoup(html, "html.parser") articles = soup.find_all("article", {"class": "Box-row"}) text_list = [f"随机数:{random.randint(0, 10000)}", "\ngithub实时热榜:\n"] index = 0 for i in articles: try: index += 1 title = i.find('h1').get_text().replace('\n', '').replace( ' ', '').replace('\\', ' \\ ') text_list.append(f"\n{index}. {title}\n") text_list.append(f"\n {i.find('p').get_text().strip()}\n") except Exception: pass text = "".join(text_list).replace("#", "") return MessageItem(MessageChain.create([Plain(text=text)]), Normal(GroupStrategy()))
async def handle(self, app: GraiaMiraiApplication, message: MessageChain, group: Group, member: Member): message_text = message.asDisplay() if re.match(r"super .*:[\n\r]+[\s\S]*", message_text): await update_user_call_count_plus1(group, member, UserCalledCount.functions, "functions") if not await get_setting(group.id, "compile"): return MessageItem( MessageChain.create([Plain(text="网络编译器功能关闭了呐~去联系管理员开启吧~") ]), Normal(GroupStrategy())) language = re.findall(r"super (.*?):", message_text, re.S)[0] code = message_text[8 + len(language):] result = await self.network_compiler(group, member, language, code) if isinstance(result, str): return MessageItem(MessageChain.create([Plain(text=result)]), QuoteSource(GroupStrategy())) else: return MessageItem( MessageChain.create([ Plain(text=result["output"] if result["output"] else result["errors"]) ]), QuoteSource(GroupStrategy())) else: return await super().handle(app, message, group, member)
async def formatted_output_bangumi(group: Group, member: Member, days: int) -> MessageItem: """ Formatted output json data Args: days: The number of days to output(1-7) Examples: data_str = formatted_output_bangumi(7) Return: MessageChain """ formatted_bangumi_data = await BiliBiliBangumiScheduleHandler.get_formatted_new_bangumi_json( ) temp_output_substring = ["------BANGUMI------\n\n"] now = datetime.datetime.now() for index in range(days): temp_output_substring.append(now.strftime("%m-%d")) temp_output_substring.append("即将播出:") for data in formatted_bangumi_data[index]: temp_output_substring.append( "\n%s %s %s\n" % (data["pub_time"], data["title"], data["pub_index"])) temp_output_substring.append("\n\n----------------\n\n") now += datetime.timedelta(days=1) content = "".join(temp_output_substring) return MessageItem( await MessageChainUtils.messagechain_to_img( MessageChain.create([Plain(text=content)])), Normal(GroupStrategy()))
async def handle(app: GraiaMiraiApplication, message: MessageChain, group: Group, member: Member): if message.asDisplay() == "搜番": await update_user_call_count_plus1(group, member, UserCalledCount.search, "search") if not await get_setting(group.id, Setting.bangumi_search): return MessageItem( MessageChain.create([Plain(text="搜番功能未开启呐~请联系管理员哦~")]), Normal(GroupStrategy())) try: await app.sendGroupMessage( group, MessageChain.create( [At(member.id), Plain("请在30秒内发送要搜索的图片呐~")])) except AccountMuted: logger.error(f"Bot 在群 <{group.name}> 被禁言,无法发送!") return None image_get = None message_received = None @Waiter.create_using_function([GroupMessage]) def waiter(event: GroupMessage, waiter_group: Group, waiter_member: Member, waiter_message: MessageChain): nonlocal image_get nonlocal message_received if time.time() - start_time < 30: if all([ waiter_group.id == group.id, waiter_member.id == member.id, len(waiter_message[Image]) == len( waiter_message.__root__) - 1 ]): image_get = True message_received = waiter_message return event else: logger.warning("等待用户超时!BangumiSearchHandler进程推出!") return event bcc = AppCore.get_core_instance().get_bcc() inc = InterruptControl(bcc) start_time = time.time() await inc.wait(waiter) if image_get: logger.success("收到用户图片,启动搜索进程!") try: await app.sendGroupMessage( group, await BangumiSearchHandler.search_bangumi( message_received[Image][0]), quote=message_received[Source][0]) except AccountMuted: logger.error(f"Bot 在群 <{group.name}> 被禁言,无法发送!") pass return None else: return None
async def handle(self, app: GraiaMiraiApplication, message: MessageChain, group: Group, member: Member): group_id = group.id message_serialization = message.asSerializationString() message_serialization = message_serialization.replace( "[mirai:source:" + re.findall(r'\[mirai:source:(.*?)]', message_serialization, re.S)[0] + "]", "") if group_id in self.__group_repeat.keys(): self.__group_repeat[group.id]["lastMsg"] = self.__group_repeat[ group.id]["thisMsg"] self.__group_repeat[group.id]["thisMsg"] = message_serialization if self.__group_repeat[group.id]["lastMsg"] != self.__group_repeat[ group.id]["thisMsg"]: self.__group_repeat[group.id]["stopMsg"] = "" else: if self.__group_repeat[group.id][ "thisMsg"] != self.__group_repeat[group.id]["stopMsg"]: self.__group_repeat[group.id][ "stopMsg"] = self.__group_repeat[group.id]["thisMsg"] return MessageItem(message.asSendable(), Normal(GroupStrategy())) else: self.__group_repeat[group_id] = { "lastMsg": "", "thisMsg": message_serialization, "stopMsg": "" } return await super().handle(app, message, group, member)
async def get_image_message(group: Group, member: Member, func: str) -> MessageItem: if func == "setu18": r18_process = await get_setting(group.id, Setting.r18_process) if r18_process == "revoke": return MessageItem( MessageChain.create( [await ImageSenderHandler.get_pic(func)]), Revoke(GroupStrategy())) elif r18_process == "flashImage": return MessageItem( MessageChain.create([ (await ImageSenderHandler.get_pic(func)).asFlash() ]), Normal(GroupStrategy())) return MessageItem( MessageChain.create([await ImageSenderHandler.get_pic(func)]), Normal(GroupStrategy()))
async def execute_setting_update(group: Group, member: Member, command: str) -> MessageItem: """ setting -set setu=True real=True 多命令执行 """ commands = command[13:].split(" ") error_commands = [] success_commands = [] for command in commands: try: command = command.strip() # .replace("-", "") if not command: continue func, value = command.split("=") func = camel_to_underscore(func) value = (True if value == "True" else False) if value in [ "True", "False" ] else value if func in command_index.keys(): if command_index[func].is_valid(value): """ update """ if await user_permission_require( group, member, command_index[func].level): try: await orm.insert_or_update( Setting, [Setting.group_id == group.id], {func: value}) success_commands.append(f"{func} -> {value}") except Exception as e: error_commands.append((command, str(e))) logger.error(traceback.format_exc()) else: error_commands.append( (command, f"权限不足,要求权限等级{command_index[func].level}")) else: error_commands.append(( f"{func} -> {value}", f"期望值:{','.join([str(valid_value) for valid_value in command_index[func].valid_values])}" )) else: error_commands.append((command, "未找到此命令")) except ValueError: error_commands.append((command, "格式非法!应为 func=value")) response_text = f"共解析{len(commands)}条命令,\n其中{len(success_commands)}条执行成功,{len(error_commands)}条失败" if success_commands: response_text += "\n\n成功命令:" for i in success_commands: response_text += f"\n{i}" if error_commands: response_text += "\n\n失败命令:" for i in error_commands: response_text += f"\n{i[0]} | {i[1]}" return MessageItem(MessageChain.create([Plain(text=response_text)]), Normal(GroupStrategy()))
async def format_output_notices(top: int = 10) -> MessageItem: data = await JLUCSWNoticeHandler.get_jlu_csw_notice(top) content = "----------------------------------\n" for i in range(10): content += f"{data[i]['title']}\n" content += f"{data[i]['href']}\n" content += f" {data[i]['time'].replace('-', '.')}\n" content += "----------------------------------\n" return MessageItem(MessageChain.create([Plain(text=content)]), Normal(GroupStrategy()))
async def grant_permission_process(group_id: int, member_id: int, new_level: int) -> MessageItem: if await grant_permission(group_id, member_id, new_level): return MessageItem( MessageChain.create([ Plain(text=f"修改成功!\n{member_id} permission level: {new_level}") ]), Normal(GroupStrategy())) else: return MessageItem(MessageChain.create([Plain(text="出现错误,请查看日志!")]), QuoteSource(GroupStrategy()))
async def handle(self, app: GraiaMiraiApplication, message: MessageChain, group: Group, member: Member): if message.asDisplay() == "舔": set_result( message, MessageItem( MessageChain.create([ Plain(text=random.choice(pero_dog_contents).replace( '*', '')) ]), Normal(GroupStrategy()))) else: return None
async def handle(app: GraiaMiraiApplication, message: MessageChain, group: Group, member: Member): if message.asDisplay() == "舔": await update_user_call_count_plus1(group, member, UserCalledCount.functions, "functions") return MessageItem( MessageChain.create([ Plain( text=random.choice(pero_dog_contents).replace('*', '')) ]), Normal(GroupStrategy())) else: return None
async def keyword_detect(keyword: str): if re.match(r"\[mirai:image:{.*}\..*]", keyword): keyword = re.findall(r"\[mirai:image:{(.*?)}\..*]", keyword, re.S)[0] if result := list(await orm.fetchall( select(KeywordReply.reply, KeywordReply.reply_type).where( KeywordReply.keyword == keyword))): reply, reply_type = random.choice(result) return MessageItem( MessageChain.create([ Plain(text=reply) if reply_type == "text" else Image.fromUnsafeBytes(base64.b64decode(reply)) ]), Normal(GroupStrategy()))
async def get_weibo_trending(group: Group, member: Member) -> MessageItem: weibo_hot_url = "http://api.weibo.cn/2/guest/search/hot/word" async with aiohttp.ClientSession() as session: async with session.get(url=weibo_hot_url) as resp: data = await resp.json() data = data["data"] text_list = [f"随机数:{random.randint(0, 10000)}", "\n微博实时热榜:"] index = 0 for i in data: index += 1 text_list.append(f"\n{index}. {i['word'].strip()}") text = "".join(text_list).replace("#", "") return MessageItem(MessageChain.create([Plain(text=text)]), Normal(GroupStrategy()))
async def get_zhihu_trending(group: Group, member: Member) -> MessageItem: zhihu_hot_url = "https://www.zhihu.com/api/v3/feed/topstory/hot-lists/total?limit=50&desktop=true" async with aiohttp.ClientSession() as session: async with session.get(url=zhihu_hot_url) as resp: data = await resp.json() data = data["data"] text_list = [f"随机数:{random.randint(0, 10000)}", "\n知乎实时热榜:"] index = 0 for i in data: index += 1 text_list.append(f"\n{index}. {i['target']['title'].strip()}") text = "".join(text_list).replace("#", "") return MessageItem(MessageChain.create([Plain(text=text)]), Normal(GroupStrategy()))
async def handle(app: GraiaMiraiApplication, message: MessageChain, group: Group, member: Member): if message.asDisplay().startswith("说 "): text = ''.join([plain.text for plain in message.get(Plain) ])[2:].replace(" ", ',') voice = await SpeakHandler.get_voice(text) if isinstance(voice, str): return MessageItem(MessageChain.create([Plain(text=voice)]), QuoteSource(GroupStrategy())) elif isinstance(voice, bytes): voice_element = await app.uploadVoice(await silkcoder.encode(voice)) return MessageItem(MessageChain.create([voice_element]), Normal(GroupStrategy()))
async def get_today_in_history(group: Group, member: Member) -> MessageItem: api_url = "https://api.sagiri-web.com/historyToday/" async with aiohttp.ClientSession() as session: async with session.get(url=api_url) as resp: text = await resp.text() text = text.replace("\\n", "\n") text = text[1:-1] while len(text) > 400: text = "\n".join(text.split("\n")[int(len(text.split("\n")) / 2):]) return MessageItem(MessageChain.create([Plain(text=text)]), Normal(GroupStrategy()))
async def gosencho_en_hoshi_style_image_generator( group: Group, member: Member, message: MessageChain) -> MessageItem: try: _, left_text, right_text = message.asDisplay().split(" ") try: img_byte = BytesIO() GoSenChoEnHoShiStyleUtils.genImage(word_a=left_text, word_b=right_text).save( img_byte, format='PNG') return MessageItem( MessageChain.create( [Image.fromUnsafeBytes(img_byte.getvalue())]), Normal(GroupStrategy())) except TypeError: return MessageItem( MessageChain.create([Plain(text="不支持的内容!不要给我一些稀奇古怪的东西!")]), Normal(GroupStrategy())) except ValueError: return MessageItem( MessageChain.create( [Plain(text="参数非法!使用格式:5000兆 text1 text2")]), Normal(GroupStrategy()))
async def support(image: Union[int, str]) -> MessageItem: avatar = await AvatarFunPicHandler.get_pil_avatar(image) support = IMG.open(f'{os.getcwd()}/statics/support.png') frame = IMG.new('RGBA', (1293, 1164), (255, 255, 255, 0)) avatar = avatar.resize((815, 815), IMG.ANTIALIAS).rotate(23, expand=True) frame.paste(avatar, (-172, -17)) frame.paste(support, mask=support) frame = frame.convert('RGB') output = BytesIO() frame.save(output, format='jpeg') return MessageItem( MessageChain.create([Image.fromUnsafeBytes(output.getvalue())]), Normal(GroupStrategy()))
async def petpet(image: Union[int, str], flip=False, squish=0, fps=20) -> MessageItem: """生成PetPet 将输入的头像生成为所需的 PetPet 并输出 参数 path: str 为头像路径 flip: bool 为是否横向反转头像 squish: float 为一个 [0, 1] 之间的数,为挤压量 fps: int 为输出 gif 每秒显示的帧数 返回 bool 但是会输出一个符合参数的 gif """ gif_frames = [] avatar = await AvatarFunPicHandler.get_pil_avatar(image) # 生成每一帧 for i in range(5): gif_frames.append(await AvatarFunPicHandler.make_frame(avatar, i, squish=squish, flip=flip)) if not os.path.exists(f"{os.getcwd()}/statics/temp/"): os.mkdir(f"{os.getcwd()}/statics/temp/") md5 = hashlib.md5(str(image).encode("utf-8")).hexdigest() await AvatarFunPicHandler.save_gif( gif_frames, f"{os.getcwd()}/statics/temp/tempPetPet-{md5}.gif", fps=fps) with open(f"{os.getcwd()}/statics/temp/tempPetPet-{md5}.gif", "rb") as r: image_bytes = r.read() os.remove(f"{os.getcwd()}/statics/temp/tempPetPet-{md5}.gif") return MessageItem( MessageChain.create([Image.fromUnsafeBytes(image_bytes)]), Normal(GroupStrategy()))
async def handle(app: GraiaMiraiApplication, message: MessageChain, group: Group, member: Member): if re.match(r"来点.+笑话", message.asDisplay()): keyword = message.asDisplay()[2:-2] if keyword in joke_non_replace.keys(): return MessageItem( MessageChain.create([ Plain(text=random.choice(joke_non_replace[keyword])) ]), Normal(GroupStrategy())) else: return MessageItem( MessageChain.create([ Plain(text=random.choice(jokes).replace( "%name%", keyword)) ]), QuoteSource(GroupStrategy()))
async def ripped(image: Union[int, str]) -> MessageItem: ripped = IMG.open(f"{os.getcwd()}/statics/ripped.png") frame = IMG.new('RGBA', (1080, 804), (255, 255, 255, 0)) avatar = await AvatarFunPicHandler.get_pil_avatar(image) left = avatar.resize((385, 385)).rotate(24, expand=True) right = avatar.resize((385, 385)).rotate(-11, expand=True) frame.paste(left, (-5, 355)) frame.paste(right, (649, 310)) frame.paste(ripped, mask=ripped) frame = frame.convert('RGB') output = BytesIO() frame.save(output, format='jpeg') return MessageItem( MessageChain.create([Image.fromUnsafeBytes(output.getvalue())]), Normal(GroupStrategy()))
async def handle(app: GraiaMiraiApplication, message: MessageChain, group: Group, member: Member): message_text = message.asDisplay() if message_text == "/chains": app_core = AppCore.get_core_instance() return MessageItem( MessageChain.create([ Plain(text="目前链序:\n " + "\n ".join([ handler.__name__ for handler in app_core.get_group_chain() ])) ]), Normal(GroupStrategy())) elif message_text == "/help": return MessageItem( MessageChain.create([ Plain( text= "SAGIRI-BOT文档地址:http://doc.sagiri-web.com/web/#/51?page_id=284" ) ]), QuoteSource(GroupStrategy())) elif message_text == "!help": app_core = AppCore.get_core_instance() content = "目前已加载Handler:\n" index = 0 for handler in app_core.get_group_chains(): index = index + 1 content += f"{index}. {handler.__name__}\n" content += "请回复 /help 序号来查看Handler描述" return MessageItem(MessageChain.create([Plain(text=content)]), QuoteSource(GroupStrategy())) elif re.match(r"!help [0-9]+", message_text): chains = AppCore.get_core_instance().get_group_chains() length = len(chains) index = int(message_text[6:]) if index > length: return MessageItem( MessageChain.create([Plain(text="非法编号!请检查发送的信息!")]), QuoteSource(GroupStrategy())) else: content = "Handler详情:\n" handler = chains[index - 1] content += f"名称:{handler.__name__}\n" content += f"描述:{handler.__description__}\n" content += f"使用方法:{handler.__usage__}" return MessageItem(MessageChain.create([Plain(text=content)]), QuoteSource(GroupStrategy())) else: return None
async def kiss(operator_image: Union[int, str], target_image: Union[int, str]) -> MessageItem: """ Author: https://github.com/SuperWaterGod """ gif_frames = [] operator = await AvatarFunPicHandler.get_pil_avatar(operator_image) target = await AvatarFunPicHandler.get_pil_avatar(target_image) operator = operator.resize((40, 40), IMG.ANTIALIAS) size = operator.size r2 = min(size[0], size[1]) circle = IMG.new('L', (r2, r2), 0) draw = ImageDraw.Draw(circle) draw.ellipse((0, 0, r2, r2), fill=255) alpha = IMG.new('L', (r2, r2), 255) alpha.paste(circle, (0, 0)) operator.putalpha(alpha) target = target.resize((50, 50), IMG.ANTIALIAS) size = target.size r2 = min(size[0], size[1]) circle = IMG.new('L', (r2, r2), 0) draw = ImageDraw.Draw(circle) draw.ellipse((0, 0, r2, r2), fill=255) alpha = IMG.new('L', (r2, r2), 255) alpha.paste(circle, (0, 0)) target.putalpha(alpha) md5 = hashlib.md5( str(str(operator_image) + str(target_image)).encode("utf-8")).hexdigest() for i in range(1, 14): gif_frames.append(await AvatarFunPicHandler.kiss_make_frame( operator, target, i)) await AvatarFunPicHandler.save_gif( gif_frames, f"{os.getcwd()}/statics/temp/tempKiss-{md5}.gif", fps=25) with open(f"{os.getcwd()}/statics/temp/tempKiss-{md5}.gif", 'rb') as r: img_content = r.read() os.remove(f"{os.getcwd()}/statics/temp/tempKiss-{md5}.gif") return MessageItem( MessageChain.create([Image.fromUnsafeBytes(img_content)]), Normal(GroupStrategy()))
async def throw(image: Union[int, str]) -> MessageItem: avatar = await AvatarFunPicHandler.get_pil_avatar(image) mask = IMG.new('L', avatar.size, 0) draw = ImageDraw.Draw(mask) offset = 1 draw.ellipse( (offset, offset, avatar.size[0] - offset, avatar.size[1] - offset), fill=255) mask = mask.filter(ImageFilter.GaussianBlur(0)) avatar.putalpha(mask) avatar = avatar.rotate(random.randint(1, 360), IMG.BICUBIC) avatar = avatar.resize((143, 143), IMG.ANTIALIAS) throw = IMG.open(f"{os.getcwd()}/statics/throw.png") throw.paste(avatar, (15, 178), mask=avatar) throw = throw.convert('RGB') output = BytesIO() throw.save(output, format='jpeg') return MessageItem( MessageChain.create([Image.fromUnsafeBytes(output.getvalue())]), Normal(GroupStrategy()))
async def crawl(image: Union[int, str]) -> MessageItem: avatar = await AvatarFunPicHandler.get_pil_avatar(image) mask = IMG.new('L', avatar.size, 0) draw = ImageDraw.Draw(mask) offset = 1 draw.ellipse( (offset, offset, avatar.size[0] - offset, avatar.size[1] - offset), fill=255) mask = mask.filter(ImageFilter.GaussianBlur(0)) avatar.putalpha(mask) images = [i for i in os.listdir(f"{os.getcwd()}/statics/crawl")] crawl = IMG.open( f"{os.getcwd()}/statics/crawl/{random.choice(images)}").resize( (500, 500), IMG.ANTIALIAS) avatar = avatar.resize((100, 100), IMG.ANTIALIAS) crawl.paste(avatar, (0, 400), mask=avatar) crawl = crawl.convert('RGB') output = BytesIO() crawl.save(output, format='jpeg') return MessageItem( MessageChain.create([Image.fromUnsafeBytes(output.getvalue())]), Normal(GroupStrategy()))
async def update_keyword(message: MessageChain, message_serialization: str) -> MessageItem: _, keyword, reply = message_serialization.split("#") keyword_type = "text" reply_type = "text" if re.match(r"\[mirai:image:{.*}\..*]", keyword): keyword = re.findall(r"\[mirai:image:{(.*?)}\..*]", keyword, re.S)[0] keyword_type = "img" if re.match(r"\[mirai:image:{.*}\..*]", reply): reply_type = "img" image: Image = message[Image][ 0] if keyword_type == "text" else message[Image][1] async with aiohttp.ClientSession() as session: async with session.get(url=image.url) as resp: content = await resp.read() reply = base64.b64encode(content) else: reply = reply.encode("utf-8") m = hashlib.md5() m.update(reply) reply_md5 = m.hexdigest() try: if result := list( orm.fetchone( select(KeywordReply).where( KeywordReply.keyword == keyword, KeywordReply.reply_type == reply_type, KeywordReply.reply_md5 == reply_md5))): print(result) return MessageItem( MessageChain.create([Plain(text=f"重复添加关键词!进程退出")]), Normal(GroupStrategy())) else: