BloomFeed Upgrade v0.21
This commit is contained in:
@@ -2,28 +2,129 @@
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Setting;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Throwable;
|
||||
|
||||
class FluxCatalogService
|
||||
{
|
||||
/**
|
||||
* Retourne le catalogue de flux embarqué (resources/data/bloomflux.json).
|
||||
* La liste est versionnée avec le code : la mettre à jour = éditer le fichier et commit.
|
||||
* Retourne le catalogue complet : le fichier embarqué (resources/data/bloomflux.json)
|
||||
* fusionné avec les sources externes configurées (URLs de fichiers bloomflux.json
|
||||
* hébergés dans d'autres dépôts). Dédoublonné par URL de flux, l'embarqué gagne.
|
||||
*
|
||||
* @return list<array{title: string, url: string, category: string, lang: string, description: ?string}>
|
||||
*/
|
||||
public function getCatalog(): array
|
||||
{
|
||||
$feeds = $this->loadEmbedded();
|
||||
|
||||
foreach (Setting::catalogSources() as $sourceUrl) {
|
||||
$feeds = array_merge($feeds, $this->loadRemoteSource($sourceUrl));
|
||||
}
|
||||
|
||||
$seen = [];
|
||||
$unique = [];
|
||||
|
||||
foreach ($feeds as $feed) {
|
||||
if (! isset($seen[$feed['url']])) {
|
||||
$seen[$feed['url']] = true;
|
||||
$unique[] = $feed;
|
||||
}
|
||||
}
|
||||
|
||||
return $unique;
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide une source distante et retourne le nombre de flux qu'elle contient,
|
||||
* ou null si elle est injoignable ou invalide.
|
||||
*/
|
||||
public function validateSource(string $sourceUrl): ?int
|
||||
{
|
||||
$feeds = $this->fetchSource($sourceUrl);
|
||||
|
||||
return $feeds === null ? null : count($feeds);
|
||||
}
|
||||
|
||||
private function loadEmbedded(): array
|
||||
{
|
||||
try {
|
||||
$raw = file_get_contents(resource_path('data/bloomflux.json'));
|
||||
$data = json_decode($raw, true, 512, JSON_THROW_ON_ERROR);
|
||||
|
||||
return $data['feeds'] ?? [];
|
||||
return $this->normalize($data['feeds'] ?? []);
|
||||
} catch (Throwable $e) {
|
||||
Log::warning('Catalogue bloomflux.json illisible', ['error' => $e->getMessage()]);
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Charge une source externe : réseau si joignable (et met le cache à jour),
|
||||
* sinon dernière copie en cache.
|
||||
*/
|
||||
private function loadRemoteSource(string $sourceUrl): array
|
||||
{
|
||||
$cacheKey = 'bloomflux.source.'.md5($sourceUrl);
|
||||
|
||||
$feeds = $this->fetchSource($sourceUrl);
|
||||
|
||||
if ($feeds !== null) {
|
||||
Cache::forever($cacheKey, $feeds);
|
||||
|
||||
return $feeds;
|
||||
}
|
||||
|
||||
Log::warning('Source de catalogue injoignable, utilisation du cache', ['source' => $sourceUrl]);
|
||||
|
||||
return Cache::get($cacheKey, []);
|
||||
}
|
||||
|
||||
private function fetchSource(string $sourceUrl): ?array
|
||||
{
|
||||
try {
|
||||
$response = Http::timeout(6)
|
||||
->withHeaders(['User-Agent' => 'BloomFeed/1.0'])
|
||||
->get($sourceUrl);
|
||||
|
||||
if ($response->failed()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$data = json_decode($response->body(), true, 512, JSON_THROW_ON_ERROR);
|
||||
|
||||
if (! isset($data['feeds']) || ! is_array($data['feeds'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->normalize($data['feeds']);
|
||||
} catch (Throwable) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private function normalize(array $feeds): array
|
||||
{
|
||||
$clean = [];
|
||||
|
||||
foreach ($feeds as $feed) {
|
||||
if (! is_array($feed) || empty($feed['title']) || empty($feed['url'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$clean[] = [
|
||||
'title' => (string) $feed['title'],
|
||||
'url' => (string) $feed['url'],
|
||||
'category' => (string) ($feed['category'] ?? 'Divers'),
|
||||
'lang' => strtolower((string) ($feed['lang'] ?? 'en')),
|
||||
'description' => isset($feed['description']) ? (string) $feed['description'] : null,
|
||||
];
|
||||
}
|
||||
|
||||
return $clean;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user