惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hacker News - Newest:
Hacker News - Newest: "LLM"
AI
AI
T
Troy Hunt's Blog
GbyAI
GbyAI
H
Hacker News: Front Page
SecWiki News
SecWiki News
V2EX - 技术
V2EX - 技术
A
About on SuperTechFans
人人都是产品经理
人人都是产品经理
Hacker News: Ask HN
Hacker News: Ask HN
S
Secure Thoughts
Last Week in AI
Last Week in AI
MyScale Blog
MyScale Blog
L
LINUX DO - 最新话题
C
CERT Recently Published Vulnerability Notes
C
Cyber Attacks, Cyber Crime and Cyber Security
O
OpenAI News
S
SegmentFault 最新的问题
Y
Y Combinator Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
The Cloudflare Blog
P
Proofpoint News Feed
Engineering at Meta
Engineering at Meta
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
美团技术团队
Google DeepMind News
Google DeepMind News
Simon Willison's Weblog
Simon Willison's Weblog
Know Your Adversary
Know Your Adversary
K
Kaspersky official blog
T
The Exploit Database - CXSecurity.com
S
Securelist
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
B
Blog RSS Feed
L
Lohrmann on Cybersecurity
Spread Privacy
Spread Privacy
博客园 - 司徒正美
Stack Overflow Blog
Stack Overflow Blog
博客园 - Franky
The GitHub Blog
The GitHub Blog
B
Blog
F
Fortinet All Blogs
I
InfoQ
C
Check Point Blog
Webroot Blog
Webroot Blog
博客园 - 叶小钗
P
Privacy International News Feed
Latest news
Latest news
Forbes - Security
Forbes - Security
博客园 - 三生石上(FineUI控件)
N
News | PayPal Newsroom

少数派

