Compare commits
No commits in common. "develop" and "develop" have entirely different histories.
|
@ -4,9 +4,6 @@ pipeline:
|
||||||
clone_friendica_base:
|
clone_friendica_base:
|
||||||
image: alpine/git
|
image: alpine/git
|
||||||
commands:
|
commands:
|
||||||
- git config --global user.email "no-reply@friendi.ca"
|
|
||||||
- git config --global user.name "Friendica"
|
|
||||||
- git config --global --add safe.directory $CI_WORKSPACE
|
|
||||||
- git clone https://github.com/friendica/friendica.git .
|
- git clone https://github.com/friendica/friendica.git .
|
||||||
- git checkout $CI_COMMIT_BRANCH
|
- git checkout $CI_COMMIT_BRANCH
|
||||||
when:
|
when:
|
||||||
|
|
|
@ -9,9 +9,6 @@ pipeline:
|
||||||
clone_friendica_base:
|
clone_friendica_base:
|
||||||
image: alpine/git
|
image: alpine/git
|
||||||
commands:
|
commands:
|
||||||
- git config --global user.email "no-reply@friendi.ca"
|
|
||||||
- git config --global user.name "Friendica"
|
|
||||||
- git config --global --add safe.directory $CI_WORKSPACE
|
|
||||||
- git clone https://github.com/friendica/friendica.git .
|
- git clone https://github.com/friendica/friendica.git .
|
||||||
- git checkout $CI_COMMIT_BRANCH
|
- git checkout $CI_COMMIT_BRANCH
|
||||||
when:
|
when:
|
||||||
|
|
|
@ -4,9 +4,6 @@ pipeline:
|
||||||
clone_friendica_base:
|
clone_friendica_base:
|
||||||
image: alpine/git
|
image: alpine/git
|
||||||
commands:
|
commands:
|
||||||
- git config --global user.email "no-reply@friendi.ca"
|
|
||||||
- git config --global user.name "Friendica"
|
|
||||||
- git config --global --add safe.directory $CI_WORKSPACE
|
|
||||||
- git clone https://github.com/friendica/friendica.git .
|
- git clone https://github.com/friendica/friendica.git .
|
||||||
- git checkout $CI_COMMIT_BRANCH
|
- git checkout $CI_COMMIT_BRANCH
|
||||||
when:
|
when:
|
||||||
|
|
|
@ -21,9 +21,6 @@ pipeline:
|
||||||
clone_friendica_base:
|
clone_friendica_base:
|
||||||
image: alpine/git
|
image: alpine/git
|
||||||
commands:
|
commands:
|
||||||
- git config --global user.email "no-reply@friendi.ca"
|
|
||||||
- git config --global user.name "Friendica"
|
|
||||||
- git config --global --add safe.directory $CI_WORKSPACE
|
|
||||||
- git clone https://github.com/friendica/friendica.git .
|
- git clone https://github.com/friendica/friendica.git .
|
||||||
- git checkout $CI_COMMIT_BRANCH
|
- git checkout $CI_COMMIT_BRANCH
|
||||||
clone_friendica_addon:
|
clone_friendica_addon:
|
||||||
|
|
|
@ -9,9 +9,6 @@ pipeline:
|
||||||
clone_friendica_base:
|
clone_friendica_base:
|
||||||
image: alpine/git
|
image: alpine/git
|
||||||
commands:
|
commands:
|
||||||
- git config --global user.email "no-reply@friendi.ca"
|
|
||||||
- git config --global user.name "Friendica"
|
|
||||||
- git config --global --add safe.directory $CI_WORKSPACE
|
|
||||||
- git clone https://github.com/friendica/friendica.git .
|
- git clone https://github.com/friendica/friendica.git .
|
||||||
- git checkout $CI_COMMIT_BRANCH
|
- git checkout $CI_COMMIT_BRANCH
|
||||||
when:
|
when:
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#
|
#
|
||||||
# Translators:
|
# Translators:
|
||||||
# fabrixxm <fabrix.xm@gmail.com>, 2018
|
# fabrixxm <fabrix.xm@gmail.com>, 2018
|
||||||
# Sylke Vicious <silkevicious@gmail.com>, 2023
|
# Sylke Vicious <silkevicious@gmail.com>, 2021
|
||||||
#
|
#
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid ""
|
msgid ""
|
||||||
|
@ -14,7 +14,7 @@ msgstr ""
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2022-05-11 08:54-0400\n"
|
"POT-Creation-Date: 2022-05-11 08:54-0400\n"
|
||||||
"PO-Revision-Date: 2018-05-24 06:41+0000\n"
|
"PO-Revision-Date: 2018-05-24 06:41+0000\n"
|
||||||
"Last-Translator: Sylke Vicious <silkevicious@gmail.com>, 2023\n"
|
"Last-Translator: Sylke Vicious <silkevicious@gmail.com>, 2021\n"
|
||||||
"Language-Team: Italian (https://app.transifex.com/Friendica/teams/12172/it/)\n"
|
"Language-Team: Italian (https://app.transifex.com/Friendica/teams/12172/it/)\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
@ -125,7 +125,7 @@ msgstr "Annulla"
|
||||||
|
|
||||||
#: advancedcontentfilter.php:295
|
#: advancedcontentfilter.php:295
|
||||||
msgid "This addon requires this node having at least one post"
|
msgid "This addon requires this node having at least one post"
|
||||||
msgstr "Questo addon richiede che questo nodo abbia almeno un messaggio"
|
msgstr ""
|
||||||
|
|
||||||
#: advancedcontentfilter.php:325 advancedcontentfilter.php:336
|
#: advancedcontentfilter.php:325 advancedcontentfilter.php:336
|
||||||
#: advancedcontentfilter.php:347 advancedcontentfilter.php:383
|
#: advancedcontentfilter.php:347 advancedcontentfilter.php:383
|
||||||
|
|
|
@ -27,7 +27,6 @@ $a->strings['Add new rule'] = 'Aggiungi nuova regola';
|
||||||
$a->strings['Rule Name'] = 'Nome Regola';
|
$a->strings['Rule Name'] = 'Nome Regola';
|
||||||
$a->strings['Rule Expression'] = 'Espressione Regola';
|
$a->strings['Rule Expression'] = 'Espressione Regola';
|
||||||
$a->strings['Cancel'] = 'Annulla';
|
$a->strings['Cancel'] = 'Annulla';
|
||||||
$a->strings['This addon requires this node having at least one post'] = 'Questo addon richiede che questo nodo abbia almeno un messaggio';
|
|
||||||
$a->strings['You must be logged in to use this method'] = 'Devi essere autenticato per usare questo metodo';
|
$a->strings['You must be logged in to use this method'] = 'Devi essere autenticato per usare questo metodo';
|
||||||
$a->strings['Invalid form security token, please refresh the page.'] = 'Token di sicurezza invalido, aggiorna la pagina.';
|
$a->strings['Invalid form security token, please refresh the page.'] = 'Token di sicurezza invalido, aggiorna la pagina.';
|
||||||
$a->strings['The rule name and expression are required.'] = 'Il nome e l\'espressione della regola sono richiesti.';
|
$a->strings['The rule name and expression are required.'] = 'Il nome e l\'espressione della regola sono richiesti.';
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Name: blockbot
|
* Name: blockbot
|
||||||
* Description: Blocking bots based on detecting bots/crawlers/spiders via the user agent and http_from header.
|
* Description: Blocking bots based on detecting bots/crawlers/spiders via the user agent and http_from header.
|
||||||
* Version: 1.0
|
* Version: 0.2
|
||||||
* Author: Philipp Holzer <admin@philipp.info>
|
* Author: Philipp Holzer <admin@philipp.info>
|
||||||
* Author: Michael Vogel <https://pirati.ca/profile/heluecht>
|
* Author: Michael Vogel <https://pirati.ca/profile/heluecht>
|
||||||
*
|
*
|
||||||
|
@ -13,10 +13,7 @@ use Friendica\DI;
|
||||||
use Jaybizzle\CrawlerDetect\CrawlerDetect;
|
use Jaybizzle\CrawlerDetect\CrawlerDetect;
|
||||||
use Friendica\Core\Logger;
|
use Friendica\Core\Logger;
|
||||||
use Friendica\Core\Renderer;
|
use Friendica\Core\Renderer;
|
||||||
use Friendica\Core\System;
|
|
||||||
use Friendica\Network\HTTPException\ForbiddenException;
|
use Friendica\Network\HTTPException\ForbiddenException;
|
||||||
use Friendica\Util\HTTPSignature;
|
|
||||||
use Friendica\Util\Network;
|
|
||||||
|
|
||||||
require_once __DIR__ . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
|
require_once __DIR__ . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
|
||||||
|
|
||||||
|
@ -31,812 +28,160 @@ function blockbot_addon_admin(string &$o)
|
||||||
|
|
||||||
$o = Renderer::replaceMacros($t, [
|
$o = Renderer::replaceMacros($t, [
|
||||||
'$submit' => DI::l10n()->t('Save Settings'),
|
'$submit' => DI::l10n()->t('Save Settings'),
|
||||||
'$security_checker' => ['security_checker', DI::l10n()->t('Allow security checkers'), DI::config()->get('blockbot', 'security_checker'), DI::l10n()->t("Don't block security checkers. They can be used for good or bad.")],
|
'$good_crawlers' => ['good_crawlers', DI::l10n()->t('Allow "good" crawlers'), DI::config()->get('blockbot', 'good_crawlers'), DI::l10n()->t("Don't block fediverse crawlers, relay servers and other bots with good purposes.")],
|
||||||
|
'$socialmedia_agents' => ['socialmedia_agents', DI::l10n()->t('Allow preview agents'), DI::config()->get('blockbot', 'socialmedia_agents'), DI::l10n()->t("Don't block agents from social media systems that want to generate preview data for links that had been set by their users.")],
|
||||||
'$http_libraries' => ['http_libraries', DI::l10n()->t('Allow generic HTTP libraries'), DI::config()->get('blockbot', 'http_libraries'), DI::l10n()->t("Don't block agents from generic HTTP libraries that could be used for good or for bad and that currently can't be traced back to any known Fediverse project.")],
|
'$http_libraries' => ['http_libraries', DI::l10n()->t('Allow generic HTTP libraries'), DI::config()->get('blockbot', 'http_libraries'), DI::l10n()->t("Don't block agents from generic HTTP libraries that could be used for good or for bad and that currently can't be traced back to any known Fediverse project.")],
|
||||||
|
'$block_gab' => ['block_gab', DI::l10n()->t('Block GabSocial'), DI::config()->get('blockbot', 'block_gab'), DI::l10n()->t('Block the software GabSocial. This will block every access for that software. You can block dedicated gab instances in the blocklist settings in the admin section.')],
|
||||||
'$training' => ['training', DI::l10n()->t('Training mode'), DI::config()->get('blockbot', 'training'), DI::l10n()->t("Activates the training mode. This is only meant for developing purposes. Don't activate this on a production machine. This can cut communication with some systems.")],
|
'$training' => ['training', DI::l10n()->t('Training mode'), DI::config()->get('blockbot', 'training'), DI::l10n()->t("Activates the training mode. This is only meant for developing purposes. Don't activate this on a production machine. This can cut communication with some systems.")],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function blockbot_addon_admin_post()
|
function blockbot_addon_admin_post()
|
||||||
{
|
{
|
||||||
DI::config()->set('blockbot', 'security_checker', $_POST['security_checker'] ?? false);
|
DI::config()->set('blockbot', 'good_crawlers', $_POST['good_crawlers'] ?? false);
|
||||||
|
DI::config()->set('blockbot', 'socialmedia_agents', $_POST['socialmedia_agents'] ?? false);
|
||||||
DI::config()->set('blockbot', 'http_libraries', $_POST['http_libraries'] ?? false);
|
DI::config()->set('blockbot', 'http_libraries', $_POST['http_libraries'] ?? false);
|
||||||
|
DI::config()->set('blockbot', 'block_gab', $_POST['block_gab'] ?? false);
|
||||||
DI::config()->set('blockbot', 'training', $_POST['training'] ?? false);
|
DI::config()->set('blockbot', 'training', $_POST['training'] ?? false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function blockbot_reject()
|
|
||||||
{
|
|
||||||
throw new ForbiddenException('Bots are not allowed. If you consider this a mistake, create an issue at https://github.com/friendica/friendica');
|
|
||||||
}
|
|
||||||
|
|
||||||
function blockbot_init_1()
|
function blockbot_init_1()
|
||||||
{
|
{
|
||||||
if (empty($_SERVER['HTTP_USER_AGENT'])) {
|
if (empty($_SERVER['HTTP_USER_AGENT'])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$crawlerDetect = new CrawlerDetect();
|
$logdata = ['agent' => $_SERVER['HTTP_USER_AGENT'], 'uri' => $_SERVER['REQUEST_URI']];
|
||||||
|
|
||||||
$isCrawler = $crawlerDetect->isCrawler();
|
// List of known unwanted crawlers.
|
||||||
|
$agents = [
|
||||||
|
'SemrushBot', 's~feedly-nikon3', 'Qwantify/Bleriot/', 'ltx71', 'Sogou web spider/',
|
||||||
|
'Diffbot/', 'YisouSpider', 'evc-batch/', 'LivelapBot/', 'TrendsmapResolver/',
|
||||||
|
'PaperLiBot/', 'Nuzzel', 'um-LN/', 'Google Favicon', 'Datanyze', 'BLEXBot/', '360Spider',
|
||||||
|
'adscanner/', 'HeadlessChrome', 'wpif', 'startmebot/', 'Googlebot/', 'Applebot/',
|
||||||
|
'GoogleImageProxy', 'bingbot/', 'heritrix/', 'ldspider',
|
||||||
|
'AwarioRssBot/', 'TweetmemeBot/', 'dcrawl/', 'PhantomJS/', 'Googlebot-Image/',
|
||||||
|
'CrowdTanglebot/', 'Mediapartners-Google', 'Baiduspider', 'datagnionbot',
|
||||||
|
'MegaIndex.ru/', 'SMUrlExpander', 'Hatena-Favicon/', 'Wappalyzer', 'FlipboardProxy/',
|
||||||
|
'NetcraftSurveyAgent/', 'Dataprovider.com', 'SMTBot/', 'Nimbostratus-Bot/',
|
||||||
|
'DuckDuckGo-Favicons-Bot/', 'IndieWebCards/', 'proximic', 'netEstate NE Crawler',
|
||||||
|
'AhrefsBot/', 'YandexBot/', 'Exabot/', 'Mediumbot-MetaTagFetcher/',
|
||||||
|
'SurdotlyBot/', 'BingPreview/', 'SabsimBot/', 'CCBot/', 'WbSrch/',
|
||||||
|
'DuckDuckBot-Https/', 'HTTP Banner Detection', 'YandexImages/', 'archive.org_bot',
|
||||||
|
'ArchiveTeam ArchiveBot/', 'yacybot', 'https://developers.google.com/+/web/snippet/',
|
||||||
|
'Scrapy/', 'MJ12bot/', 'DotBot/', 'Pinterestbot/', 'Jooblebot/',
|
||||||
|
'Cliqzbot/', 'YaK/', 'Mediatoolkitbot', 'Snacktory', 'FunWebProducts', 'oBot/',
|
||||||
|
'7Siters/', 'KOCMOHABT', 'Google-SearchByImage', 'FemtosearchBot/',
|
||||||
|
'HubSpot Crawler', 'DomainStatsBot/', 'Re-re Studio', 'AwarioSmartBot/',
|
||||||
|
'DNSResearchBot/', 'PetalBot;', 'Nmap Scripting Engine;',
|
||||||
|
'Google-Apps-Script; beanserver;', 'woorankreview/', 'Seekport Crawler;', 'AHC/',
|
||||||
|
'Semanticbot/', 'XoviOnpageCrawler;', 'Pinterest/',
|
||||||
|
'GetHPinfo.com-Bot/', 'BoardReader Favicon Fetcher', 'Google-Adwords-Instant', 'newspaper/',
|
||||||
|
'YurichevBot/', 'Crawling at Home Project', 'InfoTigerBot/', 'AdIdxBot/',
|
||||||
|
'MicrosoftPreview/', 'masscan/', 'Timpibot/', 'everyfeed-spider/', 'AndroidDownloadManager/',
|
||||||
|
'WebZIP/', 'WDG_Validator/', 'Screaming Frog SEO Spider/', ' Bytespider;', 'ISSCyberRiskCrawler/',
|
||||||
|
'BitSightBot/', 'ev-crawler/', 'CensysInspect/1.1', 'Protopage/', 'Gaisbot/', 'WellKnownBot/',
|
||||||
|
'SuperBot/', 'Googlebot-Mobile/', 'GPTBot/', 'GenomeCrawlerd/', '2ip bot/', 'Ocarinabot',
|
||||||
|
'Yahoo! Slurp;', 'AdsBot-Google', 'Gregarius/', 'FAST-WebCrawler/', 'Xenu Link Sleuth/',
|
||||||
|
'Ask Jeeves', 'alexa site audit/', 'Yahoo! Slurp China;', 'Microsoft URL Control',
|
||||||
|
'Facebot', 'Googlebot-Video/', 'msnbot/', 'Offline Explorer/', 'YandexNews/', 'msnbot-media/',
|
||||||
|
'EmailWolf', 'Download Demon/', 'FeedFetcher-Google;', 'WebCopier', '+ONB_Bot_Btrix',
|
||||||
|
'scoopit-crawler/', 'ia_archiver', 'Quora-Bot/', 'WebwikiBot/', 'FullStoryBot/',
|
||||||
|
'wpbot/', 'SearchExpress', 'DuckDuckBot/', 'Google Web Preview',
|
||||||
|
];
|
||||||
|
|
||||||
blockbot_save('all-agents', $_SERVER['HTTP_USER_AGENT']);
|
if (DI::config()->get('blockbot', 'block_gab')) {
|
||||||
|
$agents[] = 'GabSocial/';
|
||||||
$parts = blockbot_get_parts($_SERVER['HTTP_USER_AGENT']);
|
|
||||||
|
|
||||||
$logdata = ['isCrawler' => $isCrawler, 'agent' => $_SERVER['HTTP_USER_AGENT'], 'method' => $_SERVER['REQUEST_METHOD'], 'uri' => $_SERVER['REQUEST_URI'], 'parts' => $parts];
|
|
||||||
|
|
||||||
if ($isCrawler) {
|
|
||||||
blockbot_check_login_attempt($_SERVER['REQUEST_URI'], $logdata);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($parts)) {
|
// List of "good" crawlers, mostly from the fediverse.
|
||||||
Logger::debug('Known frontend found - accept', $logdata);
|
$good_agents = [
|
||||||
if ($isCrawler) {
|
'fediverse.space crawler', 'fediverse.network crawler', 'Active_Pods_CheckBot_3.0',
|
||||||
blockbot_save('badly-parsed-agents', $_SERVER['HTTP_USER_AGENT']);
|
'Social-Relay/', 'Test Certificate Info', 'Uptimebot/', 'GNUSocialBot', 'UptimeRobot/',
|
||||||
}
|
'PTST/', 'Zabbix', 'Poduptime/', 'FediFetcher', 'lemmy-stats-crawler',
|
||||||
|
'FedditLemmyverseCrawler/', 'lemmy-explorer-crawler/', 'URIports Validator',
|
||||||
|
'rss-is-dead.lol web bot;', 'fedistatsCrawler/', 'W3C_CSS_Validator_JFouffa/',
|
||||||
|
'IABot/', 'Slackbot 1', 'BeeperBot/', 'Matrix-Media-Repo/', 'P3P Validator',
|
||||||
|
'KeybaseBot;',
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!DI::config()->get('blockbot', 'good_crawlers')) {
|
||||||
|
$agents = array_merge($agents, $good_agents);
|
||||||
|
} elseif (blockbot_match($good_agents)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
blockbot_log_activitypub($_SERVER['REQUEST_URI'], $_SERVER['HTTP_USER_AGENT']);
|
// List of agents from social media systems that fetch preview data via opem graph or twitter cards.
|
||||||
|
$socialmedia_agents = ['Twitterbot', 'facebookexternalhit/', 'SkypeUriPreview Preview/',
|
||||||
|
'TelegramBot', 'WhatsApp/', 'github-camo', 'Bluesky Cardyb/', 'XING-contenttabreceiver/',
|
||||||
|
'LinkedInBot/', 'Instagram ', 'Synapse (bot; ', 'Discordbot/', 'SummalyBot/',
|
||||||
|
'Slackbot-LinkExpanding', 'Slack-ImgProxy', 'Iframely/',
|
||||||
|
];
|
||||||
|
|
||||||
if (blockbot_is_crawler($parts)) {
|
if (!DI::config()->get('blockbot', 'socialmedia_agents')) {
|
||||||
Logger::debug('Crawler found - reject', $logdata);
|
$agents = array_merge($agents, $socialmedia_agents);
|
||||||
blockbot_reject();
|
} elseif (blockbot_match($socialmedia_agents)) {
|
||||||
}
|
|
||||||
|
|
||||||
if (blockbot_is_searchbot($parts)) {
|
|
||||||
Logger::debug('Search bot found - reject', $logdata);
|
|
||||||
blockbot_reject();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (blockbot_is_unwanted($parts)) {
|
|
||||||
Logger::debug('Uncategorized unwanted agent found - reject', $logdata);
|
|
||||||
blockbot_reject();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (blockbot_is_security_checker($parts)) {
|
|
||||||
if (!DI::config()->get('blockbot', 'security_checker')) {
|
|
||||||
Logger::debug('Security checker found - reject', $logdata);
|
|
||||||
blockbot_reject();
|
|
||||||
}
|
|
||||||
Logger::debug('Security checker found - accept', $logdata);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blockbot_is_social_media($parts)) {
|
// HTTP Libraries
|
||||||
Logger::debug('Social media service found - accept', $logdata);
|
$http_libraries = ['ReactorNetty/', 'GuzzleHttp/', 'Embed PHP library', 'python-urllib3/',
|
||||||
return;
|
'EventMachine HttpClient', 'HTMLParser/'
|
||||||
}
|
];
|
||||||
|
|
||||||
if (blockbot_is_fediverse_client($parts)) {
|
|
||||||
Logger::debug('Fediverse client found - accept', $logdata);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (blockbot_is_feed_reader($parts)) {
|
|
||||||
Logger::debug('Feed reader found - accept', $logdata);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (blockbot_is_fediverse_tool($parts)) {
|
|
||||||
Logger::debug('Fediverse tool found - accept', $logdata);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (blockbot_is_service_agent($parts)) {
|
|
||||||
Logger::debug('Service agent found - accept', $logdata);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (blockbot_is_monitor($parts)) {
|
|
||||||
Logger::debug('Monitoring service found - accept', $logdata);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (blockbot_is_validator($parts)) {
|
|
||||||
Logger::debug('Validation service found - accept', $logdata);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (blockbot_is_good_tool($parts)) {
|
|
||||||
Logger::debug('Uncategorized helpful service found - accept', $logdata);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Needs to be checked at the end, since other services might use these libraries
|
|
||||||
if (blockbot_is_http_library($parts)) {
|
|
||||||
blockbot_check_login_attempt($_SERVER['REQUEST_URI'], $logdata);
|
|
||||||
if (!DI::config()->get('blockbot', 'http_libraries')) {
|
if (!DI::config()->get('blockbot', 'http_libraries')) {
|
||||||
Logger::debug('HTTP Library found - reject', $logdata);
|
$agents = array_merge($agents, $http_libraries);
|
||||||
blockbot_reject();
|
} elseif (blockbot_match($http_libraries)) {
|
||||||
}
|
|
||||||
Logger::debug('HTTP Library found - accept', $logdata);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (blockbot_match($agents)) {
|
||||||
|
throw new ForbiddenException('Bots are not allowed. If you consider this a mistake, create an issue at https://github.com/friendica/friendica');
|
||||||
|
}
|
||||||
|
|
||||||
// This switch here is only meant for developers who want to add more bots to the list above, it is not safe for production.
|
// This switch here is only meant for developers who want to add more bots to the list above, it is not safe for production.
|
||||||
if (!DI::config()->get('blockbot', 'training')) {
|
if (!DI::config()->get('blockbot', 'training')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$isCrawler) {
|
$crawlerDetect = new CrawlerDetect();
|
||||||
blockbot_save('good-agents', $_SERVER['HTTP_USER_AGENT']);
|
|
||||||
Logger::debug('Non-bot user agent detected', $logdata);
|
if (!$crawlerDetect->isCrawler()) {
|
||||||
|
logger::debug('Good user agent detected', $logdata);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
blockbot_save('bad-agents', $_SERVER['HTTP_USER_AGENT']);
|
// List of known "good" agents, mostly used by Fediverse systems, feed readers, ...
|
||||||
Logger::notice('Possible bot found - reject', $logdata);
|
$agents = [
|
||||||
blockbot_reject();
|
'curl', 'zgrab', 'Go-http-client', 'curb', 'github.com', 'reqwest', 'Feedly/',
|
||||||
}
|
'Python-urllib/', 'Liferea/', 'aiohttp/', 'WordPress.com Reader', 'hackney/',
|
||||||
|
'Faraday v', 'okhttp', 'UniversalFeedParser', 'PixelFedBot', 'python-requests',
|
||||||
|
'WordPress/', 'http.rb/', 'Apache-HttpClient/', 'WordPress.com;', 'Pleroma',
|
||||||
|
'Dispatch/', 'Ruby', 'Java/', 'libwww-perl/', 'Mastodon/', 'FeedlyApp/',
|
||||||
|
'lua-resty-http/', 'Tiny Tiny RSS/', 'Wget/', 'PostmanRuntime/',
|
||||||
|
'W3C_Validator/', 'NetNewsWire', 'FeedValidator/', 'theoldreader.com', 'axios/',
|
||||||
|
'Paw/', 'PeerTube/', 'fedi.inex.dev', 'FediDB/', 'index.community crawler',
|
||||||
|
'Slackbot-LinkExpanding', 'Firefish/', 'Takahe/', 'Akkoma ', 'Misskey/', 'Lynx/',
|
||||||
|
'camo-rs asset proxy', 'gotosocial/', 'incestoma ', 'SpaceCowboys Android RSS Reader',
|
||||||
|
'NewsBlur Feed Finder', 'Lemmy/', 'enby-town/', 'rss2tg bot;', '; HTTrack ',
|
||||||
|
'MbinBot', 'kbinBot', 'Pixelfed/', 'NewsBlur Feed Fetcher', 'NewsBlur Page Fetcher',
|
||||||
|
];
|
||||||
|
|
||||||
function blockbot_save($database, $userAgent)
|
if (blockbot_match($agents)) {
|
||||||
{
|
logger::info('False positive', $logdata);
|
||||||
if (!DI::config()->get('blockbot', 'logging') || !function_exists('dba_open')) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$resource = dba_open(System::getTempPath() . '/' . $database, 'cl');
|
logger::notice('Blocked bot', $logdata);
|
||||||
$result = dba_fetch($userAgent, $resource);
|
throw new ForbiddenException('Bots are not allowed. If you consider this a mistake, create an issue at https://github.com/friendica/friendica');
|
||||||
if ($result === false) {
|
|
||||||
dba_insert($userAgent, true, $resource);
|
|
||||||
}
|
|
||||||
dba_close($resource);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function blockbot_log_activitypub(string $url, string $agent)
|
function blockbot_match(array $agents)
|
||||||
{
|
{
|
||||||
if (!DI::config()->get('blockbot', 'logging')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$bot = ['/.well-known/nodeinfo', '/nodeinfo/2.0', '/nodeinfo/1.0'];
|
|
||||||
if (in_array($url, $bot)) {
|
|
||||||
blockbot_save('activitypub-stats', $agent);
|
|
||||||
}
|
|
||||||
|
|
||||||
$bot = ['/api/v1/instance', '/api/v2/instance', '/api/v1/instance/extended_description',
|
|
||||||
'/api/v1/instance/peers'];
|
|
||||||
if (in_array($url, $bot)) {
|
|
||||||
blockbot_save('activitypub-api-stats', $agent);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (substr($url, 0, 6) == '/api/v') {
|
|
||||||
blockbot_save('activitypub-api', $agent);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (($_SERVER['REQUEST_METHOD'] == 'POST') && in_array('inbox', explode('/', parse_url($url, PHP_URL_PATH)))) {
|
|
||||||
blockbot_save('activitypub-inbox-agents', $agent);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($_SERVER['HTTP_SIGNATURE']) && !empty(HTTPSignature::getSigner('', $_SERVER))) {
|
|
||||||
blockbot_save('activitypub-signature-agents', $agent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function blockbot_check_login_attempt(string $url, array $logdata)
|
|
||||||
{
|
|
||||||
if (in_array(trim(parse_url($url, PHP_URL_PATH), '/'), ['login', 'lostpass', 'register'])) {
|
|
||||||
Logger::debug('Login attempt detected - reject', $logdata);
|
|
||||||
blockbot_reject();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uncategorized and unwanted services
|
|
||||||
*
|
|
||||||
* @param array $parts
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
function blockbot_is_unwanted(array $parts): bool
|
|
||||||
{
|
|
||||||
$agents = [
|
|
||||||
'oii-research', 'yisouspider', 'bots.retroverse.social', 'gaisbot', 'bloglines', 'emailwolf',
|
|
||||||
'webtech', 'facebookscraper', 'www.ecsl.cs.sunysb.edu/~maxim/cgi-bin/link',
|
|
||||||
'gulper', 'magellan', 'linkcheck', 'nerdybot', 'ms search robot', 'fast-webcrawler',
|
|
||||||
'yioopbot', 'webster', 'www.admantx.com', 'openhosebot', 'lssrocketcrawler', 'dow jones searchbot',
|
|
||||||
'gomezagent', 'domainsigmacrawler', 'netseer crawler', 'superbot', 'searchexpress',
|
|
||||||
'alittle client', 'amazon-kendra', 'scanner.ducks.party', 'isscyberriskcrawler',
|
|
||||||
'google wireless transcoder',
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($parts as $part) {
|
|
||||||
if (in_array($part, $agents)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Services defined as "crawlers"
|
|
||||||
*
|
|
||||||
* @param array $parts
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
function blockbot_is_crawler(array $parts): bool
|
|
||||||
{
|
|
||||||
$agents = [
|
|
||||||
'+http://yourls.org', 'adbeat.com/policy', 'https://gtmetrix.com', 'hubspot', 'nutch-',
|
|
||||||
'openwebspider'
|
|
||||||
];
|
|
||||||
foreach ($parts as $part) {
|
|
||||||
foreach ($agents as $agent) {
|
foreach ($agents as $agent) {
|
||||||
if (strpos($part, $agent) !== false) {
|
if (stristr($_SERVER['HTTP_USER_AGENT'], $agent)) {
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$agents = [
|
|
||||||
'ahrefsbot', 'pinterest', 'proximic', 'applebot', 'synapseworkstation.3.2.1',
|
|
||||||
'slackbot-linkexpanding', 'semrushbot-sa', 'qwantify', 'google search console',
|
|
||||||
'tbot-nutch', 'screaming frog seo spider', 'exaleadcloudview', 'dotbot', 'exabot',
|
|
||||||
'spbot', 'surdotlybot', 'tweetmemebot', 'cliqzbot', 'startmebot', 'ccbot', 'zoombot',
|
|
||||||
'domain re-animator bot', 'nutch', 'archive.org_bot http://www.archive.org/details',
|
|
||||||
'yahoo link preview', 'mxt', 'grapeshotcrawler', 'maxpointcrawler', 'vagabondo',
|
|
||||||
'archive.org_bot', 'infegyatlas', '2ip bot', 'accompanybot', 'antbot', 'anthropic-ai',
|
|
||||||
'aspiegelbot', 'cispa web analyzer', 'claudebot', 'colly', 'petalbot', 'ioncrawl',
|
|
||||||
'embedly +support@embed.ly', 'gitcrawlerbot', 'google favicon', 'httpx', 'seokicks',
|
|
||||||
'kocmohabt', 'masscan-ng', 'mixnodecache', 'nicecrawler', 'birdcrawlerbot', 'seolyt',
|
|
||||||
'dataprovider.com', 'dnsresearchbot', 'domains project', 'evc-batch', 'ev-crawler',
|
|
||||||
'example3', 'geedobot', 'internetmeasurement', 'ips-agent', 'semanticscholarbot',
|
|
||||||
'sputnikfaviconbot', 't3versionsbot', 'tchelebi', 'thinkchaos', 'velenpublicwebcrawler',
|
|
||||||
'webwikibot', 'woobot', 'project-resonance', 'mtrobot', 'webprosbot', 'youbot',
|
|
||||||
'queryseekerspider', 'scanning for research', 'semrushbot', 'senutobot', 'spawning-ai',
|
|
||||||
'statista.com publication finder crawler', 'turnitin', 'who.is bot', 'zaldamosearchbot',
|
|
||||||
'nuzzel', 'boardreader blog indexer', 'hatena-favicon', 'nbertaupete95', 'scrapy',
|
|
||||||
"electronic frontier foundation's do not track verifier", 'synapse', 'trendsmapresolver',
|
|
||||||
'pinterestbot', 'um-ln', 'slack-imgproxy', 'diffbot', 'dataforseobot', 'bw', 'bitlybot',
|
|
||||||
'twingly recon-klondike', 'imagesiftbot', 'rogerbot', 'yahoocachesystem', 'favicon',
|
|
||||||
'vkshare', 'appid: s~virustotalcloud', 'clickagy intelligence bot v2', 'gptbot',
|
|
||||||
'archive.org_bot http://archive.org/details', 'wellknownbot', 'archiveteam archivebot',
|
|
||||||
'megaindex.ru', 'adbeat_bot', 'masscan', 'embedly', 'cloudflare-amp', 'exabot-thumbnails',
|
|
||||||
'yahoo ad monitoring', 'seokicks-robot', 'trendiction search', 'semrushbot-si', 'plukkie',
|
|
||||||
'hubpages v0.2.2', 'aream.bot', 'safednsbot', 'linkpadbot', 'gluten free crawler',
|
|
||||||
'turnitinbot', 'xovibot', 'domaincrawler', 'nettrack', 'domaincrawler', 'yak', 'bubing',
|
|
||||||
'netestate ne crawler', 'blexbot', 'the knowledge ai', 'optimizer', 'hubspot webcrawler',
|
|
||||||
'venuscrawler', 'adstxtcrawler', 'iframely', 'checkmarknetwork', 'semrushbot-ba',
|
|
||||||
'archive.org bot', 'aihitbot', 'sitesucker', 'adstxtlab.com crawler', 'jobboersebot',
|
|
||||||
'http://www.archive.org/details/archive.org_bot', 'heritrix', 'appid: s~snapchat-proxy',
|
|
||||||
'icc-crawler', 'mbcrawler', 'slackbot', 'trumind-crawler', 'newspaper', 'online-webceo-bot',
|
|
||||||
'haena-pepper', 'y! crawler', 'linkwalker', 'seznamemailproxy', 'seekport crawler',
|
|
||||||
'domainstatsbot', 'qwantify/mermoz', 'sprinklr', 'komodiabot', 'seoscanners.net',
|
|
||||||
'domainappender', 'mixrankbot', 'abonti', 'urlappendbot', 'sistrix crawler',
|
|
||||||
'hatenabookmark', 'metainspector', 'ezooms', 'quora link preview', 'semrushbot-bm',
|
|
||||||
'barkrowler', 'panscient.com', 'http://tweetedtimes.com', 'twingly recon',
|
|
||||||
'collection@infegy.com', 'mediatoolkitbot', 'cloudflare-amphtml', 'ramblermail',
|
|
||||||
'tineye', 'adscanner', 'datagnionbot', 'aa_crawler', 'http://www.profound.net/domainappender',
|
|
||||||
'appid: e~arsnova-filter-system', 'kinglandsystemscorp', 'crmnlcrawlagent', 'techfetch-bot',
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($parts as $part) {
|
|
||||||
if (substr($part, -13) == ' accompanybot') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (in_array($part, $agents)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Services defined as search bots
|
|
||||||
*
|
|
||||||
* @param array $parts
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
function blockbot_is_searchbot(array $parts): bool
|
|
||||||
{
|
|
||||||
$agents = ['baiduspider'];
|
|
||||||
foreach ($parts as $part) {
|
|
||||||
foreach ($agents as $agent) {
|
|
||||||
if (strpos($part, $agent) !== false) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$agents = [
|
|
||||||
'yahoo! slurp', 'linkcheck by siteimprove.com', 'googlebot', '360spider', 'haosouspider',
|
|
||||||
'mj12bot', 'feedfetcher-google', 'mediapartners-google', 'duckduckgo-favicons-bot',
|
|
||||||
'googlebot-mobile', 'gigablastopensource', 'bingbot', 'surveybot', 'yandexbot',
|
|
||||||
'google web preview', 'meanpathbot', 'wesee_bot:we_help_monitize_your_site',
|
|
||||||
'seznambot', 'sogou web spider', 'linkdexbot', 'msnbot', 'smtbot', 'yandexmetrika',
|
|
||||||
'google-site-verification', 'netcraft ssl server survey - contact info@netcraft.com',
|
|
||||||
'orangebot', 'google-adwords-instant', 'googlebot-richsnippets', 'google-lens',
|
|
||||||
'googleother', 'google-test', 'linkdex.com', 'mail.ru', 'awariobot', 'bytespider',
|
|
||||||
'coccocbot-image', 'discobot', 'google-inspectiontool', 'netcraftsurveyagent',
|
|
||||||
'tineye-bot', 'tineye-bot-live', 'bingpreview', 'ask jeeves', 'adsbot-google', "msnbot-media ",
|
|
||||||
'googlebot-image', 'googlebot-news', 'googlebot-video', 'msnbot-media', 'yahoo! slurp china',
|
|
||||||
'inoreader.com-like feedfetcher-google', 'google-amphtml', 'duckduckbot', 'coccocbot-web',
|
|
||||||
'googleassociationservice', 'yandexwebmaster', 'yacybot', 'duckduckbot-https', 'yandexmobilebot',
|
|
||||||
'mail.ru_bot/fast', 'yandeximages', 'mail.ru_bot/img', 'ia_archiver', 'yandexblogs',
|
|
||||||
'yandexaccessibilitybot', 'yandeximageresizer', 'mail.ru_bot', 'yeti', 'obot', 'baiduspider-render',
|
|
||||||
'netcraft web server survey', 'yandexnews', 'google', 'yandexrenderresourcesbot',
|
|
||||||
'match by siteimprove.com', 'yandexsitelinks', 'yandexantivirus', 'daum', 'mail.ru_bot/robots',
|
|
||||||
'yandexmedia', 'msnbot-products', 'yandexvideo', 'yandexvertis', 'catexplorador', 'yandexcalendar',
|
|
||||||
'yandexfavicons', 'user-agent\x09baiduspider', 'baiduspider-image', 'yandexpagechecker', 'mojeekbot',
|
|
||||||
'adsbot-google-mobile', 'google-adwords-displayads-webrender', 'seznam screenshot-generator',
|
|
||||||
'yandexscreenshotbot', 'zumbot', 'tracemyfile', 'wotbox', 'google-adwords-express',
|
|
||||||
'google-adwords-displayads', 'google-youtube-links', 'yandexvideoparser', 'paperlibot',
|
|
||||||
'weborama-fetcher', 'googleproducer', 'coccoc', 'acoonbot', 'psbot', 'sosospider', 'voilabot',
|
|
||||||
'blekkobot', 'easouspider', 'omgili', 'yadirectfetcher', 'sogou pic spider', 'daumoa',
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($parts as $part) {
|
|
||||||
if (in_array($part, $agents)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Services in the "security" context
|
|
||||||
*
|
|
||||||
* @param array $parts
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
function blockbot_is_security_checker(array $parts): bool
|
|
||||||
{
|
|
||||||
$agents = [
|
|
||||||
'http banner detection', 'l9explore', 'l9tcpid', 'lkx-apache2449traversalplugin',
|
|
||||||
'bitsightbot', 'censysinspect', 'pathspider', 'repolookoutbot', 'sqlmap', 'ltx71',
|
|
||||||
'netsystemsresearch studies the availability of various services across the internet. our website is netsystemsresearch.com',
|
|
||||||
'expanse a palo alto networks company searches across the global ipv4 space multiple times per day to identify customers'',
|
|
||||||
'zgrab', 'nmap scripting engine', 'l9scan', 'riddler', 'cloud mapping experiment. contact research@pdrlabs.net',
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($parts as $part) {
|
|
||||||
if (in_array($part, $agents)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Services that check pages for e.g. valid HTML
|
|
||||||
*
|
|
||||||
* @param array $parts
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
function blockbot_is_validator(array $parts): bool
|
|
||||||
{
|
|
||||||
$agents = [
|
|
||||||
'jigsaw', 'ssl labs', 'w3c_validator', 'w3c-checklink', 'p3p validator', 'csscheck', 'validator.nu',
|
|
||||||
'google-structured-data-testing-tool https://search.google.com/structured-data', 'w3c_unicorn',
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($parts as $part) {
|
|
||||||
if (in_array($part, $agents)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Services that monitor a page
|
|
||||||
*
|
|
||||||
* @param array $parts
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
function blockbot_is_monitor(array $parts): bool
|
|
||||||
{
|
|
||||||
$agents = [
|
|
||||||
'alexa site audit', 'catchpoint', 'google page speed insights', 'checkhost',
|
|
||||||
'poduptime', 'chrome-lighthouse', 'zabbix', 'cloudflare-alwaysonline', 'ptst',
|
|
||||||
'pingadmin.ru', 'pingdomtms', 'nimbostratus-bot', 'uptimebot', 'uptimerobot',
|
|
||||||
'http://notifyninja.com/monitoring', 'http://www.freewebmonitoring.com',
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($parts as $part) {
|
|
||||||
if (in_array($part, $agents)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Services in the centralized and decentralized social media environment
|
|
||||||
*
|
|
||||||
* @param array $parts
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
function blockbot_is_social_media(array $parts): bool
|
|
||||||
{
|
|
||||||
$agents = ['camo-rs asset proxy', 'camo asset proxy'];
|
|
||||||
foreach ($parts as $part) {
|
|
||||||
foreach ($agents as $agent) {
|
|
||||||
if (strpos($part, $agent) !== false) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$agents = [
|
|
||||||
'facebookexternalhit', 'twitterbot', 'mastodon', 'facebookexternalua',
|
|
||||||
'friendica', 'diasporafederation', 'buzzrelay', 'activityrelay',
|
|
||||||
'aoderelay', 'ap-relay', 'peertube', 'misskey', 'pleroma', 'foundkey', 'akkoma',
|
|
||||||
'lemmy', 'calckey', 'mobilizon', 'zot', 'camo-rs', 'gotosocial', 'pixelfed',
|
|
||||||
'pixelfedbot', 'app.wafrn.net', 'go-camo', 'http://a.gup.pe', 'iceshrimp',
|
|
||||||
'firefish', 'activity-relay', 'juick', 'camo', 'python/federation', 'nextcloud',
|
|
||||||
'snac', 'bovine', 'takahe', 'freedica', 'gnu social', 'microblogpub',
|
|
||||||
'mbin', 'mammoth', 'kbinbot', 'honksnonk', 'misskeymediaproxy', 'kbinbot', 'jistflow',
|
|
||||||
'mastodon/3.4.1 fedibird', 'fedibird', 'funkwhale', 'linkedinbot',
|
|
||||||
'wafrn-cache-generator', 'simple social network', 'mbinbot', 'wordpress.com',
|
|
||||||
'catnip', 'castopod', 'enby-town', 'vernissage', 'iceshrimp.net', 'plasmatrap',
|
|
||||||
'imgproxy', 'rustypub', 'flipboard activitypub', 'gnu social activitypub plugin',
|
|
||||||
'micro.blog', 'mastodon-bookmark-rss', 'bookwyrm', 'damus', 'primal', 'misskeyadmin',
|
|
||||||
'ruby, mastodon', 'nextcloud social', 'camo asset proxy', 'smithereen', 'sorasns',
|
|
||||||
'cherrypick', 'bonfire activitypub federation', 'upub+0.1.0', 'plume', 'incestoma',
|
|
||||||
'gyptazyfedi', 'apogee', 'quolibet', 'magpie-crawler', 'redditbot', 'facebookplatform',
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($parts as $part) {
|
|
||||||
if (in_array($part, $agents)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fediverse clients
|
|
||||||
*
|
|
||||||
* @param array $parts
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
function blockbot_is_fediverse_client(array $parts): bool
|
|
||||||
{
|
|
||||||
$agents = [
|
|
||||||
'mastodonandroid', 'tootdeck-worker', 'piefed', 'brighteon', 'pachli', 'tusky', 'mona', 'mitra',
|
|
||||||
'megalodonandroid', 'fedilab', 'mastodonapp', 'toot!', 'intravnews',
|
|
||||||
'pixeldroid', 'greatnews', 'protopage', 'newsfox', 'vienna', 'wp-urldetails', 'husky',
|
|
||||||
'activitypub-go-http-client', 'mobilesafari', 'mastodon-ios', 'mastodonpy', 'techniverse',
|
|
||||||
'relatica',
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($parts as $part) {
|
|
||||||
if (in_array($part, $agents)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Feed reading clients and services
|
|
||||||
*
|
|
||||||
* @param array $parts
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
function blockbot_is_feed_reader(array $parts): bool
|
|
||||||
{
|
|
||||||
$agents = [
|
|
||||||
'tiny tiny rss', 'mlem', 'feedly', 'flipboardproxy', 'reeder', 'netnewswire',
|
|
||||||
'freshrss', 'feedlyapp', 'feedlybot', 'feeddemon', 'rssowl', 'simplepie',
|
|
||||||
'magpierss', 'universalfeedparser', 'newsgatoronline', 'theoldreader.com',
|
|
||||||
'quiterss', 'feedburner', 'digg feed fetcher', 'r6_feedfetcher', 'apple-pubsub',
|
|
||||||
'netvibes', 'newsblur page fetcher', 'newsblur favicon fetcher', 'newsblur favicon fetcher',
|
|
||||||
'liferea', 'http://www.jetbrains.com/omea_reader/', 'feedblitz', 'bloglovin',
|
|
||||||
'windows-rss-platform', 'feedshow', 'feedreader', 'rssbandit', 'everyfeed-spider',
|
|
||||||
'feeeed', 'spacecowboys android rss reader', 'gregarius', 'feedspot',
|
|
||||||
'feedspot ssl asset proxy', 'newsgator', 'newsgator fetchlinks extension',
|
|
||||||
'akregator', 'appid: s~feedly-nikon3',
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($parts as $part) {
|
|
||||||
if (in_array($part, $agents)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function blockbot_is_fediverse_tool(array $parts): bool
|
|
||||||
{
|
|
||||||
$agents = [
|
|
||||||
'diaspora-connection-tester', 'fediblock.manalejandro.com',
|
|
||||||
'mastodoninstances', 'fedilist agent', 'https://fedilist.com/', 'fedidb',
|
|
||||||
'https://wiki.communitydata.science/communitydata:fediverse_research', 'mastofeed.com',
|
|
||||||
'lemmy-explorer-crawler', 'fedicheck.online v1.0', 'momostr', 'fedditlemmyversecrawler',
|
|
||||||
'fediseer', 'fedistatscrawler', 'gnusocialbot', 'fedifetcher', 'fedineko', 'bird.makeup',
|
|
||||||
'fediverse', 'fedicheck.online', 'https://fed.brid.gy/', 'lemmy-stats-crawler',
|
|
||||||
"fediverse's stats", 'friendicadirectory', 'rss discovery engine',
|
|
||||||
'python-opengraph-jaywink', 'connect.rocks', 'tootsdk',
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
foreach ($parts as $part) {
|
|
||||||
if (in_array($part, $agents)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* General services
|
|
||||||
*
|
|
||||||
* @param array $parts
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
function blockbot_is_service_agent(array $parts): bool
|
|
||||||
{
|
|
||||||
$agents = ['wordpress.com'];
|
|
||||||
foreach ($parts as $part) {
|
|
||||||
foreach ($agents as $agent) {
|
|
||||||
if (strpos($part, $agent) !== false) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$agents = [
|
|
||||||
'chrome privacy preserving prefetch proxy', 'http compression test', 'microsoftpreview',
|
|
||||||
'pocketimagecache', 'wordpress', 'skypeuripreview preview', 'wordpress.com', 'discordbot',
|
|
||||||
'summalybot', 'livelapbot', 'whatsapp', 'facebot', 'skypeuripreview',
|
|
||||||
'plasmatrap image proxy server', 'grammarly', 'browsershots', 'google-apps-script',
|
|
||||||
'yahoomailproxy', 'pocketparser', 'apachebench',
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($parts as $part) {
|
|
||||||
if (in_array($part, $agents)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Libraries that perform HTTP requests
|
|
||||||
*
|
|
||||||
* @param array $parts
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
function blockbot_is_http_library(array $parts): bool
|
|
||||||
{
|
|
||||||
if ((count($parts) == 1) && in_array($parts[0], ['okhttp', 'useragent', 'faraday'])) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$agents = ['faraday '];
|
|
||||||
foreach ($parts as $part) {
|
|
||||||
foreach ($agents as $agent) {
|
|
||||||
if (strpos($part, $agent) !== false) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$agents = [
|
|
||||||
'python-urllib', 'go-http-client', 'axios', 'java', 'undici', 'node', 'ruby',
|
|
||||||
'mint', 'wget', 'dart:io', 'dart', 'caveman-sieve', 'guzzlehttp', 'deno',
|
|
||||||
'aiohttp', 'networkingextension', 'python-asks', 'fasthttp', 't7', 'scalaj-http',
|
|
||||||
'curl', 'python-requests', 'node-fetch', 'offline explorer', 'aria2',
|
|
||||||
'link_thumbnailer', 'python-httpx', 'com.apple.safari.searchhelper',
|
|
||||||
'com.apple.webkit.networking', 'luasocket', 'libwww-perl', 'google-http-java-client',
|
|
||||||
'appengine-google', 'reqwest', 'htmlparser', 'headlesschrome', 'winhttp',
|
|
||||||
'webcopier', 'webzip', 'http.jl', 'got', 'hackney', 'oca\mail\vendor\favicon',
|
|
||||||
'winhttp.winhttprequest.5', 'go package http', 'jakarta commons-httpclient',
|
|
||||||
'cpp-httplib', 'fuzz faster u fool v1.3.1-dev', 'fuzz faster u fool v1.5.0-dev',
|
|
||||||
'go http package', 'go-resty', 'http.rb', 'ivre-masscan', 'java1.0.21.0',
|
|
||||||
'jsdom', 'python-urllib3', 'reactornetty', 'req', 'restsharp', 'ruby-rdf-distiller',
|
|
||||||
'pycurl', 'fdm', 'fdmx', 'lua-resty-http', 'python-httplib2', 'anyevent-http',
|
|
||||||
'node-superagent', 'unirest-java', 'gvfs', 'http_request2', 'java browser', 'cakephp',
|
|
||||||
'curly http client', 'lavf', 'typhoeus',
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($parts as $part) {
|
|
||||||
if (in_array($part, $agents)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uncategorized helpful services
|
|
||||||
*
|
|
||||||
* @param array $parts
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
function blockbot_is_good_tool(array $parts): bool
|
|
||||||
{
|
|
||||||
$agents = [
|
|
||||||
'easy-feed-oven', 'cutycapt', 'rss-is-dead.lol web bot', 'dnt-policy@eff.org',
|
|
||||||
'https://socnetv.org', 'opengraphreader', 'trendfetcher', 'iabot', 'rss-is-dead.lol feed bot',
|
|
||||||
'androiddownloadmanager', 'readybot.io', 'hydra', 'httrack', 'vlc', 'wdg_validator', 'download demon',
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
foreach ($parts as $part) {
|
|
||||||
if (in_array($part, $agents)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function blockbot_get_parts(string $agent): array
|
|
||||||
{
|
|
||||||
$parts = [];
|
|
||||||
$level = 0;
|
|
||||||
$start = 0;
|
|
||||||
$end = 0;
|
|
||||||
$has_brackets = false;
|
|
||||||
for ($pos = 0; $pos < strlen($agent); $pos++) {
|
|
||||||
if ((strpos(substr($agent, $pos), '(') === false) && ($level == 0)) {
|
|
||||||
$part = substr($agent, $pos);
|
|
||||||
$parts = array_merge($parts, blockbot_split_parts($part, strpos($part, '/'), !$has_brackets));
|
|
||||||
break;
|
|
||||||
} elseif (substr($agent, $pos, 1) == '(') {
|
|
||||||
$level++;
|
|
||||||
$has_brackets = true;
|
|
||||||
if ($level == 1) {
|
|
||||||
$part = substr($agent, $end, $pos - $end);
|
|
||||||
$parts = array_merge($parts, blockbot_split_parts($part, $start != 0, false));
|
|
||||||
$start = $pos + 1;
|
|
||||||
}
|
|
||||||
} elseif (substr($agent, $pos, 1) == ')') {
|
|
||||||
$level--;
|
|
||||||
if ($level == 0) {
|
|
||||||
$part = substr($agent, $start, $pos - $start);
|
|
||||||
$parts = array_merge($parts, blockbot_split_parts($part, false, true));
|
|
||||||
$end = $pos + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return blockbot_remove_browser_parts($parts);
|
|
||||||
}
|
|
||||||
|
|
||||||
function blockbot_remove_browser_parts(array $parts): array
|
|
||||||
{
|
|
||||||
$cleaned = [];
|
|
||||||
foreach ($parts as $part) {
|
|
||||||
if (substr($part, -6) == ' build') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$known = [
|
|
||||||
'mozilla', 'x11', 'ubuntu', 'linux x86_64', 'gecko', 'firefox', 'windows nt',
|
|
||||||
'win64', 'x64', 'android', 'applewebkit', 'khtml', 'like', 'chrome', 'safari', 'edg',
|
|
||||||
'unsupported', 'compatible', 'macintosh', 'intel mac os x', 'version', 'windows',
|
|
||||||
'u', 'en-us', '.net', '.net', 'wow64', 'linux', 'k', 'mobile', 'opr', 'msie',
|
|
||||||
'dalvik', 'build', 'nt', 'mobile safari', 'gecko/firefox', 'zh-cn', 'en-gb', 'clr',
|
|
||||||
'trident', '.net clr', 'qtwebengine', 'linux i686', 'tablet pc', 'ppc mac os x',
|
|
||||||
'en', 'fedora', 'ppc', 'edge', 'yabrowser', 'yowser', 'media center pc', 'arm_64',
|
|
||||||
'android 9', 'cros x86_64', 'iphone', 'cpu iphone os like mac os x', 'core',
|
|
||||||
'qqbrowser', 'beta', 'khtml like gecko', 'psp (playstation portable)', 'ia64',
|
|
||||||
'firephp', 'live', 'slcc2', 'infopath.2', 'bidubrowser', 'ubrowser', 'baiduboxapp',
|
|
||||||
'waterfox', 'lynx', 'libwww-fm', 'ssl-mm', 'openssl', 'gnutls', '.net4.0c', '.net4.0e',
|
|
||||||
'infopath.3', 'opera', 'palemoon', 'goanna', 'vivaldi', 'presto', 'intrepid', 'ru',
|
|
||||||
'ipad', 'cpu os like mac os x', 'omniweb', 'chromium', 'thunderbird', 'ubuntu lts',
|
|
||||||
'os', 'qupzilla', 'seamonkey', 'warp', 'konqueror', 'meego', 'nokian9', 'nokiabrowser',
|
|
||||||
'profile', 'configuration', 'untrusted', 'samsungbrowser', 'es-us', 'pocophone f1',
|
|
||||||
'sonyericssonw995', 'crios', 'lbbrowser', 'gwx:qualified', 'gwx:red', 'gwx:reserved',
|
|
||||||
'microsoft outlook', 'word', 'microsoft', 'office', 'powerpoint', 'excel',
|
|
||||||
'internet explorer', 'like gecko', 'shuame', 'qianniu', 'khtml, like gecko',
|
|
||||||
'cutycapt version', 'khtml, live gecko', '68k', 'sv1', 'aef', 'gtb7.5', 'gfe',
|
|
||||||
'embedded web browser from: http://bsalsa.com', 'wv', 'malnjs', '2.00',
|
|
||||||
'fsl', 'lcjb', 'malcjs', 'touch', 'masmjs', 'malc', 'maln', 'foxy', 'bri', 'lcte',
|
|
||||||
'embeddedwb from: http://www.bsalsa.com', '2345explorer', 'hpntdfjs', 'h4213',
|
|
||||||
'rb.gy', 'sm-a505fn', 'lenovo tb-8504x', 'silk', 'lya-al00', 'windows xp', 'openbsd',
|
|
||||||
'netbsd amd64', 'sa', 'samsung sm-g950f', 'redmi note', 'hry-lx1', 'cph2205',
|
|
||||||
'16th', 'redmi note pro', 'xiaomi/miuibrowser', 'sk-sk', 'linux i686 on x86_64',
|
|
||||||
'debian iceweasel', 'rmx2101', 'mi note pro', 'rmx1921', 'nokia6100', '04.01',
|
|
||||||
'fr-fr', 'slackware', 'sm-a225f', 'fennec', 'links', 'i386', 'windows phone os',
|
|
||||||
'blackberry', 'maxthon', 'opera mini', 'j2me', 'winnt4.0', 'phoenix', 'avant browser',
|
|
||||||
'iceweasel', 'moto e(7) plus', 'like geckoo', 'wpdesktop', 'nokia', 'lumia', 'arm',
|
|
||||||
'de-at', 'pixel', 'puffin', 'zte blade a7', 'linux armv7l', 'hd1913', 'symbianos',
|
|
||||||
'symbian os', 'de', '452', 'opera [en-us]', 'iemobile', 'windows phone', 'sm-g991b',
|
|
||||||
'sm-j810g', 'da-dk', 'symbian', 'series60', 'nokiax7-00', 'freebsd amd64', 'openbsd amd64',
|
|
||||||
'sm-n920c', 'blazer', 'palmsource', '16;320x320', 'sm-g998b', 'sm-a505g', 'freebsd i386',
|
|
||||||
'jaunty', 'shiretoko', 'playbook', 'rim tablet os', 'asus;galaxy6', 'minimo',
|
|
||||||
'linux arm7tdmi', 'blackberry7520', 'dl1036', '100011886a', 'lt-gtklauncher',
|
|
||||||
'browserng', 'nokiae7-00', 'ubuntu chromium', 'silk-accelerated=true', 'openbsd i386',
|
|
||||||
'windows ce', 'microsoft zunehd', 'epiphany', 'es-es', 'ru-ru', 'netbsd', 'ipod',
|
|
||||||
'safari', 'xbox', 'xbox one', 'fxios', 'opx', 'ucbrowser', 'u3',
|
|
||||||
'webos', 'desktop', 'compatible msie windows nt', 'sm-a525f', 'sm-g991u', 'ze520kl',
|
|
||||||
'cros i686', 'de-de', 'en-ca', 'config', 'i686', 'sm-g970u', 'win95', 'i',
|
|
||||||
'nokia7250', 'oneplus a6003', 'i2126', 'nintendo wii', 'vog-l29', 'msoffice', 'ms-office',
|
|
||||||
'oneplus a5010', 'linux mint', 'blackberry8320', 'observatory', 'qdesk',
|
|
||||||
'alexatoolbar', 'se metasr', 'qqdownload', 'alexa toolbar', 'baiduclient', 'ddg_android',
|
|
||||||
'com.duckduckgo.mobile.android', 'android api', 'duckduckgo', 'googletoolbar', 'amaya',
|
|
||||||
];
|
|
||||||
if (!in_array($part, $known) && !preg_match('=^rv:[\d]+\S*$=', $part)) {
|
|
||||||
$cleaned[] = $part;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $cleaned;
|
|
||||||
}
|
|
||||||
|
|
||||||
function blockbot_clean_part(string $part): string
|
|
||||||
{
|
|
||||||
$part = trim($part);
|
|
||||||
$subparts = [];
|
|
||||||
foreach (explode(' ', $part) as $subpart) {
|
|
||||||
$subpart = trim($subpart, ' +,');
|
|
||||||
if (!empty($subpart) && (!preg_match('=^\d+[\w\-\+\.]+$=', $subpart) || empty($subparts))) {
|
|
||||||
$subparts[] = $subpart;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return implode(' ', $subparts);
|
|
||||||
}
|
|
||||||
|
|
||||||
function blockbot_split_parts(string $agent, bool $parse_spaces, bool $parse_semicolon): array
|
|
||||||
{
|
|
||||||
$agent = strtolower(trim($agent, ' ;'));
|
|
||||||
$cleaned = [];
|
|
||||||
|
|
||||||
while (preg_match('=\w+[\s\w/\._\-]*/\d+[^;\s]*=', $agent, $matches)) {
|
|
||||||
$part = $matches[0];
|
|
||||||
if (preg_match('=/\d+[^;\s]*=', $part, $matches, PREG_OFFSET_CAPTURE)) {
|
|
||||||
$cleaned[] = substr($part, 0, $matches[0][1]);
|
|
||||||
$part = substr($part, 0, $matches[0][1] + strlen($matches[0][0]));
|
|
||||||
}
|
|
||||||
$agent = trim(str_replace($part, '', $agent));
|
|
||||||
}
|
|
||||||
if ($parse_semicolon && strpos($agent, ';') !== false) {
|
|
||||||
$parse_spaces = false;
|
|
||||||
$parts = [];
|
|
||||||
foreach (explode(';', $agent) as $part) {
|
|
||||||
$parts[] = blockbot_clean_part($part);
|
|
||||||
}
|
|
||||||
} elseif (strpos($agent, ' - ') !== false) {
|
|
||||||
$parts = [];
|
|
||||||
foreach (explode(' - ', $agent) as $part) {
|
|
||||||
$parts[] = blockbot_clean_part($part);
|
|
||||||
}
|
|
||||||
} elseif ($parse_spaces) {
|
|
||||||
$parts = explode(' ', $agent);
|
|
||||||
} else {
|
|
||||||
$parts = [$agent];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($parse_spaces) {
|
|
||||||
$subparts = [];
|
|
||||||
foreach ($parts as $part) {
|
|
||||||
while (($pos_space = strpos($part, ' ')) !== false && ($pos_slash = strpos($part, '/')) !== false) {
|
|
||||||
if ($pos_space > $pos_slash) {
|
|
||||||
$subparts[] = substr($part, 0, $pos_space);
|
|
||||||
$part = trim(substr($part, $pos_space + 1), ' +,-;');
|
|
||||||
} else {
|
|
||||||
$subparts[] = $part;
|
|
||||||
$part = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($part != '') {
|
|
||||||
$subparts[] = $part;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$parts = $subparts;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($parts as $part) {
|
|
||||||
$part = trim($part, ' +');
|
|
||||||
|
|
||||||
if (!Network::isValidHttpUrl($part) && strpos($part, '/') !== false) {
|
|
||||||
$split = explode('/', $part);
|
|
||||||
array_pop($split);
|
|
||||||
$part = implode('/', $split);
|
|
||||||
}
|
|
||||||
|
|
||||||
$pos1 = strpos($part, "'");
|
|
||||||
$pos2 = strrpos($part, "'");
|
|
||||||
if ($pos1 != $pos2) {
|
|
||||||
$part = substr($part, 0, $pos1 - 1) . substr($part, $pos2 + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
$part = trim(preg_replace('=(.*) [\d\.]+=', '$1', $part), " +,-;\u{00AD}");
|
|
||||||
if (!empty($part)) {
|
|
||||||
$cleaned[] = $part;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $cleaned;
|
|
||||||
}
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2024-04-30 12:12+0000\n"
|
"POT-Creation-Date: 2024-03-05 04:51+0000\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
@ -17,29 +17,52 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
#: blockbot.php:32
|
#: blockbot.php:30
|
||||||
msgid "Save Settings"
|
msgid "Save Settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blockbot.php:33
|
#: blockbot.php:31
|
||||||
msgid "Allow security checkers"
|
msgid "Allow \"good\" crawlers"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: blockbot.php:31
|
||||||
|
msgid ""
|
||||||
|
"Don't block fediverse crawlers, relay servers and other bots with good "
|
||||||
|
"purposes."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: blockbot.php:32
|
||||||
|
msgid "Allow preview agents"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: blockbot.php:32
|
||||||
|
msgid ""
|
||||||
|
"Don't block agents from social media systems that want to generate preview "
|
||||||
|
"data for links that had been set by their users."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blockbot.php:33
|
#: blockbot.php:33
|
||||||
msgid "Don't block security checkers. They can be used for good or bad."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: blockbot.php:34
|
|
||||||
msgid "Allow generic HTTP libraries"
|
msgid "Allow generic HTTP libraries"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: blockbot.php:34
|
#: blockbot.php:33
|
||||||
msgid ""
|
msgid ""
|
||||||
"Don't block agents from generic HTTP libraries that could be used for good "
|
"Don't block agents from generic HTTP libraries that could be used for good "
|
||||||
"or for bad and that currently can't be traced back to any known Fediverse "
|
"or for bad and that currently can't be traced back to any known Fediverse "
|
||||||
"project."
|
"project."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: blockbot.php:34
|
||||||
|
msgid "Block GabSocial"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: blockbot.php:34
|
||||||
|
msgid ""
|
||||||
|
"Block the software GabSocial. This will block every access for that "
|
||||||
|
"software. You can block dedicated gab instances in the blocklist settings in "
|
||||||
|
"the admin section."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: blockbot.php:35
|
#: blockbot.php:35
|
||||||
msgid "Training mode"
|
msgid "Training mode"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{{include file="field_checkbox.tpl" field=$security_checker}}
|
{{include file="field_checkbox.tpl" field=$good_crawlers}}
|
||||||
|
{{include file="field_checkbox.tpl" field=$socialmedia_agents}}
|
||||||
{{include file="field_checkbox.tpl" field=$http_libraries}}
|
{{include file="field_checkbox.tpl" field=$http_libraries}}
|
||||||
|
{{include file="field_checkbox.tpl" field=$block_gab}}
|
||||||
{{include file="field_checkbox.tpl" field=$training}}
|
{{include file="field_checkbox.tpl" field=$training}}
|
||||||
<div class="submit"><button type="submit" class="btn btn-primary" name="page_site" value="{{$submit}}">{{$submit}}</button></div>
|
<div class="submit"><button type="submit" class="btn btn-primary" name="page_site" value="{{$submit}}">{{$submit}}</button></div>
|
|
@ -45,12 +45,10 @@ use Friendica\Model\Tag;
|
||||||
use Friendica\Model\User;
|
use Friendica\Model\User;
|
||||||
use Friendica\Network\HTTPClient\Client\HttpClientAccept;
|
use Friendica\Network\HTTPClient\Client\HttpClientAccept;
|
||||||
use Friendica\Network\HTTPClient\Client\HttpClientOptions;
|
use Friendica\Network\HTTPClient\Client\HttpClientOptions;
|
||||||
use Friendica\Network\HTTPClient\Client\HttpClientRequest;
|
|
||||||
use Friendica\Object\Image;
|
use Friendica\Object\Image;
|
||||||
use Friendica\Protocol\Activity;
|
use Friendica\Protocol\Activity;
|
||||||
use Friendica\Protocol\Relay;
|
use Friendica\Protocol\Relay;
|
||||||
use Friendica\Util\DateTimeFormat;
|
use Friendica\Util\DateTimeFormat;
|
||||||
use Friendica\Util\Network;
|
|
||||||
use Friendica\Util\Strings;
|
use Friendica\Util\Strings;
|
||||||
|
|
||||||
const BLUESKY_DEFAULT_POLL_INTERVAL = 10; // given in minutes
|
const BLUESKY_DEFAULT_POLL_INTERVAL = 10; // given in minutes
|
||||||
|
@ -70,7 +68,6 @@ const BLUEKSY_STATUS_TOKEN_FAIL = 13;
|
||||||
const BLUESKY_DIRECTORY = 'https://plc.directory'; // Path to the directory server service to fetch the PDS of a given DID
|
const BLUESKY_DIRECTORY = 'https://plc.directory'; // Path to the directory server service to fetch the PDS of a given DID
|
||||||
const BLUESKY_PDS = 'https://bsky.social'; // Path to the personal data server service (PDS) to fetch the DID for a given handle
|
const BLUESKY_PDS = 'https://bsky.social'; // Path to the personal data server service (PDS) to fetch the DID for a given handle
|
||||||
const BLUESKY_WEB = 'https://bsky.app'; // Path to the web interface with the user profile and posts
|
const BLUESKY_WEB = 'https://bsky.app'; // Path to the web interface with the user profile and posts
|
||||||
const BLUESKY_HOSTNAME = 'bsky.social'; // Host name to be added to the handle if incomplete
|
|
||||||
|
|
||||||
function bluesky_install()
|
function bluesky_install()
|
||||||
{
|
{
|
||||||
|
@ -100,17 +97,12 @@ function bluesky_load_config(ConfigFileManager $loader)
|
||||||
|
|
||||||
function bluesky_check_item_notification(array &$notification_data)
|
function bluesky_check_item_notification(array &$notification_data)
|
||||||
{
|
{
|
||||||
if (empty($notification_data['uid'])) {
|
$did = DI::pConfig()->get($notification_data['uid'], 'bluesky', 'did');
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$did = bluesky_get_user_did($notification_data['uid']);
|
|
||||||
if (empty($did)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!empty($did)) {
|
||||||
$notification_data['profiles'][] = $did;
|
$notification_data['profiles'][] = $did;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function bluesky_probe_detect(array &$hookData)
|
function bluesky_probe_detect(array &$hookData)
|
||||||
{
|
{
|
||||||
|
@ -131,13 +123,8 @@ function bluesky_probe_detect(array &$hookData)
|
||||||
|
|
||||||
if (parse_url($hookData['uri'], PHP_URL_SCHEME) == 'did') {
|
if (parse_url($hookData['uri'], PHP_URL_SCHEME) == 'did') {
|
||||||
$did = $hookData['uri'];
|
$did = $hookData['uri'];
|
||||||
} elseif (parse_url($hookData['uri'], PHP_URL_PATH) == $hookData['uri'] && strpos($hookData['uri'], '@') === false) {
|
} elseif (preg_match('#^' . BLUESKY_WEB . '/profile/(.+)#', $hookData['uri'], $matches)) {
|
||||||
$did = bluesky_get_did($hookData['uri'], $pconfig['uid']);
|
$did = bluesky_get_did($matches[1]);
|
||||||
if (empty($did)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} elseif (Network::isValidHttpUrl($hookData['uri'])) {
|
|
||||||
$did = bluesky_get_did_by_profile($hookData['uri']);
|
|
||||||
if (empty($did)) {
|
if (empty($did)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -155,14 +142,19 @@ function bluesky_probe_detect(array &$hookData)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$hookData['result'] = bluesky_get_contact_fields($data, 0, $pconfig['uid'], true);
|
$hookData['result'] = bluesky_get_contact_fields($data, 0, $pconfig['uid'], false);
|
||||||
|
|
||||||
|
$hookData['result']['baseurl'] = bluesky_get_pds($did);
|
||||||
|
|
||||||
// Preparing probe data. This differs slightly from the contact array
|
// Preparing probe data. This differs slightly from the contact array
|
||||||
|
$hookData['result']['about'] = HTML::toBBCode($data->description ?? '');
|
||||||
$hookData['result']['photo'] = $data->avatar ?? '';
|
$hookData['result']['photo'] = $data->avatar ?? '';
|
||||||
|
$hookData['result']['header'] = $data->banner ?? '';
|
||||||
$hookData['result']['batch'] = '';
|
$hookData['result']['batch'] = '';
|
||||||
$hookData['result']['notify'] = '';
|
$hookData['result']['notify'] = '';
|
||||||
$hookData['result']['poll'] = '';
|
$hookData['result']['poll'] = '';
|
||||||
$hookData['result']['poco'] = '';
|
$hookData['result']['poco'] = '';
|
||||||
|
$hookData['result']['pubkey'] = '';
|
||||||
$hookData['result']['priority'] = 0;
|
$hookData['result']['priority'] = 0;
|
||||||
$hookData['result']['guid'] = '';
|
$hookData['result']['guid'] = '';
|
||||||
}
|
}
|
||||||
|
@ -179,21 +171,21 @@ function bluesky_item_by_link(array &$hookData)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$did = bluesky_get_did_by_profile($hookData['uri']);
|
if (!preg_match('#^' . BLUESKY_WEB . '/profile/(.+)/post/(.+)#', $hookData['uri'], $matches)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$did = bluesky_get_did($matches[1]);
|
||||||
if (empty($did)) {
|
if (empty($did)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!preg_match('#/profile/.+/post/(.+)#', $hookData['uri'], $matches)) {
|
Logger::debug('Found bluesky post', ['url' => $hookData['uri'], 'handle' => $matches[1], 'did' => $did, 'cid' => $matches[2]]);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger::debug('Found bluesky post', ['url' => $hookData['uri'], 'did' => $did, 'cid' => $matches[1]]);
|
$uri = 'at://' . $did . '/app.bsky.feed.post/' . $matches[2];
|
||||||
|
|
||||||
$uri = 'at://' . $did . '/app.bsky.feed.post/' . $matches[1];
|
|
||||||
|
|
||||||
$uri = bluesky_fetch_missing_post($uri, $hookData['uid'], $hookData['uid'], Item::PR_FETCHED, 0, 0, 0);
|
$uri = bluesky_fetch_missing_post($uri, $hookData['uid'], $hookData['uid'], Item::PR_FETCHED, 0, 0, 0);
|
||||||
Logger::debug('Got post', ['did' => $did, 'cid' => $matches[1], 'result' => $uri]);
|
Logger::debug('Got post', ['profile' => $matches[1], 'cid' => $matches[2], 'result' => $uri]);
|
||||||
if (!empty($uri)) {
|
if (!empty($uri)) {
|
||||||
$item = Post::selectFirst(['id'], ['uri' => $uri, 'uid' => $hookData['uid']]);
|
$item = Post::selectFirst(['id'], ['uri' => $uri, 'uid' => $hookData['uid']]);
|
||||||
if (!empty($item['id'])) {
|
if (!empty($item['id'])) {
|
||||||
|
@ -237,7 +229,7 @@ function bluesky_follow(array &$hook_data)
|
||||||
|
|
||||||
$post = [
|
$post = [
|
||||||
'collection' => 'app.bsky.graph.follow',
|
'collection' => 'app.bsky.graph.follow',
|
||||||
'repo' => bluesky_get_user_did($hook_data['uid']),
|
'repo' => DI::pConfig()->get($hook_data['uid'], 'bluesky', 'did'),
|
||||||
'record' => $record
|
'record' => $record
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -290,15 +282,15 @@ function bluesky_block(array &$hook_data)
|
||||||
|
|
||||||
$post = [
|
$post = [
|
||||||
'collection' => 'app.bsky.graph.block',
|
'collection' => 'app.bsky.graph.block',
|
||||||
'repo' => bluesky_get_user_did($hook_data['uid']),
|
'repo' => DI::pConfig()->get($hook_data['uid'], 'bluesky', 'did'),
|
||||||
'record' => $record
|
'record' => $record
|
||||||
];
|
];
|
||||||
|
|
||||||
$activity = bluesky_xrpc_post($hook_data['uid'], 'com.atproto.repo.createRecord', $post);
|
$activity = bluesky_xrpc_post($hook_data['uid'], 'com.atproto.repo.createRecord', $post);
|
||||||
if (!empty($activity->uri)) {
|
if (!empty($activity->uri)) {
|
||||||
$ucid = Contact::getUserContactId($hook_data['contact']['id'], $hook_data['uid']);
|
$cdata = Contact::getPublicAndUserContactID($hook_data['contact']['id'], $hook_data['uid']);
|
||||||
if ($ucid) {
|
if (!empty($cdata['user'])) {
|
||||||
Contact::remove($ucid);
|
Contact::remove($cdata['user']);
|
||||||
}
|
}
|
||||||
Logger::debug('Successfully blocked contact', ['url' => $hook_data['contact']['url'], 'uri' => $activity->uri]);
|
Logger::debug('Successfully blocked contact', ['url' => $hook_data['contact']['url'], 'uri' => $activity->uri]);
|
||||||
}
|
}
|
||||||
|
@ -350,7 +342,7 @@ function bluesky_settings(array &$data)
|
||||||
$def_enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'post_by_default') ?? false;
|
$def_enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'post_by_default') ?? false;
|
||||||
$pds = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'pds');
|
$pds = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'pds');
|
||||||
$handle = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'handle');
|
$handle = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'handle');
|
||||||
$did = bluesky_get_user_did(DI::userSession()->getLocalUserId());
|
$did = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'did');
|
||||||
$token = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'access_token');
|
$token = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'access_token');
|
||||||
$import = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'import') ?? false;
|
$import = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'import') ?? false;
|
||||||
$import_feeds = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'import_feeds') ?? false;
|
$import_feeds = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'import_feeds') ?? false;
|
||||||
|
@ -358,11 +350,8 @@ function bluesky_settings(array &$data)
|
||||||
|
|
||||||
if (DI::config()->get('bluesky', 'friendica_handles')) {
|
if (DI::config()->get('bluesky', 'friendica_handles')) {
|
||||||
$self = User::getById(DI::userSession()->getLocalUserId(), ['nickname']);
|
$self = User::getById(DI::userSession()->getLocalUserId(), ['nickname']);
|
||||||
$host_handle = $self['nickname'] . '.' . DI::baseUrl()->getHost();
|
$handle = $self['nickname'] . '.' . DI::baseUrl()->getHost();
|
||||||
$friendica_handle = ['bluesky_friendica_handle', DI::l10n()->t('Allow to use %s as your Bluesky handle.', $host_handle), $custom_handle, DI::l10n()->t('When enabled, you can use %s as your Bluesky handle. After you enabled this option, please go to https://bsky.app/settings and select to change your handle. Select that you have got your own domain. Then enter %s and select "No DNS Panel". Then select "Verify Text File".', $host_handle, $host_handle)];
|
$friendica_handle = ['bluesky_friendica_handle', DI::l10n()->t('Allow to use %s as your Bluesky handle.', $handle), $custom_handle, DI::l10n()->t('When enabled, you can use %s as your Bluesky handle. After you enabled this option, please go to https://bsky.app/settings and select to change your handle. Select that you have got your own domain. Then enter %s and select "No DNS Panel". Then select "Verify Text File".', $handle, $handle)];
|
||||||
if ($custom_handle) {
|
|
||||||
$handle = $host_handle;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
$friendica_handle = [];
|
$friendica_handle = [];
|
||||||
}
|
}
|
||||||
|
@ -375,7 +364,7 @@ function bluesky_settings(array &$data)
|
||||||
'$import_feeds' => ['bluesky_import_feeds', DI::l10n()->t('Import the pinned feeds'), $import_feeds, DI::l10n()->t('When activated, Posts will be imported from all the feeds that you pinned in Bluesky.')],
|
'$import_feeds' => ['bluesky_import_feeds', DI::l10n()->t('Import the pinned feeds'), $import_feeds, DI::l10n()->t('When activated, Posts will be imported from all the feeds that you pinned in Bluesky.')],
|
||||||
'$custom_handle' => $friendica_handle,
|
'$custom_handle' => $friendica_handle,
|
||||||
'$pds' => ['bluesky_pds', DI::l10n()->t('Personal Data Server'), $pds, DI::l10n()->t('The personal data server (PDS) is the system that hosts your profile.'), '', 'readonly'],
|
'$pds' => ['bluesky_pds', DI::l10n()->t('Personal Data Server'), $pds, DI::l10n()->t('The personal data server (PDS) is the system that hosts your profile.'), '', 'readonly'],
|
||||||
'$handle' => ['bluesky_handle', DI::l10n()->t('Bluesky handle'), $handle, '', '', $custom_handle ? 'readonly' : ''],
|
'$handle' => ['bluesky_handle', DI::l10n()->t('Bluesky handle'), $handle],
|
||||||
'$did' => ['bluesky_did', DI::l10n()->t('Bluesky DID'), $did, DI::l10n()->t('This is the unique identifier. It will be fetched automatically, when the handle is entered.'), '', 'readonly'],
|
'$did' => ['bluesky_did', DI::l10n()->t('Bluesky DID'), $did, DI::l10n()->t('This is the unique identifier. It will be fetched automatically, when the handle is entered.'), '', 'readonly'],
|
||||||
'$password' => ['bluesky_password', DI::l10n()->t('Bluesky app password'), '', DI::l10n()->t("Please don't add your real password here, but instead create a specific app password in the Bluesky settings.")],
|
'$password' => ['bluesky_password', DI::l10n()->t('Bluesky app password'), '', DI::l10n()->t("Please don't add your real password here, but instead create a specific app password in the Bluesky settings.")],
|
||||||
'$status' => bluesky_get_status($handle, $did, $pds, $token),
|
'$status' => bluesky_get_status($handle, $did, $pds, $token),
|
||||||
|
@ -446,10 +435,18 @@ function bluesky_settings_post(array &$b)
|
||||||
DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'handle', $handle);
|
DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'handle', $handle);
|
||||||
DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'import', intval($_POST['bluesky_import']));
|
DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'import', intval($_POST['bluesky_import']));
|
||||||
DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'import_feeds', intval($_POST['bluesky_import_feeds']));
|
DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'import_feeds', intval($_POST['bluesky_import_feeds']));
|
||||||
DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'friendica_handle', intval($_POST['bluesky_friendica_handle'] ?? false));
|
DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'friendica_handle', intval($_POST['bluesky_friendica_handle']));
|
||||||
|
|
||||||
if (!empty($handle)) {
|
if (!empty($handle)) {
|
||||||
$did = bluesky_get_user_did(DI::userSession()->getLocalUserId(), empty($old_did) || $old_handle != $handle);
|
if (empty($old_did) || $old_handle != $handle) {
|
||||||
|
$did = bluesky_get_did(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'handle'));
|
||||||
|
if (empty($did)) {
|
||||||
|
DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'status', BLUEKSY_STATUS_DID_FAIL);
|
||||||
|
}
|
||||||
|
DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'did', $did);
|
||||||
|
} else {
|
||||||
|
$did = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'did');
|
||||||
|
}
|
||||||
if (!empty($did) && (empty($old_pds) || $old_handle != $handle)) {
|
if (!empty($did) && (empty($old_pds) || $old_handle != $handle)) {
|
||||||
$pds = bluesky_get_pds($did);
|
$pds = bluesky_get_pds($did);
|
||||||
if (empty($pds)) {
|
if (empty($pds)) {
|
||||||
|
@ -516,13 +513,8 @@ function bluesky_cron()
|
||||||
|
|
||||||
$abandon_limit = date(DateTimeFormat::MYSQL, time() - $abandon_days * 86400);
|
$abandon_limit = date(DateTimeFormat::MYSQL, time() - $abandon_days * 86400);
|
||||||
|
|
||||||
$pconfigs = DBA::selectToArray('pconfig', [], ["`cat` = ? AND `k` IN (?, ?) AND `v`", 'bluesky', 'import', 'import_feeds']);
|
$pconfigs = DBA::selectToArray('pconfig', [], ['cat' => 'bluesky', 'k' => 'import', 'v' => true]);
|
||||||
foreach ($pconfigs as $pconfig) {
|
foreach ($pconfigs as $pconfig) {
|
||||||
if (empty(bluesky_get_user_did($pconfig['uid']))) {
|
|
||||||
Logger::debug('User has got no valid DID', ['uid' => $pconfig['uid']]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($abandon_days != 0) {
|
if ($abandon_days != 0) {
|
||||||
if (!DBA::exists('user', ["`uid` = ? AND `login_date` >= ?", $pconfig['uid'], $abandon_limit])) {
|
if (!DBA::exists('user', ["`uid` = ? AND `login_date` >= ?", $pconfig['uid'], $abandon_limit])) {
|
||||||
Logger::notice('abandoned account: timeline from user will not be imported', ['user' => $pconfig['uid']]);
|
Logger::notice('abandoned account: timeline from user will not be imported', ['user' => $pconfig['uid']]);
|
||||||
|
@ -531,27 +523,19 @@ function bluesky_cron()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refresh the token now, so that it doesn't need to be refreshed in parallel by the following workers
|
// Refresh the token now, so that it doesn't need to be refreshed in parallel by the following workers
|
||||||
Logger::debug('Refresh the token', ['uid' => $pconfig['uid']]);
|
|
||||||
bluesky_get_token($pconfig['uid']);
|
bluesky_get_token($pconfig['uid']);
|
||||||
|
|
||||||
Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_notifications.php', $pconfig['uid'], $last);
|
Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_notifications.php', $pconfig['uid'], $last);
|
||||||
if (DI::pConfig()->get($pconfig['uid'], 'bluesky', 'import')) {
|
|
||||||
Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_timeline.php', $pconfig['uid'], $last);
|
Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_timeline.php', $pconfig['uid'], $last);
|
||||||
}
|
|
||||||
if (DI::pConfig()->get($pconfig['uid'], 'bluesky', 'import_feeds')) {
|
if (DI::pConfig()->get($pconfig['uid'], 'bluesky', 'import_feeds')) {
|
||||||
Logger::debug('Fetch feeds for user', ['uid' => $pconfig['uid']]);
|
|
||||||
$feeds = bluesky_get_feeds($pconfig['uid']);
|
$feeds = bluesky_get_feeds($pconfig['uid']);
|
||||||
foreach ($feeds as $feed) {
|
foreach ($feeds as $feed) {
|
||||||
Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_feed.php', $pconfig['uid'], $feed, $last);
|
Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_feed.php', $pconfig['uid'], $feed, $last);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Logger::debug('Polling done for user', ['uid' => $pconfig['uid']]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger::notice('Polling done for all users');
|
|
||||||
|
|
||||||
DI::keyValue()->set('bluesky_last_poll', time());
|
|
||||||
|
|
||||||
$last_clean = DI::keyValue()->get('bluesky_last_clean');
|
$last_clean = DI::keyValue()->get('bluesky_last_clean');
|
||||||
if (empty($last_clean) || ($last_clean + 86400 < time())) {
|
if (empty($last_clean) || ($last_clean + 86400 < time())) {
|
||||||
Logger::notice('Start contact cleanup');
|
Logger::notice('Start contact cleanup');
|
||||||
|
@ -565,6 +549,8 @@ function bluesky_cron()
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger::notice('cron_end');
|
Logger::notice('cron_end');
|
||||||
|
|
||||||
|
DI::keyValue()->set('bluesky_last_poll', time());
|
||||||
}
|
}
|
||||||
|
|
||||||
function bluesky_hook_fork(array &$b)
|
function bluesky_hook_fork(array &$b)
|
||||||
|
@ -678,10 +664,7 @@ function bluesky_create_activity(array $item, stdClass $parent = null)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$did = bluesky_get_user_did($uid);
|
$did = DI::pConfig()->get($uid, 'bluesky', 'did');
|
||||||
if (empty($did)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($item['verb'] == Activity::LIKE) {
|
if ($item['verb'] == Activity::LIKE) {
|
||||||
$record = [
|
$record = [
|
||||||
|
@ -789,7 +772,7 @@ function bluesky_create_post(array $item, stdClass $root = null, stdClass $paren
|
||||||
|
|
||||||
$post = [
|
$post = [
|
||||||
'collection' => 'app.bsky.feed.post',
|
'collection' => 'app.bsky.feed.post',
|
||||||
'repo' => bluesky_get_user_did($uid),
|
'repo' => DI::pConfig()->get($uid, 'bluesky', 'did'),
|
||||||
'record' => $record
|
'record' => $record
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -977,7 +960,6 @@ function bluesky_upload_blob(int $uid, array $photo): ?stdClass
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Item::incrementOutbound(Protocol::BLUESKY);
|
|
||||||
Logger::debug('Uploaded blob', ['return' => $data, 'uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]);
|
Logger::debug('Uploaded blob', ['return' => $data, 'uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]);
|
||||||
return $data->blob;
|
return $data->blob;
|
||||||
}
|
}
|
||||||
|
@ -1051,8 +1033,8 @@ function bluesky_process_reason(stdClass $reason, string $uri, int $uid)
|
||||||
$item['owner-link'] = $item['author-link'];
|
$item['owner-link'] = $item['author-link'];
|
||||||
$item['owner-avatar'] = $item['author-avatar'];
|
$item['owner-avatar'] = $item['author-avatar'];
|
||||||
if (Item::insert($item)) {
|
if (Item::insert($item)) {
|
||||||
$pcid = Contact::getPublicContactId($contact['id'], $uid);
|
$cdata = Contact::getPublicAndUserContactID($contact['id'], $uid);
|
||||||
Item::update(['post-reason' => Item::PR_ANNOUNCEMENT, 'causer-id' => $pcid], ['uri' => $uri, 'uid' => $uid]);
|
Item::update(['post-reason' => Item::PR_ANNOUNCEMENT, 'causer-id' => $cdata['public']], ['uri' => $uri, 'uid' => $uid]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1231,11 +1213,7 @@ function bluesky_get_header(stdClass $post, string $uri, int $uid, int $fetch_ui
|
||||||
'source' => json_encode($post),
|
'source' => json_encode($post),
|
||||||
];
|
];
|
||||||
|
|
||||||
$account = Contact::selectFirstAccountUser(['pid'], ['id' => $contact['id']]);
|
|
||||||
|
|
||||||
$item['author-id'] = $account['pid'];
|
|
||||||
$item['uri-id'] = ItemURI::getIdByURI($uri);
|
$item['uri-id'] = ItemURI::getIdByURI($uri);
|
||||||
$item['owner-id'] = $item['author-id'];
|
|
||||||
$item['owner-name'] = $item['author-name'];
|
$item['owner-name'] = $item['author-name'];
|
||||||
$item['owner-link'] = $item['author-link'];
|
$item['owner-link'] = $item['author-link'];
|
||||||
$item['owner-avatar'] = $item['author-avatar'];
|
$item['owner-avatar'] = $item['author-avatar'];
|
||||||
|
@ -1244,17 +1222,6 @@ function bluesky_get_header(stdClass $post, string $uri, int $uid, int $fetch_ui
|
||||||
$item['post-reason'] = Item::PR_FOLLOWER;
|
$item['post-reason'] = Item::PR_FOLLOWER;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($post->labels)) {
|
|
||||||
foreach ($post->labels as $label) {
|
|
||||||
// Only flag posts as sensitive based on labels that had been provided by the author.
|
|
||||||
// When "ver" is set to "1" it was flagged by some automated process.
|
|
||||||
if (empty($label->ver)) {
|
|
||||||
$item['sensitive'] = true;
|
|
||||||
Logger::debug('Sensitive content', ['uri-id' => $item['uri-id'], 'label' => $label]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $item;
|
return $item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1410,19 +1377,6 @@ function bluesky_add_media(stdClass $embed, array $item, int $fetch_uid, int $le
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'app.bsky.embed.video#view':
|
|
||||||
$media = [
|
|
||||||
'uri-id' => $item['uri-id'],
|
|
||||||
'type' => Post\Media::HLS,
|
|
||||||
'url' => $embed->playlist,
|
|
||||||
'preview' => $embed->thumbnail,
|
|
||||||
'description' => $embed->alt ?? '',
|
|
||||||
'height' => $embed->aspectRatio->height,
|
|
||||||
'width' => $embed->aspectRatio->width,
|
|
||||||
];
|
|
||||||
Post\Media::insert($media);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'app.bsky.embed.external#view':
|
case 'app.bsky.embed.external#view':
|
||||||
$media = [
|
$media = [
|
||||||
'uri-id' => $item['uri-id'],
|
'uri-id' => $item['uri-id'],
|
||||||
|
@ -1537,10 +1491,6 @@ function bluesky_fetch_missing_post(string $uri, int $uid, int $fetch_uid, int $
|
||||||
}
|
}
|
||||||
|
|
||||||
$class = bluesky_get_uri_class($uri);
|
$class = bluesky_get_uri_class($uri);
|
||||||
if (empty($class)) {
|
|
||||||
return $fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
$fetch_uri = $class->uri;
|
$fetch_uri = $class->uri;
|
||||||
|
|
||||||
Logger::debug('Fetch missing post', ['level' => $level, 'uid' => $uid, 'uri' => $uri]);
|
Logger::debug('Fetch missing post', ['level' => $level, 'uid' => $uid, 'uri' => $uri]);
|
||||||
|
@ -1553,7 +1503,8 @@ function bluesky_fetch_missing_post(string $uri, int $uid, int $fetch_uid, int $
|
||||||
Logger::debug('Reply count', ['level' => $level, 'uid' => $uid, 'uri' => $uri]);
|
Logger::debug('Reply count', ['level' => $level, 'uid' => $uid, 'uri' => $uri]);
|
||||||
|
|
||||||
if ($causer != 0) {
|
if ($causer != 0) {
|
||||||
$causer = Contact::getPublicContactId($causer, $uid);
|
$cdata = Contact::getPublicAndUserContactID($causer, $uid);
|
||||||
|
$causer = $cdata['public'] ?? 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return bluesky_process_thread($data->thread, $uid, $fetch_uid, $post_reason, $causer, $level, $last_poll);
|
return bluesky_process_thread($data->thread, $uid, $fetch_uid, $post_reason, $causer, $level, $last_poll);
|
||||||
|
@ -1622,7 +1573,7 @@ function bluesky_process_thread(stdClass $thread, int $uid, int $fetch_uid, int
|
||||||
|
|
||||||
function bluesky_get_contact(stdClass $author, int $uid, int $fetch_uid): array
|
function bluesky_get_contact(stdClass $author, int $uid, int $fetch_uid): array
|
||||||
{
|
{
|
||||||
$condition = ['network' => Protocol::BLUESKY, 'uid' => 0, 'nurl' => $author->did];
|
$condition = ['network' => Protocol::BLUESKY, 'uid' => 0, 'url' => $author->did];
|
||||||
$contact = Contact::selectFirst(['id', 'updated'], $condition);
|
$contact = Contact::selectFirst(['id', 'updated'], $condition);
|
||||||
|
|
||||||
$update = empty($contact) || $contact['updated'] < DateTimeFormat::utc('now -24 hours');
|
$update = empty($contact) || $contact['updated'] < DateTimeFormat::utc('now -24 hours');
|
||||||
|
@ -1640,7 +1591,7 @@ function bluesky_get_contact(stdClass $author, int $uid, int $fetch_uid): array
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($uid != 0) {
|
if ($uid != 0) {
|
||||||
$condition = ['network' => Protocol::BLUESKY, 'uid' => $uid, 'nurl' => $author->did];
|
$condition = ['network' => Protocol::BLUESKY, 'uid' => $uid, 'url' => $author->did];
|
||||||
|
|
||||||
$contact = Contact::selectFirst(['id', 'rel', 'uid'], $condition);
|
$contact = Contact::selectFirst(['id', 'rel', 'uid'], $condition);
|
||||||
if (!isset($fields['rel']) && isset($contact['rel'])) {
|
if (!isset($fields['rel']) && isset($contact['rel'])) {
|
||||||
|
@ -1693,15 +1644,11 @@ function bluesky_get_contact_fields(stdClass $author, int $uid, int $fetch_uid,
|
||||||
return $fields;
|
return $fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = bluesky_get(BLUESKY_DIRECTORY . '/' . $author->did);
|
$fields['baseurl'] = bluesky_get_pds($author->did);
|
||||||
if (!empty($data)) {
|
|
||||||
$fields['baseurl'] = bluesky_get_pds('', $data);
|
|
||||||
if (!empty($fields['baseurl'])) {
|
if (!empty($fields['baseurl'])) {
|
||||||
GServer::check($fields['baseurl'], Protocol::BLUESKY);
|
GServer::check($fields['baseurl'], Protocol::BLUESKY);
|
||||||
$fields['gsid'] = GServer::getID($fields['baseurl'], true);
|
$fields['gsid'] = GServer::getID($fields['baseurl'], true);
|
||||||
}
|
}
|
||||||
$fields['pubkey'] = bluesky_get_public_key('', $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
$data = bluesky_xrpc_get($fetch_uid, 'app.bsky.actor.getProfile', ['actor' => $author->did]);
|
$data = bluesky_xrpc_get($fetch_uid, 'app.bsky.actor.getProfile', ['actor' => $author->did]);
|
||||||
if (empty($data)) {
|
if (empty($data)) {
|
||||||
|
@ -1739,9 +1686,6 @@ function bluesky_get_feeds(int $uid): array
|
||||||
{
|
{
|
||||||
$type = '$type';
|
$type = '$type';
|
||||||
$preferences = bluesky_get_preferences($uid);
|
$preferences = bluesky_get_preferences($uid);
|
||||||
if (empty($preferences) || empty($preferences->preferences)) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
foreach ($preferences->preferences as $preference) {
|
foreach ($preferences->preferences as $preference) {
|
||||||
if ($preference->$type == 'app.bsky.actor.defs#savedFeedsPref') {
|
if ($preference->$type == 'app.bsky.actor.defs#savedFeedsPref') {
|
||||||
return $preference->pinned ?? [];
|
return $preference->pinned ?? [];
|
||||||
|
@ -1750,7 +1694,7 @@ function bluesky_get_feeds(int $uid): array
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
function bluesky_get_preferences(int $uid): ?stdClass
|
function bluesky_get_preferences(int $uid): stdClass
|
||||||
{
|
{
|
||||||
$cachekey = 'bluesky:preferences:' . $uid;
|
$cachekey = 'bluesky:preferences:' . $uid;
|
||||||
$data = DI::cache()->get($cachekey);
|
$data = DI::cache()->get($cachekey);
|
||||||
|
@ -1759,57 +1703,11 @@ function bluesky_get_preferences(int $uid): ?stdClass
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = bluesky_xrpc_get($uid, 'app.bsky.actor.getPreferences');
|
$data = bluesky_xrpc_get($uid, 'app.bsky.actor.getPreferences');
|
||||||
if (empty($data)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
DI::cache()->set($cachekey, $data, Duration::HOUR);
|
DI::cache()->set($cachekey, $data, Duration::HOUR);
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
function bluesky_get_did_by_profile(string $url): string
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$curlResult = DI::httpClient()->get($url, HttpClientAccept::HTML, [HttpClientOptions::REQUEST => HttpClientRequest::CONTACTINFO]);
|
|
||||||
} catch (\Throwable $th) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
if (!$curlResult->isSuccess()) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
$profile = $curlResult->getBodyString();
|
|
||||||
if (empty($profile)) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
$doc = new DOMDocument();
|
|
||||||
try {
|
|
||||||
@$doc->loadHTML($profile);
|
|
||||||
} catch (\Throwable $th) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
$xpath = new DOMXPath($doc);
|
|
||||||
$list = $xpath->query('//p[@id]');
|
|
||||||
foreach ($list as $node) {
|
|
||||||
foreach ($node->attributes as $attribute) {
|
|
||||||
if ($attribute->name == 'id') {
|
|
||||||
$ids[$attribute->value] = $node->textContent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($ids['bsky_handle']) || empty($ids['bsky_did'])) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bluesky_valid_did($ids['bsky_did'], $ids['bsky_handle'])) {
|
|
||||||
Logger::notice('Invalid DID', ['handle' => $ids['bsky_handle'], 'did' => $ids['bsky_did']]);
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
return $ids['bsky_did'];
|
|
||||||
}
|
|
||||||
|
|
||||||
function bluesky_get_did_by_wellknown(string $handle): string
|
function bluesky_get_did_by_wellknown(string $handle): string
|
||||||
{
|
{
|
||||||
$curlResult = DI::httpClient()->get('http://' . $handle . '/.well-known/atproto-did');
|
$curlResult = DI::httpClient()->get('http://' . $handle . '/.well-known/atproto-did');
|
||||||
|
@ -1819,6 +1717,7 @@ function bluesky_get_did_by_wellknown(string $handle): string
|
||||||
Logger::notice('Invalid DID', ['handle' => $handle, 'did' => $did]);
|
Logger::notice('Invalid DID', ['handle' => $handle, 'did' => $did]);
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
Logger::debug('Got DID by wellknown', ['handle' => $handle, 'did' => $did]);
|
||||||
return $did;
|
return $did;
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
|
@ -1837,107 +1736,53 @@ function bluesky_get_did_by_dns(string $handle): string
|
||||||
Logger::notice('Invalid DID', ['handle' => $handle, 'did' => $did]);
|
Logger::notice('Invalid DID', ['handle' => $handle, 'did' => $did]);
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
return $did;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
function bluesky_get_did(string $handle, int $uid): string
|
|
||||||
{
|
|
||||||
if ($handle == '') {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strpos($handle, '.') === false) {
|
|
||||||
$handle .= '.' . BLUESKY_HOSTNAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
// At first we use the user PDS. That should cover most cases.
|
|
||||||
$pds = DI::pConfig()->get($uid, 'bluesky', 'pds');
|
|
||||||
if (!empty($pds)) {
|
|
||||||
$data = bluesky_get($pds . '/xrpc/com.atproto.identity.resolveHandle?handle=' . urlencode($handle));
|
|
||||||
if (!empty($data) && !empty($data->did)) {
|
|
||||||
Logger::debug('Got DID by user PDS call', ['handle' => $handle, 'did' => $data->did]);
|
|
||||||
return $data->did;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then we query the DNS, which is used for third party handles (DNS should be faster than wellknown)
|
|
||||||
$did = bluesky_get_did_by_dns($handle);
|
|
||||||
if ($did != '') {
|
|
||||||
Logger::debug('Got DID by DNS', ['handle' => $handle, 'did' => $did]);
|
Logger::debug('Got DID by DNS', ['handle' => $handle, 'did' => $did]);
|
||||||
return $did;
|
return $did;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then we query wellknown, which should mostly cover the rest.
|
|
||||||
$did = bluesky_get_did_by_wellknown($handle);
|
|
||||||
if ($did != '') {
|
|
||||||
Logger::debug('Got DID by wellknown', ['handle' => $handle, 'did' => $did]);
|
|
||||||
return $did;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// And finally we use the default PDS from Bluesky.
|
|
||||||
$data = bluesky_get(BLUESKY_PDS . '/xrpc/com.atproto.identity.resolveHandle?handle=' . urlencode($handle));
|
|
||||||
if (!empty($data) && !empty($data->did)) {
|
|
||||||
Logger::debug('Got DID by system PDS call', ['handle' => $handle, 'did' => $data->did]);
|
|
||||||
return $data->did;
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger::notice('No DID detected', ['handle' => $handle]);
|
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function bluesky_get_user_did(int $uid, bool $refresh = false): ?string
|
function bluesky_get_did(string $handle): string
|
||||||
{
|
{
|
||||||
if (!$refresh) {
|
// Deactivated at the moment, since it isn't reliable by now
|
||||||
$did = DI::pConfig()->get($uid, 'bluesky', 'did');
|
//$did = bluesky_get_did_by_dns($handle);
|
||||||
if (!empty($did)) {
|
//if ($did != '') {
|
||||||
return $did;
|
// return $did;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//$did = bluesky_get_did_by_wellknown($handle);
|
||||||
|
//if ($did != '') {
|
||||||
|
// return $did;
|
||||||
|
//}
|
||||||
|
|
||||||
|
$data = bluesky_get(BLUESKY_PDS . '/xrpc/com.atproto.identity.resolveHandle?handle=' . urlencode($handle));
|
||||||
|
if (empty($data) || empty($data->did)) {
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
|
Logger::debug('Got DID by PDS call', ['handle' => $handle, 'did' => $data->did]);
|
||||||
|
return $data->did;
|
||||||
}
|
}
|
||||||
|
|
||||||
$handle = DI::pConfig()->get($uid, 'bluesky', 'handle');
|
function bluesky_get_user_pds(int $uid): string
|
||||||
if (empty($handle)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$did = bluesky_get_did($handle, $uid);
|
|
||||||
if (empty($did)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger::debug('Got DID for user', ['uid' => $uid, 'handle' => $handle, 'did' => $did]);
|
|
||||||
DI::pConfig()->set($uid, 'bluesky', 'did', $did);
|
|
||||||
return $did;
|
|
||||||
}
|
|
||||||
|
|
||||||
function bluesky_get_user_pds(int $uid): ?string
|
|
||||||
{
|
{
|
||||||
$pds = DI::pConfig()->get($uid, 'bluesky', 'pds');
|
$pds = DI::pConfig()->get($uid, 'bluesky', 'pds');
|
||||||
if (!empty($pds)) {
|
if (!empty($pds)) {
|
||||||
return $pds;
|
return $pds;
|
||||||
}
|
}
|
||||||
|
$did = DI::pConfig()->get($uid, 'bluesky', 'did');
|
||||||
$did = bluesky_get_user_did($uid);
|
|
||||||
if (empty($did)) {
|
if (empty($did)) {
|
||||||
return null;
|
Logger::notice('Empty did for user', ['uid' => $uid]);
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$pds = bluesky_get_pds($did);
|
$pds = bluesky_get_pds($did);
|
||||||
if (empty($pds)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
DI::pConfig()->set($uid, 'bluesky', 'pds', $pds);
|
DI::pConfig()->set($uid, 'bluesky', 'pds', $pds);
|
||||||
return $pds;
|
return $pds;
|
||||||
}
|
}
|
||||||
|
|
||||||
function bluesky_get_pds(string $did, stdClass $data = null): ?string
|
function bluesky_get_pds(string $did): ?string
|
||||||
{
|
{
|
||||||
if (empty($data)) {
|
|
||||||
$data = bluesky_get(BLUESKY_DIRECTORY . '/' . $did);
|
$data = bluesky_get(BLUESKY_DIRECTORY . '/' . $did);
|
||||||
}
|
|
||||||
if (empty($data) || empty($data->service)) {
|
if (empty($data) || empty($data->service)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -1951,22 +1796,6 @@ function bluesky_get_pds(string $did, stdClass $data = null): ?string
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function bluesky_get_public_key(string $did, stdClass $data = null): ?string
|
|
||||||
{
|
|
||||||
if (empty($data)) {
|
|
||||||
$data = bluesky_get(BLUESKY_DIRECTORY . '/' . $did);
|
|
||||||
}
|
|
||||||
if (empty($data) || empty($data->verificationMethod)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
foreach ($data->verificationMethod as $method) {
|
|
||||||
if (!empty($method->publicKeyMultibase)) {
|
|
||||||
return $method->publicKeyMultibase;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function bluesky_valid_did(string $did, string $handle): bool
|
function bluesky_valid_did(string $did, string $handle): bool
|
||||||
{
|
{
|
||||||
$data = bluesky_get(BLUESKY_DIRECTORY . '/' . $did);
|
$data = bluesky_get(BLUESKY_DIRECTORY . '/' . $did);
|
||||||
|
@ -2009,10 +1838,7 @@ function bluesky_refresh_token(int $uid): string
|
||||||
|
|
||||||
function bluesky_create_token(int $uid, string $password): string
|
function bluesky_create_token(int $uid, string $password): string
|
||||||
{
|
{
|
||||||
$did = bluesky_get_user_did($uid);
|
$did = DI::pConfig()->get($uid, 'bluesky', 'did');
|
||||||
if (empty($did)) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
$data = bluesky_post($uid, '/xrpc/com.atproto.server.createSession', json_encode(['identifier' => $did, 'password' => $password]), ['Content-type' => 'application/json']);
|
$data = bluesky_post($uid, '/xrpc/com.atproto.server.createSession', json_encode(['identifier' => $did, 'password' => $password]), ['Content-type' => 'application/json']);
|
||||||
if (empty($data)) {
|
if (empty($data)) {
|
||||||
|
@ -2030,22 +1856,13 @@ function bluesky_create_token(int $uid, string $password): string
|
||||||
|
|
||||||
function bluesky_xrpc_post(int $uid, string $url, $parameters): ?stdClass
|
function bluesky_xrpc_post(int $uid, string $url, $parameters): ?stdClass
|
||||||
{
|
{
|
||||||
$data = bluesky_post($uid, '/xrpc/' . $url, json_encode($parameters), ['Content-type' => 'application/json', 'Authorization' => ['Bearer ' . bluesky_get_token($uid)]]);
|
return bluesky_post($uid, '/xrpc/' . $url, json_encode($parameters), ['Content-type' => 'application/json', 'Authorization' => ['Bearer ' . bluesky_get_token($uid)]]);
|
||||||
if (!empty($data)) {
|
|
||||||
Item::incrementOutbound(Protocol::BLUESKY);
|
|
||||||
}
|
|
||||||
return $data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function bluesky_post(int $uid, string $url, string $params, array $headers): ?stdClass
|
function bluesky_post(int $uid, string $url, string $params, array $headers): ?stdClass
|
||||||
{
|
{
|
||||||
$pds = bluesky_get_user_pds($uid);
|
|
||||||
if (empty($pds)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$curlResult = DI::httpClient()->post($pds . $url, $params, $headers);
|
$curlResult = DI::httpClient()->post(bluesky_get_user_pds($uid) . $url, $params, $headers);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
Logger::notice('Exception on post', ['exception' => $e]);
|
Logger::notice('Exception on post', ['exception' => $e]);
|
||||||
DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_API_FAIL);
|
DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_API_FAIL);
|
||||||
|
@ -2068,12 +1885,7 @@ function bluesky_xrpc_get(int $uid, string $url, array $parameters = []): ?stdCl
|
||||||
$url .= '?' . http_build_query($parameters);
|
$url .= '?' . http_build_query($parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
$pds = bluesky_get_user_pds($uid);
|
$data = bluesky_get(bluesky_get_user_pds($uid) . '/xrpc/' . $url, HttpClientAccept::JSON, [HttpClientOptions::HEADERS => ['Authorization' => ['Bearer ' . bluesky_get_token($uid)]]]);
|
||||||
if (empty($pds)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$data = bluesky_get($pds . '/xrpc/' . $url, HttpClientAccept::JSON, [HttpClientOptions::HEADERS => ['Authorization' => ['Bearer ' . bluesky_get_token($uid)]]]);
|
|
||||||
DI::pConfig()->set($uid, 'bluesky', 'status', is_null($data) ? BLUEKSY_STATUS_API_FAIL : BLUEKSY_STATUS_SUCCESS);
|
DI::pConfig()->set($uid, 'bluesky', 'status', is_null($data) ? BLUEKSY_STATUS_API_FAIL : BLUEKSY_STATUS_SUCCESS);
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
@ -2083,15 +1895,14 @@ function bluesky_get(string $url, string $accept_content = HttpClientAccept::DEF
|
||||||
try {
|
try {
|
||||||
$curlResult = DI::httpClient()->get($url, $accept_content, $opts);
|
$curlResult = DI::httpClient()->get($url, $accept_content, $opts);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
Logger::notice('Exception on get', ['url' => $url, 'exception' => $e]);
|
Logger::notice('Exception on get', ['exception' => $e]);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$curlResult->isSuccess()) {
|
if (!$curlResult->isSuccess()) {
|
||||||
Logger::notice('API Error', ['url' => $url, 'error' => json_decode($curlResult->getBodyString()) ?: $curlResult->getBodyString()]);
|
Logger::notice('API Error', ['error' => json_decode($curlResult->getBodyString()) ?: $curlResult->getBodyString()]);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Item::incrementInbound(Protocol::BLUESKY);
|
|
||||||
return json_decode($curlResult->getBodyString());
|
return json_decode($curlResult->getBodyString());
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,55 +6,55 @@
|
||||||
# Translators:
|
# Translators:
|
||||||
# fabrixxm <fabrix.xm@gmail.com>, 2018
|
# fabrixxm <fabrix.xm@gmail.com>, 2018
|
||||||
# Davide Pesenti <mrjive@mrjive.it>, 2018
|
# Davide Pesenti <mrjive@mrjive.it>, 2018
|
||||||
# Sylke Vicious <silkevicious@gmail.com>, 2023
|
# Sylke Vicious <silkevicious@gmail.com>, 2021
|
||||||
#
|
#
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2021-11-21 19:14-0500\n"
|
"POT-Creation-Date: 2020-12-29 00:53+0000\n"
|
||||||
"PO-Revision-Date: 2018-04-07 05:23+0000\n"
|
"PO-Revision-Date: 2018-04-07 05:23+0000\n"
|
||||||
"Last-Translator: Sylke Vicious <silkevicious@gmail.com>, 2023\n"
|
"Last-Translator: Sylke Vicious <silkevicious@gmail.com>, 2021\n"
|
||||||
"Language-Team: Italian (https://app.transifex.com/Friendica/teams/12172/it/)\n"
|
"Language-Team: Italian (https://www.transifex.com/Friendica/teams/12172/it/)\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Language: it\n"
|
"Language: it\n"
|
||||||
"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
#: catavatar.php:48
|
#: catavatar.php:48
|
||||||
msgid "Set default profile avatar or randomize the cat."
|
|
||||||
msgstr "Imposta l'immagine di profilo predefinita o crea un gatto casuale."
|
|
||||||
|
|
||||||
#: catavatar.php:53
|
|
||||||
msgid "Cat Avatar Settings"
|
|
||||||
msgstr "Impostazioni Avatar Gatto"
|
|
||||||
|
|
||||||
#: catavatar.php:56
|
|
||||||
msgid "Use Cat as Avatar"
|
msgid "Use Cat as Avatar"
|
||||||
msgstr "Usa il Gatto come avatar"
|
msgstr "Usa il Gatto come avatar"
|
||||||
|
|
||||||
#: catavatar.php:57
|
#: catavatar.php:49
|
||||||
msgid "Another random Cat!"
|
msgid "More Random Cat!"
|
||||||
msgstr "Un altro Gatto casuale!"
|
msgstr "Altro Gatto a caso!"
|
||||||
|
|
||||||
#: catavatar.php:58
|
#: catavatar.php:50
|
||||||
msgid "Reset to email Cat"
|
msgid "Reset to email Cat"
|
||||||
msgstr "Reimposta Gatto"
|
msgstr "Reimposta Gatto"
|
||||||
|
|
||||||
#: catavatar.php:77
|
#: catavatar.php:52
|
||||||
|
msgid "Cat Avatar Settings"
|
||||||
|
msgstr "Impostazioni Avatar Gatto"
|
||||||
|
|
||||||
|
#: catavatar.php:53
|
||||||
|
msgid "Set default profile avatar or randomize the cat."
|
||||||
|
msgstr "Imposta l'immagine di profilo predefinita o crea un gatto casuale."
|
||||||
|
|
||||||
|
#: catavatar.php:78
|
||||||
msgid "The cat hadn't found itself."
|
msgid "The cat hadn't found itself."
|
||||||
msgstr "Il gatto non ha trovato sé stesso."
|
msgstr "Il gatto non ha trovato sé stesso."
|
||||||
|
|
||||||
#: catavatar.php:86
|
#: catavatar.php:87
|
||||||
msgid "There was an error, the cat ran away."
|
msgid "There was an error, the cat ran away."
|
||||||
msgstr "Si è verificato un errore, il gatto è scappato."
|
msgstr "Si è verificato un errore, il gatto è scappato."
|
||||||
|
|
||||||
#: catavatar.php:92
|
#: catavatar.php:93
|
||||||
msgid "Profile Photos"
|
msgid "Profile Photos"
|
||||||
msgstr "Foto del profilo"
|
msgstr "Foto del profilo"
|
||||||
|
|
||||||
#: catavatar.php:102
|
#: catavatar.php:108
|
||||||
msgid "Meow!"
|
msgid "Meow!"
|
||||||
msgstr "Miao!"
|
msgstr "Miao!"
|
||||||
|
|
|
@ -3,13 +3,13 @@
|
||||||
if(! function_exists("string_plural_select_it")) {
|
if(! function_exists("string_plural_select_it")) {
|
||||||
function string_plural_select_it($n){
|
function string_plural_select_it($n){
|
||||||
$n = intval($n);
|
$n = intval($n);
|
||||||
if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; }
|
return intval($n != 1);
|
||||||
}}
|
}}
|
||||||
$a->strings['Set default profile avatar or randomize the cat.'] = 'Imposta l\'immagine di profilo predefinita o crea un gatto casuale.';
|
|
||||||
$a->strings['Cat Avatar Settings'] = 'Impostazioni Avatar Gatto';
|
|
||||||
$a->strings['Use Cat as Avatar'] = 'Usa il Gatto come avatar';
|
$a->strings['Use Cat as Avatar'] = 'Usa il Gatto come avatar';
|
||||||
$a->strings['Another random Cat!'] = 'Un altro Gatto casuale!';
|
$a->strings['More Random Cat!'] = 'Altro Gatto a caso!';
|
||||||
$a->strings['Reset to email Cat'] = 'Reimposta Gatto';
|
$a->strings['Reset to email Cat'] = 'Reimposta Gatto';
|
||||||
|
$a->strings['Cat Avatar Settings'] = 'Impostazioni Avatar Gatto';
|
||||||
|
$a->strings['Set default profile avatar or randomize the cat.'] = 'Imposta l\'immagine di profilo predefinita o crea un gatto casuale.';
|
||||||
$a->strings['The cat hadn\'t found itself.'] = 'Il gatto non ha trovato sé stesso.';
|
$a->strings['The cat hadn\'t found itself.'] = 'Il gatto non ha trovato sé stesso.';
|
||||||
$a->strings['There was an error, the cat ran away.'] = 'Si è verificato un errore, il gatto è scappato.';
|
$a->strings['There was an error, the cat ran away.'] = 'Si è verificato un errore, il gatto è scappato.';
|
||||||
$a->strings['Profile Photos'] = 'Foto del profilo';
|
$a->strings['Profile Photos'] = 'Foto del profilo';
|
||||||
|
|
|
@ -9,10 +9,12 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use Friendica\App;
|
||||||
use Friendica\Core\Cache\Enum\Duration;
|
use Friendica\Core\Cache\Enum\Duration;
|
||||||
use Friendica\Core\Hook;
|
use Friendica\Core\Hook;
|
||||||
use Friendica\Core\Renderer;
|
use Friendica\Core\Renderer;
|
||||||
use Friendica\DI;
|
use Friendica\DI;
|
||||||
|
use Friendica\Util\Proxy as ProxyUtils;
|
||||||
|
|
||||||
function curweather_install()
|
function curweather_install()
|
||||||
{
|
{
|
||||||
|
@ -125,7 +127,7 @@ function curweather_network_mod_init(string &$body)
|
||||||
$t = Renderer::getMarkupTemplate("widget.tpl", "addon/curweather/" );
|
$t = Renderer::getMarkupTemplate("widget.tpl", "addon/curweather/" );
|
||||||
$curweather = Renderer::replaceMacros($t, [
|
$curweather = Renderer::replaceMacros($t, [
|
||||||
'$title' => DI::l10n()->t("Current Weather"),
|
'$title' => DI::l10n()->t("Current Weather"),
|
||||||
'$icon' => 'http://openweathermap.org/img/w/'.$res['icon'].'.png',
|
'$icon' => ProxyUtils::proxifyUrl('http://openweathermap.org/img/w/'.$res['icon'].'.png'),
|
||||||
'$city' => $res['city'],
|
'$city' => $res['city'],
|
||||||
'$lon' => $res['lon'],
|
'$lon' => $res['lon'],
|
||||||
'$lat' => $res['lat'],
|
'$lat' => $res['lat'],
|
||||||
|
@ -152,7 +154,7 @@ function curweather_network_mod_init(string &$body)
|
||||||
|
|
||||||
function curweather_addon_settings_post($post)
|
function curweather_addon_settings_post($post)
|
||||||
{
|
{
|
||||||
if (!DI::userSession()->getLocalUserId() || empty($_POST['curweather-submit'])) {
|
if (!DI::userSession()->getLocalUserId() || empty($_POST['curweather-settings-submit'])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#
|
#
|
||||||
# Translators:
|
# Translators:
|
||||||
# bob lebonche <lebonche@tutanota.com>, 2021
|
# bob lebonche <lebonche@tutanota.com>, 2021
|
||||||
# cracrayol, 2024
|
|
||||||
# Hypolite Petovan <hypolite@mrpetovan.com>, 2022
|
# Hypolite Petovan <hypolite@mrpetovan.com>, 2022
|
||||||
# Hypolite Petovan <hypolite@mrpetovan.com>, 2016
|
# Hypolite Petovan <hypolite@mrpetovan.com>, 2016
|
||||||
# ea1cd8241cb389ffb6f92bc6891eff5d_dc12308 <70dced5587d47e18d88f9298024d96f8_93383>, 2015
|
# ea1cd8241cb389ffb6f92bc6891eff5d_dc12308 <70dced5587d47e18d88f9298024d96f8_93383>, 2015
|
||||||
|
@ -16,8 +15,8 @@ msgstr ""
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2021-11-21 19:14-0500\n"
|
"POT-Creation-Date: 2021-11-21 19:14-0500\n"
|
||||||
"PO-Revision-Date: 2014-06-22 11:34+0000\n"
|
"PO-Revision-Date: 2014-06-22 11:34+0000\n"
|
||||||
"Last-Translator: cracrayol, 2024\n"
|
"Last-Translator: Hypolite Petovan <hypolite@mrpetovan.com>, 2022\n"
|
||||||
"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n"
|
"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
@ -46,7 +45,7 @@ msgstr "Vent"
|
||||||
|
|
||||||
#: curweather.php:140
|
#: curweather.php:140
|
||||||
msgid "Last Updated"
|
msgid "Last Updated"
|
||||||
msgstr "Dernière mise à jour"
|
msgstr "Dernière mise-à-jour"
|
||||||
|
|
||||||
#: curweather.php:141
|
#: curweather.php:141
|
||||||
msgid "Data by"
|
msgid "Data by"
|
||||||
|
|
|
@ -10,7 +10,7 @@ $a->strings['Current Weather'] = 'Météo actuelle';
|
||||||
$a->strings['Relative Humidity'] = 'Humidité relative';
|
$a->strings['Relative Humidity'] = 'Humidité relative';
|
||||||
$a->strings['Pressure'] = 'Pression';
|
$a->strings['Pressure'] = 'Pression';
|
||||||
$a->strings['Wind'] = 'Vent';
|
$a->strings['Wind'] = 'Vent';
|
||||||
$a->strings['Last Updated'] = 'Dernière mise à jour';
|
$a->strings['Last Updated'] = 'Dernière mise-à-jour';
|
||||||
$a->strings['Data by'] = 'Données de';
|
$a->strings['Data by'] = 'Données de';
|
||||||
$a->strings['Show on map'] = 'Montrer sur la carte';
|
$a->strings['Show on map'] = 'Montrer sur la carte';
|
||||||
$a->strings['There was a problem accessing the weather data. But have a look'] = 'Une erreur est survenue lors de l\'accès aux données météo. Vous pouvez quand même jeter un oeil';
|
$a->strings['There was a problem accessing the weather data. But have a look'] = 'Une erreur est survenue lors de l\'accès aux données météo. Vous pouvez quand même jeter un oeil';
|
||||||
|
|
|
@ -5,27 +5,27 @@
|
||||||
#
|
#
|
||||||
# Translators:
|
# Translators:
|
||||||
# fabrixxm <fabrix.xm@gmail.com>, 2014-2015
|
# fabrixxm <fabrix.xm@gmail.com>, 2014-2015
|
||||||
# Sylke Vicious <silkevicious@gmail.com>, 2021,2023
|
# Sylke Vicious <silkevicious@gmail.com>, 2021
|
||||||
# Tobias Diekershoff <tobias.diekershoff@gmx.net>, 2016
|
# Tobias Diekershoff <tobias.diekershoff@gmx.net>, 2016
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: friendica\n"
|
"Project-Id-Version: friendica\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2021-11-21 19:14-0500\n"
|
"POT-Creation-Date: 2021-02-01 18:15+0100\n"
|
||||||
"PO-Revision-Date: 2014-06-22 11:34+0000\n"
|
"PO-Revision-Date: 2021-02-16 12:57+0000\n"
|
||||||
"Last-Translator: Sylke Vicious <silkevicious@gmail.com>, 2021,2023\n"
|
"Last-Translator: Sylke Vicious <silkevicious@gmail.com>\n"
|
||||||
"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n"
|
"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Language: it\n"
|
"Language: it\n"
|
||||||
"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
#: curweather.php:47
|
#: curweather.php:47
|
||||||
msgid "Error fetching weather data. Error was: "
|
msgid "Error fetching weather data. Error was: "
|
||||||
msgstr "Errore durante il recupero dei dati meteo. L'errore è stato:"
|
msgstr "Errore durante il recupero dei dati meteo. L'errore è stato:"
|
||||||
|
|
||||||
#: curweather.php:130
|
#: curweather.php:130 curweather.php:192
|
||||||
msgid "Current Weather"
|
msgid "Current Weather"
|
||||||
msgstr "Meteo"
|
msgstr "Meteo"
|
||||||
|
|
||||||
|
@ -61,66 +61,66 @@ msgstr "C'è stato un problema accedendo ai dati meteo, ma dai un'occhiata"
|
||||||
msgid "at OpenWeatherMap"
|
msgid "at OpenWeatherMap"
|
||||||
msgstr "a OpenWeatherMap"
|
msgstr "a OpenWeatherMap"
|
||||||
|
|
||||||
#: curweather.php:178
|
#: curweather.php:179
|
||||||
msgid "No APPID found, please contact your admin to obtain one."
|
msgid "No APPID found, please contact your admin to obtain one."
|
||||||
msgstr "APPID non trovata, contatta il tuo amministratore per averne una."
|
msgstr "APPID non trovata, contatta il tuo amministratore per averne una."
|
||||||
|
|
||||||
#: curweather.php:188
|
#: curweather.php:191 curweather.php:229
|
||||||
|
msgid "Save Settings"
|
||||||
|
msgstr "Salva Impostazioni"
|
||||||
|
|
||||||
|
#: curweather.php:192
|
||||||
|
msgid "Settings"
|
||||||
|
msgstr "Impostazioni"
|
||||||
|
|
||||||
|
#: curweather.php:194
|
||||||
msgid "Enter either the name of your location or the zip code."
|
msgid "Enter either the name of your location or the zip code."
|
||||||
msgstr "Inserisci il nome della tua posizione o il CAP"
|
msgstr "Inserisci il nome della tua posizione o il CAP"
|
||||||
|
|
||||||
#: curweather.php:189
|
#: curweather.php:195
|
||||||
msgid "Your Location"
|
msgid "Your Location"
|
||||||
msgstr "La tua Posizione"
|
msgstr "La tua Posizione"
|
||||||
|
|
||||||
#: curweather.php:189
|
#: curweather.php:195
|
||||||
msgid ""
|
msgid ""
|
||||||
"Identifier of your location (name or zip code), e.g. <em>Berlin,DE</em> or "
|
"Identifier of your location (name or zip code), e.g. <em>Berlin,DE</em> or "
|
||||||
"<em>14476,DE</em>."
|
"<em>14476,DE</em>."
|
||||||
msgstr "Identificatore della tua posizione (nome o CAP), p.e. <em>Roma, IT</em> or <em>00186,IT</em>."
|
msgstr "Identificatore della tua posizione (nome o CAP), p.e. <em>Roma, IT</em> or <em>00186,IT</em>."
|
||||||
|
|
||||||
#: curweather.php:190
|
#: curweather.php:196
|
||||||
msgid "Units"
|
msgid "Units"
|
||||||
msgstr "Unità"
|
msgstr "Unità"
|
||||||
|
|
||||||
#: curweather.php:190
|
#: curweather.php:196
|
||||||
msgid "select if the temperature should be displayed in °C or °F"
|
msgid "select if the temperature should be displayed in °C or °F"
|
||||||
msgstr "scegli se la temperatura deve essere mostrata in °C o in °F"
|
msgstr "scegli se la temperatura deve essere mostrata in °C o in °F"
|
||||||
|
|
||||||
#: curweather.php:191
|
#: curweather.php:197
|
||||||
msgid "Show weather data"
|
msgid "Show weather data"
|
||||||
msgstr "Mostra dati meteo"
|
msgstr "Mostra dati meteo"
|
||||||
|
|
||||||
#: curweather.php:196
|
#: curweather.php:232
|
||||||
msgid "Current Weather Settings"
|
|
||||||
msgstr "Impostazioni Meteo"
|
|
||||||
|
|
||||||
#: curweather.php:227
|
|
||||||
msgid "Save Settings"
|
|
||||||
msgstr "Salva Impostazioni"
|
|
||||||
|
|
||||||
#: curweather.php:230
|
|
||||||
msgid "Caching Interval"
|
msgid "Caching Interval"
|
||||||
msgstr "Intervallo di cache"
|
msgstr "Intervallo di cache"
|
||||||
|
|
||||||
#: curweather.php:232
|
#: curweather.php:234
|
||||||
msgid ""
|
msgid ""
|
||||||
"For how long should the weather data be cached? Choose according your "
|
"For how long should the weather data be cached? Choose according your "
|
||||||
"OpenWeatherMap account type."
|
"OpenWeatherMap account type."
|
||||||
msgstr "Per quanto tempo i dati meteo devono essere memorizzati? Scegli a seconda del tuo tipo di account su OpenWeatherMap."
|
msgstr "Per quanto tempo i dati meteo devono essere memorizzati? Scegli a seconda del tuo tipo di account su OpenWeatherMap."
|
||||||
|
|
||||||
#: curweather.php:233
|
#: curweather.php:235
|
||||||
msgid "no cache"
|
msgid "no cache"
|
||||||
msgstr "nessuna cache"
|
msgstr "nessuna cache"
|
||||||
|
|
||||||
#: curweather.php:234 curweather.php:235 curweather.php:236 curweather.php:237
|
#: curweather.php:236 curweather.php:237 curweather.php:238 curweather.php:239
|
||||||
msgid "minutes"
|
msgid "minutes"
|
||||||
msgstr "minuti"
|
msgstr "minuti"
|
||||||
|
|
||||||
#: curweather.php:240
|
#: curweather.php:242
|
||||||
msgid "Your APPID"
|
msgid "Your APPID"
|
||||||
msgstr "Il tuo APPID"
|
msgstr "Il tuo APPID"
|
||||||
|
|
||||||
#: curweather.php:240
|
#: curweather.php:242
|
||||||
msgid "Your API key provided by OpenWeatherMap"
|
msgid "Your API key provided by OpenWeatherMap"
|
||||||
msgstr "La tua chiave API da OpenWeatherMap"
|
msgstr "La tua chiave API da OpenWeatherMap"
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
if(! function_exists("string_plural_select_it")) {
|
if(! function_exists("string_plural_select_it")) {
|
||||||
function string_plural_select_it($n){
|
function string_plural_select_it($n){
|
||||||
$n = intval($n);
|
$n = intval($n);
|
||||||
if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; }
|
return intval($n != 1);
|
||||||
}}
|
}}
|
||||||
$a->strings['Error fetching weather data. Error was: '] = 'Errore durante il recupero dei dati meteo. L\'errore è stato:';
|
$a->strings['Error fetching weather data. Error was: '] = 'Errore durante il recupero dei dati meteo. L\'errore è stato:';
|
||||||
$a->strings['Current Weather'] = 'Meteo';
|
$a->strings['Current Weather'] = 'Meteo';
|
||||||
|
@ -16,14 +16,14 @@ $a->strings['Show on map'] = 'Mostra sulla mappa';
|
||||||
$a->strings['There was a problem accessing the weather data. But have a look'] = 'C\'è stato un problema accedendo ai dati meteo, ma dai un\'occhiata';
|
$a->strings['There was a problem accessing the weather data. But have a look'] = 'C\'è stato un problema accedendo ai dati meteo, ma dai un\'occhiata';
|
||||||
$a->strings['at OpenWeatherMap'] = 'a OpenWeatherMap';
|
$a->strings['at OpenWeatherMap'] = 'a OpenWeatherMap';
|
||||||
$a->strings['No APPID found, please contact your admin to obtain one.'] = 'APPID non trovata, contatta il tuo amministratore per averne una.';
|
$a->strings['No APPID found, please contact your admin to obtain one.'] = 'APPID non trovata, contatta il tuo amministratore per averne una.';
|
||||||
|
$a->strings['Save Settings'] = 'Salva Impostazioni';
|
||||||
|
$a->strings['Settings'] = 'Impostazioni';
|
||||||
$a->strings['Enter either the name of your location or the zip code.'] = 'Inserisci il nome della tua posizione o il CAP';
|
$a->strings['Enter either the name of your location or the zip code.'] = 'Inserisci il nome della tua posizione o il CAP';
|
||||||
$a->strings['Your Location'] = 'La tua Posizione';
|
$a->strings['Your Location'] = 'La tua Posizione';
|
||||||
$a->strings['Identifier of your location (name or zip code), e.g. <em>Berlin,DE</em> or <em>14476,DE</em>.'] = 'Identificatore della tua posizione (nome o CAP), p.e. <em>Roma, IT</em> or <em>00186,IT</em>.';
|
$a->strings['Identifier of your location (name or zip code), e.g. <em>Berlin,DE</em> or <em>14476,DE</em>.'] = 'Identificatore della tua posizione (nome o CAP), p.e. <em>Roma, IT</em> or <em>00186,IT</em>.';
|
||||||
$a->strings['Units'] = 'Unità';
|
$a->strings['Units'] = 'Unità';
|
||||||
$a->strings['select if the temperature should be displayed in °C or °F'] = 'scegli se la temperatura deve essere mostrata in °C o in °F';
|
$a->strings['select if the temperature should be displayed in °C or °F'] = 'scegli se la temperatura deve essere mostrata in °C o in °F';
|
||||||
$a->strings['Show weather data'] = 'Mostra dati meteo';
|
$a->strings['Show weather data'] = 'Mostra dati meteo';
|
||||||
$a->strings['Current Weather Settings'] = 'Impostazioni Meteo';
|
|
||||||
$a->strings['Save Settings'] = 'Salva Impostazioni';
|
|
||||||
$a->strings['Caching Interval'] = 'Intervallo di cache';
|
$a->strings['Caching Interval'] = 'Intervallo di cache';
|
||||||
$a->strings['For how long should the weather data be cached? Choose according your OpenWeatherMap account type.'] = 'Per quanto tempo i dati meteo devono essere memorizzati? Scegli a seconda del tuo tipo di account su OpenWeatherMap.';
|
$a->strings['For how long should the weather data be cached? Choose according your OpenWeatherMap account type.'] = 'Per quanto tempo i dati meteo devono essere memorizzati? Scegli a seconda del tuo tipo di account su OpenWeatherMap.';
|
||||||
$a->strings['no cache'] = 'nessuna cache';
|
$a->strings['no cache'] = 'nessuna cache';
|
||||||
|
|
|
@ -5,41 +5,45 @@
|
||||||
#
|
#
|
||||||
# Translators:
|
# Translators:
|
||||||
# fabrixxm <fabrix.xm@gmail.com>, 2014,2018
|
# fabrixxm <fabrix.xm@gmail.com>, 2014,2018
|
||||||
# Sylke Vicious <silkevicious@gmail.com>, 2020-2021,2023
|
# Sylke Vicious <silkevicious@gmail.com>, 2020-2021
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: friendica\n"
|
"Project-Id-Version: friendica\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2021-11-21 19:17-0500\n"
|
"POT-Creation-Date: 2021-02-01 18:15+0100\n"
|
||||||
"PO-Revision-Date: 2014-06-22 11:41+0000\n"
|
"PO-Revision-Date: 2021-02-16 12:55+0000\n"
|
||||||
"Last-Translator: Sylke Vicious <silkevicious@gmail.com>, 2020-2021,2023\n"
|
"Last-Translator: Sylke Vicious <silkevicious@gmail.com>\n"
|
||||||
"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n"
|
"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Language: it\n"
|
"Language: it\n"
|
||||||
"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
#: dwpost.php:43
|
#: dwpost.php:41
|
||||||
msgid "Post to Dreamwidth"
|
msgid "Post to Dreamwidth"
|
||||||
msgstr "Invia a Dreamwidth"
|
msgstr "Invia a Dreamwidth"
|
||||||
|
|
||||||
#: dwpost.php:63
|
#: dwpost.php:72 dwpost.php:76
|
||||||
msgid "Enable Dreamwidth Post Addon"
|
|
||||||
msgstr "Abilita il componente aggiuntivo di pubblicazione Dreamwidth"
|
|
||||||
|
|
||||||
#: dwpost.php:64
|
|
||||||
msgid "Dreamwidth username"
|
|
||||||
msgstr "Nome utente Dreamwidth"
|
|
||||||
|
|
||||||
#: dwpost.php:65
|
|
||||||
msgid "Dreamwidth password"
|
|
||||||
msgstr "Password Dreamwidth"
|
|
||||||
|
|
||||||
#: dwpost.php:66
|
|
||||||
msgid "Post to Dreamwidth by default"
|
|
||||||
msgstr "Pubblica su dreamwidth per impostazione predefinita"
|
|
||||||
|
|
||||||
#: dwpost.php:71
|
|
||||||
msgid "Dreamwidth Export"
|
msgid "Dreamwidth Export"
|
||||||
msgstr "Esporta Dreamwidth"
|
msgstr "Esporta Dreamwidth"
|
||||||
|
|
||||||
|
#: dwpost.php:80
|
||||||
|
msgid "Enable dreamwidth Post Addon"
|
||||||
|
msgstr "Abilita il componente aggiuntivo di invio a Dreamwidth"
|
||||||
|
|
||||||
|
#: dwpost.php:85
|
||||||
|
msgid "dreamwidth username"
|
||||||
|
msgstr "Nome utente Dreamwidth"
|
||||||
|
|
||||||
|
#: dwpost.php:90
|
||||||
|
msgid "dreamwidth password"
|
||||||
|
msgstr "password Dreamwidth"
|
||||||
|
|
||||||
|
#: dwpost.php:95
|
||||||
|
msgid "Post to dreamwidth by default"
|
||||||
|
msgstr "Invia sempre a Dreamwidth"
|
||||||
|
|
||||||
|
#: dwpost.php:100
|
||||||
|
msgid "Save Settings"
|
||||||
|
msgstr "Salva Impostazioni"
|
||||||
|
|
|
@ -3,11 +3,12 @@
|
||||||
if(! function_exists("string_plural_select_it")) {
|
if(! function_exists("string_plural_select_it")) {
|
||||||
function string_plural_select_it($n){
|
function string_plural_select_it($n){
|
||||||
$n = intval($n);
|
$n = intval($n);
|
||||||
if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; }
|
return intval($n != 1);
|
||||||
}}
|
}}
|
||||||
$a->strings['Post to Dreamwidth'] = 'Invia a Dreamwidth';
|
$a->strings['Post to Dreamwidth'] = 'Invia a Dreamwidth';
|
||||||
$a->strings['Enable Dreamwidth Post Addon'] = 'Abilita il componente aggiuntivo di pubblicazione Dreamwidth';
|
|
||||||
$a->strings['Dreamwidth username'] = 'Nome utente Dreamwidth';
|
|
||||||
$a->strings['Dreamwidth password'] = 'Password Dreamwidth';
|
|
||||||
$a->strings['Post to Dreamwidth by default'] = 'Pubblica su dreamwidth per impostazione predefinita';
|
|
||||||
$a->strings['Dreamwidth Export'] = 'Esporta Dreamwidth';
|
$a->strings['Dreamwidth Export'] = 'Esporta Dreamwidth';
|
||||||
|
$a->strings['Enable dreamwidth Post Addon'] = 'Abilita il componente aggiuntivo di invio a Dreamwidth';
|
||||||
|
$a->strings['dreamwidth username'] = 'Nome utente Dreamwidth';
|
||||||
|
$a->strings['dreamwidth password'] = 'password Dreamwidth';
|
||||||
|
$a->strings['Post to dreamwidth by default'] = 'Invia sempre a Dreamwidth';
|
||||||
|
$a->strings['Save Settings'] = 'Salva Impostazioni';
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
* Note: Please use Group Directory instead
|
* Note: Please use Group Directory instead
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use Friendica\App;
|
||||||
use Friendica\Content\Nav;
|
use Friendica\Content\Nav;
|
||||||
use Friendica\Content\Pager;
|
use Friendica\Content\Pager;
|
||||||
use Friendica\Content\Widget;
|
use Friendica\Content\Widget;
|
||||||
|
@ -15,8 +16,8 @@ use Friendica\Core\Hook;
|
||||||
use Friendica\Core\Renderer;
|
use Friendica\Core\Renderer;
|
||||||
use Friendica\Database\DBA;
|
use Friendica\Database\DBA;
|
||||||
use Friendica\DI;
|
use Friendica\DI;
|
||||||
|
use Friendica\Model\Profile;
|
||||||
use Friendica\Model\User;
|
use Friendica\Model\User;
|
||||||
use Friendica\Security\OpenWebAuth;
|
|
||||||
|
|
||||||
global $forumdirectory_search;
|
global $forumdirectory_search;
|
||||||
|
|
||||||
|
@ -81,7 +82,7 @@ function forumdirectory_content()
|
||||||
$gdirpath = '';
|
$gdirpath = '';
|
||||||
$dirurl = DI::config()->get('system', 'directory');
|
$dirurl = DI::config()->get('system', 'directory');
|
||||||
if (strlen($dirurl)) {
|
if (strlen($dirurl)) {
|
||||||
$gdirpath = OpenWebAuth::getZrlUrl($dirurl, true);
|
$gdirpath = Profile::zrl($dirurl, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$sql_extra = '';
|
$sql_extra = '';
|
||||||
|
@ -103,8 +104,8 @@ function forumdirectory_content()
|
||||||
$total = 0;
|
$total = 0;
|
||||||
$cnt = DBA::fetchFirst("SELECT COUNT(*) AS `total` FROM `profile`
|
$cnt = DBA::fetchFirst("SELECT COUNT(*) AS `total` FROM `profile`
|
||||||
INNER JOIN `user` ON `user`.`uid` = `profile`.`uid`
|
INNER JOIN `user` ON `user`.`uid` = `profile`.`uid`
|
||||||
WHERE $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` AND `user`.`page-flags` IN (?, ?) $sql_extra",
|
WHERE $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` AND `user`.`page-flags` = ? $sql_extra",
|
||||||
User::PAGE_FLAGS_COMMUNITY, User::PAGE_FLAGS_COMM_MAN);
|
User::PAGE_FLAGS_COMMUNITY);
|
||||||
if (DBA::isResult($cnt)) {
|
if (DBA::isResult($cnt)) {
|
||||||
$total = $cnt['total'];
|
$total = $cnt['total'];
|
||||||
}
|
}
|
||||||
|
@ -119,8 +120,8 @@ function forumdirectory_content()
|
||||||
`contact`.`addr`, `contact`.`url` FROM `profile`
|
`contact`.`addr`, `contact`.`url` FROM `profile`
|
||||||
INNER JOIN `user` ON `user`.`uid` = `profile`.`uid`
|
INNER JOIN `user` ON `user`.`uid` = `profile`.`uid`
|
||||||
INNER JOIN `contact` ON `contact`.`uid` = `user`.`uid`
|
INNER JOIN `contact` ON `contact`.`uid` = `user`.`uid`
|
||||||
WHERE $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` AND `user`.`page-flags` IN (?, ?) AND `contact`.`self`
|
WHERE $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` AND `user`.`page-flags` = ? AND `contact`.`self`
|
||||||
$sql_extra $order LIMIT $limit", User::PAGE_FLAGS_COMMUNITY, User::PAGE_FLAGS_COMM_MAN
|
$sql_extra $order LIMIT $limit", User::PAGE_FLAGS_COMMUNITY
|
||||||
);
|
);
|
||||||
|
|
||||||
if (DBA::isResult($r)) {
|
if (DBA::isResult($r)) {
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
# Translators:
|
# Translators:
|
||||||
# bob lebonche <lebonche@tutanota.com>, 2021
|
# bob lebonche <lebonche@tutanota.com>, 2021
|
||||||
# ButterflyOfFire, 2020
|
# ButterflyOfFire, 2020
|
||||||
# cracrayol, 2024
|
|
||||||
# Hypolite Petovan <hypolite@mrpetovan.com>, 2016
|
# Hypolite Petovan <hypolite@mrpetovan.com>, 2016
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -14,8 +13,8 @@ msgstr ""
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2021-11-21 19:14-0500\n"
|
"POT-Creation-Date: 2021-11-21 19:14-0500\n"
|
||||||
"PO-Revision-Date: 2014-06-23 08:27+0000\n"
|
"PO-Revision-Date: 2014-06-23 08:27+0000\n"
|
||||||
"Last-Translator: cracrayol, 2024\n"
|
"Last-Translator: bob lebonche <lebonche@tutanota.com>, 2021\n"
|
||||||
"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n"
|
"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
@ -30,7 +29,7 @@ msgstr "Remplacer les coordonnées par le nom de la localité la plus proche dan
|
||||||
|
|
||||||
#: geonames.php:136
|
#: geonames.php:136
|
||||||
msgid "Enable Geonames Addon"
|
msgid "Enable Geonames Addon"
|
||||||
msgstr "Activer l'extension Geonames"
|
msgstr "Activer l'application complémentaire Geonames"
|
||||||
|
|
||||||
#: geonames.php:141
|
#: geonames.php:141
|
||||||
msgid "Geonames Settings"
|
msgid "Geonames Settings"
|
||||||
|
|
|
@ -6,5 +6,5 @@ function string_plural_select_fr($n){
|
||||||
if (($n == 0 || $n == 1)) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; }
|
if (($n == 0 || $n == 1)) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; }
|
||||||
}}
|
}}
|
||||||
$a->strings['Replace numerical coordinates by the nearest populated location name in your posts.'] = 'Remplacer les coordonnées par le nom de la localité la plus proche dans votre publication.';
|
$a->strings['Replace numerical coordinates by the nearest populated location name in your posts.'] = 'Remplacer les coordonnées par le nom de la localité la plus proche dans votre publication.';
|
||||||
$a->strings['Enable Geonames Addon'] = 'Activer l\'extension Geonames';
|
$a->strings['Enable Geonames Addon'] = 'Activer l\'application complémentaire Geonames';
|
||||||
$a->strings['Geonames Settings'] = 'Paramètres Geonames';
|
$a->strings['Geonames Settings'] = 'Paramètres Geonames';
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
# Translators:
|
# Translators:
|
||||||
# bob lebonche <lebonche@tutanota.com>, 2021
|
# bob lebonche <lebonche@tutanota.com>, 2021
|
||||||
# ButterflyOfFire, 2020
|
# ButterflyOfFire, 2020
|
||||||
# cracrayol, 2024
|
|
||||||
# Hypolite Petovan <hypolite@mrpetovan.com>, 2016
|
# Hypolite Petovan <hypolite@mrpetovan.com>, 2016
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -14,8 +13,8 @@ msgstr ""
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2021-11-21 19:14-0500\n"
|
"POT-Creation-Date: 2021-11-21 19:14-0500\n"
|
||||||
"PO-Revision-Date: 2014-06-23 08:30+0000\n"
|
"PO-Revision-Date: 2014-06-23 08:30+0000\n"
|
||||||
"Last-Translator: cracrayol, 2024\n"
|
"Last-Translator: bob lebonche <lebonche@tutanota.com>, 2021\n"
|
||||||
"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n"
|
"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
@ -30,7 +29,7 @@ msgstr "Permettre le filtrage des notifications de commentaires par courriel sur
|
||||||
|
|
||||||
#: gnot.php:64
|
#: gnot.php:64
|
||||||
msgid "Enable this addon?"
|
msgid "Enable this addon?"
|
||||||
msgstr "Activer cette extension ?"
|
msgstr "Activer cette application complémentaire ?"
|
||||||
|
|
||||||
#: gnot.php:69
|
#: gnot.php:69
|
||||||
msgid "Gnot Settings"
|
msgid "Gnot Settings"
|
||||||
|
|
|
@ -6,6 +6,6 @@ function string_plural_select_fr($n){
|
||||||
if (($n == 0 || $n == 1)) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; }
|
if (($n == 0 || $n == 1)) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; }
|
||||||
}}
|
}}
|
||||||
$a->strings['Allows threading of email comment notifications on Gmail and anonymising the subject line.'] = 'Permettre le filtrage des notifications de commentaires par courriel sur Gmail et l\'anonymisation de l\'objet.';
|
$a->strings['Allows threading of email comment notifications on Gmail and anonymising the subject line.'] = 'Permettre le filtrage des notifications de commentaires par courriel sur Gmail et l\'anonymisation de l\'objet.';
|
||||||
$a->strings['Enable this addon?'] = 'Activer cette extension ?';
|
$a->strings['Enable this addon?'] = 'Activer cette application complémentaire ?';
|
||||||
$a->strings['Gnot Settings'] = 'Paramètres Gnot';
|
$a->strings['Gnot Settings'] = 'Paramètres Gnot';
|
||||||
$a->strings['[Friendica:Notify] Comment to conversation #%d'] = '[Friendica:Notify] Commentaire vers conversation #%d';
|
$a->strings['[Friendica:Notify] Comment to conversation #%d'] = '[Friendica:Notify] Commentaire vers conversation #%d';
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#
|
#
|
||||||
# Translators:
|
# Translators:
|
||||||
# bob lebonche <lebonche@tutanota.com>, 2021
|
# bob lebonche <lebonche@tutanota.com>, 2021
|
||||||
# cracrayol, 2024
|
|
||||||
# Marie Olive <lacellule101@gmail.com>, 2018
|
# Marie Olive <lacellule101@gmail.com>, 2018
|
||||||
# ea1cd8241cb389ffb6f92bc6891eff5d_dc12308 <70dced5587d47e18d88f9298024d96f8_93383>, 2015
|
# ea1cd8241cb389ffb6f92bc6891eff5d_dc12308 <70dced5587d47e18d88f9298024d96f8_93383>, 2015
|
||||||
msgid ""
|
msgid ""
|
||||||
|
@ -14,8 +13,8 @@ msgstr ""
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2021-02-01 18:15+0100\n"
|
"POT-Creation-Date: 2021-02-01 18:15+0100\n"
|
||||||
"PO-Revision-Date: 2014-06-23 08:33+0000\n"
|
"PO-Revision-Date: 2014-06-23 08:33+0000\n"
|
||||||
"Last-Translator: cracrayol, 2024\n"
|
"Last-Translator: bob lebonche <lebonche@tutanota.com>, 2021\n"
|
||||||
"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n"
|
"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
@ -51,7 +50,7 @@ msgid ""
|
||||||
"Libravatar addon is installed, too. Please disable Libravatar addon or this "
|
"Libravatar addon is installed, too. Please disable Libravatar addon or this "
|
||||||
"Gravatar addon.<br>The Libravatar addon will fall back to Gravatar if "
|
"Gravatar addon.<br>The Libravatar addon will fall back to Gravatar if "
|
||||||
"nothing was found at Libravatar."
|
"nothing was found at Libravatar."
|
||||||
msgstr "L'extension Libravatar est aussi installée. Merci de désactiver l'extension Libravatar ou cette extension Gravatar. L'extension se repliera sur Gravatar si rien n'est trouvé dans Libravatar."
|
msgstr "L'application complémentaire Libravatar est aussi installée. Merci de désactiver l'application complémentaire Libravatar ou cette application complémentaire Gravatar. L'application complémentaire se repliera sur Gravatar si rien n'est trouvé dans Libravatar."
|
||||||
|
|
||||||
#: gravatar.php:102
|
#: gravatar.php:102
|
||||||
msgid "Save Settings"
|
msgid "Save Settings"
|
||||||
|
|
|
@ -11,7 +11,7 @@ $a->strings['monster face'] = 'Face de monstre';
|
||||||
$a->strings['computer generated face'] = 'visage généré par ordinateur';
|
$a->strings['computer generated face'] = 'visage généré par ordinateur';
|
||||||
$a->strings['retro arcade style face'] = 'Face style retro arcade';
|
$a->strings['retro arcade style face'] = 'Face style retro arcade';
|
||||||
$a->strings['Information'] = 'Information';
|
$a->strings['Information'] = 'Information';
|
||||||
$a->strings['Libravatar addon is installed, too. Please disable Libravatar addon or this Gravatar addon.<br>The Libravatar addon will fall back to Gravatar if nothing was found at Libravatar.'] = 'L\'extension Libravatar est aussi installée. Merci de désactiver l\'extension Libravatar ou cette extension Gravatar. L\'extension se repliera sur Gravatar si rien n\'est trouvé dans Libravatar.';
|
$a->strings['Libravatar addon is installed, too. Please disable Libravatar addon or this Gravatar addon.<br>The Libravatar addon will fall back to Gravatar if nothing was found at Libravatar.'] = 'L\'application complémentaire Libravatar est aussi installée. Merci de désactiver l\'application complémentaire Libravatar ou cette application complémentaire Gravatar. L\'application complémentaire se repliera sur Gravatar si rien n\'est trouvé dans Libravatar.';
|
||||||
$a->strings['Save Settings'] = 'Sauvegarder les paramètres.';
|
$a->strings['Save Settings'] = 'Sauvegarder les paramètres.';
|
||||||
$a->strings['Default avatar image'] = 'Image par défaut d\'avatar';
|
$a->strings['Default avatar image'] = 'Image par défaut d\'avatar';
|
||||||
$a->strings['Select default avatar image if none was found at Gravatar. See README'] = 'Sélectionner l\'avatar par défaut, si aucun n\'est trouvé sur Gravatar. Voir Lisezmoi.';
|
$a->strings['Select default avatar image if none was found at Gravatar. See README'] = 'Sélectionner l\'avatar par défaut, si aucun n\'est trouvé sur Gravatar. Voir Lisezmoi.';
|
||||||
|
|
|
@ -13,8 +13,8 @@ use Friendica\Core\Hook;
|
||||||
use Friendica\Core\Renderer;
|
use Friendica\Core\Renderer;
|
||||||
use Friendica\Database\DBA;
|
use Friendica\Database\DBA;
|
||||||
use Friendica\DI;
|
use Friendica\DI;
|
||||||
|
use Friendica\Model\Profile;
|
||||||
use Friendica\Model\User;
|
use Friendica\Model\User;
|
||||||
use Friendica\Security\OpenWebAuth;
|
|
||||||
|
|
||||||
global $groupdirectory_search;
|
global $groupdirectory_search;
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ function groupdirectory_content()
|
||||||
$gdirpath = '';
|
$gdirpath = '';
|
||||||
$dirurl = DI::config()->get('system', 'directory');
|
$dirurl = DI::config()->get('system', 'directory');
|
||||||
if (strlen($dirurl)) {
|
if (strlen($dirurl)) {
|
||||||
$gdirpath = OpenWebAuth::getZrlUrl($dirurl, true);
|
$gdirpath = Profile::zrl($dirurl, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$sql_extra = '';
|
$sql_extra = '';
|
||||||
|
@ -101,8 +101,8 @@ function groupdirectory_content()
|
||||||
$total = 0;
|
$total = 0;
|
||||||
$cnt = DBA::fetchFirst("SELECT COUNT(*) AS `total` FROM `profile`
|
$cnt = DBA::fetchFirst("SELECT COUNT(*) AS `total` FROM `profile`
|
||||||
INNER JOIN `user` ON `user`.`uid` = `profile`.`uid`
|
INNER JOIN `user` ON `user`.`uid` = `profile`.`uid`
|
||||||
WHERE $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` AND `user`.`page-flags` IN (?, ?) $sql_extra",
|
WHERE $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` AND `user`.`page-flags` = ? $sql_extra",
|
||||||
User::PAGE_FLAGS_COMMUNITY, User::PAGE_FLAGS_COMM_MAN);
|
User::PAGE_FLAGS_COMMUNITY);
|
||||||
if (DBA::isResult($cnt)) {
|
if (DBA::isResult($cnt)) {
|
||||||
$total = $cnt['total'];
|
$total = $cnt['total'];
|
||||||
}
|
}
|
||||||
|
@ -117,8 +117,8 @@ function groupdirectory_content()
|
||||||
`contact`.`addr`, `contact`.`url` FROM `profile`
|
`contact`.`addr`, `contact`.`url` FROM `profile`
|
||||||
INNER JOIN `user` ON `user`.`uid` = `profile`.`uid`
|
INNER JOIN `user` ON `user`.`uid` = `profile`.`uid`
|
||||||
INNER JOIN `contact` ON `contact`.`uid` = `user`.`uid`
|
INNER JOIN `contact` ON `contact`.`uid` = `user`.`uid`
|
||||||
WHERE $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` AND `user`.`page-flags` IN (?, ?) AND `contact`.`self`
|
WHERE $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` AND `user`.`page-flags` = ? AND `contact`.`self`
|
||||||
$sql_extra $order LIMIT $limit", User::PAGE_FLAGS_COMMUNITY, User::PAGE_FLAGS_COMM_MAN
|
$sql_extra $order LIMIT $limit", User::PAGE_FLAGS_COMMUNITY
|
||||||
);
|
);
|
||||||
|
|
||||||
if (DBA::isResult($r)) {
|
if (DBA::isResult($r)) {
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#
|
#
|
||||||
# Translators:
|
# Translators:
|
||||||
# bob lebonche <lebonche@tutanota.com>, 2021
|
# bob lebonche <lebonche@tutanota.com>, 2021
|
||||||
# cracrayol, 2024
|
|
||||||
# Hypolite Petovan <hypolite@mrpetovan.com>, 2016
|
# Hypolite Petovan <hypolite@mrpetovan.com>, 2016
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -13,8 +12,8 @@ msgstr ""
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2021-11-21 19:17-0500\n"
|
"POT-Creation-Date: 2021-11-21 19:17-0500\n"
|
||||||
"PO-Revision-Date: 2014-06-23 08:37+0000\n"
|
"PO-Revision-Date: 2014-06-23 08:37+0000\n"
|
||||||
"Last-Translator: cracrayol, 2024\n"
|
"Last-Translator: bob lebonche <lebonche@tutanota.com>, 2021\n"
|
||||||
"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n"
|
"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
@ -27,7 +26,7 @@ msgstr "Publier sur Insanejournal"
|
||||||
|
|
||||||
#: ijpost.php:61
|
#: ijpost.php:61
|
||||||
msgid "Enable InsaneJournal Post Addon"
|
msgid "Enable InsaneJournal Post Addon"
|
||||||
msgstr "Activer l'extension InsaneJournal"
|
msgstr "Activer l'application complémentaire InsaneJournalPost"
|
||||||
|
|
||||||
#: ijpost.php:62
|
#: ijpost.php:62
|
||||||
msgid "InsaneJournal username"
|
msgid "InsaneJournal username"
|
||||||
|
|
|
@ -6,7 +6,7 @@ function string_plural_select_fr($n){
|
||||||
if (($n == 0 || $n == 1)) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; }
|
if (($n == 0 || $n == 1)) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; }
|
||||||
}}
|
}}
|
||||||
$a->strings['Post to Insanejournal'] = 'Publier sur Insanejournal';
|
$a->strings['Post to Insanejournal'] = 'Publier sur Insanejournal';
|
||||||
$a->strings['Enable InsaneJournal Post Addon'] = 'Activer l\'extension InsaneJournal';
|
$a->strings['Enable InsaneJournal Post Addon'] = 'Activer l\'application complémentaire InsaneJournalPost';
|
||||||
$a->strings['InsaneJournal username'] = 'Identifiant du InsaneJournal';
|
$a->strings['InsaneJournal username'] = 'Identifiant du InsaneJournal';
|
||||||
$a->strings['InsaneJournal password'] = 'Mot de passe du InsaneJournal';
|
$a->strings['InsaneJournal password'] = 'Mot de passe du InsaneJournal';
|
||||||
$a->strings['Post to InsaneJournal by default'] = 'Publier sur le InsaneJournal par défaut';
|
$a->strings['Post to InsaneJournal by default'] = 'Publier sur le InsaneJournal par défaut';
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
/*
|
/*
|
||||||
* Name: invidious
|
* Name: invidious
|
||||||
* Description: Replaces links to youtube.com to an invidious instance in all displays of postings on a node.
|
* Description: Replaces links to youtube.com to an invidious instance in all displays of postings on a node.
|
||||||
* Version: 0.4
|
* Version: 0.3
|
||||||
* Author: Matthias Ebers <https://loma.ml/profile/feb>
|
* Author: Matthias Ebers <https://loma.ml/profile/feb>
|
||||||
* Author: Michael Vogel <https://pirati.ca/profile/heluecht>
|
* Author: Michael Vogel <https://pirati.ca/profile/heluecht>
|
||||||
* Status: Unsupported
|
* Status: Unsupported
|
||||||
|
@ -93,11 +93,9 @@ function invidious_render(array &$b)
|
||||||
$original = $b['html'];
|
$original = $b['html'];
|
||||||
$server = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'invidious', 'server', DI::config()->get('invidious', 'server', INVIDIOUS_DEFAULT));
|
$server = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'invidious', 'server', DI::config()->get('invidious', 'server', INVIDIOUS_DEFAULT));
|
||||||
|
|
||||||
$b['html'] = preg_replace("~https?://(?:www\.)?youtube\.com/watch\?v=(.*?)~ism", $server . '/watch?v=$1', $b['html']);
|
$b['html'] = preg_replace("/https?:\/\/www.youtube.com\/watch\?v\=(.*?)/ism", $server . '/watch?v=$1', $b['html']);
|
||||||
$b['html'] = preg_replace("~https?://(?:www\.)?youtube\.com/embed/(.*?)~ism", $server . '/embed/$1', $b['html']);
|
$b['html'] = preg_replace("/https?:\/\/www.youtube.com\/embed\/(.*?)/ism", $server . '/embed/$1', $b['html']);
|
||||||
$b['html'] = preg_replace("~https?://(?:www\.)?youtube\.com/shorts/(.*?)~ism", $server . '/shorts/$1', $b['html']);
|
$b['html'] = preg_replace("/https?:\/\/www.youtube.com\/shorts\/(.*?)/ism", $server . '/shorts/$1', $b['html']);
|
||||||
$b['html'] = preg_replace ("/https?:\/\/music.youtube.com\/(.*?)/ism", $server . '/watch?v=$1', $b['html']);
|
|
||||||
$b['html'] = preg_replace ("/https?:\/\/m.youtube.com\/(.*?)/ism", $server . '/watch?v=$1', $b['html']);
|
|
||||||
$b['html'] = preg_replace("/https?:\/\/youtu.be\/(.*?)/ism", $server . '/watch?v=$1', $b['html']);
|
$b['html'] = preg_replace("/https?:\/\/youtu.be\/(.*?)/ism", $server . '/watch?v=$1', $b['html']);
|
||||||
|
|
||||||
if ($original != $b['html']) {
|
if ($original != $b['html']) {
|
||||||
|
|
|
@ -7,11 +7,11 @@
|
||||||
* Maintainer: Hypolite Petovan <https://friendica.mrpetovan.com/profile/hypolite>
|
* Maintainer: Hypolite Petovan <https://friendica.mrpetovan.com/profile/hypolite>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use Friendica\App;
|
||||||
use Friendica\Core\Hook;
|
use Friendica\Core\Hook;
|
||||||
use Friendica\Core\Logger;
|
use Friendica\Core\Logger;
|
||||||
use Friendica\Core\Renderer;
|
use Friendica\Core\Renderer;
|
||||||
use Friendica\DI;
|
use Friendica\DI;
|
||||||
use Friendica\Util\Images;
|
|
||||||
use Friendica\Util\Strings;
|
use Friendica\Util\Strings;
|
||||||
|
|
||||||
global $js_upload_jsonresponse;
|
global $js_upload_jsonresponse;
|
||||||
|
@ -48,14 +48,7 @@ function js_upload_post_init(array &$b)
|
||||||
global $js_upload_result, $js_upload_jsonresponse;
|
global $js_upload_result, $js_upload_jsonresponse;
|
||||||
|
|
||||||
// list of valid extensions
|
// list of valid extensions
|
||||||
$allowedExtensions = [];
|
$allowedExtensions = ['jpeg', 'gif', 'png', 'jpg'];
|
||||||
foreach (Images::IMAGETYPES as $type) {
|
|
||||||
$extension = image_type_to_extension($type, false);
|
|
||||||
if ($extension == 'jpeg') {
|
|
||||||
$allowedExtensions[] = 'jpg';
|
|
||||||
}
|
|
||||||
$allowedExtensions[] = $extension;
|
|
||||||
}
|
|
||||||
|
|
||||||
// max file size in bytes
|
// max file size in bytes
|
||||||
$sizeLimit = Strings::getBytesFromShorthand(DI::config()->get('system', 'maximagesize'));
|
$sizeLimit = Strings::getBytesFromShorthand(DI::config()->get('system', 'maximagesize'));
|
||||||
|
@ -85,6 +78,7 @@ function js_upload_post_file(array &$b)
|
||||||
$b['src'] = $result['path'];
|
$b['src'] = $result['path'];
|
||||||
$b['filename'] = $result['filename'];
|
$b['filename'] = $result['filename'];
|
||||||
$b['filesize'] = filesize($b['src']);
|
$b['filesize'] = filesize($b['src']);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function js_upload_post_end(int &$b)
|
function js_upload_post_end(int &$b)
|
||||||
|
@ -185,11 +179,11 @@ class qqUploadedFileForm
|
||||||
|
|
||||||
class qqFileUploader
|
class qqFileUploader
|
||||||
{
|
{
|
||||||
private $allowedExtensions;
|
private $allowedExtensions = [];
|
||||||
private $sizeLimit;
|
private $sizeLimit = 10485760;
|
||||||
private $file;
|
private $file;
|
||||||
|
|
||||||
function __construct(array $allowedExtensions = [], $sizeLimit)
|
function __construct(array $allowedExtensions = [], $sizeLimit = 10485760)
|
||||||
{
|
{
|
||||||
$allowedExtensions = array_map('strtolower', $allowedExtensions);
|
$allowedExtensions = array_map('strtolower', $allowedExtensions);
|
||||||
|
|
||||||
|
@ -203,6 +197,7 @@ class qqFileUploader
|
||||||
} else {
|
} else {
|
||||||
$this->file = false;
|
$this->file = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -221,9 +216,11 @@ class qqFileUploader
|
||||||
}
|
}
|
||||||
|
|
||||||
// if ($size > $this->sizeLimit) {
|
// if ($size > $this->sizeLimit) {
|
||||||
|
|
||||||
// return array('error' => DI::l10n()->t('Uploaded file is too large'));
|
// return array('error' => DI::l10n()->t('Uploaded file is too large'));
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
$maximagesize = Strings::getBytesFromShorthand(DI::config()->get('system', 'maximagesize'));
|
$maximagesize = Strings::getBytesFromShorthand(DI::config()->get('system', 'maximagesize'));
|
||||||
|
|
||||||
if (($maximagesize) && ($size > $maximagesize)) {
|
if (($maximagesize) && ($size > $maximagesize)) {
|
||||||
|
|
|
@ -5,15 +5,14 @@
|
||||||
#
|
#
|
||||||
# Translators:
|
# Translators:
|
||||||
# bob lebonche <lebonche@tutanota.com>, 2021
|
# bob lebonche <lebonche@tutanota.com>, 2021
|
||||||
# cracrayol, 2024
|
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: friendica\n"
|
"Project-Id-Version: friendica\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2021-11-21 19:14-0500\n"
|
"POT-Creation-Date: 2021-11-21 19:14-0500\n"
|
||||||
"PO-Revision-Date: 2015-07-07 15:14+0000\n"
|
"PO-Revision-Date: 2015-07-07 15:14+0000\n"
|
||||||
"Last-Translator: cracrayol, 2024\n"
|
"Last-Translator: bob lebonche <lebonche@tutanota.com>, 2021\n"
|
||||||
"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n"
|
"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
@ -22,7 +21,7 @@ msgstr ""
|
||||||
|
|
||||||
#: krynn.php:127
|
#: krynn.php:127
|
||||||
msgid "Enable Krynn Addon"
|
msgid "Enable Krynn Addon"
|
||||||
msgstr "Activer l'extension Krynn"
|
msgstr "Activer l'application complémentaire Krynn"
|
||||||
|
|
||||||
#: krynn.php:132
|
#: krynn.php:132
|
||||||
msgid "Krynn Settings"
|
msgid "Krynn Settings"
|
||||||
|
|
|
@ -5,5 +5,5 @@ function string_plural_select_fr($n){
|
||||||
$n = intval($n);
|
$n = intval($n);
|
||||||
if (($n == 0 || $n == 1)) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; }
|
if (($n == 0 || $n == 1)) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; }
|
||||||
}}
|
}}
|
||||||
$a->strings['Enable Krynn Addon'] = 'Activer l\'extension Krynn';
|
$a->strings['Enable Krynn Addon'] = 'Activer l\'application complémentaire Krynn';
|
||||||
$a->strings['Krynn Settings'] = 'Paramètres de Krynn';
|
$a->strings['Krynn Settings'] = 'Paramètres de Krynn';
|
||||||
|
|
|
@ -5,41 +5,45 @@
|
||||||
#
|
#
|
||||||
# Translators:
|
# Translators:
|
||||||
# fabrixxm <fabrix.xm@gmail.com>, 2014-2015,2018
|
# fabrixxm <fabrix.xm@gmail.com>, 2014-2015,2018
|
||||||
# Sylke Vicious <silkevicious@gmail.com>, 2021,2023
|
# Sylke Vicious <silkevicious@gmail.com>, 2021
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: friendica\n"
|
"Project-Id-Version: friendica\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2023-06-03 15:49-0400\n"
|
"POT-Creation-Date: 2021-02-01 18:15+0100\n"
|
||||||
"PO-Revision-Date: 2014-06-23 09:44+0000\n"
|
"PO-Revision-Date: 2021-02-16 12:47+0000\n"
|
||||||
"Last-Translator: Sylke Vicious <silkevicious@gmail.com>, 2021,2023\n"
|
"Last-Translator: Sylke Vicious <silkevicious@gmail.com>\n"
|
||||||
"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n"
|
"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Language: it\n"
|
"Language: it\n"
|
||||||
"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
#: libertree.php:39
|
#: libertree.php:37
|
||||||
msgid "Post to libertree"
|
msgid "Post to libertree"
|
||||||
msgstr "Invia a Libertree"
|
msgstr "Invia a Libertree"
|
||||||
|
|
||||||
#: libertree.php:59
|
#: libertree.php:71 libertree.php:75
|
||||||
|
msgid "libertree Export"
|
||||||
|
msgstr "Esporta libertree"
|
||||||
|
|
||||||
|
#: libertree.php:79
|
||||||
msgid "Enable Libertree Post Addon"
|
msgid "Enable Libertree Post Addon"
|
||||||
msgstr "Abilita il componente aggiuntivo di invio a Libertree"
|
msgstr "Abilita il componente aggiuntivo di invio a Libertree"
|
||||||
|
|
||||||
#: libertree.php:60
|
#: libertree.php:84
|
||||||
msgid "Libertree site URL"
|
|
||||||
msgstr "Indirizzo sito Libertree"
|
|
||||||
|
|
||||||
#: libertree.php:61
|
|
||||||
msgid "Libertree API token"
|
msgid "Libertree API token"
|
||||||
msgstr "Token API Libertree"
|
msgstr "Token API Libertree"
|
||||||
|
|
||||||
#: libertree.php:62
|
#: libertree.php:89
|
||||||
|
msgid "Libertree site URL"
|
||||||
|
msgstr "Indirizzo sito Libertree"
|
||||||
|
|
||||||
|
#: libertree.php:94
|
||||||
msgid "Post to Libertree by default"
|
msgid "Post to Libertree by default"
|
||||||
msgstr "Invia sempre a Libertree"
|
msgstr "Invia sempre a Libertree"
|
||||||
|
|
||||||
#: libertree.php:67
|
#: libertree.php:100
|
||||||
msgid "Libertree Export"
|
msgid "Save Settings"
|
||||||
msgstr "Esporta Libertree"
|
msgstr "Salva Impostazioni"
|
||||||
|
|
|
@ -3,11 +3,12 @@
|
||||||
if(! function_exists("string_plural_select_it")) {
|
if(! function_exists("string_plural_select_it")) {
|
||||||
function string_plural_select_it($n){
|
function string_plural_select_it($n){
|
||||||
$n = intval($n);
|
$n = intval($n);
|
||||||
if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; }
|
return intval($n != 1);
|
||||||
}}
|
}}
|
||||||
$a->strings['Post to libertree'] = 'Invia a Libertree';
|
$a->strings['Post to libertree'] = 'Invia a Libertree';
|
||||||
|
$a->strings['libertree Export'] = 'Esporta libertree';
|
||||||
$a->strings['Enable Libertree Post Addon'] = 'Abilita il componente aggiuntivo di invio a Libertree';
|
$a->strings['Enable Libertree Post Addon'] = 'Abilita il componente aggiuntivo di invio a Libertree';
|
||||||
$a->strings['Libertree site URL'] = 'Indirizzo sito Libertree';
|
|
||||||
$a->strings['Libertree API token'] = 'Token API Libertree';
|
$a->strings['Libertree API token'] = 'Token API Libertree';
|
||||||
|
$a->strings['Libertree site URL'] = 'Indirizzo sito Libertree';
|
||||||
$a->strings['Post to Libertree by default'] = 'Invia sempre a Libertree';
|
$a->strings['Post to Libertree by default'] = 'Invia sempre a Libertree';
|
||||||
$a->strings['Libertree Export'] = 'Esporta Libertree';
|
$a->strings['Save Settings'] = 'Salva Impostazioni';
|
||||||
|
|
|
@ -5,18 +5,16 @@
|
||||||
#
|
#
|
||||||
# Translators:
|
# Translators:
|
||||||
# Andreas H., 2014
|
# Andreas H., 2014
|
||||||
# foss <oss@disr.it>, 2022
|
|
||||||
# Raroun, 2023
|
|
||||||
# Tobias Diekershoff <tobias.diekershoff@gmx.net>, 2018
|
# Tobias Diekershoff <tobias.diekershoff@gmx.net>, 2018
|
||||||
# Ulf Rompe <transifex.com@rompe.org>, 2019
|
# Ulf Rompe <transifex.com@rompe.org>, 2019
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: friendica\n"
|
"Project-Id-Version: friendica\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2021-11-21 19:15-0500\n"
|
"POT-Creation-Date: 2018-03-11 19:13+0100\n"
|
||||||
"PO-Revision-Date: 2014-06-23 09:54+0000\n"
|
"PO-Revision-Date: 2019-02-18 15:05+0000\n"
|
||||||
"Last-Translator: Raroun, 2023\n"
|
"Last-Translator: Ulf Rompe <transifex.com@rompe.org>\n"
|
||||||
"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n"
|
"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
@ -31,76 +29,72 @@ msgstr "Absender"
|
||||||
msgid "Email address that stream items will appear to be from."
|
msgid "Email address that stream items will appear to be from."
|
||||||
msgstr "E-Mail-Adresse, die in hochgeladenen Artikeln erscheint."
|
msgstr "E-Mail-Adresse, die in hochgeladenen Artikeln erscheint."
|
||||||
|
|
||||||
#: mailstream.php:82
|
#: mailstream.php:82 mailstream.php:380
|
||||||
msgid "Save Settings"
|
msgid "Save Settings"
|
||||||
msgstr "Einstellungen speichern"
|
msgstr "Einstellungen speichern"
|
||||||
|
|
||||||
#: mailstream.php:311
|
#: mailstream.php:223
|
||||||
msgid "Re:"
|
msgid "Re:"
|
||||||
msgstr "Re:"
|
msgstr "Re:"
|
||||||
|
|
||||||
#: mailstream.php:324 mailstream.php:327
|
#: mailstream.php:231
|
||||||
msgid "Friendica post"
|
msgid "Friendica post"
|
||||||
msgstr "Friendica-Veröffentlichung"
|
msgstr "Friendica-Veröffentlichung"
|
||||||
|
|
||||||
#: mailstream.php:330
|
#: mailstream.php:234
|
||||||
msgid "Diaspora post"
|
msgid "Diaspora post"
|
||||||
msgstr "Diaspora-Veröffentlichung"
|
msgstr "Diaspora-Veröffentlichung"
|
||||||
|
|
||||||
#: mailstream.php:340
|
#: mailstream.php:244
|
||||||
msgid "Feed item"
|
msgid "Feed item"
|
||||||
msgstr "Artikel-Feed"
|
msgstr "Artikel-Feed"
|
||||||
|
|
||||||
#: mailstream.php:343
|
#: mailstream.php:247
|
||||||
msgid "Email"
|
msgid "Email"
|
||||||
msgstr "E-Mail"
|
msgstr "E-Mail"
|
||||||
|
|
||||||
#: mailstream.php:345
|
#: mailstream.php:249
|
||||||
msgid "Friendica Item"
|
msgid "Friendica Item"
|
||||||
msgstr "Friendica-Artikel"
|
msgstr "Friendica-Artikel"
|
||||||
|
|
||||||
#: mailstream.php:419
|
#: mailstream.php:293
|
||||||
msgid "Upstream"
|
msgid "Upstream"
|
||||||
msgstr "Upstream"
|
msgstr "Upstream"
|
||||||
|
|
||||||
#: mailstream.php:420
|
#: mailstream.php:294
|
||||||
msgid "URI"
|
|
||||||
msgstr "URI"
|
|
||||||
|
|
||||||
#: mailstream.php:421
|
|
||||||
msgid "Local"
|
msgid "Local"
|
||||||
msgstr "Lokal"
|
msgstr "Lokal"
|
||||||
|
|
||||||
#: mailstream.php:499
|
#: mailstream.php:362
|
||||||
msgid "Enabled"
|
msgid "Enabled"
|
||||||
msgstr "Aktiv"
|
msgstr "eingeschaltet"
|
||||||
|
|
||||||
#: mailstream.php:504
|
#: mailstream.php:366
|
||||||
msgid "Email Address"
|
msgid "Email Address"
|
||||||
msgstr "E-Mail-Adresse"
|
msgstr "E-Mail-Adresse"
|
||||||
|
|
||||||
#: mailstream.php:506
|
#: mailstream.php:368
|
||||||
msgid "Leave blank to use your account email address"
|
msgid "Leave blank to use your account email address"
|
||||||
msgstr "Leer lassen für deine Konto-E-Mail-Addresse"
|
msgstr "Leer lassen für deine Konto-E-Mail-Addresse"
|
||||||
|
|
||||||
#: mailstream.php:510
|
#: mailstream.php:371
|
||||||
msgid "Exclude Likes"
|
msgid "Exclude Likes"
|
||||||
msgstr "Likes ignorieren"
|
msgstr "Likes ignorieren"
|
||||||
|
|
||||||
#: mailstream.php:512
|
#: mailstream.php:373
|
||||||
msgid "Check this to omit mailing \"Like\" notifications"
|
msgid "Check this to omit mailing \"Like\" notifications"
|
||||||
msgstr "Diese Option verhindert das Versenden von \"Like\"-Benachrichtigungen per E-Mail."
|
msgstr "Diese Option verhindert das Versenden von \"Like\"-Benachrichtigungen per E-Mail."
|
||||||
|
|
||||||
#: mailstream.php:516
|
#: mailstream.php:376
|
||||||
msgid "Attach Images"
|
msgid "Attach Images"
|
||||||
msgstr "Bilder anhängen"
|
msgstr "Bilder anhängen"
|
||||||
|
|
||||||
#: mailstream.php:518
|
#: mailstream.php:378
|
||||||
msgid ""
|
msgid ""
|
||||||
"Download images in posts and attach them to the email. Useful for reading "
|
"Download images in posts and attach them to the email. Useful for reading "
|
||||||
"email while offline."
|
"email while offline."
|
||||||
msgstr "Sollen Bilder, die im Beitrag eingebettet sind, als Dateianhang in den E-Mails verschickt werden?"
|
msgstr "Sollen Bilder, die im Beitrag eingebettet sind, als Dateianhang in den E-Mails verschickt werden?"
|
||||||
|
|
||||||
#: mailstream.php:525
|
#: mailstream.php:379
|
||||||
msgid "Mail Stream Settings"
|
msgid "Mail Stream Settings"
|
||||||
msgstr "Mail-Nachrichten-Einstellungen"
|
msgstr "Mail-Nachrichten-Einstellungen"
|
||||||
|
|
|
@ -15,9 +15,8 @@ $a->strings['Feed item'] = 'Artikel-Feed';
|
||||||
$a->strings['Email'] = 'E-Mail';
|
$a->strings['Email'] = 'E-Mail';
|
||||||
$a->strings['Friendica Item'] = 'Friendica-Artikel';
|
$a->strings['Friendica Item'] = 'Friendica-Artikel';
|
||||||
$a->strings['Upstream'] = 'Upstream';
|
$a->strings['Upstream'] = 'Upstream';
|
||||||
$a->strings['URI'] = 'URI';
|
|
||||||
$a->strings['Local'] = 'Lokal';
|
$a->strings['Local'] = 'Lokal';
|
||||||
$a->strings['Enabled'] = 'Aktiv';
|
$a->strings['Enabled'] = 'eingeschaltet';
|
||||||
$a->strings['Email Address'] = 'E-Mail-Adresse';
|
$a->strings['Email Address'] = 'E-Mail-Adresse';
|
||||||
$a->strings['Leave blank to use your account email address'] = 'Leer lassen für deine Konto-E-Mail-Addresse';
|
$a->strings['Leave blank to use your account email address'] = 'Leer lassen für deine Konto-E-Mail-Addresse';
|
||||||
$a->strings['Exclude Likes'] = 'Likes ignorieren';
|
$a->strings['Exclude Likes'] = 'Likes ignorieren';
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
* Author: Matthew Exon <http://mat.exon.name>
|
* Author: Matthew Exon <http://mat.exon.name>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use Friendica\App;
|
||||||
use Friendica\Content\Text\BBCode;
|
use Friendica\Content\Text\BBCode;
|
||||||
use Friendica\Core\Hook;
|
use Friendica\Core\Hook;
|
||||||
use Friendica\Core\Logger;
|
use Friendica\Core\Logger;
|
||||||
|
@ -15,11 +16,12 @@ use Friendica\Core\Worker;
|
||||||
use Friendica\Database\DBA;
|
use Friendica\Database\DBA;
|
||||||
use Friendica\DI;
|
use Friendica\DI;
|
||||||
use Friendica\Model\Contact;
|
use Friendica\Model\Contact;
|
||||||
|
use Friendica\Model\Item;
|
||||||
use Friendica\Model\Post;
|
use Friendica\Model\Post;
|
||||||
use Friendica\Model\User;
|
use Friendica\Model\User;
|
||||||
use Friendica\Network\HTTPClient\Client\HttpClientAccept;
|
use Friendica\Network\HTTPClient\Client\HttpClientAccept;
|
||||||
use Friendica\Network\HTTPClient\Client\HttpClientOptions;
|
|
||||||
use Friendica\Protocol\Activity;
|
use Friendica\Protocol\Activity;
|
||||||
|
use Friendica\Util\DateTimeFormat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up the addon hooks and the database table
|
* Sets up the addon hooks and the database table
|
||||||
|
@ -32,7 +34,26 @@ function mailstream_install()
|
||||||
Hook::register('post_remote_end', 'addon/mailstream/mailstream.php', 'mailstream_post_hook');
|
Hook::register('post_remote_end', 'addon/mailstream/mailstream.php', 'mailstream_post_hook');
|
||||||
Hook::register('mailstream_send_hook', 'addon/mailstream/mailstream.php', 'mailstream_send_hook');
|
Hook::register('mailstream_send_hook', 'addon/mailstream/mailstream.php', 'mailstream_send_hook');
|
||||||
|
|
||||||
Logger::info("installed mailstream");
|
Logger::info("mailstream: installed");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enforces that mailstream_install has set up the current version
|
||||||
|
*/
|
||||||
|
function mailstream_check_version()
|
||||||
|
{
|
||||||
|
if (!is_null(DI::config()->get('mailstream', 'dbversion'))) {
|
||||||
|
DI::config()->delete('mailstream', 'dbversion');
|
||||||
|
Logger::info("mailstream_check_version: old version detected, reinstalling");
|
||||||
|
mailstream_install();
|
||||||
|
Hook::loadHooks();
|
||||||
|
Hook::add(
|
||||||
|
'mailstream_convert_table_entries',
|
||||||
|
'addon/mailstream/mailstream.php',
|
||||||
|
'mailstream_convert_table_entries'
|
||||||
|
);
|
||||||
|
Hook::fork(Worker::PRIORITY_LOW, 'mailstream_convert_table_entries');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -51,12 +72,10 @@ function mailstream_addon_admin(string &$o)
|
||||||
{
|
{
|
||||||
$frommail = DI::config()->get('mailstream', 'frommail');
|
$frommail = DI::config()->get('mailstream', 'frommail');
|
||||||
$template = Renderer::getMarkupTemplate('admin.tpl', 'addon/mailstream/');
|
$template = Renderer::getMarkupTemplate('admin.tpl', 'addon/mailstream/');
|
||||||
$config = [
|
$config = ['frommail',
|
||||||
'frommail',
|
|
||||||
DI::l10n()->t('From Address'),
|
DI::l10n()->t('From Address'),
|
||||||
$frommail,
|
$frommail,
|
||||||
DI::l10n()->t('Email address that stream items will appear to be from.')
|
DI::l10n()->t('Email address that stream items will appear to be from.')];
|
||||||
];
|
|
||||||
$o .= Renderer::replaceMacros($template, [
|
$o .= Renderer::replaceMacros($template, [
|
||||||
'$frommail' => $config,
|
'$frommail' => $config,
|
||||||
'$submit' => DI::l10n()->t('Save Settings')
|
'$submit' => DI::l10n()->t('Save Settings')
|
||||||
|
@ -86,7 +105,7 @@ function mailstream_generate_id(string $uri): string
|
||||||
$host = DI::baseUrl()->getHost();
|
$host = DI::baseUrl()->getHost();
|
||||||
$resource = hash('md5', $uri);
|
$resource = hash('md5', $uri);
|
||||||
$message_id = "<" . $resource . "@" . $host . ">";
|
$message_id = "<" . $resource . "@" . $host . ">";
|
||||||
Logger::debug('generated message ID', ['id' => $message_id, 'uri' => $uri]);
|
Logger::debug('mailstream: Generated message ID ' . $message_id . ' for URI ' . $uri);
|
||||||
return $message_id;
|
return $message_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,20 +114,20 @@ function mailstream_send_hook(array $data)
|
||||||
$criteria = array('uid' => $data['uid'], 'contact-id' => $data['contact-id'], 'uri' => $data['uri']);
|
$criteria = array('uid' => $data['uid'], 'contact-id' => $data['contact-id'], 'uri' => $data['uri']);
|
||||||
$item = Post::selectFirst([], $criteria);
|
$item = Post::selectFirst([], $criteria);
|
||||||
if (empty($item)) {
|
if (empty($item)) {
|
||||||
Logger::error('could not find item');
|
Logger::error('mailstream_send_hook could not find item');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$user = User::getById($item['uid']);
|
$user = User::getById($item['uid']);
|
||||||
if (empty($user)) {
|
if (empty($user)) {
|
||||||
Logger::error('could not find user', ['uid' => $item['uid']]);
|
Logger::error('mailstream_send_hook could not fund user', ['uid' => $item['uid']]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mailstream_send($data['message_id'], $item, $user)) {
|
if (!mailstream_send($data['message_id'], $item, $user)) {
|
||||||
Logger::debug('send failed, will retry', $data);
|
Logger::debug('mailstream_send_hook send failed, will retry', $data);
|
||||||
if (!Worker::defer()) {
|
if (!Worker::defer()) {
|
||||||
Logger::error('failed and could not defer', $data);
|
Logger::error('mailstream_send_hook failed and could not defer', $data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,33 +142,35 @@ function mailstream_send_hook(array $data)
|
||||||
*/
|
*/
|
||||||
function mailstream_post_hook(array &$item)
|
function mailstream_post_hook(array &$item)
|
||||||
{
|
{
|
||||||
if ($item['uid'] === 0) {
|
mailstream_check_version();
|
||||||
Logger::debug('mailstream: root user, skipping item ' . $item['id']);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!DI::pConfig()->get($item['uid'], 'mailstream', 'enabled')) {
|
if (!DI::pConfig()->get($item['uid'], 'mailstream', 'enabled')) {
|
||||||
Logger::debug('mailstream: not enabled.', ['item' => $item['id'], ' uid ' => $item['uid']]);
|
Logger::debug('mailstream: not enabled.', ['item' => $item['id'], ' uid ' => $item['uid']]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!$item['uid']) {
|
||||||
|
Logger::debug('mailstream: no uid for item ' . $item['id']);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!$item['contact-id']) {
|
if (!$item['contact-id']) {
|
||||||
Logger::debug('no contact-id', ['item' => $item['id']]);
|
Logger::debug('mailstream: no contact-id for item ' . $item['id']);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!$item['uri']) {
|
if (!$item['uri']) {
|
||||||
Logger::debug('no uri', ['item' => $item['id']]);
|
Logger::debug('mailstream: no uri for item ' . $item['id']);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ($item['verb'] == Activity::ANNOUNCE) {
|
if ($item['verb'] == Activity::ANNOUNCE) {
|
||||||
Logger::debug('ignoring announce', ['item' => $item['id']]);
|
Logger::debug('mailstream: announce item ', ['item' => $item['id']]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (DI::pConfig()->get($item['uid'], 'mailstream', 'nolikes')) {
|
if (DI::pConfig()->get($item['uid'], 'mailstream', 'nolikes')) {
|
||||||
if ($item['verb'] == Activity::LIKE) {
|
if ($item['verb'] == Activity::LIKE) {
|
||||||
Logger::debug('ignoring like', ['item' => $item['id']]);
|
Logger::debug('mailstream: like item ' . $item['id']);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ($item['verb'] == Activity::DISLIKE) {
|
if ($item['verb'] == Activity::DISLIKE) {
|
||||||
Logger::debug('ignoring dislike', ['item' => $item['id']]);
|
Logger::debug('mailstream: dislike item ' . $item['id']);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -198,17 +219,9 @@ function mailstream_do_images(array &$item, array &$attachments)
|
||||||
|
|
||||||
$cookiejar = tempnam(System::getTempPath(), 'cookiejar-mailstream-');
|
$cookiejar = tempnam(System::getTempPath(), 'cookiejar-mailstream-');
|
||||||
try {
|
try {
|
||||||
$curlResult = DI::httpClient()->get($url, HttpClientAccept::DEFAULT, [HttpClientOptions::COOKIEJAR => $cookiejar]);
|
$curlResult = DI::httpClient()->fetchFull($url, HttpClientAccept::DEFAULT, 0, $cookiejar);
|
||||||
if (!$curlResult->isSuccess()) {
|
|
||||||
Logger::debug('mailstream: fetch image url failed', [
|
|
||||||
'url' => $url,
|
|
||||||
'item_id' => $item['id'],
|
|
||||||
'return_code' => $curlResult->getReturnCode()
|
|
||||||
]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} catch (InvalidArgumentException $e) {
|
} catch (InvalidArgumentException $e) {
|
||||||
Logger::error('exception fetching url', ['url' => $url, 'item_id' => $item['id']]);
|
Logger::error('mailstream_do_images exception fetching url', ['url' => $url, 'item_id' => $item['id']]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$attachments[$url] = [
|
$attachments[$url] = [
|
||||||
|
@ -309,12 +322,13 @@ function mailstream_subject(array $item): string
|
||||||
}
|
}
|
||||||
$contact = Contact::selectFirst([], ['id' => $item['contact-id'], 'uid' => $item['uid']]);
|
$contact = Contact::selectFirst([], ['id' => $item['contact-id'], 'uid' => $item['uid']]);
|
||||||
if (!DBA::isResult($contact)) {
|
if (!DBA::isResult($contact)) {
|
||||||
Logger::error('no contact', [
|
Logger::error(
|
||||||
'item' => $item['id'],
|
'mailstream_subject no contact for item',
|
||||||
|
['id' => $item['id'],
|
||||||
'plink' => $item['plink'],
|
'plink' => $item['plink'],
|
||||||
'contact id' => $item['contact-id'],
|
'contact id' => $item['contact-id'],
|
||||||
'uid' => $item['uid']
|
'uid' => $item['uid']]
|
||||||
]);
|
);
|
||||||
return DI::l10n()->t("Friendica post");
|
return DI::l10n()->t("Friendica post");
|
||||||
}
|
}
|
||||||
if ($contact['network'] === 'dfrn') {
|
if ($contact['network'] === 'dfrn') {
|
||||||
|
@ -351,16 +365,17 @@ function mailstream_subject(array $item): string
|
||||||
function mailstream_send(string $message_id, array $item, array $user): bool
|
function mailstream_send(string $message_id, array $item, array $user): bool
|
||||||
{
|
{
|
||||||
if (!is_array($item)) {
|
if (!is_array($item)) {
|
||||||
Logger::error('item is empty', ['message_id' => $message_id]);
|
Logger::error('mailstream_send item is empty', ['message_id' => $message_id]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$item['visible']) {
|
if (!$item['visible']) {
|
||||||
Logger::debug('item not yet visible', ['item uri' => $item['uri']]);
|
Logger::debug('mailstream_send item not yet visible', ['item uri' => $item['uri']]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!$message_id) {
|
if (!$message_id) {
|
||||||
Logger::error('no message ID supplied', ['item uri' => $item['uri'], 'user email' => $user['email']]);
|
Logger::error('mailstream_send no message ID supplied', ['item uri' => $item['uri'],
|
||||||
|
'user email' => $user['email']]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -412,21 +427,18 @@ function mailstream_send(string $message_id, array $item, array $user): bool
|
||||||
'$upstream' => DI::l10n()->t('Upstream'),
|
'$upstream' => DI::l10n()->t('Upstream'),
|
||||||
'$uri' => DI::l10n()->t('URI'),
|
'$uri' => DI::l10n()->t('URI'),
|
||||||
'$local' => DI::l10n()->t('Local'),
|
'$local' => DI::l10n()->t('Local'),
|
||||||
'$item' => $item
|
'$item' => $item]);
|
||||||
]);
|
|
||||||
$mail->Body = mailstream_html_wrap($mail->Body);
|
$mail->Body = mailstream_html_wrap($mail->Body);
|
||||||
if (!$mail->Send()) {
|
if (!$mail->Send()) {
|
||||||
throw new Exception($mail->ErrorInfo);
|
throw new Exception($mail->ErrorInfo);
|
||||||
}
|
}
|
||||||
Logger::debug('sent message', [
|
Logger::debug('mailstream_send sent message', ['message ID' => $mail->MessageID,
|
||||||
'message ID' => $mail->MessageID,
|
|
||||||
'subject' => $mail->Subject,
|
'subject' => $mail->Subject,
|
||||||
'address' => $address
|
'address' => $address]);
|
||||||
]);
|
|
||||||
} catch (phpmailerException $e) {
|
} catch (phpmailerException $e) {
|
||||||
Logger::debug('PHPMailer exception sending message', ['id' => $message_id, 'error' => $e->errorMessage()]);
|
Logger::debug('mailstream_send PHPMailer exception sending message ' . $message_id . ': ' . $e->errorMessage());
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Logger::debug('exception sending message', ['id' => $message_id, 'error' => $e->getMessage()]);
|
Logger::debug('mailstream_send exception sending message ' . $message_id . ': ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -450,6 +462,29 @@ function mailstream_html_wrap(string &$text)
|
||||||
return $text;
|
return $text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert v1 mailstream table entries to v2 workerqueue items
|
||||||
|
*/
|
||||||
|
function mailstream_convert_table_entries()
|
||||||
|
{
|
||||||
|
$ms_item_ids = DBA::selectToArray('mailstream_item', [], ['message-id', 'uri', 'uid', 'contact-id'], ["`mailstream_item`.`completed` IS NULL"]);
|
||||||
|
Logger::debug('mailstream_convert_table_entries processing ' . count($ms_item_ids) . ' items');
|
||||||
|
foreach ($ms_item_ids as $ms_item_id) {
|
||||||
|
$send_hook_data = array('uid' => $ms_item_id['uid'],
|
||||||
|
'contact-id' => $ms_item_id['contact-id'],
|
||||||
|
'uri' => $ms_item_id['uri'],
|
||||||
|
'message_id' => $ms_item_id['message-id'],
|
||||||
|
'tries' => 0);
|
||||||
|
if (!$ms_item_id['message-id'] || !strlen($ms_item_id['message-id'])) {
|
||||||
|
Logger::info('mailstream_convert_table_entries: item has no message-id.', ['item' => $ms_item_id['id'], 'uri' => $ms_item_id['uri']]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Logger::info('mailstream_convert_table_entries: convert item to workerqueue', $send_hook_data);
|
||||||
|
Hook::fork(Worker::PRIORITY_LOW, 'mailstream_send_hook', $send_hook_data);
|
||||||
|
}
|
||||||
|
DBA::e('DROP TABLE `mailstream_item`');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Form for configuring mailstream features for a user
|
* Form for configuring mailstream features for a user
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Name: Mastodon Custom Emojis
|
* Name: Mastodon Custom Emojis
|
||||||
* Description: Replace emojis shortcodes in Mastodon posts with their originating server custom emojis images.
|
* Description: Replace emojis shortcodes in Mastodon posts with their originating server custom emojis images.
|
||||||
|
@ -8,11 +9,13 @@
|
||||||
* Status: Unsupported
|
* Status: Unsupported
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use Friendica\App;
|
||||||
use Friendica\Content\Smilies;
|
use Friendica\Content\Smilies;
|
||||||
use Friendica\Core\Cache\Enum\Duration;
|
use Friendica\Core\Cache\Enum\Duration;
|
||||||
use Friendica\Core\Hook;
|
use Friendica\Core\Hook;
|
||||||
use Friendica\Core\Protocol;
|
use Friendica\Core\Protocol;
|
||||||
use Friendica\DI;
|
use Friendica\DI;
|
||||||
|
use Friendica\Util\Proxy as ProxyUtils;
|
||||||
|
|
||||||
function mastodoncustomemojis_install()
|
function mastodoncustomemojis_install()
|
||||||
{
|
{
|
||||||
|
@ -76,7 +79,7 @@ function mastodoncustomemojis_fetch_custom_emojis_for_url($api_base_url)
|
||||||
|
|
||||||
$api_url = $api_base_url . '/api/v1/custom_emojis';
|
$api_url = $api_base_url . '/api/v1/custom_emojis';
|
||||||
|
|
||||||
$fetchResult = DI::httpClient()->get($api_url);
|
$fetchResult = DI::httpClient()->fetchFull($api_url);
|
||||||
|
|
||||||
if ($fetchResult->isSuccess()) {
|
if ($fetchResult->isSuccess()) {
|
||||||
$emojis_array = json_decode($fetchResult->getBodyString(), true);
|
$emojis_array = json_decode($fetchResult->getBodyString(), true);
|
||||||
|
@ -85,7 +88,7 @@ function mastodoncustomemojis_fetch_custom_emojis_for_url($api_base_url)
|
||||||
foreach ($emojis_array as $emoji) {
|
foreach ($emojis_array as $emoji) {
|
||||||
if (!empty($emoji['shortcode']) && !empty($emoji['static_url'])) {
|
if (!empty($emoji['shortcode']) && !empty($emoji['static_url'])) {
|
||||||
$return['texts'][] = ':' . $emoji['shortcode'] . ':';
|
$return['texts'][] = ':' . $emoji['shortcode'] . ':';
|
||||||
$return['icons'][] = '<img class="emoji mastodon" src="' . $emoji['static_url'] . '" alt=":' . $emoji['shortcode'] . ':" title=":' . $emoji['shortcode'] . ':"/>';
|
$return['icons'][] = '<img class="emoji mastodon" src="' . ProxyUtils::proxifyUrl($emoji['static_url']) . '" alt=":' . $emoji['shortcode'] . ':" title=":' . $emoji['shortcode'] . ':"/>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Translators:
|
# Translators:
|
||||||
# cracrayol, 2023-2024
|
# Florent C., 2023
|
||||||
# Nicolas Derive, 2022-2023
|
# Nicolas Derive, 2022-2023
|
||||||
# StefOfficiel <pichard.stephane@free.fr>, 2015
|
# StefOfficiel <pichard.stephane@free.fr>, 2015
|
||||||
# Vincent Vindarel <vindarel@mailz.org>, 2018
|
# Vincent Vindarel <vindarel@mailz.org>, 2018
|
||||||
|
@ -14,7 +14,7 @@ msgstr ""
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2022-12-10 14:42-0500\n"
|
"POT-Creation-Date: 2022-12-10 14:42-0500\n"
|
||||||
"PO-Revision-Date: 2014-06-23 10:34+0000\n"
|
"PO-Revision-Date: 2014-06-23 10:34+0000\n"
|
||||||
"Last-Translator: cracrayol, 2023-2024\n"
|
"Last-Translator: Florent C., 2023\n"
|
||||||
"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n"
|
"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
@ -42,7 +42,7 @@ msgstr "Liste de mots-clés - séparés par des virgules - à cacher"
|
||||||
msgid ""
|
msgid ""
|
||||||
"Use /expression/ to provide regular expressions, #tag to specfically match "
|
"Use /expression/ to provide regular expressions, #tag to specfically match "
|
||||||
"hashtags (case-insensitive), or regular words (case-sensitive)"
|
"hashtags (case-insensitive), or regular words (case-sensitive)"
|
||||||
msgstr "Utiliser /expression/ pour fournir des expressions régulières, #etiquette pour correspondre à une étiquette (insensible à la casse), ou des mots classiques (sensible à la casse)"
|
msgstr "Utiliser /expression/ pour fournir des expressions régulières, #tag pour correspondre à un tag (insensible à la casse), ou des mots classiques (sensible à la casse)"
|
||||||
|
|
||||||
#: nsfw.php:72
|
#: nsfw.php:72
|
||||||
msgid "Content Filter (NSFW and more)"
|
msgid "Content Filter (NSFW and more)"
|
||||||
|
|
|
@ -8,7 +8,7 @@ function string_plural_select_fr($n){
|
||||||
$a->strings['This addon searches for specified words/text in posts and collapses them. It can be used to filter content tagged with for instance #NSFW that may be deemed inappropriate at certain times or places, such as being at work. It is also useful for hiding irrelevant or annoying content from direct view.'] = 'Cette extension recherche des mots/textes spécifiés dans les publications et les masque. Elle peut être utilisée pour filtrer le contenu étiqueté par exemple avec #NSFW qui peut être considéré comme inapproprié à certains moments ou endroits, comme par exemple au travail. Elle est aussi utile pour cacher du contenu non pertinent ou ennuyeux d\'une vue directe.';
|
$a->strings['This addon searches for specified words/text in posts and collapses them. It can be used to filter content tagged with for instance #NSFW that may be deemed inappropriate at certain times or places, such as being at work. It is also useful for hiding irrelevant or annoying content from direct view.'] = 'Cette extension recherche des mots/textes spécifiés dans les publications et les masque. Elle peut être utilisée pour filtrer le contenu étiqueté par exemple avec #NSFW qui peut être considéré comme inapproprié à certains moments ou endroits, comme par exemple au travail. Elle est aussi utile pour cacher du contenu non pertinent ou ennuyeux d\'une vue directe.';
|
||||||
$a->strings['Enable Content filter'] = 'Activer le filtrage de contenu';
|
$a->strings['Enable Content filter'] = 'Activer le filtrage de contenu';
|
||||||
$a->strings['Comma separated list of keywords to hide'] = 'Liste de mots-clés - séparés par des virgules - à cacher';
|
$a->strings['Comma separated list of keywords to hide'] = 'Liste de mots-clés - séparés par des virgules - à cacher';
|
||||||
$a->strings['Use /expression/ to provide regular expressions, #tag to specfically match hashtags (case-insensitive), or regular words (case-sensitive)'] = 'Utiliser /expression/ pour fournir des expressions régulières, #etiquette pour correspondre à une étiquette (insensible à la casse), ou des mots classiques (sensible à la casse)';
|
$a->strings['Use /expression/ to provide regular expressions, #tag to specfically match hashtags (case-insensitive), or regular words (case-sensitive)'] = 'Utiliser /expression/ pour fournir des expressions régulières, #tag pour correspondre à un tag (insensible à la casse), ou des mots classiques (sensible à la casse)';
|
||||||
$a->strings['Content Filter (NSFW and more)'] = 'Filtre de contenu (NSFW et autres)';
|
$a->strings['Content Filter (NSFW and more)'] = 'Filtre de contenu (NSFW et autres)';
|
||||||
$a->strings['Regular expression "%s" fails to compile'] = 'La compilation de l\'expression régulière "%s" a échoué';
|
$a->strings['Regular expression "%s" fails to compile'] = 'La compilation de l\'expression régulière "%s" a échoué';
|
||||||
$a->strings['Filtered tag: %s'] = 'Tag filtré : %s';
|
$a->strings['Filtered tag: %s'] = 'Tag filtré : %s';
|
||||||
|
|
|
@ -1,213 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Friendica\Addon\ratioed;
|
|
||||||
|
|
||||||
use Friendica\Content\Pager;
|
|
||||||
use Friendica\Core\Logger;
|
|
||||||
use Friendica\Core\Renderer;
|
|
||||||
use Friendica\Database\DBA;
|
|
||||||
use Friendica\DI;
|
|
||||||
use Friendica\Model\User;
|
|
||||||
use Friendica\Module\Moderation\Users\Active;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class implements the "Behaviour" panel in Moderation/Users
|
|
||||||
*/
|
|
||||||
class RatioedPanel extends Active
|
|
||||||
{
|
|
||||||
protected function content(array $request = []): string
|
|
||||||
{
|
|
||||||
Active::content();
|
|
||||||
|
|
||||||
if (isset(DI::args()->getArgv()[1]) and DI::args()->getArgv()[1] === 'help') {
|
|
||||||
$template = Renderer::getMarkupTemplate('/help.tpl', 'addon/ratioed/');
|
|
||||||
return Renderer::replaceMacros($template, array('$config' => DI::baseUrl() . '/settings/addon'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$action = $this->parameters['action'] ?? '';
|
|
||||||
$uid = $this->parameters['uid'] ?? 0;
|
|
||||||
|
|
||||||
if ($uid) {
|
|
||||||
$user = User::getById($uid, ['username', 'blocked']);
|
|
||||||
if (!$user) {
|
|
||||||
$this->systemMessages->addNotice($this->t('User not found'));
|
|
||||||
$this->baseUrl->redirect('moderation/users');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ($action) {
|
|
||||||
case 'delete':
|
|
||||||
if ($this->session->getLocalUserId() != $uid) {
|
|
||||||
self::checkFormSecurityTokenRedirectOnError('moderation/users/active', 'moderation_users_active', 't');
|
|
||||||
// delete user
|
|
||||||
User::remove($uid);
|
|
||||||
|
|
||||||
$this->systemMessages->addNotice($this->t('User "%s" deleted', $user['username']));
|
|
||||||
} else {
|
|
||||||
$this->systemMessages->addNotice($this->t('You can\'t remove yourself'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->baseUrl->redirect('moderation/users/active');
|
|
||||||
break;
|
|
||||||
case 'block':
|
|
||||||
self::checkFormSecurityTokenRedirectOnError('moderation/users/active', 'moderation_users_active', 't');
|
|
||||||
User::block($uid);
|
|
||||||
$this->systemMessages->addNotice($this->t('User "%s" blocked', $user['username']));
|
|
||||||
$this->baseUrl->redirect('moderation/users/active');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
$pager = new Pager($this->l10n, $this->args->getQueryString(), 100);
|
|
||||||
|
|
||||||
$valid_orders = [
|
|
||||||
'name',
|
|
||||||
'email',
|
|
||||||
'register_date',
|
|
||||||
'last-activity',
|
|
||||||
'last-item',
|
|
||||||
'page-flags',
|
|
||||||
];
|
|
||||||
|
|
||||||
$order = 'last-item';
|
|
||||||
$order_direction = '-';
|
|
||||||
if (!empty($request['o'])) {
|
|
||||||
$new_order = $request['o'];
|
|
||||||
if ($new_order[0] === '-') {
|
|
||||||
$order_direction = '-';
|
|
||||||
$new_order = substr($new_order, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (in_array($new_order, $valid_orders)) {
|
|
||||||
$order = $new_order;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$users = User::getList($pager->getStart(), $pager->getItemsPerPage(), 'active', $order, ($order_direction == '-'));
|
|
||||||
|
|
||||||
$users = array_map($this->setupUserCallback(), $users);
|
|
||||||
|
|
||||||
$header_titles = [
|
|
||||||
$this->t('Name'),
|
|
||||||
$this->t('Email'),
|
|
||||||
$this->t('Register date'),
|
|
||||||
$this->t('Last login'),
|
|
||||||
$this->t('Last public item'),
|
|
||||||
$this->t('Type'),
|
|
||||||
$this->t('Blocked by'),
|
|
||||||
$this->t('Comments last 24h'),
|
|
||||||
$this->t('Reactions last 24h'),
|
|
||||||
$this->t('Ratio last 24h'),
|
|
||||||
];
|
|
||||||
$field_names = [
|
|
||||||
'name',
|
|
||||||
'email',
|
|
||||||
'register_date',
|
|
||||||
'login_date',
|
|
||||||
'lastitem_date',
|
|
||||||
'page_flags',
|
|
||||||
'blocked_by',
|
|
||||||
'comments',
|
|
||||||
'reactions',
|
|
||||||
'ratio',
|
|
||||||
];
|
|
||||||
$th_users = array_map(null, $header_titles, $valid_orders, $field_names);
|
|
||||||
|
|
||||||
$count = $this->database->count('user', ["`verified` AND NOT `blocked` AND NOT `account_removed` AND NOT `account_expired` AND `uid` != ?", 0]);
|
|
||||||
|
|
||||||
$t = Renderer::getMarkupTemplate('ratioed.tpl', 'addon/ratioed');
|
|
||||||
return self::getTabsHTML('ratioed') . Renderer::replaceMacros($t, [
|
|
||||||
// strings //
|
|
||||||
'$title' => $this->t('Moderation'),
|
|
||||||
'$help_url' => $this->baseUrl . '/ratioed/help',
|
|
||||||
'$page' => $this->t('Behaviour'),
|
|
||||||
'$select_all' => $this->t('select all'),
|
|
||||||
'$delete' => $this->t('Delete'),
|
|
||||||
'$block' => $this->t('Block'),
|
|
||||||
'$blocked' => $this->t('User blocked'),
|
|
||||||
'$siteadmin' => $this->t('Site admin'),
|
|
||||||
'$accountexpired' => $this->t('Account expired'),
|
|
||||||
'$h_newuser' => $this->t('Create a new user'),
|
|
||||||
|
|
||||||
'$th_users' => $th_users,
|
|
||||||
'$order_users' => $order,
|
|
||||||
'$order_direction_users' => $order_direction,
|
|
||||||
|
|
||||||
'$confirm_delete_multi' => $this->t('Selected users will be deleted!\n\nEverything these users had posted on this site will be permanently deleted!\n\nAre you sure?'),
|
|
||||||
'$confirm_delete' => $this->t('The user {0} will be deleted!\n\nEverything this user has posted on this site will be permanently deleted!\n\nAre you sure?'),
|
|
||||||
|
|
||||||
'$form_security_token' => self::getFormSecurityToken('moderation_users_active'),
|
|
||||||
|
|
||||||
// values //
|
|
||||||
'$baseurl' => $this->baseUrl,
|
|
||||||
'$query_string' => $this->args->getQueryString(),
|
|
||||||
|
|
||||||
'$users' => $users,
|
|
||||||
'$count' => $count,
|
|
||||||
'$pager' => $pager->renderFull($count),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function setupUserCallback(): \Closure
|
|
||||||
{
|
|
||||||
Logger::debug("ratioed: setupUserCallback");
|
|
||||||
$parentCallback = parent::setupUserCallback();
|
|
||||||
return function ($user) use ($parentCallback) {
|
|
||||||
$blocked_count = DBA::count('user-contact', ['uid' => $user['uid'], 'is-blocked' => 1]);
|
|
||||||
$user['blocked_by'] = $blocked_count;
|
|
||||||
|
|
||||||
$self_contact_result = DBA::p('SELECT admin_contact.id AS user_contact_uid FROM contact AS admin_contact JOIN contact AS user_contact ON admin_contact.`uri-id` = user_contact.`uri-id` AND admin_contact.self = 0 AND user_contact.self = 1 WHERE user_contact.uid = ?', $user['uid']);
|
|
||||||
if (DBA::isResult($self_contact_result)) {
|
|
||||||
$self_contact_result_row = DBA::fetch($self_contact_result);
|
|
||||||
$user['user_contact_uid'] = $self_contact_result_row['user_contact_uid'];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$user['user_contact_uid'] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($user['user_contact_uid']) {
|
|
||||||
$post_engagement_result = DBA::p('SELECT SUM(`comments`) AS `comment_count`, SUM(`activities`) AS `activities_count` FROM `post-engagement` WHERE `post-engagement`.created > DATE_SUB(now(), INTERVAL 1 DAY) AND `post-engagement`.`owner-id` = ?', $user['user_contact_uid']);
|
|
||||||
if (DBA::isResult($post_engagement_result)) {
|
|
||||||
$post_engagement_result_row = DBA::fetch($post_engagement_result);
|
|
||||||
$user['comments'] = $post_engagement_result_row['comment_count'];
|
|
||||||
$user['reactions'] = $post_engagement_result_row['activities_count'];
|
|
||||||
if ($user['reactions'] > 0) {
|
|
||||||
$user['ratio'] = number_format($user['comments'] / $user['reactions'], 1, '.', '');
|
|
||||||
$user['ratioed'] = (float)($user['ratio']) >= 2.0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if ($user['comments'] == 0) {
|
|
||||||
$user['ratio'] = '0';
|
|
||||||
$user['ratioed'] = false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$user['ratio'] = '∞';
|
|
||||||
$user['ratioed'] = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$user['comments'] = 'error';
|
|
||||||
$user['reactions'] = 'error';
|
|
||||||
$user['ratio'] = 'error';
|
|
||||||
$user['ratioed'] = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$user['comments'] = 'error';
|
|
||||||
$user['reactions'] = 'error';
|
|
||||||
$user['ratio'] = 'error';
|
|
||||||
$user['ratioed'] = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$user = $parentCallback($user);
|
|
||||||
Logger::debug("ratioed: setupUserCallback", [
|
|
||||||
'uid' => $user['uid'],
|
|
||||||
'blocked_by' => $user['blocked_by'],
|
|
||||||
'comments' => $user['comments'],
|
|
||||||
'reactions' => $user['reactions'],
|
|
||||||
'ratio' => $user['ratio'],
|
|
||||||
'ratioed' => $user['ratioed'],
|
|
||||||
]);
|
|
||||||
return $user;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,58 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* Name: Ratioed
|
|
||||||
* Description: Additional moderation user table with statistics about user behaviour
|
|
||||||
* Version: 0.1
|
|
||||||
* Author: Matthew Exon <http://mat.exon.name>
|
|
||||||
*/
|
|
||||||
|
|
||||||
use Friendica\Addon\ratioed\RatioedPanel;
|
|
||||||
use Friendica\Core\Hook;
|
|
||||||
use Friendica\Core\Logger;
|
|
||||||
use Friendica\DI;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets up the addon hooks and updates data in the database if needed
|
|
||||||
*/
|
|
||||||
function ratioed_install()
|
|
||||||
{
|
|
||||||
Hook::register('moderation_users_tabs', 'addon/ratioed/ratioed.php', 'ratioed_users_tabs');
|
|
||||||
|
|
||||||
Logger::info("ratioed: installed");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a statement rather than an actual function definition. The simple
|
|
||||||
* existence of this method is checked to figure out if the addon offers a
|
|
||||||
* module.
|
|
||||||
*/
|
|
||||||
function ratioed_module() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Adds additional users tab to the moderation panel
|
|
||||||
*
|
|
||||||
* @param array $arr Parameters, including "tabs" which is the list to modify, and "selectedTab", which is the currently selected tab ID
|
|
||||||
*/
|
|
||||||
function ratioed_users_tabs(array &$arr) {
|
|
||||||
Logger::debug("ratioed: users tabs");
|
|
||||||
|
|
||||||
array_push($arr['tabs'], [
|
|
||||||
'label' => DI::l10n()->t('Behaviour'),
|
|
||||||
'url' => 'ratioed',
|
|
||||||
'sel' => $arr['selectedTab'] == 'ratioed' ? 'active' : '',
|
|
||||||
'title' => DI::l10n()->t('Statistics about users behaviour'),
|
|
||||||
'id' => 'admin-users-ratioed',
|
|
||||||
'accesskey' => 'r',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Displays the ratioed tab in the moderation panel
|
|
||||||
*/
|
|
||||||
function ratioed_content() {
|
|
||||||
Logger::debug("ratioed: content");
|
|
||||||
|
|
||||||
$ratioed = DI::getDice()->create(RatioedPanel::class, [$_SERVER]);
|
|
||||||
$httpException = DI::getDice()->create(Friendica\Module\Special\HTTPException::class);
|
|
||||||
$ratioed->run($httpException);
|
|
||||||
}
|
|
|
@ -1,92 +0,0 @@
|
||||||
<div class="panel 'help-content-wrapper">
|
|
||||||
<div class="panel-body">
|
|
||||||
<h2>Ratioed Plugin Help</h2>
|
|
||||||
<p>
|
|
||||||
This plugin provides administrators with additional statistics about
|
|
||||||
the behaviour of users. These may be useful as early warning signs
|
|
||||||
that warrant more carefully watching the behaviour of a user. They
|
|
||||||
are <em>not</em> suitable as a trigger for instantly blocking,
|
|
||||||
muting, or reporting a user, since they lack context.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
The name of the plugin comes
|
|
||||||
from <a href="https://knowyourmeme.com/editorials/guides/what-is-the-ratio-and-what-does-it-mean-to-get-ratioed-twitters-1-rule-explained">"The
|
|
||||||
Ratio"</a>, a well-known quick rule of thumb:
|
|
||||||
</p>
|
|
||||||
<blockquote>
|
|
||||||
If the Replies:RT ratio is greater than 2:1, you done messed up.
|
|
||||||
</blockquote>
|
|
||||||
<p>
|
|
||||||
To "get ratioed" is to receive a large number of comments in a short
|
|
||||||
space of time, with relatively few likes or boosts. If commenters
|
|
||||||
were enthusiastic about the posts, they would also have liked or
|
|
||||||
boosted them. Receiving many comments without such likes or boosts
|
|
||||||
indicates the comments were probably angry. This anger may or may
|
|
||||||
not be justified, but either way this is probably something
|
|
||||||
moderators should be aware of.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
This plugin allows viewing of an actual ratio, calculated over the
|
|
||||||
last 24 hours. This is a useful timeframe for sudden dogpiling
|
|
||||||
events that administrators might not otherwise notice. The plugin
|
|
||||||
also calculates other statistics.
|
|
||||||
</p>
|
|
||||||
<h3>Explanation of Statistics</h3>
|
|
||||||
<h4>Blocked by</h4>
|
|
||||||
<p>
|
|
||||||
This summarises the number of users on remote servers that have
|
|
||||||
blocked this user.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Note that the ActivityPub spec expressly says that
|
|
||||||
implementations "SHOULD NOT" forward such block messages to
|
|
||||||
remote servers. Nevertheless some implementations do this
|
|
||||||
anyway, notably Mastodon. This statistic can only count block
|
|
||||||
messages from servers that do this, as well as blocks from local
|
|
||||||
users. As such, it is usually an undercount.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
The reason the spec recommends against forwarding these messages
|
|
||||||
is that they can lead to retaliation. For this reason, this
|
|
||||||
plugin deliberately does not provide any way to investigate
|
|
||||||
exactly who blocked the user.
|
|
||||||
</p>
|
|
||||||
<h4>Comments last 24h</h4>
|
|
||||||
<p>
|
|
||||||
This gives the number of comments made on the top-level posts that
|
|
||||||
this user made within the last 24 hours.
|
|
||||||
</p>
|
|
||||||
<h4>Reactions last 24h</h4>
|
|
||||||
<p>
|
|
||||||
This collects the number of likes, boosts, or other "one-click"
|
|
||||||
interactions made on the user's top-level posts within the last 24
|
|
||||||
hours.
|
|
||||||
</p>
|
|
||||||
<h4>Ratio last 24h</h4>
|
|
||||||
<p>
|
|
||||||
This is the ratio between "Comments last 24h" and "Reactions last
|
|
||||||
24h". It is intended to approximate the traditional ratio as
|
|
||||||
understood on Twitter.
|
|
||||||
</p>
|
|
||||||
<h3>Performance</h3>
|
|
||||||
<p>
|
|
||||||
The statistics are computed from scratch each time the page loads.
|
|
||||||
It's possible that this might put a heavy load on the database. and
|
|
||||||
the page may take a long time to load.
|
|
||||||
</p>
|
|
||||||
<h3>Extending</h3>
|
|
||||||
<p>
|
|
||||||
Suggestions for additional statistics are welcome, especially from
|
|
||||||
moderators. This plugin should be considered a sandbox for
|
|
||||||
experimentation, so it is not necessary to prove that any statistic
|
|
||||||
is correlated with unwanted behaviour.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
However, this plugin does deal with potentially sensitive
|
|
||||||
information. Even if moderators do in principle have access to all
|
|
||||||
information, it should not necessarily be highlighted. Statistics
|
|
||||||
should be kept anonymous and neutral. Also, they should be
|
|
||||||
presented only to moderators, not to the users themselves.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
|
@ -1,164 +0,0 @@
|
||||||
<script type="text/javascript" src="view/theme/frio/js/mod_admin.js?v={{constant('\Friendica\App::VERSION')}}"></script>
|
|
||||||
<link rel="stylesheet" href="view/theme/frio/css/mod_admin.css?v={{constant('\Friendica\App::VERSION')}}" type="text/css" media="screen"/>
|
|
||||||
|
|
||||||
<div id="admin-users" class="adminpage generic-page-wrapper">
|
|
||||||
<h1>{{$title}} - {{$page}} ({{$count}})</h1>
|
|
||||||
<p>
|
|
||||||
<a href="{{$base_url}}/moderation/users/create" class="btn btn-primary"><i class="fa fa-user-plus"></i> {{$h_newuser}}</a>
|
|
||||||
</p>
|
|
||||||
<form action="{{$baseurl}}/{{$query_string}}" method="post">
|
|
||||||
<input type="hidden" name="form_security_token" value="{{$form_security_token}}">
|
|
||||||
<table id="users" class="table table-hover">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>
|
|
||||||
<div class="checkbox">
|
|
||||||
<input type="checkbox" id="admin-settings-users-select" class="selecttoggle" data-select-class="users_ckbx"/>
|
|
||||||
<label for="admin-settings-users-select"></label>
|
|
||||||
</div>
|
|
||||||
</th>
|
|
||||||
<th></th>
|
|
||||||
{{foreach $th_users as $k=>$th}}
|
|
||||||
{{if $k < 2 || $order_users == $th.1 || ($k==5 && !in_array($order_users,[$th_users.2.1, $th_users.3.1, $th_users.4.1])) }}
|
|
||||||
<th class="th-{{$k}}">
|
|
||||||
<a href="{{$baseurl}}/moderation/users/active?o={{if $order_direction_users == "+"}}-{{/if}}{{$th.1}}" class="table-order">
|
|
||||||
{{if $order_users == $th.1}}
|
|
||||||
{{if $order_direction_users == "+"}}
|
|
||||||
↓
|
|
||||||
{{else}}
|
|
||||||
↑
|
|
||||||
{{/if}}
|
|
||||||
{{else}}
|
|
||||||
↕
|
|
||||||
{{/if}}
|
|
||||||
{{$th.0}}
|
|
||||||
</a>
|
|
||||||
</th>
|
|
||||||
{{/if}}
|
|
||||||
{{/foreach}}
|
|
||||||
<th></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{{foreach $users as $u}}
|
|
||||||
<tr id="user-{{$u.uid}}" class="{{if $u.ratioed}}blocked{{/if}}">
|
|
||||||
<td>
|
|
||||||
{{if $u.is_deletable}}
|
|
||||||
<div class="checkbox">
|
|
||||||
<input type="checkbox" class="users_ckbx" id="id_user_{{$u.uid}}" name="user[]" value="{{$u.uid}}"/>
|
|
||||||
<label for="id_user_{{$u.uid}}"></label>
|
|
||||||
</div>
|
|
||||||
{{else}}
|
|
||||||
|
|
||||||
{{/if}}
|
|
||||||
</td>
|
|
||||||
<td><img class="avatar-nano" src="{{$u.micro}}" title="{{$u.nickname}}"></td>
|
|
||||||
<td><a href="{{$u.url}}" title="{{$u.nickname}}"> {{$u.name}}</a></td>
|
|
||||||
<td>{{$u.email}}</td>
|
|
||||||
{{if $order_users == $th_users.2.1}}
|
|
||||||
<td>{{$u.register_date}}</td>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{if $order_users == $th_users.3.1}}
|
|
||||||
<td>{{$u.login_date}}</td>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{if $order_users == $th_users.4.1}}
|
|
||||||
<td>{{$u.lastitem_date}}</td>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{if !in_array($order_users,[$th_users.2.1, $th_users.3.1, $th_users.4.1]) }}
|
|
||||||
<td>
|
|
||||||
<i class="fa
|
|
||||||
{{if $u.page_flags_raw==0}}fa-user{{/if}} {{* PAGE_NORMAL *}}
|
|
||||||
{{if $u.page_flags_raw==1}}fa-bullhorn{{/if}} {{* PAGE_SOAPBOX *}}
|
|
||||||
{{if $u.page_flags_raw==2}}fa-users{{/if}} {{* PAGE_COMMUNITY *}}
|
|
||||||
{{if $u.page_flags_raw==3}}fa-heart{{/if}} {{* PAGE_FREELOVE *}}
|
|
||||||
{{if $u.page_flags_raw==4}}fa-rss{{/if}} {{* PAGE_BLOG *}}
|
|
||||||
{{if $u.page_flags_raw==5}}fa-user-secret{{/if}} {{* PAGE_PRVGROUP *}}
|
|
||||||
" title="{{$u.page_flags}}">
|
|
||||||
</i>
|
|
||||||
{{if $u.page_flags_raw==0 && $u.account_type_raw > 0}}
|
|
||||||
<i class="fa
|
|
||||||
{{if $u.account_type_raw==1}}fa-sitemap{{/if}} {{* ACCOUNT_TYPE_ORGANISATION *}}
|
|
||||||
{{if $u.account_type_raw==2}}fa-newspaper-o{{/if}} {{* ACCOUNT_TYPE_NEWS *}}
|
|
||||||
{{if $u.account_type_raw==3}}fa-comments{{/if}} {{* ACCOUNT_TYPE_COMMUNITY *}}
|
|
||||||
" title="{{$u.account_type}}">
|
|
||||||
</i>
|
|
||||||
{{/if}}
|
|
||||||
{{if $u.is_admin}}<i class="fa fa-user-secret text-primary" title="{{$siteadmin}}"></i>{{/if}}
|
|
||||||
{{if $u.account_expired}}<i class="fa fa-clock-o text-warning" title="{{$accountexpired}}"></i>{{/if}}
|
|
||||||
</td>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
<td class="text-right">
|
|
||||||
<button type="button" class="btn-link admin-settings-action-link" onclick="return details({{$u.uid}})"><span class="caret"></span></button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr id="user-{{$u.uid}}-detail" class=" details hidden {{if $u.blocked != 0}}blocked{{/if}}">
|
|
||||||
<td> </td>
|
|
||||||
<td colspan="4">
|
|
||||||
{{if $order_users != $th_users.2.1}}
|
|
||||||
<p>
|
|
||||||
<a href="{{$baseurl}}/ratioed?o={{if $order_direction_users == "+"}}-{{/if}}{{$th_users.2.1}}" class="btn-link table-order">
|
|
||||||
↕ {{$th_users.2.0}}</a> : {{$u.register_date}}
|
|
||||||
</p>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{if $order_users != $th_users.3.1}}
|
|
||||||
<p>
|
|
||||||
<a href="{{$baseurl}}/ratioed?o={{if $order_direction_users == "+"}}-{{/if}}{{$th_users.3.1}}" class="btn-link table-order">
|
|
||||||
↕ {{$th_users.3.0}}</a> : {{$u.login_date}}
|
|
||||||
</p>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{if $order_users != $th_users.4.1}}
|
|
||||||
<p>
|
|
||||||
<a href="{{$baseurl}}/ratioed?o={{if $order_direction_users == "+"}}-{{/if}}{{$th_users.4.1}}" class="btn-link table-order">
|
|
||||||
↕ {{$th_users.4.0}}</a> : {{$u.lastitem_date}}
|
|
||||||
</p>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{if in_array($order_users,[$th_users.2.1, $th_users.3.1, $th_users.4.1]) }}
|
|
||||||
<p>
|
|
||||||
<a href="{{$baseurl}}/ratioed?o={{if $order_direction_users == "+"}}-{{/if}}{{$th_users.5.1}}" class="btn-link table-order">
|
|
||||||
↕ {{$th_users.5.0}}</a> : {{$u.page_flags}}{{if $u.page_flags_raw==0 && $u.account_type_raw > 0}}, {{$u.account_type}}{{/if}} {{if $u.is_admin}}({{$siteadmin}}){{/if}} {{if $u.account_expired}}({{$accountexpired}}){{/if}}
|
|
||||||
</p>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{foreach $th_users as $k=>$th}}
|
|
||||||
{{if $order_users != $th.1 && $k > 5}}
|
|
||||||
<p>
|
|
||||||
{{$th.0}} : {{$u[$th.2]}}
|
|
||||||
</p>
|
|
||||||
{{/if}}
|
|
||||||
{{/foreach}}
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td class="text-right">
|
|
||||||
{{if $u.is_deletable}}
|
|
||||||
<a href="{{$baseurl}}/moderation/users/active/block/{{$u.uid}}?t={{$form_security_token}}" class="admin-settings-action-link" title="{{$block}}">
|
|
||||||
<i class="fa fa-ban" aria-hidden="true"></i>
|
|
||||||
</a>
|
|
||||||
<a href="{{$baseurl}}/moderation/users/active/delete/{{$u.uid}}?t={{$form_security_token}}" class="admin-settings-action-link" title="{{$delete}}" onclick="return confirm_delete('{{$confirm_delete}}','{{$u.name}}')">
|
|
||||||
<i class="fa fa-trash" aria-hidden="true"></i>
|
|
||||||
</a>
|
|
||||||
{{else}}
|
|
||||||
|
|
||||||
{{/if}}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{{/foreach}}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<div class="panel-footer">
|
|
||||||
<button type="submit" name="page_users_block" value="1" class="btn btn-warning">
|
|
||||||
<i class="fa fa-ban" aria-hidden="true"></i> {{$block}}
|
|
||||||
</button>
|
|
||||||
<button type="submit" name="page_users_delete" value="1" class="btn btn-danger" onclick="return confirm_delete('{{$confirm_delete_multi}}')">
|
|
||||||
<i class="fa fa-trash" aria-hidden="true"></i> {{$delete}}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{{$pager nofilter}}
|
|
||||||
</form>
|
|
||||||
</div>
|
|
|
@ -5,7 +5,7 @@
|
||||||
#
|
#
|
||||||
# Translators:
|
# Translators:
|
||||||
# Hypolite Petovan <hypolite@mrpetovan.com>, 2022
|
# Hypolite Petovan <hypolite@mrpetovan.com>, 2022
|
||||||
# cracrayol, 2024
|
# Florent C., 2023
|
||||||
#
|
#
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid ""
|
msgid ""
|
||||||
|
@ -14,7 +14,7 @@ msgstr ""
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2021-11-21 19:16-0500\n"
|
"POT-Creation-Date: 2021-11-21 19:16-0500\n"
|
||||||
"PO-Revision-Date: 2018-03-20 07:26+0000\n"
|
"PO-Revision-Date: 2018-03-20 07:26+0000\n"
|
||||||
"Last-Translator: cracrayol, 2024\n"
|
"Last-Translator: Florent C., 2023\n"
|
||||||
"Language-Team: French (https://app.transifex.com/Friendica/teams/12172/fr/)\n"
|
"Language-Team: French (https://app.transifex.com/Friendica/teams/12172/fr/)\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
@ -24,7 +24,7 @@ msgstr ""
|
||||||
|
|
||||||
#: securemail.php:50
|
#: securemail.php:50
|
||||||
msgid "Enable Secure Mail"
|
msgid "Enable Secure Mail"
|
||||||
msgstr "Activer l'extension des courriels sécurisés"
|
msgstr "Activer l'extension des emails sécurisés"
|
||||||
|
|
||||||
#: securemail.php:51
|
#: securemail.php:51
|
||||||
msgid "Public key"
|
msgid "Public key"
|
||||||
|
@ -36,7 +36,7 @@ msgstr "Votre clé publique PGP formatée compatible ASCII"
|
||||||
|
|
||||||
#: securemail.php:56
|
#: securemail.php:56
|
||||||
msgid "\"Secure Mail\" Settings"
|
msgid "\"Secure Mail\" Settings"
|
||||||
msgstr "Paramètres des courriels sécurisés"
|
msgstr "Paramètres des emails sécurisés"
|
||||||
|
|
||||||
#: securemail.php:59
|
#: securemail.php:59
|
||||||
msgid "Save Settings"
|
msgid "Save Settings"
|
||||||
|
|
|
@ -5,10 +5,10 @@ function string_plural_select_fr($n){
|
||||||
$n = intval($n);
|
$n = intval($n);
|
||||||
if (($n == 0 || $n == 1)) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; }
|
if (($n == 0 || $n == 1)) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; }
|
||||||
}}
|
}}
|
||||||
$a->strings['Enable Secure Mail'] = 'Activer l\'extension des courriels sécurisés';
|
$a->strings['Enable Secure Mail'] = 'Activer l\'extension des emails sécurisés';
|
||||||
$a->strings['Public key'] = 'Clé publique';
|
$a->strings['Public key'] = 'Clé publique';
|
||||||
$a->strings['Your public PGP key, ascii armored format'] = 'Votre clé publique PGP formatée compatible ASCII';
|
$a->strings['Your public PGP key, ascii armored format'] = 'Votre clé publique PGP formatée compatible ASCII';
|
||||||
$a->strings['"Secure Mail" Settings'] = 'Paramètres des courriels sécurisés';
|
$a->strings['"Secure Mail" Settings'] = 'Paramètres des emails sécurisés';
|
||||||
$a->strings['Save Settings'] = 'Enregistrer les paramètres';
|
$a->strings['Save Settings'] = 'Enregistrer les paramètres';
|
||||||
$a->strings['Save and send test'] = 'Enregistrer et envoyer un message de test';
|
$a->strings['Save and send test'] = 'Enregistrer et envoyer un message de test';
|
||||||
$a->strings['Test email sent'] = 'Courriel de test envoyé avec succès';
|
$a->strings['Test email sent'] = 'Courriel de test envoyé avec succès';
|
||||||
|
|
Before Width: | Height: | Size: 269 B |
Before Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 270 B |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 339 B |
Before Width: | Height: | Size: 627 B |
Before Width: | Height: | Size: 1 KiB |
Before Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 257 B |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 79 B |
Before Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 444 B |
Before Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 471 B |
Before Width: | Height: | Size: 135 B |
Before Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 418 B |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 405 B |
Before Width: | Height: | Size: 137 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1 KiB |
Before Width: | Height: | Size: 180 B After Width: | Height: | Size: 100 B |
Before Width: | Height: | Size: 410 B |
Before Width: | Height: | Size: 112 B |
Before Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 908 B |
Before Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 5 KiB |
Before Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 4.7 KiB |
|
@ -2,17 +2,17 @@
|
||||||
/*
|
/*
|
||||||
* Name: Smiley Pack
|
* Name: Smiley Pack
|
||||||
* Description: Pack of smileys that make master too AOLish.
|
* Description: Pack of smileys that make master too AOLish.
|
||||||
* Version: 1.06
|
* Version: 1.05
|
||||||
* Author: Thomas Willingham (based on Mike Macgirvin's Adult Smile template)
|
* Author: Thomas Willingham (based on Mike Macgirvin's Adult Smile template)
|
||||||
* Author: Matthias Ebers <https://loma.ml/profile/one>
|
* Author: Matthias Ebers <https://loma.ml/profile/one>
|
||||||
* All smileys from sites offering them as Public Domain
|
* All smileys from sites offering them as Public Domain
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use Friendica\App;
|
||||||
use Friendica\Core\Hook;
|
use Friendica\Core\Hook;
|
||||||
use Friendica\DI;
|
use Friendica\DI;
|
||||||
|
|
||||||
function smiley_pack_install()
|
function smiley_pack_install() {
|
||||||
{
|
|
||||||
Hook::register('smilie', 'addon/smiley_pack/smiley_pack.php', 'smiley_pack_smilies');
|
Hook::register('smilie', 'addon/smiley_pack/smiley_pack.php', 'smiley_pack_smilies');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,8 @@ function smiley_pack_smilies(array &$b)
|
||||||
#Be careful with invocation strings. If you have a smiley called foo, and another called foobar, typing :foobar will call foo. Avoid this with clever naming, using ~ instead of :
|
#Be careful with invocation strings. If you have a smiley called foo, and another called foobar, typing :foobar will call foo. Avoid this with clever naming, using ~ instead of :
|
||||||
#when all else fails.
|
#when all else fails.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#Animal smileys.
|
#Animal smileys.
|
||||||
|
|
||||||
$b['texts'][] = ':bunnyflowers:';
|
$b['texts'][] = ':bunnyflowers:';
|
||||||
|
@ -97,6 +99,8 @@ function smiley_pack_smilies(array &$b)
|
||||||
$b['texts'][] = ':pig:';
|
$b['texts'][] = ':pig:';
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/animals/pig.gif' . '" alt="' . ':pig:' . '" />';
|
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/animals/pig.gif' . '" alt="' . ':pig:' . '" />';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#Baby Smileys
|
#Baby Smileys
|
||||||
|
|
||||||
$b['texts'][] = ':baby:';
|
$b['texts'][] = ':baby:';
|
||||||
|
@ -105,12 +109,14 @@ function smiley_pack_smilies(array &$b)
|
||||||
$b['texts'][] = ':babycot:';
|
$b['texts'][] = ':babycot:';
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/babies/babycot.gif' . '" alt="' . ':babycot:' . '" />';
|
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/babies/babycot.gif' . '" alt="' . ':babycot:' . '" />';
|
||||||
|
|
||||||
|
|
||||||
$b['texts'][] = ':pregnant:';
|
$b['texts'][] = ':pregnant:';
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/babies/pregnant.gif' . '" alt="' . ':pregnant:' . '" />';
|
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/babies/pregnant.gif' . '" alt="' . ':pregnant:' . '" />';
|
||||||
|
|
||||||
$b['texts'][] = ':stork:';
|
$b['texts'][] = ':stork:';
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/babies/stork.gif' . '" alt="' . ':stork:' . '" />';
|
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/babies/stork.gif' . '" alt="' . ':stork:' . '" />';
|
||||||
|
|
||||||
|
|
||||||
#Confused Smileys
|
#Confused Smileys
|
||||||
$b['texts'][] = ':confused:';
|
$b['texts'][] = ':confused:';
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/confused/confused.gif' . '" alt="' . ':confused:' . '" />';
|
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/confused/confused.gif' . '" alt="' . ':confused:' . '" />';
|
||||||
|
@ -124,6 +130,7 @@ function smiley_pack_smilies(array &$b)
|
||||||
$b['texts'][] = ':dazed:';
|
$b['texts'][] = ':dazed:';
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/confused/dazed.gif' . '" alt="' . ':dazed:' . '" />';
|
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/confused/dazed.gif' . '" alt="' . ':dazed:' . '" />';
|
||||||
|
|
||||||
|
|
||||||
#Cool Smileys
|
#Cool Smileys
|
||||||
|
|
||||||
$b['texts'][] = ':affro:';
|
$b['texts'][] = ':affro:';
|
||||||
|
@ -383,18 +390,6 @@ function smiley_pack_smilies(array &$b)
|
||||||
$b['texts'][] = ':number1:';
|
$b['texts'][] = ':number1:';
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/respect/number1.gif' . '" alt="' . ':number1:' . '" />';
|
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/respect/number1.gif' . '" alt="' . ':number1:' . '" />';
|
||||||
|
|
||||||
$b['texts'][] = ':cc_cc:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/respect/cc.png' . '" alt="' . ':cc_cc:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':cc_by:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/respect/ccby.png' . '" alt="' . ':cc_by:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':cc_sa:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/respect/ccsa.png' . '" alt="' . ':cc_sa:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':cc_0:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/respect/cc0.png' . '" alt="' . ':cc_0:' . '" />';
|
|
||||||
|
|
||||||
#Laugh smileys
|
#Laugh smileys
|
||||||
|
|
||||||
$b['texts'][] = ':hahaha:';
|
$b['texts'][] = ':hahaha:';
|
||||||
|
@ -411,6 +406,7 @@ function smiley_pack_smilies(array &$b)
|
||||||
$b['texts'][] = ':drums:';
|
$b['texts'][] = ':drums:';
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/music/drums.gif' . '" alt="' . ':drums:' . '" />';
|
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/music/drums.gif' . '" alt="' . ':drums:' . '" />';
|
||||||
|
|
||||||
|
|
||||||
$b['texts'][] = ':guitar:';
|
$b['texts'][] = ':guitar:';
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/music/guitar.gif' . '" alt="' . ':guitar:' . '" />';
|
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/music/guitar.gif' . '" alt="' . ':guitar:' . '" />';
|
||||||
|
|
||||||
|
@ -484,9 +480,11 @@ function smiley_pack_smilies(array &$b)
|
||||||
$b['texts'][] = ':gangs:';
|
$b['texts'][] = ':gangs:';
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/fight/gangs.gif' . '" alt="' . ':gangs:' . '" />';
|
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/fight/gangs.gif' . '" alt="' . ':gangs:' . '" />';
|
||||||
|
|
||||||
|
|
||||||
$b['texts'][] = ':dj:';
|
$b['texts'][] = ':dj:';
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/music/dj.gif' . '" alt="' . ':dj:' . '" />';
|
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/music/dj.gif' . '" alt="' . ':dj:' . '" />';
|
||||||
|
|
||||||
|
|
||||||
$b['texts'][] = ':elvis:';
|
$b['texts'][] = ':elvis:';
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/music/elvis.gif' . '" alt="' . ':elivs:' . '" />';
|
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/music/elvis.gif' . '" alt="' . ':elivs:' . '" />';
|
||||||
|
|
||||||
|
@ -497,10 +495,7 @@ function smiley_pack_smilies(array &$b)
|
||||||
# Fediverse
|
# Fediverse
|
||||||
|
|
||||||
$b['texts'][] = ':friendica:';
|
$b['texts'][] = ':friendica:';
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/fediverse/friendica.png' . '" alt="' . ':friendica:' . '" />';
|
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/fediverse/friendica.gif' . '" alt="' . ':friendica:' . '" />';
|
||||||
|
|
||||||
$b['texts'][] = ':fediverse:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/fediverse/fediverse.gif' . '" alt="' . ':fediverse:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':mastodon:';
|
$b['texts'][] = ':mastodon:';
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/fediverse/mastodon.gif' . '" alt="' . ':mastodon:' . '" />';
|
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/fediverse/mastodon.gif' . '" alt="' . ':mastodon:' . '" />';
|
||||||
|
@ -512,10 +507,10 @@ function smiley_pack_smilies(array &$b)
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/fediverse/misskey.gif' . '" alt="' . ':misskey:' . '" />';
|
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/fediverse/misskey.gif' . '" alt="' . ':misskey:' . '" />';
|
||||||
|
|
||||||
$b['texts'][] = ':diaspora:';
|
$b['texts'][] = ':diaspora:';
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/fediverse/diaspora.png' . '" alt="' . ':diaspora:' . '" />';
|
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/fediverse/diaspora.gif' . '" alt="' . ':diaspora:' . '" />';
|
||||||
|
|
||||||
$b['texts'][] = ':hubzilla:';
|
$b['texts'][] = ':hubzilla:';
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/fediverse/hubzilla.png' . '" alt="' . ':hubzilla:' . '" />';
|
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/fediverse/hubzilla.gif' . '" alt="' . ':hubzilla:' . '" />';
|
||||||
|
|
||||||
$b['texts'][] = ':pixelfed:';
|
$b['texts'][] = ':pixelfed:';
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/fediverse/pixelfed.gif' . '" alt="' . ':pixelfeed:' . '" />';
|
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/fediverse/pixelfed.gif' . '" alt="' . ':pixelfeed:' . '" />';
|
||||||
|
@ -544,107 +539,4 @@ function smiley_pack_smilies(array &$b)
|
||||||
|
|
||||||
$b['texts'][] = ':twitch:';
|
$b['texts'][] = ':twitch:';
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/commercial/twitch.gif' . '" alt="' . ':twitch:' . '" />';
|
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/commercial/twitch.gif' . '" alt="' . ':twitch:' . '" />';
|
||||||
|
|
||||||
$b['texts'][] = ':facebook:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/commercial/facebook.gif' . '" alt="' . ':facebook:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':threads:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/commercial/threads.png' . '" alt="' . ':threads:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':google:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/commercial/google.gif' . '" alt="' . ':google:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':signal:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/commercial/signal.gif' . '" alt="' . ':signal:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':tiktok:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/commercial/tiktok.gif' . '" alt="' . ':tiktok:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':whatsapp:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/commercial/whatsapp.gif' . '" alt="' . ':whatsapp:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':instagram:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/commercial/instagram.gif' . '" alt="' . ':instagram:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':telegram:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/commercial/telegram.gif' . '" alt="' . ':telegram:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':windows:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/commercial/windows.png' . '" alt="' . ':windows:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':github:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/commercial/github.png' . '" alt="' . ':github:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':threema:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/commercial/threema.png' . '" alt="' . ':threema:' . '" />';
|
|
||||||
|
|
||||||
# nonCommercial
|
|
||||||
|
|
||||||
$b['texts'][] = ':invidious:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/noncommercial/invidious.gif' . '" alt="' . ':invidious:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':bluesky:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/noncommercial/bluesky.png' . '" alt="' . ':bluesky:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':vivaldi:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/noncommercial/vivaldi.png' . '" alt="' . ':vivaldi:' . '" />';
|
|
||||||
|
|
||||||
# opensource
|
|
||||||
|
|
||||||
$b['texts'][] = ':firefox:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/firefox.png' . '" alt="' . ':firefox:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':linuxopensuse:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/opensuse.png' . '" alt="' . ':linuxopensuse:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':linuxdebian:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/debian.png' . '" alt="' . ':linuxdebian:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':linuxfedora:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/fedora.png' . '" alt="' . ':linuxfedora:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':linuxubuntu:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/ubuntu.png' . '" alt="' . ':linuxubuntu:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':linuxmint:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/mint.png' . '" alt="' . ':linuxmint:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':fdroid:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/fdroid.png' . '" alt="' . ':fdroid:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':tutanota:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/tutanota.png' . '" alt="' . ':tutanota:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':raspi:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/raspi.png' . '" alt="' . ':raspi:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':linux:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/linux.png' . '" alt="' . ':linux:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':kde:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/kde.png' . '" alt="' . ':kde:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':firefoxnightly:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/firefoxnightly.png' . '" alt="' . ':firefoxnightly:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':archlinux:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/archlinux.png' . '" alt="' . ':archlinux:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':thunderbird:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/thunderbird.png' . '" alt="' . ':thunderbird:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':vivaldi:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/vivaldi.png' . '" alt="' . ':vivaldi:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':jabber:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/jabber.png' . '" alt="' . ':jabber:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':matrix:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/matrix.png' . '" alt="' . ':matrix:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':xmpp:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/xmpp.png' . '" alt="' . ':xmpp:' . '" />';
|
|
||||||
|
|
||||||
$b['texts'][] = ':foss:';
|
|
||||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/foss.png' . '" alt="' . ':foss:' . '" />';
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,81 +8,64 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: friendica\n"
|
"Project-Id-Version: friendica\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2023-04-29 06:56+0000\n"
|
"POT-Creation-Date: 2021-07-25 13:15+0000\n"
|
||||||
"PO-Revision-Date: 2014-06-23 12:58+0000\n"
|
"PO-Revision-Date: 2021-02-20 00:23+0000\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: Farida Khalaf <faridakhalaf@hotmail.com>\n"
|
||||||
"Language-Team: Arabic (http://app.transifex.com/Friendica/friendica/language/ar/)\n"
|
"Language-Team: Arabic (http://www.transifex.com/Friendica/friendica/language/ar/)\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Language: ar\n"
|
"Language: ar\n"
|
||||||
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
|
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
|
||||||
|
|
||||||
#: tumblr.php:243
|
#: tumblr.php:40
|
||||||
msgid "Permission denied."
|
msgid "Permission denied."
|
||||||
msgstr "الطلب مرفوض."
|
msgstr "الطلب مرفوض."
|
||||||
|
|
||||||
#: tumblr.php:296
|
#: tumblr.php:70 tumblr.php:284
|
||||||
msgid "Save Settings"
|
msgid "Save Settings"
|
||||||
msgstr "Save Settings"
|
msgstr "Save Settings"
|
||||||
|
|
||||||
#: tumblr.php:297
|
#: tumblr.php:72
|
||||||
msgid "Consumer Key"
|
msgid "Consumer Key"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tumblr.php:298
|
#: tumblr.php:73
|
||||||
msgid "Consumer Secret"
|
msgid "Consumer Secret"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tumblr.php:299
|
#: tumblr.php:178
|
||||||
msgid "Maximum tags"
|
msgid "You are now authenticated to tumblr."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tumblr.php:299
|
#: tumblr.php:179
|
||||||
msgid ""
|
msgid "return to the connector page"
|
||||||
"Maximum number of tags that a user can follow. Enter 0 to deactivate the "
|
msgstr "الرجوع إلى صفحة الموصل"
|
||||||
"feature."
|
|
||||||
|
#: tumblr.php:195
|
||||||
|
msgid "Post to Tumblr"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tumblr.php:336
|
#: tumblr.php:225 tumblr.php:229
|
||||||
msgid "Post to page:"
|
msgid "Tumblr Export"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tumblr.php:342
|
#: tumblr.php:233
|
||||||
msgid "(Re-)Authenticate your tumblr page"
|
msgid "(Re-)Authenticate your tumblr page"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tumblr.php:343
|
#: tumblr.php:237
|
||||||
msgid "You are not authenticated to tumblr"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tumblr.php:348
|
|
||||||
msgid "Enable Tumblr Post Addon"
|
msgid "Enable Tumblr Post Addon"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tumblr.php:349
|
#: tumblr.php:243
|
||||||
msgid "Post to Tumblr by default"
|
msgid "Post to Tumblr by default"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tumblr.php:350
|
#: tumblr.php:264
|
||||||
msgid "Import the remote timeline"
|
msgid "Post to page:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tumblr.php:351
|
#: tumblr.php:278
|
||||||
msgid "Subscribed tags"
|
msgid "You are not authenticated to tumblr"
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tumblr.php:351
|
|
||||||
#, php-format
|
|
||||||
msgid ""
|
|
||||||
"Comma separated list of up to %d tags that will be imported additionally to "
|
|
||||||
"the timeline"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tumblr.php:357
|
|
||||||
msgid "Tumblr Import/Export"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tumblr.php:375
|
|
||||||
msgid "Post to Tumblr"
|
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|