### Full Example: Multi-functional Robot Service with DingTalk Stream SDK Go Source: https://context7.com/open-dingtalk/dingtalk-stream-sdk-go/llms.txt This Go code provides a complete example of a DingTalk Stream robot service that handles multiple functionalities simultaneously: chat messages, event subscriptions, AI plugin callbacks, and interactive card callbacks. It demonstrates how to register different handlers for each type of incoming request and how to configure the client with application credentials. The example also shows how to enable debug logging and start the stream client. ```go package main import ( "context" "flag" "fmt" "github.com/open-dingtalk/dingtalk-stream-sdk-go/card" "github.com/open-dingtalk/dingtalk-stream-sdk-go/chatbot" "github.com/open-dingtalk/dingtalk-stream-sdk-go/client" "github.com/open-dingtalk/dingtalk-stream-sdk-go/event" "github.com/open-dingtalk/dingtalk-stream-sdk-go/logger" "github.com/open-dingtalk/dingtalk-stream-sdk-go/payload" "github.com/open-dingtalk/dingtalk-stream-sdk-go/plugin" ) // OnChatBotMessageReceived handles incoming chat bot messages. func OnChatBotMessageReceived(ctx context.Context, data *chatbot.BotCallbackDataModel) ([]byte, error) { replyMsg := fmt.Sprintf("收到消息: [%s]", data.Text.Content) replier := chatbot.NewChatbotReplier() return []byte(""), replier.SimpleReplyText(ctx, data.SessionWebhook, []byte(replyMsg)) } // OnPluginMessageReceived handles AI plugin requests. func OnPluginMessageReceived(ctx context.Context, request *plugin.GraphRequest) (*plugin.GraphResponse, error) { return &plugin.GraphResponse{ Body: `{"text": "插件响应", "content": []}`, }, nil } // OnEventReceived handles DingTalk events. func OnEventReceived(ctx context.Context, df *payload.DataFrame) (*payload.DataFrameResponse, error) { eventHeader := event.NewEventHeaderFromDataFrame(df) logger.GetLogger().Infof("事件: type=%s, id=%s", eventHeader.EventType, eventHeader.EventId) response := payload.NewSuccessDataFrameResponse() response.SetJson(event.NewEventProcessResultSuccess()) return response, nil } // OnCardCallbackReceived handles interactive card callbacks. func OnCardCallbackReceived(ctx context.Context, request *card.CardRequest) (*card.CardResponse, error) { logger.GetLogger().Infof("卡片回调: userId=%s, outTrackId=%s", request.UserId, request.OutTrackId) return &card.CardResponse{CardData: &card.CardDataDto{}}, } // main function to set up and run the DingTalk Stream client. func main() { var clientId, clientSecret string flag.StringVar(&clientId, "client_id", "", "应用 ClientId") flag.StringVar(&clientSecret, "client_secret", "", "应用 ClientSecret") flag.Parse() if clientId == "" || clientSecret == "" { fmt.Println("请提供 --client_id 和 --client_secret 参数") return } // Enable debug logging logger.SetLogger(logger.NewStdTestLoggerWithDebug()) // Create client cli := client.NewStreamClient( client.WithAppCredential(client.NewAppCredentialConfig(clientId, clientSecret)), ) // Register all handlers cli.RegisterAllEventRouter(OnEventReceived) cli.RegisterChatBotCallbackRouter(OnChatBotMessageReceived) cli.RegisterPluginCallbackRouter(OnPluginMessageReceived) cli.RegisterCardCallbackRouter(OnCardCallbackReceived) // Start the service if err := cli.Start(context.Background()); err != nil { panic(err) } defer cli.Close() logger.GetLogger().Infof("钉钉 Stream 服务已启动") select {} } ``` -------------------------------- ### Register Event Subscription Handlers Source: https://context7.com/open-dingtalk/dingtalk-stream-sdk-go/llms.txt Demonstrates how to register event routers to process system events. It includes examples of using generic DataFrame handlers and specific IEventHandler implementations to parse and respond to events. ```go package main import ( "context" "encoding/json" "fmt" "github.com/open-dingtalk/dingtalk-stream-sdk-go/client" "github.com/open-dingtalk/dingtalk-stream-sdk-go/event" "github.com/open-dingtalk/dingtalk-stream-sdk-go/payload" ) func OnEventReceived(ctx context.Context, df *payload.DataFrame) (*payload.DataFrameResponse, error) { eventHeader := event.NewEventHeaderFromDataFrame(df) fmt.Printf("收到事件: %s\n", eventHeader.EventType) response := payload.NewSuccessDataFrameResponse() if err := response.SetJson(event.NewEventProcessResultSuccess()); err != nil { return nil, err } return response, nil } func main() { cli := client.NewStreamClient(client.WithAppCredential(client.NewAppCredentialConfig("client-id", "client-secret"))) cli.RegisterAllEventRouter(OnEventReceived) if err := cli.Start(context.Background()); err != nil { panic(err) } defer cli.Close() } ``` -------------------------------- ### Implement Custom Logger with ILogger Interface in Go Source: https://context7.com/open-dingtalk/dingtalk-stream-sdk-go/llms.txt This Go code demonstrates how to implement a custom logger by adhering to the ILogger interface provided by the DingTalk Stream SDK. It allows integration with existing logging systems or custom logging logic. The default SDK does not output logs, making custom implementation necessary for visibility. This example uses standard Go log package to output messages to stdout and stderr. ```go package main import ( "log" "os" "github.com/open-dingtalk/dingtalk-stream-sdk-go/logger" ) // CustomLogger implements the ILogger interface for custom logging. type CustomLogger struct { debugLogger *log.Logger infoLogger *log.Logger warnLogger *log.Logger errorLogger *log.Logger } // NewCustomLogger creates a new instance of CustomLogger. func NewCustomLogger() *CustomLogger { return &CustomLogger{ debugLogger: log.New(os.Stdout, "[DEBUG] ", log.Ldate|log.Ltime|log.Lshortfile), infoLogger: log.New(os.Stdout, "[INFO] ", log.Ldate|log.Ltime), warnLogger: log.New(os.Stdout, "[WARN] ", log.Ldate|log.Ltime), errorLogger: log.New(os.Stderr, "[ERROR] ", log.Ldate|log.Ltime|log.Lshortfile), } } // Debugf logs a debug message. func (l *CustomLogger) Debugf(format string, args ...interface{}) { l.debugLogger.Printf(format, args...) } // Infof logs an info message. func (l *CustomLogger) Infof(format string, args ...interface{}) { l.infoLogger.Printf(format, args...) } // Warningf logs a warning message. func (l *CustomLogger) Warningf(format string, args ...interface{}) { l.warnLogger.Printf(format, args...) } // Errorf logs an error message. func (l *CustomLogger) Errorf(format string, args ...interface{}) { l.errorLogger.Printf(format, args...) } // Fatalf logs a fatal error message and exits. func (l *CustomLogger) Fatalf(format string, args ...interface{}) { l.errorLogger.Fatalf(format, args...) } func main() { // Use custom logger implementation logger.SetLogger(NewCustomLogger()) // Get the current logger instance log := logger.GetLogger() log.Infof("Logger initialized") } ``` -------------------------------- ### Register Custom Callback Routers with DingTalk Stream SDK Go Source: https://context7.com/open-dingtalk/dingtalk-stream-sdk-go/llms.txt Demonstrates registering custom callback routers for handling various subscription types and topics using the DingTalk Stream SDK for Go. It shows how to use `RegisterRouter`, `RegisterCallbackRouter`, and `RegisterEventRouter` to manage incoming data frames. ```go package main import ( "context" "fmt" "github.com/open-dingtalk/dingtalk-stream-sdk-go/client" "github.com/open-dingtalk/dingtalk-stream-sdk-go/payload" "github.com/open-dingtalk/dingtalk-stream-sdk-go/utils" ) // 自定义帧处理函数 func CustomFrameHandler(ctx context.Context, df *payload.DataFrame) (*payload.DataFrameResponse, error) { fmt.Printf("收到数据帧:\n") fmt.Printf(" 类型: %s\n", df.Type) fmt.Printf(" 主题: %s\n", df.GetTopic()) fmt.Printf(" 消息ID: %s\n", df.GetMessageId()) fmt.Printf(" 时间戳: %d\n", df.GetTimestamp()) fmt.Printf(" 数据: %s\n", df.Data) // 获取自定义头信息 customHeader := df.GetHeader("customHeaderKey") fmt.Printf(" 自定义头: %s\n", customHeader) // 构建响应 response := payload.NewSuccessDataFrameResponse() response.SetHeader(payload.DataFrameHeaderKContentType, payload.DataFrameContentTypeKJson) response.SetData(`{"result": "success"}`) return response, nil } func main() { cli := client.NewStreamClient( client.WithAppCredential(client.NewAppCredentialConfig("client-id", "client-secret")), ) // 方式1: 使用通用注册方法(指定订阅类型和主题) // 订阅类型常量: // - utils.SubscriptionTypeKCallback = "CALLBACK" // - utils.SubscriptionTypeKEvent = "EVENT" // - utils.SubscriptionTypeKSystem = "SYSTEM" cli.RegisterRouter(utils.SubscriptionTypeKCallback, "custom_topic", CustomFrameHandler) // 方式2: 注册回调类型路由(订阅类型固定为 CALLBACK) cli.RegisterCallbackRouter("another_custom_topic", CustomFrameHandler) // 方式3: 注册事件类型路由(订阅类型固定为 EVENT) cli.RegisterEventRouter("specific_event_type", CustomFrameHandler) if err := cli.Start(context.Background()); err != nil { panic(err) } defer cli.Close() select {} } ``` -------------------------------- ### Register Interactive Card Callback Handlers Source: https://context7.com/open-dingtalk/dingtalk-stream-sdk-go/llms.txt Shows how to register a callback router for interactive cards. This allows the application to respond to user interactions, such as button clicks, by updating card data or private user data. ```go package main import ( "context" "fmt" "github.com/open-dingtalk/dingtalk-stream-sdk-go/card" "github.com/open-dingtalk/dingtalk-stream-sdk-go/client" ) func OnCardCallbackReceived(ctx context.Context, request *card.CardRequest) (*card.CardResponse, error) { fmt.Printf("收到卡片回调: %s\n", request.Type) response := &card.CardResponse{ CardUpdateOptions: &card.CardUpdateOptions{UpdateCardDataByKey: true}, CardData: &card.CardDataDto{CardParamMap: map[string]string{"status": "已处理"}}, } return response, nil } func main() { cli := client.NewStreamClient(client.WithAppCredential(client.NewAppCredentialConfig("client-id", "client-secret"))) cli.RegisterCardCallbackRouter(OnCardCallbackReceived) if err := cli.Start(context.Background()); err != nil { panic(err) } defer cli.Close() } ``` -------------------------------- ### Register AI Plugin Callback Source: https://context7.com/open-dingtalk/dingtalk-stream-sdk-go/llms.txt Registers a handler for AI plugin requests, allowing the application to process incoming requests from DingTalk AI assistants. ```APIDOC ## RegisterPluginCallbackRouter ### Description Registers a callback function to handle requests sent by DingTalk AI assistants to custom plugins. ### Method Internal SDK Method (Event-Driven) ### Parameters - **handler** (func) - Required - A function with signature `func(context.Context, *plugin.GraphRequest) (*plugin.GraphResponse, error)` ### Request Example { "city": "Beijing", "date": "2023-10-27" } ### Response #### Success Response (200) - **text** (string) - The response message text. - **content** (array) - List of structured content items (title, description, url). #### Response Example { "text": "Beijing weather: Sunny, 25°C", "content": [ { "title": "Today's Weather", "description": "Sunny, 25°C", "url": "https://weather.example.com" } ] } ``` -------------------------------- ### Register AI Plugin Callback Handler with DingTalk Stream SDK Go Source: https://context7.com/open-dingtalk/dingtalk-stream-sdk-go/llms.txt Registers a callback handler for AI plugin requests in the DingTalk Stream SDK for Go. This function processes incoming requests from DingTalk AI assistants when they invoke custom plugins. It demonstrates parsing request bodies, handling business logic, and constructing JSON responses. ```go package main import ( "context" "encoding/json" "fmt" "github.com/open-dingtalk/dingtalk-stream-sdk-go/client" "github.com/open-dingtalk/dingtalk-stream-sdk-go/plugin" ) // 插件请求参数结构 type WeatherRequest struct { City string `json:"city"` Date string `json:"date"` } // 插件消息处理函数 func OnPluginMessageReceived(ctx context.Context, request *plugin.GraphRequest) (*plugin.GraphResponse, error) { fmt.Printf("收到插件请求:\n") fmt.Printf(" 请求方法: %s\n", request.RequestLine.Method) fmt.Printf(" 请求路径: %s\n", request.RequestLine.Path) fmt.Printf(" 请求URI: %s\n", request.RequestLine.Uri) fmt.Printf(" 请求头: %v\n", request.Headers) fmt.Printf(" 请求体: %s\n", request.Body) // 解析请求参数 var weatherReq WeatherRequest if err := json.Unmarshal([]byte(request.Body), &weatherReq); err != nil { // 使用 ParseRequest 辅助方法 if err := request.ParseRequest(&weatherReq); err != nil { return nil, err } } // 处理业务逻辑,构建响应 responseBody := map[string]interface{}{ "text": fmt.Sprintf("%s的天气: 晴天,温度25°C", weatherReq.City), "content": []map[string]string{ { "title": "今日天气", "description": "晴天,25°C", "url": "https://weather.example.com", }, { "title": "明日天气", "description": "多云,22°C", "url": "https://weather.example.com/tomorrow", }, }, } bodyBytes, _ := json.Marshal(responseBody) response := &plugin.GraphResponse{ StatusLine: plugin.GraphStatusLine{ Code: 200, Reason: "OK", }, Headers: map[string]string{ "Content-Type": "application/json", }, Body: string(bodyBytes), } return response, nil } func main() { cli := client.NewStreamClient( client.WithAppCredential(client.NewAppCredentialConfig("client-id", "client-secret")), ) // 注册 AI 插件回调处理器 cli.RegisterPluginCallbackRouter(OnPluginMessageReceived) if err := cli.Start(context.Background()); err != nil { panic(err) } defer cli.Close() select {} } ``` -------------------------------- ### Register Custom Router Source: https://context7.com/open-dingtalk/dingtalk-stream-sdk-go/llms.txt Registers custom routes for handling specific subscription types and topics, including CALLBACK, EVENT, and SYSTEM types. ```APIDOC ## RegisterRouter / RegisterCallbackRouter / RegisterEventRouter ### Description Registers custom handlers for specific event types or topics. Supports generic routing or specialized methods for callbacks and events. ### Method Internal SDK Method (Event-Driven) ### Parameters - **subscriptionType** (string) - Required - Type of subscription (e.g., CALLBACK, EVENT, SYSTEM). - **topic** (string) - Required - The specific topic to listen for. - **handler** (func) - Required - A function with signature `func(context.Context, *payload.DataFrame) (*payload.DataFrameResponse, error)` ### Request Example { "type": "EVENT", "topic": "specific_event_type", "data": "..." } ### Response #### Success Response (200) - **result** (string) - Status of the operation. #### Response Example { "result": "success" } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.