Files
nixcn-cms/data/event.go
2025-12-26 03:49:28 +08:00

146 lines
3.8 KiB
Go

package data
import (
"errors"
"slices"
"time"
"github.com/go-viper/mapstructure/v2"
"github.com/google/uuid"
"github.com/meilisearch/meilisearch-go"
"gorm.io/datatypes"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
type Event struct {
Id uint `json:"id" gorm:"primarykey;autoincrement"`
UUID uuid.UUID `json:"uuid" gorm:"type:uuid;uniqueIndex;not null"`
EventId uuid.UUID `json:"event_id" gorm:"type:uuid;uniqueIndex;not null"`
Name string `json:"name" gorm:"type:varchar(255);index;not null"`
StartTime time.Time `json:"start_time" gorm:"index"`
EndTime time.Time `json:"end_time" gorm:"index"`
JoinedUsers datatypes.JSONSlice[uuid.UUID] `json:"joined_users"`
}
type EventSearchDoc struct {
EventId string `json:"event_id"`
Name string `json:"name"`
StartTime time.Time `json:"start_time"`
EndTime time.Time `json:"end_time"`
}
func (self *Event) GetEventById(eventId uuid.UUID) error {
return Database.Transaction(func(tx *gorm.DB) error {
if err := tx.Where("event_id = ?", eventId).First(&self).Error; err != nil {
return err
}
return nil
})
}
func (self *Event) UpdateEventById(eventId uuid.UUID) error {
return Database.Transaction(func(tx *gorm.DB) error {
if err := tx.Model(&Event{}).Where("event_id = ?", eventId).Updates(&self).Error; err != nil {
return err
}
// Update event to document index
doc := EventSearchDoc{
EventId: self.EventId.String(),
Name: self.Name,
StartTime: self.StartTime,
EndTime: self.EndTime,
}
index := MeiliSearch.Index("event")
docPrimaryKey := "event_id"
meiliOptions := &meilisearch.DocumentOptions{PrimaryKey: &docPrimaryKey}
if _, err := index.UpdateDocuments([]EventSearchDoc{doc}, meiliOptions); err != nil {
return err
}
return nil
})
}
func (self *Event) CreateEvent() error {
if self.UUID == uuid.Nil {
self.UUID = uuid.New()
}
if self.EventId == uuid.Nil {
self.EventId = uuid.New()
}
return Database.Transaction(func(tx *gorm.DB) error {
if err := tx.Create(&self).Error; err != nil {
return err
}
// Add event to document index
doc := EventSearchDoc{
EventId: self.EventId.String(),
Name: self.Name,
StartTime: self.StartTime,
EndTime: self.EndTime,
}
index := MeiliSearch.Index("event")
docPrimaryKey := "event_id"
meiliOptions := &meilisearch.DocumentOptions{PrimaryKey: &docPrimaryKey}
if _, err := index.AddDocuments([]EventSearchDoc{doc}, meiliOptions); err != nil {
return err
}
return nil
})
}
func (self *Event) UserJoinEvent(userId, eventId uuid.UUID) error {
return Database.Transaction(func(tx *gorm.DB) error {
var event Event
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).
Where("event_id = ?", eventId).
First(&event).Error; err != nil {
return err
}
// Check if user already joined
if slices.Contains(event.JoinedUsers, userId) {
return errors.New("user already joined")
}
// Add user to list
event.JoinedUsers = append(event.JoinedUsers, userId)
if err := tx.Model(&Event{}).Where("event_id = ?", eventId).Update("joined_users", event.JoinedUsers).Error; err != nil {
return err
}
*self = event
return nil
})
}
func (self *Event) GetFullTable() (*[]Event, error) {
var events []Event
err := Database.Find(&events).Error
if err != nil {
return nil, err
}
return &events, err
}
func (self *Event) FastListEvents(limit, offset int64) (*[]EventSearchDoc, error) {
index := MeiliSearch.Index("event")
result, err := index.Search("", &meilisearch.SearchRequest{
Limit: limit,
Offset: offset,
})
if err != nil {
return nil, err
}
var list []EventSearchDoc
if err := mapstructure.Decode(result.Hits, &list); err != nil {
return nil, err
}
return &list, nil
}