chenchaoyun commited on
Commit ·
4e99ca3
1
Parent(s): 900d6f9
fix: 飞书通知
Browse files- api_routes.py +109 -11
- config.py +5 -0
api_routes.py
CHANGED
|
@@ -11,6 +11,7 @@ import shutil
|
|
| 11 |
import time
|
| 12 |
import uuid
|
| 13 |
import subprocess
|
|
|
|
| 14 |
from concurrent.futures import ThreadPoolExecutor
|
| 15 |
from datetime import datetime
|
| 16 |
from typing import Any, Dict, List, Optional, Tuple
|
|
@@ -36,16 +37,37 @@ except Exception:
|
|
| 36 |
from fastapi.responses import JSONResponse, FileResponse, HTMLResponse
|
| 37 |
|
| 38 |
import wx_access_token
|
| 39 |
-
from config import
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
from database import (
|
| 50 |
record_image_creation,
|
| 51 |
fetch_paged_image_records,
|
|
@@ -1589,8 +1611,8 @@ async def app_analyze_face(
|
|
| 1589 |
"device_model": request.headers.get("x-device-model"),
|
| 1590 |
"os_version": request.headers.get("x-os-version"),
|
| 1591 |
"app_version": request.headers.get("x-app-version"),
|
| 1592 |
-
"timezone": request.headers.get("x-timezone"),
|
| 1593 |
"region": request.headers.get("x-region"),
|
|
|
|
| 1594 |
"language": request.headers.get("Accept-Language"),
|
| 1595 |
}
|
| 1596 |
# 创建异步任务,不阻塞当前请求
|
|
@@ -1608,6 +1630,82 @@ async def app_analyze_face(
|
|
| 1608 |
)
|
| 1609 |
|
| 1610 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1611 |
@api_router.post("/image_search", response_model=ImageFileList, tags=["图像搜索"])
|
| 1612 |
@log_api_params
|
| 1613 |
async def search_by_image(
|
|
|
|
| 11 |
import time
|
| 12 |
import uuid
|
| 13 |
import subprocess
|
| 14 |
+
import requests
|
| 15 |
from concurrent.futures import ThreadPoolExecutor
|
| 16 |
from datetime import datetime
|
| 17 |
from typing import Any, Dict, List, Optional, Tuple
|
|
|
|
| 37 |
from fastapi.responses import JSONResponse, FileResponse, HTMLResponse
|
| 38 |
|
| 39 |
import wx_access_token
|
| 40 |
+
from config import (
|
| 41 |
+
logger,
|
| 42 |
+
OUTPUT_DIR,
|
| 43 |
+
IMAGES_DIR,
|
| 44 |
+
DEEPFACE_AVAILABLE,
|
| 45 |
+
DLIB_AVAILABLE,
|
| 46 |
+
GFPGAN_AVAILABLE,
|
| 47 |
+
DDCOLOR_AVAILABLE,
|
| 48 |
+
REALESRGAN_AVAILABLE,
|
| 49 |
+
UPSCALE_SIZE,
|
| 50 |
+
CLIP_AVAILABLE,
|
| 51 |
+
REALESRGAN_MODEL,
|
| 52 |
+
REMBG_AVAILABLE,
|
| 53 |
+
ANIME_STYLE_AVAILABLE,
|
| 54 |
+
SAVE_QUALITY,
|
| 55 |
+
AUTO_INIT_ANALYZER,
|
| 56 |
+
AUTO_INIT_GFPGAN,
|
| 57 |
+
AUTO_INIT_DDCOLOR,
|
| 58 |
+
AUTO_INIT_REALESRGAN,
|
| 59 |
+
MODELS_PATH,
|
| 60 |
+
AUTO_INIT_REMBG,
|
| 61 |
+
AUTO_INIT_ANIME_STYLE,
|
| 62 |
+
RVM_AVAILABLE,
|
| 63 |
+
AUTO_INIT_RVM,
|
| 64 |
+
FACE_SCORE_MAX_IMAGES,
|
| 65 |
+
FEMALE_AGE_ADJUSTMENT,
|
| 66 |
+
FEMALE_AGE_ADJUSTMENT_THRESHOLD,
|
| 67 |
+
CELEBRITY_SOURCE_DIR,
|
| 68 |
+
CELEBRITY_FIND_THRESHOLD,
|
| 69 |
+
FEISHU_WEBHOOK_URL,
|
| 70 |
+
)
|
| 71 |
from database import (
|
| 72 |
record_image_creation,
|
| 73 |
fetch_paged_image_records,
|
|
|
|
| 1611 |
"device_model": request.headers.get("x-device-model"),
|
| 1612 |
"os_version": request.headers.get("x-os-version"),
|
| 1613 |
"app_version": request.headers.get("x-app-version"),
|
|
|
|
| 1614 |
"region": request.headers.get("x-region"),
|
| 1615 |
+
"timezone": request.headers.get("x-timezone"),
|
| 1616 |
"language": request.headers.get("Accept-Language"),
|
| 1617 |
}
|
| 1618 |
# 创建异步任务,不阻塞当前请求
|
|
|
|
| 1630 |
)
|
| 1631 |
|
| 1632 |
|
| 1633 |
+
@api_router.post("/send_feishu_notification", tags=["系统通知"])
|
| 1634 |
+
@log_api_params
|
| 1635 |
+
async def send_feishu_notification(
|
| 1636 |
+
request: Request,
|
| 1637 |
+
title: str = Form(..., description="通知标题"),
|
| 1638 |
+
payload: str = Form(None, description="自定义业务数据的JSON字符串"),
|
| 1639 |
+
):
|
| 1640 |
+
"""
|
| 1641 |
+
发送飞书消息通知,集成设备信息与自定义内容。
|
| 1642 |
+
"""
|
| 1643 |
+
# 提取设备信息
|
| 1644 |
+
device_info = {
|
| 1645 |
+
"device_id": request.headers.get("x-device-id"),
|
| 1646 |
+
"device_type": request.headers.get("x-device-type"),
|
| 1647 |
+
"device_model": request.headers.get("x-device-model"),
|
| 1648 |
+
"os_version": request.headers.get("x-os-version"),
|
| 1649 |
+
"app_version": request.headers.get("x-app-version"),
|
| 1650 |
+
"region": request.headers.get("x-region"),
|
| 1651 |
+
}
|
| 1652 |
+
|
| 1653 |
+
# 构造飞书文案
|
| 1654 |
+
time_str = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
| 1655 |
+
text_lines = [f"📢 【{title}】"]
|
| 1656 |
+
text_lines.append(f"⏱️ 时间:{time_str}")
|
| 1657 |
+
|
| 1658 |
+
# 映射表
|
| 1659 |
+
header_mapping = {
|
| 1660 |
+
"device_id": "🆔 设备ID",
|
| 1661 |
+
"device_type": "📱 设备类型",
|
| 1662 |
+
"device_model": "🛠️ 设备型号",
|
| 1663 |
+
"os_version": "💿 系统版本",
|
| 1664 |
+
"app_version": "📦 App版本",
|
| 1665 |
+
"region": "🌍 地区"
|
| 1666 |
+
}
|
| 1667 |
+
|
| 1668 |
+
for key, label in header_mapping.items():
|
| 1669 |
+
val = device_info.get(key)
|
| 1670 |
+
if val:
|
| 1671 |
+
text_lines.append(f"{label}:{val}")
|
| 1672 |
+
|
| 1673 |
+
# 处理自定义 payload
|
| 1674 |
+
if payload:
|
| 1675 |
+
try:
|
| 1676 |
+
extra_data = json.loads(payload)
|
| 1677 |
+
if isinstance(extra_data, dict):
|
| 1678 |
+
for k, v in extra_data.items():
|
| 1679 |
+
text_lines.append(f"🔹 {k}:{v}")
|
| 1680 |
+
else:
|
| 1681 |
+
text_lines.append(f"🔹 内容:{payload}")
|
| 1682 |
+
except json.JSONDecodeError:
|
| 1683 |
+
text_lines.append(f"🔹 内容:{payload}")
|
| 1684 |
+
|
| 1685 |
+
full_text = "\n".join(text_lines)
|
| 1686 |
+
|
| 1687 |
+
# 发送通知(在线程池中执行以防阻塞)
|
| 1688 |
+
def _send():
|
| 1689 |
+
try:
|
| 1690 |
+
if not FEISHU_WEBHOOK_URL:
|
| 1691 |
+
logger.warning("FEISHU_WEBHOOK_URL is not configured, skip sending.")
|
| 1692 |
+
return
|
| 1693 |
+
resp = requests.post(
|
| 1694 |
+
FEISHU_WEBHOOK_URL,
|
| 1695 |
+
json={"msg_type": "text", "content": {"text": full_text}},
|
| 1696 |
+
timeout=10
|
| 1697 |
+
)
|
| 1698 |
+
logger.info(f"Feishu notification sent: {resp.status_code}, {resp.text}")
|
| 1699 |
+
except Exception as exc:
|
| 1700 |
+
logger.warning(f"Failed to send Feishu notification: {exc}")
|
| 1701 |
+
|
| 1702 |
+
# 使用 run_in_executor 避免阻塞
|
| 1703 |
+
loop = asyncio.get_event_loop()
|
| 1704 |
+
loop.run_in_executor(executor, _send)
|
| 1705 |
+
|
| 1706 |
+
return {"success": True, "message": "Notification scheduled"}
|
| 1707 |
+
|
| 1708 |
+
|
| 1709 |
@api_router.post("/image_search", response_model=ImageFileList, tags=["图像搜索"])
|
| 1710 |
@log_api_params
|
| 1711 |
async def search_by_image(
|
config.py
CHANGED
|
@@ -200,6 +200,11 @@ CELEBRITY_FIND_THRESHOLD = float(
|
|
| 200 |
)
|
| 201 |
|
| 202 |
# ---- start ----
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 203 |
# 微信小程序配置(默认值仅用于本地开发)
|
| 204 |
WECHAT_APPID = os.environ.get("WECHAT_APPID", "******").strip()
|
| 205 |
WECHAT_SECRET = os.environ.get("WCT_SECRET", "******").strip()
|
|
|
|
| 200 |
)
|
| 201 |
|
| 202 |
# ---- start ----
|
| 203 |
+
# 飞书 Webhook 配置
|
| 204 |
+
FEISHU_WEBHOOK_URL = os.environ.get(
|
| 205 |
+
"FEISHU_WEBHOOK_URL",
|
| 206 |
+
"https://open.feishu.cn/open-apis/bot/v2/hook/07cfc4b6-4dfd-4b5c-80a4-a66ccba83547"
|
| 207 |
+
).strip()
|
| 208 |
# 微信小程序配置(默认值仅用于本地开发)
|
| 209 |
WECHAT_APPID = os.environ.get("WECHAT_APPID", "******").strip()
|
| 210 |
WECHAT_SECRET = os.environ.get("WCT_SECRET", "******").strip()
|