get on gopipe's level (almost)
Marco Andronaco andronacomarco@gmail.com
Fri, 22 Nov 2024 22:18:12 +0100
6 files changed,
76 insertions(+),
27 deletions(-)
M
handlers.go
→
handlers.go
@@ -38,7 +38,7 @@ }
func clearHandler(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { - http.Redirect(w, r, "/", http.StatusMovedPermanently) + http.Redirect(w, r, "/", http.StatusFound) return }@@ -63,13 +63,15 @@ }
func videoHandler(videoId string, invidiousClient *invidious.Client, w http.ResponseWriter, r *http.Request) { url := "https://www.youtube.com/watch?v=" + videoId - userAgent := r.UserAgent() - res := userAgentRegex.MatchString(userAgent) - if !res { - logger.Debug("Regex did not match. Redirecting. UA:", userAgent) - http.Redirect(w, r, url, http.StatusMovedPermanently) - return - } + /* + userAgent := r.UserAgent() + res := userAgentRegex.MatchString(userAgent) + if !res { + logger.Debug("Regex did not match. Redirecting. UA:", userAgent) + http.Redirect(w, r, url, http.StatusFound) + return + } + */ if !videoRegex.MatchString(videoId) { logger.Info("Invalid video ID: ", videoId)@@ -86,7 +88,7 @@ }
if video.Url == "" { logger.Debug("No URL available. Redirecting.") - http.Redirect(w, r, url, http.StatusMovedPermanently) + http.Redirect(w, r, url, http.StatusFound) return }
M
invidious/api.go
→
invidious/api.go
@@ -15,6 +15,14 @@ Name string `json:"qualityLabel"`
Url string `json:"url"` Container string `json:"container"` Size string `json:"size"` + Itag string `json:"itag"` +} + +type VideoThumbnail struct { + Quality string `json:"quality"` + URL string `json:"url"` + Width int `json:"width"` + Height int `json:"height"` } func (c *Client) fetchVideo(videoId string) (*Video, int) {@@ -48,7 +56,11 @@ logger.Error(err)
return nil, http.StatusInternalServerError } - mp4Test := func(f Format) bool { return f.Container == "mp4" } + if len(res.VideoThumbnails) > 0 { + res.Thumbnail = res.VideoThumbnails[0].URL + } + + mp4Test := func(f Format) bool { return f.Itag == "18" } res.Formats = filter(res.Formats, mp4Test) expireString := expireRegex.FindStringSubmatch(res.Formats[0].Url)
M
invidious/cache.go
→
invidious/cache.go
@@ -42,7 +42,7 @@ return err
} defer cacheVideo.Close() - _, err = cacheVideo.Exec(v.VideoId, v.Title, v.Description, v.Uploader, v.Duration, v.Url, v.Expire) + _, err = cacheVideo.Exec(v.VideoId, v.Title, v.Description, v.Uploader, v.Duration, v.Url, v.Thumbnail, v.Expire) if err != nil { logger.Error("Could not cache video: ", err) return err@@ -63,7 +63,7 @@ }
defer getVideo.Close() v := &Video{} - err = getVideo.QueryRow(videoId).Scan(&v.VideoId, &v.Title, &v.Description, &v.Uploader, &v.Duration, &v.Url, &v.Expire) + err = getVideo.QueryRow(videoId).Scan(&v.VideoId, &v.Title, &v.Description, &v.Uploader, &v.Duration, &v.Url, &v.Thumbnail, &v.Expire) if err != nil { logger.Debug("Could not get video:", err) return nil, err
M
invidious/invidious.go
→
invidious/invidious.go
@@ -37,14 +37,16 @@ Options ClientOptions
} type Video struct { - VideoId string `json:"videoId"` - Title string `json:"title"` - Description string `json:"description"` - Uploader string `json:"author"` - Duration int `json:"lengthSeconds"` - Formats []Format `json:"formatStreams"` - Expire time.Time - Url string + VideoId string `json:"videoId"` + Title string `json:"title"` + Description string `json:"description"` + Uploader string `json:"author"` + VideoThumbnails []VideoThumbnail `json:"videoThumbnails"` + Duration int `json:"lengthSeconds"` + Formats []Format `json:"formatStreams"` + Expire time.Time + Url string + Thumbnail string } func filter[T any](ss []T, test func(T) bool) (ret []T) {
M
invidious/queries.go
→
invidious/queries.go
@@ -8,11 +8,12 @@ description TEXT NOT NULL,
uploader TEXT NOT NULL, duration int NOT NULL, url TEXT NOT NULL, + thumbnail TEXT, expire DATETIME NOT NULL );` const getVideoQuery = "SELECT * FROM videos WHERE videoId = (?);" -const cacheVideoQuery = "INSERT OR REPLACE INTO videos (videoId, title, description, uploader, duration, url, expire) VALUES (?, ?, ?, ?, ?, ?, ?);" +const cacheVideoQuery = "INSERT OR REPLACE INTO videos (videoId, title, description, uploader, duration, url, thumbnail, expire) VALUES (?, ?, ?, ?, ?, ?, ?);" const clearQuery = "DELETE FROM videos;"
M
templates/video.html
→
templates/video.html
@@ -1,4 +1,5 @@
-<!DOCTYPE html> +<!doctype html> +<!-- ███████ ██ ██ ██ ██ ██ ███ ██ ██ ██████ ██ ██ ██████ ███████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ █████ ██ ███ ████ ██ ██ ██ ██ ██ ██ ██ ██████ █████@@ -7,9 +8,14 @@ ██ ██ ██ ██ ██ ███ ███ ██ ███ ██████ ███████
██ ██ A better way to embed YouTube videos on Telegram (inspired by FixTweet). ██ -<html lang="en"><head> +--> +<html lang="en"> + +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <title>{{ .Title }} - GoPipe</title> <link rel="canonical" href="https://www.youtube.com/watch?v={{ .VideoId }}" /> - <meta http-equiv="refresh" content="0;url=https://www.youtube.com/watch?v={{ .VideoId }}" /> <meta property="og:url" content="https://www.youtube.com/watch?v={{ .VideoId }}" /> <meta property="theme-color" content="0000FF" /> <meta property="twitter:card" content="player" />@@ -18,8 +24,8 @@ <meta property="twitter:creator" content="{{ .Uploader }}" />
<meta property="twitter:title" content="{{ .Title }}" /> <meta property="og:title" content="{{ .Title }}" /> <meta property="og:description" content="{{ .Description }}" /> - <meta property="og:site_name" content="FixYouTube ({{ .Uploader }})" /> - <meta property="twitter:image" content="0" /> + <meta property="og:site_name" content="GoPipe ({{ .Uploader }})" /> + <meta property="twitter:image" content="{{ .Thumbnail }}" /> <meta property="twitter:player:stream:content_type" content="video/mp4" /> {{ if .Url }} <meta property="og:video" content="{{ .Url }}" />@@ -27,4 +33,30 @@ <meta property="og:video:secure_url" content="{{ .Url }}" />
<meta property="og:video:duration" content="{{ .Duration }}"> <meta property="og:video:type" content="video/mp4" /> {{ end }} -</head><body></body></html> + <link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text fill=%22white%22 y=%22.9em%22 font-size=%2290%22>🛠</text></svg>"> + <link rel="stylesheet" href="https://unpkg.com/@picocss/pico@latest/css/pico.min.css"> +</head> + +<body> + <main class="container" style="max-width: 35rem"> + <video style="width: 100%" autoplay controls> + <source src="{{ .Url }}" type="video/mp4" /> + </video> + <h2>{{ .Title }}</h2> + <h3>> {{ .Uploader }}</h3> + <pre style="white-space: pre-wrap">{{ .Description }}</pre> + <a href="https://www.youtube.com/watch?v={{ .VideoId }}">Watch on YouTube</a> + <br /> + <a href="/">What is this?</a> + <hr> + <section> + <small> + <a href="https://github.com/birabittoh/fixyoutube-go" target="_blank">Source code</a> + </small> + <br /> + <small>• YouTube is a trademark of Google LLC. This app is not affiliated with Google LLC.</small> + </section> + </main> +</body> + +</html>