import { CustomGoogleGeminiClient } from '../client/CustomGoogleGeminiClient.js' import { Config } from '../utils/config.js' import { getImg } from '../utils/common.js' import { getChatHistoryGroup } from '../utils/chat.js' import { SearchVideoTool } from '../utils/tools/SearchBilibiliTool.js' import { SerpImageTool } from '../utils/tools/SearchImageTool.js' import { SearchMusicTool } from '../utils/tools/SearchMusicTool.js' import { SendAvatarTool } from '../utils/tools/SendAvatarTool.js' import { SendVideoTool } from '../utils/tools/SendBilibiliTool.js' import { SendMusicTool } from '../utils/tools/SendMusicTool.js' import { SendPictureTool } from '../utils/tools/SendPictureTool.js' import { WebsiteTool } from '../utils/tools/WebsiteTool.js' import { convertFaces, faceMap } from '../utils/face.js' import { WeatherTool } from '../utils/tools/WeatherTool.js' import { EditCardTool } from '../utils/tools/EditCardTool.js' import { JinyanTool } from '../utils/tools/JinyanTool.js' import { KickOutTool } from '../utils/tools/KickOutTool.js' import { SetTitleTool } from '../utils/tools/SetTitleTool.js' import {SerpTool} from '../utils/tools/SerpTool.js' import { APTool } from '../utils/tools/APTool.js' import { CustomSearchTool } from '../utils/tools/CustomSearchTool.js' import { UrlExtractionTool } from '../utils/tools/UrlExtractionTool.js' import { MailSenderTool } from '../utils/tools/MailSenderTool.js' // 角色映射表 const roleMap = { owner: '群主', admin: '管理员', member: '成员' } // 格式化日期时间 const formatDate = (date) => { const year = date.getFullYear() const month = (date.getMonth() + 1).toString().padStart(2, '0') const day = date.getDate().toString().padStart(2, '0') const hours = date.getHours().toString().padStart(2, '0') const minutes = date.getMinutes().toString().padStart(2, '0') const seconds = date.getSeconds().toString().padStart(2, '0') return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}` } export class bym extends plugin { constructor () { super({ name: 'ChatGPT-Plugin 伪人bym', dsc: 'bym', /** https://oicqjs.github.io/oicq/#events */ event: 'message', priority: 5000, rule: [ { reg: '^[^#][sS]*', fnc: 'bym', priority: '-1000000', log: false } ] }) } /** * 获取特殊身份用户的提示信息 * @param {number} sender - 发送者的 QQ 号码 * @returns {string} - 特殊身份用户的提示信息 */ getSpecialUserNotice(sender) { // 获取特殊身份用户的 QQ 号码列表 const specialUserQQs = Config.specialUserQQs; // 获取特殊身份用户的名称列表 const specialUserNames = Config.specialUserNames; // 查找当前发送者是否在特殊身份用户列表中 const index = specialUserQQs.indexOf(String(sender)); if (index !== -1) { // 如果找到了,获取对应的名称 const name = specialUserNames[index]; return `,其中 QQ 号码为 ${sender}是你的${name},你要重视他的发言。`; } return ''; } /** 复读 */ async bym (e) { if (!Config.enableBYM) { return false } let opt = { maxOutputTokens: 500, temperature: 1, replyPureTextCallback: e.reply } let imgs = await getImg(e) if (!e.msg) { if (imgs && imgs.length > 0) { let image = imgs[0] const response = await fetch(image) const base64Image = Buffer.from(await response.arrayBuffer()) opt.image = base64Image.toString('base64') e.msg = '[图片]' } else { return } } if (!opt.image && imgs && imgs.length > 0) { let image = imgs[0] const response = await fetch(image) const base64Image = Buffer.from(await response.arrayBuffer()) opt.image = base64Image.toString('base64') } let sender = e.sender.user_id let card = e.sender.card || e.sender.nickname let group = e.group_id let prop = Math.floor(Math.random() * 100) if (Config.assistantLabel && e.msg?.includes(Config.assistantLabel)) { prop = -1 } if (e.msg?.endsWith('?')) { prop = prop / 10 } let fuck = false let candidate = Config.bymPreset if (Config.bymFuckList?.find(i => e.msg.includes(i))) { fuck = true candidate = candidate + Config.bymFuckPrompt } if (prop < Config.bymRate) { logger.info('random chat hit') let chats = await getChatHistoryGroup(e, 20) // 调用 getSpecialUserNotice 方法获取提示信息 let specialUserNotice = this.getSpecialUserNotice(sender); // 使用 specialUserNotice 更新提示词 opt.system = `你的名字是“${Config.assistantLabel}”,你在一个qq群里,群号是${group},当前和你说话的人群名片是${card}, qq号是${sender}${specialUserNotice}, 请你结合用户的发言和聊天记录作出回应,要求表现得随性一点,最好参与讨论,混入其中。${specialUserNotice ? '你要重视他的发言。' : ''}与你相关的话题时,你可以去回应一下,不相关你就随便应付就行了,不要过分插科打诨,不知道说什么可以复读群友的话。 当群友要求你做关键词搜索、URL内容提取、搜图、发图、发B站视频、发邮件、画图、禁言、踢人、改头衔和昵称等操作时,需要使用工具,不可以直接发文字来蒙混过关。你必须根据需要来调用各种工具,并回复相关问题。要求优先使用中文进行对话。你也可以自行根据当前话题内容选择性的调用这些工具,增加趣味性,以及对违规的群友使用禁言工具进行惩罚,等这种自我主张式的调用方法来进行合理且富有人性的聊天。 在进行搜索或URL提取时需要详细的给出工具返回的内容,也可以在对不懂的问题自行调用自定义搜索工具来解答你的疑惑! 不可以胡乱调用工具来回答,必须自行判断需要调用的工具。 以下是你可以使用的表情列表: ${Object.values(faceMap).map(face => `[/${face}]`).join(',')} 请在回复中适当使用以上表情,但是不要过度频繁使用这些表情。禁止使用表情列表之外的任何表情,比如[/思考]。` + candidate + '以下是聊天记录:' + chats .map(chat => { let sender = chat.sender || chat || {} return `【${sender.card || sender.nickname}】(qq:${sender.user_id}, ${roleMap[sender.role] || '未知角色'}, 群头衔:${sender.title || '无'}, 时间:${formatDate(new Date(chat.time * 1000))}, messageId: ${chat.message_id}) 说:${chat.raw_message}` }) .join('\n') + `\n你的回复应该尽可能简练,像人类一样随意,但是也要保留“${Config.assistantLabel}”的角色风格,不要附加任何奇怪的东西,不能模仿聊天记录的格式,要以第一人称视角对话,禁止重复聊天记录。` let client = new CustomGoogleGeminiClient({ e, userId: e.sender.user_id, key: Config.geminiKey, model: Config.geminiModel, baseUrl: Config.geminiBaseUrl, debug: Config.debug }) /** * tools * @type {(AbstractTool)[]} */ const tools = [ new SearchVideoTool(), new SerpImageTool(), new SearchMusicTool(), new SendAvatarTool(), new SendVideoTool(), new SendMusicTool(), new SendPictureTool(), new APTool(), new MailSenderTool(), new WebsiteTool(), new UrlExtractionTool(), new CustomSearchTool(), new WeatherTool() ] if (Config.azSerpKey) { tools.push(new SerpTool()) } if (e.group.is_admin || e.group.is_owner) { tools.push(new EditCardTool()) tools.push(new JinyanTool()) tools.push(new KickOutTool()) } if (e.group.is_owner) { tools.push(new SetTitleTool()) } client.addTools(tools) // console.log(JSON.stringify(opt)) let rsp = await client.sendMessage(e.msg, opt) let text = rsp.text let texts = text.split(/(? { setTimeout(() => { resolve() }, Math.min(t.length * 200, 3000)) }) } } return false } }