币聊机器人 API 说明

机器人 API

币聊机器人采用「HTTP 主动调用 + Webhook 被动推送」模式:你在 App 创建机器人拿到 bot_token,服务端把用户消息 POST 到你的 Webhook,你的服务再用 Token 调 API 回复。下文按上手 → 收消息 → 发消息 → 接口明细组织,示例域名 https://api.bi.ink 可按实际环境替换。

上手

整体流程如下,按顺序完成即可跑通最小闭环:

  1. 创建机器人:App 内创建,保存 bot_tokenwebhook_secret(创建时返回,用于校验推送签名)。
  2. 配置 Webhook:在机器人设置里填写公网 HTTPS 地址(如 https://your.domain/webhook),用户发消息时服务端会 POST 到此地址。
  3. 接收事件:你的服务解析 JSON,根据 event_type 分支处理(见 Webhook)。
  4. 调用 API 回复:用 bot_token/bot/sendmessage 等接口发消息。

1. 鉴权 Token

下列机器人 API(发消息、改消息、上传等)均需在 Header 携带 Authorization: Bearer YOUR_BOT_TOKEN。Token 泄露等同于机器人账号被盗,请勿写入前端或公开仓库。

2. 发一条文字(最小示例)

bash
curl -X POST "https://api.bi.ink/bot/sendmessage" \
  -H "Authorization: Bearer YOUR_BOT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "target_user_id": "user_456",
    "message_type": "text",
    "content": "你好,我是机器人"
  }'

会话目标二选一:群聊填 group_id;私聊填 target_user_id(用户 ID,不是 username)。

3. 发图片(先上传再发送)

图片 / 视频 / 音频 / 文件需先上传拿 file_id,再调用发消息接口。

bash
# ① 上传
curl -X POST "https://api.bi.ink/bot/uploadfile" \
  -H "Authorization: Bearer YOUR_BOT_TOKEN" \
  -F "file=@/path/to/image.jpg"

# ② 发送(用上一步返回的 file_id)
curl -X POST "https://api.bi.ink/bot/sendmessage" \
  -H "Authorization: Bearer YOUR_BOT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "group_id": "group_123",
    "message_type": "image",
    "file_id": "file_123456",
    "content": "可选说明文字"
  }'

鉴权与响应

机器人 API 请求头

路径以 /bot/sendmessage/bot/getme 等为代表的接口,使用 bot_token 鉴权:

http
Authorization: Bearer YOUR_BOT_TOKEN
Content-Type: application/json

App 内管理机器人(创建、改 Webhook、重置 Token)走用户登录态 access_token,与 bot_token 不同,详见 App 内机器人管理页。

统一响应格式

成功时 code200(部分旧接口也可能为 0),业务数据在 data 里;失败时 code 非 200,msg 为错误说明。

json
{
  "code": 200,
  "msg": "发送成功",
  "data": { ... }
}
HTTP 状态 常见原因
401 Token 无效、过期或未携带
403 机器人不在群内、无禁言/删消息权限、只能编辑自己的消息等
400 参数缺失、group_idtarget_user_id 均未填等

消息类型

message_type 取值与 JSON 骨架如下(group_id / target_user_id 按会话类型选一个)。

文本 text

纯文字。

json
{
  "group_id": "group_123",
  "message_type": "text",
  "content": "这是一条文本消息"
}
字段 类型 说明 必填
message_type string 固定 text
content string 正文

图片 image

JPG / PNG / GIF 等,需先有 file_id

json
{
  "group_id": "group_123",
  "message_type": "image",
  "content": "可选说明",
  "file_id": "file_123456"
}
字段 类型 说明 必填
message_type string 固定 image
file_id string 上传接口返回
content string 说明,可空

视频 video

如 MP4、MOV。

json
{
  "group_id": "group_123",
  "message_type": "video",
  "content": "可选说明",
  "file_id": "file_123456"
}
字段 类型 说明 必填
message_type string 固定 video
file_id string 上传接口返回
content string 说明,可空

音频 audio

如 MP3、WAV、M4A。

json
{
  "group_id": "group_123",
  "message_type": "audio",
  "content": "可选说明",
  "file_id": "file_123456"
}
字段 类型 说明 必填
message_type string 固定 audio
file_id string 上传接口返回
content string 说明,可空

文件 file

任意附件类型。

json
{
  "group_id": "group_123",
  "message_type": "file",
  "content": "可选说明",
  "file_id": "file_123456"
}
字段 类型 说明 必填
message_type string 固定 file
file_id string 上传接口返回
content string 说明,可空

