Home

Awesome

go-lark

build codecov Go Report Card Go Module Go Reference Mentioned in Awesome Go

简体中文

go-lark is an easy-to-use SDK for Feishu and Lark Open Platform, which implements messaging APIs, with full-fledged supports on building Chat Bot and Notification Bot.

It is widely used and tested by ~650 ByteDance in-house developers with over 3k Go packages.

Features

Installation

go get github.com/go-lark/lark

Quick Start

Prerequisite

There are two types of bot that is supported by go-lark. We need to create a bot manually.

Chat Bot:

Notification Bot:

Sending Message

Chat Bot:

import "github.com/go-lark/lark"

func main() {
    bot := lark.NewChatBot("<App ID>", "<App Secret>")
    bot.StartHeartbeat()
    bot.PostText("hello, world", lark.WithEmail("someone@example.com"))
}

Notification Bot:

import "github.com/go-lark/lark"

func main() {
    bot := lark.NewNotificationBot("<WEB HOOK URL>")
    bot.PostNotificationV2(lark.NewMsgBuffer(lark.MsgText).Text("hello, wolrd").Build())
}

Feishu/Lark API offers more features, please refers to Usage for further documentation.

Limits

Switch to Lark Endpoints

The default API endpoints are for Feishu, in order to switch to Lark, we should use SetDomain:

bot := lark.NewChatBot("<App ID>", "<App Secret>")
bot.SetDomain(lark.DomainLark)

Usage

Auth

Auto-renewable authentication:

// initialize a chat bot with appID and appSecret
bot := lark.NewChatBot(appID, appSecret)
// Renew access token periodically
bot.StartHeartbeat()
// Stop renewal
bot.StopHeartbeat()

Single-pass authentication:

bot := lark.NewChatBot(appID, appSecret)
resp, err := bot.GetTenantAccessTokenInternal(true)
// and we can now access the token value with `bot.TenantAccessToken()`

Example: examples/auth

Messaging

For Chat Bot, we can send simple messages with the following method:

Basic message examples: examples/basic-message

To build rich messages, we may use Message Buffer (or simply MsgBuffer), which builds message conveniently with chaining methods.

Examples

Apart from the general auth and messaging chapter, there are comprehensive examples for almost all APIs. Here is a collection of ready-to-run examples for each part of go-lark:

Message Buffer

We can build message body with MsgBuffer and send with PostMessage, which supports the following message types:

MsgBuffer provides binding functions and content functions.

Binding functions:

FunctionUsageComment
BindChatIDBind a chat IDEither OpenID, UserID, Email, ChatID or UnionID should be present
BindOpenIDBind a user open ID
BindUserIDBind a user ID
BindUnionIDBind a union ID
BindEmailBind a user email
BindReplyBind a reply IDRequired when reply a message

Content functions pair with message content types. If it mismatched, it would not have sent successfully. Content functions:

FunctionMessage TypeUsageComment
TextMsgTextAppend plain textMay build with TextBuilder
PostMsgPostAppend rich textMay build with PostBuilder
CardMsgInteractiveAppend interactive cardMay build with CardBuilder
ShareChatMsgShareCardAppend group share card
ShareUserMsgShareUserAppend user share card
ImageMsgImageAppend imageRequired to upload to Lark server in advance
FileMsgFileAppend fileRequired to upload to Lark server in advance
AudioMsgAudioAppend audioRequired to upload to Lark server in advance
MediaMsgMediaAppend mediaRequired to upload to Lark server in advance
StickerMsgStickerAppend stickerRequired to upload to Lark server in advance

Error Handling

Each go-lark API function returns response and err. err is the error from HTTP client, when it was not nil, HTTP might have gone wrong.

While response is HTTP response from Lark API server, in which Code and OK represent whether it succeeds. The meaning of Code is defined here.

Event

Lark provides a number of events and they are in two different schema (1.0/2.0). go-lark now only implements a few of them, which are needed for interacting between bot and Lark server:

We recommend HTTP middlewares to handle these events.

Middlewares

We have already implemented HTTP middlewares to support event handling:

Example: examples/gin-middleware examples/hertz-middleware

URL Challenge

