飞书接入机器人NODE开发自动回复

一、创建飞书应用

1.登录飞书开放平台 进入开发者后台 创建自建应用

2.添加应用能力 选择机器人添加

3.添加事件订阅并根据权限开通权限  此处只添加获取消息事件

4.配置应用服务端地址(当事件触发 会触发设置的地址 并发送事件数据)开启Encrypt Key 实现回调数据加密 接收到数据后 通过开发文档 - 飞书开放平台 文档介绍 解密

 5.创建测试企业 测试人员 测试应用无压力不要审核

 二、搭建服务 接入 https 证书 创建api

const express = require('express')const app = express()const https = require('https');// node接入证书
const options = {cert: fs.readFileSync('./ssl/xyz.pem'),key: fs.readFileSync('./ssl/xyz.key')
}
let server = https.createServer(options, app)const bodyParser = require('body-parser')app.use(bodyParser.urlencoded({extended: false
}))
app.use(bodyParser.json())server.listen(8443, (err) => {if (!err) {console.log('服务器已启动 端口号8443:::')console.log('http://127.0.0.1:8443')}
})
app.all('*', function(req, res, next) {res.header('Access-Control-Allow-Origin', '*')res.header('Access-Control-Allow-Headers', 'X-Requested-With,Content-Type')res.header('Access-Control-Allow-Methods', 'GET,POST,OPTIONS')next()
})

1.引入axios 调用飞书api接口做准备  npm i axios 并封装

// 封装axios
let tenantToken = ''
let tokenTimes = ''
const httpsAxios = async (url, data) => {if(!tenantToken || ((new Date().getTime() - tokenTimes ) / 1000) > 5400) {tokenTimes = new Date().getTime()tenantToken = await getTenantToken()}return new Promise((resolve, reject) => {axios({url,method: 'post',headers: { Authorization: `Bearer ${tenantToken}`, 'Content-Type': 'application/json; charset=utf-8' },data: data}).then(res=>{resolve(res)}).catch(err=>{reject(err)})})
}

2. 获取飞书的access_token 在调用api中 身份象征 

// 获取飞书 tenant_access_token 的方法
const getTenantToken = async () => {const Bool = await addFile()console.log(Bool)if(!Bool) {const url ='https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal';const res = await axios.post(url, {app_id: obj.appID,app_secret: obj.EncryptKey});addFile(res.data)return res.data.tenant_access_token;} else {return Bool;}
}

2.1. addFile 存储 access_token 有效期为2小时 则设置为5400秒重新获取 , 没有用数据库 则使用文件json保存到本地目录下

