Compare commits

..

No commits in common. "227df20bf21e6b5d48ef44d820dda0d51b7bde75" and "b2c7dcae830a0c4b535df21f9296a3683ed55298" have entirely different histories.

4 changed files with 2 additions and 177 deletions

View File

@ -8,7 +8,6 @@ import (
"net/http"
"os"
"path/filepath"
"strconv"
"strings"
"syscall"
@ -55,52 +54,11 @@ var logoutCmd = &cobra.Command{
Run: runLogout,
}
var inboxCmd = &cobra.Command{
Use: "inbox",
Short: "View your termail inbox",
Long: "View, search, and manage your termail inbox.",
Run: runInbox,
}
var inboxReadCmd = &cobra.Command{
Use: "read [termail_id]",
Short: "Mark termail as read",
Long: "Mark a specific termail as read by ID.",
Args: cobra.ExactArgs(1),
Run: runInboxRead,
}
var inboxDeleteCmd = &cobra.Command{
Use: "delete [termail_id]",
Short: "Delete termail",
Long: "Delete a specific termail by ID.",
Args: cobra.ExactArgs(1),
Run: runInboxDelete,
}
var sendCmd = &cobra.Command{
Use: "send [username]",
Short: "Send termail to a user",
Long: "Send termail to a specific user by username.",
Args: cobra.ExactArgs(1),
Run: runSend,
}
func init() {
inboxCmd.Flags().StringP("search", "s", "", "Search termails by content, subject, or sender")
inboxCmd.Flags().IntP("limit", "l", 10, "Number of termails to show")
inboxCmd.Flags().IntP("offset", "o", 0, "Number of termails to skip")
inboxCmd.Flags().Bool("unread", false, "Show only unread termails")
inboxCmd.AddCommand(inboxReadCmd)
inboxCmd.AddCommand(inboxDeleteCmd)
authCmd.AddCommand(registerCmd)
authCmd.AddCommand(loginCmd)
authCmd.AddCommand(logoutCmd)
rootCmd.AddCommand(authCmd)
rootCmd.AddCommand(inboxCmd)
rootCmd.AddCommand(sendCmd)
}
func Execute() error {

View File

@ -72,19 +72,13 @@ func CreateTables() error {
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS termails (
CREATE TABLE IF NOT EXISTS messages (
id SERIAL PRIMARY KEY,
sender_id INT REFERENCES users(id),
receiver_id INT REFERENCES users(id),
subject VARCHAR(255) NOT NULL,
content TEXT NOT NULL,
is_read BOOLEAN DEFAULT FALSE,
sent_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_termails_receiver_id ON termails(receiver_id);
CREATE INDEX IF NOT EXISTS idx_termails_sender_id ON termails(sender_id);
CREATE INDEX IF NOT EXISTS idx_termails_sent_at ON termails(sent_at);
`)
return err

View File

@ -16,16 +16,10 @@ CREATE TABLE verification_codes (
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE termails (
CREATE TABLE messages (
id SERIAL PRIMARY KEY,
sender_id INT REFERENCES users(id),
receiver_id INT REFERENCES users(id),
subject VARCHAR(255) NOT NULL,
content TEXT NOT NULL,
is_read BOOLEAN DEFAULT FALSE,
sent_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_termails_receiver_id ON termails(receiver_id);
CREATE INDEX idx_termails_sender_id ON termails(sender_id);
CREATE INDEX idx_termails_sent_at ON termails(sent_at);

View File

@ -173,127 +173,6 @@ 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