Skip to content

Commit

Permalink
Merge pull request #62 from hyvor/giphy-tenor
Browse files Browse the repository at this point in the history
tenor and giphy with oembed
  • Loading branch information
supun-io authored Nov 14, 2024
2 parents 3b62d30 + 8df86e8 commit e462d19
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 1 deletion.
13 changes: 12 additions & 1 deletion src/Embed/EmbedParserAbstract.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ private function parseOEmbed(): string
$content = $response->getBody()->getContents();

if ($status !== 200) {
$content = substr($content, 0, 1000);
throw new EmbedParserException(
"Failed to fetch oEmbed data from the endpoint. Status: $status. Response: $content"
);
Expand All @@ -131,7 +132,7 @@ private function parseOEmbed(): string
throw new EmbedParserException("Failed to parse JSON response from oEmbed endpoint");
}

$html = $parsed['html'] ?? null;
$html = $this->htmlFromOEmbedArray($parsed);

if (!is_string($html) || empty($html)) {
throw new EmbedParserException("Failed to get HTML from oEmbed endpoint");
Expand All @@ -149,4 +150,14 @@ private function parseCustom(array $matches): string
return $this->getEmbedHtml($matches);
}

/**
* @param array<string, mixed> $data
*/
protected function htmlFromOEmbedArray(array $data): ?string
{
/** @var ?string $html */
$html = $data['html'] ?? null;
return $html;
}

}
77 changes: 77 additions & 0 deletions src/Embed/Platforms/Giphy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php

namespace Hyvor\Unfold\Embed\Platforms;

use Hyvor\Unfold\Embed\EmbedParserAbstract;
use Hyvor\Unfold\Embed\EmbedParserOEmbedInterface;

class Giphy extends EmbedParserAbstract implements EmbedParserOEmbedInterface
{
public function regex()
{
return [
/**
* /gifs/ oembed returns a photo response
* We return a simple <img> tag
*/
"https://giphy.com/gifs/.*",

/**
* 2024-11-14: Clips oEmbed returns an iframe
* but the iframe doesn't work due to X-Frame-Options: DENY
*/
// "https://giphy.com/clips/.*",

// 2024-11-14: gph.is links don't work with oembed
// "http://gph.is/.*",

"https://media\d?.giphy.com/media/.*/giphy.(gif|webp)",
];
}

public function oEmbedUrl(): string
{
return 'https://giphy.com/services/oembed';
}

protected function htmlFromOEmbedArray(array $data): ?string
{
$type = $data['type'] ?? null;

/**
* giphy.com/gifs/* return a photo oembed
* so, we simply generate an <img> tag
*/
if ($type === 'photo') {
/** @var ?string $url */
$url = $data['url'] ?? null;

if (!$url) {
return null;
}

/** @var ?string $title */
$title = $data['title'] ?? '';

$width = $data['width'] ?? null;
// $height = $data['height'] ?? null;

$attrs = [
'src' => $url,
'alt' => strval($title),
'width' => is_int($width) ? min($width, 600) : null,
//'height' => is_int($height) ? min($height, 600) : null,
'style' => 'max-width: 100%;'
];
$attrs = array_filter($attrs);
$attrs = array_map(fn($key, $value) => "$key=\"$value\"", array_keys($attrs), $attrs);

return "<img " . implode(' ', $attrs) . ">";
}

/** @var ?string $html */
$html = $data['html'] ?? null;

return $html;
}
}
21 changes: 21 additions & 0 deletions src/Embed/Platforms/Tenor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace Hyvor\Unfold\Embed\Platforms;

use Hyvor\Unfold\Embed\EmbedParserAbstract;
use Hyvor\Unfold\Embed\EmbedParserOEmbedInterface;

class Tenor extends EmbedParserAbstract implements EmbedParserOEmbedInterface
{
public function regex()
{
return [
'https://tenor.com/view/(.*)',
];
}

public function oEmbedUrl(): string
{
return 'https://tenor.com/oembed';
}
}
50 changes: 50 additions & 0 deletions tests/Unit/Embed/Platforms/GiphyTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace Unit\Parsers;

