Guest User

Readerss

a guest
Sep 11th, 2025
34
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6.     <title>Simple RSS Reader</title>
  7.     <style>
  8.         body { font-family: Arial, sans-serif; }
  9.         #feedItems { margin-top: 20px; }
  10.         .feed { margin-bottom: 10px; }
  11.         a { text-decoration: none; color: blue; }
  12.         a:visited { color: purple; }
  13.        
  14.         summary {background-color: Aliceblue;}
  15.         details {border: 1px solid white; background-color: beige;}
  16.     </style>
  17. </head>
  18. <body>
  19.     <h1>Simple RSS Reader</h1>
  20.     <input type="text" id="feedUrl" placeholder="Enter RSS Feed URL(s) - comma/semicolon separated">
  21.     <button id="subscribe">Subscribe</button>
  22.     <button id="export">Export</button>
  23.     <div id="subscriptions"></div>
  24.     <div id="feedItems"></div>
  25.  
  26.     <script>
  27.         let allEpisodes = []; // Array to store episodes from all feeds
  28.         let podcastTitles = {}; // Object to store podcast titles by feed URL
  29.         let podcastDescriptions = {}; // Object to store podcast descriptions by feed URL
  30.  
  31.         // Function to load subscribed feeds from local storage
  32.         function loadFeeds() {
  33.             const feeds = JSON.parse(localStorage.getItem('subscribedFeeds')) || [];
  34.             feeds.forEach(feed => fetchFeed(feed));
  35.             displaySubscriptions(feeds); // Display subscriptions
  36.         }
  37.  
  38.         // Function to display subscriptions
  39.         function displaySubscriptions(feeds) {
  40.             const subscriptionsDiv = document.getElementById('subscriptions');
  41.             subscriptionsDiv.innerHTML = '<h4>Subscriptions:</h4>';
  42.             feeds.forEach(feed => {
  43.                 const podcastTitle = podcastTitles[feed] || feed; // Use stored title or feed URL
  44.                 const podcastDescription = podcastDescriptions[feed] || '';
  45.                 subscriptionsDiv.innerHTML += `
  46.                     <details>
  47.                         <summary><a href="${feed}" target="_blank">${podcastTitle}</a> <button onclick="removeFeed('${feed}')">Remove</button></summary>
  48.                         ${podcastDescription || 'No description available'}
  49.                     </details>`;
  50.             });
  51.         }
  52.  
  53.         // Function to fetch a single feed
  54.         function fetchFeed(feedUrl) {
  55.             fetch(feedUrl)
  56.                 .then(response => {
  57.                     if (!response.ok) {
  58.                         throw new Error('Network response was not ok: ' + response.statusText);
  59.                     }
  60.                     return response.text();
  61.                 })
  62.                 .then(str => {
  63.                     const parser = new window.DOMParser();
  64.                     const data = parser.parseFromString(str, "text/xml");
  65.                     const items = Array.from(data.querySelectorAll("item"));
  66.  
  67.                     if (items.length === 0) {
  68.                         console.error("No items found in the feed.");
  69.                         return;
  70.                     }
  71.  
  72.                     const podcastTitle = data.querySelector("title").textContent; // Get podcast title
  73.                     const podcastDescription = data.querySelector("description") ? data.querySelector("description").textContent : '';
  74.                     podcastTitles[feedUrl] = podcastTitle; // Store podcast title by feed URL
  75.                     podcastDescriptions[feedUrl] = podcastDescription; // Store podcast description by feed URL
  76.  
  77.                     // Extract episodes and add to allEpisodes array
  78.                     items.forEach(el => {
  79.                         const title = el.querySelector("title").textContent;
  80.                         const audioUrl = el.querySelector("enclosure").getAttribute("url");
  81.                         const pubDate = new Date(el.querySelector("pubDate").textContent);
  82.                         const episodeDescription = el.querySelector("description") ? el.querySelector("description").textContent : '';
  83.                         allEpisodes.push({ podcastTitle, title, audioUrl, pubDate, episodeDescription });
  84.                     });
  85.  
  86.                     // Sort all episodes by publication date (recent to old)
  87.                     allEpisodes.sort((a, b) => b.pubDate - a.pubDate);
  88.  
  89.                     // Display all episodes
  90.                     displayEpisodes();
  91.                     const currentFeeds = JSON.parse(localStorage.getItem('subscribedFeeds')) || [];
  92.                     displaySubscriptions(currentFeeds); // Update subscriptions display
  93.                 })
  94.                 .catch(error => {
  95.                     console.error("Error fetching the feed:", error);
  96.                 });
  97.         }
  98.  
  99.         // Function to display all episodes
  100.         function displayEpisodes() {
  101.             let html = '<h4>Episodes:</h4>';
  102.             allEpisodes.forEach((episode, index) => {
  103.                 html += `<details><summary>${episode.podcastTitle} - <a href="${episode.audioUrl}" target="_blank">${episode.title}</a></summary>${episode.episodeDescription || 'No description available'}</details>`;
  104.             });
  105.             document.getElementById('feedItems').innerHTML = html;
  106.         }
  107.  
  108.         // Function to subscribe to feed(s)
  109.         document.getElementById('subscribe').addEventListener('click', function() {
  110.             const input = document.getElementById('feedUrl').value;
  111.             if (input) {
  112.                 // First try splitting by comma or semicolon, then fallback to whitespace if no commas/semicolons
  113.                 let urls;
  114.                 if (input.includes(',') || input.includes(';')) {
  115.                     urls = input.split(/[,;]+/).map(url => url.trim()).filter(url => url);
  116.                 } else {
  117.                     urls = input.split(/\s+/).map(url => url.trim()).filter(url => url);
  118.                 }
  119.                
  120.                 const feeds = JSON.parse(localStorage.getItem('subscribedFeeds')) || [];
  121.                 let added = 0;
  122.                 urls.forEach(url => {
  123.                     if (url && !feeds.includes(url)) {
  124.                         feeds.push(url);
  125.                         added++;
  126.                         fetchFeed(url);
  127.                     }
  128.                 });
  129.                 if (added > 0) {
  130.                     localStorage.setItem('subscribedFeeds', JSON.stringify(feeds));
  131.                                                                                                        
  132.                 }
  133.                 document.getElementById('feedUrl').value = '';
  134.             }
  135.         });
  136.  
  137.         // Export function
  138.         document.getElementById('export').addEventListener('click', function() {
  139.             const feeds = JSON.parse(localStorage.getItem('subscribedFeeds')) || [];
  140.             if (feeds.length > 0) {
  141.                 const exportText = feeds.join(', ');
  142.                 if (navigator.clipboard && navigator.clipboard.writeText) {
  143.                     navigator.clipboard.writeText(exportText).then(() => {
  144.                         alert('Feeds copied to clipboard!');
  145.                     }).catch(() => {
  146.                         prompt('Copy this text:', exportText);
  147.                     });
  148.                 } else {
  149.                     prompt('Copy this text:', exportText);
  150.                 }
  151.             }
  152.         });
  153.  
  154.         // Function to remove a feed
  155.         function removeFeed(feedUrl) {
  156.             let feeds = JSON.parse(localStorage.getItem('subscribedFeeds')) || [];
  157.             feeds = feeds.filter(feed => feed !== feedUrl);
  158.             localStorage.setItem('subscribedFeeds', JSON.stringify(feeds));
  159.             allEpisodes = []; // Reset the episodes array
  160.             delete podcastTitles[feedUrl]; // Remove the podcast title from the object
  161.             delete podcastDescriptions[feedUrl]; // Remove the podcast description from the object
  162.             loadFeeds(); // Reload feeds to update the display
  163.         }
  164.  
  165.         // Load feeds on page load
  166.         loadFeeds();
  167.     </script>
  168. </body>
  169. </html>
Advertisement
Add Comment
Please, Sign In to add comment