package main import ( "fmt" "log" "net/http" "os" "path/filepath" "strconv" "strings" "gitea.seeseepuff.be/seeseemelk/mysqlite" ) func serveWebview(db *mysqlite.Db) { addr := "localhost:8081" log.Printf("Listening on %s", addr) http.Handle("/static/", http.StripPrefix("/static/", staticFileServer())) http.HandleFunc("/video/", serveVideo(db)) http.HandleFunc("/stream/", serveStream(db)) http.HandleFunc("/", serveIndex(db)) // http.HandleFunc("/video/", handleVideoActions(db)) err := http.ListenAndServe(addr, nil) if err != nil { panic(err) } } func serveIndex(db *mysqlite.Db) func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) { // Query the database for the oldest unwatched episode var id int var title, description, thumbnail string err := db.Query(`SELECT id, title, description, thumbnail FROM videos WHERE (watch_state IS NULL OR watch_state != 'watched') ORDER BY upload_date, episode LIMIT 1`).ScanSingle(&id, &title, &description, &thumbnail) if err != nil { http.Error(w, "No unwatched episodes found", http.StatusNotFound) return } vm := VideoInfoVM{ ID: id, Title: title, Description: description, Thumbnail: thumbnail, } err = renderTemplate(w, "index", vm) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } } } func serveVideo(db *mysqlite.Db) func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return } // Parse the video ID from the URL pathParts := strings.Split(r.URL.Path, "/") if len(pathParts) < 3 { http.Error(w, "Invalid video ID", http.StatusBadRequest) return } videoIDStr := pathParts[2] videoID, err := strconv.Atoi(videoIDStr) if err != nil { http.Error(w, "Invalid video ID", http.StatusBadRequest) return } // Query the database for the video with the given ID var title, description string err = db.Query(`SELECT title, description FROM videos WHERE id = ?`).Bind(videoID).ScanSingle(&title, &description) if err != nil { http.Error(w, "Video not found", http.StatusNotFound) return } vm := VideoPlayerVM{ ID: videoID, Title: title, Description: description, } err = renderTemplate(w, "video", vm) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } } } func serveStream(db *mysqlite.Db) func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) { // Parse the video ID from the URL pathParts := strings.Split(r.URL.Path, "/") if len(pathParts) < 3 { http.Error(w, "Invalid video ID", http.StatusBadRequest) return } videoIDStr := pathParts[2] videoID, err := strconv.Atoi(videoIDStr) if err != nil { http.Error(w, "Invalid video ID", http.StatusBadRequest) return } // Get video metadata from database var year, episode int err = db.Query(`SELECT year, episode FROM videos WHERE id = ?`).Bind(videoID).ScanSingle(&year, &episode) if err != nil { http.Error(w, "Video not found", http.StatusNotFound) return } // Determine the video file path downloadDir := os.Getenv("VIVAPLUS_DESTINATION") if downloadDir == "" { downloadDir = "./downloads" } seasonDir := filepath.Join(downloadDir, fmt.Sprintf("Season %d", year)) videoFilename := fmt.Sprintf("S%dE%03d.mp4", year, episode) videoPath := filepath.Join(seasonDir, videoFilename) // Check if the file exists log.Printf("Streaming video: %s", videoPath) _, err = os.Stat(videoPath) if os.IsNotExist(err) { http.Error(w, "Video file not found", http.StatusNotFound) return } // Serve the file http.ServeFile(w, r, videoPath) } } // func handleVideoActions(db *mysqlite.Db) func(w http.ResponseWriter, r *http.Request) { // return func(w http.ResponseWriter, r *http.Request) { // // Only handle POST requests for actions // if r.Method != http.MethodPost { // http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) // return // } // pathParts := strings.Split(r.URL.Path, "/") // if len(pathParts) < 4 { // http.Error(w, "Invalid URL format", http.StatusBadRequest) // return // } // videoIDStr := pathParts[2] // action := pathParts[3] // videoID, err := strconv.Atoi(videoIDStr) // if err != nil { // http.Error(w, "Invalid video ID", http.StatusBadRequest) // return // } // switch action { // case "mark-watched": // err = db.Query(`UPDATE videos SET watch_state = 'watched' WHERE id = ?`).Bind(videoID).Exec() // if err != nil { // http.Error(w, "Failed to update watch state", http.StatusInternalServerError) // return // } // // Redirect back to the homepage // http.Redirect(w, r, "/", http.StatusSeeOther) // default: // http.Error(w, "Unknown action", http.StatusBadRequest) // return // } // } // }