{"record":{"id":"837ed6356ee28cbf","repo":"hmjz100/LinkSwift","slug":"br-837ed6","errorCode":null,"errorMessage":"错误：<br/>请先登录网盘后再获取文件呢~","messagePattern":"错误：<br/>请先登录网盘后再获取文件呢~","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"（改）网盘直链下载助手.user.js","lineNumber":7719,"sourceCode":"\t\t\t\t\t\tdevice_id: deviceId,\r\n\t\t\t\t\t\tmeta: {\r\n\t\t\t\t\t\t\tusername: \"\", phone_number: \"\", email: \"\",\r\n\t\t\t\t\t\t\tpackage_name: location.host,\r\n\t\t\t\t\t\t\tclient_version: clientVersion,\r\n\t\t\t\t\t\t\tcaptcha_sign: this._getCaptchaSign(clientId, clientVersion, location.host, deviceId, timestamp.toString()),\r\n\t\t\t\t\t\t\ttimestamp: timestamp.toString(),\r\n\t\t\t\t\t\t\tuser_id: userId\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}, { \"Content-Type\": \"application/json\" });\r\n\r\n\t\t\t\t\tif (res?.captcha_token) {\r\n\t\t\t\t\t\tcap = { token: res.captcha_token, expires_at: new Date(timestamp + res.expires_in * 1000).toString() };\r\n\t\t\t\t\t\tbase.setStorage(capKey, cap);\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tthrow new Error(`错误：<br/>令牌刷新失败，${res?.error_description || res?.error || \"未知错误\"}`);\r\n\t\t\t\t\t}\r\n\t\t\t\t} else if (!creds || !cap || !clientId || !deviceId) {\r\n\t\t\t\t\tthrow new Error(`错误：<br/>请先登录网盘后再获取文件呢~`);\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn { credentials: creds, captcha: cap, device_id: deviceId };\r\n\t\t\t});\r\n\t\t},\r\n\t\tasync getFileUrl(item, index, isRetry = false) {\r\n\t\t\tif (item.downloadUrl) return { index, downloadUrl: item.downloadUrl };\r\n\r\n\t\t\t// 获取当前内存中的 token\r\n\t\t\tconst token = await this.getToken(false, false).catch(e => {\r\n\t\t\t\tif (e instanceof Error) throw e;\r\n\t\t\t\tthrow new Error(e?.message || e || \"[迅雷云盘] 获取令牌失败\");\r\n\t\t\t});\r\n\r\n\t\t\tconst res = await base.get(config.$xunlei.api.getLink + item.id, {\r\n\t\t\t\t\"Authorization\": `${token.credentials?.token_type} ${token.credentials?.access_token}`,\r\n\t\t\t\t\"Content-Type\": \"application/json\",\r\n\t\t\t\t\"X-Captcha-Token\": token.captcha.token,\r","sourceCodeStart":7701,"sourceCodeEnd":7737,"githubUrl":"https://github.com/hmjz100/LinkSwift/blob/417ea5e28a3e1a90339710e17356e9fd22b8a34b/（改）网盘直链下载助手.user.js#L7701-L7737","documentation":"Pre-flight guard thrown before any API call when required login state is incomplete: it requires stored credentials (creds), a cached captcha token (cap), a clientId, and a deviceId. If any of these is missing or falsy, the library refuses to proceed and asks the user to log in to the cloud drive first. It is an intentional validation error, not an API failure.","triggerScenarios":"Invoking getFileUrl/getLink (or any flow calling this auth-check function) while !creds || !cap || !clientId || !deviceId — i.e. never logged in, or storage was cleared so cached credentials/captcha are gone.","commonSituations":"Fresh browser profile or incognito mode with no stored login; user cleared site data/localStorage; first-time use of the script without completing the cloud-drive login step; storage key renamed after a userscript upgrade.","solutions":["Open the cloud drive web page and complete the login flow in the userscript so creds/cap/clientId/deviceId are stored","Clear and redo the userscript login if storage appears partially populated (e.g. creds present but captcha missing)","Verify the script runs on the correct domain so storage keys and clientId/deviceId can be initialized","Reinstall/update the userscript if a version change altered storage key names"],"exampleFix":"// caller-side pre-check\nconst creds = GM_getValue(capKeyPrefix + 'creds');\nif (!creds || !GM_getValue(capKey) || !clientId || !deviceId) {\n  alert('请先在网盘页面登录再获取链接');\n  return;\n}","handlingStrategy":"validation","validationCode":"const { credentials, captcha, clientId, deviceId } = readAuthState();\nif (!credentials || !captcha || !clientId || !deviceId) { openLoginFlow(); return; }","typeGuard":"function isLoggedIn(state) { return Boolean(state && state.credentials && state.captcha && state.clientId && state.deviceId); }","tryCatchPattern":"try { await getLink(); } catch (e) { if (e.message.includes('请先登录网盘')) { showLoginModal(); } else throw e; }","preventionTips":["Check login state before showing the download button","Avoid clearing site data while using the script","Re-run login after userscript upgrades","Detect partial storage and force full re-login"],"tags":["authentication","login-required","validation","storage"],"backgroundTag":"login-required","analyzedSha":"417ea5e28a3e1a90339710e17356e9fd22b8a34b","analyzedAt":"2026-09-02T18:13:32.837Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T21:17:11.164Z"}