const fs = require('fs');
const path = require('path');
// 存储数据access_token 到本地文件
const addFile = (data) => {const configFile = path.resolve(__dirname, './json/Info.json')let Obj = JSON.parse(fs.readFileSync(configFile, 'UTF-8').toString())return new Promise(re => {if(data) {Obj.tenant_access_token = data.tenant_access_tokenObj.tenant_access_token_time = new Date().getTime()fs.writeFileSync(configFile, JSON.stringify(Obj))re(Obj.tenant_access_token)} elseif (!Obj.tenant_access_token) {re(false)} else {let time = new Date().getTime()console.log((time - Obj.tenant_access_token_time ))// 一个小时三十分钟就重新获取if(((time - Obj.tenant_access_token_time ) / 1000) > 5400) {re(false)} else {re(Obj.tenant_access_token)}}})
}

3.事件订阅接收数据 接收数据 由于加密过的 需要AESCipher 解密 监听 im.message.receive_v1 获取用户发送的数据  如果你有gpt的话 可以接上webGpt

app.post('/gptTest', async (req, res) => {cipher = new AESCipher(obj.encrypt)let data = JSON.parse(cipher.decrypt(req.body.encrypt))console.log(data)//接收到的数据过期 10秒就不做处理if(new Date().getTime() - Number(data.header.create_time) > 10000) {res.send({data: {},message: 'err',code: 400})return}if (data.header.event_type == 'im.message.receive_v1') {let contents = JSON.parse(data.event.message.content)console.log(contents)console.log(data.event.sender.sender_id.open_id)let result = '测试'//GPT识别码if(contents.text.indexOf('GPT') != -1) {setMessages(data.event.sender.sender_id.open_id)result = await webGpt(contents.text.substring((contents.text.indexOf('GPT')+ 3)))console.log(result)if(!result) {result = '网络不稳定,请重试'}}const url = `https://open.feishu.cn/open-apis/im/v1/messages/${data.event.message.message_id}/reply`;// at功能// if (data.event.sender.sender_id.open_id) content = `<at user_id="${data.event.sender.sender_id.open_id}"></at> ${content}`;const getData = await httpsAxios(url, { content: JSON.stringify({ text: result }),"msg_type": "text"})res.send({data: {},message: 'success',code: 200})} else {res.send({data: {},message: 'err',code: 400})}// 	res.send({// 		challenge: req.body.challenge,// 		data: {},// 		message: 'err',// 		code: 500// 	})
})

 3.1  AESCipher 解密

// 解密接收事件数据
const crypto = require("crypto");
class AESCipher {constructor(key) {const hash = crypto.createHash('sha256');hash.update(key);this.key = hash.digest();}decrypt(encrypt) {const encryptBuffer = Buffer.from(encrypt, 'base64');const decipher = crypto.createDecipheriv('aes-256-cbc', this.key, encryptBuffer.slice(0, 16));let decrypted = decipher.update(encryptBuffer.slice(16).toString('hex'), 'hex', 'utf8');decrypted += decipher.final('utf8');return decrypted;}
}

3.2 回复用户信息 调取api 开发文档 - 飞书开放平台https://open.feishu.cn/open-apis/im/v1/messages/${data.event.message.message_id}/reply

let url = `https://open.feishu.cn/open-apis/im/v1/messages/${data.event.message.message_id}/reply`
let result = ''
const getData = await httpsAxios(url, { content: JSON.stringify({ text: result }),"msg_type": "text"})

3.3 发送信息给用户 调用 api 开发文档 - 飞书开放平台

https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=open_id

//receive_id 用户open_id
const setMessages = (receive_id) =>{httpsAxios('https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=open_id', {"receive_id": receive_id,"msg_type": "text","content": "{\"text\":\"等我C一下...\"}"}).then(res=>{}).catch(err=>{})
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/14852.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot 中的任务执行器是什么,如何使用

Spring Boot 中的任务执行器是什么&#xff0c;如何使用 Spring Boot 是一个非常流行的 Java 开发框架&#xff0c;它的核心理念是通过简单的配置和约定来提高开发效率。在很多情况下&#xff0c;我们需要在后台执行一些任务&#xff0c;比如异步处理、定时任务等等。为了简化…

【ARM Coresight 系列文章 3 - ARM Coresight 组件 DAP(Debug Access Port) 介绍】

文章目录 1.1 Debug Access Port1.2 Access Port1.2.1 IDR 寄存器 1.3 Mem-APs 介绍1.3.1 Debug 寄存器访问模型1.3.2 APs 中寄存器的介绍 1.1 Debug Access Port 外部 Debugger(DS-5/Trace32) 会通过JTAG接口或者SWD接口和DAP相连&#xff1a; JITAG 一般是5个pin&#xff1…

qt对话框

完善文本编辑器 #include "second.h" #include "ui_second.h"second::second(QWidget *parent) :QWidget(parent),ui(new Ui::second) {ui->setupUi(this);this->setWindowTitle("聊天室界面");//设置标题this->setWindowIcon(QIcon(&…

Spring Boot 中的 @HystrixCommand 注解

Spring Boot 中的 HystrixCommand 注解 简介 在分布式系统中&#xff0c;服务之间的调用是不可避免的。但随着服务数量的增加&#xff0c;服务之间的依赖关系也会变得越来越复杂&#xff0c;服务的故障也会变得越来越常见。一旦某个服务出现故障&#xff0c;它所依赖的服务也…

keepalived 实现 IP 地址漂移

&#x1f388; 作者&#xff1a;Linux猿 &#x1f388; 简介&#xff1a;CSDN博客专家&#x1f3c6;&#xff0c;华为云享专家&#x1f3c6;&#xff0c;Linux、C/C、云计算、物联网、面试、刷题、算法尽管咨询我&#xff0c;关注我&#xff0c;有问题私聊&#xff01; &…

RabbitMQ学习笔记9 TTL死信队列+延迟队列实战

我们去新建一个交换机&#xff1a; 然后我们再用这种方法直接创建一个队列&#xff1a; 点击bind这样我们的交换机和队列就绑定到一起了。 然后我们要新建普通队列&#xff0c;设置过期时间&#xff0c;指定死信交换机。 发布一条消息。 它会把队列传递到死信队列中去。

nvm 下载nodejs 失败

解决办法&#xff1a; 1.查看nvm安装路径 nvm root2、在安装路径下找到setting.txt,添加两句话 node_mirror: http://npm.taobao.org/mirrors/node/ npm_mirror: https://npm.taobao.org/mirrors/npm/3.再执行nvm install 就可以了。

【网络】TCP三次握手和四次挥手(感性理解)

目录 三次握手 文字描述三次握手过程 为什么是三次握手&#xff1f; 什么是SYN洪水&#xff1f; 连接和半连接队列 一次、两次握手行不行&#xff0c;四/五/六次握手行不行&#xff1f; 三次握手一定会成功吗&#xff1f; 三次握手的过程中可不可以携带数据 TCP中的IS…

flutter开发实战-自定义Switch开关控件Widget

flutter开发实战-自定义Switch开关控件 在flutter中实现自定义Switch&#xff0c;主要实现类似IOS的UISwitch样式的开关控件 一、效果图 二、实现Switch开关的Widget 实现自定义Switch的Widget&#xff0c;主要实现交织动画。 交织动画 有些时候我们可能会需要一些复杂的动画…

OpenCV在一个图像上画一个空心绿色的圆和一个实心红色的圆

/*** void cvCircle( CvArr* img, CvPoint center, int radius, CvScalar color, int thickness=1, int line_type=8, int shift=0 );* Opencv画点 其实画的是小圆圈* img:图像。* center:圆心坐标。* radius:圆形的半径。* color:线条的颜色。* thickness:如果是正数,表…

了解k8s容器组pods

一&#xff1a;Pods概述 在 部署第一个应用程序 中创建 Deployment 后&#xff0c;k8s创建了一个 Pod&#xff08;容器组&#xff09; 来放置应用程序实例&#xff08;container 容器&#xff09; Pod 容器组 是一个k8s中一个抽象的概念&#xff0c;用于存放一组 container&a…

文字和祝福语:创意的粒子效果网页(❤️好看好用❤️)HTML+CSS+JS

✨博主&#xff1a;命运之光 &#x1f338;专栏&#xff1a;Python星辰秘典 &#x1f433;专栏&#xff1a;web开发&#xff08;简单好用又好看&#xff09; ❤️专栏&#xff1a;Java经典程序设计 ☀️博主的其他文章&#xff1a;点击进入博主的主页 前言&#xff1a;欢迎踏入…