派早报:Google 发布 Fitbit Air 等 - 少数派 「新人报到」確認需求,再開始 - 少数派 从 SOLO 独立开发者社区,我看到了越来越多开发者开始做自己的产品 - 少数派 我怎么管理那些"不常做,但总会忘"的生活事项 - 少数派 人形机器人量产元年,数据才是具身智能的“生死线” - 少数派 BuhoLaunchpad 高度还原 Mac 启动台:开发历程与思考 - 少数派 五年陪伴依然不舍,DIY 换壳后让罗技 MX Master 3 继续服役 - 少数派 新玩意 240|少数派的编辑们最近买了啥? - 少数派 一日一技|为什么你应该关闭 iOS 的键盘声音 - 少数派 我做了个插件和 Skills,一键提取任何网站的设计规范 Design.md - 少数派 住在三四线城市的你,该开始录播客了 - 少数派 甘南秘境,大白高国 - 少数派 AI的审美:谁让把我变成川内倫子 - 少数派 返工怎能不烦恼,打工人片单总有一部是你的「嘴替」 - 少数派 为了让「上厕所」更健康,我做了一个小工具 - 少数派 AI + Skill,能够让生成的文章去除 AI 味吗? - 少数派 新玩意|韶音OpenDots ONE 耳夹式耳机 - 少数派 《美满》| 在每一个春天的晚上相爱(362) - 少数派 新玩意|优篮子 PS01 MagSnap 磁吸支架 - 少数派 自我整合手记 | 我开始早睡了:用稳定规则,为自由托底 - 少数派 用龙虾(OpenClaw)两个多月,我最深的12个体会 - 少数派 听歌时间到,12 张你可能错过的 2025 华语乐坛好专辑 - 少数派 承诺能追吗 - 少数派 macOS 26启动台没了? 我做了个不一样的App启动器 - Keboard - 少数派 《四海为家的人》| INTJ对话INTJ(361) - 少数派 你发过的那些黑历史,是时候一次清干净了 - 少数派 新玩意:安安静静玩,越玩越专注:计客密码机 - 少数派 iPad 用户首次体验 Android 平板:vivo Pad6 Pro - 少数派 数据逻辑强 - 少数派 极北行+ | 一路向北,探访日本至北之地 | 001 - 少数派 万字剖析:千问App深度体验报告(2026) - 少数派 在2026年,如何真正防止别人抄袭你的作品 - 少数派 怎么用 50 块搭个 AI 语音助手?我踩了 3 天坑 - 少数派 YeeroAI:让 AI 对话真正成为知识管理的一部分 - 少数派 爬泰山 - 少数派 「旅图显影」 App 更新:这次,我们补上了一点「手感」 - 少数派 假期出门太折磨?我的 23 条经验帮你规划惬意旅行 - 少数派 工作流会变吗 - 少数派 Claude Opus 4.6 怎么用最省钱?我测了 5 种方案 - 少数派 GPT Image 2 让图文并茂不再稀罕 - 少数派 用户侧出发——什么是AI,我要不要学习? - 少数派 找片、转存、整理、播放一条龙!让你的付费网盘值回票价 - 少数派 欢迎试用!日课一问2.0插件 - 少数派 自己做的MDeditor,原本想购买 Typora 试了两次支付不成功,干脆自己做一个 - 少数派 vibe coding了一个 3MB 的小工具,让 ~/Downloads 彻底告别混乱 - 少数派 因为受不了 Mac 的风扇策略,我做了一个风扇控制工具 - 少数派 别只怪模型 - 少数派 Warp 终端的 AI 功能怎么用?我测了一周的体验 - 少数派 AI 写代码老是出 bug?这 5 个配置我后悔没早知道 - 少数派 「新玩意」苹果出相机可能就这样:Sigma BF + 45mm F2.8 DG Contemporary - 少数派 一个面向2030年的AI操作系统是什么样子的:浅谈cola这款有灵魂的Agent - 少数派 别只看写代码 - 少数派 每天解决10个问题,还是一口气攻坚解决400个? - 少数派 AI 交易机器人怎么搭?我用 Claude 跑了一周实盘 - 少数派 Maptoposter Online:把你爱的城市画成艺术海报 - 少数派 Function Calling 怎么用?我测了 3 个模型发现差距真大 - 少数派 Legend Talk:我做了个 AI 圆桌,让 160 位思想家围着你的问题转 - 少数派 如何找到自己的蓝方?在小县城寻找压力测试 - 少数派 语音输入与软件接口|2026年聊AI时,我们都聊些什么(上) - 少数派 混动已经卖爆,纯电又来补刀——钛7闪充版简直“不讲武德” - 少数派 本月玩什么|朋友收藏、识质存在、沙罗周期 - 少数派 为什么要每天坚持输出? - 少数派 Claude API 挂了好几个小时,你的项目有备用方案吗? - 少数派 Function Calling 没你想的复杂——我用它做了个有点用的工具 - 少数派 登录系统立即播放视频或者图片音乐的软件 - 少数派 我为什么创建 FlipHTML5 下载工具 - 少数派 残局没电?多品牌外设电量统一管理软件EasyBluetooth已支持RTSS游戏内显示以及AIDA64 - 少数派 前往通义路的路 - 少数派 太好看了,媲美Sun的个人导航页,NAS部署星云门户 - 少数派 乌黑嘴唇“一键检测”上线了 - 少数派 派早报:Claude AI 接入多个创意软件生态、FILCO 生产方接手品牌等 - 少数派 【更新】BearCLI、Claude 连接器与 MCP 服务器 - 少数派 记了上千条流水,还是看不懂财务?我做了一个让 AI 读懂账本的工作台 - 少数派 MINI R56 升级原厂 Sport 模式 - 少数派 新玩意 | 一棵柠檬树(仿真版) - 少数派 Momenta的“物理AI”野望,需迈过“含摩量”这道关 - 少数派 网页直接投屏控制手机!NAS一键部署PandaScrcpy,流畅丝滑可远程。 - 少数派 众测|邀你一同探索随身 AI 硬件入口 YoooClaw C·ONE - 少数派 2050大会:分享时间是真诚 参会记 - 少数派 iPad 赋能电影创作:国内首部宣纸手绘长片《燃比娃》的幕后故事 - 少数派 AI的审美:我用 8 个大模型给 100 张旅行照片打分 - 少数派 普通人如何破圈?去参加一个本地协会 - 少数派 把极空间的图标全换了,主题DIY全攻略打造你的专属NAS桌面 - 少数派 电子便签墙,帮你实现便签自由 - 少数派 我如何用三个 CLI 工具取代文档创建需求 - 少数派 原来真的有人可以玩一辈子 - 少数派 社区速递 139 | 派友热议三月买了啥、复古单反尼康 Df 体验 - 少数派 06 作品的赏析与评价 - 少数派 TDS REVIEW|索尼 WF-1000XM6 降噪真无线耳机体验 - 少数派 35.98万起售的第二代腾势D9,我看重的不是堆料,而是不凑合 - 少数派 鼠须管 Squirrel 皮肤配置指北 - 少数派 从watch ultra2换到redmi watch6 - 少数派 派早报:阿里巴巴发布视频生成模型 HappyHorse 1.0 等 - 少数派 别迷信1M - 少数派 家人们天塌了!网盘“大封杀”,多个渠道多条路,NAS部署PanHub - 少数派 AI与人勾心斗角!NAS一键部署AI狼人杀,假日休闲必备。 - 少数派 电商必备!Comfyui工作流批量生图插件,一次生成12张!支持Nano banana pro模型 - 少数派 Comfyui工作流配置Gpt-image-2模型教程,0.03/张 - 少数派 OpenClaw第三方APi怎么配置?可使用Gpt-image-2模型 - 少数派 会员社区话题精选 Ep. 103 - 少数派
用上飞书的机器人,自己动手做一个群组投票功能 - 少数派
2019-12-11 · via 少数派

