mirror of
https://github.com/jxxghp/MoviePilot-Plugins.git
synced 2026-03-27 10:05:57 +00:00
fix BugReporter
This commit is contained in:
@@ -541,11 +541,12 @@
|
||||
"name": "Bug反馈",
|
||||
"description": "自动上报异常,协助开发者发现和解决问题。",
|
||||
"labels": "开发",
|
||||
"version": "1.1",
|
||||
"version": "1.2",
|
||||
"icon": "Alist_encrypt_A.png",
|
||||
"author": "jxxghp",
|
||||
"level": 1,
|
||||
"history": {
|
||||
"v1.2": "优化上报信息量",
|
||||
"v1.1": "加强脱敏处理"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import re
|
||||
import socket
|
||||
import ssl
|
||||
from typing import Any, Dict
|
||||
from typing import List, Tuple
|
||||
from urllib.parse import urlparse, parse_qs, urlencode, urlunparse
|
||||
|
||||
import sentry_sdk
|
||||
from app.plugins import _PluginBase
|
||||
from version import APP_VERSION
|
||||
|
||||
|
||||
class SentrySanitizer:
|
||||
@@ -13,7 +16,9 @@ class SentrySanitizer:
|
||||
"password", "passwd", "pwd",
|
||||
"secret", "token", "access_token", "refresh_token",
|
||||
"authorization", "api_key", "apikey",
|
||||
"cookie", "set-cookie", "passkey"
|
||||
"cookie", "set-cookie", "passkey",
|
||||
"key", "credential", "auth", "login", "user", "username",
|
||||
"email", "phone", "address", "ip", "host", "domain"
|
||||
}
|
||||
|
||||
# 匹配包含敏感关键词的正则
|
||||
@@ -21,6 +26,26 @@ class SentrySanitizer:
|
||||
"|".join(re.escape(key) for key in SENSITIVE_KEYS), re.IGNORECASE
|
||||
)
|
||||
|
||||
# 网络连接错误类异常(不上报)
|
||||
NETWORK_ERRORS = {
|
||||
"ConnectionError", "ConnectionRefusedError", "ConnectionAbortedError",
|
||||
"ConnectionResetError", "TimeoutError", "socket.timeout", "socket.error",
|
||||
"ssl.SSLError", "ssl.SSLCertVerificationError", "ssl.SSLWantReadError",
|
||||
"ssl.SSLWantWriteError", "ssl.SSLZeroReturnError", "ssl.SSLSyscallError",
|
||||
"urllib.error.URLError", "urllib.error.HTTPError", "requests.exceptions.ConnectionError",
|
||||
"requests.exceptions.Timeout", "requests.exceptions.ConnectTimeout",
|
||||
"requests.exceptions.ReadTimeout", "requests.exceptions.SSLError",
|
||||
"aiohttp.ClientConnectionError", "aiohttp.ClientTimeout", "aiohttp.ServerTimeoutError",
|
||||
"aiohttp.ServerDisconnectedError", "aiohttp.ClientOSError"
|
||||
}
|
||||
|
||||
# 网络连接错误关键词
|
||||
NETWORK_ERROR_KEYWORDS = [
|
||||
"connection", "timeout", "network", "dns", "ssl", "certificate",
|
||||
"refused", "reset", "aborted", "unreachable", "no route to host",
|
||||
"name or service not known", "temporary failure", "network is unreachable"
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def scrub_dict(cls, data: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""
|
||||
@@ -59,11 +84,44 @@ class SentrySanitizer:
|
||||
print(str(err))
|
||||
return url
|
||||
|
||||
@classmethod
|
||||
def is_network_error(cls, event) -> bool:
|
||||
"""
|
||||
判断是否为网络连接错误类异常
|
||||
"""
|
||||
# 检查异常类型
|
||||
if "exception" in event:
|
||||
for exc in event["exception"].get("values", []):
|
||||
if "type" in exc:
|
||||
exc_type = exc["type"]
|
||||
if exc_type in cls.NETWORK_ERRORS:
|
||||
return True
|
||||
|
||||
# 检查异常消息是否包含网络错误关键词
|
||||
if "value" in exc:
|
||||
exc_value = exc["value"].lower()
|
||||
for keyword in cls.NETWORK_ERROR_KEYWORDS:
|
||||
if keyword in exc_value:
|
||||
return True
|
||||
|
||||
# 检查日志消息
|
||||
if "message" in event:
|
||||
message = event["message"].lower()
|
||||
for keyword in cls.NETWORK_ERROR_KEYWORDS:
|
||||
if keyword in message:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def before_send(cls, event, hint):
|
||||
"""
|
||||
在发送到 Sentry 之前脱敏
|
||||
在发送到 Sentry 之前脱敏和过滤
|
||||
"""
|
||||
# 如果是网络连接错误,直接返回 None 不上报
|
||||
if cls.is_network_error(event):
|
||||
return None
|
||||
|
||||
# 处理 request 数据
|
||||
request = event.get("request", {})
|
||||
if "url" in request:
|
||||
@@ -88,6 +146,18 @@ class SentrySanitizer:
|
||||
for exc in event["exception"].get("values", []):
|
||||
if "value" in exc and cls.SENSITIVE_PATTERN.search(exc["value"]):
|
||||
exc["value"] = "[Filtered Exception Message]"
|
||||
|
||||
# 清理异常堆栈中的敏感信息
|
||||
if "stacktrace" in exc and "frames" in exc["stacktrace"]:
|
||||
for frame in exc["stacktrace"]["frames"]:
|
||||
if "vars" in frame:
|
||||
frame["vars"] = cls.scrub_dict(frame["vars"])
|
||||
if "context_line" in frame and cls.SENSITIVE_PATTERN.search(frame["context_line"]):
|
||||
frame["context_line"] = "[Filtered]"
|
||||
|
||||
# 清理消息中的敏感信息
|
||||
if "message" in event and cls.SENSITIVE_PATTERN.search(event["message"]):
|
||||
event["message"] = "[Filtered Message]"
|
||||
|
||||
return event
|
||||
|
||||
@@ -100,7 +170,7 @@ class BugReporter(_PluginBase):
|
||||
# 插件图标
|
||||
plugin_icon = "Alist_encrypt_A.png"
|
||||
# 插件版本
|
||||
plugin_version = "1.1"
|
||||
plugin_version = "1.2"
|
||||
# 插件作者
|
||||
plugin_author = "jxxghp"
|
||||
# 作者主页
|
||||
@@ -119,6 +189,7 @@ class BugReporter(_PluginBase):
|
||||
if self._enable:
|
||||
sentry_sdk.init("https://88da01ad33b4423cb0380620de53efa8@glitchtip.movie-pilot.org/1",
|
||||
before_send=SentrySanitizer.before_send,
|
||||
release=APP_VERSION,
|
||||
send_default_pii=False)
|
||||
|
||||
@staticmethod
|
||||
@@ -168,7 +239,7 @@ class BugReporter(_PluginBase):
|
||||
'props': {
|
||||
'type': 'warning',
|
||||
'variant': 'tonal',
|
||||
'text': '注意:开启插件即代表你同意将部分异常信息自动发送给开发者,以帮助改进软件;如果你不希望自动发送任何数据,请关闭或卸载此插件;仅上报系统异常信息,不会包含任何个人隐私信息或敏感数据;异常信息采集为使用开源项目解决方案:GlitchTip。',
|
||||
'text': '注意:开启插件即代表你同意将部分异常信息自动发送给开发者,以帮助改进软件;如果你不希望自动发送任何数据,请关闭或卸载此插件;仅上报系统异常信息,不会包含任何个人隐私信息或敏感数据;网络连接错误类异常不会上报;异常信息采集为使用开源项目解决方案:GlitchTip。',
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user