package dav import ( "encoding/xml" "fmt" "log" "net/http" "os" "path" "strings" "github.com/debridmediamanager.com/zurg/pkg/dav" "github.com/debridmediamanager.com/zurg/pkg/realdebrid" "github.com/debridmediamanager.com/zurg/pkg/repo" ) func findTorrentByName(torrents []realdebrid.Torrent, filename string) *realdebrid.Torrent { for _, torrent := range torrents { if torrent.Filename == filename { return &torrent } } return nil } func Router(mux *http.ServeMux, db *repo.Database) { torrents, err := realdebrid.GetTorrents(os.Getenv("RD_TOKEN")) if err != nil { log.Printf("Cannot get torrents: %v", err.Error()) return } rootResponse := dav.MultiStatus{ XMLNS: "DAV:", Response: []dav.Response{ dav.Directory("/"), dav.Directory("/torrents"), }, } mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { requestPath := path.Clean(r.URL.Path) log.Println(r.Method, requestPath) switch r.Method { case "PROPFIND": var output []byte var err error if requestPath == "/" { output, err = xml.MarshalIndent(rootResponse, "", " ") } else if requestPath == "/torrents" { var allTorrentsResponse *dav.MultiStatus allTorrentsResponse, err = createMultiTorrentResponse(torrents) if err != nil { log.Printf("Cannot read directory: %v", err.Error()) http.Error(w, fmt.Sprintf("Cannot read directory: %v", err.Error()), http.StatusInternalServerError) return } output, err = xml.MarshalIndent(allTorrentsResponse, "", " ") } else { torrentName := path.Base(requestPath) torrent := findTorrentByName(torrents, torrentName) if torrent == nil { log.Println("Cannot find directory") http.Error(w, "Cannot find directory", http.StatusNotFound) return } var torrentResponse *dav.MultiStatus torrentResponse, err = createSingleTorrentResponse(*torrent, db) if err != nil { log.Printf("Cannot read directory: %v", err.Error()) http.Error(w, fmt.Sprintf("Cannot read directory: %v", err.Error()), http.StatusInternalServerError) return } output, err = xml.MarshalIndent(torrentResponse, "", " ") } if err != nil { log.Printf("Cannot marshal xml: %v", err.Error()) http.Error(w, fmt.Sprintf("Cannot marshal xml: %v", err.Error()), http.StatusInternalServerError) return } w.Header().Set("Content-Type", "text/xml; charset=\"utf-8\"") w.WriteHeader(http.StatusMultiStatus) fmt.Fprintf(w, "\n%s\n", output) case http.MethodOptions: w.WriteHeader(http.StatusOK) case http.MethodGet: segments := strings.Split(requestPath, "/") // If there are less than 3 segments, return an error or adjust as needed if len(segments) < 3 { log.Println("Cannot find file") http.Error(w, "Cannot find file", http.StatusNotFound) } // Get the last two segments torrentName := segments[len(segments)-2] torrent := findTorrentByName(torrents, torrentName) if torrent == nil { log.Println("Cannot find directory") http.Error(w, "Cannot find directory", http.StatusNotFound) return } filename := segments[len(segments)-1] unrestrict, dbErr := db.Get(torrent.Hash, filename) if dbErr != nil { log.Printf("Cannot find file in db: %v", dbErr.Error()) http.Error(w, fmt.Sprintf("Cannot find file in db: %v", dbErr.Error()), http.StatusInternalServerError) return } unrestrictFn := func() (realdebrid.UnrestrictResponse, error) { return realdebrid.UnrestrictLink(os.Getenv("RD_TOKEN"), unrestrict.Link) } resp := realdebrid.RetryUntilOk(unrestrictFn) if resp == nil { // TODO: Delete the link from the database log.Printf("Cannot unrestrict link: %v", err.Error()) http.Error(w, fmt.Sprintf("Cannot unrestrict link: %v", err.Error()), http.StatusNotFound) return } http.Redirect(w, r, resp.Download, http.StatusFound) default: log.Println("Method not implemented") http.Error(w, "Method not implemented", http.StatusMethodNotAllowed) } }) }