Added redirectors for Bluesky and Fediverse.
This commit is contained in:
parent
1157c85d83
commit
1c9332b9d0
3 changed files with 124 additions and 3 deletions
26
public/assets/bsky.js
Normal file
26
public/assets/bsky.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
(async () => {
|
||||
const status = document.querySelector('.js-status');
|
||||
status.textContent = 'Looking up DID...';
|
||||
|
||||
const format = BSKY_FORMAT.replace('%s', location.protocol.substring(0, location.protocol.length - 1));
|
||||
let did = null;
|
||||
|
||||
try {
|
||||
const response = await fetch(`${location.protocol}//${BSKY_HANDLE}/.well-known/atproto-did`);
|
||||
did = await response.text();
|
||||
} catch(ex) {
|
||||
status.style.color = 'red';
|
||||
status.textContent = `Could not find DID! ${ex}`;
|
||||
return;
|
||||
}
|
||||
|
||||
if(typeof did !== 'string' || !did.startsWith('did:')) {
|
||||
status.style.color = 'red';
|
||||
status.textContent = 'Look up result was not a valid DID.';
|
||||
return;
|
||||
}
|
||||
|
||||
const url = format.replace('%s', did);
|
||||
status.textContent = `Redirecting to ${url}...`;
|
||||
location.replace(url);
|
||||
})();
|
39
public/assets/fedi.js
Normal file
39
public/assets/fedi.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
(async () => {
|
||||
const status = document.querySelector('.js-status');
|
||||
status.textContent = 'Looking up Fediverse profile...';
|
||||
|
||||
let url = null;
|
||||
try {
|
||||
const response = await fetch(`${location.protocol}//${FEDI_INSTANCE}/.well-known/webfinger?format=json&resource=acct:${FEDI_USERNAME}@${FEDI_INSTANCE}`);
|
||||
const webfinger = await response.json();
|
||||
|
||||
if(typeof webfinger === 'object') {
|
||||
if(Array.isArray(webfinger.links))
|
||||
for(const link of webfinger.links)
|
||||
if(typeof link === 'object' && link.rel === 'http://webfinger.net/rel/profile-page' && typeof link.href === 'string') {
|
||||
url = link.href;
|
||||
break;
|
||||
}
|
||||
|
||||
if(typeof url !== 'string' && Array.isArray(webfinger.aliases))
|
||||
for(const alias of webfinger.aliases)
|
||||
if(typeof alias === 'string') {
|
||||
url = alias;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch(ex) {
|
||||
status.style.color = 'red';
|
||||
status.textContent = `Could not complete Webfinger lookup! ${ex}`;
|
||||
return;
|
||||
}
|
||||
|
||||
if(typeof url !== 'string' || (!url.startsWith('https://') && !url.startsWith('http://'))) {
|
||||
status.style.color = 'red';
|
||||
status.textContent = 'Could not find an acceptable profile URL.';
|
||||
return;
|
||||
}
|
||||
|
||||
status.textContent = `Redirecting to ${url}...`;
|
||||
location.replace(url);
|
||||
})();
|
|
@ -49,9 +49,10 @@ final class RedirectorRoutes implements IRouteHandler {
|
|||
$this->redirect($response, $request, $info->getString(1));
|
||||
}
|
||||
|
||||
private function redirectSimple($response, $request, string $format, string $argument) {
|
||||
$scheme = empty($_SERVER['HTTPS']) ? 'http' : 'https';
|
||||
$argument = rawurlencode($argument);
|
||||
private function redirectSimple($response, $request, string $format, string $argument, bool $forceSecure = false, bool $encodeArgument = true) {
|
||||
$scheme = !$forceSecure && empty($_SERVER['HTTPS']) ? 'http' : 'https';
|
||||
if($encodeArgument)
|
||||
$argument = rawurlencode($argument);
|
||||
$url = sprintf($format, $scheme, $argument);
|
||||
|
||||
$this->redirect($response, $request, $url);
|
||||
|
@ -77,4 +78,59 @@ final class RedirectorRoutes implements IRouteHandler {
|
|||
public function redirectForumPost($response, $request, string $postId) {
|
||||
$this->redirectSimple($response, $request, $this->urls->getString('forum_post'), $postId);
|
||||
}
|
||||
|
||||
#[HttpGet('/bsky/((did:[a-z0-9]+:[A-Za-z0-9.\-_:%]+)|(([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])))')]
|
||||
public function redirecyBluesky($response, $request, string $handle) {
|
||||
$did = null;
|
||||
|
||||
if(str_starts_with($handle, 'did:'))
|
||||
$did = $handle;
|
||||
else {
|
||||
$timeout = ini_get('default_socket_timeout');
|
||||
try {
|
||||
ini_set('default_socket_timeout', 3);
|
||||
$records = dns_get_record(sprintf('_atproto.%s', $handle), DNS_TXT);
|
||||
|
||||
|
||||
if(is_array($records))
|
||||
foreach($records as $record)
|
||||
if(array_key_exists('txt', $record) && str_starts_with($record['txt'], 'did=')) {
|
||||
$did = trim(substr(trim($record['txt']), 4));
|
||||
break;
|
||||
}
|
||||
} finally {
|
||||
ini_set('default_socket_timeout', $timeout);
|
||||
}
|
||||
}
|
||||
|
||||
$format = $this->urls->getString('bsky_profile', '%s://bsky.app/profile/%s');
|
||||
if(is_string($did)) {
|
||||
$this->redirectSimple($response, $request, $format, $did, encodeArgument: false);
|
||||
return;
|
||||
}
|
||||
|
||||
$handle = rawurlencode($handle);
|
||||
echo <<<HTML
|
||||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>Redirecting to Bluesky profile...</title>
|
||||
<div class=js-status><noscript>Javascript must be enabled for Bluesky redirects to work.</noscript></div>
|
||||
<script>const BSKY_FORMAT = '{$format}'; const BSKY_HANDLE = decodeURIComponent('{$handle}');</script>
|
||||
<script src="/assets/bsky.js"></script>
|
||||
HTML;
|
||||
}
|
||||
|
||||
#[HttpGet('/fedi/([A-Za-z0-9._%+-]+)@([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})')]
|
||||
public function redirecyFediverse($response, $request, string $userName, string $instance) {
|
||||
$userName = rawurlencode($userName);
|
||||
$instance = rawurlencode($instance);
|
||||
echo <<<HTML
|
||||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>Redirecting to Fediverse profile...</title>
|
||||
<div class=js-status><noscript>Javascript must be enabled for Fediverse redirects to work.</noscript></div>
|
||||
<script>const FEDI_USERNAME = '{$userName}'; const FEDI_INSTANCE = decodeURIComponent('{$instance}');</script>
|
||||
<script src="/assets/fedi.js"></script>
|
||||
HTML;
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue