Files
wxauto_api/services/plugin_notification_service.py
2026-04-07 14:11:45 +08:00

148 lines
5.3 KiB
Python

# ///
# plugin_notification_service.py
# 描述:插件通知服务,支持向配置的地址发送插件告警通知
# 作者:User
# 创建日期:2026-04-07
# ///
import logging
import httpx
from typing import Any, Dict, List, Optional
from datetime import datetime
logger = logging.getLogger("plugin_notification")
class PluginNotificationService:
def __init__(self):
self._notification_url: Optional[str] = None
self._enabled: bool = False
self._webhook_configs: List[Dict[str, Any]] = []
self._plugin_webhook_map: Dict[str, str] = {}
def initialize(self):
from database_service import get_db_service
db_service = get_db_service()
if not db_service:
logger.warning("Database service not available, plugin notification disabled")
return
try:
self._load_notification_config(db_service)
self._load_webhook_configs(db_service)
except Exception as e:
logger.error(f"Failed to initialize plugin notification service: {e}")
def _load_notification_config(self, db_service):
try:
from models import WebhookUrl
webhooks = db_service.get_all_webhooks()
for wh in webhooks:
event_types = getattr(wh, 'event_types', '') or ''
if 'plugin_notification' in event_types or event_types == '*':
self._notification_url = wh.url
self._enabled = wh.enabled
logger.info(f"Plugin notification enabled: {wh.name} - {wh.url}")
break
except Exception as e:
logger.warning(f"Failed to load notification config: {e}")
def _load_webhook_configs(self, db_service):
try:
from models import WebhookUrl
webhooks = db_service.get_all_webhooks()
self._webhook_configs = []
for wh in webhooks:
event_types = getattr(wh, 'event_types', '') or ''
event_types_list = event_types.split(',') if isinstance(event_types, str) else []
self._webhook_configs.append({
'id': wh.id,
'name': wh.name,
'url': wh.url,
'format': getattr(wh, 'format', 'bark'),
'enabled': wh.enabled,
'event_types': event_types_list
})
if 'plugin_notification' in event_types_list or '*' in event_types_list:
self._notification_url = wh.url
self._enabled = wh.enabled
except Exception as e:
logger.warning(f"Failed to load webhook configs: {e}")
def reload_config(self):
self.initialize()
def send_notification(
self,
plugin_name: str,
title: str,
message: str,
level: str = "info"
) -> bool:
logger.info(f"send_notification called: {plugin_name} - {title}, enabled={self._enabled}, url={self._notification_url}")
if not self._enabled or not self._notification_url:
logger.warning(f"Plugin notification disabled or no URL: enabled={self._enabled}, url={self._notification_url}")
logger.info(f"Available webhook configs: {self._webhook_configs}")
return False
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
content = f"""【{plugin_name} 插件通知】
级别: {level.upper()}
标题: {title}
消息: {message}
时间: {timestamp}"""
payload = {
"title": f"[{level.upper()}] {plugin_name}",
"body": content,
"icon": "https://is3-ssl.mzstatic.com/image/thumb/Purple122/v4/8e/1a/b5/8e1ab5a2-09c7-2c06-ae03-2056b0348d2c/AppIcon-Production-20x20@2x.png/0x0ss.png"
}
for config in self._webhook_configs:
if not config['enabled']:
continue
event_types = config['event_types']
if 'plugin_notification' not in event_types and '*' not in event_types:
continue
try:
url = config['url']
format_type = config.get('format', 'bark')
if format_type == 'wechat':
payload = {
"msgtype": "text",
"text": {
"content": content
}
}
result = self._send_webhook(url, payload)
if result:
logger.info(f"Plugin notification sent: {plugin_name} - {level} -> {config['name']}")
return result
except Exception as e:
logger.error(f"Failed to send plugin notification: {e}")
return False
def _send_webhook(self, url: str, payload: Dict[str, Any]) -> bool:
try:
with httpx.Client(timeout=10) as client:
response = client.post(url, json=payload)
return response.status_code == 200
except Exception as e:
logger.error(f"Webhook request failed: {e}")
return False
def is_enabled(self) -> bool:
return self._enabled
def get_notification_url(self) -> Optional[str]:
return self._notification_url
plugin_notification_service = PluginNotificationService()