Webhook
Webhook 允许 Bubble 平台通过 HTTP POST 请求将事件推送到您的服务器。
配置 Webhook
- 登录 Bubble 平台
- 进入「机器人管理」
- 找到「Webhook URL」设置
- 输入您的接收地址(必须是 HTTPS)
- 保存配置
Webhook 请求格式
请求头
POST /webhook HTTP/1.1
Host: your-server.com
Content-Type: application/json
X-Bubble-Event: MESSAGE_CREATE
X-Bubble-Signature: sha256=...
请求体
{
"type": "MESSAGE_CREATE",
"data": {
"id": 1001,
"channelId": 5,
"guildId": 10,
"content": "Hello!",
"author": {
"id": 1,
"name": "user"
},
"timestamp": "2025-12-31T12:00:00Z"
}
}
接收示例
Express (Node.js)
const express = require('express');
const app = express();
app.use(express.json());
app.post('/webhook', (req, res) => {
const eventType = req.headers['x-bubble-event'];
const event = req.body;
console.log(`收到事件: ${eventType}`);
// 处理不同类型的事件
switch (event.type) {
case 'MESSAGE_CREATE':
handleMessage(event.data);
break;
case 'GUILD_MEMBER_ADD':
handleMemberJoin(event.data);
break;
}
// 必须返回 200
res.status(200).send('OK');
});
app.listen(3000);
Flask (Python)
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/webhook', methods=['POST'])
def webhook():
event_type = request.headers.get('X-Bubble-Event')
event = request.json
print(f'收到事件: {event_type}')
if event['type'] == 'MESSAGE_CREATE':
handle_message(event['data'])
return jsonify({'status': 'ok'}), 200
app.run(port=3000)
推送的事件类型
Webhook 会推送所有事件类型(无法选择性订阅):
- MESSAGE_CREATE
- MESSAGE_UPDATE
- MESSAGE_DELETE
- DM_MESSAGE_CREATE
- DM_MESSAGE_UPDATE
- DM_MESSAGE_DELETE
- GUILD_MEMBER_ADD
- GUILD_MEMBER_REMOVE
完整列表请参考 事件参考。
安全验证
签名验证(即将支持)
验证请求来自 Bubble 平台:
const crypto = require('crypto');
function verifySignature(payload, signature, secret) {
const hmac = crypto.createHmac('sha256', secret);
const digest = 'sha256=' + hmac.update(payload).digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(digest)
);
}
app.post('/webhook', (req, res) => {
const signature = req.headers['x-bubble-signature'];
const payload = JSON.stringify(req.body);
if (!verifySignature(payload, signature, BOT_SECRET)) {
return res.status(401).send('Invalid signature');
}
// 处理事件...
});