package domain import ( "database/sql/driver" "encoding/json" "errors" "fmt" "time" "github.com/chaitin/panda-wiki/consts" ) type AppType uint8 const ( AppTypeWeb AppType = iota + 1 AppTypeWidget AppTypeDingTalkBot AppTypeFeishuBot AppTypeWechatBot AppTypeWechatServiceBot AppTypeDisCordBot AppTypeWechatOfficialAccount AppTypeOpenAIAPI AppTypeWecomAIBot AppTypeLarkBot AppTypeMcpServer ) var AppTypes = []AppType{ AppTypeWeb, AppTypeWidget, AppTypeDingTalkBot, AppTypeFeishuBot, AppTypeWechatBot, AppTypeWechatServiceBot, AppTypeDisCordBot, AppTypeWechatOfficialAccount, AppTypeOpenAIAPI, AppTypeWecomAIBot, AppTypeLarkBot, AppTypeMcpServer, } func (t AppType) ToSourceType() consts.SourceType { switch t { case AppTypeWeb: return "" case AppTypeWidget: return consts.SourceTypeWidget case AppTypeDingTalkBot: return consts.SourceTypeDingtalkBot case AppTypeFeishuBot: return consts.SourceTypeFeishuBot case AppTypeWechatBot: return consts.SourceTypeWechatBot case AppTypeWecomAIBot: return consts.SourceTypeWecomAIBot case AppTypeWechatServiceBot: return consts.SourceTypeWechatServiceBot case AppTypeDisCordBot: return consts.SourceTypeDiscordBot case AppTypeWechatOfficialAccount: return consts.SourceTypeWechatOfficialAccount case AppTypeOpenAIAPI: return consts.SourceTypeOpenAIAPI case AppTypeLarkBot: return consts.SourceTypeLarkBot default: return "" } } type App struct { ID string `json:"id" gorm:"primaryKey"` KBID string `json:"kb_id"` Name string `json:"name"` Type AppType `json:"type"` Settings AppSettings `json:"settings" gorm:"type:jsonb"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } type AppSettings struct { // nav Title string `json:"title,omitempty"` Icon string `json:"icon,omitempty"` Btns []any `json:"btns,omitempty"` // welcome WelcomeStr string `json:"welcome_str,omitempty"` SearchPlaceholder string `json:"search_placeholder,omitempty"` RecommendQuestions []string `json:"recommend_questions,omitempty"` RecommendNodeIDs []string `json:"recommend_node_ids,omitempty"` // seo Desc string `json:"desc,omitempty"` Keyword string `json:"keyword,omitempty"` // inject code HeadCode string `json:"head_code,omitempty"` BodyCode string `json:"body_code,omitempty"` // DingTalkBot DingTalkBotIsEnabled *bool `json:"dingtalk_bot_is_enabled,omitempty"` DingTalkBotClientID string `json:"dingtalk_bot_client_id,omitempty"` DingTalkBotClientSecret string `json:"dingtalk_bot_client_secret,omitempty"` DingTalkBotTemplateID string `json:"dingtalk_bot_template_id,omitempty"` // FeishuBot FeishuBotIsEnabled *bool `json:"feishu_bot_is_enabled,omitempty"` FeishuBotAppID string `json:"feishu_bot_app_id,omitempty"` FeishuBotAppSecret string `json:"feishu_bot_app_secret,omitempty"` // LarkBot LarkBotSettings LarkBotSettings `json:"lark_bot_settings,omitempty"` // WechatAppBot 企业微信机器人 WeChatAppIsEnabled *bool `json:"wechat_app_is_enabled,omitempty"` WeChatAppToken string `json:"wechat_app_token,omitempty"` WeChatAppEncodingAESKey string `json:"wechat_app_encodingaeskey,omitempty"` WeChatAppCorpID string `json:"wechat_app_corpid,omitempty"` WeChatAppSecret string `json:"wechat_app_secret,omitempty"` WeChatAppAgentID string `json:"wechat_app_agent_id,omitempty"` WeChatAppAdvancedSetting WeChatAppAdvancedSetting `json:"wechat_app_advanced_setting"` // WecomAIBotSettings 企业微信智能机器人 WecomAIBotSettings WecomAIBotSettings `json:"wecom_ai_bot_settings"` // WechatServiceBot WeChatServiceIsEnabled *bool `json:"wechat_service_is_enabled,omitempty"` WeChatServiceToken string `json:"wechat_service_token,omitempty"` WeChatServiceEncodingAESKey string `json:"wechat_service_encodingaeskey,omitempty"` WeChatServiceCorpID string `json:"wechat_service_corpid,omitempty"` WeChatServiceSecret string `json:"wechat_service_secret,omitempty"` WechatServiceLogo string `json:"wechat_service_logo,omitempty"` WechatServiceContainKeywords []string `json:"wechat_service_contain_keywords"` WechatServiceEqualKeywords []string `json:"wechat_service_equal_keywords"` // DisCordBot DiscordBotIsEnabled *bool `json:"discord_bot_is_enabled,omitempty"` DiscordBotToken string `json:"discord_bot_token,omitempty"` // WechatOfficialAccount WechatOfficialAccountIsEnabled *bool `json:"wechat_official_account_is_enabled,omitempty"` WechatOfficialAccountAppID string `json:"wechat_official_account_app_id,omitempty"` WechatOfficialAccountAppSecret string `json:"wechat_official_account_app_secret,omitempty"` WechatOfficialAccountToken string `json:"wechat_official_account_token,omitempty"` WechatOfficialAccountEncodingAESKey string `json:"wechat_official_account_encodingaeskey,omitempty"` // theme ThemeMode string `json:"theme_mode,omitempty"` ThemeAndStyle ThemeAndStyle `json:"theme_and_style"` // catalog settings CatalogSettings CatalogSettings `json:"catalog_settings"` // footer settings FooterSettings FooterSettings `json:"footer_settings"` // Widget bot settings WidgetBotSettings WidgetBotSettings `json:"widget_bot_settings"` // webapp comment settings WebAppCommentSettings WebAppCommentSettings `json:"web_app_comment_settings"` // document feedback DocumentFeedBackIsEnabled *bool `json:"document_feedback_is_enabled,omitempty"` // AI feedback AIFeedbackSettings AIFeedbackSettings `json:"ai_feedback_settings"` // WebAppCustomStyle WebAppCustomSettings WebAppCustomSettings `json:"web_app_custom_style"` // OpenAI API Bot settings OpenAIAPIBotSettings OpenAIAPIBotSettings `json:"openai_api_bot_settings"` // Disclaimer Settings DisclaimerSettings DisclaimerSettings `json:"disclaimer_settings"` // WebAppLandingConfigs WebAppLandingConfigs []WebAppLandingConfig `json:"web_app_landing_configs,omitempty"` WebAppLandingTheme WebAppLandingTheme `json:"web_app_landing_theme"` WatermarkContent string `json:"watermark_content"` WatermarkSetting consts.WatermarkSetting `json:"watermark_setting" validate:"omitempty,oneof='' hidden visible"` CopySetting consts.CopySetting `json:"copy_setting" validate:"omitempty,oneof='' append disabled"` ContributeSettings ContributeSettings `json:"contribute_settings"` HomePageSetting consts.HomePageSetting `json:"home_page_setting"` ConversationSetting ConversationSetting `json:"conversation_setting"` // MCP Server Settings MCPServerSettings MCPServerSettings `json:"mcp_server_settings,omitempty"` StatsSetting StatsSetting `json:"stats_setting"` } type WeChatAppAdvancedSetting struct { TextResponseEnable bool `json:"text_response_enable,omitempty"` FeedbackEnable bool `json:"feedback_enable,omitempty"` FeedbackType []string `json:"feedback_type,omitempty"` DisclaimerContent string `json:"disclaimer_content,omitempty"` Prompt string `json:"prompt,omitempty"` } type StatsSetting struct { PVEnable bool `json:"pv_enable"` } type ConversationSetting struct { CopyrightInfo string `json:"copyright_info"` CopyrightHideEnabled bool `json:"copyright_hide_enabled"` } type WebAppLandingTheme struct { Name string `json:"name"` } type MCPServerSettings struct { IsEnabled bool `json:"is_enabled"` DocsToolSettings MCPToolSettings `json:"docs_tool_settings"` SampleAuth SimpleAuth `json:"sample_auth"` } type MCPToolSettings struct { Name string `json:"name"` Desc string `json:"desc"` } type LarkBotSettings struct { IsEnabled *bool `json:"is_enabled"` AppID string `json:"app_id"` AppSecret string `json:"app_secret"` VerifyToken string `json:"verify_token"` EncryptKey string `json:"encrypt_key"` } type BannerConfig struct { Title string `json:"title"` TitleColor string `json:"title_color"` TitleFontSize int `json:"title_font_size"` Subtitle string `json:"subtitle"` Placeholder string `json:"placeholder"` SubtitleColor string `json:"subtitle_color"` SubtitleFontSize int `json:"subtitle_font_size"` BgURL string `json:"bg_url"` HotSearch []string `json:"hot_search"` Btns []struct { ID string `json:"id"` Text string `json:"text"` Type string `json:"type"` Href string `json:"href"` } `json:"btns"` } type BasicDocConfig struct { Title string `json:"title"` TitleColor string `json:"title_color"` BgColor string `json:"bg_color"` } type DirDocConfig struct { Title string `json:"title"` TitleColor string `json:"title_color"` BgColor string `json:"bg_color"` } type NavDocConfig struct { NavIds []string `json:"nav_ids"` Title string `json:"title"` } type SimpleDocConfig struct { Title string `json:"title"` TitleColor string `json:"title_color"` BgColor string `json:"bg_color"` } type CarouselConfig struct { Title string `json:"title"` BgColor string `json:"bg_color"` List []struct { ID string `json:"id"` Title string `json:"title"` URL string `json:"url"` Desc string `json:"desc"` } `json:"list"` } type FaqConfig struct { Title string `json:"title"` TitleColor string `json:"title_color"` BgColor string `json:"bg_color"` List []struct { ID string `json:"id"` Question string `json:"question"` Link string `json:"link"` } `json:"list"` } type TextConfig struct { Type string `json:"type"` Title string `json:"title"` } type MetricsConfig struct { Type string `json:"type"` Title string `json:"title"` List []struct { ID string `json:"id"` Name string `json:"name"` Number string `json:"number"` } `json:"list"` } type CaseConfig struct { Type string `json:"type"` Title string `json:"title"` List []struct { ID string `json:"id"` Name string `json:"name"` Link string `json:"link"` } `json:"list"` } type CommentConfig struct { Type string `json:"type"` Title string `json:"title"` List []struct { ID string `json:"id"` Avatar string `json:"avatar"` UserName string `json:"user_name"` Profession string `json:"profession"` Comment string `json:"comment"` } `json:"list"` } type FeatureConfig struct { Type string `json:"type"` Title string `json:"title"` List []struct { ID string `json:"id"` Name string `json:"name"` Desc string `json:"desc"` } `json:"list"` } type ImgTextConfig struct { Type string `json:"type"` Title string `json:"title"` Item struct { URL string `json:"url"` Name string `json:"name"` Desc string `json:"desc"` } `json:"item"` } type TextImgConfig struct { Type string `json:"type"` Title string `json:"title"` Item struct { URL string `json:"url"` Name string `json:"name"` Desc string `json:"desc"` } `json:"item"` } type QuestionConfig struct { Type string `json:"type"` Title string `json:"title"` List []struct { ID string `json:"id"` Question string `json:"question"` } `json:"list"` } type BlockGridConfig struct { Type string `json:"type"` Title string `json:"title"` List []struct { ID string `json:"id"` Name string `json:"name"` URL string `json:"url"` } `json:"list"` } type WebAppLandingConfig struct { Type string `json:"type"` NodeIds []string `json:"node_ids"` BannerConfig *BannerConfig `json:"banner_config,omitempty"` BasicDocConfig *BasicDocConfig `json:"basic_doc_config,omitempty"` DirDocConfig *DirDocConfig `json:"dir_doc_config,omitempty"` NavDocConfig *NavDocConfig `json:"nav_doc_config,omitempty"` SimpleDocConfig *SimpleDocConfig `json:"simple_doc_config,omitempty"` CarouselConfig *CarouselConfig `json:"carousel_config,omitempty"` FaqConfig *FaqConfig `json:"faq_config,omitempty"` MetricsConfig *MetricsConfig `json:"metrics_config,omitempty"` CaseConfig *CaseConfig `json:"case_config,omitempty"` TextConfig *TextConfig `json:"text_config,omitempty"` CommentConfig *CommentConfig `json:"comment_config,omitempty"` FeatureConfig *FeatureConfig `json:"feature_config,omitempty"` ImgTextConfig *ImgTextConfig `json:"img_text_config,omitempty"` TextImgConfig *TextImgConfig `json:"text_img_config,omitempty"` QuestionConfig *QuestionConfig `json:"question_config,omitempty"` BlockGridConfig *BlockGridConfig `json:"block_grid_config,omitempty"` ComConfigOrder []string `json:"com_config_order"` } type WecomAIBotSettings struct { IsEnabled bool `json:"is_enabled,omitempty"` Token string `json:"token,omitempty"` EncodingAESKey string `json:"encodingaeskey,omitempty"` } type DisclaimerSettings struct { Content *string `json:"content"` } type ContributeSettings struct { IsEnable bool `json:"is_enable"` } type OpenAIAPIBotSettings struct { IsEnabled bool `json:"is_enabled"` SecretKey string `json:"secret_key"` } type WebAppCustomSettings struct { AllowThemeSwitching *bool `json:"allow_theme_switching"` HeaderPlaceholder string `json:"header_search_placeholder"` SocialMediaAccounts []SocialMediaAccount `json:"social_media_accounts"` ShowBrandInfo *bool `json:"show_brand_info"` FooterShowIntro *bool `json:"footer_show_intro"` } type SocialMediaAccount struct { Channel string `json:"channel"` Text string `json:"text"` Link string `json:"link"` Icon string `json:"icon"` Phone string `json:"phone"` } type WebAppCommentSettings struct { IsEnable bool `json:"is_enable"` ModerationEnable bool `json:"moderation_enable"` } type AIFeedbackSettings struct { AIFeedbackIsEnabled *bool `json:"is_enabled"` AIFeedbackType []string `json:"ai_feedback_type"` } type ThemeAndStyle struct { BGImage string `json:"bg_image,omitempty"` DocWidth string `json:"doc_width,omitempty"` } type CatalogSettings struct { CatalogFolder int `json:"catalog_folder,omitempty"` // 1: 展开, 2: 折叠, default: 1 CatalogWidth int `json:"catalog_width,omitempty"` // 200 - 300, default: 260 CatalogVisible int `json:"catalog_visible,omitempty"` // 1: 显示, 2: 隐藏, default: 1 } type FooterSettings struct { FooterStyle string `json:"footer_style,omitempty"` CorpName string `json:"corp_name,omitempty"` ICP string `json:"icp,omitempty"` BrandName string `json:"brand_name,omitempty"` BrandDesc string `json:"brand_desc,omitempty"` BrandLogo string `json:"brand_logo,omitempty"` BrandGroups []BrandGroup `json:"brand_groups,omitempty"` } type WidgetBotSettings struct { IsOpen bool `json:"is_open,omitempty"` ThemeMode string `json:"theme_mode,omitempty"` BtnText string `json:"btn_text,omitempty"` BtnLogo string `json:"btn_logo,omitempty"` RecommendQuestions []string `json:"recommend_questions,omitempty"` RecommendNodeIDs []string `json:"recommend_node_ids,omitempty"` BtnStyle string `json:"btn_style,omitempty"` BtnID string `json:"btn_id,omitempty"` BtnPosition string `json:"btn_position,omitempty"` ModalPosition string `json:"modal_position,omitempty"` SearchMode string `json:"search_mode,omitempty"` Placeholder string `json:"placeholder,omitempty"` Disclaimer string `json:"disclaimer,omitempty"` CopyrightInfo string `json:"copyright_info,omitempty"` CopyrightHideEnabled bool `json:"copyright_hide_enabled,omitempty"` } type BrandGroup struct { Name string `json:"name,omitempty"` Links []Link `json:"links,omitempty"` } type Link struct { Name string `json:"name,omitempty"` URL string `json:"url,omitempty"` } func (s *AppSettings) Scan(value any) error { bytes, ok := value.([]byte) if !ok { return errors.New(fmt.Sprint("invalid app settings value type:", value)) } return json.Unmarshal(bytes, s) } func (s AppSettings) Value() (driver.Value, error) { return json.Marshal(s) } type AppDetailResp struct { ID string `json:"id" gorm:"primaryKey"` KBID string `json:"kb_id"` Name string `json:"name"` Type AppType `json:"type"` Settings AppSettingsResp `json:"settings" gorm:"type:jsonb"` RecommendNodes []*RecommendNodeListResp `json:"recommend_nodes,omitempty" gorm:"-"` } type AppSettingsResp struct { // nav Title string `json:"title,omitempty"` Icon string `json:"icon,omitempty"` Btns []any `json:"btns,omitempty"` // welcome WelcomeStr string `json:"welcome_str,omitempty"` SearchPlaceholder string `json:"search_placeholder,omitempty"` RecommendQuestions []string `json:"recommend_questions,omitempty"` RecommendNodeIDs []string `json:"recommend_node_ids,omitempty"` // seo Desc string `json:"desc,omitempty"` Keyword string `json:"keyword,omitempty"` // inject code HeadCode string `json:"head_code,omitempty"` BodyCode string `json:"body_code,omitempty"` // DingTalkBot DingTalkBotIsEnabled *bool `json:"dingtalk_bot_is_enabled,omitempty"` DingTalkBotClientID string `json:"dingtalk_bot_client_id,omitempty"` DingTalkBotClientSecret string `json:"dingtalk_bot_client_secret,omitempty"` DingTalkBotTemplateID string `json:"dingtalk_bot_template_id,omitempty"` // FeishuBot FeishuBotIsEnabled *bool `json:"feishu_bot_is_enabled,omitempty"` FeishuBotAppID string `json:"feishu_bot_app_id,omitempty"` FeishuBotAppSecret string `json:"feishu_bot_app_secret,omitempty"` // LarkBot LarkBotSettings LarkBotSettings `json:"lark_bot_settings,omitempty"` // WechatAppBot WeChatAppIsEnabled *bool `json:"wechat_app_is_enabled,omitempty"` WeChatAppToken string `json:"wechat_app_token,omitempty"` WeChatAppEncodingAESKey string `json:"wechat_app_encodingaeskey,omitempty"` WeChatAppCorpID string `json:"wechat_app_corpid,omitempty"` WeChatAppSecret string `json:"wechat_app_secret,omitempty"` WeChatAppAgentID string `json:"wechat_app_agent_id,omitempty"` WeChatAppAdvancedSetting WeChatAppAdvancedSetting `json:"wechat_app_advanced_setting"` // WechatServiceBot WeChatServiceIsEnabled *bool `json:"wechat_service_is_enabled,omitempty"` WeChatServiceToken string `json:"wechat_service_token,omitempty"` WeChatServiceEncodingAESKey string `json:"wechat_service_encodingaeskey,omitempty"` WeChatServiceCorpID string `json:"wechat_service_corpid,omitempty"` WeChatServiceSecret string `json:"wechat_service_secret,omitempty"` WechatServiceLogo string `json:"wechat_service_logo,omitempty"` WechatServiceContainKeywords []string `json:"wechat_service_contain_keywords"` WechatServiceEqualKeywords []string `json:"wechat_service_equal_keywords"` // DisCordBot DiscordBotIsEnabled *bool `json:"discord_bot_is_enabled,omitempty"` DiscordBotToken string `json:"discord_bot_token,omitempty"` // WechatOfficialAccount WechatOfficialAccountIsEnabled *bool `json:"wechat_official_account_is_enabled,omitempty"` WechatOfficialAccountAppID string `json:"wechat_official_account_app_id,omitempty"` WechatOfficialAccountAppSecret string `json:"wechat_official_account_app_secret,omitempty"` WechatOfficialAccountToken string `json:"wechat_official_account_token,omitempty"` WechatOfficialAccountEncodingAESKey string `json:"wechat_official_account_encodingaeskey,omitempty"` WecomAIBotSettings WecomAIBotSettings `json:"wecom_ai_bot_settings"` // theme ThemeMode string `json:"theme_mode,omitempty"` ThemeAndStyle ThemeAndStyle `json:"theme_and_style"` // catalog settings CatalogSettings CatalogSettings `json:"catalog_settings"` // footer settings FooterSettings FooterSettings `json:"footer_settings"` // WidgetBot WidgetBotSettings WidgetBotSettings `json:"widget_bot_settings"` // webapp comment settings WebAppCommentSettings WebAppCommentSettings `json:"web_app_comment_settings"` // document feedback DocumentFeedBackIsEnabled *bool `json:"document_feedback_is_enabled,omitempty"` // AI feedback AIFeedbackSettings AIFeedbackSettings `json:"ai_feedback_settings"` // WebAppCustomStyle WebAppCustomSettings WebAppCustomSettings `json:"web_app_custom_style"` WatermarkContent string `json:"watermark_content"` WatermarkSetting consts.WatermarkSetting `json:"watermark_setting"` CopySetting consts.CopySetting `json:"copy_setting"` ContributeSettings ContributeSettings `json:"contribute_settings"` // OpenAI API settings OpenAIAPIBotSettings OpenAIAPIBotSettings `json:"openai_api_bot_settings"` // Disclaimer Settings DisclaimerSettings DisclaimerSettings `json:"disclaimer_settings"` // WebApp Landing Settings WebAppLandingConfigs []WebAppLandingConfigResp `json:"web_app_landing_configs,omitempty"` WebAppLandingTheme WebAppLandingTheme `json:"web_app_landing_theme"` HomePageSetting consts.HomePageSetting `json:"home_page_setting"` ConversationSetting ConversationSetting `json:"conversation_setting"` // MCP Server Settings MCPServerSettings MCPServerSettings `json:"mcp_server_settings,omitempty"` StatsSetting StatsSetting `json:"stats_setting"` } type WebAppLandingConfigResp struct { Type string `json:"type"` BannerConfig *BannerConfig `json:"banner_config,omitempty"` BasicDocConfig *BasicDocConfig `json:"basic_doc_config,omitempty"` DirDocConfig *DirDocConfig `json:"dir_doc_config,omitempty"` NavDocConfig *NavDocConfig `json:"nav_doc_config,omitempty"` SimpleDocConfig *SimpleDocConfig `json:"simple_doc_config,omitempty"` CarouselConfig *CarouselConfig `json:"carousel_config,omitempty"` FaqConfig *FaqConfig `json:"faq_config,omitempty"` MetricsConfig *MetricsConfig `json:"metrics_config,omitempty"` CaseConfig *CaseConfig `json:"case_config,omitempty"` TextConfig *TextConfig `json:"text_config,omitempty"` CommentConfig *CommentConfig `json:"comment_config,omitempty"` FeatureConfig *FeatureConfig `json:"feature_config,omitempty"` ImgTextConfig *ImgTextConfig `json:"img_text_config,omitempty"` TextImgConfig *TextImgConfig `json:"text_img_config,omitempty"` QuestionConfig *QuestionConfig `json:"question_config,omitempty"` BlockGridConfig *BlockGridConfig `json:"block_grid_config,omitempty"` ComConfigOrder []string `json:"com_config_order"` NodeIds []string `json:"node_ids"` Nodes []*RecommendNodeListResp `json:"nodes" gorm:"-"` } func (s *AppSettingsResp) Scan(value any) error { bytes, ok := value.([]byte) if !ok { return errors.New(fmt.Sprint("invalid app settings value type:", value)) } return json.Unmarshal(bytes, s) } func (s AppSettingsResp) Value() (driver.Value, error) { return json.Marshal(s) } type UpdateAppReq struct { Name *string `json:"name"` KbID string `json:"kb_id"` Settings *AppSettings `json:"settings" gorm:"type:jsonb"` } type CreateAppReq struct { Name string `json:"name"` Type AppType `json:"type" validate:"required,oneof=1 2 3 4 5 6 7 8"` Icon string `json:"icon"` KBID string `json:"kb_id" validate:"required"` } type AppInfoResp struct { Name string `json:"name"` Settings AppSettingsResp `json:"settings" gorm:"type:jsonb"` BaseUrl string `json:"base_url"` RecommendNodes []*RecommendNodeListResp `json:"recommend_nodes,omitempty" gorm:"-"` }