2
0
Files
logikonline 42e18e0fe1
All checks were successful
Build and Release / Create Release (push) Successful in 0s
Build and Release / Unit Tests (push) Successful in 3m17s
Build and Release / Integration Tests (PostgreSQL) (push) Successful in 4m49s
Build and Release / Lint (push) Successful in 4m57s
Build and Release / Build Binaries (amd64, linux, linux-latest) (push) Successful in 3m0s
Build and Release / Build Binaries (amd64, windows, windows-latest) (push) Successful in 9h4m54s
Build and Release / Build Binaries (amd64, darwin, macos) (push) Successful in 7m7s
Build and Release / Build Binaries (arm64, darwin, macos) (push) Successful in 7m59s
Build and Release / Build Binary (linux/arm64) (push) Successful in 8m35s
style(wishlist): fix linter warnings and formatting
Adds revive:disable-line comments for exported types without doc comments. Fixes column alignment in migration struct. Adds explanatory nolint comments for intentional nil returns. Sorts imports alphabetically.
2026-02-02 16:01:58 -05:00

159 lines
4.8 KiB
Go

// Copyright 2026 MarketAlly. All rights reserved.
// SPDX-License-Identifier: MIT
package wishlist
import (
"context"
"code.gitcaddy.com/server/v3/models/db"
"code.gitcaddy.com/server/v3/modules/timeutil"
)
// WishlistCommentReaction represents a thumbs up/down reaction on a wishlist comment.
type WishlistCommentReaction struct { //revive:disable-line:exported
ID int64 `xorm:"pk autoincr"`
CommentID int64 `xorm:"INDEX NOT NULL"`
UserID int64 `xorm:"INDEX NOT NULL"`
IsLike bool `xorm:"NOT NULL DEFAULT true"`
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
}
func init() {
db.RegisterModel(new(WishlistCommentReaction))
}
// CommentReactionCounts holds aggregated reaction counts.
type CommentReactionCounts struct {
Likes int64
Dislikes int64
}
// ToggleCommentReaction creates, updates, or removes a reaction.
func ToggleCommentReaction(ctx context.Context, commentID, userID int64, isLike bool) (reacted bool, err error) {
existing := &WishlistCommentReaction{}
has, err := db.GetEngine(ctx).Where("comment_id = ? AND user_id = ?", commentID, userID).Get(existing)
if err != nil {
return false, err
}
if has {
if existing.IsLike == isLike {
// Same type — toggle off
_, err = db.GetEngine(ctx).ID(existing.ID).Delete(new(WishlistCommentReaction))
return false, err
}
// Different type — switch
existing.IsLike = isLike
_, err = db.GetEngine(ctx).ID(existing.ID).Cols("is_like").Update(existing)
return true, err
}
_, err = db.GetEngine(ctx).Insert(&WishlistCommentReaction{
CommentID: commentID,
UserID: userID,
IsLike: isLike,
})
return true, err
}
// GetCommentReactionCounts returns aggregated counts for a comment.
func GetCommentReactionCounts(ctx context.Context, commentID int64) (*CommentReactionCounts, error) {
likes, err := db.GetEngine(ctx).Where("comment_id = ? AND is_like = ?", commentID, true).Count(new(WishlistCommentReaction))
if err != nil {
return nil, err
}
dislikes, err := db.GetEngine(ctx).Where("comment_id = ? AND is_like = ?", commentID, false).Count(new(WishlistCommentReaction))
if err != nil {
return nil, err
}
return &CommentReactionCounts{Likes: likes, Dislikes: dislikes}, nil
}
// GetCommentReactionCountsBatch returns reaction counts for multiple comments.
func GetCommentReactionCountsBatch(ctx context.Context, commentIDs []int64) (map[int64]*CommentReactionCounts, error) {
result := make(map[int64]*CommentReactionCounts, len(commentIDs))
for _, id := range commentIDs {
result[id] = &CommentReactionCounts{}
}
if len(commentIDs) == 0 {
return result, nil
}
type countRow struct {
CommentID int64 `xorm:"comment_id"`
IsLike bool `xorm:"is_like"`
Cnt int64 `xorm:"cnt"`
}
var rows []countRow
err := db.GetEngine(ctx).Table("wishlist_comment_reaction").
Select("comment_id, is_like, COUNT(*) AS cnt").
In("comment_id", commentIDs).
GroupBy("comment_id, is_like").
Find(&rows)
if err != nil {
return nil, err
}
for _, r := range rows {
counts, ok := result[r.CommentID]
if !ok {
counts = &CommentReactionCounts{}
result[r.CommentID] = counts
}
if r.IsLike {
counts.Likes = r.Cnt
} else {
counts.Dislikes = r.Cnt
}
}
return result, nil
}
// GetUserCommentReaction returns the user's reaction for a comment, or nil.
func GetUserCommentReaction(ctx context.Context, commentID, userID int64) (*WishlistCommentReaction, error) {
r := &WishlistCommentReaction{}
has, err := db.GetEngine(ctx).Where("comment_id = ? AND user_id = ?", commentID, userID).Get(r)
if err != nil {
return nil, err
}
if !has {
return nil, nil
}
return r, nil
}
// GetUserCommentReactionsBatch returns the user's reactions for multiple comments.
func GetUserCommentReactionsBatch(ctx context.Context, commentIDs []int64, userID int64) (map[int64]*WishlistCommentReaction, error) {
result := make(map[int64]*WishlistCommentReaction, len(commentIDs))
if len(commentIDs) == 0 || userID == 0 {
return result, nil
}
var reactions []*WishlistCommentReaction
err := db.GetEngine(ctx).
Where("user_id = ?", userID).
In("comment_id", commentIDs).
Find(&reactions)
if err != nil {
return nil, err
}
for _, r := range reactions {
result[r.CommentID] = r
}
return result, nil
}
// DeleteCommentReactionsByCommentID removes all reactions for a comment.
func DeleteCommentReactionsByCommentID(ctx context.Context, commentID int64) error {
_, err := db.GetEngine(ctx).Where("comment_id = ?", commentID).Delete(new(WishlistCommentReaction))
return err
}
// DeleteCommentReactionsByItemID removes all comment reactions for an item's comments.
func DeleteCommentReactionsByItemID(ctx context.Context, itemID int64) error {
_, err := db.GetEngine(ctx).
Where("comment_id IN (SELECT id FROM wishlist_comment WHERE item_id = ?)", itemID).
Delete(new(WishlistCommentReaction))
return err
}