Feed-Reader
Ein minimalistischer Feed-Reader, erster Funktionstest des Pakets XML. Erforderlich ist außerdem das Tool wget, das Internet-Quellen einliest. Bei Linux ist es im Lieferumfang, bei Windows müsste es besorgt werden.
Feeds sind auszuwählen mit Kontext-Menü. Durch Anklicken wird ein Browserfenster geöffnet.
Vegnügen!
#!/usr/bin/tclsh # # file: rssreader.tcl # # Minimalistic RSS reader # Prerequisites: package XML by wdb # external tools: # wget # Any web browser # # Costomize feeds: # see procedure setMenu below # # caveats: tested on Linux # should work on Windows as well if wget is present # package require Tk if {[info commands send] ne ""} then { if {[tk appname feedreader] ne "feedreader"} then { send feedreader { wm withdraw . wm deiconify . } exit } } ::tcl::tm::path add ~/bin/TM package require XML namespace import ::tcl::mathop::* # variable browserCommand opera # variable browserCommand "chromium-browser -new-window" variable browserCommand "firefox -new-window" variable prefs { geometry {} links {} title {} font {Times 14} visited {} } variable visited {} proc markVisited href { variable prefs dict set prefs visited $href [clock seconds] } proc linkColor href { variable prefs expr { $href in [dict keys [dict get $prefs visited]] ? "maroon" : "" } } if {[info script] eq ""} then { variable initFile ~/.rssreader.tcl } else { variable initFile\ [file normalize [file join ~ .[file tail [info script]]]] } proc cat file { set chan [open $file r] set result [read $chan] close $chan set result } proc wget url { exec wget -U google-chrome -q -O - $url } proc rssLinks tree { set paths [xml findElementsByName $tree item] foreach path $paths { set item [xml getElement $tree {*}$path] lassign [xml findElementsByName $item link] linkPath lassign [xml findElementsByName $item title] titlePath lappend result\ [string trim [xml getText $item {*}$titlePath]]\ [string map {{ } %20} [xml getText $item {*}$linkPath]] } lappend result } proc atomLinks tree { set paths [xml findElementsByName $tree entry] foreach path $paths { set entry [xml getElement $tree {*}$path] lassign [xml findElementsByName $entry title] titlePath lappend result\ [string trim [xml getText $entry {*}$titlePath]] set paths [xml findElementsByName $entry link] foreach path $paths { set linkElement [xml getElement $entry {*}$path] if {[dict exists $linkElement attribute rel] && [dict get $linkElement attribute rel] eq "alternate"} break } lappend result [string map {{ } %20} [dict get $linkElement attribute href]] } lappend result } proc rdfLinks tree { foreach path [xml findElementsByName $tree item] { set item [xml getElement $tree {*}$path] lassign [xml findElementsByName $item title] titlePath lassign [xml findElementsByName $item link] linkPath lappend result\ [xml getText $item {*}$titlePath]\ [string map {{ } %20} [xml getText $item {*}$linkPath]] } lappend result } proc readLinks url { set tree [xml parse [wget $url]] switch -exact -- [dict get $tree name] { rss { rssLinks $tree } feed { atomLinks $tree } rdf - rdf:RDF { rdfLinks $tree } default { return -code error "[info level 0] -- unkown [dict get $tree name]" } } } # window bind [winfo class .] <Destroy> exit proc hideScrollBars {} { lassign [.v get] a b if {$b - $a == 1} then { place .t -width 0 place .h -width 0 } else { place .t -width -[winfo reqwidth .v] place .h -width -[winfo reqwidth .v] } lassign [.h get] c d if {$d - $c == 1} then { place .t -height 0 place .v -height 0 } else { place .t -height -[winfo reqheight .h] place .v -height -[winfo reqheight .h] } } proc vScrollbarSet {a b} { .v set $a $b after cancel hideScrollBars after idle hideScrollBars } proc hScrollbarSet {a b} { .h set $a $b after cancel hideScrollBars after idle hideScrollBars } destroy .h .v .t text .t\ -font [dict get $prefs font]\ -cursor ""\ -wrap none\ -highlightthickness 0\ -foreground navy\ -background LightYellow1\ -yscrollcommand vScrollbarSet\ -xscrollcommand hScrollbarSet scrollbar .v\ -orient vertical\ -command {.t yview} scrollbar .h\ -orient horizontal\ -command {.t xview} frame .t.destroy bind .t.destroy <Destroy> [list apply { {} { variable prefs variable initFile dict set prefs geometry [wm geometry .] dict set prefs font [.t cget -font] set chan [open $initFile w] puts $chan $prefs close $chan } }] place .t\ -anchor nw\ -relheight 1.0\ -height -[winfo reqheight .h]\ -relwidth 1.0\ -width -[winfo reqwidth .v] place .v\ -relx 1.0\ -anchor ne\ -relheight 1.0\ -height -[winfo reqheight .h] place .h\ -rely 1.0\ -anchor sw\ -relwidth 1.0\ -width -[winfo reqwidth .v] raise .t bind . <FocusIn> {focus .t} bind .t <Control-plus> { apply { win { set font [$win cget -font] lassign $font family size if {$size < 18} then { $win configure -font [list $family [incr size]] } } } %W } bind .t <Control-minus> { apply { win { set font [$win cget -font] lassign $font family size if {$size > 8} then { $win configure -font [list $family [incr size -1]] } } } %W } bind .t <Control-0> { %W configure -font "Times 14" } wm title . RSS-Reader wm geometry . 400x300 .t replace 1.0 end " RSS-Feed mit Kontextmenü auswählen! Choose RSS feed with context menu!" .t configure -state disabled proc decode str { lappend map \ufffd {} {*}{ < < > > & & " " " " " " ' ʼ ä ä ö ö ü ü ß ß "\n" " " Ä Ä Ö Ö Ü Ü } set decEnt [regexp -inline -all {&#[0-9]+;} $str] foreach ent [lsort -unique $decEnt] { regexp {[[:digit:]]+} $ent dec lappend map $ent [format %c $dec] } string map $map $str } proc setLinks url { variable browserCommand variable prefs if {$url ne ""} then { dict set prefs links [readLinks $url] dict set prefs geometry [wm geometry .] dict set prefs font [.t cget -font] } .t delete 1.0 end foreach {text href} [dict get $prefs links] { .t insert insert " [string trim [decode $text]] " href[incr i] \n {} .t tag configure href$i\ -borderwidth 2 -background [.t cget -background] -foreground [linkColor $href] .t tag bind href$i <Enter> " .t tag configure href$i -foreground red .t configure -cursor hand1 " .t tag bind href$i <Leave>\ [subst -nocommand { .t tag configure href$i -background {} -relief flat -foreground [linkColor $href] .t configure -cursor "" }] .t tag bind href$i <1> " .t tag configure href$i\ -relief sunken -background LightYellow2 -foreground {} update " .t tag bind href$i <1><ButtonRelease> " after 1500 [list .t configure -cursor [.t cget -cursor]] exec {*}$browserCommand [string map {& & % %%} $href] & .t tag configure href$i\ -relief flat -background [.t cget -background] -foreground red .t tag remove sel 1.0 end .t configure -cursor watch markVisited $href " } .t delete end-1chars .t configure -state disabled } proc setRSS {name url} { variable prefs dict set prefs title "Feed: [join $name { ⇨ }]" wm title . [dict get $prefs title] .t configure -state normal .t replace 1.0 end " $url" tk busy .t update tk busy forget .t setLinks $url } menu .m bind .t <3><ButtonRelease> {after idle "tk_popup .m %X %Y" 0} # bind Menu <Map> {wm title %W Feed} bind Menu <Map> [list apply { win { if {[string match tearoff* [wm title $win]]} then { after idle [list wm title $win Feed] } } } %W] proc checkVisited {} { variable prefs set now [clock seconds] dict for {href date} [dict get $prefs visited] { if {$now - $date > (3600 * 24 * 7)} then { dict unset prefs visited $href } } after cancel [info level 0] after 600000 [info level 0] } proc setMenu {l {menu .m} {leading {}}} { destroy $menu menu $menu foreach {action label what} $l { switch -exact -- $action { command { $menu add command\ -label $label\ -command [list setRSS [concat $leading [list $label]] $what] } menu { $menu add cascade\ -label $label\ -menu [setMenu $what $menu.[incr i] [concat $leading [list $label]]] } default { $menu add separator } } } set menu } setMenu { menu Polit { command Burks https://www.burks.de/burksblog/feed command Rubikon https://www.rubikon.news/artikel.atom command Kenfm https://kenfm.de/feed/ - - - command ScienceFiles https://sciencefiles.org/feed/ command Deutschland-Kurier https://www.deutschland-kurier.org/feed/ command "Achse der Guten" https://www.achgut.com/rss2 command German-foreign-policy https://www.german-foreign-policy.com/feed.rss command "Alles Schall und Rauch"\ http://alles-schallundrauch.blogspot.com/feeds/posts/default command PI http://www.pi-news.net/feed/ command "Jürgen Fritz" https://juergenfritz.com/feed/ command Publico https://www.publicomag.com/feed/ command Danisch http://www.danisch.de/blog/feed/ - - - command "Norbert Häring"\ http://norberthaering.de/de/?format=feed&type=rss command Fassadenkratzer https://fassadenkratzer.wordpress.com/feed/ command Voltaire\ http://www.voltairenet.org/spip.php?page=backend&id_secteur=1110&lang=de menu "Philosophia Perennis" { command "Alle Themen" https://philosophia-perennis.com/?feed=rss2 command "APO 2018" https://philosophia-perennis.com/category/apo-2018/?feed=rss2 command Islamisierung\ https://philosophia-perennis.com/category/islamisierung/?feed=rss2 command Gender\ https://philosophia-perennis.com/category/genderwahnsinn/?feed=rss2 } command Anti-Spiegel https://www.anti-spiegel.ru/feed/ command Tichy https://www.tichyseinblick.de/feed } menu Law { command Lawblog http://www.lawblog.de/index.php/feed/ command Richtersicht http://www.richtersicht.de/feed/ command Kompa https://kanzleikompa.de/feed/ command WBS https://www.wbs-law.de/feed/ command Verfassungsblog https://verfassungsblog.de/feed/ command LTO https://www.lto.de/nachrichten-rss/rss/feed.xml command "De Legibus" https://blog.delegibus.com/feed/ command "Wilfried Schmitz" https://www.rechtsanwalt-wilfried-schmitz.de/feed/ } menu Zeitung { menu NOZ { command Samtgemeinde https://www.noz.de/rss/ressort/Samtgemeinde Artland command Bramsche https://www.noz.de/rss/ressort/Bramsche command Bersenbrück https://www.noz.de/rss/ressort/Samtgemeinde Bersenbrück command Osnabrück https://www.noz.de/rss/ressort/Osnabrück command Niedersachsen https://www.noz.de/rss/ressort/Niedersachsen command Politik https://www.noz.de/rss/ressort/Politik command Sport https://www.noz.de/rss/ressort/Sport command Wirtschaft https://www.noz.de/rss/ressort/Wirtschaft command Kultur https://www.noz.de/rss/ressort/Kultur command Medien https://www.noz.de/rss/ressort/Medien command Vermischtes https://www.noz.de/rss/ressort/Vermischtes } menu NZZ { command "Neuste Artikel" http://www.nzz.ch/recent.rss command "Topthemen der Startseite" http://www.nzz.ch/startseite.rss command International http://www.nzz.ch/international.rss command Schweiz http://www.nzz.ch/schweiz.rss command Wirtschaft http://www.nzz.ch/wirtschaft.rss command Finanznachrichten http://www.nzz.ch/finanzen.rss command Kultur http://www.nzz.ch/feuilleton.rss command Sport http://www.nzz.ch/sport.rss command Zürich http://www.nzz.ch/zuerich.rss command Panorama http://www.nzz.ch/panorama.rss command Wissenschaft http://www.nzz.ch/wissenschaft.rss command Auto http://www.nzz.ch/mobilitaet/auto-mobil.rss command Digital http://www.nzz.ch/mehr/digital.rss command Lebensart http://www.nzz.ch/lebensart.rss } menu taz { command "Alle Artikel" https://taz.de/!s=&ExportStatus=Intern&SuchRahmen=Online;rss/ command Politik https://taz.de/!p4615;rss/ command Deutschland https://taz.de/!p4616;rss/ command Öko https://taz.de/!p4610;rss/ command Gesellschaft https://taz.de/!p4611;rss/ command Kultur https://taz.de/!p4639;rss/ command Berlin https://taz.de/!p4649;rss/ command Nord https://taz.de/!p4650;rss/ command Wahrheit https://taz.de/!p4644;rss/ command Sport https://taz.de/!p4646;rss/ } menu Spiegel { command Schlagzeilen https://www.spiegel.de/schlagzeilen/index.rss command Kultur https://www.spiegel.de/kultur/index.rss command Gesellschaft https://www.spiegel.de/kultur/gesellschaft/index.rss command "Slavoj Zizek" https://www.spiegel.de/thema/slavoj_zizek/dossier.rss } menu Welt { command Neu https://www.welt.de/feeds/latest.rss command Nachrichten https://www.welt.de/feeds/topnews.rss command Mediathek https://www.welt.de/feeds/section/mediathek.rss command Videos https://www.welt.de/feeds/section/videos.rss command Politik https://www.welt.de/feeds/section/politik.rss command Wirtschaft https://www.welt.de/feeds/section/wirtschaft.rss command Bilanz https://www.welt.de/feeds/section/wirtschaft/bilanz.rss command Geld https://www.welt.de/feeds/section/finanzen.rss command Digital https://www.welt.de/feeds/section/wirtschaft/webwelt.rss command Wissen https://www.welt.de/feeds/section/wissenschaft.rss command Kultur https://www.welt.de/feeds/section/kultur.rss command Sport https://www.welt.de/feeds/section/sport.rss command Icon https://www.welt.de/feeds/section/icon.rss command Gesundheit https://www.welt.de/feeds/section/gesundheit.rss command Panorama https://www.welt.de/feeds/section/vermischtes.rss command Motor https://www.welt.de/feeds/section/motor.rss command Reise https://www.welt.de/feeds/section/reise.rss command Regional https://www.welt.de/feeds/section/regionales.rss command Meinung https://www.welt.de/feeds/section/debatte.rss } menu Hessenschau { command Alle https://www.hessenschau.de/index.rss menu Hessen { command Rhein-Main https://www.hessenschau.de/rheinmain/index.rss command Nordhessen https://www.hessenschau.de/nordhessen/index.rss command Mittelhessen https://www.hessenschau.de/mittelhessen/index.rss command Osthessen https://www.hessenschau.de/osthessen/index.rss command Südhessen https://www.hessenschau.de/suedhessen/index.rss } command Politik https://www.hessenschau.de/politik/index.rss command Gesellschaft https://www.hessenschau.de/gesellschaft/index.rss command Wirtschaft https://www.hessenschau.de/wirtschaft/index.rss command Kultur https://www.hessenschau.de/kultur/index.rss command Sport https://www.hessenschau.de/sport/index.rss command Panorama https://www.hessenschau.de/panorama/index.rss command Freizeit https://www.hessenschau.de/freizeit/index.rss } command Meedia https://meedia.de/feed/ command Süddeutsche https://rss.sueddeutsche.de/rss/Topthemen command Cicero https://www.cicero.de/rss.xml command Epoch https://www.epochtimes.de/?feed=rss command RT-Deutsch https://deutsch.rt.com/feeds/news/ command Wochenblick https://www.wochenblick.at/feed/ command tz http://www.tz.de/rssfeed.rdf } menu Gender { command Genderama http://genderama.blogspot.com/feeds/posts/default command Auschfrei https://auschfrei.wordpress.com/feed/ menu Frauen { command PinkStinks https://pinkstinks.de/feed/ command "Antje Schrupp" https://antjeschrupp.com/feed/ command Störenfriedas https://diestoerenfriedas.de/feed/ command IfGbsG https://ifgbsg.org/feed/ command Missy https://missy-magazine.de/feed/ command Mädchenmannschaft https://maedchenmannschaft.net/feed/ command "Andreas Kemper" https://andreaskemper.org/feed/ } menu Männer { command "Maskulismus für Anfänger"\ https://maninthmiddle.blogspot.com/feeds/posts/default command "man tau" https://man-tau.com/feed/ command uepsiloniks https://uepsilonniks.wordpress.com/feed/ command "Jungs und Mädchen" https://jungsundmaedchen.wordpress.com/feed/ command Männermagazin https://das-maennermagazin.com/blog/feed command Stapelchips https://stapelchipsblog.wordpress.com/feed/ command "Alles Evolution" https://allesevolution.wordpress.com/feed/ command Alternativlos-Aquarium https://alternativlos-aquarium.blogspot.com/feeds/posts/default } menu Prostitution { command Ella https://netzwerk-ella.de/index.php/feed/ command Streetgirl https://streetgirl.twoday.net/index.rdf } command Cuncti http://cuncti.net/?format=feed&type=rss command "Philosophia Perennis"\ https://philosophia-perennis.com/category/genderwahnsinn/?feed=rss2 command Apokolokynthose https://apokolokynthose.wordpress.com/feed/ } menu Left { command Nachdenkseiten https://www.nachdenkseiten.de/?feed=rss2 command Feynsinn https://feynsinn.org/?feed=rss2 command Neulandrebellen https://www.neulandrebellen.de/feed/ command ND https://www.neues-deutschland.de/rss/aktuell.php command Rubikon https://www.rubikon.news/artikel.atom command "Ad Sinistram" https://ad-sinistram.blogspot.com/feeds/posts/default } menu Science { command Scinexx https://www.scinexx.de/feed/ menu "Wissenschaft aktuell" { command Allgemein https://www.wissenschaft-aktuell.de/onTEAM/Wissenschaft-Aktuell.xml command Mensch https://www.wissenschaft-aktuell.de/onTEAM/WSA-Mensch.xml command Technik https://www.wissenschaft-aktuell.de/onTEAM/WSA-Technik.xml command Natur https://www.wissenschaft-aktuell.de/onTEAM/WSA-Natur.xml command Weltraum https://www.wissenschaft-aktuell.de/onTEAM/WSA-Weltraum.xml command Geist https://www.wissenschaft-aktuell.de/onTEAM/WSA-Geist.xml command Energie https://www.wissenschaft-aktuell.de/onTEAM/WSA-Energie.xml } command Spiegel https://www.spiegel.de/wissenschaft/index.rss command Astrodictium http://scienceblogs.de/astrodicticum-simplex/feed/ command "Forschung und Wissen" https://www.forschung-und-wissen.de/feed.rss } menu Verschiedenes { command "Gott und die Welt" http://gottunddiewelt.net/feed/ command "Mathias Broeckers" https://www.broeckers.com/feed/ command Neusprech https://neusprech.org/feed/ command Saftpresse https://diesaftpressederleutevomortundderjunge.com/feed/ command Salonkolumnisten https://www.salonkolumnisten.com/feed/ command "Ina Eff" https://nachdenklichekrankenschwester.blog/feed/ command "Neue Debatte" https://neue-debatte.com/feed/ } - - - menu Heise { command Telepolis https://www.heise.de/tp/news-atom.xml menu IT { command Newsticker https://www.heise.de/rss/heise-atom.xml command Developer https://www.heise.de/developer/rss/news-atom.xml command Netze https://www.heise.de/thema/netze?view=atom command "Open Source" https://www.heise.de/thema/linux-und-open-source?view=atom command Security https://www.heise.de/security/rss/news-atom.xml } command "Technology Review" https://www.heise.de/tr/rss/news-atom.xml command Autos http://www.heise.de/autos/rss/news-atom.xml command TechStage http://www.techstage.de/rss.xml command cʼt https://www.heise.de/ct/rss/artikel-atom.xml command iX http://www.heise.de/ix/rss/news-atom.xml command Fotografie https://www.heise.de/foto/rss/news-atom.xml command Mac&i https://www.heise.de/mac-and-i/news-atom.xml command Make https://www.heise.de/make/rss/hardware-hacks-atom.xml } command Newsticker https://www.heise.de/rss/heise-atom.xml command Golem https://rss.golem.de/rss.php?feed=RSS1.0 command Gulli https://www.gulli.com/feed/ - - - command Pornoanwalt https://pornoanwalt.de/?feed=rss2 command Schockwellenreiter http://blog.schockwellenreiter.de/feed/rss.xml command Rebellmarkt https://rebellmarkt.blogger.de/rss menu Pollmer { command EU.L.E https://euleev.de/?format=feed&type=rss command Podcast https://podcast.euleev.de/eule.xml } command "Acta Diurna" https://michael-klonovsky.de/acta-diurna?format=feed&type=rss command Tagebuch http://wolf-dieter-busch.de/blog/rss.xml command "Russland aktuell" https://www.fit4russland.com/?format=feed&type=rss command Sputnik https://de.sputniknews.com/export/rss2/archive/index.xml command "Der kleine Akif" https://der-kleine-akif.de/feed/ command fefe http://blog.fefe.de/rss.xml?html command Parnassos http://www.felix-bartels.de/feed/ command Jouwatch https://www.journalistenwatch.com/feed/ command PinkKosherNostra https://pinkkoshernostra.org/feed/ command Prinzessinnenreporter https://www.prinzessinnenreporter.de/feed/ menu underdogs { command deliberationdaily http://www.deliberationdaily.de/feed/ command "Fliegende Bretter" https://fliegende-bretter.blogspot.com/feeds/posts/default command "Tante Jay" https://tantejay.com/feed/ } } apply { script { set state [.t cget -state] .t configure -state normal variable prefs variable initFile if {[catch { if [file exists $initFile] then { set prefs [dict replace $prefs {*}[cat $initFile]] .t configure -font [dict get $prefs font] wm geometry . [dict get $prefs geometry] wm title . [dict get $prefs title] after 100 checkVisited setLinks "" } } err]} then { puts $err } .t configure -state $state } } [info script]
Um den Browser einzustellen, Quelltext anpassen (suche „variable browserCommand“).
Um eigene Feed-Quellen einzutragen, Quelltext anpassen (suche „Hier Feeds erstellen“). Die Voreinstellung zeigt beispielhaft, wie es geht.
Einige Quellen laden grottig langsam – da bleibt nichts übrig, als sich in Geduld zu fassen. Einige Quellen werfen die Fehlermeldung „Zugriff verweigert“.
31.5.2022
<< | Heimatseite | Verzeichnis | Stichworte | Autor | >>