From e8c36373d51fc57d1c6081a6ed443f702cce31eb Mon Sep 17 00:00:00 2001 From: "chenxingtong.jerry" Date: Tue, 14 Apr 2026 20:53:06 +0800 Subject: [PATCH] feat(im): support user access token upload file/media/audio/image and send the resource message Change-Id: I3d7fd528dd30fef9aea2d88100ceb03db4c7c3ac --- shortcuts/common/runner.go | 4 ++-- shortcuts/im/helpers.go | 8 ++++---- skills/lark-im/references/lark-im-messages-reply.md | 2 +- skills/lark-im/references/lark-im-messages-send.md | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/shortcuts/common/runner.go b/shortcuts/common/runner.go index 1ddb69e51..7d9685a13 100644 --- a/shortcuts/common/runner.go +++ b/shortcuts/common/runner.go @@ -263,8 +263,8 @@ func (ctx *RuntimeContext) DoAPI(req *larkcore.ApiReq, opts ...larkcore.RequestO } // DoAPIAsBot executes a raw Lark SDK request using bot identity (tenant access token), -// regardless of the current --as flag. Use this for bot-only APIs (e.g. image/file upload) -// that must be called with TAT even when the surrounding shortcut runs as user. +// regardless of the current --as flag. Use this for APIs that must always be called +// with TAT even when the surrounding shortcut runs as user. func (ctx *RuntimeContext) DoAPIAsBot(req *larkcore.ApiReq, opts ...larkcore.RequestOptionFunc) (*larkcore.ApiResp, error) { ac, err := ctx.getAPIClient() if err != nil { diff --git a/shortcuts/im/helpers.go b/shortcuts/im/helpers.go index f4a3dd8ed..053b9f98e 100644 --- a/shortcuts/im/helpers.go +++ b/shortcuts/im/helpers.go @@ -1131,7 +1131,7 @@ func uploadImageToIM(ctx context.Context, runtime *common.RuntimeContext, filePa fd.AddField("image_type", imageType) fd.AddFile("image", f) - apiResp, err := runtime.DoAPIAsBot(&larkcore.ApiReq{ + apiResp, err := runtime.DoAPI(&larkcore.ApiReq{ HttpMethod: http.MethodPost, ApiPath: "/open-apis/im/v1/images", Body: fd, @@ -1172,7 +1172,7 @@ func uploadFileToIM(ctx context.Context, runtime *common.RuntimeContext, filePat } fd.AddFile("file", f) - apiResp, err := runtime.DoAPIAsBot(&larkcore.ApiReq{ + apiResp, err := runtime.DoAPI(&larkcore.ApiReq{ HttpMethod: http.MethodPost, ApiPath: "/open-apis/im/v1/files", Body: fd, @@ -1200,7 +1200,7 @@ func uploadImageFromReader(ctx context.Context, runtime *common.RuntimeContext, fd.AddField("image_type", imageType) fd.AddFile("image", r) - apiResp, err := runtime.DoAPIAsBot(&larkcore.ApiReq{ + apiResp, err := runtime.DoAPI(&larkcore.ApiReq{ HttpMethod: http.MethodPost, ApiPath: "/open-apis/im/v1/images", Body: fd, @@ -1232,7 +1232,7 @@ func uploadFileFromReader(ctx context.Context, runtime *common.RuntimeContext, r } fd.AddFile("file", r) - apiResp, err := runtime.DoAPIAsBot(&larkcore.ApiReq{ + apiResp, err := runtime.DoAPI(&larkcore.ApiReq{ HttpMethod: http.MethodPost, ApiPath: "/open-apis/im/v1/files", Body: fd, diff --git a/skills/lark-im/references/lark-im-messages-reply.md b/skills/lark-im/references/lark-im-messages-reply.md index 3cee0685e..cc73a5993 100644 --- a/skills/lark-im/references/lark-im-messages-reply.md +++ b/skills/lark-im/references/lark-im-messages-reply.md @@ -211,7 +211,7 @@ The reply appears in the target message's thread and does not show up in the mai - When using `--content`, you are responsible for making the JSON structure match the effective `msg_type` - `--reply-in-thread` adds `reply_in_thread=true` to the API request - `--reply-in-thread` is mainly meaningful in chats that support thread replies -- `--image`/`--file`/`--video`/`--audio`/`--video-cover` support local file paths; the shortcut uploads first and then sends the reply; file/image upload is bot-only, so when using `--as user`, the upload step is automatically performed with bot identity, and only the final send uses user identity +- `--image`/`--file`/`--video`/`--audio`/`--video-cover` support local file paths; the shortcut uploads first and then sends the reply; both the upload and send steps use the same identity (UAT when `--as user`, TAT when `--as bot`) - If the provided media value starts with `img_` or `file_`, it is treated as an existing key and used directly - `--markdown` always sends `msg_type=post` - If you explicitly set `--msg-type` and it conflicts with the chosen content flag, validation fails diff --git a/skills/lark-im/references/lark-im-messages-send.md b/skills/lark-im/references/lark-im-messages-send.md index d9a578165..a328063a3 100644 --- a/skills/lark-im/references/lark-im-messages-send.md +++ b/skills/lark-im/references/lark-im-messages-send.md @@ -211,7 +211,7 @@ lark-cli im +messages-send --chat-id oc_xxx --markdown $'## Test\n\nhello' --dry - `--chat-id` and `--user-id` are mutually exclusive; you must provide exactly one - `--content` must be valid JSON - When using `--content`, you are responsible for making the JSON structure match the effective `msg_type` -- `--image`/`--file`/`--video`/`--audio` support local file paths; the shortcut uploads first and then sends the message; file/image upload is bot-only, so when using `--as user`, the upload step is automatically performed with bot identity, and only the final send uses user identity +- `--image`/`--file`/`--video`/`--audio` support local file paths; the shortcut uploads first and then sends the message; both the upload and send steps use the same identity (UAT when `--as user`, TAT when `--as bot`) - If the provided media value starts with `img_` or `file_`, it is treated as an existing key and used directly - `--markdown` always sends `msg_type=post`, even if you do not explicitly set `--msg-type post` - If you explicitly set `--msg-type` and it conflicts with the chosen content flag, validation fails