当下聊天工具和协作平台争奇斗艳,「开放平台」成为挑选的重要标准之一。飞书的开放平台集各家之所长,既有类似于 Telegram 的 Bot 机器人,也有类似微信公众号的小程序和网页应用。
本文以 Bot 机器人为例,尝试在飞书的开放平台动手完成一个「投票机器人」,借此一窥飞书开放平台的能力和用法。

创建一个 Bot

为便于体验,我们建立一个「企业自建机器人」。在创建时,我们可以选择配置应用名称、应用副标题以及为应用选择一个图标。

进入后台配置页面,开启「机器人」权限,这样,Bot 就创建完成了。 

为了收到用户与 Bot 之间的互动消息,我们需要配置一个 URL 用于接收消息。这个网址需要填写到两个地方,一个是上图中的「消息卡片请求网址」处,另一个是在「事件订阅」菜单下的「请求网址 URL」中。

填写网址后,飞书系统会向这个网址发送一个 POST 请求。这个请求的内容如下:

POST /sspai HTTP/1.1
Host: fs.xxx.xxx
Content-Length: 121
User-Agent: Go-http-client/1.1
Content-Type: application/json;charset=utf-8
X-Request-Id: 17212xxxxxxx
Accept-Encoding: gzip

{"challenge":"b715df13-587e-48e8-acf4-84d3e8dbaa51","token":"9a86Lk3lTNsXhNmu4Jkwce6NO1cje7yR","type":"url_verification"}

按照飞书官方的说法

应用接收此请求后,需要解析出 CHALLENGE 值,并于 1 秒内回复 CHALLENGE 值。

不过由于回复的消息体仍然需要使用 json 格式,并且飞书服务器只读取 challenge 值,因此可以把发过来的消息体原样 echo 回去,并不需要从请求体的 json 数据中解析出 challenge 值。

使用 Python 框架

在进行 challenge 值验证,以及后续与用户的互动中,我们都是使用 RESTful 编程接口与飞书服务器进行交互。如今许多语言都有成熟的框架来支持 RESTful 接口编程,本文以 Python 的 Flask 框架 为例进行操作。

如果不加赘余的验证,那么整个 challenge 过程的代码非常简单:

from flask import Flask, request
app = Flask(__name__)

@app.route('/sspai', methods=['POST'])
def sspai():
    return request.data.decode('utf8')

