youtube/vimeo iframes

This commit is contained in:
Nazar Kanaev 2021-04-01 16:46:26 +01:00
parent 0a6e621c02
commit 2cd815d9cd
7 changed files with 93 additions and 11 deletions

View File

@ -1,4 +1,3 @@
- etc: test new parser extensively - etc: test new parser extensively
- etc: check feedburner - etc: check feedburner
- new: youtube/vimeo iframe generator in "read here"
- fix: loading items (by scrolling down) is glitching while feeds are refreshing - fix: loading items (by scrolling down) is glitching while feeds are refreshing

View File

@ -260,8 +260,10 @@
<time>{{ formatDate(itemSelectedDetails.date) }}</time> <time>{{ formatDate(itemSelectedDetails.date) }}</time>
</div> </div>
<hr> <hr>
<div v-if="!itemSelectedReadability">
<img :src="itemSelectedDetails.image" v-if="itemSelectedDetails.image" class="mb-3"> <img :src="itemSelectedDetails.image" v-if="itemSelectedDetails.image" class="mb-3">
<audio class="w-100" controls v-if="itemSelectedDetails.podcast_url" :src="itemSelectedDetails.podcast_url"></audio> <audio class="w-100" controls v-if="itemSelectedDetails.podcast_url" :src="itemSelectedDetails.podcast_url"></audio>
</div>
<div v-html="itemSelectedContent"></div> <div v-html="itemSelectedContent"></div>
</div> </div>
</div> </div>

View File

@ -105,7 +105,7 @@
return api('post', './logout') return api('post', './logout')
}, },
crawl: function(url) { crawl: function(url) {
return api('post', './page?url=' + url).then(json) return api('get', './page?url=' + url).then(json)
} }
} }
})() })()

View File

@ -386,6 +386,12 @@ select.form-control:not([multiple]):not([size]) {
height: auto; height: auto;
} }
.content iframe {
display: block;
max-width: 100%;
margin-bottom: 0.5rem;
}
.content pre { .content pre {
overflow-x: auto; overflow-x: auto;
color: inherit; color: inherit;

View File

@ -0,0 +1,38 @@
package silo
import (
"fmt"
"net/url"
"regexp"
"strings"
)
var (
youtubeFrame = `<iframe src="https://www.youtube.com/embed/%s" width="560" height="315" frameborder="0" allowfullscreen></iframe>`
vimeoFrame = `<iframe src="https://player.vimeo.com/video/%s" width="640" height="360" frameborder="0" allowfullscreen></iframe>`
vimeoRegex = regexp.MustCompile(`\/(\d+)$`)
)
func VideoIFrame(link string) string {
l, err := url.Parse(link)
if err != nil {
return ""
}
youtubeID := ""
if l.Host == "www.youtube.com" && l.Path == "/watch" {
youtubeID = l.Query().Get("v")
} else if l.Host == "youtu.be" {
youtubeID = strings.TrimLeft(l.Path, "/")
}
if youtubeID != "" {
return fmt.Sprintf(youtubeFrame, youtubeID)
}
if l.Host == "vimeo.com" {
if matches := vimeoRegex.FindStringSubmatch(l.Path); len(matches) > 0 {
return fmt.Sprintf(vimeoFrame, matches[1])
}
}
return ""
}

View File

@ -0,0 +1,36 @@
package silo
import "testing"
func TestYoutubeIframe(t *testing.T) {
links := []string{
"https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"https://youtu.be/dQw4w9WgXcQ",
"https://youtu.be/dQw4w9WgXcQ",
}
for _, link := range links {
have := VideoIFrame(link)
want := `<iframe src="https://www.youtube.com/embed/dQw4w9WgXcQ" width="560" height="315" frameborder="0" allowfullscreen></iframe>`
if have != want {
t.Logf("want: %s", want)
t.Logf("have: %s", have)
t.Fail()
}
}
}
func TestVimeoIframe(t *testing.T) {
links := []string{
"https://vimeo.com/channels/staffpicks/526381128",
"https://vimeo.com/526381128",
}
for _, link := range links {
have := VideoIFrame(link)
want := `<iframe src="https://player.vimeo.com/video/526381128" width="640" height="360" frameborder="0" allowfullscreen></iframe>`
if have != want {
t.Logf("want: %s", want)
t.Logf("have: %s", have)
t.Fail()
}
}
}

View File

@ -10,6 +10,7 @@ import (
"github.com/nkanaev/yarr/src/assets" "github.com/nkanaev/yarr/src/assets"
"github.com/nkanaev/yarr/src/content/readability" "github.com/nkanaev/yarr/src/content/readability"
"github.com/nkanaev/yarr/src/content/sanitizer" "github.com/nkanaev/yarr/src/content/sanitizer"
"github.com/nkanaev/yarr/src/content/silo"
"github.com/nkanaev/yarr/src/server/router" "github.com/nkanaev/yarr/src/server/router"
"github.com/nkanaev/yarr/src/server/auth" "github.com/nkanaev/yarr/src/server/auth"
"github.com/nkanaev/yarr/src/server/opml" "github.com/nkanaev/yarr/src/server/opml"
@ -403,19 +404,19 @@ func (s *Server) handleOPMLExport(c *router.Context) {
} }
func (s *Server) handlePageCrawl(c *router.Context) { func (s *Server) handlePageCrawl(c *router.Context) {
if c.Req.Method != "POST" {
c.Out.WriteHeader(http.StatusBadRequest)
return
}
url := c.Req.URL.Query().Get("url") url := c.Req.URL.Query().Get("url")
if url == "" {
c.Out.WriteHeader(http.StatusBadRequest) if content := silo.VideoIFrame(url); content != "" {
c.JSON(http.StatusOK, map[string]string{
"content": content,
})
return return
} }
res, err := http.Get(url) res, err := http.Get(url)
if err != nil { if err != nil {
log.Print(err) log.Print(err)
c.Out.WriteHeader(http.StatusNoContent) c.Out.WriteHeader(http.StatusBadRequest)
return return
} }
defer res.Body.Close() defer res.Body.Close()