dragg2 commited on
Commit
28fef86
·
verified ·
1 Parent(s): 076bf20

Update main.go

Browse files
Files changed (1) hide show
  1. main.go +180 -41
main.go CHANGED
@@ -10,6 +10,7 @@ import (
10
  "net/http"
11
  "net/url"
12
  "os"
 
13
  "strings"
14
  "time"
15
 
@@ -368,66 +369,204 @@ func requestToken() (string, error) {
368
  }
369
 
370
  func requestTokenAndHash() (string, string, error) {
371
- req, err := http.NewRequest("GET", "https://duckduckgo.com/duckchat/v1/status", nil)
 
 
 
 
372
  if err != nil {
373
- return "", "", fmt.Errorf("创建请求失败: %v", err)
374
  }
 
375
  for k, v := range config.FakeHeaders {
376
  req.Header.Set(k, v)
377
  }
378
- req.Header.Set("x-vqd-accept", "1")
379
-
380
- client := createHTTPClient(10 * time.Second)
381
-
382
- log.Println("发送 token 请求")
383
  resp, err := client.Do(req)
384
  if err != nil {
385
- return "", "", fmt.Errorf("请求失败: %v", err)
386
  }
387
  defer resp.Body.Close()
388
-
389
  if resp.StatusCode != http.StatusOK {
390
  bodyBytes, _ := io.ReadAll(resp.Body)
391
- bodyString := string(bodyBytes)
392
- log.Printf("requestToken: 非200响应: %d, 内容: %s\n", resp.StatusCode, bodyString)
393
- return "", "", fmt.Errorf("非200响应: %d, 内容: %s", resp.StatusCode, bodyString)
394
  }
395
-
396
- // 从响应头中获取令牌
397
- token := resp.Header.Get("x-vqd-4")
398
- if token == "" {
399
- return "", "", errors.New("响应中未包含x-vqd-4头")
400
  }
401
-
402
- // 从响应头中获取x-vqd-hash-1
403
- vqdHash := resp.Header.Get("x-vqd-hash-1")
404
- if vqdHash == "" {
405
- // 尝试从响应体中获取
406
- bodyBytes, err := io.ReadAll(resp.Body)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
407
  if err != nil {
408
- log.Printf("读取响应体失败: %v", err)
409
- } else {
410
- // 记录响应体以便调试
411
- log.Printf("响应体: %s", string(bodyBytes))
412
-
413
- // 尝试从JSON响应中解析可能包含的哈希值
414
- var respObj map[string]interface{}
415
- if err := json.Unmarshal(bodyBytes, &respObj); err == nil {
416
- if hashValue, ok := respObj["x-vqd-hash-1"].(string); ok {
417
- vqdHash = hashValue
418
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
419
  }
420
  }
421
  }
422
 
423
- log.Printf("获取到的 token: %s", token)
424
- if vqdHash != "" {
425
- log.Printf("获取到的 hash: %s", vqdHash)
426
- } else {
427
- log.Println("未获取到 hash 值")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
428
  }
429
 
430
- return token, vqdHash, nil
431
  }
432
 
433
  func prepareMessages(messages []struct {
@@ -532,4 +671,4 @@ func createHTTPClient(timeout time.Duration) *http.Client {
532
  }
533
 
534
  return client
535
- }
 
10
  "net/http"
11
  "net/url"
12
  "os"
13
+ "regexp"
14
  "strings"
15
  "time"
16
 
 
369
  }
370
 
371
  func requestTokenAndHash() (string, string, error) {
372
+ // Create a client with proper settings
373
+ client := createHTTPClient(30 * time.Second)
374
+
375
+ // First, visit the DuckDuckGo main page
376
+ req, err := http.NewRequest("GET", "https://duckduckgo.com/", nil)
377
  if err != nil {
378
+ return "", "", fmt.Errorf("failed to create homepage request: %v", err)
379
  }
380
+
381
  for k, v := range config.FakeHeaders {
382
  req.Header.Set(k, v)
383
  }
384
+
385
+ log.Println("Sending request to DuckDuckGo homepage")
 
 
 
386
  resp, err := client.Do(req)
387
  if err != nil {
388
+ return "", "", fmt.Errorf("homepage request failed: %v", err)
389
  }
390
  defer resp.Body.Close()
391
+
392
  if resp.StatusCode != http.StatusOK {
393
  bodyBytes, _ := io.ReadAll(resp.Body)
394
+ return "", "", fmt.Errorf("homepage request returned status %d: %s", resp.StatusCode, string(bodyBytes))
 
 
395
  }
396
+
397
+ // Read homepage content to extract vqd-related JavaScript
398
+ bodyBytes, err := io.ReadAll(resp.Body)
399
+ if err != nil {
400
+ return "", "", fmt.Errorf("failed to read homepage: %v", err)
401
  }
402
+
403
+ bodyStr := string(bodyBytes)
404
+
405
+ // Method 1: Try to extract the vqd directly from the HTML attributes
406
+ // DuckDuckGo often embeds this in data attributes or JavaScript variables
407
+ vqdRegex := regexp.MustCompile(`vqd=["']([^"']+)["']`)
408
+ matches := vqdRegex.FindStringSubmatch(bodyStr)
409
+
410
+ if len(matches) < 2 {
411
+ // Try alternate regex patterns if the first one didn't match
412
+ alternatePatterns := []string{
413
+ `vqd[:=]["']([^"']+)["']`,
414
+ `"vqd":"([^"]+)"`,
415
+ `'vqd':'([^']+)'`,
416
+ }
417
+
418
+ for _, pattern := range alternatePatterns {
419
+ r := regexp.MustCompile(pattern)
420
+ matches = r.FindStringSubmatch(bodyStr)
421
+ if len(matches) >= 2 {
422
+ break
423
+ }
424
+ }
425
+ }
426
+
427
+ if len(matches) >= 2 {
428
+ token := matches[1]
429
+ log.Printf("Successfully extracted vqd token: %s", token)
430
+ return token, "", nil
431
+ }
432
+
433
+ // Method 2: Get the JavaScript file that contains the token generation logic
434
+ jsURLRegex := regexp.MustCompile(`(\/dist\/[^"']+\.js)`)
435
+ jsMatches := jsURLRegex.FindAllStringSubmatch(bodyStr, -1)
436
+
437
+ for _, match := range jsMatches {
438
+ if len(match) < 2 {
439
+ continue
440
+ }
441
+
442
+ jsURL := "https://duckduckgo.com" + match[1]
443
+ log.Printf("Trying to get vqd from JavaScript file: %s", jsURL)
444
+
445
+ jsReq, err := http.NewRequest("GET", jsURL, nil)
446
  if err != nil {
447
+ log.Printf("Failed to create request for JS file: %v", err)
448
+ continue
449
+ }
450
+
451
+ for k, v := range config.FakeHeaders {
452
+ jsReq.Header.Set(k, v)
453
+ }
454
+
455
+ jsResp, err := client.Do(jsReq)
456
+ if err != nil {
457
+ log.Printf("Failed to get JS file: %v", err)
458
+ continue
459
+ }
460
+
461
+ jsBytes, err := io.ReadAll(jsResp.Body)
462
+ jsResp.Body.Close()
463
+
464
+ if err != nil {
465
+ log.Printf("Failed to read JS file: %v", err)
466
+ continue
467
+ }
468
+
469
+ jsContent := string(jsBytes)
470
+
471
+ // Look for vqd token patterns in the JS file
472
+ vqdInJSRegex := regexp.MustCompile(`vqd\s*[:=]\s*["']([^"']+)["']`)
473
+ jsMatches := vqdInJSRegex.FindStringSubmatch(jsContent)
474
+
475
+ if len(jsMatches) >= 2 {
476
+ token := jsMatches[1]
477
+ log.Printf("Found vqd token in JS file: %s", token)
478
+ return token, "", nil
479
+ }
480
+
481
+ // Try another pattern specific to the format in the JS file
482
+ vqdInJSRegex2 := regexp.MustCompile(`"vqd"\s*:\s*"([^"]+)"`)
483
+ jsMatches2 := vqdInJSRegex2.FindStringSubmatch(jsContent)
484
+
485
+ if len(jsMatches2) >= 2 {
486
+ token := jsMatches2[1]
487
+ log.Printf("Found vqd token in JS file (pattern 2): %s", token)
488
+ return token, "", nil
489
+ }
490
+ }
491
+
492
+ // Method 3 (Fallback): Try to request duck.js or related files which might contain the token
493
+ fallbackURLs := []string{
494
+ "https://duckduckgo.com/duck.js",
495
+ "https://duckduckgo.com/chat.js",
496
+ "https://duckduckgo.com/d.js",
497
+ }
498
+
499
+ for _, url := range fallbackURLs {
500
+ fallbackReq, err := http.NewRequest("GET", url, nil)
501
+ if err != nil {
502
+ log.Printf("Failed to create request for fallback URL %s: %v", url, err)
503
+ continue
504
+ }
505
+
506
+ for k, v := range config.FakeHeaders {
507
+ fallbackReq.Header.Set(k, v)
508
+ }
509
+
510
+ fallbackResp, err := client.Do(fallbackReq)
511
+ if err != nil {
512
+ log.Printf("Failed to get fallback URL %s: %v", url, err)
513
+ continue
514
+ }
515
+
516
+ fallbackBytes, err := io.ReadAll(fallbackResp.Body)
517
+ fallbackResp.Body.Close()
518
+
519
+ if err != nil {
520
+ log.Printf("Failed to read fallback URL %s: %v", url, err)
521
+ continue
522
+ }
523
+
524
+ fallbackContent := string(fallbackBytes)
525
+
526
+ // Try multiple regex patterns to find the vqd token
527
+ patterns := []string{
528
+ `vqd\s*[:=]\s*["']([^"']+)["']`,
529
+ `"vqd"\s*:\s*"([^"]+)"`,
530
+ `'vqd'\s*:\s*'([^']+)'`,
531
+ }
532
+
533
+ for _, pattern := range patterns {
534
+ r := regexp.MustCompile(pattern)
535
+ m := r.FindStringSubmatch(fallbackContent)
536
+ if len(m) >= 2 {
537
+ token := m[1]
538
+ log.Printf("Found vqd token in fallback URL %s: %s", url, token)
539
+ return token, "", nil
540
  }
541
  }
542
  }
543
 
544
+ // Last resort: try the duckchat/v1/status endpoint which we know returns the token in headers
545
+ statusReq, err := http.NewRequest("GET", "https://duckduckgo.com/duckchat/v1/status", nil)
546
+ if err != nil {
547
+ return "", "", fmt.Errorf("failed to create status request: %v", err)
548
+ }
549
+
550
+ for k, v := range config.FakeHeaders {
551
+ statusReq.Header.Set(k, v)
552
+ }
553
+ statusReq.Header.Set("x-vqd-accept", "1")
554
+
555
+ log.Println("Trying duckchat/v1/status as last resort")
556
+ statusResp, err := client.Do(statusReq)
557
+ if err != nil {
558
+ return "", "", fmt.Errorf("status request failed: %v", err)
559
+ }
560
+ defer statusResp.Body.Close()
561
+
562
+ // Check X-VQD-4 header
563
+ token := statusResp.Header.Get("x-vqd-4")
564
+ if token != "" {
565
+ log.Printf("Found vqd token in status response header: %s", token)
566
+ return token, "", nil
567
  }
568
 
569
+ return "", "", errors.New("could not find vqd token using any method")
570
  }
571
 
572
  func prepareMessages(messages []struct {
 
671
  }
672
 
673
  return client
674
+ }