diff --git a/public/index.html b/public/index.html index ca66166..f14d1af 100644 --- a/public/index.html +++ b/public/index.html @@ -112,6 +112,7 @@ + @@ -210,7 +211,7 @@ const response_data = await response.json(); if (response.status === 200) { if (apps_subs === "onedrive" || apps_subs === "115cloud" - || apps_subs === "baiduyun" || apps_subs === "googleui") { + || apps_subs === "baiduyun" || apps_subs === "googleui" || apps_subs === "yandex") { window.location.href = response_data.text; } if (apps_subs === "123cloud") { diff --git a/src/index.ts b/src/index.ts index 82713c3..0833834 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,6 +9,7 @@ import * as ui115 from './115ui'; import * as ui123 from './123ui'; import * as baidu from './baidu'; import * as goapi from './goapi'; +import * as yandex from './yandex'; export type Bindings = { MAIN_URLS: string, baiduyun_ext: string, @@ -17,7 +18,9 @@ export type Bindings = { baiduyun_uid: string, baiduyun_key: string, cloud115_uid: string, cloud115_key: string, googleui_uid: string, googleui_key: string, + YANDEX_CLIENT_ID: string, YANDEX_CLIENT_SECRET: string, } + const app = new Hono<{ Bindings: Bindings }>() app.use("*", serveStatic({manifest: manifest, root: "./"})); @@ -80,5 +83,8 @@ app.get('/googleui/callback', async (c: Context) => { return goapi.oneToken(c); }); +app.get('/yandex/requests', async (c: Context) => {return yandex.yandexLogin(c)}); + +app.get('/yandex/callback', async (c: Context) => {return yandex.yandexCallBack(c)}); export default app \ No newline at end of file diff --git a/src/yandex.ts b/src/yandex.ts new file mode 100644 index 0000000..6c5a5ec --- /dev/null +++ b/src/yandex.ts @@ -0,0 +1,101 @@ +import {Context} from "hono"; +import {showErr} from "./error"; +import * as local from "hono/cookie"; +interface Token { + token_type?: string; + access_token?: string; + expires_in?: number; + refresh_token?: string; + scope?: string; + error?: string; + error_description?: string; +} + +export async function yandexLogin(c: Context) { + const env = c.env + const client_uid: string = c.req.query('client_uid'); + const client_key: string = c.req.query('client_key'); + const server_use: string = c.req.query('server_use'); + if (server_use == "false" && (!client_uid || !client_key)) + return c.json({text: "参数缺少"}, 500); + const params_all: Record = { + response_type: 'code', + client_id: server_use == "true" ? env.YANDEX_CLIENT_ID : client_uid, + }; + if (server_use == "false") { + local.setCookie(c, 'client_uid', client_uid); + local.setCookie(c, 'client_key', client_key); + } + local.setCookie(c, 'server_use', server_use); + const urlWithParams = new URL("https://oauth.yandex.com/authorize"); + Object.keys(params_all).forEach(key => { + urlWithParams.searchParams.append(key, params_all[key]); + }); + try { + return c.json({text: urlWithParams.href}, 200); + } catch (error) { + return c.json({text: error}, 500); + } +} + + +export async function yandexCallBack(c: Context) { + const env = c.env; + const code = c.req.query("code"); + const error = c.req.query("error"); + const error_description = c.req.query("error_description"); + + const getToken = async (): Promise => { + const params = new URLSearchParams(); + params.append("grant_type", "authorization_code"); + params.append("client_id", env.YANDEX_CLIENT_ID); + params.append("client_secret", env.YANDEX_CLIENT_SECRET); + params.append("code", code); + + const resp = await fetch("https://oauth.yandex.com/token", { + method: "POST", + body: params, + }); + + if (!resp.ok) { + throw new Error(`HTTP ${resp.status}: ${resp.statusText}`); + } + + return await resp.json(); + }; + + if (error) { + return c.redirect(showErr(error_description || error, "", "")); + } + + if (!code) { + return c.redirect(showErr("Authorization code missing", "", "")); + } + + try { + const token: Token = await getToken(); + console.log("Yandex token response:", token); + if (!token.error && token.access_token) { + const server_use = local.getCookie(c, 'server_use'); + const client_uid = local.getCookie(c, 'client_uid'); + const client_key = local.getCookie(c, 'client_key'); + + local.deleteCookie(c, 'server_use'); + local.deleteCookie(c, 'client_uid'); + local.deleteCookie(c, 'client_key'); + + return c.redirect( + `/?access_token=${token.access_token}` + + `&refresh_token=${token.refresh_token}` + + `&client_uid=${server_use == "true" ? "" : client_uid || ""}` + + `&client_key=${server_use == "true" ? "" : client_key || ""}` + + `&driver_txt=yandex_go` + ); + } else { + return c.redirect(showErr(token.error_description || token.error || "Token request failed", "", "")); + } + } catch (error) { + console.error("Token request error:", error); + return c.redirect(showErr("Failed to get access token", "", "")); + } +} \ No newline at end of file