writekit/internal/tenant/reactions.go
2026-01-09 00:16:46 +02:00

159 lines
4.2 KiB
Go

package tenant
import (
"context"
"database/sql"
)
func (q *Queries) ListReactions(ctx context.Context, postSlug string) ([]Reaction, error) {
rows, err := q.db.QueryContext(ctx, `SELECT id, user_id, anon_id, post_slug, emoji, created_at
FROM reactions WHERE post_slug = ?`, postSlug)
if err != nil {
return nil, err
}
defer rows.Close()
var reactions []Reaction
for rows.Next() {
r, err := scanReaction(rows)
if err != nil {
return nil, err
}
reactions = append(reactions, r)
}
return reactions, rows.Err()
}
func (q *Queries) GetReactionCounts(ctx context.Context, postSlug string) (map[string]int, error) {
rows, err := q.db.QueryContext(ctx, `SELECT emoji, COUNT(*) as count FROM reactions WHERE post_slug = ? GROUP BY emoji`, postSlug)
if err != nil {
return nil, err
}
defer rows.Close()
counts := make(map[string]int)
for rows.Next() {
var emoji string
var count int64
if err := rows.Scan(&emoji, &count); err != nil {
return nil, err
}
counts[emoji] = int(count)
}
return counts, rows.Err()
}
func (q *Queries) ToggleReaction(ctx context.Context, userID, anonID, postSlug, emoji string) (bool, error) {
var exists bool
if userID != "" {
var dummy int64
err := q.db.QueryRowContext(ctx, `SELECT 1 FROM reactions WHERE user_id = ? AND post_slug = ? AND emoji = ?`,
userID, postSlug, emoji).Scan(&dummy)
exists = err == nil
} else if anonID != "" {
var dummy int64
err := q.db.QueryRowContext(ctx, `SELECT 1 FROM reactions WHERE anon_id = ? AND post_slug = ? AND emoji = ?`,
anonID, postSlug, emoji).Scan(&dummy)
exists = err == nil
} else {
return false, nil
}
if !exists {
if userID != "" {
_, err := q.db.ExecContext(ctx, `INSERT INTO reactions (user_id, post_slug, emoji) VALUES (?, ?, ?)`,
userID, postSlug, emoji)
return true, err
}
_, err := q.db.ExecContext(ctx, `INSERT INTO reactions (anon_id, post_slug, emoji) VALUES (?, ?, ?)`,
anonID, postSlug, emoji)
return true, err
}
if userID != "" {
_, err := q.db.ExecContext(ctx, `DELETE FROM reactions WHERE user_id = ? AND post_slug = ? AND emoji = ?`,
userID, postSlug, emoji)
return false, err
}
_, err := q.db.ExecContext(ctx, `DELETE FROM reactions WHERE anon_id = ? AND post_slug = ? AND emoji = ?`,
anonID, postSlug, emoji)
return false, err
}
func (q *Queries) GetUserReactions(ctx context.Context, userID, postSlug string) ([]string, error) {
rows, err := q.db.QueryContext(ctx, `SELECT emoji FROM reactions WHERE user_id = ? AND post_slug = ?`, userID, postSlug)
if err != nil {
return nil, err
}
defer rows.Close()
var emojis []string
for rows.Next() {
var emoji string
if err := rows.Scan(&emoji); err != nil {
return nil, err
}
emojis = append(emojis, emoji)
}
return emojis, rows.Err()
}
func (q *Queries) GetAnonReactions(ctx context.Context, anonID, postSlug string) ([]string, error) {
rows, err := q.db.QueryContext(ctx, `SELECT emoji FROM reactions WHERE anon_id = ? AND post_slug = ?`, anonID, postSlug)
if err != nil {
return nil, err
}
defer rows.Close()
var emojis []string
for rows.Next() {
var emoji string
if err := rows.Scan(&emoji); err != nil {
return nil, err
}
emojis = append(emojis, emoji)
}
return emojis, rows.Err()
}
func (q *Queries) HasUserReacted(ctx context.Context, userID, postSlug string) (bool, error) {
var dummy int64
err := q.db.QueryRowContext(ctx, `SELECT 1 FROM reactions WHERE user_id = ? AND post_slug = ? LIMIT 1`,
userID, postSlug).Scan(&dummy)
if err == sql.ErrNoRows {
return false, nil
}
if err != nil {
return false, nil
}
return true, nil
}
func (q *Queries) HasAnonReacted(ctx context.Context, anonID, postSlug string) (bool, error) {
var dummy int64
err := q.db.QueryRowContext(ctx, `SELECT 1 FROM reactions WHERE anon_id = ? AND post_slug = ? LIMIT 1`,
anonID, postSlug).Scan(&dummy)
if err == sql.ErrNoRows {
return false, nil
}
if err != nil {
return false, nil
}
return true, nil
}
func scanReaction(s scanner) (Reaction, error) {
var r Reaction
var userID, anonID, createdAt sql.NullString
err := s.Scan(&r.ID, &userID, &anonID, &r.PostSlug, &r.Emoji, &createdAt)
if err != nil {
return r, err
}
r.UserID = userID.String
r.AnonID = anonID.String
r.CreatedAt = parseTime(createdAt.String)
return r, nil
}