mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-08-26 01:52:16 +08:00
feat: make chat-channel and implement WhatsApp bot (#17518)
This commit is contained in:
@@ -30,6 +30,7 @@ type ChatChannelService interface {
|
||||
List(ctx context.Context, tenantID string) ([]*entity.ChatChannelListResponse, error)
|
||||
GetChatChannel(ctx context.Context, userID, channelID string) (*entity.ChatChannel, common.ErrorCode, error)
|
||||
UpdateChatChannel(ctx context.Context, userID, channelID string, req map[string]interface{}) (*entity.ChatChannel, common.ErrorCode, error)
|
||||
GetChatChannelRuntime(ctx context.Context, userID, channelID string) (map[string]any, common.ErrorCode, error)
|
||||
DeleteChatChannel(ctx context.Context, userID, channelID string) (bool, common.ErrorCode, error)
|
||||
}
|
||||
|
||||
@@ -49,7 +50,7 @@ func NewChatChannel() *ChatChannelHandler {
|
||||
type CreateChatChannelRequest struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
Channel string `json:"channel" binding:"required"`
|
||||
Config entity.JSONMap `json:"config" binding:"required"`
|
||||
Config entity.JSONMap `json:"config"`
|
||||
ChatID *string `json:"chat_id"`
|
||||
}
|
||||
|
||||
@@ -66,6 +67,9 @@ func (h *ChatChannelHandler) CreateChatChannel(c *gin.Context) {
|
||||
common.ResponseWithCodeData(c, common.CodeDataError, nil, "Invalid request: "+err.Error())
|
||||
return
|
||||
}
|
||||
if req.Config == nil {
|
||||
req.Config = entity.JSONMap{}
|
||||
}
|
||||
|
||||
ctx := c.Request.Context()
|
||||
|
||||
@@ -167,6 +171,35 @@ func (h *ChatChannelHandler) UpdateChatChannel(c *gin.Context) {
|
||||
common.SuccessWithData(c, result, "success")
|
||||
}
|
||||
|
||||
// GetChatChannelRuntime returns live runtime metadata for a running chat channel.
|
||||
func (h *ChatChannelHandler) GetChatChannelRuntime(c *gin.Context) {
|
||||
user, errorCode, errorMessage := GetUser(c)
|
||||
if errorCode != common.CodeSuccess {
|
||||
common.ErrorWithCode(c, errorCode, errorMessage)
|
||||
return
|
||||
}
|
||||
|
||||
userID := strings.TrimSpace(user.ID)
|
||||
if userID == "" {
|
||||
common.ResponseWithCodeData(c, common.CodeArgumentError, nil, "user_id is required")
|
||||
return
|
||||
}
|
||||
|
||||
channelID := strings.TrimSpace(c.Param("channel_id"))
|
||||
if channelID == "" {
|
||||
common.ResponseWithCodeData(c, common.CodeArgumentError, nil, "channel_id is required")
|
||||
return
|
||||
}
|
||||
|
||||
ctx := c.Request.Context()
|
||||
result, code, err := h.chatChannelService.GetChatChannelRuntime(ctx, userID, channelID)
|
||||
if code != common.CodeSuccess || err != nil {
|
||||
writeChatChannelError(c, code, chatChannelErrMsg(code, err))
|
||||
return
|
||||
}
|
||||
common.SuccessWithData(c, result, "success")
|
||||
}
|
||||
|
||||
// DeleteChatChannel handles DELETE /chat-channels/:channel_id.
|
||||
func (h *ChatChannelHandler) DeleteChatChannel(c *gin.Context) {
|
||||
user, errorCode, errorMessage := GetUser(c)
|
||||
|
||||
@@ -16,11 +16,12 @@ import (
|
||||
)
|
||||
|
||||
type fakeChatChannelService struct {
|
||||
createFn func(tenantID, name, channelType string, config entity.JSONMap, chatID *string) (*entity.ChatChannel, error)
|
||||
listFn func(tenantID string) ([]*entity.ChatChannelListResponse, error)
|
||||
getFn func(userID, channelID string) (*entity.ChatChannel, common.ErrorCode, error)
|
||||
updateFn func(userID, channelID string, req map[string]interface{}) (*entity.ChatChannel, common.ErrorCode, error)
|
||||
deleteFn func(userID, channelID string) (bool, common.ErrorCode, error)
|
||||
createFn func(tenantID, name, channelType string, config entity.JSONMap, chatID *string) (*entity.ChatChannel, error)
|
||||
listFn func(tenantID string) ([]*entity.ChatChannelListResponse, error)
|
||||
getFn func(userID, channelID string) (*entity.ChatChannel, common.ErrorCode, error)
|
||||
updateFn func(userID, channelID string, req map[string]interface{}) (*entity.ChatChannel, common.ErrorCode, error)
|
||||
runtimeFn func(userID, channelID string) (map[string]any, common.ErrorCode, error)
|
||||
deleteFn func(userID, channelID string) (bool, common.ErrorCode, error)
|
||||
}
|
||||
|
||||
func (f fakeChatChannelService) CreateChatChannel(ctx context.Context, tenantID, name, channelType string, config entity.JSONMap, chatID *string) (*entity.ChatChannel, error) {
|
||||
@@ -51,6 +52,13 @@ func (f fakeChatChannelService) UpdateChatChannel(ctx context.Context, userID, c
|
||||
return f.updateFn(userID, channelID, req)
|
||||
}
|
||||
|
||||
func (f fakeChatChannelService) GetChatChannelRuntime(ctx context.Context, userID, channelID string) (map[string]any, common.ErrorCode, error) {
|
||||
if f.runtimeFn == nil {
|
||||
return nil, common.CodeServerError, errors.New("unexpected GetChatChannelRuntime call")
|
||||
}
|
||||
return f.runtimeFn(userID, channelID)
|
||||
}
|
||||
|
||||
func (f fakeChatChannelService) DeleteChatChannel(ctx context.Context, userID, channelID string) (bool, common.ErrorCode, error) {
|
||||
if f.deleteFn == nil {
|
||||
return false, common.CodeServerError, errors.New("unexpected DeleteChatChannel call")
|
||||
@@ -327,3 +335,44 @@ func TestChatChannelHandlerDeleteChatChannelSuccess(t *testing.T) {
|
||||
t.Fatalf("payload=%v", payload)
|
||||
}
|
||||
}
|
||||
|
||||
func TestChatChannelHandlerGetRuntimeSuccess(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
var gotUserID, gotChannelID string
|
||||
h := &ChatChannelHandler{
|
||||
chatChannelService: fakeChatChannelService{
|
||||
runtimeFn: func(userID, channelID string) (map[string]any, common.ErrorCode, error) {
|
||||
gotUserID = userID
|
||||
gotChannelID = channelID
|
||||
return map[string]any{"status": "waiting"}, common.CodeSuccess, nil
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
router := gin.New()
|
||||
router.GET("/api/v1/chat-channels/:channel_id/runtime", func(c *gin.Context) {
|
||||
c.Set("user", &entity.User{ID: "tenant-1"})
|
||||
h.GetChatChannelRuntime(c)
|
||||
})
|
||||
|
||||
resp := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/chat-channels/cc-1/runtime", nil)
|
||||
router.ServeHTTP(resp, req)
|
||||
|
||||
if gotUserID != "tenant-1" || gotChannelID != "cc-1" {
|
||||
t.Fatalf("userID=%q channelID=%q", gotUserID, gotChannelID)
|
||||
}
|
||||
|
||||
var payload map[string]interface{}
|
||||
if err := json.Unmarshal(resp.Body.Bytes(), &payload); err != nil {
|
||||
t.Fatalf("unmarshal response: %v", err)
|
||||
}
|
||||
if payload["code"] != float64(common.CodeSuccess) {
|
||||
t.Fatalf("payload=%v", payload)
|
||||
}
|
||||
data, _ := payload["data"].(map[string]interface{})
|
||||
if data["status"] != "waiting" {
|
||||
t.Fatalf("payload=%v", payload)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user