mirror of
https://github.com/Ernous/TorrServerJellyfin.git
synced 2025-12-19 13:36:09 +05:00
refactor and to go mod
This commit is contained in:
51
server/web/api/cache.go
Normal file
51
server/web/api/cache.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"server/torr"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
//Action: get
|
||||
type cacheReqJS struct {
|
||||
requestI
|
||||
Hash string `json:"hash,omitempty"`
|
||||
}
|
||||
|
||||
func cache(c *gin.Context) {
|
||||
var req cacheReqJS
|
||||
err := c.ShouldBindJSON(&req)
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
c.Status(http.StatusBadRequest)
|
||||
switch req.Action {
|
||||
case "get":
|
||||
{
|
||||
getCache(req, c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getCache(req cacheReqJS, c *gin.Context) {
|
||||
if req.Hash == "" {
|
||||
c.AbortWithError(http.StatusBadRequest, errors.New("hash is empty"))
|
||||
return
|
||||
}
|
||||
tor := torr.GetTorrent(req.Hash)
|
||||
|
||||
if tor != nil {
|
||||
st := tor.CacheState()
|
||||
if st == nil {
|
||||
c.JSON(200, struct{}{})
|
||||
} else {
|
||||
c.JSON(200, st)
|
||||
}
|
||||
} else {
|
||||
c.Status(http.StatusNotFound)
|
||||
}
|
||||
}
|
||||
41
server/web/api/doc.go
Normal file
41
server/web/api/doc.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package api
|
||||
|
||||
/*
|
||||
API
|
||||
|
||||
respnose JSON{
|
||||
|
||||
}
|
||||
request JSON{
|
||||
Action string
|
||||
}
|
||||
|
||||
echo version
|
||||
|
||||
{
|
||||
add torrent
|
||||
remove torrent
|
||||
list all torrents
|
||||
get torrent
|
||||
stream torrent
|
||||
} all in one function
|
||||
|
||||
{
|
||||
get viewed files mark in torrent
|
||||
set viewed files mark in torrent
|
||||
rem viewed files mark in torrent
|
||||
} all in one
|
||||
|
||||
{
|
||||
get m3u list of one torrent
|
||||
get m3u list of one torrent and resume play
|
||||
get m3u list of all torrent
|
||||
}
|
||||
|
||||
{
|
||||
get settings
|
||||
set settings
|
||||
}
|
||||
|
||||
???
|
||||
*/
|
||||
125
server/web/api/m3u.go
Normal file
125
server/web/api/m3u.go
Normal file
@@ -0,0 +1,125 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/anacrolix/missinggo/httptoo"
|
||||
sets "server/settings"
|
||||
"server/torr"
|
||||
"server/torr/state"
|
||||
"server/utils"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func allPlayList(c *gin.Context) {
|
||||
torrs := torr.ListTorrent()
|
||||
|
||||
host := "http://" + c.Request.Host
|
||||
list := "#EXTM3U\n"
|
||||
hash := ""
|
||||
// fn=file.m3u fix forkplayer bug with end .m3u in link
|
||||
for _, tr := range torrs {
|
||||
list += "#EXTINF:0 type=\"playlist\"," + tr.Title + "\n"
|
||||
list += host + "/stream/" + url.PathEscape(tr.Title) + ".m3u?link=" + tr.TorrentSpec.InfoHash.HexString() + "&m3u&fn=file.m3u\n"
|
||||
hash += tr.Hash().HexString()
|
||||
}
|
||||
|
||||
sendM3U(c, "all.m3u", hash, list)
|
||||
}
|
||||
|
||||
// http://127.0.0.1:8090/playlist?hash=...
|
||||
// http://127.0.0.1:8090/playlist?hash=...&fromlast
|
||||
func playList(c *gin.Context) {
|
||||
hash, _ := c.GetQuery("hash")
|
||||
_, fromlast := c.GetQuery("fromlast")
|
||||
if hash == "" {
|
||||
c.AbortWithError(http.StatusBadRequest, errors.New("hash is empty"))
|
||||
return
|
||||
}
|
||||
|
||||
tor := torr.GetTorrent(hash)
|
||||
if tor == nil {
|
||||
c.AbortWithStatus(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
if !tor.WaitInfo() {
|
||||
c.AbortWithError(http.StatusInternalServerError, errors.New("error get torrent info"))
|
||||
return
|
||||
}
|
||||
|
||||
host := "http://" + c.Request.Host
|
||||
list := getM3uList(tor.Status(), host, fromlast)
|
||||
list = "#EXTM3U\n" + list
|
||||
|
||||
sendM3U(c, tor.Name()+".m3u", tor.Hash().HexString(), list)
|
||||
}
|
||||
|
||||
func sendM3U(c *gin.Context, name, hash string, m3u string) {
|
||||
c.Header("Content-Type", "audio/x-mpegurl")
|
||||
c.Header("Connection", "close")
|
||||
if hash != "" {
|
||||
c.Header("ETag", httptoo.EncodeQuotedString(fmt.Sprintf("%s/%s", hash, name)))
|
||||
}
|
||||
if name == "" {
|
||||
name = "playlist.m3u"
|
||||
}
|
||||
c.Header("Content-Disposition", `attachment; filename="`+name+`"`)
|
||||
http.ServeContent(c.Writer, c.Request, name, time.Now(), bytes.NewReader([]byte(m3u)))
|
||||
c.Status(200)
|
||||
}
|
||||
|
||||
func getM3uList(tor *state.TorrentStatus, host string, fromLast bool) string {
|
||||
m3u := ""
|
||||
from := 0
|
||||
if fromLast {
|
||||
pos := searchLastPlayed(tor)
|
||||
if pos != -1 {
|
||||
from = pos
|
||||
}
|
||||
}
|
||||
for i, f := range tor.FileStats {
|
||||
if i >= from {
|
||||
if utils.GetMimeType(f.Path) != "*/*" {
|
||||
fn := filepath.Base(f.Path)
|
||||
if fn == "" {
|
||||
fn = f.Path
|
||||
}
|
||||
m3u += "#EXTINF:0," + fn + "\n"
|
||||
name := filepath.Base(f.Path)
|
||||
m3u += host + "/stream/" + url.PathEscape(name) + "?link=" + tor.Hash + "&index=" + fmt.Sprint(f.Id) + "&play\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
return m3u
|
||||
}
|
||||
|
||||
func searchLastPlayed(tor *state.TorrentStatus) int {
|
||||
viewed := sets.ListViewed(tor.Hash)
|
||||
if len(viewed) == 0 {
|
||||
return -1
|
||||
}
|
||||
sort.Slice(viewed, func(i, j int) bool {
|
||||
return viewed[i].FileIndex > viewed[j].FileIndex
|
||||
})
|
||||
|
||||
lastViewedIndex := viewed[0].FileIndex
|
||||
|
||||
for i, stat := range tor.FileStats {
|
||||
if stat.Id == lastViewedIndex {
|
||||
if i >= len(tor.FileStats) {
|
||||
return -1
|
||||
}
|
||||
return i
|
||||
}
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
55
server/web/api/route.go
Normal file
55
server/web/api/route.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
sets "server/settings"
|
||||
"server/torr"
|
||||
"server/version"
|
||||
)
|
||||
|
||||
type requestI struct {
|
||||
Action string `json:"action,omitempty"`
|
||||
}
|
||||
|
||||
func SetupRoute(route *gin.Engine) {
|
||||
route.GET("/echo", echo)
|
||||
route.GET("/shutdown", shutdown)
|
||||
|
||||
route.POST("/settings", settings)
|
||||
|
||||
route.POST("/torrents", torrents)
|
||||
route.POST("/torrent/upload", torrentUpload)
|
||||
|
||||
route.POST("/cache", cache)
|
||||
|
||||
route.HEAD("/stream", stream)
|
||||
route.HEAD("/stream/*fname", stream)
|
||||
|
||||
route.GET("/stream", stream)
|
||||
route.GET("/stream/*fname", stream)
|
||||
|
||||
route.POST("/viewed", viewed)
|
||||
|
||||
route.GET("/playlistall/all.m3u", allPlayList)
|
||||
route.GET("/playlist", playList)
|
||||
route.GET("/playlist/*fname", playList)
|
||||
}
|
||||
|
||||
func echo(c *gin.Context) {
|
||||
c.String(200, "%v", version.Version)
|
||||
}
|
||||
|
||||
func shutdown(c *gin.Context) {
|
||||
if sets.ReadOnly {
|
||||
c.Status(http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
c.Status(200)
|
||||
go func() {
|
||||
time.Sleep(1000)
|
||||
torr.Shutdown()
|
||||
}()
|
||||
}
|
||||
37
server/web/api/settings.go
Normal file
37
server/web/api/settings.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
sets "server/settings"
|
||||
"server/torr"
|
||||
)
|
||||
|
||||
//Action: get, set
|
||||
type setsReqJS struct {
|
||||
requestI
|
||||
Sets *sets.BTSets `json:"sets,omitempty"`
|
||||
}
|
||||
|
||||
func settings(c *gin.Context) {
|
||||
var req setsReqJS
|
||||
err := c.ShouldBindJSON(&req)
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
if req.Action == "get" {
|
||||
c.JSON(200, sets.BTsets)
|
||||
return
|
||||
}
|
||||
if req.Action == "set" {
|
||||
torr.SetSettings(req.Sets)
|
||||
c.Status(200)
|
||||
return
|
||||
}
|
||||
c.AbortWithError(http.StatusBadRequest, errors.New("action is empty"))
|
||||
}
|
||||
113
server/web/api/stream.go
Normal file
113
server/web/api/stream.go
Normal file
@@ -0,0 +1,113 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"server/torr"
|
||||
"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&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")
|
||||
|
||||
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, err := torr.AddTorrent(spec, title, poster, "")
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
if !tor.GotInfo() {
|
||||
c.AbortWithError(http.StatusInternalServerError, errors.New("timeout connection torrent"))
|
||||
return
|
||||
}
|
||||
|
||||
// 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 {
|
||||
m3ulist := "#EXTM3U\n" + getM3uList(tor.Status(), "http://"+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
|
||||
}
|
||||
}
|
||||
137
server/web/api/torrents.go
Normal file
137
server/web/api/torrents.go
Normal file
@@ -0,0 +1,137 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"server/log"
|
||||
"server/torr"
|
||||
"server/torr/state"
|
||||
"server/web/api/utils"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
//Action: add, get, rem, list, drop
|
||||
type torrReqJS struct {
|
||||
requestI
|
||||
Link string `json:"link,omitempty"`
|
||||
Hash string `json:"hash,omitempty"`
|
||||
Title string `json:"title,omitempty"`
|
||||
Poster string `json:"poster,omitempty"`
|
||||
Data string `json:"data,omitempty"`
|
||||
SaveToDB bool `json:"save_to_db,omitempty"`
|
||||
}
|
||||
|
||||
func torrents(c *gin.Context) {
|
||||
var req torrReqJS
|
||||
err := c.ShouldBindJSON(&req)
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
c.Status(http.StatusBadRequest)
|
||||
switch req.Action {
|
||||
case "add":
|
||||
{
|
||||
addTorrent(req, c)
|
||||
}
|
||||
case "get":
|
||||
{
|
||||
getTorrent(req, c)
|
||||
}
|
||||
case "rem":
|
||||
{
|
||||
remTorrent(req, c)
|
||||
}
|
||||
case "list":
|
||||
{
|
||||
listTorrent(req, c)
|
||||
}
|
||||
case "drop":
|
||||
{
|
||||
dropTorrent(req, c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func addTorrent(req torrReqJS, c *gin.Context) {
|
||||
if req.Link == "" {
|
||||
c.AbortWithError(http.StatusBadRequest, errors.New("link is empty"))
|
||||
return
|
||||
}
|
||||
|
||||
log.TLogln("add torrent", req.Link)
|
||||
torrSpec, err := utils.ParseLink(req.Link)
|
||||
if err != nil {
|
||||
log.TLogln("error add torrent:", err)
|
||||
c.AbortWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
tor, err := torr.AddTorrent(torrSpec, req.Title, req.Poster, req.Data)
|
||||
if err != nil {
|
||||
log.TLogln("error add torrent:", err)
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
go func() {
|
||||
if !tor.GotInfo() {
|
||||
log.TLogln("error add torrent:", "timeout connection torrent")
|
||||
return
|
||||
}
|
||||
|
||||
if req.SaveToDB {
|
||||
torr.SaveTorrentToDB(tor)
|
||||
}
|
||||
}()
|
||||
|
||||
c.JSON(200, tor.Status())
|
||||
}
|
||||
|
||||
func getTorrent(req torrReqJS, c *gin.Context) {
|
||||
if req.Hash == "" {
|
||||
c.AbortWithError(http.StatusBadRequest, errors.New("hash is empty"))
|
||||
return
|
||||
}
|
||||
tor := torr.GetTorrent(req.Hash)
|
||||
|
||||
if tor != nil {
|
||||
st := tor.Status()
|
||||
c.JSON(200, st)
|
||||
} else {
|
||||
c.Status(http.StatusNotFound)
|
||||
}
|
||||
}
|
||||
|
||||
func remTorrent(req torrReqJS, c *gin.Context) {
|
||||
if req.Hash == "" {
|
||||
c.AbortWithError(http.StatusBadRequest, errors.New("hash is empty"))
|
||||
return
|
||||
}
|
||||
torr.RemTorrent(req.Hash)
|
||||
c.Status(200)
|
||||
}
|
||||
|
||||
func listTorrent(req torrReqJS, c *gin.Context) {
|
||||
list := torr.ListTorrent()
|
||||
if list == nil {
|
||||
c.JSON(200, []*state.TorrentStatus{})
|
||||
return
|
||||
}
|
||||
var stats []*state.TorrentStatus
|
||||
for _, tr := range list {
|
||||
stats = append(stats, tr.Status())
|
||||
}
|
||||
c.JSON(200, stats)
|
||||
}
|
||||
|
||||
func dropTorrent(req torrReqJS, c *gin.Context) {
|
||||
if req.Hash == "" {
|
||||
c.AbortWithError(http.StatusBadRequest, errors.New("hash is empty"))
|
||||
return
|
||||
}
|
||||
torr.DropTorrent(req.Hash)
|
||||
c.Status(200)
|
||||
}
|
||||
70
server/web/api/upload.go
Normal file
70
server/web/api/upload.go
Normal file
@@ -0,0 +1,70 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"server/log"
|
||||
"server/torr"
|
||||
"server/web/api/utils"
|
||||
)
|
||||
|
||||
func torrentUpload(c *gin.Context) {
|
||||
form, err := c.MultipartForm()
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
defer form.RemoveAll()
|
||||
|
||||
save := len(form.Value["save"]) > 0
|
||||
title := ""
|
||||
if len(form.Value["title"]) > 0 {
|
||||
title = form.Value["title"][0]
|
||||
}
|
||||
poster := ""
|
||||
if len(form.Value["poster"]) > 0 {
|
||||
poster = form.Value["poster"][0]
|
||||
}
|
||||
data := ""
|
||||
if len(form.Value["data"]) > 0 {
|
||||
data = form.Value["data"][0]
|
||||
}
|
||||
var tor *torr.Torrent
|
||||
for name, file := range form.File {
|
||||
log.TLogln("add torrent file", name)
|
||||
|
||||
torrFile, err := file[0].Open()
|
||||
if err != nil {
|
||||
log.TLogln("error upload torrent:", err)
|
||||
continue
|
||||
}
|
||||
defer torrFile.Close()
|
||||
|
||||
spec, err := utils.ParseFile(torrFile)
|
||||
if err != nil {
|
||||
log.TLogln("error upload torrent:", err)
|
||||
continue
|
||||
}
|
||||
|
||||
tor, err = torr.AddTorrent(spec, title, poster, data)
|
||||
if err != nil {
|
||||
log.TLogln("error upload torrent:", err)
|
||||
continue
|
||||
}
|
||||
|
||||
go func() {
|
||||
if !tor.GotInfo() {
|
||||
log.TLogln("error add torrent:", "timeout connection torrent")
|
||||
return
|
||||
}
|
||||
|
||||
if save {
|
||||
torr.SaveTorrentToDB(tor)
|
||||
}
|
||||
}()
|
||||
|
||||
break
|
||||
}
|
||||
c.JSON(200, tor.Status())
|
||||
}
|
||||
133
server/web/api/utils/link.go
Normal file
133
server/web/api/utils/link.go
Normal file
@@ -0,0 +1,133 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/anacrolix/torrent"
|
||||
"github.com/anacrolix/torrent/metainfo"
|
||||
)
|
||||
|
||||
func ParseFile(file multipart.File) (*torrent.TorrentSpec, error) {
|
||||
minfo, err := metainfo.Load(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
info, err := minfo.UnmarshalInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mag := minfo.Magnet(info.Name, minfo.HashInfoBytes())
|
||||
return &torrent.TorrentSpec{
|
||||
InfoBytes: minfo.InfoBytes,
|
||||
Trackers: [][]string{mag.Trackers},
|
||||
DisplayName: info.Name,
|
||||
InfoHash: minfo.HashInfoBytes(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func ParseLink(link string) (*torrent.TorrentSpec, error) {
|
||||
urlLink, err := url.Parse(link)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch strings.ToLower(urlLink.Scheme) {
|
||||
case "magnet":
|
||||
return fromMagnet(urlLink.String())
|
||||
case "http", "https":
|
||||
return fromHttp(urlLink.String())
|
||||
case "":
|
||||
return fromMagnet("magnet:?xt=urn:btih:" + urlLink.Path)
|
||||
case "file":
|
||||
return fromFile(urlLink.Path)
|
||||
default:
|
||||
err = fmt.Errorf("unknown scheme:", urlLink, urlLink.Scheme)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func fromMagnet(link string) (*torrent.TorrentSpec, error) {
|
||||
mag, err := metainfo.ParseMagnetUri(link)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var trackers [][]string
|
||||
if len(mag.Trackers) > 0 {
|
||||
trackers = [][]string{mag.Trackers}
|
||||
}
|
||||
|
||||
return &torrent.TorrentSpec{
|
||||
InfoBytes: nil,
|
||||
Trackers: trackers,
|
||||
DisplayName: mag.DisplayName,
|
||||
InfoHash: mag.InfoHash,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func fromHttp(url string) (*torrent.TorrentSpec, error) {
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client := new(http.Client)
|
||||
client.Timeout = time.Duration(time.Second * 30)
|
||||
req.Header.Set("User-Agent", "DWL/1.1.1 (Torrent)")
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != 200 {
|
||||
return nil, errors.New(resp.Status)
|
||||
}
|
||||
|
||||
minfo, err := metainfo.Load(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
info, err := minfo.UnmarshalInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mag := minfo.Magnet(info.Name, minfo.HashInfoBytes())
|
||||
|
||||
return &torrent.TorrentSpec{
|
||||
InfoBytes: minfo.InfoBytes,
|
||||
Trackers: [][]string{mag.Trackers},
|
||||
DisplayName: info.Name,
|
||||
InfoHash: minfo.HashInfoBytes(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func fromFile(path string) (*torrent.TorrentSpec, error) {
|
||||
if runtime.GOOS == "windows" && strings.HasPrefix(path, "/") {
|
||||
path = strings.TrimPrefix(path, "/")
|
||||
}
|
||||
minfo, err := metainfo.LoadFromFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
info, err := minfo.UnmarshalInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mag := minfo.Magnet(info.Name, minfo.HashInfoBytes())
|
||||
return &torrent.TorrentSpec{
|
||||
InfoBytes: minfo.InfoBytes,
|
||||
Trackers: [][]string{mag.Trackers},
|
||||
DisplayName: info.Name,
|
||||
InfoHash: minfo.HashInfoBytes(),
|
||||
}, nil
|
||||
}
|
||||
57
server/web/api/viewed.go
Normal file
57
server/web/api/viewed.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
sets "server/settings"
|
||||
)
|
||||
|
||||
/*
|
||||
file index starts from 1
|
||||
*/
|
||||
|
||||
// Action: set, rem, list
|
||||
type viewedReqJS struct {
|
||||
requestI
|
||||
*sets.Viewed
|
||||
}
|
||||
|
||||
func viewed(c *gin.Context) {
|
||||
var req viewedReqJS
|
||||
err := c.ShouldBindJSON(&req)
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
switch req.Action {
|
||||
case "set":
|
||||
{
|
||||
setViewed(req, c)
|
||||
}
|
||||
case "rem":
|
||||
{
|
||||
remViewed(req, c)
|
||||
}
|
||||
case "list":
|
||||
{
|
||||
listViewed(req, c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setViewed(req viewedReqJS, c *gin.Context) {
|
||||
sets.SetViewed(req.Viewed)
|
||||
c.Status(200)
|
||||
}
|
||||
|
||||
func remViewed(req viewedReqJS, c *gin.Context) {
|
||||
sets.RemViewed(req.Viewed)
|
||||
c.Status(200)
|
||||
}
|
||||
|
||||
func listViewed(req viewedReqJS, c *gin.Context) {
|
||||
list := sets.ListViewed(req.Hash)
|
||||
c.JSON(200, list)
|
||||
}
|
||||
Reference in New Issue
Block a user