128 lines
4.0 KiB
PHP
128 lines
4.0 KiB
PHP
<?php
|
|
// Timezone: where RSS feeds go to die and be reborn
|
|
date_default_timezone_set('UTC'); // Adjust to your server's actual timezone
|
|
|
|
// RSS Feed with analytics tracking
|
|
header('Content-Type: application/xml; charset=utf-8');
|
|
|
|
// Track RSS feed access and active subscribers
|
|
$dataDir = '/var/www/data/analytics';
|
|
$date = date('Y-m-d');
|
|
$hour = date('H');
|
|
$summaryFile = $dataDir . '/summary_' . $date . '.json';
|
|
$readersFile = $dataDir . '/rss_readers.json';
|
|
|
|
// Track unique RSS readers
|
|
$userAgent = $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown';
|
|
$ip = $_SERVER['REMOTE_ADDR'] ?? 'Unknown';
|
|
$readerId = md5($userAgent . $ip); // Unique identifier for this reader
|
|
$now = time();
|
|
|
|
// Load existing readers data
|
|
$readers = [];
|
|
if (file_exists($readersFile)) {
|
|
$readers = json_decode(file_get_contents($readersFile), true) ?: [];
|
|
}
|
|
|
|
// Update or add this reader's last fetch time
|
|
$readers[$readerId] = [
|
|
'lastFetch' => $now,
|
|
'userAgent' => substr($userAgent, 0, 200), // Limit length
|
|
'ip' => $ip,
|
|
'firstSeen' => $readers[$readerId]['firstSeen'] ?? $now
|
|
];
|
|
|
|
// Clean up old readers (haven't fetched in 30+ days to keep file size manageable)
|
|
$thirtyDaysAgo = $now - (30 * 24 * 60 * 60);
|
|
foreach ($readers as $id => $reader) {
|
|
if ($reader['lastFetch'] < $thirtyDaysAgo) {
|
|
unset($readers[$id]);
|
|
}
|
|
}
|
|
|
|
// Save readers data
|
|
file_put_contents($readersFile, json_encode($readers, JSON_PRETTY_PRINT));
|
|
|
|
// Calculate active subscribers (fetched in last 7 days)
|
|
$sevenDaysAgo = $now - (7 * 24 * 60 * 60);
|
|
$activeSubscribers = 0;
|
|
foreach ($readers as $reader) {
|
|
if ($reader['lastFetch'] >= $sevenDaysAgo) {
|
|
$activeSubscribers++;
|
|
}
|
|
}
|
|
|
|
// Update summary - track RSS feed fetch (for historical data)
|
|
$summary = [];
|
|
if (file_exists($summaryFile)) {
|
|
$summary = json_decode(file_get_contents($summaryFile), true) ?: [];
|
|
}
|
|
|
|
if (!isset($summary['rss'])) {
|
|
$summary['rss'] = 0;
|
|
}
|
|
$summary['rss']++;
|
|
$summary['activeRssSubscribers'] = $activeSubscribers; // Store active count
|
|
|
|
// Ensure directory is writable
|
|
$result = file_put_contents($summaryFile, json_encode($summary, JSON_PRETTY_PRINT));
|
|
if ($result === false) {
|
|
error_log("Failed to write RSS tracking to $summaryFile");
|
|
}
|
|
|
|
// Generate and output RSS feed
|
|
$postsFile = __DIR__ . '/../data/posts.json';
|
|
$posts = [];
|
|
if (file_exists($postsFile)) {
|
|
$posts = json_decode(file_get_contents($postsFile), true) ?: [];
|
|
}
|
|
|
|
// Sort posts by date (newest first)
|
|
usort($posts, function($a, $b) {
|
|
return strtotime($b['date']) - strtotime($a['date']);
|
|
});
|
|
|
|
// Escape XML
|
|
function escapeXml($str) {
|
|
if (!$str) return '';
|
|
return htmlspecialchars($str, ENT_XML1, 'UTF-8');
|
|
}
|
|
|
|
// Format content
|
|
function formatContent($content) {
|
|
return nl2br(htmlspecialchars($content, ENT_XML1, 'UTF-8'));
|
|
}
|
|
|
|
// Generate RSS items
|
|
$rssItems = '';
|
|
foreach ($posts as $post) {
|
|
$title = escapeXml($post['title']);
|
|
$excerpt = escapeXml($post['excerpt']);
|
|
$content = formatContent($post['content']);
|
|
$pubDate = date('r', strtotime($post['date']));
|
|
$link = 'https://example.com/blog/post.html?id=' . $post['id'];
|
|
|
|
$rssItems .= " <item>\n";
|
|
$rssItems .= " <title>{$title}</title>\n";
|
|
$rssItems .= " <link>{$link}</link>\n";
|
|
$rssItems .= " <guid>{$link}</guid>\n";
|
|
$rssItems .= " <pubDate>{$pubDate}</pubDate>\n";
|
|
$rssItems .= " <description><![CDATA[{$excerpt}<br/><br/>{$content}]]></description>\n";
|
|
$rssItems .= " </item>\n";
|
|
}
|
|
|
|
// Output RSS XML
|
|
echo '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
|
|
echo '<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">' . "\n";
|
|
echo " <channel>\n";
|
|
echo " <title>My Blog</title>\n";
|
|
echo " <link>https://example.com/blog</link>\n";
|
|
echo " <description>Blog posts</description>\n";
|
|
echo " <language>en-us</language>\n";
|
|
echo " <lastBuildDate>" . date('r') . "</lastBuildDate>\n";
|
|
echo " <atom:link href=\"https://example.com/blog/api/feed.php\" rel=\"self\" type=\"application/rss+xml\"/>\n";
|
|
echo $rssItems;
|
|
echo " </channel>\n";
|
|
echo "</rss>\n";
|
|
?>
|