all repos — fixyoutube-go @ ca53f1b94dd67a7a9153a0ca0af1ba95c240da1f

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

invidious/proxy.go (view raw)

 1package invidious
 2
 3import (
 4	"bytes"
 5	"io"
 6	"net/http"
 7)
 8
 9func (c *Client) urlToBuffer(url string) (*VideoBuffer, int) {
10	if url == "" {
11		return nil, http.StatusBadRequest
12	}
13
14	req, err := http.NewRequest(http.MethodGet, url, nil)
15	if err != nil {
16		logger.Error(err) // bad request
17		return nil, http.StatusInternalServerError
18	}
19
20	resp, err := c.http.Do(req)
21	if err != nil {
22		logger.Error(err) // request failed
23		return nil, http.StatusGone
24	}
25
26	if resp.StatusCode != http.StatusOK {
27		return nil, resp.StatusCode
28	}
29
30	if resp.ContentLength == 0 {
31		return nil, http.StatusNoContent
32	}
33
34	if resp.ContentLength > maxSizeBytes {
35		logger.Debug("Content-Length exceeds max size.")
36		return nil, http.StatusBadRequest
37	}
38	defer resp.Body.Close()
39
40	b := new(bytes.Buffer)
41	l, err := io.Copy(b, resp.Body)
42	if l != resp.ContentLength {
43		logger.Debug("Content-Length is inconsistent.")
44		return nil, http.StatusBadRequest
45	}
46
47	return &VideoBuffer{b, l}, http.StatusOK
48}
49
50func (c *Client) findCompatibleFormat(video *Video) (*VideoBuffer, int) {
51	for i := len(video.Formats) - 1; i >= 0; i-- {
52		url := video.Formats[i].Url
53		logger.Debug(url)
54		vb, httpStatus := c.urlToBuffer(url)
55		if httpStatus == http.StatusOK {
56			videoBuffer := vb.Clone()
57			c.buffers.Set(video.VideoId, videoBuffer)
58			return vb, i
59		}
60		logger.Debug("Format ", i, "failed with status code ", httpStatus)
61	}
62	return nil, -1
63}
64
65func (c *Client) getBuffer(video Video) (*VideoBuffer, int) {
66	vb, err := c.buffers.Get(video.VideoId)
67	if err != nil {
68		vb, s := c.urlToBuffer(video.Url)
69		if vb.Length > 0 {
70			videoBuffer := vb.Clone()
71			c.buffers.Set(video.VideoId, videoBuffer)
72		}
73		return vb, s
74	}
75
76	videoBuffer := vb.Clone()
77	return videoBuffer, http.StatusOK
78}
79
80func (c *Client) ProxyVideoId(videoId string) (*VideoBuffer, int) {
81	video, err := GetVideoDB(videoId)
82	if err != nil {
83		logger.Info("Cannot proxy a video that is not cached: https://youtu.be/", videoId)
84		return nil, http.StatusBadRequest
85	}
86	return c.getBuffer(*video)
87}