mirror of
https://github.com/larksuite/cli.git
synced 2026-07-04 06:29:52 +08:00
94 lines
2.8 KiB
Go
94 lines
2.8 KiB
Go
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package doc
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"strings"
|
|
|
|
"github.com/larksuite/cli/internal/output"
|
|
"github.com/larksuite/cli/shortcuts/common"
|
|
)
|
|
|
|
// docsSceneContextKey lets in-process embedders pass a server-owned docs_ai
|
|
// scene without exposing it as a user-controlled CLI flag.
|
|
const docsSceneContextKey = "lark_cli_docs_scene"
|
|
|
|
type documentRef struct {
|
|
Kind string
|
|
Token string
|
|
}
|
|
|
|
func parseDocumentRef(input string) (documentRef, error) {
|
|
raw := strings.TrimSpace(input)
|
|
if raw == "" {
|
|
return documentRef{}, output.ErrValidation("--doc cannot be empty")
|
|
}
|
|
|
|
if token, ok := extractDocumentToken(raw, "/wiki/"); ok {
|
|
return documentRef{Kind: "wiki", Token: token}, nil
|
|
}
|
|
if token, ok := extractDocumentToken(raw, "/docx/"); ok {
|
|
return documentRef{Kind: "docx", Token: token}, nil
|
|
}
|
|
if token, ok := extractDocumentToken(raw, "/doc/"); ok {
|
|
return documentRef{Kind: "doc", Token: token}, nil
|
|
}
|
|
if strings.Contains(raw, "://") {
|
|
return documentRef{}, output.ErrValidation("unsupported --doc input %q: use a docx URL/token or a wiki URL that resolves to docx", raw)
|
|
}
|
|
if strings.ContainsAny(raw, "/?#") {
|
|
return documentRef{}, output.ErrValidation("unsupported --doc input %q: use a docx token or a wiki URL", raw)
|
|
}
|
|
|
|
return documentRef{Kind: "docx", Token: raw}, nil
|
|
}
|
|
|
|
func extractDocumentToken(raw, marker string) (string, bool) {
|
|
idx := strings.Index(raw, marker)
|
|
if idx < 0 {
|
|
return "", false
|
|
}
|
|
token := raw[idx+len(marker):]
|
|
if end := strings.IndexAny(token, "/?#"); end >= 0 {
|
|
token = token[:end]
|
|
}
|
|
token = strings.TrimSpace(token)
|
|
if token == "" {
|
|
return "", false
|
|
}
|
|
return token, true
|
|
}
|
|
|
|
// doDocAPI executes an OpenAPI request against the docs_ai endpoints and returns
|
|
// the parsed "data" field from the standard Lark response envelope {code, msg, data}.
|
|
// Uses the log-id-aware variant so the x-tt-logid header is surfaced in both the
|
|
// success payload and error details — doc v2 callers rely on it for support escalations.
|
|
func doDocAPI(runtime *common.RuntimeContext, method, apiPath string, body interface{}) (map[string]interface{}, error) {
|
|
return runtime.DoAPIJSONWithLogID(method, apiPath, nil, body)
|
|
}
|
|
|
|
func docsSceneFromContext(ctx context.Context) string {
|
|
if ctx == nil {
|
|
return ""
|
|
}
|
|
scene, _ := ctx.Value(docsSceneContextKey).(string)
|
|
return strings.TrimSpace(scene)
|
|
}
|
|
|
|
func injectDocsScene(runtime *common.RuntimeContext, body map[string]interface{}) {
|
|
if scene := docsSceneFromContext(runtime.Ctx()); scene != "" {
|
|
body["scene"] = scene
|
|
}
|
|
}
|
|
|
|
func buildDriveRouteExtra(docID string) (string, error) {
|
|
extra, err := json.Marshal(map[string]string{"drive_route_token": docID})
|
|
if err != nil {
|
|
return "", output.Errorf(output.ExitInternal, "internal_error", "failed to marshal upload extra data: %v", err)
|
|
}
|
|
return string(extra), nil
|
|
}
|