Files
dingtalk-workspace-cli/internal/shortcut/smart/broadcast.go
Dennis 8687d68567 feat: gate unverified shortcuts for release
Hide shortcuts that did not pass real testing from public help/list discovery while keeping commands available for internal retest.

Record real shortcut inputs/outputs, backend issue summaries, next-release hidden list, and refresh skill guidance to mirror the lark-cli shortcut integration pattern.
2026-07-15 16:45:51 +08:00

117 lines
4.3 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Copyright 2026 Alibaba Group
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package smart
import (
"encoding/json"
"fmt"
"strings"
apperrors "github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/errors"
"github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/shortcut"
)
// Broadcast: send the SAME single-chat message to several people by NAME.
//
// Steps: split the --to name CSV → resolve each name to a unique user →
// send an individual single-chat message to each user's openDingTalkId. Names that
// fail to resolve (unknown / ambiguous) are collected and reported at the end
// without aborting delivery to the others. Replaces manually running
// `chat +dm` once per recipient.
//
// dws chat +broadcast --to "张三,李四,王五" --text "今晚 8 点上线,请留意群公告"
var Broadcast = shortcut.Shortcut{
Service: "chat",
Command: "+broadcast",
Product: "chat",
Description: "按姓名逐一给多个人群发同一条单聊消息(自动解析 userId、逐个发送)",
Intent: "当你想把同一条通知一次性单聊发给多位同事、但只知道他们的姓名不想逐个查 userId 时使用;" +
"内部把姓名列表逐个解析成唯一用户后,用 openDingTalkId 对每个人单独发一条单聊消息,并汇总成功/失败人数。" +
"某个姓名匹配不到人或匹配到多人时,会跳过该人并在结尾报出,不影响其他人收到消息。会真实发出多条消息。",
Risk: shortcut.RiskWrite,
Flags: []shortcut.Flag{
{Name: "to", Type: shortcut.FlagStringSlice, Desc: "收件人姓名/花名,逗号分隔的多个人", Required: true},
{Name: "text", Type: shortcut.FlagString, Desc: "消息内容(支持 Markdown),所有人收到同一条", Required: true},
},
Tips: []string{`dws chat +broadcast --to "张三,李四,王五" --text "今晚 8 点上线,请留意"`},
Execute: func(rt *shortcut.RuntimeContext) error {
text := rt.Str("text")
names := rt.StrSlice("to")
if len(names) == 0 {
return apperrors.NewValidation("--to 至少要包含一个姓名")
}
content, _ := json.Marshal(map[string]string{"title": text, "text": text})
var (
sent []string
failed []string
)
for _, raw := range names {
name := strings.TrimSpace(raw)
if name == "" {
continue
}
// Step 1 — resolve this name to a unique userId. On failure
// (unknown / ambiguous) record it and keep going.
user, err := resolveUser(rt, name)
if err != nil {
failed = append(failed, fmt.Sprintf("%s(%s)", name, err.Error()))
continue
}
if user.openDingTalkID == "" {
failed = append(failed, fmt.Sprintf("%s(通讯录结果缺少 openDingTalkId)", name))
continue
}
// Step 2 — send the single-chat message to this recipient. Under
// --dry-run we still resolve names (a read) but never send: record the
// resolved recipient as "would send" and move on.
if rt.DryRun() {
sent = append(sent, user.name)
continue
}
if _, err := rt.CallMCPWriteData("chat", "send_personal_message", map[string]any{
"receiverOpenDingTalkId": user.openDingTalkID,
"msgType": "markdown",
"content": string(content),
}); err != nil {
failed = append(failed, fmt.Sprintf("%s(发送失败:%s)", name, err.Error()))
continue
}
sent = append(sent, user.name)
}
// Summarize via rt.Output (structured, honours --format/--jq/--fields)
// instead of fmt.Printf, which ignored the output flags.
if len(sent) == 0 {
return apperrors.NewValidation("没有任何人收到消息,请检查姓名是否正确")
}
result := map[string]any{
"sentCount": len(sent),
"failedCount": len(failed),
"sent": sent,
}
if len(failed) > 0 {
result["failed"] = failed
}
return rt.Output(result)
},
}
func init() {
shortcut.Register(Broadcast)
}