Better resolving of links

pull/341/head
Lim Chee Aun 2023-11-25 21:26:27 +08:00
rodzic 1422c5da33
commit 7019c09e5b
2 zmienionych plików z 79 dodań i 23 usunięć

Wyświetl plik

@ -1,34 +1,73 @@
import { useLayoutEffect } from 'preact/hooks';
import { useLayoutEffect, useState } from 'preact/hooks';
import { useLocation } from 'react-router-dom';
import Link from '../components/link';
import getInstanceStatusURL from '../utils/get-instance-status-url';
import Loader from '../components/loader';
import { api } from '../utils/api';
import getInstanceStatusURL, {
getInstanceStatusObject,
} from '../utils/get-instance-status-url';
export default function HttpRoute() {
const location = useLocation();
const url = location.pathname.replace(/^\//, '');
const statusURL = getInstanceStatusURL(url);
const statusObject = getInstanceStatusObject(url);
// const statusURL = getInstanceStatusURL(url);
const statusURL = statusObject?.instance
? `/${statusObject.instance}/s/${statusObject.id}`
: null;
const [uiState, setUIState] = useState('loading');
useLayoutEffect(() => {
if (statusURL) {
setTimeout(() => {
window.location.hash = statusURL + '?view=full';
}, 300);
}
setUIState('loading');
(async () => {
const { instance, id } = statusObject;
const { masto } = api({ instance });
// Check if status returns 200
try {
const status = await masto.v1.statuses.$select(id).fetch();
if (status) {
window.location.hash = statusURL + '?view=full';
return;
}
} catch (e) {}
// Fallback to search
{
const { masto: currentMasto, instance: currentInstance } = api();
const result = await currentMasto.v2.search.fetch({
q: url,
type: 'statuses',
limit: 1,
resolve: true,
});
if (result.statuses.length) {
const status = result.statuses[0];
window.location.hash = `/${currentInstance}/s/${status.id}?view=full`;
} else {
// Fallback to original URL, which will probably show error
window.location.hash = statusURL + '?view=full';
}
}
})();
}, [statusURL]);
return (
<div class="ui-state" tabIndex="-1">
{statusURL ? (
{uiState === 'loading' ? (
<>
<h2>Redirecting</h2>
<Loader abrupt />
<h2>Resolving</h2>
<p>
<a href={`#${statusURL}?view=full`}>{statusURL}</a>
<a href={url} target="_blank" rel="noopener noreferrer">
{url}
</a>
</p>
</>
) : (
<>
<h2>Unable to process URL</h2>
<h2>Unable to resolve URL</h2>
<p>
<a href={url} target="_blank" rel="noopener noreferrer">
{url}

Wyświetl plik

@ -1,19 +1,36 @@
export const statusRegex = /\/@([^@\/]+)@?([^\/]+)?\/([^\/]+)\/?$/i;
export const statusNoteRegex = /\/notes\/([^\/]+)\/?$/i;
function getInstanceStatusURL(url) {
// export const statusRegex = /\/@([^@\/]+)@?([^\/]+)?\/([^\/]+)\/?$/i;
// export const statusNoteRegex = /\/notes\/([^\/]+)\/?$/i;
const statusPostRegexes = [
/^\/@[^@\/]+\/(?:statuses|posts)\/([^\/]+)/i, // GoToSocial, Takahe
/\/notes\/([^\/]+)/i, // Misskey, Firefish
/^\/(?:notice|objects)\/([a-z0-9-]+)/i, // Pleroma
/\/@[^@\/]+@?[^\/]+?\/([^\/]+)/i, // Mastodon
];
export function getInstanceStatusObject(url) {
// Regex /:username/:id, where username = @username or @username@domain, id = anything
const { hostname, pathname } = new URL(url);
const [, username, domain, id] = pathname.match(statusRegex) || [];
if (id) {
return `/${hostname}/s/${id}`;
// const [, username, domain, id] = pathname.match(statusRegex) || [];
for (const regex of statusPostRegexes) {
const [, id] = pathname.match(regex) || [];
console.log(pathname, regex, id);
if (id) {
return {
instance: hostname,
id,
};
}
}
return null;
}
const [, noteId] = pathname.match(statusNoteRegex) || [];
if (noteId) {
return `/${hostname}/s/${noteId}`;
function getInstanceStatusURL(url) {
const { instance, id } = getInstanceStatusObject(url);
if (instance && id) {
return `/${instance}/s/${id}`;
}
return null;
}
export default getInstanceStatusURL;