Add preview commands (read and select) and experimenting with XEP-0249

This commit is contained in:
Schimon Jehudah 2023-11-26 05:48:09 +00:00
parent efa05aaba1
commit 31baf96430
31 changed files with 584 additions and 176 deletions

View file

@ -0,0 +1,2 @@
name, url, language, country
HELLOTUX Blog, https://www.hellotux.com/rss.php, en-US, Hungary
1 name url language country
2 HELLOTUX Blog https://www.hellotux.com/rss.php en-US Hungary

2
datasets/events/xmpp.csv Normal file
View file

@ -0,0 +1,2 @@
name, url, language, country
Berlin XMPP Meetup, https://mov.im/feed/pubsub.movim.eu/berlin-xmpp-meetup, en-US, Germany
1 name url language country
2 Berlin XMPP Meetup https://mov.im/feed/pubsub.movim.eu/berlin-xmpp-meetup en-US Germany

View file

@ -0,0 +1,2 @@
name, url, language, country
eGPU.io, https://egpu.io/feed/, en-US, Worldwide
1 name url language country
2 eGPU.io https://egpu.io/feed/ en-US Worldwide

View file

@ -1,2 +1,3 @@
name, url, language, country name, url, language, country
Blender Developer Forum - Latest posts, https://devtalk.blender.org/posts.rss, en-US, USA Blender Developer Forum - Latest posts, https://devtalk.blender.org/posts.rss, en-US, United States
eGPU.io, https://egpu.io/feed/, en-US, Worldwide

1 name url language country
2 Blender Developer Forum - Latest posts https://devtalk.blender.org/posts.rss en-US USA United States
3 eGPU.io https://egpu.io/feed/ en-US Worldwide

View file

@ -1,2 +1,3 @@
name, url, language, country name, url, language, country
Leak Zone - Leaking & Cracking Forum - All Forums, https://leakzone.net/syndication.php?type=atom1.0, en-US, Worldwide Leak Zone - Leaking & Cracking Forum, https://leakzone.net/syndication.php?type=atom1.0, en-US, Worldwide
Pale Moon, https://forum.palemoon.org/app.php/feed/forum/1, en-US, Worldwide

1 name url language country
2 Leak Zone - Leaking & Cracking Forum - All Forums Leak Zone - Leaking & Cracking Forum https://leakzone.net/syndication.php?type=atom1.0 en-US Worldwide
3 Pale Moon https://forum.palemoon.org/app.php/feed/forum/1 en-US Worldwide

View file

@ -0,0 +1,3 @@
name, url, language, country
Pale Moon, https://forum.palemoon.org/app.php/feed, en-US, Worldwide
Transmission BT, https://forum.transmissionbt.com/app.php/feed, en-US, Worldwide
1 name url language country
2 Pale Moon https://forum.palemoon.org/app.php/feed en-US Worldwide
3 Transmission BT https://forum.transmissionbt.com/app.php/feed en-US Worldwide

View file

@ -3,3 +3,4 @@ The Public Domain Review, https://publicdomainreview.org/rss.xml, en-US, United
třiapůl česky, https://triapul.cz/feed/cesky.xml, cz-CZ, Czech třiapůl česky, https://triapul.cz/feed/cesky.xml, cz-CZ, Czech
triapul.cz, http://triapul.cz/feed/english.xml, en-US, Czech triapul.cz, http://triapul.cz/feed/english.xml, en-US, Czech
techno-mage in:, https://bsd.network/@prahou.rss, en-US, United States techno-mage in:, https://bsd.network/@prahou.rss, en-US, United States
Behance Featured Projects, https://www.behance.net/feeds/projects, en-US, United States

1 name url language country
3 třiapůl česky https://triapul.cz/feed/cesky.xml cz-CZ Czech
4 triapul.cz http://triapul.cz/feed/english.xml en-US Czech
5 techno-mage in: https://bsd.network/@prahou.rss en-US United States
6 Behance Featured Projects https://www.behance.net/feeds/projects en-US United States

5
datasets/news/bsd.csv Normal file
View file

@ -0,0 +1,5 @@
name, url, language, country
drkhsh, https://drkhsh.at/atom.xml, en-US, Austria
OpenBSD Webzine, https://webzine.puffy.cafe/atom.xml, en-US, United States
Solene'%, https://dataswamp.org/~solene/rss.xml, en-US, United States
Solene'%, https://dataswamp.org/~solene/rss-html.xml, en-US, United States
1 name url language country
2 drkhsh https://drkhsh.at/atom.xml en-US Austria
3 OpenBSD Webzine https://webzine.puffy.cafe/atom.xml en-US United States
4 Solene'% https://dataswamp.org/~solene/rss.xml en-US United States
5 Solene'% https://dataswamp.org/~solene/rss-html.xml en-US United States

View file

@ -12,3 +12,5 @@ ynet - כלכלה, https://www.ynet.co.il/Integration/StoryRss6.xml, he-IL, Isra
דה מרקר - כותרות דף הבית, https://www.themarker.com/srv/tm-all-articles, he-IL, Israel דה מרקר - כותרות דף הבית, https://www.themarker.com/srv/tm-all-articles, he-IL, Israel
דה מרקר - כותרות היום, https://www.themarker.com/srv/tm-news, he-IL, Israel דה מרקר - כותרות היום, https://www.themarker.com/srv/tm-news, he-IL, Israel
דה מרקר - פרשנויות היום, https://www.themarker.com/srv/tm-opinions, he-IL, Israel דה מרקר - פרשנויות היום, https://www.themarker.com/srv/tm-opinions, he-IL, Israel
שוק ההון והשקעות, https://www.globes.co.il/webservice/rss/rssfeeder.asmx/FeederNode?iID=585, he-IL, Israel
StockNews, https://stocknews.com/feed/, en-US, United States

1 name url language country
12 דה מרקר - כותרות דף הבית https://www.themarker.com/srv/tm-all-articles he-IL Israel
13 דה מרקר - כותרות היום https://www.themarker.com/srv/tm-news he-IL Israel
14 דה מרקר - פרשנויות היום https://www.themarker.com/srv/tm-opinions he-IL Israel
15 שוק ההון והשקעות https://www.globes.co.il/webservice/rss/rssfeeder.asmx/FeederNode?iID=585 he-IL Israel
16 StockNews https://stocknews.com/feed/ en-US United States

View file

@ -1,5 +1,6 @@
name, url, language, country name, url, language, country
camen design, https://camendesign.com/rss, en-US, USA Liliputing, https://liliputing.com/feed/, en-US, Worldwide
camen design, https://camendesign.com/rss, en-US, United States
computers are bad, https://computer.rip/rss.xml, en-US, Worldwide computers are bad, https://computer.rip/rss.xml, en-US, Worldwide
Jacob McCormick, https://mccor.xyz/rss.xml, en-US, United States Jacob McCormick, https://mccor.xyz/rss.xml, en-US, United States
OpenNews.opennet.ru: Общая лента новостей, https://www.opennet.ru/opennews/opennews_all_utf.rss, ru-RU, Russia OpenNews.opennet.ru: Общая лента новостей, https://www.opennet.ru/opennews/opennews_all_utf.rss, ru-RU, Russia
@ -58,3 +59,11 @@ alexander cobleigh (articles), https://cblgh.org/articles.xml, en-US, United Sta
Debricked, https://debricked.com/blog/feed/, en-US, United States Debricked, https://debricked.com/blog/feed/, en-US, United States
out there in space, https://dataswamp.org/~lich/atom.xml, en-US, United States out there in space, https://dataswamp.org/~lich/atom.xml, en-US, United States
journal de prx, https://si3t.ch/log/atom.xml, fr-FR, Switzerland journal de prx, https://si3t.ch/log/atom.xml, fr-FR, Switzerland
Kitty Cat, https://kitty.social/@Kitty.rss, en-US, Worldwide
Stephen Foskett, Pack Rat, http://feeds.fosketts.net/StephenFoskettPackRat, en-US, United States
Apple, http://feeds.fosketts.net/StephenFoskettPackRat_Apple, en-US, United States
Computer History, http://feeds.fosketts.net/StephenFoskettPackRat_ComputerHistory, en-US, United States
Enterprise Storage, http://feeds.fosketts.net/StephenFoskettPackRat_EnterpriseStorage, en-US, United States
Personal, http://feeds.fosketts.net/StephenFoskettPackRat_Personal, en-US, United States
Terabyte Home, http://feeds.fosketts.net/StephenFoskettPackRat_TerabyteHome, en-US, United States
Virtual Storage, http://feeds.fosketts.net/StephenFoskettPackRat_VirtualStorage, en-US, United States

