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
|
||||
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
|
||||
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
|
||||
triapul.cz, http://triapul.cz/feed/english.xml, en-US, Czech
|
||||
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-news, 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
|
||||
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
|
||||
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
|
||||
|
@ -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
|
||||
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
|
||||
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 (DE), https://fsfe.org/news/news.de.rss, de-DE, 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
|
||||
Lili Saintcrow, https://www.lilithsaintcrow.com/feed/, 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
|
||||
Oliver Smith, https://fosstodon.org/@ollieparanoid, en-US, Germany
|
||||
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
|
||||
Keywan Tonekaboni, https://social.heise.de/@ktn.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
|
||||
Daniel Aleksandersen, https://mastodon.daniel.priv.no/@da.rss, en-US, United States
|
||||
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
|
||||
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
|
||||
Codemadness, https://codemadness.org/atom.xml, 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
|
||||
drkhsh, https://drkhsh.at/atom.xml, en-US, Austria
|
||||
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
|
||||
Redecentralize Blog, https://redecentralize.org/blog/feed.rss, 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
|
||||
Real Liberty Media, https://www.reallibertymedia.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
|
||||
drkhsh, https://drkhsh.at/atom.xml, en-US, Austria
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
|
@ -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
|
||||
Dino, https://dino.im/index.xml, en-US, Worldwide
|
||||
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
|
||||
Eleventy, https://www.11ty.dev/blog/feed.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_0060') # PubSub
|
||||
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.
|
||||
xmpp.connect()
|
||||
|
|
|
@ -42,6 +42,8 @@ async def get_value_default(key):
|
|||
result = 3
|
||||
case "random":
|
||||
result = 0
|
||||
case "read":
|
||||
result = "https://www.blacklistednews.com/rss.php"
|
||||
return result
|
||||
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ from urllib.parse import urlunsplit
|
|||
from lxml import html
|
||||
|
||||
|
||||
# NOTE Why (if res[0]) and (if res[1] == 200)?
|
||||
async def download_updates(db_file, url=None):
|
||||
"""
|
||||
Check feeds for new entries.
|
||||
|
@ -127,6 +128,9 @@ async def download_updates(db_file, url=None):
|
|||
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 = None
|
||||
exist = await sqlitehandler.check_entry_exist(
|
||||
|
@ -139,19 +143,7 @@ async def download_updates(db_file, url=None):
|
|||
)
|
||||
if not exist:
|
||||
# new_entry = new_entry + 1
|
||||
if entry.has_key("published"):
|
||||
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:
|
||||
if not date:
|
||||
# TODO Just set date = "*** No date ***"
|
||||
# date = await datetime.now().isoformat()
|
||||
date = await datetimehandler.now()
|
||||
|
@ -215,6 +207,162 @@ async def download_updates(db_file, url=None):
|
|||
# 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):
|
||||
"""
|
||||
Add given feed without validity check.
|
||||
|
@ -278,26 +426,7 @@ async def add_feed(db_file, url):
|
|||
"Bozo detected. Failed to load: {}."
|
||||
).format(url)
|
||||
print(bozo)
|
||||
try:
|
||||
# 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)
|
||||
msg = await probe_page(add_feed, url, res[0], db_file)
|
||||
else:
|
||||
status = res[1]
|
||||
msg = await sqlitehandler.add_feed(
|
||||
|
@ -310,7 +439,7 @@ async def add_feed(db_file, url):
|
|||
else:
|
||||
status = res[1]
|
||||
msg = (
|
||||
"> {}\nFailed to get URL. Reason: {}"
|
||||
"> {}\nFailed to load URL. Reason: {}"
|
||||
).format(url, status)
|
||||
else:
|
||||
ix = exist[0]
|
||||
|
@ -323,6 +452,41 @@ async def add_feed(db_file, url):
|
|||
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):
|
||||
"""
|
||||
Download content of given URL.
|
||||
|
@ -560,7 +724,7 @@ async def trim_url(url):
|
|||
|
||||
|
||||
# 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.
|
||||
|
||||
|
@ -639,8 +803,8 @@ async def feed_mode_request(db_file, url, tree):
|
|||
positive = 1
|
||||
msg += (
|
||||
"Title: {}\n"
|
||||
" Link: {}\n"
|
||||
"Count: {}\n"
|
||||
"Link : {}\n"
|
||||
"Items: {}\n"
|
||||
"\n"
|
||||
).format(
|
||||
feed_name,
|
||||
|
@ -656,12 +820,10 @@ async def feed_mode_request(db_file, url, tree):
|
|||
).format(url)
|
||||
return msg
|
||||
elif feeds:
|
||||
feed_addr = list(feeds)[0]
|
||||
msg = await add_feed(db_file, feed_addr)
|
||||
return msg
|
||||
return feeds
|
||||
|
||||
|
||||
async def feed_mode_scan(db_file, url, tree):
|
||||
async def feed_mode_scan(url, tree):
|
||||
"""
|
||||
Scan page for potential feeds by pathname.
|
||||
|
||||
|
@ -760,12 +922,10 @@ async def feed_mode_scan(db_file, url, tree):
|
|||
).format(url)
|
||||
return msg
|
||||
elif feeds:
|
||||
feed_addr = list(feeds)[0]
|
||||
msg = await add_feed(db_file, feed_addr)
|
||||
return msg
|
||||
return feeds
|
||||
|
||||
|
||||
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.
|
||||
|
||||
|
@ -819,14 +979,7 @@ async def feed_mode_auto_discovery(db_file, url, tree):
|
|||
return msg
|
||||
elif feeds:
|
||||
feed_addr = await join_url(url, feeds[0].xpath('@href')[0])
|
||||
# if feed_addr.startswith("/"):
|
||||
# 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
|
||||
return [feed_addr]
|
||||
|
||||
|
||||
async def feed_to_http(url):
|
||||
|
|
|
@ -669,7 +669,7 @@ async def toggle_status(db_file, ix):
|
|||
"id": ix
|
||||
})
|
||||
msg = (
|
||||
"Updates for '{}' are now {}."
|
||||
"Updates from '{}' are now {}."
|
||||
).format(title, state)
|
||||
except:
|
||||
msg = (
|
||||
|
@ -1157,12 +1157,13 @@ async def search_feeds(db_file, query):
|
|||
"""
|
||||
cur = get_cursor(db_file)
|
||||
sql = (
|
||||
"SELECT name, address, id "
|
||||
"SELECT name, address, id, enabled "
|
||||
"FROM feeds "
|
||||
"WHERE name LIKE ? "
|
||||
"OR address LIKE ? "
|
||||
"LIMIT 50"
|
||||
)
|
||||
results = cur.execute(sql, [f'%{query}%'])
|
||||
results = cur.execute(sql, [f'%{query}%', f'%{query}%'])
|
||||
results_list = (
|
||||
"Feeds containing '{}':\n```"
|
||||
).format(query)
|
||||
|
@ -1170,14 +1171,16 @@ async def search_feeds(db_file, query):
|
|||
for result in results:
|
||||
counter += 1
|
||||
results_list += (
|
||||
"\nName: {}"
|
||||
"\n URL: {}"
|
||||
"\n ID: {}"
|
||||
"\nName : {}"
|
||||
"\nURL : {}"
|
||||
"\nIndex : {}"
|
||||
"\nMode : {}"
|
||||
"\n"
|
||||
).format(
|
||||
str(result[0]),
|
||||
str(result[1]),
|
||||
str(result[2])
|
||||
str(result[2]),
|
||||
str(result[3])
|
||||
)
|
||||
if 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
|
||||
async def set_settings_value_default(cur, key):
|
||||
"""
|
||||
Set default settings value.
|
||||
Set default settings value, if no value found.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
|
|
@ -23,6 +23,10 @@ TODO
|
|||
4) Do not send updates when busy or away.
|
||||
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
|
||||
|
||||
1) Self presence
|
||||
|
@ -69,10 +73,9 @@ await taskhandler.start_tasks(
|
|||
async def start_tasks_xmpp(self, jid, tasks):
|
||||
task_manager[jid] = {}
|
||||
for task in tasks:
|
||||
print("task")
|
||||
print(task)
|
||||
print("tasks")
|
||||
print(tasks)
|
||||
# print("task:", task)
|
||||
# print("tasks:")
|
||||
# print(tasks)
|
||||
# breakpoint()
|
||||
match task:
|
||||
case "check":
|
||||
|
@ -174,7 +177,7 @@ async def task_jid(self, jid):
|
|||
|
||||
|
||||
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.
|
||||
|
||||
|
@ -194,7 +197,7 @@ async def send_update(self, jid, num=None):
|
|||
)
|
||||
if new:
|
||||
# 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(
|
||||
self,
|
||||
mto=jid,
|
||||
|
@ -235,7 +238,7 @@ async def send_update(self, jid, num=None):
|
|||
|
||||
|
||||
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.
|
||||
|
||||
|
@ -253,19 +256,19 @@ async def send_status(self, jid):
|
|||
)
|
||||
if not enabled:
|
||||
status_mode = "xa"
|
||||
status_text = "Send \"Start\" to receive news."
|
||||
status_text = "📫️ Send \"Start\" to receive updates"
|
||||
else:
|
||||
feeds = await filehandler.initdb(
|
||||
jid,
|
||||
sqlitehandler.get_number_of_items,
|
||||
"feeds"
|
||||
)
|
||||
print(">>> feeds:", feeds, "jid:", jid)
|
||||
# print(await datetimehandler.current_time(), jid, "has", feeds, "feeds")
|
||||
if not feeds:
|
||||
print(">>> not feeds:", feeds, "jid:", jid)
|
||||
status_mode = "available"
|
||||
status_text = (
|
||||
"📂️ Send a URL from a blog or a news website."
|
||||
"📭️ Send a URL from a blog or a news website"
|
||||
)
|
||||
else:
|
||||
unread = await filehandler.initdb(
|
||||
|
@ -275,7 +278,7 @@ async def send_status(self, jid):
|
|||
if unread:
|
||||
status_mode = "chat"
|
||||
status_text = (
|
||||
"📰 You have {} news items to read."
|
||||
"📬️ You have {} news items"
|
||||
).format(str(unread))
|
||||
# status_text = (
|
||||
# "📰 News items: {}"
|
||||
|
@ -285,10 +288,10 @@ async def send_status(self, jid):
|
|||
# ).format(str(unread))
|
||||
else:
|
||||
status_mode = "available"
|
||||
status_text = "🗞 No news"
|
||||
status_text = "📪️ No news"
|
||||
|
||||
# breakpoint()
|
||||
print(status_text, "for", jid)
|
||||
# print(await datetimehandler.current_time(), status_text, "for", jid)
|
||||
xmpphandler.Slixfeed.send_presence(
|
||||
self,
|
||||
pshow=status_mode,
|
||||
|
@ -357,7 +360,7 @@ async def refresh_task(self, jid, callback, key, val=None):
|
|||
# TODO Take this function out of
|
||||
# <class 'slixmpp.clientxmpp.ClientXMPP'>
|
||||
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.
|
||||
|
||||
|
|
|
@ -33,12 +33,18 @@ NOTE
|
|||
JID: self.boundjid.bare
|
||||
MUC: self.nick
|
||||
|
||||
2) Extracting attribute using xmltodict.
|
||||
import xmltodict
|
||||
message = xmltodict.parse(str(message))
|
||||
jid = message["message"]["x"]["@jid"]
|
||||
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
import os
|
||||
import slixmpp
|
||||
from random import randrange
|
||||
|
||||
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.
|
||||
"""
|
||||
def __init__(self, jid, password):
|
||||
def __init__(self, jid, password, room=None, nick=None):
|
||||
slixmpp.ClientXMPP.__init__(self, jid, password)
|
||||
|
||||
# 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_resumed", self.start_session)
|
||||
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("presence_unavailable", self.stop_tasks)
|
||||
|
||||
# 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
|
||||
# MUC messages and error messages.
|
||||
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_direct_invite", self.muc_invite)
|
||||
self.add_event_handler("groupchat_invite", self.accept_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("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_subscribe", self.presence_subscribe)
|
||||
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_unsubscribed", self.presence_unsubscribed)
|
||||
self.add_event_handler("presence_unsubscribed", self.unsubscribe)
|
||||
|
||||
# Initialize event loop
|
||||
# self.loop = asyncio.get_event_loop()
|
||||
|
@ -141,7 +148,7 @@ class Slixfeed(slixmpp.ClientXMPP):
|
|||
|
||||
"""
|
||||
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:
|
||||
jid = presence["from"].bare
|
||||
await taskhandler.clean_tasks_xmpp(
|
||||
|
@ -157,10 +164,14 @@ class Slixfeed(slixmpp.ClientXMPP):
|
|||
# main_task.extend([asyncio.create_task(taskhandler.task_jid(jid))])
|
||||
# print(main_task)
|
||||
|
||||
async def presence_unavailable(self, presence):
|
||||
async def stop_tasks(self, presence):
|
||||
if not self.boundjid.bare:
|
||||
print("presence_unavailable", presence["from"].bare, presence["type"])
|
||||
print(presence)
|
||||
jid = presence["from"].bare
|
||||
print(">>> unavailable:", jid)
|
||||
await taskhandler.clean_tasks_xmpp(
|
||||
jid,
|
||||
["interval", "status", "check"]
|
||||
)
|
||||
|
||||
|
||||
async def presence_error(self, presence):
|
||||
|
@ -175,32 +186,30 @@ class Slixfeed(slixmpp.ClientXMPP):
|
|||
print("presence_subscribed")
|
||||
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):
|
||||
print("reactions")
|
||||
print(message)
|
||||
|
||||
async def muc_invite(self, message):
|
||||
print(message)
|
||||
breakpoint()
|
||||
muc = message
|
||||
self.add_event_handler(
|
||||
"muc::[room]::message",
|
||||
self.message
|
||||
)
|
||||
async def accept_muc_invite(self, message):
|
||||
ctr = message["from"].bare
|
||||
jid = message['groupchat_invite']['jid']
|
||||
tkn = randrange(10000, 99999)
|
||||
self.plugin['xep_0045'].join_muc(
|
||||
self.room,
|
||||
self.nick,
|
||||
jid,
|
||||
"Slixfeed (RSS News Bot)",
|
||||
# If a room password is needed, use:
|
||||
# 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):
|
||||
|
@ -279,33 +288,14 @@ class Slixfeed(slixmpp.ClientXMPP):
|
|||
-------
|
||||
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
|
||||
# print(">>> type", presence["type"], presence["from"].bare)
|
||||
# # away chat dnd xa
|
||||
# print(">>> show", presence["show"], presence["from"].bare)
|
||||
|
||||
jid = presence["from"].bare
|
||||
if presence["type"] == "unavailable":
|
||||
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"):
|
||||
if presence["show"] in ("away", "dnd", "xa"):
|
||||
print(">>> away, dnd, xa:", jid)
|
||||
await taskhandler.clean_tasks_xmpp(
|
||||
jid,
|
||||
|
@ -351,6 +341,81 @@ class Slixfeed(slixmpp.ClientXMPP):
|
|||
# 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):
|
||||
"""
|
||||
Process incoming message stanzas. Be aware that this also
|
||||
|
@ -367,9 +432,18 @@ class Slixfeed(slixmpp.ClientXMPP):
|
|||
"""
|
||||
# print("message")
|
||||
# print(msg)
|
||||
if msg["type"] in ("chat", "normal"):
|
||||
if msg["type"] in ("chat", "groupchat", "normal"):
|
||||
action = 0
|
||||
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
|
||||
# # Deprecated in favour of event "presence_available"
|
||||
|
@ -377,8 +451,12 @@ class Slixfeed(slixmpp.ClientXMPP):
|
|||
# os.chdir(db_dir)
|
||||
# if jid + ".db" not in os.listdir():
|
||||
# await taskhandler.task_jid(jid)
|
||||
|
||||
print(msg["body"])
|
||||
print(msg["body"].split())
|
||||
message = " ".join(msg["body"].split())
|
||||
if msg["type"] == "groupchat":
|
||||
message = message[1:]
|
||||
print(message)
|
||||
message_lowercase = message.lower()
|
||||
|
||||
print(await datetimehandler.current_time(), "ACCOUNT: " + str(msg["from"]))
|
||||
|
@ -387,13 +465,23 @@ class Slixfeed(slixmpp.ClientXMPP):
|
|||
match message_lowercase:
|
||||
case "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 = (
|
||||
"Greeting! I'm Slixfeed The News Bot!"
|
||||
"\n"
|
||||
"Send a URL of a news website to start."
|
||||
"Greeting!\n"
|
||||
"I'm Slixfeed, an RSS News Bot!\n"
|
||||
"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"):
|
||||
message = message[4:]
|
||||
url = message.split(" ")[0]
|
||||
|
@ -461,6 +549,9 @@ class Slixfeed(slixmpp.ClientXMPP):
|
|||
).format(val)
|
||||
else:
|
||||
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
|
||||
message_lowercase.startswith("feed:")):
|
||||
url = message
|
||||
|
@ -581,8 +672,19 @@ class Slixfeed(slixmpp.ClientXMPP):
|
|||
).format(val)
|
||||
else:
|
||||
action = "Missing value."
|
||||
case _ if message_lowercase.startswith("random"):
|
||||
case "random":
|
||||
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"):
|
||||
num = message[7:]
|
||||
if num:
|
||||
|
@ -657,6 +759,16 @@ class Slixfeed(slixmpp.ClientXMPP):
|
|||
jid,
|
||||
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 "):
|
||||
ix = message[7:]
|
||||
action = await filehandler.initdb(
|
||||
|
@ -711,6 +823,82 @@ class Slixfeed(slixmpp.ClientXMPP):
|
|||
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():
|
||||
"""
|
||||
Print help manual.
|
||||
|
@ -735,6 +923,10 @@ def print_help():
|
|||
" Enable bot and send updates.\n"
|
||||
" stop\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"
|
||||
" List subscriptions.\n"
|
||||
" interval N\n"
|
||||
|
@ -742,7 +934,21 @@ def print_help():
|
|||
" next N\n"
|
||||
" Send N next updates.\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"
|
||||
"FILTER OPTIONS\n"
|
||||
" allow\n"
|
||||
|
@ -755,10 +961,6 @@ def print_help():
|
|||
# " Reset deny list.\n"
|
||||
"\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 feed from subscription list.\n"
|
||||
" status ID\n"
|
||||
|
@ -793,46 +995,15 @@ def print_help():
|
|||
"SUPPORT\n"
|
||||
" help\n"
|
||||
" Print this help manual.\n"
|
||||
" info\n"
|
||||
" Print information page.\n"
|
||||
" support\n"
|
||||
" Join xmpp:slixmpp@muc.poez.io?join\n"
|
||||
"\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"
|
||||
"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
|
||||
|
|
Loading…
Reference in a new issue