diff --git a/install/data/defaults.json b/install/data/defaults.json index 195c99b0f2..d5f5aacb91 100644 --- a/install/data/defaults.json +++ b/install/data/defaults.json @@ -193,6 +193,8 @@ "disableCustomUserSkins": 0, "activitypubEnabled": 1, "activitypubAllowLoopback": 0, + "activitypubProbe": 1, + "activitypubProbeTimeout": 500, "activitypubContentPruneDays": 30, "activitypubUserPruneDays": 7, "activitypubFilter": 0 diff --git a/public/language/en-GB/admin/settings/activitypub.json b/public/language/en-GB/admin/settings/activitypub.json index 36f450b30d..16b088f034 100644 --- a/public/language/en-GB/admin/settings/activitypub.json +++ b/public/language/en-GB/admin/settings/activitypub.json @@ -12,6 +12,12 @@ "allowLoopback": "Allow loopback processing", "allowLoopback-help": "Useful for debugging purposes only. You should probably leave this disabled.", + "probe": "Open in App", + "probe-enabled": "Try to open ActivityPub-enabled resources in NodeBB", + "probe-enabled-help": "If enabled, NodeBB will check every external link for an ActivityPub equivalent, and load it in NodeBB instead.", + "probe-timeout": "Lookup Timeout (milliseconds)", + "probe-timeout-help": "(Default: 500) If the lookup query does not receive a response within the set timeframe, will send the user to the link directly instead. Adjust this number higher if sites are responding slowly and you wish to give extra time.", + "server-filtering": "Filtering", "count": "This NodeBB is currently aware of %1 server(s)", "server.filter-help": "Specify servers you would like to bar from federating with your NodeBB. Alternatively, you may opt to selectively allow federation with specific servers, instead. Both options are supported, although they are mutually exclusive.", diff --git a/public/src/ajaxify.js b/public/src/ajaxify.js index 5abfd4958d..40c35c3332 100644 --- a/public/src/ajaxify.js +++ b/public/src/ajaxify.js @@ -609,7 +609,7 @@ $(document).ready(function () { ajaxify.go('outgoing?url=' + encodeURIComponent(href)); e.preventDefault(); } - } else { + } else if (config.activitypub.probe) { ajaxify.go(`ap?resource=${encodeURIComponent(this.href)}`); e.preventDefault(); } diff --git a/src/activitypub/index.js b/src/activitypub/index.js index 1f258c16e4..1b7c4b84e2 100644 --- a/src/activitypub/index.js +++ b/src/activitypub/index.js @@ -490,8 +490,10 @@ ActivityPub.probe = async ({ uid, url }) => { } // Opportunistic HEAD - const { response } = await request.head(url); - try { + async function checkHeader(timeout) { + const { response } = await request.head(url, { + timeout, + }); const { headers } = response; if (headers && headers.link) { let parts = headers.link.split(';'); @@ -509,8 +511,19 @@ ActivityPub.probe = async ({ uid, url }) => { return true; } } + + return false; + } + try { + await checkHeader(meta.config.activitypubProbeTimeout || 500); } catch (e) { - // ... + if (e.name === 'TimeoutError') { + // Return early but retry for caching purposes + checkHeader(1000 * 60).then((result) => { + probeCache.set(url, result); + }); + return false; + } } probeCache.set(url, false); diff --git a/src/controllers/api.js b/src/controllers/api.js index a4d1f34291..261683634e 100644 --- a/src/controllers/api.js +++ b/src/controllers/api.js @@ -97,6 +97,9 @@ apiController.loadConfig = async function (req) { styles: fontawesome_styles, version: fontawesome_version, }, + activitypub: { + probe: meta.config.activitypubProbe, + }, }; let settings = config; diff --git a/src/views/admin/settings/activitypub.tpl b/src/views/admin/settings/activitypub.tpl index 9dd74206df..749fb57629 100644 --- a/src/views/admin/settings/activitypub.tpl +++ b/src/views/admin/settings/activitypub.tpl @@ -24,6 +24,26 @@ +
+
[[admin/settings/activitypub:probe]]
+
+
+
+ + +

[[admin/settings/activitypub:probe-enabled-help]]

+
+
+ + +
+ [[admin/settings/activitypub:probe-timeout-help]] +
+
+
+
+
+
[[admin/settings/activitypub:pruning]]