Modification des entrées du site. Il est passé sur wordpress. Problème pour l'agenda, c'est que ics -> tranformé en rss
This commit is contained in:
+7
-88
@@ -2,15 +2,9 @@
|
||||
/**
|
||||
* Fonctions communes aux 3 flux RSS (actualites.php, agenda.php, facebook.php).
|
||||
*
|
||||
* Le site www.silly.be est derriere Cloudflare : son WAF bloque les
|
||||
* requetes dont l'empreinte TLS/HTTP2 n'est pas "navigateur" (urllib
|
||||
* Python passe, par ex., mais renvoie un corps vide). L'extension
|
||||
* curl de PHP (libcurl) reproduit la meme empreinte que le binaire
|
||||
* curl en ligne de commande, donc ca passe nativement.
|
||||
*
|
||||
* Autre contrainte observee sur l'API : b_size doit valoir exactement
|
||||
* 20 (toute autre valeur renvoie un corps vide) ; la pagination se
|
||||
* fait donc via b_start par pas de 20.
|
||||
* Depuis le 14/10/2026, www.silly.be tourne sous WordPress (l'ancienne API
|
||||
* JSON Plone / imio.smartweb n'existe plus). Les sources sont desormais :
|
||||
* le flux RSS WordPress natif (actualites) et l'iCal officiel (agenda).
|
||||
*/
|
||||
|
||||
const USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36';
|
||||
@@ -21,13 +15,13 @@ const CACHE_TTL_SECONDS = 900; // 15 minutes
|
||||
* Recupere une URL via curl (necessaire pour passer le WAF Cloudflare
|
||||
* de silly.be) et renvoie le corps de la reponse en texte.
|
||||
*/
|
||||
function http_get(string $url, array $extraHeaders = []): string
|
||||
function http_get(string $url, array $headers = ['Accept: */*']): string
|
||||
{
|
||||
$ch = curl_init($url);
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_USERAGENT => USER_AGENT,
|
||||
CURLOPT_HTTPHEADER => array_merge(['Accept: application/json'], $extraHeaders),
|
||||
CURLOPT_HTTPHEADER => $headers,
|
||||
CURLOPT_TIMEOUT => 20,
|
||||
CURLOPT_FOLLOWLOCATION => true,
|
||||
CURLOPT_MAXREDIRS => 3,
|
||||
@@ -52,7 +46,7 @@ function http_get(string $url, array $extraHeaders = []): string
|
||||
* $builder() si le cache est absent ou perime. Evite de solliciter
|
||||
* silly.be / fetchrss.com a chaque poll de chaque abonne FreshRSS.
|
||||
*/
|
||||
function serve_cached_feed(string $cacheKey, callable $builder): void
|
||||
function serve_cached_feed(string $cacheKey, callable $builder, int $ttl = CACHE_TTL_SECONDS): void
|
||||
{
|
||||
// text/xml plutot que application/rss+xml : les navigateurs affichent
|
||||
// ce type en ligne (arbre XML) au lieu de forcer un telechargement,
|
||||
@@ -66,7 +60,7 @@ function serve_cached_feed(string $cacheKey, callable $builder): void
|
||||
}
|
||||
$cacheFile = CACHE_DIR . '/' . $cacheKey . '.xml';
|
||||
|
||||
if (is_file($cacheFile) && (time() - filemtime($cacheFile)) < CACHE_TTL_SECONDS) {
|
||||
if (is_file($cacheFile) && (time() - filemtime($cacheFile)) < $ttl) {
|
||||
readfile($cacheFile);
|
||||
return;
|
||||
}
|
||||
@@ -88,81 +82,6 @@ function serve_cached_feed(string $cacheKey, callable $builder): void
|
||||
}
|
||||
}
|
||||
|
||||
function strip_html(?string $text): string
|
||||
{
|
||||
if (!$text) {
|
||||
return '';
|
||||
}
|
||||
$text = preg_replace('/<[^>]+>/', ' ', $text);
|
||||
$text = html_entity_decode($text, ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||||
return trim(preg_replace('/\s+/', ' ', $text));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reproduit le slug d'URL genere par le site (cosmetique : le routeur
|
||||
* JS de silly.be lit en realite le parametre `u` pour savoir quel item
|
||||
* afficher, pas ce segment de chemin - mais autant coller a l'URL
|
||||
* "officielle" telle qu'on la voit dans la barre d'adresse).
|
||||
*/
|
||||
function slugify(string $text): string
|
||||
{
|
||||
$ascii = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $text);
|
||||
if ($ascii === false) {
|
||||
$ascii = $text;
|
||||
}
|
||||
$ascii = strtolower($ascii);
|
||||
$ascii = preg_replace('/[^a-z0-9]+/', '-', $ascii);
|
||||
return trim($ascii, '-');
|
||||
}
|
||||
|
||||
/**
|
||||
* Construit le HTML des liens vers les pieces jointes (PDF, etc.)
|
||||
* renvoyees par l'API dans le champ "items" de chaque actualite/evenement.
|
||||
*/
|
||||
function attachments_html(array $item): string
|
||||
{
|
||||
$html = '';
|
||||
foreach ($item['items'] ?? [] as $sub) {
|
||||
$url = $sub['file']['download'] ?? $sub['targetUrl'] ?? null;
|
||||
if (!$url) {
|
||||
continue;
|
||||
}
|
||||
$label = $sub['title'] ?? basename($url);
|
||||
$html .= '<p><a href="' . htmlspecialchars($url, ENT_QUOTES, 'UTF-8') . '">'
|
||||
. htmlspecialchars($label, ENT_QUOTES, 'UTF-8') . '</a></p>';
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Image principale de l'item (deja fournie par l'API, aucune requete
|
||||
* supplementaire necessaire). "paysage_affiche" est une taille
|
||||
* intermediaire raisonnable pour une image de flux RSS.
|
||||
*/
|
||||
function lead_image_html(array $item, string $title): string
|
||||
{
|
||||
$url = $item['image_affiche_scale'] ?? $item['image_full_scale'] ?? null;
|
||||
if (!$url) {
|
||||
return '';
|
||||
}
|
||||
return '<p><img src="' . htmlspecialchars($url, ENT_QUOTES, 'UTF-8') . '" alt="'
|
||||
. htmlspecialchars($title, ENT_QUOTES, 'UTF-8') . '" /></p>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Corps HTML complet d'un item (image + texte riche + pieces jointes),
|
||||
* avec repli sur le resume court si le texte complet est vide.
|
||||
*/
|
||||
function full_body_html(array $item, string $title): string
|
||||
{
|
||||
$body = trim($item['text_fr']['data'] ?? '');
|
||||
if ($body === '') {
|
||||
$summary = strip_html($item['description_fr'] ?? $item['description'] ?? null);
|
||||
$body = $summary !== '' ? '<p>' . htmlspecialchars($summary, ENT_QUOTES, 'UTF-8') . '</p>' : '';
|
||||
}
|
||||
return lead_image_html($item, $title) . $body . attachments_html($item);
|
||||
}
|
||||
|
||||
function rfc822(?string $isoDate): string
|
||||
{
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user