准备工作
- 开通了接收消息权限的飞书机器人,例如我希望用户跟飞书机器人私聊,就需要开通这个权限:读取用户发给机器人的单聊消息 im:message.p2p_msg:readonly
- 准备好飞书机器人的API key 和Secret
- deepseek-v3的api key+secret:https://platform.deepseek.com/api_keys 这里获取,一开始有10元的免费额度,趁能充多充点,经常不让充值。
- 自己部署一下dify,推荐使用docker-compose方式,这个有很多教程就不赘述了
飞书机器人通过长连接获取用户私聊发的消息
我们使用长连接的方式接收用户消息,需要在飞书开发者后台中配置一下应用,见
配置回调订阅方式
代码如下:
import(
larkevent "github.com/larksuite/oapi-sdk-go/v3/event"
"github.com/larksuite/oapi-sdk-go/v3/event/dispatcher"
"github.com/larksuite/oapi-sdk-go/v3/service/auth/v3"
larkim "github.com/larksuite/oapi-sdk-go/v3/service/im/v1"
larkws "github.com/larksuite/oapi-sdk-go/v3/ws"
)
var sent map[string]struct{} // 这里简单去个重 实际使用要自己再写去重部分
// 飞书消息过来Content字段值是{\"text\":\"早上好~\"}这样的,需要再解析一下
type Text struct {
Text string `json:"text"`
}
// 处理接收到用户消息的事件
func callback() {
sent = make(map[string]struct{})
// 注册事件回调,OnP2MessageReceiveV1 为接收消息 v2.0;OnCustomizedEvent 内的 message 为接收消息 v1.0。NewEventDispatcher()里的两个参数都填空字符串
eventHandler := dispatcher.NewEventDispatcher("", "").
OnP2MessageReceiveV1(func(ctx context.Context, event *larkim.P2MessageReceiveV1) error {
// messageid简单去重
if _, ok := sent[*event.Event.Message.MessageId]; ok {
return nil
} else {
sent[*event.Event.Message.MessageId] = struct{}{}
}
fmt.Printf("[ OnP2MessageReceiveV1 access ], data: %s\n", larkcore.Prettify(event))
fmt.Println(event.Event.Message.Content) // content中就是用户发过来的消息内容
var text Text
json.Unmarshal([]byte(*event.Event.Message.Content), &text)
fmt.Println(text.Text)
// 这里可以把用户输入发给deepseek或者dify并接收其响应,具体实现后面讲
//resp, e := deepseek.CallDeepSeekAPI(text.Text)
//if e != nil {
// return e
//}
resp := dify.ChatMessages(text.Text)
fmt.Println(resp)
// 这里组织飞书机器人发送消息的content格式,跟接收到消息的一样,也是{\"text\":\"say something\"}
var contentStruct struct {
Text string `json:"text"`
}
contentStruct.Text = resp
content, _ := json.Marshal(contentStruct)
// 这个messages是机器人发送消息函数,见下方
messages(getTernantAccessToken(), *event.Event.Sender.SenderId.OpenId, *event.Event.Message.MessageType, string(content))
return nil
}).
//im:message.p2p_msg:readonly 这个先不用管
OnCustomizedEvent("", func(ctx context.Context, event *larkevent.EventReq) error {
fmt.Printf("[ OnCustomizedEvent access ], type: message, data: %s\n", string(event.Body))
return nil
})
// 创建Client
cli := larkws.NewClient(AppID, AppSecret,
larkws.WithEventHandler(eventHandler),
larkws.WithLogLevel(