forked from sch/Slixfeed
Add preview commands (read and select) and experimenting with XEP-0249
This commit is contained in:
parent
efa05aaba1
commit
31baf96430
31 changed files with 584 additions and 176 deletions
2
datasets/catalogues/gear.csv
Normal file
2
datasets/catalogues/gear.csv
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
name, url, language, country
|
||||||
|
HELLOTUX Blog, https://www.hellotux.com/rss.php, en-US, Hungary
|
|
2
datasets/events/xmpp.csv
Normal file
2
datasets/events/xmpp.csv
Normal 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
|
|
2
datasets/forums/computer.csv
Normal file
2
datasets/forums/computer.csv
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
name, url, language, country
|
||||||
|
eGPU.io, https://egpu.io/feed/, en-US, Worldwide
|
|
|
@ -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,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
|
||||||
|
|
|
3
datasets/forums/intrenet.csv
Normal file
3
datasets/forums/intrenet.csv
Normal 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
|
|
|
@ -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
|
||||||
|
|
|
5
datasets/news/bsd.csv
Normal file
5
datasets/news/bsd.csv
Normal 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
|
|
|
@ -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,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.
|
|
@ -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
|
||||||
|
|
|
3
datasets/news/design.csv
Normal file
3
datasets/news/design.csv
Normal 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
|
|
2
datasets/news/law.csv
Normal file
2
datasets/news/law.csv
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
name, url, language, country
|
||||||
|
North Carolina Lawyers Weekly, https://nclawyersweekly.com/feed/, en-US, United States
|
|
26
datasets/news/linux.csv
Normal file
26
datasets/news/linux.csv
Normal 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
|
|
|
@ -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
|
||||||
|
|
|
2
datasets/news/north_carolina.csv
Normal file
2
datasets/news/north_carolina.csv
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
name, url, language, country
|
||||||
|
North Carolina Lawyers Weekly, https://nclawyersweekly.com/feed/, en-US, United States
|
|
|
@ -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,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
|
||||||
|
|
|
|
@ -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
|
||||||
|
|
|
|
@ -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
|
||||||
|
|
|
|
@ -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
|
||||||
|
|
|
|
@ -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,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,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
|
||||||
|
|
|
|
@ -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
|
||||||
|
|
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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
|
||||||
----------
|
----------
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue