mirror of
https://github.com/linuxserver/Heimdall.git
synced 2026-02-20 02:16:32 +08:00
- Add SearXNG entry to searchproviders.yaml - Add searx_url setting for user-configurable instance URL - Modify Search::providerDetails() to inject user's SearXNG URL - Add English translations for new setting and provider SearXNG is a self-hosted metasearch engine, so unlike other providers the URL cannot be hardcoded. This implementation allows users to configure their instance URL in settings, which is then dynamically injected when performing searches.
163 lines
5.4 KiB
PHP
163 lines
5.4 KiB
PHP
<?php
|
|
|
|
namespace App;
|
|
|
|
use Illuminate\Support\Collection;
|
|
use Illuminate\Support\Facades\Request as Input;
|
|
use Yaml;
|
|
|
|
abstract class Search
|
|
{
|
|
/**
|
|
* List of all search providers
|
|
*
|
|
* @return Collection
|
|
*/
|
|
public static function providers(): Collection
|
|
{
|
|
$providers = self::standardProviders();
|
|
$providers = $providers + self::appProviders();
|
|
|
|
return collect($providers);
|
|
}
|
|
|
|
/**
|
|
* Gets details for a single provider
|
|
*
|
|
* @return false|object
|
|
*/
|
|
public static function providerDetails($provider)
|
|
{
|
|
$providers = self::providers();
|
|
if (! isset($providers[$provider])) {
|
|
return false;
|
|
}
|
|
|
|
$details = (object) $providers[$provider] ?? false;
|
|
|
|
// For SearXNG, use user-configured URL
|
|
if ($provider === 'searx') {
|
|
$searxUrl = Setting::fetch('searx_url');
|
|
if (!empty($searxUrl)) {
|
|
// Ensure URL doesn't have trailing slash
|
|
$searxUrl = rtrim($searxUrl, '/');
|
|
$details->url = $searxUrl . '/search';
|
|
$details->autocomplete = $searxUrl . '/autocompleter?format=x-suggestions&q={query}';
|
|
}
|
|
}
|
|
|
|
return $details;
|
|
}
|
|
|
|
/**
|
|
* Array of the standard providers
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function standardProviders(): array
|
|
{
|
|
// $providers = json_decode(file_get_contents(storage_path('app/searchproviders.json')));
|
|
// print_r($providers);
|
|
$providers = Yaml::parseFile(storage_path('app/searchproviders.yaml'));
|
|
$all = [];
|
|
foreach ($providers as $key => $provider) {
|
|
$all[$key] = $provider;
|
|
$all[$key]['type'] = 'standard';
|
|
}
|
|
|
|
return $all;
|
|
}
|
|
|
|
/**
|
|
* Loops through users apps to see if app is a search provider, might be worth
|
|
* looking into caching this at some point
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function appProviders(): array
|
|
{
|
|
$providers = [];
|
|
$userapps = Item::all();
|
|
foreach ($userapps as $app) {
|
|
if (empty($app->class)) {
|
|
continue;
|
|
}
|
|
if (($provider = Item::isSearchProvider($app->class)) !== false) {
|
|
$name = Item::nameFromClass($app->class);
|
|
$providers[$app->id] = [
|
|
'id' => $app->id,
|
|
'type' => $provider->type,
|
|
'class' => $app->class,
|
|
'url' => $app->url,
|
|
'name' => $app->title,
|
|
'colour' => $app->colour,
|
|
'icon' => $app->icon,
|
|
'description' => $app->description,
|
|
];
|
|
}
|
|
}
|
|
|
|
return $providers;
|
|
}
|
|
|
|
/**
|
|
* Outputs the search form
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function form(): string
|
|
{
|
|
$output = '';
|
|
$homepage_search = Setting::fetch('homepage_search');
|
|
$search_provider = Setting::where('key', '=', 'search_provider')->first();
|
|
$user_search_provider = Setting::fetch('search_provider');
|
|
//die(print_r($search_provider));
|
|
|
|
//die(var_dump($user_search_provider));
|
|
// return early if search isn't applicable
|
|
if ((bool) $homepage_search !== true) {
|
|
return $output;
|
|
}
|
|
$user_search_provider = Input::get('p') ?? $user_search_provider ?? 'none';
|
|
|
|
if ((bool) $search_provider) {
|
|
if ((bool) $user_search_provider) {
|
|
$name = 'app.options.'.$user_search_provider;
|
|
$provider = self::providerDetails($user_search_provider);
|
|
$providers = self::providers();
|
|
$providerCount = count($providers);
|
|
|
|
// If there's only one provider, use its key instead of the user's setting
|
|
if ($providerCount === 1) {
|
|
$user_search_provider = $providers->keys()->first();
|
|
}
|
|
|
|
$output .= '<div class="searchform">';
|
|
$output .= '<form action="'.url('search').'"'.getLinkTargetAttribute().' method="get">';
|
|
$output .= '<div id="search-container" class="input-container">';
|
|
|
|
// Only show dropdown if there's more than one provider
|
|
if ($providerCount > 1) {
|
|
$output .= '<select name="provider">';
|
|
foreach ($providers as $key => $searchprovider) {
|
|
$selected = ((string) $key === (string) $user_search_provider) ? ' selected="selected"' : '';
|
|
$output .= '<option value="'.$key.'"'.$selected.'>'.$searchprovider['name'].'</option>';
|
|
}
|
|
$output .= '</select>';
|
|
} else {
|
|
// Hidden input for single provider
|
|
$output .= '<input type="hidden" name="provider" value="'.$user_search_provider.'" />';
|
|
}
|
|
|
|
$output .= '<input type="text" name="q" value="'.e(Input::get('q') ?? '').'" class="homesearch" autofocus placeholder="'.__('app.settings.search').'..." />';
|
|
$output .= '<button type="submit">'.ucwords(__('app.settings.search')).'</button>';
|
|
$output .= '</div>';
|
|
$output .= '</form>';
|
|
$output .= '</div>';
|
|
}
|
|
}
|
|
|
|
return $output;
|
|
}
|
|
}
|