async def get_personal_review(group_id: int, member_id: int, review_type: str) -> list: mask_path = f"./statics/wordCloud/PersonalCustomizationMask/{group_id}_{member_id}.jpg" time = datetime.datetime.now() year, month, day, hour, minute, second = time.strftime( "%Y %m %d %H %M %S").split(" ") if review_type == "year": yearp, monthp, dayp, hourp, minutep, secondp = ( time - relativedelta(years=1)).strftime("%Y %m %d %H %M %S").split(" ") tag = "年内" elif review_type == "month": yearp, monthp, dayp, hourp, minutep, secondp = ( time - relativedelta(months=1)).strftime("%Y %m %d %H %M %S").split(" ") tag = "月内" else: return [ "None", MessageChain.create([Plain(text="Error: review_type invalid!")]) ] sql = f"""SELECT * FROM chatRecord WHERE groupId={group_id} AND memberId={member_id} AND time<'{year}-{month}-{day} {hour}:{minute}:{second}' AND time>'{yearp}-{monthp}-{dayp} {hourp}:{minutep}:{secondp}'""" # print(sql) res = await execute_sql(sql) texts = [] for i in res: if i[4]: texts += i[4].split(",") else: texts.append(i[3]) print(texts) top_n = await count_words(texts, 20000) if os.path.exists(mask_path): await draw_word_cloud(top_n, mask_path) else: await draw_word_cloud(top_n) sql = f"""SELECT count(*) FROM chatRecord WHERE groupId={group_id} AND memberId={member_id} AND time<'{year}-{month}-{day} {hour}:{minute}:{second}' AND time>'{yearp}-{monthp}-{dayp} {hourp}:{minutep}:{secondp}'""" res = await execute_sql(sql) times = res[0][0] return [ "quoteSource", MessageChain.create([ Plain(text="记录时间:\n"), Plain(text=f"{yearp}-{monthp}-{dayp} {hourp}:{minutep}:{secondp}"), Plain(text="\n---------至---------\n"), Plain(text=f"{year}-{month}-{day} {hour}:{minute}:{second}"), Plain(text=f"\n自有记录以来,你一共发了{times}条消息\n下面是你的{tag}个人词云:\n"), Image.fromLocalFile("./statics/temp/tempWordCloud.png") ]) ]
async def get_book_recommand_by_tag(tag: str) -> list: path = await getImagePath(tag) if path: return [ "quoteSource", MessageChain.create([Image.fromLocalFile(path)]) ] else: return [ "quoteSource", MessageChain.create([Plain(text=f"没有找到有关{tag}的图书呐~换个标签吧~")]) ]
async def get_review(group_id: int, member_id: int, review_type: str, target: str) -> MessageChain: time = datetime.datetime.now() year, month, day, hour, minute, second = time.strftime( "%Y %m %d %H %M %S").split(" ") if review_type == "year": yearp, monthp, dayp, hourp, minutep, secondp = ( time - relativedelta(years=1)).strftime("%Y %m %d %H %M %S").split(" ") tag = "年内" elif review_type == "month": yearp, monthp, dayp, hourp, minutep, secondp = ( time - relativedelta(months=1)).strftime("%Y %m %d %H %M %S").split(" ") tag = "月内" else: return MessageChain.create([Plain(text="Error: review_type invalid!")]) sql = f"""SELECT * FROM chatRecord WHERE groupId={group_id} {f'AND memberId={member_id}' if target == 'member' else ''} AND time<'{year}-{month}-{day} {hour}:{minute}:{second}' AND time>'{yearp}-{monthp}-{dayp} {hourp}:{minutep}:{secondp}'""" # print(sql) res = await execute_sql(sql) texts = [] for i in res: if i[4]: texts += i[4].split(",") else: texts.append(i[3]) print(texts) top_n = await count_words(texts, 20000) await draw_word_cloud(top_n) sql = f"""SELECT count(*) FROM chatRecord WHERE groupId={group_id} {f'AND memberId={member_id}' if target == 'member' else ''} AND time<'{year}-{month}-{day} {hour}:{minute}:{second}' AND time>'{yearp}-{monthp}-{dayp} {hourp}:{minutep}:{secondp}'""" res = await execute_sql(sql) times = res[0][0] return MessageChain.create([ Plain(text="记录时间:\n"), Plain(text=f"{yearp}-{monthp}-{dayp} {hourp}:{minutep}:{secondp}"), Plain(text="\n---------至---------\n"), Plain(text=f"{year}-{month}-{day} {hour}:{minute}:{second}"), Plain( text= f"\n自有记录以来,{'你' if target == 'member' else '本群'}一共发了{times}条消息\n下面是{'你的' if target == 'member' else '本群的'}{tag}词云:\n" ), Image.fromLocalFile(f"{BASE_PATH}tempWordCloud.png") ])
async def search_pdf(keyword: str) -> MessageChain: url = f"https://zh.1lib.us/s/?q={keyword}" base_url = "https://zh.1lib.us" async with aiohttp.ClientSession() as session: async with session.get(url=url) as resp: html = await resp.read() soup = BeautifulSoup(html, "html.parser") divs = soup.find("div", { "id": "searchResultBox" }).find_all("div", {"class": "resItemBox resItemBoxBooks exactMatch"}) count = 0 books = [] text = "搜索到以下结果:\n\n" for div in divs: count += 1 if count > 5: break name = div.find("h3").get_text().strip() href = div.find("h3").find("a", href=True)["href"] first_div = div.find("table").find("table").find("div") publisher = first_div.get_text().strip() if re.search( '.*?title="Publisher".*?', str(first_div)) else None authors = div.find("div", {"class": "authors"}).get_text().strip() text += f"{count}.\n" text += f"名字:{name}\n" text += f"作者:{authors}\n" if authors else "" text += f"出版社:{publisher}\n" if publisher else "" text += f"页面链接:{base_url + href}\n\n" books.append({ "name": name, "href": base_url + href, "publisher": publisher, "authors": authors, # "download_href": base_url + download_href }) print(name, href, publisher, authors, sep="\n", end="\n\n") if not books: text = "未搜索到结果呢 >A<\n要不要换个关键词试试呢~" return MessageChain.create([Plain(text=text)]) text = text.replace("搜索到以下结果:\n\n", "") pics_path = await text2piiic_with_link(text=text) msg = [Plain(text="搜索到以下结果:\n\n")] for path in pics_path: msg.append(Image.fromLocalFile(path)) return MessageChain.create(msg)
async def keyword_reply(message_text: str): with open('./json/reply_keywords.json', 'r', encoding='utf-8') as f: # 从json读配置 keywords_dict = json.loads(f.read()) if message_text in keywords_dict.keys(): return [ "None", MessageChain.create([Plain(text=keywords_dict[message_text][1])]) ] if keywords_dict[message_text][0] == "text" else [ "None", MessageChain.create( [Image.fromLocalFile(keywords_dict[message_text][1])]) ] else: return None
async def get_gallery_status(base_name: str) -> list: legal_name = {"setu", "setu18", "real", "realHighq", "bizhi"} if base_name not in legal_name: return [ "quoteSource", MessageChain.create([ Plain(text="base_name错误!") ]) ] else: return [ "None", MessageChain.create([ Plain(text=f"{base_name}图库总数量:{await get_file_count(base_name)}") ]) ]
async def get_user_info(group_id: int, member_id: int, member_name: str, member_count: int) -> list: sql = f"select * from userCalled where groupId={group_id} and memberId={member_id}" data = await execute_sql(sql) if data: data = data[0] sql = f"SELECT count(*) FROM chatRecord WHERE groupId={group_id} AND memberId={member_id}" count = await execute_sql(sql) count = count[0][0] sql = f"SELECT count(*) FROM chatRecord WHERE groupId={group_id}" total_count = await execute_sql(sql) total_count = total_count[0][0] avg = round(total_count / member_count, 2) text = f"{member_name},下面是你的总结哦~\n" text += f"\n你在本群一共发了{count}条消息,本群人均消息数为{avg}," text += "好家伙您这可是真能水啊,我愿称您为水怪!\n" if count >= 2 * avg else "在群内很活跃呢!\n" if count >= avg else "看来不是很活跃呢~\n" text += f"\n你在本群一共要过{data[2] + data[3] + data[4]}张图\n其中{data[2]}张setu,{data[3]}张real,{data[4]}张bizhi\n" text += "看来你真是个十足的LSP呢!\n" if data[2] + data[ 3] >= 10 else "再接再厉!争当LSP!\n" text += f"\n一共@过我{data[5]}次," text += "看来你很喜欢找我玩呐~嘿嘿,被纱雾的美貌迷住了吧~\n" if data[ 5] >= 10 else "这可不行,要多多来找纱雾玩哦~\n" text += f"\n一共搜过{data[6]}次图," text += "看来纱雾也被人依赖了呢!嘿嘿,开心!\n" if data[6] >= 5 else "来多多依赖纱雾嘛~\n" text += f"\n一共点过{data[9]}首歌," text += "看来你很喜欢听歌呐!" if data[9] > 0 else "快来试试点歌吧~" return ["quoteSource", MessageChain.create([Plain(text=text)])] else: sql = f"SELECT count(*) FROM chatRecord WHERE groupId={group_id} AND memberId={member_id}" count = await execute_sql(sql) count = count[0][0] sql = f"SELECT count(*) FROM chatRecord WHERE groupId={group_id}" total_count = await execute_sql(sql) total_count = total_count[0][0] avg = round(total_count / member_count, 2) text = f"{member_name},下面是你的总结哦~\n" text += f"\n你在本群一共发了{count}条消息,本群人均消息数为{avg}," text += "好家伙您这可是真能水啊,我愿称您为水怪!\n" if count >= 2 * avg else "在群内很活跃呢!\n" if count >= avg else "看来不是很活跃呢~\n" text += "\n你在本群一共要过0张图\n其中0张setu,0张real,0张bizhi\n" text += "再接再厉!争当LSP!\n" text += "\n一共@过我{0}次," text += "这可不行,要多多来找纱雾玩哦~\n" text += "\n一共搜过0次图," text += "来多多依赖纱雾嘛~\n" text += "\n一共点过0首歌," text += "快来试试点歌吧~" return ["quoteSource", MessageChain.create([Plain(text=text)])]
async def make_qrcode(content: str) -> list: img = qrcode.make(content) img.save("./statics/temp/tempQrcodeMaked.jpg") return [ "quoteSource", MessageChain.create( [Image.fromLocalFile("./statics/temp/tempQrcodeMaked.jpg")]) ]
async def get_bot_status(base_name: str, group_id: int) -> list: legal_status_name = {"all", "memory", "system", "cpu", "setting", "bot"} legal_gallery_name = {"setu", "setu18", "real", "realHighq", "bizhi"} if base_name in legal_gallery_name: return [ "None", MessageChain.create([ Plain( text=f"{base_name}图库总数量:{await get_file_count(base_name)}") ]) ] elif base_name in legal_status_name: return ["None", Plain(text="SAGIRI-BOT STATUS:")] else: return [ "quoteSource", MessageChain.create([Plain(text="base_name错误!")]) ]
async def plugins_manager(app: GraiaMiraiApplication, group: Group): plugins = platform.get_plugins() text = "SagiriGraiaPlatform\n\n目前已加载插件:" serial_number = 1 for plugin in plugins: text += f"\n\n{serial_number}. {plugin['name']}:" text += f"\n{plugin['description']}" serial_number += 1 text += "\n\n你可输入 'pluginHelp 插件序号' 命令来查看插件详情" await app.sendGroupMessage(group, MessageChain.create([Plain(text=text)]))
async def set_personal_wordcloud_mask(group_id: int, member_id: int, mask: Image) -> list: img_url = mask.url path = f"./statics/wordCloud/PersonalCustomizationMask/{group_id}_{member_id}.jpg" async with aiohttp.ClientSession() as session: async with session.get(url=img_url) as resp: img_content = await resp.read() image = IMG.open(BytesIO(img_content)) image.save(path) return ["quoteSource", MessageChain.create([Plain(text="添加成功!")])]
async def get_personal_achievement(group_id: int, member_id: int): sql = f"select * from achievement where groupId={group_id} and memberId={member_id}" if result := await execute_sql(sql): result = result[0] setu = result[2] lsp_dragon = result[3] chat = result[4] if setu == 0 and lsp_dragon == 0 and chat == 0: return [ "quoteSource", MessageChain.create([Plain(text="你还没有获得任何成就呐~")]) ] msg_str = f"你已获得成就:\n\n" msg_str += (setu_achievement_code[setu] + "\n " + setu_achievement_description[setu] + "\n\n") if setu != 0 else "" msg_str += (lsp_dragon_achievement_code[lsp_dragon] + "\n " + lsp_dragon_achievement_description[lsp_dragon] + "\n\n") if lsp_dragon != 0 else "" msg_str += (chat_achievement_code[chat] + "\n " + chat_achievement_description[chat]) if chat != 0 else "" return ["quoteSource", MessageChain.create([Plain(text=msg_str)])]
async def check996(keyword: str) -> list: sql = f"SELECT * FROM db996 WHERE `name` LIKE '%{keyword}%'" result = await execute_sql(sql) if result: if len(result) > 5: return [ "quoteSource", MessageChain.create([ Plain( text= f"共找到{len(result)}条结果呢~\n太多了人家也不太好发呢~\n要不要再把关键词精确一些再进行查找呢~\n我不想被风控呐~" ) ]) ] text = f"共找到{len(result)}条结果:\n\n" index = 0 for i in result: index += 1 text += f"{index}.\n" text += f"公司名称:{i[1]}\n" text += f"所在城市:{i[0]}\n" text += f"曝光/施行时间:{i[2]}\n" text += f"制度描述:{i[3]}\n\n" return [ "quoteSource", MessageChain.create([ Plain(text=text), Plain(text="声明:无记录并不代表非996,所有数据皆从github项目996.ICU获取,请自行甄别") ]) ] else: return [ "quoteSource", MessageChain.create([ Plain(text=f"没有找到{keyword}的信息呢~\n"), Plain(text="可能公司不是996哦~\n(只是可能哦~)\n\n"), Plain(text="声明:无记录并不代表非996,所有数据皆从github项目996.ICU获取,请自行甄别") ]) ]
def exception_resender_listener(app: GraiaMiraiApplication, exception_resender_instance: ExceptionReSender, loop): while True: task = exception_resender_instance.get() # print("task: ", task) if task: print("task catched!") print("len:", exception_resender_instance.getLen()) print("task: ", task) try: if len(task) > 1 and task[0] == "None": asyncio.run_coroutine_threadsafe( app.sendGroupMessage(task[4], task[1]), loop) # await app.sendGroupMessage(task[4], task[1]) elif len(task) > 1 and task[0] == "AtSender": asyncio.run_coroutine_threadsafe( app.sendGroupMessage(task[4], task[1]), loop) # await app.sendGroupMessage(task[4], task[1]) elif len(task) > 1 and task[0] == "quoteSource": asyncio.run_coroutine_threadsafe( app.sendGroupMessage(task[4], task[1], quote=task[2][Source][0]), loop) # await app.sendGroupMessage(task[4], task[1], quote=task[2][Source][0]) elif len(task) > 1 and task[0] == "revoke": asyncio.run_coroutine_threadsafe(revoke_process(app, task), loop) # msg = asyncio.run_coroutine_threadsafe(app.sendGroupMessage(task[4], task[1]), loop) # asyncio.run_coroutine_threadsafe(asyncio.sleep(20), loop) # asyncio.run_coroutine_threadsafe(app.revokeMessage(msg.result()), loop) # msg = await app.sendGroupMessage(task[4], task[1]) # await asyncio.sleep(20) # await app.revokeMessage(msg) except Exception: task[5] += 1 if task[5] <= exception_resender_instance.max_retries: exception_resender_instance.addTask(task) else: asyncio.run_coroutine_threadsafe( app.sendGroupMessage( task[4], MessageChain.create([ Plain( text= "Maximum number of retries exceeded! Task cancelled!" ) ]), quote=task[2][Source][0]), loop) time.sleep(2)
async def plugins_manager(app: GraiaMiraiApplication, group: Group, message: MessageChain): plugins = platform.get_plugins() target = message.asDisplay()[11:] if target.isdigit(): target = int(target) if target > len(plugins): await app.sendGroupMessage( group, MessageChain.create([Plain(text="非法插件序号!")])) else: plugin = plugins[target - 1] await app.sendGroupMessage( group, MessageChain.create([ Plain(text=f"插件详细信息:"), Plain(text=f"\n\n插件名:{plugin['name']}"), Plain(text=f"\n\n插件描述: {plugin['description']}"), Plain(text=f"\n\n插件作者: {plugin['author']}"), Plain(text=f"\n\n使用方法: {plugin['usage']}") ])) else: await app.sendGroupMessage( group, MessageChain.create([Plain(text="非法插件序号!")]))
async def get_weibo_hot(display: str = "img") -> MessageChain: url = "http://api.weibo.cn/2/guest/search/hot/word" async with aiohttp.ClientSession() as session: async with session.get(url=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("\n%d. %s" % (index, i["word"].strip())) text = "".join(text_list).replace("#", "") msg = MessageChain.create([Plain(text=text)]) if display == "img": return await messagechain_to_img(msg) elif display == "text": return msg else: raise ValueError("Invalid display value!")
async def get_almanac() -> list: url = "https://laohuangli.bmcx.com/" headers = { "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 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") target_trs = soup.find_all("table")[3].find_all("tr") # print(target_trs) data = {} for i in target_trs: tds = i.find_all("td") key = tds[0].get_text().strip() value = tds[1].get_text().strip() data[key] = value text = f"今天是{data['日期']}\n宜:{data['宜'].replace('.', '、')}\n忌:{data['忌'].replace('.', '、')}" return ["None", MessageChain.create([Plain(text=text)])]
async def get_group_announcement(content: str) -> list: group_announcement_json = """ { "app": "com.tencent.mannounce", "config": { "ctime": 1610424762, "forward": 0, "token": "190bcca54b1eb9c543676aa1c82762ab" }, "desc": "群公告", "extra": { "app_type": 1, "appid": 1101236949, "uin": 1900384123 }, "meta": { "mannounce": { "cr": 1, "encode": 1, "fid": "93206d3900000000ba21fd5fa58a0500", "gc": "963453075", "sign": "cbbf90a7cbf1dc938ac5bdb8224fc3cb", "text": "%s", "title": "576k5YWs5ZGK", "tw": 1, "uin": "1900384123" } }, "prompt": "[群公告]test", "ver": "1.0.0.43", "view": "main" }""" % base64.b64encode(content.encode('utf-8')) return [ "None", MessageChain.create([App(content=group_announcement_json)]) ]
MessageChain.create([Plain(text="你还没有获得任何成就呐~")]) ] msg_str = f"你已获得成就:\n\n" msg_str += (setu_achievement_code[setu] + "\n " + setu_achievement_description[setu] + "\n\n") if setu != 0 else "" msg_str += (lsp_dragon_achievement_code[lsp_dragon] + "\n " + lsp_dragon_achievement_description[lsp_dragon] + "\n\n") if lsp_dragon != 0 else "" msg_str += (chat_achievement_code[chat] + "\n " + chat_achievement_description[chat]) if chat != 0 else "" return ["quoteSource", MessageChain.create([Plain(text=msg_str)])] else: return [ "quoteSource", MessageChain.create([Plain(text="你还没有获得任何成就呐~")]) ] async def setu_achievement_check(group_id: int, member_id: int): sql = f"select setu+`real` from userCalled where groupId={group_id} and memberId={member_id}" # print(sql) result = await execute_sql(sql) count = result[0][0] # print(count) if count >= 1000: achievement_code = 6 elif count >= 500: achievement_code = 5 elif count >= 200: achievement_code = 4
async def search_bangumi(group_id: int, sender: int, img_url: str) -> list: await set_get_img_ready(group_id, sender, False, "searchBangumiReady") async with aiohttp.ClientSession() as session: async with session.get(url=img_url) as resp: img_content = await resp.read() url = "https://trace.moe/search" headers = { "X-Requested-With": "XMLHttpRequest", "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", } image_b64 = base64.b64encode(img_content) params = f"data={quote(f'data:image/jpeg;base64,{image_b64.decode()}')}&filter={''}&trial={'0'}" async with aiohttp.ClientSession() as session: async with session.post(url=url, headers=headers, data=params) as resp: print(await resp.text()) result = await resp.json() docs = result["docs"] if docs: try: print(docs[0]) title_chinese = docs[0]["title_chinese"] title_origin = docs[0]["title_chinese"] file_name = docs[0]["file"] anilist_id = docs[0]["anilist_id"] time_from = docs[0]["from"] time_to = docs[0]["to"] t = docs[0]["t"] tokenthumb = docs[0]["tokenthumb"] thumbnail_url = f"https://trace.moe/thumbnail.php?anilist_id={anilist_id}&file={quote(file_name)}&t={t}&token={tokenthumb}" print(thumbnail_url) # 下载缩略图 path = "./statics/temp/tempSearchBangumi.jpg" async with aiohttp.ClientSession() as session: async with session.get(url=thumbnail_url) as resp: thumbnail_content = await resp.read() image = IMG.open(BytesIO(thumbnail_content)) image.save(path) url = f"https://trace.moe/info?anilist_id={anilist_id}" async with aiohttp.ClientSession() as session: async with session.get(url=url) as resp: result = await resp.json() result = result[0] start_date = f"{result['startDate']['year']}-{result['startDate']['month']}-{result['startDate']['day']}" end_date = f"{result['endDate']['year']}-{result['endDate']['month']}-{result['endDate']['day']}" score = result["averageScore"] message = MessageChain.create([ Plain(text="搜索到结果:\n"), Image.fromLocalFile(path), Plain(text=f"name: {title_origin}\n"), Plain(text=f"Chinese name: {title_chinese}\n"), Plain(text=f"file name: {file_name}\n"), Plain( text= f"time: {await sec_to_str(time_from)} ~ {await sec_to_str(time_to)}\n" ), Plain(text=f"score: {score}\n"), Plain(text=f"Broadcast date: {start_date} ~ {end_date}\n") ]) return [ "quoteSource", await messagechain_to_img(message=message, max_width=1080, img_fixed=True) ] except Exception as e: return [ "quoteSource", MessageChain.create( [Plain(text="出错了呢~\n"), Plain(text=str(e))]) ] else: return ["quoteSource", MessageChain.create([Plain(text="没有搜索到结果呐~")])]
async def get_douban_new_books() -> list: url = "https://book.douban.com/latest?icn=index-latestbook-all" async with aiohttp.ClientSession() as session: async with session.get(url=url) as resp: html = await resp.read() soup = BeautifulSoup(html, "html.parser") div = soup.find("div", {"id": "content"}) fictitious = div.find("div", {"class": "article"}) non_fictitious = div.find("div", {"class": "aside"}) fictitious_lis = fictitious.find_all("li") non_fictitious_lis = non_fictitious.find_all("li") fictitiou_books = [] non_fictitiou_books = [] count = 0 for fictitious_li in fictitious_lis: count += 1 if count > 3: count = 0 break name = fictitious_li.find("h2").find("a").get_text().strip() href = fictitious_li.find("h2").find("a", href=True)["href"] cover = fictitious_li.find("a", { "class": "cover" }, href=True).find("img")["src"] rating = fictitious_li.find("p", { "class": "rating" }).get_text().strip() rating = rating if rating else "尚无评价" publishment = fictitious_li.find("p", { "class": "color-gray" }).get_text().strip() detail = fictitious_li.find("p", { "class": "detail" }).get_text().strip() fictitiou_books.append({ "name": name, "cover": cover, "href": href, "rating": rating, "publishment": publishment, "detail": detail }) # print(name, href, cover, rating, publishment, detail, sep="\n", end="\n\n") for non_fictitious_li in non_fictitious_lis: count += 1 if count > 3: break name = non_fictitious_li.find("h2").find("a").get_text().strip() href = non_fictitious_li.find("h2").find("a", href=True)["href"] cover = non_fictitious_li.find("a", { "class": "cover" }, href=True).find("img")["src"] rating = non_fictitious_li.find("p", { "class": "rating" }).get_text().strip() rating = rating if rating else "尚无评价" publishment = non_fictitious_li.find("p", { "class": "color-gray" }).get_text().strip() detail = non_fictitious_li.find_all("p")[2].get_text().strip() non_fictitiou_books.append({ "name": name, "cover": cover, "href": href, "rating": rating, "publishment": publishment, "detail": detail }) text = "" for book in fictitiou_books: text += f"书名:{book['name']}\n" text += f"评分:{book['rating']}\n" text += f"信息:{book['publishment']}\n" text += f"描述:{book['detail']}\n" text += f"链接:{book['href']}\n" for book in non_fictitiou_books: text += f"书名:{book['name']}\n" text += f"评分:{book['rating']}\n" text += f"信息:{book['publishment']}\n" text += f"描述:{book['detail']}\n" text += f"链接:{book['href']}\n" pics_path = await text2piiic_with_link(text=text) msg = [Plain(text="新书速递:\n\n")] for path in pics_path: msg.append(Image.fromLocalFile(path)) # img.save("./statics/temp/tempPDFSearch.png") return ["quoteSource", MessageChain.create(msg)]
async def search_pdf(group_id: int, keyword: str) -> list: url = f"https://zh.1lib.us/s/?q={keyword}" base_url = "https://zh.1lib.us" async with aiohttp.ClientSession() as session: async with session.get(url=url) as resp: html = await resp.read() soup = BeautifulSoup(html, "html.parser") divs = soup.find("div", { "id": "searchResultBox" }).find_all("div", {"class": "resItemBox resItemBoxBooks exactMatch"}) count = 0 books = [] text = "搜索到以下结果:\n\n" for div in divs: count += 1 if count > 5: break name = div.find("h3").get_text().strip() href = div.find("h3").find("a", href=True)["href"] first_div = div.find("table").find("table").find("div") publisher = first_div.get_text().strip() if re.search( '.*?title="Publisher".*?', str(first_div)) else None authors = div.find("div", {"class": "authors"}).get_text().strip() # async with aiohttp.ClientSession() as session: # async with session.get(url=base_url + href) as resp: # html = await resp.read() # # re_res = re.findall(r'<a class="btn btn-primary dlButton addDownloadedBook" href="(.*?)"', str(html), re.S) # download_href = re_res[0] if re_res else None text += f"{count}.\n" text += f"名字:{name}\n" text += f"作者:{authors}\n" if authors else "" text += f"出版社:{publisher}\n" if publisher else "" text += f"页面链接:{base_url + href}\n\n" books.append({ "name": name, "href": base_url + href, "publisher": publisher, "authors": authors, # "download_href": base_url + download_href }) print(name, href, publisher, authors, sep="\n", end="\n\n") if not books: text = "未搜索到结果呢 >A<\n要不要换个关键词试试呢~" return ["quoteSource", MessageChain.create([Plain(text=text)])] long_text_setting = await get_setting(group_id, "longTextType") if long_text_setting == "img": # img = text2piiic(string=text, poster="", length=max(len(x) for x in text.split("\n"))) text = text.replace("搜索到以下结果:\n\n", "") pics_path = await text2piiic_with_link(text=text) msg = [Plain(text="搜索到以下结果:\n\n")] for path in pics_path: msg.append(Image.fromLocalFile(path)) # img.save("./statics/temp/tempPDFSearch.png") return ["quoteSource", MessageChain.create(msg)] elif long_text_setting == "text": return ["quoteSource", MessageChain.create([Plain(text=text)])] else: return [ "None", MessageChain.create([Plain(text="数据库 longTextType 项出错!请检查!")]) ]
async def messagechain_to_img( message: MessageChain, max_width: int = 1080, font_size: int = 40, spacing: int = 15, padding_x: int = 20, padding_y: int = 15, img_fixed: bool = False, font_path: str = "./simhei.ttf", save_path: str = "./temp/tempMessageChainToImg.png") -> MessageChain: """ 将 MessageChain 转换为图片,仅支持只含有本地图片/文本的 MessageChain Args: message: 要转换的MessageChain max_width: 最大长度 font_size: 字体尺寸 spacing: 行间距 padding_x: x轴距离边框大小 padding_y: y轴距离边框大小 img_fixed: 图片是否适应大小(仅适用于图片小于最大长度时) font_path: 字体文件路径 save_path: 图片存储路径 Examples: msg = await messagechain_to_img(message=message) Returns: MessageChain (内含图片Image类) """ if not os.path.exists("temp"): os.mkdir("temp") font = ImageFont.truetype(font_path, font_size, encoding="utf-8") message = message.asMerged() elements = message.__root__ plains = message.get(Plain) text_gather = "\n".join([plain.text for plain in plains]) # print(max(font.getsize(text)[0] for text in text_gather.split("\n")) + 2 * padding_x) final_width = min( max(font.getsize(text)[0] for text in text_gather.split("\n")) + 2 * padding_x, max_width) text_width = final_width - 2 * padding_x text_height = (font_size + spacing) * await get_final_text_lines( text_gather, text_width, font) img_height_sum = 0 temp_img_list = [] images = message.get(Image_LocalFile) for image in images: if isinstance(image, Image_LocalFile): temp_img = IMG.open(image.filepath) img_width, img_height = temp_img.size temp_img_list.append( temp_img := temp_img.resize(( int(final_width - 2 * spacing), int( float(img_height * (final_width - 2 * spacing)) / float(img_width)))) if img_width > final_width - 2 * spacing or (img_fixed and img_width < final_width - 2 * spacing) else temp_img) img_height_sum = img_height_sum + temp_img.size[1] # elif isinstance(image, Image_UnsafeBytes): # temp_img = IMG.open(BytesIO(image.image_bytes)) else: raise Exception("messagechain_to_img:仅支持本地图片即Image_LocalFile类的处理!") final_height = 2 * padding_y + text_height + img_height_sum picture = IMG.new('RGB', (final_width, final_height), (255, 255, 255)) draw = ImageDraw.Draw(picture) present_x = padding_x present_y = padding_y image_index = 0 for element in elements: if isinstance(element, Image_LocalFile): # print(f"adding img {image_index}") picture.paste(temp_img_list[image_index], (present_x, present_y)) present_y += (spacing + temp_img_list[image_index].size[1]) image_index += 1 elif isinstance(element, Plain): # print(f"adding text '{element.text}'") for char in element.text: if char == "\n": present_y += (font_size + spacing) present_x = padding_x continue if char == "\r": continue if present_x + font.getsize(char)[0] > text_width: present_y += (font_size + spacing) present_x = padding_x draw.text((present_x, present_y), char, font=font, fill=(0, 0, 0)) present_x += font.getsize(char)[0] present_y += (font_size + spacing) present_x = padding_x picture.save(save_path) print(f"process finished! Image saved at {save_path}") return MessageChain.create([Image.fromLocalFile(save_path)])
async def search_bangumi(group_id: int, sender: int, img_url: str) -> list: await set_get_img_ready(group_id, sender, False, "searchBangumiReady") async with aiohttp.ClientSession() as session: async with session.get(url=img_url) as resp: img_content = await resp.read() url = "https://trace.moe/search" headers = { "X-Requested-With": "XMLHttpRequest", "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", } image_b64 = base64.b64encode(img_content) params = f"data={quote(f'data:image/jpeg;base64,{image_b64.decode()}')}&filter={''}&trial={'0'}" async with aiohttp.ClientSession() as session: async with session.post(url=url, headers=headers, data=params) as resp: result = await resp.json() docs = result["docs"] if docs: try: print(docs[0]) title_chinese = docs[0]["title_chinese"] title_origin = docs[0]["title_chinese"] file_name = docs[0]["file"] anilist_id = docs[0]["anilist_id"] time_from = docs[0]["from"] time_to = docs[0]["to"] url = f"https://trace.moe/info?anilist_id={anilist_id}" async with aiohttp.ClientSession() as session: async with session.get(url=url) as resp: result = await resp.json() result = result[0] start_date = f"{result['startDate']['year']}-{result['startDate']['month']}-{result['startDate']['day']}" end_date = f"{result['endDate']['year']}-{result['endDate']['month']}-{result['endDate']['day']}" score = result["averageScore"] return [ "quoteSource", MessageChain.create([ Plain(text="搜索到结果:\n"), Plain(text=f"name: {title_origin}\n"), Plain(text=f"Chinese name: {title_chinese}\n"), Plain(text=f"file name: {file_name}\n"), Plain(text=f"time: {time_from}s ~ {time_to}s\n"), Plain(text=f"score: {score}\n"), Plain(text=f"Broadcast date: {start_date} ~ {end_date}\n") ]) ] except Exception as e: return [ "quoteSource", MessageChain.create([ Plain(text="出错了呢~\n"), Plain(text=str(e)) ]) ] else: return [ "quoteSource", MessageChain.create([ Plain(text="没有搜索到结果呐~") ]) ]
async def group_message_process(message: MessageChain, message_info: GroupMessage, app: GraiaMiraiApplication) -> list: """ Process the received message and return the corresponding message Args: message: Received message(MessageChain) message_info: Received message(GroupMessage) app: APP Examples: message_list = await message_process(message, message_info) Return: [ str: Auxiliary treatment to be done(Such as add statement), MessageChain: Message to be send(MessageChain) ] """ message_text = message.asDisplay() message_serialization = message.asSerializationString() sender = message_info.sender.id group_id = message_info.sender.group.id # print("message_serialization:", message_serialization) if message.has(At) and message.get(At)[0].target == await get_config( "BotQQ"): await update_user_called_data(group_id, sender, "at", 1) if message.has(At) and message.get(At)[0].target == await get_config( "BotQQ") and re.search("@.* setting.*", message_text): try: _, config, new_value = message_text.split(".") return await setting_process(group_id, sender, config, new_value) except ValueError: return [ "None", MessageChain.create([Plain(text="Command Error!")]) ] """ 图片功能: setu real bizhi time search yellow predict lsp rank """ if message_text in response_set["setu"]: if await get_setting(group_id, "setu"): if sender == 80000000: return [ "None", MessageChain.create([Plain(text="要涩图就光明正大!匿名算什么好汉!")]) ] await update_dragon_data(group_id, sender, "normal") await update_user_called_data(group_id, sender, "setu", 1) if await get_setting(group_id, "r18"): return await get_pic("setu18", group_id, sender) else: return await get_pic("setu", group_id, sender) else: return [ "None", MessageChain.create([Plain(text="我们是正规群呐,不搞那一套哦,想看去辣种群看哟~")]) ] elif re.search("来点.*[色涩]图", message_text): if await get_setting(group_id, "setu"): if sender == 80000000: return [ "None", MessageChain.create([Plain(text="要涩图就光明正大!匿名算什么好汉!")]) ] keyword = re.findall("来点(.*?)[涩色]图", message_text, re.S)[0] print(keyword) if keyword in ["r18", "R18", "r-18", "R-18"]: return [ "quoteSource", MessageChain.create( [Plain(text="此功能暂时还不支持搜索R18涩图呐~忍忍吧LSP!")]) ] await app.sendGroupMessage( group=group_id, message=MessageChain.create([ Plain( text= f"你要的是{keyword}涩图对叭~等等呐~网很慢的>^<,没有反应不是卡死了就是图发出来被屏蔽了呐~就不要等了呐~" ) ]), quote=message[Source][0]) await update_dragon_data(group_id, sender, "normal") await update_user_called_data(group_id, sender, "setu", 1) return await get_setu_keyword(keyword=keyword) else: return [ "None", MessageChain.create([Plain(text="我们是正规群呐,不搞那一套哦,想看去辣种群看哟~")]) ] elif message_text in response_set["real"]: if await get_setting(group_id, "real"): if sender == 80000000: return [ "None", MessageChain.create([Plain(text="要涩图就光明正大!匿名算什么好汉!")]) ] await update_dragon_data(group_id, sender, "normal") await update_user_called_data(group_id, sender, "real", 1) return await get_pic("real", group_id, sender) else: return [ "None", MessageChain.create([Plain(text="我们是正规群呐,不搞那一套哦,想看去辣种群看哟~")]) ] elif message_text in response_set["realHighq"]: if await get_setting(group_id, "real"): if sender == 80000000: return [ "None", MessageChain.create([Plain(text="要涩图就光明正大!匿名算什么好汉!")]) ] await update_dragon_data(group_id, sender, "normal") await update_user_called_data(group_id, sender, "real", 1) return await get_pic("realHighq", group_id, sender) else: return [ "None", MessageChain.create([Plain(text="我们是正规群呐,不搞那一套哦,想看去辣种群看哟~")]) ] elif message_text in response_set["bizhi"]: if await get_setting(group_id, "bizhi"): if sender == 80000000: return [ "None", MessageChain.create([Plain(text="要涩图就光明正大!匿名算什么好汉!")]) ] await update_user_called_data(group_id, sender, "bizhi", 1) return await get_pic("bizhi", group_id, sender) else: return [ "None", MessageChain.create([Plain(text="壁纸功能关闭了呐~想要打开的话就联系管理员吧~")]) ] elif message_text.startswith("setu*") or message_text.startswith( "real*") or message_text.startswith("bizhi*"): if message_text.startswith("bizhi*"): command = "bizhi" num = message_text[6:] else: command = message_text[:4] num = message_text[5:] if num.isdigit(): num = int(num) if sender not in await get_admin(group_id): if 0 <= num <= 5: return [ "None", MessageChain.create([ Plain(text="只有主人和管理员可以使用%s*num命令哦~你没有权限的呐~" % command) ]) ] elif num < 0: return [ "None", MessageChain.create( [Plain(text="%d?你有问题?不如给爷吐出%d张来" % (num, -num))]) ] else: return [ "None", MessageChain.create( [Plain(text="不是管理员你要你🐎呢?老色批!还要那么多?给你🐎一拳,给爷爬!")]) ] if num < 0: return [ "None", MessageChain.create( [Plain(text="%d?你有问题?不如给爷吐出%d张来" % (num, -num))]) ] elif num > 5: if sender == await get_config("HostQQ"): return ["%s*" % command, num] else: return [ "None", MessageChain.create( [Plain(text="管理最多也只能要5张呐~我可不会被轻易玩儿坏呢!!!!")]) ] else: if sender != await get_config("HostQQ"): await update_user_called_data(group_id, sender, command, num) return ["%s*" % command, int(num)] else: return ["None", MessageChain.create([Plain(text="必须为数字!")])] elif message_text == "几点了": return await get_wallpaper_time(group_id, sender) elif message_text.startswith("选择表盘"): if message_text == "选择表盘": return await show_clock_wallpaper(sender) elif message_text == "搜图": if await get_setting(group_id, "search"): await set_get_img_ready(group_id, sender, True, "searchReady") return [ "None", MessageChain.create( [At(sender), Plain(text="请发送要搜索的图片呐~(仅支持pixiv图片搜索呐!)")]) ] else: return [ "None", MessageChain.create( [At(sender), Plain(text="搜图功能关闭了呐~想要打开就联系管理员吧~")]) ] elif message.has(Image) and await get_setting( group_id, "search") and await get_image_ready( group_id, sender, "searchReady"): # print("status:", await get_image_ready(group_id, sender, "searchReady")) image = message.get(Image)[0] await update_user_called_data(group_id, sender, "search", 1) return await search_image(group_id, sender, image) elif message_text == "这张图涩吗": if await get_setting(group_id, "yellowPredict"): await set_get_img_ready(group_id, sender, True, "yellowPredictReady") return [ "None", MessageChain.create( [At(target=sender), Plain(text="请发送要预测的图片呐~")]) ] else: return [ "None", MessageChain.create([ At(target=sender), Plain(text="图片涩度评价功能关闭了呐~想要打开就联系机器人管理员吧~") ]) ] elif message.has(Image) and await get_setting( group_id, "yellowPredict") and await get_image_ready( group_id, sender, "yellowPredictReady"): image = message.get(Image)[0] await update_user_called_data(group_id, sender, "yellowPredict", 1) return await image_yellow_judge(group_id, sender, image, "yellowPredict") elif message_text == "搜番": if await get_setting(group_id, "searchBangumi"): await set_get_img_ready(group_id, sender, True, "searchBangumiReady") return [ "None", MessageChain.create( [At(sender), Plain(text="请发送要搜索的图片呐~(仅支持番剧图片搜索呐!)")]) ] else: return [ "None", MessageChain.create( [At(sender), Plain(text="搜番功能关闭了呐~想要打开就联系管理员吧~")]) ] elif message.has(Image) and await get_setting( group_id, "searchBangumi") and await get_image_ready( group_id, sender, "searchBangumiReady"): # print("status:", await get_image_ready(group_id, sender, "searchReady")) image = message.get(Image)[0] await update_user_called_data(group_id, sender, "search", 1) return await search_bangumi(group_id, sender, image.url) elif message_text == "rank": return await get_rank(group_id, app) # 爬虫相关功能 """ SAGIRI API相关功能: 历史上的今天 """ if message_text == "历史上的今天": return await get_history_today() """ 微博相关功能: 微博热搜 """ if message_text == "weibo" or message_text == "微博": # return [ # "None", # MessageChain.create([ # Plain(text="本功能已停用,短时间内不再开放!请勿多次申请") # ]) # ] return await get_weibo_hot() """ B站相关功能: B站新番时间表 B站直播间查询 """ if message_text[-4:] == "日内新番": num = message_text[:-4] if not num.isdigit() or int(num) <= 0 or int(num) > 7: return [At(target=sender), Plain(text="参数错误!必须为数字1-7!")] else: return await formatted_output_bangumi(int(num)) """ 力扣相关功能: 用户信息查询 每日一题查询 具体题目查询 """ if message_text.startswith("leetcode "): return await get_leetcode_statics(message_text.replace( "leetcode ", "")) """ steam相关功能: steam游戏查询 """ if message_text.startswith("steam "): return await get_steam_game_search(message_text.replace("steam ", "")) """ bangumi相关功能: 番剧查询 """ if message_text.startswith("番剧 "): keyword = message_text[3:] return await get_bangumi_info(sender, keyword) """ 其他功能: 文本翻译 点歌 机器人帮助 自动回复 笑话 群语录 平安经(群人数过多时慎用) pornhub风格图片生成 摸~ """ if message.has(At) and message.get(At)[0].target == await get_config( "BotQQ") and re.search(".*用.*怎么说", message_text): return await get_translate(message_text, sender) elif message_text.startswith("点歌 ") and len(message_text) >= 4: print("search song:", message_text[3:]) return await get_song_ordered(message_text[3:]) if message_text == "help" or message_text == "!help" or message_text == "/help" or message_text == "!help": return [ "None", MessageChain.create([ Plain( text= "点击链接查看帮助:http://doc.sagiri-web.com/web/#/p/c79d523043f6ec05c1ac1416885477c7\n" ), Plain(text="文档尚未完善,功能说明还在陆续增加中!") ]) ] if message_text == "教务通知": return await get_jlu_csw_notice() if re.search("来点.*笑话", message_text): joke_dict = { "苏联": "soviet", "法国": "french", "法兰西": "french", "美国": "america", "美利坚": "america" } name = re.findall(r'来点(.*?)笑话', message_text, re.S) if name == ['']: return [ "None", MessageChain.create( [At(target=sender), Plain(text="来点儿啥笑话啊,你又不告诉人家!哼!")]) ] elif name[0] in joke_dict.keys(): msg = await get_key_joke(joke_dict[name[0]]) await write_log("joke", "none", sender, group_id, True, "function") return msg else: msg = await get_joke(name[0]) await write_log("joke", "none", sender, group_id, True, "function") return msg if message_text == "群语录": return await get_group_quotes(group_id, app, "None", "random", "None") elif re.search("来点.*语录", message_text): name = re.findall(r'来点(.*?)语录', message_text, re.S)[0] at_obj = message.get(At) if name == [] and at_obj == []: return ["None"] elif at_obj: at_str = at_obj[0].asSerializationString() member_id = re.findall(r'\[mirai:at:(.*?),@.*?\]', at_str, re.S)[0] await write_log("quotes", "None", sender, group_id, True, "function") if message_text[-4:] == ".all": return await get_group_quotes(group_id, app, member_id, "all", "memberId") else: return await get_group_quotes(group_id, app, member_id, "select", "memberId") elif name: await write_log("quotes", "None", sender, group_id, True, "function") if message_text[-4:] == ".all": return await get_group_quotes(group_id, app, name, "all", "nickname") else: return await get_group_quotes(group_id, app, name, "select", "nickname") if message_text == "平安": member_list = await app.memberList(group_id) msg = list() msg.append(Plain(text=f"群{message_info.sender.group.name}平安经\n")) for i in member_list: msg.append(Plain(text=f"{i.name}平安\n")) return ["None", MessageChain.create(msg)] if message_text.startswith("ph ") and len(message_text.split(" ")) == 3: if "\\" in message_text or "/" in message_text: return [ "None", MessageChain.create([Plain(text="不支持 '/' 与 '\\' !")]) ] args = message_text.split(" ") left_text = args[1] right_text = args[2] path = f'./statics/temp/ph_{left_text}_{right_text}.png' if not os.path.exists(path): try: await make_ph_style_logo(left_text, right_text) except OSError as e: if "[Errno 22] Invalid argument:" in str(e): return [ "quoteSource", MessageChain.create([Plain(text="非法字符!")]) ] return ["None", MessageChain.create([Image.fromLocalFile(path)])] if message.has(At) and message_text.startswith( "摸") or message_text.startswith("摸 "): target_id = message.get(At)[0].target await petpet(target_id) return [ "None", MessageChain.create([ Image.fromLocalFile( f'./statics/temp/tempPetPet-{target_id}.gif') ]) ] if message.has(At) and message.get(At)[0].target == await get_config( "BotQQ"): return await reply_process(group_id, sender, message_text) return ["None"]
async def setu_saver(message: MessageChain, group: Group): """ 使用方法: 添加图片:在群中发送 /添加涩图 pid即可 删除图片:在群中发送 /删除涩图 pid即可 插件来源:SAGIRI-kawaii """ message_text = message.asDisplay() if message_text.startswith("/添加涩图 "): img_id = message_text[6:] if os.path.exists(BASE_PATH + f"{img_id}.jpg"): await app.sendGroupMessage( group, MessageChain.create([Plain(text=f"图片 {img_id} 已存在于SetuLib中!") ])) return if img_id.isdigit(): await app.sendGroupMessage( group, MessageChain.create([Plain(text="正在搜索...请稍后...")])) path = BASE_PATH + f"{img_id}.jpg" success = False url = f"https://pixiv.cat/{img_id}.jpg" async with aiohttp.ClientSession() as session: async with session.get(url=url) as resp: status_code = resp.status print(status_code) if status_code != 404: img_content = await resp.read() success = True if not success: url = f"https://pixiv.cat/{img_id}-1.jpg" async with aiohttp.ClientSession() as session: async with session.get(url=url) as resp: status_code = resp.status print(status_code) if status_code != 404: img_content = await resp.read() success = True if not success: await app.sendGroupMessage( group, MessageChain.create( [Plain(text=f"未搜索到图片 {img_id}!请检查输入是否正确!")])) return image = IMG.open(BytesIO(img_content)) image = image.convert('RGB') image.save(path) await app.sendGroupMessage( group, MessageChain.create([ Plain(text=f"图片 {img_id} 添加成功!\n"), Image.fromUnsafeBytes(img_content) ])) else: await app.sendGroupMessage( group, MessageChain.create([Plain(text="非法pid!只接受全数字参数!")])) elif message_text.startswith("/删除涩图 "): img_id = message_text[6:] if os.path.exists(f"{BASE_PATH}{img_id}.jpg"): os.remove(f"{BASE_PATH}{img_id}.jpg") await app.sendGroupMessage( group, MessageChain.create([Plain(text=f"图片 {img_id} 已从SetuLib中删除!") ])) else: await app.sendGroupMessage( group, MessageChain.create([Plain(text=f"图片 {img_id} 不存在!")]))
WHERE groupId={group_id} AND time>='{year}-{month}-{day} 00:00:00' AND memberId!=80000000 GROUP BY memberId ORDER BY count(memberId) desc""" # print(sql) res = await execute_sql(sql) res = res[:10] # print(res) plt.rcdefaults() plt.rcParams['font.sans-serif'] = ['SimHei'] plt.rcParams['axes.unicode_minus'] = False name = [] for data in res: if member := await app.getMember(group_id, data[0]): name.append(member.name) else: name.append("NameNullError!") # name = [(await app.getMember(group_id, member[0])).name for member in res] count = [data[1] for data in res] print(name) print(count) plt.barh(range(len(count)), count, tick_label=name) plt.title(f"群{(await app.getGroup(group_id)).name}今日发言前十(截至目前)") plt.tight_layout() plt.savefig("./statics/temp/tempDailyChatRank.jpg") plt.close() return [ "None", MessageChain.create( [Image.fromLocalFile("./statics/temp/tempDailyChatRank.jpg")]) ]