r := gin.Default()
middleware := larkgin.NewLarkMiddleware()
middleware.BindURLPrefix("/handle") // supposed URL is http://your.domain.com/handle
r.Use(middleware.LarkChallengeHandler())

Event V2

Lark has provided event v2 and it applied automatically to newly created bots.

r := gin.Default()
middleware := larkgin.NewLarkMiddleware()
r.Use(middleware.LarkEventHandler())

Get the event (e.g. Message):

r.POST("/", func(c *gin.Context) {
    if evt, ok := middleware.GetEvent(c); ok { // => GetEvent instead of GetMessage
        if evt.Header.EventType == lark.EventTypeMessageReceived {
            if msg, err := evt.GetMessageReceived(); err == nil {
                fmt.Println(msg.Message.Content)
            }
        }
    }
})

Card Callback

We may also setup callback for card actions (e.g. button). The URL challenge part is the same.

We may use LarkCardHandler to handle the actions:

r.Use(middleware.LarkCardHandler())
r.POST("/callback", func(c *gin.Context) {
    if card, ok := middleware.GetCardCallback(c); ok {
    }
})

Receiving Message (Event V1)

For older bots, please use v1:

r := gin.Default()
middleware := larkgin.NewLarkMiddleware()
middleware.BindURLPrefix("/handle") // supposed URL is http://your.domain.com/handle
r.POST("/handle", func(c *gin.Context) {
    if msg, ok := middleware.GetMessage(c); ok && msg != nil {
        text := msg.Event.Text
        // your awesome logic
    }
})

Security & Encryption

Lark Open Platform offers AES encryption and token verification to ensure security for events.

We recommend you to enable token verification. If HTTPS is not available on your host, then enable AES encryption.

middleware.WithTokenVerfication("<verification-token>")
middleware.WithEncryption("<encryption-key>")

Debugging

Lark does not provide messaging API debugger officially. Thus, we have to debug with real Lark conversation. We recommend ngrok to debug events.

And we add PostEvent to simulate message sending to make it even easier. PostEvent can also be used to redirect events, which acts like a reverse proxy.

Development

Test

  1. Dotenv Setup

    go-lark uses godotenv test locally. You may have to create a .env file in repo directory, which contains environmental variables:

    LARK_APP_ID
    LARK_APP_SECRET
    LARK_USER_EMAIL
    LARK_USER_ID
    LARK_UNION_ID
    LARK_OPEN_ID
    LARK_CHAT_ID
    LARK_WEBHOOK_V2
    LARK_WEBHOOK_V2_SIGNED
    

    LARK_APP_ID and LARK_APP_SECRET are mandatory. Others are required only by specific API tests.

  2. Run Test

    GO_LARK_TEST_MODE=local ./scripts/test.sh
    

Extensions

go-lark's dev utilities (authentication, HTTP handling, and etc.) are capable for easily implementing most of APIs provided by Lark Open Platform. And we may use that as an extension for go-lark.

Here is an example that implementing a Lark Doc API with go-lark:

package lark

import "github.com/go-lark/lark"

const copyFileAPIPattern = "/open-apis/drive/explorer/v2/file/copy/files/%s"

// CopyFileResponse .
type CopyFileResponse struct {
	lark.BaseResponse

	Data CopyFileData `json:"data"`
}

// CopyFileData .
type CopyFileData struct {
	FolderToken string `json:"folderToken"`
	Revision    int64  `json:"revision"`
	Token       string `json:"token"`
	Type        string `json:"type"`
	URL         string `json:"url"`
}

// CopyFile implementation
func CopyFile(bot *lark.Bot, fileToken, dstFolderToken, dstName string) (*CopyFileResponse, error) {
	var respData model.CopyFileResponse
	err := bot.PostAPIRequest(
		"CopyFile",
		fmt.Sprintf(copyFileAPIPattern, fileToken),
		true,
		map[string]interface{}{
			"type":             "doc",
			"dstFolderToken":   dstFolderToken,
			"dstName":          dstName,
			"permissionNeeded": true,
			"CommentNeeded":    false,
		},
		&respData,
	)
	return &respData, err
}

FAQ

Contributing

License

Copyright (c) David Zhang, 2018-2024. Licensed under MIT License.