sbrl / Pepperminty-Wiki

A wiki in a box
https://peppermint.mooncarrot.space/
Mozilla Public License 2.0
177 stars 20 forks source link

Feature Request: More universal embeds #250

Open Steve0Greatness opened 5 months ago

Steve0Greatness commented 5 months ago

There are many possible video hosts(not all of which are as popular as YouTube or Vimeo). Such sites rely the Open Graph protocol for external embeds.

Open Graph is how platforms like Mastodon know how to title and describe a page, or in this case, know how to embed it. Open Graph works with specific meta tags on the page, these meta tags use the [property] attribute to describe their purpose, and the [content] attribute for what that value is set to. As an example: <meta property="og:description" content="Lorem Ipsum" />.

In order to describe video embeds, sites use og:video:* properties. Specifically, sites like YouTube and Vimeo, and platforms like Peertube, include both og:video:url and og:video:secure_url, meanwhile sites like Twitch only have og:video:secure_url, as such: default to using og:video:secure_url, but fall back on og:video:url. Some sites include a og:video:type, it's almost always set to text/html, however keep in mind that it could also be set a video/* type, meaning it shouldn't be embed in an iFrame. There are exceptions to this norm, media.ccc.de, which uses og:video to link directly to it's video origin.

I'm not entirely sure if you're already doing this, but going off of the latest release as of writing, you only have support for Vimeo and YouTube. Sorry if I wasted your time.

sbrl commented 5 months ago

Heya, thanks for the suggestion!

I did not know that Open Graph could be used to identify videos. I've become a big fan of the Fediverse. I didn't realise the fediverse was a thing when I implemented this, so in hindsight this sounds like an important missed feature here.

This would necessitate making a HTTP/S request to the remote server to grab the HTML page though (which we don't currently do), so we would need to implement a cache here. Thankfully, we have $paths->cache_directory as a dedicated directory in which to cache content, so we could download it once and cache it there for a period of time to avoid a HTTP/S request every time we parse the content for every page view.

The parser is in this file: https://github.com/sbrl/Pepperminty-Wiki/blob/master/modules/parser-parsedown.php#L1351

...it's a bit long due to all the extra features I've added over the years and a limitation of the build system (I need to rewrite it again I think to allow for multi-file modules).

Would you like to have a go at implementing this at all? I'd be happy to accept a contribution via a pull request!

Steve0Greatness commented 5 months ago

Thanks for the offer. I'm not terribly great at PHP, but I'll see what I can do.

sbrl commented 5 months ago

Cool! Let me know if you need an assistance.

This project is a long-time passion of mine, so don't feel you're wasting my time at all :-)

Steve0Greatness commented 5 months ago

I've found that I probably won't be able to contribute to this project. I'm (currently) running Windows 11, so I don't believe I can debug(feel free correct me if I'm wrong on this), in addition, Composer is really finicky, and refuses to work(at least importing libraries into the code doesn't work).

Besides that, I did find a library that can already query and get the OpenGraph metadata, it's called Embed. I've written a function that allows the HTML code output of Embed to the array you're using for generating the embed. I'd also recommend caching either the HTML outputted library, or the output of the function below.

function __convert_embed_output(string $output, string $alt_text) {
    $src = array();
    $element = array();
    preg_match('/(?<=src=")[^"]*(?=")/', $output, $src);
    preg_match("/(?<=<)(iframe|video)(?= )/", $output, $element);
    return [
        "name" => $element[0],
        "attributes" => [
            "src" => $src[0],
            "frameborder" => "0",
            "allow" => "fullscreen; encrypted-media; picture-in-picture",
            "allowfullscreen" => "true",
            "allowTransparency" => "true",
        ],
        "text" => $alt_text
    ];
}

Not sure how much this will help, or if it will integrate at all, but this is just what I've figured out.

sbrl commented 5 months ago

Ah, no worries. Software stacks can be a pain sometimes haha

Thanks for the contribution though!

I'll take a look into implementing this with your suggestion as soon as I have a moment.