Files
TorrServerJellyfin/server/web/api/stream.go
2023-10-13 17:38:41 +03:00

222 lines
5.1 KiB
Go

package api
import (
"net/http"
"net/url"
"strconv"
"strings"
"server/torr"
"server/torr/state"
utils2 "server/utils"
"server/web/api/utils"
"github.com/gin-gonic/gin"
"github.com/pkg/errors"
)
// get stat
// http://127.0.0.1:8090/stream/fname?link=...&stat
// get m3u
// http://127.0.0.1:8090/stream/fname?link=...&index=1&m3u
// http://127.0.0.1:8090/stream/fname?link=...&index=1&m3u&fromlast
// stream torrent
// http://127.0.0.1:8090/stream/fname?link=...&index=1&play
// http://127.0.0.1:8090/stream/fname?link=...&index=1&play&preload
// http://127.0.0.1:8090/stream/fname?link=...&index=1&play&save
// http://127.0.0.1:8090/stream/fname?link=...&index=1&play&save&title=...&poster=...
// only save
// http://127.0.0.1:8090/stream/fname?link=...&save&title=...&poster=...
func stream(c *gin.Context) {
link := c.Query("link")
indexStr := c.Query("index")
_, preload := c.GetQuery("preload")
_, stat := c.GetQuery("stat")
_, save := c.GetQuery("save")
_, m3u := c.GetQuery("m3u")
_, fromlast := c.GetQuery("fromlast")
_, play := c.GetQuery("play")
title := c.Query("title")
poster := c.Query("poster")
data := ""
notAuth := c.GetBool("not_auth")
if notAuth && (play || m3u) {
streamNoAuth(c)
return
}
if notAuth {
c.Header("WWW-Authenticate", "Basic realm=Authorization Required")
c.AbortWithStatus(http.StatusUnauthorized)
return
}
if link == "" {
c.AbortWithError(http.StatusBadRequest, errors.New("link should not be empty"))
return
}
title, _ = url.QueryUnescape(title)
link, _ = url.QueryUnescape(link)
poster, _ = url.QueryUnescape(poster)
spec, err := utils.ParseLink(link)
if err != nil {
c.AbortWithError(http.StatusInternalServerError, err)
return
}
tor := torr.GetTorrent(spec.InfoHash.HexString())
if tor != nil {
title = tor.Title
poster = tor.Poster
data = tor.Data
}
if tor == nil || tor.Stat == state.TorrentInDB {
tor, err = torr.AddTorrent(spec, title, poster, data)
if err != nil {
c.AbortWithError(http.StatusInternalServerError, err)
return
}
}
if !tor.GotInfo() {
c.AbortWithError(http.StatusInternalServerError, errors.New("timeout connection torrent"))
return
}
if tor.Title == "" {
tor.Title = tor.Name()
}
// save to db
if save {
torr.SaveTorrentToDB(tor)
c.Status(200) // only set status, not return
}
// find file
index := -1
if len(tor.Files()) == 1 {
index = 1
} else {
ind, err := strconv.Atoi(indexStr)
if err == nil {
index = ind
}
}
if index == -1 && play { // if file index not set and play file exec
c.AbortWithError(http.StatusBadRequest, errors.New("\"index\" is empty or wrong"))
return
}
// preload torrent
if preload {
torr.Preload(tor, index)
}
// return stat if query
if stat {
c.JSON(200, tor.Status())
return
} else
// return m3u if query
if m3u {
name := strings.ReplaceAll(c.Param("fname"), `/`, "") // strip starting / from param
if name == "" {
name = tor.Name() + ".m3u"
} else {
name += ".m3u"
}
m3ulist := "#EXTM3U\n" + getM3uList(tor.Status(), utils2.GetScheme(c)+"://"+c.Request.Host, fromlast)
sendM3U(c, name, tor.Hash().HexString(), m3ulist)
return
} else
// return play if query
if play {
tor.Stream(index, c.Request, c.Writer)
return
}
}
func streamNoAuth(c *gin.Context) {
link := c.Query("link")
indexStr := c.Query("index")
_, preload := c.GetQuery("preload")
_, m3u := c.GetQuery("m3u")
_, fromlast := c.GetQuery("fromlast")
_, play := c.GetQuery("play")
title := c.Query("title")
poster := c.Query("poster")
data := ""
if link == "" {
c.AbortWithError(http.StatusBadRequest, errors.New("link should not be empty"))
return
}
link, _ = url.QueryUnescape(link)
spec, err := utils.ParseLink(link)
if err != nil {
c.AbortWithError(http.StatusInternalServerError, err)
return
}
tor := torr.GetTorrent(spec.InfoHash.HexString())
if tor == nil {
c.Header("WWW-Authenticate", "Basic realm=Authorization Required")
c.AbortWithStatus(http.StatusUnauthorized)
return
}
title = tor.Title
poster = tor.Poster
data = tor.Data
if tor.Stat == state.TorrentInDB {
tor, err = torr.AddTorrent(spec, title, poster, data)
if err != nil {
c.AbortWithError(http.StatusInternalServerError, err)
return
}
}
if !tor.GotInfo() {
c.AbortWithError(http.StatusInternalServerError, errors.New("timeout connection torrent"))
return
}
// find file
index := -1
if len(tor.Files()) == 1 {
index = 1
} else {
ind, err := strconv.Atoi(indexStr)
if err == nil {
index = ind
}
}
if index == -1 && play { // if file index not set and play file exec
c.AbortWithError(http.StatusBadRequest, errors.New("\"index\" is empty or wrong"))
return
}
// preload torrent
if preload {
torr.Preload(tor, index)
}
// return m3u if query
if m3u {
m3ulist := "#EXTM3U\n" + getM3uList(tor.Status(), utils2.GetScheme(c)+"://"+c.Request.Host, fromlast)
sendM3U(c, tor.Name()+".m3u", tor.Hash().HexString(), m3ulist)
return
} else
// return play if query
if play {
tor.Stream(index, c.Request, c.Writer)
return
}
c.Header("WWW-Authenticate", "Basic realm=Authorization Required")
c.AbortWithStatus(http.StatusUnauthorized)
}