diff --git a/advancedcontentfilter/lang/it/messages.po b/advancedcontentfilter/lang/it/messages.po index f32c5b94..325be52c 100644 --- a/advancedcontentfilter/lang/it/messages.po +++ b/advancedcontentfilter/lang/it/messages.po @@ -5,7 +5,7 @@ # # Translators: # fabrixxm , 2018 -# Sylke Vicious , 2021 +# Sylke Vicious , 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 , 2021\n" +"Last-Translator: Sylke Vicious , 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 diff --git a/advancedcontentfilter/lang/it/strings.php b/advancedcontentfilter/lang/it/strings.php index 5cc01739..d47d7a5a 100644 --- a/advancedcontentfilter/lang/it/strings.php +++ b/advancedcontentfilter/lang/it/strings.php @@ -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.'; diff --git a/blockbot/blockbot.php b/blockbot/blockbot.php index e11f23f7..adf0a7c2 100644 --- a/blockbot/blockbot.php +++ b/blockbot/blockbot.php @@ -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 * Author: Michael Vogel * @@ -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; -} \ No newline at end of file +} + +/** + * 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'', + '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; +} diff --git a/blockbot/lang/C/messages.po b/blockbot/lang/C/messages.po index a99ccc5a..6926c8a1 100644 --- a/blockbot/lang/C/messages.po +++ b/blockbot/lang/C/messages.po @@ -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 \n" "Language-Team: LANGUAGE \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 "" diff --git a/blockbot/templates/admin.tpl b/blockbot/templates/admin.tpl index 5f41ae70..86a462da 100644 --- a/blockbot/templates/admin.tpl +++ b/blockbot/templates/admin.tpl @@ -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}} -
+
\ No newline at end of file diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index fe66d9a4..19466a42 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -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()); } diff --git a/bluesky/lang/C/messages.po b/bluesky/lang/C/messages.po index 0d69cc10..9521ab89 100644 --- a/bluesky/lang/C/messages.po +++ b/bluesky/lang/C/messages.po @@ -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 \n" "Language-Team: LANGUAGE \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 diff --git a/catavatar/lang/it/messages.po b/catavatar/lang/it/messages.po index e05bd277..9155bb48 100644 --- a/catavatar/lang/it/messages.po +++ b/catavatar/lang/it/messages.po @@ -6,55 +6,55 @@ # Translators: # fabrixxm , 2018 # Davide Pesenti , 2018 -# Sylke Vicious , 2021 +# Sylke Vicious , 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 , 2021\n" -"Language-Team: Italian (https://www.transifex.com/Friendica/teams/12172/it/)\n" +"Last-Translator: Sylke Vicious , 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!" diff --git a/catavatar/lang/it/strings.php b/catavatar/lang/it/strings.php index 3a33374a..8f78b3fe 100644 --- a/catavatar/lang/it/strings.php +++ b/catavatar/lang/it/strings.php @@ -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'; diff --git a/curweather/curweather.php b/curweather/curweather.php index f614840a..9aa8584a 100644 --- a/curweather/curweather.php +++ b/curweather/curweather.php @@ -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; } diff --git a/curweather/lang/fr/messages.po b/curweather/lang/fr/messages.po index 57ed6b8b..21e60c54 100644 --- a/curweather/lang/fr/messages.po +++ b/curweather/lang/fr/messages.po @@ -5,6 +5,7 @@ # # Translators: # bob lebonche , 2021 +# cracrayol, 2024 # Hypolite Petovan , 2022 # Hypolite Petovan , 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 , 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" diff --git a/curweather/lang/fr/strings.php b/curweather/lang/fr/strings.php index be5c1ba5..268b3a42 100644 --- a/curweather/lang/fr/strings.php +++ b/curweather/lang/fr/strings.php @@ -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'; diff --git a/curweather/lang/it/messages.po b/curweather/lang/it/messages.po index 5a7e2cac..c53b3a6e 100644 --- a/curweather/lang/it/messages.po +++ b/curweather/lang/it/messages.po @@ -5,27 +5,27 @@ # # Translators: # fabrixxm , 2014-2015 -# Sylke Vicious , 2021 +# Sylke Vicious , 2021,2023 # Tobias Diekershoff , 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 \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 , 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. Berlin,DE or " "14476,DE." msgstr "Identificatore della tua posizione (nome o CAP), p.e. Roma, IT or 00186,IT." -#: 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 °C or °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" diff --git a/curweather/lang/it/strings.php b/curweather/lang/it/strings.php index a497dace..6c651e1b 100644 --- a/curweather/lang/it/strings.php +++ b/curweather/lang/it/strings.php @@ -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. Berlin,DE or 14476,DE.'] = 'Identificatore della tua posizione (nome o CAP), p.e. Roma, IT or 00186,IT.'; $a->strings['Units'] = 'Unità'; $a->strings['select if the temperature should be displayed in °C or °F'] = 'scegli se la temperatura deve essere mostrata in °C o in °F'; $a->strings['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'; diff --git a/dwpost/lang/it/messages.po b/dwpost/lang/it/messages.po index 5f7c2ee2..a5a79d47 100644 --- a/dwpost/lang/it/messages.po +++ b/dwpost/lang/it/messages.po @@ -5,45 +5,41 @@ # # Translators: # fabrixxm , 2014,2018 -# Sylke Vicious , 2020-2021 +# Sylke Vicious , 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 \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 , 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" diff --git a/dwpost/lang/it/strings.php b/dwpost/lang/it/strings.php index 0234c1f7..22ecc7b1 100644 --- a/dwpost/lang/it/strings.php +++ b/dwpost/lang/it/strings.php @@ -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'; diff --git a/forumdirectory/forumdirectory.php b/forumdirectory/forumdirectory.php index 79267c4e..9a155a00 100644 --- a/forumdirectory/forumdirectory.php +++ b/forumdirectory/forumdirectory.php @@ -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)) { diff --git a/geonames/lang/fr/messages.po b/geonames/lang/fr/messages.po index b1cd8ce1..9fe03bdb 100644 --- a/geonames/lang/fr/messages.po +++ b/geonames/lang/fr/messages.po @@ -6,6 +6,7 @@ # Translators: # bob lebonche , 2021 # ButterflyOfFire, 2020 +# cracrayol, 2024 # Hypolite Petovan , 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 , 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" diff --git a/geonames/lang/fr/strings.php b/geonames/lang/fr/strings.php index 297e3b73..802dd118 100644 --- a/geonames/lang/fr/strings.php +++ b/geonames/lang/fr/strings.php @@ -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'; diff --git a/gnot/lang/fr/messages.po b/gnot/lang/fr/messages.po index 3ce82e7f..8a928544 100644 --- a/gnot/lang/fr/messages.po +++ b/gnot/lang/fr/messages.po @@ -6,6 +6,7 @@ # Translators: # bob lebonche , 2021 # ButterflyOfFire, 2020 +# cracrayol, 2024 # Hypolite Petovan , 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 , 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" diff --git a/gnot/lang/fr/strings.php b/gnot/lang/fr/strings.php index c498f7e8..53104349 100644 --- a/gnot/lang/fr/strings.php +++ b/gnot/lang/fr/strings.php @@ -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'; diff --git a/gravatar/lang/fr/messages.po b/gravatar/lang/fr/messages.po index f8a64a1b..6ffa6214 100644 --- a/gravatar/lang/fr/messages.po +++ b/gravatar/lang/fr/messages.po @@ -5,6 +5,7 @@ # # Translators: # bob lebonche , 2021 +# cracrayol, 2024 # Marie Olive , 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 , 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.
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" diff --git a/gravatar/lang/fr/strings.php b/gravatar/lang/fr/strings.php index b826ab65..930d7169 100644 --- a/gravatar/lang/fr/strings.php +++ b/gravatar/lang/fr/strings.php @@ -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.
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.
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.'; diff --git a/groupdirectory/groupdirectory.php b/groupdirectory/groupdirectory.php index 7bad1ef9..615d7024 100644 --- a/groupdirectory/groupdirectory.php +++ b/groupdirectory/groupdirectory.php @@ -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)) { diff --git a/ijpost/lang/fr/messages.po b/ijpost/lang/fr/messages.po index bc322337..6f29cad7 100644 --- a/ijpost/lang/fr/messages.po +++ b/ijpost/lang/fr/messages.po @@ -5,6 +5,7 @@ # # Translators: # bob lebonche , 2021 +# cracrayol, 2024 # Hypolite Petovan , 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 , 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" diff --git a/ijpost/lang/fr/strings.php b/ijpost/lang/fr/strings.php index d8e3e95d..d2fafc92 100644 --- a/ijpost/lang/fr/strings.php +++ b/ijpost/lang/fr/strings.php @@ -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'; diff --git a/invidious/invidious.php b/invidious/invidious.php index 1078d26d..7153aab9 100644 --- a/invidious/invidious.php +++ b/invidious/invidious.php @@ -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 * Author: Michael Vogel * 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']) { diff --git a/js_upload/js_upload.php b/js_upload/js_upload.php index 089cb7e2..0d045dee 100644 --- a/js_upload/js_upload.php +++ b/js_upload/js_upload.php @@ -7,11 +7,11 @@ * Maintainer: Hypolite Petovan */ -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 ]; } diff --git a/krynn/lang/fr/messages.po b/krynn/lang/fr/messages.po index a96af8de..8a306eb1 100644 --- a/krynn/lang/fr/messages.po +++ b/krynn/lang/fr/messages.po @@ -5,14 +5,15 @@ # # Translators: # bob lebonche , 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 , 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" diff --git a/krynn/lang/fr/strings.php b/krynn/lang/fr/strings.php index 3c3574d0..84293f79 100644 --- a/krynn/lang/fr/strings.php +++ b/krynn/lang/fr/strings.php @@ -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'; diff --git a/libertree/lang/it/messages.po b/libertree/lang/it/messages.po index 7c3bc1ec..cc890cc5 100644 --- a/libertree/lang/it/messages.po +++ b/libertree/lang/it/messages.po @@ -5,45 +5,41 @@ # # Translators: # fabrixxm , 2014-2015,2018 -# Sylke Vicious , 2021 +# Sylke Vicious , 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 \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 , 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" diff --git a/libertree/lang/it/strings.php b/libertree/lang/it/strings.php index 02d26542..8abcfa2d 100644 --- a/libertree/lang/it/strings.php +++ b/libertree/lang/it/strings.php @@ -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'; diff --git a/mailstream/lang/de/messages.po b/mailstream/lang/de/messages.po index 236e7d0e..cd55d952 100644 --- a/mailstream/lang/de/messages.po +++ b/mailstream/lang/de/messages.po @@ -5,16 +5,18 @@ # # Translators: # Andreas H., 2014 +# foss , 2022 +# Raroun, 2023 # Tobias Diekershoff , 2018 # Ulf Rompe , 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 \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" diff --git a/mailstream/lang/de/strings.php b/mailstream/lang/de/strings.php index 80f9a7a2..e107b7d0 100644 --- a/mailstream/lang/de/strings.php +++ b/mailstream/lang/de/strings.php @@ -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'; diff --git a/mailstream/mailstream.php b/mailstream/mailstream.php index b513cf36..4056aac6 100644 --- a/mailstream/mailstream.php +++ b/mailstream/mailstream.php @@ -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; diff --git a/mastodoncustomemojis/mastodoncustomemojis.php b/mastodoncustomemojis/mastodoncustomemojis.php index f67054a1..561262f1 100644 --- a/mastodoncustomemojis/mastodoncustomemojis.php +++ b/mastodoncustomemojis/mastodoncustomemojis.php @@ -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'][] = ':' . $emoji['shortcode'] . ':'; + $return['icons'][] = ':' . $emoji['shortcode'] . ':'; } } } diff --git a/nsfw/lang/fr/messages.po b/nsfw/lang/fr/messages.po index 36fd22cc..2af1c3d4 100644 --- a/nsfw/lang/fr/messages.po +++ b/nsfw/lang/fr/messages.po @@ -4,7 +4,7 @@ # # # Translators: -# Florent C., 2023 +# cracrayol, 2023-2024 # Nicolas Derive, 2022-2023 # StefOfficiel , 2015 # Vincent Vindarel , 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)" diff --git a/nsfw/lang/fr/strings.php b/nsfw/lang/fr/strings.php index fc03d5ad..0f717797 100644 --- a/nsfw/lang/fr/strings.php +++ b/nsfw/lang/fr/strings.php @@ -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'; diff --git a/securemail/lang/fr/messages.po b/securemail/lang/fr/messages.po index 828d507b..6e6cc657 100644 --- a/securemail/lang/fr/messages.po +++ b/securemail/lang/fr/messages.po @@ -5,7 +5,7 @@ # # Translators: # Hypolite Petovan , 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" diff --git a/securemail/lang/fr/strings.php b/securemail/lang/fr/strings.php index 9d40a8e2..b13cc5ce 100644 --- a/securemail/lang/fr/strings.php +++ b/securemail/lang/fr/strings.php @@ -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'; diff --git a/tumblr/lang/ar/messages.po b/tumblr/lang/ar/messages.po index 7879231d..48a9e8cb 100644 --- a/tumblr/lang/ar/messages.po +++ b/tumblr/lang/ar/messages.po @@ -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 \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 \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 "" diff --git a/tumblr/lang/ar/strings.php b/tumblr/lang/ar/strings.php index ffd3337c..3f7ca4e4 100644 --- a/tumblr/lang/ar/strings.php +++ b/tumblr/lang/ar/strings.php @@ -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'] = 'الرجوع إلى صفحة الموصل'; diff --git a/tumblr/lang/cs/messages.po b/tumblr/lang/cs/messages.po index 4e031be6..cb6f91e6 100644 --- a/tumblr/lang/cs/messages.po +++ b/tumblr/lang/cs/messages.po @@ -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" diff --git a/tumblr/lang/cs/strings.php b/tumblr/lang/cs/strings.php index 2f5f8115..3135b0b8 100644 --- a/tumblr/lang/cs/strings.php +++ b/tumblr/lang/cs/strings.php @@ -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'; diff --git a/tumblr/lang/de/messages.po b/tumblr/lang/de/messages.po index 8056174d..c41ba45f 100644 --- a/tumblr/lang/de/messages.po +++ b/tumblr/lang/de/messages.po @@ -4,6 +4,8 @@ # # # Translators: +# Raroun, 2023 +# Raroun, 2023 # Tobias Diekershoff , 2014-2015 # Tobias Diekershoff , 2018,2021 # Ulf Rompe , 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 , 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" diff --git a/tumblr/lang/de/strings.php b/tumblr/lang/de/strings.php index ce43615c..ed9af957 100644 --- a/tumblr/lang/de/strings.php +++ b/tumblr/lang/de/strings.php @@ -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'; diff --git a/tumblr/lang/fr/messages.po b/tumblr/lang/fr/messages.po index ef2f0e3c..43dba8e3 100644 --- a/tumblr/lang/fr/messages.po +++ b/tumblr/lang/fr/messages.po @@ -5,7 +5,7 @@ # # Translators: # bob lebonche , 2021 -# Florent C., 2023 +# cracrayol, 2023-2024 # StefOfficiel , 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" diff --git a/tumblr/lang/fr/strings.php b/tumblr/lang/fr/strings.php index ece76c74..f23c9c44 100644 --- a/tumblr/lang/fr/strings.php +++ b/tumblr/lang/fr/strings.php @@ -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'; diff --git a/tumblr/lang/it/messages.po b/tumblr/lang/it/messages.po index f3d1df55..0f7e2237 100644 --- a/tumblr/lang/it/messages.po +++ b/tumblr/lang/it/messages.po @@ -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 , 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" diff --git a/tumblr/lang/it/strings.php b/tumblr/lang/it/strings.php index d4d4e257..e58ab31c 100644 --- a/tumblr/lang/it/strings.php +++ b/tumblr/lang/it/strings.php @@ -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'; diff --git a/tumblr/lang/pl/messages.po b/tumblr/lang/pl/messages.po index 27a44e15..a8676455 100644 --- a/tumblr/lang/pl/messages.po +++ b/tumblr/lang/pl/messages.po @@ -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 , 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" diff --git a/tumblr/lang/pl/strings.php b/tumblr/lang/pl/strings.php index a9f3bfb5..896b21ba 100644 --- a/tumblr/lang/pl/strings.php +++ b/tumblr/lang/pl/strings.php @@ -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'; diff --git a/tumblr/lang/sv/messages.po b/tumblr/lang/sv/messages.po index fe631007..3ff328a8 100644 --- a/tumblr/lang/sv/messages.po +++ b/tumblr/lang/sv/messages.po @@ -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 \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 , 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 "" diff --git a/tumblr/lang/sv/strings.php b/tumblr/lang/sv/strings.php index 4d39d3c2..84a0e774 100644 --- a/tumblr/lang/sv/strings.php +++ b/tumblr/lang/sv/strings.php @@ -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'; diff --git a/tumblr/tumblr.php b/tumblr/tumblr.php index 78e415ee..dd34bd41 100644 --- a/tumblr/tumblr.php +++ b/tumblr/tumblr.php @@ -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)]]);