Can't render this file because it has a wrong number of fields in line 63.

View file

@ -6,3 +6,4 @@ ollieparanoid, https://ollieparanoid.github.io/feed.xml, en-US, United States
FSFE News, https://fsfe.org/news/news.en.rss, en-US, Germany FSFE News, https://fsfe.org/news/news.en.rss, en-US, Germany
FSFE News (DE), https://fsfe.org/news/news.de.rss, de-DE, Germany FSFE News (DE), https://fsfe.org/news/news.de.rss, de-DE, Germany
FSFE News (FR), https://fsfe.org/news/news.fr.rss, fr-FR, Germany FSFE News (FR), https://fsfe.org/news/news.fr.rss, fr-FR, Germany
Schneier on Security, https://www.schneier.com/feed/atom/, en-US, United States

1 name url language country
6 FSFE News https://fsfe.org/news/news.en.rss en-US Germany
7 FSFE News (DE) https://fsfe.org/news/news.de.rss de-DE Germany
8 FSFE News (FR) https://fsfe.org/news/news.fr.rss fr-FR Germany
9 Schneier on Security https://www.schneier.com/feed/atom/ en-US United States

3
datasets/news/design.csv Normal file
View file

@ -0,0 +1,3 @@
name, url, language, country
Crumina, https://crumina.net/feed/, en-US, Ukraine
Behance Featured Projects, https://www.behance.net/feeds/projects, en-US, United States
1 name url language country
2 Crumina https://crumina.net/feed/ en-US Ukraine
3 Behance Featured Projects https://www.behance.net/feeds/projects en-US United States

2
datasets/news/law.csv Normal file
View file

@ -0,0 +1,2 @@
name, url, language, country
North Carolina Lawyers Weekly, https://nclawyersweekly.com/feed/, en-US, United States
1 name url language country
2 North Carolina Lawyers Weekly https://nclawyersweekly.com/feed/ en-US United States

26
datasets/news/linux.csv Normal file
View file

@ -0,0 +1,26 @@
name, url, language, country
Linux Professional Institute (LPI), https://www.lpi.org/feed/, en-US, Canada
LinuxConfig, https://linuxconfig.org/feed, en-US, Worldwide
The Logs, https://www.flu0r1ne.net/logs/rss.xml, en-US, United States
Ctrl blog: Fedora Linux, https://feed.ctrl.blog/topic/fedora-linux.atom, en-US, United States
Ctrl blog: Linux, https://feed.ctrl.blog/topic/linux.atom, en-US, United States
Anjan Momi, https://momi.ca/feed.xml, en-US, United States
postmarketOS, https://postmarketos.org/blog/feed.atom, en-US, United States
PureTryOut (Alpine Linux, postmarketOS), https://mastodon.fam-ribbers.com/@bart.rss, en-US, Netherlands
Blog on Bart Ribbers - PureTryOut (Alpine Linux, postmarketOS), https://fam-ribbers.com/blog/index.xml, en-US, Netherlands
LZone | Devops, https://lzone.de/feed/devops.xml, en-US, Germany
Necuno Solutions, https://necunos.com/feed.xml, en-US, Finland
Laslo Hunhold, https://laslo.hunhold.de/index.xml, en-US, Germany
Alpine Linux, https://fosstodon.org/@alpinelinux.rss, en-US, United States
ollieparanoid, https://ollieparanoid.github.io/feed.xml, en-US, United States
FSFE News, https://fsfe.org/news/news.en.rss, en-US, Germany
FSFE News (DE), https://fsfe.org/news/news.de.rss, de-DE, Germany
9to5Linux, https://9to5linux.com/feed, en-US, United States
FSFE News (FR), https://fsfe.org/news/news.fr.rss, fr-FR, Germany
Justine Smithies blog, https://justine.smithies.me.uk/atom.xml, en-US, United States
Justine Smithies, https://fosstodon.org/@JustineSmithies.rss, en-US, United States
TuxPhones, https://tuxphones.com/rss/, en-US, United States
Collabora Office and Collabora Online, https://www.collaboraoffice.com/feed/, en-US, United States
LGUG2Z, https://lgug2z.com/index.xml, en-US, United States
Hugo Barrera's site, https://whynothugo.nl/posts.xml, en-US, United States
ShadowKat Studios, https://shadowkat.net/rss.xml, en-US, Worldwide
1 name, url, language, country
2 Linux Professional Institute (LPI), https://www.lpi.org/feed/, en-US, Canada
3 LinuxConfig, https://linuxconfig.org/feed, en-US, Worldwide
4 The Logs, https://www.flu0r1ne.net/logs/rss.xml, en-US, United States
5 Ctrl blog: Fedora Linux, https://feed.ctrl.blog/topic/fedora-linux.atom, en-US, United States
6 Ctrl blog: Linux, https://feed.ctrl.blog/topic/linux.atom, en-US, United States
7 Anjan Momi, https://momi.ca/feed.xml, en-US, United States
8 postmarketOS, https://postmarketos.org/blog/feed.atom, en-US, United States
9 PureTryOut (Alpine Linux, postmarketOS), https://mastodon.fam-ribbers.com/@bart.rss, en-US, Netherlands
10 Blog on Bart Ribbers - PureTryOut (Alpine Linux, postmarketOS), https://fam-ribbers.com/blog/index.xml, en-US, Netherlands
11 LZone | Devops, https://lzone.de/feed/devops.xml, en-US, Germany
12 Necuno Solutions, https://necunos.com/feed.xml, en-US, Finland
13 Laslo Hunhold, https://laslo.hunhold.de/index.xml, en-US, Germany
14 Alpine Linux, https://fosstodon.org/@alpinelinux.rss, en-US, United States
15 ollieparanoid, https://ollieparanoid.github.io/feed.xml, en-US, United States
16 FSFE News, https://fsfe.org/news/news.en.rss, en-US, Germany
17 FSFE News (DE), https://fsfe.org/news/news.de.rss, de-DE, Germany
18 9to5Linux, https://9to5linux.com/feed, en-US, United States
19 FSFE News (FR), https://fsfe.org/news/news.fr.rss, fr-FR, Germany
20 Justine Smithies blog, https://justine.smithies.me.uk/atom.xml, en-US, United States
21 Justine Smithies, https://fosstodon.org/@JustineSmithies.rss, en-US, United States
22 TuxPhones, https://tuxphones.com/rss/, en-US, United States
23 Collabora Office and Collabora Online, https://www.collaboraoffice.com/feed/, en-US, United States
24 LGUG2Z, https://lgug2z.com/index.xml, en-US, United States
25 Hugo Barrera's site, https://whynothugo.nl/posts.xml, en-US, United States
26 ShadowKat Studios, https://shadowkat.net/rss.xml, en-US, Worldwide

View file

@ -2,3 +2,4 @@ name, url, language, country
Stories by Williams, https://storiesbywilliams.com/feed/, en-US, United States Stories by Williams, https://storiesbywilliams.com/feed/, en-US, United States
Lili Saintcrow, https://www.lilithsaintcrow.com/feed/, en-US, United States Lili Saintcrow, https://www.lilithsaintcrow.com/feed/, en-US, United States
Shannon Kay, https://blog.shannonkay.me/feed.xml, en-US, United States Shannon Kay, https://blog.shannonkay.me/feed.xml, en-US, United States
V.K. Dixon, https://vkdixon.substack.com/feed, en-US, United States

1 name url language country
2 Stories by Williams https://storiesbywilliams.com/feed/ en-US United States
3 Lili Saintcrow https://www.lilithsaintcrow.com/feed/ en-US United States
4 Shannon Kay https://blog.shannonkay.me/feed.xml en-US United States
5 V.K. Dixon https://vkdixon.substack.com/feed en-US United States

View file

@ -0,0 +1,2 @@
name, url, language, country
North Carolina Lawyers Weekly, https://nclawyersweekly.com/feed/, en-US, United States
1 name url language country
2 North Carolina Lawyers Weekly https://nclawyersweekly.com/feed/ en-US United States

View file

