mirror of
https://github.com/miniflux/v2.git
synced 2025-06-27 16:36:00 +00:00
feat(rewrite): add support for YouTube Shorts video URL pattern
This commit is contained in:
parent
8a014c6abc
commit
40727704c2
3 changed files with 109 additions and 16 deletions
|
@ -21,7 +21,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
youtubeRegex = regexp.MustCompile(`youtube\.com/watch\?v=(.*)$`)
|
youtubeVideoRegex = regexp.MustCompile(`youtube\.com/watch\?v=(.*)$`)
|
||||||
|
youtubeShortRegex = regexp.MustCompile(`youtube\.com/shorts/([a-zA-Z0-9_-]{11})$`)
|
||||||
youtubeIdRegex = regexp.MustCompile(`youtube_id"?\s*[:=]\s*"([a-zA-Z0-9_-]{11})"`)
|
youtubeIdRegex = regexp.MustCompile(`youtube_id"?\s*[:=]\s*"([a-zA-Z0-9_-]{11})"`)
|
||||||
invidioRegex = regexp.MustCompile(`https?://(.*)/watch\?v=(.*)`)
|
invidioRegex = regexp.MustCompile(`https?://(.*)/watch\?v=(.*)`)
|
||||||
textLinkRegex = regexp.MustCompile(`(?mi)(\bhttps?:\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])`)
|
textLinkRegex = regexp.MustCompile(`(?mi)(\bhttps?:\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])`)
|
||||||
|
@ -259,22 +260,34 @@ func useNoScriptImages(entryContent string) string {
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
func addYoutubeVideo(entryURL, entryContent string) string {
|
func getYoutubVideoIDFromURL(entryURL string) string {
|
||||||
matches := youtubeRegex.FindStringSubmatch(entryURL)
|
matches := youtubeVideoRegex.FindStringSubmatch(entryURL)
|
||||||
|
|
||||||
|
if len(matches) != 2 {
|
||||||
|
matches = youtubeShortRegex.FindStringSubmatch(entryURL)
|
||||||
|
}
|
||||||
|
|
||||||
if len(matches) == 2 {
|
if len(matches) == 2 {
|
||||||
video := `<iframe width="650" height="350" frameborder="0" src="` + config.Opts.YouTubeEmbedUrlOverride() + matches[1] + `" allowfullscreen></iframe>`
|
return matches[1]
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func addVideoPlayerIframe(absoluteVideoURL, entryContent string) string {
|
||||||
|
video := `<iframe width="650" height="350" frameborder="0" src="` + absoluteVideoURL + `" allowfullscreen></iframe>`
|
||||||
return video + `<br>` + entryContent
|
return video + `<br>` + entryContent
|
||||||
|
}
|
||||||
|
|
||||||
|
func addYoutubeVideoRewriteRule(entryURL, entryContent string) string {
|
||||||
|
if videoURL := getYoutubVideoIDFromURL(entryURL); videoURL != "" {
|
||||||
|
return addVideoPlayerIframe(config.Opts.YouTubeEmbedUrlOverride()+videoURL, entryContent)
|
||||||
}
|
}
|
||||||
return entryContent
|
return entryContent
|
||||||
}
|
}
|
||||||
|
|
||||||
func addYoutubeVideoUsingInvidiousPlayer(entryURL, entryContent string) string {
|
func addYoutubeVideoUsingInvidiousPlayer(entryURL, entryContent string) string {
|
||||||
matches := youtubeRegex.FindStringSubmatch(entryURL)
|
if videoURL := getYoutubVideoIDFromURL(entryURL); videoURL != "" {
|
||||||
|
return addVideoPlayerIframe(`https://`+config.Opts.InvidiousInstance()+`/embed/`+videoURL, entryContent)
|
||||||
if len(matches) == 2 {
|
|
||||||
video := `<iframe width="650" height="350" frameborder="0" src="https://` + config.Opts.InvidiousInstance() + `/embed/` + matches[1] + `" allowfullscreen></iframe>`
|
|
||||||
return video + `<br>` + entryContent
|
|
||||||
}
|
}
|
||||||
return entryContent
|
return entryContent
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ func (rule rule) applyRule(entryURL string, entry *model.Entry) {
|
||||||
case "add_dynamic_iframe":
|
case "add_dynamic_iframe":
|
||||||
entry.Content = addDynamicIframe(entry.Content)
|
entry.Content = addDynamicIframe(entry.Content)
|
||||||
case "add_youtube_video":
|
case "add_youtube_video":
|
||||||
entry.Content = addYoutubeVideo(entryURL, entry.Content)
|
entry.Content = addYoutubeVideoRewriteRule(entryURL, entry.Content)
|
||||||
case "add_invidious_video":
|
case "add_invidious_video":
|
||||||
entry.Content = addInvidiousVideo(entryURL, entry.Content)
|
entry.Content = addInvidiousVideo(entryURL, entry.Content)
|
||||||
case "add_youtube_video_using_invidious_player":
|
case "add_youtube_video_using_invidious_player":
|
||||||
|
|
|
@ -66,7 +66,7 @@ func TestRewriteWithNoMatchingRule(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRewriteWithYoutubeLink(t *testing.T) {
|
func TestRewriteYoutubeVideoLink(t *testing.T) {
|
||||||
config.Opts = config.NewOptions()
|
config.Opts = config.NewOptions()
|
||||||
|
|
||||||
controlEntry := &model.Entry{
|
controlEntry := &model.Entry{
|
||||||
|
@ -86,7 +86,47 @@ func TestRewriteWithYoutubeLink(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRewriteWithYoutubeLinkAndCustomEmbedURL(t *testing.T) {
|
func TestRewriteYoutubeShortLink(t *testing.T) {
|
||||||
|
config.Opts = config.NewOptions()
|
||||||
|
|
||||||
|
controlEntry := &model.Entry{
|
||||||
|
URL: "https://www.youtube.com/shorts/1LUWKWZkPjo",
|
||||||
|
Title: `A title`,
|
||||||
|
Content: `<iframe width="650" height="350" frameborder="0" src="https://www.youtube-nocookie.com/embed/1LUWKWZkPjo" allowfullscreen></iframe><br>Video Description`,
|
||||||
|
}
|
||||||
|
testEntry := &model.Entry{
|
||||||
|
URL: "https://www.youtube.com/shorts/1LUWKWZkPjo",
|
||||||
|
Title: `A title`,
|
||||||
|
Content: `Video Description`,
|
||||||
|
}
|
||||||
|
ApplyContentRewriteRules(testEntry, ``)
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(testEntry, controlEntry) {
|
||||||
|
t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRewriteIncorrectYoutubeLink(t *testing.T) {
|
||||||
|
config.Opts = config.NewOptions()
|
||||||
|
|
||||||
|
controlEntry := &model.Entry{
|
||||||
|
URL: "https://www.youtube.com/some-page",
|
||||||
|
Title: `A title`,
|
||||||
|
Content: `Video Description`,
|
||||||
|
}
|
||||||
|
testEntry := &model.Entry{
|
||||||
|
URL: "https://www.youtube.com/some-page",
|
||||||
|
Title: `A title`,
|
||||||
|
Content: `Video Description`,
|
||||||
|
}
|
||||||
|
ApplyContentRewriteRules(testEntry, ``)
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(testEntry, controlEntry) {
|
||||||
|
t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRewriteYoutubeLinkAndCustomEmbedURL(t *testing.T) {
|
||||||
os.Clearenv()
|
os.Clearenv()
|
||||||
os.Setenv("YOUTUBE_EMBED_URL_OVERRIDE", "https://invidious.custom/embed/")
|
os.Setenv("YOUTUBE_EMBED_URL_OVERRIDE", "https://invidious.custom/embed/")
|
||||||
|
|
||||||
|
@ -115,6 +155,46 @@ func TestRewriteWithYoutubeLinkAndCustomEmbedURL(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRewriteYoutubeVideoLinkUsingInvidious(t *testing.T) {
|
||||||
|
config.Opts = config.NewOptions()
|
||||||
|
controlEntry := &model.Entry{
|
||||||
|
URL: "https://www.youtube.com/watch?v=1234",
|
||||||
|
Title: `A title`,
|
||||||
|
Content: `<iframe width="650" height="350" frameborder="0" src="https://yewtu.be/embed/1234" allowfullscreen></iframe><br>Video Description`,
|
||||||
|
}
|
||||||
|
testEntry := &model.Entry{
|
||||||
|
URL: "https://www.youtube.com/watch?v=1234",
|
||||||
|
Title: `A title`,
|
||||||
|
Content: `Video Description`,
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplyContentRewriteRules(testEntry, `add_youtube_video_using_invidious_player`)
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(testEntry, controlEntry) {
|
||||||
|
t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRewriteYoutubeShortLinkUsingInvidious(t *testing.T) {
|
||||||
|
config.Opts = config.NewOptions()
|
||||||
|
controlEntry := &model.Entry{
|
||||||
|
URL: "https://www.youtube.com/shorts/1LUWKWZkPjo",
|
||||||
|
Title: `A title`,
|
||||||
|
Content: `<iframe width="650" height="350" frameborder="0" src="https://yewtu.be/embed/1LUWKWZkPjo" allowfullscreen></iframe><br>Video Description`,
|
||||||
|
}
|
||||||
|
testEntry := &model.Entry{
|
||||||
|
URL: "https://www.youtube.com/shorts/1LUWKWZkPjo",
|
||||||
|
Title: `A title`,
|
||||||
|
Content: `Video Description`,
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplyContentRewriteRules(testEntry, `add_youtube_video_using_invidious_player`)
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(testEntry, controlEntry) {
|
||||||
|
t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestRewriteWithInexistingCustomRule(t *testing.T) {
|
func TestRewriteWithInexistingCustomRule(t *testing.T) {
|
||||||
controlEntry := &model.Entry{
|
controlEntry := &model.Entry{
|
||||||
URL: "https://www.youtube.com/watch?v=1234",
|
URL: "https://www.youtube.com/watch?v=1234",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue