package api import ( "fmt" "net/http" "strconv" "strings" "git.iioio.com/freefire/jiang13-forum/services" "github.com/gin-gonic/gin" ) // APIApplyFriendLink 提交友情链接申请 func (h *Handlers) APIApplyFriendLink(c *gin.Context) { uid := h.currentUserID(c) if uid == 0 { c.JSON(http.StatusUnauthorized, gin.H{"error": "请先登录"}) return } var req struct { Name string `json:"name"` URL string `json:"url"` Logo string `json:"logo"` LinkOnHomepage bool `json:"link_on_homepage"` ReciprocalPageURL string `json:"reciprocal_page_url"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "参数错误"}) return } result, err := h.FriendLinkApply.Create(services.FriendLinkApplyInput{ UserID: uid, Name: req.Name, URL: req.URL, Logo: req.Logo, LinkOnHomepage: req.LinkOnHomepage, ReciprocalPageURL: req.ReciprocalPageURL, OurSiteURL: h.publicBaseURL(c), }) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } resp := gin.H{ "message": friendLinkApplySubmittedMessage(h.Settings.FriendLinkReciprocalCheckEnabled(), false), "apply": result.Apply, } c.JSON(http.StatusOK, resp) } // APIUploadFriendLinkLogo 上传友链申请 LOGO func (h *Handlers) APIUploadFriendLinkLogo(c *gin.Context) { uid := h.currentUserID(c) if uid == 0 { c.JSON(http.StatusUnauthorized, gin.H{"error": "请先登录"}) return } file, err := c.FormFile("logo") if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "请选择 LOGO 图片"}) return } maxBytes := int64(h.Settings.AvatarMaxMB()) * 1024 * 1024 if file.Size > maxBytes { c.JSON(http.StatusBadRequest, gin.H{"error": "图片文件过大"}) return } url, err := services.SaveUploadedImage( h.Store, file, services.UploadCategorySite, fmt.Sprintf("fl_%d", uid), ) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"message": "LOGO 已上传", "url": url}) } // APIAdminFriendLinkApplies 管理员友链申请列表 func (h *Handlers) APIAdminFriendLinkApplies(c *gin.Context) { page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) size, _ := strconv.Atoi(c.DefaultQuery("size", "20")) status := strings.TrimSpace(c.DefaultQuery("status", "pending")) list, total, err := h.FriendLinkApply.ListAdmin(services.FriendLinkApplyListQuery{ Page: page, Size: size, Status: status, }) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } pending, _ := h.FriendLinkApply.PendingCount() c.JSON(http.StatusOK, gin.H{ "applies": list, "total": total, "page": page, "pending_count": pending, "reciprocal_check_enabled": h.Settings.FriendLinkReciprocalCheckEnabled(), }) } // APIAdminUpdateFriendLinkSettings 更新友链相关开关(回链检测 / 入口展示) func (h *Handlers) APIAdminUpdateFriendLinkSettings(c *gin.Context) { var req struct { ReciprocalCheckEnabled *bool `json:"reciprocal_check_enabled"` NavShowFriendLinks *bool `json:"nav_show_friend_links"` FooterShowFriendLinks *bool `json:"footer_show_friend_links"` AsideShowFriendLinks *bool `json:"aside_show_friend_links"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "参数错误"}) return } if req.ReciprocalCheckEnabled == nil && req.NavShowFriendLinks == nil && req.FooterShowFriendLinks == nil && req.AsideShowFriendLinks == nil { c.JSON(http.StatusBadRequest, gin.H{"error": "参数错误"}) return } if req.ReciprocalCheckEnabled != nil { if err := h.Settings.SetFriendLinkReciprocalCheckEnabled(*req.ReciprocalCheckEnabled); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } } if req.NavShowFriendLinks != nil { if err := h.Settings.SetNavShowFriendLinks(*req.NavShowFriendLinks); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } } if req.FooterShowFriendLinks != nil { if err := h.Settings.SetFooterShowFriendLinks(*req.FooterShowFriendLinks); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } } if req.AsideShowFriendLinks != nil { if err := h.Settings.SetAsideFriendLinksEnabled(*req.AsideShowFriendLinks); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } } msg := "设置已保存" if req.ReciprocalCheckEnabled != nil && req.NavShowFriendLinks == nil && req.FooterShowFriendLinks == nil && req.AsideShowFriendLinks == nil { if *req.ReciprocalCheckEnabled { msg = "已开启回链检测" } else { msg = "已关闭回链检测" } } c.JSON(http.StatusOK, gin.H{ "message": msg, "reciprocal_check_enabled": h.Settings.FriendLinkReciprocalCheckEnabled(), "nav_show_friend_links": h.Settings.NavShowFriendLinks(), "footer_show_friend_links": h.Settings.FooterShowFriendLinks(), "aside_show_friend_links": h.Settings.AsideShowFriendLinks(), }) } // APIAdminApproveFriendLinkApply 通过友链申请 func (h *Handlers) APIAdminApproveFriendLinkApply(c *gin.Context) { id, _ := strconv.ParseUint(c.Param("id"), 10, 64) apply, err := h.FriendLinkApply.Approve(uint(id)) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"message": "已通过并加入友情链接", "apply": apply}) } // APIAdminRejectFriendLinkApply 拒绝友链申请 func (h *Handlers) APIAdminRejectFriendLinkApply(c *gin.Context) { id, _ := strconv.ParseUint(c.Param("id"), 10, 64) var req struct { Note string `json:"note"` } _ = c.ShouldBindJSON(&req) apply, err := h.FriendLinkApply.Reject(uint(id), req.Note) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"message": "已拒绝申请", "apply": apply}) } // APIMyFriendLinkApplies 当前用户的友链申请列表 func (h *Handlers) APIMyFriendLinkApplies(c *gin.Context) { uid := h.currentUserID(c) if uid == 0 { c.JSON(http.StatusUnauthorized, gin.H{"error": "请先登录"}) return } list, err := h.FriendLinkApply.ListMine(uid) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"applies": list}) } // APICancelFriendLinkApply 撤销待审友链申请 func (h *Handlers) APICancelFriendLinkApply(c *gin.Context) { uid := h.currentUserID(c) if uid == 0 { c.JSON(http.StatusUnauthorized, gin.H{"error": "请先登录"}) return } id, _ := strconv.ParseUint(c.Param("id"), 10, 64) if err := h.FriendLinkApply.Cancel(uid, uint(id)); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"message": "已撤销申请"}) } // APIUpdateFriendLinkApply 修改并重新提交友链申请 func (h *Handlers) APIUpdateFriendLinkApply(c *gin.Context) { uid := h.currentUserID(c) if uid == 0 { c.JSON(http.StatusUnauthorized, gin.H{"error": "请先登录"}) return } id, _ := strconv.ParseUint(c.Param("id"), 10, 64) var req struct { Name string `json:"name"` URL string `json:"url"` Logo string `json:"logo"` LinkOnHomepage bool `json:"link_on_homepage"` ReciprocalPageURL string `json:"reciprocal_page_url"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "参数错误"}) return } result, err := h.FriendLinkApply.Update(uid, uint(id), services.FriendLinkApplyInput{ UserID: uid, Name: req.Name, URL: req.URL, Logo: req.Logo, LinkOnHomepage: req.LinkOnHomepage, ReciprocalPageURL: req.ReciprocalPageURL, OurSiteURL: h.publicBaseURL(c), }) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } resp := gin.H{ "message": friendLinkApplySubmittedMessage(h.Settings.FriendLinkReciprocalCheckEnabled(), true), "apply": result.Apply, } c.JSON(http.StatusOK, resp) } // APIAdminRecheckFriendLinkApply 管理员重新检测回链 func (h *Handlers) APIAdminRecheckFriendLinkApply(c *gin.Context) { id, _ := strconv.ParseUint(c.Param("id"), 10, 64) apply, err := h.FriendLinkApply.RecheckReciprocal(uint(id), h.publicBaseURL(c)) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"message": "已开始重新检测回链", "apply": apply}) } func friendLinkApplySubmittedMessage(checkEnabled, isUpdate bool) string { if isUpdate { if checkEnabled { return "申请已更新,回链检测将在后台进行" } return "申请已更新" } if checkEnabled { return "申请已提交,回链检测将在后台进行" } return "申请已提交" }