From 2595c099a2839caabedcea9776c6df22a874d914 Mon Sep 17 00:00:00 2001 From: damiva <96115589+damiva@users.noreply.github.com> Date: Fri, 10 May 2024 17:47:08 +0300 Subject: [PATCH] Update msx.go new MSX --- server/web/msx/msx.go | 202 +++++++++++++++++++++++++++--------------- 1 file changed, 130 insertions(+), 72 deletions(-) diff --git a/server/web/msx/msx.go b/server/web/msx/msx.go index 274dde2..4544397 100644 --- a/server/web/msx/msx.go +++ b/server/web/msx/msx.go @@ -1,96 +1,154 @@ 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 +const base, fls = "https://damiva.github.io/msx", "files" - 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) -} -func SetupRoute(r *gin.RouterGroup) { - r.GET("/msx/:pth", func(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) +func SetupRoute(r gin.IRouter) { + authorized := r.Group("/", auth.CheckAuth()) + authorized.Any("/msx", func(c *gin.Context) { + if l := c.Query("url"); l != "" { + proxy(c, l, c.QueryArray("header")...) + } else if c.Request.Method == "POST" { + serve(c) + } else { + proxy(c, base+"/ts.html") } }) - r.GET("/msx/imdb", func(c *gin.Context) { - idb.Lock() - defer idb.Unlock() - l := len(ids) - ids = make(map[string]string) - c.JSON(200, l) + 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))) + } }) - r.GET("/msx/imdb/:id", func(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 { + 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 { - i = j.D[0].I.ImageUrl + l = j.D[0].I.ImageUrl } } + r.Body.Close() } - ids[p] = i } - c.JSON(200, i) + 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) + } +}