mirror of
https://gitlab.com/octospacc/Proxatore.git
synced 2025-06-05 17:19:18 +02:00
Initial GitHub+Gists support; Handle Pinterest pin.it links; First functional testing cases
This commit is contained in:
@@ -50,7 +50,7 @@ define('USER_AGENT', "Proxatore/2025/1 ({$_SERVER['SERVER_NAME']})");
|
|||||||
/*************************************/
|
/*************************************/
|
||||||
|
|
||||||
//define('SCRIPT_NAME', $_SERVER['SCRIPT_NAME'] /* '/' */);
|
//define('SCRIPT_NAME', $_SERVER['SCRIPT_NAME'] /* '/' */);
|
||||||
define('SCRIPT_NAME', ($_SERVER['SCRIPT_NAME'] === '/' ? $_SERVER['SCRIPT_NAME'] : "{$_SERVER['SCRIPT_NAME']}/"));
|
define('SCRIPT_NAME', ($_SERVER['SCRIPT_NAME'] === '/' ? '/' : "{$_SERVER['SCRIPT_NAME']}/"));
|
||||||
define('HISTORY_FILE', './Proxatore.history.jsonl');
|
define('HISTORY_FILE', './Proxatore.history.jsonl');
|
||||||
|
|
||||||
// const OPTIONS_OVERRIDES = [
|
// const OPTIONS_OVERRIDES = [
|
||||||
@@ -61,6 +61,8 @@ define('HISTORY_FILE', './Proxatore.history.jsonl');
|
|||||||
|
|
||||||
const PLATFORMS = [
|
const PLATFORMS = [
|
||||||
'spaccbbs' => ['bbs.spacc.eu.org'],
|
'spaccbbs' => ['bbs.spacc.eu.org'],
|
||||||
|
'github' => ['github.com'],
|
||||||
|
'github-gist' => ['gist.github.com'],
|
||||||
'bilibili' => ['bilibili.com'],
|
'bilibili' => ['bilibili.com'],
|
||||||
'bluesky' => ['bsky.app'],
|
'bluesky' => ['bsky.app'],
|
||||||
'facebook' => ['facebook.com', 'm.facebook.com'],
|
'facebook' => ['facebook.com', 'm.facebook.com'],
|
||||||
@@ -105,11 +107,15 @@ const PLATFORMS_PROXIES = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
const PLATFORMS_REDIRECTS = [
|
const PLATFORMS_REDIRECTS = [
|
||||||
|
'pin.it' => 'pinterest',
|
||||||
'vm.tiktok.com' => 'tiktok',
|
'vm.tiktok.com' => 'tiktok',
|
||||||
'youtu.be' => 'youtube',
|
'youtu.be' => 'youtube',
|
||||||
];
|
];
|
||||||
|
|
||||||
const PLATFORMS_API = [
|
const PLATFORMS_API = [
|
||||||
|
'github-gist' => [
|
||||||
|
'tag' => 'article',
|
||||||
|
],
|
||||||
'spotify' => [
|
'spotify' => [
|
||||||
'id' => '__NEXT_DATA__',
|
'id' => '__NEXT_DATA__',
|
||||||
'data' => [
|
'data' => [
|
||||||
@@ -150,6 +156,13 @@ const EMBEDS = [
|
|||||||
'reddit' => ['embed.reddit.com'],
|
'reddit' => ['embed.reddit.com'],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const EMBEDS_COMPLEX = [
|
||||||
|
'github-gist' => [
|
||||||
|
'prefix' => 'data:text/html;charset=utf-8,<script src="',
|
||||||
|
'suffix' => '.js"></script>',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
const EMBEDS_API = [
|
const EMBEDS_API = [
|
||||||
'soundcloud' => [
|
'soundcloud' => [
|
||||||
'meta' => 'twitter:player',
|
'meta' => 'twitter:player',
|
||||||
@@ -309,6 +322,8 @@ function makeEmbedUrl(string $platform, string $relativeUrl, array $meta=null):
|
|||||||
$url = EMBEDS_PREFIXES_FULL[$platform] . urlencode($relativeUrl);
|
$url = EMBEDS_PREFIXES_FULL[$platform] . urlencode($relativeUrl);
|
||||||
} else if ($api = (EMBEDS_API[$platform] ?? null)) {
|
} else if ($api = (EMBEDS_API[$platform] ?? null)) {
|
||||||
return $meta[$api['meta']];
|
return $meta[$api['meta']];
|
||||||
|
//} else if ($api = EMBEDS_COMPLEX[$platform] ?? null) {
|
||||||
|
//return $api['prefix'] . $relativeUrl . $api['suffix'];
|
||||||
} else {
|
} else {
|
||||||
$url = (EMBEDS[$platform][0] ?? PLATFORMS[$platform][0] ?? PLATFORMS_PROXIES[$platform][0] ?? $platform) . '/' . trim($relativeUrl, '/') . (EMBEDS_SUFFIXES[$platform] ?? '');
|
$url = (EMBEDS[$platform][0] ?? PLATFORMS[$platform][0] ?? PLATFORMS_PROXIES[$platform][0] ?? $platform) . '/' . trim($relativeUrl, '/') . (EMBEDS_SUFFIXES[$platform] ?? '');
|
||||||
}
|
}
|
||||||
@@ -566,11 +581,16 @@ function fetchPageMedia(array &$item): void {
|
|||||||
$relativeUrl = $item['result']['relativeurl'];
|
$relativeUrl = $item['result']['relativeurl'];
|
||||||
if ($api = platformMapGet($platform, PLATFORMS_API)) {
|
if ($api = platformMapGet($platform, PLATFORMS_API)) {
|
||||||
$json = null;
|
$json = null;
|
||||||
if (isset($api['url'])) {
|
if ($apiUrl = $api['url'] ?? null) {
|
||||||
$json = fetchContent($api['url'] . urlLast($relativeUrl))['body'];
|
$json = fetchContent($apiUrl . urlLast($relativeUrl))['body'];
|
||||||
} else if (isset($api['id'])) {
|
} else {
|
||||||
$doc = htmldom(fetchContent(makeEmbedUrl($platform, $relativeUrl, $item['meta']))['body']);
|
$doc = htmldom(fetchContent(makeEmbedUrl($platform, $relativeUrl, $item['meta']))['body']);
|
||||||
$json = $doc->getElementById($api['id'])->textContent;
|
if ($id = $api['id'] ?? null) {
|
||||||
|
$json = $doc->getElementById($id)->textContent;
|
||||||
|
} else if ($tag = $api['tag'] ?? null) {
|
||||||
|
$item['result']['description'] = $doc->getElementsByTagName($tag)[0]->textContent;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$data = json_decode($json, true);
|
$data = json_decode($json, true);
|
||||||
$values = [];
|
$values = [];
|
||||||
@@ -1071,23 +1091,6 @@ ul.platforms a {
|
|||||||
and to view them with a clean and streamlined interface, that works well on both modern systems and old browsers or slow connections.
|
and to view them with a clean and streamlined interface, that works well on both modern systems and old browsers or slow connections.
|
||||||
<br />Additionally, it allows you to share links between social media platforms, ensuring link previews, which are often blocked by competitors, always display correctly.
|
<br />Additionally, it allows you to share links between social media platforms, ensuring link previews, which are often blocked by competitors, always display correctly.
|
||||||
</p>
|
</p>
|
||||||
<h3>How to self-host?</h3><p>
|
|
||||||
This software is free and open-source, and you can host it on your own server, for either private or public use.
|
|
||||||
</p>
|
|
||||||
<h4>Base requirements</h4><dl>
|
|
||||||
<dt>A web server with PHP</dt>
|
|
||||||
<dd>(Currently only tested on nginx with PHP 8.2 and IIS with PHP 8.3, as of May 2025.)</dd>
|
|
||||||
<dt><code>curl</code> and <code>mbstring</code> PHP extensions</dt>
|
|
||||||
<dd>The program requires these PHP extensions to be installed and enabled on the server to work.</dd>
|
|
||||||
</dl>
|
|
||||||
<h4>Optional requirements</h4><dl>
|
|
||||||
<dt>A dedicated domain name</dt>
|
|
||||||
<dd>To host the program properly, instead of in a subpath.</dd>
|
|
||||||
<dt><a href="https://github.com/yt-dlp/yt-dlp" target="_blank">yt-dlp</a> on your server</dt>
|
|
||||||
<dd>To stream videos from various platforms in MP4 format.</dd>
|
|
||||||
<dt>A <a href="https://github.com/imputnet/cobalt">cobalt</a> API server</dt>
|
|
||||||
<dd>To have a fallback for access to media files for the most popular platforms.</dd>
|
|
||||||
</dl>
|
|
||||||
</details>';
|
</details>';
|
||||||
echo '<p>
|
echo '<p>
|
||||||
Made with 🕸️ and 🧨 by <a href="https://hub.octt.eu.org">OctoSpacc</a>.
|
Made with 🕸️ and 🧨 by <a href="https://hub.octt.eu.org">OctoSpacc</a>.
|
||||||
|
107
Tests.php
Normal file
107
Tests.php
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
const PROXATORE_URL = 'https://proxatore.octt.eu.org/'; // getenv('PROXY_BASE_URL') ?: 'http://localhost';
|
||||||
|
|
||||||
|
const SEARCH_HEADING = '<h3>Search results:</h3>';
|
||||||
|
|
||||||
|
$tests = [
|
||||||
|
[
|
||||||
|
'name' => 'Search with "test" query',
|
||||||
|
'path' => '?proxatore-search=test',
|
||||||
|
'expectedContains' => [SEARCH_HEADING],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'Search with inexistent term',
|
||||||
|
'path' => '?proxatore-search=ThisStringSaying'.uniqid('', true).'DoesNeverExist',
|
||||||
|
'expectedContains' => [SEARCH_HEADING, '<p>Nothing was found.</p>'],
|
||||||
|
],
|
||||||
|
// [
|
||||||
|
// 'name' => 'Invalid platform',
|
||||||
|
// 'path' => 'unknown/path',
|
||||||
|
// 'expectedContains' => ['No immediate results or search query provided.'],
|
||||||
|
// ],
|
||||||
|
];
|
||||||
|
|
||||||
|
$linkTests = [
|
||||||
|
[
|
||||||
|
'name' => 'YouTube 1',
|
||||||
|
'title' => 'Rick Astley - Never Gonna Give You Up (Official Music Video)',
|
||||||
|
'path' => 'youtube.com/watch?v=dQw4w9WgXcQ',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'YouTube 2',
|
||||||
|
'title' => 'Me at the zoo',
|
||||||
|
'path' => 'youtube.com/watch?v=jNQXAC9IVRw',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'Pinterest 1',
|
||||||
|
'path' => 'pinterest.com/pin/305118943524103084',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'Telegram Image 1',
|
||||||
|
'title' => 'Pavel Durov',
|
||||||
|
'path' => 'telegram.me/durov/6',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'Telegram Image+Text 1',
|
||||||
|
'path' => 'telegram.me/SpaccInc/7',
|
||||||
|
'expectedContains' => ['Simple spacc from yesterday, my USB wall charger is definitely close to breaking completely.'],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($linkTests as $test) {
|
||||||
|
$path = explode('/', ltrim($test['path'], '/'));
|
||||||
|
$platform = implode('.', array_slice(explode('.', reset($path)), 0, -1));
|
||||||
|
$realPath = "{$platform}/" . implode('/', array_slice($path, 1));
|
||||||
|
$tests[] = [ ...$test, 'path' => "http://{$test['path']}", 'expectedRedirect' => $realPath ];
|
||||||
|
$tests[] = [ ...$test, 'path' => "https://{$test['path']}", 'expectedRedirect' => $realPath ];
|
||||||
|
$tests[] = [ ...$test, 'expectedRedirect' => $realPath ];
|
||||||
|
$tests[] = [ ...$test, 'path' => $realPath ];
|
||||||
|
}
|
||||||
|
|
||||||
|
$allPassed = true;
|
||||||
|
|
||||||
|
foreach ($tests as $test) {
|
||||||
|
if (!isset($test['expectedCode'])) {
|
||||||
|
$test['expectedCode'] = (isset($test['expectedRedirect']) ? 302 : 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
$url = rtrim(PROXATORE_URL, '/') . '/' . $test['path'];
|
||||||
|
$ch = curl_init($url);
|
||||||
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
$body = curl_exec($ch);
|
||||||
|
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||||
|
$error = curl_error($ch);
|
||||||
|
curl_close($ch);
|
||||||
|
|
||||||
|
$passed = true;
|
||||||
|
$messages = [];
|
||||||
|
|
||||||
|
if ($code !== $test['expectedCode']) {
|
||||||
|
$passed = false;
|
||||||
|
$messages[] = "Expected HTTP code {$test['expectedCode']}, got $code.";
|
||||||
|
}
|
||||||
|
if ($code !== 0 && $test['expectedCode'] !== 302) {
|
||||||
|
foreach ($test['expectedContains'] ?? (($test['title'] ?? null) ? [$test['title']] : []) as $substr) {
|
||||||
|
if (strpos($body, $substr) === false) {
|
||||||
|
$passed = false;
|
||||||
|
$messages[] = "Response body did not contain '$substr'.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$messages[] = $error;
|
||||||
|
}
|
||||||
|
|
||||||
|
$status = $passed ? '✅ PASS' : '❌ FAIL';
|
||||||
|
$name = $test['name'] . (($test['title'] ?? null) ? ": {$test['title']}" : null);
|
||||||
|
echo "[{$status}] {$name} <{$test['path']}>\n";
|
||||||
|
if (!$passed) {
|
||||||
|
foreach ($messages as $msg) {
|
||||||
|
echo " - $msg\n";
|
||||||
|
}
|
||||||
|
$allPassed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit($allPassed ? 0 : 1);
|
Reference in New Issue
Block a user