feat(notify): 添加发送到群聊
This commit is contained in:
@@ -3,4 +3,7 @@ UID=
|
|||||||
USER_NO=
|
USER_NO=
|
||||||
SCHOOL_ACCOUNT=
|
SCHOOL_ACCOUNT=
|
||||||
USER_NAME=
|
USER_NAME=
|
||||||
WECHAT_COMANY_BOT_KEY=
|
WECHAT_COMANY_BOT_KEY=
|
||||||
|
WEBHOOK_API_URL=
|
||||||
|
WEBHOOK_GROUP_ID=
|
||||||
|
WEBHOOK_API_TOKEN=
|
||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,3 +1,5 @@
|
|||||||
__pycache__
|
__pycache__
|
||||||
data
|
data
|
||||||
fonts/*.ttf
|
fonts/*.ttf
|
||||||
|
.env
|
||||||
|
.vscode
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
- 安装依赖
|
- 安装依赖
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
pip install aiosqlite apscheduler httpx matplotlib dotenv
|
pip install aiosqlite apscheduler httpx matplotlib dotenv uvicorn
|
||||||
```
|
```
|
||||||
|
|
||||||
- 通过 `scheduler.py` 修改监控时长配置(不懂的请问 AI)
|
- 通过 `scheduler.py` 修改监控时长配置(不懂的请问 AI)
|
||||||
|
|||||||
@@ -17,3 +17,8 @@ USER_NAME = os.getenv("USER_NAME", "张三") # 姓名
|
|||||||
WECHAT_COMANY_BOT_KEY = os.getenv(
|
WECHAT_COMANY_BOT_KEY = os.getenv(
|
||||||
"WECHAT_COMANY_BOT_KEY", "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
|
"WECHAT_COMANY_BOT_KEY", "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Webhook 服务相关配置
|
||||||
|
WEBHOOK_API_URL = os.getenv("WEBHOOK_API_URL", "http://127.0.0.1:8081")
|
||||||
|
WEBHOOK_API_TOKEN = os.getenv("WEBHOOK_API_TOKEN", "xxx")
|
||||||
|
WEBHOOK_GROUP_ID = os.getenv("WEBHOOK_GROUP_ID", "")
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import httpx
|
import httpx
|
||||||
import config
|
import config
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
async def send_image(base64_str: str, md5: str):
|
async def send_image(base64_str: str, md5: str):
|
||||||
@@ -10,3 +11,71 @@ async def send_image(base64_str: str, md5: str):
|
|||||||
async with httpx.AsyncClient(timeout=10) as client:
|
async with httpx.AsyncClient(timeout=10) as client:
|
||||||
resp = await client.post(url, json=payload)
|
resp = await client.post(url, json=payload)
|
||||||
resp.raise_for_status()
|
resp.raise_for_status()
|
||||||
|
|
||||||
|
|
||||||
|
async def upload_file(file_path: str, filename: str = "None") -> str:
|
||||||
|
"""
|
||||||
|
上传文件到 webhook 服务的 /upload 端点
|
||||||
|
|
||||||
|
Args:
|
||||||
|
file_path: 本地文件路径
|
||||||
|
filename: 上传时的文件名,不指定则使用原文件名
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
远程文件路径
|
||||||
|
"""
|
||||||
|
if filename is None:
|
||||||
|
filename = Path(file_path).name
|
||||||
|
|
||||||
|
url = f"{config.WEBHOOK_API_URL}/upload"
|
||||||
|
headers = {"Authorization": f"Bearer {config.WEBHOOK_API_TOKEN}"}
|
||||||
|
|
||||||
|
with open(file_path, "rb") as f:
|
||||||
|
files = {"file": (filename, f)}
|
||||||
|
async with httpx.AsyncClient(timeout=30) as client:
|
||||||
|
resp = await client.post(url, files=files, headers=headers)
|
||||||
|
resp.raise_for_status()
|
||||||
|
data = resp.json()
|
||||||
|
return data.get("path", data.get("files", [None])[0])
|
||||||
|
|
||||||
|
|
||||||
|
async def send_webhook(group_id: str, file_url: str) -> dict:
|
||||||
|
"""
|
||||||
|
发送 webhook 请求通知文件
|
||||||
|
|
||||||
|
Args:
|
||||||
|
group_id: 群组 ID
|
||||||
|
file_url: 远程文件路径
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
API 响应字典
|
||||||
|
"""
|
||||||
|
url = f"{config.WEBHOOK_API_URL}/webhook"
|
||||||
|
headers = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Authorization": f"Bearer {config.WEBHOOK_API_TOKEN}",
|
||||||
|
}
|
||||||
|
|
||||||
|
payload = {"group_id": group_id, "url": file_url, "type": "image"}
|
||||||
|
|
||||||
|
async with httpx.AsyncClient(timeout=10) as client:
|
||||||
|
resp = await client.post(url, json=payload, headers=headers)
|
||||||
|
resp.raise_for_status()
|
||||||
|
return resp.json()
|
||||||
|
|
||||||
|
|
||||||
|
async def upload_and_notify(file_path: str, group_id: str, filename: str = "") -> dict:
|
||||||
|
"""
|
||||||
|
上传文件并发送 webhook 通知(组合函数)
|
||||||
|
|
||||||
|
Args:
|
||||||
|
file_path: 本地文件路径
|
||||||
|
group_id: 群组 ID
|
||||||
|
filename: 上传时的文件名,不指定则使用原文件名
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
API 响应字典
|
||||||
|
"""
|
||||||
|
remote_path = await upload_file(file_path, filename)
|
||||||
|
result = await send_webhook(group_id, remote_path)
|
||||||
|
return result
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import logging
|
|||||||
import base64
|
import base64
|
||||||
import hashlib
|
import hashlib
|
||||||
|
|
||||||
from notify.wechat_company import send_image
|
from notify.wechat_company import send_image, upload_and_notify
|
||||||
from services.render import render_ammeter_chart, render_water_chart
|
from services.render import render_ammeter_chart, render_water_chart
|
||||||
from services import collector
|
from services import collector
|
||||||
import config
|
import config
|
||||||
@@ -122,8 +122,11 @@ class SD:
|
|||||||
ele_img_path = await render_ammeter_chart()
|
ele_img_path = await render_ammeter_chart()
|
||||||
if ele_img_path:
|
if ele_img_path:
|
||||||
logger.info("生成电表图表成功: %s", ele_img_path)
|
logger.info("生成电表图表成功: %s", ele_img_path)
|
||||||
ele_b64, ele_md5 = image_to_base64_md5(ele_img_path)
|
# ele_b64, ele_md5 = image_to_base64_md5(ele_img_path)
|
||||||
await send_image(ele_b64, ele_md5)
|
# await send_image(ele_b64, ele_md5)
|
||||||
|
await upload_and_notify(
|
||||||
|
ele_img_path, config.WEBHOOK_GROUP_ID, ele_img_path.split("/")[-1]
|
||||||
|
)
|
||||||
logger.info("电表图表推送完成")
|
logger.info("电表图表推送完成")
|
||||||
else:
|
else:
|
||||||
logger.warning("未生成电表图表,跳过推送")
|
logger.warning("未生成电表图表,跳过推送")
|
||||||
@@ -131,8 +134,13 @@ class SD:
|
|||||||
water_img_path = await render_water_chart()
|
water_img_path = await render_water_chart()
|
||||||
if water_img_path:
|
if water_img_path:
|
||||||
logger.info("生成水表图表成功: %s", water_img_path)
|
logger.info("生成水表图表成功: %s", water_img_path)
|
||||||
water_b64, water_md5 = image_to_base64_md5(water_img_path)
|
# water_b64, water_md5 = image_to_base64_md5(water_img_path)
|
||||||
await send_image(water_b64, water_md5)
|
# await send_image(water_b64, water_md5)
|
||||||
|
await upload_and_notify(
|
||||||
|
water_img_path,
|
||||||
|
config.WEBHOOK_GROUP_ID,
|
||||||
|
water_img_path.split("/")[-1],
|
||||||
|
)
|
||||||
logger.info("水表图表推送完成")
|
logger.info("水表图表推送完成")
|
||||||
else:
|
else:
|
||||||
logger.warning("未生成水表图表,跳过推送")
|
logger.warning("未生成水表图表,跳过推送")
|
||||||
|
|||||||
Reference in New Issue
Block a user