贴纸 sticker

file_id 即可,服务端会解析资源。

json
{
  "group_id": "group_123",
  "message_type": "sticker",
  "file_id": "sticker_123456"
}

骰子 dice

当前仅支持标准骰子 🎲(点数 1–6)。暂不支持飞镖、篮球等其他互动 emoji。点数由服务端随机生成,请求里不能指定,也不能在发完后再查接口补拿——必须在当次响应或 Webhook 里读取。

① 机器人发骰子

content 可省略(默认 🎲),一般只需 message_type: "dice" 加会话目标即可。

bash
curl -X POST "https://api.bi.ink/bot/sendmessage" \
  -H "Authorization: Bearer YOUR_BOT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "target_user_id": "user_456",
    "message_type": "dice"
  }'

② 如何获取点数(机器人自己发的)

调用 /bot/sendmessage 成功后,从响应体读取:

data.content.value → 整数 1–6,即本次掷出的点数。

json
{
  "code": 200,
  "msg": "发送成功",
  "data": {
    "message_id": "msg_abc123",
    "conversation_id": "private_xxx_yyy",
    "message_type": "dice",
    "content": {
      "type": "dice",
      "emoji": "🎲",
      "text": "🎲",
      "value": 4
    },
    "created_at": 1732636800
  }
}

data.content对象(不是字符串)。业务里用 result["data"]["content"]["value"] 即可。可同时保存 message_id 供后续引用。

字段 类型 说明 必填
message_type string 固定 dice
content string 可省略;若填则仅 🎲 有效,其他 emoji 会被服务端归一为 🎲

③ 用户发骰子(Webhook 推送)

用户向机器人私聊或群内发送骰子时,Webhook 里 message_typedice,但 contentJSON 字符串,需先解析再取 value

python
# Webhook 收到用户骰子
import json
dice = json.loads(event["content"])
points = dice["value"]   # 1-6
json
{
  "event_type": "private_message",
  "message_type": "dice",
  "content": "{\"type\":\"dice\",\"emoji\":\"🎲\",\"text\":\"🎲\",\"value\":5}"
}

两种场景对比

场景 点数在哪 content 格式
机器人调用 sendmessage 发骰子 HTTP 响应 data.content.value 对象
用户发骰子 → Webhook 通知机器人 Webhook 正文 content 解析后的 value JSON 字符串,需 parse

联系人 contact

分享名片,file_id 此处为用户相关标识(与业务约定一致)。

json
{
  "group_id": "group_123",
  "message_type": "contact",
  "file_id": "user_123456"
}

按钮与回复

内联键盘

发消息时在 extra.inline_keyboard 里放二维数组,每项为 text + callback_data

json
{
  "group_id": "group_123",
  "message_type": "text",
  "content": "请选择:",
  "extra": {
    "inline_keyboard": [
      [
        {"text": "确认", "callback_data": "confirm"},
        {"text": "取消", "callback_data": "cancel"}
      ],
      [
        {"text": "查看详情", "callback_data": "detail"}
      ]
    ]
  }
}

回调怎么处理

  1. 用户点了按钮,你的 Webhook 会收到 event_typecallback_query 的 JSON。
  2. 里面会有 callback_id(形如 cb_userId_xxx)、callback_data、原消息 message_id、点击人 sender_id
  3. 在约 30 秒内请求 POST /bot/answercallback,把 callback_id 回给服务端;需要的话再调 editmessage 改文案或清掉键盘。

Webhook 回调示例

json
{
  "event_type": "callback_query",
  "message_id": "msg_abc123",
  "sender_id": "user_xxx",
  "sender_username": "john",
  "sender_display_name": "John Doe",
  "group_id": "group_123",
  "group_title": "测试群组",
  "message_type": "callback",
  "content": "confirm",
  "timestamp": 1732636800,
  "callback_id": "cb_user123_abc12345",
  "callback_data": "confirm"
}

应答回调

bash
curl -X POST "https://api.bi.ink/bot/answercallback" \
  -H "Authorization: Bearer YOUR_BOT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "callback_id": "cb_user123_abc12345",
    "text": "操作成功",
    "show_alert": false
  }'

text:提示文案;show_alerttrue 时用弹窗,否则多为轻提示;url 可选,给按钮跳转用。

回复某条消息

json
{
  "group_id": "group_123",
  "message_type": "text",
  "content": "回复内容",
  "reply_to_id": "msg_123456"
}

