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
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.
159 lines
4.8 KiB
Go
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
|
|
}
|