Merge branch '2024.06-rc' into stable

This commit is contained in:
Tobias Diekershoff 2024-08-17 16:54:44 +02:00
commit 5c04e7136f
55 changed files with 1509 additions and 617 deletions

View file

@ -5,7 +5,7 @@
#
# Translators:
# fabrixxm <fabrix.xm@gmail.com>, 2018
# Sylke Vicious <silkevicious@gmail.com>, 2021
# Sylke Vicious <silkevicious@gmail.com>, 2023
#
#, fuzzy
msgid ""
@ -14,7 +14,7 @@ msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-05-11 08:54-0400\n"
"PO-Revision-Date: 2018-05-24 06:41+0000\n"
"Last-Translator: Sylke Vicious <silkevicious@gmail.com>, 2021\n"
"Last-Translator: Sylke Vicious <silkevicious@gmail.com>, 2023\n"
"Language-Team: Italian (https://app.transifex.com/Friendica/teams/12172/it/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -125,7 +125,7 @@ msgstr "Annulla"
#: advancedcontentfilter.php:295
msgid "This addon requires this node having at least one post"
msgstr ""
msgstr "Questo addon richiede che questo nodo abbia almeno un messaggio"
#: advancedcontentfilter.php:325 advancedcontentfilter.php:336
#: advancedcontentfilter.php:347 advancedcontentfilter.php:383

View file

