mirror of
https://github.com/Ernous/TorrServerJellyfin.git
synced 2025-12-19 21:46:11 +05:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -76,6 +76,10 @@ func loadBTSets() {
|
|||||||
log.TLogln("Error unmarshal btsets", err)
|
log.TLogln("Error unmarshal btsets", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SetDefault()
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetDefault() {
|
||||||
sets := new(BTSets)
|
sets := new(BTSets)
|
||||||
sets.EnableDebug = false
|
sets.EnableDebug = false
|
||||||
sets.DisableUTP = true
|
sets.DisableUTP = true
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ func GetTorrent(hashHex string) *Torrent {
|
|||||||
if tr != nil {
|
if tr != nil {
|
||||||
tr.Title = tor.Title
|
tr.Title = tor.Title
|
||||||
tr.Poster = tor.Poster
|
tr.Poster = tor.Poster
|
||||||
|
tr.Data = tor.Data
|
||||||
tr.Size = tor.Size
|
tr.Size = tor.Size
|
||||||
tr.Timestamp = tor.Timestamp
|
tr.Timestamp = tor.Timestamp
|
||||||
tr.GotInfo()
|
tr.GotInfo()
|
||||||
@@ -128,6 +129,15 @@ func SetSettings(set *sets.BTSets) {
|
|||||||
bts.Connect()
|
bts.Connect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SetDefSettings() {
|
||||||
|
if sets.ReadOnly {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
bts.Disconnect()
|
||||||
|
sets.SetDefault()
|
||||||
|
bts.Connect()
|
||||||
|
}
|
||||||
|
|
||||||
func Shutdown() {
|
func Shutdown() {
|
||||||
bts.Disconnect()
|
bts.Disconnect()
|
||||||
sets.CloseDB()
|
sets.CloseDB()
|
||||||
|
|||||||
@@ -46,20 +46,6 @@ func (t *Torrent) Stream(fileID int, req *http.Request, resp http.ResponseWriter
|
|||||||
|
|
||||||
reader := t.NewReader(file)
|
reader := t.NewReader(file)
|
||||||
|
|
||||||
//off := int64(0)
|
|
||||||
//buf := make([]byte, 32*1024)
|
|
||||||
//for true {
|
|
||||||
// n, err := reader.Read(buf)
|
|
||||||
// if err != nil {
|
|
||||||
// fmt.Println("error read", err)
|
|
||||||
// break
|
|
||||||
// }
|
|
||||||
// off = off + int64(n)
|
|
||||||
// if off%(200*1024*1024) == 0 {
|
|
||||||
// time.Sleep(time.Second * 15)
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
log.Println("Connect client")
|
log.Println("Connect client")
|
||||||
|
|
||||||
sets.SetViewed(&sets.Viewed{t.Hash().HexString(), fileID})
|
sets.SetViewed(&sets.Viewed{t.Hash().HexString(), fileID})
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
"server/torr"
|
"server/torr"
|
||||||
)
|
)
|
||||||
|
|
||||||
//Action: get, set
|
//Action: get, set, def
|
||||||
type setsReqJS struct {
|
type setsReqJS struct {
|
||||||
requestI
|
requestI
|
||||||
Sets *sets.BTSets `json:"sets,omitempty"`
|
Sets *sets.BTSets `json:"sets,omitempty"`
|
||||||
@@ -27,11 +27,14 @@ func settings(c *gin.Context) {
|
|||||||
if req.Action == "get" {
|
if req.Action == "get" {
|
||||||
c.JSON(200, sets.BTsets)
|
c.JSON(200, sets.BTsets)
|
||||||
return
|
return
|
||||||
}
|
} else if req.Action == "set" {
|
||||||
if req.Action == "set" {
|
|
||||||
torr.SetSettings(req.Sets)
|
torr.SetSettings(req.Sets)
|
||||||
c.Status(200)
|
c.Status(200)
|
||||||
return
|
return
|
||||||
|
} else if req.Action == "def" {
|
||||||
|
torr.SetDefSettings()
|
||||||
|
c.Status(200)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
c.AbortWithError(http.StatusBadRequest, errors.New("action is empty"))
|
c.AbortWithError(http.StatusBadRequest, errors.New("action is empty"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,17 @@ func stream(c *gin.Context) {
|
|||||||
_, play := c.GetQuery("play")
|
_, play := c.GetQuery("play")
|
||||||
title := c.Query("title")
|
title := c.Query("title")
|
||||||
poster := c.Query("poster")
|
poster := c.Query("poster")
|
||||||
|
notAuth := c.GetBool("not_auth")
|
||||||
|
|
||||||
|
if notAuth && play {
|
||||||
|
streamNoAuth(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if notAuth {
|
||||||
|
c.Header("WWW-Authenticate", "Basic realm=Authorization Required")
|
||||||
|
c.AbortWithStatus(http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if link == "" {
|
if link == "" {
|
||||||
c.AbortWithError(http.StatusBadRequest, errors.New("link should not be empty"))
|
c.AbortWithError(http.StatusBadRequest, errors.New("link should not be empty"))
|
||||||
@@ -111,3 +122,65 @@ func stream(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func streamNoAuth(c *gin.Context) {
|
||||||
|
link := c.Query("link")
|
||||||
|
indexStr := c.Query("index")
|
||||||
|
_, preload := c.GetQuery("preload")
|
||||||
|
title := c.Query("title")
|
||||||
|
poster := c.Query("poster")
|
||||||
|
|
||||||
|
if link == "" {
|
||||||
|
c.AbortWithError(http.StatusBadRequest, errors.New("link should not be empty"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if title == "" {
|
||||||
|
title = c.Param("fname")
|
||||||
|
title, _ = url.PathUnescape(title)
|
||||||
|
title = strings.TrimLeft(title, "/")
|
||||||
|
} else {
|
||||||
|
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 {
|
||||||
|
c.AbortWithError(http.StatusNotFound, errors.New("Torrent not found"))
|
||||||
|
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 { // 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
tor.Stream(index, c.Request, c.Writer)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
package auth
|
package auth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
@@ -19,7 +24,7 @@ func SetupAuth(engine *gin.Engine) *gin.RouterGroup {
|
|||||||
if accs == nil {
|
if accs == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return engine.Group("/", gin.BasicAuth(accs))
|
return engine.Group("/", BasicAuth(accs))
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAccounts() gin.Accounts {
|
func getAccounts() gin.Accounts {
|
||||||
@@ -34,3 +39,62 @@ func getAccounts() gin.Accounts {
|
|||||||
}
|
}
|
||||||
return accs
|
return accs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type authPair struct {
|
||||||
|
value string
|
||||||
|
user string
|
||||||
|
}
|
||||||
|
type authPairs []authPair
|
||||||
|
|
||||||
|
func (a authPairs) searchCredential(authValue string) (string, bool) {
|
||||||
|
if authValue == "" {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
for _, pair := range a {
|
||||||
|
if pair.value == authValue {
|
||||||
|
return pair.user, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
func BasicAuth(accounts gin.Accounts) gin.HandlerFunc {
|
||||||
|
pairs := processAccounts(accounts)
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
user, found := pairs.searchCredential(c.Request.Header.Get("Authorization"))
|
||||||
|
if !found {
|
||||||
|
if strings.HasPrefix(c.FullPath(), "/stream") {
|
||||||
|
c.Set("not_auth", true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Header("WWW-Authenticate", "Basic realm=Authorization Required")
|
||||||
|
c.AbortWithStatus(http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Set(gin.AuthUserKey, user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func processAccounts(accounts gin.Accounts) authPairs {
|
||||||
|
pairs := make(authPairs, 0, len(accounts))
|
||||||
|
for user, password := range accounts {
|
||||||
|
value := authorizationHeader(user, password)
|
||||||
|
pairs = append(pairs, authPair{
|
||||||
|
value: value,
|
||||||
|
user: user,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return pairs
|
||||||
|
}
|
||||||
|
|
||||||
|
func authorizationHeader(user, password string) string {
|
||||||
|
base := user + ":" + password
|
||||||
|
return "Basic " + base64.StdEncoding.EncodeToString(StringToBytes(base))
|
||||||
|
}
|
||||||
|
|
||||||
|
func StringToBytes(s string) (b []byte) {
|
||||||
|
sh := *(*reflect.StringHeader)(unsafe.Pointer(&s))
|
||||||
|
bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
|
||||||
|
bh.Data, bh.Len, bh.Cap = sh.Data, sh.Len, sh.Len
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user