准备工作:飞书开放平台创建应用

要发送消息,首先需要一个消息发起方,因此需要先前往飞书开放平台,创建一个应用: 应用下添加一个机器人,后续在飞书群组中添加该机器人来发送消息:然后进入自己创建的应用详情页面,查看应用凭证信息:同时注意权限设置:在左侧导航栏中,进入 开发配置 > 权限管理,在 API 权限 中,添加以下权限。

  • 获取与更新群组信息
  • 获取与发送单聊、群组消息

至此,准备工作就已经完成。

开始编码 编写代码通过应用凭证信息app_id+app_secret,封装get_access_token方法,获取该机器人的访问令牌:access_token

def get_access_token(app_id, app_secret):
    """
    获取机器人access_token
    """
    url = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal"
    req = {
        "app_id": app_id,
        "app_secret": app_secret
    }
    request_content = json.dumps(req)
    headers = {
        'Content-Type': 'application/json; charset=utf-8'
    }
    response = requests.request("POST", url, headers=headers, data=request_content)
    print(response.text)
    token = response.json()["tenant_access_token"]
    print("token的值:", token)
    return token
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.

成功获取到access_token值,返回结果如下图: 飞书里面,将该机器人添加到需要发送消息的群组内。封装get_chats方法,通过access_token入参,获取该机器人所在群组的信息,用于后续往指定群组发送消息使用:

def get_chats(access_token):
    """
    获取飞书机器人所在的群列表
    """
    url = "https://open.feishu.cn/open-apis/im/v1/chats"
    headers = {"Authorization": "Bearer {0}".format(access_token)}
    response = requests.request("GET", url, headers=headers)
    res = response.json()
    chats = [{"chat_id": i["chat_id"], "name": i["name"]} for i in res["data"]["items"]]
    print("所在群列表:", chats)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

成功获取该机器人所在群组的信息, 根据前面获得的access_token + 群组信息,封装send方法,调用飞书机器人发送消息API接口,向指定群组发送自定义的消息内容:

def send(access_token, chat_id, msg):
    """
    执行机器人向飞书群组发送消息
    """
    url = "https://open.feishu.cn/open-apis/im/v1/messages"
    params = {"receive_id_type": "chat_id"}
    msg_content = {
        "text": msg,
    }
    req = {
        "receive_id": chat_id,
        "content": json.dumps(msg_content),
        "msg_type": "text",
    }
    payload = json.dumps(req)
    headers = {
        'Authorization': 'Bearer {0}'.format(access_token),
        'Content-Type': 'application/json'
    }
    response = requests.request("POST", url, params=params, headers=headers, data=payload)
    if response.status_code != 200:
        raise Exception("执行机器人向飞书群组发送消息失败")
    res = response.json()
    return res
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.

3.4 最后调用上面封装的方法,完成给指定群组发送指定消息内容的发送,注意将代码中app_id、app_secret的值改为你的应用的值:

if __name__ == '__main__':


    # 项目测试进度消息发送
    app_id = "你的应用app_id"
    app_secret = "你的应用app_secret"
    # 获取机器人的访问令牌
    access_token = get_access_token(app_id,app_secret)
    # 获取该机器人所在群组
    chart_group = get_chats(access_token)


    # 机器人可能在多个群组中,给指定某个群组发消息
    for i in chart_group:
        if i['name'] == '测试消息群':
            # 自定义项目名称、消息体内容
            project_name = '字节跳动'
            detail_message = '1. 项目处于第一轮新功能测试阶段,测试进度60%'
            msg = """<at user_id="all">所有人</at>今日%s项目,测试进度情况如下,请相关责任人注意把控风险:
%s""" % (project_name, detail_message)
            # 发送消息
            send(access_token,i['chat_id'],msg)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.

成功在飞书中给“测试消息群”,发送了以下消息:

五、优化:只在工作日发送消息

5.1 很多时候,我们只想在工作日定时发送飞书消息通知,节假日和周末的时候,就不要再无脑定时发送消息去打扰大家。这个时候就需要判断当前日期是不是节假日,这里给大家推荐一个好用的Python库:chinese_calendar。

5.2 安装:

pip install chinese_calendar
  • 1.

5.3 常用函数:

is_workday    判断是否为工作日,语法:is_workday(date)
is_holiday    判断是否为节假日/休息日,语法:is_holiday(date)
get_holiday_detail 判断是否为节假日并获取节假日名称,语法:get_holiday_detail(date)
get_workdays    传入开始日期和结束日期,得到工作日的日期,语法:get_workdays(start_date,end_date)
get_holidays    传入开始日期和结束日期,得到休息日的日期,语法:get_holidays(start_date,end_date)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

5.4 用法举例:

import datetime
from chinese_calendar import is_workday


date = datetime.datetime.now().date()
# 判断当前日期是不是工作日,工作日才发消息
if is_workday(date):
    print("是工作日")
else:
    print("是休息日")
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

5.5 结合之前发送飞书消息的代码,则是在调用方法前先判断是不是工作日,是工作日才发送消息

if __name__ == '__main__':
    # 获取当前日期并判断是不是工作日,工作日才发消息
    date = datetime.datetime.now().date()
    if is_workday(date):
        # 项目测试进度消息发送
        ......
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

六、更炫酷的卡片消息

6.1 使用上面的内容,发送普通飞书消息已经没有问题。现在飞书还提供了交互页面更好看的卡片消息,让数据更加可视化,并且还能支持一些简单的交互操作。普通消息和卡片消息对比图:


是不是比普通消息更加炫酷、交互也更友好!限于本文篇幅,详细的搭建使用方法如果有大家需要的话,后续可以单独写一篇文章来介绍,这里只简单提一下:

req = {
   // 消息接收者的ID
  "receive_id": "机器人所在的群组ID",
  
  // 卡片消息类型为interactive
  "msg_type": "interactive",
  
  // 消息内容
  "content": "{\"type\":\"template\",\"data\":{\"template_id\":\"xxxxxxxxxxxx\",\"template_version_name\":\"1.0.0\",\"template_variable\":{\"key1\":\"value1\",\"key2\":\"value2\"}}}"
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 消息内容说明:
template_id:搭建工具中创建的卡片的ID,如 AAqigYkzabcef,可在搭建工具中通过复制卡片ID获取
template_version_name:搭建平台中创建的卡片的版本号,如 1.0.0
template_variable:如果卡片模板内设置了变量,则可以在此处为变量名(key)赋值(value),需要动态生成卡片内容时会用到
  • 1.
  • 2.
  • 3.


七、总结

完成代码编写后,建议进行测试和调试,确保你的代码可以正常发送消息,并且消息能够正确显示在指定的群组中。

通过对接飞书API发送群组消息,不仅可以实现高效的团队协作,还可以根据业务需求进行定制化开发,满足不同场景下的工作需求,希望本文能为你在使用飞书API时提供一些帮助和指导。