@ -27,6 +27,7 @@ $a->strings['Add new rule'] = 'Aggiungi nuova regola';
$a->strings['Rule Name'] = 'Nome Regola';
$a->strings['Rule Expression'] = 'Espressione Regola';
$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['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.';

View file

@ -2,7 +2,7 @@
/**
* Name: blockbot
* Description: Blocking bots based on detecting bots/crawlers/spiders via the user agent and http_from header.
* Version: 0.2
* Version: 1.0
* Author: Philipp Holzer <admin@philipp.info>
* Author: Michael Vogel <https://pirati.ca/profile/heluecht>
*
@ -13,7 +13,10 @@ use Friendica\DI;
use Jaybizzle\CrawlerDetect\CrawlerDetect;
use Friendica\Core\Logger;
use Friendica\Core\Renderer;
use Friendica\Core\System;
use Friendica\Network\HTTPException\ForbiddenException;
use Friendica\Util\HTTPSignature;
use Friendica\Util\Network;
require_once __DIR__ . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
@ -28,115 +31,127 @@ function blockbot_addon_admin(string &$o)
$o = Renderer::replaceMacros($t, [
'$submit' => DI::l10n()->t('Save Settings'),
'$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.")],
'$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.")],
'$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.")],
]);
}
function blockbot_addon_admin_post()
{
DI::config()->set('blockbot', 'good_crawlers', $_POST['good_crawlers'] ?? false);
DI::config()->set('blockbot', 'socialmedia_agents', $_POST['socialmedia_agents'] ?? false);
DI::config()->set('blockbot', 'security_checker', $_POST['security_checker'] ?? 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);
}
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()
{
if (empty($_SERVER['HTTP_USER_AGENT'])) {
return;
}
$logdata = ['agent' => $_SERVER['HTTP_USER_AGENT'], 'uri' => $_SERVER['REQUEST_URI']];
$crawlerDetect = new CrawlerDetect();
// 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',
];
$isCrawler = $crawlerDetect->isCrawler();
if (DI::config()->get('blockbot', 'block_gab')) {
$agents[] = 'GabSocial/';
blockbot_save('all-agents', $_SERVER['HTTP_USER_AGENT']);
$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);
}
// List of "good" crawlers, mostly from the fediverse.
$good_agents = [
'fediverse.space crawler', 'fediverse.network crawler', 'Active_Pods_CheckBot_3.0',
'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)) {
if (empty($parts)) {
Logger::debug('Known frontend found - accept', $logdata);
if ($isCrawler) {
blockbot_save('badly-parsed-agents', $_SERVER['HTTP_USER_AGENT']);
}
return;
}
// 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/',
];
blockbot_log_activitypub($_SERVER['REQUEST_URI'], $_SERVER['HTTP_USER_AGENT']);
if (!DI::config()->get('blockbot', 'socialmedia_agents')) {
$agents = array_merge($agents, $socialmedia_agents);
} elseif (blockbot_match($socialmedia_agents)) {
return;
if (blockbot_is_crawler($parts)) {
Logger::debug('Crawler found - reject', $logdata);
blockbot_reject();
}
// HTTP Libraries
$http_libraries = ['ReactorNetty/', 'GuzzleHttp/', 'Embed PHP library', 'python-urllib3/',
'EventMachine HttpClient', 'HTMLParser/'
];
if (!DI::config()->get('blockbot', 'http_libraries')) {
$agents = array_merge($agents, $http_libraries);
} elseif (blockbot_match($http_libraries)) {
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;
}
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');
if (blockbot_is_social_media($parts)) {
Logger::debug('Social media service found - accept', $logdata);
return;
}
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')) {
Logger::debug('HTTP Library found - reject', $logdata);
blockbot_reject();
}
Logger::debug('HTTP Library found - accept', $logdata);
return;
}
// This switch here is only meant for developers who want to add more bots to the list above, it is not safe for production.
@ -144,44 +159,684 @@ function blockbot_init_1()
return;
}
$crawlerDetect = new CrawlerDetect();
if (!$crawlerDetect->isCrawler()) {
logger::debug('Good user agent detected', $logdata);
if (!$isCrawler) {
blockbot_save('good-agents', $_SERVER['HTTP_USER_AGENT']);
Logger::debug('Non-bot user agent detected', $logdata);
return;
}
// List of known "good" agents, mostly used by Fediverse systems, feed readers, ...
$agents = [
'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',
];
if (blockbot_match($agents)) {
logger::info('False positive', $logdata);
return;
}
logger::notice('Blocked bot', $logdata);
throw new ForbiddenException('Bots are not allowed. If you consider this a mistake, create an issue at https://github.com/friendica/friendica');
blockbot_save('bad-agents', $_SERVER['HTTP_USER_AGENT']);
Logger::notice('Possible bot found - reject', $logdata);
blockbot_reject();
}
function blockbot_match(array $agents)
function blockbot_save($database, $userAgent)
{
foreach ($agents as $agent) {
if (stristr($_SERVER['HTTP_USER_AGENT'], $agent)) {
if (!DI::config()->get('blockbot', 'logging') || !function_exists('dba_open')) {
return;
}
$resource = dba_open(System::getTempPath() . '/' . $database, 'cl');
$result = dba_fetch($userAgent, $resource);
if ($result === false) {
dba_insert($userAgent, true, $resource);
}
dba_close($resource);
}
function blockbot_log_activitypub(string $url, string $agent)
{
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) {
if (strpos($part, $agent) !== false) {
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 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&#39',
'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;
}

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-03-05 04:51+0000\n"
"POT-Creation-Date: 2024-04-30 12:12+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -17,52 +17,29 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: blockbot.php:30
#: blockbot.php:32
msgid "Save Settings"
msgstr ""
#: blockbot.php:31
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."
#: blockbot.php:33
msgid "Allow security checkers"
msgstr ""
#: 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"
msgstr ""
#: blockbot.php:33
#: blockbot.php:34
msgid ""
"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."
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
msgid "Training mode"
msgstr ""

View file

@ -1,6 +1,4 @@
{{include file="field_checkbox.tpl" field=$good_crawlers}}
{{include file="field_checkbox.tpl" field=$socialmedia_agents}}
{{include file="field_checkbox.tpl" field=$security_checker}}
{{include file="field_checkbox.tpl" field=$http_libraries}}
{{include file="field_checkbox.tpl" field=$block_gab}}
{{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>

View file

@ -68,6 +68,7 @@ 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_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_HOSTNAME = 'bsky.social'; // Host name to be added to the handle if incomplete
function bluesky_install()
{
@ -97,11 +98,16 @@ function bluesky_load_config(ConfigFileManager $loader)
function bluesky_check_item_notification(array &$notification_data)
{
$did = DI::pConfig()->get($notification_data['uid'], 'bluesky', 'did');
if (!empty($did)) {
$notification_data['profiles'][] = $did;
if (empty($notification_data['uid'])) {
return;
}
$did = bluesky_get_user_did($notification_data['uid']);
if (empty($did)) {
return;
}
$notification_data['profiles'][] = $did;
}
function bluesky_probe_detect(array &$hookData)
@ -229,7 +235,7 @@ function bluesky_follow(array &$hook_data)
$post = [
'collection' => 'app.bsky.graph.follow',
'repo' => DI::pConfig()->get($hook_data['uid'], 'bluesky', 'did'),
'repo' => bluesky_get_user_did($hook_data['uid']),
'record' => $record
];
@ -282,15 +288,15 @@ function bluesky_block(array &$hook_data)
$post = [
'collection' => 'app.bsky.graph.block',
'repo' => DI::pConfig()->get($hook_data['uid'], 'bluesky', 'did'),
'repo' => bluesky_get_user_did($hook_data['uid']),
'record' => $record
];
$activity = bluesky_xrpc_post($hook_data['uid'], 'com.atproto.repo.createRecord', $post);
if (!empty($activity->uri)) {
$cdata = Contact::getPublicAndUserContactID($hook_data['contact']['id'], $hook_data['uid']);
if (!empty($cdata['user'])) {
Contact::remove($cdata['user']);
$ucid = Contact::getUserContactId($hook_data['contact']['id'], $hook_data['uid']);
if ($ucid) {
Contact::remove($ucid);
}
Logger::debug('Successfully blocked contact', ['url' => $hook_data['contact']['url'], 'uri' => $activity->uri]);
}
@ -323,7 +329,7 @@ function bluesky_addon_admin(string &$o)
$o = Renderer::replaceMacros($t, [
'$submit' => DI::l10n()->t('Save Settings'),
'$friendica_handles' => ['friendica_handles', DI::l10n()->t('Allow your users to use your hostname for their Bluesky handles'), DI::config()->get('bluesky', 'friendica_handles'), DI::l10n()->t('Before enabling this option, you have to download and configure the bluesky-handles repository on your system. See https://git.friendi.ca/heluecht/bluesky-handles')],
'$friendica_handles' => ['friendica_handles', DI::l10n()->t('Allow your users to use your hostname for their Bluesky handles'), DI::config()->get('bluesky', 'friendica_handles'), DI::l10n()->t('Before enabling this option, you have to setup a wildcard domain configuration and you have to enable wildcard requests in your webserver configuration. On Apache this is done by adding "ServerAlias *.%s" to your HTTP configuration. You don\'t need to change the HTTPS configuration.', DI::baseUrl()->getHost())],
]);
}
@ -342,7 +348,7 @@ function bluesky_settings(array &$data)
$def_enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'post_by_default') ?? false;
$pds = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'pds');
$handle = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'handle');
$did = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'did');
$did = bluesky_get_user_did(DI::userSession()->getLocalUserId());
$token = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'access_token');
$import = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'import') ?? false;
$import_feeds = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'import_feeds') ?? false;
@ -350,8 +356,11 @@ function bluesky_settings(array &$data)
if (DI::config()->get('bluesky', 'friendica_handles')) {
$self = User::getById(DI::userSession()->getLocalUserId(), ['nickname']);
$handle = $self['nickname'] . '.' . DI::baseUrl()->getHost();
$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)];
$host_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)];
if ($custom_handle) {
$handle = $host_handle;
}
} else {
$friendica_handle = [];
}
@ -364,7 +373,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.')],
'$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'],
'$handle' => ['bluesky_handle', DI::l10n()->t('Bluesky handle'), $handle],
'$handle' => ['bluesky_handle', DI::l10n()->t('Bluesky handle'), $handle, '', '', $custom_handle ? '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.")],
'$status' => bluesky_get_status($handle, $did, $pds, $token),
@ -435,18 +444,10 @@ function bluesky_settings_post(array &$b)
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_feeds', intval($_POST['bluesky_import_feeds']));
DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'friendica_handle', intval($_POST['bluesky_friendica_handle']));
DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'friendica_handle', intval($_POST['bluesky_friendica_handle'] ?? false));
if (!empty($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');
}
$did = bluesky_get_user_did(DI::userSession()->getLocalUserId(), empty($old_did) || $old_handle != $handle);
if (!empty($did) && (empty($old_pds) || $old_handle != $handle)) {
$pds = bluesky_get_pds($did);
if (empty($pds)) {
@ -513,8 +514,13 @@ function bluesky_cron()
$abandon_limit = date(DateTimeFormat::MYSQL, time() - $abandon_days * 86400);
$pconfigs = DBA::selectToArray('pconfig', [], ['cat' => 'bluesky', 'k' => 'import', 'v' => true]);
$pconfigs = DBA::selectToArray('pconfig', [], ["`cat` = ? AND `k` IN (?, ?) AND `v`", 'bluesky', 'import', 'import_feeds']);
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 (!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']]);
@ -523,19 +529,27 @@ function bluesky_cron()
}
// 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']);
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_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);
}
if (DI::pConfig()->get($pconfig['uid'], 'bluesky', 'import_feeds')) {
Logger::debug('Fetch feeds for user', ['uid' => $pconfig['uid']]);
$feeds = bluesky_get_feeds($pconfig['uid']);
foreach ($feeds as $feed) {
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');
if (empty($last_clean) || ($last_clean + 86400 < time())) {
Logger::notice('Start contact cleanup');
@ -549,8 +563,6 @@ function bluesky_cron()
}
Logger::notice('cron_end');
DI::keyValue()->set('bluesky_last_poll', time());
}
function bluesky_hook_fork(array &$b)
@ -664,7 +676,10 @@ function bluesky_create_activity(array $item, stdClass $parent = null)
return;
}
$did = DI::pConfig()->get($uid, 'bluesky', 'did');
$did = bluesky_get_user_did($uid);
if (empty($did)) {
return;
}
if ($item['verb'] == Activity::LIKE) {
$record = [
@ -724,7 +739,7 @@ function bluesky_create_post(array $item, stdClass $root = null, stdClass $paren
$item['body'] .= "\n[url]" . $media['url'] . "[/url]\n";
}
}
if (!empty($item['quote-uri-id'])) {
$quote = Post::selectFirstPost(['uri', 'plink'], ['uri-id' => $item['quote-uri-id']]);
if (!empty($quote)) {
@ -733,7 +748,7 @@ function bluesky_create_post(array $item, stdClass $root = null, stdClass $paren
}
}
}
$urls = bluesky_get_urls($item['body']);
$item['body'] = $urls['body'];
@ -772,7 +787,7 @@ function bluesky_create_post(array $item, stdClass $root = null, stdClass $paren
$post = [
'collection' => 'app.bsky.feed.post',
'repo' => DI::pConfig()->get($uid, 'bluesky', 'did'),
'repo' => bluesky_get_user_did($uid),
'record' => $record
];
@ -960,6 +975,7 @@ function bluesky_upload_blob(int $uid, array $photo): ?stdClass
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]);
return $data->blob;
}
@ -1033,8 +1049,8 @@ function bluesky_process_reason(stdClass $reason, string $uri, int $uid)
$item['owner-link'] = $item['author-link'];
$item['owner-avatar'] = $item['author-avatar'];
if (Item::insert($item)) {
$cdata = Contact::getPublicAndUserContactID($contact['id'], $uid);
Item::update(['post-reason' => Item::PR_ANNOUNCEMENT, 'causer-id' => $cdata['public']], ['uri' => $uri, 'uid' => $uid]);
$pcid = Contact::getPublicContactId($contact['id'], $uid);
Item::update(['post-reason' => Item::PR_ANNOUNCEMENT, 'causer-id' => $pcid], ['uri' => $uri, 'uid' => $uid]);
}
}
@ -1176,6 +1192,8 @@ function bluesky_process_post(stdClass $post, int $uid, int $fetch_uid, int $pos
$item = bluesky_add_media($post->embed, $item, $uid, $level, $last_poll);
}
$item['restrictions'] = bluesky_get_restrictions_for_user($post, $item, $post_reason);
if (empty($item['post-reason'])) {
$item['post-reason'] = $post_reason;
}
@ -1211,7 +1229,11 @@ function bluesky_get_header(stdClass $post, string $uri, int $uid, int $fetch_ui
'source' => json_encode($post),
];
$account = Contact::selectFirstAccountUser(['pid'], ['id' => $contact['id']]);
$item['author-id'] = $account['pid'];
$item['uri-id'] = ItemURI::getIdByURI($uri);
$item['owner-id'] = $item['author-id'];
$item['owner-name'] = $item['author-name'];
$item['owner-link'] = $item['author-link'];
$item['owner-avatar'] = $item['author-avatar'];
@ -1220,9 +1242,63 @@ function bluesky_get_header(stdClass $post, string $uri, int $uid, int $fetch_ui
$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;
}
function bluesky_get_restrictions_for_user(stdClass $post, array $item, int $post_reason): ?int
{
if (!empty($post->viewer->replyDisabled)) {
return Item::CANT_REPLY;
}
if (empty($post->threadgate)) {
return null;
}
if (!isset($post->threadgate->record->allow)) {
return null;
}
if ($item['uid'] == 0) {
return Item::CANT_REPLY;
}
$restrict = true;
$type = '$type';
foreach ($post->threadgate->record->allow as $allow) {
switch ($allow->$type) {
case 'app.bsky.feed.threadgate#followingRule':
// Only followers can reply.
if (Contact::isFollower($item['author-id'], $item['uid'])) {
$restrict = false;
}
break;
case 'app.bsky.feed.threadgate#mentionRule':
// Only mentioned accounts can reply.
if ($post_reason == Item::PR_TO) {
$restrict = false;
}
break;
case 'app.bsky.feed.threadgate#listRule';
// Only accounts in the provided list can reply. We don't support this at the moment.
break;
}
}
return $restrict ? Item::CANT_REPLY : null;
}
function bluesky_get_content(array $item, stdClass $record, string $uri, int $uid, int $fetch_uid, int $level, int $last_poll): array
{
if (empty($item)) {
@ -1446,6 +1522,10 @@ function bluesky_fetch_missing_post(string $uri, int $uid, int $fetch_uid, int $
}
$class = bluesky_get_uri_class($uri);
if (empty($class)) {
return $fallback;
}
$fetch_uri = $class->uri;
Logger::debug('Fetch missing post', ['level' => $level, 'uid' => $uid, 'uri' => $uri]);
@ -1458,8 +1538,7 @@ function bluesky_fetch_missing_post(string $uri, int $uid, int $fetch_uid, int $
Logger::debug('Reply count', ['level' => $level, 'uid' => $uid, 'uri' => $uri]);
if ($causer != 0) {
$cdata = Contact::getPublicAndUserContactID($causer, $uid);
$causer = $cdata['public'] ?? 0;
$causer = Contact::getPublicContactId($causer, $uid);
}
return bluesky_process_thread($data->thread, $uid, $fetch_uid, $post_reason, $causer, $level, $last_poll);
@ -1528,7 +1607,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
{
$condition = ['network' => Protocol::BLUESKY, 'uid' => 0, 'url' => $author->did];
$condition = ['network' => Protocol::BLUESKY, 'uid' => 0, 'nurl' => $author->did];
$contact = Contact::selectFirst(['id', 'updated'], $condition);
$update = empty($contact) || $contact['updated'] < DateTimeFormat::utc('now -24 hours');
@ -1546,7 +1625,7 @@ function bluesky_get_contact(stdClass $author, int $uid, int $fetch_uid): array
}
if ($uid != 0) {
$condition = ['network' => Protocol::BLUESKY, 'uid' => $uid, 'url' => $author->did];
$condition = ['network' => Protocol::BLUESKY, 'uid' => $uid, 'nurl' => $author->did];
$contact = Contact::selectFirst(['id', 'rel', 'uid'], $condition);
if (!isset($fields['rel']) && isset($contact['rel'])) {
@ -1641,6 +1720,9 @@ function bluesky_get_feeds(int $uid): array
{
$type = '$type';
$preferences = bluesky_get_preferences($uid);
if (empty($preferences) || empty($preferences->preferences)) {
return [];
}
foreach ($preferences->preferences as $preference) {
if ($preference->$type == 'app.bsky.actor.defs#savedFeedsPref') {
return $preference->pinned ?? [];
@ -1649,7 +1731,7 @@ function bluesky_get_feeds(int $uid): array
return [];
}
function bluesky_get_preferences(int $uid): stdClass
function bluesky_get_preferences(int $uid): ?stdClass
{
$cachekey = 'bluesky:preferences:' . $uid;
$data = DI::cache()->get($cachekey);
@ -1658,6 +1740,9 @@ function bluesky_get_preferences(int $uid): stdClass
}
$data = bluesky_xrpc_get($uid, 'app.bsky.actor.getPreferences');
if (empty($data)) {
return null;
}
DI::cache()->set($cachekey, $data, Duration::HOUR);
return $data;
@ -1669,7 +1754,7 @@ function bluesky_get_did_by_wellknown(string $handle): string
if ($curlResult->isSuccess() && substr($curlResult->getBodyString(), 0, 4) == 'did:') {
$did = $curlResult->getBodyString();
if (!bluesky_valid_did($did, $handle)) {
Logger::notice('Invalid DID', ['handle' => $handle, 'did' => $did]);
Logger::notice('Invalid DID', ['handle' => $handle, 'did' => $did]);
return '';
}
Logger::debug('Got DID by wellknown', ['handle' => $handle, 'did' => $did]);
@ -1688,7 +1773,7 @@ function bluesky_get_did_by_dns(string $handle): string
if (!empty($record['txt']) && substr($record['txt'], 0, 4) == 'did=') {
$did = substr($record['txt'], 4);
if (!bluesky_valid_did($did, $handle)) {
Logger::notice('Invalid DID', ['handle' => $handle, 'did' => $did]);
Logger::notice('Invalid DID', ['handle' => $handle, 'did' => $did]);
return '';
}
Logger::debug('Got DID by DNS', ['handle' => $handle, 'did' => $did]);
@ -1700,17 +1785,25 @@ function bluesky_get_did_by_dns(string $handle): string
function bluesky_get_did(string $handle): string
{
if ($handle == '') {
return '';
}
if (strpos($handle, '.') === false) {
$handle .= '.' . BLUESKY_HOSTNAME;
}
// Deactivated at the moment, since it isn't reliable by now
//$did = bluesky_get_did_by_dns($handle);
//if ($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 '';
@ -1719,18 +1812,47 @@ function bluesky_get_did(string $handle): string
return $data->did;
}
function bluesky_get_user_pds(int $uid): string
function bluesky_get_user_did(int $uid, bool $refresh = false): ?string
{
if (!$refresh) {
$did = DI::pConfig()->get($uid, 'bluesky', 'did');
if (!empty($did)) {
return $did;
}
}
$handle = DI::pConfig()->get($uid, 'bluesky', 'handle');
if (empty($handle)) {
return null;
}
$did = bluesky_get_did($handle);
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');
if (!empty($pds)) {
return $pds;
}
$did = DI::pConfig()->get($uid, 'bluesky', 'did');
$did = bluesky_get_user_did($uid);
if (empty($did)) {
Logger::notice('Empty did for user', ['uid' => $uid]);
return '';
return null;
}
$pds = bluesky_get_pds($did);
if (empty($pds)) {
return null;
}
DI::pConfig()->set($uid, 'bluesky', 'pds', $pds);
return $pds;
}
@ -1793,7 +1915,10 @@ function bluesky_refresh_token(int $uid): string
function bluesky_create_token(int $uid, string $password): string
{
$did = DI::pConfig()->get($uid, 'bluesky', 'did');
$did = bluesky_get_user_did($uid);
if (empty($did)) {
return '';
}
$data = bluesky_post($uid, '/xrpc/com.atproto.server.createSession', json_encode(['identifier' => $did, 'password' => $password]), ['Content-type' => 'application/json']);
if (empty($data)) {
@ -1811,13 +1936,22 @@ function bluesky_create_token(int $uid, string $password): string
function bluesky_xrpc_post(int $uid, string $url, $parameters): ?stdClass
{
return bluesky_post($uid, '/xrpc/' . $url, json_encode($parameters), ['Content-type' => 'application/json', 'Authorization' => ['Bearer ' . bluesky_get_token($uid)]]);
$data = 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
{
$pds = bluesky_get_user_pds($uid);
if (empty($pds)) {
return null;
}
try {
$curlResult = DI::httpClient()->post(bluesky_get_user_pds($uid) . $url, $params, $headers);
$curlResult = DI::httpClient()->post($pds . $url, $params, $headers);
} catch (\Exception $e) {
Logger::notice('Exception on post', ['exception' => $e]);
DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_API_FAIL);
@ -1840,7 +1974,12 @@ function bluesky_xrpc_get(int $uid, string $url, array $parameters = []): ?stdCl
$url .= '?' . http_build_query($parameters);
}
$data = bluesky_get(bluesky_get_user_pds($uid) . '/xrpc/' . $url, HttpClientAccept::JSON, [HttpClientOptions::HEADERS => ['Authorization' => ['Bearer ' . bluesky_get_token($uid)]]]);
$pds = bluesky_get_user_pds($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);
return $data;
}
@ -1850,14 +1989,15 @@ function bluesky_get(string $url, string $accept_content = HttpClientAccept::DEF
try {
$curlResult = DI::httpClient()->get($url, $accept_content, $opts);
} catch (\Exception $e) {
Logger::notice('Exception on get', ['exception' => $e]);
Logger::notice('Exception on get', ['url' => $url, 'exception' => $e]);
return null;
}
if (!$curlResult->isSuccess()) {
Logger::notice('API Error', ['error' => json_decode($curlResult->getBodyString()) ?: $curlResult->getBodyString()]);
Logger::notice('API Error', ['url' => $url, 'error' => json_decode($curlResult->getBodyString()) ?: $curlResult->getBodyString()]);
return null;
}
Item::incrementInbound(Protocol::BLUESKY);
return json_decode($curlResult->getBodyString());
}

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-02-28 03:05+0000\n"
"POT-Creation-Date: 2024-03-22 05:31+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -26,10 +26,12 @@ msgid "Allow your users to use your hostname for their Bluesky handles"
msgstr ""
#: bluesky.php:326
#, php-format
msgid ""
"Before enabling this option, you have to download and configure the bluesky-"
"handles repository on your system. See https://git.friendi.ca/heluecht/"
"bluesky-handles"
"Before enabling this option, you have to setup a wildcard domain "
"configuration and you have to enable wildcard requests in your webserver "
"configuration. On Apache this is done by adding \"ServerAlias *.%s\" to your "
"HTTP configuration. You don't need to change the HTTPS configuration."
msgstr ""
#: bluesky.php:354

View file

@ -6,55 +6,55 @@
# Translators:
# fabrixxm <fabrix.xm@gmail.com>, 2018
# Davide Pesenti <mrjive@mrjive.it>, 2018
# Sylke Vicious <silkevicious@gmail.com>, 2021
# Sylke Vicious <silkevicious@gmail.com>, 2023
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-12-29 00:53+0000\n"
"POT-Creation-Date: 2021-11-21 19:14-0500\n"
"PO-Revision-Date: 2018-04-07 05:23+0000\n"
"Last-Translator: Sylke Vicious <silkevicious@gmail.com>, 2021\n"
"Language-Team: Italian (https://www.transifex.com/Friendica/teams/12172/it/)\n"
"Last-Translator: Sylke Vicious <silkevicious@gmail.com>, 2023\n"
"Language-Team: Italian (https://app.transifex.com/Friendica/teams/12172/it/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: it\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
#: catavatar.php:48
msgid "Use Cat as Avatar"
msgstr "Usa il Gatto come avatar"
#: catavatar.php:49
msgid "More Random Cat!"
msgstr "Altro Gatto a caso!"
#: catavatar.php:50
msgid "Reset to email Cat"
msgstr "Reimposta Gatto"
#: 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
#: catavatar.php:53
msgid "Cat Avatar Settings"
msgstr "Impostazioni Avatar Gatto"
#: catavatar.php:56
msgid "Use Cat as Avatar"
msgstr "Usa il Gatto come avatar"
#: catavatar.php:57
msgid "Another random Cat!"
msgstr "Un altro Gatto casuale!"
#: catavatar.php:58
msgid "Reset to email Cat"
msgstr "Reimposta Gatto"
#: catavatar.php:77
msgid "The cat hadn't found itself."
msgstr "Il gatto non ha trovato sé stesso."
#: catavatar.php:87
#: catavatar.php:86
msgid "There was an error, the cat ran away."
msgstr "Si è verificato un errore, il gatto è scappato."
#: catavatar.php:93
#: catavatar.php:92
msgid "Profile Photos"
msgstr "Foto del profilo"
#: catavatar.php:108
#: catavatar.php:102
msgid "Meow!"
msgstr "Miao!"

View file

@ -3,13 +3,13 @@
if(! function_exists("string_plural_select_it")) {
function string_plural_select_it($n){
$n = intval($n);
return intval($n != 1);
if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; }
}}
$a->strings['Use Cat as Avatar'] = 'Usa il Gatto come avatar';
$a->strings['More Random Cat!'] = 'Altro Gatto a caso!';
$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['Cat Avatar Settings'] = 'Impostazioni Avatar Gatto';
$a->strings['Use Cat as Avatar'] = 'Usa il Gatto come avatar';
$a->strings['Another random Cat!'] = 'Un altro Gatto casuale!';
$a->strings['Reset to email Cat'] = 'Reimposta Gatto';
$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['Profile Photos'] = 'Foto del profilo';

View file

@ -9,12 +9,10 @@
*
*/
use Friendica\App;
use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Hook;
use Friendica\Core\Renderer;
use Friendica\DI;
use Friendica\Util\Proxy as ProxyUtils;
function curweather_install()
{
@ -127,7 +125,7 @@ function curweather_network_mod_init(string &$body)
$t = Renderer::getMarkupTemplate("widget.tpl", "addon/curweather/" );
$curweather = Renderer::replaceMacros($t, [
'$title' => DI::l10n()->t("Current Weather"),
'$icon' => ProxyUtils::proxifyUrl('http://openweathermap.org/img/w/'.$res['icon'].'.png'),
'$icon' => 'http://openweathermap.org/img/w/'.$res['icon'].'.png',
'$city' => $res['city'],
'$lon' => $res['lon'],
'$lat' => $res['lat'],
@ -154,7 +152,7 @@ function curweather_network_mod_init(string &$body)
function curweather_addon_settings_post($post)
{
if (!DI::userSession()->getLocalUserId() || empty($_POST['curweather-settings-submit'])) {
if (!DI::userSession()->getLocalUserId() || empty($_POST['curweather-submit'])) {
return;
}

View file

@ -5,6 +5,7 @@
#
# Translators:
# bob lebonche <lebonche@tutanota.com>, 2021
# cracrayol, 2024
# Hypolite Petovan <hypolite@mrpetovan.com>, 2022
# Hypolite Petovan <hypolite@mrpetovan.com>, 2016
# ea1cd8241cb389ffb6f92bc6891eff5d_dc12308 <70dced5587d47e18d88f9298024d96f8_93383>, 2015
@ -15,8 +16,8 @@ msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-21 19:14-0500\n"
"PO-Revision-Date: 2014-06-22 11:34+0000\n"
"Last-Translator: Hypolite Petovan <hypolite@mrpetovan.com>, 2022\n"
"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n"
"Last-Translator: cracrayol, 2024\n"
"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@ -45,7 +46,7 @@ msgstr "Vent"
#: curweather.php:140
msgid "Last Updated"
msgstr "Dernière mise-à-jour"
msgstr "Dernière mise à jour"
#: curweather.php:141
msgid "Data by"

View file

@ -10,7 +10,7 @@ $a->strings['Current Weather'] = 'Météo actuelle';
$a->strings['Relative Humidity'] = 'Humidité relative';
$a->strings['Pressure'] = 'Pression';
$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['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';

View file

@ -5,27 +5,27 @@
#
# Translators:
# fabrixxm <fabrix.xm@gmail.com>, 2014-2015
# Sylke Vicious <silkevicious@gmail.com>, 2021
# Sylke Vicious <silkevicious@gmail.com>, 2021,2023
# Tobias Diekershoff <tobias.diekershoff@gmx.net>, 2016
msgid ""
msgstr ""
"Project-Id-Version: friendica\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-02-01 18:15+0100\n"
"PO-Revision-Date: 2021-02-16 12:57+0000\n"
"Last-Translator: Sylke Vicious <silkevicious@gmail.com>\n"
"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n"
"POT-Creation-Date: 2021-11-21 19:14-0500\n"
"PO-Revision-Date: 2014-06-22 11:34+0000\n"
"Last-Translator: Sylke Vicious <silkevicious@gmail.com>, 2021,2023\n"
"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: it\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
#: curweather.php:47
msgid "Error fetching weather data. Error was: "
msgstr "Errore durante il recupero dei dati meteo. L'errore è stato:"
#: curweather.php:130 curweather.php:192
#: curweather.php:130
msgid "Current Weather"
msgstr "Meteo"
@ -61,66 +61,66 @@ msgstr "C'è stato un problema accedendo ai dati meteo, ma dai un'occhiata"
msgid "at OpenWeatherMap"
msgstr "a OpenWeatherMap"
#: curweather.php:179
#: curweather.php:178
msgid "No APPID found, please contact your admin to obtain one."
msgstr "APPID non trovata, contatta il tuo amministratore per averne una."
#: curweather.php:191 curweather.php:229
msgid "Save Settings"
msgstr "Salva Impostazioni"
#: curweather.php:192
msgid "Settings"
msgstr "Impostazioni"
#: curweather.php:194
#: curweather.php:188
msgid "Enter either the name of your location or the zip code."
msgstr "Inserisci il nome della tua posizione o il CAP"
#: curweather.php:195
#: curweather.php:189
msgid "Your Location"
msgstr "La tua Posizione"
#: curweather.php:195
#: curweather.php:189
msgid ""
"Identifier of your location (name or zip code), e.g. <em>Berlin,DE</em> or "
"<em>14476,DE</em>."
msgstr "Identificatore della tua posizione (nome o CAP), p.e. <em>Roma, IT</em> or <em>00186,IT</em>."
#: curweather.php:196
#: curweather.php:190
msgid "Units"
msgstr "Unità"
#: curweather.php:196
#: curweather.php:190
msgid "select if the temperature should be displayed in &deg;C or &deg;F"
msgstr "scegli se la temperatura deve essere mostrata in °C o in °F"
#: curweather.php:197
#: curweather.php:191
msgid "Show weather data"
msgstr "Mostra dati meteo"
#: curweather.php:232
#: curweather.php:196
msgid "Current Weather Settings"
msgstr "Impostazioni Meteo"
#: curweather.php:227
msgid "Save Settings"
msgstr "Salva Impostazioni"
#: curweather.php:230
msgid "Caching Interval"
msgstr "Intervallo di cache"
#: curweather.php:234
#: curweather.php:232
msgid ""
"For how long should the weather data be cached? Choose according your "
"OpenWeatherMap account type."
msgstr "Per quanto tempo i dati meteo devono essere memorizzati? Scegli a seconda del tuo tipo di account su OpenWeatherMap."
#: curweather.php:235
#: curweather.php:233
msgid "no cache"
msgstr "nessuna cache"
#: curweather.php:236 curweather.php:237 curweather.php:238 curweather.php:239
#: curweather.php:234 curweather.php:235 curweather.php:236 curweather.php:237
msgid "minutes"
msgstr "minuti"
#: curweather.php:242
#: curweather.php:240
msgid "Your APPID"
msgstr "Il tuo APPID"
#: curweather.php:242
#: curweather.php:240
msgid "Your API key provided by OpenWeatherMap"
msgstr "La tua chiave API da OpenWeatherMap"

View file

@ -3,7 +3,7 @@
if(! function_exists("string_plural_select_it")) {
function string_plural_select_it($n){
$n = intval($n);
return intval($n != 1);
if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; }
}}
$a->strings['Error fetching weather data. Error was: '] = 'Errore durante il recupero dei dati meteo. L\'errore è stato:';
$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['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['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['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['Units'] = 'Unità';
$a->strings['select if the temperature should be displayed in &deg;C or &deg;F'] = 'scegli se la temperatura deve essere mostrata in °C o in °F';
$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['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';

View file

@ -5,45 +5,41 @@
#
# Translators:
# fabrixxm <fabrix.xm@gmail.com>, 2014,2018
# Sylke Vicious <silkevicious@gmail.com>, 2020-2021
# Sylke Vicious <silkevicious@gmail.com>, 2020-2021,2023
msgid ""
msgstr ""
"Project-Id-Version: friendica\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-02-01 18:15+0100\n"
"PO-Revision-Date: 2021-02-16 12:55+0000\n"
"Last-Translator: Sylke Vicious <silkevicious@gmail.com>\n"
"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n"
"POT-Creation-Date: 2021-11-21 19:17-0500\n"
"PO-Revision-Date: 2014-06-22 11:41+0000\n"
"Last-Translator: Sylke Vicious <silkevicious@gmail.com>, 2020-2021,2023\n"
"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: it\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
#: dwpost.php:41
#: dwpost.php:43
msgid "Post to Dreamwidth"
msgstr "Invia a Dreamwidth"
#: dwpost.php:72 dwpost.php:76
msgid "Dreamwidth Export"
msgstr "Esporta Dreamwidth"
#: dwpost.php:63
msgid "Enable Dreamwidth Post Addon"
msgstr "Abilita il componente aggiuntivo di pubblicazione Dreamwidth"
#: dwpost.php:80
msgid "Enable dreamwidth Post Addon"
msgstr "Abilita il componente aggiuntivo di invio a Dreamwidth"
#: dwpost.php:85
msgid "dreamwidth username"
#: dwpost.php:64
msgid "Dreamwidth username"
msgstr "Nome utente Dreamwidth"
#: dwpost.php:90
msgid "dreamwidth password"
msgstr "password Dreamwidth"
#: dwpost.php:65
msgid "Dreamwidth password"
msgstr "Password Dreamwidth"
#: dwpost.php:95
msgid "Post to dreamwidth by default"
msgstr "Invia sempre a Dreamwidth"
#: dwpost.php:66
msgid "Post to Dreamwidth by default"
msgstr "Pubblica su dreamwidth per impostazione predefinita"
#: dwpost.php:100
msgid "Save Settings"
msgstr "Salva Impostazioni"
#: dwpost.php:71
msgid "Dreamwidth Export"
msgstr "Esporta Dreamwidth"

View file

@ -3,12 +3,11 @@
if(! function_exists("string_plural_select_it")) {
function string_plural_select_it($n){
$n = intval($n);
return intval($n != 1);
if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; }
}}
$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['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';

View file

@ -8,7 +8,6 @@
* Note: Please use Group Directory instead
*/
use Friendica\App;
use Friendica\Content\Nav;
use Friendica\Content\Pager;
use Friendica\Content\Widget;
@ -16,8 +15,8 @@ use Friendica\Core\Hook;
use Friendica\Core\Renderer;
use Friendica\Database\DBA;
use Friendica\DI;
use Friendica\Model\Profile;
use Friendica\Model\User;
use Friendica\Security\OpenWebAuth;
global $forumdirectory_search;
@ -82,7 +81,7 @@ function forumdirectory_content()
$gdirpath = '';
$dirurl = DI::config()->get('system', 'directory');
if (strlen($dirurl)) {
$gdirpath = Profile::zrl($dirurl, true);
$gdirpath = OpenWebAuth::getZrlUrl($dirurl, true);
}
$sql_extra = '';
@ -104,8 +103,8 @@ function forumdirectory_content()
$total = 0;
$cnt = DBA::fetchFirst("SELECT COUNT(*) AS `total` FROM `profile`
INNER JOIN `user` ON `user`.`uid` = `profile`.`uid`
WHERE $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` AND `user`.`page-flags` = ? $sql_extra",
User::PAGE_FLAGS_COMMUNITY);
WHERE $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` AND `user`.`page-flags` IN (?, ?) $sql_extra",
User::PAGE_FLAGS_COMMUNITY, User::PAGE_FLAGS_COMM_MAN);
if (DBA::isResult($cnt)) {
$total = $cnt['total'];
}
@ -120,8 +119,8 @@ function forumdirectory_content()
`contact`.`addr`, `contact`.`url` FROM `profile`
INNER JOIN `user` ON `user`.`uid` = `profile`.`uid`
INNER JOIN `contact` ON `contact`.`uid` = `user`.`uid`
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
WHERE $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` AND `user`.`page-flags` IN (?, ?) AND `contact`.`self`
$sql_extra $order LIMIT $limit", User::PAGE_FLAGS_COMMUNITY, User::PAGE_FLAGS_COMM_MAN
);
if (DBA::isResult($r)) {

View file

@ -6,6 +6,7 @@
# Translators:
# bob lebonche <lebonche@tutanota.com>, 2021
# ButterflyOfFire, 2020
# cracrayol, 2024
# Hypolite Petovan <hypolite@mrpetovan.com>, 2016
msgid ""
msgstr ""
@ -13,8 +14,8 @@ msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-21 19:14-0500\n"
"PO-Revision-Date: 2014-06-23 08:27+0000\n"
"Last-Translator: bob lebonche <lebonche@tutanota.com>, 2021\n"
"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n"
"Last-Translator: cracrayol, 2024\n"
"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@ -29,7 +30,7 @@ msgstr "Remplacer les coordonnées par le nom de la localité la plus proche dan
#: geonames.php:136
msgid "Enable Geonames Addon"
msgstr "Activer l'application complémentaire Geonames"
msgstr "Activer l'extension Geonames"
#: geonames.php:141
msgid "Geonames Settings"

View file

@ -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; }
}}
$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\'application complémentaire Geonames';
$a->strings['Enable Geonames Addon'] = 'Activer l\'extension Geonames';
$a->strings['Geonames Settings'] = 'Paramètres Geonames';

View file

@ -6,6 +6,7 @@
# Translators:
# bob lebonche <lebonche@tutanota.com>, 2021
# ButterflyOfFire, 2020
# cracrayol, 2024
# Hypolite Petovan <hypolite@mrpetovan.com>, 2016
msgid ""
msgstr ""
@ -13,8 +14,8 @@ msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-21 19:14-0500\n"
"PO-Revision-Date: 2014-06-23 08:30+0000\n"
"Last-Translator: bob lebonche <lebonche@tutanota.com>, 2021\n"
"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n"
"Last-Translator: cracrayol, 2024\n"
"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@ -29,7 +30,7 @@ msgstr "Permettre le filtrage des notifications de commentaires par courriel sur
#: gnot.php:64
msgid "Enable this addon?"
msgstr "Activer cette application complémentaire ?"
msgstr "Activer cette extension ?"
#: gnot.php:69
msgid "Gnot Settings"

View file

@ -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; }
}}
$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 application complémentaire ?';
$a->strings['Enable this addon?'] = 'Activer cette extension ?';
$a->strings['Gnot Settings'] = 'Paramètres Gnot';
$a->strings['[Friendica:Notify] Comment to conversation #%d'] = '[Friendica:Notify] Commentaire vers conversation #%d';

View file

@ -5,6 +5,7 @@
#
# Translators:
# bob lebonche <lebonche@tutanota.com>, 2021
# cracrayol, 2024
# Marie Olive <lacellule101@gmail.com>, 2018
# ea1cd8241cb389ffb6f92bc6891eff5d_dc12308 <70dced5587d47e18d88f9298024d96f8_93383>, 2015
msgid ""
@ -13,8 +14,8 @@ msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-02-01 18:15+0100\n"
"PO-Revision-Date: 2014-06-23 08:33+0000\n"
"Last-Translator: bob lebonche <lebonche@tutanota.com>, 2021\n"
"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n"
"Last-Translator: cracrayol, 2024\n"
"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@ -50,7 +51,7 @@ msgid ""
"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."
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."
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."
#: gravatar.php:102
msgid "Save Settings"

View file

@ -11,7 +11,7 @@ $a->strings['monster face'] = 'Face de monstre';
$a->strings['computer generated face'] = 'visage généré par ordinateur';
$a->strings['retro arcade style face'] = 'Face style retro arcade';
$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\'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['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['Save Settings'] = 'Sauvegarder les paramètres.';
$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.';

View file

@ -13,8 +13,8 @@ use Friendica\Core\Hook;
use Friendica\Core\Renderer;
use Friendica\Database\DBA;
use Friendica\DI;
use Friendica\Model\Profile;
use Friendica\Model\User;
use Friendica\Security\OpenWebAuth;
global $groupdirectory_search;
@ -79,7 +79,7 @@ function groupdirectory_content()
$gdirpath = '';
$dirurl = DI::config()->get('system', 'directory');
if (strlen($dirurl)) {
$gdirpath = Profile::zrl($dirurl, true);
$gdirpath = OpenWebAuth::getZrlUrl($dirurl, true);
}
$sql_extra = '';
@ -101,8 +101,8 @@ function groupdirectory_content()
$total = 0;
$cnt = DBA::fetchFirst("SELECT COUNT(*) AS `total` FROM `profile`
INNER JOIN `user` ON `user`.`uid` = `profile`.`uid`
WHERE $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` AND `user`.`page-flags` = ? $sql_extra",
User::PAGE_FLAGS_COMMUNITY);
WHERE $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` AND `user`.`page-flags` IN (?, ?) $sql_extra",
User::PAGE_FLAGS_COMMUNITY, User::PAGE_FLAGS_COMM_MAN);
if (DBA::isResult($cnt)) {
$total = $cnt['total'];
}
@ -117,8 +117,8 @@ function groupdirectory_content()
`contact`.`addr`, `contact`.`url` FROM `profile`
INNER JOIN `user` ON `user`.`uid` = `profile`.`uid`
INNER JOIN `contact` ON `contact`.`uid` = `user`.`uid`
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
WHERE $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` AND `user`.`page-flags` IN (?, ?) AND `contact`.`self`
$sql_extra $order LIMIT $limit", User::PAGE_FLAGS_COMMUNITY, User::PAGE_FLAGS_COMM_MAN
);
if (DBA::isResult($r)) {

View file

@ -5,6 +5,7 @@
#
# Translators:
# bob lebonche <lebonche@tutanota.com>, 2021
# cracrayol, 2024
# Hypolite Petovan <hypolite@mrpetovan.com>, 2016
msgid ""
msgstr ""
@ -12,8 +13,8 @@ msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-21 19:17-0500\n"
"PO-Revision-Date: 2014-06-23 08:37+0000\n"
"Last-Translator: bob lebonche <lebonche@tutanota.com>, 2021\n"
"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n"
"Last-Translator: cracrayol, 2024\n"
"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@ -26,7 +27,7 @@ msgstr "Publier sur Insanejournal"
#: ijpost.php:61
msgid "Enable InsaneJournal Post Addon"
msgstr "Activer l'application complémentaire InsaneJournalPost"
msgstr "Activer l'extension InsaneJournal"
#: ijpost.php:62
msgid "InsaneJournal username"

View file

@ -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; }
}}
$a->strings['Post to Insanejournal'] = 'Publier sur Insanejournal';
$a->strings['Enable InsaneJournal Post Addon'] = 'Activer l\'application complémentaire InsaneJournalPost';
$a->strings['Enable InsaneJournal Post Addon'] = 'Activer l\'extension InsaneJournal';
$a->strings['InsaneJournal username'] = 'Identifiant 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';

View file

@ -2,7 +2,7 @@
/*
* Name: invidious
* Description: Replaces links to youtube.com to an invidious instance in all displays of postings on a node.
* Version: 0.3
* Version: 0.4
* Author: Matthias Ebers <https://loma.ml/profile/feb>
* Author: Michael Vogel <https://pirati.ca/profile/heluecht>
* Status: Unsupported
@ -93,9 +93,9 @@ function invidious_render(array &$b)
$original = $b['html'];
$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\/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/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/shorts/(.*?)~ism", $server . '/shorts/$1', $b['html']);
$b['html'] = preg_replace("/https?:\/\/youtu.be\/(.*?)/ism", $server . '/watch?v=$1', $b['html']);
if ($original != $b['html']) {

View file

@ -7,11 +7,11 @@
* Maintainer: Hypolite Petovan <https://friendica.mrpetovan.com/profile/hypolite>
*/
use Friendica\App;
use Friendica\Core\Hook;
use Friendica\Core\Logger;
use Friendica\Core\Renderer;
use Friendica\DI;
use Friendica\Util\Images;
use Friendica\Util\Strings;
global $js_upload_jsonresponse;
@ -20,9 +20,9 @@ global $js_upload_result;
function js_upload_install()
{
Hook::register('photo_upload_form', __FILE__, 'js_upload_form');
Hook::register('photo_post_init', __FILE__, 'js_upload_post_init');
Hook::register('photo_post_file', __FILE__, 'js_upload_post_file');
Hook::register('photo_post_end', __FILE__, 'js_upload_post_end');
Hook::register('photo_post_init', __FILE__, 'js_upload_post_init');
Hook::register('photo_post_file', __FILE__, 'js_upload_post_file');
Hook::register('photo_post_end', __FILE__, 'js_upload_post_end');
}
function js_upload_form(array &$b)
@ -34,11 +34,11 @@ function js_upload_form(array &$b)
$tpl = Renderer::getMarkupTemplate('js_upload.tpl', 'addon/js_upload');
$b['addon_text'] .= Renderer::replaceMacros($tpl, [
'$upload_msg' => DI::l10n()->t('Select files for upload'),
'$drop_msg' => DI::l10n()->t('Drop files here to upload'),
'$cancel' => DI::l10n()->t('Cancel'),
'$failed' => DI::l10n()->t('Failed'),
'$post_url' => $b['post_url'],
'$upload_msg' => DI::l10n()->t('Select files for upload'),
'$drop_msg' => DI::l10n()->t('Drop files here to upload'),
'$cancel' => DI::l10n()->t('Cancel'),
'$failed' => DI::l10n()->t('Failed'),
'$post_url' => $b['post_url'],
'$maximagesize' => Strings::getBytesFromShorthand(DI::config()->get('system', 'maximagesize')),
]);
}
@ -48,7 +48,14 @@ function js_upload_post_init(array &$b)
global $js_upload_result, $js_upload_jsonresponse;
// list of valid extensions
$allowedExtensions = ['jpeg', 'gif', 'png', 'jpg'];
$allowedExtensions = [];
foreach (Images::IMAGETYPES as $type) {
$extension = image_type_to_extension($type, false);
if ($extension == 'jpeg') {
$allowedExtensions[] = 'jpg';
}
$allowedExtensions[] = $extension;
}
// max file size in bytes
$sizeLimit = Strings::getBytesFromShorthand(DI::config()->get('system', 'maximagesize'));
@ -75,10 +82,9 @@ function js_upload_post_file(array &$b)
$result = $js_upload_result;
$b['src'] = $result['path'];
$b['src'] = $result['path'];
$b['filename'] = $result['filename'];
$b['filesize'] = filesize($b['src']);
}
function js_upload_post_end(int &$b)
@ -179,11 +185,11 @@ class qqUploadedFileForm
class qqFileUploader
{
private $allowedExtensions = [];
private $sizeLimit = 10485760;
private $allowedExtensions;
private $sizeLimit;
private $file;
function __construct(array $allowedExtensions = [], $sizeLimit = 10485760)
function __construct(array $allowedExtensions = [], $sizeLimit)
{
$allowedExtensions = array_map('strtolower', $allowedExtensions);
@ -197,7 +203,6 @@ class qqFileUploader
} else {
$this->file = false;
}
}
/**
@ -215,11 +220,9 @@ class qqFileUploader
return ['error' => DI::l10n()->t('Uploaded file is empty')];
}
// if ($size > $this->sizeLimit) {
// return array('error' => DI::l10n()->t('Uploaded file is too large'));
// }
// if ($size > $this->sizeLimit) {
// return array('error' => DI::l10n()->t('Uploaded file is too large'));
// }
$maximagesize = Strings::getBytesFromShorthand(DI::config()->get('system', 'maximagesize'));
@ -241,14 +244,14 @@ class qqFileUploader
if ($this->file->save()) {
return [
'success' => true,
'path' => $this->file->getPath(),
'success' => true,
'path' => $this->file->getPath(),
'filename' => $filename . '.' . $ext
];
} else {
return [
'error' => DI::l10n()->t('Upload was cancelled, or server error encountered'),
'path' => $this->file->getPath(),
'error' => DI::l10n()->t('Upload was cancelled, or server error encountered'),
'path' => $this->file->getPath(),
'filename' => $filename . '.' . $ext
];
}

View file

@ -5,14 +5,15 @@
#
# Translators:
# bob lebonche <lebonche@tutanota.com>, 2021
# cracrayol, 2024
msgid ""
msgstr ""
"Project-Id-Version: friendica\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-21 19:14-0500\n"
"PO-Revision-Date: 2015-07-07 15:14+0000\n"
"Last-Translator: bob lebonche <lebonche@tutanota.com>, 2021\n"
"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n"
"Last-Translator: cracrayol, 2024\n"
"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@ -21,7 +22,7 @@ msgstr ""
#: krynn.php:127
msgid "Enable Krynn Addon"
msgstr "Activer l'application complémentaire Krynn"
msgstr "Activer l'extension Krynn"
#: krynn.php:132
msgid "Krynn Settings"

View file

@ -5,5 +5,5 @@ function string_plural_select_fr($n){
$n = intval($n);
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\'application complémentaire Krynn';
$a->strings['Enable Krynn Addon'] = 'Activer l\'extension Krynn';
$a->strings['Krynn Settings'] = 'Paramètres de Krynn';

View file

@ -5,45 +5,41 @@
#
# Translators:
# fabrixxm <fabrix.xm@gmail.com>, 2014-2015,2018
# Sylke Vicious <silkevicious@gmail.com>, 2021
# Sylke Vicious <silkevicious@gmail.com>, 2021,2023
msgid ""
msgstr ""
"Project-Id-Version: friendica\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-02-01 18:15+0100\n"
"PO-Revision-Date: 2021-02-16 12:47+0000\n"
"Last-Translator: Sylke Vicious <silkevicious@gmail.com>\n"
"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n"
"POT-Creation-Date: 2023-06-03 15:49-0400\n"
"PO-Revision-Date: 2014-06-23 09:44+0000\n"
"Last-Translator: Sylke Vicious <silkevicious@gmail.com>, 2021,2023\n"
"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: it\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
#: libertree.php:37
#: libertree.php:39
msgid "Post to libertree"
msgstr "Invia a Libertree"
#: libertree.php:71 libertree.php:75
msgid "libertree Export"
msgstr "Esporta libertree"
#: libertree.php:79
#: libertree.php:59
msgid "Enable Libertree Post Addon"
msgstr "Abilita il componente aggiuntivo di invio a Libertree"
#: libertree.php:84
msgid "Libertree API token"
msgstr "Token API Libertree"
#: libertree.php:89
#: libertree.php:60
msgid "Libertree site URL"
msgstr "Indirizzo sito Libertree"
#: libertree.php:94
#: libertree.php:61
msgid "Libertree API token"
msgstr "Token API Libertree"
#: libertree.php:62
msgid "Post to Libertree by default"
msgstr "Invia sempre a Libertree"
#: libertree.php:100
msgid "Save Settings"
msgstr "Salva Impostazioni"
#: libertree.php:67
msgid "Libertree Export"
msgstr "Esporta Libertree"

View file

@ -3,12 +3,11 @@
if(! function_exists("string_plural_select_it")) {
function string_plural_select_it($n){
$n = intval($n);
return intval($n != 1);
if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; }
}}
$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['Libertree API token'] = 'Token API Libertree';
$a->strings['Libertree site URL'] = 'Indirizzo sito Libertree';
$a->strings['Libertree API token'] = 'Token API Libertree';
$a->strings['Post to Libertree by default'] = 'Invia sempre a Libertree';
$a->strings['Save Settings'] = 'Salva Impostazioni';
$a->strings['Libertree Export'] = 'Esporta Libertree';

View file

@ -5,16 +5,18 @@
#
# Translators:
# Andreas H., 2014
# foss <oss@disr.it>, 2022
# Raroun, 2023
# Tobias Diekershoff <tobias.diekershoff@gmx.net>, 2018
# Ulf Rompe <transifex.com@rompe.org>, 2019
msgid ""
msgstr ""
"Project-Id-Version: friendica\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-03-11 19:13+0100\n"
"PO-Revision-Date: 2019-02-18 15:05+0000\n"
"Last-Translator: Ulf Rompe <transifex.com@rompe.org>\n"
"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n"
"POT-Creation-Date: 2021-11-21 19:15-0500\n"
"PO-Revision-Date: 2014-06-23 09:54+0000\n"
"Last-Translator: Raroun, 2023\n"
"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@ -29,72 +31,76 @@ msgstr "Absender"
msgid "Email address that stream items will appear to be from."
msgstr "E-Mail-Adresse, die in hochgeladenen Artikeln erscheint."
#: mailstream.php:82 mailstream.php:380
#: mailstream.php:82
msgid "Save Settings"
msgstr "Einstellungen speichern"
#: mailstream.php:223
#: mailstream.php:311
msgid "Re:"
msgstr "Re:"
#: mailstream.php:231
#: mailstream.php:324 mailstream.php:327
msgid "Friendica post"
msgstr "Friendica-Veröffentlichung"
#: mailstream.php:234
#: mailstream.php:330
msgid "Diaspora post"
msgstr "Diaspora-Veröffentlichung"
#: mailstream.php:244
#: mailstream.php:340
msgid "Feed item"
msgstr "Artikel-Feed"
#: mailstream.php:247
#: mailstream.php:343
msgid "Email"
msgstr "E-Mail"
#: mailstream.php:249
#: mailstream.php:345
msgid "Friendica Item"
msgstr "Friendica-Artikel"
#: mailstream.php:293
#: mailstream.php:419
msgid "Upstream"
msgstr "Upstream"
#: mailstream.php:294
#: mailstream.php:420
msgid "URI"
msgstr "URI"
#: mailstream.php:421
msgid "Local"
msgstr "Lokal"
#: mailstream.php:362
#: mailstream.php:499
msgid "Enabled"
msgstr "eingeschaltet"
msgstr "Aktiv"
#: mailstream.php:366
#: mailstream.php:504
msgid "Email Address"
msgstr "E-Mail-Adresse"
#: mailstream.php:368
#: mailstream.php:506
msgid "Leave blank to use your account email address"
msgstr "Leer lassen für deine Konto-E-Mail-Addresse"
#: mailstream.php:371
#: mailstream.php:510
msgid "Exclude Likes"
msgstr "Likes ignorieren"
#: mailstream.php:373
#: mailstream.php:512
msgid "Check this to omit mailing \"Like\" notifications"
msgstr "Diese Option verhindert das Versenden von \"Like\"-Benachrichtigungen per E-Mail."
#: mailstream.php:376
#: mailstream.php:516
msgid "Attach Images"
msgstr "Bilder anhängen"
#: mailstream.php:378
#: mailstream.php:518
msgid ""
"Download images in posts and attach them to the email. Useful for reading "
"email while offline."
msgstr "Sollen Bilder, die im Beitrag eingebettet sind, als Dateianhang in den E-Mails verschickt werden?"
#: mailstream.php:379
#: mailstream.php:525
msgid "Mail Stream Settings"
msgstr "Mail-Nachrichten-Einstellungen"

View file

@ -15,8 +15,9 @@ $a->strings['Feed item'] = 'Artikel-Feed';
$a->strings['Email'] = 'E-Mail';
$a->strings['Friendica Item'] = 'Friendica-Artikel';
$a->strings['Upstream'] = 'Upstream';
$a->strings['URI'] = 'URI';
$a->strings['Local'] = 'Lokal';
$a->strings['Enabled'] = 'eingeschaltet';
$a->strings['Enabled'] = 'Aktiv';
$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['Exclude Likes'] = 'Likes ignorieren';

View file

@ -220,6 +220,11 @@ function mailstream_do_images(array &$item, array &$attachments)
$cookiejar = tempnam(System::getTempPath(), 'cookiejar-mailstream-');
try {
$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) {
Logger::error('mailstream_do_images exception fetching url', ['url' => $url, 'item_id' => $item['id']]);
continue;

View file

@ -15,7 +15,6 @@ use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Hook;
use Friendica\Core\Protocol;
use Friendica\DI;
use Friendica\Util\Proxy as ProxyUtils;
function mastodoncustomemojis_install()
{
@ -88,7 +87,7 @@ function mastodoncustomemojis_fetch_custom_emojis_for_url($api_base_url)
foreach ($emojis_array as $emoji) {
if (!empty($emoji['shortcode']) && !empty($emoji['static_url'])) {
$return['texts'][] = ':' . $emoji['shortcode'] . ':';
$return['icons'][] = '<img class="emoji mastodon" src="' . ProxyUtils::proxifyUrl($emoji['static_url']) . '" alt=":' . $emoji['shortcode'] . ':" title=":' . $emoji['shortcode'] . ':"/>';
$return['icons'][] = '<img class="emoji mastodon" src="' . $emoji['static_url'] . '" alt=":' . $emoji['shortcode'] . ':" title=":' . $emoji['shortcode'] . ':"/>';
}
}
}

View file

@ -4,7 +4,7 @@
#
#
# Translators:
# Florent C., 2023
# cracrayol, 2023-2024
# Nicolas Derive, 2022-2023
# StefOfficiel <pichard.stephane@free.fr>, 2015
# Vincent Vindarel <vindarel@mailz.org>, 2018
@ -14,7 +14,7 @@ msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-12-10 14:42-0500\n"
"PO-Revision-Date: 2014-06-23 10:34+0000\n"
"Last-Translator: Florent C., 2023\n"
"Last-Translator: cracrayol, 2023-2024\n"
"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n"
"MIME-Version: 1.0\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 ""
"Use /expression/ to provide regular expressions, #tag to specfically match "
"hashtags (case-insensitive), or regular words (case-sensitive)"
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)"
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)"
#: nsfw.php:72
msgid "Content Filter (NSFW and more)"

View file

@ -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['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['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['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['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['Filtered tag: %s'] = 'Tag filtré : %s';

View file

@ -5,7 +5,7 @@
#
# Translators:
# Hypolite Petovan <hypolite@mrpetovan.com>, 2022
# Florent C., 2023
# cracrayol, 2024
#
#, fuzzy
msgid ""
@ -14,7 +14,7 @@ msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-21 19:16-0500\n"
"PO-Revision-Date: 2018-03-20 07:26+0000\n"
"Last-Translator: Florent C., 2023\n"
"Last-Translator: cracrayol, 2024\n"
"Language-Team: French (https://app.transifex.com/Friendica/teams/12172/fr/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -24,7 +24,7 @@ msgstr ""
#: securemail.php:50
msgid "Enable Secure Mail"
msgstr "Activer l'extension des emails sécurisés"
msgstr "Activer l'extension des courriels sécurisés"
#: securemail.php:51
msgid "Public key"
@ -36,7 +36,7 @@ msgstr "Votre clé publique PGP formatée compatible ASCII"
#: securemail.php:56
msgid "\"Secure Mail\" Settings"
msgstr "Paramètres des emails sécurisés"
msgstr "Paramètres des courriels sécurisés"
#: securemail.php:59
msgid "Save Settings"

View file

@ -5,10 +5,10 @@ function string_plural_select_fr($n){
$n = intval($n);
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 emails sécurisés';
$a->strings['Enable Secure Mail'] = 'Activer l\'extension des courriels sécurisés';
$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['"Secure Mail" Settings'] = 'Paramètres des emails sécurisés';
$a->strings['"Secure Mail" Settings'] = 'Paramètres des courriels sécurisés';
$a->strings['Save Settings'] = 'Enregistrer les paramètres';
$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';

View file

@ -8,64 +8,81 @@ msgid ""
msgstr ""
"Project-Id-Version: friendica\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-07-25 13:15+0000\n"
"PO-Revision-Date: 2021-02-20 00:23+0000\n"
"Last-Translator: Farida Khalaf <faridakhalaf@hotmail.com>\n"
"Language-Team: Arabic (http://www.transifex.com/Friendica/friendica/language/ar/)\n"
"POT-Creation-Date: 2023-04-29 06:56+0000\n"
"PO-Revision-Date: 2014-06-23 12:58+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Arabic (http://app.transifex.com/Friendica/friendica/language/ar/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\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"
#: tumblr.php:40
#: tumblr.php:243
msgid "Permission denied."
msgstr "الطلب مرفوض."
#: tumblr.php:70 tumblr.php:284
#: tumblr.php:296
msgid "Save Settings"
msgstr "Save Settings"
#: tumblr.php:72
#: tumblr.php:297
msgid "Consumer Key"
msgstr ""
#: tumblr.php:73
#: tumblr.php:298
msgid "Consumer Secret"
msgstr ""
#: tumblr.php:178
msgid "You are now authenticated to tumblr."
#: tumblr.php:299
msgid "Maximum tags"
msgstr ""
#: tumblr.php:179
msgid "return to the connector page"
msgstr "الرجوع إلى صفحة الموصل"
#: tumblr.php:195
msgid "Post to Tumblr"
#: tumblr.php:299
msgid ""
"Maximum number of tags that a user can follow. Enter 0 to deactivate the "
"feature."
msgstr ""
#: tumblr.php:225 tumblr.php:229
msgid "Tumblr Export"
msgstr ""
#: tumblr.php:233
msgid "(Re-)Authenticate your tumblr page"
msgstr ""
#: tumblr.php:237
msgid "Enable Tumblr Post Addon"
msgstr ""
#: tumblr.php:243
msgid "Post to Tumblr by default"
msgstr ""
#: tumblr.php:264
#: tumblr.php:336
msgid "Post to page:"
msgstr ""
#: tumblr.php:278
#: tumblr.php:342
msgid "(Re-)Authenticate your tumblr page"
msgstr ""
#: tumblr.php:343
msgid "You are not authenticated to tumblr"
msgstr ""
#: tumblr.php:348
msgid "Enable Tumblr Post Addon"
msgstr ""
#: tumblr.php:349
msgid "Post to Tumblr by default"
msgstr ""
#: tumblr.php:350
msgid "Import the remote timeline"
msgstr ""
#: tumblr.php:351
msgid "Subscribed tags"
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 ""

View file

@ -7,4 +7,3 @@ function string_plural_select_ar($n){
}}
$a->strings['Permission denied.'] = 'الطلب مرفوض.';
$a->strings['Save Settings'] = 'Save Settings';
$a->strings['return to the connector page'] = 'الرجوع إلى صفحة الموصل';

View file

@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: friendica\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-21 19:17-0500\n"
"POT-Creation-Date: 2023-04-29 06:56+0000\n"
"PO-Revision-Date: 2014-06-23 12:58+0000\n"
"Last-Translator: Aditoo, 2018\n"
"Language-Team: Czech (http://app.transifex.com/Friendica/friendica/language/cs/)\n"
@ -21,54 +21,71 @@ msgstr ""
"Language: cs\n"
"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n"
#: tumblr.php:39
#: tumblr.php:243
msgid "Permission denied."
msgstr "Přístup odmítnut."
#: tumblr.php:69
#: tumblr.php:296
msgid "Save Settings"
msgstr ""
#: tumblr.php:71
#: tumblr.php:297
msgid "Consumer Key"
msgstr ""
#: tumblr.php:72
#: tumblr.php:298
msgid "Consumer Secret"
msgstr ""
#: tumblr.php:177
msgid "You are now authenticated to tumblr."
msgstr "Nyní jste přihlášen/a k Tumblr."
#: tumblr.php:299
msgid "Maximum tags"
msgstr ""
#: tumblr.php:178
msgid "return to the connector page"
msgstr "návrat ke stránce konektor"
#: tumblr.php:299
msgid ""
"Maximum number of tags that a user can follow. Enter 0 to deactivate the "
"feature."
msgstr ""
#: tumblr.php:194
msgid "Post to Tumblr"
msgstr "Posílat na Tumblr"
#: tumblr.php:225
#: tumblr.php:336
msgid "Post to page:"
msgstr "Posílat na stránku:"
#: tumblr.php:231
#: tumblr.php:342
msgid "(Re-)Authenticate your tumblr page"
msgstr "(Znovu) přihlásit k Vaší stránce Tumblr"
#: tumblr.php:232
#: tumblr.php:343
msgid "You are not authenticated to tumblr"
msgstr "Nyní nejste přihlášen/a k Tumblr."
#: tumblr.php:237
#: tumblr.php:348
msgid "Enable Tumblr Post Addon"
msgstr "Povolit doplněk Tumblr Post"
#: tumblr.php:238
#: tumblr.php:349
msgid "Post to Tumblr by default"
msgstr "Ve výchozím stavu posílat příspěvky na Tumblr"
#: tumblr.php:244
msgid "Tumblr Export"
#: tumblr.php:350
msgid "Import the remote timeline"
msgstr ""
#: tumblr.php:351
msgid "Subscribed tags"
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 "Posílat na Tumblr"

View file

@ -6,11 +6,9 @@ function string_plural_select_cs($n){
if (($n == 1 && $n % 1 == 0)) { return 0; } else if (($n >= 2 && $n <= 4 && $n % 1 == 0)) { return 1; } else if (($n % 1 != 0 )) { return 2; } else { return 3; }
}}
$a->strings['Permission denied.'] = 'Přístup odmítnut.';
$a->strings['You are now authenticated to tumblr.'] = 'Nyní jste přihlášen/a k Tumblr.';
$a->strings['return to the connector page'] = 'návrat ke stránce konektor';
$a->strings['Post to Tumblr'] = 'Posílat na Tumblr';
$a->strings['Post to page:'] = 'Posílat na stránku:';
$a->strings['(Re-)Authenticate your tumblr page'] = '(Znovu) přihlásit k Vaší stránce Tumblr';
$a->strings['You are not authenticated to tumblr'] = 'Nyní nejste přihlášen/a k Tumblr.';
$a->strings['Enable Tumblr Post Addon'] = 'Povolit doplněk Tumblr Post';
$a->strings['Post to Tumblr by default'] = 'Ve výchozím stavu posílat příspěvky na Tumblr';
$a->strings['Post to Tumblr'] = 'Posílat na Tumblr';

View file

@ -4,6 +4,8 @@
#
#
# Translators:
# Raroun, 2023
# Raroun, 2023
# Tobias Diekershoff <tobias.diekershoff@gmx.net>, 2014-2015
# Tobias Diekershoff <tobias.diekershoff@gmx.net>, 2018,2021
# Ulf Rompe <transifex.com@rompe.org>, 2019
@ -11,9 +13,9 @@ msgid ""
msgstr ""
"Project-Id-Version: friendica\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-21 19:17-0500\n"
"POT-Creation-Date: 2023-04-29 06:56+0000\n"
"PO-Revision-Date: 2014-06-23 12:58+0000\n"
"Last-Translator: Tobias Diekershoff <tobias.diekershoff@gmx.net>, 2018,2021\n"
"Last-Translator: Raroun, 2023\n"
"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -21,54 +23,71 @@ msgstr ""
"Language: de\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: tumblr.php:39
#: tumblr.php:243
msgid "Permission denied."
msgstr "Zugriff verweigert."
#: tumblr.php:69
#: tumblr.php:296
msgid "Save Settings"
msgstr "Einstellungen speichern"
#: tumblr.php:71
#: tumblr.php:297
msgid "Consumer Key"
msgstr "Consumer Key"
#: tumblr.php:72
#: tumblr.php:298
msgid "Consumer Secret"
msgstr "Consumer Secret"
#: tumblr.php:177
msgid "You are now authenticated to tumblr."
msgstr "Du bist nun auf tumblr authentifiziert."
#: tumblr.php:299
msgid "Maximum tags"
msgstr "Maximale Anzahl an Tags"
#: tumblr.php:178
msgid "return to the connector page"
msgstr "zurück zur Connector-Seite"
#: tumblr.php:299
msgid ""
"Maximum number of tags that a user can follow. Enter 0 to deactivate the "
"feature."
msgstr "Maximale Anzahl von Tags, die ein Benutzer verfolgen kann. Geben Sie 0 ein, um die Funktion zu deaktivieren."
#: tumblr.php:194
msgid "Post to Tumblr"
msgstr "Auf Tumblr veröffentlichen"
#: tumblr.php:225
#: tumblr.php:336
msgid "Post to page:"
msgstr "Auf tumblr veröffentlichen"
#: tumblr.php:231
#: tumblr.php:342
msgid "(Re-)Authenticate your tumblr page"
msgstr "(Re-)Authentifizierung deiner tumblr-Seite"
#: tumblr.php:232
#: tumblr.php:343
msgid "You are not authenticated to tumblr"
msgstr "Du bist gegenüber tumblr nicht authentifiziert"
#: tumblr.php:237
#: tumblr.php:348
msgid "Enable Tumblr Post Addon"
msgstr "Tumblr-Post-Addon aktivieren"
#: tumblr.php:238
#: tumblr.php:349
msgid "Post to Tumblr by default"
msgstr "Standardmäßig bei Tumblr veröffentlichen"
#: tumblr.php:244
msgid "Tumblr Export"
msgstr "Tumblr Export"
#: tumblr.php:350
msgid "Import the remote timeline"
msgstr "Importiere die entfernte Timeline"
#: tumblr.php:351
msgid "Subscribed tags"
msgstr "Abonnierte Tags"
#: tumblr.php:351
#, php-format
msgid ""
"Comma separated list of up to %d tags that will be imported additionally to "
"the timeline"
msgstr "Durch Kommata getrennte Liste von bis zu %d Tags, die zusätzlich in die Timeline importiert werden sollen"
#: tumblr.php:357
msgid "Tumblr Import/Export"
msgstr "Tumblr Import/Export"
#: tumblr.php:375
msgid "Post to Tumblr"
msgstr "Auf Tumblr veröffentlichen"

View file

@ -9,12 +9,15 @@ $a->strings['Permission denied.'] = 'Zugriff verweigert.';
$a->strings['Save Settings'] = 'Einstellungen speichern';
$a->strings['Consumer Key'] = 'Consumer Key';
$a->strings['Consumer Secret'] = 'Consumer Secret';
$a->strings['You are now authenticated to tumblr.'] = 'Du bist nun auf tumblr authentifiziert.';
$a->strings['return to the connector page'] = 'zurück zur Connector-Seite';
$a->strings['Post to Tumblr'] = 'Auf Tumblr veröffentlichen';
$a->strings['Maximum tags'] = 'Maximale Anzahl an Tags';
$a->strings['Maximum number of tags that a user can follow. Enter 0 to deactivate the feature.'] = 'Maximale Anzahl von Tags, die ein Benutzer verfolgen kann. Geben Sie 0 ein, um die Funktion zu deaktivieren.';
$a->strings['Post to page:'] = 'Auf tumblr veröffentlichen';
$a->strings['(Re-)Authenticate your tumblr page'] = '(Re-)Authentifizierung deiner tumblr-Seite';
$a->strings['You are not authenticated to tumblr'] = 'Du bist gegenüber tumblr nicht authentifiziert';
$a->strings['Enable Tumblr Post Addon'] = 'Tumblr-Post-Addon aktivieren';
$a->strings['Post to Tumblr by default'] = 'Standardmäßig bei Tumblr veröffentlichen';
$a->strings['Tumblr Export'] = 'Tumblr Export';
$a->strings['Import the remote timeline'] = 'Importiere die entfernte Timeline';
$a->strings['Subscribed tags'] = 'Abonnierte Tags';
$a->strings['Comma separated list of up to %d tags that will be imported additionally to the timeline'] = 'Durch Kommata getrennte Liste von bis zu %d Tags, die zusätzlich in die Timeline importiert werden sollen';
$a->strings['Tumblr Import/Export'] = 'Tumblr Import/Export';
$a->strings['Post to Tumblr'] = 'Auf Tumblr veröffentlichen';

View file

@ -5,7 +5,7 @@
#
# Translators:
# bob lebonche <lebonche@tutanota.com>, 2021
# Florent C., 2023
# cracrayol, 2023-2024
# StefOfficiel <pichard.stephane@free.fr>, 2015
msgid ""
msgstr ""
@ -13,7 +13,7 @@ msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-04-29 06:56+0000\n"
"PO-Revision-Date: 2014-06-23 12:58+0000\n"
"Last-Translator: Florent C., 2023\n"
"Last-Translator: cracrayol, 2023-2024\n"
"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -39,13 +39,13 @@ msgstr "Secret utilisateur"
#: tumblr.php:299
msgid "Maximum tags"
msgstr "Tags maximum"
msgstr "Étiquettes maximum"
#: tumblr.php:299
msgid ""
"Maximum number of tags that a user can follow. Enter 0 to deactivate the "
"feature."
msgstr "Nombre maximum de tags qu'un utilisateur peut suivre. Entrez 0 pour désactiver cette fonctionnalité."
msgstr "Nombre maximum d'étiquettes qu'un utilisateur peut suivre. Entrez 0 pour désactiver cette fonctionnalité."
#: tumblr.php:336
msgid "Post to page:"
@ -73,14 +73,14 @@ msgstr "Importer le flux distant"
#: tumblr.php:351
msgid "Subscribed tags"
msgstr "Tags suivis"
msgstr "Étiquettes suivies"
#: tumblr.php:351
#, php-format
msgid ""
"Comma separated list of up to %d tags that will be imported additionally to "
"the timeline"
msgstr "Liste séparée par des virgules contenant jusqu'à %d tags qui seront importés dans le flux"
msgstr "Liste contenant jusqu'à %d étiquettes, séparées par des virgules, qui seront importées dans le flux"
#: tumblr.php:357
msgid "Tumblr Import/Export"

View file

@ -9,15 +9,15 @@ $a->strings['Permission denied.'] = 'Permission refusée.';
$a->strings['Save Settings'] = 'Sauvegarder les paramètres';
$a->strings['Consumer Key'] = 'Clé utilisateur';
$a->strings['Consumer Secret'] = 'Secret utilisateur';
$a->strings['Maximum tags'] = 'Tags maximum';
$a->strings['Maximum number of tags that a user can follow. Enter 0 to deactivate the feature.'] = 'Nombre maximum de tags qu\'un utilisateur peut suivre. Entrez 0 pour désactiver cette fonctionnalité.';
$a->strings['Maximum tags'] = 'Étiquettes maximum';
$a->strings['Maximum number of tags that a user can follow. Enter 0 to deactivate the feature.'] = 'Nombre maximum d\'étiquettes qu\'un utilisateur peut suivre. Entrez 0 pour désactiver cette fonctionnalité.';
$a->strings['Post to page:'] = 'Publier sur la page :';
$a->strings['(Re-)Authenticate your tumblr page'] = '(re)Authentifiez votre page Tumblr';
$a->strings['You are not authenticated to tumblr'] = 'Vous n\'êtes pas identifié sur Tumblr';
$a->strings['Enable Tumblr Post Addon'] = 'Activez l\'extension de publication Tumblr';
$a->strings['Post to Tumblr by default'] = 'Publier sur Tumblr par défaut';
$a->strings['Import the remote timeline'] = 'Importer le flux distant';
$a->strings['Subscribed tags'] = 'Tags suivis';
$a->strings['Comma separated list of up to %d tags that will be imported additionally to the timeline'] = 'Liste séparée par des virgules contenant jusqu\'à %d tags qui seront importés dans le flux';
$a->strings['Subscribed tags'] = 'Étiquettes suivies';
$a->strings['Comma separated list of up to %d tags that will be imported additionally to the timeline'] = 'Liste contenant jusqu\'à %d étiquettes, séparées par des virgules, qui seront importées dans le flux';
$a->strings['Tumblr Import/Export'] = 'Import/Export Tumblr';
$a->strings['Post to Tumblr'] = 'Publier vers Tumblr';

View file

@ -10,7 +10,7 @@ msgid ""
msgstr ""
"Project-Id-Version: friendica\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-21 19:17-0500\n"
"POT-Creation-Date: 2023-04-29 06:56+0000\n"
"PO-Revision-Date: 2014-06-23 12:58+0000\n"
"Last-Translator: Sylke Vicious <silkevicious@gmail.com>, 2021\n"
"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n"
@ -20,54 +20,71 @@ msgstr ""
"Language: it\n"
"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
#: tumblr.php:39
#: tumblr.php:243
msgid "Permission denied."
msgstr "Permesso negato."
#: tumblr.php:69
#: tumblr.php:296
msgid "Save Settings"
msgstr "Salva Impostazioni"
#: tumblr.php:71
#: tumblr.php:297
msgid "Consumer Key"
msgstr "Consumer Key"
#: tumblr.php:72
#: tumblr.php:298
msgid "Consumer Secret"
msgstr "Consumer Secret"
#: tumblr.php:177
msgid "You are now authenticated to tumblr."
msgstr "Sei autenticato su Tumblr."
#: tumblr.php:299
msgid "Maximum tags"
msgstr ""
#: tumblr.php:178
msgid "return to the connector page"
msgstr "ritorna alla pagina del connettore"
#: tumblr.php:299
msgid ""
"Maximum number of tags that a user can follow. Enter 0 to deactivate the "
"feature."
msgstr ""
#: tumblr.php:194
msgid "Post to Tumblr"
msgstr "Invia a Tumblr"
#: tumblr.php:225
#: tumblr.php:336
msgid "Post to page:"
msgstr "Invia alla pagina:"
#: tumblr.php:231
#: tumblr.php:342
msgid "(Re-)Authenticate your tumblr page"
msgstr "(Ri)Autenticati con la tua pagina Tumblr"
#: tumblr.php:232
#: tumblr.php:343
msgid "You are not authenticated to tumblr"
msgstr "Non sei autenticato su Tumblr"
#: tumblr.php:237
#: tumblr.php:348
msgid "Enable Tumblr Post Addon"
msgstr "Abilita componente aggiuntivo di invio a Tumblr"
#: tumblr.php:238
#: tumblr.php:349
msgid "Post to Tumblr by default"
msgstr "Invia sempre a Tumblr"
#: tumblr.php:244
msgid "Tumblr Export"
msgstr "Esporta Tumblr"
#: tumblr.php:350
msgid "Import the remote timeline"
msgstr ""
#: tumblr.php:351
msgid "Subscribed tags"
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 "Invia a Tumblr"

View file

@ -9,12 +9,9 @@ $a->strings['Permission denied.'] = 'Permesso negato.';
$a->strings['Save Settings'] = 'Salva Impostazioni';
$a->strings['Consumer Key'] = 'Consumer Key';
$a->strings['Consumer Secret'] = 'Consumer Secret';
$a->strings['You are now authenticated to tumblr.'] = 'Sei autenticato su Tumblr.';
$a->strings['return to the connector page'] = 'ritorna alla pagina del connettore';
$a->strings['Post to Tumblr'] = 'Invia a Tumblr';
$a->strings['Post to page:'] = 'Invia alla pagina:';
$a->strings['(Re-)Authenticate your tumblr page'] = '(Ri)Autenticati con la tua pagina Tumblr';
$a->strings['You are not authenticated to tumblr'] = 'Non sei autenticato su Tumblr';
$a->strings['Enable Tumblr Post Addon'] = 'Abilita componente aggiuntivo di invio a Tumblr';
$a->strings['Post to Tumblr by default'] = 'Invia sempre a Tumblr';
$a->strings['Tumblr Export'] = 'Esporta Tumblr';
$a->strings['Post to Tumblr'] = 'Invia a Tumblr';

View file

@ -10,64 +10,81 @@ msgid ""
msgstr ""
"Project-Id-Version: friendica\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-21 19:17-0500\n"
"POT-Creation-Date: 2023-04-29 06:56+0000\n"
"PO-Revision-Date: 2014-06-23 12:58+0000\n"
"Last-Translator: Piotr Strębski <strebski@gmail.com>, 2022\n"
"Language-Team: Polish (http://www.transifex.com/Friendica/friendica/language/pl/)\n"
"Language-Team: Polish (http://app.transifex.com/Friendica/friendica/language/pl/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: pl\n"
"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n"
#: tumblr.php:39
#: tumblr.php:243
msgid "Permission denied."
msgstr "Odmowa dostępu."
#: tumblr.php:69
#: tumblr.php:296
msgid "Save Settings"
msgstr "Zapisz ustawienia"
#: tumblr.php:71
#: tumblr.php:297
msgid "Consumer Key"
msgstr "Klucz klienta"
#: tumblr.php:72
#: tumblr.php:298
msgid "Consumer Secret"
msgstr "Tajny klucz klienta"
#: tumblr.php:177
msgid "You are now authenticated to tumblr."
msgstr "Jesteś teraz uwierzytelniony na tumblr."
#: tumblr.php:299
msgid "Maximum tags"
msgstr ""
#: tumblr.php:178
msgid "return to the connector page"
msgstr "powrót do strony łącza"
#: tumblr.php:299
msgid ""
"Maximum number of tags that a user can follow. Enter 0 to deactivate the "
"feature."
msgstr ""
#: tumblr.php:194
msgid "Post to Tumblr"
msgstr "Opublikuj w Tumblr"
#: tumblr.php:225
#: tumblr.php:336
msgid "Post to page:"
msgstr "Opublikuj na stronie:"
#: tumblr.php:231
#: tumblr.php:342
msgid "(Re-)Authenticate your tumblr page"
msgstr "(Re-) Uwierzytelnij swoją stronę tumblr"
#: tumblr.php:232
#: tumblr.php:343
msgid "You are not authenticated to tumblr"
msgstr "Nie jesteś uwierzytelniony w tumblr"
#: tumblr.php:237
#: tumblr.php:348
msgid "Enable Tumblr Post Addon"
msgstr "Włącz dodatek Tumblr"
#: tumblr.php:238
#: tumblr.php:349
msgid "Post to Tumblr by default"
msgstr "Wyślij domyślnie do Tumblr"
#: tumblr.php:244
msgid "Tumblr Export"
msgstr "Eksportuj do Tumblr"
#: tumblr.php:350
msgid "Import the remote timeline"
msgstr ""
#: tumblr.php:351
msgid "Subscribed tags"
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 "Opublikuj w Tumblr"

View file

@ -9,12 +9,9 @@ $a->strings['Permission denied.'] = 'Odmowa dostępu.';
$a->strings['Save Settings'] = 'Zapisz ustawienia';
$a->strings['Consumer Key'] = 'Klucz klienta';
$a->strings['Consumer Secret'] = 'Tajny klucz klienta';
$a->strings['You are now authenticated to tumblr.'] = 'Jesteś teraz uwierzytelniony na tumblr.';
$a->strings['return to the connector page'] = 'powrót do strony łącza';
$a->strings['Post to Tumblr'] = 'Opublikuj w Tumblr';
$a->strings['Post to page:'] = 'Opublikuj na stronie:';
$a->strings['(Re-)Authenticate your tumblr page'] = '(Re-) Uwierzytelnij swoją stronę tumblr';
$a->strings['You are not authenticated to tumblr'] = 'Nie jesteś uwierzytelniony w tumblr';
$a->strings['Enable Tumblr Post Addon'] = 'Włącz dodatek Tumblr';
$a->strings['Post to Tumblr by default'] = 'Wyślij domyślnie do Tumblr';
$a->strings['Tumblr Export'] = 'Eksportuj do Tumblr';
$a->strings['Post to Tumblr'] = 'Opublikuj w Tumblr';

View file

@ -10,64 +10,81 @@ msgid ""
msgstr ""
"Project-Id-Version: friendica\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-21 19:17-0500\n"
"PO-Revision-Date: 2022-01-16 00:55+0000\n"
"Last-Translator: Kristoffer Grundström <lovaren@gmail.com>\n"
"Language-Team: Swedish (http://www.transifex.com/Friendica/friendica/language/sv/)\n"
"POT-Creation-Date: 2023-04-29 06:56+0000\n"
"PO-Revision-Date: 2014-06-23 12:58+0000\n"
"Last-Translator: Kristoffer Grundström <lovaren@gmail.com>, 2022\n"
"Language-Team: Swedish (http://app.transifex.com/Friendica/friendica/language/sv/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: sv\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: tumblr.php:39
#: tumblr.php:243
msgid "Permission denied."
msgstr "Åtkomst nekad."
#: tumblr.php:69
#: tumblr.php:296
msgid "Save Settings"
msgstr ""
#: tumblr.php:71
#: tumblr.php:297
msgid "Consumer Key"
msgstr ""
#: tumblr.php:72
#: tumblr.php:298
msgid "Consumer Secret"
msgstr ""
#: tumblr.php:177
msgid "You are now authenticated to tumblr."
msgstr "Du är nu autentiserad till tumblr."
#: tumblr.php:178
msgid "return to the connector page"
#: tumblr.php:299
msgid "Maximum tags"
msgstr ""
#: tumblr.php:194
msgid "Post to Tumblr"
#: tumblr.php:299
msgid ""
"Maximum number of tags that a user can follow. Enter 0 to deactivate the "
"feature."
msgstr ""
#: tumblr.php:225
#: tumblr.php:336
msgid "Post to page:"
msgstr ""
#: tumblr.php:231
#: tumblr.php:342
msgid "(Re-)Authenticate your tumblr page"
msgstr ""
#: tumblr.php:232
#: tumblr.php:343
msgid "You are not authenticated to tumblr"
msgstr "Du är inte autentiserad till tumblr"
#: tumblr.php:237
#: tumblr.php:348
msgid "Enable Tumblr Post Addon"
msgstr ""
#: tumblr.php:238
#: tumblr.php:349
msgid "Post to Tumblr by default"
msgstr ""
#: tumblr.php:244
msgid "Tumblr Export"
#: tumblr.php:350
msgid "Import the remote timeline"
msgstr ""
#: tumblr.php:351
msgid "Subscribed tags"
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 ""

View file

@ -6,5 +6,4 @@ function string_plural_select_sv($n){
return intval($n != 1);
}}
$a->strings['Permission denied.'] = 'Åtkomst nekad.';
$a->strings['You are now authenticated to tumblr.'] = 'Du är nu autentiserad till tumblr.';
$a->strings['You are not authenticated to tumblr'] = 'Du är inte autentiserad till tumblr';

View file

@ -133,6 +133,7 @@ function tumblr_item_by_link(array &$hookData)
Logger::debug('Got post', ['blog' => $matches[1], 'id' => $matches[2], 'result' => $result->response->posts]);
if (!empty($result->response->posts)) {
$hookData['item_id'] = tumblr_process_post($result->response->posts[0], $hookData['uid'], Item::PR_FETCHED);
Item::incrementInbound(Protocol::TUMBLR);
}
}
@ -203,9 +204,9 @@ function tumblr_block(array &$hook_data)
$hook_data['result'] = ($result->meta->status <= 399);
if ($hook_data['result']) {
$cdata = Contact::getPublicAndUserContactID($hook_data['contact']['id'], $hook_data['uid']);
if (!empty($cdata['user'])) {
Contact::remove($cdata['user']);
$ucid = Contact::getUserContactId($hook_data['contact']['id'], $hook_data['uid']);
if ($ucid) {
Contact::remove($ucid);
}
}
}
@ -238,9 +239,7 @@ function tumblr_get_contact_uuid(array $contact): string
* existence of this method is checked to figure out if the addon offers a
* module.
*/
function tumblr_module()
{
}
function tumblr_module() {}
function tumblr_content()
{
@ -608,13 +607,22 @@ function tumblr_send_legacy(array $b)
$body = BBCode::removeShareInformation($b['body']);
$body = Post\Media::removeFromEndOfBody($body);
if (!empty($b['quote-uri-id'])) {
$quote = Post::selectFirstPost(['uri', 'plink'], ['uri-id' => $b['quote-uri-id']]);
if (!empty($quote)) {
if ((strpos($body, $quote['plink'] ?: $quote['uri']) === false) && (strpos($body, $quote['uri']) === false)) {
$body .= "\n[url]" . ($quote['plink'] ?: $quote['uri']) . "[/url]\n";
}
}
}
if ($photo !== false) {
$params['type'] = 'photo';
$params['caption'] = BBCode::convertForUriId($b['uri-id'], $body, BBCode::CONNECTORS);
$params['data'] = [];
foreach ($media as $photo) {
if ($photo['type'] == Post\Media::IMAGE) {
if (Network::isLocalLink($photo['url']) && ($data = Photo::getResourceData($photo['url']))) {
if (DI::baseUrl()->isLocalUrl($photo['url']) && ($data = Photo::getResourceData($photo['url']))) {
$photo = Photo::selectFirst([], ["`resource-id` = ? AND `scale` > ?", $data['guid'], 0]);
if (!empty($photo)) {
$params['data'][] = Photo::getImageDataForPhoto($photo);
@ -648,7 +656,7 @@ function tumblr_send_legacy(array $b)
} else {
$params['type'] = 'text';
$params['title'] = $title;
$params['body'] = BBCode::convertForUriId($b['uri-id'], $b['body'], BBCode::CONNECTORS);
$params['body'] = BBCode::convertForUriId($b['uri-id'], $body, BBCode::CONNECTORS);
}
if (isset($params['caption']) && (trim($title) != '')) {
@ -747,6 +755,7 @@ function tumblr_fetch_tags(int $uid, int $last_poll)
$post = Post::selectFirst(['uri-id'], ['id' => $id]);
$stored = Post\Category::storeFileByURIId($post['uri-id'], $uid, Post\Category::SUBCRIPTION, $tag);
Logger::debug('Stored tag subscription for user', ['uri-id' => $post['uri-id'], 'uid' => $uid, 'tag' => $tag, 'stored' => $stored]);
Item::incrementInbound(Protocol::TUMBLR);
}
}
}
@ -786,6 +795,7 @@ function tumblr_fetch_dashboard(int $uid, int $last_poll)
Logger::debug('Importing post', ['uid' => $uid, 'created' => date(DateTimeFormat::MYSQL, $post->timestamp), 'id' => $post->id_string]);
tumblr_process_post($post, $uid, Item::PR_NONE, $last_poll);
Item::incrementInbound(Protocol::TUMBLR);
DI::pConfig()->set($uid, 'tumblr', 'last_id', $last);
}
@ -1158,6 +1168,7 @@ function tumblr_get_contact_fields(stdClass $blog, int $uid, bool $update): arra
Logger::notice('Error fetching blog info', ['meta' => $info->meta, 'response' => $info->response, 'errors' => $info->errors]);
return $fields;
}
Item::incrementInbound(Protocol::TUMBLR);
$avatar = $info->response->blog->avatar;
if (!empty($avatar)) {
@ -1222,6 +1233,8 @@ function tumblr_get_blogs(int $uid): array
return [];
}
Item::incrementInbound(Protocol::TUMBLR);
$blogs = [];
foreach ($userinfo->response->user->blogs as $blog) {
$blogs[$blog->uuid] = $blog->name;
@ -1278,10 +1291,11 @@ function tumblr_get_contact_by_url(string $url, int $uid): ?array
if ($info->meta->status > 399) {
Logger::notice('Error fetching blog info', ['meta' => $info->meta, 'response' => $info->response, 'errors' => $info->errors, 'blog' => $blog, 'uid' => $uid]);
return null;
} else {
Logger::debug('Got data', ['blog' => $blog, 'meta' => $info->meta]);
}
Logger::debug('Got data', ['blog' => $blog, 'meta' => $info->meta]);
Item::incrementInbound(Protocol::TUMBLR);
$baseurl = 'https://tumblr.com';
$url = $baseurl . '/' . $info->response->blog->name;
@ -1346,6 +1360,7 @@ function tumblr_get(int $uid, string $url, array $parameters = []): stdClass
*/
function tumblr_post(int $uid, string $url, array $parameters): stdClass
{
Item::incrementOutbound(Protocol::TUMBLR);
$url = 'https://api.tumblr.com/v2/' . $url;
$curlResult = DI::httpClient()->post($url, $parameters, ['Authorization' => ['Bearer ' . tumblr_get_token($uid)]]);