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

news2024/10/6 2:25:03

一、创建飞书应用

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_token
            Obj.tenant_access_token_time = new Date().getTime()
            fs.writeFileSync(configFile, JSON.stringify(Obj))
            re(Obj.tenant_access_token)
        } else
        if (!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.coloradmin.cn/o/720948.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

简要介绍 | 元学习:学会学习的新途径

注1&#xff1a;本文系“简要介绍”系列之一&#xff0c;仅从概念上对元学习&#xff08;Meta-Learning&#xff09;进行非常简要的介绍&#xff0c;不适合用于深入和详细的了解。 元学习&#xff1a;学会学习的新途径 BLOG | Samsung Research 1 背景介绍 元学习&#xff08;…

Linux基础工具|C/C++编译器:gcc/g++的使用

1.基础使用 gcc是专门用来编译C语言的编译器&#xff0c;而g是编译C的编译器&#xff08;也可以编译C语言&#xff0c;毕竟C语言兼容C&#xff09;。Linux下gcc默认使用8字节的指针。 下载安装&#xff1a;gcc的安装指令“sudo yum install gcc”&#xff08;在Linux里大部分…

【C++】详解set和map

目录 一、什么是关联式容器及树形结构的关联式容器二、键值对三、set1、什么是set2、set的使用1&#xff09;set的模版参数列表2&#xff09;set的构造3&#xff09;set的迭代器4&#xff09;set的容量5&#xff09;set的修改操作 3、multiset的介绍及使用 四、map1、什么是map…

vue3怎么把路由的 # 去掉 ? 为什么用mode: ‘history‘没有生效?

代码完成后 请重启项目 一定要重启&#xff01; 重启&#xff01;重启&#xff01; &#xff08;没重启项目不生效&#xff09; 1.找到项目中的路由文件 2.引用vueRouter // vue3 import { createRouter, createWebHistory } from "vue-router";var router crea…

C# 交错数组学习

C# 交错数组是元素为数组的数组。 一个示例&#xff1b; using System;class Program {static void Main(string[] args) {string[][] weeks new string[3][];weeks[0] new string[] { "星期日", "星期一", "星期二", "星期三", &…

R语言学习——线性拟合、检查正态分布、秩和检验、百分比检验、卡方检验、方差检验

test <- read.table(/Users/zhangzhishuai/Downloads/20 lesson20 R相关性检验及线性拟合/BMI.txt, sep \t, header T,row.names 1) test plot(test$weight,test$height) cor(test$weight,test$height) cor.test(test$weight,test$height)# 线性拟合 result lm(height~w…

6月《中国数据库行业分析报告》已发布,首发空间、搜索引擎数据库【全球产业图谱】

为了帮助大家及时了解中国数据库行业发展现状、梳理当前数据库市场环境和产品生态等情况&#xff0c;从2022年4月起&#xff0c;墨天轮社区行业分析研究团队出品将持续每月为大家推出最新《中国数据库行业分析报告》&#xff0c;持续传播数据技术知识、努力促进技术创新与行业生…

Python 简易表格数据处理CSV+XLS+XLSX

概述 在实际应用中我们进行数据处理与分析时&#xff0c;往往涉及大量的表格。一般来说&#xff0c;使用Python的专业数据分析处理工具包&#xff0c;完全可以胜任我们的大多数需求&#xff0c;比如NumpyPandas。但是有时候往往我们对表格数据的操作是很简单的&#xff0c;不需…

git常用记录

一些日常使用记录 常用命令 切换分支 在git checkout 分支名查看分支 git branch -r git branch -a //查看所有分支包括本地分支和远程分支合并分支 git merge 来源分支删除分支 git branch -D 分支名 //删除本地分支 git push origin --delete 分支名 //删除远程分支本…

ES6新特性总结

最近&#xff0c;在面试中也是经常被问道ES6关于新特性的面试题&#xff0c;那我也来个总结&#xff0c;记录下。 ES6新特性总结 let、const命令&#xff08;1&#xff09;let&#xff08;2&#xff09;const 模板字符串增强的函数&#xff08;1&#xff09;函数的参数可以设置…

6.4.4 GLSL实现奶牛颜色动态变化

#include <osg/Program> #include <osgDB/ReadFile> #include <osgViewer/Viewer>static const char* vertSource {"varying vec3 normal;\n"//易变量 用于着色器之间的传值"void main()\n""{\n"" normal normalize…

Kscan-简单的资产测绘工具

下载地址&#xff1a;https://github.com/lcvvvv/kscan 简介 &#xff1a; Kscan是一款纯go开发的全方位扫描器&#xff0c;具备端口扫描、协议检测、指纹识别&#xff0c;暴力破解等功能。支持协议1200&#xff0c;协议指纹10000&#xff0c;应用指纹20000&#xff0c;暴力破…

UNI-APP_subNVue原生子窗口使用,web-view层级问题解决

subNVues文档 app-subnvues文档 subNVues开发指南 需求&#xff1a;在pages/cloud_control/index页面使用subNVue原生子窗口 1.pages文件配置 "app-plus": {"bounce": "none","subNVues":[{"id": "control_popup&qu…

Mongodb基础及应用、部署(超详细)

目录 一、简介 二、应用场景 三、概念 四、安装部署 1、关闭防火墙和selinux 2、指定一个进程同一时间最多可开启的文件数 3、用户最多可开启的进程数目 4、安装版本下载地址 5、创建数据目录&#xff0c;日志文件及目录并创建相应配置文件 6、启动MongoDB数据库&#xff0c…

接口自动化你一定能要知道的基本流程和测试思路

接口自动化大致步骤&#xff1a; 1、发送请求 2、解析结果 3、验证结果 定义三个和业务相关的类 1、一个用来封装HTTPclient&#xff0c;用来发送请求 2、解析结果xml的类 3、一个用于比较测试结果和期望值的类&#xff0c;用于验证 4、自动生成报告的类&#xff1a;自…

Nerf-Wild代码学习笔记Neural Radiance Fields for Unconstrained Photo Collections

前言&#xff1a; 本文为记录自己在Nerf学习道路的一些笔记&#xff0c;包括对论文以及其代码的思考内容。公众号&#xff1a; AI知识物语 B站讲解&#xff1a;出门吃三碗饭 本篇文章主要针对其代码来学习其内容&#xff0c;关于代码的理解可能会有出入&#xff0c;欢迎批评指…

如何使用P-One的全链路压测工具来定位问题节点和分析性能问题

首先&#xff0c;简单介绍一下&#xff0c;性能测试平台P-One。 PerformanceOne&#xff08;简称&#xff1a;P-One&#xff09;是泽众软件自主研发的一套一站式性能测试平台软件产品。 该产品采用 B/S 架构开发&#xff0c;实现了集管理、设计、压测、监控以及分析于一体的全方…

(06)ATF代码导读之BL31

代码导读 关于平台相关的代码和函数均以qemu实现解读。 BL31 在BL2中触发安全监控模式调用后会跳转到BL31中执行&#xff0c;同理复位的入口函数为bl31_entrypoint。BL31最主要的两个功能&#xff1a;作为启动流程&#xff0c;初始化硬件和加载BL32、BL31等&#xff1b;启动…

scratch 角色移动

scratch 角色移动 这是本人的第一个scratch程序。入坑scratch是因为希望体验一下图形化编程并制作以动画为主的图形化程序。用的软件是Mind。Mind是由scratch改编的开源IDE&#xff0c;可以图形化开发Arduino程序&#xff0c;本人使用Mind的另一个原因是Mind提供快捷地在OLED屏…

【数据库】MySQL安装(最新图文保姆级别超详细版本介绍)

1.总共两部分&#xff08;第二部可省略&#xff09; 安装mysql体验mysql环境变量配置 1.1安装mysql 1.输入官网地址https://www.mysql.com/ 下载完成后&#xff0c;我们双击打开我们的下载文件 打开后的界面&#xff0c;如图所示 我们选择custom&#xff0c;点击nex…