{"record":{"id":"0c3bc51ca36206fa","repo":"fish2018/pansou","slug":"error-0c3bc5","errorCode":null,"errorMessage":"无法解析响应","messagePattern":"无法解析响应","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"plugin/qqpd/qqpd.go","lineNumber":1848,"sourceCode":"\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]\n\n\t// 提取uin\n\tuinRe := regexp.MustCompile(`uin=(\\d+)`)\n\tuinMatches := uinRe.FindStringSubmatch(url)\n\tif len(uinMatches) < 2 {\n\t\treturn \"\", \"\", fmt.Errorf(\"未找到uin\")\n\t}","sourceCodeStart":1830,"sourceCodeEnd":1866,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/qqpd/qqpd.go#L1830-L1866","documentation":"extractLoginInfo (plugin/qqpd/qqpd.go:1848) finds 'ptuiCB(' but the regex `ptuiCB\\('0','0','([^']+)'` fails to capture a URL. This happens when the callback's status code is not '0' (login not fully successful) or the argument structure differs, so no URL group is matched. It is returned as '无法解析响应'.","triggerScenarios":"checkQRLoginStatus -> extractLoginInfo: response contains ptuiCB( but the callback arguments don't match `('0','0','<url>')` — e.g. ptuiCB('67','0',...) meaning the QR was scanned but not confirmed, or the code indicates expiration.","commonSituations":"User scanned the QR but hasn't confirmed on the phone yet, the QR code expired (code 65/67 states), or QQ changed the callback argument order.","solutions":["Check the first ptuiCB argument in the response body to see the actual status code and handle it explicitly (expired, scanned-but-unconfirmed, etc.)","Poll again until the user confirms on the phone, then re-run checkQRLoginStatus","Loosen/extend the regex to capture any status and dispatch on it","Regenerate the QR code if the code indicates expiration"],"exampleFix":"// before\nre := regexp.MustCompile(`ptuiCB\\('0','0','([^']+)'`)\nmatches := re.FindStringSubmatch(responseText)\nif len(matches) < 2 {\n    return \"\", \"\", fmt.Errorf(\"无法解析响应\")\n}\n// after\nre := regexp.MustCompile(`ptuiCB\\('(\\d+)','\\d+','([^']*)'`)\nm := re.FindStringSubmatch(responseText)\nif m == nil {\n    return \"\", \"\", fmt.Errorf(\"无法解析响应: %s\", responseText)\n}\nif m[1] != \"0\" {\n    return \"\", \"\", fmt.Errorf(\"登录未完成, 状态码: %s\", m[1])\n}","handlingStrategy":"type-guard","validationCode":"// inspect the ptuiCB status code before attempting URL extraction\nre := regexp.MustCompile(`ptuiCB\\('(\\d+)'`)\nm := re.FindStringSubmatch(bodyStr)\nif m == nil || m[1] != \"0\" {\n    return fmt.Errorf(\"login not complete, ptuiCB code=%v\", m)\n}","typeGuard":"func ptuiCBSuccess(body string) bool {\n    re := regexp.MustCompile(`ptuiCB\\('0','0','[^']+'`)\n    return re.MatchString(body)\n}\n// call extractLoginInfo only if ptuiCBSuccess(bodyStr)","tryCatchPattern":"ptsigx, uin, err := p.extractLoginInfo(bodyStr)\nif err != nil {\n    if err.Error() == \"无法解析响应\" {\n        return nil, errors.New(\"QR code scanned but not confirmed or expired; poll again or refresh QR\")\n    }\n    return nil, err\n}","preventionTips":["Decode and branch on the ptuiCB status code (0=ok, 65/67=pending/expired) instead of parsing blindly","Keep polling until the status is 0 before extracting the URL","Add tests covering all known ptuiCB status codes","Refresh the QR code when status indicates expiration"],"tags":["parsing","regex","qr-code"],"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"}