From 22f0703162fb14fae4f12774fbf1ab4ebc3f5f27 Mon Sep 17 00:00:00 2001 From: Scott Feeney Date: Thu, 10 Oct 2024 17:31:16 -0700 Subject: [PATCH] Store nodeInfo separately + other feedback --- src/utils/api.js | 48 ++++++++++++++++++++++------------------ src/utils/store-utils.js | 14 ++++++++++++ src/utils/supports.js | 26 ++++++++++++++-------- 3 files changed, 57 insertions(+), 31 deletions(-) diff --git a/src/utils/api.js b/src/utils/api.js index 4ea12ddc..ff22f3d2 100644 --- a/src/utils/api.js +++ b/src/utils/api.js @@ -80,6 +80,7 @@ export async function initInstance(client, instance) { } __BENCHMARK.end('fetch-instance'); if (!info) return; + console.log(info); const { // v1 uri, @@ -89,28 +90,6 @@ export async function initInstance(client, instance) { configuration: { urls: { streaming } = {} } = {}, } = 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') || {}; if (uri || domain) { instances[ @@ -124,6 +103,31 @@ export async function initInstance(client, instance) { instances[instance.toLowerCase()] = info; } 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 // Reason: Streaming WebSocket URL may change, unlike the standard API REST URLs const supportsWebSocket = 'WebSocket' in window; diff --git a/src/utils/store-utils.js b/src/utils/store-utils.js index cc236215..99f3186d 100644 --- a/src/utils/store-utils.js +++ b/src/utils/store-utils.js @@ -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 // - Pleroma function getInstanceConfiguration(instance) { diff --git a/src/utils/supports.js b/src/utils/supports.js index 07b1d54b..f8183526 100644 --- a/src/utils/supports.js +++ b/src/utils/supports.js @@ -2,7 +2,7 @@ import { satisfies } from 'compare-versions'; import features from '../data/features.json'; -import { getCurrentInstance } from './store-utils'; +import { getCurrentInstance, getCurrentNodeInfo } from './store-utils'; // Non-semver(?) UA string detection const containPixelfed = /pixelfed/i; @@ -31,7 +31,13 @@ const supportsCache = {}; function supports(feature) { 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}`; if (supportsCache[key]) return supportsCache[key]; @@ -42,13 +48,15 @@ function supports(feature) { const range = features[feature]; if (!range) return false; - return (supportsCache[key] = ( - containGTS.test(feature) === containGTS.test(software_name) - && satisfies(version, range, { - includePrerelease: true, - loose: true, - }) - )); + + // '@mastodon/blah' => 'mastodon' + const featureSoftware = feature.match(/^@([a-z]+)\//)[1]; + + const doesSoftwareMatch = featureSoftware === softwareName.toLowerCase(); + return (supportsCache[key] = doesSoftwareMatch && satisfies(version, range, { + includePrerelease: true, + loose: true, + })); } catch (e) { return false; }