91 lines
2.3 KiB
TypeScript
91 lines
2.3 KiB
TypeScript
const MAX_ERROR_CAUSE_DEPTH = 3
|
|
|
|
export const EXPECTED_UPSTREAM_MUSIC_ERROR_PATTERNS = [
|
|
'QQ 音乐播放链接解析失败:',
|
|
'返回已知无效音频链接',
|
|
'qq-music-api 未返回歌词',
|
|
'[tx.lyric] qq-music-api 歌词接口失败',
|
|
'The operation was aborted due to timeout',
|
|
'request timed out',
|
|
'timeout exceeded',
|
|
'TimeoutError'
|
|
]
|
|
|
|
type SentryLikeEvent = {
|
|
message?: unknown
|
|
exception?: {
|
|
values?: Array<{
|
|
type?: unknown
|
|
value?: unknown
|
|
}>
|
|
}
|
|
logentry?: {
|
|
message?: unknown
|
|
params?: unknown
|
|
}
|
|
}
|
|
|
|
type SentryLikeHint = {
|
|
originalException?: unknown
|
|
syntheticException?: unknown
|
|
}
|
|
|
|
export const stringifyErrorValue = (
|
|
value: unknown,
|
|
depth = 0,
|
|
seen = new WeakSet<object>()
|
|
): string => {
|
|
if (!value || depth > MAX_ERROR_CAUSE_DEPTH) return ''
|
|
if (typeof value === 'string') return value
|
|
if (typeof value !== 'object') return String(value)
|
|
|
|
if (seen.has(value)) return ''
|
|
seen.add(value)
|
|
|
|
const record = value as Record<string, unknown>
|
|
const errorName = value instanceof Error ? value.name : record.name
|
|
const errorMessage = value instanceof Error ? value.message : record.message
|
|
|
|
return [
|
|
errorName,
|
|
errorMessage,
|
|
record.statusMessage,
|
|
record.statusCode,
|
|
stringifyErrorValue(record.cause, depth + 1, seen)
|
|
]
|
|
.filter((item) => item !== undefined && item !== null && item !== '')
|
|
.map(String)
|
|
.join(' ')
|
|
}
|
|
|
|
export const getSentryEventSearchText = (
|
|
event: SentryLikeEvent,
|
|
hint?: SentryLikeHint
|
|
): string => {
|
|
const exceptionValues = event.exception?.values || []
|
|
const exceptionTexts = exceptionValues.flatMap((value) => [
|
|
value.type,
|
|
value.value
|
|
])
|
|
const logEntry = event.logentry || {}
|
|
|
|
return [
|
|
event.message,
|
|
logEntry.message,
|
|
...(Array.isArray(logEntry.params) ? logEntry.params : []),
|
|
...exceptionTexts,
|
|
stringifyErrorValue(hint?.originalException),
|
|
stringifyErrorValue(hint?.syntheticException)
|
|
]
|
|
.filter((item) => item !== undefined && item !== null && item !== '')
|
|
.map(String)
|
|
.join('\n')
|
|
}
|
|
|
|
export const isExpectedUpstreamMusicError = (text: string): boolean => {
|
|
const normalizedText = text.toLowerCase()
|
|
return EXPECTED_UPSTREAM_MUSIC_ERROR_PATTERNS.some((pattern) =>
|
|
normalizedText.includes(pattern.toLowerCase())
|
|
)
|
|
}
|