@ -11,6 +11,7 @@ Blog on Bart Ribbers - PureTryOut, https://fam-ribbers.com/blog/index.xml, en-US
ollieparanoid, https://ollieparanoid.github.io/feed.xml, en-US, United States ollieparanoid, https://ollieparanoid.github.io/feed.xml, en-US, United States
Oliver Smith, https://fosstodon.org/@ollieparanoid, en-US, Germany Oliver Smith, https://fosstodon.org/@ollieparanoid, en-US, Germany
drkhsh, https://drkhsh.at/atom.xml, en-US, Austria drkhsh, https://drkhsh.at/atom.xml, en-US, Austria
Personal, http://feeds.fosketts.net/StephenFoskettPackRat_Personal, en-US, United States
Codemadness, https://codemadness.org/atom.xml, en-US, United States Codemadness, https://codemadness.org/atom.xml, en-US, United States
Keywan Tonekaboni, https://social.heise.de/@ktn.rss, de-DE, Germany Keywan Tonekaboni, https://social.heise.de/@ktn.rss, de-DE, Germany
keywan, https://chaos.social/@keywan.rss, de-DE, Germany keywan, https://chaos.social/@keywan.rss, de-DE, Germany
@ -39,3 +40,4 @@ alexander cobleigh, https://cblgh.org/all.xml, en-US, United States
alexander cobleigh (updates), https://cblgh.org/updates.xml, en-US, United States alexander cobleigh (updates), https://cblgh.org/updates.xml, en-US, United States
Daniel Aleksandersen, https://mastodon.daniel.priv.no/@da.rss, en-US, United States Daniel Aleksandersen, https://mastodon.daniel.priv.no/@da.rss, en-US, United States
Laslo Hunhold, https://laslo.hunhold.de/index.xml, en-US, Germany Laslo Hunhold, https://laslo.hunhold.de/index.xml, en-US, Germany
Kitty Cat, https://kitty.social/@Kitty.rss, en-US, Worldwide

1 name url language country
11 ollieparanoid https://ollieparanoid.github.io/feed.xml en-US United States
12 Oliver Smith https://fosstodon.org/@ollieparanoid en-US Germany
13 drkhsh https://drkhsh.at/atom.xml en-US Austria
14 Personal http://feeds.fosketts.net/StephenFoskettPackRat_Personal en-US United States
15 Codemadness https://codemadness.org/atom.xml en-US United States
16 Keywan Tonekaboni https://social.heise.de/@ktn.rss de-DE Germany
17 keywan https://chaos.social/@keywan.rss de-DE Germany
40 alexander cobleigh (updates) https://cblgh.org/updates.xml en-US United States
41 Daniel Aleksandersen https://mastodon.daniel.priv.no/@da.rss en-US United States
42 Laslo Hunhold https://laslo.hunhold.de/index.xml en-US Germany
43 Kitty Cat https://kitty.social/@Kitty.rss en-US Worldwide

View file

@ -1,2 +1,3 @@
name, url, language, country name, url, language, country
Kasparov, https://www.kasparov.com/feed/, en-US, United States Kasparov, https://www.kasparov.com/feed/, en-US, United States
РЖЕВСКАЯ ПРАВДА, https://presska.ru/feed/, ru-RU, Russia

1 name url language country
2 Kasparov https://www.kasparov.com/feed/ en-US United States
3 РЖЕВСКАЯ ПРАВДА https://presska.ru/feed/ ru-RU Russia

View file

@ -5,6 +5,7 @@ The Logs, https://www.flu0r1ne.net/logs/rss.xml, en-US, United States
CryptoSlate, https://cryptoslate.com/feed/, en-US, United States CryptoSlate, https://cryptoslate.com/feed/, en-US, United States
Codemadness, https://codemadness.org/atom.xml, en-US, United States Codemadness, https://codemadness.org/atom.xml, en-US, United States
Daily Stormer, https://dailystormer.in/feed/, en-US, United States Daily Stormer, https://dailystormer.in/feed/, en-US, United States
ShadowKat Studios, https://shadowkat.net/rss.xml, en-US, Worldwide
Futurism, https://futurism.com/feed, en-US, United States Futurism, https://futurism.com/feed, en-US, United States
drkhsh, https://drkhsh.at/atom.xml, en-US, Austria drkhsh, https://drkhsh.at/atom.xml, en-US, Austria
Automation Rhapsody, https://automationrhapsody.com/feed/, en-US, United States Automation Rhapsody, https://automationrhapsody.com/feed/, en-US, United States

1 name url language country
5 CryptoSlate https://cryptoslate.com/feed/ en-US United States
6 Codemadness https://codemadness.org/atom.xml en-US United States
7 Daily Stormer https://dailystormer.in/feed/ en-US United States
8 ShadowKat Studios https://shadowkat.net/rss.xml en-US Worldwide
9 Futurism https://futurism.com/feed en-US United States
10 drkhsh https://drkhsh.at/atom.xml en-US Austria
11 Automation Rhapsody https://automationrhapsody.com/feed/ en-US United States

View file

@ -2,3 +2,4 @@ name, url, language, country
The XMPP Blog on XMPP, https://xmpp.org/feeds/all.atom.xml, en-US, Worldwide The XMPP Blog on XMPP, https://xmpp.org/feeds/all.atom.xml, en-US, Worldwide
Redecentralize Blog, https://redecentralize.org/blog/feed.rss, en-US, United States Redecentralize Blog, https://redecentralize.org/blog/feed.rss, en-US, United States
ollieparanoid, https://ollieparanoid.github.io/feed.xml, en-US, United States ollieparanoid, https://ollieparanoid.github.io/feed.xml, en-US, United States
ShadowKat Studios, https://shadowkat.net/rss.xml, en-US, Worldwide

1 name url language country
2 The XMPP Blog on XMPP https://xmpp.org/feeds/all.atom.xml en-US Worldwide
3 Redecentralize Blog https://redecentralize.org/blog/feed.rss en-US United States
4 ollieparanoid https://ollieparanoid.github.io/feed.xml en-US United States
5 ShadowKat Studios https://shadowkat.net/rss.xml en-US Worldwide

View file

@ -7,3 +7,4 @@ BlackListed News, https://www.blacklistednews.com/rss.php, en-US, United States
Tampa Free Press, https://www.tampafp.com/feed/, en-US, United States Tampa Free Press, https://www.tampafp.com/feed/, en-US, United States
Real Liberty Media, https://www.reallibertymedia.com/feed/, en-US, United States Real Liberty Media, https://www.reallibertymedia.com/feed/, en-US, United States
Robert Reich, https://robertreich.substack.com/feed, en-US, United States Robert Reich, https://robertreich.substack.com/feed, en-US, United States
North Carolina Lawyers Weekly, https://nclawyersweekly.com/feed/, en-US, United States

1 name, url, language, country
7 Tampa Free Press, https://www.tampafp.com/feed/, en-US, United States
8 Real Liberty Media, https://www.reallibertymedia.com/feed/, en-US, United States
9 Robert Reich, https://robertreich.substack.com/feed, en-US, United States
10 North Carolina Lawyers Weekly, https://nclawyersweekly.com/feed/, en-US, United States

View file

@ -30,3 +30,4 @@ Solene'%, https://dataswamp.org/~solene/rss.xml, en-US, United States
Solene'%, https://dataswamp.org/~solene/rss-html.xml, en-US, United States Solene'%, https://dataswamp.org/~solene/rss-html.xml, en-US, United States
drkhsh, https://drkhsh.at/atom.xml, en-US, Austria drkhsh, https://drkhsh.at/atom.xml, en-US, Austria
OpenBSD Webzine, https://webzine.puffy.cafe/atom.xml, en-US, United States OpenBSD Webzine, https://webzine.puffy.cafe/atom.xml, en-US, United States
ShadowKat Studios, https://shadowkat.net/rss.xml, en-US, Worldwide
1 name, url, language, country
30 Solene'%, https://dataswamp.org/~solene/rss-html.xml, en-US, United States
31 drkhsh, https://drkhsh.at/atom.xml, en-US, Austria
32 OpenBSD Webzine, https://webzine.puffy.cafe/atom.xml, en-US, United States
33 ShadowKat Studios, https://shadowkat.net/rss.xml, en-US, Worldwide

View file

@ -1,3 +1,5 @@
name, url, language, country name, url, language, country
The XMPP Blog on XMPP, https://xmpp.org/feeds/all.atom.xml, en-US, Worldwide The XMPP Blog on XMPP, https://xmpp.org/feeds/all.atom.xml, en-US, Worldwide
Swift IM, https://swift.im/wordpress/index.php/feed/, en-US, Worldwide Swift IM, https://swift.im/wordpress/index.php/feed/, en-US, Worldwide
Berlin XMPP Meetup, https://mov.im/feed/pubsub.movim.eu/berlin-xmpp-meetup, en-US, Germany
Хомяк diSabler'а, https://dsy.name/feed/, ru-RU, Russia

