Fix: current movie model

pull/21/head
zijiren233 2 years ago
parent 216ee19b16
commit 73dee5aa34

@ -11,7 +11,7 @@ import (
type CreateRoomConfig func(r *model.Room) type CreateRoomConfig func(r *model.Room)
func WithSetting(setting model.Setting) CreateRoomConfig { func WithSetting(setting model.Settings) CreateRoomConfig {
return func(r *model.Room) { return func(r *model.Room) {
r.Settings = setting r.Settings = setting
} }
@ -77,7 +77,7 @@ func GetRoomAndCreatorByID(id uint) (*model.Room, error) {
return r, err return r, err
} }
func ChangeRoomSetting(roomID uint, setting model.Setting) error { func ChangeRoomSetting(roomID uint, setting model.Settings) error {
err := db.Model(&model.Room{}).Where("id = ?", roomID).Update("setting", setting).Error err := db.Model(&model.Room{}).Where("id = ?", roomID).Update("setting", setting).Error
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
return errors.New("room not found") return errors.New("room not found")
@ -165,13 +165,13 @@ func GetAllRooms(scopes ...func(*gorm.DB) *gorm.DB) []*model.Room {
func GetAllRoomsWithoutHidden(scopes ...func(*gorm.DB) *gorm.DB) []*model.Room { func GetAllRoomsWithoutHidden(scopes ...func(*gorm.DB) *gorm.DB) []*model.Room {
rooms := []*model.Room{} rooms := []*model.Room{}
db.Preload("Setting", "hidden = ?", false).Scopes(scopes...).Find(&rooms) db.Where("settings_hidden = ?", false).Scopes(scopes...).Find(&rooms)
return rooms return rooms
} }
func GetAllRoomsWithoutHiddenCount(scopes ...func(*gorm.DB) *gorm.DB) int64 { func GetAllRoomsWithoutHiddenCount(scopes ...func(*gorm.DB) *gorm.DB) int64 {
var count int64 var count int64
db.Model(&model.Room{}).Preload("Setting", "hidden = ?", false).Scopes(scopes...).Count(&count) db.Model(&model.Room{}).Where("settings_hidden = ?", false).Scopes(scopes...).Count(&count)
return count return count
} }

@ -1,19 +1,19 @@
package model package model
import ( import "time"
"gorm.io/gorm"
)
type Movie struct { type Movie struct {
gorm.Model ID uint `gorm:"primarykey" json:"id"`
Position uint `gorm:"not null"` CreatedAt time.Time `json:"-"`
RoomID uint `gorm:"not null;index"` UpdatedAt time.Time `json:"-"`
Position uint `gorm:"not null" json:"-"`
RoomID uint `gorm:"not null;index" json:"-"`
CreatorID uint `gorm:"not null;index" json:"creatorId"` CreatorID uint `gorm:"not null;index" json:"creatorId"`
MovieInfo MovieInfo
} }
type MovieInfo struct { type MovieInfo struct {
BaseMovieInfo Base BaseMovieInfo `gorm:"embedded;embeddedPrefix:base_" json:"base"`
PullKey string `json:"pullKey"` PullKey string `json:"pullKey"`
} }

@ -1,12 +1,15 @@
package model package model
import ( import (
"time"
"github.com/synctv-org/synctv/internal/provider" "github.com/synctv-org/synctv/internal/provider"
"gorm.io/gorm"
) )
type UserProvider struct { type UserProvider struct {
gorm.Model ID uint `gorm:"primarykey"`
CreatedAt time.Time
UpdatedAt time.Time
UserID uint `gorm:"not null"` UserID uint `gorm:"not null"`
Provider provider.OAuth2Provider `gorm:"not null;uniqueIndex:provider_user_id"` Provider provider.OAuth2Provider `gorm:"not null;uniqueIndex:provider_user_id"`
ProviderUserID uint `gorm:"not null;uniqueIndex:provider_user_id"` ProviderUserID uint `gorm:"not null;uniqueIndex:provider_user_id"`

@ -1,6 +1,6 @@
package model package model
import "gorm.io/gorm" import "time"
type RoomRole uint32 type RoomRole uint32
@ -38,7 +38,9 @@ func (p Permission) Has(permission Permission) bool {
} }
type RoomUserRelation struct { type RoomUserRelation struct {
gorm.Model ID uint `gorm:"primarykey"`
CreatedAt time.Time
UpdatedAt time.Time
UserID uint `gorm:"not null;uniqueIndex:idx_user_room"` UserID uint `gorm:"not null;uniqueIndex:idx_user_room"`
RoomID uint `gorm:"not null;uniqueIndex:idx_user_room"` RoomID uint `gorm:"not null;uniqueIndex:idx_user_room"`
Role RoomRole `gorm:"not null"` Role RoomRole `gorm:"not null"`

@ -1,21 +1,28 @@
package model package model
import ( import (
"time"
"github.com/zijiren233/stream" "github.com/zijiren233/stream"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
) )
type Room struct { type Room struct {
gorm.Model ID uint `gorm:"primarykey"`
CreatedAt time.Time
UpdatedAt time.Time
Name string `gorm:"not null;uniqueIndex"` Name string `gorm:"not null;uniqueIndex"`
Settings Setting `gorm:"foreignKey:RoomID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"` Settings Settings `gorm:"embedded;embeddedPrefix:settings_"`
CreatorID uint `gorm:"index"` CreatorID uint `gorm:"index"`
HashedPassword []byte HashedPassword []byte
GroupUserRelations []RoomUserRelation `gorm:"foreignKey:RoomID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"` GroupUserRelations []RoomUserRelation `gorm:"foreignKey:RoomID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
Movies []Movie `gorm:"foreignKey:RoomID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"` Movies []Movie `gorm:"foreignKey:RoomID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
} }
type Settings struct {
Hidden bool
}
func (r *Room) NeedPassword() bool { func (r *Room) NeedPassword() bool {
return len(r.HashedPassword) != 0 return len(r.HashedPassword) != 0
} }

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

@ -3,6 +3,7 @@ package model
import ( import (
"fmt" "fmt"
"math/rand" "math/rand"
"time"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -17,7 +18,9 @@ const (
) )
type User struct { type User struct {
gorm.Model ID uint `gorm:"primarykey"`
CreatedAt time.Time
UpdatedAt time.Time
Providers []UserProvider `gorm:"foreignKey:UserID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"` Providers []UserProvider `gorm:"foreignKey:UserID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
Username string `gorm:"not null;uniqueIndex"` Username string `gorm:"not null;uniqueIndex"`
Role Role `gorm:"not null"` Role Role `gorm:"not null"`

@ -90,13 +90,13 @@ func (c *Current) Proto() *pb.Current {
Movie: &pb.MovieInfo{ Movie: &pb.MovieInfo{
Id: uint64(c.Movie.ID), Id: uint64(c.Movie.ID),
Base: &pb.BaseMovieInfo{ Base: &pb.BaseMovieInfo{
Url: c.Movie.BaseMovieInfo.Url, Url: c.Movie.Base.Url,
Name: c.Movie.BaseMovieInfo.Name, Name: c.Movie.Base.Name,
Live: c.Movie.BaseMovieInfo.Live, Live: c.Movie.Base.Live,
Proxy: c.Movie.BaseMovieInfo.Proxy, Proxy: c.Movie.Base.Proxy,
RtmpSource: c.Movie.BaseMovieInfo.RtmpSource, RtmpSource: c.Movie.Base.RtmpSource,
Type: c.Movie.BaseMovieInfo.Type, Type: c.Movie.Base.Type,
Headers: c.Movie.BaseMovieInfo.Headers, Headers: c.Movie.Base.Headers,
}, },
PullKey: c.Movie.PullKey, PullKey: c.Movie.PullKey,
CreatedAt: c.Movie.CreatedAt.UnixMilli(), CreatedAt: c.Movie.CreatedAt.UnixMilli(),
@ -111,7 +111,7 @@ func (c *Current) Proto() *pb.Current {
} }
func (c *Current) updateSeek() { func (c *Current) updateSeek() {
if c.Movie.BaseMovieInfo.Live { if c.Movie.Base.Live {
c.Status.lastUpdate = time.Now() c.Status.lastUpdate = time.Now()
return return
} }
@ -130,7 +130,7 @@ func (c *Current) setLiveStatus() Status {
} }
func (c *Current) SetStatus(playing bool, seek, rate, timeDiff float64) Status { func (c *Current) SetStatus(playing bool, seek, rate, timeDiff float64) Status {
if c.Movie.BaseMovieInfo.Live { if c.Movie.Base.Live {
return c.setLiveStatus() return c.setLiveStatus()
} }
c.Status.Playing = playing c.Status.Playing = playing
@ -145,7 +145,7 @@ func (c *Current) SetStatus(playing bool, seek, rate, timeDiff float64) Status {
} }
func (c *Current) SetSeekRate(seek, rate, timeDiff float64) Status { func (c *Current) SetSeekRate(seek, rate, timeDiff float64) Status {
if c.Movie.BaseMovieInfo.Live { if c.Movie.Base.Live {
return c.setLiveStatus() return c.setLiveStatus()
} }
if c.Status.Playing { if c.Status.Playing {
@ -159,7 +159,7 @@ func (c *Current) SetSeekRate(seek, rate, timeDiff float64) Status {
} }
func (c *Current) SetSeek(seek, timeDiff float64) Status { func (c *Current) SetSeek(seek, timeDiff float64) Status {
if c.Movie.BaseMovieInfo.Live { if c.Movie.Base.Live {
return c.setLiveStatus() return c.setLiveStatus()
} }
if c.Status.Playing { if c.Status.Playing {

@ -32,9 +32,9 @@ func (m *movie) Channel() (*rtmps.Channel, error) {
func (m *movie) init() (err error) { func (m *movie) init() (err error) {
switch { switch {
case m.RtmpSource && m.Proxy: case m.Base.RtmpSource && m.Base.Proxy:
return errors.New("rtmp source and proxy can't be true at the same time") return errors.New("rtmp source and proxy can't be true at the same time")
case m.Live && m.RtmpSource: case m.Base.Live && m.Base.RtmpSource:
if !conf.Conf.Rtmp.Enable { if !conf.Conf.Rtmp.Enable {
return errors.New("rtmp is not enabled") return errors.New("rtmp is not enabled")
} }
@ -45,11 +45,11 @@ func (m *movie) init() (err error) {
m.channel = rtmps.NewChannel() m.channel = rtmps.NewChannel()
m.channel.InitHlsPlayer() m.channel.InitHlsPlayer()
} }
case m.Live && m.Proxy: case m.Base.Live && m.Base.Proxy:
if !conf.Conf.Proxy.LiveProxy { if !conf.Conf.Proxy.LiveProxy {
return errors.New("live proxy is not enabled") return errors.New("live proxy is not enabled")
} }
u, err := url.Parse(m.Url) u, err := url.Parse(m.Base.Url)
if err != nil { if err != nil {
return err return err
} }
@ -58,7 +58,7 @@ func (m *movie) init() (err error) {
} }
switch u.Scheme { switch u.Scheme {
case "rtmp": case "rtmp":
m.PullKey = uuid.NewMD5(uuid.NameSpaceURL, []byte(m.Url)).String() m.PullKey = uuid.NewMD5(uuid.NameSpaceURL, []byte(m.Base.Url)).String()
if m.channel == nil { if m.channel == nil {
m.channel = rtmps.NewChannel() m.channel = rtmps.NewChannel()
m.channel.InitHlsPlayer() m.channel.InitHlsPlayer()
@ -68,7 +68,7 @@ func (m *movie) init() (err error) {
return return
} }
cli := core.NewConnClient() cli := core.NewConnClient()
if err = cli.Start(m.Url, av.PLAY); err != nil { if err = cli.Start(m.Base.Url, av.PLAY); err != nil {
cli.Close() cli.Close()
time.Sleep(time.Second) time.Sleep(time.Second)
continue continue
@ -81,10 +81,10 @@ func (m *movie) init() (err error) {
}() }()
} }
case "http", "https": case "http", "https":
if m.Type != "flv" { if m.Base.Type != "flv" {
return errors.New("only flv is supported") return errors.New("only flv is supported")
} }
m.PullKey = uuid.NewMD5(uuid.NameSpaceURL, []byte(m.Url)).String() m.PullKey = uuid.NewMD5(uuid.NameSpaceURL, []byte(m.Base.Url)).String()
if m.channel == nil { if m.channel == nil {
m.channel = rtmps.NewChannel() m.channel = rtmps.NewChannel()
m.channel.InitHlsPlayer() m.channel.InitHlsPlayer()
@ -94,11 +94,11 @@ func (m *movie) init() (err error) {
return return
} }
r := resty.New().R() r := resty.New().R()
for k, v := range m.Headers { for k, v := range m.Base.Headers {
r.SetHeader(k, v) r.SetHeader(k, v)
} }
// r.SetHeader("User-Agent", UserAgent) // r.SetHeader("User-Agent", UserAgent)
resp, err := r.Get(m.Url) resp, err := r.Get(m.Base.Url)
if err != nil { if err != nil {
time.Sleep(time.Second) time.Sleep(time.Second)
continue continue
@ -113,13 +113,13 @@ func (m *movie) init() (err error) {
default: default:
return errors.New("unsupported scheme") return errors.New("unsupported scheme")
} }
case !m.Live && m.RtmpSource: case !m.Base.Live && m.Base.RtmpSource:
return errors.New("rtmp source can't be true when movie is not live") return errors.New("rtmp source can't be true when movie is not live")
case !m.Live && m.Proxy: case !m.Base.Live && m.Base.Proxy:
if !conf.Conf.Proxy.MovieProxy { if !conf.Conf.Proxy.MovieProxy {
return errors.New("movie proxy is not enabled") return errors.New("movie proxy is not enabled")
} }
u, err := url.Parse(m.Url) u, err := url.Parse(m.Base.Url)
if err != nil { if err != nil {
return err return err
} }
@ -129,9 +129,9 @@ func (m *movie) init() (err error) {
if u.Scheme != "http" && u.Scheme != "https" { if u.Scheme != "http" && u.Scheme != "https" {
return errors.New("unsupported scheme") return errors.New("unsupported scheme")
} }
m.PullKey = uuid.NewMD5(uuid.NameSpaceURL, []byte(m.Url)).String() m.PullKey = uuid.NewMD5(uuid.NameSpaceURL, []byte(m.Base.Url)).String()
case !m.Live && !m.Proxy, m.Live && !m.Proxy && !m.RtmpSource: case !m.Base.Live && !m.Base.Proxy, m.Base.Live && !m.Base.Proxy && !m.Base.RtmpSource:
u, err := url.Parse(m.Url) u, err := url.Parse(m.Base.Url)
if err != nil { if err != nil {
return err return err
} }
@ -162,6 +162,6 @@ func (m *movie) Update(movie model.BaseMovieInfo) error {
m.lock.Lock() m.lock.Lock()
defer m.lock.Unlock() defer m.lock.Unlock()
m.terminate() m.terminate()
m.Movie.BaseMovieInfo = movie m.Movie.Base = movie
return m.init() return m.init()
} }

@ -61,14 +61,24 @@ func MovieList(ctx *gin.Context) {
for i, v := range m { for i, v := range m {
mresp[i] = model.MoviesResp{ mresp[i] = model.MoviesResp{
Id: v.ID, Id: v.ID,
Base: m[i].BaseMovieInfo, Base: m[i].Base,
PullKey: v.PullKey, PullKey: v.PullKey,
Creater: op.GetUserName(v.CreatorID), Creater: op.GetUserName(v.CreatorID),
} }
} }
current := room.Current()
ctx.JSON(http.StatusOK, model.NewApiDataResp(gin.H{ ctx.JSON(http.StatusOK, model.NewApiDataResp(gin.H{
"current": room.Current(), "current": &model.CurrentMovieResp{
Status: current.Status,
Movie: model.MoviesResp{
Id: current.Movie.ID,
Base: current.Movie.Base,
PullKey: current.Movie.PullKey,
Creater: op.GetUserName(current.Movie.CreatorID),
},
},
"total": room.GetMoviesCount(), "total": room.GetMoviesCount(),
"movies": mresp, "movies": mresp,
})) }))
@ -99,7 +109,7 @@ func Movies(ctx *gin.Context) {
for i, v := range m { for i, v := range m {
mresp[i] = model.MoviesResp{ mresp[i] = model.MoviesResp{
Id: v.ID, Id: v.ID,
Base: m[i].BaseMovieInfo, Base: m[i].Base,
PullKey: v.PullKey, PullKey: v.PullKey,
Creater: op.GetUserName(v.CreatorID), Creater: op.GetUserName(v.CreatorID),
} }
@ -122,7 +132,7 @@ func PushMovie(ctx *gin.Context) {
} }
mi := user.NewMovie(dbModel.MovieInfo{ mi := user.NewMovie(dbModel.MovieInfo{
BaseMovieInfo: dbModel.BaseMovieInfo(req), Base: dbModel.BaseMovieInfo(req),
}) })
err := room.AddMovie(mi) err := room.AddMovie(mi)
@ -164,7 +174,7 @@ func NewPublishKey(ctx *gin.Context) {
return return
} }
if !movie.RtmpSource { if !movie.Base.RtmpSource {
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("only live movie can get publish key")) ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("only live movie can get publish key"))
return return
} }
@ -361,22 +371,22 @@ func ProxyMovie(ctx *gin.Context) {
return return
} }
if !m.Proxy || m.Live || m.RtmpSource { if !m.Base.Proxy || m.Base.Live || m.Base.RtmpSource {
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("not support proxy")) ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("not support proxy"))
return return
} }
if l, err := utils.ParseURLIsLocalIP(m.Url); err != nil || l { if l, err := utils.ParseURLIsLocalIP(m.Base.Url); err != nil || l {
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("parse url error or url is local ip")) ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("parse url error or url is local ip"))
return return
} }
r := resty.New().R() r := resty.New().R()
for k, v := range m.Headers { for k, v := range m.Base.Headers {
r.SetHeader(k, v) r.SetHeader(k, v)
} }
resp, err := r.Head(m.Url) resp, err := r.Head(m.Base.Url)
if err != nil { if err != nil {
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err)) ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err))
return return
@ -399,9 +409,9 @@ func ProxyMovie(ctx *gin.Context) {
return return
} }
hrs := proxy.NewBufferedHttpReadSeeker(128*1024, m.Url, hrs := proxy.NewBufferedHttpReadSeeker(128*1024, m.Base.Url,
proxy.WithContext(ctx), proxy.WithContext(ctx),
proxy.WithHeaders(m.Headers), proxy.WithHeaders(m.Base.Headers),
proxy.WithContext(ctx), proxy.WithContext(ctx),
proxy.WithContentLength(length), proxy.WithContentLength(length),
) )

@ -6,6 +6,7 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
json "github.com/json-iterator/go" json "github.com/json-iterator/go"
"github.com/synctv-org/synctv/internal/model" "github.com/synctv-org/synctv/internal/model"
"github.com/synctv-org/synctv/internal/op"
) )
var ( var (
@ -114,3 +115,8 @@ type MoviesResp struct {
PullKey string `json:"pullKey"` PullKey string `json:"pullKey"`
Creater string `json:"creater"` Creater string `json:"creater"`
} }
type CurrentMovieResp struct {
Status op.Status `json:"status"`
Movie MoviesResp `json:"movie"`
}

@ -41,7 +41,7 @@ func (f FormatEmptyPasswordError) Error() string {
type CreateRoomReq struct { type CreateRoomReq struct {
RoomName string `json:"roomName"` RoomName string `json:"roomName"`
Password string `json:"password"` Password string `json:"password"`
Setting model.Setting `json:"setting"` Setting model.Settings `json:"setting"`
} }
func (c *CreateRoomReq) Decode(ctx *gin.Context) error { func (c *CreateRoomReq) Decode(ctx *gin.Context) error {

Loading…
Cancel
Save