diff --git a/src/Entity/StationMedia.php b/src/Entity/StationMedia.php index f4476ed96..738dd8c7d 100644 --- a/src/Entity/StationMedia.php +++ b/src/Entity/StationMedia.php @@ -192,6 +192,15 @@ class StationMedia implements ] protected int $art_updated_at = 0; + #[ + OA\Property( + description: "The latest time (UNIX timestamp) when the search record for this entry was updated.", + example: OpenApi::SAMPLE_TIMESTAMP + ), + ORM\Column + ] + protected int $search_updated_at = 0; + /** @var Collection */ #[ OA\Property(type: "array", items: new OA\Items()), diff --git a/src/Environment.php b/src/Environment.php index d580ddbbe..5edfa12f8 100644 --- a/src/Environment.php +++ b/src/Environment.php @@ -54,6 +54,8 @@ final class Environment public const ENABLE_WEB_UPDATER = 'ENABLE_WEB_UPDATER'; + public const MEILI_MASTER_KEY = 'MEILI_MASTER_KEY'; + // Database and Cache Configuration Variables public const DB_HOST = 'MYSQL_HOST'; public const DB_PORT = 'MYSQL_PORT'; @@ -90,6 +92,8 @@ final class Environment self::PROFILING_EXTENSION_HTTP_KEY => 'dev', self::ENABLE_WEB_UPDATER => false, + + self::MEILI_MASTER_KEY => 'azur4c457', ]; public function __construct(array $elements = []) @@ -370,6 +374,11 @@ final class Environment return $this->isDocker() && self::envToBool($this->data[self::ENABLE_WEB_UPDATER] ?? false); } + public function getMeiliMasterKey(): string + { + return $this->data[self::MEILI_MASTER_KEY] ?? $this->defaults[self::MEILI_MASTER_KEY]; + } + public static function getDefaultsForEnvironment(Environment $existingEnv): self { return new self([ diff --git a/src/Message/AddMediaToSearchIndexMessage.php b/src/Message/AddMediaToSearchIndexMessage.php new file mode 100644 index 000000000..989295033 --- /dev/null +++ b/src/Message/AddMediaToSearchIndexMessage.php @@ -0,0 +1,33 @@ + $this->storage_location_id, + 'media' => $this->media, + ], JSON_THROW_ON_ERROR) + ); + + return 'AddMediaToSearchIndexMessage_' . $messageHash; + } + + public function getQueue(): string + { + return QueueManagerInterface::QUEUE_MEDIA; + } +} diff --git a/src/Service/Meilisearch.php b/src/Service/Meilisearch.php new file mode 100644 index 000000000..39d8d9973 --- /dev/null +++ b/src/Service/Meilisearch.php @@ -0,0 +1,95 @@ +environment->isDocker(); + } + + public function getClient(): Client + { + static $client; + + if (!$this->isSupported()) { + throw new \RuntimeException('This feature is not supported on this installation.'); + } + + if (!isset($client)) { + $psrFactory = new HttpFactory(); + $client = new Client( + 'http://localhost:6070', + $this->environment->getMeiliMasterKey(), + $this->httpClient, + requestFactory: $psrFactory, + streamFactory: $psrFactory + ); + } + + return $client; + } + + public function setupIndex(StorageLocation $storageLocation): void + { + $indexSettings = [ + 'primaryKey' => 'id', + 'filterableAttributes' => [ + 'playlists', + 'is_requestable', + 'is_on_demand' + ], + 'sortableAttributes' => [ + 'path', + 'mtime', + 'length', + 'title', + 'artist', + 'album', + 'genre', + 'isrc', + ], + ]; + + foreach($this->customFieldRepo->getFieldIds() as $fieldId => $fieldShortCode) { + $indexSettings['sortableAttributes'][] = 'custom_field_'.$fieldId; + } + + $client = $this->getClient(); + $client->updateIndex( + self::getIndexId($storageLocation), + $indexSettings + ); + } + + public function addToIndex( + StorageLocation $storageLocation, + array $ids + ): void { + + } + + public static function getIndexId(StorageLocation $storageLocation): string + { + return 'media_'.$storageLocation->getIdRequired(); + } +} diff --git a/src/Service/ServiceControl.php b/src/Service/ServiceControl.php index f4287585e..2fdaf9e6e 100644 --- a/src/Service/ServiceControl.php +++ b/src/Service/ServiceControl.php @@ -84,6 +84,7 @@ final class ServiceControl 'redis' => __('Cache'), 'sftpgo' => __('SFTP service'), 'centrifugo' => __('Live Now Playing updates'), + 'meilisearch' => __('Meilisearch'), ]; if (!$this->centrifugo->isSupported()) {