diff --git a/server/web/msx/msx.go b/server/web/msx/msx.go
index 9b99511..3422e2d 100644
--- a/server/web/msx/msx.go
+++ b/server/web/msx/msx.go
@@ -1,141 +1,162 @@
package msx
import (
- _ "embed"
"encoding/json"
"net/http"
- "sync"
-
+ "net/url"
+ "os"
+ "path"
+ "path/filepath"
+ "server/settings"
+ "server/torr"
"server/version"
"server/web/auth"
+ "strconv"
+ "strings"
"github.com/gin-gonic/gin"
)
-var (
- //go:embed russian.json.gz
- rus []byte
- //go:embed torrents.js.gz
- trs []byte
- //go:embed torrent.js.gz
- trn []byte
- //go:embed ts.js.gz
- its []byte
-
- idb = new(sync.Mutex)
- ids = make(map[string]string)
-)
-
-func asset(c *gin.Context, t string, d []byte) {
- c.Header("Content-Encoding", "gzip")
- c.Data(200, t+"; charset=UTF-8", d)
-}
+const base, fls = "https://damiva.github.io/msx", "files"
func SetupRoute(r gin.IRouter) {
authorized := r.Group("/", auth.CheckAuth())
-
- authorized.GET("/msx/:pth", msxPTH)
- authorized.GET("/msx/imdb", msxIMDB)
- authorized.GET("/msx/imdb/:id", msxIMDBID)
-}
-
-// msxPTH godoc
-//
-// @Summary Multi usage endpoint
-// @Description Multi usage endpoint.
-//
-// @Tags MSX
-//
-// @Param link path string true "Route MSX pages"
-//
-// @Produce json
-// @Success 200 "Data returned according to path"
-// @Router /msx/{pth} [get]
-func msxPTH(c *gin.Context) {
- js := []string{"http://msx.benzac.de/js/tvx-plugin.min.js"}
- switch p := c.Param("pth"); p {
- case "start.json":
- c.JSON(200, map[string]string{
- "name": "TorrServer",
- "version": version.Version,
- "parameter": "menu:request:interaction:init@{PREFIX}{SERVER}/msx/ts",
- })
- case "russian.json":
- asset(c, "application/json", rus)
- case "torrents.js":
- asset(c, "text/javascript", trs)
- case "torrent.js":
- asset(c, "text/javascript", trn)
- case "ts.js":
- asset(c, "text/javascript", its)
- case "torrents":
- js = append(js, p+".js")
- p = "torrent"
- fallthrough
- case "torrent":
- if c.Query("platform") == "tizen" {
- js = append(js, "http://msx.benzac.de/interaction/js/tizen-player.js")
- }
- fallthrough
- case "ts":
- b := []byte("\n\n
\nTorrServer Plugin\n\n")
- for _, j := range append(js, p+".js") {
- b = append(b, "\n"...)
- }
- c.Data(200, "text/html; charset=UTF-8", append(b, "\n\n"...))
- default:
- c.AbortWithStatus(404)
- }
-}
-
-// msxIMDB godoc
-//
-// @Summary Get MSX IMDB informations
-// @Description Get MSX IMDB informations.
-//
-// @Tags MSX
-//
-// @Produce json
-// @Success 200 "JSON MSX IMDB informations"
-// @Router /msx/imdb [get]
-func msxIMDB(c *gin.Context) {
- idb.Lock()
- defer idb.Unlock()
- l := len(ids)
- ids = make(map[string]string)
- c.JSON(200, l)
-}
-
-// msxIMDB godoc
-//
-// @Summary Get MSX IMDB informations
-// @Description Get MSX IMDB informations.
-//
-// @Tags MSX
-//
-// @Param id path string true "IMDB ID"
-//
-// @Produce json
-// @Success 200 "JSON MSX IMDB informations"
-// @Router /msx/imdb/{id} [get]
-func msxIMDBID(c *gin.Context) {
- idb.Lock()
- defer idb.Unlock()
- p := c.Param("id")
- i, o := ids[p]
- if !o {
- if r, e := http.Get("https://v2.sg.media-imdb.com/suggestion/h/" + p + ".json"); e == nil {
- defer r.Body.Close()
- if r.StatusCode == 200 {
- var j struct {
- D []struct{ I struct{ ImageUrl string } }
- }
- if e = json.NewDecoder(r.Body).Decode(&j); e == nil && len(j.D) > 0 {
- i = j.D[0].I.ImageUrl
+ authorized.Any("/msx", func(c *gin.Context) {
+ if l := c.Query("url"); l != "" {
+ proxy(c, l, c.QueryArray("header")...)
+ } else if l = c.Query("indb"); l != "" {
+ var r bool
+ for _, t := range settings.ListTorrent() {
+ if r = t.InfoHash.HexString() == l; r {
+ break
}
}
+ c.JSON(200, r)
+ } else if c.Request.Method == "POST" {
+ serve(c)
+ } else {
+ proxy(c, base+"/ts.html")
}
- ids[p] = i
- }
- c.JSON(200, i)
+ })
+ authorized.GET("/msx/*pth", func(c *gin.Context) {
+ p := c.Param("pth")
+ if _, n := path.Split(p); n == "" {
+ files(c, filepath.Join(fls, filepath.Clean(p)))
+ } else if n = strings.ToLower(path.Ext(n)); n == "" {
+ c.AbortWithStatus(http.StatusNotFound)
+ } else if n == ".html" || n == ".js" || n == ".json" {
+ proxy(c, base+p)
+ } else {
+ c.File(filepath.Join(fls, filepath.Clean(p)))
+ }
+ })
+ authorized.GET("/imdb/:id", func(c *gin.Context) {
+ const x = ".json"
+ i, l := c.Param("id"), ""
+ j := strings.HasSuffix(i, x)
+ if i = strings.TrimSuffix(i, x); i != "" {
+ if r, e := http.Get("https://v2.sg.media-imdb.com/suggestion/h/" + i + x); e == nil {
+ if r.StatusCode == http.StatusOK {
+ var j struct {
+ D []struct{ I struct{ ImageUrl string } }
+ }
+ if e = json.NewDecoder(r.Body).Decode(&j); e == nil && len(j.D) > 0 {
+ l = j.D[0].I.ImageUrl
+ }
+ }
+ r.Body.Close()
+ }
+ }
+ if j {
+ c.JSON(200, l)
+ } else if l == "" {
+ c.Status(http.StatusNotFound)
+ } else {
+ c.Redirect(http.StatusMovedPermanently, l)
+ }
+ })
+}
+func proxy(c *gin.Context, u string, h ...string) {
+ if u == "" {
+ c.AbortWithStatus(http.StatusBadRequest)
+ } else if q, e := http.NewRequest(c.Request.Method, u, c.Request.Body); e != nil {
+ c.AbortWithError(http.StatusInternalServerError, e)
+ } else {
+ for _, v := range h {
+ if v := strings.SplitN(v, ":", 2); len(v) == 2 {
+ q.Header.Add(v[0], v[1])
+ }
+ }
+ if r, e := http.DefaultClient.Do(q); e != nil {
+ c.AbortWithError(http.StatusInternalServerError, e)
+ } else {
+ c.DataFromReader(r.StatusCode, r.ContentLength, r.Header.Get("Content-Type"), r.Body, nil)
+ r.Body.Close()
+ }
+ }
+}
+func serve(c *gin.Context) {
+ var j struct {
+ Data struct {
+ Update string
+ Info struct{ Content struct{ Flag string } }
+ }
+ }
+ if e := c.Bind(&j); e != nil {
+ c.AbortWithError(http.StatusBadRequest, e)
+ } else if j.Data.Update == "" && j.Data.Info.Content.Flag == "" {
+ r := map[string]any{"version": version.Version, "search": settings.BTsets.EnableRutorSearch}
+ if l, e := os.Readlink(fls); e == nil {
+ r["files"] = l
+ } else if !os.IsNotExist(e) {
+ r["error"] = e.Error()
+ }
+ c.JSON(200, r)
+ } else {
+ var r map[string]any
+ h, sc, st := j.Data.Info.Content.Flag, "", ""
+ if h == "" {
+ h = j.Data.Update[strings.LastIndexByte(j.Data.Update, ':')+1:]
+ }
+ if t := torr.GetTorrent(h); t != nil {
+ if t := t.Status(); t != nil && t.Stat < 5 {
+ switch t.Stat {
+ case 4:
+ sc = "msx-red"
+ case 3:
+ sc = "msx-green"
+ default:
+ sc = "msx-yellow"
+ }
+ st = "{ico:north} " + strconv.Itoa(t.ActivePeers) + " / " + strconv.Itoa(t.TotalPeers) + " {ico:south} " + strconv.Itoa(t.ConnectedSeeders)
+ }
+ }
+ if j.Data.Update != "" {
+ r = map[string]any{"action": "update:" + j.Data.Update, "data": map[string]string{"stamp": st, "stampColor": sc}}
+ } else {
+ if sc != "" {
+ sc = "{tb}{tb}{col:" + sc + "}"
+ }
+ r = map[string]any{"action": "player:label:position:{LABEL}" + sc + st}
+ }
+ c.JSON(200, map[string]any{"response": map[string]any{"status": http.StatusOK, "data": r}})
+ }
+}
+func files(c *gin.Context, p string) {
+ if d, e := os.ReadDir(p); e == nil {
+ var ds, fs []map[string]any
+ u := c.Request.URL.EscapedPath()
+ for _, f := range d {
+ if n := f.Name(); f.IsDir() {
+ ds = append(ds, map[string]any{"id": u + url.PathEscape(n) + "/", "path": n})
+ } else if f, e := f.Info(); e == nil {
+ fs = append(fs, map[string]any{"id": u + url.PathEscape(n), "path": n, "length": f.Size()})
+ }
+ }
+ c.JSON(200, map[string]any{"title": filepath.Base(strings.TrimSuffix(p, "/")), "path": u, "files": append(ds, fs...)})
+ } else if os.IsNotExist(e) {
+ c.AbortWithError(http.StatusNotFound, e)
+ } else {
+ c.AbortWithError(http.StatusInternalServerError, e)
+ }
}
diff --git a/server/web/msx/russian.json.gz b/server/web/msx/russian.json.gz
deleted file mode 100644
index fc4f98f..0000000
Binary files a/server/web/msx/russian.json.gz and /dev/null differ
diff --git a/server/web/msx/torrent.js.gz b/server/web/msx/torrent.js.gz
deleted file mode 100644
index bc246dc..0000000
Binary files a/server/web/msx/torrent.js.gz and /dev/null differ
diff --git a/server/web/msx/torrents.js.gz b/server/web/msx/torrents.js.gz
deleted file mode 100644
index 8d479bd..0000000
Binary files a/server/web/msx/torrents.js.gz and /dev/null differ
diff --git a/server/web/msx/ts.js.gz b/server/web/msx/ts.js.gz
deleted file mode 100644
index 4f6236c..0000000
Binary files a/server/web/msx/ts.js.gz and /dev/null differ