1 name url language country
2 The XMPP Blog on XMPP https://xmpp.org/feeds/all.atom.xml en-US Worldwide
3 Swift IM https://swift.im/wordpress/index.php/feed/ en-US Worldwide
4 Berlin XMPP Meetup https://mov.im/feed/pubsub.movim.eu/berlin-xmpp-meetup en-US Germany
5 Хомяк diSabler'а https://dsy.name/feed/ ru-RU Russia

View file

@ -1,5 +1,6 @@
name, url, language, country name, url, language, country
DownThemAll!, https://www.downthemall.org/feed, en-US, Worldwide DownThemAll!, https://www.downthemall.org/feed, en-US, Worldwide
Pale Moon, https://forum.palemoon.org/app.php/feed/forum/1, en-US, Worldwide
Falkon - KDE web browser, https://www.falkon.org/atom.xml, en-US, Czech Falkon - KDE web browser, https://www.falkon.org/atom.xml, en-US, Czech
What's Up, Fraidycat?, https://fraidyc.at/blog/feed.xml, en-US, Worldwide What's Up, Fraidycat?, https://fraidyc.at/blog/feed.xml, en-US, Worldwide
geomyidae, branch HEAD, gopher://bitreich.org:70/0/scm/geomyidae/atom.xml, en-US, United States geomyidae, branch HEAD, gopher://bitreich.org:70/0/scm/geomyidae/atom.xml, en-US, United States
@ -16,3 +17,4 @@ Swift IM, https://swift.im/wordpress/index.php/feed/, en-US, Worldwide
Kaidan, https://www.kaidan.im/atom.xml, en-US, Worldwide Kaidan, https://www.kaidan.im/atom.xml, en-US, Worldwide
Dino, https://dino.im/index.xml, en-US, Worldwide Dino, https://dino.im/index.xml, en-US, Worldwide
Vivaldi Browser, https://vivaldi.com/feed/, en-US, United States Vivaldi Browser, https://vivaldi.com/feed/, en-US, United States
wicd Announcements, http://feeds.launchpad.net/wicd/announcements.atom, en-US, Worldwide

1 name, url, language, country
2 DownThemAll!, https://www.downthemall.org/feed, en-US, Worldwide
3 Pale Moon, https://forum.palemoon.org/app.php/feed/forum/1, en-US, Worldwide
4 Falkon - KDE web browser, https://www.falkon.org/atom.xml, en-US, Czech
5 What's Up, Fraidycat?, https://fraidyc.at/blog/feed.xml, en-US, Worldwide
6 geomyidae, branch HEAD, gopher://bitreich.org:70/0/scm/geomyidae/atom.xml, en-US, United States
17 Kaidan, https://www.kaidan.im/atom.xml, en-US, Worldwide
18 Dino, https://dino.im/index.xml, en-US, Worldwide
19 Vivaldi Browser, https://vivaldi.com/feed/, en-US, United States
20 wicd Announcements, http://feeds.launchpad.net/wicd/announcements.atom, en-US, Worldwide

View file

@ -15,3 +15,4 @@ WordPress, https://wordpress.org/news/feed/, en-US, Worldwide
Foswiki, https://foswiki.org/Home/WebRss, en-US, Worldwide Foswiki, https://foswiki.org/Home/WebRss, en-US, Worldwide
Eleventy, https://www.11ty.dev/blog/feed.xml, en-US, Worldwide Eleventy, https://www.11ty.dev/blog/feed.xml, en-US, Worldwide
bliper, https://git.2f30.org/bliper/atom.xml, en-US, Worldwide bliper, https://git.2f30.org/bliper/atom.xml, en-US, Worldwide
LinkStack, https://linkstack.org/feed/, en-US, Worldwide

1 name url language country
15 Foswiki https://foswiki.org/Home/WebRss en-US Worldwide
16 Eleventy https://www.11ty.dev/blog/feed.xml en-US Worldwide
17 bliper https://git.2f30.org/bliper/atom.xml en-US Worldwide
18 LinkStack https://linkstack.org/feed/ en-US Worldwide

View file

@ -115,6 +115,7 @@ if __name__ == '__main__':
xmpp.register_plugin('xep_0045') # Multi-User Chat xmpp.register_plugin('xep_0045') # Multi-User Chat
xmpp.register_plugin('xep_0060') # PubSub xmpp.register_plugin('xep_0060') # PubSub
xmpp.register_plugin('xep_0199') # XMPP Ping xmpp.register_plugin('xep_0199') # XMPP Ping
xmpp.register_plugin('xep_0249') # Multi-User Chat
# Connect to the XMPP server and start processing XMPP stanzas. # Connect to the XMPP server and start processing XMPP stanzas.
xmpp.connect() xmpp.connect()

View file

@ -42,6 +42,8 @@ async def get_value_default(key):
result = 3 result = 3
case "random": case "random":
result = 0 result = 0
case "read":
result = "https://www.blacklistednews.com/rss.php"
return result return result

View file

