package api import ( "net/http" "strings" "server/dlna" "server/log" set "server/settings" "server/torr" "server/torr/state" "server/web/api/utils" "github.com/gin-gonic/gin" "github.com/pkg/errors" ) // Action: add, get, set, rem, list, drop type torrReqJS struct { requestI Link string `json:"link,omitempty"` Hash string `json:"hash,omitempty"` Title string `json:"title,omitempty"` Category string `json:"category,omitempty"` Poster string `json:"poster,omitempty"` Data string `json:"data,omitempty"` SaveToDB bool `json:"save_to_db,omitempty"` } // torrents godoc // // @Summary Handle torrents informations // @Description Allow to add, get or set torrents to server. The action depends of what has been asked. // // @Tags API // // @Param request body torrReqJS true "Torrent request" // // @Accept json // @Produce json // @Success 200 // @Router /torrents [post] 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 "set": { setTorrent(req, c) } case "rem": { remTorrent(req, c) } case "list": { listTorrent(req, c) } case "drop": { dropTorrent(req, c) } case "wipe": { wipeTorrents(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) req.Link = strings.ReplaceAll(req.Link, "&", "&") torrSpec, err := utils.ParseLink(req.Link) if err != nil { log.TLogln("error parse link:", err) c.AbortWithError(http.StatusBadRequest, err) return } tor, err := torr.AddTorrent(torrSpec, req.Title, req.Poster, req.Data, req.Category) if tor.Data != "" { log.TLogln("torrent data:", tor.Data) } if tor.Category != "" { log.TLogln("torrent category:", tor.Category) } 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 get torrent info") return } if tor.Title == "" { tor.Title = torrSpec.DisplayName // prefer dn over name tor.Title = strings.ReplaceAll(tor.Title, "rutor.info", "") tor.Title = strings.ReplaceAll(tor.Title, "_", " ") tor.Title = strings.Trim(tor.Title, " ") if tor.Title == "" { tor.Title = tor.Name() } } if req.SaveToDB { torr.SaveTorrentToDB(tor) } }() // TODO: remove if set.BTsets.EnableDLNA { dlna.Stop() dlna.Start() } 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 setTorrent(req torrReqJS, c *gin.Context) { if req.Hash == "" { c.AbortWithError(http.StatusBadRequest, errors.New("hash is empty")) return } torr.SetTorrent(req.Hash, req.Title, req.Poster, req.Category, req.Data) c.Status(200) } func remTorrent(req torrReqJS, c *gin.Context) { if req.Hash == "" { c.AbortWithError(http.StatusBadRequest, errors.New("hash is empty")) return } torr.RemTorrent(req.Hash) // TODO: remove if set.BTsets.EnableDLNA { dlna.Stop() dlna.Start() } c.Status(200) } func listTorrent(req torrReqJS, c *gin.Context) { list := torr.ListTorrent() if len(list) == 0 { 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) } func wipeTorrents(req torrReqJS, c *gin.Context) { torrents := torr.ListTorrent() for _, t := range torrents { torr.RemTorrent(t.TorrentSpec.InfoHash.HexString()) } // TODO: remove (copied todo from remTorrent()) if set.BTsets.EnableDLNA { dlna.Stop() dlna.Start() } c.Status(200) }