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.
176 lines
3.8 KiB
Go
176 lines
3.8 KiB
Go
package entities
|
|
|
|
import (
|
|
"movie-sync-server/utils"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/samber/lo"
|
|
"github.com/sirupsen/logrus"
|
|
socket "github.com/zishang520/socket.io/v2/socket"
|
|
)
|
|
|
|
type Room interface {
|
|
Name() string
|
|
SetName(name string)
|
|
SetUrl(url string)
|
|
GetUrl() string
|
|
GetPlayTime() int64
|
|
SetPlayTime(playTime int64)
|
|
GetPlaying() bool
|
|
SetPlaying(playing bool)
|
|
AddUser(user User)
|
|
RemoveUser(username string)
|
|
Broadcast(event string, message any)
|
|
BroadcastRoomState()
|
|
GetUsers() []User
|
|
GetUser(name string) User
|
|
GetAllUserStatus() []UserStatus
|
|
InitUsers()
|
|
Refresh()
|
|
}
|
|
|
|
var (
|
|
_ Room = (*RoomImpl)(nil)
|
|
)
|
|
|
|
type RoomImpl struct {
|
|
name string
|
|
url string
|
|
users map[string]User
|
|
lastUpdatePlayTime int64 // 上次更新时间
|
|
playTime int64
|
|
playing bool
|
|
broadcastRoomInfoLock sync.Mutex
|
|
}
|
|
|
|
func (r *RoomImpl) Name() string {
|
|
return r.name
|
|
}
|
|
|
|
func (r *RoomImpl) SetName(name string) {
|
|
r.name = name
|
|
}
|
|
|
|
func (r *RoomImpl) SetUrl(url string) {
|
|
r.url = url
|
|
}
|
|
|
|
func (r *RoomImpl) GetUrl() string {
|
|
return r.url
|
|
}
|
|
|
|
func (r *RoomImpl) GetPlayTime() int64 {
|
|
if r.lastUpdatePlayTime == 0 { // 暂停状态
|
|
return r.playTime
|
|
}
|
|
|
|
// 计算实时播放时间
|
|
deltaTime := time.Now().Unix() - r.lastUpdatePlayTime
|
|
realPlayTime := max(r.playTime+deltaTime, 0)
|
|
|
|
return realPlayTime
|
|
}
|
|
|
|
func (r *RoomImpl) SetPlayTime(playTime int64) {
|
|
r.playTime = playTime
|
|
r.lastUpdatePlayTime = time.Now().Unix()
|
|
}
|
|
|
|
func (r *RoomImpl) GetPlaying() bool {
|
|
return r.playing
|
|
}
|
|
|
|
func (r *RoomImpl) SetPlaying(playing bool) {
|
|
r.playing = playing
|
|
if playing {
|
|
r.SetPlayTime(r.GetPlayTime()) // 更新播放时间为当前时间
|
|
} else {
|
|
r.SetPlayTime(r.GetPlayTime())
|
|
r.lastUpdatePlayTime = 0 // 清除上次更新时间,表示暂停状态
|
|
}
|
|
}
|
|
|
|
func (r *RoomImpl) AddUser(user User) {
|
|
r.users[user.ID()] = user
|
|
GetCinema().SetUserRoom(user.ID(), r)
|
|
user.GetSocket().Join(socket.Room(r.name))
|
|
}
|
|
|
|
func (r *RoomImpl) RemoveUser(username string) {
|
|
tmpUser, ok := r.users[username]
|
|
if ok {
|
|
tmpUser.GetSocket().Leave(socket.Room(r.name))
|
|
GetCinema().DeleteUserRoom(tmpUser.ID())
|
|
delete(r.users, username)
|
|
}
|
|
}
|
|
|
|
func (r *RoomImpl) Broadcast(event string, message any) {
|
|
rawMsg, err := utils.StructToMapViaJSON(message)
|
|
if err != nil {
|
|
logrus.WithError(err).Errorf("broadcast event marshal [%v]:{%v} error", event, message)
|
|
}
|
|
|
|
err = GetServer().To(socket.Room(r.name)).Emit(event, rawMsg)
|
|
if err != nil {
|
|
logrus.WithError(err).Errorf("broadcast event [%v]:{%v} error", event, message)
|
|
}
|
|
}
|
|
|
|
func (r *RoomImpl) BroadcastRoomState() {
|
|
// 限制广播频率
|
|
if r.broadcastRoomInfoLock.TryLock() {
|
|
go func() {
|
|
r.Broadcast("roomInfo", RoomStateChangedMessage{
|
|
ServerTime: time.Now().Unix(),
|
|
URL: r.GetUrl(),
|
|
UserStatus: r.GetAllUserStatus(),
|
|
Playing: r.GetPlaying(),
|
|
PlayTime: r.GetPlayTime(),
|
|
})
|
|
|
|
// 延迟一段时间后再次广播最新状态
|
|
time.Sleep(time.Millisecond * 500)
|
|
|
|
r.Broadcast("roomInfo", RoomStateChangedMessage{
|
|
ServerTime: time.Now().Unix(),
|
|
URL: r.GetUrl(),
|
|
UserStatus: r.GetAllUserStatus(),
|
|
Playing: r.GetPlaying(),
|
|
PlayTime: r.GetPlayTime(),
|
|
})
|
|
|
|
r.broadcastRoomInfoLock.Unlock()
|
|
}()
|
|
} else {
|
|
return
|
|
}
|
|
}
|
|
|
|
func (r *RoomImpl) InitUsers() {
|
|
r.users = make(map[string]User)
|
|
}
|
|
|
|
func (r *RoomImpl) Refresh() {
|
|
GetServer().To(socket.Room(r.name)).Emit("refresh")
|
|
}
|
|
|
|
func (r *RoomImpl) GetUsers() []User {
|
|
return lo.MapToSlice(r.users, func(k string, v User) User { return v })
|
|
}
|
|
|
|
func (r *RoomImpl) GetUser(name string) User {
|
|
user, ok := r.users[name]
|
|
if ok {
|
|
return user
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (r *RoomImpl) GetAllUserStatus() []UserStatus {
|
|
return lo.MapToSlice(r.users, func(k string, v User) UserStatus {
|
|
return v.ToUserStatus()
|
|
})
|
|
}
|