mirror of
https://github.com/larksuite/cli.git
synced 2026-07-06 00:06:28 +08:00
101 lines
2.8 KiB
Go
101 lines
2.8 KiB
Go
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package base
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
"github.com/larksuite/cli/internal/output"
|
|
"github.com/larksuite/cli/shortcuts/common"
|
|
)
|
|
|
|
// handleRoleResponse parses the role API response.
|
|
// The response has two layers of code/message:
|
|
// - Outer: SDK-level code/msg (handled by DoAPI for transport errors)
|
|
// - Inner: business-level code/message inside the data object
|
|
//
|
|
// The data field may be a JSON object (actual behavior) or a JSON string (per doc).
|
|
func handleRoleResponse(runtime *common.RuntimeContext, rawBody []byte, action string) error {
|
|
var resp struct {
|
|
Code int `json:"code"`
|
|
Msg string `json:"msg"`
|
|
Data json.RawMessage `json:"data"`
|
|
}
|
|
if err := json.Unmarshal(rawBody, &resp); err != nil {
|
|
return fmt.Errorf("failed to parse response: %v", err)
|
|
}
|
|
if resp.Code != 0 {
|
|
msg := resp.Msg
|
|
// When outer msg is empty, try to extract error details from data.error.message
|
|
if msg == "" && len(resp.Data) > 0 {
|
|
var errData struct {
|
|
Error struct {
|
|
Message string `json:"message"`
|
|
Hint string `json:"hint"`
|
|
} `json:"error"`
|
|
}
|
|
if json.Unmarshal(resp.Data, &errData) == nil && errData.Error.Message != "" {
|
|
msg = errData.Error.Message
|
|
}
|
|
}
|
|
return output.ErrAPI(resp.Code, fmt.Sprintf("%s: [%d] %s", action, resp.Code, msg), nil)
|
|
}
|
|
|
|
if len(resp.Data) == 0 || string(resp.Data) == "null" || string(resp.Data) == `""` {
|
|
runtime.Out(map[string]any{"success": true}, nil)
|
|
return nil
|
|
}
|
|
|
|
// Parse data
|
|
var data any
|
|
if err := json.Unmarshal(resp.Data, &data); err != nil {
|
|
runtime.Out(map[string]any{"data": string(resp.Data)}, nil)
|
|
return nil
|
|
}
|
|
|
|
// If data is a string (double-encoded JSON), try to parse it
|
|
if s, ok := data.(string); ok && s != "" {
|
|
var inner any
|
|
if err := json.Unmarshal([]byte(s), &inner); err == nil {
|
|
data = inner
|
|
}
|
|
}
|
|
|
|
// Check for business-level error: data may contain its own code/message
|
|
if m, ok := data.(map[string]any); ok {
|
|
if code, exists := m["code"]; exists {
|
|
var codeInt int
|
|
switch v := code.(type) {
|
|
case float64:
|
|
codeInt = int(v)
|
|
case int:
|
|
codeInt = v
|
|
}
|
|
if codeInt != 0 {
|
|
msg, _ := m["message"].(string)
|
|
return output.ErrAPI(codeInt, fmt.Sprintf("%s: [%d] %s", action, codeInt, msg), nil)
|
|
}
|
|
// code == 0, extract the inner data if present
|
|
if innerData, hasInner := m["data"]; hasInner {
|
|
// Inner data might be a double-encoded JSON string
|
|
if s, ok := innerData.(string); ok && s != "" {
|
|
var parsed any
|
|
if err := json.Unmarshal([]byte(s), &parsed); err == nil {
|
|
runtime.Out(parsed, nil)
|
|
return nil
|
|
}
|
|
}
|
|
runtime.Out(innerData, nil)
|
|
return nil
|
|
}
|
|
runtime.Out(map[string]any{"success": true}, nil)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
runtime.Out(data, nil)
|
|
return nil
|
|
}
|