diff --git a/README.md b/README.md index 2f636ea..ff77ccd 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ Downloadable archive packages for numbered releases will also be available from 1. Download the contents of the extension, as outlined above. 2. Create an EmbedVideo folder in the extensions/ folder of your MediaWiki installation. 3. Copy the contents of this distribution into that folder +4. Install FFmpeg, when using the local video handler (enabled by default) Add the following line to your LocalSettings.php: @@ -151,6 +152,9 @@ E.g. using named id and unnamed description `{{#ev:service||||This is the Descri ## Examples +## SharePoint +For more information on SharePoint embeds see [Issue #60](https://github.com/StarCitizenWiki/mediawiki-extensions-EmbedVideo/issues/60#issuecomment-1641493146). + ### YouTube Examples #### YouTube Example #1 @@ -225,9 +229,12 @@ As of version 3.x, EmbedVideo supports embedding video content from the followin |----------------------------------------------------------|---------------------------------|--------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------| | [Archive.org Videos](https://archive.org/details/movies) | `archiveorg` | electricsheep-flock-244-80000-6 | https://archive.org/details/electricsheep-flock-244-80000-6
https://archive.org/embed/electricsheep-flock-244-80000-6 | | [Bilibili](https://www.bilibili.com/) | `bilibili` | BV1Hz4y1k7ae | https://player.bilibili.com/player.html?bvid=1Hz4y1k7ae&page=1 | -| [KakaoTV](https://tv.kakao.com/) | `kakaotv` | 301157950 | https://play-tv.kakao.com/embed/player/cliplink/301157950 | -| [NaverTV](https://tv.naver.com/) | `navertv` | 27831593 | https://tv.naver.com/embed/27831593 | +| [DailyMotion](https://dailymotion.com/) | `dailymotion` | x1adiiw_archer-waking-up-as-h-jon-benjamin_shortfilms | http://www.dailymotion.com/video/x1adiiw_archer-waking-up-as-h-jon-benjamin_shortfilms | +| [KakaoTV](https://tv.kakao.com/) | `kakaotv` | 301157950 | https://play-tv.kakao.com/embed/player/cliplink/301157950 | +| [Loom](https://www.loom.com/) | `loom` | e5b8c04bca094dd8a5507925ab887002 | https://www.loom.com/share/e5b8c04bca094dd8a5507925ab887002 | +| [NaverTV](https://tv.naver.com/) | `navertv` | 27831593 | https://tv.naver.com/embed/27831593 | | [Niconico](http://nicovideo.jp/) | `niconico` | sm40807360 | https://embed.nicovideo.jp/watch/sm40807360 | +| SharePoint | `sharepoint` | Not Applicable | https://[SUB].sharepoint.com/sites/[PATH]/_layouts/15/embed.aspx?UniqueId=[ID]&embed=[...] | | [SoundCloud](http://soundcloud.com/) | `soundcloud` | | https://soundcloud.com/skrillex/skrillex-rick-ross-purple-lamborghini | | [Spotify](http://spotify.com/) | `spotifyalbum` - Art embed | 3B61kSKTxlY36cYgzvf3cP | https://open.spotify.com/album/3B61kSKTxlY36cYgzvf3cP | | [Spotify](http://spotify.com/) | `spotifyartist` - Artist embed | 0YC192cP3KPCRWx8zr8MfZ | https://open.spotify.com/artist/0YC192cP3KPCRWx8zr8MfZ | diff --git a/composer.json b/composer.json index 077c9ca..0f5153a 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "starcitizenwiki/embedvideo", - "version": "3.2.7", + "version": "3.2.8", "type": "mediawiki-extension", "description": "Adds a parser function embedding video from popular sources.", "license": "MIT", diff --git a/extension.json b/extension.json index cec1d49..e8c566a 100644 --- a/extension.json +++ b/extension.json @@ -1,6 +1,6 @@ { "name": "EmbedVideo", - "version": "3.2.7", + "version": "3.2.8", "author": [ "[https://www.mediawiki.org/wiki/User:Octfx Octfx]", "[https://www.mediawiki.org/wiki/User:Alistair3149 Alistair3149]", @@ -14,7 +14,7 @@ "license-name": "MIT", "type": "parserhook", "requires": { - "MediaWiki": ">= 1.35.0", + "MediaWiki": ">= 1.37.0", "platform": { "php": ">=7.3.0", "ext-curl": "*" diff --git a/i18n/de.json b/i18n/de.json index 0a99c60..04a7cc5 100644 --- a/i18n/de.json +++ b/i18n/de.json @@ -20,9 +20,11 @@ "embedvideo-service-archiveorg": "Archiv.org", "embedvideo-service-bilibili": "Bilibili", "embedvideo-service-kakaotv": "KakaoTV", + "embedvideo-service-loom": "Loom", "embedvideo-service-navertv": "NaverTV", "embedvideo-service-niconico": "Niconico", "embedvideo-service-soundcloud": "SoundCloud", + "embedvideo-service-sharepoint": "SharePoint", "embedvideo-service-spotify": "Spotify", "embedvideo-service-twitch": "Twitch", "embedvideo-service-vimeo": "Vimeo", diff --git a/i18n/en.json b/i18n/en.json index b32dd91..c2c99c9 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -13,10 +13,13 @@ "embedvideo-consent-privacy-notice-dismiss": "Dismiss", "embedvideo-service-archiveorg": "Archive.org", "embedvideo-service-bilibili": "Bilibili", + "embedvideo-service-dailymotion": "Dailymotion", "embedvideo-service-kakaotv": "KakaoTV", + "embedvideo-service-loom": "Loom", "embedvideo-service-navertv": "NaverTV", "embedvideo-service-niconico": "Niconico", "embedvideo-service-soundcloud": "SoundCloud", + "embedvideo-service-sharepoint": "SharePoint", "embedvideo-service-spotify": "Spotify", "embedvideo-service-twitch": "Twitch", "embedvideo-service-vimeo": "Vimeo", diff --git a/i18n/fr.json b/i18n/fr.json index 1f4ac90..c8b628f 100644 --- a/i18n/fr.json +++ b/i18n/fr.json @@ -18,10 +18,13 @@ "embedvideo-consent-privacy-notice-dismiss": "Ignorer", "embedvideo-service-archiveorg": "Archive.org", "embedvideo-service-bilibili": "Bilibili", + "embedvideo-service-dailymotion": "Dailymotion", "embedvideo-service-kakaotv": "KakaoTV", + "embedvideo-service-loom": "Loom", "embedvideo-service-navertv": "NaverTV", "embedvideo-service-niconico": "Niconico", "embedvideo-service-soundcloud": "SoundCloud", + "embedvideo-service-sharepoint": "SharePoint", "embedvideo-service-spotify": "Spotify", "embedvideo-service-twitch": "Twitch", "embedvideo-service-vimeo": "Vimeo", diff --git a/i18n/ia.json b/i18n/ia.json index e062e78..3dbccab 100644 --- a/i18n/ia.json +++ b/i18n/ia.json @@ -15,10 +15,13 @@ "embedvideo-consent-privacy-notice-dismiss": "Clauder", "embedvideo-service-archiveorg": "Archive.org", "embedvideo-service-bilibili": "Bilibili", + "embedvideo-service-dailymotion": "Dailymotion", "embedvideo-service-kakaotv": "KakaoTV", + "embedvideo-service-loom": "Loom", "embedvideo-service-navertv": "NaverTV", "embedvideo-service-niconico": "Niconico", "embedvideo-service-soundcloud": "SoundCloud", + "embedvideo-service-sharepoint": "SharePoint", "embedvideo-service-spotify": "Spotify", "embedvideo-service-twitch": "Twitch", "embedvideo-service-vimeo": "Vimeo", diff --git a/i18n/lb.json b/i18n/lb.json index 1cfe41b..60f9ce3 100644 --- a/i18n/lb.json +++ b/i18n/lb.json @@ -12,6 +12,8 @@ "embedvideo-consent-privacy-notice-continue": "Virufueren", "embedvideo-consent-privacy-notice-dismiss": "Verwerfen", "embedvideo-service-bilibili": "Bilibili", + "embedvideo-service-dailymotion": "Dailymotion", + "embedvideo-service-sharepoint": "SharePoint", "embedvideo-service-fauxembedservice": "Lokale Fichier", "embedvideo-play": "Video spillen", "embedvideo-error-cantdecode_evu": "Konnt de Video vun $1 net analyséieren", diff --git a/i18n/mk.json b/i18n/mk.json index c6fa5a5..6cf4876 100644 --- a/i18n/mk.json +++ b/i18n/mk.json @@ -15,10 +15,13 @@ "embedvideo-consent-privacy-notice-dismiss": "Тргни", "embedvideo-service-archiveorg": "Archive.org", "embedvideo-service-bilibili": "Bilibili", + "embedvideo-service-dailymotion": "Dailymotion", "embedvideo-service-kakaotv": "KakaoTV", + "embedvideo-service-loom": "Loom", "embedvideo-service-navertv": "NaverTV", "embedvideo-service-niconico": "Niconico", "embedvideo-service-soundcloud": "SoundCloud", + "embedvideo-service-sharepoint": "SharePoint", "embedvideo-service-spotify": "Spotify", "embedvideo-service-twitch": "Twitch", "embedvideo-service-vimeo": "Vimeo", diff --git a/i18n/qqq.json b/i18n/qqq.json index b63e42a..8911522 100644 --- a/i18n/qqq.json +++ b/i18n/qqq.json @@ -2,6 +2,7 @@ "@metadata": { "authors": [ "Amire80", + "McDutchie", "Robby" ] }, @@ -9,6 +10,7 @@ "embedvideo-consent-privacy-notice-dismiss": "{{identical|Dismiss}}", "embedvideo-service-archiveorg": "{{Optional}}", "embedvideo-service-bilibili": "{{Optional}}", + "embedvideo-service-dailymotion": "Name of Dailymotion video streaming service, see https://www.dailymotion.com", "embedvideo-service-kakaotv": "{{Optional}}", "embedvideo-service-navertv": "{{Optional}}", "embedvideo-service-niconico": "{{Optional}}", diff --git a/i18n/sh.json b/i18n/sh-latn.json similarity index 97% rename from i18n/sh.json rename to i18n/sh-latn.json index 2bcf633..f127aa5 100644 --- a/i18n/sh.json +++ b/i18n/sh-latn.json @@ -1,7 +1,7 @@ { "@metadata": { "authors": [ - "Vlad5250" + "Winston Sung" ] }, "embedvideo-type-audio": "zvuk", diff --git a/i18n/sl.json b/i18n/sl.json index 0ae81d8..b843827 100644 --- a/i18n/sl.json +++ b/i18n/sl.json @@ -15,10 +15,13 @@ "embedvideo-consent-privacy-notice-dismiss": "Opusti", "embedvideo-service-archiveorg": "Archive.org", "embedvideo-service-bilibili": "Bilibili", + "embedvideo-service-dailymotion": "Dailymotion", "embedvideo-service-kakaotv": "KakaoTV", + "embedvideo-service-loom": "Loom", "embedvideo-service-navertv": "NaverTV", "embedvideo-service-niconico": "Niconico", "embedvideo-service-soundcloud": "SoundCloud", + "embedvideo-service-sharepoint": "SharePoint", "embedvideo-service-spotify": "Spotify", "embedvideo-service-twitch": "Twitch", "embedvideo-service-vimeo": "Vimeo", diff --git a/i18n/zh-hant.json b/i18n/zh-hant.json index 40fabf3..07f6ec3 100644 --- a/i18n/zh-hant.json +++ b/i18n/zh-hant.json @@ -18,10 +18,13 @@ "embedvideo-consent-privacy-notice-dismiss": "關閉", "embedvideo-service-archiveorg": "Archive.org", "embedvideo-service-bilibili": "嗶哩嗶哩", + "embedvideo-service-dailymotion": "Dailymotion", "embedvideo-service-kakaotv": "KakaoTV", + "embedvideo-service-loom": "Loom", "embedvideo-service-navertv": "NaverTV", "embedvideo-service-niconico": "Niconico", "embedvideo-service-soundcloud": "SoundCloud", + "embedvideo-service-sharepoint": "SharePoint", "embedvideo-service-spotify": "Spotify", "embedvideo-service-twitch": "Twitch", "embedvideo-service-vimeo": "Vimeo", diff --git a/includes/EmbedService/DailyMotion.php b/includes/EmbedService/DailyMotion.php new file mode 100644 index 0000000..e7b7792 --- /dev/null +++ b/includes/EmbedService/DailyMotion.php @@ -0,0 +1,76 @@ + 'no', + ]; + + /** + * @inheritDoc + */ + public function getBaseUrl(): string { + return ''; + } + + /** + * @inheritDoc + */ + public function getAspectRatio(): ?float { + return 16 / 9; + } + + /** + * @inheritDoc + */ + public function getDefaultWidth(): int { + return 640; + } + + /** + * @inheritDoc + */ + public function getDefaultHeight(): int { + return 360; + } + + /** + * @inheritDoc + */ + protected function getUrlRegex(): array { + return [ + '#^(https://[\w-]+.sharepoint.com/sites/.+\.\w+)$#is', + ]; + } + + /** + * @inheritDoc + */ + protected function getIdRegex(): array { + return []; + } + + /** + * @inheritDoc + */ + public function getContentType(): ?string { + return 'video'; + } + + /** + * @inheritDoc + */ + public function getPrivacyPolicyUrl(): ?string { + return 'https://privacy.microsoft.com/en-us/privacystatement'; + } + + /** + * @inheritDoc + */ + public function getCSPUrls(): array { + return [ + 'https://*.sharepoint.com' + ]; + } + + /** + * @inheritDoc + */ + public function getUrl(): string { + return $this->id; + } +} diff --git a/includes/Media/AudioHandler.php b/includes/Media/AudioHandler.php index 646dd75..cc16d92 100644 --- a/includes/Media/AudioHandler.php +++ b/includes/Media/AudioHandler.php @@ -14,20 +14,19 @@ use stdClass; class AudioHandler extends MediaHandler { - /** - * Temporary map - * Saving cache results - * - * @var array - */ - protected static $ffprobeCache = []; - protected $contentLanguage; public function __construct() { $this->contentLanguage = MediaWikiServices::getInstance()->getContentLanguage(); } + /** + * @inheritDoc + */ + protected function useLegacyMetadata() { + return false; + } + /** * Get an associative array mapping magic word IDs to parameter names. * Will be used by the parser to identify parameters. @@ -153,25 +152,6 @@ public function normaliseParams( $image, &$params ): bool { return true; } - /** - * Get an image size array like that returned by getimagesize(), or false if it - * can't be determined. - * - * This function is used for determining the width, height and bitdepth directly - * from an image. The results are stored in the database in the img_width, - * img_height, img_bits fields. - * - * @note If this is a multipage file, return the width and height of the - * first page. - * - * @param File $file The file object, or false if there isn't one - * @param string $path The filename - * @return array|false An array following the format of PHP getimagesize() function or false if not supported. - */ - public function getImageSize( $file, $path ) { - return false; - } - /** * Get a MediaTransformOutput object representing the transformed output. Does the * transform unless $flags contains self::TRANSFORM_LATER. @@ -266,59 +246,61 @@ public function getLongDesc( $file ): string { /** * @inheritDoc */ - public function getMetadata( $image, $path ): string { + public function getSizeAndMetadata( $state, $path ) { [ 'stream' => $stream, 'format' => $format, - ] = $this->getFFProbeResult( $image ); + ] = $this->getFFProbeResult( $path ); - $streamData = []; - $formatData = []; + $data = [ + 'metadata' => [], + ]; - if ( $stream !== false ) { - $streamData = [ + if ( $stream !== false && $stream !== null ) { + $data['metadata'] = [ 'duration' => $stream->getDuration(), 'codec' => $stream->getCodecName(), 'bitdepth' => $stream->getBitDepth(), ]; + + if ( !empty( $stream->getWidth() ) ) { + $data['width'] = $stream->getWidth(); + $data['height'] = $stream->getHeight(); + } } - if ( $format !== false ) { - $formatData = [ - 'bitrate' => $format->getBitRate(), - ]; + if ( $format !== false && $format !== null ) { + $data['bits'] = $format->getBitRate(); } - return serialize( array_merge( $streamData, $formatData ) ); + return $data; } /** * Runs FFProbe and caches results in the Main WAN Object cache * - * @param FSFile|File $file The file to work on + * @param string|FSFile|File $file The file to work on * @param string $select Video / Audio track to select * @return array */ protected function getFFProbeResult( $file, string $select = 'v:0' ): array { - if ( $file instanceof FSFile ) { - $cacheKey = $file->getSha1Base36(); - } else { - $cacheKey = $file->getSha1(); + $path = $file; + + if ( $file instanceof File ) { + $path = $file->getLocalRefPath(); + } elseif ( $file instanceof FSFile ) { + $path = $file->getPath(); } - if ( isset( self::$ffprobeCache[$cacheKey] ) ) { - return self::$ffprobeCache[$cacheKey]; + if ( $file === false ) { + return []; } - $probe = new FFProbe( $file ); + $probe = new FFProbe( $path, $file ); - $result = [ + return [ 'stream' => $probe->getStream( $select ), 'format' => $probe->getFormat() ]; - - self::$ffprobeCache[$cacheKey] = $result; - - return $result; } } diff --git a/includes/Media/FFProbe/FFProbe.php b/includes/Media/FFProbe/FFProbe.php index e94631f..6789931 100644 --- a/includes/Media/FFProbe/FFProbe.php +++ b/includes/Media/FFProbe/FFProbe.php @@ -11,6 +11,7 @@ use JsonException; use MediaWiki\MediaWikiServices; use MediaWiki\ProcOpenError; +use MediaWiki\Settings\SettingsBuilder; use MediaWiki\Shell\Shell; use MediaWiki\ShellDisabledError; use Wikimedia\LightweightObjectStore\ExpirationAwareness; @@ -19,7 +20,12 @@ class FFProbe { /** * MediaWiki File * - * @var File|FSFile + * @var string + */ + private $filename; + + /** + * @var FSFile|File|string */ private $file; @@ -33,10 +39,12 @@ class FFProbe { /** * Main Constructor * - * @param File|FSFile $file MediaWiki File + * @param string $filename MediaWiki File name + * @param FSFile|File|string $file * @return void */ - public function __construct( $file ) { + public function __construct( $filename, $file ) { + $this->filename = $filename; $this->file = $file; } @@ -44,51 +52,50 @@ public function __construct( $file ) { * Return the entire cache of metadata. * * @param string $select The selected audio/video stream - * @return array Meta Data + * @return bool Flag if loading did succeed */ - public function getMetaData( string $select = 'v:0' ): array { - if ( $this->file instanceof FSFile ) { - $cacheKey = $this->file->getSha1Base36(); - } else { - $cacheKey = $this->file->getSha1(); + public function loadMetaData( string $select = 'v:0' ): bool { + // If this is in a maintenance call context, don't use the cache + if ( isset( $GLOBALS['wgSettings'] ) && $GLOBALS['wgSettings'] instanceof SettingsBuilder ) { + $isMaintenance = $GLOBALS['wgSettings']->getConfig()->get( 'CommandLineMode' ); + if ( $isMaintenance ) { + $metadata = $this->invokeFFProbe(); + $this->metadata = $metadata; + + return is_array( $metadata ); + } } $cache = MediaWikiServices::getInstance()->getMainWANObjectCache(); - $cacheKey = $cache->makeGlobalKey( 'EmbedVideo', 'ffprobe', $cacheKey, $select ); + $cacheKey = $cache->makeGlobalKey( 'EmbedVideo', 'ffprobe', $this->filename, $select ); + $ttl = ( $this->file instanceof File || is_string( $this->file ) ) + ? ExpirationAwareness::TTL_INDEFINITE : ExpirationAwareness::TTL_MINUTE; $result = $cache->getWithSetCallback( $cacheKey, - // FSFiles are usually only present for uploads(?), only "real" files are relevant - $this->file instanceof File ? ExpirationAwareness::TTL_INDEFINITE : ExpirationAwareness::TTL_MINUTE, + $ttl, function ( $old, &$ttl ) { - if ( $this->file instanceof FSFile ) { - $title = 'Newly uploaded file'; - } else { - $title = $this->file->getTitle(); - $title = $title !== null ? $title->getBaseText() : 'Untitled file'; - } - - wfDebugLog( - 'EmbedVideo', - sprintf( 'Writing FFProbe Cache for %s', $title ) - ); - $result = $this->invokeFFProbe(); - if ( $result === false ) { + if ( $result === null ) { $ttl = ExpirationAwareness::TTL_UNCACHEABLE; return $old; } - return $this->metadata; + return $result; } ); if ( is_array( $result ) ) { - return $result; + $this->metadata = [ + 'streams' => $result['streams'], + 'format' => $result['format'], + ]; + + return true; } - return []; + return false; } /** @@ -105,7 +112,7 @@ function ( $old, &$ttl ) { * @return false|StreamInfo StreamInfo object or false if does not exist. */ public function getStream( string $select ) { - $this->getMetaData( $select ); + $this->loadMetaData( $select ); $types = [ 'v' => 'video', @@ -145,7 +152,7 @@ public function getStream( string $select ) { * @return false|FormatInfo FormatInfo object or false if does not exist. */ public function getFormat() { - $this->getMetaData(); + $this->loadMetaData(); if ( !isset( $this->metadata['format'] ) ) { return false; @@ -158,31 +165,26 @@ public function getFormat() { * @return bool|string */ private function getFilePath() { - if ( $this->file instanceof FSFile ) { - return $this->file->getPath(); - } - - return $this->file->getLocalRefPath(); + return $this->filename; } /** * Invoke ffprobe on the command line. * - * @return bool Success + * @return array|null Success */ - private function invokeFFProbe(): bool { + private function invokeFFProbe(): ?array { try { $ffprobeLocation = MediaWikiServices::getInstance() ->getConfigFactory() ->makeConfig( 'EmbedVideo' ) ->get( 'FFProbeLocation' ); } catch ( ConfigException $e ) { - return false; + return null; } if ( Shell::isDisabled() || $ffprobeLocation === false || !file_exists( $ffprobeLocation ) ) { - $this->metadata = []; - return false; + return null; } $command = Shell::command( $ffprobeLocation ); @@ -201,17 +203,13 @@ private function invokeFFProbe(): bool { $json = json_decode( $result->getStdout(), true, 512, JSON_THROW_ON_ERROR ); } catch ( Exception | JsonException | ShellDisabledError | ProcOpenError $e ) { wfLogWarning( $e->getMessage() ); - $this->metadata = []; - return false; + return null; } if ( is_array( $json ) ) { - $this->metadata = $json; - } else { - $this->metadata = []; - return false; + return $json; } - return true; + return null; } } diff --git a/includes/Media/VideoHandler.php b/includes/Media/VideoHandler.php index 15f1cb8..7b7c6fc 100644 --- a/includes/Media/VideoHandler.php +++ b/includes/Media/VideoHandler.php @@ -12,6 +12,7 @@ use MediaWiki\MediaWikiServices; use RequestContext; use Title; +use TrivialMediaHandlerState; class VideoHandler extends AudioHandler { /** @@ -58,7 +59,7 @@ public function validateParam( $name, $value ): bool { * Returns false if the parameters are unacceptable and the transform should fail * * @param File $image File - * @param array $params Parameters + * @param array &$params Parameters * @return bool Success */ public function normaliseParams( $image, &$params ): bool { @@ -96,12 +97,15 @@ public function normaliseParams( $image, &$params ): bool { } // Note: MediaHandler declares getImageSize with a local path, but we don't need it here. - [ $width, $height ] = $this->getImageSize( $image, '' ); + [ 'width' => $width, 'height' => $height ] = $this->getSizeAndMetadata( + new TrivialMediaHandlerState(), + $image->getLocalRefPath() + ); if ( $width === 0 && $height === 0 ) { // Force a reset. $width = $config->get( 'EmbedVideoDefaultWidth' ); - $height = (int)( $width * ( 16 / 9 ) ); + $height = (int)( $width / ( 16 / 9 ) ); } if ( isset( $params['width'] ) && @@ -138,27 +142,6 @@ public function normaliseParams( $image, &$params ): bool { return true; } - /** - * @inheritDoc - */ - public function getImageSize( $file, $path ): array { - [ - 'stream' => $stream, - ] = $this->getFFProbeResult( $file ); - - if ( $stream !== false ) { - return [ - $stream->getWidth(), - $stream->getHeight(), - 0, - sprintf( 'width="%s" height="%s"', $stream->getWidth(), $stream->getHeight() ), - 'bits' => $stream->getBitDepth() - ]; - } - - return [ 0, 0, 0, 'width="0" height="0"', 'bits' => 0 ]; - } - /** * Get a MediaTransformOutput object representing the transformed output. Does the * transform unless $flags contains self::TRANSFORM_LATER. diff --git a/resources/fetchers/fetchFactory.js b/resources/fetchers/fetchFactory.js index cc876bc..3c78f6b 100644 --- a/resources/fetchers/fetchFactory.js +++ b/resources/fetchers/fetchFactory.js @@ -11,6 +11,9 @@ const fetchFactory = function (service) { case 'bilibili': //fetcher = require('./bilibili.js').fetcher; break; + case 'loom': + fetcher = oEmbedFetchers.loom; + break; // Niconico is missing CORS headers case 'niconico': //fetcher = require('./niconico.js').fetcher; diff --git a/resources/fetchers/oembed.js b/resources/fetchers/oembed.js index d816e3f..39a0494 100644 --- a/resources/fetchers/oembed.js +++ b/resources/fetchers/oembed.js @@ -33,6 +33,10 @@ const kakaotv = function(url) { return oembed('https://tv.kakao.com/oembed?url=' + url); }; +const loom = function(url) { + return oembed('https://www.loom.com/v1/oembed?url=https://www.loom.com/share/' + url); +}; + const oembed = function(url) { return fetch(url, { credentials: "omit", @@ -60,6 +64,7 @@ const oembed = function(url) { module.exports = { navertv, kakaotv, + loom, youtube, vimeo, spotifyalbum,