109 lines
2.9 KiB
Go
109 lines
2.9 KiB
Go
package questiontable
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
)
|
|
|
|
type Field struct {
|
|
ID string `json:"id"`
|
|
Name string `json:"name"`
|
|
Type string `json:"type"`
|
|
}
|
|
|
|
type RequiredField struct {
|
|
Logical string
|
|
Name string
|
|
Type string
|
|
}
|
|
|
|
func QuestionSchema() []RequiredField {
|
|
return []RequiredField{
|
|
{"chinese_question", "中文问题", "text"},
|
|
{"asked_time", "提问时间", "date"},
|
|
{"asker", "提问人", "user"},
|
|
{"original_question", "原始问题", "text"},
|
|
{"answer", "AI答案", "text"},
|
|
{"trigger_person", "流程触发人员信息", "text"},
|
|
{"language", "语言", "text"},
|
|
{"department", "部门", "text"},
|
|
{"region", "区域", "text"},
|
|
}
|
|
}
|
|
|
|
func FAQSchema() []RequiredField {
|
|
return []RequiredField{
|
|
{"standard_question", "标准问题(必填)", "text"},
|
|
{"original_question", "原始问题", "text"},
|
|
{"language", "语言", "text"},
|
|
{"asker", "提问人", "user"},
|
|
}
|
|
}
|
|
|
|
func MapRequiredFields(fields []Field, required []RequiredField) (map[string]string, error) {
|
|
out := make(map[string]string, len(required))
|
|
for _, want := range required {
|
|
nameMatches := make([]Field, 0, 1)
|
|
for _, got := range fields {
|
|
if strings.TrimSpace(got.Name) == want.Name {
|
|
nameMatches = append(nameMatches, got)
|
|
}
|
|
}
|
|
if len(nameMatches) == 0 {
|
|
return nil, errors.New("missing_field")
|
|
}
|
|
if len(nameMatches) > 1 {
|
|
return nil, errors.New("duplicate_field")
|
|
}
|
|
if strings.TrimSpace(nameMatches[0].Type) != want.Type {
|
|
return nil, errors.New("field_type_mismatch")
|
|
}
|
|
if strings.TrimSpace(nameMatches[0].ID) == "" {
|
|
return nil, errors.New("missing_field_id")
|
|
}
|
|
out[want.Logical] = strings.TrimSpace(nameMatches[0].ID)
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
func (c *Client) ReadFields(ctx context.Context) ([]Field, error) {
|
|
token, err := c.getAccessToken(ctx)
|
|
if err != nil {
|
|
return nil, errors.New("schema_token_failed")
|
|
}
|
|
endpoint := fmt.Sprintf("%s/v1.0/notable/bases/%s/sheets/%s/fields?operatorId=%s", c.baseURL, url.PathEscape(c.baseID), url.PathEscape(c.sheetID), url.QueryEscape(c.operatorID))
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, nil)
|
|
if err != nil {
|
|
return nil, errors.New("schema_request_failed")
|
|
}
|
|
req.Header.Set("x-acs-dingtalk-access-token", token)
|
|
resp, err := c.http.Do(req)
|
|
if err != nil {
|
|
return nil, errors.New("schema_network_failed")
|
|
}
|
|
defer resp.Body.Close()
|
|
raw, err := io.ReadAll(io.LimitReader(resp.Body, 256<<10))
|
|
if err != nil {
|
|
return nil, errors.New("schema_read_failed")
|
|
}
|
|
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
|
return nil, fmt.Errorf("schema_http_%d", resp.StatusCode)
|
|
}
|
|
var payload struct {
|
|
Value []Field `json:"value"`
|
|
}
|
|
if json.Unmarshal(raw, &payload) != nil {
|
|
return nil, errors.New("schema_decode_failed")
|
|
}
|
|
if len(payload.Value) == 0 {
|
|
return nil, errors.New("schema_empty")
|
|
}
|
|
return payload.Value, nil
|
|
}
|