From 334b928c1e2f45c1fa24adf223133fc8b3b0a3f0 Mon Sep 17 00:00:00 2001
From: Starbeamrainbowlabs <sbrl@starbeamrainbowlabs.com>
Date: Mon, 7 Feb 2022 02:46:47 +0000
Subject: [PATCH] Add initial support for embedding videos from YouTube, Vimeo,
 etc

---
 Changelog.md                 |  5 +++
 modules/parser-parsedown.php | 70 +++++++++++++++++++++++++++++++++++-
 2 files changed, 74 insertions(+), 1 deletion(-)

diff --git a/Changelog.md b/Changelog.md
index d0c5096..5e27c6c 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -4,6 +4,11 @@ This file holds the changelog for Pepperminty Wiki. This is the master list of t
 
 ## v0.24-dev
 
+### Added
+ - Added support for embedding external YouTube and Vimeo videos (e.g. `![alt text](https://youtube.com/watch?v=pID0xQ2qnrQ)`)
+     - If you know of a cool service that should be supported, please open an issue - YouTube and Vimeo were just the only 2 I could think of
+     - Known issue: specifying the size (i.e. with ` | 500x400` inside the brackets `()` there) doesn't currently work because iframes are weird
+
 ### Changed
  - Display returnto URL above the login form if present to further mitigate CSRF issues
 
diff --git a/modules/parser-parsedown.php b/modules/parser-parsedown.php
index 4948776..79837de 100644
--- a/modules/parser-parsedown.php
+++ b/modules/parser-parsedown.php
@@ -1205,6 +1205,11 @@ class PeppermintParsedown extends ParsedownExtra
 			$urlType = system_extension_mime_type($urlExtension);
 			$embed_type = substr($urlType, 0, strpos($urlType, "/"));
 			if($urlType == "application/pdf") $embed_type = "pdf";
+			
+			// Check if the URL is a recognised external provider
+			$ext_provider_result = $this->__make_embed($imageUrl, $altText);
+			if($ext_provider_result !== null) $embed_type = "ext_provider";
+			
 			$result = [];
 			switch($embed_type)
 			{
@@ -1226,7 +1231,12 @@ class PeppermintParsedown extends ParsedownExtra
 						]
 					];
 					break;
-				
+				case "ext_provider":
+					$result = [
+						"extent" => strlen($matches[0]),
+						"element" => $ext_provider_result
+					];
+					break;
 				case "audio":
 					$result = [
 						"extent" => strlen($matches[0]),
@@ -1322,6 +1332,64 @@ class PeppermintParsedown extends ParsedownExtra
 		}
 	}
 	
+	/**
+	 * Makes an embed HTML tree for a given URL.
+	 * Example URLs include YouTube links, Vimeo, etc.
+	 * @param  string $url	The URL to generate an embed for.
+	 * @return array|null	The embed HTML tree, or null if generation failed (e.g. if the URL wasn't recognised).
+	 */
+	protected function __make_embed(string $url_text, string $alt_text) {
+		// 1: URL parsing
+		$url = parse_url($url_text);
+		$url["host"] = preg_replace("/^www\./", "", $url["host"] ?? "");
+		parse_str($url["query"] ?? "", $query);
+		// 2: Pre-generation transforms
+		switch($url["host"]) {
+			case "player.vimeo.com":
+				$url["host"] = "vimeo.com";
+				$url["path"] = preg_replace("/^\/video/", "", $url["path"]);
+				break;
+			case "youtu.be":
+				$query["v"] = preg_replace("/^\//", "", $url["path"]);
+				$url["host"] = "youtube.com";
+				$url["path"] = "/watch";
+				break;
+		}
+		// 3: Actual embed generation
+		switch ($url["host"]) {
+			case "youtube.com":
+				if($url["path"] !== "/watch" || empty($query["v"]))
+					return null;
+				
+				return [
+					"name" => "iframe",
+					"attributes" => [
+						"src" => "https://www.youtube.com/embed/{$query["v"]}",
+						"frameborder" => "0",
+						"allow" => "fullscreen; encrypted-media; picture-in-picture"
+					],
+					"text" => "YouTube: $alt_text"
+				];
+				break;
+			
+			case "vimeo.com":
+				if(strlen($url["path"]) <= 1 || preg_match("/[^0-9\/]/", $url["path"]) === 1) return null;
+				return [
+					"name" => "iframe",
+					"attributes" => [
+						"src" => "https://player.vimeo.com/video{$url["path"]}",
+						"frameborder" => "0",
+						"allow" => "fullscreen; picture-in-picture"
+					],
+					"text" => "Vimeo: $alt_text"
+				];
+				break;
+			
+			default:
+				return null;
+		}
+	}
+	
 	
 	/*
 	 *  ██████  ██████  ██████  ███████     ██████  ██       ██████   ██████ ██   ██
