fin onedrive official token

This commit is contained in:
pikachuim 2025-06-12 13:01:25 +08:00
parent a254e273e5
commit 9e6b420326
9 changed files with 215 additions and 76 deletions

11
.gitignore vendored Normal file
View File

@ -0,0 +1,11 @@
/tmp
/out-tsc
/node_modules
npm-debug.log*
yarn-debug.log*
yarn-error.log*
/.pnp
.pnp.js
.vscode/*

12
.idea/cf-worker-api.iml generated Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

2
.idea/modules.xml generated
View File

@ -2,7 +2,7 @@
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/CFWorker-api.iml" filepath="$PROJECT_DIR$/.idea/CFWorker-api.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/cf-worker-api.iml" filepath="$PROJECT_DIR$/.idea/cf-worker-api.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

83
.idea/workspace.xml generated Normal file
View File

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="987ac7e2-ceaa-49a2-b5c9-aed65a7c598d" name="更改" comment="fin onedrive official token">
<change afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/cf-worker-api.iml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/vcs.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/modules.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/modules.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/public/index.html" beforeDir="false" afterPath="$PROJECT_DIR$/public/index.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/public/static/style-all.css" beforeDir="false" afterPath="$PROJECT_DIR$/public/static/style-all.css" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/index.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/index.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/wrangler.jsonc.example" beforeDir="false" afterPath="$PROJECT_DIR$/wrangler.jsonc" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="ProjectColorInfo">{
&quot;associatedIndex&quot;: 4
}</component>
<component name="ProjectId" id="2yODHqSaoKJtcQuARzcBv8XxHZq" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"ModuleVcsDetector.initialDetectionPerformed": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
"RunOnceActivity.git.unshallow": "true",
"git-widget-placeholder": "main",
"last_opened_file_path": "G:/AList/cf-worker-api",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
"node.js.selected.package.tslint": "(autodetect)",
"nodejs_package_manager_path": "npm",
"settings.editor.selected.configurable": "preferences.language.and.region",
"ts.external.directory.path": "C:\\Users\\pikachuren\\AppData\\Local\\Programs\\WebStorm\\plugins\\javascript-plugin\\jsLanguageServicesImpl\\external",
"vue.rearranger.settings.migration": "true"
}
}]]></component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
<recent name="G:\AList\cf-worker-api" />
</key>
</component>
<component name="SharedIndexes">
<attachedChunks>
<set>
<option value="bundled-js-predefined-d6986cc7102b-b26f3e71634d-JavaScript-WS-251.26094.131" />
</set>
</attachedChunks>
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="默认任务">
<changelist id="987ac7e2-ceaa-49a2-b5c9-aed65a7c598d" name="更改" comment="" />
<created>1749696640494</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1749696640494</updated>
<workItem from="1749696641557" duration="119000" />
<workItem from="1749696773818" duration="18000" />
<workItem from="1749696801474" duration="7490000" />
</task>
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
<component name="VcsManagerConfiguration">
<MESSAGE value="fin onedrive official token" />
<option name="LAST_COMMIT_MESSAGE" value="fin onedrive official token" />
</component>
</project>

View File

@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AList Token获取工具</title>
<title>OpenList Token获取工具</title>
<link href="static/style-all.css" rel="stylesheet">
<link href="static/bootstrap.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@9"></script>
@ -14,10 +14,10 @@
<body>
<div class="container">
<div class="form-container" style="max-width: 1600px;">
<h1>AList Token获取工具</h1>
<h1>OpenList Token获取工具</h1>
<div class="input-group">
<label for="site-select">OneDrive 站点</label>
<label for="site-select">网盘名称</label>
<select id="site-select">
<option value="official" selected>OneDrive 官方站点</option>
<!-- <option value="cn">OneDrive 世纪互联</option>-->
@ -25,19 +25,19 @@
</div>
<div class="input-group">
<label for="client-id">客户端ID</label>
<label for="client-id">客户端ID(Client ID)</label>
<input type="text" id="client-id" name="client-id">
</div>
<div class="input-group">
<label for="app-secret">应用机密</label>
<label for="app-secret">应用机密(App Secret)</label>
<input type="text" id="app-secret" name="app-secret">
</div>
<div class="input-group">
<label for="callback-url">回调地址</label>
<input type="text" id="callback-url" name="callback-url" value="https://baidu.com/onedrive/callback"
readonly>
<label for="callback-url">回调地址(Callback URL)</label>
<input type="text" id="callback-url" name="callback-url" value="https://api.oplist.org/onedrive/callback"
readonly onclick="autoCopy(this)">
</div>
<div class="input-group">
@ -45,13 +45,13 @@
</div>
<div class="input-group">
<label for="refresh-token">访问秘钥(Access Token)</label>
<input type="text" id="access-token" name="access-token" readonly disabled="disabled">
<label for="access-token">访问秘钥(Access Token)</label>
<textarea type="text" id="access-token" name="access-token" readonly onclick="autoCopy(this)"></textarea>
</div>
<div class="input-group">
<label for="refresh-token">刷新秘钥(Refresh Token)</label>
<input type="text" id="refresh-token" name="refresh-token" readonly disabled="disabled">
<textarea type="text" id="refresh-token" name="refresh-token" readonly onclick="autoCopy(this)"></textarea>
</div>
</div>
</div>
@ -60,11 +60,22 @@
<script>
let intervalId;
// 获取登录秘钥 ==============================================================================
// 获取登录秘钥 #######################################################
async function getLogin() {
let apps_uuid = document.getElementById("client-id").value;
let apps_keys = document.getElementById("app-secret").value;
let post_urls = "/onedrive/requests?client_uid=" + apps_uuid + "&client_key=" + apps_keys;
if (apps_uuid === "" || apps_keys === "") {
Swal.fire({
position: 'top',
icon: 'info',
title: '获取失败',
text: '请先填写客户端ID和应用机密',
showConfirmButton: true,
});
return;
}
let post_urls = "/onedrive/requests?client_uid=" + apps_uuid
+ "&client_key=" + apps_keys;
try {
const response = await fetch(post_urls, {
method: 'GET', headers: {'Content-Type': 'application/json'}
@ -72,8 +83,8 @@
// 解析响应内容 ===============================================
const response_data = await response.json();
if (response.status === 200) {
window.open(response_data.text)
intervalId = setInterval(getToken, 3000);
// window.open(response_data.text)
window.location.href = response_data.text;
} else Swal.fire({
icon: 'error',
title: "获取秘钥失败: " + response_data.text,
@ -90,26 +101,44 @@
}
}
async function getToken() {
let apps_uuid = document.getElementById("client-id").value;
let post_urls = "/onedrive/gettoken?client_uid=" + apps_uuid;
try {
const response = await fetch(post_urls, {method: 'GET'});
// 解析响应内容 ===============================================
const response_data = await response.json();
if (response.status === 200) {
console.log(response_data);
clearInterval(intervalId);
}
} catch (error) {
// 自动复制内容 #####################################################
function autoCopy(on_element) {
// if (on_element.innerText === "") return;
navigator.clipboard.writeText(on_element.value).then(() => {
// 显示复制成功的提示
Swal.fire({
icon: 'error',
title: '获取秘钥失败: ' + error,
showConfirmButton: true,
timer: 1000
position: 'top',
icon: 'success',
title: '内容已复制',
showConfirmButton: false,
timer: 700
});
}
}).catch(err => {
// 复制失败时的处理
console.error('无法复制文本:', err);
Swal.fire({
position: 'top',
icon: 'error',
title: '复制失败',
text: '请手动复制',
showConfirmButton: true,
});
})
}
async function getToken() {
const strSearch = window.location.search;
const urlParams = new URLSearchParams(strSearch);
const client_uid = urlParams.get("client_uid");
const client_key = urlParams.get("client_key");
const access_token = urlParams.get("access_token");
const refresh_token = urlParams.get("refresh_token");
document.getElementById("client-id").value = client_uid;
document.getElementById("app-secret").value = client_key;
document.getElementById("access-token").value = access_token;
document.getElementById("refresh-token").value = refresh_token;
}
getToken();
</script>
</html>

View File

@ -49,7 +49,7 @@ h1 {
color: #555;
}
.input-group input, .input-group select {
.input-group input, .input-group select,.input-group textarea{
width: 100%;
padding: 10px;
border: 1px solid #ddd;

View File

@ -2,18 +2,21 @@ import {Context, Hono} from 'hono'
import {KVNamespace} from '@cloudflare/workers-types';
import {serveStatic} from 'hono/cloudflare-workers' // @ts-ignore
import manifest from '__STATIC_CONTENT_MANIFEST'
import * as local from "hono/cookie";
export type Bindings = {
MAIN_URLS: string, DATABASE: KVNamespace,
MAIN_URLS: string
}
const app = new Hono<{ Bindings: Bindings }>()
app.use("*", serveStatic({manifest: manifest, root: "./"}));
// 登录申请 ##############################################################################
app.get('/onedrive/requests', async (c) => {
const client_uid = <string>c.req.query('client_uid');
const client_key = <string>c.req.query('client_key');
const scopes_all = 'offline_access Files.ReadWrite.All';
const client_url = 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize';
// 请求参数 ==========================================================================
const params_all: Record<string, any> = {
client_id: client_uid,
scope: scopes_all,
@ -24,37 +27,26 @@ app.get('/onedrive/requests', async (c) => {
Object.keys(params_all).forEach(key => {
urlWithParams.searchParams.append(key, params_all[key]);
});
// 执行请求 ===========================================================================
try {
const response = await fetch(urlWithParams.href, {
method: 'GET',
});
console.log(response);
await c.env.DATABASE.put(client_uid, JSON.stringify({
"keys": client_key,
"data": "",
}))
local.setCookie(c, 'client_uid', client_uid);
local.setCookie(c, 'client_key', client_key);
return c.json({text: response.url}, 200);
} catch (error) {
return c.json({text: error}, 500);
}
})
app.get('/onedrive/callback/', async (c) => {
// 令牌申请 ##############################################################################
app.get('/onedrive/callback', async (c) => {
const login_data = <string>c.req.query('code');
const client_uid = <string>c.req.query('uuid');
const client_key = <string>c.req.query('keys');
console.log(login_data);
let data: string = <string>await c.env.DATABASE.get(client_uid)
// getToken(c,)
})
app.get('/onedrive/gettoken/', (c) => {
const client_uid = <string>c.req.query('uuid');
})
async function getToken(c: Context, client_uid: string, client_key: string, login_data: string) {
const client_uid: string | undefined = local.getCookie(c, 'client_uid')
const client_key: string | undefined = local.getCookie(c, 'client_key')
const client_url = 'https://login.microsoftonline.com/common/oauth2/v2.0/token';
console.log(login_data);
// 请求参数 ==========================================================================
const params_all = {
client_id: client_uid,
client_secret: client_key,
@ -62,24 +54,36 @@ async function getToken(c: Context, client_uid: string, client_key: string, logi
code: login_data,
grant_type: 'authorization_code'
};
// 执行请求 ===========================================================================
try {
const response = await fetch(client_url, {
const paramsString = new URLSearchParams(params_all).toString();
const response: Response = await fetch(client_url, {
method: 'POST',
body: params_all,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: paramsString,
});
const json = JSON.parse(response.body);
console.log(response);
if (!response.ok)
return c.json({text: response.text()}, 403);
const json: Record<string, any> = await response.json();
if (json.token_type === 'Bearer') {
return c.json({
access_token: json.access_token,
refresh_token: json.refresh_token ? json.refresh_token : 'Error',
});
} else {
return c.json({error: 'Invalid token type'});
return c.redirect(
`/?access_token=${json.access_token}`
+ `&refresh_token=${json.refresh_token}`
+ `&client_uid=${client_uid}`
+ `&client_key=${client_key}`);
// return c.json({
// access_token: json.access_token,
// refresh_token: json.refresh_token,
// });
}
} catch (error) {
return c.json({error: error});
console.error(error);
return c.json({text: error}, 500);
}
}
})
export default app

View File

@ -7,15 +7,9 @@
"nodejs_compat"
],
"vars": {
"MAIN_URLS": "example.com"
"MAIN_URLS": "api.oplist.org"
},
"site": {
"bucket": "./public"
},
"kv_namespaces": [
{
"binding": "DATABASE",
"id": "*******************************"
}
]
}