commit 3ab2184a435241f7be5eef857816cc5a82fbcc08 Author: abearxiong Date: Tue Dec 30 00:45:54 2025 +0800 upadte diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/github/index.ts b/github/index.ts new file mode 100644 index 0000000..83ec5cd --- /dev/null +++ b/github/index.ts @@ -0,0 +1 @@ +import './list.ts'; diff --git a/github/lib/get-token.ts b/github/lib/get-token.ts new file mode 100644 index 0000000..b2a79e3 --- /dev/null +++ b/github/lib/get-token.ts @@ -0,0 +1,50 @@ +import { useConfig } from '@kevisual/use-config'; + +type GithubConfig = { + clientId: string; + clientSecret: string; + redirect_uri: string; +}; +const { github } = useConfig<{ github: GithubConfig }>(); +// 获取 GitHub access_token 的函数 +async function getGithubToken(github: GithubConfig, code) { + const { clientId, clientSecret, redirect_uri } = github; + // 设置请求 URL 和参数 + const tokenUrl = 'https://github.com/login/oauth/access_token'; + const params = { + client_id: clientId, + client_secret: clientSecret, + code: code, + redirect_uri: redirect_uri, + }; + + try { + // 发送 POST 请求获取 access_token + const response = await fetch(tokenUrl, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json', + }, + body: JSON.stringify(params), + }); + + // 解析响应 JSON + const data: any = await response.json(); + + if (data.access_token) { + console.log('Access Token:', data.access_token); + return data.access_token; + } else { + console.error('Error:', data.error || 'Failed to get access token'); + return null; + } + } catch (error) { + console.error('Error fetching access token:', error); + return null; + } +} + +export const getAccessToken = async (code?: string) => { + return getGithubToken(github, code); +}; diff --git a/github/list.ts b/github/list.ts new file mode 100644 index 0000000..4c0b041 --- /dev/null +++ b/github/list.ts @@ -0,0 +1,48 @@ +import { app } from '@/app.ts'; +import { CustomError } from '@kevisual/router'; +import { getAccessToken } from './lib/get-token.ts'; +import { GithubModel } from './models/github.ts'; + +app + .route({ + path: 'github', + key: 'token', + middleware: ['auth'], + }) + .define(async (ctx) => { + const tokenUser = ctx.state.tokenUser; + const github = await GithubModel.findOne({ + where: { + uid: tokenUser.id, + }, + logging: false, + }); + if (github) { + ctx.body = { + githubToken: github.githubToken, + }; + return; + } + const { code } = ctx.query; + if (!code) { + throw new CustomError(400, 'code is required'); + } + try { + console.log('get access token from github, code:', code); + const token = await getAccessToken(code); + if (!token) { + throw new CustomError(500, 'Failed to get access token'); + } + await GithubModel.create({ + uid: tokenUser.id, + githubToken: token, + }); + ctx.body = { + githubToken: token, + }; + } catch (e) { + console.error('get access token from github error:', e); + throw new CustomError(500, 'Failed to get access token'); + } + }) + .addTo(app); diff --git a/github/models/github.ts b/github/models/github.ts new file mode 100644 index 0000000..7f1c15c --- /dev/null +++ b/github/models/github.ts @@ -0,0 +1,45 @@ +import { sequelize } from '../../../modules/sequelize.ts'; +import { DataTypes, Model } from 'sequelize'; + +export type Github = Partial>; + +/** + * 用户代码容器 + */ +export class GithubModel extends Model { + declare id: string; + declare title: string; + declare githubToken: string; + declare uid: string; +} +GithubModel.init( + { + id: { + type: DataTypes.UUID, + primaryKey: true, + defaultValue: DataTypes.UUIDV4, + comment: 'id', + }, + title: { + type: DataTypes.STRING, + defaultValue: '', + }, + githubToken: { + type: DataTypes.STRING, + defaultValue: '', + }, + uid: { + type: DataTypes.UUID, + allowNull: true, + }, + }, + { + sequelize, + tableName: 'kv_github', + paranoid: true, + }, +); + +// GithubModel.sync({ alter: true, logging: false }).catch((e) => { +// console.error('GithubModel sync', e); +// });