src/app/handlers.go (view raw)
1package app
2
3import (
4 "fmt"
5 "log"
6 "net/http"
7 "regexp"
8 "text/template"
9
10 g "github.com/birabittoh/gopipe/src/globals"
11 "golang.org/x/time/rate"
12)
13
14const (
15 fmtYouTubeURL = "https://www.youtube.com/watch?v=%s"
16 err404 = "Not Found"
17 err500 = "Internal Server Error"
18)
19
20var (
21 templates = template.Must(template.ParseGlob("templates/*.html"))
22 userAgentRegex = regexp.MustCompile(`(?i)bot|facebook|embed|got|firefox\/92|firefox\/38|curl|wget|go-http|yahoo|generator|whatsapp|preview|link|proxy|vkshare|images|analyzer|index|crawl|spider|python|cfnetwork|node`)
23 videoRegex = regexp.MustCompile(`(?i)^[a-z0-9_-]{11}$`)
24)
25
26func limit(limiter *rate.Limiter, next http.Handler) http.Handler {
27 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
28 if !limiter.Allow() {
29 status := http.StatusTooManyRequests
30 http.Error(w, http.StatusText(status), status)
31 return
32 }
33 next.ServeHTTP(w, r)
34 })
35}
36
37func indexHandler(w http.ResponseWriter, r *http.Request) {
38 err := templates.ExecuteTemplate(w, "index.html", nil)
39 if err != nil {
40 log.Println("indexHandler ERROR: ", err)
41 http.Error(w, err500, http.StatusInternalServerError)
42 return
43 }
44}
45
46func videoHandler(w http.ResponseWriter, r *http.Request) {
47 videoID := r.URL.Query().Get("v")
48 if videoID == "" {
49 videoID = r.PathValue("videoID")
50 if videoID == "" {
51 http.Error(w, "Missing video ID", http.StatusBadRequest)
52 return
53 }
54 }
55
56 if !userAgentRegex.MatchString(r.UserAgent()) {
57 log.Println("Regex did not match. UA: ", r.UserAgent())
58 if !g.Debug {
59 log.Println("Redirecting.")
60 http.Redirect(w, r, getURL(videoID), http.StatusFound)
61 return
62 }
63 }
64
65 if !videoRegex.MatchString(videoID) {
66 log.Println("Invalid video ID: ", videoID)
67 http.Error(w, "Invalid video ID.", http.StatusBadRequest)
68 return
69 }
70
71 formatID := getFormatID(r.PathValue("formatID"))
72
73 video, format, err := getVideo(videoID, formatID)
74 if err != nil {
75 http.Error(w, err500, http.StatusInternalServerError)
76 return
77 }
78
79 if video == nil || format == nil {
80 http.Error(w, err500, http.StatusInternalServerError)
81 return
82 }
83
84 var thumbnail string
85 if len(video.Thumbnails) > 0 {
86 thumbnail = video.Thumbnails[len(video.Thumbnails)-1].URL
87 }
88
89 videoURL := format.URL
90 if g.Proxy {
91 videoURL = fmt.Sprintf("/proxy/%s/%d", videoID, formatID)
92 }
93
94 data := map[string]interface{}{
95 "VideoID": videoID,
96 "VideoURL": videoURL,
97 "Uploader": video.Author,
98 "Title": video.Title,
99 "Description": video.Description,
100 "Thumbnail": thumbnail,
101 "Duration": video.Duration,
102 "Debug": g.Debug,
103 }
104
105 err = templates.ExecuteTemplate(w, "video.html", data)
106 if err != nil {
107 log.Println("indexHandler ERROR: ", err)
108 http.Error(w, err500, http.StatusInternalServerError)
109 return
110 }
111}