94 lines
5.3 KiB
PHP
94 lines
5.3 KiB
PHP
<?php
|
|
|
|
// Configuration
|
|
$jsonUrl = "https://indieblog.page/export";
|
|
$rssFile = "/app/data/public/indieblogv2_feed.xml";
|
|
$cacheFile = "/app/data/cache/indieblogv2_cache.txt";
|
|
$cutoffDate = strtotime('-10 days'); // Seulement les 10 derniers jours
|
|
|
|
// Liste des mots/expressions à exclure (insensibilité à la casse activée avec `(?i)`)
|
|
$excludePatterns = [
|
|
'(?i)(azure|powershell|rimworld|Olympique|Olympic|Paris 2024|sportif|windows|twitter|freebsd|mastodon)',
|
|
'(?i)(metalcore|deathcore|death metal|black metal|death punk|deathpunk|djent|blackmetal|blackened)',
|
|
'(?i)(JO|foot)',
|
|
'(?i)(guerre|bluesky|combat|terror|craindre|fear|décliner|declin|climat|inégalité|fuite|ont fui|a fui|musk|tesla|voitures|dying|indifference|feux|abandon|chômage|scam|arnaque|fraud|craindre|inquiét|openai|victime|violence|violent|violemm|pénurie|impôt|taxes|deuil|chasse|bombes|a perdu|vide exist|fake|poursuivi|subir|pauvre|riches|politique|politic|Macron|marine le pen|michel barnier|zemmour|Matignon|tremble|aucun n\'a|décès|crise|difficile|marre|action contre|irrecevable|pollution|élimination|pourrai|tourisme|mauvaise humeur|stress|dangereux|détruit|insupportable|de droite|souffre|chaleur|cyber|attaque|extrême.droite|risque|travail|offensi|sacrif|canard pc|photos|videos|crisis|trump|nocif|negatif|négative|pollution|poids|plainte|escro|usurp|contamin|advertising|anniversary edition|en voyage|extermin|kamikaze|nationalis|mittal|est prévu pour 202|is planned for|due in 202|incendies|fires|inondation|ligue 1|le suicide|gaza|terreur|capitalism|attentat|calvaire|calvitie|la gauche|esclave|paris|ségrégation|athlète|précarité|Hezbollah|Israël|morts|frappes|marine lepen|dérives|un drame|sans-abri|protobuf|paralympique|nazi|mélenchon|ministre|Review: (?:[1-3]\.\d|[1-2]\.\d|3\.0)/5\.0|licenciement|misère|du jamais vu|il faut|Palestiniens|israél|palestine|vaccin|mpox|épidémie|violeur|rapist|pédo|criminel|poutine|le RN |réseau social x|gendarme|policier|kurde|condamnation|perquisition|incendi|gabriel attal|attaqué|justice|tués par|tué par|snapdragon|qualcomm|porn|barnier|occultes|désinformation|immigration|racism|spacex|islam|condamné|de viol|pour viol)'
|
|
];
|
|
|
|
// Corrige les barres obliques pour qu'elles ne cassent pas `preg_match`
|
|
$excludePatterns = array_map(fn($pattern) => str_replace('/', '\/', $pattern), $excludePatterns);
|
|
|
|
// Crée une expression régulière unique pour matcher toutes les exclusions
|
|
$excludeRegex = '/' . implode('|', $excludePatterns) . '/i';
|
|
|
|
@mkdir(dirname($rssFile), 0777, true);
|
|
@mkdir(dirname($cacheFile), 0777, true);
|
|
|
|
$jsonData = @file_get_contents($jsonUrl);
|
|
if (!$jsonData) die("Error: Unable to fetch JSON from $jsonUrl\n");
|
|
|
|
$data = json_decode($jsonData, true);
|
|
if (!$data) die("Error: Invalid JSON data from $jsonUrl\n");
|
|
|
|
$includedIds = file_exists($cacheFile) ? file($cacheFile, FILE_IGNORE_NEW_LINES) : [];
|
|
|
|
// Filtrer les articles récents, non déjà inclus, et ne contenant pas de termes exclus
|
|
$newItems = array_filter($data, function ($item) use ($includedIds, $cutoffDate, $excludeRegex) {
|
|
return isset($item['published'], $item['itemid'], $item['itemtitle']) &&
|
|
!in_array($item['itemid'], $includedIds) &&
|
|
$item['published'] >= $cutoffDate &&
|
|
!preg_match($excludeRegex, $item['itemtitle']); // Exclure si le titre contient des termes interdits
|
|
});
|
|
|
|
usort($newItems, fn($a, $b) => $b['published'] <=> $a['published']);
|
|
|
|
$groupedByDay = [];
|
|
foreach ($newItems as $item) {
|
|
$day = isset($item['published']) && is_numeric($item['published'])
|
|
? date('Y-m-d', $item['published'])
|
|
: date('Y-m-d');
|
|
$groupedByDay[$day][] = $item;
|
|
}
|
|
|
|
$rss = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"></rss>');
|
|
$channel = $rss->addChild('channel');
|
|
$channel->addChild('title', 'IndieBlog Feed (Filtered, Last 10 Days)');
|
|
$channel->addChild('link', 'https://indieblog.page/');
|
|
$channel->addChild('description', 'RSS feed of articles from the last 10 days, excluding unwanted topics');
|
|
$channel->addChild('language', 'en');
|
|
|
|
$newEntries = [];
|
|
foreach ($groupedByDay as $day => $items) {
|
|
$rssItem = $channel->addChild('item');
|
|
$rssItem->addChild('title', "Links for $day");
|
|
$rssItem->addChild('link', "https://indieblog.page/$day#" . md5(json_encode($items)));
|
|
$rssItem->addChild('guid', "https://indieblog.page/$day#" . md5(json_encode($items)));
|
|
$rssItem->addChild('pubDate', date(DATE_RSS, strtotime($day)));
|
|
|
|
$description = "<ul>";
|
|
foreach ($items as $item) {
|
|
$postTitle = htmlspecialchars($item['itemtitle'] ?? 'No title', ENT_XML1);
|
|
$postUrl = htmlspecialchars($item['itemurl'] ?? '#', ENT_XML1);
|
|
$blogTitle = htmlspecialchars($item['feedtitle'] ?? 'Unknown Blog', ENT_XML1);
|
|
$blogUrl = htmlspecialchars($item['feedurl'] ?? '#', ENT_XML1);
|
|
|
|
$description .= "<li><a href=\"$postUrl\">$postTitle</a> (<a href=\"$blogUrl\">$blogTitle</a>)</li>";
|
|
$newEntries[] = $item['itemid'];
|
|
}
|
|
$description .= "</ul>";
|
|
|
|
addCData($rssItem->addChild('description'), $description);
|
|
}
|
|
|
|
if (!empty($newEntries)) {
|
|
file_put_contents($cacheFile, implode("\n", array_merge($includedIds, $newEntries)));
|
|
}
|
|
|
|
$rss->asXML($rssFile);
|
|
|
|
function addCData(SimpleXMLElement $node, $content)
|
|
{
|
|
$domNode = dom_import_simplexml($node);
|
|
$domOwner = $domNode->ownerDocument;
|
|
$domNode->appendChild($domOwner->createCDATASection($content));
|
|
}
|