Download plugins/BotTracking/BotTracking.php from Leon4gr45/matomo: direct link, hf CLI and curl.
- Browser
- Download file 7.83 kB
-
https://huggingface.co/spaces/Leon4gr45/matomo/resolve/main/plugins/BotTracking/BotTracking.php
- Command line
-
hf download hf://spaces/Leon4gr45/matomo/plugins/BotTracking/BotTracking.php
-
curl -L -o BotTracking.php https://huggingface.co/spaces/Leon4gr45/matomo/resolve/main/plugins/BotTracking/BotTracking.php
7.83 kB
| /** | |
| * Matomo - free/libre analytics platform | |
| * | |
| * @link https://matomo.org | |
| * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later | |
| */ | |
| declare(strict_types=1); | |
| namespace Piwik\Plugins\BotTracking; | |
| use Piwik\Date; | |
| use Piwik\Piwik; | |
| use Piwik\Plugin; | |
| use Piwik\Plugins\BotTracking\Dao\BotRequestsDao; | |
| use Piwik\Plugins\SitesManager\API; | |
| use Piwik\Plugins\BotTracking\Metrics as BotMetrics; | |
| use Piwik\Plugins\BotTracking\Reports\AIChatbotsRealTimeWidgets; | |
| use Piwik\Tracker\Request; | |
| /** | |
| * BotTracking Plugin | |
| * | |
| * Tracks AI assistant and bot interactions without creating visits. | |
| * Stores telemetry data in dedicated tables for analysis of bot behavior | |
| * and system performance. | |
| */ | |
| class BotTracking extends Plugin | |
| { | |
| /** | |
| * @return bool | |
| */ | |
| public function isTrackerPlugin() | |
| { | |
| return true; | |
| } | |
| /** | |
| * @return array<string, string> | |
| */ | |
| public function registerEvents(): array | |
| { | |
| return [ | |
| 'AssetManager.getStylesheetFiles' => 'getStylesheetFiles', | |
| 'PrivacyManager.deleteLogsOlderThan' => 'deleteLogsOlderThan', | |
| 'PrivacyManager.deleteDataSubjectsForDeletedSites' => 'deleteDataSubjectsForDeletedSites', | |
| 'Tracker.isBotRequest' => 'isBotRequest', | |
| 'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys', | |
| 'Metrics.getEvolutionUnit' => 'getEvolutionUnit', | |
| 'Metrics.getDefaultMetricTranslations' => 'addMetricTranslations', | |
| 'Metrics.getDefaultMetricDocumentationTranslations' => 'addMetricDocumentationTranslations', | |
| 'Metrics.getDefaultMetricSemanticTypes' => 'addMetricSemanticTypes', | |
| 'API.addGlossaryItems' => 'addGlossaryItems', | |
| ]; | |
| } | |
| /** | |
| * @return void | |
| */ | |
| public function install() | |
| { | |
| (new BotRequestsDao())->createTable(); | |
| } | |
| /** | |
| * @return void | |
| */ | |
| public function uninstall() | |
| { | |
| (new BotRequestsDao())->dropTable(); | |
| } | |
| public function deleteLogsOlderThan(Date $dateUpperLimit): void | |
| { | |
| (new BotRequestsDao())->deleteOldRecords($dateUpperLimit); | |
| } | |
| /** | |
| * @param array<string, int> $result | |
| */ | |
| public function deleteDataSubjectsForDeletedSites(array &$result): void | |
| { | |
| $allExistingIdSites = API::getInstance()->getAllSitesId(); | |
| $allExistingIdSites = array_map('intval', $allExistingIdSites); | |
| $maxIdSite = max($allExistingIdSites); | |
| if (empty($maxIdSite)) { | |
| return; | |
| } | |
| $dao = new BotRequestsDao(); | |
| $idSitesInTable = $dao->getDistinctIdSitesInTable($maxIdSite); | |
| $idSitesNoLongerExisting = array_diff($idSitesInTable, $allExistingIdSites); | |
| if (count($idSitesNoLongerExisting) > 0) { | |
| $result[$dao::getTableName()] = $dao->deleteRecordsForIdSites($idSitesNoLongerExisting); | |
| } | |
| } | |
| /** | |
| * @todo Remove, once Device Detector is able to detect all known ai bots | |
| */ | |
| public function isBotRequest(bool &$isBot, Request $request): void | |
| { | |
| $botDetector = new BotDetector($request->getUserAgent()); | |
| if ($botDetector->isBot()) { | |
| $isBot = true; | |
| } | |
| } | |
| public function getEvolutionUnit(?string &$unit, string $column): void | |
| { | |
| if ($column === Metrics::METRIC_AI_CHATBOTS_CLICK_THROUGH_RATE) { | |
| $unit = '%'; | |
| } | |
| } | |
| /** | |
| * @param array<string, string> $translations | |
| */ | |
| public function addMetricTranslations(array &$translations): void | |
| { | |
| $translations = array_merge($translations, BotMetrics::getMetricTranslations()); | |
| // Register a default name for the generic 'requests' column used by the new content-URL | |
| // reports. Without this the Glossary majority heuristic renders name = null for the | |
| // 'requests' metric because three reports expose it under different per-report scoped | |
| // documentation strings, leaving no single translation with a majority. Registering the | |
| // default here mirrors the documentation registration in addMetricDocumentationTranslations. | |
| if (!isset($translations[Metrics::COLUMN_REQUESTS])) { | |
| $translations[Metrics::COLUMN_REQUESTS] = Piwik::translate('BotTracking_ColumnRequests'); | |
| } | |
| } | |
| /** | |
| * @param array<string, string> $translations | |
| */ | |
| public function addMetricDocumentationTranslations(array &$translations): void | |
| { | |
| $translations = array_merge($translations, BotMetrics::getMetricDocumentation()); | |
| // Register a default documentation for the generic 'requests' column used by the | |
| // new content-URL reports. Without this default the Glossary majority heuristic | |
| // (array_sum - max < max) would not pick a winner because the three reports that | |
| // expose 'requests' each use a different documentation string (generic, page-scoped, | |
| // document-scoped), leaving no single value with a majority. Setting a default here | |
| // ensures the metric always appears in the glossary with the generic tooltip. | |
| if (!isset($translations[Metrics::COLUMN_REQUESTS])) { | |
| $translations[Metrics::COLUMN_REQUESTS] = Piwik::translate('BotTracking_ColumnRequestsDocumentation'); | |
| } | |
| } | |
| /** | |
| * @param array<string|int, string> $types | |
| */ | |
| public function addMetricSemanticTypes(array &$types): void | |
| { | |
| $types = array_merge($types, BotMetrics::getMetricSemanticTypes()); | |
| } | |
| /** | |
| * @param array<string, array{title: string, entries: array<int, array<string, string>>}> $glossaryItems | |
| */ | |
| public function addGlossaryItems(array &$glossaryItems): void | |
| { | |
| Piwik::checkUserHasSomeViewAccess(); | |
| $category = Piwik::translate('General_AIAssistants'); | |
| foreach (AIChatbotsRealTimeWidgets::getAllWidgets() as $widget) { | |
| $glossaryItems['reports']['entries'][] = [ | |
| 'name' => sprintf('%s (%s)', Piwik::translate($widget['name']), $category), | |
| 'documentation' => Piwik::translate($widget['documentation']), | |
| ]; | |
| } | |
| } | |
| /** | |
| * @param string[] $translationKeys | |
| * @return void | |
| */ | |
| public function getClientSideTranslationKeys(&$translationKeys) | |
| { | |
| $translationKeys[] = 'BotTracking_DetectingYourSite'; | |
| $translationKeys[] = 'BotTracking_SiteWithoutDataBackToMatomo'; | |
| $translationKeys[] = 'BotTracking_SiteWithoutDataChooseTrackingMethod'; | |
| $translationKeys[] = 'BotTracking_SiteWithoutDataChooseTrackingMethodPreamble1'; | |
| $translationKeys[] = 'BotTracking_SiteWithoutDataChooseTrackingMethodPreamble2'; | |
| $translationKeys[] = 'BotTracking_SiteWithoutDataInstallWithX'; | |
| $translationKeys[] = 'BotTracking_SiteWithoutDataNotYetReady'; | |
| $translationKeys[] = 'BotTracking_SiteWithoutDataOtherInstallMethods'; | |
| $translationKeys[] = 'BotTracking_SiteWithoutDataOtherInstallMethodsIntro'; | |
| $translationKeys[] = 'BotTracking_SiteWithoutDataInstallWithXRecommendation'; | |
| $translationKeys[] = 'BotTracking_SiteWithoutDataRecommendationText'; | |
| $translationKeys[] = 'General_ErrorRequest'; | |
| $translationKeys[] = 'General_Refresh'; | |
| $translationKeys[] = 'Mobile_NavigationBack'; | |
| $translationKeys[] = 'BotTracking_NoRecentAIBotRequests'; | |
| } | |
| /** | |
| * @param string[] $stylesheets | |
| * @return void | |
| */ | |
| public function getStylesheetFiles(&$stylesheets) | |
| { | |
| $stylesheets[] = "plugins/BotTracking/stylesheets/BotTracking.less"; | |
| } | |
| } | |