Store nodeInfo separately + other feedback

This commit is contained in:
Scott Feeney 2024-10-10 17:31:16 -07:00
parent ad0ab0c845
commit 22f0703162
3 changed files with 57 additions and 31 deletions

View file

@ -80,6 +80,7 @@ export async function initInstance(client, instance) {
} }
__BENCHMARK.end('fetch-instance'); __BENCHMARK.end('fetch-instance');
if (!info) return; if (!info) return;
console.log(info);
const { const {
// v1 // v1
uri, uri,
@ -89,28 +90,6 @@ export async function initInstance(client, instance) {
configuration: { urls: { streaming } = {} } = {}, configuration: { urls: { streaming } = {} } = {},
} = info; } = info;
// GoToSocial requires we get the NodeInfo to identify server type
// spec: https://github.com/jhass/nodeinfo
try {
if (uri || domain) {
let urlBase = uri || `https://${domain}`;
const wellKnown = await (await fetch(`${urlBase}/.well-known/nodeinfo`)).json();
if (Array.isArray(wellKnown?.links)) {
const nodeInfoUrl = wellKnown.links.find(
(link) => typeof link.rel === 'string' &&
link.rel.startsWith('http://nodeinfo.diaspora.software/ns/schema/')
)?.href;
if (nodeInfoUrl && nodeInfoUrl.startsWith(urlBase)) {
const nodeInfo = await (await fetch(nodeInfoUrl)).json();
if (typeof nodeInfo?.software?.name === 'string') {
info.software_name = nodeInfo.software.name;
}
}
}
}
} catch (e) {}
console.log(info);
const instances = store.local.getJSON('instances') || {}; const instances = store.local.getJSON('instances') || {};
if (uri || domain) { if (uri || domain) {
instances[ instances[
@ -124,6 +103,31 @@ export async function initInstance(client, instance) {
instances[instance.toLowerCase()] = info; instances[instance.toLowerCase()] = info;
} }
store.local.setJSON('instances', instances); store.local.setJSON('instances', instances);
let nodeInfo;
// GoToSocial requires we get the NodeInfo to identify server type
// spec: https://github.com/jhass/nodeinfo
try {
if (uri || domain) {
let urlBase = uri || `https://${domain}`;
const wellKnown = await (await fetch(`${urlBase}/.well-known/nodeinfo`)).json();
if (Array.isArray(wellKnown?.links)) {
const nodeInfoUrl = wellKnown.links.find(
(link) => typeof link.rel === 'string' &&
link.rel.startsWith('http://nodeinfo.diaspora.software/ns/schema/')
)?.href;
if (nodeInfoUrl && nodeInfoUrl.startsWith(urlBase)) {
nodeInfo = await (await fetch(nodeInfoUrl)).json();
}
}
}
} catch (e) {}
const nodeInfos = store.local.getJSON('nodeInfos') || {};
if (nodeInfo) {
nodeInfos[instance.toLowerCase()] = nodeInfo;
}
store.local.setJSON('nodeInfos', nodeInfos);
// This is a weird place to put this but here's updating the masto instance with the streaming API URL set in the configuration // This is a weird place to put this but here's updating the masto instance with the streaming API URL set in the configuration
// Reason: Streaming WebSocket URL may change, unlike the standard API REST URLs // Reason: Streaming WebSocket URL may change, unlike the standard API REST URLs
const supportsWebSocket = 'WebSocket' in window; const supportsWebSocket = 'WebSocket' in window;

View file

@ -115,6 +115,20 @@ export function getCurrentInstance() {
} }
} }
let currentNodeInfo = null;
export function getCurrentNodeInfo() {
if (currentNodeInfo) return currentNodeInfo;
try {
const account = getCurrentAccount();
const nodeInfos = store.local.getJSON('nodeInfos') || {};
const instanceURL = account.instanceURL.toLowerCase();
return (currentNodeInfo = (nodeInfos[instanceURL] || {}));
} catch (e) {
console.error(e);
return {};
}
}
// Massage these instance configurations to match the Mastodon API // Massage these instance configurations to match the Mastodon API
// - Pleroma // - Pleroma
function getInstanceConfiguration(instance) { function getInstanceConfiguration(instance) {

View file

@ -2,7 +2,7 @@ import { satisfies } from 'compare-versions';
import features from '../data/features.json'; import features from '../data/features.json';
import { getCurrentInstance } from './store-utils'; import { getCurrentInstance, getCurrentNodeInfo } from './store-utils';
// Non-semver(?) UA string detection // Non-semver(?) UA string detection
const containPixelfed = /pixelfed/i; const containPixelfed = /pixelfed/i;
@ -31,7 +31,13 @@ const supportsCache = {};
function supports(feature) { function supports(feature) {
try { try {
let { version, domain, software_name } = getCurrentInstance(); let { version, domain } = getCurrentInstance();
let softwareName = getCurrentNodeInfo()?.software?.name || 'mastodon';
if (softwareName === 'hometown') {
// Hometown is a Mastodon fork and inherits its features
softwareName = 'mastodon';
}
const key = `${domain}-${feature}`; const key = `${domain}-${feature}`;
if (supportsCache[key]) return supportsCache[key]; if (supportsCache[key]) return supportsCache[key];
@ -42,13 +48,15 @@ function supports(feature) {
const range = features[feature]; const range = features[feature];
if (!range) return false; if (!range) return false;
return (supportsCache[key] = (
containGTS.test(feature) === containGTS.test(software_name) // '@mastodon/blah' => 'mastodon'
&& satisfies(version, range, { const featureSoftware = feature.match(/^@([a-z]+)\//)[1];
const doesSoftwareMatch = featureSoftware === softwareName.toLowerCase();
return (supportsCache[key] = doesSoftwareMatch && satisfies(version, range, {
includePrerelease: true, includePrerelease: true,
loose: true, loose: true,
}) }));
));
} catch (e) { } catch (e) {
return false; return false;
} }