{"record":{"id":"ad5accde3b48e7f2","repo":"fish2018/pansou","slug":"w-s","errorCode":null,"errorMessage":"%w: %s","messagePattern":"%w: %s","errorType":"exception","errorClass":"errLoginRequired","httpStatus":null,"severity":"error","filePath":"plugin/panlian/panlian.go","lineNumber":822,"sourceCode":"\t\tif truncated {\n\t\t\tbreak\n\t\t}\n\t}\n\n\treturn links, strings.Join(summaryParts, \" / \"), latest, truncated\n}\n\nfunc (p *PanlianPlugin) fetchVideos(client *http.Client, cookie string, keyword string) (*VideoSearchResponse, error) {\n\tvalues := url.Values{}\n\tvalues.Set(\"wd\", keyword)\n\tvalues.Set(\"pg\", \"1\")\n\n\tvar resp VideoSearchResponse\n\tif err := p.doJSONGET(client, cookie, \"/api/get_videos.php\", values, &resp); err != nil {\n\t\treturn nil, err\n\t}\n\tif resp.Code == -1 && strings.Contains(resp.Msg, \"登录\") {\n\t\treturn nil, fmt.Errorf(\"%w: %s\", errLoginRequired, resp.Msg)\n\t}\n\tif resp.Code != 1 {\n\t\treturn nil, fmt.Errorf(\"盘链列表接口异常: %s\", resp.Msg)\n\t}\n\treturn &resp, nil\n}\n\nfunc (p *PanlianPlugin) fetchPanLinks(client *http.Client, cookie string, keyword string, vodID int) (*PanLinkResponse, error) {\n\tvalues := url.Values{}\n\tvalues.Set(\"keyword\", keyword)\n\tvalues.Set(\"vod_id\", fmt.Sprintf(\"%d\", vodID))\n\tvalues.Set(\"_t\", fmt.Sprintf(\"%d\", time.Now().UnixMilli()))\n\n\tvar resp PanLinkResponse\n\tif err := p.doJSONGET(client, cookie, \"/api/search_pan_links.php\", values, &resp); err != nil {\n\t\treturn nil, err\n\t}\n\tif !resp.Success && strings.Contains(resp.Message, \"登录\") {","sourceCodeStart":804,"sourceCodeEnd":840,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/panlian/panlian.go#L804-L840","documentation":"In the panlian video search flow, when the upstream list API (/api/get_videos.php) returns Code == -1 and its message contains '登录' (login), the plugin wraps errLoginRequired with the server message. It signals the panlian cookie/session is no longer valid and re-login is needed.","triggerScenarios":"Calling the search/list API with an expired, revoked, or missing panlian cookie; server invalidates the session (password change, forced logout, session TTL) so Code=-1 with a login-related Msg.","commonSituations":"Cookie pasted once at setup expired days later; user changed panlian password elsewhere; panlian server restarted and dropped sessions; multiple devices triggering session invalidation.","solutions":["Re-login to panlian and update the stored cookie via the plugin's config/set-cookie command.","Detect errors.Is(err, errLoginRequired) in the caller and prompt the user to refresh credentials instead of retrying.","Check the cookie string for whitespace or quotes when pasting it into config.","Verify the account still works by calling panlian directly in a browser."],"exampleFix":"// before\nresults, err := p.searchVideos(keyword) // err: login required\n// after\nif errors.Is(err, plugin.ErrLoginRequired) {\n    promptUserToRefreshPanlianCookie()\n    return\n}","handlingStrategy":"try-catch","validationCode":"// before calling search: check a cookie is configured and non-empty\nif strings.TrimSpace(cookie) == \"\" {\n    return fmt.Errorf(\"panlian cookie not configured; set it before searching\")\n}","typeGuard":null,"tryCatchPattern":"resp, err := plugin.SearchVideos(ctx, keyword)\nif errors.Is(err, plugin.ErrLoginRequired) { // panlian wraps errLoginRequired with %w\n    refreshPanlianCookieAndRetry()\n    return\n}\nif err != nil { return err }","preventionTips":["Refresh the panlian cookie proactively before session TTL expires.","Check errors.Is(err, errLoginRequired) rather than string matching.","Never paste cookies with surrounding quotes/newlines into config.","Re-verify the cookie after any panlian password change."],"tags":["authentication","cookie","session-expired","upstream-api"],"backgroundTag":"authentication-required","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"}