View Source

The actual code behind this page. No minification. No transpilation. What you see is what runs.

↓ Download PHP edition
reddit.php 101 lines
<?php
/**
* Pure-PHP Reddit post fetcher for dispelled.ca.
*
* Uses old.reddit.com multi-sub RSS (Atom) with a browser User-Agent.
* Reddit blocks generic PHP user-agents but permits Firefox UA requests.
* Results are cached for 10 minutes.
*/
function getRedditPosts(): array
{
$cacheFile = CACHE_DIR . '/reddit.json';
if (file_exists($cacheFile) && (time() - filemtime($cacheFile)) < 600) {
$cached = json_decode(file_get_contents($cacheFile), true);
if (is_array($cached) && count($cached) > 0) return $cached;
}
$subs = 'linux+programming+netsec+sysadmin+opensource';
$url = "https://old.reddit.com/r/{$subs}.rss?limit=50";
$ctx = stream_context_create(['http' => [
'method' => 'GET',
'header' => implode("\r\n", [
'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:125.0) Gecko/20100101 Firefox/125.0',
'Accept: application/rss+xml, application/xml, text/xml;q=0.9, */*;q=0.8',
'Accept-Language: en-US,en;q=0.5',
'Cache-Control: no-cache',
]) . "\r\n",
'timeout' => 12,
]]);
$raw = @file_get_contents($url, false, $ctx);
if (!$raw) return [];
libxml_use_internal_errors(true);
$xml = simplexml_load_string($raw);
libxml_clear_errors();
if (!$xml) return [];
$labelMap = [
'linux' => 'r/linux',
'programming' => 'r/programming',
'netsec' => 'r/netsec',
'sysadmin' => 'r/sysadmin',
'opensource' => 'r/opensource',
];
$items = [];
foreach ($xml->entry as $entry) {
// Subreddit from <category term="linux">
$sub = null;
foreach ($entry->category as $cat) {
$term = strtolower((string)$cat['term']);
if (isset($labelMap[$term])) { $sub = $term; break; }
}
if (!$sub) continue;
// URL from <link rel="alternate" href="...">
$postUrl = '';
foreach ($entry->link as $link) {
if ((string)$link['rel'] === 'alternate') {
$postUrl = (string)$link['href'];
break;
}
}
if (!$postUrl) $postUrl = (string)($entry->link['href'] ?? '');
// Description: strip HTML content, remove Reddit boilerplate
$desc = '';
if (isset($entry->content)) {
$desc = strip_tags((string)$entry->content);
$desc = html_entity_decode($desc, ENT_QUOTES | ENT_HTML5, 'UTF-8');
$desc = preg_replace('/\s+/', ' ', trim($desc));
$desc = preg_replace('/\s*submitted by\s+\/u\/\S+(\s+\[link\])?(\s+\[comments\])?/i', '', $desc);
$desc = preg_replace('/\s*\[link\]\s*(\[comments\])?/i', '', $desc);
$desc = trim($desc);
if (mb_strlen($desc) < 15) $desc = '';
elseif (mb_strlen($desc) > 300) $desc = mb_substr($desc, 0, 300) . '…';
}
$idRaw = (string)$entry->id;
$items[] = [
'id' => 'reddit-' . ($idRaw ?: md5($postUrl)),
'title' => html_entity_decode((string)$entry->title, ENT_QUOTES | ENT_HTML5, 'UTF-8'),
'url' => $postUrl,
'description' => $desc !== '' ? $desc : null,
'subreddit' => $sub,
'subredditLabel' => $labelMap[$sub],
'publishedAt' => (string)$entry->updated,
];
}
if (count($items) > 0) {
if (!is_dir(CACHE_DIR)) mkdir(CACHE_DIR, 0755, true);
file_put_contents($cacheFile, json_encode($items));
}
return $items;
}