完整更新日志在底部。
45:openai网站添加了内容安全策略,禁止加载外站脚本,所以现在必须安装“Disable Content-Security-Policy”扩展然后对chatgpt聊天页面启用,机器人脚本才能正常加载。
44:支持在油猴脚本中预定义用户名和密码,方便无人值守部署。
如果document.hu60User
或document.hu60Pwd
为空,则会弹出prompt
对话框询问用户名密码。
如果两者均不为空,则无论如何都不会弹出alert
和prompt
对话框。
// ==UserScript==
// @name 虎绿林ChatGPT机器人
// @namespace https://hu60.cn/
// @version 1.0
// @description 把ChatGPT接入hu60wap6网站程序
// @author 老虎会游泳
// @match https://chat.openai.com/*
// @icon https://hu60.cn/favicon.ico
// @grant none
// ==/UserScript==
document.hu60User = ''; // 虎绿林用户名
document.hu60Pwd = ''; // 虎绿林密码
document.hu60AdminUids = [1, 19346, 15953]; // 机器人管理员uid,管理员可以发“@ChatGPT,刷新页面”来重启机器人
document.hu60Domain = 'https://hu60.cn'; // 如果要对接其他网站,请修改此处的域名
var script = document.createElement("script");
script.src = document.hu60Domain + '/tpl/jhin/js/chatgpt/chatgpt.js?r=' + (new Date().getTime());
document.head.appendChild(script);
打开 https://chat.openai.com/ 并登录。然后去Chrome应用商店安装“Always Disable Content-Security-Policy”扩展,并对该站启用。因为openai网站添加了内容安全策略,禁止加载外站脚本,所以必须启用该扩展关闭安全策略,机器人脚本才能正常加载。
在来到 https://chat.openai.com/chat 页面时,会弹出输入虎绿林用户名密码的提示框。
如果你要把机器人接入虎绿林,请注册一个新帐号。使用现有帐号运行机器人将被删帖或禁言。
输入新帐号用户名密码后,机器人即启动,保持页面不要关闭。
机器人会使用你在此处输入的帐号与其他用户进行对话,在虎绿林用其他帐号@该帐号
即可尝试对话。
注意,使用该帐号自己@自己
是不会有反应的,必须用另一个账号来和机器人对话。
页面必须保持电脑版,机器人才能正常工作。如果因为屏幕分辨率太低,页面自动变成手机版,请用缩放功能缩小网页,直到它变成电脑版。手机版和电脑版的区别在于,手机版顶部左上角是菜单按钮,右上角是加号,而电脑版没有顶部菜单。
建议按F12打开开发者控制台(按F12,点“控制台”或“Console”),可以看到机器人的运行情况,而且好像能提升机器人运行的稳定性。
如何切换登录的帐号?按F12打开开发者工具,点“控制台”或“Console”,然后输入以下代码并回车:
login(true)
将会重新弹出用户名密码输入框。
你可以在油猴脚本的末尾添加一个自定义主循环,用于把机器人接入其他类型的网站。以下是一个例子:
document.run = async function() {
while (true) {
try {
// 访问你的网站获取要发给ChatGPT的内容
// 网站必须是https的,否则连不上。
// 此外网站还必须设置 Access-Control-Allow-Origin: * 头信息,否则也连不上。
let response = await fetch('https://example.com/my-message.php');
// 假设获取到的信息是JSON,把它转换成JSON对象
// 网站必须设置 content-type: application/json 头信息,否则转换会失败。
let messages = response.json();
// 假设JSON结构是这样:
// {"data": [
// {"uid":3, "text":"@ChatGPT,你好"},
// {"uid":2, "text":"@ChatGPT,我有一个问题"},
// {"uid":1, "text":"@ChatGPT,刷新页面"},
// ]}
let exceptionCount = 0;
for (let i=0; i<messages.data.length; i++) {
// 要发给ChatGPT的话,开头包含的“@机器人名称,”会被后续流程自动去除。
// 开头写“@机器人名称 2,”可以选择第二个ChatGPT模型(Legacy模型,仅限ChatGPT Plus用户)。
let text = messages.data.text;
// 用户id,可以是字符串,所以给出用户名也是可以的。
let uid = messages.data.uid;
try {
// 把对话发给ChatGPT
// 返回的 modelIndex 是为对话选择的模型id(从0开始编号)
// 模型id和序号的对应关系见 chatgpt.js 里的 modelMap 变量
let modelIndex = await sendRequest(text, uid);
// 从ChatGPT读取回复
let replyText = await readReply();
// 发送回复到你的网站
// 创建一个POST表单
let formData = new FormData();
formData.append('token', '用于用户身份验证的密钥');
formData.append('reply', replyText); // 回复内容
// 提交POST表单
// 网站必须是https的,否则连不上。
// 此外网站还必须设置 Access-Control-Allow-Origin: * 头信息,否则也连不上。
let response = await fetch('https://example.com/my-reply.php', {
body: formData,
method: "post",
redirect: "manual" // 不自动重定向
});
// 在控制台打印提交结果
if (response.type == 'opaqueredirect') {
console.log('提交后收到重定向(目标网址未知,根据标准,浏览器不告诉我们),不清楚提交是否成功');
} else {
let result = await response.text();
console.log('提交结果', result);
}
// 避免操作太快
await sleep(100);
} catch (ex) {
exceptionCount++; // 统计异常次数
console.error(ex); // 打印异常到控制台
await sleep(1000); // 异常后等久一点
}
// 重命名会话
await renameWant();
}
// 执行管理员命令(比如“刷新页面”)
await runAdminCommand();
// 异常太多,自动刷新页面
if (exceptionCount > 0 && exceptionCount >= messages.data.length) {
location.reload();
}
// 限制拉取信息的速度,避免对自己的网站造成CC攻击
await sleep(1000);
} catch (ex) {
console.error(ex);
await sleep(1000);
}
}
}
定期与ChatGPT对话,防止连接断开会话丢失。
// ==UserScript==
// @name ChatGPT保活机器人
// @namespace https://hu60.cn/
// @version 1.0
// @description 每分钟问一次还在吗
// @author 老虎会游泳
// @match https://chat.openai.com/chat*
// @icon https://hu60.cn/favicon.ico
// @grant none
// ==/UserScript==
document.run = async function() {
// 这里写每次刷新页面后自动发送的内容
await sendText('你好,我是老虎会游泳,初次见面请多关照', 0, 1);
while (true) {
try {
await sleep(60000);
if (document.querySelector(chatBoxSelector).textContent == '') {
await sendText('还在吗', 0, 1);
}
} catch (ex) {
console.error(ex);
await sleep(1000);
}
}
}
document.hu60AdminUids = []; // 不需要设置
document.hu60Domain = 'https://hu60.cn'; // 不需要修改
var script = document.createElement("script");
script.src = document.hu60Domain + '/tpl/jhin/js/chatgpt/chatgpt.js?r=' + (new Date().getTime());
document.head.appendChild(script);
20: 按用户隔离会话;交换模型1和模型2(默认模型改为Default)。
26:修复同时收到多条@消息时后发送的被先处理的问题。
27:主动等待内容出现,减少读取回复出错的可能性;修复代码高亮没有指定编程语言时turndown报错的问题。
28:添加结束会话功能(@ChatGPT,结束会话
);为新会话添加标记([新会话] @老虎会游泳,……
)。
29:修复虎绿林接口报错导致会话重命名失败的问题。
30:不再无限期等待回答结束,最多等120秒,防止回答始终不结束导致机器人卡住。
31:修复登录失败后不会再次弹出密码框的问题。
32:改为通过油猴自动加载脚本,提升稳定性。
33:更新已知机器人列表;优化错误处理,在遇到未捕捉异常时刷新页面。
34:添加了管理员命令功能,机器人管理员可以发“@ChatGPT,刷新页面”来重启机器人。注意油猴脚本需要更新,新增了管理员uid。
35:允许添加自定义主循环来把机器人接入其他类型的网站,见下方“如何把机器人接入其他类型的网站”一节。
36:修复帖子正文@ChatGPT
无效的问题;改进会话重命名和操作完成等待逻辑。
37:添加了重试功能,发送@ChatGPT,重试
相当于把上一条内容重新发送一次,可在ChatGPT出错时使用。
38:有用户发言失败时自动刷新页面,尽量实现自动故障恢复。
39:刷新页面前自动保存控制台日志到localStorage
以供分析。
如何查看日志(以chrome为例):打开F12控制台,点“应用”,在左侧展开“本地存储空间”,选中展开后的第一项,然后右侧找“console:”开头的key,点击后,底部可以换行显示value
,把底部拉大即可查看完整日志。
日志最多保存5个,之前的会被清理。
40:尝试解决发言失败时获取到上一条发言的问题;在模型2回复的开头添加“[2]”标记。
41:添加了html模式,说@ChatGPT html,生成一段html hello world
,生成的代码将用[html][/html]
包围。以下是完整格式:
@ChatGPT html,输出一段html hello world
@ChatGPT 2 html,输出一段html hello world
@ChatGPT html=500,输出一段html hello world
@ChatGPT 2 html=300x500,输出一段html hello world
@ChatGPT text,讲个笑话
@ChatGPT latex,证明勾股定理,内容放在Markdown代码块中,采用Latex格式书写
@ChatGPT math,证明勾股定理,公式采用Latex格式书写并单独放在markdown代码块中(备注:不好用,公式无法正常显示,有待修复)
42:ChatGPT界面改版了,移除了切换会话功能,所以我们只能回到所有用户共享单个会话的旧模式。
43:切换会话功能回来了,如果你还是看不到该功能,可以尝试清空浏览器缓存。
@幕后导演,代码在这里,需要搭建一个hu60wap6来对接:https://gitee.com/hu60t/hu60wap6