From bff164146b101a18392f22cd942ec1c9a8589628 Mon Sep 17 00:00:00 2001 From: Bernhard Posselt Date: Tue, 11 Nov 2014 13:21:51 +0100 Subject: add youtube playlist support, fix #620, fix #618 --- CHANGELOG.md | 3 ++ appinfo/application.php | 8 ++++ fetcher/youtubefetcher.php | 75 +++++++++++++++++++++++++++++++ tests/unit/fetcher/YoutubeFetcherTest.php | 68 ++++++++++++++++++++++++++++ 4 files changed, 154 insertions(+) create mode 100644 fetcher/youtubefetcher.php create mode 100644 tests/unit/fetcher/YoutubeFetcherTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index b7f31e9c1..ad30876e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +owncloud-news (4.0.2) +* **Enhancement**: Transform YouTube urls to allow subscribing to channels and playlists + owncloud-news (4.0.1) * **Bugfix**: Fix heise.de encoding issues diff --git a/appinfo/application.php b/appinfo/application.php index 84b0440f3..3820603b0 100644 --- a/appinfo/application.php +++ b/appinfo/application.php @@ -55,6 +55,7 @@ use \OCA\News\Utility\ProxyConfigParser; use \OCA\News\Fetcher\Fetcher; use \OCA\News\Fetcher\FeedFetcher; +use \OCA\News\Fetcher\YoutubeFetcher; use \OCA\News\ArticleEnhancer\Enhancer; use \OCA\News\ArticleEnhancer\GlobalArticleEnhancer; @@ -466,6 +467,7 @@ class Application extends App { // register fetchers in order // the most generic fetcher should be the last one + $fetcher->registerFetcher($c->query('YoutubeFetcher')); $fetcher->registerFetcher($c->query('FeedFetcher')); return $fetcher; @@ -480,6 +482,12 @@ class Application extends App { ); }); + $container->registerService('YoutubeFetcher', function($c) { + return new YoutubeFetcher( + $c->query('FeedFetcher') + ); + }); + $container->registerService('StatusFlag', function() { return new StatusFlag(); }); diff --git a/fetcher/youtubefetcher.php b/fetcher/youtubefetcher.php new file mode 100644 index 000000000..cc96e987f --- /dev/null +++ b/fetcher/youtubefetcher.php @@ -0,0 +1,75 @@ + + * @copyright Bernhard Posselt 2012, 2014 + */ + +namespace OCA\News\Fetcher; + + +class YoutubeFetcher implements IFeedFetcher { + + private $feedFetcher; + + public function __construct(FeedFetcher $feedFetcher){ + $this->feedFetcher = $feedFetcher; + } + + + private function buildUrl($url) { + $baseRegex = '%(?:https?://|//)?(?:www.)?youtube.com'; + $playRegex = $baseRegex . '.*?list=([^&]*)%'; + + if (preg_match($playRegex, $url, $matches)) { + $id = $matches[1]; + return 'http://gdata.youtube.com/feeds/api/playlists/' . $id; + } else { + return false; + } + } + + + /** + * This fetcher handles all the remaining urls therefore always returns true + */ + public function canHandle($url){ + return $this->buildUrl($url) !== false; + } + + + /** + * Fetch a feed from remote + * @param string $url remote url of the feed + * @param boolean $getFavicon if the favicon should also be fetched, + * defaults to true + * @param string $lastModified a last modified value from an http header + * defaults to false. If lastModified matches the http header from the feed + * no results are fetched + * @param string $etag an etag from an http header. + * If lastModified matches the http header from the feed + * no results are fetched + * @throws FetcherException if it fails + * @return array an array containing the new feed and its items, first + * element being the Feed and second element being an array of Items + */ + public function fetch($url, $getFavicon=true, $lastModified=null, + $etag=null) { + $transformedUrl = $this->buildUrl($url); + + $result = $this->feedFetcher->fetch( + $transformedUrl, $getFavicon, $lastModified, $etag + ); + + // reset feed url so we know the correct added url for the feed + $result[0]->setUrl($url); + + return $result; + } + + +} diff --git a/tests/unit/fetcher/YoutubeFetcherTest.php b/tests/unit/fetcher/YoutubeFetcherTest.php new file mode 100644 index 000000000..4adf734ba --- /dev/null +++ b/tests/unit/fetcher/YoutubeFetcherTest.php @@ -0,0 +1,68 @@ + + * @copyright Bernhard Posselt 2012, 2014 + */ + +namespace OCA\News\Fetcher; + +use \OCA\News\Db\Feed; + + +class YoutubeFetcherTest extends \PHPUnit_Framework_TestCase { + + private $fetcher; + private $feedFetcher; + + public function setUp() { + $this->feedFetcher = $this->getMockBuilder( + '\OCA\News\Fetcher\FeedFetcher') + ->disableOriginalConstructor() + ->getMock(); + $this->fetcher = new YoutubeFetcher($this->feedFetcher); + } + + + public function testCanHandleFails() { + $url = 'http://youtube.com'; + $this->assertFalse($this->fetcher->canHandle($url)); + } + + + public function testCanHandle() { + $url = 'http://youtube.com/test/?test=a&list=b&b=c'; + $this->assertTrue($this->fetcher->canHandle($url)); + } + + + public function testPlaylistUrl() { + $url = 'http://youtube.com/something/weird?a=b&list=sobo3&c=1'; + $transformedUrl = 'http://gdata.youtube.com/feeds/api/playlists/sobo3'; + $favicon = true; + $modified = 3; + $etag = 5; + $feed = new Feed(); + $feed->setUrl('http://google.de'); + $result = [$feed, []]; + + $this->feedFetcher->expects($this->once()) + ->method('fetch') + ->with( + $this->equalTo($transformedUrl), + $this->equalTo($favicon), + $this->equalTo($modified), + $this->equalTo($etag) + ) + ->will($this->returnValue($result)); + $feed = $this->fetcher->fetch($url, $favicon, $modified, $etag); + + $this->assertEquals($url, $result[0]->getUrl()); + } + + +} \ No newline at end of file -- cgit v1.2.3