mirror of
https://github.com/openimsdk/open-im-server.git
synced 2026-09-05 07:02:06 +08:00
* feat: afterMsgSaveDB webhook fix(config): add default webhook event filters fix(core): handle group mentions and webhook enqueue errors Use group IDs when filtering group-message attention callbacks, and report failures when asynchronous webhook tasks cannot be queued or posted. feat(webhook): add standalone mock webhook server CLI test(webhook): add mock server and test suite for all callback commands feat(msgtransfer): trigger afterMsgSaveDB webhook when message saved to DB feat(config): add afterMsgSaveDB webhook configuration feat(callbackstruct): add CallbackAfterMsgSaveDB command and request structs * refactor(core): simplify asynchronous webhook enqueueing
104 lines
3.4 KiB
Go
104 lines
3.4 KiB
Go
// Copyright © 2023 OpenIM. All rights reserved.
|
|
//
|
|
// 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 main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"flag"
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"os/signal"
|
|
"strings"
|
|
"syscall"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct"
|
|
"github.com/openimsdk/open-im-server/v3/test/webhook"
|
|
"github.com/openimsdk/protocol/constant"
|
|
)
|
|
|
|
func main() {
|
|
port := flag.Int("port", 10006, "Webhook server listening port")
|
|
sensitiveWord := flag.String("mask-word", "xxx", "Keyword to mask in callbackBeforeMsgModifyCommand")
|
|
flag.Parse()
|
|
|
|
gin.SetMode(gin.ReleaseMode)
|
|
srv := webhook.NewServer()
|
|
|
|
// 1. Log every incoming webhook request in real-time
|
|
srv.OnRequest(func(command string, reqBody []byte, c *gin.Context) {
|
|
log.Printf("[Webhook] %s %s | Command: %s | Body: %s",
|
|
c.Request.Method, c.Request.URL.Path, command, string(reqBody))
|
|
})
|
|
|
|
// 2. Example: Custom hook for message content modification (sensitive word filtering)
|
|
if *sensitiveWord != "" {
|
|
webhook.RegisterCallback(srv, cbapi.CallbackBeforeMsgModifyCommand, func(c *gin.Context, req *cbapi.CallbackMsgModifyCommandReq) (*cbapi.CallbackMsgModifyCommandResp, error) {
|
|
var resp cbapi.CallbackMsgModifyCommandResp
|
|
if req.ContentType != constant.Text {
|
|
return &resp, nil
|
|
}
|
|
var textElem struct {
|
|
Content string `json:"content"`
|
|
}
|
|
if err := json.Unmarshal([]byte(req.Content), &textElem); err != nil {
|
|
return nil, err
|
|
}
|
|
if strings.Contains(textElem.Content, *sensitiveWord) {
|
|
textElem.Content = strings.ReplaceAll(textElem.Content, *sensitiveWord, strings.Repeat("*", len(*sensitiveWord)))
|
|
masked, err := json.Marshal(&textElem)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
s := string(masked)
|
|
resp.Content = &s
|
|
log.Printf("[Webhook Mask] Masked content: %s -> %s", req.Content, s)
|
|
}
|
|
return &resp, nil
|
|
})
|
|
}
|
|
|
|
addr := fmt.Sprintf(":%d", *port)
|
|
log.Printf("=================================================================")
|
|
log.Printf(" OpenIM Mock Webhook Server is listening on %s", addr)
|
|
log.Printf(" Callback URL in config/webhooks.yml:")
|
|
log.Printf(" url: 'http://127.0.0.1:%d/callbackExample'", *port)
|
|
log.Printf(" Supported callbacks: 48 registered OpenIM callback commands")
|
|
log.Printf(" Press Ctrl+C to stop")
|
|
log.Printf("=================================================================")
|
|
|
|
go func() {
|
|
if err := srv.Start(addr); err != nil && err != http.ErrServerClosed {
|
|
log.Fatalf("Server listen error: %v", err)
|
|
}
|
|
}()
|
|
|
|
quit := make(chan os.Signal, 1)
|
|
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
|
<-quit
|
|
log.Println("Shutting down Webhook Server...")
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
defer cancel()
|
|
if err := srv.Shutdown(ctx); err != nil {
|
|
log.Fatalf("Server forced to shutdown: %v", err)
|
|
}
|
|
log.Println("Webhook Server exited cleanly.")
|
|
}
|