mirror of
https://github.com/ikechan8370/chatgpt-plugin.git
synced 2025-12-17 05:47:11 +00:00
Conversation communication (#165)
* init: conversation in api3 (WIP) * feat: beta conversation * fix: fix some problems * fix: add help message
This commit is contained in:
parent
a1e72c7757
commit
a3b14b1a79
11 changed files with 658 additions and 215 deletions
|
|
@ -4,8 +4,6 @@ import StealthPlugin from 'puppeteer-extra-plugin-stealth'
|
|||
import { getOpenAIAuth } from './openai-auth.js'
|
||||
import delay from 'delay'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { pTimeout } from './common.js'
|
||||
console.log({ pTimeout })
|
||||
const chatUrl = 'https://chat.openai.com/chat'
|
||||
let puppeteer = {}
|
||||
|
||||
|
|
|
|||
117
utils/conversation.js
Normal file
117
utils/conversation.js
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
import fetch from 'node-fetch'
|
||||
import { Config } from '../config/index.js'
|
||||
|
||||
export async function getConversations (qq = '') {
|
||||
let accessToken = await redis.get('CHATGPT:TOKEN')
|
||||
if (!accessToken) {
|
||||
throw new Error('未绑定ChatGPT AccessToken,请使用#chatgpt设置token命令绑定token')
|
||||
}
|
||||
let response = await fetch(`${Config.apiBaseUrl}/api/conversations?offset=0&limit=20`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer ' + accessToken
|
||||
}
|
||||
})
|
||||
let json = await response.text()
|
||||
if (Config.debug) {
|
||||
logger.mark(json)
|
||||
}
|
||||
let conversations = JSON.parse(json)
|
||||
let result = conversations.items?.sort((a, b) => b.create_time - a.create_time)
|
||||
let map = {}
|
||||
for (let i = 0; i < conversations.items.length; i++) {
|
||||
// 老用户初次更新该功能,这里频繁请求可能会429。由并行改为串行以尽量降低频率。必要时可可能还要等待。
|
||||
let item = conversations.items[i]
|
||||
let cachedConversationLastMessage = await redis.get(`CHATGPT:CONVERSATION_LAST_MESSAGE_PROMPT:${item.id}`)
|
||||
if (!cachedConversationLastMessage) {
|
||||
map[item.id] = cachedConversationLastMessage
|
||||
} else {
|
||||
// 缓存中没有,就去查官方api
|
||||
let conversationDetailResponse = await fetch(`${Config.apiBaseUrl}/api/conversation/${item.id}`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer ' + accessToken
|
||||
}
|
||||
})
|
||||
let conversationDetail = await conversationDetailResponse.text()
|
||||
if (Config.debug) {
|
||||
logger.mark('conversation detail for conversation ' + item.id, conversationDetail)
|
||||
}
|
||||
conversationDetail = JSON.parse(conversationDetail)
|
||||
let messages = Object.values(conversationDetail.mapping)
|
||||
|
||||
messages = messages
|
||||
.filter(message => message.message)
|
||||
.map(messages => messages.message)
|
||||
|
||||
let messagesAssistant = messages.filter(messages => messages.role === 'assistant')
|
||||
.sort((a, b) => b.create_time - a.create_time)
|
||||
let messagesUser = messages.filter(messages => messages.role === 'user')
|
||||
.sort((a, b) => b.create_time - a.create_time)
|
||||
await redis.set(`CHATGPT:CONVERSATION_LENGTH:${item.id}`, messagesUser?.length || 0)
|
||||
let lastMessage = null
|
||||
if (messagesUser.length > 0) {
|
||||
lastMessage = messagesUser[0].content.parts[0]
|
||||
await redis.set(`CHATGPT:CONVERSATION_LAST_MESSAGE_PROMPT:${item.id}`, lastMessage)
|
||||
}
|
||||
if (messagesAssistant.length > 0) {
|
||||
await redis.set(`CHATGPT:CONVERSATION_LAST_MESSAGE_ID:${item.id}`, messagesAssistant[0].id)
|
||||
}
|
||||
await redis.set(`CHATGPT:CONVERSATION_CREATE_TIME:${item.id}`, new Date(conversationDetail.create_time * 1000).toLocaleString())
|
||||
map[item.id] = lastMessage
|
||||
}
|
||||
}
|
||||
let res = []
|
||||
let usingConversationId
|
||||
if (qq) {
|
||||
usingConversationId = await redis.get(`CHATGPT:QQ_CONVERSATION:${qq}`)
|
||||
}
|
||||
let promisesPostProcess = result.map(async conversation => {
|
||||
conversation.lastPrompt = map[conversation.id]
|
||||
conversation.create_time = new Date(conversation.create_time).toLocaleString()
|
||||
// 这里的时间格式还可以。不用管了。conversation.create_time =
|
||||
// title 全是 New chat,不要了
|
||||
delete conversation.title
|
||||
conversation.creater = await redis.get(`CHATGPT:CONVERSATION_CREATER_NICK_NAME:${conversation.id}`)
|
||||
if (qq && conversation.id === usingConversationId) {
|
||||
conversation.status = 'using'
|
||||
} else {
|
||||
conversation.status = 'normal'
|
||||
}
|
||||
if (conversation.lastPrompt?.length > 80) {
|
||||
conversation.lastPrompt = conversation.lastPrompt.slice(0, 80) + '......'
|
||||
}
|
||||
res.push(conversation)
|
||||
})
|
||||
await Promise.all(promisesPostProcess)
|
||||
return res
|
||||
}
|
||||
|
||||
export async function getLatestMessageIdByConversationId (conversationId) {
|
||||
let accessToken = await redis.get('CHATGPT:TOKEN')
|
||||
if (!accessToken) {
|
||||
throw new Error('未绑定ChatGPT AccessToken,请使用#chatgpt设置token命令绑定token')
|
||||
}
|
||||
let conversationDetailResponse = await fetch(`${Config.apiBaseUrl}/api/conversation/${conversationId}`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer ' + accessToken
|
||||
}
|
||||
})
|
||||
let conversationDetail = await conversationDetailResponse.text()
|
||||
if (Config.debug) {
|
||||
logger.mark('conversation detail for conversation ' + conversationId, conversationDetail)
|
||||
}
|
||||
conversationDetail = JSON.parse(conversationDetail)
|
||||
let messages = Object.values(conversationDetail.mapping)
|
||||
messages = messages
|
||||
.filter(message => message.message)
|
||||
.map(messages => messages.message)
|
||||
.filter(messages => messages.role === 'assistant')
|
||||
.sort((a, b) => b.create_time - a.create_time)
|
||||
await redis.set(`CHATGPT:CONVERSATION_LAST_MESSAGE_ID:${conversationId}`, messages[0].id)
|
||||
return messages[0].id
|
||||
}
|
||||
0
utils/redis-key.js
Normal file
0
utils/redis-key.js
Normal file
Loading…
Add table
Add a link
Reference in a new issue