package op import ( "errors" "hash/crc32" "time" "github.com/synctv-org/synctv/internal/db" "github.com/synctv-org/synctv/internal/model" synccache "github.com/synctv-org/synctv/utils/syncCache" ) var roomTTL = time.Hour * 24 * 2 var roomCache *synccache.SyncCache[uint, *Room] func CreateRoom(name, password string, conf ...db.CreateRoomConfig) (*Room, error) { r, err := db.CreateRoom(name, password, conf...) if err != nil { return nil, err } return InitRoom(r) } func InitRoom(room *model.Room) (*Room, error) { r := &Room{ Room: *room, version: crc32.ChecksumIEEE(room.HashedPassword), current: newCurrent(), movies: movies{ roomID: room.ID, }, } i, loaded := roomCache.LoadOrStore(room.ID, r, roomTTL) if loaded { return r, errors.New("room already init") } return i.Value(), nil } func LoadOrInitRoom(room *model.Room) (*Room, bool) { i, loaded := roomCache.LoadOrStore(room.ID, &Room{ Room: *room, version: crc32.ChecksumIEEE(room.HashedPassword), current: newCurrent(), movies: movies{ roomID: room.ID, }, }, roomTTL) if loaded { i.SetExpiration(time.Now().Add(roomTTL)) } return i.Value(), loaded } func DeleteRoom(roomID uint) error { err := db.DeleteRoomByID(roomID) if err != nil { return err } return CloseRoom(roomID) } func CloseRoom(roomID uint) error { r, loaded := roomCache.LoadAndDelete(roomID) if loaded { r.Value().close() } return errors.New("room not found in cache") } func LoadRoomByID(id uint) (*Room, error) { r2, loaded := roomCache.Load(id) if loaded { r2.SetExpiration(time.Now().Add(roomTTL)) return r2.Value(), nil } return nil, errors.New("room not found") } func LoadOrInitRoomByID(id uint) (*Room, error) { i, loaded := roomCache.Load(id) if loaded { i.SetExpiration(time.Now().Add(roomTTL)) return i.Value(), nil } room, err := db.GetRoomByID(id) if err != nil { return nil, err } r, _ := LoadOrInitRoom(room) return r, nil } func ClientNum(roomID uint) int64 { r, loaded := roomCache.Load(roomID) if loaded { return r.Value().ClientNum() } return 0 } func HasRoom(roomID uint) bool { _, ok := roomCache.Load(roomID) if ok { return true } ok, err := db.HasRoom(roomID) if err != nil { return false } return ok } func HasRoomByName(name string) bool { ok, err := db.HasRoomByName(name) if err != nil { return false } return ok } func SetRoomPassword(roomID uint, password string) error { r, err := LoadOrInitRoomByID(roomID) if err != nil { return err } return r.SetPassword(password) } func GetAllRoomsInCacheWithNoNeedPassword() []*Room { rooms := make([]*Room, 0) roomCache.Range(func(key uint, value *synccache.Entry[*Room]) bool { v := value.Value() if !v.NeedPassword() { rooms = append(rooms, v) } return true }) return rooms } func GetAllRoomsInCacheWithoutHidden() []*Room { rooms := make([]*Room, 0) roomCache.Range(func(key uint, value *synccache.Entry[*Room]) bool { v := value.Value() if !v.Settings.Hidden { rooms = append(rooms, v) } return true }) return rooms }