Merge pull request #9260 from annando/ap-relay-settings

Relay settings are now valid for the ActivityRelay as well
This commit is contained in:
Hypolite Petovan 2020-09-23 12:46:32 -04:00 committed by GitHub
commit fa94c82299
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 546 additions and 430 deletions

View file

@ -42,7 +42,7 @@ class Search
$tags = []; $tags = [];
while ($term = DBA::fetch($termsStmt)) { while ($term = DBA::fetch($termsStmt)) {
$tags[] = trim($term['term'], '#'); $tags[] = trim(mb_strtolower($term['term']), '#');
} }
DBA::close($termsStmt); DBA::close($termsStmt);
return $tags; return $tags;

View file

@ -691,8 +691,8 @@ class Site extends BaseAdmin
'$worker_fastlane' => ['worker_fastlane', DI::l10n()->t('Enable fastlane'), DI::config()->get('system', 'worker_fastlane'), DI::l10n()->t('When enabed, the fastlane mechanism starts an additional worker if processes with higher priority are blocked by processes of lower priority.')], '$worker_fastlane' => ['worker_fastlane', DI::l10n()->t('Enable fastlane'), DI::config()->get('system', 'worker_fastlane'), DI::l10n()->t('When enabed, the fastlane mechanism starts an additional worker if processes with higher priority are blocked by processes of lower priority.')],
'$worker_frontend' => ['worker_frontend', DI::l10n()->t('Enable frontend worker'), DI::config()->get('system', 'frontend_worker'), DI::l10n()->t('When enabled the Worker process is triggered when backend access is performed (e.g. messages being delivered). On smaller sites you might want to call %s/worker on a regular basis via an external cron job. You should only enable this option if you cannot utilize cron/scheduled jobs on your server.', DI::baseUrl()->get())], '$worker_frontend' => ['worker_frontend', DI::l10n()->t('Enable frontend worker'), DI::config()->get('system', 'frontend_worker'), DI::l10n()->t('When enabled the Worker process is triggered when backend access is performed (e.g. messages being delivered). On smaller sites you might want to call %s/worker on a regular basis via an external cron job. You should only enable this option if you cannot utilize cron/scheduled jobs on your server.', DI::baseUrl()->get())],
'$relay_subscribe' => ['relay_subscribe', DI::l10n()->t('Subscribe to relay'), DI::config()->get('system', 'relay_subscribe'), DI::l10n()->t('Enables the receiving of public posts from the relay. They will be included in the search, subscribed tags and on the global community page.')], '$relay_subscribe' => ['relay_subscribe', DI::l10n()->t('Use relay servers'), DI::config()->get('system', 'relay_subscribe'), DI::l10n()->t('Enables the receiving of public posts from relay servers. They will be included in the search, subscribed tags and on the global community page.')],
'$relay_server' => ['relay_server', DI::l10n()->t('Relay server'), DI::config()->get('system', 'relay_server'), DI::l10n()->t('Address of the relay server where public posts should be send to. For example %s', 'https://social-relay.isurf.ca')], '$relay_server' => ['relay_server', DI::l10n()->t('"Social Relay" server'), DI::config()->get('system', 'relay_server'), DI::l10n()->t('Address of the "Social Relay" server where public posts should be send to. For example %s. ActivityRelay servers are administrated via the "console relay" command line command.', 'https://social-relay.isurf.ca')],
'$relay_directly' => ['relay_directly', DI::l10n()->t('Direct relay transfer'), DI::config()->get('system', 'relay_directly'), DI::l10n()->t('Enables the direct transfer to other servers without using the relay servers')], '$relay_directly' => ['relay_directly', DI::l10n()->t('Direct relay transfer'), DI::config()->get('system', 'relay_directly'), DI::l10n()->t('Enables the direct transfer to other servers without using the relay servers')],
'$relay_scope' => ['relay_scope', DI::l10n()->t('Relay scope'), DI::config()->get('system', 'relay_scope'), DI::l10n()->t('Can be "all" or "tags". "all" means that every public post should be received. "tags" means that only posts with selected tags should be received.'), ['' => DI::l10n()->t('Disabled'), 'all' => DI::l10n()->t('all'), 'tags' => DI::l10n()->t('tags')]], '$relay_scope' => ['relay_scope', DI::l10n()->t('Relay scope'), DI::config()->get('system', 'relay_scope'), DI::l10n()->t('Can be "all" or "tags". "all" means that every public post should be received. "tags" means that only posts with selected tags should be received.'), ['' => DI::l10n()->t('Disabled'), 'all' => DI::l10n()->t('all'), 'tags' => DI::l10n()->t('tags')]],
'$relay_server_tags' => ['relay_server_tags', DI::l10n()->t('Server tags'), DI::config()->get('system', 'relay_server_tags'), DI::l10n()->t('Comma separated list of tags for the "tags" subscription.')], '$relay_server_tags' => ['relay_server_tags', DI::l10n()->t('Server tags'), DI::config()->get('system', 'relay_server_tags'), DI::l10n()->t('Comma separated list of tags for the "tags" subscription.')],

View file

