feat: 支持claude单人对话;注意:需要重新设置slack权限和配置插件

This commit is contained in:
ikechan8370 2023-04-16 19:12:56 +08:00
parent 3dee3ccec7
commit c1599e4f34
4 changed files with 115 additions and 33 deletions

View file

@ -216,7 +216,8 @@ export class chatgpt extends plugin {
// slackChannelId: Config.slackChannelId // slackChannelId: Config.slackChannelId
// }) // })
// await client.endConversation() // await client.endConversation()
await e.reply('由于Slack官方限制结束Claude对话请前往网站或客户端执行/reset。', true) await redis.del(`CHATGPT:SLACK_CONVERSATION:${e.sender.user_id}`)
await e.reply('claude对话已结束')
return return
} }
let ats = e.message.filter(m => m.type === 'at') let ats = e.message.filter(m => m.type === 'at')
@ -353,7 +354,7 @@ export class chatgpt extends plugin {
async endAllConversations (e) { async endAllConversations (e) {
let use = await redis.get('CHATGPT:USE') || 'api' let use = await redis.get('CHATGPT:USE') || 'api'
if (use === 'claude') { if (use === 'claude') {
await e.reply('由于Slack官方限制结束Claude对话请前往网站或客户端执行/reset。', true) await e.reply('claude暂不支持结束全部对话', true)
return return
} }
let deleted = 0 let deleted = 0
@ -1389,7 +1390,7 @@ export class chatgpt extends plugin {
slackUserToken: Config.slackUserToken, slackUserToken: Config.slackUserToken,
slackChannelId: Config.slackChannelId slackChannelId: Config.slackChannelId
}) })
let text = await client.sendMessage(prompt) let text = await client.sendMessage(prompt, e)
return { return {
text text
} }

View file

