From 406da4a620a8c6f63b1a7bc8c3987c25f0d1745b Mon Sep 17 00:00:00 2001 From: nek0us <1130131059@qq.com> Date: Thu, 11 Jul 2024 23:04:05 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0QQ=E9=80=82=E9=85=8D=E5=99=A8?= =?UTF-8?q?=20Url=20=E8=BE=93=E5=87=BA=E6=9B=BF=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 12 +++++- nonebot_plugin_gpt/api.py | 79 ++++++++++++++++++++++++++++++++++-- nonebot_plugin_gpt/config.py | 14 ++++++- pyproject.toml | 4 +- 4 files changed, 101 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 2d9eb43..fdacd99 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,7 @@ _✨ NoneBot GPT ✨_ | gpt_manage_ids | 否 | 无 | List[str] | 超管群/频道id,通过日志等方式获得 | | gpt_lgr_markdown| 否 | false | bool | 以拉格兰md消息回复 | | gpt_httpx| 否 | false | bool | 使用httpx | +| gpt_url_replace| 否 | false | bool | QQ适配器url输出时替换 | ```bash # gpt配置示例 @@ -126,6 +127,7 @@ gpt_session='[ ]' gpt_proxy='http://127.0.0.1:8080' +# gpt_proxy='http://username:password@127.0.0.1:8080' arkose_status=false @@ -153,8 +155,10 @@ gpt_ban_str='[ gpt_manage_ids=['qq group id......'] # onebot适配器 拉格兰md消息兼容 gpt_lgr_markdown=false -# 使用httpx(暂不完善) +# 使用httpx(暂不完善,请关闭) gpt_httpx=false +# 开启QQ适配器url替换 +gpt_url_replace=true # 插件需要一些其他的Nonebot基础配置,请检查是否存在 # 机器人名 @@ -224,6 +228,12 @@ C:\Users\UserName\AppData\Local\nonebot2\nonebot_plugin_gpt\\{bot_name\} ``` ### 更新日志 +2024.07.11 0.0.33 +1. 添加QQ适配器 Url 输出替换 +2. 优化登录流程 +3. 优化消息超时问题 + + 2024.06.23 0.0.32 1. 修复多账户下相关命令换号发送的情况 2. 优化了登录部分 diff --git a/nonebot_plugin_gpt/api.py b/nonebot_plugin_gpt/api.py index d86cfa3..d10f7f7 100644 --- a/nonebot_plugin_gpt/api.py +++ b/nonebot_plugin_gpt/api.py @@ -202,7 +202,9 @@ async def chat_msg(event: MessageEvent|QQMessageEvent,chatbot: chatgpt,text: Mes elif send_md_status and isinstance(event,QQMessageEvent): #TODO QQ适配器 md模板等兼容发送,待续 pass - + if config_gpt.gpt_url_replace and isinstance(event,QQMessageEvent): + data.msg_recv = replace_dot_in_domain(data.msg_recv) + await matcher.finish(replace_name(data).msg_recv) @@ -223,6 +225,8 @@ async def reset_history(event: MessageEvent|QQMessageEvent,chatbot: chatgpt,text data = await chatbot.back_init_personality(data) if isinstance(event,GroupMessageEvent): data = await group_handle(data,await tools.get_group_member_list(event.group_id)) + if config_gpt.gpt_url_replace and isinstance(event,QQMessageEvent): + data.msg_recv = replace_dot_in_domain(data.msg_recv) await matcher.finish(replace_name(data).msg_recv) async def back_last(event: MessageEvent|QQMessageEvent,chatbot: chatgpt,text:Message|QQMessage = EventMessage()): @@ -243,6 +247,8 @@ async def back_last(event: MessageEvent|QQMessageEvent,chatbot: chatgpt,text:Mes data = await chatbot.back_chat_from_input(data) if isinstance(event,GroupMessageEvent): data = await group_handle(data,await tools.get_group_member_list(event.group_id)) + if config_gpt.gpt_url_replace and isinstance(event,QQMessageEvent): + data.msg_recv = replace_dot_in_domain(data.msg_recv) await matcher.finish(replace_name(data).msg_recv) async def back_anywhere(event: MessageEvent|QQMessageEvent,chatbot:chatgpt,arg: Message|QQMessage): @@ -263,6 +269,8 @@ async def back_anywhere(event: MessageEvent|QQMessageEvent,chatbot:chatgpt,arg: data = await chatbot.back_chat_from_input(data) if isinstance(event,GroupMessageEvent): data = await group_handle(data,await tools.get_group_member_list(event.group_id)) + if config_gpt.gpt_url_replace and isinstance(event,QQMessageEvent): + data.msg_recv = replace_dot_in_domain(data.msg_recv) await matcher.finish(replace_name(data).msg_recv) async def init_gpt(event: MessageEvent|QQMessageEvent,chatbot:chatgpt,arg :Message|QQMessage): @@ -313,6 +321,8 @@ async def init_gpt(event: MessageEvent|QQMessageEvent,chatbot:chatgpt,arg :Messa await ban_check(event,matcher,Message(data.msg_recv)) if isinstance(event,QQMessageEvent): + if config_gpt.gpt_url_replace: + data.msg_recv = replace_dot_in_domain(data.msg_recv) await matcher.finish(replace_name(data).msg_recv) else: msg = Message(MessageSegment.node_custom(user_id=event.self_id,nickname=arg.extract_plain_text(),content=Message(replace_name(data).msg_recv))) @@ -529,7 +539,11 @@ async def chatmsg_history(event: MessageEvent|QQMessageEvent,chatbot: chatgpt,te await tools.send_private_forward_msg_by_bots_once(user_id=event.user_id,node_msg=chat_his,bot_id=str(event.self_id)) elif isinstance(event,QQMessageEvent): res = await chatbot.show_chat_history(data) - await matcher.finish('\n'.join(res)) + if config_gpt.gpt_url_replace: + send_msg = replace_dot_in_domain('\n'.join(res)) + else: + send_msg = '\n'.join(res) + await matcher.finish(send_msg) await matcher.finish() @@ -810,4 +824,63 @@ async def plus_all_status(arg: Message|QQMessage): else: await matcher.finish("仅支持 开启/关闭") plusstatus.write_text(json.dumps(plus_status_tmp)) - await matcher.finish(f"全局plus状态 {arg.extract_plain_text()} 完成") \ No newline at end of file + await matcher.finish(f"全局plus状态 {arg.extract_plain_text()} 完成") + + +def replace_dot_in_domain(text: str): + '''替换url过检测''' + # 较为完整的顶级域名列表(截至目前) + tlds = [ + "com", "org", "net", "edu", "gov", "mil", "int", "info", "biz", "name", "museum", "coop", "aero", "pro", "jobs", "mobi", + "travel", "xxx", "asia", "cat", "tel", "post", "ac", "ad", "ae", "af", "ag", "ai", "al", "am", "an", "ao", "aq", "ar", + "as", "at", "au", "aw", "ax", "az", "ba", "bb", "bd", "be", "bf", "bg", "bh", "bi", "bj", "bm", "bn", "bo", "br", "bs", + "bt", "bv", "bw", "by", "bz", "ca", "cc", "cd", "cf", "cg", "ch", "ci", "ck", "cl", "cm", "cn", "co", "cr", "cu", "cv", + "cw", "cx", "cy", "cz", "de", "dj", "dk", "dm", "do", "dz", "ec", "ee", "eg", "er", "es", "et", "eu", "fi", "fj", "fk", + "fm", "fo", "fr", "ga", "gb", "gd", "ge", "gf", "gg", "gh", "gi", "gl", "gm", "gn", "gp", "gq", "gr", "gs", "gt", "gu", + "gw", "gy", "hk", "hm", "hn", "hr", "ht", "hu", "id", "ie", "il", "im", "in", "io", "iq", "ir", "is", "it", "je", "jm", + "jo", "jp", "ke", "kg", "kh", "ki", "km", "kn", "kp", "kr", "kw", "ky", "kz", "la", "lb", "lc", "li", "lk", "lr", "ls", + "lt", "lu", "lv", "ly", "ma", "mc", "md", "me", "mg", "mh", "mk", "ml", "mm", "mn", "mo", "mp", "mq", "mr", "ms", "mt", + "mu", "mv", "mw", "mx", "my", "mz", "na", "nc", "ne", "nf", "ng", "ni", "nl", "no", "np", "nr", "nu", "nz", "om", "pa", + "pe", "pf", "pg", "ph", "pk", "pl", "pm", "pn", "pr", "ps", "pt", "pw", "py", "qa", "re", "ro", "rs", "ru", "rw", "sa", + "sb", "sc", "sd", "se", "sg", "sh", "si", "sj", "sk", "sl", "sm", "sn", "so", "sr", "ss", "st", "su", "sv", "sx", "sy", + "sz", "tc", "td", "tf", "tg", "th", "tj", "tk", "tl", "tm", "tn", "to", "tp", "tr", "tt", "tv", "tw", "tz", "ua", "ug", + "uk", "us", "uy", "uz", "va", "vc", "ve", "vg", "vi", "vn", "vu", "wf", "ws", "ye", "yt", "za", "zm", "zw", "academy", + "accountants", "actor", "adult", "aero", "agency", "airforce", "apartments", "app", "army", "associates", "attorney", + "auction", "audio", "autos", "band", "bar", "bargains", "beer", "best", "bet", "bid", "bike", "bingo", "bio", "biz", + "black", "blog", "blue", "bot", "boutique", "build", "builders", "business", "buzz", "cab", "cafe", "camera", "camp", "capital", + "cards", "care", "career", "careers", "cash", "casino", "catering", "center", "charity", "chat", "cheap", "christmas", + "church", "city", "claims", "cleaning", "clinic", "clothing", "cloud", "club", "coach", "codes", "coffee", "college", + "community", "company", "computer", "condos", "construction", "consulting", "contractors", "cooking", "cool", "coop", + "country", "coupons", "credit", "creditcard", "cricket", "cruises", "dance", "dating", "day", "deals", "degree", + "delivery", "democrat", "dental", "dentist", "desi", "design", "diamonds", "digital", "direct", "directory", "discount", + "dog", "domains", "education", "email", "energy", "engineer", "engineering", "enterprises", "equipment", "estate", + "events", "exchange", "expert", "exposed", "express", "fail", "faith", "family", "fans", "farm", "fashion", "film", + "finance", "financial", "fish", "fishing", "fitness", "flights", "florist", "flowers", "football", "forsale", "foundation", + "fun", "fund", "furniture", "futbol", "fyi", "gallery", "games", "gifts", "gives", "glass", "gmbh", "gold", "golf", + "graphics", "gratis", "green", "gripe", "group", "guide", "guru", "health", "healthcare", "help", "here", "hiphop", + "hockey", "holdings", "holiday", "home", "homes", "horse", "hospital", "host", "house", "how", "industries", "ink", + "institute", "insure", "international", "investments", "jewelry", "jobs", "kitchen", "land", "lawyer", "lease", + "legal", "life", "lighting", "limited", "limo", "link", "live", "loan", "loans", "lol", "love", "ltd", "luxe", "luxury", + "management", "market", "marketing", "mba", "media", "memorial", "moda", "money", "mortgage", "movie", "museum", + "name", "navy", "network", "news", "ninja", "now", "online", "ooo", "page", "partners", "parts", "party", "pet", + "photo", "photography", "photos", "pics", "pictures", "pink", "pizza", "place", "plumbing", "plus", "poker", "press", + "productions", "properties", "property", "pub", "recipes", "red", "rehab", "reise", "reviews", "rip", "rocks", "run", + "sale", "salon", "school", "schule", "services", "shoes", "show", "singles", "site", "soccer", "social", "software", + "solar", "solutions", "space", "studio", "style", "sucks", "supplies", "supply", "support", "surgery", "systems", + "tattoo", "tax", "taxi", "team", "tech", "technology", "tennis", "theater", "tips", "tires", "today", "tools", "top", + "tours", "town", "toys", "trade", "training", "travel", "university", "vacations", "vet", "viajes", "video", "villas", + "vin", "vision", "vodka", "voyage", "watch", "webcam", "website", "wedding", "wiki", "win", "wine", "work", "works", + "world", "wtf", "zone" + ] + + # 将顶级域名列表转换为正则表达式 + tlds_pattern = '|'.join(tlds) + # 正则表达式匹配网址,包括不含 http/https 前缀的情况 + url_pattern = re.compile( + fr'\b((?:https?://)?(?:[a-zA-Z0-9-]+\.)+(?:{tlds_pattern})(?:/[^\s]*)?)\b' + ) + + def replace_dot(match): + return match.group(0).replace('.', '。') + # 使用正则表达式进行替换 + return url_pattern.sub(replace_dot, text) \ No newline at end of file diff --git a/nonebot_plugin_gpt/config.py b/nonebot_plugin_gpt/config.py index 1755839..8bc0d85 100644 --- a/nonebot_plugin_gpt/config.py +++ b/nonebot_plugin_gpt/config.py @@ -22,6 +22,7 @@ class Config(BaseModel): gpt_manage_ids: list = [] gpt_lgr_markdown: bool = False gpt_httpx: bool = False + gpt_url_replace: bool = False @validator("gpt_manage_ids", always=True, pre=True) def check_gpt_manage_ids(cls,v): @@ -171,7 +172,16 @@ def check_gpt_httpx(cls,v): logger.success("已开启 gpt_httpx httpx使用") else: logger.success("已关闭 gpt_httpx httpx使用") - return v - + return v + + @validator("gpt_url_replace", always=True, pre=True) + def check_gpt_url_replace(cls,v): + if isinstance(v,bool): + if v: + logger.success("已开启 gpt_url_replace QQ适配器url输出检测替换") + else: + logger.success("已关闭 gpt_url_replace QQ适配器url输出检测替换") + return v + config_gpt = get_plugin_config(Config) config_nb = get_driver().config \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 4192173..9b899ca 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,12 +1,12 @@ [project] name = "nonebot-plugin-gpt" -version = "0.0.32" +version = "0.0.33" description = "Nonebot2's plugin of ChatGPT " authors = [ {name = "nek0us", email = "nekouss@mail.com"}, ] license = {text = "GPL3"} -dependencies = ["ChatGPTWeb>=0.2.34","nonebot_adapter_onebot>=2.3.1","nonebot-plugin-sendmsg-by-bots>=0.1.6","nonebot_adapter_qq>=1.3.5","nonebot2>=2.0.0","more_itertools","nonebot_plugin_htmlrender","nonebot_plugin_localstore"] +dependencies = ["ChatGPTWeb>=0.2.36","nonebot_adapter_onebot>=2.3.1","nonebot-plugin-sendmsg-by-bots>=0.1.6","nonebot_adapter_qq>=1.3.5","nonebot2>=2.0.0","more_itertools","nonebot_plugin_htmlrender","nonebot_plugin_localstore"] requires-python = ">=3.10" readme = "README.md"