From fa66ad4540e00eded8c3378af16748d73cbce68f Mon Sep 17 00:00:00 2001 From: kolsys Date: Wed, 8 Sep 2021 04:28:46 +0300 Subject: [PATCH] Add support Media Station X --- server/web/api/msx.go | 214 ++++++++++++++++++++++++++++++++++++++++ server/web/api/route.go | 5 + 2 files changed, 219 insertions(+) create mode 100644 server/web/api/msx.go diff --git a/server/web/api/msx.go b/server/web/api/msx.go new file mode 100644 index 0000000..8079eba --- /dev/null +++ b/server/web/api/msx.go @@ -0,0 +1,214 @@ +package api + +import ( + "fmt" + "strings" + "net/url" + "path/filepath" + + sets "server/settings" + "server/torr" + "server/torr/state" + "server/utils" + "server/version" + + "github.com/gin-gonic/gin" +) + +type msxMenu struct { + Logo string `json:"logo,omitempty"` + Menu []msxMenuItem `json:"menu"` +} + +type msxMenuItem struct { + Icon string `json:"icon,omitempty"` + Label string `json:"label,omitempty"` + Data msxData `json:"data,omitempty"` +} + +type msxData struct { + Type string `json:"type,omitempty"` + Headline string `json:"headline,omitempty"` + Action string `json:"action,omitempty"` + Template gin.H `json:"template,omitempty"` + Items []msxItem `json:"items,omitempty"` + Pages []msxPage `json:"pages,omitempty"` +} + +type msxItem struct { + Title string `json:"title,omitempty"` + Label string `json:"label,omitempty"` + PlayerLabel string `json:"playerLabel,omitempty"` + Action string `json:"action,omitempty"` + Image string `json:"image,omitempty"` + Icon string `json:"icon,omitempty"` + Badge string `json:"badge,omitempty"` + Tag string `json:"tag,omitempty"` +} + +type msxPage struct { + Items []gin.H `json:"items,omitempty"` +} + +func msxStart(c *gin.Context) { + c.JSON(200, gin.H{ + "name": "TorrServer", + "version": version.Version, + "parameter": "menu:{PREFIX}{SERVER}/msx/torrents", + }) +} + +// /msx/torrents +func msxTorrents(c *gin.Context) { + torrs := torr.ListTorrent() + + host := utils.GetScheme(c) + "://" + c.Request.Host + logo := host + "/apple-touch-icon.png" + list := make([]msxItem, len(torrs)) + + for i, tor := range torrs { + item := msxItem{ + Title: tor.Title, + Image: tor.Poster, + Action: "content:" + host + "/msx/playlist/" + url.PathEscape(tor.Title) + "?hash=" + tor.TorrentSpec.InfoHash.HexString(), + } + list[i] = item + } + + c.JSON(200, msxMenu{ + Logo: logo, + Menu: []msxMenuItem{ + // Main page + { + Icon: "list", + Label: "Torrents", + Data: msxData{ + Type: "pages", + Template: gin.H{ + "type": "separate", + "layout": "0,0,2,4", + "icon": "msx-white-soft:movie", + "color": "msx-glass", + }, + Items: list, + }, + // About + },{ + Icon: "info", + Label: "About", + Data: msxData{ + Pages: []msxPage{ + { + Items: []gin.H{ + { + "type": "default", + "headline": "TorrServer " + version.Version, + "text": "https://github.com/YouROK/TorrServer", + "image": logo, + "imageFiller": "height-left", + "imageWidth": 2, + "layout": "0,0,8,2", + "color": "msx-gray-soft", + }, + }, + }, + }, + }, + }, + }, + }) +} + +// /msx/playlist?hash=... +func msxPlaylist(c *gin.Context) { + hash, _ := c.GetQuery("hash") + if hash == "" { + c.JSON(200, msxData{ + Action: "error:Item not found", + }) + return + } + + tor := torr.GetTorrent(hash) + if tor == nil { + c.JSON(200, msxData{ + Action: "error:Item not found", + }) + return + } + + if tor.Stat == state.TorrentInDB { + tor = torr.LoadTorrent(tor) + if tor == nil { + c.JSON(200, msxData{ + Action: "error:Error while getting torrent info", + }) + return + } + } + + host := utils.GetScheme(c) + "://" + c.Request.Host + status := tor.Status() + viewed := sets.ListViewed(hash) + list := []msxItem{} + + for _, f := range status.FileStats { + mime := utils.GetMimeType(f.Path) + action := mime[0 : len(mime)-2] + + if (action == "*") { + continue + } + name := filepath.Base(f.Path) + item := msxItem{ + Label: name, + PlayerLabel: strings.TrimSuffix(name, filepath.Ext(name)), + Action: action + ":" + host + "/stream/" + url.PathEscape(name) + "?link=" + hash + "&index=" + fmt.Sprint(f.Id) + "&play", + } + if (isViewed(viewed, f.Id)) { + item.Tag = " " + } + if (action == "audio") { + item.Icon = "msx-white-soft:music-note" + } + list = append(list, item) + } + + if (len(list) == 0) { + c.JSON(200, msxData{ + Action: "error:No supported content found", + }) + return + } + + res := msxData{ + Headline: tor.Title, + Type: "list", + Template: gin.H{ + "type": "control", + "layout": "0,2,12,1", + "color": "msx-glass", + "icon": "msx-white-soft:movie", + "iconSize": "medium", + "badgeColor": "msx-yellow", + "tagColor": "msx-yellow", + }, + Items: list, + } + + // If only one item start to play immediately but it not works + // if (len(list) == 1) { + // res.Action = "execute:" + list[0].Action + // } + + c.JSON(200, res) +} + +func isViewed(viewed []*sets.Viewed, id int) bool { + for _, v := range viewed { + if (v.FileIndex == id) { + return true + } + } + return false +} diff --git a/server/web/api/route.go b/server/web/api/route.go index 1ad71a2..0a4c3be 100644 --- a/server/web/api/route.go +++ b/server/web/api/route.go @@ -38,6 +38,11 @@ func SetupRoute(route *gin.RouterGroup) { route.GET("/playlistall/all.m3u", allPlayList) route.GET("/playlist", playList) route.GET("/playlist/*fname", playList) + + route.GET("/msx/start.json", msxStart) + route.GET("/msx/torrents", msxTorrents) + route.GET("/msx/playlist", msxPlaylist) + route.GET("/msx/playlist/*fname", msxPlaylist) } func shutdown(c *gin.Context) {