mirror of
https://github.com/cheeaun/phanpy.git
synced 2024-12-18 09:51:57 +03:00
Use NodeInfo to detect features if available
For Mastodon <=4.3 (all current stable releases of Mastodon), the NodeInfo request will always fail due to mastodon/mastodon#23135 and fall back to the existing behavior. For other server software, this will allow for more accurate checking of feature availability. Fixes #808: adds support for exclusive lists with GoToSocial 0.17+.
This commit is contained in:
parent
4a09740ae9
commit
839023cefc
4 changed files with 88 additions and 40 deletions
|
@ -1,8 +0,0 @@
|
||||||
{
|
|
||||||
"@mastodon/edit-media-attributes": ">=4.1",
|
|
||||||
"@mastodon/list-exclusive": ">=4.2",
|
|
||||||
"@mastodon/filtered-notifications": "~4.3 || >=4.3",
|
|
||||||
"@mastodon/fetch-multiple-statuses": "~4.3 || >=4.3",
|
|
||||||
"@mastodon/trending-link-posts": "~4.3 || >=4.3",
|
|
||||||
"@mastodon/grouped-notifications": "~4.3 || >=4.3"
|
|
||||||
}
|
|
|
@ -80,7 +80,6 @@ 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,6 +88,32 @@ export async function initInstance(client, instance) {
|
||||||
domain,
|
domain,
|
||||||
configuration: { urls: { streaming } = {} } = {},
|
configuration: { urls: { streaming } = {} } = {},
|
||||||
} = info;
|
} = info;
|
||||||
|
|
||||||
|
let nodeInfo;
|
||||||
|
try {
|
||||||
|
if (uri || domain) {
|
||||||
|
let urlBase = uri || `https://${domain}`;
|
||||||
|
const wellKnownResponse = await fetch(`${urlBase}/.well-known/nodeinfo`);
|
||||||
|
if (wellKnownResponse.ok) {
|
||||||
|
const wellKnown = await wellKnownResponse.json();
|
||||||
|
if (wellKnown && 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 nodeInfoResponse = await fetch(nodeInfoUrl);
|
||||||
|
nodeInfo = await nodeInfoResponse.json();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
|
if (nodeInfo) {
|
||||||
|
info.nodeInfo = nodeInfo;
|
||||||
|
}
|
||||||
|
console.log(info);
|
||||||
|
|
||||||
const instances = store.local.getJSON('instances') || {};
|
const instances = store.local.getJSON('instances') || {};
|
||||||
if (uri || domain) {
|
if (uri || domain) {
|
||||||
instances[
|
instances[
|
||||||
|
|
|
@ -163,5 +163,5 @@ export function getVapidKey() {
|
||||||
|
|
||||||
export function isMediaFirstInstance() {
|
export function isMediaFirstInstance() {
|
||||||
const instance = getCurrentInstance();
|
const instance = getCurrentInstance();
|
||||||
return /pixelfed/i.test(instance?.version);
|
return instance.nodeInfo?.software?.name === 'pixelfed';
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,51 +1,82 @@
|
||||||
import { satisfies } from 'compare-versions';
|
import { satisfies } from 'compare-versions';
|
||||||
|
|
||||||
import features from '../data/features.json';
|
|
||||||
|
|
||||||
import { getCurrentInstance } from './store-utils';
|
import { getCurrentInstance } from './store-utils';
|
||||||
|
|
||||||
// Non-semver(?) UA string detection
|
|
||||||
const containPixelfed = /pixelfed/i;
|
|
||||||
const notContainPixelfed = /^(?!.*pixelfed).*$/i;
|
|
||||||
const containPleroma = /pleroma/i;
|
|
||||||
const containAkkoma = /akkoma/i;
|
|
||||||
const platformFeatures = {
|
const platformFeatures = {
|
||||||
'@mastodon/lists': notContainPixelfed,
|
'@mastodon/edit-media-attributes': [['mastodon', '>=4.1']],
|
||||||
'@mastodon/filters': notContainPixelfed,
|
'@mastodon/list-exclusive': [
|
||||||
'@mastodon/mentions': notContainPixelfed,
|
['mastodon', '>=4.2'],
|
||||||
'@mastodon/trending-hashtags': notContainPixelfed,
|
['gotosocial', '>=0.17'],
|
||||||
'@mastodon/trending-links': notContainPixelfed,
|
],
|
||||||
'@mastodon/post-bookmark': notContainPixelfed,
|
'@mastodon/filtered-notifications': [['mastodon', '>=4.3']],
|
||||||
'@mastodon/post-edit': notContainPixelfed,
|
'@mastodon/fetch-multiple-statuses': [['mastodon', '>=4.3']],
|
||||||
'@mastodon/profile-edit': notContainPixelfed,
|
'@mastodon/trending-link-posts': [['mastodon', '>=4.3']],
|
||||||
'@mastodon/profile-private-note': notContainPixelfed,
|
'@mastodon/grouped-notifications': [['mastodon', '>=4.3']],
|
||||||
'@pixelfed/trending': containPixelfed,
|
'@mastodon/lists': [['!pixelfed']],
|
||||||
'@pixelfed/home-include-reblogs': containPixelfed,
|
'@mastodon/filters': [['!pixelfed']],
|
||||||
'@pixelfed/global-feed': containPixelfed,
|
'@mastodon/mentions': [['!pixelfed']],
|
||||||
'@pleroma/local-visibility-post': containPleroma,
|
'@mastodon/trending-hashtags': [['!pixelfed']],
|
||||||
'@akkoma/local-visibility-post': containAkkoma,
|
'@mastodon/trending-links': [['!pixelfed']],
|
||||||
|
'@mastodon/post-bookmark': [['!pixelfed']],
|
||||||
|
'@mastodon/post-edit': [['!pixelfed']],
|
||||||
|
'@mastodon/profile-edit': [['!pixelfed']],
|
||||||
|
'@mastodon/profile-private-note': [['!pixelfed']],
|
||||||
|
'@pixelfed/trending': [['pixelfed']],
|
||||||
|
'@pixelfed/home-include-reblogs': [['pixelfed']],
|
||||||
|
'@pixelfed/global-feed': [['pixelfed']],
|
||||||
|
'@pleroma/local-visibility-post': [['pleroma']],
|
||||||
|
'@akkoma/local-visibility-post': [['akkoma']],
|
||||||
};
|
};
|
||||||
|
|
||||||
const supportsCache = {};
|
const supportsCache = {};
|
||||||
|
|
||||||
function supports(feature) {
|
function supports(feature) {
|
||||||
|
const specs = platformFeatures[feature];
|
||||||
|
if (!specs) return false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { version, domain } = getCurrentInstance();
|
let { version, domain, nodeInfo } = getCurrentInstance();
|
||||||
|
|
||||||
const key = `${domain}-${feature}`;
|
const key = `${domain}-${feature}`;
|
||||||
if (supportsCache[key]) return supportsCache[key];
|
if (supportsCache[key]) return supportsCache[key];
|
||||||
|
|
||||||
if (platformFeatures[feature]) {
|
let software = 'mastodon';
|
||||||
return (supportsCache[key] = platformFeatures[feature].test(version));
|
if (
|
||||||
|
nodeInfo && nodeInfo.software && typeof nodeInfo.software.version === 'string'
|
||||||
|
&& typeof nodeInfo.software.name === 'string'
|
||||||
|
) {
|
||||||
|
software = nodeInfo.software.name.toLowerCase();
|
||||||
|
version = nodeInfo.software.version;
|
||||||
}
|
}
|
||||||
|
|
||||||
const range = features[feature];
|
const isSupported = specs.some((spec) => versionSatisfies(software, version, spec));
|
||||||
if (!range) return false;
|
return (supportsCache[key] = isSupported);
|
||||||
return (supportsCache[key] = satisfies(version, range, {
|
|
||||||
includePrerelease: true,
|
|
||||||
loose: true,
|
|
||||||
}));
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function versionSatisfies(software, version, [softwareSpec, versionSpec]) {
|
||||||
|
let softwareMatches;
|
||||||
|
|
||||||
|
// Inverted spec, like !pixelfed
|
||||||
|
if (softwareSpec.startsWith('!')) {
|
||||||
|
softwareMatches = software !== softwareSpec.slice(1);
|
||||||
|
} else {
|
||||||
|
softwareMatches = (
|
||||||
|
software === softwareSpec || (
|
||||||
|
// Hometown inherits Mastodon features
|
||||||
|
software === 'hometown' && softwareSpec === 'mastodon'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return softwareMatches && (
|
||||||
|
versionSpec == null || satisfies(version, versionSpec, {
|
||||||
|
includePrerelease: true,
|
||||||
|
loose: true,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export default supports;
|
export default supports;
|
||||||
|
|
Loading…
Reference in a new issue