@ -34,6 +34,7 @@ from urllib.parse import urlunsplit
from lxml import html from lxml import html
# NOTE Why (if res[0]) and (if res[1] == 200)?
async def download_updates(db_file, url=None): async def download_updates(db_file, url=None):
""" """
Check feeds for new entries. Check feeds for new entries.
@ -127,6 +128,9 @@ async def download_updates(db_file, url=None):
if entry.has_key("published"): if entry.has_key("published"):
date = entry.published date = entry.published
date = await datetimehandler.rfc2822_to_iso8601(date) date = await datetimehandler.rfc2822_to_iso8601(date)
elif entry.has_key("updated"):
date = entry.updated
date = await datetimehandler.rfc2822_to_iso8601(date)
else: else:
date = None date = None
exist = await sqlitehandler.check_entry_exist( exist = await sqlitehandler.check_entry_exist(
@ -139,19 +143,7 @@ async def download_updates(db_file, url=None):
) )
if not exist: if not exist:
# new_entry = new_entry + 1 # new_entry = new_entry + 1
if entry.has_key("published"): if not date:
date = entry.published
date = await datetimehandler.rfc2822_to_iso8601(date)
# try:
# date = datetime.strptime(date, "%a, %d %b %Y %H:%M:%S %z")
# except:
# date = datetime.strptime(date, '%a, %d %b %Y %H:%M:%S %Z')
# finally:
# date = date.isoformat()
# if parsedate(date): # Is RFC 2822 format
# date = parsedate_to_datetime(date) # Process timestamp
# date = date.isoformat() # Convert to ISO 8601
else:
# TODO Just set date = "*** No date ***" # TODO Just set date = "*** No date ***"
# date = await datetime.now().isoformat() # date = await datetime.now().isoformat()
date = await datetimehandler.now() date = await datetimehandler.now()
@ -215,6 +207,162 @@ async def download_updates(db_file, url=None):
# print(await datetimehandler.current_time(), exist, title) # print(await datetimehandler.current_time(), exist, title)
# NOTE Why (if result[0]) and (if result[1] == 200)?
async def view_feed(db_file, url):
"""
Check feeds for new entries.
Parameters
----------
db_file : str
Path to database file.
url : str, optional
URL. The default is None.
Returns
-------
msg : str
Feed content or error message.
"""
result = await download_feed(url)
if result[0]:
try:
feed = feedparser.parse(result[0])
if feed.bozo:
# msg = (
# ">{}\n"
# "WARNING: Bozo detected!\n"
# "For more information, visit "
# "https://pythonhosted.org/feedparser/bozo.html"
# ).format(url)
# msg = await probe_page(view_feed, url, result[0])
msg = await probe_page(view_feed, url, result[0], db_file)
return msg
except (
IncompleteReadError,
IncompleteRead,
error.URLError
) as e:
# print(e)
# TODO Print error to log
msg = (
"> {}\n"
"Error: {}"
).format(url, e)
breakpoint()
if result[1] == 200:
title = await get_title(url, result[0])
entries = feed.entries
msg = "Extracted {} entries from {}:\n```\n".format(
len(entries),
title
)
count = 0
for entry in entries:
count += 1
if entry.has_key("title"):
title = entry.title
else:
title = "*** No title ***"
if entry.has_key("link"):
# link = complete_url(source, entry.link)
link = await join_url(url, entry.link)
link = await trim_url(link)
else:
link = "*** No link ***"
if entry.has_key("published"):
date = entry.published
date = await datetimehandler.rfc2822_to_iso8601(date)
elif entry.has_key("updated"):
date = entry.updated
date = await datetimehandler.rfc2822_to_iso8601(date)
else:
date = "*** No date ***"
msg += (
"Title : {}\n"
"Date : {}\n"
"Link : {}\n"
"Count : {}\n"
"\n"
).format(
title,
date,
link,
count
)
msg += (
"```\n"
"Source: {}\n"
"Enter a number from 1 - {} using command `select` "
"to view a specific item from the list."
).format(url, count)
await sqlitehandler.set_settings_value(db_file, ["read", url])
else:
msg = (
">{}\nFailed to load URL. Reason: {}"
).format(url, result[1])
return msg
async def view_entry(db_file, num):
num = int(num) - 1
url = await sqlitehandler.get_settings_value(db_file, "read")
result = await download_feed(url)
if result[1] == 200:
feed = feedparser.parse(result[0])
title = await get_title(url, result[0])
entries = feed.entries
entry = entries[num]
if entry.has_key("title"):
title = entry.title
else:
title = "*** No title ***"
if entry.has_key("published"):
date = entry.published
date = await datetimehandler.rfc2822_to_iso8601(date)
elif entry.has_key("updated"):
date = entry.updated
date = await datetimehandler.rfc2822_to_iso8601(date)
else:
date = "*** No date ***"
if entry.has_key("summary"):
summary = entry.summary
# Remove HTML tags
# summary = BeautifulSoup(summary, "lxml").text
# TODO Limit text length
# summary = summary.replace("\n\n", "\n")
else:
summary = "*** No summary ***"
if entry.has_key("link"):
# link = complete_url(source, entry.link)
link = await join_url(url, entry.link)
link = await trim_url(link)
else:
link = "*** No link ***"
msg = (
"{}\n"
"\n"
"{}\n"
"\n"
"{}\n"
"\n"
"{}\n"
"\n"
).format(
title,
date,
summary,
link
)
else:
msg = (
">{}\n"
"Failed to load URL. Reason: {}\n"
"Try again momentarily."
).format(url, result[1])
return msg
async def add_feed_no_check(db_file, data): async def add_feed_no_check(db_file, data):
""" """
Add given feed without validity check. Add given feed without validity check.
@ -278,26 +426,7 @@ async def add_feed(db_file, url):
"Bozo detected. Failed to load: {}." "Bozo detected. Failed to load: {}."
).format(url) ).format(url)
print(bozo) print(bozo)
try: msg = await probe_page(add_feed, url, res[0], db_file)
# tree = etree.fromstring(res[0]) # etree is for xml
tree = html.fromstring(res[0])
except:
msg = (
"> {}\nFailed to parse URL as feed."
).format(url)
if not msg:
print("RSS Auto-Discovery Engaged")
msg = await feed_mode_auto_discovery(db_file, url, tree)
if not msg:
print("RSS Scan Mode Engaged")
msg = await feed_mode_scan(db_file, url, tree)
if not msg:
print("RSS Arbitrary Mode Engaged")
msg = await feed_mode_request(db_file, url, tree)
if not msg:
msg = (
"> {}\nNo news feeds were found for URL."
).format(url)
else: else:
status = res[1] status = res[1]
msg = await sqlitehandler.add_feed( msg = await sqlitehandler.add_feed(
@ -310,7 +439,7 @@ async def add_feed(db_file, url):
else: else:
status = res[1] status = res[1]
msg = ( msg = (
"> {}\nFailed to get URL. Reason: {}" "> {}\nFailed to load URL. Reason: {}"
).format(url, status) ).format(url, status)
else: else:
ix = exist[0] ix = exist[0]
@ -323,6 +452,41 @@ async def add_feed(db_file, url):
return msg return msg
# TODO callback for use with add_feed and view_feed
async def probe_page(callback, url, doc, db_file=None):
msg = None
try:
# tree = etree.fromstring(res[0]) # etree is for xml
tree = html.fromstring(doc)
except:
msg = (
"> {}\nFailed to parse URL as feed."
).format(url)
if not msg:
print("RSS Auto-Discovery Engaged")
msg = await feed_mode_auto_discovery(url, tree)
if not msg:
print("RSS Scan Mode Engaged")
msg = await feed_mode_scan(url, tree)
if not msg:
print("RSS Arbitrary Mode Engaged")
msg = await feed_mode_request(url, tree)
if not msg:
msg = (
"> {}\nNo news feeds were found for URL."
).format(url)
# elif msg:
else:
if isinstance(msg, str):
return msg
elif isinstance(msg, list):
url = msg[0]
if db_file:
return await callback(db_file, url)
else:
return await callback(url)
async def download_feed(url): async def download_feed(url):
""" """
Download content of given URL. Download content of given URL.
@ -560,7 +724,7 @@ async def trim_url(url):
# TODO Improve scan by gradual decreasing of path # TODO Improve scan by gradual decreasing of path
async def feed_mode_request(db_file, url, tree): async def feed_mode_request(url, tree):
""" """
Lookup for feeds by pathname using HTTP Requests. Lookup for feeds by pathname using HTTP Requests.
@ -639,8 +803,8 @@ async def feed_mode_request(db_file, url, tree):
positive = 1 positive = 1
msg += ( msg += (
"Title: {}\n" "Title: {}\n"
" Link: {}\n" "Link : {}\n"
"Count: {}\n" "Items: {}\n"
"\n" "\n"
).format( ).format(
feed_name, feed_name,
@ -656,12 +820,10 @@ async def feed_mode_request(db_file, url, tree):
).format(url) ).format(url)
return msg return msg
elif feeds: elif feeds:
feed_addr = list(feeds)[0] return feeds
msg = await add_feed(db_file, feed_addr)
return msg
async def feed_mode_scan(db_file, url, tree): async def feed_mode_scan(url, tree):
""" """
Scan page for potential feeds by pathname. Scan page for potential feeds by pathname.
@ -760,12 +922,10 @@ async def feed_mode_scan(db_file, url, tree):
).format(url) ).format(url)
return msg return msg
elif feeds: elif feeds:
feed_addr = list(feeds)[0] return feeds
msg = await add_feed(db_file, feed_addr)
return msg
async def feed_mode_auto_discovery(db_file, url, tree): async def feed_mode_auto_discovery(url, tree):
""" """
Lookup for feeds using RSS autodiscovery technique. Lookup for feeds using RSS autodiscovery technique.
@ -819,14 +979,7 @@ async def feed_mode_auto_discovery(db_file, url, tree):
return msg return msg
elif feeds: elif feeds:
feed_addr = await join_url(url, feeds[0].xpath('@href')[0]) feed_addr = await join_url(url, feeds[0].xpath('@href')[0])
# if feed_addr.startswith("/"): return [feed_addr]
# feed_addr = url + feed_addr
# NOTE Why wouldn't add_feed return a message
# upon success unless return is explicitly
# mentioned, yet upon failure it wouldn't?
# return await add_feed(db_file, feed_addr)
msg = await add_feed(db_file, feed_addr)
return msg
async def feed_to_http(url): async def feed_to_http(url):

View file

