Merge branch 'develop' of https://github.com/NodeBB/NodeBB into develop

This commit is contained in:
Barış Soner Uşaklı
2026-02-26 16:04:15 -05:00
110 changed files with 688 additions and 266 deletions

View File

@@ -135,11 +135,17 @@ ActivityPub.resolveInboxes = async (ids) => {
// Filter out blocked instances
const blocked = [];
inboxArr = inboxArr.filter((inbox) => {
const { hostname } = new URL(inbox);
const allowed = ActivityPub.instances.isAllowed(hostname);
if (!allowed) {
blocked.push(inbox);
let allowed = false;
try {
const { hostname } = new URL(inbox);
allowed = ActivityPub.instances.isAllowed(hostname);
if (!allowed) {
blocked.push(inbox);
}
} catch (e) {
winston.warn(`[activitypub/resolveInboxes] Malformed URL encountered while filtering out blocked instances: ${inbox}`);
}
return allowed;
});
if (blocked.length) {

View File

@@ -8,6 +8,7 @@ const sanitize = require('sanitize-html');
const tokenizer = require('sbd');
const db = require('../database');
const meta = require('../meta');
const user = require('../user');
const categories = require('../categories');
const posts = require('../posts');
@@ -710,7 +711,7 @@ Mocks.notes.public = async (post) => {
// Special handling for main posts (as:Article w/ as:Note preview)
const plaintext = posts.sanitizePlaintext(content);
const isArticle = post.pid === post.topic.mainPid && plaintext.length > 500;
const isArticle = post.pid === post.topic.mainPid && plaintext.length > meta.config.activitypubSummaryLimit;
if (post.isMainPost) {
const thumbs = await topics.thumbs.get(post.tid);
@@ -755,17 +756,16 @@ Mocks.notes.public = async (post) => {
// attachment,
// };
const breakString = '[...]';
if (post.content.includes(breakString)) {
const index = post.content.indexOf(breakString);
summary = post.content.slice(0, index + breakString.length);
if (post.content.includes(meta.config.activitypubBreakString)) {
const index = post.content.indexOf(meta.config.activitypubBreakString);
summary = post.content.slice(0, index + meta.config.activitypubBreakString.length);
} else {
const sentences = tokenizer.sentences(post.content, { newline_boundaries: true });
// Append sentences to summary until it contains just under 500 characters of content
const limit = 500;
// Append sentences to summary until until just under configured character limit
const limit = meta.config.activitypubSummaryLimit;
let remaining = limit;
let finished = false;
summary = sentences.reduce((memo, sentence) => {
summary = sentences.reduce((memo, sentence, index) => {
if (finished) {
return memo;
}
@@ -776,7 +776,7 @@ Mocks.notes.public = async (post) => {
});
remaining = remaining - clean.length;
if (remaining > 0) {
memo += ` ${sentence}`;
memo += `${index > 0 ? ' ' : ''}${sentence}`;
} else { // There was more but summary generation is complete
finished = true;
memo += ' [...]';

View File

@@ -10,6 +10,12 @@ federationController.general = function (req, res) {
});
};
federationController.content = function (req, res) {
res.render(`admin/federation/content`, {
title: '[[admin/menu:federation/content]]',
});
};
federationController.rules = async function (req, res) {
const rules = await activitypub.rules.list();
@@ -36,8 +42,11 @@ federationController.pruning = function (req, res) {
});
};
federationController.safety = function (req, res) {
federationController.safety = async function (req, res) {
const instanceCount = await activitypub.instances.getCount();
res.render(`admin/federation/safety`, {
title: '[[admin/menu:federation/safety]]',
instanceCount,
});
};

View File

@@ -164,21 +164,6 @@ settingsController.api = async (req, res) => {
});
};
settingsController.activitypub = async (req, res) => {
const [instanceCount, rules, relays] = await Promise.all([
activitypub.instances.getCount(),
activitypub.rules.list(),
activitypub.relays.list(),
]);
res.render('admin/settings/activitypub', {
title: `[[admin/menu:settings/activitypub]]`,
instanceCount,
rules,
relays,
});
};
settingsController.cookies = async (req, res) => {
res.render(`admin/settings/cookies`, {
title: `[[admin/menu:settings/cookies]]`,

View File

@@ -58,7 +58,7 @@ module.exports = function (Posts) {
}
if (!type.startsWith('activitypub.')) {
postData.content = postData.content.replace('[...]', '');
postData.content = postData.content.replace(meta.config.activitypubBreakString, '');
}
({ postData } = await plugins.hooks.fire('filter:parse.post', { postData, type }));
postData.content = translator.escape(postData.content);

View File

@@ -47,12 +47,12 @@ module.exports = function (app, name, middleware, controllers) {
helpers.setupAdminPageRoute(app, `/${name}/settings/pagination`, middlewares, controllers.admin.settings.pagination);
helpers.setupAdminPageRoute(app, `/${name}/settings/notifications`, middlewares, controllers.admin.settings.notifications);
helpers.setupAdminPageRoute(app, `/${name}/settings/api`, middlewares, controllers.admin.settings.api);
helpers.setupAdminPageRoute(app, `/${name}/settings/activitypub`, middlewares, controllers.admin.settings.activitypub);
helpers.setupAdminPageRoute(app, `/${name}/settings/cookies`, middlewares, controllers.admin.settings.cookies);
helpers.setupAdminPageRoute(app, `/${name}/settings/web-crawler`, middlewares, controllers.admin.settings.webCrawler);
helpers.setupAdminPageRoute(app, `/${name}/settings/advanced`, middlewares, controllers.admin.settings.advanced);
helpers.setupAdminPageRoute(app, `/${name}/federation/general`, middlewares, controllers.admin.federation.general);
helpers.setupAdminPageRoute(app, `/${name}/federation/content`, middlewares, controllers.admin.federation.content);
helpers.setupAdminPageRoute(app, `/${name}/federation/rules`, middlewares, controllers.admin.federation.rules);
helpers.setupAdminPageRoute(app, `/${name}/federation/relays`, middlewares, controllers.admin.federation.relays);
helpers.setupAdminPageRoute(app, `/${name}/federation/pruning`, middlewares, controllers.admin.federation.pruning);

View File

@@ -0,0 +1,29 @@
<div class="acp-page-container">
<!-- IMPORT admin/partials/settings/header.tpl -->
<div class="row settings m-0">
<div id="spy-container" class="col-12 col-md-8 px-0 mb-4" tabindex="0">
<div id="outgoing" class="mb-4">
<h5 class="fw-bold tracking-tight settings-header">[[admin/settings/activitypub:content.outgoing]]</h5>
<form>
<div class="mb-3">
<label class="form-label" for="activitypubSummaryLimit">[[admin/settings/activitypub:content.summary-limit]]</label>
<input type="number" id="activitypubSummaryLimit" name="activitypubSummaryLimit" data-field="activitypubSummaryLimit" title="[[admin/settings/activitypub:content.summary-limit]]" class="form-control" />
<div class="form-text">
[[admin/settings/activitypub:content.summary-limit-help]]
</div>
</div>
<div class="mb-3">
<label class="form-label" for="activitypubBreakString">[[admin/settings/activitypub:content.break-string]]</label>
<input type="text" id="activitypubBreakString" name="activitypubBreakString" data-field="activitypubBreakString" title="[[admin/settings/activitypub:content.break-string]]" class="form-control" />
<div class="form-text">
[[admin/settings/activitypub:content.break-string-help]]
</div>
</div>
</form>
</div>
</div>
<!-- IMPORT admin/partials/settings/toc.tpl -->
</div>
</div>

View File

@@ -104,6 +104,7 @@
<div id="collapseFederation" class="accordion-collapse collapse" data-bs-parent="#accordionACP">
<div class="accordion-body p-0 d-grid">
<a class="btn btn-ghost btn-sm text-start" id="federation-general" href="{relative_path}/admin/federation/general">[[admin/menu:federation/general]]</a>
<a class="btn btn-ghost btn-sm text-start" id="federation-content" href="{relative_path}/admin/federation/content">[[admin/menu:federation/content]]</a>
<a class="btn btn-ghost btn-sm text-start" id="federation-rules" href="{relative_path}/admin/federation/rules">[[admin/menu:federation/rules]]</a>
<a class="btn btn-ghost btn-sm text-start" id="federation-relays" href="{relative_path}/admin/federation/relays">[[admin/menu:federation/relays]]</a>
<a class="btn btn-ghost btn-sm text-start" id="federation-pruning" href="{relative_path}/admin/federation/pruning">[[admin/menu:federation/pruning]]</a>