try {
common_log(LOG_INFO, 'Trying to discover an oEmbed endpoint using link headers.');
$api = oEmbedHelper::oEmbedEndpointFromHTML($dom);
- common_log(LOG_INFO, 'Found API endpoint ' . $api . ' for URL ' . $url);
+ common_log(LOG_INFO, 'Found oEmbed API endpoint ' . $api . ' for URL ' . $url);
$params = array(
'maxwidth' => common_config('thumbnail', 'width'),
'maxheight' => common_config('thumbnail', 'height'),
);
$metadata = oEmbedHelper::getOembedFrom($api, $url, $params);
-
} catch (Exception $e) {
- common_log(LOG_INFO, 'Could not find an oEmbed endpoint using link headers.');
+ common_log(LOG_INFO, 'Could not find an oEmbed endpoint using link headers, trying OpenGraph from HTML.');
// Just ignore it!
+ $metadata = OpenGraphHelper::ogFromHtml($dom);
}
}
--- /dev/null
+<?php
+
+if (!defined('GNUSOCIAL')) { exit(1); }
+
+
+/**
+ * Utility class to get OpenGraph data from HTML DOMs etc.
+ */
+class OpenGraphHelper
+{
+ const KEY_REGEX = '/^og\:(\w+)(?:\:(\w+))?/';
+ protected static $property_map = [
+ 'site_name' => 'provider_name',
+ 'title' => 'title',
+ 'description' => 'html',
+ 'type' => 'type',
+ 'url' => 'url',
+ 'image' => 'thumbnail_url',
+ ];
+
+ // This regex map has: /pattern(match)/ => matchindex | string
+ protected static $type_regex_map = [
+ '/^(video)/' => 1,
+ '/^image/' => 'photo',
+ ];
+
+ static function ogFromHtml(DOMDocument $dom) {
+ $obj = new stdClass();
+ $nodes = $dom->getElementsByTagName('meta');
+ for ($i = 0; $i < $nodes->length; $i++) {
+ $node = $nodes->item($i);
+ if (!$node->hasAttributes()) {
+ continue;
+ }
+ $property = $node->attributes->getNamedItem('property');
+ $matches = array();
+ if (!preg_match(self::KEY_REGEX, $property->value, $matches)) {
+ // not property="og:something"
+ continue;
+ }
+ if (!isset(self::$property_map[$matches[1]])) {
+ // unknown metadata property, nothing we would care about anyway
+ continue;
+ }
+
+ $prop = self::$property_map[$matches[1]];
+ $obj->{$prop} = $node->attributes->getNamedItem('content')->value;
+ // I don't care right now if they're empty
+ }
+ if (isset($obj->type)) {
+ // Loop through each known OpenGraph type where we have a match in oEmbed
+ foreach (self::$type_regex_map as $pattern=>$replacement) {
+ $matches = array();
+ if (preg_match($pattern, $obj->type, $matches)) {
+ $obj->type = is_int($replacement)
+ ? $matches[$replacement]
+ : $replacement;
+ break;
+ }
+ }
+ // If it's not known to our type map, we just pass it through in hopes of it getting handled anyway
+ } elseif (isset($obj->url)) {
+ // If no type is set but we have a URL, let's set type=link
+ $obj->type = 'link';
+ }
+ return $obj;
+ }
+}