247 lines
8.3 KiB
Go
247 lines
8.3 KiB
Go
package share
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
|
|
"github.com/labstack/echo/v4"
|
|
wechat_v2 "github.com/silenceper/wechat/v2"
|
|
"github.com/silenceper/wechat/v2/cache"
|
|
offConfig "github.com/silenceper/wechat/v2/officialaccount/config"
|
|
"github.com/silenceper/wechat/v2/officialaccount/message"
|
|
|
|
"github.com/chaitin/panda-wiki/consts"
|
|
"github.com/chaitin/panda-wiki/domain"
|
|
"github.com/chaitin/panda-wiki/handler"
|
|
"github.com/chaitin/panda-wiki/log"
|
|
"github.com/chaitin/panda-wiki/usecase"
|
|
)
|
|
|
|
type ShareAppHandler struct {
|
|
*handler.BaseHandler
|
|
logger *log.Logger
|
|
usecase *usecase.AppUsecase
|
|
}
|
|
|
|
func NewShareAppHandler(
|
|
e *echo.Echo,
|
|
baseHandler *handler.BaseHandler,
|
|
logger *log.Logger,
|
|
usecase *usecase.AppUsecase,
|
|
) *ShareAppHandler {
|
|
h := &ShareAppHandler{
|
|
BaseHandler: baseHandler,
|
|
logger: logger.WithModule("handler.share.app"),
|
|
usecase: usecase,
|
|
}
|
|
|
|
share := e.Group("share/v1/app",
|
|
func(next echo.HandlerFunc) echo.HandlerFunc {
|
|
return func(c echo.Context) error {
|
|
c.Response().Header().Set("Access-Control-Allow-Origin", "*")
|
|
c.Response().Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
|
|
c.Response().Header().Set("Access-Control-Allow-Headers", "Content-Type, Origin, Accept")
|
|
if c.Request().Method == "OPTIONS" {
|
|
return c.NoContent(http.StatusOK)
|
|
}
|
|
return next(c)
|
|
}
|
|
})
|
|
share.GET("/web/info", h.GetWebAppInfo)
|
|
share.GET("/widget/info", h.GetWidgetAppInfo)
|
|
share.GET("/wechat/info", h.WechatAppInfo)
|
|
|
|
// wechat official account
|
|
share.GET("/wechat/official_account", h.VerifyUrlWechatOfficialAccount)
|
|
share.POST("/wechat/official_account", h.WechatHandlerOfficialAccount)
|
|
return h
|
|
}
|
|
|
|
// GetWebAppInfo
|
|
//
|
|
// @Summary GetAppInfo
|
|
// @Description GetAppInfo
|
|
// @Tags share_app
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param X-KB-ID header string true "kb id"
|
|
// @Success 200 {object} domain.Response{data=domain.AppInfoResp}
|
|
// @Router /share/v1/app/web/info [get]
|
|
func (h *ShareAppHandler) GetWebAppInfo(c echo.Context) error {
|
|
kbID := c.Request().Header.Get("X-KB-ID")
|
|
if kbID == "" {
|
|
return h.NewResponseWithError(c, "kb_id is required", nil)
|
|
}
|
|
ctx := context.WithValue(c.Request().Context(), consts.ContextKeyEdition, consts.GetLicenseEdition(c))
|
|
appInfo, err := h.usecase.ShareGetWebAppInfo(ctx, kbID, domain.GetAuthID(c))
|
|
if err != nil {
|
|
return h.NewResponseWithError(c, err.Error(), err)
|
|
}
|
|
return h.NewResponseWithData(c, appInfo)
|
|
}
|
|
|
|
// GetWidgetAppInfo
|
|
//
|
|
// @Summary GetWidgetAppInfo
|
|
// @Description GetWidgetAppInfo
|
|
// @Tags share_app
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param X-KB-ID header string true "kb id"
|
|
// @Success 200 {object} domain.Response
|
|
// @Router /share/v1/app/widget/info [get]
|
|
func (h *ShareAppHandler) GetWidgetAppInfo(c echo.Context) error {
|
|
kbID := c.Request().Header.Get("X-KB-ID")
|
|
if kbID == "" {
|
|
return h.NewResponseWithError(c, "kb_id is required", nil)
|
|
}
|
|
appInfo, err := h.usecase.GetWidgetAppInfo(c.Request().Context(), kbID)
|
|
if err != nil {
|
|
return h.NewResponseWithError(c, err.Error(), err)
|
|
}
|
|
return h.NewResponseWithData(c, appInfo)
|
|
}
|
|
|
|
// WechatAppInfo
|
|
//
|
|
// @Summary WechatAppInfo
|
|
// @Description WechatAppInfo
|
|
// @Tags share_chat
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param X-KB-ID header string true "kb id"
|
|
// @Success 200 {object} domain.Response{data=v1.WechatAppInfoResp}
|
|
// @Router /share/v1/app/wechat/info [get]
|
|
func (h *ShareAppHandler) WechatAppInfo(c echo.Context) error {
|
|
kbID := c.Request().Header.Get("X-KB-ID")
|
|
if kbID == "" {
|
|
return h.NewResponseWithError(c, "kb_id is required", nil)
|
|
}
|
|
appInfo, err := h.usecase.GetWechatAppInfo(c.Request().Context(), kbID)
|
|
if err != nil {
|
|
return h.NewResponseWithError(c, err.Error(), err)
|
|
}
|
|
return h.NewResponseWithData(c, appInfo)
|
|
}
|
|
|
|
func (h *ShareAppHandler) VerifyUrlWechatOfficialAccount(c echo.Context) error {
|
|
kbID := c.Request().Header.Get("X-KB-ID")
|
|
|
|
if kbID == "" {
|
|
return h.NewResponseWithError(c, "kb_id is required", nil)
|
|
}
|
|
ctx := c.Request().Context()
|
|
|
|
// get wechat official account info
|
|
appInfo, err := h.usecase.GetAppDetailByKBIDAndAppType(ctx, kbID, domain.AppTypeWechatOfficialAccount)
|
|
if err != nil {
|
|
h.logger.Error("get app detail failed")
|
|
return h.NewResponseWithError(c, "GetAppDetailByKBIDAndAppType failed", err)
|
|
}
|
|
|
|
if appInfo.Settings.WechatOfficialAccountIsEnabled != nil && !*appInfo.Settings.WechatOfficialAccountIsEnabled {
|
|
return h.NewResponseWithError(c, "wechat official account is not enabled", err)
|
|
}
|
|
wc := wechat_v2.NewWechat()
|
|
memory := cache.NewMemory()
|
|
cfg := &offConfig.Config{
|
|
AppID: appInfo.Settings.WechatOfficialAccountAppID,
|
|
AppSecret: appInfo.Settings.WechatOfficialAccountAppSecret,
|
|
Token: appInfo.Settings.WechatOfficialAccountToken,
|
|
EncodingAESKey: appInfo.Settings.WechatOfficialAccountEncodingAESKey,
|
|
Cache: memory,
|
|
}
|
|
officialAccount := wc.GetOfficialAccount(cfg)
|
|
server := officialAccount.GetServer(c.Request(), c.Response().Writer)
|
|
|
|
// success
|
|
err = server.Serve()
|
|
if err != nil {
|
|
return h.NewResponseWithError(c, "serve message failed", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (h *ShareAppHandler) WechatHandlerOfficialAccount(c echo.Context) error {
|
|
kbID := c.Request().Header.Get("X-KB-ID")
|
|
|
|
if kbID == "" {
|
|
return h.NewResponseWithError(c, "kb_id is required", nil)
|
|
}
|
|
ctx := c.Request().Context()
|
|
|
|
// get wechat official account info
|
|
appInfo, err := h.usecase.GetAppDetailByKBIDAndAppType(ctx, kbID, domain.AppTypeWechatOfficialAccount)
|
|
if err != nil {
|
|
h.logger.Error("get app detail failed")
|
|
return h.NewResponseWithError(c, "GetAppDetailByKBIDAndAppType failed", err)
|
|
}
|
|
|
|
if appInfo.Settings.WechatOfficialAccountIsEnabled != nil && !*appInfo.Settings.WechatOfficialAccountIsEnabled {
|
|
return h.NewResponseWithError(c, "wechat official account is not enabled", err)
|
|
}
|
|
wc := wechat_v2.NewWechat()
|
|
memory := cache.NewMemory()
|
|
cfg := &offConfig.Config{
|
|
AppID: appInfo.Settings.WechatOfficialAccountAppID,
|
|
AppSecret: appInfo.Settings.WechatOfficialAccountAppSecret,
|
|
Token: appInfo.Settings.WechatOfficialAccountToken,
|
|
EncodingAESKey: appInfo.Settings.WechatOfficialAccountEncodingAESKey,
|
|
Cache: memory,
|
|
}
|
|
officialAccount := wc.GetOfficialAccount(cfg)
|
|
server := officialAccount.GetServer(c.Request(), c.Response().Writer)
|
|
|
|
// message handler
|
|
server.SetMessageHandler(func(msg *message.MixMessage) *message.Reply {
|
|
h.logger.Info("received message:", log.Any("msgtype", msg.MsgType), log.Any("fromUserName", msg.FromUserName), log.String("content", msg.Content), log.Any("event type", msg.Event))
|
|
|
|
switch msg.MsgType {
|
|
case message.MsgTypeText:
|
|
// text消息
|
|
userOpenID := msg.FromUserName
|
|
userContent := msg.Content
|
|
h.logger.Info("user_open_id user_content", log.Any("user_open_id", userOpenID), log.Any("user content", userContent))
|
|
// 异步发送
|
|
go func(openID, content string) {
|
|
ctx := context.Background()
|
|
// send content to ai
|
|
result, err := h.usecase.GetWechatOfficialAccountResponse(ctx, officialAccount, kbID, openID, content)
|
|
if err != nil {
|
|
h.logger.Error("get wechat official account response failed", log.Error(err))
|
|
return
|
|
}
|
|
// send response to user --> 需要开启客服消息权限
|
|
err = h.usecase.SendCustomerServiceMessage(officialAccount, string(userOpenID), result)
|
|
if err != nil {
|
|
h.logger.Error("send to customer service failed", log.Error(err))
|
|
}
|
|
}(string(userOpenID), userContent)
|
|
return &message.Reply{MsgType: message.MsgTypeText, MsgData: message.NewText("您的问题已经收到,正在努力思考中,请稍候...")}
|
|
case message.MsgTypeEvent:
|
|
if msg.Event == message.EventSubscribe {
|
|
return &message.Reply{MsgType: message.MsgTypeText, MsgData: message.NewText("感谢关注,欢迎提问!")} // 立即回复简单信息
|
|
}
|
|
return nil
|
|
default:
|
|
h.logger.Info("unknown message type", log.Any("message type", msg.MsgType))
|
|
return &message.Reply{MsgType: message.MsgTypeText, MsgData: message.NewText("未知消息类型,请发送正确的类型...")}
|
|
}
|
|
})
|
|
|
|
// success
|
|
err = server.Serve()
|
|
if err != nil {
|
|
h.logger.Error("serve message failed", log.Error(err))
|
|
return h.NewResponseWithError(c, "serve message failed", err)
|
|
}
|
|
|
|
// send message to user
|
|
err = server.Send()
|
|
if err != nil {
|
|
h.logger.Error("send message failed", log.Error(err))
|
|
return h.NewResponseWithError(c, "send message failed", err)
|
|
}
|
|
return nil
|
|
}
|