diff options
author | emkael <emkael@tlen.pl> | 2025-04-08 02:24:30 +0200 |
---|---|---|
committer | emkael <emkael@tlen.pl> | 2025-04-08 02:24:30 +0200 |
commit | af150891df3b90fda846941d62ea76616f42a6ab (patch) | |
tree | 6363926d7f4a2fe09dc4d1b763b67fbb8d949c09 /providers | |
parent | af2da903d47550cdf1d7eb2d7b5e5b972d847958 (diff) |
Diffstat (limited to 'providers')
-rw-r--r-- | providers/Youtube.php | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/providers/Youtube.php b/providers/Youtube.php index bd38a52..03d0e27 100644 --- a/providers/Youtube.php +++ b/providers/Youtube.php @@ -3,9 +3,20 @@ namespace Providers; require_once('Rss.php'); +require_once('../lib/php-youtube-api/src/autoload.php'); class Youtube extends Rss { + const DEFAULT_MIN_DURATION = 60; + + public function __construct($feed, $options=[]) { + parent::__construct($feed, $options); + $config = json_decode(file_get_contents('../config/youtube.json'), TRUE); + $this->_youtube = new \Madcoda\Youtube\Youtube([ + 'key' => $config['key'] + ]); + } + protected function _getFeedUrl($feed) { return 'https://www.youtube.com/feeds/videos.xml?channel_id=' . $feed; } @@ -14,6 +25,90 @@ class Youtube extends Rss { return '../cache/youtube.%s'; } + protected function _mapRssItem($item) { + $itemObj = parent::_mapRssItem($item); + if (array_key_exists('descriptionlink', $this->_options)) { + $linkConfig = explode(':', $this->_options['descriptionlink']); + $linkDomain = NULL; + if (!is_numeric($linkConfig[0])) { + $linkDomain = array_shift($linkConfig); + if (!$linkConfig) { + $linkConfig = ['1']; + } + } + $linkIndex = intval($linkConfig[0]) - 1; + $textLinks = []; + if (preg_match_all('#(?:(?:https?|ftp):\/\/)?[\w/\-?=%.]+\.[\w/\-&?=%.]+#', $itemObj->Text, $textLinks)) { + $textLinks = $textLinks[0]; + if ($linkDomain) { + $textLinks = array_values(array_filter($textLinks, function($link) use($linkDomain) { + if($linkParts = parse_url($link)) { + return $linkParts['host'] == $linkDomain; + } + })); + } + if (count($textLinks) > $linkIndex) { + $itemObj->Link = $textLinks[$linkIndex]; + } + } + } + return $itemObj; + } + + private function _getVideoMetadata($ids) { + $cacheFile = sprintf($this->_getCachePath() . '.metadata', $this->_feed); + $cacheData = []; + if (file_exists($cacheFile)) { + $cacheData = unserialize(file_get_contents($cacheFile)); + } + $oldIDs = array_keys($cacheData); + $newIDs = array_diff($ids, $oldIDs); + if ($newIDs) { + $metadata = $this->_youtube->getVideosInfo($newIDs); + foreach ($metadata as $video) { + $cacheData[$video->id] = $video; + } + } + file_put_contents($cacheFile, serialize($cacheData)); + return array_filter($cacheData, function($item) use($ids) { + return in_array($item->id, $ids); + }); + } + + private function _getVideoDurations($ids) { + $metadata = $this->_getVideoMetadata($ids); + $return = []; + foreach ($ids as $id) { + $duration = new \DateInterval($metadata[$id]->contentDetails->duration); + $return[$id] = $duration->h * 3600 + $duration->i * 60 + $duration->s; + } + return $return; + } + + private function _getVideoID($item) { + return preg_replace('/^yt:video:/', '', $item->ID); + } + + protected function _filterItemContent($items) { + $items = parent::_filterItemContent($items); + + if (array_key_exists('duration', $this->_options)) { + $duration = intval($this->_options['duration']); + $videoIDs = array_map(array($this, '_getVideoID'), $items); + $durations = $this->_getVideoDurations($videoIDs); + $minDuration = self::DEFAULT_MIN_DURATION; + if (is_numeric($this->_options['duration'])) { + $minDuration = intval($this->_options['duration']); + } + $items = array_filter($items, function($item) use($minDuration, $durations) { + $videoID = $this->_getVideoID($item); + return $durations[$videoID] >= $minDuration; + }); + } + + return $items; + } + } ?> |