feat: show api balance (#582)
* feat: show api balance * Update index.ts * 保留小数点后五位 * perf: 判断优化 --------- Co-authored-by: Redon <790348264@qq.com>
This commit is contained in:
parent
116ed7b0bf
commit
e46d3685a0
|
@ -24,6 +24,7 @@
|
|||
"common:cleanup": "rimraf node_modules && rimraf pnpm-lock.yaml"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.3.4",
|
||||
"chatgpt": "^5.0.10",
|
||||
"dotenv": "^16.0.3",
|
||||
"esno": "^0.16.3",
|
||||
|
|
|
@ -4,6 +4,7 @@ specifiers:
|
|||
'@antfu/eslint-config': ^0.35.3
|
||||
'@types/express': ^4.17.17
|
||||
'@types/node': ^18.14.6
|
||||
axios: ^1.3.4
|
||||
chatgpt: ^5.0.10
|
||||
dotenv: ^16.0.3
|
||||
eslint: ^8.35.0
|
||||
|
@ -18,6 +19,7 @@ specifiers:
|
|||
typescript: ^4.9.5
|
||||
|
||||
dependencies:
|
||||
axios: 1.3.4
|
||||
chatgpt: 5.0.10
|
||||
dotenv: 16.0.3
|
||||
esno: 0.16.3
|
||||
|
@ -766,6 +768,10 @@ packages:
|
|||
es-shim-unscopables: 1.0.0
|
||||
dev: true
|
||||
|
||||
/asynckit/0.4.0:
|
||||
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
|
||||
dev: false
|
||||
|
||||
/atomically/2.0.1:
|
||||
resolution: {integrity: sha512-sxBhVZUFBFhqSAsYMM3X2oaUi2NVDJ8U026FsIusM8gYXls9AYs/eXzgGrufs1Qjpkxi9zunds+75QUFz+m7UQ==}
|
||||
dependencies:
|
||||
|
@ -778,6 +784,16 @@ packages:
|
|||
engines: {node: '>= 0.4'}
|
||||
dev: true
|
||||
|
||||
/axios/1.3.4:
|
||||
resolution: {integrity: sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==}
|
||||
dependencies:
|
||||
follow-redirects: 1.15.2
|
||||
form-data: 4.0.0
|
||||
proxy-from-env: 1.1.0
|
||||
transitivePeerDependencies:
|
||||
- debug
|
||||
dev: false
|
||||
|
||||
/balanced-match/1.0.2:
|
||||
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
||||
dev: true
|
||||
|
@ -966,6 +982,13 @@ packages:
|
|||
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
|
||||
dev: true
|
||||
|
||||
/combined-stream/1.0.8:
|
||||
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
dependencies:
|
||||
delayed-stream: 1.0.0
|
||||
dev: false
|
||||
|
||||
/commander/4.1.1:
|
||||
resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
|
||||
engines: {node: '>= 6'}
|
||||
|
@ -1082,6 +1105,11 @@ packages:
|
|||
object-keys: 1.1.1
|
||||
dev: true
|
||||
|
||||
/delayed-stream/1.0.0:
|
||||
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
dev: false
|
||||
|
||||
/depd/2.0.0:
|
||||
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
@ -1852,12 +1880,31 @@ packages:
|
|||
resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==}
|
||||
dev: true
|
||||
|
||||
/follow-redirects/1.15.2:
|
||||
resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
|
||||
engines: {node: '>=4.0'}
|
||||
peerDependencies:
|
||||
debug: '*'
|
||||
peerDependenciesMeta:
|
||||
debug:
|
||||
optional: true
|
||||
dev: false
|
||||
|
||||
/for-each/0.3.3:
|
||||
resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
|
||||
dependencies:
|
||||
is-callable: 1.2.7
|
||||
dev: true
|
||||
|
||||
/form-data/4.0.0:
|
||||
resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
|
||||
engines: {node: '>= 6'}
|
||||
dependencies:
|
||||
asynckit: 0.4.0
|
||||
combined-stream: 1.0.8
|
||||
mime-types: 2.1.35
|
||||
dev: false
|
||||
|
||||
/formdata-polyfill/4.0.10:
|
||||
resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==}
|
||||
engines: {node: '>=12.20.0'}
|
||||
|
@ -2918,6 +2965,10 @@ packages:
|
|||
ipaddr.js: 1.9.1
|
||||
dev: false
|
||||
|
||||
/proxy-from-env/1.1.0:
|
||||
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
|
||||
dev: false
|
||||
|
||||
/punycode/2.3.0:
|
||||
resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==}
|
||||
engines: {node: '>=6'}
|
||||
|
|
|
@ -5,6 +5,7 @@ import { ChatGPTAPI, ChatGPTUnofficialProxyAPI } from 'chatgpt'
|
|||
import { SocksProxyAgent } from 'socks-proxy-agent'
|
||||
import { HttpsProxyAgent } from 'https-proxy-agent'
|
||||
import fetch from 'node-fetch'
|
||||
import axios from 'axios'
|
||||
import { sendResponse } from '../utils'
|
||||
import { isNotEmptyString } from '../utils/is'
|
||||
import type { ApiModel, ChatContext, ChatGPTUnofficialProxyAPIOptions, ModelConfig } from '../types'
|
||||
|
@ -99,14 +100,35 @@ async function chatReplyProcess(
|
|||
}
|
||||
}
|
||||
|
||||
async function chatConfig() {
|
||||
const reverseProxy = process.env.API_REVERSE_PROXY ?? '-'
|
||||
const socksProxy = (process.env.SOCKS_PROXY_HOST && process.env.SOCKS_PROXY_PORT) ? (`${process.env.SOCKS_PROXY_HOST}:${process.env.SOCKS_PROXY_PORT}`) : '-'
|
||||
const httpsProxy = (process.env.HTTPS_PROXY || process.env.ALL_PROXY) ?? '-'
|
||||
async function fetchBalance() {
|
||||
const OPENAI_API_KEY = process.env.OPENAI_API_KEY
|
||||
if (!isNotEmptyString(OPENAI_API_KEY))
|
||||
return Promise.resolve('-')
|
||||
|
||||
try {
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${OPENAI_API_KEY}`,
|
||||
}
|
||||
const response = await axios.get('https://api.openai.com/dashboard/billing/credit_grants', { headers })
|
||||
const balance = response.data.total_available ?? 0
|
||||
return Promise.resolve(balance.toFixed(3))
|
||||
}
|
||||
catch {
|
||||
return Promise.resolve('-')
|
||||
}
|
||||
}
|
||||
|
||||
async function chatConfig() {
|
||||
const balance = await fetchBalance()
|
||||
const reverseProxy = process.env.API_REVERSE_PROXY ?? '-'
|
||||
const httpsProxy = (process.env.HTTPS_PROXY || process.env.ALL_PROXY) ?? '-'
|
||||
const socksProxy = (process.env.SOCKS_PROXY_HOST && process.env.SOCKS_PROXY_PORT)
|
||||
? (`${process.env.SOCKS_PROXY_HOST}:${process.env.SOCKS_PROXY_PORT}`)
|
||||
: '-'
|
||||
return sendResponse<ModelConfig>({
|
||||
type: 'Success',
|
||||
data: { apiModel, reverseProxy, timeoutMs, socksProxy, httpsProxy },
|
||||
data: { apiModel, reverseProxy, timeoutMs, socksProxy, httpsProxy, balance },
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -133,6 +155,10 @@ function setupProxy(options: ChatGPTAPIOptions | ChatGPTUnofficialProxyAPIOption
|
|||
}
|
||||
}
|
||||
|
||||
function currentModel(): ApiModel {
|
||||
return apiModel
|
||||
}
|
||||
|
||||
export type { ChatContext, ChatMessage }
|
||||
|
||||
export { chatReplyProcess, chatConfig }
|
||||
export { chatReplyProcess, chatConfig, currentModel }
|
||||
|
|
|
@ -20,6 +20,7 @@ export interface ModelConfig {
|
|||
timeoutMs?: number
|
||||
socksProxy?: string
|
||||
httpsProxy?: string
|
||||
balance?: string
|
||||
}
|
||||
|
||||
export type ApiModel = 'ChatGPTAPI' | 'ChatGPTUnofficialProxyAPI' | undefined
|
||||
|
|
|
@ -10,6 +10,7 @@ interface ConfigState {
|
|||
apiModel?: string
|
||||
socksProxy?: string
|
||||
httpsProxy?: string
|
||||
balance?: string
|
||||
}
|
||||
|
||||
const loading = ref(false)
|
||||
|
@ -55,6 +56,7 @@ onMounted(() => {
|
|||
</p>
|
||||
</div>
|
||||
<p>{{ $t("setting.api") }}:{{ config?.apiModel ?? '-' }}</p>
|
||||
<p>{{ $t("setting.balance") }}:{{ config?.balance ?? '-' }}</p>
|
||||
<p>{{ $t("setting.reverseProxy") }}:{{ config?.reverseProxy ?? '-' }}</p>
|
||||
<p>{{ $t("setting.timeout") }}:{{ config?.timeoutMs ?? '-' }}</p>
|
||||
<p>{{ $t("setting.socks") }}:{{ config?.socksProxy ?? '-' }}</p>
|
||||
|
|
|
@ -63,6 +63,7 @@ export default {
|
|||
timeout: 'Timeout',
|
||||
socks: 'Socks',
|
||||
httpsProxy: 'HTTPS Proxy',
|
||||
balance: 'API Balance',
|
||||
},
|
||||
store: {
|
||||
local: 'Local',
|
||||
|
|
|
@ -63,6 +63,7 @@ export default {
|
|||
timeout: '超时',
|
||||
socks: 'Socks',
|
||||
httpsProxy: 'HTTPS Proxy',
|
||||
balance: 'API余额',
|
||||
},
|
||||
store: {
|
||||
local: '本地',
|
||||
|
|
|
@ -63,6 +63,7 @@ export default {
|
|||
timeout: '逾時',
|
||||
socks: 'Socks',
|
||||
httpsProxy: 'HTTPS Proxy',
|
||||
balance: 'API余額',
|
||||
},
|
||||
store: {
|
||||
local: '本機',
|
||||
|
|
Loading…
Reference in New Issue