{"record":{"id":"04e3948c6a66ca94","repo":"fish2018/pansou","slug":"ptuicb","errorCode":null,"errorMessage":"未找到ptuiCB","messagePattern":"未找到ptuiCB","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/qqpd/qqpd.go","lineNumber":1841,"sourceCode":"\n\t\treturn &LoginResult{\n\t\t\tStatus:   \"success\",\n\t\t\tCookie:   cookie,\n\t\t\tQQMasked: qqMasked,\n\t\t}, nil\n\t}\n\n\t// 等待扫码\n\treturn &LoginResult{Status: \"waiting\"}, nil\n}\n\n// extractLoginInfo 从登录响应中提取ptsigx和uin\nfunc (p *QQPDPlugin) extractLoginInfo(responseText string) (string, string, error) {\n\t// 解析返回的JavaScript回调：ptuiCB('0','0','url',...)\n\t// 需要提取第3个参数的URL\n\tstart := strings.Index(responseText, \"ptuiCB(\")\n\tif start == -1 {\n\t\treturn \"\", \"\", fmt.Errorf(\"未找到ptuiCB\")\n\t}\n\n\t// 简单解析，提取URL部分\n\tre := regexp.MustCompile(`ptuiCB\\('0','0','([^']+)'`)\n\tmatches := re.FindStringSubmatch(responseText)\n\tif len(matches) < 2 {\n\t\treturn \"\", \"\", fmt.Errorf(\"无法解析响应\")\n\t}\n\n\turl := matches[1]\n\n\t// 提取ptsigx\n\tptsigxRe := regexp.MustCompile(`ptsigx=([A-Za-z0-9]+)`)\n\tptsigxMatches := ptsigxRe.FindStringSubmatch(url)\n\tif len(ptsigxMatches) < 2 {\n\t\treturn \"\", \"\", fmt.Errorf(\"未找到ptsigx\")\n\t}\n\tptsigx := ptsigxMatches[1]","sourceCodeStart":1823,"sourceCodeEnd":1859,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/qqpd/qqpd.go#L1823-L1859","documentation":"extractLoginInfo (plugin/qqpd/qqpd.go:1841) expects the ptqrlogin response to contain a JavaScript callback starting with 'ptuiCB('. If strings.Index cannot find it, it returns '未找到ptuiCB'. This means the response body is not the expected QQ login callback format at all.","triggerScenarios":"checkQRLoginStatus detects '登录成功' in bodyStr and calls extractLoginInfo, but the body lacks any 'ptuiCB(' substring — e.g. an unexpected HTML/JSON error page.","commonSituations":"QQ server returning an error or captcha page instead of the callback, an encoding issue mangling the body, or a QQ-side format change renaming/restructuring ptuiCB.","solutions":["Print and inspect the raw response body stored in the preceding log line","Confirm the response is really a success payload; check ptuiCB's first argument code (0 = success)","Update extractLoginInfo's parsing if QQ changed the callback format","Regenerate the QR code and retry, as stale sessions can yield malformed payloads"],"exampleFix":"// before\nstart := strings.Index(responseText, \"ptuiCB(\")\nif start == -1 {\n    return \"\", \"\", fmt.Errorf(\"未找到ptuiCB\")\n}\n// after\nstart := strings.Index(responseText, \"ptuiCB(\")\nif start == -1 {\n    return \"\", \"\", fmt.Errorf(\"未找到ptuiCB, 响应前缀: %.200s\", responseText)\n}","handlingStrategy":"validation","validationCode":"// pre-check before invoking the parser\nif !strings.Contains(bodyStr, \"ptuiCB(\") {\n    return errors.New(\"login response missing ptuiCB callback\")\n}","typeGuard":null,"tryCatchPattern":"ptsigx, uin, err := p.extractLoginInfo(bodyStr)\nif err != nil {\n    if err.Error() == \"未找到ptuiCB\" {\n        // unexpected body: save bodyStr to disk for diagnosis\n        _ = os.WriteFile(\"last_qqpd_body.txt\", []byte(bodyStr), 0644)\n    }\n    return err\n}","preventionTips":["Always persist the raw response body alongside the parse error","Verify success-marker ('登录成功') and callback presence together","Watch for QQ-side format changes and add regression tests with recorded bodies","Retry with a fresh QR code when the body shape is unexpected"],"tags":["parsing","qq-login","response-format"],"backgroundTag":"unexpected-response-shape","analyzedSha":"beaa56133755a548ebc51b090b3816e2ae044aa6","analyzedAt":"2026-09-07T00:31:18.025Z","contentChangedAt":"2026-09-07T00:31:18.025Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}