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)
func WithSetting(setting model.Setting) CreateRoomConfig {
func WithSetting(setting model.Settings) CreateRoomConfig {
return func(r *model.Room) {
r.Settings = setting
}
@ -77,7 +77,7 @@ func GetRoomAndCreatorByID(id uint) (*model.Room, error) {
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
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
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 {
rooms := []*model.Room{}
db.Preload("Setting", "hidden = ?", false).Scopes(scopes...).Find(&rooms)
db.Where("settings_hidden = ?", false).Scopes(scopes...).Find(&rooms)
return rooms
}
func GetAllRoomsWithoutHiddenCount(scopes ...func(*gorm.DB) *gorm.DB) 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
}

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

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

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

@ -1,21 +1,28 @@
package model
import (
"time"
"github.com/zijiren233/stream"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
)
type Room struct {
gorm.Model
Name string `gorm:"not null;uniqueIndex"`
Settings Setting `gorm:"foreignKey:RoomID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
CreatorID uint `gorm:"index"`
ID uint `gorm:"primarykey"`
CreatedAt time.Time
UpdatedAt time.Time
Name string `gorm:"not null;uniqueIndex"`
Settings Settings `gorm:"embedded;embeddedPrefix:settings_"`
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"`
}
type Settings struct {
Hidden bool
}
func (r *Room) NeedPassword() bool {
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 (
"fmt"
"math/rand"
"time"
"gorm.io/gorm"
)
@ -17,7 +18,9 @@ const (
)
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"`
Username string `gorm:"not null;uniqueIndex"`
Role Role `gorm:"not null"`

@ -90,13 +90,13 @@ func (c *Current) Proto() *pb.Current {
Movie: &pb.MovieInfo{
Id: uint64(c.Movie.ID),
Base: &pb.BaseMovieInfo{
Url: c.Movie.BaseMovieInfo.Url,
Name: c.Movie.BaseMovieInfo.Name,
Live: c.Movie.BaseMovieInfo.Live,
Proxy: c.Movie.BaseMovieInfo.Proxy,
RtmpSource: c.Movie.BaseMovieInfo.RtmpSource,
Type: c.Movie.BaseMovieInfo.Type,
Headers: c.Movie.BaseMovieInfo.Headers,
Url: c.Movie.Base.Url,
Name: c.Movie.Base.Name,
Live: c.Movie.Base.Live,
Proxy: c.Movie.Base.Proxy,
RtmpSource: c.Movie.Base.RtmpSource,
Type: c.Movie.Base.Type,
Headers: c.Movie.Base.Headers,
},
PullKey: c.Movie.PullKey,
CreatedAt: c.Movie.CreatedAt.UnixMilli(),
@ -111,7 +111,7 @@ func (c *Current) Proto() *pb.Current {
}
func (c *Current) updateSeek() {
if c.Movie.BaseMovieInfo.Live {
if c.Movie.Base.Live {
c.Status.lastUpdate = time.Now()
return
}
@ -130,7 +130,7 @@ func (c *Current) setLiveStatus() 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()
}
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 {
if c.Movie.BaseMovieInfo.Live {
if c.Movie.Base.Live {
return c.setLiveStatus()
}
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 {
if c.Movie.BaseMovieInfo.Live {
if c.Movie.Base.Live {
return c.setLiveStatus()
}
if c.Status.Playing {

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

@ -61,16 +61,26 @@ func MovieList(ctx *gin.Context) {
for i, v := range m {
mresp[i] = model.MoviesResp{
Id: v.ID,
Base: m[i].BaseMovieInfo,
Base: m[i].Base,
PullKey: v.PullKey,
Creater: op.GetUserName(v.CreatorID),
}
}
current := room.Current()
ctx.JSON(http.StatusOK, model.NewApiDataResp(gin.H{
"current": room.Current(),
"total": room.GetMoviesCount(),
"movies": mresp,
"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(),
"movies": mresp,
}))
}
@ -99,7 +109,7 @@ func Movies(ctx *gin.Context) {
for i, v := range m {
mresp[i] = model.MoviesResp{
Id: v.ID,
Base: m[i].BaseMovieInfo,
Base: m[i].Base,
PullKey: v.PullKey,
Creater: op.GetUserName(v.CreatorID),
}
@ -122,7 +132,7 @@ func PushMovie(ctx *gin.Context) {
}
mi := user.NewMovie(dbModel.MovieInfo{
BaseMovieInfo: dbModel.BaseMovieInfo(req),
Base: dbModel.BaseMovieInfo(req),
})
err := room.AddMovie(mi)
@ -164,7 +174,7 @@ func NewPublishKey(ctx *gin.Context) {
return
}
if !movie.RtmpSource {
if !movie.Base.RtmpSource {
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("only live movie can get publish key"))
return
}
@ -361,22 +371,22 @@ func ProxyMovie(ctx *gin.Context) {
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"))
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"))
return
}
r := resty.New().R()
for k, v := range m.Headers {
for k, v := range m.Base.Headers {
r.SetHeader(k, v)
}
resp, err := r.Head(m.Url)
resp, err := r.Head(m.Base.Url)
if err != nil {
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err))
return
@ -399,9 +409,9 @@ func ProxyMovie(ctx *gin.Context) {
return
}
hrs := proxy.NewBufferedHttpReadSeeker(128*1024, m.Url,
hrs := proxy.NewBufferedHttpReadSeeker(128*1024, m.Base.Url,
proxy.WithContext(ctx),
proxy.WithHeaders(m.Headers),
proxy.WithHeaders(m.Base.Headers),
proxy.WithContext(ctx),
proxy.WithContentLength(length),
)

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

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

Loading…
Cancel
Save