Feat: lazy init room

pull/21/head
zijiren233 2 years ago
parent e38eb7aa6a
commit e2a83a68c0

@ -32,7 +32,6 @@ var ServerCmd = &cobra.Command{
bootstrap.InitProvider,
bootstrap.InitOp,
bootstrap.InitRtmp,
bootstrap.InitRoom,
)
if !flags.DisableUpdateCheck {
boot.Add(bootstrap.InitCheckUpdate)

@ -15,7 +15,6 @@ require (
github.com/google/uuid v1.3.1
github.com/gorilla/websocket v1.5.0
github.com/json-iterator/go v1.1.12
github.com/maruel/natural v1.1.0
github.com/mitchellh/go-homedir v1.1.0
github.com/natefinch/lumberjack v2.0.0+incompatible
github.com/quic-go/quic-go v0.39.1
@ -66,6 +65,7 @@ require (
github.com/jinzhu/now v1.1.5 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/maruel/natural v1.1.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect

@ -286,8 +286,6 @@ gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls=
gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
modernc.org/libc v1.24.1 h1:uvJSeCKL/AgzBo2yYIPPTy82v21KgGnizcGYfBHaNuM=
modernc.org/libc v1.24.1/go.mod h1:FmfO1RLrU3MHJfyi9eYYmZBfi/R+tqZ6+hQ3yQQUkak=
modernc.org/libc v1.25.0 h1:nbTrmtr6NSdZe59ut3MvXS4ZQQPfxhicocdlKbkmZkg=
modernc.org/libc v1.25.0/go.mod h1:DaG/4Q3LRRdqpiLyP0C2m1B8ZMGkQ+cCgOIjEtQlYhQ=
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E=

@ -1,24 +0,0 @@
package bootstrap
import (
"context"
log "github.com/sirupsen/logrus"
"github.com/synctv-org/synctv/internal/db"
"github.com/synctv-org/synctv/internal/op"
)
func InitRoom(ctx context.Context) error {
r, err := db.GetAllRooms()
if err != nil {
return err
}
for _, room := range r {
_, err := op.LoadRoom(room)
if err != nil {
log.Errorf("load room error: %v", err)
return err
}
}
return nil
}

@ -32,7 +32,7 @@ func auth(ReqAppName, ReqChannelName string, IsPublisher bool) (*rtmps.Channel,
log.Errorf("rtmp: parse channel name to id error: %v", err)
return nil, err
}
r, err := op.GetRoomByID(uint(id))
r, err := op.LoadOrInitRoomByID(uint(id))
if err != nil {
log.Errorf("rtmp: get room by id error: %v", err)
return nil, err
@ -49,7 +49,7 @@ func auth(ReqAppName, ReqChannelName string, IsPublisher bool) (*rtmps.Channel,
log.Errorf("rtmp: parse channel name to id error: %v", err)
return nil, err
}
r, err := op.GetRoomByID(uint(id))
r, err := op.LoadOrInitRoomByID(uint(id))
if err != nil {
log.Errorf("rtmp: get room by id error: %v", err)
return nil, err

@ -45,3 +45,45 @@ func Close() {
return
}
}
func Paginate(page, pageSize int) func(db *gorm.DB) *gorm.DB {
return func(db *gorm.DB) *gorm.DB {
if page <= 0 {
page = 1
}
if pageSize <= 0 {
pageSize = 10
}
offset := (page - 1) * pageSize
return db.Offset(offset).Limit(pageSize)
}
}
func OrderByAsc(column string) func(db *gorm.DB) *gorm.DB {
return func(db *gorm.DB) *gorm.DB {
return db.Order(column + " asc")
}
}
func OrderByDesc(column string) func(db *gorm.DB) *gorm.DB {
return func(db *gorm.DB) *gorm.DB {
return db.Order(column + " desc")
}
}
func OrderByCreatedAtAsc(db *gorm.DB) *gorm.DB {
return db.Order("created_at asc")
}
func OrderByCreatedAtDesc(db *gorm.DB) *gorm.DB {
return db.Order("created_at desc")
}
func OrderByIDAsc(db *gorm.DB) *gorm.DB {
return db.Order("id asc")
}
func OrderByIDDesc(db *gorm.DB) *gorm.DB {
return db.Order("id desc")
}

@ -13,7 +13,7 @@ type CreateRoomConfig func(r *model.Room)
func WithSetting(setting model.Setting) CreateRoomConfig {
return func(r *model.Room) {
r.Setting = setting
r.Settings = setting
}
}
@ -157,29 +157,26 @@ func SetRoomHashedPassword(roomID uint, hashedPassword []byte) error {
return err
}
func GetAllRooms() ([]*model.Room, error) {
func GetAllRooms(scopes ...func(*gorm.DB) *gorm.DB) []*model.Room {
rooms := []*model.Room{}
err := db.Find(&rooms).Error
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
return rooms, nil
}
return rooms, err
db.Scopes(scopes...).Find(&rooms)
return rooms
}
func GetAllRoomsAndCreator() ([]*model.Room, error) {
func GetAllRoomsWithoutHidden(scopes ...func(*gorm.DB) *gorm.DB) []*model.Room {
rooms := []*model.Room{}
err := db.Preload("Creater").Find(&rooms).Error
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
return rooms, nil
}
return rooms, err
db.Preload("Setting").Where("setting.hidden = ?", false).Scopes(scopes...).Find(&rooms)
return rooms
}
func GetAllRoomsByUserID(userID uint) ([]*model.Room, error) {
func GetAllRoomsAndCreator(scopes ...func(*gorm.DB) *gorm.DB) []*model.Room {
rooms := []*model.Room{}
err := db.Where("creator_id = ?", userID).Find(&rooms).Error
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
return rooms, nil
}
return rooms, err
db.Preload("Creator").Scopes(scopes...).Find(&rooms)
return rooms
}
func GetAllRoomsByUserID(userID uint) []*model.Room {
rooms := []*model.Room{}
db.Where("creator_id = ?", userID).Find(&rooms)
return rooms
}

@ -9,13 +9,17 @@ import (
type Room struct {
gorm.Model
Name string `gorm:"not null;uniqueIndex"`
Setting
Settings Setting `gorm:"foreignKey:RoomID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
CreatorID uint `gorm:"index"`
HashedPassword []byte
GroupUserRelations []RoomUserRelation `gorm:"foreignKey:RoomID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
Movies []Movie `gorm:"foreignKey:RoomID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
}
func (r *Room) NeedPassword() bool {
return len(r.HashedPassword) != 0
}
func (r *Room) CheckPassword(password string) bool {
return len(r.HashedPassword) == 0 || bcrypt.CompareHashAndPassword(r.HashedPassword, stream.StringToBytes(password)) == nil
return !r.NeedPassword() || bcrypt.CompareHashAndPassword(r.HashedPassword, stream.StringToBytes(password)) == nil
}

@ -1,5 +1,9 @@
package model
import "gorm.io/gorm"
type Setting struct {
gorm.Model
RoomID uint `gorm:"uniqueIndex"`
Hidden bool
}

@ -40,7 +40,7 @@ func (r *Room) LazyInit() (err error) {
r.hub = newHub(r.ID)
var ms []*model.Movie
ms, err = r.GetAllMoviesByRoomID()
ms, err = r.GetAllMovies()
if err != nil {
log.Errorf("failed to get movies: %s", err.Error())
return
@ -331,7 +331,7 @@ func (r *Room) GetMoviesCount() (int, error) {
return GetMoviesCountByRoomID(r.ID)
}
func (r *Room) GetAllMoviesByRoomID() ([]*model.Movie, error) {
func (r *Room) GetAllMovies() ([]*model.Movie, error) {
ms, err := GetAllMoviesByRoomID(r.ID)
if err != nil {
return nil, err

@ -3,7 +3,6 @@ package op
import (
"errors"
"hash/crc32"
"sync/atomic"
"github.com/synctv-org/synctv/internal/db"
"github.com/synctv-org/synctv/internal/model"
@ -17,35 +16,30 @@ func CreateRoom(name, password string, conf ...db.CreateRoomConfig) (*Room, erro
if err != nil {
return nil, err
}
return initRoom(r)
return InitRoom(r)
}
type RoomConf func(r *Room)
func WithVersion(version uint32) RoomConf {
return func(r *Room) {
atomic.StoreUint32(&r.version, version)
}
}
func initRoom(room *model.Room, conf ...RoomConf) (*Room, error) {
func InitRoom(room *model.Room) (*Room, error) {
r := &Room{
Room: *room,
version: crc32.ChecksumIEEE(room.HashedPassword),
current: newCurrent(),
}
for _, c := range conf {
c(r)
}
r, loaded := roomCache.LoadOrStore(room.ID, r)
if loaded {
return r, errors.New("room already exists")
return r, errors.New("room already init")
}
return r, nil
}
func LoadRoom(room *model.Room) (*Room, error) {
return initRoom(room)
func LoadOrInitRoom(room *model.Room) (r *Room, loaded bool) {
r = &Room{
Room: *room,
version: crc32.ChecksumIEEE(room.HashedPassword),
current: newCurrent(),
}
r, loaded = roomCache.LoadOrStore(room.ID, r)
return
}
func DeleteRoom(room *Room) error {
@ -63,16 +57,25 @@ func DeleteRoomByID(id uint) error {
return db.DeleteRoomByID(r.ID)
}
func GetRoomByID(id uint) (*Room, error) {
func LoadRoomByID(id uint) (*Room, error) {
r2, ok := roomCache.Load(id)
if ok {
return r2, nil
}
r, err := db.GetRoomByID(id)
return nil, errors.New("room not found")
}
func LoadOrInitRoomByID(id uint) (*Room, error) {
r, ok := roomCache.Load(id)
if ok {
return r, nil
}
room, err := db.GetRoomByID(id)
if err != nil {
return nil, err
}
return initRoom(r)
r, _ = LoadOrInitRoom(room)
return r, nil
}
func HasRoom(roomID uint) bool {
@ -96,14 +99,14 @@ func HasRoomByName(name string) bool {
}
func SetRoomPassword(roomID uint, password string) error {
r, err := GetRoomByID(roomID)
r, err := LoadOrInitRoomByID(roomID)
if err != nil {
return err
}
return r.SetPassword(password)
}
func GetAllRooms() []*Room {
func GetAllRoomsInCache() []*Room {
rooms := make([]*Room, roomCache.Len())
roomCache.Range(func(key uint, value *Room) bool {
rooms = append(rooms, value)
@ -112,7 +115,7 @@ func GetAllRooms() []*Room {
return rooms
}
func GetAllRoomsWithNoNeedPassword() []*Room {
func GetAllRoomsInCacheWithNoNeedPassword() []*Room {
rooms := make([]*Room, roomCache.Len())
roomCache.Range(func(key uint, value *Room) bool {
if !value.NeedPassword() {
@ -123,10 +126,10 @@ func GetAllRoomsWithNoNeedPassword() []*Room {
return rooms
}
func GetAllRoomsWithoutHidden() []*Room {
func GetAllRoomsInCacheWithoutHidden() []*Room {
rooms := make([]*Room, 0, roomCache.Len())
roomCache.Range(func(key uint, value *Room) bool {
if !value.Setting.Hidden {
if !value.Settings.Hidden {
rooms = append(rooms, value)
}
return true

@ -77,22 +77,20 @@ func CreateOrLoadUser(username string, p provider.OAuth2Provider, pid uint, conf
}
func DeleteUserByID(userID uint) error {
rs, err := db.GetAllRoomsByUserID(userID)
if err != nil {
return err
}
err = db.DeleteUserByID(userID)
err := db.DeleteUserByID(userID)
if err != nil {
return err
}
userCache.Remove(userID)
for _, r := range rs {
r2, loaded := roomCache.LoadAndDelete(r.ID)
if loaded {
r2.close()
}
roomCache.Range(func(key uint, value *Room) bool {
if value.CreatorID == userID {
roomCache.Delete(key)
value.close()
}
return true
})
return nil
}

@ -3,7 +3,6 @@ package provider
import (
"context"
"net/http"
"time"
json "github.com/json-iterator/go"
"golang.org/x/oauth2"
@ -61,49 +60,6 @@ func (p *GithubProvider) GetUserInfo(ctx context.Context, config *oauth2.Config,
type githubUserInfo struct {
Login string `json:"login"`
ID uint `json:"id"`
NodeID string `json:"node_id"`
AvatarURL string `json:"avatar_url"`
GravatarID string `json:"gravatar_id"`
URL string `json:"url"`
HTMLURL string `json:"html_url"`
FollowersURL string `json:"followers_url"`
FollowingURL string `json:"following_url"`
GistsURL string `json:"gists_url"`
StarredURL string `json:"starred_url"`
SubscriptionsURL string `json:"subscriptions_url"`
OrganizationsURL string `json:"organizations_url"`
ReposURL string `json:"repos_url"`
EventsURL string `json:"events_url"`
ReceivedEventsURL string `json:"received_events_url"`
Type string `json:"type"`
SiteAdmin bool `json:"site_admin"`
Name string `json:"name"`
Company interface{} `json:"company"`
Blog string `json:"blog"`
Location string `json:"location"`
Email interface{} `json:"email"`
Hireable interface{} `json:"hireable"`
Bio string `json:"bio"`
TwitterUsername interface{} `json:"twitter_username"`
PublicRepos int `json:"public_repos"`
PublicGists int `json:"public_gists"`
Followers int `json:"followers"`
Following int `json:"following"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
PrivateGists int `json:"private_gists"`
TotalPrivateRepos int `json:"total_private_repos"`
OwnedPrivateRepos int `json:"owned_private_repos"`
DiskUsage int `json:"disk_usage"`
Collaborators int `json:"collaborators"`
TwoFactorAuthentication bool `json:"two_factor_authentication"`
Plan Plan `json:"plan"`
}
type Plan struct {
Name string `json:"name"`
Space int `json:"space"`
Collaborators int `json:"collaborators"`
PrivateRepos int `json:"private_repos"`
}
func init() {

@ -24,32 +24,32 @@ import (
"github.com/zijiren233/livelib/protocol/httpflv"
)
func GetPageAndMax(ctx *gin.Context) (int64, int64, error) {
max, err := strconv.ParseInt(ctx.DefaultQuery("max", "10"), 10, 64)
func GetPageAndPageSize(ctx *gin.Context) (int, int, error) {
pageSize, err := strconv.Atoi(ctx.DefaultQuery("max", "10"))
if err != nil {
return 0, 0, errors.New("max must be a number")
}
page, err := strconv.ParseInt(ctx.DefaultQuery("page", "1"), 10, 64)
page, err := strconv.Atoi(ctx.DefaultQuery("page", "1"))
if err != nil {
return 0, 0, errors.New("page must be a number")
}
return page, max, nil
return page, pageSize, nil
}
func GetPageItems[T any](ctx *gin.Context, items []T) ([]T, error) {
page, max, err := GetPageAndMax(ctx)
page, max, err := GetPageAndPageSize(ctx)
if err != nil {
return nil, err
}
return utils.GetPageItems(items, max, page), nil
return utils.GetPageItems(items, page, max), nil
}
func MovieList(ctx *gin.Context) {
room := ctx.MustGet("room").(*op.Room)
// user := ctx.MustGet("user").(*op.User)
page, max, err := GetPageAndMax(ctx)
page, max, err := GetPageAndPageSize(ctx)
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err))
return
@ -97,7 +97,7 @@ func Movies(ctx *gin.Context) {
room := ctx.MustGet("room").(*op.Room)
// user := ctx.MustGet("user").(*op.User)
page, max, err := GetPageAndMax(ctx)
page, max, err := GetPageAndPageSize(ctx)
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err))
return
@ -369,7 +369,8 @@ func ProxyMovie(ctx *gin.Context) {
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err))
return
}
room, err := op.GetRoomByID(uint(id))
room, err := op.LoadOrInitRoomByID(uint(id))
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err))
return

@ -7,13 +7,14 @@ import (
"strconv"
"github.com/gin-gonic/gin"
"github.com/maruel/natural"
"github.com/synctv-org/synctv/internal/db"
dbModel "github.com/synctv-org/synctv/internal/model"
"github.com/synctv-org/synctv/internal/op"
"github.com/synctv-org/synctv/server/middlewares"
"github.com/synctv-org/synctv/server/model"
"github.com/synctv-org/synctv/utils"
"github.com/zijiren233/gencontainer/vec"
"gorm.io/gorm"
)
var (
@ -42,11 +43,7 @@ func CreateRoom(ctx *gin.Context) {
return
}
room, err := op.LoadRoom(r)
if err != nil {
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err))
return
}
room, _ := op.LoadOrInitRoom(r)
token, err := middlewares.NewAuthRoomToken(user, room)
if err != nil {
@ -61,14 +58,31 @@ func CreateRoom(ctx *gin.Context) {
}
func RoomList(ctx *gin.Context) {
r := op.GetAllRoomsWithoutHidden()
resp := vec.New[*model.RoomListResp](vec.WithCmpLess[*model.RoomListResp](func(v1, v2 *model.RoomListResp) bool {
page, pageSize, err := GetPageAndPageSize(ctx)
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err))
return
}
resp := make([]*model.RoomListResp, 0, pageSize)
var desc = ctx.DefaultQuery("sort", "desc") == "desc"
scopes := []func(db *gorm.DB) *gorm.DB{
db.Paginate(page, pageSize),
}
total := 0
switch ctx.DefaultQuery("order", "peopleNum") {
case "peopleNum":
r := op.GetAllRoomsInCacheWithoutHidden()
rs := vec.New[*model.RoomListResp](vec.WithCmpLess[*model.RoomListResp](func(v1, v2 *model.RoomListResp) bool {
return v1.PeopleNum < v2.PeopleNum
}), vec.WithCmpEqual[*model.RoomListResp](func(v1, v2 *model.RoomListResp) bool {
return v1.PeopleNum == v2.PeopleNum
}))
for _, v := range r {
resp.Push(&model.RoomListResp{
rs.Push(&model.RoomListResp{
RoomId: v.ID,
RoomName: v.Name,
PeopleNum: v.ClientNum(),
@ -77,65 +91,64 @@ func RoomList(ctx *gin.Context) {
CreatedAt: v.Room.CreatedAt.UnixMilli(),
})
}
switch ctx.DefaultQuery("sort", "peopleNum") {
case "peopleNum":
resp.SortStable()
case "creator":
resp.SortStableFunc(func(v1, v2 *model.RoomListResp) bool {
return natural.Less(v1.Creator, v2.Creator)
}, func(t1, t2 *model.RoomListResp) bool {
return t1.Creator == t2.Creator
})
rs.SortStable()
if desc {
rs.Reverse()
}
total = rs.Len()
resp = utils.GetPageItems(rs.Slice(), page, pageSize)
case "createdAt":
resp.SortStableFunc(func(v1, v2 *model.RoomListResp) bool {
return v1.CreatedAt < v2.CreatedAt
}, func(t1, t2 *model.RoomListResp) bool {
return t1.CreatedAt == t2.CreatedAt
})
if desc {
scopes = append(scopes, db.OrderByCreatedAtDesc)
} else {
scopes = append(scopes, db.OrderByCreatedAtAsc)
}
resp = genRoomsResp(resp, scopes...)
case "roomName":
resp.SortStableFunc(func(v1, v2 *model.RoomListResp) bool {
return natural.Less(v1.RoomName, v2.RoomName)
}, func(t1, t2 *model.RoomListResp) bool {
return t1.RoomName == t2.RoomName
})
if desc {
scopes = append(scopes, db.OrderByDesc("name"))
} else {
scopes = append(scopes, db.OrderByAsc("name"))
}
resp = genRoomsResp(resp, scopes...)
case "roomId":
resp.SortStableFunc(func(v1, v2 *model.RoomListResp) bool {
return v1.RoomId < v2.RoomId
}, func(t1, t2 *model.RoomListResp) bool {
return t1.RoomId == t2.RoomId
})
case "needPassword":
resp.SortStableFunc(func(v1, v2 *model.RoomListResp) bool {
return v1.NeedPassword && !v2.NeedPassword
}, func(t1, t2 *model.RoomListResp) bool {
return t1.NeedPassword == t2.NeedPassword
})
default:
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("sort must be peoplenum or roomid"))
return
if desc {
scopes = append(scopes, db.OrderByIDDesc)
} else {
scopes = append(scopes, db.OrderByIDAsc)
}
switch ctx.DefaultQuery("order", "desc") {
case "asc":
// do nothing
case "desc":
resp.Reverse()
resp = genRoomsResp(resp, scopes...)
default:
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("order must be asc or desc"))
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("not support order"))
return
}
list, err := GetPageItems(ctx, resp.Slice())
ctx.JSON(http.StatusOK, model.NewApiDataResp(gin.H{
"total": total,
"list": resp,
}))
}
func genRoomsResp(resp []*model.RoomListResp, scopes ...func(db *gorm.DB) *gorm.DB) []*model.RoomListResp {
var clientNum int64
for _, r := range db.GetAllRooms(scopes...) {
room, err := op.LoadRoomByID(r.ID)
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err))
return
clientNum = 0
} else {
clientNum = room.ClientNum()
}
ctx.JSON(http.StatusOK, model.NewApiDataResp(gin.H{
"total": resp.Len(),
"list": list,
}))
resp = append(resp, &model.RoomListResp{
RoomId: r.ID,
RoomName: r.Name,
PeopleNum: clientNum,
NeedPassword: len(r.HashedPassword) != 0,
Creator: op.GetUserName(r.CreatorID),
CreatedAt: r.CreatedAt.UnixMilli(),
})
}
return resp
}
func CheckRoom(ctx *gin.Context) {
@ -145,14 +158,21 @@ func CheckRoom(ctx *gin.Context) {
return
}
r, err := op.GetRoomByID(uint(id))
r, err := db.GetRoomByID(uint(id))
if err != nil {
ctx.AbortWithStatusJSON(http.StatusNotFound, model.NewApiErrorResp(err))
return
}
var peopleNum int64
room, err := op.LoadRoomByID(r.ID)
if err == nil {
peopleNum = room.ClientNum()
}
ctx.JSON(http.StatusOK, model.NewApiDataResp(gin.H{
"peopleNum": r.ClientNum(),
"peopleNum": peopleNum,
"needPassword": r.NeedPassword(),
}))
}
@ -234,7 +254,7 @@ func RoomSetting(ctx *gin.Context) {
// user := ctx.MustGet("user").(*op.User)
ctx.JSON(http.StatusOK, model.NewApiDataResp(gin.H{
"hidden": room.Setting.Hidden,
"hidden": room.Settings.Hidden,
"needPassword": room.NeedPassword(),
}))
}

