| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- const API = require('../../../lib/API')
- const { BaseStdResponse } = require('../../../BaseStdResponse')
- const AccessControl = require('../../../lib/AccessControl')
- const db = require('../../../plugin/DataBase/db')
- const OneBotV11 = require('../../../plugin/OneBot/OneBotV11')
- const { ConversationService } = require('../../../lib/AIChat/ConversationService')
- const { checkQuota, consumeQuota } = require('../../../lib/AIChat/QuotaService')
- class SendMessage extends API {
- constructor() {
- super()
- this.setPath('/AIChat/Message')
- this.setMethod('POST')
- }
- async onRequest(req, res) {
- const { uuid, session, conversation_id, content, images = [] } = req.body
- if ([uuid, session].some(v => v === '' || v === null || v === undefined)) {
- return res.json({ ...BaseStdResponse.MISSING_PARAMETER })
- }
- if (!await AccessControl.checkSession(uuid, session)) {
- return res.status(401).json({ ...BaseStdResponse.ACCESS_DENIED })
- }
- const cleanContent = String(content || '').trim()
- const cleanImages = Array.isArray(images) ? images.filter(Boolean) : []
- if (!cleanContent && cleanImages.length === 0) {
- return res.json({ ...BaseStdResponse.MISSING_PARAMETER, msg: '请输入消息或上传图片' })
- }
- if (conversation_id) {
- const rows = await db.query(
- 'SELECT channel FROM ai_chat_conversation WHERE id = ? AND create_user = ? AND state = 1 LIMIT 1',
- [conversation_id, uuid]
- )
- if (!rows || rows.length !== 1) return res.json({ ...BaseStdResponse.ERR, msg: '会话不存在或无权发送' })
- if (rows[0].channel === 'wechat') return res.json({ ...BaseStdResponse.ERR, msg: '微信会话仅支持查看,请在微信内继续对话' })
- }
- const quotaCheck = await checkQuota({ uuid, channel: 'web' })
- if (!quotaCheck.allowed) {
- return res.json({ ...BaseStdResponse.ERR, msg: quotaCheck.message || '今日与小妍助理聊天次数已达上限,请明天再试' })
- }
- const saved = await ConversationService.addUserMessage({
- uuid,
- conversationId: conversation_id,
- content: cleanContent,
- images: cleanImages,
- channel: 'web'
- })
- if (!saved) return res.json({ ...BaseStdResponse.ERR, msg: '会话不存在或无权发送' })
- if (saved.missingContent) return res.json({ ...BaseStdResponse.MISSING_PARAMETER, msg: '请输入消息或上传图片' })
- if (saved.readonly) return res.json({ ...BaseStdResponse.ERR, msg: '微信会话仅支持查看,请在微信内继续对话' })
- const quota = await consumeQuota({ uuid, channel: 'web' })
- if (!quota.allowed) {
- await ConversationService.addSystemMessage({
- conversationId: saved.conversationId,
- content: quota.message || '今日与小妍助理聊天次数已达上限,请明天再试',
- status: 'error',
- errorMsg: 'quota exceeded',
- channel: 'web'
- })
- return res.json({ ...BaseStdResponse.ERR, msg: quota.message || '今日与小妍助理聊天次数已达上限,请明天再试' })
- }
- res.json({
- ...BaseStdResponse.OK,
- data: {
- message_id: saved.messageId,
- conversation_id: saved.conversationId,
- conversation_no: saved.conversationNo,
- conversation: saved.conversation,
- message: saved.message,
- quota: {
- limit: quota.limit,
- used: quota.used,
- remaining: quota.remaining,
- channel: 'web',
- vip: quota.vip
- }
- }
- })
- try {
- await OneBotV11.sendAiChatMessage({
- conversationId: saved.conversationId,
- conversationNo: saved.conversationNo,
- senderUuid: uuid,
- content: saved.content,
- images: saved.images,
- channel: 'web'
- })
- } catch (err) {
- this.logger.error(`AIChat OneBot forward failed: ${err.stack || err}`)
- await ConversationService.addSystemMessage({
- conversationId: saved.conversationId,
- content: '消息已保存,但暂时无法连接小妍助理,请稍后再试。',
- status: 'error',
- errorMsg: err.message || 'OneBot send failed',
- channel: 'web'
- })
- }
- }
- }
- module.exports.SendMessage = SendMessage
|