引用消息

json
{
  "group_id": "group_123",
  "message_type": "text",
  "content": "引用回复",
  "quote_message_id": "msg_123455"
}

Webhook

在 App 机器人设置中配置 webhook_url 后,相关事件会以 POST + JSON 推送到你的服务器。你的服务应在几秒内返回 HTTP 2xx;耗时逻辑请异步处理,否则可能触发重试(最多 1 次)。

推送请求头

Header 说明
Content-Type: application/json 固定 JSON 正文
X-Bot-Token 机器人 Token,可用于核对来源
X-Bot-User-Id 机器人用户 ID
X-Webhook-Signature 原始 JSON 正文的 HMAC-SHA256 十六进制签名(配置了 webhook_secret 时才有)

签名校验(推荐)

创建机器人时会得到 webhook_secret。收到推送后,用同样算法验签,防止伪造请求:

python
import hmac, hashlib

def verify_webhook(raw_body: bytes, secret: str, signature: str) -> bool:
    expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature or "")

事件类型 event_type

event_type 何时触发 说明
private_message 用户私聊机器人 group_id 为空
group_message 群内有人发消息 机器人须在群内且拥有读消息权限(can_read_messages=1
callback_query 用户点击内联按钮 callback_id,须在 30 秒内 answercallback
member_joined 新成员入群 message_typemember_eventcontent 为邀请人 user_id(无则为空)
member_left 成员退群 / 被踢 content 为原因:left / kicked / banned
group_dissolved 群被解散 content 固定 dissolved

载荷字段说明

字段 类型 说明
event_typestring事件类型,见上表
message_idstring消息 ID(成员事件可能为空)
sender_idstring发送者 / 相关用户 ID
sender_usernamestring发送者 @用户名
sender_display_namestring发送者昵称
sender_avatar_urlstring发送者头像
sender_rolestring群内角色:owner / admin / member(仅群消息)
group_idstring群组 ID,私聊为空
group_titlestring群名称
message_typestring消息类型:textimagedicecallback
contentstring文本内容;骰子为 JSON 字符串(见下)
timestampintUnix 秒级时间戳
callback_idstring按钮回调 ID(仅 callback_query)
callback_datastring按钮自定义数据(仅 callback_query)

私聊文字消息示例

json
{
  "event_type": "private_message",
  "message_id": "msg_abc123",
  "sender_id": "user_xxx",
  "sender_username": "john",
  "sender_display_name": "John Doe",
  "group_id": "",
  "message_type": "text",
  "content": "你好",
  "timestamp": 1732636800
}

群消息示例

json
{
  "event_type": "group_message",
  "message_id": "msg_grp_001",
  "sender_id": "user_xxx",
  "sender_username": "alice",
  "sender_display_name": "Alice",
  "sender_role": "member",
  "group_id": "group_123",
  "group_title": "测试群组",
  "message_type": "text",
  "content": "/help",
  "timestamp": 1732636800
}

用户掷骰子(Webhook)

用户发送骰子时,message_typedicecontent 为 JSON 字符串。解析后取 value(1–6)。与机器人自己发骰子不同:Webhook 里 content 是字符串,sendmessage 响应里 content 是对象。详见 骰子

json
{
  "event_type": "private_message",
  "message_id": "msg_dice_001",
  "sender_id": "user_xxx",
  "message_type": "dice",
  "content": "{\"type\":\"dice\",\"emoji\":\"🎲\",\"text\":\"🎲\",\"value\":5}",
  "timestamp": 1732636800
}

新成员入群示例

json
{
  "event_type": "member_joined",
  "sender_id": "user_newbie",
  "sender_username": "newbie",
  "sender_display_name": "新同学",
  "group_id": "group_123",
  "group_title": "欢迎群",
  "message_type": "member_event",
  "content": "user_inviter_id",
  "timestamp": 1732636800
}

接口列表

以下接口均使用 bot_token 鉴权,请求方法均为 POST,路径前缀 /bot/

路径 作用
/bot/getme获取当前机器人信息
/bot/sendmessage发送消息(文本 / 媒体 / 骰子 / 按钮等)
/bot/editmessage编辑机器人自己发的消息
/bot/deletemessage删除消息(单条或批量)
/bot/uploadfile上传文件,获取 file_id
/bot/answercallback响应内联按钮点击
/bot/botapisetcommands设置命令菜单(最多 100 条)
/bot/botapigetcommands读取命令菜单
/bot/getgroup获取机器人所在群资料
/bot/mutemember禁言成员 / 全员禁言
/bot/unmutemember解除禁言 / 解除全员禁言

sendmessage 公共参数

字段 类型 说明 必填
group_idstring群 ID(群聊)与 target_user_id 二选一
target_user_idstring用户 ID(私聊)与 group_id 二选一
message_typestring消息类型
contentstring文本 / 说明 / 骰子 emoji视类型而定
file_idstring媒体文件 ID(上传接口返回)媒体类必填
reply_to_idstring回复某条消息
quote_message_idstring引用某条消息
mention_user_idsstring[]@提及的用户名列表(username,非 user_id)
mention_allbool@所有人
extra.inline_keyboardarray内联按钮,见按钮与回复

上传文件 uploadfile

POST /bot/uploadfilemultipart/form-data,字段名 file。单文件最大 100MB,支持常见图片 / 视频 / 音频 / 文档 / 压缩包。

bash
curl -X POST "https://api.bi.ink/bot/uploadfile" \
  -H "Authorization: Bearer YOUR_BOT_TOKEN" \
  -F "file=@/path/to/file.jpg"
json
{
  "code": 200,
  "msg": "文件上传成功",
  "data": {
    "file_id": "file_123456"
  }
}

发消息 sendmessage

POST /bot/sendmessage。媒体类传 file_id;骰子见 骰子——点数在响应 data.content.value,无单独查询接口。

json
{
  "code": 200,
  "msg": "发送成功",
  "data": {
    "message_id": "msg_xxx",
    "conversation_id": "private_bot_user",
    "message_type": "dice",
    "content": {
      "type": "dice",
      "emoji": "🎲",
      "text": "🎲",
      "value": 3
    },
    "created_at": 1732636800
  }
}

编辑消息

POST /bot/editmessage

json
{
  "message_id": "msg_xxx",
  "content": "已更新",
  "extra": {
    "inline_keyboard": []
  }
}

删消息

POST /bot/deletemessage。单条:

json
{ "message_id": "msg_xxx" }

多条:

json
{ "message_ids": ["msg_123", "msg_456", "msg_789"] }

群里通常要有管理权限或机器人被授予相应能力;私聊里参与者规则以客户端为准。

当前机器人信息 getme

POST /bot/getme,无请求体。返回机器人 user_id、username、昵称、头像等。

json
{
  "code": 200,
  "msg": "获取成功",
  "data": {
    "user_id": "bot_xxx",
    "username": "my_bot",
    "display_name": "我的机器人",
    "bio": "简介",
    "avatar_url": "https://...",
    "status": 1,
    "created_at": "2025-01-01 00:00:00"
  }
}

群资料 getgroup

POST /bot/getgroup,机器人须在目标群内。为隐私考虑不返回群主 ID

json
// 请求
{ "group_id": "group_123" }

// 响应 data
{
  "group_id": "group_123",
  "title": "测试群",
  "description": "群简介",
  "avatar": "https://...",
  "member_count": 128,
  "is_public": 1,
  "is_cy": 0,
  "created_at": "2025-01-01 00:00:00"
}

应答按钮 answercallback

POST /bot/answercallback,收到 callback_query 后尽快调用。

json
{
  "callback_id": "cb_user123_abc12345",
  "text": "操作成功",
  "show_alert": false,
  "url": ""
}
字段 类型 说明 必填
callback_id string Webhook 里原样带回
text string 提示文案
show_alert bool 是否弹窗
url string 打开链接

命令菜单

设置:POST /bot/botapisetcommands

json
{
  "commands": [
    {"command": "start", "description": "开始使用"},
    {"command": "help", "description": "帮助"},
    {"command": "price", "description": "查价"}
  ]
}

读取:POST /bot/botapigetcommands

群成员禁言 mutemember / unmutemember

机器人须为群主、管理员,或被授予 can_mute_members 权限。不能禁言群主或其他管理员。

json
// 禁言单人 3600 秒(1 小时);mute_duration=0 表示永久
{
  "group_id": "group_123",
  "member_user_id": "user_456",
  "mute_duration": 3600
}

// 全员禁言:member_user_id 传 "all" 或 "*"
{
  "group_id": "group_123",
  "member_user_id": "all",
  "mute_duration": 0
}

// 解除单人禁言
{
  "group_id": "group_123",
  "member_user_id": "user_456"
}

// 解除全员禁言
{
  "group_id": "group_123",
  "member_user_id": "all"
}

不提供「拉取完整群成员列表」接口;定向操作请使用业务侧已知的 user_id

常见问题

收不到 Webhook?
确认 URL 为公网 HTTPS;App 内已保存 Webhook;机器人已加入目标群且拥有读消息权限(群消息)。本地调试可用 ngrok 等隧道。
群消息是否必须 @ 机器人?
群内所有消息都会推送给有读权限的机器人(与 Telegram 不同),请在业务层自行过滤命令或关键词。
私聊用户 ID 从哪来?
Webhook 推送里的 sender_id 即为 target_user_id,回复私聊时原样填入即可。
机器人发骰子后怎么知道点数?
看当次 /bot/sendmessage 响应里的 data.content.value(整数 1–6)。没有「按 message_id 再查点数」的接口,发完必须当场读响应。
骰子能指定点数吗?
不能。仅支持 🎲(1–6),由服务端 crypto/rand 随机,Bot 与用户均不可指定或篡改。
按钮点了没反应?
须在 30 秒内调用 /bot/answercallback 并传入 Webhook 里的 callback_id;可用 editmessage 更新原消息或清空键盘。
code 用 200 还是 0?
新接口统一 200 表示成功;示例代码中建议写 code in (0, 200) 兼容旧版。

示例代码

Python:发文字

python
import requests

def send_text_message(bot_token, group_id, content):
    url = "https://api.bi.ink/bot/sendmessage"
    headers = {
        "Authorization": f"Bearer {bot_token}",
        "Content-Type": "application/json"
    }
    data = {
        "group_id": group_id,
        "message_type": "text",
        "content": content
    }
    response = requests.post(url, json=data, headers=headers)
    return response.json()

Python:上传后发图

python
import requests

def upload_file(bot_token, file_path):
    url = "https://api.bi.ink/bot/uploadfile"
    headers = {"Authorization": f"Bearer {bot_token}"}
    with open(file_path, 'rb') as f:
        files = {'file': f}
        response = requests.post(url, files=files, headers=headers)
        result = response.json()
        if result.get('code') == 200:
            return result['data']['file_id']
        raise RuntimeError(result.get('msg', 'upload failed'))

def send_image_message(bot_token, group_id, file_id, caption=""):
    url = "https://api.bi.ink/bot/sendmessage"
    headers = {
        "Authorization": f"Bearer {bot_token}",
        "Content-Type": "application/json"
    }
    data = {
        "group_id": group_id,
        "message_type": "image",
        "file_id": file_id,
        "content": caption
    }
    response = requests.post(url, json=data, headers=headers)
    return response.json()

file_id = upload_file(bot_token, "/path/to/image.jpg")
send_image_message(bot_token, "group_123", file_id, "说明")

Python:带按钮

python
def send_message_with_buttons(bot_token, group_id, content):
    url = "https://api.bi.ink/bot/sendmessage"
    headers = {
        "Authorization": f"Bearer {bot_token}",
        "Content-Type": "application/json"
    }
    data = {
        "group_id": group_id,
        "message_type": "text",
        "content": content,
        "extra": {
            "inline_keyboard": [
                [
                    {"text": "确认", "callback_data": "confirm"},
                    {"text": "取消", "callback_data": "cancel"}
                ]
            ]
        }
    }
    return requests.post(url, json=data, headers=headers).json()

Python:Flask 收 Webhook(含验签 + 私聊回复)

python
import json, hmac, hashlib, requests
from flask import Flask, request

app = Flask(__name__)
BOT_TOKEN = "your_bot_token"
WEBHOOK_SECRET = "your_webhook_secret"
API_BASE = "https://api.bi.ink"

def verify_signature(raw: bytes, sig: str) -> bool:
    expected = hmac.new(WEBHOOK_SECRET.encode(), raw, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, sig or "")

def api_post(path, payload):
    return requests.post(
        f"{API_BASE}{path}",
        json=payload,
        headers={"Authorization": f"Bearer {BOT_TOKEN}", "Content-Type": "application/json"},
        timeout=10,
    )

@app.route("/webhook", methods=["POST"])
def webhook():
    raw = request.get_data()
    if not verify_signature(raw, request.headers.get("X-Webhook-Signature", "")):
        return "invalid signature", 403
    event = json.loads(raw)

    et = event.get("event_type")
    if et == "private_message" and event.get("content") == "/start":
        api_post("/bot/sendmessage", {
            "target_user_id": event["sender_id"],
            "message_type": "text",
            "content": "欢迎使用,发送 /help 查看命令",
        })
    elif et == "private_message" and event.get("message_type") == "dice":
        dice = json.loads(event["content"])
        api_post("/bot/sendmessage", {
            "target_user_id": event["sender_id"],
            "message_type": "text",
            "content": f"你掷出了 {dice['value']} 点",
        })
    elif et == "callback_query":
        api_post("/bot/answercallback", {
            "callback_id": event["callback_id"],
            "text": "已收到",
            "show_alert": False,
        })
    return "OK", 200

Python:机器人发骰子并读取点数

python
import requests

def send_dice_and_get_value(bot_token, target_user_id):
    r = requests.post(
        "https://api.bi.ink/bot/sendmessage",
        json={
            "target_user_id": target_user_id,
            "message_type": "dice",
        },
        headers={"Authorization": f"Bearer {bot_token}"},
        timeout=10,
    ).json()
    if r.get("code") not in (0, 200):
        raise RuntimeError(r.get("msg", "send failed"))
    # 点数在这里 —— 必须是对象,不是字符串
    value = r["data"]["content"]["value"]
    message_id = r["data"]["message_id"]
    return value, message_id

# 示例:掷骰后回复文字
points, _ = send_dice_and_get_value(BOT_TOKEN, "user_456")
requests.post(
    "https://api.bi.ink/bot/sendmessage",
    json={
        "target_user_id": "user_456",
        "message_type": "text",
        "content": f"机器人掷出了 {points} 点",
    },
    headers={"Authorization": f"Bearer {BOT_TOKEN}"},
)

Python:Flask 收 Webhook(按钮回调,精简版)

python
import requests
from flask import Flask, request

app = Flask(__name__)
BOT_TOKEN = "your_bot_token"
API_BASE_URL = "https://api.bi.ink"

@app.route('/webhook', methods=['POST'])
def webhook():
    event = request.json
    if event.get('event_type') == 'callback_query':
        callback_id = event['callback_id']
        callback_data = event['callback_data']
        message_id = event['message_id']
        if callback_data == 'confirm':
            answer_callback(callback_id, '已确认', False)
            edit_message(message_id, '已确认', {'inline_keyboard': []})
        elif callback_data == 'cancel':
            answer_callback(callback_id, '已取消', False)
    return 'OK', 200

def answer_callback(callback_id, text, show_alert):
    requests.post(
        f"{API_BASE_URL}/bot/answercallback",
        json={"callback_id": callback_id, "text": text, "show_alert": show_alert},
        headers={"Authorization": f"Bearer {BOT_TOKEN}", "Content-Type": "application/json"},
    )

def edit_message(message_id, content, extra):
    requests.post(
        f"{API_BASE_URL}/bot/editmessage",
        json={"message_id": message_id, "content": content, "extra": extra},
        headers={"Authorization": f"Bearer {BOT_TOKEN}", "Content-Type": "application/json"},
    )

Go:发文字

go
package main

import (
    "bytes"
    "encoding/json"
    "net/http"
)

func sendMessage(botToken, groupID, content string) error {
    url := "https://api.bi.ink/bot/sendmessage"
    data := map[string]interface{}{
        "group_id":     groupID,
        "message_type": "text",
        "content":      content,
    }
    jsonData, _ := json.Marshal(data)
    req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
    req.Header.Set("Authorization", "Bearer "+botToken)
    req.Header.Set("Content-Type", "application/json")
    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        return err
    }
    defer resp.Body.Close()
    return nil
}

Node:Express Webhook

javascript
const express = require('express');
const axios = require('axios');
const app = express();
app.use(express.json());

const BOT_TOKEN = 'your_bot_token';
const API_BASE_URL = 'https://api.bi.ink';

app.post('/webhook', async (req, res) => {
    const event = req.body;
    if (event.event_type === 'private_message' && event.content === '/start') {
        await axios.post(`${API_BASE_URL}/bot/sendmessage`, {
            target_user_id: event.sender_id,
            message_type: 'text',
            content: '欢迎使用'
        }, { headers: { Authorization: `Bearer ${BOT_TOKEN}` } });
    } else if (event.event_type === 'callback_query') {
        await axios.post(`${API_BASE_URL}/bot/answercallback`, {
            callback_id: event.callback_id,
            text: '收到',
            show_alert: false
        }, { headers: { Authorization: `Bearer ${BOT_TOKEN}` } });
    }
    res.status(200).send('OK');
});

app.listen(3000);