mirror of https://github.com/synctv-org/synctv
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
194 lines
4.6 KiB
Go
194 lines
4.6 KiB
Go
package op
|
|
|
|
import (
|
|
"errors"
|
|
"hash/crc32"
|
|
"time"
|
|
|
|
"github.com/synctv-org/synctv/internal/db"
|
|
"github.com/synctv-org/synctv/internal/model"
|
|
"github.com/synctv-org/synctv/internal/settings"
|
|
"github.com/zijiren233/gencontainer/synccache"
|
|
"github.com/zijiren233/gencontainer/vec"
|
|
)
|
|
|
|
var roomCache *synccache.SyncCache[string, *Room]
|
|
|
|
func CreateRoom(name, password string, maxCount int64, conf ...db.CreateRoomConfig) (*Room, error) {
|
|
r, err := db.CreateRoom(name, password, maxCount, conf...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return LoadOrInitRoom(r)
|
|
}
|
|
|
|
var (
|
|
ErrRoomPending = errors.New("room pending, please wait for admin to approve")
|
|
ErrRoomBanned = errors.New("room banned")
|
|
)
|
|
|
|
func LoadOrInitRoom(room *model.Room) (*Room, error) {
|
|
switch room.Status {
|
|
case model.RoomStatusBanned:
|
|
return nil, ErrRoomBanned
|
|
case model.RoomStatusPending:
|
|
return nil, ErrRoomPending
|
|
}
|
|
i, _ := roomCache.LoadOrStore(room.ID, &Room{
|
|
Room: *room,
|
|
version: crc32.ChecksumIEEE(room.HashedPassword),
|
|
current: newCurrent(),
|
|
movies: movies{
|
|
roomID: room.ID,
|
|
},
|
|
}, time.Duration(settings.RoomTTL.Get())*time.Hour)
|
|
return i.Value(), nil
|
|
}
|
|
|
|
func DeleteRoomByID(roomID string) error {
|
|
err := db.DeleteRoomByID(roomID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return CloseRoomById(roomID)
|
|
}
|
|
|
|
func CompareAndDeleteRoom(room *Room) error {
|
|
err := db.DeleteRoomByID(room.ID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return CompareAndCloseRoom(room)
|
|
}
|
|
|
|
func CloseRoomById(roomID string) error {
|
|
r, loaded := roomCache.LoadAndDelete(roomID)
|
|
if loaded {
|
|
r.Value().close()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func CompareAndCloseRoomEntry(id string, room *synccache.Entry[*Room]) error {
|
|
if roomCache.CompareAndDelete(id, room) {
|
|
room.Value().close()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func CompareAndCloseRoom(room *Room) error {
|
|
r, loaded := roomCache.Load(room.ID)
|
|
if loaded {
|
|
if r.Value() != room {
|
|
return errors.New("room compare failed")
|
|
}
|
|
if roomCache.CompareAndDelete(room.ID, r) {
|
|
r.Value().close()
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func LoadRoomByID(id string) (*Room, error) {
|
|
r2, loaded := roomCache.Load(id)
|
|
if loaded {
|
|
r2.SetExpiration(time.Now().Add(time.Duration(settings.RoomTTL.Get()) * time.Hour))
|
|
return r2.Value(), nil
|
|
}
|
|
return nil, errors.New("room not found")
|
|
}
|
|
|
|
func LoadOrInitRoomByID(id string) (*Room, error) {
|
|
if len(id) != 32 {
|
|
return nil, errors.New("room id is not 32 bit")
|
|
}
|
|
i, loaded := roomCache.Load(id)
|
|
if loaded {
|
|
i.SetExpiration(time.Now().Add(time.Duration(settings.RoomTTL.Get()) * time.Hour))
|
|
return i.Value(), nil
|
|
}
|
|
room, err := db.GetRoomByID(id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return LoadOrInitRoom(room)
|
|
}
|
|
|
|
func PeopleNum(roomID string) int64 {
|
|
r, loaded := roomCache.Load(roomID)
|
|
if loaded {
|
|
return r.Value().PeopleNum()
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func GetAllRoomsInCacheWithNoNeedPassword() []*Room {
|
|
rooms := make([]*Room, 0)
|
|
roomCache.Range(func(key string, 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 string, value *synccache.Entry[*Room]) bool {
|
|
v := value.Value()
|
|
if !v.Settings.Hidden {
|
|
rooms = append(rooms, v)
|
|
}
|
|
return true
|
|
})
|
|
return rooms
|
|
}
|
|
|
|
type RoomInfo struct {
|
|
RoomId string `json:"roomId"`
|
|
RoomName string `json:"roomName"`
|
|
PeopleNum int64 `json:"peopleNum"`
|
|
NeedPassword bool `json:"needPassword"`
|
|
CreatorID string `json:"creatorId"`
|
|
Creator string `json:"creator"`
|
|
CreatedAt int64 `json:"createdAt"`
|
|
Status model.RoomStatus `json:"status"`
|
|
}
|
|
|
|
func GetRoomHeapInCacheWithoutHidden() []*RoomInfo {
|
|
rooms := vec.New[*RoomInfo](vec.WithCmpLess[*RoomInfo](func(v1, v2 *RoomInfo) bool {
|
|
return v1.PeopleNum > v2.PeopleNum
|
|
}), vec.WithCmpEqual[*RoomInfo](func(v1, v2 *RoomInfo) bool {
|
|
return v1.RoomId == v2.RoomId
|
|
}))
|
|
roomCache.Range(func(key string, value *synccache.Entry[*Room]) bool {
|
|
v := value.Value()
|
|
if !v.Settings.Hidden {
|
|
rooms.Push(&RoomInfo{
|
|
RoomId: v.ID,
|
|
RoomName: v.Name,
|
|
PeopleNum: v.PeopleNum(),
|
|
NeedPassword: v.NeedPassword(),
|
|
Creator: GetUserName(v.CreatorID),
|
|
CreatedAt: v.CreatedAt.UnixMilli(),
|
|
})
|
|
}
|
|
return true
|
|
})
|
|
return rooms.SortStable().Slice()
|
|
}
|
|
|
|
func SetRoomStatus(roomID string, status model.RoomStatus) error {
|
|
err := db.SetRoomStatus(roomID, status)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
e, loaded := roomCache.LoadAndDelete(roomID)
|
|
if loaded {
|
|
e.Value().close()
|
|
}
|
|
return nil
|
|
}
|