场景示例
飞书开放平台基于 SDK,封装了常用的 API 组合调用及业务场景示例供你参考。在 oapi-sdk-go-demo 中包含了以下多种场景示例代码。
发送文件消息
发送文件消息,使用到两个OpenAPI:上传文件 和发送消息。
java
package im
import (
"context"
"encoding/json"
"fmt"
"io"
"github.com/larksuite/oapi-sdk-go/v3"
larkcore "github.com/larksuite/oapi-sdk-go/v3/core"
"github.com/larksuite/oapi-sdk-go/v3/service/im/v1"
)
type SendFileRequest struct {
FileType string
FileName string
File io.Reader
Duration int
ReceiveIdType string
ReceiveId string
Uuid string
}
type SendFileResponse struct {
*larkcore.CodeError
CreateFileResponse *larkim.CreateFileRespData
CreateMessageResponse *larkim.CreateMessageRespData
}
// SendFile 发送文件消息
func SendFile(client *lark.Client, request *SendFileRequest) (*SendFileResponse, error) {
// 上传文件
createFileReq := larkim.NewCreateFileReqBuilder().
Body(larkim.NewCreateFileReqBodyBuilder().
FileType(request.FileType).
FileName(request.FileName).
Duration(request.Duration).
File(request.File).
Build()).
Build()
createFileResp, err := client.Im.File.Create(context.Background(), createFileReq)
if err != nil {
return nil, err
}
if !createFileResp.Success() {
fmt.Printf("client.Im.File.Create failed, code: %d, msg: %s, log_id: %s\n",
createFileResp.Code, createFileResp.Msg, createFileResp.RequestId())
return nil, createFileResp.CodeError
}
// 发送消息
bs, err := json.Marshal(createFileResp.Data)
if err != nil {
return nil, err
}
createMessageReq := larkim.NewCreateMessageReqBuilder().
ReceiveIdType(request.ReceiveIdType).
Body(larkim.NewCreateMessageReqBodyBuilder().
ReceiveId(request.ReceiveId).
MsgType("file").
Content(string(bs)).
Uuid(request.Uuid).
Build()).
Build()
createMessageResp, err := client.Im.Message.Create(context.Background(), createMessageReq)
if err != nil {
return nil, err
}
if !createMessageResp.Success() {
fmt.Printf("client.Im.Message.Create failed, code: %d, msg: %s, log_id: %s\n",
createMessageResp.Code, createMessageResp.Msg, createMessageResp.RequestId())
return nil, createMessageResp.CodeError
}
// 返回结果
return &SendFileResponse{
CodeError: &larkcore.CodeError{
Code: 0,
Msg: "success",
},
CreateFileResponse: createFileResp.Data,
CreateMessageResponse: createMessageResp.Data,
}, nil
}发送图片消息
发送图片消息,使用到两个OpenAPI:上传图片和发送消息。
java
package im
import (
"context"
"encoding/json"
"fmt"
"io"
"github.com/larksuite/oapi-sdk-go/v3"
larkcore "github.com/larksuite/oapi-sdk-go/v3/core"
"github.com/larksuite/oapi-sdk-go/v3/service/im/v1"
)
type SendImageRequest struct {
Image io.Reader
ReceiveIdType string
ReceiveId string
Uuid string
}
type SendImageResponse struct {
*larkcore.CodeError
CreateImageResponse *larkim.CreateImageRespData
CreateMessageResponse *larkim.CreateMessageRespData
}
// SendImage 发送图片消息
func SendImage(client *lark.Client, request *SendImageRequest) (*SendImageResponse, error) {
// 上传图片
createImageReq := larkim.NewCreateImageReqBuilder().
Body(larkim.NewCreateImageReqBodyBuilder().
ImageType("message").
Image(request.Image).
Build()).
Build()
createImageResp, err := client.Im.Image.Create(context.Background(), createImageReq)
if err != nil {
return nil, err
}
if !createImageResp.Success() {
fmt.Printf("client.Im.Image.Create failed, code: %d, msg: %s, log_id: %s\n",
createImageResp.Code, createImageResp.Msg, createImageResp.RequestId())
return nil, createImageResp.CodeError
}
// 发送消息
bs, err := json.Marshal(createImageResp.Data)
if err != nil {
return nil, err
}
createMessageReq := larkim.NewCreateMessageReqBuilder().
ReceiveIdType(request.ReceiveIdType).
Body(larkim.NewCreateMessageReqBodyBuilder().
ReceiveId(request.ReceiveId).
MsgType("image").
Content(string(bs)).
Uuid(request.Uuid).
Build()).
Build()
createMessageResp, err := client.Im.Message.Create(context.Background(), createMessageReq)
if err != nil {
return nil, err
}
if !createMessageResp.Success() {
fmt.Printf("client.Im.Message.Create failed, code: %d, msg: %s, log_id: %s\n",
createMessageResp.Code, createMessageResp.Msg, createMessageResp.RequestId())
return nil, createMessageResp.CodeError
}
// 返回结果
return &SendImageResponse{
CodeError: &larkcore.CodeError{
Code: 0,
Msg: "success",
},
CreateImageResponse: createImageResp.Data,
CreateMessageResponse: createMessageResp.Data,
}, nil
}获取部门下所有用户列表
获取部门下所有用户列表,使用到两个OpenAPI:获取子部门列表和获取部门直属用户列表。
java
package contact
import (
"context"
"fmt"
lark "github.com/larksuite/oapi-sdk-go/v3"
larkcore "github.com/larksuite/oapi-sdk-go/v3/core"
larkcontact "github.com/larksuite/oapi-sdk-go/v3/service/contact/v3"
)
type ListUserByDepartmentRequest struct {
DepartmentId string
}
type ListUserByDepartmentResponse struct {
*larkcore.CodeError
ChildrenDepartmentResponse *larkcontact.ChildrenDepartmentRespData
FindByDepartmentUserResponse []*larkcontact.User
}
// ListUserByDepartment 获取部门下所有用户列表
func ListUserByDepartment(client *lark.Client, request *ListUserByDepartmentRequest) (*ListUserByDepartmentResponse, error) {
// 获取子部门列表
childrenDepartmentReq := larkcontact.NewChildrenDepartmentReqBuilder().
DepartmentIdType("open_department_id").
DepartmentId(request.DepartmentId).
Build()
childrenDepartmentResp, err := client.Contact.Department.Children(context.Background(), childrenDepartmentReq)
if err != nil {
return nil, err
}
if !childrenDepartmentResp.Success() {
fmt.Printf("client.Contact.Department.Children failed, code: %d, msg: %s, log_id: %s\n",
childrenDepartmentResp.Code, childrenDepartmentResp.Msg, childrenDepartmentResp.RequestId())
return nil, childrenDepartmentResp.CodeError
}
// 获取部门直属用户列表
users := make([]*larkcontact.User, 0)
openDepartmentIds := []string{request.DepartmentId}
for _, item := range childrenDepartmentResp.Data.Items {
openDepartmentIds = append(openDepartmentIds, *item.OpenDepartmentId)
}
for _, id := range openDepartmentIds {
findByDepartmentUserReq := larkcontact.NewFindByDepartmentUserReqBuilder().
DepartmentId(id).
Build()
findByDepartmentUserResp, err := client.Contact.User.FindByDepartment(context.Background(), findByDepartmentUserReq)
if err != nil {
return nil, err
}
if !findByDepartmentUserResp.Success() {
fmt.Printf("client.Contact.User.FindByDepartment failed, code: %d, msg: %s, log_id: %s\n",
findByDepartmentUserResp.Code, findByDepartmentUserResp.Msg, findByDepartmentUserResp.RequestId())
return nil, findByDepartmentUserResp.CodeError
}
users = append(users, findByDepartmentUserResp.Data.Items...)
}
// 返回结果
return &ListUserByDepartmentResponse{
CodeError: &larkcore.CodeError{
Code: 0,
Msg: "success",
},
ChildrenDepartmentResponse: childrenDepartmentResp.Data,
FindByDepartmentUserResponse: users,
}, nil
}创建多维表格同时添加数据表
创建多维表格同时添加数据表,使用到两个 OpenAPI:创建多维表格和新增一个数据表:
java
package base
import (
"context"
"fmt"
lark "github.com/larksuite/oapi-sdk-go/v3"
larkcore "github.com/larksuite/oapi-sdk-go/v3/core"
larkbitable "github.com/larksuite/oapi-sdk-go/v3/service/bitable/v1"
)
type CreateAppAndTablesRequest struct {
Name string
FolderToken string
Tables []*larkbitable.ReqTable
}
type CreateAppAndTablesResponse struct {
*larkcore.CodeError
CreateAppResponse *larkbitable.CreateAppRespData
CreateAppTablesResponse []*larkbitable.CreateAppTableRespData
}
// CreateAppAndTables 创建多维表格同时添加数据表
func CreateAppAndTables(client *lark.Client, request *CreateAppAndTablesRequest) (*CreateAppAndTablesResponse, error) {
// 创建多维表格
createAppReq := larkbitable.NewCreateAppReqBuilder().
ReqApp(larkbitable.NewReqAppBuilder().
Name(request.Name).
FolderToken(request.FolderToken).
Build()).
Build()
createAppResp, err := client.Bitable.App.Create(context.Background(), createAppReq)
if err != nil {
return nil, err
}
if !createAppResp.Success() {
fmt.Printf("client.Bitable.App.Create failed, code: %d, msg: %s, log_id: %s\n",
createAppResp.Code, createAppResp.Msg, createAppResp.RequestId())
return nil, createAppResp.CodeError
}
// 添加数据表
tables := make([]*larkbitable.CreateAppTableRespData, 0)
for _, table := range request.Tables {
req := larkbitable.NewCreateAppTableReqBuilder().
AppToken(*createAppResp.Data.App.AppToken).
Body(larkbitable.NewCreateAppTableReqBodyBuilder().
Table(table).
Build()).
Build()
createAppTableResp, err := client.Bitable.AppTable.Create(context.Background(), req)
if err != nil {
return nil, err
}
if !createAppTableResp.Success() {
fmt.Printf("client.Bitable.AppTable.Create failed, code: %d, msg: %s, log_id: %s\n",
createAppTableResp.Code, createAppTableResp.Msg, createAppTableResp.RequestId())
return nil, createAppTableResp.CodeError
}
tables = append(tables, createAppTableResp.Data)
}
// 返回结果
return &CreateAppAndTablesResponse{
CodeError: &larkcore.CodeError{
Code: 0,
Msg: "success",
},
CreateAppResponse: createAppResp.Data,
CreateAppTablesResponse: tables,
}, nil
}复制粘贴某个范围的单元格数据
复制粘贴某个范围的单元格数据,使用到两个OpenAPI:读取单个范围和向单个范围写入数据。
java
package sheets
import (
"context"
"encoding/json"
"fmt"
"net/http"
lark "github.com/larksuite/oapi-sdk-go/v3"
larkcore "github.com/larksuite/oapi-sdk-go/v3/core"
)
type CopyAndPasteByRangeRequest struct {
SpreadsheetToken string
SrcRange string
DstRange string
}
type CopyAndPasteRangeResponse struct {
*larkcore.CodeError
ReadResponse *SpreadsheetRespData
WriteResponse *SpreadsheetRespData
}
// CopyAndPasteRange 复制粘贴某个范围的单元格数据
func CopyAndPasteRange(client *lark.Client, request *CopyAndPasteByRangeRequest) (*CopyAndPasteRangeResponse, error) {
// 读取单个范围
readResp, err := client.Do(context.Background(), &larkcore.ApiReq{
HttpMethod: http.MethodGet,
ApiPath: fmt.Sprintf("/open-apis/sheets/v2/spreadsheets/%s/values/%s", request.SpreadsheetToken, request.SrcRange),
SupportedAccessTokenTypes: []larkcore.AccessTokenType{larkcore.AccessTokenTypeTenant},
})
if err != nil {
return nil, err
}
readSpreadsheetResp := &SpreadsheetResp{}
err = json.Unmarshal(readResp.RawBody, readSpreadsheetResp)
if err != nil {
return nil, err
}
readSpreadsheetResp.ApiResp = readResp
if readSpreadsheetResp.Code != 0 {
fmt.Printf("read spreadsheet failed, code: %d, msg: %s, log_id: %s\n",
readSpreadsheetResp.Code, readSpreadsheetResp.Msg, readSpreadsheetResp.RequestId())
return nil, readSpreadsheetResp.CodeError
}
// 向单个范围写入数据
valueRange := map[string]interface{}{}
valueRange["range"] = request.DstRange
valueRange["values"] = readSpreadsheetResp.Data.ValueRange.Values
body := map[string]interface{}{}
body["valueRange"] = valueRange
writeResp, err := client.Do(context.Background(), &larkcore.ApiReq{
HttpMethod: http.MethodPut,
ApiPath: fmt.Sprintf("/open-apis/sheets/v2/spreadsheets/%s/values", request.SpreadsheetToken),
Body: body,
SupportedAccessTokenTypes: []larkcore.AccessTokenType{larkcore.AccessTokenTypeTenant},
})
if err != nil {
return nil, err
}
writeSpreadsheetResp := &SpreadsheetResp{}
err = json.Unmarshal(writeResp.RawBody, writeSpreadsheetResp)
if err != nil {
return nil, err
}
writeSpreadsheetResp.ApiResp = writeResp
if writeSpreadsheetResp.Code != 0 {
fmt.Printf("write spreadsheet failed, code: %d, msg: %s, log_id: %s\n",
writeSpreadsheetResp.Code, writeSpreadsheetResp.Msg, writeSpreadsheetResp.RequestId())
return nil, writeSpreadsheetResp.CodeError
}
// 返回结果
return &CopyAndPasteRangeResponse{
CodeError: &larkcore.CodeError{
Code: 0,
Msg: "success",
},
ReadResponse: readSpreadsheetResp.Data,
WriteResponse: writeSpreadsheetResp.Data,
}, nil
}下载指定范围单元格的所有素材列表
下载指定范围单元格的所有素材列表,使用到两个OpenAPI:读取单个范围和下载素材:
java
package sheets
import (
"context"
"encoding/json"
"fmt"
"net/http"
"reflect"
lark "github.com/larksuite/oapi-sdk-go/v3"
larkcore "github.com/larksuite/oapi-sdk-go/v3/core"
larkdrive "github.com/larksuite/oapi-sdk-go/v3/service/drive/v1"
)
type DownloadMediaByRangeRequest struct {
SpreadsheetToken string
Range string
}
type DownloadMediaByRangeResponse struct {
*larkcore.CodeError
ReadResponse *SpreadsheetRespData
DownloadMediaResponse []*larkdrive.DownloadMediaResp
}
func DownloadMediaByRange(client *lark.Client, request *DownloadMediaByRangeRequest) (*DownloadMediaByRangeResponse, error) {
// 读取单个范围
readResp, err := client.Do(context.Background(), &larkcore.ApiReq{
HttpMethod: http.MethodGet,
ApiPath: fmt.Sprintf("/open-apis/sheets/v2/spreadsheets/%s/values/%s", request.SpreadsheetToken, request.Range),
SupportedAccessTokenTypes: []larkcore.AccessTokenType{larkcore.AccessTokenTypeTenant},
})
if err != nil {
return nil, err
}
readSpreadsheetResp := &SpreadsheetResp{}
err = json.Unmarshal(readResp.RawBody, readSpreadsheetResp)
if err != nil {
return nil, err
}
readSpreadsheetResp.ApiResp = readResp
if readSpreadsheetResp.Code != 0 {
fmt.Printf("read spreadsheet failed, code: %d, msg: %s, log_id: %s\n",
readSpreadsheetResp.Code, readSpreadsheetResp.Msg, readSpreadsheetResp.RequestId())
return nil, readSpreadsheetResp.CodeError
}
// 下载文件
files := make([]*larkdrive.DownloadMediaResp, 0)
values := readSpreadsheetResp.Data.ValueRange.Values
tokens := parseFileToken(values, make(map[string]bool))
for _, token := range tokens {
downloadMediaReq := larkdrive.NewDownloadMediaReqBuilder().
FileToken(token).
Build()
downloadMediaResp, err := client.Drive.Media.Download(context.Background(), downloadMediaReq)
if err != nil {
return nil, err
}
if !downloadMediaResp.Success() {
fmt.Printf("client.Drive.Media.Download failed, code: %d, msg: %s, log_id: %s\n",
downloadMediaResp.Code, downloadMediaResp.Msg, downloadMediaResp.RequestId())
return nil, downloadMediaResp.CodeError
}
files = append(files, downloadMediaResp)
}
// 返回结果
return &DownloadMediaByRangeResponse{
CodeError: &larkcore.CodeError{
Code: 0,
Msg: "success",
},
ReadResponse: readSpreadsheetResp.Data,
DownloadMediaResponse: files,
}, nil
}
func parseFileToken(values []interface{}, tokens map[string]bool) []string {
if len(values) == 0 {
res := make([]string, 0, len(tokens))
for k := range tokens {
res = append(res, k)
}
return res
}
for _, i := range values {
kind := reflect.TypeOf(i).Kind()
if kind == reflect.Slice {
parseFileToken(i.([]interface{}), tokens)
} else if kind == reflect.Map {
m := i.(map[string]interface{})
if val, ok := m["fileToken"]; ok {
tokens[val.(string)] = true
}
}
}
res := make([]string, 0, len(tokens))
for k := range tokens {
res = append(res, k)
}
return res
}