@ -76,7 +76,7 @@ func AuthRoom(Authorization string) (*op.User, *op.Room, error) {
return nil, nil, err
}
r, err := op.GetRoomByID(claims.RoomId)
r, err := op.LoadOrInitRoomByID(claims.RoomId)
if err != nil {
return nil, nil, err
}
@ -88,7 +88,7 @@ func AuthRoom(Authorization string) (*op.User, *op.Room, error) {
}
func AuthRoomWithPassword(u *op.User, roomId uint, password string) (*op.Room, error) {
r, err := op.GetRoomByID(roomId)
r, err := op.LoadOrInitRoomByID(roomId)
if err != nil {
return nil, err
}

@ -5,6 +5,7 @@ import (
"time"
"github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"
"github.com/synctv-org/synctv/internal/op"
"github.com/synctv-org/synctv/internal/provider"
"github.com/synctv-org/synctv/server/middlewares"
@ -90,6 +91,8 @@ func OAuth2Callback(ctx *gin.Context) {
return
}
logrus.Info("asdasd")
RenderToken(ctx, "/web/", token)
}

@ -34,16 +34,16 @@ func RandBytes(n int) []byte {
return b
}
func GetPageItems[T any](items []T, max, page int64) []T {
if max <= 0 || page <= 0 {
func GetPageItems[T any](items []T, page, pageSize int) []T {
if pageSize <= 0 || page <= 0 {
return nil
}
start := (page - 1) * max
l := int64(len(items))
start := (page - 1) * pageSize
l := len(items)
if start > l {
start = l
}
end := page * max
end := page * pageSize
if end > l {
end = l
}

@ -10,8 +10,8 @@ import (
func TestGetPageItems(t *testing.T) {
type args struct {
items []int
max int64
page int64
page int
pageSize int
}
tests := []struct {
name string
@ -22,7 +22,7 @@ func TestGetPageItems(t *testing.T) {
name: "Test Case 1",
args: args{
items: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
max: 5,
pageSize: 5,
page: 1,
},
want: []int{1, 2, 3, 4, 5},
@ -31,7 +31,7 @@ func TestGetPageItems(t *testing.T) {
name: "Test Case 2",
args: args{
items: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
max: 5,
pageSize: 5,
page: 2,
},
want: []int{6, 7, 8, 9, 10},
@ -40,7 +40,7 @@ func TestGetPageItems(t *testing.T) {
name: "Test Case 3",
args: args{
items: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
max: 5,
pageSize: 5,
page: 3,
},
want: []int{},
@ -48,7 +48,7 @@ func TestGetPageItems(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := utils.GetPageItems(tt.args.items, tt.args.max, tt.args.page); !reflect.DeepEqual(got, tt.want) {
if got := utils.GetPageItems(tt.args.items, tt.args.page, tt.args.pageSize); !reflect.DeepEqual(got, tt.want) {
t.Errorf("GetPageItems() = %v, want %v", got, tt.want)
}
})

Loading…
Cancel
Save