Files
silly-rss/php/facebook.php
T
paraandClaude Sonnet 5 476c1bf413 Fix W3C validator errors in the Facebook feed proxy
FetchRSS's raw feed fails validation: entry <id> is a bare Facebook post
ID rather than a full URI, and <link rel="self"> points at the FetchRSS
URL instead of where we actually serve it. Parse the fetched XML with
DOMDocument and fix both before caching/serving: reuse each entry's own
alternate link (already a full post URL) as its id, and rewrite the self
link to our own facebook.php URL.

Requires the php-xml extension (ext-dom) — near-universal on shared
hosting, but worth checking if this breaks on deploy.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-26 00:23:02 +02:00

81 lines
2.7 KiB
PHP

<?php
require __DIR__ . '/common.php';
/**
* Proxy/cache du flux Facebook (page communedesilly) genere par
* FetchRSS (https://fetchrss.com). Scraper Facebook nous-memes n'est
* pas fiable (mur de connexion, blocage anti-bot systematique -
* confirme aussi en cassant l'instance RSS-Bridge testee) ; FetchRSS
* s'en charge et on se contente de re-servir/cacher son flux sous
* notre propre domaine pour avoir une URL stable a partager.
*/
const FETCHRSS_URL = 'https://fetchrss.com/feed/1xABzW0ZB9CM1xAByX0rYAhW.atom';
const SELF_URL = 'https://sillycone-village.be/silly-rss/facebook.php';
/**
* Le flux FetchRSS brut ne passe pas le validateur W3C :
* - <id> de chaque <entry> est l'identifiant numerique brut du post
* Facebook, alors que la spec Atom exige une URI complete. On reutilise
* le <link rel="alternate"> de l'entree (deja une URL complete vers le
* post) a la place.
* - Le <link rel="self"> pointe vers l'URL FetchRSS d'origine au lieu de
* celle ou ce flux est reellement servi.
*/
function fetch_facebook_feed(): string
{
$raw = http_get(FETCHRSS_URL, ['Accept: application/atom+xml, application/xml']);
$doc = new DOMDocument();
if (!$doc->loadXML($raw)) {
return $raw; // XML illisible : on sert quand meme le brut plutot que de casser le flux
}
$atomNs = 'http://www.w3.org/2005/Atom';
$xpath = new DOMXPath($doc);
$xpath->registerNamespace('a', $atomNs);
foreach ($xpath->query('/a:feed/a:link[@rel="self"]') as $selfLink) {
$selfLink->setAttribute('href', SELF_URL);
}
foreach ($xpath->query('/a:feed/a:entry') as $entry) {
$idNode = $xpath->query('a:id', $entry)->item(0);
$linkNode = $xpath->query('a:link[@rel="alternate"]', $entry)->item(0);
if ($idNode && $linkNode) {
$href = $linkNode->getAttribute('href');
if ($href && !preg_match('#^https?://#', $idNode->textContent)) {
$idNode->textContent = $href;
}
}
}
return $doc->saveXML();
}
// text/xml plutot que application/atom+xml : voir la note dans common.php
header('Content-Type: text/xml; charset=utf-8');
if (!is_dir(CACHE_DIR)) {
mkdir(CACHE_DIR, 0775, true);
}
$cacheFile = CACHE_DIR . '/facebook.xml';
if (is_file($cacheFile) && (time() - filemtime($cacheFile)) < CACHE_TTL_SECONDS) {
readfile($cacheFile);
return;
}
try {
$xml = fetch_facebook_feed();
file_put_contents($cacheFile, $xml);
echo $xml;
} catch (Throwable $e) {
if (is_file($cacheFile)) {
readfile($cacheFile);
return;
}
http_response_code(502);
header('Content-Type: text/plain; charset=utf-8');
echo 'Erreur de recuperation du flux Facebook : ' . $e->getMessage();
}