fish2018/pansou · warning
无法解析响应
Error message
无法解析响应
What it means
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 '无法解析响应'.
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
Example fix
// before
re := regexp.MustCompile(`ptuiCB\('0','0','([^']+)'`)
matches := re.FindStringSubmatch(responseText)
if len(matches) < 2 {
return "", "", fmt.Errorf("无法解析响应")
}
// after
re := regexp.MustCompile(`ptuiCB\('(\d+)','\d+','([^']*)'`)
m := re.FindStringSubmatch(responseText)
if m == nil {
return "", "", fmt.Errorf("无法解析响应: %s", responseText)
}
if m[1] != "0" {
return "", "", fmt.Errorf("登录未完成, 状态码: %s", m[1])
} Defensive patterns
Strategy: type-guard
Validate before calling
// inspect the ptuiCB status code before attempting URL extraction
re := regexp.MustCompile(`ptuiCB\('(\d+)'`)
m := re.FindStringSubmatch(bodyStr)
if m == nil || m[1] != "0" {
return fmt.Errorf("login not complete, ptuiCB code=%v", m)
} Type guard
func ptuiCBSuccess(body string) bool {
re := regexp.MustCompile(`ptuiCB\('0','0','[^']+'`)
return re.MatchString(body)
}
// call extractLoginInfo only if ptuiCBSuccess(bodyStr) Try / catch
ptsigx, uin, err := p.extractLoginInfo(bodyStr)
if err != nil {
if err.Error() == "无法解析响应" {
return nil, errors.New("QR code scanned but not confirmed or expired; poll again or refresh QR")
}
return nil, err
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/0c3bc51ca36206fa.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/qqpd/qqpd.go:1848
// 等待扫码
return &LoginResult{Status: "waiting"}, nil
}
// extractLoginInfo 从登录响应中提取ptsigx和uin
func (p *QQPDPlugin) extractLoginInfo(responseText string) (string, string, error) {
// 解析返回的JavaScript回调:ptuiCB('0','0','url',...)
// 需要提取第3个参数的URL
start := strings.Index(responseText, "ptuiCB(")
if start == -1 {
return "", "", fmt.Errorf("未找到ptuiCB")
}
// 简单解析,提取URL部分
re := regexp.MustCompile(`ptuiCB\('0','0','([^']+)'`)
matches := re.FindStringSubmatch(responseText)
if len(matches) < 2 {
return "", "", fmt.Errorf("无法解析响应")
}
url := matches[1]
// 提取ptsigx
ptsigxRe := regexp.MustCompile(`ptsigx=([A-Za-z0-9]+)`)
ptsigxMatches := ptsigxRe.FindStringSubmatch(url)
if len(ptsigxMatches) < 2 {
return "", "", fmt.Errorf("未找到ptsigx")
}
ptsigx := ptsigxMatches[1]
// 提取uin
uinRe := regexp.MustCompile(`uin=(\d+)`)
uinMatches := uinRe.FindStringSubmatch(url)
if len(uinMatches) < 2 {
return "", "", fmt.Errorf("未找到uin")
}View on GitHub (pinned to beaa561337)