package models import "time" // Photo یکی از عکس‌های پروفایل کاربر type Photo struct { ID uint `gorm:"primaryKey" json:"id"` UserID uint `gorm:"not null;index" json:"user_id"` URL string `gorm:"size:500;not null" json:"url"` SortOrder int `gorm:"default:0;not null" json:"sort_order"` CreatedAt time.Time `json:"created_at"` } func (Photo) TableName() string { return "photos" } // SwipeAction نوع تصمیمی که کاربر روی یک پروفایل دیگه گرفته type SwipeAction string const ( SwipeLike SwipeAction = "like" SwipeSuperlike SwipeAction = "superlike" SwipePass SwipeAction = "pass" ) // Swipe ثبت تصمیم یک کاربر (لایک/ردّ) روی یک کاربر دیگه. // هر جفت (SwiperID, SwipedID) فقط یک بار می‌تونه ثبت بشه؛ توی discovery feed // کسایی که قبلاً روشون تصمیم گرفته شده دیگه نشون داده نمی‌شن. type Swipe struct { ID uint `gorm:"primaryKey" json:"id"` SwiperID uint `gorm:"not null;uniqueIndex:idx_swiper_swiped" json:"swiper_id"` SwipedID uint `gorm:"not null;uniqueIndex:idx_swiper_swiped;index" json:"swiped_id"` Action SwipeAction `gorm:"size:10;not null" json:"action"` CreatedAt time.Time `json:"created_at"` } func (Swipe) TableName() string { return "swipes" } // Match وقتی ساخته می‌شه که دو کاربر متقابلاً همدیگه رو لایک کرده باشن. // UserOneID همیشه شناسه‌ی کوچیک‌تره (برای جلوگیری از رکورد تکراری در دو جهت). type Match struct { ID uint `gorm:"primaryKey" json:"id"` UserOneID uint `gorm:"not null;uniqueIndex:idx_match_pair" json:"user_one_id"` UserTwoID uint `gorm:"not null;uniqueIndex:idx_match_pair" json:"user_two_id"` CreatedAt time.Time `json:"created_at"` UserOne *User `gorm:"foreignKey:UserOneID" json:"-"` UserTwo *User `gorm:"foreignKey:UserTwoID" json:"-"` } func (Match) TableName() string { return "matches" } // Message یک پیام داخل یک مچ. از رمزنگاری سرتاسری (E2EE) استفاده می‌شه: // سرور فقط CipherText+Nonce (خروجی رمزنگاری‌شده‌ی سمت کلاینت با NaCl box، // X25519-XSalsa20-Poly1305) رو ذخیره می‌کنه و هیچ‌وقت متن خام پیام رو نمی‌بینه. // Text قدیمی (قبل از اضافه شدن E2EE) برای نمایش پیام‌های تاریخی نگه داشته می‌شه؛ // پیام‌های جدید Text خالی دارن و به‌جاش CipherText/Nonce پر می‌شه. type Message struct { ID uint `gorm:"primaryKey" json:"id"` MatchID uint `gorm:"not null;index" json:"match_id"` SenderID uint `gorm:"not null" json:"sender_id"` Text string `gorm:"size:2000;not null" json:"text"` CipherText *string `gorm:"size:12000" json:"cipher_text,omitempty"` Nonce *string `gorm:"size:64" json:"nonce,omitempty"` ReadAt *time.Time `json:"read_at,omitempty"` CreatedAt time.Time `json:"created_at"` } func (Message) TableName() string { return "messages" }