@ -669,7 +669,7 @@ async def toggle_status(db_file, ix):
"id": ix "id": ix
}) })
msg = ( msg = (
"Updates for '{}' are now {}." "Updates from '{}' are now {}."
).format(title, state) ).format(title, state)
except: except:
msg = ( msg = (
@ -1157,12 +1157,13 @@ async def search_feeds(db_file, query):
""" """
cur = get_cursor(db_file) cur = get_cursor(db_file)
sql = ( sql = (
"SELECT name, address, id " "SELECT name, address, id, enabled "
"FROM feeds " "FROM feeds "
"WHERE name LIKE ? " "WHERE name LIKE ? "
"OR address LIKE ? "
"LIMIT 50" "LIMIT 50"
) )
results = cur.execute(sql, [f'%{query}%']) results = cur.execute(sql, [f'%{query}%', f'%{query}%'])
results_list = ( results_list = (
"Feeds containing '{}':\n```" "Feeds containing '{}':\n```"
).format(query) ).format(query)
@ -1170,14 +1171,16 @@ async def search_feeds(db_file, query):
for result in results: for result in results:
counter += 1 counter += 1
results_list += ( results_list += (
"\nName: {}" "\nName : {}"
"\n URL: {}" "\nURL : {}"
"\n ID: {}" "\nIndex : {}"
"\nMode : {}"
"\n" "\n"
).format( ).format(
str(result[0]), str(result[0]),
str(result[1]), str(result[1]),
str(result[2]) str(result[2]),
str(result[3])
) )
if counter: if counter:
return results_list + "\n```\nTotal of {} feeds".format(counter) return results_list + "\n```\nTotal of {} feeds".format(counter)
@ -1359,7 +1362,7 @@ async def set_settings_value(db_file, key_value):
# TODO Place settings also in a file # TODO Place settings also in a file
async def set_settings_value_default(cur, key): async def set_settings_value_default(cur, key):
""" """
Set default settings value. Set default settings value, if no value found.
Parameters Parameters
---------- ----------

View file

@ -23,6 +23,10 @@ TODO
4) Do not send updates when busy or away. 4) Do not send updates when busy or away.
See https://slixmpp.readthedocs.io/en/latest/event_index.html#term-changed_status See https://slixmpp.readthedocs.io/en/latest/event_index.html#term-changed_status
5) Animate "You have X news items"
📬 when sent
📫 after sent
NOTE NOTE
1) Self presence 1) Self presence
@ -69,10 +73,9 @@ await taskhandler.start_tasks(
async def start_tasks_xmpp(self, jid, tasks): async def start_tasks_xmpp(self, jid, tasks):
task_manager[jid] = {} task_manager[jid] = {}
for task in tasks: for task in tasks:
print("task") # print("task:", task)
print(task) # print("tasks:")
print("tasks") # print(tasks)
print(tasks)
# breakpoint() # breakpoint()
match task: match task:
case "check": case "check":
@ -174,7 +177,7 @@ async def task_jid(self, jid):
async def send_update(self, jid, num=None): async def send_update(self, jid, num=None):
print(await datetimehandler.current_time(), jid, "def send_update") # print(await datetimehandler.current_time(), jid, "def send_update")
""" """
Send news items as messages. Send news items as messages.
@ -194,7 +197,7 @@ async def send_update(self, jid, num=None):
) )
if new: if new:
# TODO Add while loop to assure delivery. # TODO Add while loop to assure delivery.
print(await datetimehandler.current_time(), ">>> ACT send_message",jid) # print(await datetimehandler.current_time(), ">>> ACT send_message",jid)
xmpphandler.Slixfeed.send_message( xmpphandler.Slixfeed.send_message(
self, self,
mto=jid, mto=jid,
@ -235,7 +238,7 @@ async def send_update(self, jid, num=None):
async def send_status(self, jid): async def send_status(self, jid):
print(await datetimehandler.current_time(), jid, "def send_status") # print(await datetimehandler.current_time(), jid, "def send_status")
""" """
Send status message. Send status message.
@ -253,19 +256,19 @@ async def send_status(self, jid):
) )
if not enabled: if not enabled:
status_mode = "xa" status_mode = "xa"
status_text = "Send \"Start\" to receive news." status_text = "📫️ Send \"Start\" to receive updates"
else: else:
feeds = await filehandler.initdb( feeds = await filehandler.initdb(
jid, jid,
sqlitehandler.get_number_of_items, sqlitehandler.get_number_of_items,
"feeds" "feeds"
) )
print(">>> feeds:", feeds, "jid:", jid) # print(await datetimehandler.current_time(), jid, "has", feeds, "feeds")
if not feeds: if not feeds:
print(">>> not feeds:", feeds, "jid:", jid) print(">>> not feeds:", feeds, "jid:", jid)
status_mode = "available" status_mode = "available"
status_text = ( status_text = (
"📂️ Send a URL from a blog or a news website." "📭️ Send a URL from a blog or a news website"
) )
else: else:
unread = await filehandler.initdb( unread = await filehandler.initdb(
@ -275,7 +278,7 @@ async def send_status(self, jid):
if unread: if unread:
status_mode = "chat" status_mode = "chat"
status_text = ( status_text = (
"📰 You have {} news items to read." "📬️ You have {} news items"
).format(str(unread)) ).format(str(unread))
# status_text = ( # status_text = (
# "📰 News items: {}" # "📰 News items: {}"
@ -285,10 +288,10 @@ async def send_status(self, jid):
# ).format(str(unread)) # ).format(str(unread))
else: else:
status_mode = "available" status_mode = "available"
status_text = "🗞 No news" status_text = "📪️ No news"
# breakpoint() # breakpoint()
print(status_text, "for", jid) # print(await datetimehandler.current_time(), status_text, "for", jid)
xmpphandler.Slixfeed.send_presence( xmpphandler.Slixfeed.send_presence(
self, self,
pshow=status_mode, pshow=status_mode,
@ -357,7 +360,7 @@ async def refresh_task(self, jid, callback, key, val=None):
# TODO Take this function out of # TODO Take this function out of
# <class 'slixmpp.clientxmpp.ClientXMPP'> # <class 'slixmpp.clientxmpp.ClientXMPP'>
async def check_updates(jid): async def check_updates(jid):
print(await datetimehandler.current_time(), jid, "def check_updates") # print(await datetimehandler.current_time(), jid, "def check_updates")
""" """
Start calling for update check up. Start calling for update check up.

View file

@ -33,12 +33,18 @@ NOTE
JID: self.boundjid.bare JID: self.boundjid.bare
MUC: self.nick MUC: self.nick
2) Extracting attribute using xmltodict.
import xmltodict
message = xmltodict.parse(str(message))
jid = message["message"]["x"]["@jid"]
""" """
import asyncio import asyncio
import logging import logging
import os import os
import slixmpp import slixmpp
from random import randrange
from slixmpp.plugins.xep_0363.http_upload import FileTooBig, HTTPError, UploadServiceNotFound from slixmpp.plugins.xep_0363.http_upload import FileTooBig, HTTPError, UploadServiceNotFound
@ -71,7 +77,7 @@ class Slixfeed(slixmpp.ClientXMPP):
------- -------
News bot that sends updates from RSS feeds. News bot that sends updates from RSS feeds.
""" """
def __init__(self, jid, password): def __init__(self, jid, password, room=None, nick=None):
slixmpp.ClientXMPP.__init__(self, jid, password) slixmpp.ClientXMPP.__init__(self, jid, password)
# The session_start event will be triggered when # The session_start event will be triggered when
@ -82,8 +88,9 @@ class Slixfeed(slixmpp.ClientXMPP):
self.add_event_handler("session_start", self.start_session) self.add_event_handler("session_start", self.start_session)
self.add_event_handler("session_resumed", self.start_session) self.add_event_handler("session_resumed", self.start_session)
self.add_event_handler("got_offline", print("got_offline")) self.add_event_handler("got_offline", print("got_offline"))
self.add_event_handler("got_online", self.check_readiness) # self.add_event_handler("got_online", self.check_readiness)
self.add_event_handler("changed_status", self.check_readiness) self.add_event_handler("changed_status", self.check_readiness)
self.add_event_handler("presence_unavailable", self.stop_tasks)
# self.add_event_handler("changed_subscription", self.check_subscription) # self.add_event_handler("changed_subscription", self.check_subscription)
@ -96,9 +103,10 @@ class Slixfeed(slixmpp.ClientXMPP):
# stanza is received. Be aware that that includes # stanza is received. Be aware that that includes
# MUC messages and error messages. # MUC messages and error messages.
self.add_event_handler("message", self.message) self.add_event_handler("message", self.message)
self.add_event_handler("message", self.settle)
self.add_event_handler("groupchat_invite", self.muc_invite) self.add_event_handler("groupchat_invite", self.accept_muc_invite)
self.add_event_handler("groupchat_direct_invite", self.muc_invite) self.add_event_handler("groupchat_direct_invite", self.accept_muc_invite)
# self.add_event_handler("groupchat_message", self.message) # self.add_event_handler("groupchat_message", self.message)
# self.add_event_handler("disconnected", self.reconnect) # self.add_event_handler("disconnected", self.reconnect)
@ -109,9 +117,8 @@ class Slixfeed(slixmpp.ClientXMPP):
self.add_event_handler("presence_error", self.presence_error) self.add_event_handler("presence_error", self.presence_error)
self.add_event_handler("presence_subscribe", self.presence_subscribe) self.add_event_handler("presence_subscribe", self.presence_subscribe)
self.add_event_handler("presence_subscribed", self.presence_subscribed) self.add_event_handler("presence_subscribed", self.presence_subscribed)
self.add_event_handler("presence_unavailable", self.presence_unavailable)
self.add_event_handler("presence_unsubscribe", self.presence_unsubscribe) self.add_event_handler("presence_unsubscribe", self.presence_unsubscribe)
self.add_event_handler("presence_unsubscribed", self.presence_unsubscribed) self.add_event_handler("presence_unsubscribed", self.unsubscribe)
# Initialize event loop # Initialize event loop
# self.loop = asyncio.get_event_loop() # self.loop = asyncio.get_event_loop()
@ -141,7 +148,7 @@ class Slixfeed(slixmpp.ClientXMPP):
""" """
async def presence_available(self, presence): async def presence_available(self, presence):
print("def presence_available", presence["from"].bare) # print("def presence_available", presence["from"].bare)
if presence["from"].bare not in self.boundjid.bare: if presence["from"].bare not in self.boundjid.bare:
jid = presence["from"].bare jid = presence["from"].bare
await taskhandler.clean_tasks_xmpp( await taskhandler.clean_tasks_xmpp(
@ -157,10 +164,14 @@ class Slixfeed(slixmpp.ClientXMPP):
# main_task.extend([asyncio.create_task(taskhandler.task_jid(jid))]) # main_task.extend([asyncio.create_task(taskhandler.task_jid(jid))])
# print(main_task) # print(main_task)
async def presence_unavailable(self, presence): async def stop_tasks(self, presence):
if not self.boundjid.bare: if not self.boundjid.bare:
print("presence_unavailable", presence["from"].bare, presence["type"]) jid = presence["from"].bare
print(presence) print(">>> unavailable:", jid)
await taskhandler.clean_tasks_xmpp(
jid,
["interval", "status", "check"]
)
async def presence_error(self, presence): async def presence_error(self, presence):
@ -175,32 +186,30 @@ class Slixfeed(slixmpp.ClientXMPP):
print("presence_subscribed") print("presence_subscribed")
print(presence) print(presence)
async def presence_unsubscribe(self, presence):
print("presence_unsubscribe")
print(presence)
async def presence_unsubscribed(self, presence):
print("presence_unsubscribed")
print(presence)
async def reactions(self, message): async def reactions(self, message):
print("reactions") print("reactions")
print(message) print(message)
async def muc_invite(self, message): async def accept_muc_invite(self, message):
print(message) ctr = message["from"].bare
breakpoint() jid = message['groupchat_invite']['jid']
muc = message tkn = randrange(10000, 99999)
self.add_event_handler(
"muc::[room]::message",
self.message
)
self.plugin['xep_0045'].join_muc( self.plugin['xep_0045'].join_muc(
self.room, jid,
self.nick, "Slixfeed (RSS News Bot)",
# If a room password is needed, use: # If a room password is needed, use:
# password=the_room_password, # password=the_room_password,
) )
self.send_message(
mto=ctr,
mbody=(
"Send activation token {} to groupchat xmpp:{}?join."
).format(tkn, jid)
)
# self.add_event_handler(
# "muc::[room]::message",
# self.message
# )
async def on_session_end(self, event): async def on_session_end(self, event):
@ -279,33 +288,14 @@ class Slixfeed(slixmpp.ClientXMPP):
------- -------
None. None.
""" """
print("def check_readiness", presence["from"].bare, presence["type"]) # print("def check_readiness", presence["from"].bare, presence["type"])
# # available unavailable away (chat) dnd xa # # available unavailable away (chat) dnd xa
# print(">>> type", presence["type"], presence["from"].bare) # print(">>> type", presence["type"], presence["from"].bare)
# # away chat dnd xa # # away chat dnd xa
# print(">>> show", presence["show"], presence["from"].bare) # print(">>> show", presence["show"], presence["from"].bare)
jid = presence["from"].bare jid = presence["from"].bare
if presence["type"] == "unavailable": if presence["show"] in ("away", "dnd", "xa"):
print(">>> unavailable:", jid)
await taskhandler.clean_tasks_xmpp(
jid,
["interval", "status", "check"]
)
# elif presence["type"] == "available":
# # elif presence["type"] == "available" or presence["show"] == "chat":
# print(">>> available:", jid)
# # breakpoint()
# try:
# if task_manager[jid]:
# for task in task_manager[jid]:
# # print(">>>", jid, "cancel", task)
# task_manager[jid][task].cancel()
# except:
# print(">>> EXC: No task_manager for:", jid)
# await taskhandler.task_jid(jid)
# # print(task_manager[jid])
elif presence["show"] in ("away", "dnd", "xa"):
print(">>> away, dnd, xa:", jid) print(">>> away, dnd, xa:", jid)
await taskhandler.clean_tasks_xmpp( await taskhandler.clean_tasks_xmpp(
jid, jid,
@ -351,6 +341,81 @@ class Slixfeed(slixmpp.ClientXMPP):
# await taskhandler.select_file() # await taskhandler.select_file()
async def settle(self, msg):
"""
Add JID to roster and settle subscription.
Parameters
----------
jid : str
Jabber ID.
Returns
-------
None.
"""
jid = msg["from"].bare
await self.get_roster()
# Check whether JID is in roster; otherwise, add it.
if jid not in self.client_roster.keys():
self.send_presence_subscription(
pto=jid,
ptype="subscribe",
pnick="Slixfeed RSS News Bot"
)
self.update_roster(
jid,
subscription="both"
)
# Check whether JID is subscribed; otherwise, ask for presence.
if not self.client_roster[jid]["to"]:
self.send_presence_subscription(
pto=jid,
pfrom=self.boundjid.bare,
ptype="subscribe",
pnick="Slixfeed RSS News Bot"
)
self.send_message(
mto=jid,
mtype="headline",
msubject="RSS News Bot",
mbody=("Accept subscription request to receive updates."),
mfrom=self.boundjid.bare,
mnick="Slixfeed RSS News Bot"
)
self.send_presence(
pto=jid,
pfrom=self.boundjid.bare,
# Accept symbol 🉑️ 👍️ ✍
pstatus="✒️ Accept subscription request to receive updates",
# ptype="subscribe",
pnick="Slixfeed RSS News Bot"
)
async def presence_unsubscribe(self, presence):
print("presence_unsubscribe")
print(presence)
async def unsubscribe(self, presence):
jid = presence["from"].bare
self.send_presence(
pto=jid,
pfrom=self.boundjid.bare,
pstatus="🖋️ Subscribe to receive updates",
pnick="Slixfeed RSS News Bot"
)
self.send_message(
mto=jid,
mbody="You have been unsubscribed."
)
self.update_roster(
jid,
subscription="remove"
)
async def message(self, msg): async def message(self, msg):
""" """
Process incoming message stanzas. Be aware that this also Process incoming message stanzas. Be aware that this also
@ -367,9 +432,18 @@ class Slixfeed(slixmpp.ClientXMPP):
""" """
# print("message") # print("message")
# print(msg) # print(msg)
if msg["type"] in ("chat", "normal"): if msg["type"] in ("chat", "groupchat", "normal"):
action = 0 action = 0
jid = msg["from"].bare jid = msg["from"].bare
if msg["type"] == "groupchat":
ctr = await filehandler.initdb(
jid,
sqlitehandler.get_settings_value,
"masters"
)
if (msg["from"][msg["from"].index("/")+1:] not in ctr
or not msg["body"].startswith("!")):
return
# # Begin processing new JID # # Begin processing new JID
# # Deprecated in favour of event "presence_available" # # Deprecated in favour of event "presence_available"
@ -377,8 +451,12 @@ class Slixfeed(slixmpp.ClientXMPP):
# os.chdir(db_dir) # os.chdir(db_dir)
# if jid + ".db" not in os.listdir(): # if jid + ".db" not in os.listdir():
# await taskhandler.task_jid(jid) # await taskhandler.task_jid(jid)
print(msg["body"])
print(msg["body"].split())
message = " ".join(msg["body"].split()) message = " ".join(msg["body"].split())
if msg["type"] == "groupchat":
message = message[1:]
print(message)
message_lowercase = message.lower() message_lowercase = message.lower()
print(await datetimehandler.current_time(), "ACCOUNT: " + str(msg["from"])) print(await datetimehandler.current_time(), "ACCOUNT: " + str(msg["from"]))
@ -387,13 +465,23 @@ class Slixfeed(slixmpp.ClientXMPP):
match message_lowercase: match message_lowercase:
case "help": case "help":
action = print_help() action = print_help()
case _ if message_lowercase in ["greetings", "hello", "hey"]: case "info":
action = print_info()
case _ if message_lowercase in [
"greetings", "hallo", "hello", "hey",
"hi", "hola", "holla", "hollo"]:
action = ( action = (
"Greeting! I'm Slixfeed The News Bot!" "Greeting!\n"
"\n" "I'm Slixfeed, an RSS News Bot!\n"
"Send a URL of a news website to start." "Send \"help\" for instructions."
) )
print(task_manager[jid]) # print("task_manager[jid]")
# print(task_manager[jid])
await self.get_roster()
print("roster 1")
print(self.client_roster)
print("roster 2")
print(self.client_roster.keys())
case _ if message_lowercase.startswith("add"): case _ if message_lowercase.startswith("add"):
message = message[4:] message = message[4:]
url = message.split(" ")[0] url = message.split(" ")[0]
@ -461,6 +549,9 @@ class Slixfeed(slixmpp.ClientXMPP):
).format(val) ).format(val)
else: else:
action = "Missing keywords." action = "Missing keywords."
case _ if (message_lowercase.startswith("gemini") or
message_lowercase.startswith("gopher:")):
action = "Gemini and Gopher are not supported yet."
case _ if (message_lowercase.startswith("http") or case _ if (message_lowercase.startswith("http") or
message_lowercase.startswith("feed:")): message_lowercase.startswith("feed:")):
url = message url = message
@ -581,8 +672,19 @@ class Slixfeed(slixmpp.ClientXMPP):
).format(val) ).format(val)
else: else:
action = "Missing value." action = "Missing value."
case _ if message_lowercase.startswith("random"): case "random":
action = "Updates will be sent randomly." action = "Updates will be sent randomly."
case _ if message_lowercase.startswith("read"):
url = message[5:]
if url.startswith("http"):
# action = await datahandler.view_feed(url)
action = await filehandler.initdb(
jid,
datahandler.view_feed,
url
)
else:
action = "Missing URL."
case _ if message_lowercase.startswith("recent"): case _ if message_lowercase.startswith("recent"):
num = message[7:] num = message[7:]
if num: if num:
@ -657,6 +759,16 @@ class Slixfeed(slixmpp.ClientXMPP):
jid, jid,
sqlitehandler.statistics sqlitehandler.statistics
) )
case _ if message_lowercase.startswith("select"):
num = message[7:]
if num:
action = await filehandler.initdb(
jid,
datahandler.view_entry,
num
)
else:
action = "Missing number."
case _ if message_lowercase.startswith("status "): case _ if message_lowercase.startswith("status "):
ix = message[7:] ix = message[7:]
action = await filehandler.initdb( action = await filehandler.initdb(
@ -711,6 +823,82 @@ class Slixfeed(slixmpp.ClientXMPP):
if action: msg.reply(action).send() if action: msg.reply(action).send()
def print_info():
"""
Print information.
Returns
-------
msg : str
Message.
"""
msg = (
"```\n"
"NAME\n"
"Slixfeed - News syndication bot for Jabber/XMPP\n"
"\n"
"DESCRIPTION\n"
" Slixfeed is a news aggregator bot for online news feeds.\n"
" This program is primarily designed for XMPP.\n"
" For more information, visit https://xmpp.org/software/\n"
"\n"
# "PROTOCOLS\n"
# " Supported prootcols are IRC, Matrix and XMPP.\n"
# " For the best experience, we recommend you to use XMPP.\n"
# "\n"
"FILETYPES\n"
" Supported filetypes are Atom, RDF and RSS.\n"
"\n"
"AUTHORS\n"
" Laura Harbinger, Schimon Zackary.\n"
"\n"
"THANKS\n"
" Christian Dersch (SalixOS),"
" Cyrille Pontvieux (SalixOS, France),"
"\n"
" Denis Fomin (Gajim, Russia),"
" Dimitris Tzemos (SalixOS, Greece),"
"\n"
" Emmanuel Gil Peyrot (poezio, France),"
" George Vlahavas (SalixOS, Greece),"
"\n"
" Pierrick Le Brun (SalixOS, France),"
" Thorsten Mühlfelder (SalixOS, Germany),"
"\n"
" Yann Leboulanger (Gajim, France).\n"
"\n"
"COPYRIGHT\n"
" Slixfeed is free software; you can redistribute it and/or\n"
" modify it under the terms of the GNU General Public License\n"
" as published by the Free Software Foundation; version 3 only\n"
"\n"
" Slixfeed is distributed in the hope that it will be useful,\n"
" but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
" GNU General Public License for more details.\n"
"\n"
"NOTE\n"
" Make Slixfeed your own.\n"
"\n"
" You can run Slixfeed on your own computer, server, and\n"
" even on a Linux phone (i.e. Droidian, Mobian NixOS,\n"
" postmarketOS). You can also use Termux.\n"
"\n"
" All you need is one of the above and an XMPP account to\n"
" connect Slixfeed to.\n"
"\n"
"DOCUMENTATION\n"
" Slixfeed\n"
" https://gitgud.io/sjehuda/slixfeed\n"
" Slixmpp\n"
" https://slixmpp.readthedocs.io/\n"
" feedparser\n"
" https://pythonhosted.org/feedparser\n"
"```"
)
return msg
def print_help(): def print_help():
""" """
Print help manual. Print help manual.
@ -735,6 +923,10 @@ def print_help():
" Enable bot and send updates.\n" " Enable bot and send updates.\n"
" stop\n" " stop\n"
" Disable bot and stop updates.\n" " Disable bot and stop updates.\n"
" URL\n"
" Add URL to subscription list.\n"
" add URL TITLE\n"
" Add URL to subscription list (without validity check).\n"
" feeds\n" " feeds\n"
" List subscriptions.\n" " List subscriptions.\n"
" interval N\n" " interval N\n"
@ -742,7 +934,21 @@ def print_help():
" next N\n" " next N\n"
" Send N next updates.\n" " Send N next updates.\n"
" quantum N\n" " quantum N\n"
" Set N updates for each interval.\n" " Set amount of updates for each interval.\n"
" read URL\n"
" Display most recent 20 titles of given URL.\n"
" read URL NUM\n"
" Display specified entry from given URL.\n"
"\n"
"GROUPCHAT OPTIONS\n"
" ! (command initiation)\n"
" Use exclamation mark to initiate an actionable command.\n"
" demaster NICKNAME\n"
" Remove master privilege.\n"
" mastership NICKNAME\n"
" Add master privilege.\n"
" ownership NICKNAME\n"
" Set new owner.\n"
"\n" "\n"
"FILTER OPTIONS\n" "FILTER OPTIONS\n"
" allow\n" " allow\n"
@ -755,10 +961,6 @@ def print_help():
# " Reset deny list.\n" # " Reset deny list.\n"
"\n" "\n"
"EDIT OPTIONS\n" "EDIT OPTIONS\n"
" URL\n"
" Add URL to subscription list.\n"
" add URL TITLE\n"
" Add URL to subscription list (without validity check).\n"
" remove ID\n" " remove ID\n"
" Remove feed from subscription list.\n" " Remove feed from subscription list.\n"
" status ID\n" " status ID\n"
@ -793,46 +995,15 @@ def print_help():
"SUPPORT\n" "SUPPORT\n"
" help\n" " help\n"
" Print this help manual.\n" " Print this help manual.\n"
" info\n"
" Print information page.\n"
" support\n" " support\n"
" Join xmpp:slixmpp@muc.poez.io?join\n" " Join xmpp:slixmpp@muc.poez.io?join\n"
"\n" # "\n"
# "PROTOCOLS\n" # "PROTOCOLS\n"
# " Supported prootcols are IRC, Matrix and XMPP.\n" # " Supported prootcols are IRC, Matrix and XMPP.\n"
# " For the best experience, we recommend you to use XMPP.\n" # " For the best experience, we recommend you to use XMPP.\n"
# "\n" # "\n"
"FILETYPES\n" "```"
" Supported filetypes are Atom, RDF and RSS.\n"
"\n"
"AUTHORS\n"
" Laura Harbinger, Schimon Zackary.\n"
"\n"
"COPYRIGHT\n"
" Slixfeed is free software; you can redistribute it and/or\n"
" modify it under the terms of the GNU General Public License\n"
" as published by the Free Software Foundation; version 3 only\n"
"\n"
" Slixfeed is distributed in the hope that it will be useful,\n"
" but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
" GNU General Public License for more details.\n"
"\n"
"NOTE\n"
" Make Slixfeed your own.\n"
"\n"
" You can run Slixfeed on your own computer, server, and\n"
" even on a Linux phone (i.e. Droidian, Mobian NixOS,\n"
" postmarketOS). You can also use Termux.\n"
"\n"
" All you need is one of the above and an XMPP account to\n"
" connect Slixfeed to.\n"
"\n"
"DOCUMENTATION\n"
" Slixfeed\n"
" https://gitgud.io/sjehuda/slixfeed\n"
" Slixmpp\n"
" https://slixmpp.readthedocs.io/\n"
" feedparser\n"
" https://pythonhosted.org/feedparser\n"
"\n```"
) )
return msg return msg