网易有数 Webhook 成功对接飞书,实现报表推送

一、背景介绍

在网易有数平台的实际应用中,报表推送虽支持 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,建议使用GunicornGunicorn 是一个高性能的 WSGI 服务器,能够处理并发请求,适合在生产环境中部署 Flask 应用。

全部代码可关注公众号 DataSpeed,回复 有数webhook 即可获取。

### 飞书 Webhook 消息推送使用教程 #### 发送简单文本消息 为了通过飞书Webhook接口发送消息,请求应当遵循特定结构。对于简单的文本消息而言,HTTP POST方法被用来提交数据到指定的webhook地址。请求头部需设置`Content-Type: application/json`表示主体内容采用JSON格式。而请求体则应包含两个主要部分:`msg_type`用于指明消息类型,在这里是"text"; `content`字段下嵌套有实际要传达的文字信息。 ```json { "msg_type": "text", "content": { "text": "这是测试消息" } } ``` 此段代码展示了如何构建一个基本的消息对象并将其转换成字符串形式以便于传输[^3]。 #### Python脚本实现自动化发送 除了手动构造HTTP请求外,还可以借助编程语言如Python来简化这一过程。下面给出了一段利用requests库执行上述操作的例子: ```python import requests import json url = 'https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxx' # 替换成自己的webhook URL headers = {'Content-Type': 'application/json'} data = { "msg_type": "text", "content": { "text": "来自Python脚本的通知!" } } response = requests.post(url=url, headers=headers, data=json.dumps(data)) print(response.text) ``` 这段代码实现了向飞书群组发送一条通知的功能,并打印服务器返回的结果以供调试之用[^2]。 #### 定时任务调度 如果希望定期自动触发这类消息推送,则可引入第三方库APScheduler来管理时间间隔或具体时刻的任务安排。安装该库之后,可以根据需求配置不同的计划策略,比如每隔一段时间重复一次或者仅在某些特殊日子运行等[^4]。 ```python from apscheduler.schedulers.blocking import BlockingScheduler import time import requests import json def send_message(): url = 'https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxx' headers = {'Content-Type': 'application/json'} timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) message = f"当前时间为:{timestamp}" payload = { "msg_type": "text", "content": {"text": message} } response = requests.request("POST", url, headers=headers, data=json.dumps(payload)) print(f'Sent at {message}, Response:', response.text) sched = BlockingScheduler() # 添加job函数为send_message(), trigger='interval', seconds=10 表示每十秒执行一次. sched.add_job(send_message, 'interval', seconds=10) try: sched.start() # 启动调度器 except (KeyboardInterrupt, SystemExit): pass ``` 以上实例演示了一个基于固定周期(这里设定为10秒钟)循环发送带有当前时间戳的信息至目标聊天室的方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值