use GuzzleHttp\Client;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use GuzzleHttp\Psr7\Response;
use Hyvor\Unfold\Embed\Platforms\Giphy;
use Hyvor\Unfold\UnfoldConfig;

it('matches tenor URLs', function (string $url) {
$parser = new Giphy(UnfoldConfig::withUrl($url));
$match = $parser->match();
expect($match)->toBeArray();
})->with([
'https://giphy.com/gifs/studiosoriginals-kindness-world-day-IwADz4opoIZthLv6Mz',
'https://media3.giphy.com/media/v1.Y2lkPTc5MGI3NjExaGZhOGZwaTNmaHdtaGdrYjh0b3NtM2hsaXg5M2VsM250bWN4ZzZyciZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/IwADz4opoIZthLv6Mz/giphy.webp',
]);


it('fetches giphy', function () {
$history = [];
$historyMiddleware = Middleware::history($history);

$mock = new MockHandler([
new Response(200, [], json_encode([
'html' => '<giphy></giphy>',
]))
]);

$handlerStack = new HandlerStack($mock);
$handlerStack->push($historyMiddleware);

$client = new Client(['handler' => $handlerStack]);

$url = 'https://giphy.com/gifs/studiosoriginals-kindness-world-day-IwADz4opoIZthLv6Mz';
$config = new UnfoldConfig(httpClient: $client);
$config->start($url);
$parser = new Giphy($config);
$response = $parser->parse();
expect($response)->toBe('<giphy></giphy>');

$request = $history[0]['request'];

expect((string)$request->getUri())->toBe(
'https://giphy.com/services/oembed?url=' . $url . '&format=json'
);
});
48 changes: 48 additions & 0 deletions tests/Unit/Embed/Platforms/TenorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

namespace Unit\Parsers;

use GuzzleHttp\Client;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use GuzzleHttp\Psr7\Response;
use Hyvor\Unfold\Embed\Platforms\Tenor;
use Hyvor\Unfold\UnfoldConfig;

it('matches tenor URLs', function (string $url) {
$parser = new Tenor(UnfoldConfig::withUrl($url));
$match = $parser->match();
expect($match)->toBeArray();
})->with([
'https://tenor.com/view/shannon-sharpe-shannon-sharpe-drinking-fox-undisputed-skip-bayless-gif-23482018',
'https://tenor.com/view/steph-curry-stephen-curry-chef-curry-curry-warriors-gif-2893813801205262964'
]);

it('fetches tenor', function () {
$history = [];
$historyMiddleware = Middleware::history($history);

$mock = new MockHandler([
new Response(200, [], json_encode([
'html' => '<tenor></tenor>',
]))
]);

$handlerStack = new HandlerStack($mock);
$handlerStack->push($historyMiddleware);
$client = new Client(['handler' => $handlerStack]);

$url = 'https://tenor.com/view/shannon-sharpe-shannon-sharpe-drinking-fox-undisputed-skip-bayless-gif-23482018';
$config = new UnfoldConfig(httpClient: $client);
$config->start($url);
$parser = new Tenor($config);
$response = $parser->parse();
expect($response)->toBe('<tenor></tenor>');

$request = $history[0]['request'];

expect((string)$request->getUri())->toBe(
'https://tenor.com/oembed?url=' . $url . '&format=json'
);
});
8 changes: 8 additions & 0 deletions website/src/routes/[[slug]]/Introduction.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@
<strong>Bluesky</strong>
<OEmbedTag />: Posts
</li>
<li>
<strong>Tenor</strong>
<OEmbedTag />: GIFs
</li>
<li>
<strong>Giphy</strong>
<OEmbedTag />: GIFs
</li>
</ul>

<Callout type="info">
Expand Down

0 comments on commit e462d19

Please sign in to comment.