This commit is contained in:
2026-02-23 23:50:04 +08:00
commit 084d3b0faf
45 changed files with 4090 additions and 0 deletions

View File

@@ -0,0 +1,47 @@
package repositories
import "lv8girl/internal/models"
type CommentRepository struct{}
func NewCommentRepository() *CommentRepository {
return &CommentRepository{}
}
func (r *CommentRepository) FindByPostID(postID uint) ([]models.Comment, error) {
var comments []models.Comment
err := DB.Preload("User").Where("post_id = ?", postID).Order("created_at DESC").Find(&comments).Error
return comments, err
}
func (r *CommentRepository) FindAll() ([]models.Comment, error) {
var comments []models.Comment
err := DB.Preload("User").Order("created_at DESC").Find(&comments).Error
return comments, err
}
func (r *CommentRepository) Create(comment *models.Comment) error {
return DB.Create(comment).Error
}
func (r *CommentRepository) Delete(id uint) error {
return DB.Delete(&models.Comment{}, id).Error
}
func (r *CommentRepository) Count() (int64, error) {
var count int64
err := DB.Model(&models.Comment{}).Count(&count).Error
return count, err
}
func (r *CommentRepository) CountByPostID(postID uint) (int64, error) {
var count int64
err := DB.Model(&models.Comment{}).Where("post_id = ?", postID).Count(&count).Error
return count, err
}
func (r *CommentRepository) CountByUserID(userID uint) (int64, error) {
var count int64
err := DB.Model(&models.Comment{}).Where("user_id = ?", userID).Count(&count).Error
return count, err
}

View File

