pub / kontra

Der linke Newsaggregator.
git clone src.jayvii.de/pub/kontra.git
Home | Log | Files | Exports | Refs | README | RSS

commit 862ad8fbb699f834b52485d5e87b29425560c3f5
parent 76f7d9000b1a593062db7f8ec991303b13d5386b
Author: JayVii <jayvii[AT]posteo[DOT]de>
Date:   Mon,  9 Jun 2025 20:18:41 +0200

feat: introduce basic generation of OPML files

Diffstat:
Aindex.php | 405+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 405 insertions(+), 0 deletions(-)

diff --git a/index.php b/index.php @@ -0,0 +1,405 @@ +<!-- +SPDX-License-Identifier: AGPL-3.0-or-later +SPDX-FileCopyrightText: 2025 JayVii <jayvii+kontra[AT]posteo[DOT]de> +--> + +<!-- Loading configuration --> +<?php + $config = json_decode( + file_get_contents("./news-sources.json"), + true + ); +?> + +<!-- OPML Generator --> +<?php + + + /* Check for user input */ + if (!is_null($_POST["action"])) { + + /* Generate OPML */ + if ($_POST["action"] === "gen_opml") { + + /* Gather news sources from selection */ + $input_keys = preg_grep( + "/^source-[0-9]+$/", + array_keys($_POST) + ); + $sources = array(); + foreach ($input_keys as $key) { + array_push( + $sources, + $config["sources"][$_POST[$key]] + ); + } + + /* Build OPML file */ + header('Content-Type: application/xml; charset=UTF-8'); + header('Content-Disposition: Attachment;filename=kontra.opml'); +?> +<opml version="2.0"> +<head> + <title>Nachrichten-Export von Kontra - der linke Newsaggregator</title> +</head> +<body> +<?php + + /* Cycle through each category */ + foreach ($config["categories"] as $category) { + +?> + +<outline + title="<?php echo $category["name"]; ?>" + text="<?php echo $category["name"]; ?>" +> + +<?php + /* Within each category, find selected sources that are part of it */ + foreach ($sources as $source) { + + $match = preg_grep("/^" . $category["id"] . "$/", $source["categories"]); + if (count($match) > 0) { + +?> +<outline + title="<?php echo $source["title"]; ?>" + text="<?php echo $source["title"]; ?>" + xmlUrl="<?php echo $source["rss"]; ?>" +/> +<?php + + } // if-match + } // foreach-source + +?> + +</outline> + +<?php + + } // foreach-category + +?> + +</body> +</opml> + +<?php + + die(); + } // if-action + } // if-input + +?> + +<!doctype html> +<html> + + <!-- Head --> + <head> + <meta charset=utf-8> + <meta name=viewport content="width=device-width,initial-scale=1"> + <link rel=icon href=assets/img/favicon.png type=image/png> + <link rel=icon href=assets/img/favicon.ico type=x-image/ico> + <link rel=stylesheet href=assets/css/simple.min.css media=all> + <link rel=stylesheet href=assets/css/custom.css> + <script async src=assets/js/filter_engines.js></script> + <title>Kontra - Der Linke News Aggregator</title> + </head> + + <!-- Body --> + <body> + + <!-- Header --> + <header> + <nav> + <a href="#sources"> + Nachrichten + </a> + <a href="#faqs"> + Was ist das? + </a> + <a href="https://src.jayvii.de/pub/kontra/" target="_blank"> + Hilf mit! + </a> + </nav> + <h1>Kontra</h1> + <p>Der Linke News Aggregator</p> + </header> + + <!-- Description --> + <div class="description"> + <strong style="font-size: 133%;"> + <em>Kontra</em> gibt Nutzer:innen die Möglichkeit, + unterschiedliche Nachrichtenquellen zu einem persönlichen + Nachrichten-Feed zusammen zu stellen. Ganz ohne Tracking, + Big-Tech und algorithmischem Framing. + </strong> + <p> + Auf dieser Seite befinden sich viele seriöse Medienquellen aus + dem <em>linken Spektrum¹</em> von Zeitungen, Magazinen und + sonstigen journalistischen Veröffentlichungen, aus denen sich + persönliche Nachrichten-Feeds erstellt werden lassen. + </p> + <a href="#sources" class="button"> + Zu den Nachrichten! + </a> + <a href="#faqs" class="button"> + Wie funktioniert das? + </a> + </div> + + <!-- Search Engine Lists --> + <h3 id="sources">Eigenen Nachrichten-Feed generieren</h3> + + <!--<p> + Aktuell stehen + <strong><?php echo count($config["sources"]); ?> + Nachrichtenquellen + </strong> in + <strong><?php echo count($config["categories"]); ?> + Kategorien + </strong> + zur verfügung. + </p>--> + <p> + Wähle beliebig viele Nachrichtenquellen aus der unteren Liste aus + und klicke auf den <strong>Nachrichten-Feed erzeugen</strong> Knopf. + Speichere die darauf angebotene OPML-Datei ab und importiere sie in + deinen RSS-Reader. + </p> + + <!-- Filterbar --> + <input + id="sources_filterbar" + name="sources" + type="text" + placeholder="Suche nach Nachrichtenquellen oder Kategorien..." + oninput="filter_sources('sources_filterbar');" + > + <noscript> + <div class="notice"> + <p> + Achtung: Die Nutzung der Suchfunktion benötigt aktiviertes + JavaScript. Entweder unterstützt dein Browser diese + Funktion nicht, oder du hast sie auf dieser Seite blockiert. + <strong> + Du kannst dennoch einen Nachrichten-Feed erzeugen, jedoch + ohne die Suchfunktion oben dafür nutzen zu können. + </strong> + </p> + </div> + </noscript> + + <!-- Category Buttons --> + <details id="categories"> + <summary>Kategorien</summary> + + <div class="row"> + + <!-- List all configured categories --> + <?php + foreach ($config["categories"] as $category) { + ?> + <button + onclick="filter_category('<?php echo $category["name"]; ?>');" + title="<?php echo $category["description"]; ?>" + > + <?php echo "#" . $category["name"]; ?> + </button> + <?php + } + ?> + + </div> + + </details> + + <!-- Sources List --> + <form id="sources-selection" method="post"> + + <!-- Submit button --> + <input type="submit" value="Nachrichten-Feed erzeugen!"> + <input type="hidden" name="action" value="gen_opml"> + <?php + $cnt = 0; + foreach ($config["sources"] as $id => $source) { + $cnt++; // increase counter for POST field ID + ?> + <article> + <!-- Entry-Head --> + <h3> + <a href="<?php echo $source["web"]; ?>" target="_blank"> + <?php echo $source["title"]; ?> + </a> + </h3> + + <!-- Description --> + <p><?php echo $source["desc"]; ?></p> + + <!-- Choose this Button --> + <input + type="checkbox" + name="<?php echo "source-" . $cnt; ?>" + value="<?php echo $id; ?>" + > + <label for="<?php echo $id; ?>"> + Diese Nachrichtenquelle auswählen + </label> + + <!-- Entry-Categories --> + <div class="categories"> + + <?php + /* List all categories of current entry */ + foreach ($source["categories"] as $category) { + $catentry = $config["categories"][$category] + ?> + <mark title="<?php echo $catentry["description"];?>"> + <?php echo "#" . $catentry["name"]; ?> + </mark> + <?php + } + ?> + + </div> + + </article> + <?php + } + ?> + </form> + + <!-- FAQs / About-Section --> + <section id="faqs"> + + <h3>Was ist <em>Kontra</em>?</h3> + + <!-- meaning of name --> + <details> + <summary>What does serĉi mean?</summary> + <p> + It is the Esperanto term for "to search".This may not be the + most creative name for such a software project but to the + best of my knowledge, it is a unique one. + </p> + </details> + + <!-- what are keywords --> + <details> + <summary>What are keywords?</summary> + <p> + An idea lent from the search Engine + <a href="https://duckduckgo.com/bangs" target="_blank"> + DuckDuckGo + </a>, which has been utilized by many others since. They + call their keywords bangs, but it is the same concept and + usability. In essence, keywords are shortcuts for searching + on other websites. + </p> + <p> + For example, you can conduct a search on the website + <a + href="<?php echo $searches[$rsi]["website"]; ?>" + target="_blank" + > + <?php echo $searches[$rsi]["name"]; ?> + </a> + directly from <?php echo $_SERVER["SERVER_NAME"]; ?> by + adding the keyword + <code>!<?php echo $searches[$rsi]["keywords"][0]; ?></code> + to your search query. + </p> + <p> + You can find all keywords associated with each search engine + in the <a href="#engines">list above</a>. + </p> + </details> + + <!-- how to use --> + <details> + <summary>How can I use serĉi?</summary> + <p> + You can try serĉi directly + <a href="#searchbar">on this site</a> or + <a + href="https://src.jayvii.de/pub/serci/#hosting" + target="_blank" + > + host it yourself + </a>! + It barely needs any server resources, no database or lots of + RAM. serĉi has minimal footprint (also on user data: there + are <strong>none</strong>). + </p> + <p> + Either type your search directly into the + <a href="#searchbar">search bar at the very top</a> + or add the search to your browser by rightclicking in the + URL-bar of your web browser and choose + <emph>add serĉi - Search with !keywords</emph>. + </p> + <p> + Some browsers (for example Firefox on Android / Fennec) + allow to configure custom search engines via a so-called + search URL. Simply list following URL as + <emph>search-URL</emph> there and choose it as your fallback + search option: + </p> + <pre>https://<?php echo $_SERVER["SERVER_NAME"]; ?>/?q=%s</pre> + <p> + You can also choose the fallback search engine, used by + serĉi as fallback, when no keyword is given, through the URL + instead of choosing it from the + <a href="#engines">list above</a>, in case you do not want + serĉi to store any cookie on your device. For example, if + you wanted to use + <a + href="<?php echo $searches[$rsi]["website"]; ?>" + target="_blank" + > + <?php echo $searches[$rsi]["name"]; ?> + </a> + as your fallback search, you could use following search-URL: + </p> + <pre><?php + echo "https://" . $_SERVER["SERVER_NAME"] . + "/?fallback=" . $rsi . "&q=%s"; + ?></pre> + </details> + + <!-- no js or cookies --> + <details> + <summary> + Choosing a fallback search without cookies or Javascript + </summary> + <p> + You can simply choose a fallback search by adding the + <code>fallback</code> URL parameter. For example, if you + wanted to use + <a + href="<?php echo $searches[$rsi]["website"]; ?>" + target="_blank" + > + <?php echo $searches[$rsi]["name"]; ?> + </a> + as your fallback search, you can simply add + <code>/?fallback=<?php echo $rsi; ?></code> to the serĉi + URL: + <br> + <a href="/?fallback=<?php echo $rsi; ?>"> + <?php + echo "https://" . $_SERVER["SERVER_NAME"] . + "/?fallback=" . $rsi; + ?> + </a> + </p> + </details> + + </section> + + </body> + +</html>