fixyoutube.go (view raw)
1package main
2
3import (
4 "bytes"
5 "html/template"
6 "log"
7 "net/http"
8 "net/url"
9 "os"
10 "slices"
11 "time"
12
13 "github.com/BiRabittoh/fixyoutube-go/invidious"
14 "github.com/gorilla/mux"
15 "github.com/joho/godotenv"
16)
17
18var templatesDirectory = "templates/"
19var indexTemplate = template.Must(template.ParseFiles(templatesDirectory + "index.html"))
20var videoTemplate = template.Must(template.ParseFiles(templatesDirectory + "video.html"))
21
22func indexHandler(w http.ResponseWriter, r *http.Request) {
23 buf := &bytes.Buffer{}
24 err := indexTemplate.Execute(buf, nil)
25 if err != nil {
26 http.Error(w, err.Error(), http.StatusInternalServerError)
27 return
28 }
29
30 buf.WriteTo(w)
31}
32
33func watchHandler(newsapi *invidious.Client) http.HandlerFunc {
34 return func(w http.ResponseWriter, r *http.Request) {
35 u, err := url.Parse(r.URL.String())
36 if err != nil {
37 http.Error(w, err.Error(), http.StatusInternalServerError)
38 return
39 }
40
41 params := u.Query()
42 videoId := params.Get("v")
43
44 video, err := newsapi.FetchEverything(videoId)
45 if err != nil {
46 http.Error(w, err.Error(), http.StatusInternalServerError)
47 return
48 }
49
50 buf := &bytes.Buffer{}
51 err = videoTemplate.Execute(buf, video)
52 if err != nil {
53 http.Error(w, err.Error(), http.StatusInternalServerError)
54 return
55 }
56
57 buf.WriteTo(w)
58 }
59}
60
61var blacklist = []string{"favicon.ico", "robots.txt"}
62
63func shortHandler(newsapi *invidious.Client) http.HandlerFunc {
64 return func(w http.ResponseWriter, r *http.Request) {
65 videoId := mux.Vars(r)["videoId"]
66
67 if slices.Contains(blacklist, videoId) {
68 http.Error(w, "Not a valid ID.", http.StatusBadRequest)
69 return
70 }
71
72 video, err := newsapi.FetchEverything(videoId)
73 if err != nil {
74 http.Error(w, err.Error(), http.StatusBadRequest)
75 return
76 }
77
78 buf := &bytes.Buffer{}
79 err = videoTemplate.Execute(buf, video)
80 if err != nil {
81 http.Error(w, err.Error(), http.StatusInternalServerError)
82 return
83 }
84
85 buf.WriteTo(w)
86 }
87}
88
89func main() {
90 err := godotenv.Load()
91 if err != nil {
92 log.Println("Error loading .env file")
93 }
94
95 port := os.Getenv("PORT")
96 if port == "" {
97 port = "3000"
98 }
99
100 myClient := &http.Client{Timeout: 10 * time.Second}
101 videoapi := invidious.NewClient(myClient, "y.birabittoh.duckdns.org")
102
103 r := mux.NewRouter()
104 r.HandleFunc("/", indexHandler)
105 r.HandleFunc("/watch", watchHandler(videoapi))
106 r.HandleFunc("/{videoId}", shortHandler(videoapi))
107 //r.HandleFunc("/proxy/{videoId}", proxyHandler)
108
109 /*
110 // native go implementation (useless until february 2024)
111 r := http.NewServeMux()
112 r.HandleFunc("/watch", watchHandler(videoapi))
113 r.HandleFunc("/{videoId}/", shortHandler(videoapi))
114 r.HandleFunc("/", indexHandler)
115 */
116 println("Serving on port", port)
117 http.ListenAndServe(":"+port, r)
118}