all repos — gopipe @ 0271132d3d1468daee659b494a523291666713d6

Embed YouTube videos on Telegram, Discord and more!

src/app/handlers.go (view raw)

  1package app
  2
  3import (
  4	"fmt"
  5	"html/template"
  6	"log"
  7	"net/http"
  8	"regexp"
  9
 10	g "github.com/birabittoh/gopipe/src/globals"
 11	"github.com/kkdai/youtube/v2"
 12	"golang.org/x/time/rate"
 13)
 14
 15const (
 16	fmtYouTubeURL = "https://www.youtube.com/watch?v=%s"
 17	err404        = "Not Found"
 18	err500        = "Internal Server Error"
 19	err401        = "Unauthorized"
 20	heading       = `<!--
 21 .d8888b.       88888888888       888              
 22d88P  Y88b          888           888              
 23888    888          888           888              
 24888         .d88b.  888  888  888 88888b.   .d88b. 
 25888  88888 d88""88b 888  888  888 888 "88b d8P  Y8b
 26888    888 888  888 888  888  888 888  888 88888888
 27Y88b  d88P Y88..88P 888  Y88b 888 888 d88P Y8b.    
 28 "Y8888P88  "Y88P"  888   "Y88888 88888P"   "Y8888 
 29
 30A better way to embed YouTube videos on Telegram.
 31-->`
 32)
 33
 34var (
 35	videoRegex = regexp.MustCompile(`(?i)^[a-z0-9_-]{11}$`)
 36)
 37
 38func limit(limiter *rate.Limiter, next http.Handler) http.Handler {
 39	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 40		if !limiter.Allow() {
 41			status := http.StatusTooManyRequests
 42			http.Error(w, http.StatusText(status), status)
 43			return
 44		}
 45		next.ServeHTTP(w, r)
 46	})
 47}
 48
 49func indexHandler(w http.ResponseWriter, r *http.Request) {
 50	err := g.XT.ExecuteTemplate(w, "index.tmpl", nil)
 51	if err != nil {
 52		log.Println("indexHandler ERROR: ", err)
 53		http.Error(w, err500, http.StatusInternalServerError)
 54		return
 55	}
 56}
 57
 58func videoHandler(w http.ResponseWriter, r *http.Request) {
 59	videoID := r.URL.Query().Get("v")
 60	if videoID == "" {
 61		videoID = r.PathValue("videoID")
 62		if videoID == "" {
 63			http.Error(w, "Missing video ID", http.StatusBadRequest)
 64			return
 65		}
 66	}
 67
 68	if !videoRegex.MatchString(videoID) {
 69		log.Println("Invalid video ID: ", videoID)
 70		http.Error(w, err404, http.StatusNotFound)
 71		return
 72	}
 73
 74	formatID := getFormatID(r.PathValue("formatID"))
 75
 76	video, format, err := getVideo(videoID, formatID)
 77	if err != nil {
 78		http.Error(w, err500, http.StatusInternalServerError)
 79		return
 80	}
 81
 82	if video == nil || format == nil {
 83		http.Error(w, err500, http.StatusInternalServerError)
 84		return
 85	}
 86
 87	var thumbnail string
 88	if len(video.Thumbnails) > 0 {
 89		thumbnail = video.Thumbnails[len(video.Thumbnails)-1].URL
 90	}
 91
 92	videoURL := format.URL
 93	if g.Proxy {
 94		videoURL = fmt.Sprintf("/proxy/%s/%d", videoID, formatID)
 95	}
 96
 97	data := map[string]interface{}{
 98		"VideoID":     videoID,
 99		"VideoURL":    videoURL,
100		"Author":      video.Author,
101		"Title":       video.Title,
102		"Description": video.Description,
103		"Thumbnail":   thumbnail,
104		"Duration":    video.Duration,
105		"Captions":    getCaptions(*video),
106		"Heading":     template.HTML(heading),
107	}
108
109	err = g.XT.ExecuteTemplate(w, "video.tmpl", data)
110	if err != nil {
111		log.Println("indexHandler ERROR: ", err)
112		http.Error(w, err500, http.StatusInternalServerError)
113		return
114	}
115}
116
117func cacheHandler(w http.ResponseWriter, r *http.Request) {
118	username, password, ok := r.BasicAuth()
119	if !ok || username != g.AdminUser || password != g.AdminPass {
120		w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
121		http.Error(w, err401, http.StatusUnauthorized)
122		return
123	}
124
125	var videos []youtube.Video
126	for s := range g.KS.Keys() {
127		video, err := g.KS.Get(s)
128		if err != nil || video == nil {
129			continue
130		}
131		videos = append(videos, *video)
132	}
133
134	data := map[string]interface{}{"Videos": videos}
135	err := g.XT.ExecuteTemplate(w, "cache.tmpl", data)
136	if err != nil {
137		log.Println("cacheHandler ERROR: ", err)
138		http.Error(w, err500, http.StatusInternalServerError)
139		return
140	}
141}