pub / stories

Top News Aggregator
git clone src.jayvii.de/pub/stories.git
Home | Log | Files | Exports | Refs | RSS

index.tt (5912B)


      1 <!-- SPDX-License-Identifier: AGPL-3.0-or-later
      2      SPDX-FileCopyrightText: 2021-2026 JayVii <jayvii[AT]posteo[DOT]de>
      3 -->
      4 
      5 <!DOCTYPE html>
      6 <html>
      7   <head>
      8     <meta charset="utf-8">
      9     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
     10     <title>[% feed.title %]</title>
     11     <meta name="description" content="[% feed.description %]">
     12     [% IF feed.author %]
     13     <meta name="author" content="[% feed.author %]">
     14     [% END %]
     15     <link rel="icon" type="image/png" href="assets/favicon.png">
     16     <link rel="icon" type="image/png" sizes="16x16"
     17       href="assets/img/favicon_16.png"
     18     />
     19     <link rel="icon" type="image/png" sizes="32x32"
     20       href="assets/img/favicon_32.png"
     21     />
     22     <link rel="icon" type="image/png" sizes="64x64"
     23       href="assets/img/favicon_64.png"
     24     />
     25     <link rel="icon" type="image/png" sizes="128x128"
     26       href="assets/img/favicon_128.png"
     27     />
     28     <link rel="apple-touch-icon" href="assets/favicon.png">
     29     <link rel="stylesheet" type="text/css" href="assets/css/simple.min.css">
     30     <link rel="stylesheet" type="text/css" href="assets/css/custom.css">
     31     <script src="assets/js/og_image.js"></script>
     32     <link crossorigin="use-credentials" rel="manifest" href="assets/manifest.json">
     33     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     34     <meta name="robots" content="noindex">
     35   </head>
     36 
     37   <body>
     38 
     39     <header>
     40       <nav>
     41         <!-- About Button -->
     42         <a
     43           href="#about"
     44           title="About this page"
     45         >About</a>
     46         <!-- Privacy Policy -->
     47         <a href="https://www.jayvii.de/privacy/#newsjayviide" target="_blank">
     48           Privacy
     49         </a>
     50       </nav>
     51       <!-- Feed Title -->
     52       <h1 id="top">[% feed.title | html %]</h1>
     53       <p>[% feed.description | html %]</p>
     54     </header>
     55 
     56     <main>
     57 
     58       <?php
     59 
     60         $news = array();
     61         [% FOREACH entry IN feed.entries %]
     62         array_push(
     63           $news,
     64           array(
     65             "title" => "[%entry.title | html %]",
     66             "url" => "[% entry.link | url %]",
     67             "date" => strtotime("[% entry.issued | html %]"),
     68             "content" => "[% IF entry.summary.body %][% entry.summary.body | html %][% ELSE %][% entry.content.body | html %][% END %]"
     69           )
     70         );
     71         [% END %]
     72 
     73         // Sort News item by time stamp and remove duplicate entries
     74         function compare(array $a, array $b) {
     75           return $b["date"] - $a["date"];
     76         }
     77         usort($news, "compare");
     78         $news = array_intersect_key(
     79           $news,
     80           array_unique(
     81             array_map('serialize', $news)
     82           )
     83         );
     84 
     85         // Read ignore list (URLs)
     86         $ignore_urls = json_decode(file_get_contents("./ignore.json"), true);
     87         
     88       ?>
     89 
     90       <!-- Content Entries -->
     91       <?php
     92         $counter = 0;
     93         foreach ($news as $entry) {
     94 
     95           if ($entry["date"] < strtotime("-24 hours")) {
     96             continue;
     97           }
     98           if ($entry["content"] == "" || $entry["content"] == $entry["title"]) {
     99             continue;
    100           }
    101 
    102           $ignore_url = 0;
    103           foreach ($ignore_urls["url"] as $iv) {
    104             $ignore_pattern = '/' . $iv . '/';
    105             if (preg_match($ignore_pattern, $entry["url"])) {
    106               $ignore_url++;
    107             }
    108           }
    109           if ($ignore_url > 0) {
    110             continue;
    111           }
    112 
    113           $counter++;
    114           if ($counter > 50) {
    115             continue;
    116           }
    117 
    118           $entry["content"] = preg_replace(
    119             '/<[^>]+>/',
    120             '',
    121             html_entity_decode($entry["content"])
    122           );
    123           $entry["domain"] = preg_replace(
    124             '/^http(s)*:\/\/([^\/]+)\/.*$/',
    125             '${2}',
    126             $entry["url"]
    127           );
    128 
    129       ?>
    130       <section>
    131         <!-- Head image -->
    132         <img
    133           loading="lazy"
    134           src="assets/img/fallback.jpg"
    135           style="width:100%;height:100%;max-height:250px;object-fit:cover;margin-top:1em;"
    136           onload="insert_og_image(this, '<?php echo $entry['url']; ?>');"
    137         >
    138         <!-- Headline -->
    139         <h4 style="margin-bottom:5px;">
    140           <a href="<?php echo urldecode($entry["url"]); ?>"
    141             target="_blank"
    142             rel="nofollow ugc"
    143           >
    144             <?php echo $counter . ". " . $entry["title"]; ?>
    145           </a>
    146         </h3>
    147         <!-- Information -->
    148         <div style="width:100%;margin-bottom:1em;">
    149           <em style="margin-left:0.25em;color:var(--border);">
    150             <?php echo date("Y-m-d, H:i", $entry["date"]); ?>
    151           </em>
    152           <em style="margin-left:0.25em;color:var(--border);">
    153             <?php echo $entry["domain"]; ?>
    154           </em>
    155         </div>
    156         <!-- Content -->
    157         <p class="article_content">
    158           <?php echo $entry["content"]; ?>
    159         </p>
    160       </section>
    161 
    162       <?php
    163         }
    164       ?>
    165 
    166     </main>
    167 
    168     <footer>
    169       <h4 id="about">What is this?</h4>
    170       <p>
    171         This website <em>Stories</em> gathers news from various sources and
    172         aggregates them into a time sorted list. The goal of <em>Stories</em> is
    173         to display news, nothing more. No full content of news sites is shown,
    174         but rather a link to the original article. Only what the news outlets
    175         publish via their RSS feed is shown within the according news-card.
    176       </p>
    177       <h4 id="disclaimer">Disclaimer:</h4>
    178       <p>
    179         The news headlines, content or attitudes of the editors and authors of
    180         the news outlets, blogs and newspapers featured here do not necessarily
    181         reflect the opinions and attitudes of the operators of this website.
    182         This is a news aggregator together content from many different
    183         sources, but has no influence on the editorial content directly.
    184       </p>
    185       <a class="button" href="#top">Backto the top</a>
    186     </footer>
    187 
    188   </body>
    189 </html>