pub / kontra

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

commit d5cdd0cf135dc45af6afb1c9e056f9cdd30e77c3
parent 24474441c47aa71c48fb999c78165c06ff85ec91
Author: JayVii <jayvii[AT]posteo[DOT]de>
Date:   Mon, 20 Oct 2025 14:18:46 +0200

feat: implement preview mode

Diffstat:
M.htaccess | 1+
Mindex.php | 759+++----------------------------------------------------------------------------
Alib/gen_html_categories.php | 172+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/gen_html_description.php | 31+++++++++++++++++++++++++++++++
Alib/gen_html_faqs.php | 204+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/gen_html_feeds.php | 174+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/gen_html_footer.php | 23+++++++++++++++++++++++
Alib/gen_html_head.php | 18++++++++++++++++++
Alib/gen_html_navigation.php | 23+++++++++++++++++++++++
Alib/gen_html_preview.php | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/gen_html_usage.php | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/gen_opml.php | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/parse_rss.php | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mnews-sources.json | 5++---
14 files changed, 998 insertions(+), 737 deletions(-)

diff --git a/.htaccess b/.htaccess @@ -11,6 +11,7 @@ RedirectMatch 404 ^/.htaccess$ RedirectMatch 404 ^/.reuse/.*$ RedirectMatch 404 ^/README.md$ RedirectMatch 404 ^/tools/.*$ +RedirectMatch 404 ^/lib/.*$ # Define custom 404 page ErrorDocument 404 /404.html diff --git a/index.php b/index.php @@ -10,94 +10,27 @@ true ); - /* OPML Generator */ + /* Load libraries */ + foreach (glob("./lib/*.php") as $lib) { + include($lib); + } + + /* Custom Actions ------------------------------------------------------- */ /* 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]] - ); - } - - $exp_hash = md5(serialize($sources)); - $file_name = "kontra_" . date("Y-m-d") . "_" . $exp_hash . ".opml"; - - /* Set Download and content type headers */ - header('Content-Type: application/xml; charset=UTF-8'); - header( - 'Content-Disposition: Attachment;filename="' . $file_name . '"' - ); - - /* Build OPML file */ -?> - -<opml version="2.0"> -<head> - <title> - Nachrichten-Export von Kontra - - <?php echo "https://" . $_SERVER["SERVER_NAME"] . PHP_EOL; ?> - </title> -</head> -<body> - -<?php - - /* Cycle through each source and write source entry */ - $indexes = array( - "regions", "languages", "access", "medium", "topics" - ); - foreach ($sources as $source) { - - /* Construct title */ - $title = $config["publisher"][$source["publisher"][0]]["name"] . - ": " . $source["title"]; - - /* Create category list */ - $categories = array(); - foreach ($indexes as $index) { - foreach ($source[$index] as $category) { - array_push( - $categories, - $config[$index][$category]["name"] - ); - } - } - -?> - -<outline - title="<?php echo $title; ?>" - text="<?php echo $title; ?>" - category="<?php echo implode(",", $categories); ?>" - xmlUrl="<?php echo $source["rss"]; ?>" - htmlUrl="<?php echo $source["web"]; ?>" -/> - -<?php - - } // foreach-source - -?> - -</body> -</opml> - -<?php - + gen_opml($config); die(); } // if-action + + /* Preview feeds */ + if ($_POST["action"] === "preview") { + gen_preview($config); + die(); + } } // if-input ?> @@ -106,673 +39,31 @@ <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 - Das progressive Nachrichtenarchiv</title> - </head> + <?php gen_html_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>Das progressive Nachrichtenarchiv</p> - </header> + <!-- Header / Navigation --> + <?php gen_html_navigation(); ?> <!-- Description --> - <div class="fullheight"> - <div class="description"> - <strong style="font-size: 133%;"> - Nachrichten von Links! Ohne Tracking, ohne Tech-Konzerne und - ohne algorithmisches Framing. - </strong> - <p> - Auf dieser Seite befinden sich viele seriöse Medienquellen - aus dem <em>progressiven</em> Spektrum von Zeitungen, - Magazinen und sonstigen journalistischen Veröffentlichungen, - aus denen sich persönliche Nachrichten-Feeds erstellen - lassen. - </p> - </div> - <div class="buttonrow"> - <a href="#usage" class="button c2"> - Wie funktioniert das? - </a> - <a href="#sources" class="button c2"> - Zu den Nachrichten! - </a> - </div> - </div> - - <div class="fullheight screenshots" id="usage"> - <h3>Was ist Kontra?</h3> - <figure class="buttonrow"> - <img style="flex:26%;min-width:91px;margin:2.5px;" src="assets/img/applications/gfeeds_mobile.jpg"> - <img style="flex:72%;min-width:252px;margin:2.5px;" src="assets/img/applications/gfeeds_desktop.jpg"> - <figcaption style="width:100%;"> - Nachrichten Feeds aus Kontra in <a href="https://gfeeds.gabmus.org/" target="_blank">Gnome Feeds</a> - </figcaption> - </figure> - <p> - Kontra versetzt Nutzer:innen in die Lage, selbstbestimmt - personalisierte Nachrichten-Feeds von seriösen <em>progressiven</em> - Quellen zu erstellen, um immer auf dem Laufenden zu bleiben. - Und das selbstverständlich - <strong>ohne <a href="https://de.wikipedia.org/wiki/Web_Analytics" target="_blank">Tracking</a></strong>, - <strong>ohne Datensammelwut</strong>, - <strong>ohne Konto-Zwang</strong> - <strong>ohne <a href="https://de.wikipedia.org/wiki/Soziales_Netzwerk_(Internet)#Kritik" target="_blank">Algorithmen</a></strong> und - <strong>ohne <a href="https://de.wikipedia.org/wiki/Lock-in-Effekt" target="_blank">Lock-In Effekte</a></strong>. - Wie das funktioniert, erfährst du <a href="#faqs">hier</a>! - </p> - <p> - Die in Kontra hinterlegten Medien behandeln ein breites Spektrum - an Themen und mit unterschiedlichen Fokuspunkten. Sie vereint - eine <em>progressive</em> und politisch <em>linke</em> - Sichtweise. Die Idee hinter Kontra ist, die Nutzung von Medien - zu vereinfachen und Menschen in die Lage zu versetzen, selbst - kuratierte Nachrichtenquellen und Themenbereiche zu verfolgen. - </p> - <p> - Kontra ist ein Archiv mit aktuell - <strong><?php echo count($config["sources"]); ?></strong> - Nachrichten-Feeds aus - <strong><?php echo count($config["publisher"]); ?></strong> - unterschiedlichen Quellen, zu - <strong><?php echo count($config["topics"]); ?></strong> - Themenbereichen, innerhalb von - <strong><?php echo count($config["regions"]); ?></strong> - Regionen, in - <strong><?php echo count($config["languages"]); ?></strong> - verschiedenen Sprachen. Nutzer:innen können sich aus diesem - Katalog eigene Nachrichten-Feeds gänzlich nach ihren Interessen - zusammenstellen. Die hier herunterladbaren - <a href="https://de.wikipedia.org/wiki/Outline_Processor_Markup_Language" target="_blank"> - Nachrichten-Feed Dateien</a> - können in beliebigen - <a href="https://de.wikipedia.org/wiki/Feedreader" target="_blank"> - Feed-Readern</a> - eingeladen und sofort genutzt werden! - Zum Beispiel in diesen - <a href="https://fsfe.org/freesoftware/freesoftware.de.html" target="_blank"> - Freien</a> - und kostenlosen Apps für Android und iOS: - <ul> - <li><a href="https://apps.apple.com/us/app/netnewswire-rss-reader/id1480640210" target="_blank">NetNewsWire (iOS)</a></li> - <li><a href="https://apps.apple.com/us/app/twine-rss-reader/id6465694958" target="_blank">Twine (iOS)</a></li> - <li><a href="https://play.google.com/store/apps/details?id=com.nononsenseapps.feeder.play" target="_blank">Feeder (Android)</a></li> - <li><a href="https://play.google.com/store/apps/details?id=dev.sasikanth.rss.reader" target="_blank">Twine (Android)</a></li> - <li><a href="https://freshrss.org/" target="_blank">FreshRSS (Web)</a></li> - <li><a href="https://www.thunderbird.net/de/" target="_blank">Thunderbird (Windows, MacOS, Linux)</a></li> - <li><a href="https://gfeeds.gabmus.org/" target="_blank">Feeds (Linux)</a></li> - <li><a href="https://apps.gnome.org/de/NewsFlash/" target="_blank">NewsFlash (Linux)</a></li> - <li><a href="https://apps.kde.org/de/alligator/" target="_blank">Alligator (Linux)</a></li> - <li><a href="https://alternativeto.net/browse/search/?q=rss%20reader" target="_blank">und viele weitere</a>...</li> - </ul> - </p> - <p> - Ganz einfach in nur <strong>zwei Minuten</strong> loslegen! - Nachrichtenquellen aussuchen, Feed-Datei herunterladen, in - den Reader importieren und sofort informiert werden. - </p> - - <div class="buttonrow"> - <a href="#faqs" class="button c2"> - Mehr erfahren - </a> - <a href="#sources" class="button c2"> - Zu den Nachrichten! - </a> - </div> - </div> - - <!-- Search Engine Lists --> - <h3 id="sources" style="margin-top:5em;"> - Eigenen Nachrichten-Feed generieren - </h3> - <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> - <p> - Kontra bietet zur Zeit Zugriff auf - <strong><?php echo count($config["sources"]); ?></strong> - Nachrichten-Feeds aus - <strong><?php echo count($config["publisher"]); ?></strong> - unterschiedlichen Quellen, zu - <strong><?php echo count($config["topics"]); ?></strong> - Themenbereichen, innerhalb von - <strong><?php echo count($config["regions"]); ?></strong> - Regionen, in - <strong><?php echo count($config["languages"]); ?></strong> - verschiedenen Sprachen. Nutze die Suchfunktion und die - Kategorienliste, um die Auswahl zu erleichtern. - </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> - - <h4>Themen</h4> - <div class="row"> - - <!-- List all configured regions --> - <?php - foreach ($config["topics"] as $topic) { - ?> - <button - onclick="filter_category('<?php echo $topic["name"]; ?>');" - title="<?php echo $topic["description"]; ?>" - > - <?php echo "#" . $topic["name"]; ?> - </button> - <?php - } - ?> - - </div> - - <h4>Regionen</h4> - <div class="row"> + <?php gen_html_description(); ?> - <!-- List all configured regions --> - <?php - foreach ($config["regions"] as $region) { - ?> - <button - onclick="filter_category('<?php echo $region["name"]; ?>');" - title="<?php echo $region["description"]; ?>" - > - <?php echo "#" . $region["name"]; ?> - </button> - <?php - } - ?> + <!-- Usage --> + <?php gen_html_usage($config); ?> - </div> - - <h4>Sprachen</h4> - <div class="row"> - - <!-- List all configured languages --> - <?php - foreach ($config["languages"] as $language) { - ?> - <button - onclick="filter_category('<?php echo $language["name"]; ?>');" - title="<?php echo $language["description"]; ?>" - > - <?php echo "#" . $language["name"]; ?> - </button> - <?php - } - ?> - - </div> - - <h4>Zugriff</h4> - <div class="row"> - - <!-- List all configured access types --> - <?php - foreach ($config["access"] as $access) { - ?> - <button - onclick="filter_category('<?php echo $access["name"]; ?>');" - title="<?php echo $access["description"]; ?>" - > - <?php echo "#" . $access["name"]; ?> - </button> - <?php - } - ?> - - </div> - - <h4>Medium</h4> - <div class="row"> - - <!-- List all configured media --> - <?php - foreach ($config["medium"] as $medium) { - ?> - <button - onclick="filter_category('<?php echo $medium["name"]; ?>');" - title="<?php echo $medium["description"]; ?>" - > - <?php echo "#" . $medium["name"]; ?> - </button> - <?php - } - ?> - - </div> - - <h4>Quellen</h4> - <div class="row"> - - <!-- List all configured sources --> - <?php - foreach ($config["publisher"] as $publisher) { - ?> - <button - onclick="filter_category('<?php echo $publisher["button"]; ?>');" - title="<?php echo $publisher["description"]; ?>" - > - <?php echo "#" . $publisher["button"]; ?> - </button> - <?php - } - ?> - - </div> - - </details> + <!-- Categories List --> + <?php gen_html_categories($config); ?> <!-- Sources List --> - <form id="sources-selection" method="post"> - - <!-- Submit button --> - <div class="submit-container"> - <input type="submit" value="Nachrichten-Feed erzeugen!"> - <a href="#sources" class="button" title="Nach oben"> - &#128070; <stretch class="nomobile">Nach oben</stretch> - </a> - <a href="#faqs" class="button" title="Nach unten"> - &#128071; <stretch class="nomobile">Nach unten</stretch> - </a> - </div> - <input type="hidden" name="action" value="gen_opml"> - <?php - $cnt = 0; - foreach ($config["sources"] as $id => $source) { - $cnt++; // increase counter for POST field ID - - /* Gather publishing medium info */ - $publisher = $config["publisher"][ - array_pop($source["publisher"]) - ]; - ?> - <article> - <!-- Entry-Head --> - <h3> - <a href="<?php echo $source["web"]; ?>" target="_blank"> - <?php - echo $publisher["name"] . ": " . $source["title"]; - ?> - </a> - </h3> - - <!-- Description --> - <p> - <?php - echo $publisher["desc"] . " " . $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 --> - <table style="width:100%;"> - - <tr> - <th>Quelle:</th> - <td> - <mark title="<?php echo $publisher["desc"];?>"> - <?php echo "#" . $publisher["button"]; ?> - </mark> - </td> - </tr> - - <tr> - <th>Region:</th> - <td> - <?php - foreach ($source["regions"] as $region) { - $catentry = $config["regions"][$region] - ?> - <mark title="<?php echo $catentry["description"];?>"> - <?php echo "#" . $catentry["name"]; ?> - </mark> - <?php - } - ?> - </td> - </tr> - - <tr> - <th>Sprachen:</th> - <td> - <?php - foreach ($source["languages"] as $language) { - $catentry = $config["languages"][$language] - ?> - <mark title="<?php echo $catentry["description"];?>"> - <?php echo "#" . $catentry["name"]; ?> - </mark> - <?php - } - ?> - </td> - </tr> - - <tr> - <th>Zugang:</th> - <td> - <?php - foreach ($source["access"] as $access) { - $catentry = $config["access"][$access] - ?> - <mark title="<?php echo $catentry["description"];?>"> - <?php echo "#" . $catentry["name"]; ?> - </mark> - <?php - } - ?> - </td> - </tr> - - <tr> - <th>Medium:</th> - <td> - <?php - foreach ($source["medium"] as $medium) { - $catentry = $config["medium"][$medium] - ?> - <mark title="<?php echo $catentry["description"];?>"> - <?php echo "#" . $catentry["name"]; ?> - </mark> - <?php - } - ?> - </td> - </tr> - - <tr> - <th>Themen:</th> - <td> - <?php - foreach ($source["topics"] as $topic) { - $catentry = $config["topics"][$topic] - ?> - <mark title="<?php echo $catentry["description"];?>"> - <?php echo "#" . $catentry["name"]; ?> - </mark> - <?php - } - ?> - </td> - <tr> - </table> - - </article> - <?php - } - ?> - </form> + <?php gen_html_feeds($config); ?> <!-- FAQs / About-Section --> - <section id="faqs"> - - <h3>Was ist <em>Kontra</em>?</h3> - - <details> - <summary>Was sind Feed-Reader / RSS-Reader?</summary> - <p> - Feed- oder RSS-Reader erlauben es, so genannte RSS-Feeds zu - <em>abonnieren</em>, um regelmäßig Nachrichten von diesen zu - erhalten. Das Konzept ist vergleichbar mit einem E-Mail - Newsletter. - </p> - <p> - Der Unterschied besteht darin, dass man, um einen Newsletter - erhalten zu können, den Versender:innen eine E-Mail Adresse - hinterlegen muss. Newsletter werden dann aktiv von den - Versender:innen an bekannte Empfänger:innen verschickt. - </p> - <p> - Bei RSS-Feeds ist es umgekehrt. Empfänger:innen (bzw. von - ihnen genutzt Feed-Reader) ziehen sich die Nachrichten von - den Nachrichten-Seiten oder Blogs selbst. Letztere wissen - dabei gar nicht, wer die Empfänger:innen sind oder wie viele - es letztendlich sind. - </p> - <p> - Der RSS-Reader ist lediglich die Software, welche die - Nachrichten empfängt und diese oft in einem Listen-Format - zum Lesen anzeigt. Es gibt eine Vielzahl wirklich guter - und zeitgemäßer RSS-Reader für alle möglichen Endgeräte, - ganz egal ob am PC, Smartphone, Tablet, E-Book-Reader oder - per Webbrowser. - </p> - <p> - Folgende RSS-Reader sind kostenlos und darüber hinaus noch - <a href="https://fsfe.org/freesoftware/freesoftware.de.html" target="_blank"> - Freie, Open Source Software - </a>: - <ul> - <li><a href="https://apps.apple.com/us/app/netnewswire-rss-reader/id1480640210" target="_blank">NetNewsWire (iOS)</a></li> - <li><a href="https://apps.apple.com/us/app/twine-rss-reader/id6465694958" target="_blank">Twine (iOS)</a></li> - <li><a href="https://play.google.com/store/apps/details?id=com.nononsenseapps.feeder.play" target="_blank">Feeder (Android)</a></li> - <li><a href="https://play.google.com/store/apps/details?id=dev.sasikanth.rss.reader" target="_blank">Twine (Android)</a></li> - <li><a href="https://freshrss.org/" target="_blank">FreshRSS (Web)</a></li> - <li><a href="https://www.thunderbird.net/de/" target="_blank">Thunderbird (Windows, MacOS, Linux)</a></li> - <li><a href="https://gfeeds.gabmus.org/" target="_blank">Feeds (Linux)</a></li> - <li><a href="https://apps.kde.org/de/alligator/" target="_blank">Alligator (Linux)</a></li> - <li><a href="https://alternativeto.net/browse/search/?q=rss%20reader" target="_blank">und viele weitere</a>...</li> - </ul> - </p> - </details> - - <details> - <summary>Kann ich weitere Nachrichten-Feeds abonnieren?</summary> - <p> - Ja! Gibt es Nachrichtenquellen, die nicht in Kontra - enthalten sind, kann man diese auch einzeln im eigenen - Feed-Reader abonnieren. Auch das ist sehr einfach und dauert - in der Regel nur wenige Sekunden. - </p> - <p> - Fast alle Online-Medien haben eine Unterseite, auf der sie - ihre RSS-Feeds auflisten. Folgende Medien sind - beispielsweise wegen des Fokus auf dediziert progressive Medien - nicht in Kontra enthalten, lassen sich aber sehr einfach - über einen RSS-Reader abonnieren: - <ul> - <li><a href="https://www.tagesschau.de/infoservices/rssfeeds" target="_blank">Tagesschau (ÖRR)</a></li> - <li><a href="https://www.deutschlandfunk.de/rss-angebot-102.html" target="_blank">Deutschlandfunk (ÖRR)</a></li> - <li><a href="https://www.sueddeutsche.de/service/updates-mit-rss-uebersicht-aller-rss-feeds-fuer-sz-de-sz-magazin-und-jetzt-de-1.393950" target="_blank">Süddeutsche Zeitung</a></li> - </ul> - </p> - </details> - - <details> - <summary>Ist Kontra kostenlos?</summary> - <p> - Ja! Kontra ist und bleibt kostenlos. Es ist lediglich ein - kleines privates Software-Projekt einer Einzelperson. - </p> - <p> - Zudem wird Kontra als - <a href="https://fsfe.org/freesoftware/freesoftware.de.html" target="_blank"> - Freie, Open Source Software - </a> - entwickelt. Der Programm-Code kann also von allen jederzeit - eingesehen werden. Verbesserungsvorschläge oder eigene - Code-Beiträge sind stets willkommen. Es ist auch erlaubt, - eigene Projekte auf Kontra aufzubauen. Diese müssen jedoch - ebenfalls unter einer Freien Software-Lizenz stehen. - </p> - <p> - Du möchtest helfen? - <a href="https://src.jayvii.de/pub/kontra/" target="_blank"> - Hier - </a> findest du mehr Informationen dazu. - </p> - </details> - - <details> - <summary>Ist das <em>Abonnieren</em> eines RSS-Feed kostenlos?</summary> - <p> - Ja! Allerdings kann es sein, dass einige der in den - Nachrichten-Feeds angebotenen Artikel hinter einer - Bezahlschranke liegen, also oft nicht in voller Länge - gelesen werden können, ohne ein Abonnement bei der - jeweiligen Online-Publikation, bzw. ein Zeitungsabonnement - abzuschließen. - </p> - <p> - Kontra kennzeichnet Nachrichtenquellen, bei denen einige - Artikel hinter einer Bezahlschranke liegen können. - Nachrichtenquellen, die niemals eine Bezahlschranke nutzen - sind ebenfalls in einer eigenen Kategorie. - </p> - </details> - - <details> - <summary>Sammelt Kontra meine Daten?</summary> - <p> - Nein! Kontra sammelt keinerlei Datein über Personen und - Geräte, die diese Seite besuchen und Kontra nutzen. - Technisch bedingt, wird bei jedem Aufruf <em>jeder</em> - Webseite im Internet mindestens die eigene IP-Adresse und - oft noch weitere Informationen über das Betriebssystem, den - Webbrowser, bzw. das verwendete Gerät übermittelt. Kontra - speichert <strong>keine</strong> dieser Informationen. - </p> - <p> - Zudem stellt Kontra lediglich das Archiv von RSS-Feeds zur - Verfügung. Kontra speichert außerdem keine Informationen - darüber, welche Nachrichtenquellen von Nutzer:innen - ausgewählt werden. - </p> - <p> - Mit dem Herunterladen der Feed-Datei endet der - Datenaustausch zwischen den Nutzer:innen und Kontra. Kontra - hat technisch bedingt keinen Einblick darin, ob und welche - Nachrichten Nutzende in einen Feedreader einlesen oder - welche Nachrichten tatsächlich von Nutzer:innen gelesen - werden. Das liegt daran, dass die Nachrichten - <strong>direkt</strong> und ohne Umwege von den jeweiligen - Nachrichtenseiten kommen und zu keinem Zeitpunkt über Kontra - laufen. - </p> - </details> - - <details> - <summary>Welche Technik nutzt Kontra?</summary> - <p> - Millionen Webseiten und Online-Zeitungen weltweit bieten die - offene Schnittstelle - <a href="https://de.wikipedia.org/wiki/RSS_(Web-Feed)" target="_blank"> - RSS - </a> (zu deutsch: <em>sehr einfache Verbreitung</em>) an. - Nahezu jeder Blog, jede Nachrichtenseite und - Online-Veröffentlichungen nutzen einen <em>RSS</em> Feed. - Das ist eine maschinenlesbare Datei, welche alle dort - veröffentlichte Nachrichten und einige Zusatzinformationen - (Veröffentlichungszeitpunkt, Autor:in, Kurzzusammenfassung, - usw.) enthält. RSS kann als <em>schwarzes Brett</em> - digitaler Medien verstanden werden. - </p> - <p> - Kontra stellt eben diese RSS-Feeds für alle von Nutzer:innen - ausgewählte Medien in einer herunterladbaren Datei zusammen, - die in üblichen Feedreadern (siehe: - <em><strong>Was sind Feedreader?</strong></em>) importiert - werden kann. Diese Datei basiert auf dem offenen - <a href="https://de.wikipedia.org/wiki/Outline_Processor_Markup_Language", target="_blank"> - OPML - </a> Format und wird von nahezu allen RSS/Feed-Readern - verstanden. Damit gewährleistet Kontra, dass es keinen - sogenannten <em>Lock-In</em> Effekt gibt, der Nutzer:innen - an eine einzige App binden und der Wechsel zu Alternativen - erschwert. - </p> - <p> - Die angesprochenen OPML-Dateien enthalten nicht nur die - RSS-Feeds selbst, sondern auch alle Kategorien, die man - ihnen innerhalb des eigenen Feed-Readers zugewiesen hat. Die - OPML-Dateien aus Kontra enthalten alle Kategorie-Label, die - auch in der Liste sichtbar sind. - </p> - <p> - <strong>Kurzum:</strong> RSS und OPML sind die grundlegende - Technik, auf die <em>Kontra</em> setzt. Nachrichten können - darüber direkt von Blogs und Zeitungen bezogen werden, ohne - dass Dritte Einsicht darin haben. Feeds können in nahezu - allen Feedreadern importiert und exportiert werden. Ein - Wechsel von einer App zu einer anderen ist also innerhalb - von Sekunden möglich. - </p> - </details> - - </section> + <?php gen_html_faqs($config); ?> - <footer> - <h4>Disclaimer</h4> - <p> - Die Schlagzeilen, Inhalte oder Einstellungen der Redakteur:innen - und Autor:innen der hier aufgeführten Nachrichtenagenturen, - Blogs und Zeitungen spiegeln nicht unbedingt die Meinungen und - Einstellungen der Entwickler:innen und Betreiber:innen von - <em>Kontra</em> wider. <em>Kontra</em> ist ein Quellenarchiv für - Nachrichtenaggregatoren, der Inhalte aus vielen verschiedenen - Quellen zusammenführt werden. <em>Kontra</em> hat - selbstverständlich keinen direkten Einfluss auf den - redaktionellen Inhalt. - </p> - <em>Version:</em> <code><?php echo $config["version"]; ?></code> - </footer> + <!-- Footer --> + <?php gen_html_footer($config); ?> </body> diff --git a/lib/gen_html_categories.php b/lib/gen_html_categories.php @@ -0,0 +1,172 @@ +<?php +function gen_html_categories($config) { +?> + +<h3 id="sources" style="margin-top:5em;"> + Eigenen Nachrichten-Feed generieren +</h3> +<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> +<p> + Kontra bietet zur Zeit Zugriff auf + <strong><?php echo count($config["sources"]); ?></strong> + Nachrichten-Feeds aus + <strong><?php echo count($config["publisher"]); ?></strong> + unterschiedlichen Quellen, zu + <strong><?php echo count($config["topics"]); ?></strong> + Themenbereichen, innerhalb von + <strong><?php echo count($config["regions"]); ?></strong> + Regionen, in + <strong><?php echo count($config["languages"]); ?></strong> + verschiedenen Sprachen. Nutze die Suchfunktion und die + Kategorienliste, um die Auswahl zu erleichtern. +</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> + + <h4>Themen</h4> + <div class="row"> + + <!-- List all configured regions --> + <?php + foreach ($config["topics"] as $topic) { + ?> + <button + onclick="filter_category('<?php echo $topic["name"]; ?>');" + title="<?php echo $topic["description"]; ?>" + > + <?php echo "#" . $topic["name"]; ?> + </button> + <?php + } + ?> + + </div> + + <h4>Regionen</h4> + <div class="row"> + + <!-- List all configured regions --> + <?php + foreach ($config["regions"] as $region) { + ?> + <button + onclick="filter_category('<?php echo $region["name"]; ?>');" + title="<?php echo $region["description"]; ?>" + > + <?php echo "#" . $region["name"]; ?> + </button> + <?php + } + ?> + + </div> + + <h4>Sprachen</h4> + <div class="row"> + + <!-- List all configured languages --> + <?php + foreach ($config["languages"] as $language) { + ?> + <button + onclick="filter_category('<?php echo $language["name"]; ?>');" + title="<?php echo $language["description"]; ?>" + > + <?php echo "#" . $language["name"]; ?> + </button> + <?php + } + ?> + + </div> + + <h4>Zugriff</h4> + <div class="row"> + + <!-- List all configured access types --> + <?php + foreach ($config["access"] as $access) { + ?> + <button + onclick="filter_category('<?php echo $access["name"]; ?>');" + title="<?php echo $access["description"]; ?>" + > + <?php echo "#" . $access["name"]; ?> + </button> + <?php + } + ?> + + </div> + + <h4>Medium</h4> + <div class="row"> + + <!-- List all configured media --> + <?php + foreach ($config["medium"] as $medium) { + ?> + <button + onclick="filter_category('<?php echo $medium["name"]; ?>');" + title="<?php echo $medium["description"]; ?>" + > + <?php echo "#" . $medium["name"]; ?> + </button> + <?php + } + ?> + + </div> + + <h4>Quellen</h4> + <div class="row"> + + <!-- List all configured sources --> + <?php + foreach ($config["publisher"] as $publisher) { + ?> + <button + onclick="filter_category('<?php echo $publisher["button"]; ?>');" + title="<?php echo $publisher["description"]; ?>" + > + <?php echo "#" . $publisher["button"]; ?> + </button> + <?php + } + ?> + + </div> + +</details> + +<?php +} +?> diff --git a/lib/gen_html_description.php b/lib/gen_html_description.php @@ -0,0 +1,31 @@ +<?php +function gen_html_description() { +?> + +<div class="fullheight"> + <div class="description"> + <strong style="font-size: 133%;"> + Nachrichten von Links! Ohne Tracking, ohne Tech-Konzerne und + ohne algorithmisches Framing. + </strong> + <p> + Auf dieser Seite befinden sich viele seriöse Medienquellen + aus dem <em>progressiven</em> Spektrum von Zeitungen, + Magazinen und sonstigen journalistischen Veröffentlichungen, + aus denen sich persönliche Nachrichten-Feeds erstellen + lassen. + </p> + </div> + <div class="buttonrow"> + <a href="#usage" class="button c2"> + Wie funktioniert das? + </a> + <a href="#sources" class="button c2"> + Zu den Nachrichten! + </a> + </div> +</div> + +<?php +} +?> diff --git a/lib/gen_html_faqs.php b/lib/gen_html_faqs.php @@ -0,0 +1,204 @@ +<?php +function gen_html_faqs($config) { +?> + +<section id="faqs"> + + <h3>Was ist <em>Kontra</em>?</h3> + + <details> + <summary>Was sind Feed-Reader / RSS-Reader?</summary> + <p> + Feed- oder RSS-Reader erlauben es, so genannte RSS-Feeds zu + <em>abonnieren</em>, um regelmäßig Nachrichten von diesen zu + erhalten. Das Konzept ist vergleichbar mit einem E-Mail + Newsletter. + </p> + <p> + Der Unterschied besteht darin, dass man, um einen Newsletter + erhalten zu können, den Versender:innen eine E-Mail Adresse + hinterlegen muss. Newsletter werden dann aktiv von den + Versender:innen an bekannte Empfänger:innen verschickt. + </p> + <p> + Bei RSS-Feeds ist es umgekehrt. Empfänger:innen (bzw. von + ihnen genutzt Feed-Reader) ziehen sich die Nachrichten von + den Nachrichten-Seiten oder Blogs selbst. Letztere wissen + dabei gar nicht, wer die Empfänger:innen sind oder wie viele + es letztendlich sind. + </p> + <p> + Der RSS-Reader ist lediglich die Software, welche die + Nachrichten empfängt und diese oft in einem Listen-Format + zum Lesen anzeigt. Es gibt eine Vielzahl wirklich guter + und zeitgemäßer RSS-Reader für alle möglichen Endgeräte, + ganz egal ob am PC, Smartphone, Tablet, E-Book-Reader oder + per Webbrowser. + </p> + <p> + Folgende RSS-Reader sind kostenlos und darüber hinaus noch + <a href="https://fsfe.org/freesoftware/freesoftware.de.html" target="_blank"> + Freie, Open Source Software + </a>: + <ul> + <li><a href="https://apps.apple.com/us/app/netnewswire-rss-reader/id1480640210" target="_blank">NetNewsWire (iOS)</a></li> + <li><a href="https://apps.apple.com/us/app/twine-rss-reader/id6465694958" target="_blank">Twine (iOS)</a></li> + <li><a href="https://play.google.com/store/apps/details?id=com.nononsenseapps.feeder.play" target="_blank">Feeder (Android)</a></li> + <li><a href="https://play.google.com/store/apps/details?id=dev.sasikanth.rss.reader" target="_blank">Twine (Android)</a></li> + <li><a href="https://freshrss.org/" target="_blank">FreshRSS (Web)</a></li> + <li><a href="https://www.thunderbird.net/de/" target="_blank">Thunderbird (Windows, MacOS, Linux)</a></li> + <li><a href="https://gfeeds.gabmus.org/" target="_blank">Feeds (Linux)</a></li> + <li><a href="https://apps.kde.org/de/alligator/" target="_blank">Alligator (Linux)</a></li> + <li><a href="https://alternativeto.net/browse/search/?q=rss%20reader" target="_blank">und viele weitere</a>...</li> + </ul> + </p> + </details> + + <details> + <summary>Kann ich weitere Nachrichten-Feeds abonnieren?</summary> + <p> + Ja! Gibt es Nachrichtenquellen, die nicht in Kontra + enthalten sind, kann man diese auch einzeln im eigenen + Feed-Reader abonnieren. Auch das ist sehr einfach und dauert + in der Regel nur wenige Sekunden. + </p> + <p> + Fast alle Online-Medien haben eine Unterseite, auf der sie + ihre RSS-Feeds auflisten. Folgende Medien sind + beispielsweise wegen des Fokus auf dediziert progressive Medien + nicht in Kontra enthalten, lassen sich aber sehr einfach + über einen RSS-Reader abonnieren: + <ul> + <li><a href="https://www.tagesschau.de/infoservices/rssfeeds" target="_blank">Tagesschau (ÖRR)</a></li> + <li><a href="https://www.deutschlandfunk.de/rss-angebot-102.html" target="_blank">Deutschlandfunk (ÖRR)</a></li> + <li><a href="https://www.sueddeutsche.de/service/updates-mit-rss-uebersicht-aller-rss-feeds-fuer-sz-de-sz-magazin-und-jetzt-de-1.393950" target="_blank">Süddeutsche Zeitung</a></li> + </ul> + </p> + </details> + + <details> + <summary>Ist Kontra kostenlos?</summary> + <p> + Ja! Kontra ist und bleibt kostenlos. Es ist lediglich ein + kleines privates Software-Projekt einer Einzelperson. + </p> + <p> + Zudem wird Kontra als + <a href="https://fsfe.org/freesoftware/freesoftware.de.html" target="_blank"> + Freie, Open Source Software + </a> + entwickelt. Der Programm-Code kann also von allen jederzeit + eingesehen werden. Verbesserungsvorschläge oder eigene + Code-Beiträge sind stets willkommen. Es ist auch erlaubt, + eigene Projekte auf Kontra aufzubauen. Diese müssen jedoch + ebenfalls unter einer Freien Software-Lizenz stehen. + </p> + <p> + Du möchtest helfen? + <a href="https://src.jayvii.de/pub/kontra/" target="_blank"> + Hier + </a> findest du mehr Informationen dazu. + </p> + </details> + + <details> + <summary>Ist das <em>Abonnieren</em> eines RSS-Feed kostenlos?</summary> + <p> + Ja! Allerdings kann es sein, dass einige der in den + Nachrichten-Feeds angebotenen Artikel hinter einer + Bezahlschranke liegen, also oft nicht in voller Länge + gelesen werden können, ohne ein Abonnement bei der + jeweiligen Online-Publikation, bzw. ein Zeitungsabonnement + abzuschließen. + </p> + <p> + Kontra kennzeichnet Nachrichtenquellen, bei denen einige + Artikel hinter einer Bezahlschranke liegen können. + Nachrichtenquellen, die niemals eine Bezahlschranke nutzen + sind ebenfalls in einer eigenen Kategorie. + </p> + </details> + + <details> + <summary>Sammelt Kontra meine Daten?</summary> + <p> + Nein! Kontra sammelt keinerlei Datein über Personen und + Geräte, die diese Seite besuchen und Kontra nutzen. + Technisch bedingt, wird bei jedem Aufruf <em>jeder</em> + Webseite im Internet mindestens die eigene IP-Adresse und + oft noch weitere Informationen über das Betriebssystem, den + Webbrowser, bzw. das verwendete Gerät übermittelt. Kontra + speichert <strong>keine</strong> dieser Informationen. + </p> + <p> + Zudem stellt Kontra lediglich das Archiv von RSS-Feeds zur + Verfügung. Kontra speichert außerdem keine Informationen + darüber, welche Nachrichtenquellen von Nutzer:innen + ausgewählt werden. + </p> + <p> + Mit dem Herunterladen der Feed-Datei endet der + Datenaustausch zwischen den Nutzer:innen und Kontra. Kontra + hat technisch bedingt keinen Einblick darin, ob und welche + Nachrichten Nutzende in einen Feedreader einlesen oder + welche Nachrichten tatsächlich von Nutzer:innen gelesen + werden. Das liegt daran, dass die Nachrichten + <strong>direkt</strong> und ohne Umwege von den jeweiligen + Nachrichtenseiten kommen und zu keinem Zeitpunkt über Kontra + laufen. + </p> + </details> + + <details> + <summary>Welche Technik nutzt Kontra?</summary> + <p> + Millionen Webseiten und Online-Zeitungen weltweit bieten die + offene Schnittstelle + <a href="https://de.wikipedia.org/wiki/RSS_(Web-Feed)" target="_blank"> + RSS + </a> (zu deutsch: <em>sehr einfache Verbreitung</em>) an. + Nahezu jeder Blog, jede Nachrichtenseite und + Online-Veröffentlichungen nutzen einen <em>RSS</em> Feed. + Das ist eine maschinenlesbare Datei, welche alle dort + veröffentlichte Nachrichten und einige Zusatzinformationen + (Veröffentlichungszeitpunkt, Autor:in, Kurzzusammenfassung, + usw.) enthält. RSS kann als <em>schwarzes Brett</em> + digitaler Medien verstanden werden. + </p> + <p> + Kontra stellt eben diese RSS-Feeds für alle von Nutzer:innen + ausgewählte Medien in einer herunterladbaren Datei zusammen, + die in üblichen Feedreadern (siehe: + <em><strong>Was sind Feedreader?</strong></em>) importiert + werden kann. Diese Datei basiert auf dem offenen + <a href="https://de.wikipedia.org/wiki/Outline_Processor_Markup_Language", target="_blank"> + OPML + </a> Format und wird von nahezu allen RSS/Feed-Readern + verstanden. Damit gewährleistet Kontra, dass es keinen + sogenannten <em>Lock-In</em> Effekt gibt, der Nutzer:innen + an eine einzige App binden und der Wechsel zu Alternativen + erschwert. + </p> + <p> + Die angesprochenen OPML-Dateien enthalten nicht nur die + RSS-Feeds selbst, sondern auch alle Kategorien, die man + ihnen innerhalb des eigenen Feed-Readers zugewiesen hat. Die + OPML-Dateien aus Kontra enthalten alle Kategorie-Label, die + auch in der Liste sichtbar sind. + </p> + <p> + <strong>Kurzum:</strong> RSS und OPML sind die grundlegende + Technik, auf die <em>Kontra</em> setzt. Nachrichten können + darüber direkt von Blogs und Zeitungen bezogen werden, ohne + dass Dritte Einsicht darin haben. Feeds können in nahezu + allen Feedreadern importiert und exportiert werden. Ein + Wechsel von einer App zu einer anderen ist also innerhalb + von Sekunden möglich. + </p> + </details> + +</section> + +<?php +} +?> diff --git a/lib/gen_html_feeds.php b/lib/gen_html_feeds.php @@ -0,0 +1,174 @@ +<?php +function gen_html_feeds($config) { +?> + +<form id="sources-selection" method="post" target="_blank"> + + <!-- Submit button --> + <div class="submit-container"> + <button + type="submit" + name="action" + value="gen_opml" + title="Erzeugt die OPML-Datei, die in den RSS-Reader importiert werden kann" + > + Feed erzeugen + </button> + <button + type="submit" + name="action" + value="preview" + title="Leitet auf eine Vorschau der ausgewählten Feeds weiter" + > + Feed-Vorschau + </button> + <a href="#sources" class="button" title="Nach oben"> + &#128070; <stretch class="nomobile">Nach oben</stretch> + </a> + <a href="#faqs" class="button" title="Nach unten"> + &#128071; <stretch class="nomobile">Nach unten</stretch> + </a> + </div> + <?php + $cnt = 0; + foreach ($config["sources"] as $id => $source) { + $cnt++; // increase counter for POST field ID + + /* Gather publishing medium info */ + $publisher = $config["publisher"][ + array_pop($source["publisher"]) + ]; + ?> + <article> + <!-- Entry-Head --> + <h3> + <a + href="<?php echo $source["web"]; ?>" + target="_blank" + rel="nofollow noindex ugc" + > + <?php + echo $publisher["name"] . ": " . $source["title"]; + ?> + </a> + </h3> + + <!-- Description --> + <p> + <?php + echo $publisher["desc"] . " " . $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 --> + <table style="width:100%;"> + + <tr> + <th>Quelle:</th> + <td> + <mark title="<?php echo $publisher["desc"];?>"> + <?php echo "#" . $publisher["button"]; ?> + </mark> + </td> + </tr> + + <tr> + <th>Region:</th> + <td> + <?php + foreach ($source["regions"] as $region) { + $catentry = $config["regions"][$region] + ?> + <mark title="<?php echo $catentry["description"];?>"> + <?php echo "#" . $catentry["name"]; ?> + </mark> + <?php + } + ?> + </td> + </tr> + + <tr> + <th>Sprachen:</th> + <td> + <?php + foreach ($source["languages"] as $language) { + $catentry = $config["languages"][$language] + ?> + <mark title="<?php echo $catentry["description"];?>"> + <?php echo "#" . $catentry["name"]; ?> + </mark> + <?php + } + ?> + </td> + </tr> + + <tr> + <th>Zugang:</th> + <td> + <?php + foreach ($source["access"] as $access) { + $catentry = $config["access"][$access] + ?> + <mark title="<?php echo $catentry["description"];?>"> + <?php echo "#" . $catentry["name"]; ?> + </mark> + <?php + } + ?> + </td> + </tr> + + <tr> + <th>Medium:</th> + <td> + <?php + foreach ($source["medium"] as $medium) { + $catentry = $config["medium"][$medium] + ?> + <mark title="<?php echo $catentry["description"];?>"> + <?php echo "#" . $catentry["name"]; ?> + </mark> + <?php + } + ?> + </td> + </tr> + + <tr> + <th>Themen:</th> + <td> + <?php + foreach ($source["topics"] as $topic) { + $catentry = $config["topics"][$topic] + ?> + <mark title="<?php echo $catentry["description"];?>"> + <?php echo "#" . $catentry["name"]; ?> + </mark> + <?php + } + ?> + </td> + <tr> + </table> + + </article> + <?php + } + ?> +</form> + +<?php +} +?> diff --git a/lib/gen_html_footer.php b/lib/gen_html_footer.php @@ -0,0 +1,23 @@ +<?php +function gen_html_footer($config){ +?> + +<footer> + <h4>Disclaimer</h4> + <p> + Die Schlagzeilen, Inhalte oder Einstellungen der Redakteur:innen + und Autor:innen der hier aufgeführten Nachrichtenagenturen, + Blogs und Zeitungen spiegeln nicht unbedingt die Meinungen und + Einstellungen der Entwickler:innen und Betreiber:innen von + <em>Kontra</em> wider. <em>Kontra</em> ist ein Quellenarchiv für + Nachrichtenaggregatoren, der Inhalte aus vielen verschiedenen + Quellen zusammenführt werden. <em>Kontra</em> hat + selbstverständlich keinen direkten Einfluss auf den + redaktionellen Inhalt. + </p> + <em>Version:</em> <code><?php echo $config["version"]; ?></code> +</footer> + +<?php +} +?> diff --git a/lib/gen_html_head.php b/lib/gen_html_head.php @@ -0,0 +1,18 @@ +<?php +function gen_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 - Das progressive Nachrichtenarchiv</title> +</head> + +<?php +} +?> diff --git a/lib/gen_html_navigation.php b/lib/gen_html_navigation.php @@ -0,0 +1,23 @@ +<?php +function gen_html_navigation() { +?> + +<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>Das progressive Nachrichtenarchiv</p> +</header> + +<?php +} +?> diff --git a/lib/gen_html_preview.php b/lib/gen_html_preview.php @@ -0,0 +1,92 @@ +<?php +function gen_preview($config) { + + /* 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]] + ); + } + + + $feed = array(); + foreach ($sources as $source) { + $tmp = parse_rss( + $source["rss"], + $source["topics"], + $config["publisher"][$source["publisher"][0]]["name"] . ": " . + $source["title"] + ); + foreach ($tmp as $item) { + array_push($feed, $item); + } + } + + uasort($feed, "sort_by_date_rev"); + + +?> + +<!doctype html> +<html> + + <!-- Head --> + <?php gen_html_head(); ?> + + <!-- Body --> + <body> + + <!-- Header / Navigation --> + <?php gen_html_navigation(); ?> + + <!-- Feed Preview --> +<?php + foreach ($feed as $item) { +?> + <section> + <!-- Headline --> + <h3> + <a + href="<?php echo $item["link"]; ?>" + target="_blank" + rel="nofollow noindex ugc" + > + <?php echo $item["title"]; ?> + </a> + </h3> + <!-- Information --> + <em><?php echo $item["publ"]; ?></em> + <br> + <em><?php echo $item["date"]; ?></em> + <!-- Content --> + <p><?php echo $item["desc"]; ?></p> + <!-- Categories --> + <?php + foreach ($item["cats"] as $cat) { + ?> + <mark><?php echo $config["topics"][$cat]["name"]; ?></mark> + <?php + } + ?> + </section> + +<?php + } +?> + + <!-- Footer --> + <?php gen_html_footer(); ?> + + </body> + +</html> + +<?php +} +?> diff --git a/lib/gen_html_usage.php b/lib/gen_html_usage.php @@ -0,0 +1,88 @@ +<?php +function gen_html_usage($config) { +?> + +<div class="fullheight screenshots" id="usage"> + <h3>Was ist Kontra?</h3> + <figure class="buttonrow"> + <img style="flex:26%;min-width:91px;margin:2.5px;" src="assets/img/applications/gfeeds_mobile.jpg"> + <img style="flex:72%;min-width:252px;margin:2.5px;" src="assets/img/applications/gfeeds_desktop.jpg"> + <figcaption style="width:100%;"> + Nachrichten Feeds aus Kontra in <a href="https://gfeeds.gabmus.org/" target="_blank">Gnome Feeds</a> + </figcaption> + </figure> + <p> + Kontra versetzt Nutzer:innen in die Lage, selbstbestimmt + personalisierte Nachrichten-Feeds von seriösen <em>progressiven</em> + Quellen zu erstellen, um immer auf dem Laufenden zu bleiben. + Und das selbstverständlich + <strong>ohne <a href="https://de.wikipedia.org/wiki/Web_Analytics" target="_blank">Tracking</a></strong>, + <strong>ohne Datensammelwut</strong>, + <strong>ohne Konto-Zwang</strong> + <strong>ohne <a href="https://de.wikipedia.org/wiki/Soziales_Netzwerk_(Internet)#Kritik" target="_blank">Algorithmen</a></strong> und + <strong>ohne <a href="https://de.wikipedia.org/wiki/Lock-in-Effekt" target="_blank">Lock-In Effekte</a></strong>. + Wie das funktioniert, erfährst du <a href="#faqs">hier</a>! + </p> + <p> + Die in Kontra hinterlegten Medien behandeln ein breites Spektrum + an Themen und mit unterschiedlichen Fokuspunkten. Sie vereint + eine <em>progressive</em> und politisch <em>linke</em> + Sichtweise. Die Idee hinter Kontra ist, die Nutzung von Medien + zu vereinfachen und Menschen in die Lage zu versetzen, selbst + kuratierte Nachrichtenquellen und Themenbereiche zu verfolgen. + </p> + <p> + Kontra ist ein Archiv mit aktuell + <strong><?php echo count($config["sources"]); ?></strong> + Nachrichten-Feeds aus + <strong><?php echo count($config["publisher"]); ?></strong> + unterschiedlichen Quellen, zu + <strong><?php echo count($config["topics"]); ?></strong> + Themenbereichen, innerhalb von + <strong><?php echo count($config["regions"]); ?></strong> + Regionen, in + <strong><?php echo count($config["languages"]); ?></strong> + verschiedenen Sprachen. Nutzer:innen können sich aus diesem + Katalog eigene Nachrichten-Feeds gänzlich nach ihren Interessen + zusammenstellen. Die hier herunterladbaren + <a href="https://de.wikipedia.org/wiki/Outline_Processor_Markup_Language" target="_blank"> + Nachrichten-Feed Dateien</a> + können in beliebigen + <a href="https://de.wikipedia.org/wiki/Feedreader" target="_blank"> + Feed-Readern</a> + eingeladen und sofort genutzt werden! + Zum Beispiel in diesen + <a href="https://fsfe.org/freesoftware/freesoftware.de.html" target="_blank"> + Freien</a> + und kostenlosen Apps für Android und iOS: + <ul> + <li><a href="https://apps.apple.com/us/app/netnewswire-rss-reader/id1480640210" target="_blank">NetNewsWire (iOS)</a></li> + <li><a href="https://apps.apple.com/us/app/twine-rss-reader/id6465694958" target="_blank">Twine (iOS)</a></li> + <li><a href="https://play.google.com/store/apps/details?id=com.nononsenseapps.feeder.play" target="_blank">Feeder (Android)</a></li> + <li><a href="https://play.google.com/store/apps/details?id=dev.sasikanth.rss.reader" target="_blank">Twine (Android)</a></li> + <li><a href="https://freshrss.org/" target="_blank">FreshRSS (Web)</a></li> + <li><a href="https://www.thunderbird.net/de/" target="_blank">Thunderbird (Windows, MacOS, Linux)</a></li> + <li><a href="https://gfeeds.gabmus.org/" target="_blank">Feeds (Linux)</a></li> + <li><a href="https://apps.gnome.org/de/NewsFlash/" target="_blank">NewsFlash (Linux)</a></li> + <li><a href="https://apps.kde.org/de/alligator/" target="_blank">Alligator (Linux)</a></li> + <li><a href="https://alternativeto.net/browse/search/?q=rss%20reader" target="_blank">und viele weitere</a>...</li> + </ul> + </p> + <p> + Ganz einfach in nur <strong>zwei Minuten</strong> loslegen! + Nachrichtenquellen aussuchen, Feed-Datei herunterladen, in + den Reader importieren und sofort informiert werden. + </p> + <div class="buttonrow"> + <a href="#faqs" class="button c2"> + Mehr erfahren + </a> + <a href="#sources" class="button c2"> + Zu den Nachrichten! + </a> + </div> +</div> + +<?php +} +?> diff --git a/lib/gen_opml.php b/lib/gen_opml.php @@ -0,0 +1,83 @@ +<?php + +function gen_opml($config) { + + /* 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]] + ); + } + + $exp_hash = md5(serialize($sources)); + $file_name = "kontra_" . date("Y-m-d") . "_" . $exp_hash . ".opml"; + + /* Set Download and content type headers */ + header('Content-Type: application/xml; charset=UTF-8'); + header('Content-Disposition: Attachment;filename="' . $file_name . '"'); + + /* Build OPML file */ +?> + +<opml version="2.0"> +<head> + <title> + Nachrichten-Export von Kontra - + <?php echo "https://" . $_SERVER["SERVER_NAME"] . PHP_EOL; ?> + </title> +</head> +<body> + +<?php + + /* Cycle through each source and write source entry */ + $indexes = array( + "regions", "languages", "access", "medium", "topics" + ); + foreach ($sources as $source) { + + /* Construct title */ + $title = $config["publisher"][$source["publisher"][0]]["name"] . + ": " . $source["title"]; + + /* Create category list */ + $categories = array(); + foreach ($indexes as $index) { + foreach ($source[$index] as $category) { + array_push( + $categories, + $config[$index][$category]["name"] + ); + } + } + +?> + +<outline + title="<?php echo $title; ?>" + text="<?php echo $title; ?>" + category="<?php echo implode(",", $categories); ?>" + xmlUrl="<?php echo $source["rss"]; ?>" + htmlUrl="<?php echo $source["web"]; ?>" +/> + +<?php + + } // foreach-source + +?> + +</body> +</opml> + +<?php + +} // function + +?> diff --git a/lib/parse_rss.php b/lib/parse_rss.php @@ -0,0 +1,62 @@ +<!-- +SPDX-License-Identifier: AGPL-3.0-or-later +SPDX-FileCopyrightText: 2025 JayVii <jayvii+kontra[AT]posteo[DOT]de> +--> +<?php + +function parse_rss($url, $categories, $name) { + + /* gather XML from URL */ + $xml = simplexml_load_file($url); + + /* parse every item from XML */ + $out = array(); + for ($i = 0; $i < count($xml->channel->item); $i++) { + + /* fetch required objects */ + $title = (string) $xml->channel->item[$i]->title; + $link = (string) $xml->channel->item[$i]->link; + $description = (string) $xml->channel->item[$i]->description; + $pubDate = (string) $xml->channel->item[$i]->pubDate; + $timestamp = (string) strtotime($pubDate); + + /* insert objects into array*/ + array_push( + $out, + array( + "publ" => $name, + "cats" => $categories, + "title" => $title, + "link" => $link, + "desc" => $description, + "date" => $pubDate + ) + ); + + } + + /* return final array */ + return($out); + +} + +/* Sort by date */ +function sort_by_date($a, $b) { + $at = strtotime($a["date"]); + $bt = strtotime($b["date"]); + if ($at > $bt) { + return(+1); + } + if ($at < $bt) { + return(-1); + } + if ($at == $bt) { + return(0); + } +} +function sort_by_date_rev($a, $b) { + return(sort_by_date($a, $b) * (-1)); +} + +?> + diff --git a/news-sources.json b/news-sources.json @@ -1,5 +1,5 @@ { - "version": "1.2.9", + "version": "1.3.0", "sources": { "drr": { "title": "Alle Artikel", @@ -4503,4 +4503,4 @@ "description": "Wissenschaft und Forschung" } } -} -\ No newline at end of file +}