package handler import ( "fmt" "io" "math/rand" "net/http" "regexp" "strings" "time" "caorushizi.cn/mediago/internal/api/dto" "caorushizi.cn/mediago/internal/i18n" "caorushizi.cn/mediago/internal/logger" "github.com/gin-gonic/gin" "go.uber.org/zap" ) // EnvPaths holds server environment paths exposed via the API. type EnvPaths struct { ConfigDir string `json:"configDir"` BinDir string `json:"binDir"` Platform string `json:"platform"` PlayerUrl string `json:"playerUrl,omitempty"` } // UtilHandler handles utility endpoints. type UtilHandler struct { env EnvPaths } // NewUtilHandler creates a UtilHandler. func NewUtilHandler(env EnvPaths) *UtilHandler { return &UtilHandler{env: env} } // GetEnvPaths returns server environment paths. // @Summary Get environment paths // @Tags Util // @Produce json // @Success 200 {object} dto.SuccessResponse // @Router /env [get] func (h *UtilHandler) GetEnvPaths(c *gin.Context) { env := h.env // Compute playerUrl dynamically from the request host scheme := "http" if c.Request.TLS != nil { scheme = "https" } env.PlayerUrl = fmt.Sprintf("%s://%s/player/", scheme, c.Request.Host) c.JSON(http.StatusOK, dto.SuccessResponse{ Success: true, Code: http.StatusOK, Message: i18n.T(c, i18n.MsgOK), Data: env, }) } var titleRegex = regexp.MustCompile(`(?i)]*>(.*?)`) // GetPageTitle fetches a URL and extracts the HTML tag. // @Summary Get page title // @Tags Util // @Produce json // @Param url query string true "URL to fetch" // @Success 200 {object} dto.SuccessResponse // @Router /url/title [get] func (h *UtilHandler) GetPageTitle(c *gin.Context) { url := c.Query("url") if url == "" { c.JSON(http.StatusBadRequest, dto.ErrorResponse{ Success: false, Code: http.StatusBadRequest, Message: i18n.T(c, i18n.MsgURLRequired), }) return } title := fetchTitle(url) c.JSON(http.StatusOK, dto.SuccessResponse{ Success: true, Code: http.StatusOK, Message: i18n.T(c, i18n.MsgOK), Data: map[string]string{"data": title}, }) } func fetchTitle(url string) string { client := &http.Client{Timeout: 10 * time.Second} req, err := http.NewRequest("GET", url, nil) if err != nil { logger.Warn("getPageTitle: failed to create request", zap.String("url", url), zap.Error(err)) return randomName() } req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36") req.Header.Set("Referer", url) resp, err := client.Do(req) if err != nil { logger.Warn("getPageTitle: request failed", zap.String("url", url), zap.Error(err)) return randomName() } defer resp.Body.Close() // Read up to 64KB to find the title body, err := io.ReadAll(io.LimitReader(resp.Body, 64*1024)) if err != nil { logger.Warn("getPageTitle: failed to read body", zap.String("url", url), zap.Error(err)) return randomName() } matches := titleRegex.FindSubmatch(body) if len(matches) >= 2 { title := strings.TrimSpace(string(matches[1])) if title != "" { return title } } return randomName() } func randomName() string { return fmt.Sprintf("download_%d", rand.Int63()) }