@@ -0,0 +1,36 @@
package repositories
import (
"time"
"lv8girl/internal/models"
"github.com/glebarez/sqlite"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
var DB *gorm.DB
func Init(databasePath string) error {
var err error
DB, err = gorm.Open(sqlite.Open(databasePath), &gorm.Config{
Logger: logger.Default.LogMode(logger.Info),
})
if err != nil {
return err
}
err = DB.AutoMigrate(
&models.User{},
&models.Discussion{},
&models.Comment{},
&models.Like{},
&models.PrivateMessage{},
)
if err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,146 @@
package repositories
import (
"time"
"gorm.io/gorm"
"lv8girl/internal/models"
)
type DiscussionRepository struct{}
func NewDiscussionRepository() *DiscussionRepository {
return &DiscussionRepository{}
}
func (r *DiscussionRepository) FindByID(id uint) (*models.Discussion, error) {
var discussion models.Discussion
err := DB.Preload("User").First(&discussion, id).Error
return &discussion, err
}
func (r *DiscussionRepository) FindByIDWithStats(id uint) (*models.Discussion, int64, int64, error) {
discussion, err := r.FindByID(id)
if err != nil {
return nil, 0, 0, err
}
var likeCount, commentCount int64
DB.Model(&models.Like{}).Where("post_id = ?", id).Count(&likeCount)
DB.Model(&models.Comment{}).Where("post_id = ?", id).Count(&commentCount)
return discussion, likeCount, commentCount, nil
}
func (r *DiscussionRepository) FindApproved(limit int) ([]models.Discussion, error) {
var discussions []models.Discussion
err := DB.Preload("User").
Where("status = ?", "approved").
Order("created_at DESC").
Limit(limit).
Find(&discussions).Error
return discussions, err
}
func (r *DiscussionRepository) FindByUserID(userID uint) ([]models.Discussion, error) {
var discussions []models.Discussion
err := DB.Where("user_id = ? AND status = ?", userID, "approved").
Order("created_at DESC").
Find(&discussions).Error
return discussions, err
}
func (r *DiscussionRepository) FindPending() ([]models.Discussion, error) {
var discussions []models.Discussion
err := DB.Preload("User").
Where("status = ?", "pending").
Order("created_at DESC").
Find(&discussions).Error
return discussions, err
}
func (r *DiscussionRepository) FindAll() ([]models.Discussion, error) {
var discussions []models.Discussion
err := DB.Preload("User").Order("created_at DESC").Find(&discussions).Error
return discussions, err
}
func (r *DiscussionRepository) Create(discussion *models.Discussion) error {
return DB.Create(discussion).Error
}
func (r *DiscussionRepository) Update(discussion *models.Discussion) error {
return DB.Save(discussion).Error
}
func (r *DiscussionRepository) UpdateStatus(id uint, status string) error {
return DB.Model(&models.Discussion{}).Where("id = ?", id).Update("status", status).Error
}
func (r *DiscussionRepository) IncrementViews(id uint) error {
return DB.Model(&models.Discussion{}).Where("id = ?", id).
UpdateColumn("views", gorm.Expr("views + ?", 1)).Error
}
func (r *DiscussionRepository) Delete(id uint) error {
return DB.Delete(&models.Discussion{}, id).Error
}
func (r *DiscussionRepository) Count() (int64, error) {
var count int64
err := DB.Model(&models.Discussion{}).Count(&count).Error
return count, err
}
func (r *DiscussionRepository) CountByStatus(status string) (int64, error) {
var count int64
err := DB.Model(&models.Discussion{}).Where("status = ?", status).Count(&count).Error
return count, err
}
func (r *DiscussionRepository) CountByUserID(userID uint) (int64, error) {
var count int64
err := DB.Model(&models.Discussion{}).Where("user_id = ? AND status = ?", userID, "approved").Count(&count).Error
return count, err
}
type PostListItem struct {
ID uint
Title string
Content string
Username string
Avatar string
UserID uint
LikeCount int64
CommentCount int64
Views int
CreatedAt time.Time
}
func (r *DiscussionRepository) GetPostList(limit int) ([]PostListItem, error) {
discussions, err := r.FindApproved(limit)
if err != nil {
return nil, err
}
var posts []PostListItem
for _, d := range discussions {
var likeCount, commentCount int64
DB.Model(&models.Like{}).Where("post_id = ?", d.ID).Count(&likeCount)
DB.Model(&models.Comment{}).Where("post_id = ?", d.ID).Count(&commentCount)
posts = append(posts, PostListItem{
ID: d.ID,
Title: d.Title,
Content: d.Content,
Username: d.User.Username,
Avatar: d.User.Avatar,
UserID: d.User.ID,
LikeCount: likeCount,
CommentCount: commentCount,
Views: d.Views,
CreatedAt: d.CreatedAt,
})
}
return posts, nil
}

View File

@@ -0,0 +1,37 @@
package repositories
import "lv8girl/internal/models"
type LikeRepository struct{}
func NewLikeRepository() *LikeRepository {
return &LikeRepository{}
}
func (r *LikeRepository) FindByPostAndUser(postID, userID uint) (*models.Like, error) {
var like models.Like
err := DB.Where("post_id = ? AND user_id = ?", postID, userID).First(&like).Error
return &like, err
}
func (r *LikeRepository) Exists(postID, userID uint) bool {
var count int64
DB.Model(&models.Like{}).Where("post_id = ? AND user_id = ?", postID, userID).Count(&count)
return count > 0
}
func (r *LikeRepository) Create(like *models.Like) error {
return DB.Create(like).Error
}
func (r *LikeRepository) Count() (int64, error) {
var count int64
err := DB.Model(&models.Like{}).Count(&count).Error
return count, err
}
func (r *LikeRepository) CountByPostID(postID uint) (int64, error) {
var count int64
err := DB.Model(&models.Like{}).Where("post_id = ?", postID).Count(&count).Error
return count, err
}

View File

@@ -0,0 +1,69 @@
package repositories
import (
"time"
"lv8girl/internal/models"
)
type MessageRepository struct{}
func NewMessageRepository() *MessageRepository {
return &MessageRepository{}
}
func (r *MessageRepository) FindByID(id uint) (*models.PrivateMessage, error) {
var msg models.PrivateMessage
err := DB.First(&msg, id).Error
return &msg, err
}
func (r *MessageRepository) Create(message *models.PrivateMessage) error {
return DB.Create(message).Error
}
func (r *MessageRepository) MarkAsRead(id uint) error {
return DB.Model(&models.PrivateMessage{}).Where("id = ?", id).Update("is_read", true).Error
}
func (r *MessageRepository) CountUnread(userID uint) (int64, error) {
var count int64
err := DB.Model(&models.PrivateMessage{}).
Where("to_user_id = ? AND is_read = ?", userID, false).
Count(&count).Error
return count, err
}
func (r *MessageRepository) FindConversations(userID uint) ([]models.PrivateMessage, error) {
var messages []models.PrivateMessage
err := DB.Where("from_user_id = ? OR to_user_id = ?", userID, userID).
Order("created_at DESC").
Find(&messages).Error
return messages, err
}
func (r *MessageRepository) FindLastMessage(userID, otherUserID uint) (*models.PrivateMessage, error) {
var msg models.PrivateMessage
err := DB.Where(
"(from_user_id = ? AND to_user_id = ?) OR (from_user_id = ? AND to_user_id = ?)",
userID, otherUserID, otherUserID, userID,
).Order("created_at DESC").First(&msg).Error
return &msg, err
}
func (r *MessageRepository) CountUnreadFromUser(fromUserID, toUserID uint) (int64, error) {
var count int64
err := DB.Model(&models.PrivateMessage{}).
Where("from_user_id = ? AND to_user_id = ? AND is_read = ?", fromUserID, toUserID, false).
Count(&count).Error
return count, err
}
type ConversationSummary struct {
UserID uint
Username string
Avatar string
LastMsg string
Time time.Time
Unread int64
}

View File

@@ -0,0 +1,123 @@
package repositories
import (
"time"
"golang.org/x/crypto/bcrypt"
"lv8girl/internal/models"
)
type UserRepository struct{}
func NewUserRepository() *UserRepository {
return &UserRepository{}
}
func (r *UserRepository) FindByID(id uint) (*models.User, error) {
var user models.User
err := DB.First(&user, id).Error
return &user, err
}
func (r *UserRepository) FindByUsernameOrEmail(login string) (*models.User, error) {
var user models.User
err := DB.Where("username = ? OR email = ?", login, login).First(&user).Error
return &user, err
}
func (r *UserRepository) FindByUsername(username string) (*models.User, error) {
var user models.User
err := DB.Where("username = ?", username).First(&user).Error
return &user, err
}
func (r *UserRepository) FindByEmail(email string) (*models.User, error) {
var user models.User
err := DB.Where("email = ?", email).First(&user).Error
return &user, err
}
func (r *UserRepository) ExistsByUsernameOrEmail(username, email string) bool {
var count int64
DB.Model(&models.User{}).Where("username = ? OR email = ?", username, email).Count(&count)
return count > 0
}
func (r *UserRepository) Create(user *models.User) error {
return DB.Create(user).Error
}
func (r *UserRepository) Update(user *models.User) error {
return DB.Save(user).Error
}
func (r *UserRepository) UpdateField(id uint, field string, value interface{}) error {
return DB.Model(&models.User{}).Where("id = ?", id).Update(field, value).Error
}
func (r *UserRepository) UpdateLastActive(id uint) error {
now := time.Now()
return r.UpdateField(id, "last_active", now)
}
func (r *UserRepository) Delete(id uint) error {
return DB.Delete(&models.User{}, id).Error
}
func (r *UserRepository) Count() (int64, error) {
var count int64
err := DB.Model(&models.User{}).Count(&count).Error
return count, err
}
func (r *UserRepository) CountOnline() (int64, error) {
var count int64
fiveMinutesAgo := time.Now().Add(-5 * time.Minute)
err := DB.Model(&models.User{}).Where("last_active > ?", fiveMinutesAgo).Count(&count).Error
return count, err
}
func (r *UserRepository) CountByRole(role string) (int64, error) {
var count int64
err := DB.Model(&models.User{}).Where("role = ?", role).Count(&count).Error
return count, err
}
func (r *UserRepository) FindPending() ([]models.User, error) {
var users []models.User
err := DB.Where("status = ?", "pending").Order("created_at ASC").Find(&users).Error
return users, err
}
func (r *UserRepository) FindAll() ([]models.User, error) {
var users []models.User
err := DB.Order("id").Find(&users).Error
return users, err
}
func (r *UserRepository) HashPassword(password string) (string, error) {
bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
return string(bytes), err
}
func (r *UserRepository) CheckPassword(password, hash string) bool {
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
return err == nil
}
func (r *UserRepository) CreateAdminIfNotExists() error {
var count int64
DB.Model(&models.User{}).Where("role = ?", "admin").Count(&count)
if count == 0 {
passwordHash, _ := r.HashPassword("admin123")
admin := models.User{
Username: "admin",
Email: "admin@lv8girl.local",
PasswordHash: passwordHash,
Role: "admin",
Status: "approved",
}
return DB.Create(&admin).Error
}
return nil
}