chore: version 2.10.0

* feat: 权限验证功能

* chore: v2.10.0

* feat: 500 服务异常页面

* feat: 只有结束才会滚动到底部

* chore: 修改 CHANGELOG

* chore: 不存在时输出默认报错
This commit is contained in:
Redon
2023-03-07 22:12:15 +08:00
committed by GitHub
parent a2ffa3cb3a
commit ffd4da91cf
30 changed files with 376 additions and 60 deletions

View File

@@ -13,6 +13,9 @@ API_REVERSE_PROXY=
# timeout
TIMEOUT_MS=100000
# Secret key
AUTH_SECRET_KEY=
# Socks Proxy Host
SOCKS_PROXY_HOST=

View File

@@ -24,7 +24,7 @@
"common:cleanup": "rimraf node_modules && rimraf pnpm-lock.yaml"
},
"dependencies": {
"chatgpt": "^5.0.7",
"chatgpt": "^5.0.8",
"dotenv": "^16.0.3",
"esno": "^0.16.3",
"express": "^4.18.2",

View File

@@ -4,7 +4,7 @@ specifiers:
'@antfu/eslint-config': ^0.35.3
'@types/express': ^4.17.17
'@types/node': ^18.14.6
chatgpt: ^5.0.7
chatgpt: ^5.0.8
dotenv: ^16.0.3
eslint: ^8.35.0
esno: ^0.16.3
@@ -17,7 +17,7 @@ specifiers:
typescript: ^4.9.5
dependencies:
chatgpt: 5.0.7
chatgpt: 5.0.8
dotenv: 16.0.3
esno: 0.16.3
express: 4.18.2
@@ -902,8 +902,8 @@ packages:
resolution: {integrity: sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==}
dev: true
/chatgpt/5.0.7:
resolution: {integrity: sha512-wy69++JDNS0xKi+6rP+HDOByXBafQIVynHnlQw09apuDntGSKfwBRY902N8Q7/ZFU/XET+8NpJiio2iI69IWYw==}
/chatgpt/5.0.8:
resolution: {integrity: sha512-Bjh7Y15QIsZ+SkQvbbZGymv1PGxkZ7X1vwqAwvyqaMMhbipU4kxht/GL62VCxhoUCXPwxTfScbFeNFtNldgqaw==}
engines: {node: '>=14'}
hasBin: true
dependencies:

View File

@@ -8,11 +8,14 @@ import { sendResponse } from '../utils'
import type { ApiModel, ChatContext, ChatGPTUnofficialProxyAPIOptions, ModelConfig } from '../types'
const ErrorCodeMessage: Record<string, string> = {
401: '提供错误的API密钥 | Incorrect API key provided',
429: '服务器限流,请稍后再试 | Server was limited, please try again later',
503: '服务器繁忙,请稍后再试 | Server is busy, please try again later',
500: '服务器繁忙,请稍后再试 | Server is busy, please try again later',
403: '服务器拒绝访问,请稍后再试 | Server refused to access, please try again later',
400: '[OpenAI] 模型的最大上下文长度是4096个令牌请减少信息的长度。| This model\'s maximum context length is 4096 tokens.',
401: '[OpenAI] 提供错误的API密钥 | Incorrect API key provided',
403: '[OpenAI] 服务器拒绝访问,请稍后再试 | Server refused to access, please try again later',
429: '[OpenAI] 服务器限流,请稍后再试 | Server was limited, please try again later',
502: '[OpenAI] 错误的网关 | Bad Gateway',
503: '[OpenAI] 服务器繁忙,请稍后再试 | Server is busy, please try again later',
504: '[OpenAI] 网关超时 | Gateway Time-out',
500: '[OpenAI] 服务器繁忙,请稍后再试 | Internal Server Error',
}
dotenv.config()
@@ -106,10 +109,11 @@ async function chatReplyProcess(
return sendResponse({ type: 'Success', data: response })
}
catch (error: any) {
const code = error.statusCode || 'unknown'
const code = error.statusCode
global.console.log(error)
if (Reflect.has(ErrorCodeMessage, code))
return sendResponse({ type: 'Fail', message: ErrorCodeMessage[code] })
return sendResponse({ type: 'Fail', message: `${error.statusCode}-${error.statusText}` })
return sendResponse({ type: 'Fail', message: error.message ?? 'Please check the back-end console' })
}
}

View File

@@ -1,6 +1,7 @@
import express from 'express'
import type { ChatContext, ChatMessage } from './chatgpt'
import { chatConfig, chatReplyProcess } from './chatgpt'
import { auth } from './middleware/auth'
const app = express()
const router = express.Router()
@@ -15,7 +16,7 @@ app.all('*', (_, res, next) => {
next()
})
router.post('/chat-process', async (req, res) => {
router.post('/chat-process', auth, async (req, res) => {
res.setHeader('Content-type', 'application/octet-stream')
try {
@@ -44,6 +45,33 @@ router.post('/config', async (req, res) => {
}
})
router.post('/session', async (req, res) => {
try {
const AUTH_SECRET_KEY = process.env.AUTH_SECRET_KEY
const hasAuth = typeof AUTH_SECRET_KEY === 'string' && AUTH_SECRET_KEY.length > 0
res.send({ status: 'Success', message: '', data: { auth: hasAuth } })
}
catch (error) {
res.send({ status: 'Fail', message: error.message, data: null })
}
})
router.post('/verify', async (req, res) => {
try {
const { token } = req.body as { token: string }
if (!token)
throw new Error('Secret key is empty')
if (process.env.AUTH_SECRET_KEY !== token)
throw new Error('密钥无效 | Secret key is invalid')
res.send({ status: 'Success', message: 'Verify successfully', data: null })
}
catch (error) {
res.send({ status: 'Fail', message: error.message, data: null })
}
})
app.use('', router)
app.use('/api', router)

View File

@@ -0,0 +1,19 @@
const auth = async (req, res, next) => {
const AUTH_SECRET_KEY = process.env.AUTH_SECRET_KEY
if (typeof AUTH_SECRET_KEY === 'string' && AUTH_SECRET_KEY.length > 0) {
try {
const Authorization = req.header('Authorization')
if (!Authorization || Authorization.replace('Bearer ', '').trim() !== AUTH_SECRET_KEY.trim())
throw new Error('Error: 无访问权限 | No access rights')
next()
}
catch (error) {
res.send({ status: 'Unauthorized', message: error.message ?? 'Please authenticate.', data: null })
}
}
else {
next()
}
}
export { auth }