| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 | package sitesimport (	"context"	"net/http"	"time"	"github.com/0xJacky/Nginx-UI/internal/sitecheck"	"github.com/0xJacky/Nginx-UI/model"	"github.com/0xJacky/Nginx-UI/query"	"github.com/gin-gonic/gin"	"github.com/spf13/cast"	"github.com/uozi-tech/cosy"	"github.com/uozi-tech/cosy/logger")// GetSiteNavigation returns all sites for navigation dashboardfunc GetSiteNavigation(c *gin.Context) {	service := sitecheck.GetService()	sites := service.GetSites()	c.JSON(http.StatusOK, gin.H{		"data": sites,	})}// GetSiteNavigationStatus returns the status of site checking servicefunc GetSiteNavigationStatus(c *gin.Context) {	service := sitecheck.GetService()	c.JSON(http.StatusOK, gin.H{		"running": service.IsRunning(),	})}// UpdateSiteOrder updates the custom order of sitesfunc UpdateSiteOrder(c *gin.Context) {	var req struct {		OrderedIds []uint64 `json:"ordered_ids" binding:"required"`	}	if !cosy.BindAndValid(c, &req) {		return	}	if err := updateSiteOrderBatchByIds(req.OrderedIds); err != nil {		cosy.ErrHandler(c, err)		return	}	c.JSON(http.StatusOK, gin.H{		"message": "Order updated successfully",	})}// updateSiteOrderBatchByIds updates site order in batch using IDsfunc updateSiteOrderBatchByIds(orderedIds []uint64) error {	sc := query.SiteConfig	for i, id := range orderedIds {		if _, err := sc.Where(sc.ID.Eq(id)).Update(sc.CustomOrder, i); err != nil {			return err		}	}	return nil}// GetHealthCheck gets health check configuration for a sitefunc GetHealthCheck(c *gin.Context) {	id := cast.ToUint64(c.Param("id"))	sc := query.SiteConfig	siteConfig, err := sc.Where(sc.ID.Eq(id)).First()	if err != nil {		cosy.ErrHandler(c, err)		return	}	ensureHealthCheckConfig(siteConfig)	c.JSON(http.StatusOK, siteConfig)}// createDefaultHealthCheckConfig creates default health check configurationfunc createDefaultHealthCheckConfig() *model.HealthCheckConfig {	return &model.HealthCheckConfig{		Protocol:       "http",		Method:         "GET",		Path:           "/",		ExpectedStatus: []int{200},		GRPCMethod:     "Check",	}}// ensureHealthCheckConfig ensures health check config is not nilfunc ensureHealthCheckConfig(siteConfig *model.SiteConfig) {	if siteConfig.HealthCheckConfig == nil {		siteConfig.HealthCheckConfig = createDefaultHealthCheckConfig()	}}// UpdateHealthCheck updates health check configuration for a sitefunc UpdateHealthCheck(c *gin.Context) {	id := cast.ToUint64(c.Param("id"))	var req model.SiteConfig	if !cosy.BindAndValid(c, &req) {		return	}	sc := query.SiteConfig	siteConfig, err := sc.Where(sc.ID.Eq(id)).First()	if err != nil {		cosy.ErrHandler(c, err)		return	}	siteConfig.HealthCheckEnabled = req.HealthCheckEnabled	siteConfig.CheckInterval = req.CheckInterval	siteConfig.Timeout = req.Timeout	siteConfig.UserAgent = req.UserAgent	siteConfig.MaxRedirects = req.MaxRedirects	siteConfig.FollowRedirects = req.FollowRedirects	siteConfig.CheckFavicon = req.CheckFavicon	if req.HealthCheckConfig != nil {		siteConfig.HealthCheckConfig = req.HealthCheckConfig	}	if err = query.SiteConfig.Save(siteConfig); err != nil {		cosy.ErrHandler(c, err)		return	}	c.JSON(http.StatusOK, gin.H{		"message": "Health check configuration updated successfully",	})}// TestHealthCheck tests a health check configuration without saving itfunc TestHealthCheck(c *gin.Context) {	id := cast.ToUint64(c.Param("id"))	var req struct {		Config *model.HealthCheckConfig `json:"config" binding:"required"`	}	if !cosy.BindAndValid(c, &req) {		return	}	// Get site config to determine the host for testing	sc := query.SiteConfig	siteConfig, err := sc.Where(sc.ID.Eq(id)).First()	if err != nil {		cosy.ErrHandler(c, err)		return	}	// Create enhanced checker and test the configuration	enhancedChecker := sitecheck.NewEnhancedSiteChecker()	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)	defer cancel()	// Convert host to URL for testing	testURL := siteConfig.Scheme + "://" + siteConfig.Host	result, err := enhancedChecker.CheckSiteWithConfig(ctx, testURL, req.Config)	if err != nil {		logger.Errorf("Health check test failed for %s: %v", siteConfig.Host, err)		c.JSON(http.StatusOK, gin.H{			"success":       false,			"error":         err.Error(),			"response_time": 0,		})		return	}	success := result.Status == "online"	errorMsg := ""	if !success && result.Error != "" {		errorMsg = result.Error	}	c.JSON(http.StatusOK, gin.H{		"success":       success,		"response_time": result.ResponseTime,		"status":        result.Status,		"status_code":   result.StatusCode,		"error":         errorMsg,	})}
 |