@ -458,9 +458,9 @@ export function supportGuoba () {
component: 'Input' component: 'Input'
}, },
{ {
field: 'slackChannelId', field: 'slackClaudeUserId',
label: 'Slack私聊频道号', label: 'Slack成员id',
bottomHelpMessage: '在Slack中与Claude机器人私聊的频道号。如果页面URL为https://app.slack.com/client/TXXXXXXXX/DXXXXXXXXX/则频道号就是DXXXXXXXXX', bottomHelpMessage: '在Slack中点击Claude头像查看详情其中的成员ID复制过来',
component: 'Input' component: 'Input'
}, },
{ {

View file

@ -94,8 +94,9 @@ const defaultConfig = {
ttsRegex: '/匹配规则/匹配模式', ttsRegex: '/匹配规则/匹配模式',
slackUserToken: '', slackUserToken: '',
slackBotUserToken: '', slackBotUserToken: '',
slackChannelId: '', // slackChannelId: '',
slackSigningSecret: '', slackSigningSecret: '',
slackClaudeUserId: '',
version: 'v2.5.3' version: 'v2.5.3'
} }
const _path = process.cwd() const _path = process.cwd()

View file

@ -29,40 +29,120 @@ export class SlackClaudeClient {
} }
} }
async sendMessage (prompt) { async sendMessage (prompt, e, t = 0) {
let sendResponse = await this.app.client.chat.postMessage({ if (t > 10) {
as_user: true, return 'claude 未响应'
text: `${prompt}`, }
let qq = e.sender.user_id
let channels = await this.app.client.conversations.list({
token: this.config.slackUserToken, token: this.config.slackUserToken,
channel: this.config.slackChannelId types: 'public_channel,private_channel'
}) })
let ts = sendResponse.ts let channel = channels.channels.filter(c => c.name === '' + qq)
let response = '_Typing…_' if (!channel || channel.length === 0) {
let tryTimes = 0 let createChannelResponse = await this.app.client.conversations.create({
while (response.trim().endsWith('_Typing…_')) {
let replies = await this.app.client.conversations.history({
token: this.config.slackUserToken, token: this.config.slackUserToken,
channel: this.config.slackChannelId, name: qq + '',
limit: 1, is_private: true
oldest: ts
}) })
if (replies.messages.length > 0 && replies.messages[0].bot_profile) { channel = createChannelResponse.channel
response = replies.messages[0].text await this.app.client.conversations.invite({
if (Config.debug) { token: this.config.slackUserToken,
let text = response.replace('_Typing…_', '') channel: channel.id,
if (text) { users: 'U053NDP2YRF'
logger.info(response.replace('_Typing…_', '')) })
await delay(1000)
} else {
channel = channel[0]
}
let conversationId = await redis.get(`CHATGPT:SLACK_CONVERSATION:${qq}`)
if (!conversationId) {
let sendResponse = await this.app.client.chat.postMessage({
as_user: true,
text: `<@${Config.slackClaudeUserId}> ${prompt}`,
token: this.config.slackUserToken,
channel: channel.id
})
let ts = sendResponse.ts
let response = '_Typing…_'
let tryTimes = 0
while (response.trim().endsWith('_Typing…_')) {
let replies = await this.app.client.conversations.replies({
token: this.config.slackUserToken,
channel: channel.id,
limit: 1000,
ts: ts
})
await await redis.set(`CHATGPT:SLACK_CONVERSATION:${qq}`, `${ts}`)
if (replies.messages.length > 0) {
let formalMessages = replies.messages.filter(m => m.text.indexOf('Acceptable Use Policy') === -1)
if (!formalMessages[formalMessages.length - 1].bot_profile) {
// 问题的下一句不是bot回复的这属于意料之外的问题可能是多人同时问问题导致 再问一次吧
return await this.sendMessage(prompt, e, t + 1)
}
let reply = formalMessages[formalMessages.length - 1]
if (reply.text !== `<@${Config.slackClaudeUserId}> ${prompt}`) {
response = reply.text
if (Config.debug) {
let text = response.replace('_Typing…_', '')
if (text) {
logger.info(response.replace('_Typing…_', ''))
}
}
} }
} }
await delay(500)
tryTimes++
if (tryTimes > 10 && response === '_Typing…_') {
// 过了5秒还没任何回复就重新发一下试试
logger.warn('claude没有响应重试中')
return await this.sendMessage(prompt, e, t + 1)
}
} }
await delay(500) return response
tryTimes++ } else {
if (tryTimes > 10 && response === '_Typing…_') { await this.app.client.chat.postMessage({
// 过了5秒还没任何回复就重新发一下试试 as_user: true,
logger.warn('claude没有响应重试中') text: `<@${Config.slackClaudeUserId}> ${prompt}`,
return await this.sendMessage(prompt) token: this.config.slackUserToken,
channel: channel.id,
thread_ts: conversationId
})
let response = '_Typing…_'
let tryTimes = 0
while (response.trim().endsWith('_Typing…_')) {
let replies = await this.app.client.conversations.replies({
token: this.config.slackUserToken,
channel: channel.id,
limit: 1000,
ts: conversationId
})
if (replies.messages.length > 0) {
let formalMessages = replies.messages.filter(m => m.text.indexOf('Acceptable Use Policy') === -1)
if (!formalMessages[formalMessages.length - 1].bot_profile) {
// 问题的下一句不是bot回复的这属于意料之外的问题可能是多人同时问问题导致 再问一次吧
return await this.sendMessage(prompt, e, t + 1)
}
let reply = formalMessages[formalMessages.length - 1]
if (reply.text !== `<@${Config.slackClaudeUserId}> ${prompt}`) {
response = reply.text
if (Config.debug) {
let text = response.replace('_Typing…_', '')
if (text) {
logger.info(response.replace('_Typing…_', ''))
}
}
}
}
await delay(500)
tryTimes++
if (tryTimes > 10 && response === '_Typing…_') {
// 过了5秒还没任何回复就重新发一下试试
logger.warn('claude没有响应重试中')
return await this.sendMessage(prompt, e, t + 1)
}
} }
return response
} }
return response
} }
} }