From b9b758102b71742c106031aca1d5a40be027625c Mon Sep 17 00:00:00 2001 From: gaoao-3 <140887777+gaoao-3@users.noreply.github.com> Date: Thu, 2 Jan 2025 14:14:28 +0800 Subject: [PATCH] =?UTF-8?q?=E6=90=9E=E4=B8=AA=E4=BA=86=E5=8F=91=E9=82=AE?= =?UTF-8?q?=E4=BB=B6=E7=9A=84tool=EF=BC=8C=E6=88=91=E5=85=88=E7=8E=A9?= =?UTF-8?q?=E7=8E=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/bym.js | 7 +- guoba.support.js | 8 ++- utils/config.js | 2 + utils/tools/MailSenderTool.js | 128 ++++++++++++++++++++++++++++++++++ 4 files changed, 143 insertions(+), 2 deletions(-) create mode 100644 utils/tools/MailSenderTool.js diff --git a/apps/bym.js b/apps/bym.js index 337524c..94168f4 100644 --- a/apps/bym.js +++ b/apps/bym.js @@ -20,6 +20,7 @@ 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 = { @@ -134,7 +135,10 @@ export class bym extends plugin { // 使用 specialUserNotice 更新提示词 opt.system = `你的名字是“${Config.assistantLabel}”,你在一个qq群里,群号是${group},当前和你说话的人群名片是${card}, qq号是${sender}${specialUserNotice}, 请你结合用户的发言和聊天记录作出回应,要求表现得随性一点,最好参与讨论,混入其中。${specialUserNotice ? '你要重视他的发言。' : ''}与你相关的话题时,你可以去回应一下,不相关你就随便应付就行了,不要过分插科打诨,不知道说什么可以复读群友的话。 - 当群友要求你做搜索、关键词搜索、URL提取摘要、发图、发视频、画图、禁言、踢人、改头衔和昵称等操作时,需要使用工具,不可以直接发文字来蒙混过关。你必须根据需要来调用各种工具,并回复相关问题。要求优先使用中文进行对话。你也可以自行根据当前话题内容选择性的调用这些工具,增加趣味性,以及对违规的群友使用禁言工具进行惩罚,等这种自我主张式的调用方法来进行合理且富有人性的聊天,在进行搜索或URL提取时需要详细的给出工具返回的内容,也可以在对不懂的问题自行调用自定义搜索工具来解答你的疑惑! + 当群友要求你做关键词搜索、URL内容提取、搜图、发图、发B站视频、发邮件、画图、禁言、踢人、改头衔和昵称等操作时,需要使用工具,不可以直接发文字来蒙混过关。你必须根据需要来调用各种工具,并回复相关问题。要求优先使用中文进行对话。你也可以自行根据当前话题内容选择性的调用这些工具,增加趣味性,以及对违规的群友使用禁言工具进行惩罚,等这种自我主张式的调用方法来进行合理且富有人性的聊天。 + 在进行搜索或URL提取时需要详细的给出工具返回的内容,也可以在对不懂的问题自行调用自定义搜索工具来解答你的疑惑! + 不可以胡乱调用工具来回答,必须自行判断需要调用的工具。 + 以下是你可以使用的表情列表: ${Object.values(faceMap).map(face => `[/${face}]`).join(',')} 请在回复中适当使用以上表情,但是不要过度频繁使用这些表情。禁止使用表情列表之外的任何表情,比如[/思考]。` + @@ -168,6 +172,7 @@ ${Object.values(faceMap).map(face => `[/${face}]`).join(',')} new SendMusicTool(), new SendPictureTool(), new APTool(), + new MailSenderTool(), new WebsiteTool(), new UrlExtractionTool(), new CustomSearchTool(), diff --git a/guoba.support.js b/guoba.support.js index bd21ba0..c675327 100644 --- a/guoba.support.js +++ b/guoba.support.js @@ -54,7 +54,7 @@ export function supportGuoba () { { field: 'specialUserQQs', label: '特殊用户QQ号', - bottomHelpMessage: '在这里添加特殊用户的QQ号码。', + bottomHelpMessage: '在这里添加特殊用户的QQ号码。', component: 'Input' }, { @@ -62,6 +62,12 @@ export function supportGuoba () { label: '特殊用户名称', bottomHelpMessage: '在这里添加特殊用户的名称。', component: 'Input' + }, + { + field: 'smtpAuthCode', + label: 'qq邮箱授权码', + bottomHelpMessage: '在这里添加你的授权码', + component: 'Input' }, { field: 'enableBYM', diff --git a/utils/config.js b/utils/config.js index 46aef5e..111a2bb 100644 --- a/utils/config.js +++ b/utils/config.js @@ -200,6 +200,8 @@ const defaultConfig = { enableBYM: false, // 触发对话的概率,百分比。比如5%就写5 bymRate: 5, + // smtp + smtpAuthCode: '', // 伪人模式触发骂人反击的关键词 bymFuckList: [ '骂', diff --git a/utils/tools/MailSenderTool.js b/utils/tools/MailSenderTool.js new file mode 100644 index 0000000..a669faa --- /dev/null +++ b/utils/tools/MailSenderTool.js @@ -0,0 +1,128 @@ +import { AbstractTool } from './AbstractTool.js'; +import fetch from 'node-fetch'; +import { Config } from '../config.js'; + +/** + * 邮件发送工具类 + * @class MailSenderTool + * @extends {AbstractTool} + */ +export class MailSenderTool extends AbstractTool { + // 工具名称 + name = 'MailSenderTool'; + + // 工具参数 + parameters = { + properties: { + aiTask: { + type: 'string', + description: '描述 AI 需要发送邮件的任务,例如:给用户发送一封问候邮件', + }, + targetUserQQ: { + type: 'string', + description: '目标用户的 QQ 号码,用于拼接成 @qq.com 的邮箱地址', + }, + to: { + type: 'string', + description: '收件人邮箱地址,如果提供了 targetUserQQ,则此参数可省略', + }, + }, + required: ['aiTask'], + }; + + /** + * 工具执行函数 + * @param {Object} opt - 工具参数 + * @param {Object} ai - AI对象 + * @returns {Promise} - 邮件发送结果 + */ + func = async function (opt, ai) { + const { aiTask, targetUserQQ, to } = opt; + + // 检查必填参数 + if (!aiTask) { + return '缺少必要的参数 aiTask。'; + } + + // 从 Config 中读取 SMTP 授权码 + const smtpAuthCode = Config.smtpAuthCode; + + // 检查配置信息 + if (!smtpAuthCode) { + return 'Config 配置中缺少必要的参数 smtpAuthCode。'; + } + + // 确定收件人邮箱地址 + const recipientEmail = targetUserQQ ? `${targetUserQQ}@qq.com` : to; + if (!recipientEmail) { + return '缺少收件人邮箱地址,请提供 targetUserQQ 或 to 参数。'; + } + + // 使用 AI 生成邮件所有内容,并修改提示词为“你”的视角 + let from, aiName, title, text, aiQQNumber; + try { + const aiTaskPrompt = `你的任务是:根据“${aiTask}”这个主题,以“你”的视角,给邮箱为“${recipientEmail}”的用户写一封邮件。你需要自己决定邮件的标题、正文内容,以及你在邮件中使用的名字。同时,你需要提供你的 QQ 号码,用于构建发件人邮箱地址。请返回一个 JSON 对象,包含以下字段:title(邮件标题)、text(邮件正文)、senderName(你在邮件中使用的名字)、aiQQNumber(你的 QQ 号码)。`; + const aiResponse = await ai.toolTask(aiTaskPrompt); + // 期望的 aiResponse 格式: + // { + // title: '邮件标题', + // text: '邮件正文', + // senderName: '你在邮件中使用的名字', + // aiQQNumber: '你的 QQ 号码' + // } + title = aiResponse.title; + text = aiResponse.text; + aiName = aiResponse.senderName; + aiQQNumber = aiResponse.aiQQNumber; + + // 构建发件人邮箱 + from = `${aiQQNumber}@qq.com`; + } catch (error) { + console.error('AI 生成邮件内容失败:', error); + return `AI 生成邮件内容失败: ${error.message}`; + } + + // 构建请求 URL + const apiUrl = 'http://wswzh.ccccocccc.cc/api/mail/zdy.php'; + const queryParams = new URLSearchParams({ + api_key: 'free', + from: from, + code: smtpAuthCode, + host: 'smtp.qq.com', + to: recipientEmail, + title: title, + text: text, + sb: aiName, // 这里仍然使用 sb 参数,但其值是 AI 决定的 senderName + }); + const fullApiUrl = `${apiUrl}?${queryParams.toString()}`; + + try { + // 发送邮件请求 + const response = await fetch(fullApiUrl); + + // 检查响应状态 + if (response.ok) { + // 解析响应数据 + const data = await response.json(); + + // 根据 API 返回的数据判断邮件是否发送成功 + if (data.success) { + console.log('邮件发送成功:', data.message); + return '邮件发送成功'; + } else { + console.error('邮件发送失败:', data.error); + return `邮件发送失败: ${data.error}`; + } + } else { + console.error('邮件发送请求失败:', response.status, response.statusText); + return `邮件发送请求失败: ${response.status} ${response.statusText}`; + } + } catch (error) { + console.error('邮件发送出错:', error); + return `邮件发送出错: ${error.message}`; + } + }; + + // 工具描述 + description = '用于发送自定义邮件的工具,由 AI 以“你”的视角完全自主地决定邮件标题、内容、发件人名字和 QQ 号码,支持配置目标用户的 QQ 邮箱。'; +} \ No newline at end of file