OpenAI Plus剩余额度查询 (#161)

This commit is contained in:
夏叶 2023-02-17 19:15:06 +08:00 committed by GitHub
parent dd805136e0
commit 37f75a64fa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 52 additions and 22 deletions

View file

@ -42,7 +42,7 @@ mjAPI.config({
mjAPI.start() mjAPI.start()
export class chatgpt extends plugin { export class chatgpt extends plugin {
constructor () { constructor() {
let toggleMode = Config.toggleMode let toggleMode = Config.toggleMode
super({ super({
/** 功能名称 */ /** 功能名称 */
@ -90,6 +90,11 @@ export class chatgpt extends plugin {
reg: '#移出(chat)?队列首位', reg: '#移出(chat)?队列首位',
fnc: 'removeQueueFirst', fnc: 'removeQueueFirst',
permission: 'master' permission: 'master'
},
{
reg: '#OpenAI(剩余)?(余额|额度)',
fnc: 'totalAvailable',
permission: 'master'
} }
] ]
@ -102,7 +107,7 @@ export class chatgpt extends plugin {
* @param e * @param e
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
async getConversations (e) { async getConversations(e) {
let keys = await redis.keys('CHATGPT:CONVERSATIONS:*') let keys = await redis.keys('CHATGPT:CONVERSATIONS:*')
if (!keys || keys.length === 0) { if (!keys || keys.length === 0) {
await this.reply('当前没有人正在与机器人对话', true) await this.reply('当前没有人正在与机器人对话', true)
@ -124,7 +129,7 @@ export class chatgpt extends plugin {
* @param e * @param e
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
async destroyConversations (e) { async destroyConversations(e) {
let ats = e.message.filter(m => m.type === 'at') let ats = e.message.filter(m => m.type === 'at')
if (ats.length === 0) { if (ats.length === 0) {
let c = await redis.get(`CHATGPT:CONVERSATIONS:${e.sender.user_id}`) let c = await redis.get(`CHATGPT:CONVERSATIONS:${e.sender.user_id}`)
@ -148,17 +153,17 @@ export class chatgpt extends plugin {
} }
} }
async help (e) { async help(e) {
let response = 'chatgpt-plugin使用帮助文字版\n' + let response = 'chatgpt-plugin使用帮助文字版\n' +
'@我+聊天内容: 发起对话与AI进行聊天\n' + '@我+聊天内容: 发起对话与AI进行聊天\n' +
'#chatgpt对话列表: 查看当前发起的对话\n' + '#chatgpt对话列表: 查看当前发起的对话\n' +
'#结束对话: 结束自己或@用户的对话\n' + '#结束对话: 结束自己或@用户的对话\n' +
'#chatgpt帮助: 查看本帮助\n' + '#chatgpt帮助: 查看本帮助\n' +
'源代码https://github.com/ikechan8370/chatgpt-plugin' '源代码https://github.com/ikechan8370/chatgpt-plugin'
await this.reply(response) await this.reply(response)
} }
async switch2Picture (e) { async switch2Picture(e) {
let userSetting = await redis.get(`CHATGPT:USER:${e.sender.user_id}`) let userSetting = await redis.get(`CHATGPT:USER:${e.sender.user_id}`)
if (!userSetting) { if (!userSetting) {
userSetting = { usePicture: true } userSetting = { usePicture: true }
@ -170,7 +175,7 @@ export class chatgpt extends plugin {
await this.reply('ChatGPT回复已转换为图片模式') await this.reply('ChatGPT回复已转换为图片模式')
} }
async switch2Text (e) { async switch2Text(e) {
let userSetting = await redis.get(`CHATGPT:USER:${e.sender.user_id}`) let userSetting = await redis.get(`CHATGPT:USER:${e.sender.user_id}`)
if (!userSetting) { if (!userSetting) {
userSetting = { usePicture: false } userSetting = { usePicture: false }
@ -186,7 +191,7 @@ export class chatgpt extends plugin {
* #chatgpt * #chatgpt
* @param e oicq传递的事件参数e * @param e oicq传递的事件参数e
*/ */
async chatgpt (e) { async chatgpt(e) {
let prompt let prompt
if (this.toggleMode === 'at') { if (this.toggleMode === 'at') {
if (!e.msg || e.msg.startsWith('#')) { if (!e.msg || e.msg.startsWith('#')) {
@ -328,12 +333,12 @@ export class chatgpt extends plugin {
/** 最后回复消息 */ /** 最后回复消息 */
await e.runtime.render('chatgpt-plugin', 'content/index', { content: converted, prompt, senderName: e.sender.nickname }) await e.runtime.render('chatgpt-plugin', 'content/index', { content: converted, prompt, senderName: e.sender.nickname })
} else { } else {
if (response.length > 1000 ) { if (response.length > 1000) {
// 文字过多时自动切换到图片模式输出 // 文字过多时自动切换到图片模式输出
let converted = converter.makeHtml(response) let converted = converter.makeHtml(response)
await e.runtime.render('chatgpt-plugin', 'content/index', { content: converted, prompt, quote: chatMessage.quote, senderName: e.sender.nickname }) await e.runtime.render('chatgpt-plugin', 'content/index', { content: converted, prompt, quote: chatMessage.quote, senderName: e.sender.nickname })
} else } else
await this.reply(`${response}`, e.isGroup) await this.reply(`${response}`, e.isGroup)
if (chatMessage?.quote) { if (chatMessage?.quote) {
let quotemessage = [] let quotemessage = []
chatMessage.quote.forEach(function (item, index) { chatMessage.quote.forEach(function (item, index) {
@ -341,14 +346,14 @@ export class chatgpt extends plugin {
quotemessage.push(`${item}\n`) quotemessage.push(`${item}\n`)
} }
}) })
if(quotemessage.length > 0) if (quotemessage.length > 0)
this.reply(await makeForwardMsg(this.e, quotemessage)) this.reply(await makeForwardMsg(this.e, quotemessage))
} }
} }
if (use !== 'bing') { if (use !== 'bing') {
// 移除队列首位,释放锁 // 移除队列首位,释放锁
await redis.lPop('CHATGPT:CHAT_QUEUE', 0) await redis.lPop('CHATGPT:CHAT_QUEUE', 0)
} }
} catch (e) { } catch (e) {
logger.error(e) logger.error(e)
if (use !== 'bing') { if (use !== 'bing') {
@ -359,7 +364,7 @@ export class chatgpt extends plugin {
} }
} }
async sendMessage (prompt, conversation = {}, use) { async sendMessage(prompt, conversation = {}, use) {
if (!conversation) { if (!conversation) {
conversation = { conversation = {
timeoutMs: Config.defaultTimeoutMs timeoutMs: Config.defaultTimeoutMs
@ -440,7 +445,7 @@ export class chatgpt extends plugin {
}) })
*/ */
response = await bingAIClient.sendMessage(prompt, conversation || {}, (token) => { response = await bingAIClient.sendMessage(prompt, conversation || {}, (token) => {
reply += token reply += token
}) })
if (response.details.adaptiveCards?.[0]?.body?.[0]?.text?.trim()) { if (response.details.adaptiveCards?.[0]?.body?.[0]?.text?.trim()) {
if (response.response === undefined) { if (response.response === undefined) {
@ -510,12 +515,12 @@ export class chatgpt extends plugin {
} }
} }
async emptyQueue (e) { async emptyQueue(e) {
await redis.lTrim('CHATGPT:CHAT_QUEUE', 1, 0) await redis.lTrim('CHATGPT:CHAT_QUEUE', 1, 0)
await this.reply('已清空当前等待队列') await this.reply('已清空当前等待队列')
} }
async removeQueueFirst (e) { async removeQueueFirst(e) {
let uid = await redis.lPop('CHATGPT:CHAT_QUEUE', 0) let uid = await redis.lPop('CHATGPT:CHAT_QUEUE', 0)
if (!uid) { if (!uid) {
await this.reply('当前等待队列为空') await this.reply('当前等待队列为空')
@ -524,12 +529,32 @@ export class chatgpt extends plugin {
} }
} }
async totalAvailable(e) {
// 查询OpenAI Plus剩余试用额度
fetch('https://api.openai.com/dashboard/billing/credit_grants', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + Config.apiKey,
}
})
.then(response => response.json())
.then(data => {
if (data.error) {
console.log(data.error)
return false
} else {
this.reply('总额度:$' + data.total_granted + '\n已使用额度$' + data.total_used + '\n当前剩余额度$' + data.total_available)
}
})
}
/** /**
* #chatgpt * #chatgpt
* @param prompt 问题 * @param prompt 问题
* @param conversation 对话 * @param conversation 对话
*/ */
async chatgptBrowserBased (prompt, conversation) { async chatgptBrowserBased(prompt, conversation) {
let option = { markdown: true } let option = { markdown: true }
if (Config['2captchaToken']) { if (Config['2captchaToken']) {
option.captchaToken = Config['2captchaToken'] option.captchaToken = Config['2captchaToken']

View file

@ -71,6 +71,11 @@ let helpData = [
title: '#chatgpt设置必应token', title: '#chatgpt设置必应token',
desc: '设置ChatGPT或bing的Token' desc: '设置ChatGPT或bing的Token'
}, },
{
icon: 'help',
title: '#OpenAI剩余额度',
desc: '查询OpenAI Plus剩余试用额度'
},
{ {
icon: 'help', icon: 'help',
title: '#chatgpt模式帮助', title: '#chatgpt模式帮助',