一、背景介绍
在网易有数平台的实际应用中,报表推送虽支持 Webhook 方式,但无法直接与飞书实现对接。这一现状促使我们探索一种解决方案,以实现数据的顺畅流转,提升工作效率。
整体思路:构建一个转发服务,负责接收来自有数平台的请求,并将其转化为符合飞书 Webhook 格式的信息,从而搭建起两者之间的沟通桥梁。
二、效果预览
在完成相关配置后,当我们在网易有数平台设置报表推送时,飞书机器人会及时转发报表截图以及详细的链接地址。
具体呈现效果为:自定义机器人通过 Webhook 将消息推送至飞书,消息内容清晰显示报表更新信息。效果如下:
三、网易有数webhook设计
根据有数的文档,一次webhook需要实现两个请求
- 需根据本产品的规范,对每个添加的 webhook 地址,实现一个 get 请求接口和一个 post 请求接口。
- Get 请求用于:本产品验证 webhook 接口可用性。
- Post 请求用于:本产品调用进行消息推送。
可参考有数平台的设计文档:《有数BI用户手册 V9.0》
四、接收有数请求
代码案例如下:
# Webhook路由处理
@webhook_convert_app.route('/youdata/comment/webhook', methods=['GET', 'POST'])
def webhook_handler():
if request.method == 'GET':
timestamp = request.args.get('timestamp')
nonce = request.args.get('nonce')
signature = request.args.get('signature')
logger.info(f"Received GET request with timestamp: {timestamp}, nonce: {nonce}, signature: {signature}")
return jsonify(code=0, msg='成功')
elif request.method == 'POST':
logger.info(f"Received POST request with data: {request.json}")
# 获取请求参数
data = request.json
if data['data']['msgStatus'] == 'success':
feishu_bot = FeishuTalk()
youshu_link = data['data']['reportLink']
youshu_image_base64 = data['data']['pictureBase64']
report_name = data['data']['reportName']
project_name = data['data']['projectName']
repose_result = feishu_bot.send_image_message(youshu_link,youshu_image_base64,report_name,project_name)
print('发送请求结果为'+str(repose_result))
msg = 'ok'
else:
msg = '接收人为空,请添加接收人或配置推送图片'
print(msg)
if msg == 'ok':
return jsonify(code = 0,msg='成功')
else:
return jsonify(code = 400,msg=msg)
五、转发到飞书
转发到飞书时会有点复杂,不能直接使用飞书机器人,因为普通机器人无法直接发送图片。
需要通飞书应用上传图片,获得图片的image_key,然后使用机器人发送富文本带上image_key,才能实现图片上传。
添加机器人能力之后,复制应用的id与secret,接下来会用到。
上传图片获取image_key的demo如下:
# 上传图片到应用,返回图片的key
def uploadImage(token,image_binary):
url = "https://open.feishu.cn/open-apis/im/v1/images"
form = {'image_type': 'message',
'image': (image_binary)}
multi_form = MultipartEncoder(form)
headers = {
'Authorization': f'Bearer {token}' ## 获取tenant_access_token,
}
headers['Content-Type'] = multi_form.content_type
response = requests.request("POST", url, headers=headers, data=multi_form).json()
if response.get('code') == 0:
return response['data']['image_key']
else:
return response
这里需要注意几点
- 上传图片的请求需要获取tenant_access_token
- 图片只支持二进制格式
全部代码可关注公众号 DataSpeed,回复 有数webhook 即可获取。
上传后,采用富文本的方式发送,demo如下
def send_image_message(self, youshu_url,youshu_image_base64,report_name,project_name):
url = self.webhook_url
youshu_link = convert_youshu_link(youshu_url)
image_binary = self.base64_to_binary(youshu_image_base64)
image_key_value = uploadImage(get_app_token(),image_binary)
headers = {
"Content-Type": "application/json; charset=utf-8",
}
payload_message = {
"msg_type": "post",
"content": {
"post": {
"zh_cn": {
"title": report_name+" 报表有更新:",
"content": [
[
{
"tag": "text",
"text": project_name+" 项目,"+report_name+" 报表: "
},
{
"tag": "a",
"text": "请查看",
"href": youshu_link
},
{
"tag": "img",
"image_key": image_key_value
}
]
]
}
}
}
}
response = requests.post(url=url, data=json.dumps(payload_message), headers=headers)
return response.json()
六、有数webhook配置
在有数端设置webhook
这里有两点需要注意
- URL:IP是Python运行地址,路由要和上面代码route相同
- 自定义参数:需要写个空对象,防止参数报错
然后就可以设置定时推送了。
建议推送设置使用报告页,最好分开选,因为飞书的图片是有大小限制的,过大的报表可能会超出限制,在飞书聊天框也看不清楚。
数据类型最好选择 实时数据,以保证报表是最新的。
七、总结
有数的报表有些小技巧,如果想实现无权限限制的打开报表,可以用分享的方式,这样url是带token的;如果依旧想做有权限管控的,那就直接用报表本身的url,只要把url中的IP替换一下就行,这些在我提供的代码里已经全部实现了,
在生产环境中,不建议直接使用flask,建议使用Gunicorn,Gunicorn 是一个高性能的 WSGI 服务器,能够处理并发请求,适合在生产环境中部署 Flask 应用。
全部代码可关注公众号 DataSpeed,回复 有数webhook 即可获取。