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 findTorrentByFilename(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) switch r.Method { case "PROPFIND": log.Println("PROPFIND", requestPath) 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 { lastSegment := path.Base(requestPath) torrent := findTorrentByFilename(torrents, lastSegment) 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: log.Println("OPTIONS", requestPath) w.WriteHeader(http.StatusOK) case http.MethodGet: log.Println("GET", requestPath) segments := strings.Split(requestPath, "/") // If there are less than 2 segments, return an error or adjust as needed if len(segments) < 2 { log.Println("Cannot find file") http.Error(w, "Cannot find file", http.StatusNotFound) } // Get the last two segments secondLast := segments[len(segments)-2] last := segments[len(segments)-1] unrestrict, dbErr := db.Get(secondLast, last) 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 } resp, err := realdebrid.UnrestrictLink(os.Getenv("RD_TOKEN"), unrestrict.Link) if err != nil { log.Printf("Cannot unrestrict link: %v", err.Error()) http.Error(w, fmt.Sprintf("Cannot unrestrict link: %v", err.Error()), http.StatusInternalServerError) return } http.Redirect(w, r, resp.Download, http.StatusFound) default: log.Println("Method not implemented") http.Error(w, "Method not implemented", http.StatusMethodNotAllowed) } }) }