Created
June 15, 2023 03:10
-
-
Save ankanch/266fb2936e7ba6aaab315e944827e959 to your computer and use it in GitHub Desktop.
适用于飞书外部群的ChatGPT 机器人 (基于飞书网页版)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 适用于飞书外部群的ChatGPT 机器人 | |
* 对于飞书内部群,可以直接通过开发飞书机器人实现内部群的消息监听和回复。 | |
* 但对于飞书外部群,无法添加内部机器人程序, 只能添加非常简单的基于Webhook 的机器人 (参考:https://open.feishu.cn/document/client-docs/bot-v3/add-custom-bot) | |
* 机器人无法直接获得外部群的消息。 | |
* | |
* 本脚本实现,监听飞书网页版外部群消息(HTML元素变化),并将群消息发送给 ChatGPT 处理。 | |
* 使用方法: | |
* 1. 打开飞书网页版 | |
* 2. 等待网页版加载完成 | |
* 3. 点开一个外部群聊的聊天窗口 | |
* 4. 按 F12 打开浏览器控制台 | |
* 5. 控制台粘贴本代码,并回车 | |
* 6. 群里的其他人可以通过发送 "+GPT {你的问题}" 以选择ChatGPT回复该消息 | |
* | |
* 已知问题:某些情况下可能需要用户手动在网页版往下滑下消息,以便脚本检测到新消息。 | |
* | |
* 仅实现了单次对话,无上下文。 | |
* | |
* 你需要获取OpenAI 的API key 和 飞书外部群机器人webhook 链接以使用本脚本。 | |
*/ | |
console.log('飞书网页版消息'); | |
// ChatGPT API配置 | |
const apiEndpoint = 'https://api.openai.com/v1/chat/completions'; | |
// ============================================================================================== | |
// ========================== 请在下面填入你的 OpenAI API Key ========================== | |
// ============================================================================================== | |
const apiKey = '{your chat gpt api key}'; | |
// 示例 : https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxxx | |
// 如何获取以上链接,请参考 https://open.feishu.cn/document/client-docs/bot-v3/add-custom-bot | |
const feishuGroupBotEndpoint = "{your feishu group webhook URL}"; | |
// ============================================================================================== | |
// ===================== 请在上面填入你的 飞书外部群机器人webhook地址 ========================== | |
// ============================================================================================== | |
// 发送消息给ChatGPT | |
async function sendMessage(message) { | |
try { | |
const response = await fetch(apiEndpoint, { | |
method: 'POST', | |
headers: { | |
'Authorization': `Bearer ${apiKey}`, | |
'Content-Type': 'application/json' | |
}, | |
body: JSON.stringify({ | |
model: 'gpt-3.5-turbo', | |
messages: [{ role: 'system', content: 'You are a helpful assistant.' }, { role: 'user', content: message }] | |
}) | |
}); | |
const data = await response.json(); | |
const reply = data.choices[0].message.content; | |
return reply; | |
} catch (error) { | |
console.error('API请求错误:', error); | |
return '发生错误,请重试。'; | |
} | |
} | |
// 发送消息给飞书群 | |
async function sendMessageToFeishu(message) { | |
try { | |
const response = await fetch(feishuGroupBotEndpoint, { | |
method: 'POST', | |
headers: { | |
'Content-Type': 'application/json' | |
}, | |
body: JSON.stringify({ | |
msg_type: 'text', | |
content: { | |
text: message | |
} | |
}) | |
}); | |
return ""; | |
} catch (error) { | |
console.error('sendMessageToFeishu API请求错误:', error); | |
return 'sendMessageToFeishu 发生错误,请重试。'; | |
} | |
} | |
// 设置要监控的CSS选择器 | |
var selector = "#root-messenger-nav-application > div > div > div.lark-chat-right-box.js-lark-chat-right-box > div.lark-chat-right > div > div > div > div > div.chatSidebar_content > div > div.chatMainContent > div.bizChat > div.chatMessages > div.messageContainer._2AC2c > div.messageList > div > div > div > div.list_items"; | |
// 获取目标元素 | |
var targetElement = document.querySelector(selector); | |
// 定义MutationObserver回调函数 | |
var observerCallback = function (mutationsList, observer) { | |
for (var mutation of mutationsList) { | |
if (mutation.type === "childList") { | |
var addedNodes = mutation.addedNodes; | |
for (var i = 0; i < addedNodes.length; i++) { | |
var addedNode = addedNodes[i]; | |
console.log("新增内容:", addedNode.innerHTML); | |
var messageTextDiv = addedNode.querySelector('.message-text'); | |
var textContent = messageTextDiv.textContent.trim(); | |
if (textContent.endsWith('展开')) { | |
textContent = textContent.slice(0, -2); | |
console.log('移除后的字符串:', textContent); | |
} | |
if (!textContent.startsWith('+GPT')) { | |
console.log('忽略输入,请使用 +GTP 开头 : ',textContent); | |
return; | |
} | |
textContent = textContent.replace(/^(\+GPT\s*)+/, ''); | |
console.log('SEND--->:', textContent); | |
sendMessage(textContent) | |
.then(reply => { | |
console.log('<---RECV:', reply); | |
sendMessageToFeishu(reply); | |
}) | |
.catch(error => { | |
console.error('发生错误:', error); | |
}); | |
} | |
} | |
} | |
}; | |
// 创建MutationObserver实例 | |
var observer = new MutationObserver(observerCallback); | |
// 配置MutationObserver | |
var observerConfig = { childList: true, subtree: true }; | |
// 开始监控目标元素的变化 | |
observer.observe(targetElement, observerConfig); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment