From 04ce1fd2b44304587a4f86f4805c909e2fe2d464 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 21 Mar 2024 07:40:46 +0000 Subject: [PATCH 01/32] Bluesky: Support Restrictions / Updated Friendica handle description --- bluesky/bluesky.php | 49 ++++++++++++++++++++++++++++++++++++-- bluesky/lang/C/messages.po | 10 ++++---- 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index fe66d9a4..2cd2d263 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -323,7 +323,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())], ]); } @@ -525,8 +525,8 @@ function bluesky_cron() // Refresh the token now, so that it doesn't need to be refreshed in parallel by the following workers 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); + 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')) { $feeds = bluesky_get_feeds($pconfig['uid']); @@ -1176,6 +1176,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; } @@ -1223,6 +1225,49 @@ function bluesky_get_header(stdClass $post, string $uri, int $uid, int $fetch_ui 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)) { 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 From 3bdbcd3b0248dd9a6f6fa277db14f1935a1a690b Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 22 Mar 2024 15:53:47 +0100 Subject: [PATCH 02/32] [Hotfix] Fix REPO_URL for woodpecker --- .woodpecker/.code_standards_check.yml | 2 +- .woodpecker/.continuous-deployment.yml | 2 +- .woodpecker/.messages.po_check.yml | 2 +- .woodpecker/.phpunit.yml | 2 +- .woodpecker/.releaser.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.woodpecker/.code_standards_check.yml b/.woodpecker/.code_standards_check.yml index 9d59dc08..8e0f7dc7 100644 --- a/.woodpecker/.code_standards_check.yml +++ b/.woodpecker/.code_standards_check.yml @@ -13,7 +13,7 @@ pipeline: commands: - git config --global user.email "no-reply@friendi.ca" - git config --global user.name "Friendica" - - git clone $CI_REPO_LINK addon + - git clone $CI_REPO_CLONE_URL addon - cd addon/ - git checkout $CI_COMMIT_BRANCH - git fetch origin $CI_COMMIT_REF diff --git a/.woodpecker/.continuous-deployment.yml b/.woodpecker/.continuous-deployment.yml index 3756a8bf..d1202978 100644 --- a/.woodpecker/.continuous-deployment.yml +++ b/.woodpecker/.continuous-deployment.yml @@ -20,7 +20,7 @@ pipeline: commands: - git config --global user.email "no-reply@friendi.ca" - git config --global user.name "Friendica" - - git clone $CI_REPO_LINK addon + - git clone $CI_REPO_CLONE_URL addon - cd addon/ - git checkout $CI_COMMIT_BRANCH - git fetch origin $CI_COMMIT_REF diff --git a/.woodpecker/.messages.po_check.yml b/.woodpecker/.messages.po_check.yml index f5691e00..ea9fa4d5 100644 --- a/.woodpecker/.messages.po_check.yml +++ b/.woodpecker/.messages.po_check.yml @@ -13,7 +13,7 @@ pipeline: commands: - git config --global user.email "no-reply@friendi.ca" - git config --global user.name "Friendica" - - git clone $CI_REPO_LINK addon + - git clone $CI_REPO_CLONE_URL addon - cd addon/ - git checkout $CI_COMMIT_BRANCH - git fetch origin $CI_COMMIT_REF diff --git a/.woodpecker/.phpunit.yml b/.woodpecker/.phpunit.yml index 1e6189d3..0c25a2bd 100644 --- a/.woodpecker/.phpunit.yml +++ b/.woodpecker/.phpunit.yml @@ -28,7 +28,7 @@ pipeline: commands: - git config --global user.email "no-reply@friendi.ca" - git config --global user.name "Friendica" - - git clone $CI_REPO_LINK addon + - git clone $CI_REPO_CLONE_URL addon - cd addon/ - git checkout $CI_COMMIT_BRANCH - git fetch origin $CI_COMMIT_REF diff --git a/.woodpecker/.releaser.yml b/.woodpecker/.releaser.yml index 5751f07f..68bdfb21 100644 --- a/.woodpecker/.releaser.yml +++ b/.woodpecker/.releaser.yml @@ -19,7 +19,7 @@ pipeline: commands: - git config --global user.email "no-reply@friendi.ca" - git config --global user.name "Friendica" - - git clone $CI_REPO_LINK addon + - git clone $CI_REPO_CLONE_URL addon - cd addon/ - git checkout $CI_COMMIT_BRANCH - git fetch origin $CI_COMMIT_REF From 340f5e627c85c29fceebe5a6bff2fa373f29d07d Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 23 Mar 2024 06:59:13 +0000 Subject: [PATCH 03/32] Bluesky: Added support for sensitive posts --- bluesky/bluesky.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 2cd2d263..4a1f4f60 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -1222,6 +1222,17 @@ 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; } From 9627e95b1964a23f833ee3efb6b81810bc040240 Mon Sep 17 00:00:00 2001 From: loma-one Date: Sun, 14 Apr 2024 19:45:06 +0200 Subject: [PATCH 04/32] invidious/invidious.php aktualisiert Now intercepts YouTube links without a leading "www". --- invidious/invidious.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/invidious/invidious.php b/invidious/invidious.php index 1078d26d..6ae9bc78 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 @@ -96,6 +96,9 @@ function invidious_render(array &$b) $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?:\/\/youtube.com\/watch\?v\=(.*?)/ism", $server . '/watch?v=$1', $b['html']); + $b['html'] = preg_replace("/https?:\/\/youtube.com\/embed\/(.*?)/ism", $server . '/embed/$1', $b['html']); + $b['html'] = preg_replace("/https?:\/\/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']) { From 3bf547ee6e778fff9137bd9fc11a8f2dd6ec8d39 Mon Sep 17 00:00:00 2001 From: loma-one Date: Mon, 15 Apr 2024 06:02:58 +0200 Subject: [PATCH 05/32] invidious/invidious.php aktualisiert Note taken from @MrPetovan --- invidious/invidious.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/invidious/invidious.php b/invidious/invidious.php index 6ae9bc78..7153aab9 100644 --- a/invidious/invidious.php +++ b/invidious/invidious.php @@ -93,12 +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?:\/\/youtube.com\/watch\?v\=(.*?)/ism", $server . '/watch?v=$1', $b['html']); - $b['html'] = preg_replace("/https?:\/\/youtube.com\/embed\/(.*?)/ism", $server . '/embed/$1', $b['html']); - $b['html'] = preg_replace("/https?:\/\/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']) { From 9c6a86ffaa569ed4e1b059ca9f2c13c1b5807cdd Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 15 Apr 2024 19:34:07 +0000 Subject: [PATCH 06/32] Proxify functionality is removed --- curweather/curweather.php | 4 +--- mastodoncustomemojis/mastodoncustomemojis.php | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/curweather/curweather.php b/curweather/curweather.php index f614840a..5a14a9cf 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'], 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'] . ':'; } } } From dc7a8adf292f3ebd83a70470056b5f9f06e13856 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 16 Apr 2024 04:43:54 +0000 Subject: [PATCH 07/32] Issue 13812: Public groups with manual request approval --- forumdirectory/forumdirectory.php | 8 ++++---- groupdirectory/groupdirectory.php | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/forumdirectory/forumdirectory.php b/forumdirectory/forumdirectory.php index 79267c4e..114da1da 100644 --- a/forumdirectory/forumdirectory.php +++ b/forumdirectory/forumdirectory.php @@ -104,8 +104,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 +120,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/groupdirectory/groupdirectory.php b/groupdirectory/groupdirectory.php index 7bad1ef9..6d562cdc 100644 --- a/groupdirectory/groupdirectory.php +++ b/groupdirectory/groupdirectory.php @@ -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)) { From b9d0cece0a64c41da428694df74ea9d49726ac4b Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 28 Apr 2024 10:36:47 +0000 Subject: [PATCH 08/32] Bluesky: Improved fetching of the user DID --- bluesky/bluesky.php | 67 +++++++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 26 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 4a1f4f60..3e658bef 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -97,7 +97,7 @@ function bluesky_load_config(ConfigFileManager $loader) function bluesky_check_item_notification(array &$notification_data) { - $did = DI::pConfig()->get($notification_data['uid'], 'bluesky', 'did'); + $did = bluesky_get_user_did($notification_data['uid']); if (!empty($did)) { $notification_data['profiles'][] = $did; @@ -342,7 +342,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; @@ -438,15 +438,7 @@ function bluesky_settings_post(array &$b) DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'friendica_handle', intval($_POST['bluesky_friendica_handle'])); 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)) { @@ -664,7 +656,7 @@ function bluesky_create_activity(array $item, stdClass $parent = null) return; } - $did = DI::pConfig()->get($uid, 'bluesky', 'did'); + $did = bluesky_get_user_did($uid); if ($item['verb'] == Activity::LIKE) { $record = [ @@ -724,7 +716,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 +725,7 @@ function bluesky_create_post(array $item, stdClass $root = null, stdClass $paren } } } - + $urls = bluesky_get_urls($item['body']); $item['body'] = $urls['body']; @@ -1242,7 +1234,7 @@ function bluesky_get_restrictions_for_user(stdClass $post, array $item, int $pos return Item::CANT_REPLY; } - if(empty($post->threadgate)) { + if (empty($post->threadgate)) { return null; } @@ -1725,7 +1717,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]); @@ -1744,7 +1736,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]); @@ -1761,12 +1753,12 @@ function bluesky_get_did(string $handle): string //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 ''; @@ -1775,18 +1767,41 @@ function bluesky_get_did(string $handle): string return $data->did; } +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'); + $did = bluesky_get_did($handle); + if (empty($did)) { + Logger::notice('Error fetching DID for handle', ['uid' => $uid, 'handle' => $handle]); + DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_DID_FAIL); + } + 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'); - if (empty($did)) { + $did = bluesky_get_user_did($uid); + if (!empty($did)) { + $pds = bluesky_get_pds($did); + } else { Logger::notice('Empty did for user', ['uid' => $uid]); - return ''; } - $pds = bluesky_get_pds($did); + if (empty($pds)) { + return BLUESKY_PDS; + } DI::pConfig()->set($uid, 'bluesky', 'pds', $pds); return $pds; } @@ -1849,7 +1864,7 @@ 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); $data = bluesky_post($uid, '/xrpc/com.atproto.server.createSession', json_encode(['identifier' => $did, 'password' => $password]), ['Content-type' => 'application/json']); if (empty($data)) { @@ -1906,12 +1921,12 @@ 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; } From 6c76139ce179470a9d9ff1b9fe098c0ab9c4bab3 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 3 May 2024 02:58:45 +0000 Subject: [PATCH 09/32] Bluesky: Fixes "bluesky_get_did(): Argument #1 ($handle) must be of type string, null given" --- bluesky/bluesky.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 3e658bef..7577948a 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -97,6 +97,10 @@ function bluesky_load_config(ConfigFileManager $loader) function bluesky_check_item_notification(array &$notification_data) { + if (empty($notification_data['uid'])) { + return; + } + $did = bluesky_get_user_did($notification_data['uid']); if (!empty($did)) { From 85d254f2f8e0afda89ce459d7d5c68b4ca9fb2e0 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 4 May 2024 01:00:44 +0000 Subject: [PATCH 10/32] Bluesky: Fix error for missing handles --- bluesky/bluesky.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 7577948a..d69a9c41 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -1771,7 +1771,7 @@ function bluesky_get_did(string $handle): string return $data->did; } -function bluesky_get_user_did(int $uid, bool $refresh = false): string +function bluesky_get_user_did(int $uid, bool $refresh = false): ?string { if (!$refresh) { $did = DI::pConfig()->get($uid, 'bluesky', 'did'); @@ -1781,7 +1781,9 @@ function bluesky_get_user_did(int $uid, bool $refresh = false): string } $handle = DI::pConfig()->get($uid, 'bluesky', 'handle'); - $did = bluesky_get_did($handle); + if (!empty($handle)) { + $did = bluesky_get_did($handle); + } if (empty($did)) { Logger::notice('Error fetching DID for handle', ['uid' => $uid, 'handle' => $handle]); DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_DID_FAIL); From 67b464cc47a32a5f51a6b6193bed513e0b16fbb7 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 16 Apr 2024 05:00:23 +0000 Subject: [PATCH 11/32] Blockbot: Reworked user agent parsing --- blockbot/blockbot.php | 771 ++++++++++++++++++++++++++++++----- blockbot/lang/C/messages.po | 41 +- blockbot/templates/admin.tpl | 6 +- 3 files changed, 670 insertions(+), 148 deletions(-) diff --git a/blockbot/blockbot.php b/blockbot/blockbot.php index e11f23f7..77886edf 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,9 @@ 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\Network; require_once __DIR__ . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php'; @@ -28,115 +30,123 @@ 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'], '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', $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/', - ]; - - 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', $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', $logdata); + blockbot_reject(); + } + + if (blockbot_is_unwanted($parts)) { + Logger::debug('Uncategorized unwanted agent found', $logdata); + blockbot_reject(); + } + + if (blockbot_is_security_checker($parts)) { + Logger::debug('Security checker found', $logdata); + if (!DI::config()->get('blockbot', 'security_checker')) { + blockbot_reject(); + } 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', $logdata); + return; + } + + if (blockbot_is_fediverse_client($parts)) { + Logger::debug('Fediverse client found', $logdata); + return; + } + + if (blockbot_is_feed_reader($parts)) { + Logger::debug('Feed reader found', $logdata); + return; + } + + if (blockbot_is_fediverse_tool($parts)) { + Logger::debug('Fediverse tool found', $logdata); + return; + } + + if (blockbot_is_service_agent($parts)) { + Logger::debug('Service agent found', $logdata); + return; + } + + if (blockbot_is_monitor($parts)) { + Logger::debug('Monitoring service found', $logdata); + return; + } + + if (blockbot_is_validator($parts)) { + Logger::debug('Validation service found', $logdata); + return; + } + + if (blockbot_is_good_tool($parts)) { + Logger::debug('Uncategorized helpful service found', $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); + Logger::debug('HTTP Library found', $logdata); + if (!DI::config()->get('blockbot', 'http_libraries')) { + blockbot_reject(); + } + 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 +154,581 @@ 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('Blocked bot', $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', 'training') || !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_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', $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', 'gptbot', '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 = [ + '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', 'google', 'rogerbot', 'yahoocachesystem', + 'vkshare', 'appid: s~virustotalcloud', 'clickagy intelligence bot v2', + ]; + + 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 = [ + 'yahoo! slurp', 'linkcheck by siteimprove.com', 'googlebot', '360spider', 'haosouspider', + 'mj12bot', 'feedfetcher-google', 'mediapartners-google', 'duckduckgo-favicons-bot', + 'googlebot-mobile', 'gigablastopensource', 'bingbot', 'surveybot', 'yandexbot', + 'baiduspider', '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', + ]; + + 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', + ]; + + 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', + ]; + + 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', + ]; + + 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', + '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', + ]; + + 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', + ]; + + 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', + ]; + + 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 = [ + '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', + ]; + + 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'])) { + 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', + ]; + + 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', 'wellknownbot', '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 From c7a6ecb34691abda06c31dc149a66178bf6eebba Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 10 May 2024 09:33:36 +0000 Subject: [PATCH 12/32] Blockbot: More agents added --- blockbot/blockbot.php | 138 ++++++++++++++++++++++++++++++++---------- 1 file changed, 106 insertions(+), 32 deletions(-) diff --git a/blockbot/blockbot.php b/blockbot/blockbot.php index 77886edf..e5de1ef3 100644 --- a/blockbot/blockbot.php +++ b/blockbot/blockbot.php @@ -62,14 +62,14 @@ function blockbot_init_1() $parts = blockbot_get_parts($_SERVER['HTTP_USER_AGENT']); - $logdata = ['isCrawler' => $isCrawler, 'agent' => $_SERVER['HTTP_USER_AGENT'], 'uri' => $_SERVER['REQUEST_URI'], 'parts' => $parts]; + $logdata = ['isCrawler' => $isCrawler, 'agent' => $_SERVER['HTTP_USER_AGENT'], 'method' => $_SERVER['REQUEST_METHOD'], 'uri' => $_SERVER['REQUEST_URI'], 'parts' => $parts]; if ($isCrawler) { blockbot_check_login_attempt($_SERVER['REQUEST_URI'], $logdata); } if (empty($parts)) { - Logger::debug('Known frontend found', $logdata); + Logger::debug('Known frontend found - accept', $logdata); if ($isCrawler) { blockbot_save('badly-parsed-agents', $_SERVER['HTTP_USER_AGENT']); } @@ -77,75 +77,77 @@ function blockbot_init_1() } if (blockbot_is_crawler($parts)) { - Logger::debug('Crawler found', $logdata); + Logger::debug('Crawler found - reject', $logdata); blockbot_reject(); } if (blockbot_is_searchbot($parts)) { - Logger::debug('Search bot found', $logdata); + Logger::debug('Search bot found - reject', $logdata); blockbot_reject(); } if (blockbot_is_unwanted($parts)) { - Logger::debug('Uncategorized unwanted agent found', $logdata); + Logger::debug('Uncategorized unwanted agent found - reject', $logdata); blockbot_reject(); } if (blockbot_is_security_checker($parts)) { - Logger::debug('Security checker found', $logdata); 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_is_social_media($parts)) { - Logger::debug('Social media service found', $logdata); + Logger::debug('Social media service found - accept', $logdata); return; } if (blockbot_is_fediverse_client($parts)) { - Logger::debug('Fediverse client found', $logdata); + Logger::debug('Fediverse client found - accept', $logdata); return; } if (blockbot_is_feed_reader($parts)) { - Logger::debug('Feed reader found', $logdata); + Logger::debug('Feed reader found - accept', $logdata); return; } if (blockbot_is_fediverse_tool($parts)) { - Logger::debug('Fediverse tool found', $logdata); + Logger::debug('Fediverse tool found - accept', $logdata); return; } if (blockbot_is_service_agent($parts)) { - Logger::debug('Service agent found', $logdata); + Logger::debug('Service agent found - accept', $logdata); return; } if (blockbot_is_monitor($parts)) { - Logger::debug('Monitoring service found', $logdata); + Logger::debug('Monitoring service found - accept', $logdata); return; } if (blockbot_is_validator($parts)) { - Logger::debug('Validation service found', $logdata); + Logger::debug('Validation service found - accept', $logdata); return; } if (blockbot_is_good_tool($parts)) { - Logger::debug('Uncategorized helpful service found', $logdata); + 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); - Logger::debug('HTTP Library found', $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; } @@ -161,7 +163,7 @@ function blockbot_init_1() } blockbot_save('bad-agents', $_SERVER['HTTP_USER_AGENT']); - Logger::notice('Blocked bot', $logdata); + Logger::notice('Possible bot found - reject', $logdata); blockbot_reject(); } @@ -182,7 +184,7 @@ function blockbot_save($database, $userAgent) 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', $logdata); + Logger::debug('Login attempt detected - reject', $logdata); blockbot_reject(); } } @@ -198,9 +200,9 @@ 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', + 'gulper', 'magellan', 'linkcheck', 'nerdybot', 'ms search robot', 'fast-webcrawler', 'yioopbot', 'webster', 'www.admantx.com', 'openhosebot', 'lssrocketcrawler', 'dow jones searchbot', - 'gomezagent', 'domainsigmacrawler', 'netseer crawler', 'gptbot', 'superbot', 'searchexpress', + 'gomezagent', 'domainsigmacrawler', 'netseer crawler', 'superbot', 'searchexpress', 'alittle client', 'amazon-kendra', 'scanner.ducks.party', 'isscyberriskcrawler', 'google wireless transcoder', ]; @@ -221,6 +223,18 @@ function blockbot_is_unwanted(array $parts): bool */ 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', @@ -241,8 +255,26 @@ function blockbot_is_crawler(array $parts): bool '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', 'google', 'rogerbot', 'yahoocachesystem', - 'vkshare', 'appid: s~virustotalcloud', 'clickagy intelligence bot v2', + '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) { @@ -265,11 +297,20 @@ function blockbot_is_crawler(array $parts): bool */ 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', - 'baiduspider', 'google web preview', 'meanpathbot', 'wesee_bot:we_help_monitize_your_site', + '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', @@ -281,6 +322,15 @@ function blockbot_is_searchbot(array $parts): bool '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) { @@ -304,7 +354,7 @@ function blockbot_is_security_checker(array $parts): bool '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', + 'zgrab', 'nmap scripting engine', 'l9scan', 'riddler', 'cloud mapping experiment. contact research@pdrlabs.net', ]; foreach ($parts as $part) { @@ -324,7 +374,8 @@ function blockbot_is_security_checker(array $parts): bool function blockbot_is_validator(array $parts): bool { $agents = [ - 'jigsaw', 'ssl labs', 'w3c_validator', 'w3c-checklink', 'p3p validator', 'csscheck', + '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) { @@ -345,7 +396,9 @@ function blockbot_is_monitor(array $parts): bool { $agents = [ 'alexa site audit', 'catchpoint', 'google page speed insights', 'checkhost', - 'poduptime', 'chrome-lighthouse', 'zabbix', 'cloudflare-alwaysonline', + '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) { @@ -382,14 +435,14 @@ function blockbot_is_social_media(array $parts): bool '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', + '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', + 'gyptazyfedi', 'apogee', 'quolibet', 'magpie-crawler', 'redditbot', 'facebookplatform', ]; foreach ($parts as $part) { @@ -441,7 +494,7 @@ function blockbot_is_feed_reader(array $parts): bool 'windows-rss-platform', 'feedshow', 'feedreader', 'rssbandit', 'everyfeed-spider', 'feeeed', 'spacecowboys android rss reader', 'gregarius', 'feedspot', 'feedspot ssl asset proxy', 'newsgator', 'newsgator fetchlinks extension', - 'akregator', + 'akregator', 'appid: s~feedly-nikon3', ]; foreach ($parts as $part) { @@ -482,11 +535,21 @@ function blockbot_is_fediverse_tool(array $parts): bool */ 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', + 'plasmatrap image proxy server', 'grammarly', 'browsershots', 'google-apps-script', + 'yahoomailproxy', 'pocketparser', 'apachebench', ]; foreach ($parts as $part) { @@ -505,10 +568,19 @@ function blockbot_is_service_agent(array $parts): bool */ function blockbot_is_http_library(array $parts): bool { - if ((count($parts) == 1) && in_array($parts[0], ['okhttp', 'useragent'])) { + 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', @@ -522,7 +594,9 @@ function blockbot_is_http_library(array $parts): bool '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', + '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) { @@ -544,7 +618,7 @@ 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', 'wellknownbot', 'wdg_validator', 'download demon', + 'androiddownloadmanager', 'readybot.io', 'hydra', 'httrack', 'vlc', 'wdg_validator', 'download demon', ]; From e7dd7111aca76ee4436e16212587513422c92b00 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 12 May 2024 00:53:46 +0000 Subject: [PATCH 13/32] Bluesky: fix unneeded check for user PDS --- bluesky/bluesky.php | 61 ++++++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index d69a9c41..ed2a8496 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -102,10 +102,11 @@ function bluesky_check_item_notification(array &$notification_data) } $did = bluesky_get_user_did($notification_data['uid']); - - if (!empty($did)) { - $notification_data['profiles'][] = $did; + if (empty($did)) { + return; } + + $notification_data['profiles'][] = $did; } function bluesky_probe_detect(array &$hookData) @@ -233,7 +234,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 ]; @@ -286,7 +287,7 @@ 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 ]; @@ -511,6 +512,10 @@ function bluesky_cron() $pconfigs = DBA::selectToArray('pconfig', [], ['cat' => 'bluesky', 'k' => 'import', 'v' => true]); foreach ($pconfigs as $pconfig) { + if (empty(bluesky_get_user_did($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']]); @@ -661,6 +666,9 @@ function bluesky_create_activity(array $item, stdClass $parent = null) } $did = bluesky_get_user_did($uid); + if (empty($did)) { + return; + } if ($item['verb'] == Activity::LIKE) { $record = [ @@ -768,7 +776,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 ]; @@ -1781,33 +1789,37 @@ function bluesky_get_user_did(int $uid, bool $refresh = false): ?string } $handle = DI::pConfig()->get($uid, 'bluesky', 'handle'); - if (!empty($handle)) { - $did = bluesky_get_did($handle); + if (empty($handle)) { + return null; } + + $did = bluesky_get_did($handle); if (empty($did)) { - Logger::notice('Error fetching DID for handle', ['uid' => $uid, 'handle' => $handle]); - DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_DID_FAIL); + 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 +function bluesky_get_user_pds(int $uid): ?string { $pds = DI::pConfig()->get($uid, 'bluesky', 'pds'); if (!empty($pds)) { return $pds; } + $did = bluesky_get_user_did($uid); - if (!empty($did)) { - $pds = bluesky_get_pds($did); - } else { - Logger::notice('Empty did for user', ['uid' => $uid]); + if (empty($did)) { + return null; } + + $pds = bluesky_get_pds($did); if (empty($pds)) { - return BLUESKY_PDS; + return null; } + DI::pConfig()->set($uid, 'bluesky', 'pds', $pds); return $pds; } @@ -1871,6 +1883,9 @@ function bluesky_refresh_token(int $uid): string function bluesky_create_token(int $uid, string $password): string { $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)) { @@ -1893,8 +1908,13 @@ function bluesky_xrpc_post(int $uid, string $url, $parameters): ?stdClass function bluesky_post(int $uid, string $url, string $params, array $headers): ?stdClass { + $pds = bluesky_get_user_pds($uid); + if (empty($pds)) { + return null; + } + try { - $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); @@ -1917,7 +1937,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; } From 2306261ab2962e8e160f36a9785fd6ff98c874f2 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 16 May 2024 12:24:34 +0000 Subject: [PATCH 14/32] Tumblr: "isLocalLink" is now "isLocalUrl" / Bluesky: Fix for an empty uri --- bluesky/bluesky.php | 4 ++++ tumblr/tumblr.php | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index ed2a8496..ba7c1d65 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -1506,6 +1506,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]); diff --git a/tumblr/tumblr.php b/tumblr/tumblr.php index 78e415ee..04f6a0a4 100644 --- a/tumblr/tumblr.php +++ b/tumblr/tumblr.php @@ -614,7 +614,7 @@ function tumblr_send_legacy(array $b) $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); From 9ae8925069fe87ff35b138668ee91946304593bf Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 19 May 2024 18:08:19 +0000 Subject: [PATCH 15/32] Upload: Fix available file extension check --- js_upload/js_upload.php | 43 ++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/js_upload/js_upload.php b/js_upload/js_upload.php index 089cb7e2..786fc3c2 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,10 @@ 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) { + $allowedExtensions[] = image_type_to_extension($type, false); + } // max file size in bytes $sizeLimit = Strings::getBytesFromShorthand(DI::config()->get('system', 'maximagesize')); @@ -75,10 +78,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 +181,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 +199,6 @@ class qqFileUploader } else { $this->file = false; } - } /** @@ -216,11 +217,9 @@ class qqFileUploader } // if ($size > $this->sizeLimit) { - // return array('error' => DI::l10n()->t('Uploaded file is too large')); // } - $maximagesize = Strings::getBytesFromShorthand(DI::config()->get('system', 'maximagesize')); if (($maximagesize) && ($size > $maximagesize)) { @@ -241,14 +240,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 ]; } From 084a2a705761f4a21d6e720c267600b92750b700 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 27 May 2024 04:45:17 +0000 Subject: [PATCH 16/32] "zrl" functionility is moved --- forumdirectory/forumdirectory.php | 5 ++--- groupdirectory/groupdirectory.php | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/forumdirectory/forumdirectory.php b/forumdirectory/forumdirectory.php index 114da1da..9c99d63f 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::zrl($dirurl, true); } $sql_extra = ''; diff --git a/groupdirectory/groupdirectory.php b/groupdirectory/groupdirectory.php index 6d562cdc..df4bbb33 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::zrl($dirurl, true); } $sql_extra = ''; From 39247ca28f84ec25b49e41482b7e5ea91bdf8b21 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 29 May 2024 06:07:48 +0000 Subject: [PATCH 17/32] Function renamed --- forumdirectory/forumdirectory.php | 2 +- groupdirectory/groupdirectory.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/forumdirectory/forumdirectory.php b/forumdirectory/forumdirectory.php index 9c99d63f..9a155a00 100644 --- a/forumdirectory/forumdirectory.php +++ b/forumdirectory/forumdirectory.php @@ -81,7 +81,7 @@ function forumdirectory_content() $gdirpath = ''; $dirurl = DI::config()->get('system', 'directory'); if (strlen($dirurl)) { - $gdirpath = OpenWebAuth::zrl($dirurl, true); + $gdirpath = OpenWebAuth::getZrlUrl($dirurl, true); } $sql_extra = ''; diff --git a/groupdirectory/groupdirectory.php b/groupdirectory/groupdirectory.php index df4bbb33..615d7024 100644 --- a/groupdirectory/groupdirectory.php +++ b/groupdirectory/groupdirectory.php @@ -79,7 +79,7 @@ function groupdirectory_content() $gdirpath = ''; $dirurl = DI::config()->get('system', 'directory'); if (strlen($dirurl)) { - $gdirpath = OpenWebAuth::zrl($dirurl, true); + $gdirpath = OpenWebAuth::getZrlUrl($dirurl, true); } $sql_extra = ''; From c7f4d183b18aa55129af46a88179d416f03e5118 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Mon, 3 Jun 2024 08:13:08 +0200 Subject: [PATCH 18/32] FR translation updates - nsfw, securemail, tumblr --- nsfw/lang/fr/messages.po | 6 +++--- nsfw/lang/fr/strings.php | 2 +- securemail/lang/fr/messages.po | 8 ++++---- securemail/lang/fr/strings.php | 4 ++-- tumblr/lang/fr/messages.po | 12 ++++++------ tumblr/lang/fr/strings.php | 8 ++++---- 6 files changed, 20 insertions(+), 20 deletions(-) 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/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'; From 77c471ab4df90e68f9557df4e2bc37ddccfa2d51 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 5 Jun 2024 03:37:43 +0000 Subject: [PATCH 19/32] Bluesky: Fix error on restricted posts / improve performance --- bluesky/bluesky.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index ba7c1d65..453c4ead 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -1217,7 +1217,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']; @@ -1592,7 +1596,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'); @@ -1610,7 +1614,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'])) { From 734d35d22b7a41c0f5bbe7cedea8e5eb9358b6ae Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 5 Jun 2024 03:35:00 +0000 Subject: [PATCH 20/32] Blockbot: Logging of AP actors --- blockbot/blockbot.php | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/blockbot/blockbot.php b/blockbot/blockbot.php index e5de1ef3..eb634b1f 100644 --- a/blockbot/blockbot.php +++ b/blockbot/blockbot.php @@ -15,6 +15,7 @@ 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'; @@ -76,6 +77,8 @@ function blockbot_init_1() return; } + blockbot_log_activitypub($_SERVER['REQUEST_URI'], $_SERVER['HTTP_USER_AGENT']); + if (blockbot_is_crawler($parts)) { Logger::debug('Crawler found - reject', $logdata); blockbot_reject(); @@ -169,7 +172,7 @@ function blockbot_init_1() function blockbot_save($database, $userAgent) { - if (!DI::config()->get('blockbot', 'training') || !function_exists('dba_open')) { + if (!DI::config()->get('blockbot', 'logging') || !function_exists('dba_open')) { return; } @@ -181,6 +184,36 @@ function blockbot_save($database, $userAgent) 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'])) { From 231d830db0929fb0627e075b18da5c0b331e9c18 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 9 Jun 2024 20:32:23 +0000 Subject: [PATCH 21/32] Bluesky: Fix overwritten handle when "friendica handles" is selected --- bluesky/bluesky.php | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 453c4ead..fa5ba232 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -355,8 +355,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 = []; } @@ -369,7 +372,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), @@ -440,7 +443,7 @@ 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)) { $did = bluesky_get_user_did(DI::userSession()->getLocalUserId(), empty($old_did) || $old_handle != $handle); @@ -510,7 +513,7 @@ 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']))) { continue; @@ -527,8 +530,9 @@ function bluesky_cron() bluesky_get_token($pconfig['uid']); Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_notifications.php', $pconfig['uid'], $last); - Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_timeline.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')) { $feeds = bluesky_get_feeds($pconfig['uid']); foreach ($feeds as $feed) { From fa16adccaf47f94e7fe29e9e1a7e389e2f767039 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 10 Jun 2024 05:39:58 +0000 Subject: [PATCH 22/32] Bluesky: more logging added --- bluesky/bluesky.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index fa5ba232..e9648018 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -516,6 +516,7 @@ function bluesky_cron() $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; } @@ -527,6 +528,7 @@ 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_notifications.php', $pconfig['uid'], $last); @@ -534,13 +536,19 @@ function bluesky_cron() 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'); @@ -554,8 +562,6 @@ function bluesky_cron() } Logger::notice('cron_end'); - - DI::keyValue()->set('bluesky_last_poll', time()); } function bluesky_hook_fork(array &$b) From 6f56932f120fe0a57c8bd9383735c99d7d9b9c5a Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 13 Jun 2024 04:32:00 +0000 Subject: [PATCH 23/32] Bluesky: Handle API error when fetching feeds --- bluesky/bluesky.php | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index e9648018..6994b3e3 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() { @@ -1719,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 ?? []; @@ -1727,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); @@ -1736,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; @@ -1778,6 +1785,14 @@ 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 != '') { From 9525259fc8c74b89f2c5d8ac2aaf66392060470d Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 15 Jun 2024 13:51:47 +0000 Subject: [PATCH 24/32] Tumblr: Add link for quoted post --- tumblr/tumblr.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tumblr/tumblr.php b/tumblr/tumblr.php index 04f6a0a4..f0c68f33 100644 --- a/tumblr/tumblr.php +++ b/tumblr/tumblr.php @@ -608,6 +608,15 @@ 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); @@ -648,7 +657,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) != '')) { From af868f45ab6095a222b2133c210d31c9c220087d Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 16 Jun 2024 14:35:19 +0000 Subject: [PATCH 25/32] JS Uploader: "jpg" added to the list of allowed file extensions --- js_upload/js_upload.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/js_upload/js_upload.php b/js_upload/js_upload.php index 786fc3c2..0d045dee 100644 --- a/js_upload/js_upload.php +++ b/js_upload/js_upload.php @@ -50,7 +50,11 @@ function js_upload_post_init(array &$b) // list of valid extensions $allowedExtensions = []; foreach (Images::IMAGETYPES as $type) { - $allowedExtensions[] = image_type_to_extension($type, false); + $extension = image_type_to_extension($type, false); + if ($extension == 'jpeg') { + $allowedExtensions[] = 'jpg'; + } + $allowedExtensions[] = $extension; } // max file size in bytes @@ -216,9 +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')); From 3e1b98d5d97a3c7a4c6e5fb28591293acfc0db89 Mon Sep 17 00:00:00 2001 From: Matthew Exon Date: Sun, 16 Jun 2024 17:10:28 +0200 Subject: [PATCH 26/32] Leave failed image URLs in place --- mailstream/mailstream.php | 5 +++++ 1 file changed, 5 insertions(+) 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; From 2789e880dc7f3a2614e9811a179dca291ae8a986 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Fri, 21 Jun 2024 20:38:42 +0200 Subject: [PATCH 27/32] translation updates AR, CS, DE, IT, PL, SV for various addons --- advancedcontentfilter/lang/it/messages.po | 6 +- advancedcontentfilter/lang/it/strings.php | 1 + catavatar/lang/it/messages.po | 50 ++++++------- catavatar/lang/it/strings.php | 10 +-- curweather/lang/it/messages.po | 56 +++++++-------- curweather/lang/it/strings.php | 6 +- dwpost/lang/it/messages.po | 46 ++++++------ dwpost/lang/it/strings.php | 11 ++- libertree/lang/it/messages.po | 38 +++++----- libertree/lang/it/strings.php | 7 +- mailstream/lang/de/messages.po | 50 +++++++------ mailstream/lang/de/strings.php | 3 +- tumblr/lang/ar/messages.po | 85 ++++++++++++++--------- tumblr/lang/ar/strings.php | 1 - tumblr/lang/cs/messages.po | 61 ++++++++++------ tumblr/lang/cs/strings.php | 4 +- tumblr/lang/de/messages.po | 67 +++++++++++------- tumblr/lang/de/strings.php | 11 +-- tumblr/lang/it/messages.po | 63 +++++++++++------ tumblr/lang/it/strings.php | 5 +- tumblr/lang/pl/messages.po | 65 ++++++++++------- tumblr/lang/pl/strings.php | 5 +- tumblr/lang/sv/messages.po | 63 +++++++++++------ tumblr/lang/sv/strings.php | 1 - 24 files changed, 405 insertions(+), 310 deletions(-) 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/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/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/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/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/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'; From 14e7413eb2f89effd151b4460c0a56cdb560c681 Mon Sep 17 00:00:00 2001 From: hankg Date: Mon, 24 Jun 2024 22:20:35 +0200 Subject: [PATCH 28/32] Add Relatica to blockbot fediverse client list --- blockbot/blockbot.php | 1 + 1 file changed, 1 insertion(+) diff --git a/blockbot/blockbot.php b/blockbot/blockbot.php index eb634b1f..adf0a7c2 100644 --- a/blockbot/blockbot.php +++ b/blockbot/blockbot.php @@ -499,6 +499,7 @@ function blockbot_is_fediverse_client(array $parts): bool '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) { From b2108c7a4c7efe5c79f8c5e762e3cae207d9e0d2 Mon Sep 17 00:00:00 2001 From: Hannes Heute Date: Thu, 27 Jun 2024 11:44:15 +0200 Subject: [PATCH 29/32] fix for curweather --- curweather/curweather.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/curweather/curweather.php b/curweather/curweather.php index 5a14a9cf..9aa8584a 100644 --- a/curweather/curweather.php +++ b/curweather/curweather.php @@ -152,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; } From c0535db74214eb0983c7bd145702d9600fc169f2 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 5 Aug 2024 20:37:58 +0000 Subject: [PATCH 30/32] Statistics: inbound / outbound for Tumblr and Bluesky --- bluesky/bluesky.php | 2 ++ tumblr/tumblr.php | 2 ++ 2 files changed, 4 insertions(+) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 6994b3e3..9f21674f 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -1946,6 +1946,7 @@ function bluesky_post(int $uid, string $url, string $params, array $headers): ?s return null; } + Item::incrementOutbound(Protocol::BLUESKY); try { $curlResult = DI::httpClient()->post($pds . $url, $params, $headers); } catch (\Exception $e) { @@ -1982,6 +1983,7 @@ function bluesky_xrpc_get(int $uid, string $url, array $parameters = []): ?stdCl function bluesky_get(string $url, string $accept_content = HttpClientAccept::DEFAULT, array $opts = []): ?stdClass { + Item::incrementInbound(Protocol::BLUESKY); try { $curlResult = DI::httpClient()->get($url, $accept_content, $opts); } catch (\Exception $e) { diff --git a/tumblr/tumblr.php b/tumblr/tumblr.php index f0c68f33..945f8f35 100644 --- a/tumblr/tumblr.php +++ b/tumblr/tumblr.php @@ -1326,6 +1326,7 @@ function tumblr_get_contact_by_url(string $url, int $uid): ?array */ function tumblr_get(int $uid, string $url, array $parameters = []): stdClass { + Item::incrementInbound(Protocol::TUMBLR); $url = 'https://api.tumblr.com/v2/' . $url; if ($uid == 0) { @@ -1355,6 +1356,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)]]); From 4bfdb45e81c8550ab89381670c068455d780bcf5 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 12 Aug 2024 20:20:32 +0000 Subject: [PATCH 31/32] Bluesky/Tumblr: Improved statistics --- bluesky/bluesky.php | 23 +++++++++++++---------- tumblr/tumblr.php | 22 +++++++++++++--------- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 9f21674f..19466a42 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -294,9 +294,9 @@ function bluesky_block(array &$hook_data) $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]); } @@ -975,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; } @@ -1048,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]); } } @@ -1537,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); @@ -1936,7 +1936,11 @@ 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 @@ -1946,7 +1950,6 @@ function bluesky_post(int $uid, string $url, string $params, array $headers): ?s return null; } - Item::incrementOutbound(Protocol::BLUESKY); try { $curlResult = DI::httpClient()->post($pds . $url, $params, $headers); } catch (\Exception $e) { @@ -1983,7 +1986,6 @@ function bluesky_xrpc_get(int $uid, string $url, array $parameters = []): ?stdCl function bluesky_get(string $url, string $accept_content = HttpClientAccept::DEFAULT, array $opts = []): ?stdClass { - Item::incrementInbound(Protocol::BLUESKY); try { $curlResult = DI::httpClient()->get($url, $accept_content, $opts); } catch (\Exception $e) { @@ -1996,5 +1998,6 @@ function bluesky_get(string $url, string $accept_content = HttpClientAccept::DEF return null; } + Item::incrementInbound(Protocol::BLUESKY); return json_decode($curlResult->getBodyString()); } diff --git a/tumblr/tumblr.php b/tumblr/tumblr.php index 945f8f35..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() { @@ -756,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); } } } @@ -795,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); } @@ -1167,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)) { @@ -1231,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; @@ -1287,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; @@ -1326,7 +1331,6 @@ function tumblr_get_contact_by_url(string $url, int $uid): ?array */ function tumblr_get(int $uid, string $url, array $parameters = []): stdClass { - Item::incrementInbound(Protocol::TUMBLR); $url = 'https://api.tumblr.com/v2/' . $url; if ($uid == 0) { From a55f80cb39ea8737a56e265cb9edda6739cc2755 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Thu, 15 Aug 2024 06:44:57 +0200 Subject: [PATCH 32/32] updated translations --- curweather/lang/fr/messages.po | 7 ++++--- curweather/lang/fr/strings.php | 2 +- geonames/lang/fr/messages.po | 7 ++++--- geonames/lang/fr/strings.php | 2 +- gnot/lang/fr/messages.po | 7 ++++--- gnot/lang/fr/strings.php | 2 +- gravatar/lang/fr/messages.po | 7 ++++--- gravatar/lang/fr/strings.php | 2 +- ijpost/lang/fr/messages.po | 7 ++++--- ijpost/lang/fr/strings.php | 2 +- krynn/lang/fr/messages.po | 7 ++++--- krynn/lang/fr/strings.php | 2 +- 12 files changed, 30 insertions(+), 24 deletions(-) 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/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/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/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';