bf9395e022
CI / license-header (push) Has been skipped
CI / e2e-dry-run (push) Has been skipped
CI / fast-gate (push) Failing after 0s
Test PR Label Logic / test-pr-labels (push) Failing after 1s
Skill Format Check / check-format (push) Failing after 2s
CI / security (push) Failing after 5s
CI / unit-test (push) Has been skipped
CI / lint (push) Has been skipped
CI / script-test (push) Has been skipped
CI / deterministic-gate (push) Has been skipped
CI / coverage (push) Has been skipped
CI / results (push) Has been cancelled
CI / deadcode (push) Has been cancelled
CI / e2e-live (push) Has been cancelled
489 lines
18 KiB
Go
489 lines
18 KiB
Go
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package backward
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/larksuite/cli/errs"
|
|
"github.com/larksuite/cli/extension/fileio"
|
|
"github.com/larksuite/cli/internal/validate"
|
|
"github.com/larksuite/cli/shortcuts/common"
|
|
)
|
|
|
|
// Drive media parent_type values for uploading an image into a spreadsheet.
|
|
// Native spreadsheets use "sheet_image"; imported "office" spreadsheets carry a
|
|
// synthetic token prefixed with "fake_office_" and the backend requires
|
|
// "office_sheet_file" instead.
|
|
const (
|
|
sheetImageParentType = "sheet_image"
|
|
officeSheetFileParentType = "office_sheet_file"
|
|
fakeOfficeTokenPrefix = "fake_office_"
|
|
)
|
|
|
|
// sheetMediaParentType returns the drive media parent_type to use when
|
|
// uploading an image whose parent_node is spreadsheetToken, mapping the
|
|
// "fake_office_" imported-spreadsheet token prefix to "office_sheet_file".
|
|
func sheetMediaParentType(spreadsheetToken string) string {
|
|
if strings.HasPrefix(spreadsheetToken, fakeOfficeTokenPrefix) {
|
|
return officeSheetFileParentType
|
|
}
|
|
return sheetImageParentType
|
|
}
|
|
|
|
var SheetMediaUpload = common.Shortcut{
|
|
Service: "sheets",
|
|
Command: "+media-upload",
|
|
Description: "Upload a local image for use as a floating image and return the file_token",
|
|
Risk: "write",
|
|
Scopes: []string{"docs:document.media:upload"},
|
|
AuthTypes: []string{"user", "bot"},
|
|
Flags: []common.Flag{
|
|
{Name: "url", Desc: "spreadsheet URL"},
|
|
{Name: "spreadsheet-token", Desc: "spreadsheet token"},
|
|
{Name: "file", Desc: "local image path (files > 20MB use multipart upload automatically)", Required: true},
|
|
},
|
|
Validate: func(ctx context.Context, runtime *common.RuntimeContext) error {
|
|
if _, err := resolveSheetMediaUploadParent(runtime); err != nil {
|
|
return err
|
|
}
|
|
_, _, err := validateSheetMediaUploadFile(runtime, runtime.Str("file"))
|
|
return err
|
|
},
|
|
DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI {
|
|
parentNode, err := resolveSheetMediaUploadParent(runtime)
|
|
if err != nil {
|
|
return common.NewDryRunAPI().Set("error", err.Error())
|
|
}
|
|
filePath := runtime.Str("file")
|
|
fileName := filepath.Base(filePath)
|
|
|
|
dry := common.NewDryRunAPI()
|
|
if sheetMediaShouldUseMultipart(runtime.FileIO(), filePath) {
|
|
dry.Desc("chunked media upload (files > 20MB)").
|
|
POST("/open-apis/drive/v1/medias/upload_prepare").
|
|
Body(map[string]interface{}{
|
|
"file_name": fileName,
|
|
"parent_type": sheetMediaParentType(parentNode),
|
|
"parent_node": parentNode,
|
|
"size": "<file_size>",
|
|
}).
|
|
POST("/open-apis/drive/v1/medias/upload_part").
|
|
Body(map[string]interface{}{
|
|
"upload_id": "<upload_id>",
|
|
"seq": "<chunk_index>",
|
|
"size": "<chunk_size>",
|
|
"file": "<chunk_binary>",
|
|
}).
|
|
POST("/open-apis/drive/v1/medias/upload_finish").
|
|
Body(map[string]interface{}{
|
|
"upload_id": "<upload_id>",
|
|
"block_num": "<block_num>",
|
|
})
|
|
return dry.Set("spreadsheet_token", parentNode)
|
|
}
|
|
return dry.Desc("multipart/form-data upload").
|
|
POST("/open-apis/drive/v1/medias/upload_all").
|
|
Body(map[string]interface{}{
|
|
"file_name": fileName,
|
|
"parent_type": sheetMediaParentType(parentNode),
|
|
"parent_node": parentNode,
|
|
"size": "<file_size>",
|
|
"file": "@" + filePath,
|
|
}).
|
|
Set("spreadsheet_token", parentNode)
|
|
},
|
|
Execute: func(ctx context.Context, runtime *common.RuntimeContext) error {
|
|
parentNode, err := resolveSheetMediaUploadParent(runtime)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
filePath := runtime.Str("file")
|
|
|
|
safePath, stat, err := validateSheetMediaUploadFile(runtime, filePath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
fileName := filepath.Base(safePath)
|
|
fmt.Fprintf(runtime.IO().ErrOut, "Uploading: %s (%s) -> spreadsheet %s\n",
|
|
fileName, common.FormatSize(stat.Size()), common.MaskToken(parentNode))
|
|
if stat.Size() > common.MaxDriveMediaUploadSinglePartSize {
|
|
fmt.Fprintf(runtime.IO().ErrOut, "File exceeds 20MB, using multipart upload\n")
|
|
}
|
|
|
|
fileToken, err := uploadSheetMediaFile(runtime, safePath, fileName, stat.Size(), parentNode)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
runtime.Out(map[string]interface{}{
|
|
"file_token": fileToken,
|
|
"file_name": fileName,
|
|
"size": stat.Size(),
|
|
"spreadsheet_token": parentNode,
|
|
}, nil)
|
|
return nil
|
|
},
|
|
}
|
|
|
|
func validateSheetMediaUploadFile(runtime *common.RuntimeContext, filePath string) (string, fileio.FileInfo, error) {
|
|
stat, err := runtime.FileIO().Stat(filePath)
|
|
if err != nil {
|
|
wrapped := common.WrapInputStatErrorTyped(err, "file not found")
|
|
if v, ok := wrapped.(*errs.ValidationError); ok {
|
|
return "", nil, v.WithParam("--file")
|
|
}
|
|
return "", nil, wrapped
|
|
}
|
|
if !stat.Mode().IsRegular() {
|
|
return "", nil, errs.NewValidationError(errs.SubtypeInvalidArgument, "file must be a regular file: %s", filePath).WithParam("--file")
|
|
}
|
|
return filePath, stat, nil
|
|
}
|
|
|
|
func resolveSheetMediaUploadParent(runtime *common.RuntimeContext) (string, error) {
|
|
token := runtime.Str("spreadsheet-token")
|
|
if u := runtime.Str("url"); u != "" {
|
|
if parsed := extractSpreadsheetToken(u); parsed != "" {
|
|
token = parsed
|
|
}
|
|
}
|
|
if token == "" {
|
|
return "", errs.NewValidationError(errs.SubtypeInvalidArgument, "specify --url or --spreadsheet-token").WithParams(errs.InvalidParam{Name: "--url", Reason: "required; specify one"}, errs.InvalidParam{Name: "--spreadsheet-token", Reason: "required; specify one"})
|
|
}
|
|
return token, nil
|
|
}
|
|
|
|
func uploadSheetMediaFile(runtime *common.RuntimeContext, filePath, fileName string, fileSize int64, parentNode string) (string, error) {
|
|
parentType := sheetMediaParentType(parentNode)
|
|
if fileSize <= common.MaxDriveMediaUploadSinglePartSize {
|
|
pn := parentNode
|
|
return common.UploadDriveMediaAllTyped(runtime, common.DriveMediaUploadAllConfig{
|
|
FilePath: filePath,
|
|
FileName: fileName,
|
|
FileSize: fileSize,
|
|
ParentType: parentType,
|
|
ParentNode: &pn,
|
|
})
|
|
}
|
|
return common.UploadDriveMediaMultipartTyped(runtime, common.DriveMediaMultipartUploadConfig{
|
|
FilePath: filePath,
|
|
FileName: fileName,
|
|
FileSize: fileSize,
|
|
ParentType: parentType,
|
|
ParentNode: parentNode,
|
|
})
|
|
}
|
|
|
|
func sheetMediaShouldUseMultipart(fio fileio.FileIO, filePath string) bool {
|
|
info, err := fio.Stat(filePath)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
return info.Mode().IsRegular() && info.Size() > common.MaxDriveMediaUploadSinglePartSize
|
|
}
|
|
|
|
func floatImageBasePath(token, sheetID string) string {
|
|
return fmt.Sprintf("/open-apis/sheets/v3/spreadsheets/%s/sheets/%s/float_images",
|
|
validate.EncodePathSegment(token), validate.EncodePathSegment(sheetID))
|
|
}
|
|
|
|
func floatImageItemPath(token, sheetID, floatImageID string) string {
|
|
return fmt.Sprintf("%s/%s", floatImageBasePath(token, sheetID), validate.EncodePathSegment(floatImageID))
|
|
}
|
|
|
|
func validateFloatImageToken(runtime *common.RuntimeContext) (string, error) {
|
|
token := runtime.Str("spreadsheet-token")
|
|
if u := runtime.Str("url"); u != "" {
|
|
if parsed := extractSpreadsheetToken(u); parsed != u {
|
|
token = parsed
|
|
}
|
|
}
|
|
if token == "" {
|
|
return "", errs.NewValidationError(errs.SubtypeInvalidArgument, "specify --url or --spreadsheet-token").WithParams(errs.InvalidParam{Name: "--url", Reason: "required; specify one"}, errs.InvalidParam{Name: "--spreadsheet-token", Reason: "required; specify one"})
|
|
}
|
|
return token, nil
|
|
}
|
|
|
|
func validateFloatImageRange(sheetID, rangeVal string) error {
|
|
if rangeVal == "" {
|
|
return nil
|
|
}
|
|
if err := validateSingleCellRange(rangeVal); err != nil {
|
|
return err
|
|
}
|
|
if prefix, _, ok := splitSheetRange(rangeVal); ok && sheetID != "" && prefix != sheetID {
|
|
return errs.NewValidationError(errs.SubtypeInvalidArgument, "--range prefix %q does not match --sheet-id %q", prefix, sheetID).WithParam("--range")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func validateFloatImageUpdatePayload(runtime *common.RuntimeContext) error {
|
|
hasField := runtime.Str("range") != "" ||
|
|
runtime.Cmd.Flags().Changed("width") ||
|
|
runtime.Cmd.Flags().Changed("height") ||
|
|
runtime.Cmd.Flags().Changed("offset-x") ||
|
|
runtime.Cmd.Flags().Changed("offset-y")
|
|
if !hasField {
|
|
return errs.NewValidationError(errs.SubtypeInvalidArgument, "specify at least one of --range, --width, --height, --offset-x, --offset-y to update").WithParams(errs.InvalidParam{Name: "--range", Reason: "required; specify at least one"}, errs.InvalidParam{Name: "--width", Reason: "required; specify at least one"}, errs.InvalidParam{Name: "--height", Reason: "required; specify at least one"}, errs.InvalidParam{Name: "--offset-x", Reason: "required; specify at least one"}, errs.InvalidParam{Name: "--offset-y", Reason: "required; specify at least one"})
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func validateFloatImageDims(runtime *common.RuntimeContext) error {
|
|
if runtime.Cmd.Flags().Changed("width") {
|
|
if v := runtime.Int("width"); v < 20 {
|
|
return errs.NewValidationError(errs.SubtypeInvalidArgument, "--width must be >= 20 pixels, got %d", v).WithParam("--width")
|
|
}
|
|
}
|
|
if runtime.Cmd.Flags().Changed("height") {
|
|
if v := runtime.Int("height"); v < 20 {
|
|
return errs.NewValidationError(errs.SubtypeInvalidArgument, "--height must be >= 20 pixels, got %d", v).WithParam("--height")
|
|
}
|
|
}
|
|
if runtime.Cmd.Flags().Changed("offset-x") {
|
|
if v := runtime.Int("offset-x"); v < 0 {
|
|
return errs.NewValidationError(errs.SubtypeInvalidArgument, "--offset-x must be >= 0, got %d", v).WithParam("--offset-x")
|
|
}
|
|
}
|
|
if runtime.Cmd.Flags().Changed("offset-y") {
|
|
if v := runtime.Int("offset-y"); v < 0 {
|
|
return errs.NewValidationError(errs.SubtypeInvalidArgument, "--offset-y must be >= 0, got %d", v).WithParam("--offset-y")
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func buildFloatImageBody(runtime *common.RuntimeContext, includeToken bool) map[string]interface{} {
|
|
body := map[string]interface{}{}
|
|
if includeToken {
|
|
if s := runtime.Str("float-image-token"); s != "" {
|
|
body["float_image_token"] = s
|
|
}
|
|
}
|
|
if s := runtime.Str("range"); s != "" {
|
|
body["range"] = s
|
|
}
|
|
if runtime.Cmd.Flags().Changed("width") {
|
|
body["width"] = runtime.Int("width")
|
|
}
|
|
if runtime.Cmd.Flags().Changed("height") {
|
|
body["height"] = runtime.Int("height")
|
|
}
|
|
if runtime.Cmd.Flags().Changed("offset-x") {
|
|
body["offset_x"] = runtime.Int("offset-x")
|
|
}
|
|
if runtime.Cmd.Flags().Changed("offset-y") {
|
|
body["offset_y"] = runtime.Int("offset-y")
|
|
}
|
|
return body
|
|
}
|
|
|
|
var SheetCreateFloatImage = common.Shortcut{
|
|
Service: "sheets",
|
|
Command: "+create-float-image",
|
|
Description: "Create a floating image on a sheet",
|
|
Risk: "write",
|
|
Scopes: []string{"sheets:spreadsheet:write_only"},
|
|
AuthTypes: []string{"user", "bot"},
|
|
Flags: []common.Flag{
|
|
{Name: "url", Desc: "spreadsheet URL"},
|
|
{Name: "spreadsheet-token", Desc: "spreadsheet token"},
|
|
{Name: "sheet-id", Desc: "sheet ID", Required: true},
|
|
{Name: "float-image-token", Desc: "image file token (from upload API)", Required: true},
|
|
{Name: "range", Desc: "anchor cell, must be a single cell (e.g. sheetId!A1:A1)", Required: true},
|
|
{Name: "width", Type: "int", Desc: "width in pixels (>=20)"},
|
|
{Name: "height", Type: "int", Desc: "height in pixels (>=20)"},
|
|
{Name: "offset-x", Type: "int", Desc: "horizontal offset from anchor cell's top-left (pixels, >=0)"},
|
|
{Name: "offset-y", Type: "int", Desc: "vertical offset from anchor cell's top-left (pixels, >=0)"},
|
|
{Name: "float-image-id", Desc: "custom 10-char alphanumeric ID (auto-generated if omitted)"},
|
|
},
|
|
Validate: func(ctx context.Context, runtime *common.RuntimeContext) error {
|
|
if _, err := validateFloatImageToken(runtime); err != nil {
|
|
return err
|
|
}
|
|
if err := validateFloatImageRange(runtime.Str("sheet-id"), runtime.Str("range")); err != nil {
|
|
return err
|
|
}
|
|
return validateFloatImageDims(runtime)
|
|
},
|
|
DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI {
|
|
token, _ := validateFloatImageToken(runtime)
|
|
body := buildFloatImageBody(runtime, true)
|
|
if s := runtime.Str("float-image-id"); s != "" {
|
|
body["float_image_id"] = s
|
|
}
|
|
return common.NewDryRunAPI().
|
|
POST("/open-apis/sheets/v3/spreadsheets/:token/sheets/:sheet_id/float_images").
|
|
Body(body).Set("token", token).Set("sheet_id", runtime.Str("sheet-id"))
|
|
},
|
|
Execute: func(ctx context.Context, runtime *common.RuntimeContext) error {
|
|
token, _ := validateFloatImageToken(runtime)
|
|
body := buildFloatImageBody(runtime, true)
|
|
if s := runtime.Str("float-image-id"); s != "" {
|
|
body["float_image_id"] = s
|
|
}
|
|
data, err := runtime.CallAPITyped("POST", floatImageBasePath(token, runtime.Str("sheet-id")), nil, body)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
runtime.Out(data, nil)
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var SheetUpdateFloatImage = common.Shortcut{
|
|
Service: "sheets",
|
|
Command: "+update-float-image",
|
|
Description: "Update a floating image",
|
|
Risk: "write",
|
|
Scopes: []string{"sheets:spreadsheet:write_only"},
|
|
AuthTypes: []string{"user", "bot"},
|
|
Flags: []common.Flag{
|
|
{Name: "url", Desc: "spreadsheet URL"},
|
|
{Name: "spreadsheet-token", Desc: "spreadsheet token"},
|
|
{Name: "sheet-id", Desc: "sheet ID", Required: true},
|
|
{Name: "float-image-id", Desc: "float image ID", Required: true},
|
|
{Name: "range", Desc: "new anchor cell, must be a single cell (e.g. sheetId!B2:B2)"},
|
|
{Name: "width", Type: "int", Desc: "width in pixels (>=20)"},
|
|
{Name: "height", Type: "int", Desc: "height in pixels (>=20)"},
|
|
{Name: "offset-x", Type: "int", Desc: "horizontal offset from anchor cell's top-left (pixels, >=0)"},
|
|
{Name: "offset-y", Type: "int", Desc: "vertical offset from anchor cell's top-left (pixels, >=0)"},
|
|
},
|
|
Validate: func(ctx context.Context, runtime *common.RuntimeContext) error {
|
|
if _, err := validateFloatImageToken(runtime); err != nil {
|
|
return err
|
|
}
|
|
if err := validateFloatImageUpdatePayload(runtime); err != nil {
|
|
return err
|
|
}
|
|
if err := validateFloatImageRange(runtime.Str("sheet-id"), runtime.Str("range")); err != nil {
|
|
return err
|
|
}
|
|
return validateFloatImageDims(runtime)
|
|
},
|
|
DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI {
|
|
token, _ := validateFloatImageToken(runtime)
|
|
body := buildFloatImageBody(runtime, false)
|
|
return common.NewDryRunAPI().
|
|
PATCH("/open-apis/sheets/v3/spreadsheets/:token/sheets/:sheet_id/float_images/:float_image_id").
|
|
Body(body).Set("token", token).Set("sheet_id", runtime.Str("sheet-id")).Set("float_image_id", runtime.Str("float-image-id"))
|
|
},
|
|
Execute: func(ctx context.Context, runtime *common.RuntimeContext) error {
|
|
token, _ := validateFloatImageToken(runtime)
|
|
body := buildFloatImageBody(runtime, false)
|
|
data, err := runtime.CallAPITyped("PATCH", floatImageItemPath(token, runtime.Str("sheet-id"), runtime.Str("float-image-id")), nil, body)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
runtime.Out(data, nil)
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var SheetGetFloatImage = common.Shortcut{
|
|
Service: "sheets",
|
|
Command: "+get-float-image",
|
|
Description: "Get a floating image by ID",
|
|
Risk: "read",
|
|
Scopes: []string{"sheets:spreadsheet:read"},
|
|
AuthTypes: []string{"user", "bot"},
|
|
Flags: []common.Flag{
|
|
{Name: "url", Desc: "spreadsheet URL"},
|
|
{Name: "spreadsheet-token", Desc: "spreadsheet token"},
|
|
{Name: "sheet-id", Desc: "sheet ID", Required: true},
|
|
{Name: "float-image-id", Desc: "float image ID", Required: true},
|
|
},
|
|
Validate: func(ctx context.Context, runtime *common.RuntimeContext) error {
|
|
_, err := validateFloatImageToken(runtime)
|
|
return err
|
|
},
|
|
DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI {
|
|
token, _ := validateFloatImageToken(runtime)
|
|
return common.NewDryRunAPI().
|
|
GET("/open-apis/sheets/v3/spreadsheets/:token/sheets/:sheet_id/float_images/:float_image_id").
|
|
Set("token", token).Set("sheet_id", runtime.Str("sheet-id")).Set("float_image_id", runtime.Str("float-image-id"))
|
|
},
|
|
Execute: func(ctx context.Context, runtime *common.RuntimeContext) error {
|
|
token, _ := validateFloatImageToken(runtime)
|
|
data, err := runtime.CallAPITyped("GET", floatImageItemPath(token, runtime.Str("sheet-id"), runtime.Str("float-image-id")), nil, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
runtime.Out(data, nil)
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var SheetListFloatImages = common.Shortcut{
|
|
Service: "sheets",
|
|
Command: "+list-float-images",
|
|
Description: "List all floating images in a sheet",
|
|
Risk: "read",
|
|
Scopes: []string{"sheets:spreadsheet:read"},
|
|
AuthTypes: []string{"user", "bot"},
|
|
Flags: []common.Flag{
|
|
{Name: "url", Desc: "spreadsheet URL"},
|
|
{Name: "spreadsheet-token", Desc: "spreadsheet token"},
|
|
{Name: "sheet-id", Desc: "sheet ID", Required: true},
|
|
},
|
|
Validate: func(ctx context.Context, runtime *common.RuntimeContext) error {
|
|
_, err := validateFloatImageToken(runtime)
|
|
return err
|
|
},
|
|
DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI {
|
|
token, _ := validateFloatImageToken(runtime)
|
|
return common.NewDryRunAPI().
|
|
GET("/open-apis/sheets/v3/spreadsheets/:token/sheets/:sheet_id/float_images/query").
|
|
Set("token", token).Set("sheet_id", runtime.Str("sheet-id"))
|
|
},
|
|
Execute: func(ctx context.Context, runtime *common.RuntimeContext) error {
|
|
token, _ := validateFloatImageToken(runtime)
|
|
data, err := runtime.CallAPITyped("GET", floatImageBasePath(token, runtime.Str("sheet-id"))+"/query", nil, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
runtime.Out(data, nil)
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var SheetDeleteFloatImage = common.Shortcut{
|
|
Service: "sheets",
|
|
Command: "+delete-float-image",
|
|
Description: "Delete a floating image",
|
|
Risk: "write",
|
|
Scopes: []string{"sheets:spreadsheet:write_only"},
|
|
AuthTypes: []string{"user", "bot"},
|
|
Flags: []common.Flag{
|
|
{Name: "url", Desc: "spreadsheet URL"},
|
|
{Name: "spreadsheet-token", Desc: "spreadsheet token"},
|
|
{Name: "sheet-id", Desc: "sheet ID", Required: true},
|
|
{Name: "float-image-id", Desc: "float image ID", Required: true},
|
|
},
|
|
Validate: func(ctx context.Context, runtime *common.RuntimeContext) error {
|
|
_, err := validateFloatImageToken(runtime)
|
|
return err
|
|
},
|
|
DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI {
|
|
token, _ := validateFloatImageToken(runtime)
|
|
return common.NewDryRunAPI().
|
|
DELETE("/open-apis/sheets/v3/spreadsheets/:token/sheets/:sheet_id/float_images/:float_image_id").
|
|
Set("token", token).Set("sheet_id", runtime.Str("sheet-id")).Set("float_image_id", runtime.Str("float-image-id"))
|
|
},
|
|
Execute: func(ctx context.Context, runtime *common.RuntimeContext) error {
|
|
token, _ := validateFloatImageToken(runtime)
|
|
data, err := runtime.CallAPITyped("DELETE", floatImageItemPath(token, runtime.Str("sheet-id"), runtime.Str("float-image-id")), nil, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
runtime.Out(data, nil)
|
|
return nil
|
|
},
|
|
}
|