all repos — fixyoutube-go @ main

A better way to embed YouTube videos everywhere (inspired by FixTweet).

fixyoutube.go (view raw)

 1package main
 2
 3import (
 4	"net/http"
 5	"os"
 6	"strconv"
 7	"time"
 8
 9	"github.com/BiRabittoh/fixyoutube-go/invidious"
10	"github.com/joho/godotenv"
11	"github.com/sirupsen/logrus"
12	"golang.org/x/time/rate"
13)
14
15var (
16	apiKey      string
17	debugSwitch = false
18	logger      = logrus.New()
19)
20
21func limit(limiter *rate.Limiter, next http.Handler) http.Handler {
22	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
23		if !limiter.Allow() {
24			status := http.StatusTooManyRequests
25			http.Error(w, http.StatusText(status), status)
26			return
27		}
28		next.ServeHTTP(w, r)
29	})
30}
31
32func getenvDefault(key string, def string) string {
33	res := os.Getenv(key)
34	if res == "" {
35		return def
36	}
37	return res
38}
39
40func getenvDefaultParse(key string, def string) float64 {
41	value := getenvDefault(key, def)
42	res, err := strconv.ParseFloat(value, 64)
43	if err != nil {
44		logger.Fatal(err)
45	}
46	return res
47}
48
49func main() {
50	err := godotenv.Load()
51	if err != nil {
52		logger.Info("No .env file provided.")
53	}
54
55	if os.Getenv("DEBUG") != "" {
56		logger.SetLevel(logrus.DebugLevel)
57		logger.Debug("Debug mode enabled (rate limiting is disabled)")
58		debugSwitch = true
59	}
60
61	apiKey = getenvDefault("API_KEY", "itsme")
62	port := getenvDefault("PORT", "3000")
63	burstTokens := getenvDefaultParse("BURST_TOKENS", "3")
64	rateLimit := getenvDefaultParse("RATE_LIMIT", "1")
65	cacheDuration := getenvDefaultParse("CACHE_DURATION_MINUTES", "5")
66	timeoutDuration := getenvDefaultParse("TIMEOUT_DURATION_MINUTES", "10")
67	cleanupInterval := getenvDefaultParse("CLEANUP_INTERVAL_SECONDS", "30")
68	maxSizeMB := getenvDefaultParse("MAX_SIZE_MB", "20")
69
70	myClient := &http.Client{Timeout: 10 * time.Second}
71	options := invidious.ClientOptions{
72		CacheDuration:   time.Duration(cacheDuration) * time.Minute,
73		TimeoutDuration: time.Duration(timeoutDuration) * time.Minute,
74		CleanupInterval: time.Duration(cleanupInterval) * time.Second,
75		MaxSizeBytes:    int64(maxSizeMB * 1000000),
76	}
77	videoapi := invidious.NewClient(myClient, options)
78
79	r := http.NewServeMux()
80	r.HandleFunc("/", indexHandler)
81	r.HandleFunc("/clear", clearHandler)
82	r.HandleFunc("/watch", watchHandler(videoapi))
83	r.HandleFunc("/proxy/{videoId}", proxyHandler(videoapi))
84	r.HandleFunc("/{videoId}", shortHandler(videoapi))
85
86	var serveMux http.Handler
87	if debugSwitch {
88		serveMux = r
89	} else {
90		limiter := rate.NewLimiter(rate.Limit(rateLimit), int(burstTokens))
91		serveMux = limit(limiter, r)
92	}
93	logger.Info("Serving on port ", port)
94	http.ListenAndServe(":"+port, serveMux)
95}