diff --git a/README.md b/README.md index f5fee1a..0884d2f 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,14 @@ +
+ +[![CI/CD](https://github.com/Cassius0924/WeChatter/actions/workflows/test.yml/badge.svg)](https://github.com/Cassius0924/WeChatter/actions/workflows/test.yml) +[![GitHub Release](https://img.shields.io/github/v/release/Cassius0924/WeChatter)](https://github.com/Cassius0924/WeChatter/releases) +[![GitHub License](https://img.shields.io/github/license/Cassius0924/WeChatter)](https://github.com/Cassius0924/WeChatter/blob/master/LICENSE) + +
+ ## 介绍 基于 [wechatbot-webhook](https://github.com/danni-cool/wechatbot-webhook) 的微信机器人💬,支持 GPT 问答、热搜、天气预报、消息转发、Webhook提醒等功能。 @@ -123,7 +131,7 @@ python3 main.py | 配置项 | 解释 | 备注 | | --- | --- | --- | -| `wechatter_port` | WeChattter服务器的端口,接受消息的端口 | 默认为 `4000`,需和 `wxbotwebhook` Docker 的 `RECV_MSG_API` 参数的端口一致 | +| `wechatter_port` | WeChatter服务器的端口,接受消息的端口 | 默认为 `4000`,需和 `wxbotwebhook` Docker 的 `RECV_MSG_API` 参数的端口一致 | ### ⚙️ WxBotWebhook 配置 diff --git a/main.py b/main.py index 06636ad..18c991e 100644 --- a/main.py +++ b/main.py @@ -1,4 +1,4 @@ -# 项目启动文件 +# WeChatter 启动文件 import uvicorn from loguru import logger diff --git a/requirements.txt b/requirements.txt index 76011cc..84470b1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,3 +10,4 @@ bs4~=0.0.1 apscheduler==3.10.4 pre-commit==3.5.0 loguru==0.7.2 +tenacity==8.2.3 diff --git a/wechatter/commands/_commands/bili_hot.py b/wechatter/commands/_commands/bili_hot.py index 2ec01e7..b03fea1 100644 --- a/wechatter/commands/_commands/bili_hot.py +++ b/wechatter/commands/_commands/bili_hot.py @@ -9,7 +9,9 @@ @command( - command="bili-hot", keys=["b站热搜", "bili-hot"], desc="获取b站热搜。", value=20 + command="bili-hot", + keys=["b站热搜", "bili-hot"], + desc="获取b站热搜。", ) def bili_hot_command_handler(to: SendTo, message: str = "") -> None: try: @@ -23,7 +25,9 @@ def bili_hot_command_handler(to: SendTo, message: str = "") -> None: def get_bili_hot_str() -> str: - response = get_request_json(url="https://app.bilibili.com/x/v2/search/trending/ranking") + response = get_request_json( + url="https://app.bilibili.com/x/v2/search/trending/ranking" + ) hot_list = _extract_bili_hot_data(response) return _generate_bili_hot_message(hot_list) diff --git a/wechatter/commands/_commands/copilot_gpt4.py b/wechatter/commands/_commands/copilot_gpt4.py index f8680fd..38f2273 100644 --- a/wechatter/commands/_commands/copilot_gpt4.py +++ b/wechatter/commands/_commands/copilot_gpt4.py @@ -17,7 +17,11 @@ DEFAULT_CONVERSATIONS = [{"role": "system", "content": "你是一位乐于助人的助手"}] -@command(command="gpt35", keys=["gpt"], desc="使用GPT3.5进行对话。", value=30) +@command( + command="gpt35", + keys=["gpt"], + desc="使用GPT3.5进行对话。", +) def gpt35_command_handler(to: SendTo, message: str = "") -> None: _gptx("gpt-3.5-turbo", to, message) @@ -26,7 +30,6 @@ def gpt35_command_handler(to: SendTo, message: str = "") -> None: command="gpt35-chats", keys=["gpt-chats", "gpt对话记录"], desc="列出GPT3.5对话记录。", - value=31, ) def gpt35_chats_command_handler(to: SendTo, message: str = "") -> None: _gptx_chats("gpt-3.5-turbo", to, message) @@ -36,7 +39,6 @@ def gpt35_chats_command_handler(to: SendTo, message: str = "") -> None: command="gpt35-record", keys=["gpt-record", "gpt记录"], desc="获取GPT3.5对话记录。", - value=32, ) def gpt35_record_command_handler(to: SendTo, message: str = "") -> None: _gptx_record("gpt-3.5-turbo", to, message) @@ -46,13 +48,16 @@ def gpt35_record_command_handler(to: SendTo, message: str = "") -> None: command="gpt35-continue", keys=["gpt-continue", "gpt继续"], desc="继续GPT3.5对话。", - value=33, ) def gpt35_continue_command_handler(to: SendTo, message: str = "") -> None: _gptx_continue("gpt-3.5-turbo", to, message) -@command(command="gpt4", keys=["gpt4"], desc="使用GPT4进行对话。", value=40) +@command( + command="gpt4", + keys=["gpt4"], + desc="使用GPT4进行对话。", +) def gpt4_command_handler(to: SendTo, message: str = "") -> None: _gptx("gpt-4", to, message) @@ -61,7 +66,6 @@ def gpt4_command_handler(to: SendTo, message: str = "") -> None: command="gpt4-chats", keys=["gpt4-chats", "gpt4对话记录"], desc="列出GPT4对话记录。", - value=41, ) def gpt4_chats_command_handler(to: SendTo, message: str = "") -> None: _gptx_chats("gpt-4", to, message) @@ -71,7 +75,6 @@ def gpt4_chats_command_handler(to: SendTo, message: str = "") -> None: command="gpt4-record", keys=["gpt4-record", "gpt4记录"], desc="获取GPT4对话记录。", - value=42, ) def gpt4_record_command_handler(to: SendTo, message: str = "") -> None: _gptx_record("gpt-4", to, message) @@ -81,7 +84,6 @@ def gpt4_record_command_handler(to: SendTo, message: str = "") -> None: command="gpt4-continue", keys=["gpt4-continue", "gpt4继续"], desc="继续GPT4对话。", - value=43, ) def gpt4_continue_command_handler(to: SendTo, message: str = "") -> None: _gptx_continue("gpt-4", to, message) diff --git a/wechatter/commands/_commands/douyin_hot.py b/wechatter/commands/_commands/douyin_hot.py index d0c41af..08e2cdf 100644 --- a/wechatter/commands/_commands/douyin_hot.py +++ b/wechatter/commands/_commands/douyin_hot.py @@ -12,7 +12,6 @@ command="douyin-hot", keys=["抖音热搜", "douyin-hot"], desc="获取抖音热搜。", - value=50, ) def douyin_hot_command_handler(to: SendTo, message: str = "") -> None: try: @@ -24,6 +23,7 @@ def douyin_hot_command_handler(to: SendTo, message: str = "") -> None: else: Sender.send_msg(to, SendMessage(SendMessageType.TEXT, result)) + def get_douyin_hot_str() -> str: r_json = get_request_json( url="https://www.iesdouyin.com/web/api/v2/hotsearch/billboard/word/" @@ -31,6 +31,7 @@ def get_douyin_hot_str() -> str: hot_list = _extract_douyin_hot_data(r_json) return _generate_douyin_hot_message(hot_list) + def _extract_douyin_hot_data(r_json: Dict) -> List: try: hot_list = r_json["word_list"] @@ -48,4 +49,4 @@ def _generate_douyin_hot_message(hot_list: List) -> str: for i, hot_search in enumerate(hot_list[:20]): hot_str += f"{i + 1}. {hot_search.get('word')}\n" - return hot_str \ No newline at end of file + return hot_str diff --git a/wechatter/commands/_commands/food_calories.py b/wechatter/commands/_commands/food_calories.py index 2caf6cc..767bf2d 100644 --- a/wechatter/commands/_commands/food_calories.py +++ b/wechatter/commands/_commands/food_calories.py @@ -1,21 +1,20 @@ -from typing import List, Dict +from typing import Dict, List from urllib.parse import quote import requests from bs4 import BeautifulSoup from wechatter.commands.handlers import command +from wechatter.exceptions import Bs4ParsingError from wechatter.models.message import SendMessage, SendMessageType, SendTo from wechatter.sender import Sender from wechatter.utils import get_request -from wechatter.exceptions import Bs4ParsingError @command( command="food-calories", keys=["食物热量", "food-calories", "热量", "calories", "卡路里"], desc="获取食物热量。", - value=150, ) def food_calories_command_handler(to: SendTo, message: str = "") -> None: try: diff --git a/wechatter/commands/_commands/github_trending.py b/wechatter/commands/_commands/github_trending.py index aa4c314..1dd3aed 100644 --- a/wechatter/commands/_commands/github_trending.py +++ b/wechatter/commands/_commands/github_trending.py @@ -15,7 +15,6 @@ command="github-trending", keys=["GitHub趋势", "github-trending"], desc="获取GitHub趋势。", - value=60, ) def github_trending_command_handler(to: SendTo, message: str = "") -> None: try: diff --git a/wechatter/commands/_commands/help.py b/wechatter/commands/_commands/help.py index 7343ff5..293db6c 100644 --- a/wechatter/commands/_commands/help.py +++ b/wechatter/commands/_commands/help.py @@ -6,7 +6,7 @@ from wechatter.utils.text_to_image import text_to_image -@command(command="help", keys=["帮助", "help"], desc="获取帮助信息。", value=10) +@command(command="help", keys=["帮助", "help"], desc="获取帮助信息。") def help_command_handler(to: SendTo, message: str = "") -> None: # # 获取帮助信息(文本) # from command.help import get_help_msg @@ -23,7 +23,7 @@ def help_command_handler(to: SendTo, message: str = "") -> None: def get_help_msg() -> str: help_msg = "=====帮助信息=====\n" for value in commands.values(): - if value["value"] == 0: + if value == "None": continue cmd_msg = "" for key in value["keys"]: diff --git a/wechatter/commands/_commands/pai_post.py b/wechatter/commands/_commands/pai_post.py index ebe382d..f5385f6 100644 --- a/wechatter/commands/_commands/pai_post.py +++ b/wechatter/commands/_commands/pai_post.py @@ -15,7 +15,6 @@ command="pai-post", keys=["派早报", "pai-post"], desc="获取少数派早报。", - value=70, ) def pai_post_command_handler(to: SendTo, message: str = "") -> None: try: diff --git a/wechatter/commands/_commands/people_daily.py b/wechatter/commands/_commands/people_daily.py index b2c9cf6..1aae93b 100644 --- a/wechatter/commands/_commands/people_daily.py +++ b/wechatter/commands/_commands/people_daily.py @@ -10,7 +10,6 @@ command="people", keys=["人民日报", "people", "people-daily"], desc="获取人民日报。", - value=80, ) def people_daily_command_handler(to: SendTo, message: str = "") -> None: """发送人民日报url""" @@ -39,7 +38,6 @@ def people_daily_command_handler(to: SendTo, message: str = "") -> None: command="people-url", keys=["人民日报链接", "people-url", "people-daily-url"], desc="获取人民日报url。", - value=81, ) def people_daily_url_command_handler(to: SendTo, message: str = "") -> None: """发送人民日报url""" diff --git a/wechatter/commands/_commands/qrcode.py b/wechatter/commands/_commands/qrcode.py index 2969af7..fd79134 100644 --- a/wechatter/commands/_commands/qrcode.py +++ b/wechatter/commands/_commands/qrcode.py @@ -14,7 +14,6 @@ command="qrcode", keys=["二维码", "qrcode"], desc="将文本或链接转换为二维码。", - value=90, ) def qrcode_command_handler(to: SendTo, message: str = "") -> None: # 获取二维码 diff --git a/wechatter/commands/_commands/today_in_history.py b/wechatter/commands/_commands/today_in_history.py index dc1757f..b54f162 100644 --- a/wechatter/commands/_commands/today_in_history.py +++ b/wechatter/commands/_commands/today_in_history.py @@ -12,7 +12,6 @@ command="today-in-history", keys=["历史上的今天", "today-in-history", "t-i-h"], desc="获取历史上的今天。", - value=100, ) def today_in_history_command_handler(to: SendTo, message: str = "") -> None: # 获取历史上的今天 diff --git a/wechatter/commands/_commands/todo.py b/wechatter/commands/_commands/todo.py index 1362c22..2fe02b2 100644 --- a/wechatter/commands/_commands/todo.py +++ b/wechatter/commands/_commands/todo.py @@ -16,7 +16,6 @@ command="todo", keys=["待办事项", "待办", "todo"], desc="获取待办事项。", - value=110, ) def todo_command_handler(to: SendTo, message: str = "") -> None: # 判断是查询还是添加 @@ -40,7 +39,6 @@ def todo_command_handler(to: SendTo, message: str = "") -> None: command="remove-todo", keys=["删除待办事项", "remove-todo", "rmtd"], desc="删除待办事项。", - value=111, ) def remove_todo_command_handler(to: SendTo, message: str = "") -> None: indices = [ diff --git a/wechatter/commands/_commands/translate.py b/wechatter/commands/_commands/translate.py index 1b6981d..9d6d84e 100644 --- a/wechatter/commands/_commands/translate.py +++ b/wechatter/commands/_commands/translate.py @@ -15,7 +15,6 @@ command="word", keys=["word", "单词"], desc="翻译单词或短语。", - value=120, ) def word_command_handler(to: SendTo, message: str = "") -> None: from_lang = _detect_lang(message) @@ -79,6 +78,7 @@ def word_command_handler(to: SendTo, message: str = "") -> None: # fmt: on + # 获取翻译字符串 def get_reverso_context_tran_str(content: str, from_lang: str, to_lang: str) -> str: if not _check_lang_support(from_lang, to_lang): @@ -110,7 +110,9 @@ def get_reverso_context_tran_str(content: str, from_lang: str, to_lang: str) -> else: logger.info(f"不支持的语言音译:{from_lang}") - message = _generate_translate_message(content, from_lang, to_lang, word_list, transliteration) + message = _generate_translate_message( + content, from_lang, to_lang, word_list, transliteration + ) return message @@ -123,10 +125,11 @@ def _extract_transliteration_data(r_json: Dict) -> str: return transliteration -def _generate_translate_message(content: str, from_lang: str, to_lang: str, word_list: List, - transliteration: str) -> str: +def _generate_translate_message( + content: str, from_lang: str, to_lang: str, word_list: List, transliteration: str +) -> str: tran_direction_msg = ( - LANG_EMOJI_DICT.get(from_lang, "") + "->" + LANG_EMOJI_DICT.get(to_lang, "") + LANG_EMOJI_DICT.get(from_lang, "") + "->" + LANG_EMOJI_DICT.get(to_lang, "") ) msg = f'({tran_direction_msg}) "{content}" 翻译:\n' if transliteration != "": diff --git a/wechatter/commands/_commands/weather.py b/wechatter/commands/_commands/weather.py index 8480fc7..82efbbd 100644 --- a/wechatter/commands/_commands/weather.py +++ b/wechatter/commands/_commands/weather.py @@ -18,7 +18,6 @@ command="weather", keys=["weather", "天气", "天气预报", "几度"], desc="获取天气预报", - value=160, ) def weather_command_handler(to: SendTo, message: str = "") -> None: try: diff --git a/wechatter/commands/_commands/weibo_hot.py b/wechatter/commands/_commands/weibo_hot.py index dd4e9cb..6cc29fc 100644 --- a/wechatter/commands/_commands/weibo_hot.py +++ b/wechatter/commands/_commands/weibo_hot.py @@ -7,11 +7,11 @@ from wechatter.sender import Sender from wechatter.utils import get_request_json + @command( command="weibo-hot", keys=["微博热搜", "weibo-hot"], desc="获取微博热搜。", - value=130, ) def weibo_hot_command_handler(to: SendTo, message: str = "") -> None: try: @@ -23,6 +23,7 @@ def weibo_hot_command_handler(to: SendTo, message: str = "") -> None: else: Sender.send_msg(to, SendMessage(SendMessageType.TEXT, result)) + def get_weibo_hot_str() -> str: r_json = get_request_json( url="https://m.weibo.cn/api/container/getIndex?containerid=106003%26filter_type%3Drealtimehot" @@ -30,6 +31,7 @@ def get_weibo_hot_str() -> str: hot_list = _extract_weibo_hot_data(r_json) return _generate_weibo_hot_message(hot_list) + def _extract_weibo_hot_data(r_json: Dict) -> List: try: hot_list = r_json["data"]["cards"][0]["card_group"][:20] diff --git a/wechatter/commands/_commands/zhihu_hot.py b/wechatter/commands/_commands/zhihu_hot.py index b2513ef..9876739 100644 --- a/wechatter/commands/_commands/zhihu_hot.py +++ b/wechatter/commands/_commands/zhihu_hot.py @@ -1,4 +1,5 @@ from typing import Dict, List + from loguru import logger from wechatter.commands.handlers import command @@ -11,7 +12,6 @@ command="zhihu-hot", keys=["知乎热搜", "zhihu-hot"], desc="获取知乎热搜。", - value=140, ) def zhihu_hot_command_handler(to: SendTo, message: str = "") -> None: try: diff --git a/wechatter/commands/handlers.py b/wechatter/commands/handlers.py index d13a813..b1559f3 100644 --- a/wechatter/commands/handlers.py +++ b/wechatter/commands/handlers.py @@ -6,13 +6,12 @@ """ -def command(command: str, keys: List[str], desc: str, value: int): +def command(command: str, keys: List[str], desc: str): """ 注册命令 :param command: 命令 :param keys: 命令关键词列表 :param desc: 命令描述 - :param value: 命令值 :return: 装饰器 """ @@ -20,7 +19,6 @@ def decorator(func): commands[command] = {} commands[command]["keys"] = keys commands[command]["desc"] = desc - commands[command]["value"] = value commands[command]["handler"] = func return func diff --git a/wechatter/init_logger.py b/wechatter/init_logger.py index 2f7b5ff..997776a 100644 --- a/wechatter/init_logger.py +++ b/wechatter/init_logger.py @@ -7,7 +7,8 @@ from wechatter.utils.path_manager import get_abs_path # 使用环境变量中的 LOG_LEVEL -LOG_LEVEL = logging.getLevelName(os.environ.get("LOG_LEVEL", "INFO")) +LOG_LEVEL_NAME = os.environ.get("LOG_LEVEL", "INFO") +LOG_LEVEL = logging.getLevelName(LOG_LEVEL_NAME) LOGURU_FORMAT = ( "{time:YYYY-MM-DD HH:mm:ss} | " @@ -54,6 +55,7 @@ def init_logger(): { "sink": sys.stdout, "format": LOGURU_FORMAT, + "level": LOG_LEVEL_NAME, } ], ) diff --git a/wechatter/message/message_parser.py b/wechatter/message/message_parser.py index ede4875..eebc03a 100644 --- a/wechatter/message/message_parser.py +++ b/wechatter/message/message_parser.py @@ -57,7 +57,6 @@ def parse_command(self, content: str, is_mentioned: bool, is_group: bool) -> dic cmd_dict = { "command": "None", "desc": "", - "value": 0, "arg": "", "handler": None, } @@ -75,7 +74,6 @@ def parse_command(self, content: str, is_mentioned: bool, is_group: bool) -> dic if no_prefix.lower() in info["keys"]: cmd_dict["command"] = command cmd_dict["desc"] = info["desc"] - cmd_dict["value"] = info["value"] cmd_dict["handler"] = info["handler"] if len(cont_list) == 2: cmd_dict["arg"] = cont_list[1] # 消息内容 diff --git a/wechatter/sender/sender.py b/wechatter/sender/sender.py index 9efb088..e29e836 100644 --- a/wechatter/sender/sender.py +++ b/wechatter/sender/sender.py @@ -1,9 +1,8 @@ import json -import time -from collections.abc import Callable from typing import List import requests +import tenacity from loguru import logger import wechatter.config as config @@ -13,26 +12,63 @@ SendMessageType, SendTo, ) +from wechatter.utils import post_request -def _check(response: requests.Response) -> bool: +# 对retry装饰器重新包装,增加日志输出 +def _retry( + stop=tenacity.stop_after_attempt(3), + retry_error_log_level="ERROR", +): + def wrapper(func): + @tenacity.retry(stop=stop) + def wrapped_func(*args, **kwargs): + try: + return func(*args, **kwargs) + except Exception as e: + logger.log( + retry_error_log_level, + f"重试 {func.__name__} 失败,错误信息:{str(e)}", + ) + raise + + return wrapped_func + + return wrapper + + +@_retry() +def _post_request( + url, data=None, json=None, files=None, headers=None, timeout=5 +) -> requests.Response: + return post_request( + url, data=data, json=json, files=files, headers=headers, timeout=timeout + ) + + +def _log(response: requests.Response) -> bool: """检查发送状态""" - if response.status_code != 200: - logger.error(f"发送消息失败,状态码:{response.status_code}") - return False - result = response.json() + # if response.status_code != 200: + # logger.error(f"发送消息失败,状态码:{response.status_code}") + # return False + r_json = response.json() # 即使code为200,也需要检查success字段 - task = result.get("task", None) + task = r_json.get("task", None) if task is not None: - if not result["success"] or not task["successCount"] == task["totalCount"]: - logger.error(f"发送消息失败,错误信息:{result['message']}") + if not r_json["success"] or not task["successCount"] == task["totalCount"]: + logger.error(f"发送消息失败,错误信息:{r_json['message']}") return False # 部分成功 if task["successCount"] > 0 and task["successCount"] < task["totalCount"]: logger.warning(f"发送消息部分成功,成功数:{task['successCount']}") return True - data = json.loads(response.request.body.decode("utf-8")) + try: + data = json.loads(response.request.body.decode("utf-8")) + except UnicodeDecodeError: + # 本地文件发送无法解码 + logger.info("发送图片成功") + return True if isinstance(data, list): for item in data: logger.info( @@ -43,13 +79,13 @@ def _check(response: requests.Response) -> bool: return True -def _retry(times: int, func: Callable) -> bool: - """重试函数""" - for _ in range(times): - time.sleep(0.5) - if func(): - return True - return False +# def _retry(times: int, func: Callable) -> bool: +# """重试函数""" +# for _ in range(times): +# time.sleep(0.5) +# if func(): +# return True +# return False class Sender: @@ -101,10 +137,7 @@ def send_msg_p(to_p_name: str, message: SendMessage) -> bool: "isRoom": False, "data": {"type": message.type, "content": message.content}, } - # 判断是否发送成功,如果失败则重试,最多重试 3 次 - return _retry( - 3, lambda: _check(requests.post(Sender.url, headers=headers, json=data)) - ) + _log(_post_request(Sender.url, headers=headers, json=data)) @staticmethod def send_msg_g(to_g_name: str, message: SendMessage) -> bool: @@ -115,10 +148,7 @@ def send_msg_g(to_g_name: str, message: SendMessage) -> bool: "isRoom": True, "data": {"type": message.type, "content": message.content}, } - # 判断是否发送成功,如果失败则重试,最多重试 3 次 - return _retry( - 3, lambda: _check(requests.post(Sender.url, headers=headers, json=data)) - ) + _log(post_request(Sender.url, headers=headers, json=data)) # 给同一个对象发送多条消息 """ @@ -154,9 +184,7 @@ def send_msgs_p(to_p_name: str, messages: SendMessageList) -> bool: for message in messages.messages: msg = {"type": message.type, "content": message.content} data["data"].append(msg) - return _retry( - 3, lambda: _check(requests.post(Sender.url, headers=headers, json=data)) - ) + _log(post_request(Sender.url, headers=headers, json=data)) # 给同一个群组发送多条消息 @staticmethod @@ -166,9 +194,7 @@ def send_msgs_g(to_g_name: str, messages: SendMessageList) -> bool: for message in messages.messages: msg = {"type": message.type, "content": message.content} data["data"].append(msg) - return _retry( - 3, lambda: _check(requests.post(Sender.url, headers=headers, json=data)) - ) + _log(post_request(Sender.url, headers=headers, json=data)) # 给多个人发送一条消息(群发) """ @@ -204,9 +230,7 @@ def send_msg_ps(to_p_names: List[str], message: SendMessage) -> bool: "data": {"type": message.type, "content": message.content}, } data.append(msg) - return _retry( - 3, lambda: _check(requests.post(Sender.url, headers=headers, json=data)) - ) + _log(post_request(Sender.url, headers=headers, json=data)) @staticmethod def send_msg_gs(to_g_names: List[str], message: SendMessage) -> bool: @@ -222,9 +246,7 @@ def send_msg_gs(to_g_names: List[str], message: SendMessage) -> bool: "data": {"type": message.type, "content": message.content}, } data.append(msg) - return _retry( - 3, lambda: _check(requests.post(Sender.url, headers=headers, json=data)) - ) + _log(post_request(Sender.url, headers=headers, json=data)) # TODO: 给多个人发送多条消息 @@ -249,19 +271,14 @@ def send_localfile_msg_p(to_p_name: str, file_path: str) -> bool: """发送本地文件给个人""" data = {"to": to_p_name, "isRoom": 0} files = {"content": open(file_path, "rb")} - return _retry( - 3, lambda: _check(requests.post(Sender.v1_url, data=data, files=files)) - ) + _log(post_request(Sender.v1_url, data=data, files=files)) @staticmethod def send_localfile_msg_g(to_g_name: str, file_path: str) -> bool: """发送本地文件给群组""" data = {"to": to_g_name, "isRoom": 1} files = {"content": open(file_path, "rb")} - return _retry( - 3, - lambda: _check(requests.post(Sender.v1_url, data=data, files=files)), - ) + _log(post_request(Sender.v1_url, data=data, files=files)) @staticmethod def send_msg_to_admins(message: str) -> None: @@ -331,7 +348,7 @@ def send_msg_to_github_webhook_receivers(message: str) -> None: # url = "http://localhost:3001/webhook/msg" # headers = {"Content-Type": "application/json"} # data = {"to": to_p_name, "type": "text", "content": message} -# requests.post(url, headers=headers, json=data) +# post_request(url, headers=headers, json=data) # @staticmethod # def send_text_msg_g(to_g_name: str, message: str) -> None: @@ -339,7 +356,7 @@ def send_msg_to_github_webhook_receivers(message: str) -> None: # url = "http://localhost:3001/webhook/msg" # headers = {"Content-Type": "application/json"} # data = {"to": to_g_name, "isRoom": True, "type": "text", "content": message} -# requests.post(url, headers=headers, json=data) +# post_request(url, headers=headers, json=data) # # 通过文件URL发送文件 # """ @@ -367,7 +384,7 @@ def send_msg_to_github_webhook_receivers(message: str) -> None: # url = "http://localhost:3001/webhook/msg" # headers = {"Content-Type": "application/json"} # data = {"to": to_p_name, "type": "fileUrl", "content": file_url} -# requests.post(url, headers=headers, json=data) +# post_request(url, headers=headers, json=data) # @staticmethod # def send_urlfile_msg_g(to_g_name: str, file_url: str) -> None: @@ -375,7 +392,7 @@ def send_msg_to_github_webhook_receivers(message: str) -> None: # url = "http://localhost:3001/webhook/msg" # headers = {"Content-Type": "application/json"} # data = {"to": to_g_name, "isRoom": True, "type": "fileUrl", "content": file_url} -# requests.post(url, headers=headers, json=data) +# post_request(url, headers=headers, json=data) # # 本地文件发送 # """ @@ -399,7 +416,7 @@ def send_msg_to_github_webhook_receivers(message: str) -> None: # url = "http://localhost:3001/webhook/msg" # data = {"to": to_p_name, "isRoom": 0} # files = {"content": open(file_path, "rb")} -# requests.post(url, data=data, files=files) +# post_request(url, data=data, files=files) # @staticmethod # def send_localfile_msg_g(to_g_name: str, file_path: str) -> None: @@ -407,4 +424,4 @@ def send_msg_to_github_webhook_receivers(message: str) -> None: # url = "http://localhost:3001/webhook/msg" # data = {"to": to_g_name, "isRoom": 1} # files = {"content": open(file_path, "rb")} -# requests.post(url, data=data, files=files) +# post_request(url, data=data, files=files) diff --git a/wechatter/utils/http_request.py b/wechatter/utils/http_request.py index 4da5ea4..8468964 100644 --- a/wechatter/utils/http_request.py +++ b/wechatter/utils/http_request.py @@ -24,7 +24,6 @@ def get_request( response = requests.get(url, params=params, headers=headers, timeout=timeout) response.encoding = "utf-8" response.raise_for_status() # 如果响应状态码不是 200,就主动抛出异常 - return response except requests.ConnectionError as e: logger.error(f"请求 {url} 失败,连接错误:{e}") raise @@ -43,6 +42,8 @@ def get_request( except Exception as e: logger.error(f"请求 {url} 失败,未知错误:{e}") raise + else: + return response def get_request_json(url, params=None, headers=DEAULT_HEADERS, timeout=5) -> Dict: @@ -63,13 +64,14 @@ def get_request_json(url, params=None, headers=DEAULT_HEADERS, timeout=5) -> Dic def post_request( - url, data=None, json=None, headers=DEAULT_HEADERS, timeout=5 + url, data=None, json=None, files=None, headers=DEAULT_HEADERS, timeout=5 ) -> requests.Response: """ 发送POST请求,并返回Response对象 :param url: 请求的URL :param data: 请求体(默认为None) :param json: 请求体(默认为None) + :param files: 文件(默认为None) :param headers: 请求头(默认为带有User-Agent的请求头) :param timeout: 超时时间(默认为5秒) :return: Response对象 @@ -77,11 +79,9 @@ def post_request( headers = _check_headers(headers) try: response = requests.post( - url, data=data, json=json, headers=headers, timeout=timeout + url, data=data, json=json, files=files, headers=headers, timeout=timeout ) - response.encoding = "utf-8" response.raise_for_status() - return response except requests.ConnectionError as e: logger.error(f"请求 {url} 失败,连接错误:{e}") raise @@ -100,21 +100,27 @@ def post_request( except Exception as e: logger.error(f"请求 {url} 失败,未知错误:{e}") raise + else: + response.encoding = "utf-8" + return response def post_request_json( - url, data=None, json=None, headers=DEAULT_HEADERS, timeout=5 + url, data=None, json=None, files=None, headers=DEAULT_HEADERS, timeout=5 ) -> Dict: """ 发送POST请求,并解析返回的JSON :param url: 请求的URL :param data: 请求体(默认为None) :param json: 请求体(默认为None) + :param files: 文件(默认为None) :param headers: 请求头(默认为带有User-Agent的请求头) :param timeout: 超时时间(默认为5秒) :return: JSON对象 """ - response = post_request(url, data=data, json=json, headers=headers, timeout=timeout) + response = post_request( + url, data=data, json=json, files=None, headers=headers, timeout=timeout + ) try: return response.json() except requests.exceptions.JSONDecodeError as e: