package route import ( "app/shelfly/internal/download" "app/shelfly/internal/library" "app/shelfly/internal/login" "app/shelfly/internal/users" "app/shelfly/renders" "fmt" "log" "net/http" "os" "path/filepath" "time" "github.com/gorilla/mux" "golang.org/x/net/webdav" "gorm.io/gorm" ) type spaHandler struct { staticPath string indexPath string } // Routes non protégées func RoutesPublic(r *mux.Router, bd *gorm.DB) { // Fichiers statiques (CSS, JS, etc.) staticDir := "./templates/assets/" r.PathPrefix("/templates/assets/").Handler( http.StripPrefix("/templates/assets/", http.FileServer(http.Dir(staticDir))), ) // Page de login r.HandleFunc("/login", renders.Login) // Endpoint d'API pour se logger r.HandleFunc("/api/login", login.LoginHandler(bd)).Methods("POST") r.HandleFunc("/api/scan/{id}", library.ScanFolder(bd)).Methods("GET") r.HandleFunc("/api/download/stream", renders.HandleJobsStream(bd)) r.HandleFunc("/playlist.m3u", func(w http.ResponseWriter, r *http.Request) { uploadDir := "/app/upload" w.Header().Set("Content-Type", "audio/x-mpegurl") fmt.Fprintln(w, "#EXTM3U") err := filepath.Walk(uploadDir, func(path string, info os.FileInfo, err error) error { if err != nil { return err } if info.IsDir() { return nil } // On construit l'URL HTTP complète relPath, _ := filepath.Rel(uploadDir, path) // Important : remplacer \ par / pour Windows relPath = filepath.ToSlash(relPath) fileURL := fmt.Sprintf("https://media.canguidev.fr/upload/%s", relPath) fmt.Fprintln(w, fileURL) return nil }) if err != nil { http.Error(w, "Erreur lors de la génération de la playlist", http.StatusInternalServerError) } }) webdavHandler := &webdav.Handler{ Prefix: "/webdav/", FileSystem: webdav.Dir("/app/upload"), LockSystem: webdav.NewMemLS(), } r.PathPrefix("/webdav/").Handler(http.StripPrefix("/webdav/", webdavHandler)) } // Routes protégées func RoutesProtected(r *mux.Router, bd *gorm.DB) { // Ici on place les vues et API qui doivent être protégées r.HandleFunc("/stream", StreamHandler) r.HandleFunc("/dashboard", renders.Dashboard(bd)) r.HandleFunc("/settings", renders.Settings) r.HandleFunc("/library", renders.Library) r.HandleFunc("/menuLibary", renders.Library) r.HandleFunc("/godownloader/downloads", renders.GoDownload) r.HandleFunc("/godownloader/linkcollectors", renders.GoDownloadLinkCollectors) r.HandleFunc("/godownloader/settings", renders.GoDownloadSetting(bd)) r.HandleFunc("/godownloader/poll-status", renders.PollStatusHandler(bd)) r.HandleFunc("/godownloader/table-refresh", renders.GoDownloadPartialTable(bd)) r.HandleFunc("/godownloader/settings/delete", renders.GoDownloadSettingDelete(bd)) r.HandleFunc("/api/download/add", renders.HandleAddJob(bd)).Methods("POST") r.HandleFunc("/api/download/all", renders.HandleListJobsPartial(bd)).Methods("GET") r.HandleFunc("/downloads", renders.GoDownload2(bd)) r.HandleFunc("/stream/{id}", download.HandleStreamPage()).Methods("GET") r.HandleFunc("/api/download/start/{id}", renders.HandleStartJob(bd)).Methods("POST") r.HandleFunc("/api/download/pause/{id}", renders.HandlePauseJob).Methods("POST") r.HandleFunc("/api/download/resume/{id}", renders.HandleResumeJob(bd)).Methods("POST") r.HandleFunc("/api/download/delete/{id}", renders.HandleDeleteJob(bd)).Methods("DELETE") r.HandleFunc("/api/download/delete-multiple", renders.HandleDeleteMultipleJobs(bd)).Methods("POST") // API user r.HandleFunc("/api/user/create", users.CreateUser(bd)).Methods("POST") r.HandleFunc("/api/user/update/{id}", users.UpdateUser(bd)).Methods("PUT") r.HandleFunc("/api/user/delete/{id}", users.DeleteUser(bd)).Methods("DELETE") r.HandleFunc("/api/user/all/", users.ReadAllUser(bd)).Methods("GET") r.HandleFunc("/api/user/{id}", users.FindUserById(bd)).Methods("GET") // API download r.HandleFunc("/api/pathDownload/create", download.CreateSavePath(bd)).Methods("POST") r.HandleFunc("/api/pathDownload/update/{id}", download.UpdateSavePath(bd)).Methods("PUT") r.HandleFunc("/api/pathDownload/delete/{id}", download.DeleteSavePath(bd)).Methods("DELETE") r.HandleFunc("/api/pathDownload/all/", download.ReadAllSavePath(bd)).Methods("GET") //API Check path r.HandleFunc("/validate-path", download.PathValidationHandler) //API Scan folder } func StreamHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/event-stream") w.Header().Set("Cache-Control", "no-cache") w.Header().Set("Connection", "keep-alive") flusher, ok := w.(http.Flusher) if !ok { http.Error(w, "Le streaming n’est pas supporté par ce serveur", http.StatusInternalServerError) return } ticker := time.NewTicker(1 * time.Second) defer ticker.Stop() // Boucle infinie (ou jusqu'à annulation) for { select { case <-ticker.C: fmt.Fprintf(w, "data:
Message #%d
\n\n") flusher.Flush() case <-r.Context().Done(): // Le client a probablement fermé la connexion log.Println("Client déconnecté") return } } }