BloomFeed Bash Script Upgrade v0.2
This commit is contained in:
@@ -30,14 +30,6 @@ DB_PASSWORD=
|
|||||||
# Utilisé par docker-compose pour initialiser MariaDB (doit correspondre à DB_PASSWORD ci-dessus)
|
# Utilisé par docker-compose pour initialiser MariaDB (doit correspondre à DB_PASSWORD ci-dessus)
|
||||||
DB_ROOT_PASSWORD=
|
DB_ROOT_PASSWORD=
|
||||||
|
|
||||||
# Catalogue central BloomFluxDB (lecture seule)
|
|
||||||
BLOOMFLUX_DB_HOST=163.5.159.95
|
|
||||||
BLOOMFLUX_DB_PORT=3306
|
|
||||||
BLOOMFLUX_DB_DATABASE=bloomfluxdb
|
|
||||||
BLOOMFLUX_DB_USERNAME=bloomflux_reader
|
|
||||||
BLOOMFLUX_DB_PASSWORD=BloomFlux_Public_Read_2026
|
|
||||||
BLOOMFLUX_DB_TIMEOUT=4
|
|
||||||
|
|
||||||
SESSION_DRIVER=database
|
SESSION_DRIVER=database
|
||||||
SESSION_LIFETIME=120
|
SESSION_LIFETIME=120
|
||||||
SESSION_ENCRYPT=false
|
SESSION_ENCRYPT=false
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ n'a qu'un seul compte propriétaire, créé une seule fois au premier lancement.
|
|||||||
- Lecture approfondie intégrée : extraction du contenu principal (via
|
- Lecture approfondie intégrée : extraction du contenu principal (via
|
||||||
[Readability](https://github.com/fivefilters/readability.php)) converti en Markdown, sans
|
[Readability](https://github.com/fivefilters/readability.php)) converti en Markdown, sans
|
||||||
quitter BloomFeed.
|
quitter BloomFeed.
|
||||||
- Catalogue de flux façon "market" alimenté par **BloomFluxDB** (base centrale en lecture seule),
|
- Catalogue de flux façon "market" : une sélection de flux embarquée avec l'application
|
||||||
avec cache local de secours si le serveur catalogue est injoignable.
|
([resources/data/bloomflux.json](resources/data/bloomflux.json)), à ajouter en un clic.
|
||||||
- Récupération périodique des flux via une tâche planifiée.
|
- Récupération périodique des flux via une tâche planifiée.
|
||||||
- Thème clair/sombre.
|
- Thème clair/sombre.
|
||||||
- Inscription fermée après la création du compte propriétaire — pas de SaaS ouvert.
|
- Inscription fermée après la création du compte propriétaire — pas de SaaS ouvert.
|
||||||
@@ -80,23 +80,19 @@ Pour désinstaller proprement (avec confirmation avant toute suppression de donn
|
|||||||
bash uninstall.sh
|
bash uninstall.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
## BloomFluxDB (catalogue central)
|
## Catalogue de flux (BloomFlux)
|
||||||
|
|
||||||
Les instances BloomFeed consultent en lecture seule une base MariaDB centrale contenant une
|
L'onglet **Catalogue** propose une sélection de flux pré-faits (actualités, tech, développement,
|
||||||
liste de flux pré-sélectionnés, affichée dans l'onglet **Catalogue**. La liste est mise en cache
|
IT/sysadmin, sécurité, sciences…) à ajouter en un clic. La liste vit dans
|
||||||
localement : si le serveur catalogue est injoignable, la dernière copie connue est servie, et
|
[resources/data/bloomflux.json](resources/data/bloomflux.json), versionnée avec le code : pour
|
||||||
elle se rafraîchit automatiquement à la prochaine consultation réussie.
|
l'enrichir, éditez le fichier et déployez — aucun service externe n'est nécessaire.
|
||||||
|
|
||||||
Le script de création (base, table, utilisateur `bloomflux_reader` en `SELECT` uniquement, et
|
Format d'une entrée :
|
||||||
liste de flux initiale) est dans [docs/bloomfluxdb-setup.sql](docs/bloomfluxdb-setup.sql) — à
|
|
||||||
exécuter sur le serveur catalogue :
|
|
||||||
|
|
||||||
```bash
|
```json
|
||||||
mysql -u root -p < docs/bloomfluxdb-setup.sql
|
{ "title": "Nom du flux", "url": "https://exemple.com/rss.xml", "category": "Tech", "lang": "fr", "description": "Courte description." }
|
||||||
```
|
```
|
||||||
|
|
||||||
La connexion se configure dans le `.env` de chaque instance via les variables `BLOOMFLUX_DB_*`.
|
|
||||||
|
|
||||||
## Licence
|
## Licence
|
||||||
|
|
||||||
MIT.
|
MIT.
|
||||||
|
|||||||
@@ -10,14 +10,10 @@ class CatalogController extends Controller
|
|||||||
{
|
{
|
||||||
public function index(Request $request, FluxCatalogService $catalog): View
|
public function index(Request $request, FluxCatalogService $catalog): View
|
||||||
{
|
{
|
||||||
$result = $catalog->getCatalog();
|
|
||||||
|
|
||||||
$subscribedUrls = $request->user()->feeds()->pluck('url')->all();
|
$subscribedUrls = $request->user()->feeds()->pluck('url')->all();
|
||||||
|
|
||||||
return view('catalog', [
|
return view('catalog', [
|
||||||
'feeds' => collect($result['feeds'])->groupBy('category'),
|
'feeds' => collect($catalog->getCatalog())->groupBy('category'),
|
||||||
'fromCache' => $result['fromCache'],
|
|
||||||
'updatedAt' => $result['updatedAt'],
|
|
||||||
'subscribedUrls' => $subscribedUrls,
|
'subscribedUrls' => $subscribedUrls,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,53 +2,28 @@
|
|||||||
|
|
||||||
namespace App\Services;
|
namespace App\Services;
|
||||||
|
|
||||||
use Illuminate\Support\Carbon;
|
|
||||||
use Illuminate\Support\Facades\Cache;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
|
||||||
class FluxCatalogService
|
class FluxCatalogService
|
||||||
{
|
{
|
||||||
private const CACHE_KEY = 'bloomflux.catalog';
|
|
||||||
|
|
||||||
private const CACHE_TIME_KEY = 'bloomflux.catalog_updated_at';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retourne le catalogue BloomFluxDB, en le rafraîchissant depuis le serveur
|
* Retourne le catalogue de flux embarqué (resources/data/bloomflux.json).
|
||||||
* distant quand il est joignable, sinon en servant la dernière copie en cache.
|
* La liste est versionnée avec le code : la mettre à jour = éditer le fichier et commit.
|
||||||
*
|
*
|
||||||
* @return array{feeds: list<array{title: string, url: string, category: string, lang: string, description: ?string}>, fromCache: bool, updatedAt: ?Carbon}
|
* @return list<array{title: string, url: string, category: string, lang: string, description: ?string}>
|
||||||
*/
|
*/
|
||||||
public function getCatalog(): array
|
public function getCatalog(): array
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$rows = DB::connection('bloomflux')
|
$raw = file_get_contents(resource_path('data/bloomflux.json'));
|
||||||
->table('feeds')
|
$data = json_decode($raw, true, 512, JSON_THROW_ON_ERROR);
|
||||||
->where('is_active', 1)
|
|
||||||
->orderBy('category')
|
|
||||||
->orderBy('title')
|
|
||||||
->get(['title', 'url', 'category', 'lang', 'description'])
|
|
||||||
->map(fn ($row) => (array) $row)
|
|
||||||
->all();
|
|
||||||
|
|
||||||
Cache::forever(self::CACHE_KEY, $rows);
|
return $data['feeds'] ?? [];
|
||||||
Cache::forever(self::CACHE_TIME_KEY, now()->toIso8601String());
|
|
||||||
|
|
||||||
return ['feeds' => $rows, 'fromCache' => false, 'updatedAt' => now()];
|
|
||||||
} catch (Throwable $e) {
|
} catch (Throwable $e) {
|
||||||
Log::warning('BloomFluxDB unreachable, serving cached catalog', [
|
Log::warning('Catalogue bloomflux.json illisible', ['error' => $e->getMessage()]);
|
||||||
'error' => $e->getMessage(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
$cached = Cache::get(self::CACHE_KEY, []);
|
return [];
|
||||||
$updatedAt = Cache::get(self::CACHE_TIME_KEY);
|
|
||||||
|
|
||||||
return [
|
|
||||||
'feeds' => $cached,
|
|
||||||
'fromCache' => true,
|
|
||||||
'updatedAt' => $updatedAt ? Carbon::parse($updatedAt) : null,
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,24 +64,6 @@ return [
|
|||||||
]) : [],
|
]) : [],
|
||||||
],
|
],
|
||||||
|
|
||||||
// Catalogue central BloomFluxDB (lecture seule, distant) — timeout court
|
|
||||||
// pour ne jamais bloquer la page si le serveur catalogue est injoignable.
|
|
||||||
'bloomflux' => [
|
|
||||||
'driver' => 'mysql',
|
|
||||||
'host' => env('BLOOMFLUX_DB_HOST', '163.5.159.95'),
|
|
||||||
'port' => env('BLOOMFLUX_DB_PORT', '3306'),
|
|
||||||
'database' => env('BLOOMFLUX_DB_DATABASE', 'bloomfluxdb'),
|
|
||||||
'username' => env('BLOOMFLUX_DB_USERNAME', 'bloomflux_reader'),
|
|
||||||
'password' => env('BLOOMFLUX_DB_PASSWORD', 'BloomFlux_Public_Read_2026'),
|
|
||||||
'charset' => 'utf8mb4',
|
|
||||||
'collation' => 'utf8mb4_unicode_ci',
|
|
||||||
'prefix' => '',
|
|
||||||
'strict' => true,
|
|
||||||
'options' => extension_loaded('pdo_mysql') ? [
|
|
||||||
\PDO::ATTR_TIMEOUT => (int) env('BLOOMFLUX_DB_TIMEOUT', 4),
|
|
||||||
] : [],
|
|
||||||
],
|
|
||||||
|
|
||||||
'mariadb' => [
|
'mariadb' => [
|
||||||
'driver' => 'mariadb',
|
'driver' => 'mariadb',
|
||||||
'url' => env('DB_URL'),
|
'url' => env('DB_URL'),
|
||||||
|
|||||||
@@ -1,77 +0,0 @@
|
|||||||
/* ============================================================ */
|
|
||||||
/* BloomFluxDB — catalogue central de flux RSS pour les instances BloomFeed */
|
|
||||||
/* À exécuter sur le serveur catalogue (163.5.159.95), en root MariaDB/MySQL : */
|
|
||||||
/* mysql -u root -p < bloomfluxdb-setup.sql */
|
|
||||||
/* Prérequis réseau : MariaDB doit écouter sur l'extérieur */
|
|
||||||
/* (bind-address = 0.0.0.0 dans /etc/mysql/mariadb.conf.d/50-server.cnf, */
|
|
||||||
/* puis systemctl restart mariadb) et le port 3306 doit être ouvert. */
|
|
||||||
/* ============================================================ */
|
|
||||||
|
|
||||||
CREATE DATABASE IF NOT EXISTS bloomfluxdb
|
|
||||||
CHARACTER SET utf8mb4
|
|
||||||
COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
USE bloomfluxdb;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS feeds (
|
|
||||||
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
title VARCHAR(255) NOT NULL,
|
|
||||||
url VARCHAR(2048) NOT NULL,
|
|
||||||
category VARCHAR(100) NOT NULL DEFAULT 'Divers',
|
|
||||||
lang CHAR(2) NOT NULL DEFAULT 'fr',
|
|
||||||
description VARCHAR(500) NULL,
|
|
||||||
is_active TINYINT(1) NOT NULL DEFAULT 1,
|
|
||||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
||||||
UNIQUE KEY uq_feeds_url (url(500)),
|
|
||||||
KEY idx_feeds_category (category),
|
|
||||||
KEY idx_feeds_active (is_active)
|
|
||||||
) ENGINE = InnoDB;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/* Utilisateur en LECTURE SEULE pour les instances BloomFeed ('%' = accessible */
|
|
||||||
/* depuis n'importe quelle IP). Changez le mot de passe si vous voulez restreindre, */
|
|
||||||
/* et reportez-le dans le .env des instances (BLOOMFLUX_DB_PASSWORD). */
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
CREATE USER IF NOT EXISTS 'bloomflux_reader'@'%' IDENTIFIED BY 'BloomFlux_Public_Read_2026';
|
|
||||||
GRANT SELECT ON bloomfluxdb.feeds TO 'bloomflux_reader'@'%';
|
|
||||||
FLUSH PRIVILEGES;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/* Liste de flux pré-faite (extensible à volonté : INSERT depuis root/localhost) */
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
INSERT IGNORE INTO feeds (title, url, category, lang, description) VALUES
|
|
||||||
/* Actualités générales */
|
|
||||||
('Le Monde', 'https://www.lemonde.fr/rss/une.xml', 'Actualités', 'fr', 'La une du journal Le Monde.'),
|
|
||||||
('France Info', 'https://www.franceinfo.fr/titres.rss', 'Actualités', 'fr', 'Les titres de France Info en continu.'),
|
|
||||||
('Courrier International', 'https://www.courrierinternational.com/feed/all/rss.xml', 'Actualités', 'fr', 'L''actualité internationale vue par la presse étrangère.'),
|
|
||||||
('BBC News', 'https://feeds.bbci.co.uk/news/rss.xml', 'Actualités', 'en', 'Fil d''actualité mondial de la BBC.'),
|
|
||||||
/* Tech & informatique */
|
|
||||||
('Korben', 'https://korben.info/feed', 'Tech', 'fr', 'Actu tech, astuces et bidouilles.'),
|
|
||||||
('Numerama', 'https://www.numerama.com/feed/', 'Tech', 'fr', 'Société numérique, tech et sciences.'),
|
|
||||||
('Next', 'https://next.ink/feed/', 'Tech', 'fr', 'Actualité informatique et numérique de fond.'),
|
|
||||||
('Journal du hacker', 'https://www.journalduhacker.net/rss', 'Tech', 'fr', 'Liens tech partagés par la communauté francophone.'),
|
|
||||||
('Ars Technica', 'https://feeds.arstechnica.com/arstechnica/index', 'Tech', 'en', 'Analyses tech approfondies.'),
|
|
||||||
('Hacker News', 'https://news.ycombinator.com/rss', 'Tech', 'en', 'Les liens les plus discutés de la communauté HN.'),
|
|
||||||
('The Verge', 'https://www.theverge.com/rss/index.xml', 'Tech', 'en', 'Tech, science et culture numérique.'),
|
|
||||||
/* Linux & open source */
|
|
||||||
('Phoronix', 'https://www.phoronix.com/rss.php', 'Open source', 'en', 'Linux, matériel et open source.'),
|
|
||||||
('LinuxFr', 'https://linuxfr.org/news.atom', 'Open source', 'fr', 'L''actualité du logiciel libre en français.'),
|
|
||||||
('It''s FOSS', 'https://itsfoss.com/rss/', 'Open source', 'en', 'Tutoriels et actus Linux/open source.'),
|
|
||||||
/* Sécurité */
|
|
||||||
('CERT-FR', 'https://www.cert.ssi.gouv.fr/feed/', 'Sécurité', 'fr', 'Alertes et avis de sécurité de l''ANSSI.'),
|
|
||||||
('Krebs on Security', 'https://krebsonsecurity.com/feed/', 'Sécurité', 'en', 'Investigations cybersécurité de Brian Krebs.'),
|
|
||||||
('Zataz', 'https://www.zataz.com/feed/', 'Sécurité', 'fr', 'Actualité cybersécurité et fuites de données.'),
|
|
||||||
/* Développement */
|
|
||||||
('Dev.to', 'https://dev.to/feed', 'Développement', 'en', 'Articles de la communauté dev.to.'),
|
|
||||||
('GitHub Blog', 'https://github.blog/feed/', 'Développement', 'en', 'Nouveautés et ingénierie GitHub.'),
|
|
||||||
('Laravel News', 'https://feed.laravel-news.com/', 'Développement', 'en', 'L''écosystème Laravel au quotidien.'),
|
|
||||||
/* Sciences */
|
|
||||||
('Futura Sciences', 'https://www.futura-sciences.com/rss/actualites.xml', 'Sciences', 'fr', 'Actualités scientifiques tous domaines.'),
|
|
||||||
('CNRS Le Journal', 'https://lejournal.cnrs.fr/rss', 'Sciences', 'fr', 'Le journal de la recherche française.'),
|
|
||||||
/* Jeux vidéo */
|
|
||||||
('Gamekult', 'https://www.gamekult.com/feed.xml', 'Jeux vidéo', 'fr', 'Actualité et critiques jeux vidéo.'),
|
|
||||||
('Rock Paper Shotgun', 'https://www.rockpapershotgun.com/feed', 'Jeux vidéo', 'en', 'Jeux PC, tests et actus.');
|
|
||||||
|
|
||||||
/* Vérification rapide */
|
|
||||||
SELECT category, COUNT(*) AS nb FROM feeds GROUP BY category ORDER BY category;
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 213 KiB After Width: | Height: | Size: 330 KiB |
@@ -1008,17 +1008,6 @@ h1, h2, h3 {
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cache-notice {
|
|
||||||
background: var(--accent-soft);
|
|
||||||
border: 1px solid var(--accent-soft-strong);
|
|
||||||
border-radius: var(--radius-sm);
|
|
||||||
padding: 12px 16px;
|
|
||||||
font-size: var(--font-sm);
|
|
||||||
font-weight: 600;
|
|
||||||
color: var(--accent-strong);
|
|
||||||
animation: fade-up 350ms var(--ease-out) both;
|
|
||||||
}
|
|
||||||
|
|
||||||
.market-search {
|
.market-search {
|
||||||
font-size: var(--font-base);
|
font-size: var(--font-base);
|
||||||
padding: 13px 18px;
|
padding: 13px 18px;
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"updated_at": "2026-07-03",
|
||||||
|
"feeds": [
|
||||||
|
{ "title": "Le Monde", "url": "https://www.lemonde.fr/rss/une.xml", "category": "Actualités", "lang": "fr", "description": "La une du journal Le Monde." },
|
||||||
|
{ "title": "France Info", "url": "https://www.franceinfo.fr/titres.rss", "category": "Actualités", "lang": "fr", "description": "Les titres de France Info en continu." },
|
||||||
|
{ "title": "Courrier International", "url": "https://www.courrierinternational.com/feed/all/rss.xml", "category": "Actualités", "lang": "fr", "description": "L'actualité internationale vue par la presse étrangère." },
|
||||||
|
{ "title": "BBC News", "url": "https://feeds.bbci.co.uk/news/rss.xml", "category": "Actualités", "lang": "en", "description": "Fil d'actualité mondial de la BBC." },
|
||||||
|
|
||||||
|
{ "title": "Korben", "url": "https://korben.info/feed", "category": "Tech", "lang": "fr", "description": "Actu tech, astuces et bidouilles." },
|
||||||
|
{ "title": "Numerama", "url": "https://www.numerama.com/feed/", "category": "Tech", "lang": "fr", "description": "Société numérique, tech et sciences." },
|
||||||
|
{ "title": "Next", "url": "https://next.ink/feed/", "category": "Tech", "lang": "fr", "description": "Actualité informatique et numérique de fond." },
|
||||||
|
{ "title": "Journal du hacker", "url": "https://www.journalduhacker.net/rss", "category": "Tech", "lang": "fr", "description": "Liens tech partagés par la communauté francophone." },
|
||||||
|
{ "title": "Ars Technica", "url": "https://feeds.arstechnica.com/arstechnica/index", "category": "Tech", "lang": "en", "description": "Analyses tech approfondies." },
|
||||||
|
{ "title": "Hacker News", "url": "https://news.ycombinator.com/rss", "category": "Tech", "lang": "en", "description": "Les liens les plus discutés de la communauté HN." },
|
||||||
|
{ "title": "The Verge", "url": "https://www.theverge.com/rss/index.xml", "category": "Tech", "lang": "en", "description": "Tech, science et culture numérique." },
|
||||||
|
|
||||||
|
{ "title": "Dev.to", "url": "https://dev.to/feed", "category": "Développement", "lang": "en", "description": "Articles de la communauté dev.to." },
|
||||||
|
{ "title": "GitHub Blog", "url": "https://github.blog/feed/", "category": "Développement", "lang": "en", "description": "Nouveautés et ingénierie GitHub." },
|
||||||
|
{ "title": "Laravel News", "url": "https://feed.laravel-news.com/", "category": "Développement", "lang": "en", "description": "L'écosystème Laravel au quotidien." },
|
||||||
|
{ "title": "Stack Overflow Blog", "url": "https://stackoverflow.blog/feed/", "category": "Développement", "lang": "en", "description": "Le blog officiel de Stack Overflow." },
|
||||||
|
{ "title": "freeCodeCamp", "url": "https://www.freecodecamp.org/news/rss/", "category": "Développement", "lang": "en", "description": "Tutoriels et articles pour apprendre à coder." },
|
||||||
|
{ "title": "CSS-Tricks", "url": "https://css-tricks.com/feed/", "category": "Développement", "lang": "en", "description": "Tout sur le CSS et le front-end." },
|
||||||
|
{ "title": "Smashing Magazine", "url": "https://www.smashingmagazine.com/feed/", "category": "Développement", "lang": "en", "description": "Design et développement web." },
|
||||||
|
{ "title": "Développez.com", "url": "https://www.developpez.com/index/rss", "category": "Développement", "lang": "fr", "description": "L'actualité des développeurs francophones." },
|
||||||
|
{ "title": "Human Coders News", "url": "https://news.humancoders.com/items/feed", "category": "Développement", "lang": "fr", "description": "Veille dev partagée par la communauté francophone." },
|
||||||
|
|
||||||
|
{ "title": "IT-Connect", "url": "https://www.it-connect.fr/feed/", "category": "IT / Sysadmin", "lang": "fr", "description": "Tutoriels et actus sysadmin, Windows et Linux." },
|
||||||
|
{ "title": "ZDNet France", "url": "https://www.zdnet.fr/feeds/rss/actualites/", "category": "IT / Sysadmin", "lang": "fr", "description": "L'actualité IT pour les professionnels." },
|
||||||
|
{ "title": "Silicon", "url": "https://www.silicon.fr/feed", "category": "IT / Sysadmin", "lang": "fr", "description": "L'actualité IT et cloud pour les DSI." },
|
||||||
|
{ "title": "The Register", "url": "https://www.theregister.com/headlines.atom", "category": "IT / Sysadmin", "lang": "en", "description": "L'IT sans langue de bois." },
|
||||||
|
{ "title": "ServeTheHome", "url": "https://www.servethehome.com/feed/", "category": "IT / Sysadmin", "lang": "en", "description": "Serveurs, stockage, réseau et homelab." },
|
||||||
|
|
||||||
|
{ "title": "Phoronix", "url": "https://www.phoronix.com/rss.php", "category": "Open source", "lang": "en", "description": "Linux, matériel et open source." },
|
||||||
|
{ "title": "LinuxFr", "url": "https://linuxfr.org/news.atom", "category": "Open source", "lang": "fr", "description": "L'actualité du logiciel libre en français." },
|
||||||
|
{ "title": "It's FOSS", "url": "https://itsfoss.com/rss/", "category": "Open source", "lang": "en", "description": "Tutoriels et actus Linux/open source." },
|
||||||
|
|
||||||
|
{ "title": "CERT-FR", "url": "https://www.cert.ssi.gouv.fr/feed/", "category": "Sécurité", "lang": "fr", "description": "Alertes et avis de sécurité de l'ANSSI." },
|
||||||
|
{ "title": "Krebs on Security", "url": "https://krebsonsecurity.com/feed/", "category": "Sécurité", "lang": "en", "description": "Investigations cybersécurité de Brian Krebs." },
|
||||||
|
{ "title": "Zataz", "url": "https://www.zataz.com/feed/", "category": "Sécurité", "lang": "fr", "description": "Actualité cybersécurité et fuites de données." },
|
||||||
|
|
||||||
|
{ "title": "Futura Sciences", "url": "https://www.futura-sciences.com/rss/actualites.xml", "category": "Sciences", "lang": "fr", "description": "Actualités scientifiques tous domaines." },
|
||||||
|
{ "title": "CNRS Le Journal", "url": "https://lejournal.cnrs.fr/rss", "category": "Sciences", "lang": "fr", "description": "Le journal de la recherche française." },
|
||||||
|
|
||||||
|
{ "title": "Gamekult", "url": "https://www.gamekult.com/feed.xml", "category": "Jeux vidéo", "lang": "fr", "description": "Actualité et critiques jeux vidéo." },
|
||||||
|
{ "title": "Rock Paper Shotgun", "url": "https://www.rockpapershotgun.com/feed", "category": "Jeux vidéo", "lang": "en", "description": "Jeux PC, tests et actus." }
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -10,26 +10,14 @@
|
|||||||
<div>
|
<div>
|
||||||
<h2 style="margin:0;">Catalogue de flux</h2>
|
<h2 style="margin:0;">Catalogue de flux</h2>
|
||||||
<p class="text-muted text-sm" style="margin:4px 0 0;">
|
<p class="text-muted text-sm" style="margin:4px 0 0;">
|
||||||
Une sélection de flux RSS maintenue par BloomFluxDB — ajoutez-les à votre collection en un clic.
|
Une sélection de flux RSS livrée avec BloomFeed — ajoutez-les à votre collection en un clic.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if ($fromCache)
|
|
||||||
<div class="cache-notice">
|
|
||||||
⚠ Serveur catalogue injoignable — liste servie depuis le cache local
|
|
||||||
@if ($updatedAt)
|
|
||||||
(mise à jour {{ $updatedAt->diffForHumans() }})
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
@if ($feeds->isEmpty())
|
@if ($feeds->isEmpty())
|
||||||
<div class="card empty-state">
|
<div class="card empty-state">
|
||||||
Le catalogue est vide pour le moment.
|
Le catalogue est vide pour le moment.
|
||||||
@if ($fromCache)
|
|
||||||
Il sera récupéré automatiquement dès que le serveur catalogue sera joignable.
|
|
||||||
@endif
|
|
||||||
</div>
|
</div>
|
||||||
@else
|
@else
|
||||||
<input type="search" id="market-search" class="form-input market-search" placeholder="Rechercher un flux… (nom, description, catégorie)">
|
<input type="search" id="market-search" class="form-input market-search" placeholder="Rechercher un flux… (nom, description, catégorie)">
|
||||||
|
|||||||
Reference in New Issue
Block a user