diff --git a/doc/todo.txt b/doc/todo.txt index 2ea5236..85bf458 100644 --- a/doc/todo.txt +++ b/doc/todo.txt @@ -1,4 +1,3 @@ - etc: test new parser extensively - etc: check feedburner -- new: youtube/vimeo iframe generator in "read here" - fix: loading items (by scrolling down) is glitching while feeds are refreshing diff --git a/src/assets/index.html b/src/assets/index.html index 46bf240..5814253 100644 --- a/src/assets/index.html +++ b/src/assets/index.html @@ -260,8 +260,10 @@
- - +
+ + +
diff --git a/src/assets/javascripts/api.js b/src/assets/javascripts/api.js index 3422465..ead9e8f 100644 --- a/src/assets/javascripts/api.js +++ b/src/assets/javascripts/api.js @@ -105,7 +105,7 @@ return api('post', './logout') }, crawl: function(url) { - return api('post', './page?url=' + url).then(json) + return api('get', './page?url=' + url).then(json) } } })() diff --git a/src/assets/stylesheets/app.css b/src/assets/stylesheets/app.css index 277d001..1525250 100644 --- a/src/assets/stylesheets/app.css +++ b/src/assets/stylesheets/app.css @@ -386,6 +386,12 @@ select.form-control:not([multiple]):not([size]) { height: auto; } +.content iframe { + display: block; + max-width: 100%; + margin-bottom: 0.5rem; +} + .content pre { overflow-x: auto; color: inherit; diff --git a/src/content/silo/iframe.go b/src/content/silo/iframe.go new file mode 100644 index 0000000..57fc6d6 --- /dev/null +++ b/src/content/silo/iframe.go @@ -0,0 +1,38 @@ +package silo + +import ( + "fmt" + "net/url" + "regexp" + "strings" +) + +var ( + youtubeFrame = `` + vimeoFrame = `` + 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 "" +} diff --git a/src/content/silo/iframe_test.go b/src/content/silo/iframe_test.go new file mode 100644 index 0000000..1b88802 --- /dev/null +++ b/src/content/silo/iframe_test.go @@ -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 := `` + 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 := `` + if have != want { + t.Logf("want: %s", want) + t.Logf("have: %s", have) + t.Fail() + } + } +} diff --git a/src/server/routes.go b/src/server/routes.go index daf033c..36a3928 100644 --- a/src/server/routes.go +++ b/src/server/routes.go @@ -10,6 +10,7 @@ import ( "github.com/nkanaev/yarr/src/assets" "github.com/nkanaev/yarr/src/content/readability" "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/auth" "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) { - if c.Req.Method != "POST" { - c.Out.WriteHeader(http.StatusBadRequest) - return - } 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 } + res, err := http.Get(url) if err != nil { log.Print(err) - c.Out.WriteHeader(http.StatusNoContent) + c.Out.WriteHeader(http.StatusBadRequest) return } defer res.Body.Close()