在这份代码中,前两行可以理解成使用 Flask 创建了一个服务器应用,而第三行提示为访问到 /sspai 这个路径的 POST 请求 进行处理,最后一行则实现了「消息体原样返回」的功能。

启动服务后,在飞书后台填写网址并点击「保存」,认证就会自动完成。

第一次聊天

当正式发布版本后,用户就可以在「工作台」中看到新增的机器人。

点击机器人就可以与它单独聊天,也就是「私聊」的页面。比如,我们可以偷偷地问一下机器人,在今天的抽奖活动中有没有中奖:

当用户向机器人发送消息时,飞书会向我们的服务器发送下面的信息。由于所有通信都采用 JSON 格式,我在下文中将只列出消息体,而省略消息的头部:

{
  "uuid":"095c3xxxxxxxxxxxxxxxxxxxxxxxx",
  "event":{
    "app_id":"cli_9d64bxxxxxxxxxxxxxxx",
    "chat_type":"private",
    "is_mention":false,
    "message_id":"",
    "msg_type":"text",
    "open_chat_id":"oc_c6c35bxxxxxxxxxxxxxxxx",
    "open_id":"ou_27033dxxxxxxxxxxxxxxx",
    "open_message_id":"om_ce23eexxxxxxxxxxxxxxxxxxxx",
    "parent_id":"",
    "root_id":"",
    "tenant_key":"2exxxxxxxxxxxxx",
    "text":"我中奖了吗?",
    "text_without_at_bot":"我中奖了吗?",
    "type":"message",
    "user_agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Lark/3.11.4 Chrome/73.0.3683.119 Electron/5.0.0 Safari/537.36 LarkLocale/zh_CN",
    "user_open_id":"ou_27033dfxxxxxxxxxxxxxxxxx"
  },
  "token":"Qo0xxxxxxxxxxxxxxxxxxxxx",
  "ts":"1576051466.125391",
  "type":"event_callback"
}

在这个消息体中,我们可以依据 "type": "message" 来判定这是一条聊天消息的事件,并依据 "chat_type": "private" 来判定这是一个私聊的消息。在 text 中包含了消息的内容,一系列 ID 则可以确定用户和聊天窗口的信息。

完成了消息的「接收」,下面来看看消息的「发送」。在飞书 Bot 中,消息的发送使用单独的 POST 请求来完成。下面是一个简单的例子:

{
  "chat_id":"oc_c6c35bxxxxxxxxxxxxxxxx",
  "msg_type":"text",
  "content":{
    "text":"你没有中奖,下次努力"
  }
}

把这个消息体发送到 https://open.feishu.cn/open-apis/message/v4/send/ 后,用户就可以接收到对应的文本消息。详细的接口文档可以查看官方说明

这个过程的代码如下:

if(j['event']['chat_type'] == 'private' and j['event']['text'] == '我中奖了吗?'):
    # 经查询,该用户没有中奖
    r = requests.post('https://open.feishu.cn/open-apis/message/v4/send/', headers={'Authorization': 'Bearer '+token}, json={'chat_id': j['event']['open_chat_id'], 'msg_type': 'text', 'content': {'text': '你没有中奖,下次努力'}})
    print(json.dumps(r.json(), indent=4, ensure_ascii=False))

不过,在发送消息之前,我们需要向飞书服务器证明我们的身份,以确认我们确实代表了「中奖啦」这一机器人。这个过程通过向飞书服务器发送我们应用的 app_idapp_secret 来完成,飞书向我们回复的 json 消息中包含 tenant_access_token 字段,也就是我填入前面请求头部的 Authorization 信息。代码如下:

def get_token():
    global token
    r = requests.post('https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal/',json={"app_id": "cli_9dxxxxxxx", "app_secret": "T0OifQVaxxxxxxx"})
    token = r.json()['tenant_access_token']

关于认证的过程,在官方文档中有详细的描述。

创建投票

通过来回的消息互动,可以收集抽奖所需的各个选项:

特别地,当我们的机器人收到一个图片时,隐去一些 ID 之后,消息大致是这样的:

