|
import { generateVqdHash } from "./vm.ts"; |
|
import { userAgent } from "./utils.ts"; |
|
import { CONFIG, getHash, setHash } from "./utils.ts"; |
|
import { ChatMessage } from "./types.ts"; |
|
import { errorResponse } from "./response.ts"; |
|
|
|
export class DDGService { |
|
private hash: string | null = null; |
|
|
|
async getVqdHash(): Promise<string | Response> { |
|
|
|
const envHash = getHash(); |
|
if (envHash) { |
|
return envHash; |
|
} |
|
|
|
try { |
|
const response = await fetch(CONFIG.DDG_STATUS_URL, { |
|
method: "GET", |
|
headers: { |
|
"User-Agent": userAgent, |
|
"x-vqd-accept": "1", |
|
}, |
|
}); |
|
|
|
if (!response.ok) { |
|
return errorResponse(`hash初始化请求失败: ${response.status}`, 502); |
|
} |
|
|
|
const hash = response.headers.get("x-vqd-hash-1"); |
|
|
|
if (!hash) { |
|
return errorResponse(`未找到hash头部,状态码: ${response.status}`, 502); |
|
} |
|
|
|
let decryptedHash: string; |
|
try { |
|
decryptedHash = generateVqdHash(hash); |
|
} catch (decryptError) { |
|
return errorResponse(`hash解密失败: ${decryptError.message}`, 502); |
|
} |
|
|
|
if (!decryptedHash || decryptedHash.trim() === "") { |
|
return errorResponse(`hash解密结果为空`, 502); |
|
} |
|
setHash(decryptedHash); |
|
return decryptedHash; |
|
} catch (error) { |
|
return errorResponse(`获取hash失败: ${error.message}`, 502); |
|
} |
|
} |
|
|
|
|
|
private async sendMessage( |
|
model: string, |
|
messages: ChatMessage[] |
|
): Promise<{ |
|
success: boolean; |
|
response?: Response; |
|
error?: string; |
|
status?: number; |
|
}> { |
|
const hash = await this.getVqdHash(); |
|
if (hash instanceof Response) { |
|
return { success: false, error: "获取hash失败", status: hash.status }; |
|
} |
|
|
|
const payload = { |
|
model, |
|
messages, |
|
canUseTools: false, |
|
canUseApproxLocation: false, |
|
}; |
|
|
|
try { |
|
const response = await fetch(CONFIG.DDG_CHAT_URL, { |
|
method: "POST", |
|
headers: { |
|
"User-Agent": userAgent, |
|
"x-vqd-hash-1": hash, |
|
"Content-Type": "application/json", |
|
}, |
|
body: JSON.stringify(payload), |
|
}); |
|
|
|
if (!response.ok) { |
|
const errorText = await response.text(); |
|
return { |
|
success: false, |
|
error: `上游错误: ${response.status} - ${errorText}`, |
|
status: response.status, |
|
}; |
|
} |
|
|
|
return { success: true, response }; |
|
} catch (error) { |
|
return { |
|
success: false, |
|
error: `请求失败: ${error.message}`, |
|
status: 502, |
|
}; |
|
} |
|
} |
|
|
|
|
|
async sendMessageWithRetry( |
|
model: string, |
|
messages: ChatMessage[], |
|
maxRetries = 1 |
|
): Promise<Response> { |
|
let lastResult: { |
|
success: boolean; |
|
response?: Response; |
|
error?: string; |
|
status?: number; |
|
} | null = null; |
|
|
|
for (let attempt = 0; attempt <= maxRetries; attempt++) { |
|
if (attempt > 0) { |
|
setHash(""); |
|
} |
|
|
|
const result = await this.sendMessage(model, messages); |
|
|
|
if (result.success && result.response) { |
|
return result.response; |
|
} |
|
|
|
lastResult = result; |
|
|
|
|
|
if (result.status === 418 || 429) { |
|
continue; |
|
} else { |
|
|
|
break; |
|
} |
|
} |
|
|
|
|
|
return errorResponse( |
|
lastResult?.error || "发送消息失败", |
|
lastResult?.status || 502 |
|
); |
|
} |
|
} |
|
|