mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-03 18:22:57 +00:00
dev day #80
This commit is contained in:
@@ -15,6 +15,29 @@ import (
|
||||
|
||||
type CommentController struct{ DB *gorm.DB }
|
||||
|
||||
// Admin: list active bans
|
||||
// GET /api/v1/admin/comments/bans
|
||||
func (cc *CommentController) AdminListBans(c *gin.Context) {
|
||||
var bans []models.CommentBan
|
||||
// Active = until is NULL (permanent) OR until > now
|
||||
now := time.Now()
|
||||
if err := cc.DB.Where("until IS NULL OR until > ?", now).Order("created_at DESC").Find(&bans).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error":"Failed to load bans"}); return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"items": bans})
|
||||
}
|
||||
|
||||
// Admin: lift a ban early by setting until = now
|
||||
// POST /api/v1/admin/comments/bans/:id/lift
|
||||
func (cc *CommentController) AdminLiftBan(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
now := time.Now()
|
||||
if err := cc.DB.Model(&models.CommentBan{}).Where("id = ?", id).Update("until", now).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error":"Failed to lift ban"}); return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"ok": true})
|
||||
}
|
||||
|
||||
// ReportComment allows a user to report a comment with an optional reason
|
||||
func (cc *CommentController) ReportComment(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
@@ -59,6 +82,9 @@ func (cc *CommentController) React(c *gin.Context) {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to react"})
|
||||
return
|
||||
}
|
||||
// Award a small amount of points for reactions (capped per day in service)
|
||||
svc := services.NewEngagementService(cc.DB)
|
||||
_, _ = svc.AwardPointsCapped(uid.(uint), 1, "comment_reacted", map[string]interface{}{"comment_id": cm.ID})
|
||||
c.JSON(http.StatusOK, gin.H{"ok": true})
|
||||
}
|
||||
|
||||
@@ -196,8 +222,8 @@ type userSlim struct {
|
||||
ID uint `json:"id"`
|
||||
FirstName string `json:"first_name"`
|
||||
LastName string `json:"last_name"`
|
||||
Email string `json:"email"`
|
||||
Role string `json:"role"`
|
||||
Username string `json:"username,omitempty"`
|
||||
AvatarURL string `json:"avatar_url,omitempty"`
|
||||
}
|
||||
|
||||
@@ -217,7 +243,6 @@ func toOutput(c models.Comment) commentOutput {
|
||||
ID: c.User.ID,
|
||||
FirstName: c.User.FirstName,
|
||||
LastName: c.User.LastName,
|
||||
Email: c.User.Email,
|
||||
Role: c.User.Role,
|
||||
},
|
||||
SpamScore: c.SpamScore,
|
||||
@@ -291,25 +316,24 @@ func (cc *CommentController) GetComments(c *gin.Context) {
|
||||
for _, r := range rs { myReactions[r.CommentID] = r.Type }
|
||||
}
|
||||
}
|
||||
// Preload user profiles for avatar (prefer animated when available)
|
||||
avatarByUser := map[uint]string{}
|
||||
// Preload user profiles for username + avatar (prefer animated when available)
|
||||
type up struct{ UserID uint; AvatarURL string; AnimatedAvatarURL string; Username string }
|
||||
profByUser := map[uint]up{}
|
||||
if len(userIDs) > 0 {
|
||||
type up struct{ UserID uint; AvatarURL string; AnimatedAvatarURL string }
|
||||
var profs []up
|
||||
_ = cc.DB.Table("user_profiles").Select("user_id, avatar_url, animated_avatar_url").Where("user_id IN ?", userIDs).Scan(&profs).Error
|
||||
_ = cc.DB.Table("user_profiles").Select("user_id, avatar_url, animated_avatar_url, username").Where("user_id IN ?", userIDs).Scan(&profs).Error
|
||||
for _, p := range profs {
|
||||
if strings.TrimSpace(p.AnimatedAvatarURL) != "" {
|
||||
avatarByUser[p.UserID] = p.AnimatedAvatarURL
|
||||
} else {
|
||||
avatarByUser[p.UserID] = p.AvatarURL
|
||||
}
|
||||
profByUser[p.UserID] = p
|
||||
}
|
||||
}
|
||||
|
||||
for _, r := range rows {
|
||||
co := toOutput(r)
|
||||
if co.User.ID != 0 {
|
||||
if av, ok := avatarByUser[co.User.ID]; ok { co.User.AvatarURL = av }
|
||||
if p, ok := profByUser[co.User.ID]; ok {
|
||||
if strings.TrimSpace(p.Username) != "" { co.User.Username = p.Username }
|
||||
if strings.TrimSpace(p.AnimatedAvatarURL) != "" { co.User.AvatarURL = p.AnimatedAvatarURL } else { co.User.AvatarURL = p.AvatarURL }
|
||||
}
|
||||
}
|
||||
if rc, ok := reactionCounts[r.ID]; ok { co.Reactions = rc } else { co.Reactions = map[string]int{} }
|
||||
if myReactions != nil { if t, ok := myReactions[r.ID]; ok { co.MyReaction = t } }
|
||||
@@ -395,10 +419,10 @@ func (cc *CommentController) CreateComment(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// Award engagement points for visible comment
|
||||
// Award engagement points for visible comment (capped per day)
|
||||
if status == "visible" {
|
||||
svc := services.NewEngagementService(cc.DB)
|
||||
_, _ = svc.AwardPoints(userID, 5, "comment_create", map[string]interface{}{"comment_id": cm.ID})
|
||||
_, _ = svc.AwardPointsCapped(userID, 5, "comment_create", map[string]interface{}{"comment_id": cm.ID})
|
||||
_ = svc.CheckAndAwardAchievements(userID)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user