mirror of
https://github.com/ikechan8370/chatgpt-plugin.git
synced 2025-12-17 13:57:10 +00:00
feat: 查看API余额功能;修复频道和部分情况下无法读取群信息时的报错
This commit is contained in:
parent
bda0431714
commit
fe42df5928
4 changed files with 139 additions and 25 deletions
118
apps/chat.js
118
apps/chat.js
|
|
@ -109,6 +109,12 @@ export class chatgpt extends plugin {
|
||||||
/** 执行方法 */
|
/** 执行方法 */
|
||||||
fnc: 'bing'
|
fnc: 'bing'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
/** 命令正则匹配 */
|
||||||
|
reg: '^#claude[sS]*',
|
||||||
|
/** 执行方法 */
|
||||||
|
fnc: 'claude'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
/** 命令正则匹配 */
|
/** 命令正则匹配 */
|
||||||
reg: toggleMode === 'at' ? '^[^#][sS]*' : '^#chat[^gpt][sS]*',
|
reg: toggleMode === 'at' ? '^[^#][sS]*' : '^#chat[^gpt][sS]*',
|
||||||
|
|
@ -690,7 +696,7 @@ export class chatgpt extends plugin {
|
||||||
}
|
}
|
||||||
if (e.user_id == Bot.uin) return false
|
if (e.user_id == Bot.uin) return false
|
||||||
prompt = e.raw_message.trim()
|
prompt = e.raw_message.trim()
|
||||||
if (e.isGroup) {
|
if (e.isGroup && typeof this.e.group.getMemberMap === 'function') {
|
||||||
let mm = await this.e.group.getMemberMap()
|
let mm = await this.e.group.getMemberMap()
|
||||||
let me = mm.get(Bot.uin)
|
let me = mm.get(Bot.uin)
|
||||||
let card = me.card
|
let card = me.card
|
||||||
|
|
@ -1087,13 +1093,11 @@ export class chatgpt extends plugin {
|
||||||
this.reply('当前对话超过上限,已重置对话', false, { at: true })
|
this.reply('当前对话超过上限,已重置对话', false, { at: true })
|
||||||
await redis.del(`CHATGPT:CONVERSATIONS_BING:${e.sender.user_id}`)
|
await redis.del(`CHATGPT:CONVERSATIONS_BING:${e.sender.user_id}`)
|
||||||
return false
|
return false
|
||||||
}
|
} else if (response === 'Unexpected message author.') {
|
||||||
else if(response === 'Unexpected message author.') {
|
|
||||||
this.reply('无法回答当前话题,已重置对话', false, { at: true })
|
this.reply('无法回答当前话题,已重置对话', false, { at: true })
|
||||||
await redis.del(`CHATGPT:CONVERSATIONS_BING:${e.sender.user_id}`)
|
await redis.del(`CHATGPT:CONVERSATIONS_BING:${e.sender.user_id}`)
|
||||||
return false
|
return false
|
||||||
}
|
} else if (response === 'Throttled: Request is throttled.') {
|
||||||
else if(response === 'Throttled: Request is throttled.') {
|
|
||||||
this.reply('今日对话已达上限')
|
this.reply('今日对话已达上限')
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
@ -1208,13 +1212,11 @@ export class chatgpt extends plugin {
|
||||||
this.reply('当前对话超过上限,已重置对话', false, { at: true })
|
this.reply('当前对话超过上限,已重置对话', false, { at: true })
|
||||||
await redis.del(`CHATGPT:CONVERSATIONS_BING:${e.sender.user_id}`)
|
await redis.del(`CHATGPT:CONVERSATIONS_BING:${e.sender.user_id}`)
|
||||||
return false
|
return false
|
||||||
}
|
} else if (response === 'Unexpected message author.') {
|
||||||
else if(response === 'Unexpected message author.') {
|
|
||||||
this.reply('无法回答当前话题,已重置对话', false, { at: true })
|
this.reply('无法回答当前话题,已重置对话', false, { at: true })
|
||||||
await redis.del(`CHATGPT:CONVERSATIONS_BING:${e.sender.user_id}`)
|
await redis.del(`CHATGPT:CONVERSATIONS_BING:${e.sender.user_id}`)
|
||||||
return false
|
return false
|
||||||
}
|
} else if (response === 'Throttled: Request is throttled.') {
|
||||||
else if(response === 'Throttled: Request is throttled.') {
|
|
||||||
this.reply('今日对话已达上限')
|
this.reply('今日对话已达上限')
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
@ -1338,6 +1340,29 @@ export class chatgpt extends plugin {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async claude (e) {
|
||||||
|
if (!e.isMaster && e.isPrivate && !Config.enablePrivateChat) {
|
||||||
|
// await this.reply('ChatGpt私聊通道已关闭。')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (!Config.allowOtherMode) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
let ats = e.message.filter(m => m.type === 'at')
|
||||||
|
if (!e.atme && ats.length > 0) {
|
||||||
|
if (Config.debug) {
|
||||||
|
logger.mark('艾特别人了,没艾特我,忽略#bing')
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
let prompt = _.replace(e.raw_message.trimStart(), '#claude', '').trim()
|
||||||
|
if (prompt.length === 0) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
await this.abstractChat(e, prompt, 'claude')
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
async cacheContent (e, use, content, prompt, quote = [], mood = '', suggest = '', imgUrls = []) {
|
async cacheContent (e, use, content, prompt, quote = [], mood = '', suggest = '', imgUrls = []) {
|
||||||
let cacheData = { file: '', cacheUrl: Config.cacheUrl, status: '' }
|
let cacheData = { file: '', cacheUrl: Config.cacheUrl, status: '' }
|
||||||
cacheData.file = randomString()
|
cacheData.file = randomString()
|
||||||
|
|
@ -1503,7 +1528,7 @@ export class chatgpt extends plugin {
|
||||||
bingAIClient.opts.userToken = bingToken
|
bingAIClient.opts.userToken = bingToken
|
||||||
bingAIClient.opts.cookies = cookies
|
bingAIClient.opts.cookies = cookies
|
||||||
opt.messageType = allThrottled ? 'Chat' : 'SearchQuery'
|
opt.messageType = allThrottled ? 'Chat' : 'SearchQuery'
|
||||||
if (Config.enableGroupContext && e.isGroup) {
|
if (Config.enableGroupContext && e.isGroup && typeof e.group.getMemberMap === 'function') {
|
||||||
try {
|
try {
|
||||||
opt.groupId = e.group_id
|
opt.groupId = e.group_id
|
||||||
opt.qq = e.sender.user_id
|
opt.qq = e.sender.user_id
|
||||||
|
|
@ -1515,7 +1540,7 @@ export class chatgpt extends plugin {
|
||||||
opt.masterName = e.group.pickMember(parseInt(master)).card || e.group.pickMember(parseInt(master)).nickname
|
opt.masterName = e.group.pickMember(parseInt(master)).card || e.group.pickMember(parseInt(master)).nickname
|
||||||
}
|
}
|
||||||
if (master && !e.group) {
|
if (master && !e.group) {
|
||||||
opt.masterName = Bot.getFriendList().get(master)?.nickname
|
opt.masterName = Bot.getFriendList().get(parseInt(master))?.nickname
|
||||||
}
|
}
|
||||||
let latestChat = await e.group.getChatHistory(0, 1)
|
let latestChat = await e.group.getChatHistory(0, 1)
|
||||||
let seq = latestChat[0].seq
|
let seq = latestChat[0].seq
|
||||||
|
|
@ -1895,16 +1920,47 @@ export class chatgpt extends plugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
async totalAvailable (e) {
|
async totalAvailable (e) {
|
||||||
if (!Config.apiKey) {
|
if (!Config.OpenAiPlatformRefreshToken) {
|
||||||
this.reply('当前未配置OpenAI API key,请在锅巴面板或插件配置文件config/config.js中配置。若使用免费的API3则无需关心计费。')
|
this.reply('当前未配置platform.openai.com的刷新token,请发送【#chatgpt设置后台刷新token】进行配置。温馨提示:仅API模式需要关心计费。')
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// 查询OpenAI API剩余试用额度
|
let refreshRes = await newFetch('https://auth0.openai.com/oauth/token', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({
|
||||||
|
refresh_token: Config.OpenAiPlatformRefreshToken,
|
||||||
|
client_id: 'DRivsnm2Mu42T3KOpqdtwB3NYviHYzwD',
|
||||||
|
grant_type: 'refresh_token'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
if (refreshRes.status !== 200) {
|
||||||
|
let errMsg = await refreshRes.json()
|
||||||
|
if (errMsg.error === 'access_denied') {
|
||||||
|
await e.reply('刷新令牌失效,请重新发送【#chatgpt设置后台刷新token】进行配置。建议退出platform.openai.com重新登录后再获取和配置')
|
||||||
|
} else {
|
||||||
|
await e.reply('获取失败')
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
let newToken = await refreshRes.json()
|
||||||
|
// eslint-disable-next-line camelcase
|
||||||
|
const { access_token, refresh_token } = newToken
|
||||||
|
// eslint-disable-next-line camelcase
|
||||||
|
Config.OpenAiPlatformRefreshToken = refresh_token
|
||||||
|
let res = await newFetch(`${Config.openAiBaseUrl}/dashboard/onboarding/login`, {
|
||||||
|
headers: {
|
||||||
|
// eslint-disable-next-line camelcase
|
||||||
|
Authorization: `Bearer ${access_token}`
|
||||||
|
},
|
||||||
|
method: 'POST'
|
||||||
|
})
|
||||||
|
if (res.status === 200) {
|
||||||
|
let authRes = await res.json()
|
||||||
|
let sess = authRes.user.session.sensitive_id
|
||||||
newFetch(`${Config.openAiBaseUrl}/dashboard/billing/credit_grants`, {
|
newFetch(`${Config.openAiBaseUrl}/dashboard/billing/credit_grants`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
Authorization: 'Bearer ' + Config.apiKey
|
Authorization: 'Bearer ' + sess
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
|
|
@ -1913,13 +1969,45 @@ export class chatgpt extends plugin {
|
||||||
this.reply('获取失败:' + data.error.code)
|
this.reply('获取失败:' + data.error.code)
|
||||||
return false
|
return false
|
||||||
} else {
|
} else {
|
||||||
|
// eslint-disable-next-line camelcase
|
||||||
let total_granted = data.total_granted.toFixed(2)
|
let total_granted = data.total_granted.toFixed(2)
|
||||||
|
// eslint-disable-next-line camelcase
|
||||||
let total_used = data.total_used.toFixed(2)
|
let total_used = data.total_used.toFixed(2)
|
||||||
|
// eslint-disable-next-line camelcase
|
||||||
let total_available = data.total_available.toFixed(2)
|
let total_available = data.total_available.toFixed(2)
|
||||||
|
// eslint-disable-next-line camelcase
|
||||||
let expires_at = new Date(data.grants.data[0].expires_at * 1000).toLocaleDateString().replace(/\//g, '-')
|
let expires_at = new Date(data.grants.data[0].expires_at * 1000).toLocaleDateString().replace(/\//g, '-')
|
||||||
|
// eslint-disable-next-line camelcase
|
||||||
this.reply('总额度:$' + total_granted + '\n已经使用额度:$' + total_used + '\n当前剩余额度:$' + total_available + '\n到期日期(UTC):' + expires_at)
|
this.reply('总额度:$' + total_granted + '\n已经使用额度:$' + total_used + '\n当前剩余额度:$' + total_available + '\n到期日期(UTC):' + expires_at)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
let errorMsg = await res.text()
|
||||||
|
logger.error(errorMsg)
|
||||||
|
await e.reply(errorMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// // 查询OpenAI API剩余试用额度
|
||||||
|
// newFetch(`${Config.openAiBaseUrl}/dashboard/billing/credit_grants`, {
|
||||||
|
// method: 'GET',
|
||||||
|
// headers: {
|
||||||
|
// 'Content-Type': 'application/json',
|
||||||
|
// Authorization: 'Bearer ' + Config.apiKey
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// .then(response => response.json())
|
||||||
|
// .then(data => {
|
||||||
|
// if (data.error) {
|
||||||
|
// this.reply('获取失败:' + data.error.code)
|
||||||
|
// return false
|
||||||
|
// } else {
|
||||||
|
// let total_granted = data.total_granted.toFixed(2)
|
||||||
|
// let total_used = data.total_used.toFixed(2)
|
||||||
|
// let total_available = data.total_available.toFixed(2)
|
||||||
|
// let expires_at = new Date(data.grants.data[0].expires_at * 1000).toLocaleDateString().replace(/\//g, '-')
|
||||||
|
// this.reply('总额度:$' + total_granted + '\n已经使用额度:$' + total_used + '\n当前剩余额度:$' + total_available + '\n到期日期(UTC):' + expires_at)
|
||||||
|
// }
|
||||||
|
// })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -200,6 +200,11 @@ let helpData = [
|
||||||
icon: 'eat',
|
icon: 'eat',
|
||||||
title: '#chatgpt查看(API|Sydney)设定',
|
title: '#chatgpt查看(API|Sydney)设定',
|
||||||
desc: '查看AI当前的风格设定,文本形式返回,设定太长可能发不出来'
|
desc: '查看AI当前的风格设定,文本形式返回,设定太长可能发不出来'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'token',
|
||||||
|
title: '#chatgpt设置后台刷新token',
|
||||||
|
desc: '用于查看API余额。注意和配置的key保持同一账号。'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -231,6 +231,10 @@ export class ChatgptManagement extends plugin {
|
||||||
{
|
{
|
||||||
reg: '^#chatgpt角色列表$',
|
reg: '^#chatgpt角色列表$',
|
||||||
fnc: 'getTTSRoleList'
|
fnc: 'getTTSRoleList'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reg: '^#chatgpt设置后台(刷新|refresh)(t|T)oken$',
|
||||||
|
fnc: 'setOpenAIPlatformToken'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
@ -262,6 +266,7 @@ export class ChatgptManagement extends plugin {
|
||||||
}
|
}
|
||||||
await this.reply(roleList)
|
await this.reply(roleList)
|
||||||
}
|
}
|
||||||
|
|
||||||
async ttsSwitch (e) {
|
async ttsSwitch (e) {
|
||||||
let regExp = /#语音切换(.*)/
|
let regExp = /#语音切换(.*)/
|
||||||
let ttsMode = e.msg.match(regExp)[1]
|
let ttsMode = e.msg.match(regExp)[1]
|
||||||
|
|
@ -1222,4 +1227,19 @@ export class ChatgptManagement extends plugin {
|
||||||
const viewHost = Config.serverHost ? `http://${Config.serverHost}/` : `http://${await getPublicIP()}:${Config.serverPort || 3321}/`
|
const viewHost = Config.serverHost ? `http://${Config.serverHost}/` : `http://${await getPublicIP()}:${Config.serverPort || 3321}/`
|
||||||
await this.reply(`请登录${viewHost + 'admin/dashboard'}进行系统配置`, true)
|
await this.reply(`请登录${viewHost + 'admin/dashboard'}进行系统配置`, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async setOpenAIPlatformToken (e) {
|
||||||
|
this.setContext('doSetOpenAIPlatformToken')
|
||||||
|
await e.reply('请发送refreshToken\n你可以在已登录的platform.openai.com后台界面打开调试窗口,在终端中执行\nJSON.parse(localStorage.getItem(Object.keys(localStorage).filter(k => k.includes(\'auth0\'))[0])).body.refresh_token\n如果仍不能查看余额,请退出登录重新获取刷新令牌')
|
||||||
|
}
|
||||||
|
|
||||||
|
async doSetOpenAIPlatformToken () {
|
||||||
|
let token = this.e.msg
|
||||||
|
if (!token) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
Config.OpenAiPlatformRefreshToken = token.replaceAll('\'', '')
|
||||||
|
await this.e.reply('设置成功')
|
||||||
|
this.finish('doSetOpenAIPlatformToken')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ const defaultConfig = {
|
||||||
cacheEntry: false,
|
cacheEntry: false,
|
||||||
apiKey: '',
|
apiKey: '',
|
||||||
openAiBaseUrl: defaultOpenAIReverseProxy,
|
openAiBaseUrl: defaultOpenAIReverseProxy,
|
||||||
|
OpenAiPlatformRefreshToken: '',
|
||||||
openAiForceUseReverse: false,
|
openAiForceUseReverse: false,
|
||||||
drawCD: 30,
|
drawCD: 30,
|
||||||
model: '',
|
model: '',
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue