From a4a9afc4b0140123c8ef79766c7ad5187265aa05 Mon Sep 17 00:00:00 2001
From: damiva <96115589+damiva@users.noreply.github.com>
Date: Tue, 28 May 2024 15:29:59 +0300
Subject: [PATCH] Update msx.go (#411)
---
server/web/msx/msx.go | 267 ++++++++++++++++++------------------------
1 file changed, 116 insertions(+), 151 deletions(-)
diff --git a/server/web/msx/msx.go b/server/web/msx/msx.go
index b797209..ffe50f3 100644
--- a/server/web/msx/msx.go
+++ b/server/web/msx/msx.go
@@ -2,93 +2,125 @@ package msx
import (
"encoding/json"
- "errors"
"net/http"
"os"
- "path"
- "strconv"
- "strings"
- "time"
-
+ "path/filepath"
"server/settings"
"server/torr"
"server/utils"
"server/version"
"server/web/auth"
+ "strconv"
+ "strings"
"github.com/gin-gonic/gin"
)
-const (
- files = `files`
- base = `https://damiva.github.io/msx/`
- htmlB = `
-
-
- TorrServer MSX Plugin
-
-
-
-
-
-`
-)
+const base, files = "tsmsx.yourok.ru", "media"
-var start = struct {
- N string `json:"name"`
- V string `json:"version"`
- P string `json:"parameter"`
-}{"TorrServer", version.Version, "menu:request:interaction:init@{PREFIX}{SERVER}/msx/ts"}
+var param = "menu:request:interaction:{SERVER}@{PREFIX}" + base + "/start.html"
+
+func trn(h string) (st, sc string) {
+ if h := torr.GetTorrent(h); h != nil {
+ if h := h.Status(); h != nil && h.Stat < 5 {
+ switch h.Stat {
+ case 4:
+ sc = "msx-red"
+ case 3:
+ sc = "msx-green"
+ default:
+ sc = "msx-yellow"
+ }
+ st = "{ico:north} " + strconv.Itoa(h.ActivePeers) + " / " + strconv.Itoa(h.TotalPeers) + " {ico:south} " + strconv.Itoa(h.ConnectedSeeders)
+ }
+ }
+ return
+}
+func rsp(c *gin.Context, r *http.Response, e error) {
+ if e != nil {
+ c.AbortWithError(http.StatusInternalServerError, e)
+ } else {
+ defer r.Body.Close()
+ c.DataFromReader(r.StatusCode, r.ContentLength, r.Header.Get("Content-Type"), r.Body, nil)
+ }
+}
func SetupRoute(r gin.IRouter) {
authorized := r.Group("/", auth.CheckAuth())
- // MSX:
- authorized.Any("/msx/*pth", func(c *gin.Context) {
- switch p := strings.TrimPrefix(c.Param("pth"), "/"); p {
- case "start.json":
- if c.Request.Method != "POST" {
- c.JSON(200, &start)
- } else if e := json.NewDecoder(c.Request.Body).Decode(&start); e != nil {
- c.AbortWithError(http.StatusBadRequest, e)
- }
- case "proxy":
- proxy(c, c.Query("url"), c.QueryArray("header")...)
- case "torrent":
- torrent(c)
- default:
- if p != "" && !strings.HasSuffix(p, "/") && path.Ext(p) == "" {
- p = base + p + `.js?t=` + strconv.FormatInt(time.Now().Unix(), 16)
- c.Data(200, "text/html;charset=UTF-8", append(append([]byte(htmlB), p...), htmlE...))
- } else {
- proxy(c, base+p)
- }
- }
+ //MSX:
+ authorized.GET("/msx/", func(c *gin.Context) {
+ r, e := http.Get("http://" + base)
+ rsp(c, r, e)
})
- // files:
- authorized.GET("/files", func(c *gin.Context) {
- if l, e := os.Readlink(files); e == nil || os.IsNotExist(e) {
- c.JSON(200, l)
- } else {
- c.AbortWithError(http.StatusInternalServerError, e)
- }
+ authorized.GET("/msx/start.json", func(c *gin.Context) {
+ c.JSON(200, map[string]string{"name": "TorrServer", "version": version.Version, "parameter": param})
})
- authorized.POST("/files", func(c *gin.Context) {
- var l string
- if e := c.Bind(&l); e != nil {
+ authorized.POST("/msx/start.json", func(c *gin.Context) {
+ if e := json.NewDecoder(c.Request.Body).Decode(¶m); e != nil {
c.AbortWithError(http.StatusBadRequest, e)
- } else if e = os.Remove(files); e != nil && !os.IsNotExist(e) {
- c.AbortWithError(http.StatusInternalServerError, e)
- } else if l != "" {
- if e = os.Symlink(l, files); e != nil {
- c.AbortWithError(http.StatusInternalServerError, e)
- }
}
})
- authorized.StaticFS("/files/", gin.Dir(files, true))
- // IMDB:
- authorized.GET("/imdb/:id", func(c *gin.Context) {
+ authorized.GET("/msx/trn", func(c *gin.Context) {
+ r := false
+ if h := c.Query("hash"); h != "" {
+ for _, t := range settings.ListTorrent() {
+ if r = (t != nil && t.InfoHash.HexString() == h); r {
+ break
+ }
+ }
+ }
+ c.JSON(200, r)
+ })
+ authorized.POST("/msx/trn", func(c *gin.Context) {
+ var r struct {
+ R struct {
+ S int `json:"status"`
+ T string `json:"text"`
+ M string `json:"message,omitempty"`
+ D map[string]any `json:"data,omitempty"`
+ } `json:"response"`
+ }
+ if j := struct{ Data string }{Data: c.Query("hash")}; j.Data != "" {
+ st, sc := trn(j.Data)
+ if sc != "" {
+ sc = "{col:" + sc + "}"
+ }
+ r.R.S, r.R.D = http.StatusOK, map[string]any{"action": "player:label:position:{LABEL}{tb}{tb}" + sc + st}
+ } else if e := json.NewDecoder(c.Request.Body).Decode(&j); e != nil {
+ r.R.S, r.R.M = http.StatusBadRequest, e.Error()
+ } else if j.Data == "" {
+ r.R.S, r.R.M = http.StatusBadRequest, "data is not set"
+ } else {
+ st, sc := trn(j.Data[strings.LastIndexByte(j.Data, ':')+1:])
+ r.R.D = map[string]any{"stamp": st, "stampColor": sc}
+ if sc != "" {
+ r.R.D["live"] = map[string]any{
+ "type": "airtime", "duration": 1000, "over": map[string]any{
+ "action": "execute:" + utils.GetScheme(c) + "://" + c.Request.Host + c.Request.URL.Path, "data": j.Data,
+ },
+ }
+ }
+ r.R.S, r.R.D = http.StatusOK, map[string]any{"action": j.Data, "data": r.R.D}
+ }
+ r.R.T = http.StatusText(r.R.S)
+ c.JSON(200, &r)
+ })
+ authorized.Any("/msx/proxy", func(c *gin.Context) {
+ if u := c.Query("url"); 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 c.QueryArray("header") {
+ if v := strings.SplitN(v, ":", 2); len(v) == 2 {
+ q.Header.Add(v[0], v[1])
+ }
+ }
+ r, e := http.DefaultClient.Do(q)
+ rsp(c, r, e)
+ }
+ })
+ authorized.GET("/msx/imdb/:id", func(c *gin.Context) {
i, l, j := strings.TrimPrefix(c.Param("id"), "/"), "", false
if j = strings.HasSuffix(i, ".json"); !j {
i += ".json"
@@ -112,92 +144,25 @@ func SetupRoute(r gin.IRouter) {
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)
+ //Files:
+ authorized.StaticFS("/files/", gin.Dir(filepath.Join(settings.Path, files), true))
+ authorized.GET("/files", func(c *gin.Context) {
+ if l, e := os.Readlink(filepath.Join(settings.Path, files)); e == nil || os.IsNotExist(e) {
+ c.JSON(200, l)
} else {
- c.DataFromReader(r.StatusCode, r.ContentLength, r.Header.Get("Content-Type"), r.Body, nil)
- r.Body.Close()
+ c.AbortWithError(http.StatusInternalServerError, e)
}
- }
-}
-
-func trnGet(h string) (st, sc string) {
- if h := torr.GetTorrent(h); h != nil {
- if h := h.Status(); h != nil && h.Stat < 5 {
- switch h.Stat {
- case 4:
- sc = "msx-red"
- case 3:
- sc = "msx-green"
- default:
- sc = "msx-yellow"
- }
- st = "{ico:north} " + strconv.Itoa(h.ActivePeers) + " / " + strconv.Itoa(h.TotalPeers) + " {ico:south} " + strconv.Itoa(h.ConnectedSeeders)
- }
- }
- return
-}
-
-func response(c *gin.Context, a any) {
- var r struct {
- R struct {
- S int `json:"status"`
- T string `json:"text"`
- M string `json:"message,omitempty"`
- D any `json:"data,omitempty"`
- } `json:"response"`
- }
- if e, o := a.(error); o {
- r.R.S, r.R.M = http.StatusBadRequest, e.Error()
- } else {
- r.R.S, r.R.D = http.StatusOK, a
- }
- r.R.T = http.StatusText(r.R.S)
- c.JSON(200, &r)
-}
-
-func torrent(c *gin.Context) {
- if c.Request.Method != "POST" {
- r := false
- if h := c.Query("hash"); h != "" {
- for _, t := range settings.ListTorrent() {
- if r = (t != nil && t.InfoHash.HexString() == h); r {
- break
- }
+ })
+ authorized.POST("/files", func(c *gin.Context) {
+ var l string
+ if e := c.Bind(&l); e != nil {
+ c.AbortWithError(http.StatusBadRequest, e)
+ } else if e = os.Remove(filepath.Join(settings.Path, files)); e != nil && !os.IsNotExist(e) {
+ c.AbortWithError(http.StatusInternalServerError, e)
+ } else if l != "" {
+ if e = os.Symlink(l, filepath.Join(settings.Path, files)); e != nil {
+ c.AbortWithError(http.StatusInternalServerError, e)
}
}
- c.JSON(200, r)
- } else if j := struct{ Data string }{Data: c.Query("hash")}; j.Data != "" {
- st, sc := trnGet(j.Data)
- if sc != "" {
- sc = "{col:" + sc + "}"
- }
- response(c, map[string]string{"action": "player:label:position:{VALUE}{tb}{tb}" + sc + st})
- } else if e := json.NewDecoder(c.Request.Body).Decode(&j); e != nil {
- response(c, e)
- } else if j.Data == "" {
- response(c, errors.New("data is not set"))
- } else {
- st, sc := trnGet(j.Data[strings.LastIndexByte(j.Data, ':')+1:])
- response(c, map[string]any{"action": j.Data, "data": map[string]any{
- "stamp": st, "stampColor": sc, "live": map[string]any{
- "type": "airtime", "duration": 1000, "over": map[string]any{
- "action": "execute:" + utils.GetScheme(c) + "://" + c.Request.Host + c.Request.URL.Path, "data": j.Data,
- },
- },
- }})
- }
+ })
}