@ -35,6 +35,7 @@ use Friendica\Model\Event;
use Friendica\Model\Item; use Friendica\Model\Item;
use Friendica\Model\ItemURI; use Friendica\Model\ItemURI;
use Friendica\Model\Mail; use Friendica\Model\Mail;
use Friendica\Model\Search;
use Friendica\Model\Tag; use Friendica\Model\Tag;
use Friendica\Model\User; use Friendica\Model\User;
use Friendica\Protocol\Activity; use Friendica\Protocol\Activity;
@ -42,6 +43,7 @@ use Friendica\Protocol\ActivityPub;
use Friendica\Util\DateTimeFormat; use Friendica\Util\DateTimeFormat;
use Friendica\Util\JsonLD; use Friendica\Util\JsonLD;
use Friendica\Util\Strings; use Friendica\Util\Strings;
use Text_LanguageDetect;
/** /**
* ActivityPub Processor Protocol class * ActivityPub Processor Protocol class
@ -767,6 +769,10 @@ class Processor
$ldactivity['thread-completion'] = true; $ldactivity['thread-completion'] = true;
$ldactivity['from-relay'] = Contact::getIdForURL($relay_actor); $ldactivity['from-relay'] = Contact::getIdForURL($relay_actor);
if (!empty($relay_actor) && !self::acceptIncomingMessage($ldactivity, $object['id'])) {
return '';
}
ActivityPub\Receiver::processActivity($ldactivity, json_encode($activity), $uid, true, false, $signer); ActivityPub\Receiver::processActivity($ldactivity, json_encode($activity), $uid, true, false, $signer);
Logger::notice('Activity had been fetched and processed.', ['url' => $url, 'object' => $activity['id']]); Logger::notice('Activity had been fetched and processed.', ['url' => $url, 'object' => $activity['id']]);
@ -774,6 +780,92 @@ class Processor
return $activity['id']; return $activity['id'];
} }
/**
* Test if incoming relay messages should be accepted
*
* @param array $activity activity array
* @param string $id object ID
* @return boolean true if message is accepted
*/
private static function acceptIncomingMessage(array $activity, string $id)
{
if (empty($activity['as:object'])) {
Logger::info('No object field in activity - accepted', ['id' => $id]);
return true;
}
$config = DI::config();
$subscribe = $config->get('system', 'relay_subscribe', false);
if ($subscribe) {
$scope = $config->get('system', 'relay_scope', SR_SCOPE_ALL);
} else {
$scope = SR_SCOPE_NONE;
}
if ($scope == SR_SCOPE_ALL) {
Logger::info('Server accept all posts - accepted', ['id' => $id]);
return true;
}
$replyto = JsonLD::fetchElement($activity['as:object'], 'as:inReplyTo', '@id');
if (Item::exists(['uri' => $replyto])) {
Logger::info('Post is a reply to an existing post - accepted', ['id' => $id, 'replyto' => $replyto]);
return true;
}
if ($scope == SR_SCOPE_NONE) {
Logger::info('Server does not accept relay posts - rejected', ['id' => $id]);
return false;
}
$messageTags = [];
$tags = Receiver::processTags(JsonLD::fetchElementArray($activity['as:object'], 'as:tag') ?? []);
if (!empty($tags)) {
foreach ($tags as $tag) {
if ($tag['type'] != 'Hashtag') {
continue;
}
$messageTags[] = ltrim(mb_strtolower($tag['name']), '#');
}
}
$systemTags = [];
$userTags = [];
if ($scope == SR_SCOPE_TAGS) {
$server_tags = $config->get('system', 'relay_server_tags', []);
$tagitems = explode(',', mb_strtolower($server_tags));
foreach ($tagitems AS $tag) {
$systemTags[] = trim($tag, '# ');
}
if ($config->get('system', 'relay_user_tags')) {
$userTags = Search::getUserTags();
}
}
$content = mb_strtolower(BBCode::toPlaintext(HTML::toBBCode(JsonLD::fetchElement($activity['as:object'], 'as:content', '@value')), false));
$tagList = array_unique(array_merge($systemTags, $userTags));
foreach ($messageTags as $tag) {
if (in_array($tag, $tagList)) {
Logger::info('Subscribed hashtag found - accepted', ['id' => $id, 'hashtag' => $tag]);
return true;
}
// We check with "strpos" for performance issues. Only when this is true, the regular expression check is used
// RegExp is taken from here: https://medium.com/@shiba1014/regex-word-boundaries-with-unicode-207794f6e7ed
if ((strpos($content, $tag) !== false) && preg_match('/(?<=[\s,.:;"\']|^)' . preg_quote($tag, '/') . '(?=[\s,.:;"\']|$)/', $content)) {
Logger::info('Subscribed hashtag found in content - accepted', ['id' => $id, 'hashtag' => $tag]);
return true;
}
}
Logger::info('No matching hashtags found - rejected', ['id' => $id]);
return false;
}
/** /**
* perform a "follow" request * perform a "follow" request
* *

View file

@ -181,7 +181,11 @@ class Receiver
return; return;
} }
Processor::fetchMissingActivity($object_id, [], $actor); $id = Processor::fetchMissingActivity($object_id, [], $actor);
if (empty($id)) {
Logger::notice('Relayed message had not been fetched', ['id' => $object_id]);
return;
}
$item_id = Item::searchByLink($object_id); $item_id = Item::searchByLink($object_id);
if ($item_id) { if ($item_id) {
@ -964,7 +968,7 @@ class Receiver
* *
* @return array with tags in a simplified format * @return array with tags in a simplified format
*/ */
private static function processTags(array $tags) public static function processTags(array $tags)
{ {
$taglist = []; $taglist = [];

File diff suppressed because it is too large Load diff