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>