-
Notifications
You must be signed in to change notification settings - Fork 50
Expand file tree
/
Copy pathsniffer.js
More file actions
209 lines (175 loc) · 5.71 KB
/
sniffer.js
File metadata and controls
209 lines (175 loc) · 5.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
/**
* 嗅探服务 API
* 用于调用代理嗅探接口进行视频链接嗅探
*/
/**
* 调用嗅探接口
* @param {string|Object} urlOrParseData - 要嗅探的页面URL或T4解析数据
* @param {Object} options - 嗅探选项
* @param {string} options.snifferUrl - 嗅探器接口地址
* @param {number} options.timeout - 嗅探器服务端超时时间(秒),来自设置页面的"嗅探超时"配置
* @param {string} options.mode - 嗅探模式:0=单个链接,1=多个链接
* @param {string} options.is_pc - 设备模拟:0=移动设备,1=PC
* @returns {Promise<Object>} 嗅探结果
*/
export const sniffVideo = async (urlOrParseData, options = {}) => {
const {
snifferUrl = 'http://localhost:57573/sniffer',
timeout = 15,
mode = '0',
is_pc = '0'
} = options
if (!urlOrParseData) {
throw new Error('URL或解析数据参数不能为空')
}
if (!snifferUrl) {
throw new Error('嗅探器接口地址不能为空')
}
try {
let requestUrl
// 检查是否是T4解析数据格式
if (typeof urlOrParseData === 'object' && urlOrParseData.parse === 1) {
// T4解析数据格式:{ parse: 1, url: string, js: string, parse_extra: string }
const { url, js, parse_extra } = urlOrParseData
if (!url) {
throw new Error('T4解析数据中缺少URL')
}
// 确保URL是字符串格式
const urlString = typeof url === 'string' ? url : (url.toString ? url.toString() : String(url))
console.log('处理T4解析数据:', urlOrParseData)
console.log('提取的URL:', urlString)
console.log('=== 调试结束 ===')
// 构建基础参数
const params = new URLSearchParams({
url: urlString,
mode: mode,
is_pc: is_pc,
timeout: (timeout * 1000).toString() // 嗅探器服务端超时时间(毫秒)
})
// 添加脚本参数
if (js) {
params.set('script', js)
}
// 构建请求URL
requestUrl = `${snifferUrl}?${params.toString()}`
// 添加额外参数(parse_extra)
if (parse_extra) {
// parse_extra 通常以 & 开头,直接拼接
requestUrl += parse_extra
}
} else {
// 普通URL格式
const url = typeof urlOrParseData === 'string' ? urlOrParseData : urlOrParseData.toString()
// 构建请求参数
const params = new URLSearchParams({
url: url,
mode: mode,
is_pc: is_pc,
timeout: (timeout * 1000).toString() // 嗅探器服务端超时时间(毫秒)
})
requestUrl = `${snifferUrl}?${params.toString()}`
}
console.log('嗅探请求URL:', requestUrl)
// 发起嗅探请求,设置客户端超时
const controller = new AbortController()
// 客户端超时 = 嗅探器超时 + 5秒网络缓冲时间,确保嗅探器有足够时间完成工作
const timeoutId = setTimeout(() => controller.abort(), timeout * 1000 + 5000)
const response = await fetch(requestUrl, {
method: 'GET',
signal: controller.signal,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
})
clearTimeout(timeoutId)
if (!response.ok) {
throw new Error(`嗅探请求失败: ${response.status} ${response.statusText}`)
}
const result = await response.json()
console.log('嗅探响应结果:', result)
// 检查响应格式
if (result.code !== 200) {
throw new Error(result.msg || '嗅探失败')
}
// 返回标准化的结果
return {
success: true,
data: result.data,
message: result.msg || '嗅探成功',
timestamp: result.timestamp
}
} catch (error) {
console.error('嗅探请求失败:', error)
// 处理不同类型的错误
if (error.name === 'AbortError') {
throw new Error(`嗅探超时(${timeout}秒)`)
} else if (error.message.includes('Failed to fetch')) {
throw new Error('无法连接到嗅探器服务,请检查嗅探器是否正常运行')
} else {
throw error
}
}
}
/**
* 从本地存储获取嗅探器配置
* @returns {Object} 嗅探器配置
*/
export const getSnifferConfig = () => {
try {
const savedAddresses = localStorage.getItem('addressSettings')
if (savedAddresses) {
const parsed = JSON.parse(savedAddresses)
return {
enabled: parsed.proxySniffEnabled || false,
url: parsed.proxySniff || 'http://localhost:57573/sniffer',
timeout: parsed.snifferTimeout || 15
}
}
} catch (error) {
console.error('获取嗅探器配置失败:', error)
}
// 返回默认配置
return {
enabled: false,
url: 'http://localhost:57573/sniffer',
timeout: 15
}
}
/**
* 检查是否启用嗅探功能
* @returns {boolean} 是否启用嗅探
*/
export const isSnifferEnabled = () => {
const config = getSnifferConfig()
return config.enabled && config.url
}
/**
* 嗅探视频链接(带配置检查)
* @param {string} url - 要嗅探的页面URL
* @param {Object} customOptions - 自定义选项(可选)
* @returns {Promise<Object>} 嗅探结果
*/
export const sniffVideoWithConfig = async (url, customOptions = {}) => {
// 获取配置
const config = getSnifferConfig()
if (!config.enabled) {
throw new Error('嗅探功能未启用')
}
if (!config.url) {
throw new Error('嗅探器接口地址未配置')
}
// 合并配置和自定义选项
const options = {
snifferUrl: config.url,
timeout: config.timeout,
...customOptions
}
return await sniffVideo(url, options)
}
export default {
sniffVideo,
sniffVideoWithConfig,
getSnifferConfig,
isSnifferEnabled
}