From 91c39549bd6c4030d68c2bf45f7d652d5ffd7bca Mon Sep 17 00:00:00 2001 From: Keiran Date: Wed, 6 Aug 2025 06:31:09 +0100 Subject: [PATCH] add termail db functions --- internal/db/user.go | 121 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/internal/db/user.go b/internal/db/user.go index 33e09c1..b86136e 100644 --- a/internal/db/user.go +++ b/internal/db/user.go @@ -173,6 +173,127 @@ func GetUserByEmail(ctx context.Context, email string) (*User, error) { return &user, nil } +type Termail struct { + ID int `json:"id"` + SenderID int `json:"sender_id"` + ReceiverID int `json:"receiver_id"` + Subject string `json:"subject"` + Content string `json:"content"` + IsRead bool `json:"is_read"` + SentAt time.Time `json:"sent_at"` + Sender string `json:"sender,omitempty"` + Receiver string `json:"receiver,omitempty"` +} + +type SendTermailRequest struct { + ReceiverUsername string `json:"receiver_username"` + Subject string `json:"subject"` + Content string `json:"content"` +} + +func SendTermail(ctx context.Context, senderID int, req SendTermailRequest) (*Termail, error) { + receiver, err := GetUserByUsername(ctx, req.ReceiverUsername) + if err != nil { + return nil, fmt.Errorf("user not found: %s", req.ReceiverUsername) + } + + var termail Termail + err = Pool.QueryRow(ctx, + "INSERT INTO termails (sender_id, receiver_id, subject, content) VALUES ($1, $2, $3, $4) RETURNING id, sender_id, receiver_id, subject, content, is_read, sent_at", + senderID, receiver.ID, req.Subject, req.Content, + ).Scan(&termail.ID, &termail.SenderID, &termail.ReceiverID, &termail.Subject, &termail.Content, &termail.IsRead, &termail.SentAt) + + if err != nil { + return nil, err + } + + return &termail, nil +} + +func GetInbox(ctx context.Context, userID int, limit, offset int) ([]Termail, error) { + query := ` + SELECT t.id, t.sender_id, t.receiver_id, t.subject, t.content, t.is_read, t.sent_at, u.username as sender + FROM termails t + JOIN users u ON t.sender_id = u.id + WHERE t.receiver_id = $1 + ORDER BY t.sent_at DESC + LIMIT $2 OFFSET $3 + ` + + rows, err := Pool.Query(ctx, query, userID, limit, offset) + if err != nil { + return nil, err + } + defer rows.Close() + + var termails []Termail + for rows.Next() { + var t Termail + err := rows.Scan(&t.ID, &t.SenderID, &t.ReceiverID, &t.Subject, &t.Content, &t.IsRead, &t.SentAt, &t.Sender) + if err != nil { + return nil, err + } + termails = append(termails, t) + } + + return termails, nil +} + +func MarkTermailAsRead(ctx context.Context, termailID, userID int) error { + _, err := Pool.Exec(ctx, + "UPDATE termails SET is_read = true WHERE id = $1 AND receiver_id = $2", + termailID, userID, + ) + return err +} + +func DeleteTermail(ctx context.Context, termailID, userID int) error { + result, err := Pool.Exec(ctx, + "DELETE FROM termails WHERE id = $1 AND receiver_id = $2", + termailID, userID, + ) + if err != nil { + return err + } + + rowsAffected := result.RowsAffected() + if rowsAffected == 0 { + return fmt.Errorf("termail not found or access denied") + } + + return nil +} + +func SearchTermails(ctx context.Context, userID int, query string, limit, offset int) ([]Termail, error) { + sqlQuery := ` + SELECT t.id, t.sender_id, t.receiver_id, t.subject, t.content, t.is_read, t.sent_at, u.username as sender + FROM termails t + JOIN users u ON t.sender_id = u.id + WHERE t.receiver_id = $1 AND (t.subject ILIKE $2 OR t.content ILIKE $2 OR u.username ILIKE $2) + ORDER BY t.sent_at DESC + LIMIT $3 OFFSET $4 + ` + + searchPattern := "%" + query + "%" + rows, err := Pool.Query(ctx, sqlQuery, userID, searchPattern, limit, offset) + if err != nil { + return nil, err + } + defer rows.Close() + + var termails []Termail + for rows.Next() { + var t Termail + err := rows.Scan(&t.ID, &t.SenderID, &t.ReceiverID, &t.Subject, &t.Content, &t.IsRead, &t.SentAt, &t.Sender) + if err != nil { + return nil, err + } + termails = append(termails, t) + } + + return termails, nil +} + func CleanupUnverifiedUsers(ctx context.Context) error { _, err := Pool.Exec(ctx, ` DELETE FROM users