GeminiBot commited on
Commit
d819405
1 Parent(s): c98a3e7

Fix syntax error in duckai.ts and consolidate all patches

Browse files
Files changed (1) hide show
  1. src/duckai.ts +112 -50
src/duckai.ts CHANGED
@@ -14,29 +14,14 @@ export class DuckAI {
14
  resources: "usable"
15
  });
16
 
17
- const window = dom.window as any;
18
-
19
- // 袚袥校袘袨袣袗携 协袦校袥携笑袠携
20
- Object.defineProperties(window.navigator, {
21
- userAgent: { value: ua },
22
- platform: { value: 'Win32' },
23
- webdriver: { value: false },
24
- languages: { value: ['en-US', 'en'] }
25
- });
26
-
27
- window.screen = { width: 1920, height: 1080, availWidth: 1920, availHeight: 1080 };
28
- window.chrome = { runtime: {} };
29
-
30
- // Fix for 'Cannot read properties of null (reading 'contentDocument')'
31
- // Immortal DOM + Environment Mocks
32
  const mockWindow = dom.window as any;
33
-
34
  // Self-reference fixes
35
  mockWindow.self = mockWindow;
36
  mockWindow.parent = mockWindow;
37
  mockWindow.top = mockWindow;
38
-
39
- // Immortal DOM Strategy
40
  const originalGetElementById = mockWindow.document.getElementById;
41
  mockWindow.document.getElementById = function(id: string) {
42
  const el = originalGetElementById.call(this, id);
@@ -53,6 +38,17 @@ export class DuckAI {
53
  return mockWindow.document.createElement('div');
54
  };
55
 
 
 
 
 
 
 
 
 
 
 
 
56
  // Aggressive Patch for iframe contentDocument
57
  Object.defineProperty(mockWindow.HTMLIFrameElement.prototype, 'contentDocument', {
58
  get: function() { return mockWindow.document; },
@@ -64,34 +60,100 @@ export class DuckAI {
64
  configurable: true
65
  });
66
 
67
- dom.window.top.__DDG_BE_VERSION__ = 1;
68
- dom.window.top.__DDG_FE_CHAT_HASH__ = 1;
69
-
70
- const result = await dom.window.eval(jsScript) as any;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
 
72
- if (!result || !result.client_hashes) {
73
- throw new Error("Invalid Challenge Response");
74
- }
 
 
 
 
75
 
76
- result.client_hashes[0] = ua;
77
- result.client_hashes = result.client_hashes.map((t: string) => {
78
- const hash = createHash('sha256');
79
- hash.update(t);
80
- return hash.digest('base64');
81
- });
82
-
83
- return btoa(JSON.stringify(result));
84
- } catch (e: any) {
85
- console.error(`[DuckAI] Challenge Solver Failed: ${e.message}`);
86
- // Fallback: Return the original hash (sometimes works if challenge is optional or server is lenient)
87
- // or return a dummy base64 json.
88
- console.log("[DuckAI] Attempting fallback with original VQD...");
89
- return vqdHash; // Try returning the VQD itself as a fallback
90
- }
91
- }
92
- dom.window.top.__DDG_FE_CHAT_HASH__ = 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
 
94
- const result = await dom.window.eval(jsScript) as any;
95
 
96
  if (!result || !result.client_hashes) {
97
  throw new Error("Invalid Challenge Response");
@@ -106,16 +168,17 @@ export class DuckAI {
106
 
107
  return btoa(JSON.stringify(result));
108
  } catch (e: any) {
109
- throw new Error(`Challenge Solver Error: ${e.message}`);
 
 
110
  }
111
  }
112
 
113
  getAvailableModels(): string[] {
114
  return [
115
  "gpt-4o-mini",
116
- "claude-3-haiku-20240307",
117
- "meta-llama/Llama-3.3-70B-Instruct-Turbo",
118
- "mistralai/Mistral-Small-24B-Instruct-2501"
119
  ];
120
  }
121
 
@@ -142,7 +205,7 @@ export class DuckAI {
142
 
143
  console.log("[DuckAI] Solving challenge...");
144
  const solvedVqd = await this.solveChallenge(hashHeader, ua);
145
- console.log("[DuckAI] Challenge solved.");
146
 
147
  const response = await fetch("https://duckduckgo.com/duckchat/v1/chat", {
148
  method: "POST",
@@ -159,7 +222,6 @@ export class DuckAI {
159
  }
160
 
161
  const text = await response.text();
162
- // console.log(`[DuckAI] Raw response: ${text.substring(0, 200)}...`); // Uncomment for ultra verbose
163
 
164
  let llmResponse = "";
165
  const lines = text.split("\n");
@@ -181,4 +243,4 @@ export class DuckAI {
181
 
182
  return llmResponse.trim();
183
  }
184
- }
 
14
  resources: "usable"
15
  });
16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  const mockWindow = dom.window as any;
18
+
19
  // Self-reference fixes
20
  mockWindow.self = mockWindow;
21
  mockWindow.parent = mockWindow;
22
  mockWindow.top = mockWindow;
23
+
24
+ // IMMORTAL DOM Strategy
25
  const originalGetElementById = mockWindow.document.getElementById;
26
  mockWindow.document.getElementById = function(id: string) {
27
  const el = originalGetElementById.call(this, id);
 
38
  return mockWindow.document.createElement('div');
39
  };
40
 