{
  "event":{
    "chat_type":"private",
    "image_height":"756",
    "image_key":"img_2098xxxxxxxxxxxxxxxxxxx",
    "image_url":"https://oapi.zjurl.cn/open-apis/api/v2/file/f/img_2098axxxxxxxxxxxxxx",
    "image_width":"1359",
    "is_mention":false,
    "msg_type":"image",
    "type":"message"
  },
  "type":"event_callback"
}

消息中包含了图片的尺寸,以及一个唯一的 image_key。我们可以直接用它来进行后续消息的发送,也可以通过指定接口把图片下载下来保存

拉进群里一起嗨

除了私聊,机器人当然还可以在群里和大家一起玩耍。

把机器人加入到群聊后,我们的服务器会收到相应的事件提示。如果需要,可以在每次加入群的时候自动跟大家问个好。消息内容大致如下:

{
  "event":{
    "chat_name":"抽个奖",
    "type":"add_bot"
  },
  "type":"event_callback"
}

同样的,当用户 @ 了我们的 Bot,服务器就会收到对应的请求,以便我们进行处理:

{
  "event":{
    "chat_type":"group",
    "is_mention":true,
    "msg_type":"text",
    "text":"1021 <at open_id=\"ou_437a0e8372339eefab712c09388f61eb\">@中奖啦</at>",
    "text_without_at_bot":"1021 ",
    "type":"message"
  },
  "type":"event_callback"
}

更自由的消息卡片

在生成投票后,我们可以使用「消息卡片」在群里发起投票。飞书机器人的消息卡片不但可以包含图片、分割线、纯文本、Markdown 格式的内容,还可以包含多选菜单、日期选择和按钮等互动组件,用来与用户之间形成更友好的互动。

在上图这个消息卡片中,「iPad Air 3」是消息卡片的标题。内容部分分成三块,首先是之前上传的图片,第二部分是以 Markdown 格式撰写的正文内容,最底下是一个互动按钮。
整个消息卡片的请求体如下:

{
  "open_chat_id":"oc_8e9a1dcc6d83b231ddf1bb951de09f58",
  "msg_type":"interactive",
  "card":{
    "header":{
      "title":{
        "tag":"plain_text",
        "content":"iPad Air 3"
      }
    },
    "elements":[
      {
        "tag":"img",
        "img_key":"img_2098a60d-8267-4d4c-91a8-d94b2baf90dg",
        "alt":{
          "tag":"plain_text",
          "content":"iPad Air 3"
        }
      },
      {
        "tag":"div",
        "text":{
          "tag":"lark_md",
          "content":"活动描述:**Apple 出品**\n开奖时间:**2019-12-11 18:00**"
        }
      },
      {
        "tag":"action",
        "actions":[
          {
            "tag":"button",
            "text":{
              "tag":"plain_text",
              "content":"参加抽奖"
            },
            "type":"default"
          }
        ]
      }
    ]
  }
}

自上而下分成四部分,消息卡片的基础排版格式十分清晰。除此之外,卡片还支持多种元素的组合排版,用以呈现更加丰富、定制化的卡片效果。

参加抽奖并揭晓结果

当群里的用户点击了「参加抽奖」按钮,我们的服务器会收到一个事件提示:

{
  "open_id":"ou_27033xxxxxxx",
  "user_id":"d1xxxxxx",
  "open_message_id":"om_06308xxxxxxxxxx",
  "tenant_key":"2exxxxxxxx",
  "token":"c-981edd0xxxxxxx",
  "action":{
    "tag":"button"
  }
}

由于消息中包含了用户信息,我们可以向该用户发送私信,通知他已成功参加抽奖。揭晓结果时,同样可以用私聊的形式通知该用户。
此外,在结果揭晓时,机器人会发送一条群信息,公布所有获奖的用户。通过用户的 open_id,我们可以直接在群里 @ 他们:

{
  "chat_id":"oc_8e9a1xxxxxxxxxx",
  "msg_type":"text",
  "content":{
    "text":"恭喜中奖 <at user_id=\"ou_270xxxxxxx\"></at>"
  }
}

效果如下:

如此,我们便完成了整个抽奖过程。