View Source
The actual code behind this page. No minification. No transpilation. What you see is what runs.
|
| /** |
| * 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; |
| } |
dispelled