41
+ // 袚袥校袘袨袣袗携 协袦校袥携笑袠携
42
+ Object.defineProperties(mockWindow.navigator, {
43
+ userAgent: { value: ua },
44
+ platform: { value: 'Win32' },
45
+ webdriver: { value: false },
46
+ languages: { value: ['en-US', 'en'] }
47
+ });
48
+
49
+ mockWindow.screen = { width: 1920, height: 1080, availWidth: 1920, availHeight: 1080 };
50
+ mockWindow.chrome = { runtime: {} };
51
+
52
  // Aggressive Patch for iframe contentDocument
53
  Object.defineProperty(mockWindow.HTMLIFrameElement.prototype, 'contentDocument', {
54
  get: function() { return mockWindow.document; },
 
60
  configurable: true
61
  });
62
 
63
+ // Also keep the createElement hook just in case
64
+ const originalCreateElement = mockWindow.document.createElement;
65
+ mockWindow.document.createElement = function(tagName: string) {
66
+ const element = originalCreateElement.call(this, tagName);
67
+ if (tagName.toLowerCase() === 'iframe') {
68
+ try {
69
+ Object.defineProperty(element, 'contentDocument', {
70
+ get: () => mockWindow.document,
71
+ configurable: true
72
+ });
73
+ Object.defineProperty(element, 'contentWindow', {
74
+ get: () => mockWindow,
75
+ configurable: true
76
+ });
77
+ } catch (e) {}
78
+ }
79
+ return element;
80
+ };
81
 
82
+ // Robust Canvas Mock
83
+ const originalGetContext = mockWindow.HTMLCanvasElement.prototype.getContext;
84
+ mockWindow.HTMLCanvasElement.prototype.getContext = function (type: string, options?: any) {
85
+ try {
86
+ const ctx = originalGetContext.call(this, type, options);
87
+ if (ctx) return ctx;
88
+ } catch (e) {}
89
 
90
+ return {
91
+ canvas: this,
92
+ fillRect: () => {},
93
+ clearRect: () => {},
94
+ getImageData: (x: number, y: number, w: number, h: number) => ({
95
+ data: new Uint8ClampedArray(w * h * 4),
96
+ width: w,
97
+ height: h
98
+ }),
99
+ putImageData: () => {},
100
+ createImageData: () => ({ data: new Uint8ClampedArray(4) }),
101
+ setTransform: () => {},
102
+ drawImage: () => {},
103
+ save: () => {},
104
+ restore: () => {},
105
+ beginPath: () => {},
106
+ moveTo: () => {},
107
+ lineTo: () => {},
108
+ closePath: () => {},
109
+ stroke: () => {},
110
+ translate: () => {},
111
+ scale: () => {},
112
+ rotate: () => {},
113
+ arc: () => {},
114
+ fill: () => {},
115
+ measureText: () => ({ width: 0, actualBoundingBoxAscent: 0, actualBoundingBoxDescent: 0 }),
116
+ transform: () => {},
117
+ rect: () => {},
118
+ clip: () => {},
119
+ createLinearGradient: () => ({ addColorStop: () => {} }),
120
+ createRadialGradient: () => ({ addColorStop: () => {} }),
121
+ createPattern: () => ({}),
122
+ bezierCurveTo: () => {},
123
+ quadraticCurveTo: () => {},
124
+ fillText: () => {},
125
+ strokeText: () => {},
126
+ globalAlpha: 1,
127
+ globalCompositeOperation: 'source-over',
128
+ fillStyle: '#000000',
129
+ strokeStyle: '#000000',
130
+ lineWidth: 1,
131
+ lineCap: 'butt',
132
+ lineJoin: 'miter',
133
+ miterLimit: 10,
134
+ shadowOffsetX: 0,
135
+ shadowOffsetY: 0,
136
+ shadowBlur: 0,
137
+ shadowColor: 'rgba(0, 0, 0, 0)',
138
+ font: '10px sans-serif',
139
+ textAlign: 'start',
140
+ textBaseline: 'alphabetic'
141
+ };
142
+ } as any;
143
+
144
+ const originalToDataURL = mockWindow.HTMLCanvasElement.prototype.toDataURL;
145
+ mockWindow.HTMLCanvasElement.prototype.toDataURL = function(type?: string, quality?: any) {
146
+ try {
147
+ const result = originalToDataURL.call(this, type, quality);
148
+ if (result && result !== "data:,") return result;
149
+ } catch(e) {}
150
+ return "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==";
151
+ };
152
+
153
+ mockWindow.top.__DDG_BE_VERSION__ = 1;
154
+ mockWindow.top.__DDG_FE_CHAT_HASH__ = 1;
155
 
156
+ const result = await mockWindow.eval(jsScript) as any;
157
 
158
  if (!result || !result.client_hashes) {
159
  throw new Error("Invalid Challenge Response");
 
168
 
169
  return btoa(JSON.stringify(result));
170
  } catch (e: any) {
171
+ console.error(`[DuckAI] Challenge Solver Failed: ${e.message}`);
172
+ console.log("[DuckAI] Attempting fallback with original VQD...");
173
+ return vqdHash;
174
  }
175
  }
176
 
177
  getAvailableModels(): string[] {
178
  return [
179
  "gpt-4o-mini",
180
+ "gpt-5-mini",
181
+ "openai/gpt-oss-120b"
 
182
  ];
183
  }
184
 
 
205
 
206
  console.log("[DuckAI] Solving challenge...");
207
  const solvedVqd = await this.solveChallenge(hashHeader, ua);
208
+ console.log("[DuckAI] Challenge solved (or fallback used).");
209
 
210
  const response = await fetch("https://duckduckgo.com/duckchat/v1/chat", {
211
  method: "POST",
 
222
  }
223
 
224
  const text = await response.text();
 
225
 
226
  let llmResponse = "";
227
  const lines = text.split("\n");
 
243
 
244
  return llmResponse.trim();
245
  }
246
+ }