All checks were successful
Build / build (push) Successful in 3m15s
180 lines
4.9 KiB
Go
180 lines
4.9 KiB
Go
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
|
|
// }
|
|
// }
|
|
// }
|