Do not send updates when updates are not enabled. Add a new module for handling URLs. Remove awaitables from functions of mere runtime actions.
This commit is contained in:
parent
d8203abb20
commit
d4b0d08480
7 changed files with 393 additions and 337 deletions
|
@ -25,8 +25,8 @@ async def get_value_default(key):
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
key : str
|
key : str
|
||||||
Key: archive, enabled, allow, deny,interval,
|
Key: archive, enabled, interval,
|
||||||
length, old, quantum, random, replace.
|
length, old, quantum, random.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
|
|
|
@ -23,6 +23,7 @@ from feedparser import parse
|
||||||
from http.client import IncompleteRead
|
from http.client import IncompleteRead
|
||||||
from lxml import html
|
from lxml import html
|
||||||
from datetimehandler import now, rfc2822_to_iso8601
|
from datetimehandler import now, rfc2822_to_iso8601
|
||||||
|
from urlhandler import complete_url, join_url, trim_url
|
||||||
from confighandler import get_list
|
from confighandler import get_list
|
||||||
from listhandler import is_listed
|
from listhandler import is_listed
|
||||||
import sqlitehandler as sqlite
|
import sqlitehandler as sqlite
|
||||||
|
@ -109,14 +110,14 @@ async def download_updates(db_file, url=None):
|
||||||
# TODO Pass date too for comparion check
|
# TODO Pass date too for comparion check
|
||||||
if entry.has_key("published"):
|
if entry.has_key("published"):
|
||||||
date = entry.published
|
date = entry.published
|
||||||
date = await rfc2822_to_iso8601(date)
|
date = rfc2822_to_iso8601(date)
|
||||||
elif entry.has_key("updated"):
|
elif entry.has_key("updated"):
|
||||||
date = entry.updated
|
date = entry.updated
|
||||||
date = await rfc2822_to_iso8601(date)
|
date = rfc2822_to_iso8601(date)
|
||||||
else:
|
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 now()
|
date = now()
|
||||||
# NOTE Would seconds result in better database performance
|
# NOTE Would seconds result in better database performance
|
||||||
# date = datetime.datetime(date)
|
# date = datetime.datetime(date)
|
||||||
# date = (date-datetime.datetime(1970,1,1)).total_seconds()
|
# date = (date-datetime.datetime(1970,1,1)).total_seconds()
|
||||||
|
@ -128,8 +129,8 @@ async def download_updates(db_file, url=None):
|
||||||
# title = feed["feed"]["title"]
|
# title = feed["feed"]["title"]
|
||||||
if entry.has_key("link"):
|
if entry.has_key("link"):
|
||||||
# link = complete_url(source, entry.link)
|
# link = complete_url(source, entry.link)
|
||||||
link = await join_url(source, entry.link)
|
link = join_url(source, entry.link)
|
||||||
link = await trim_url(link)
|
link = trim_url(link)
|
||||||
else:
|
else:
|
||||||
link = source
|
link = source
|
||||||
if entry.has_key("id"):
|
if entry.has_key("id"):
|
||||||
|
@ -208,9 +209,9 @@ async def download_updates(db_file, url=None):
|
||||||
source,
|
source,
|
||||||
entry
|
entry
|
||||||
)
|
)
|
||||||
# print(await current_time(), entry, title)
|
# print(current_time(), entry, title)
|
||||||
# else:
|
# else:
|
||||||
# print(await current_time(), exist, title)
|
# print(current_time(), exist, title)
|
||||||
|
|
||||||
|
|
||||||
# NOTE Why (if result[0]) and (if result[1] == 200)?
|
# NOTE Why (if result[0]) and (if result[1] == 200)?
|
||||||
|
@ -256,7 +257,8 @@ async def view_feed(url):
|
||||||
).format(url, e)
|
).format(url, e)
|
||||||
# breakpoint()
|
# breakpoint()
|
||||||
if result[1] == 200:
|
if result[1] == 200:
|
||||||
title = await get_title(url, result[0])
|
feed = parse(result[0])
|
||||||
|
title = get_title(url, feed)
|
||||||
entries = feed.entries
|
entries = feed.entries
|
||||||
msg = "Preview of {}:\n```\n".format(title)
|
msg = "Preview of {}:\n```\n".format(title)
|
||||||
count = 0
|
count = 0
|
||||||
|
@ -268,16 +270,16 @@ async def view_feed(url):
|
||||||
title = "*** No title ***"
|
title = "*** No title ***"
|
||||||
if entry.has_key("link"):
|
if entry.has_key("link"):
|
||||||
# link = complete_url(source, entry.link)
|
# link = complete_url(source, entry.link)
|
||||||
link = await join_url(url, entry.link)
|
link = join_url(url, entry.link)
|
||||||
link = await trim_url(link)
|
link = trim_url(link)
|
||||||
else:
|
else:
|
||||||
link = "*** No link ***"
|
link = "*** No link ***"
|
||||||
if entry.has_key("published"):
|
if entry.has_key("published"):
|
||||||
date = entry.published
|
date = entry.published
|
||||||
date = await rfc2822_to_iso8601(date)
|
date = rfc2822_to_iso8601(date)
|
||||||
elif entry.has_key("updated"):
|
elif entry.has_key("updated"):
|
||||||
date = entry.updated
|
date = entry.updated
|
||||||
date = await rfc2822_to_iso8601(date)
|
date = rfc2822_to_iso8601(date)
|
||||||
else:
|
else:
|
||||||
date = "*** No date ***"
|
date = "*** No date ***"
|
||||||
msg += (
|
msg += (
|
||||||
|
@ -333,7 +335,7 @@ async def view_entry(url, num):
|
||||||
# breakpoint()
|
# breakpoint()
|
||||||
if result[1] == 200:
|
if result[1] == 200:
|
||||||
feed = parse(result[0])
|
feed = parse(result[0])
|
||||||
title = await get_title(url, result[0])
|
title = get_title(url, result[0])
|
||||||
entries = feed.entries
|
entries = feed.entries
|
||||||
num = int(num) - 1
|
num = int(num) - 1
|
||||||
entry = entries[num]
|
entry = entries[num]
|
||||||
|
@ -343,10 +345,10 @@ async def view_entry(url, num):
|
||||||
title = "*** No title ***"
|
title = "*** No title ***"
|
||||||
if entry.has_key("published"):
|
if entry.has_key("published"):
|
||||||
date = entry.published
|
date = entry.published
|
||||||
date = await rfc2822_to_iso8601(date)
|
date = rfc2822_to_iso8601(date)
|
||||||
elif entry.has_key("updated"):
|
elif entry.has_key("updated"):
|
||||||
date = entry.updated
|
date = entry.updated
|
||||||
date = await rfc2822_to_iso8601(date)
|
date = rfc2822_to_iso8601(date)
|
||||||
else:
|
else:
|
||||||
date = "*** No date ***"
|
date = "*** No date ***"
|
||||||
if entry.has_key("summary"):
|
if entry.has_key("summary"):
|
||||||
|
@ -359,8 +361,8 @@ async def view_entry(url, num):
|
||||||
summary = "*** No summary ***"
|
summary = "*** No summary ***"
|
||||||
if entry.has_key("link"):
|
if entry.has_key("link"):
|
||||||
# link = complete_url(source, entry.link)
|
# link = complete_url(source, entry.link)
|
||||||
link = await join_url(url, entry.link)
|
link = join_url(url, entry.link)
|
||||||
link = await trim_url(link)
|
link = trim_url(link)
|
||||||
else:
|
else:
|
||||||
link = "*** No link ***"
|
link = "*** No link ***"
|
||||||
msg = (
|
msg = (
|
||||||
|
@ -402,7 +404,7 @@ async def add_feed_no_check(db_file, data):
|
||||||
"""
|
"""
|
||||||
url = data[0]
|
url = data[0]
|
||||||
title = data[1]
|
title = data[1]
|
||||||
url = await trim_url(url)
|
url = trim_url(url)
|
||||||
exist = await sqlite.check_feed_exist(db_file, url)
|
exist = await sqlite.check_feed_exist(db_file, url)
|
||||||
if not exist:
|
if not exist:
|
||||||
msg = await sqlite.insert_feed(db_file, url, title)
|
msg = await sqlite.insert_feed(db_file, url, title)
|
||||||
|
@ -435,13 +437,13 @@ async def add_feed(db_file, url):
|
||||||
Status message.
|
Status message.
|
||||||
"""
|
"""
|
||||||
msg = None
|
msg = None
|
||||||
url = await trim_url(url)
|
url = trim_url(url)
|
||||||
exist = await sqlite.check_feed_exist(db_file, url)
|
exist = await sqlite.check_feed_exist(db_file, url)
|
||||||
if not exist:
|
if not exist:
|
||||||
res = await download_feed(url)
|
res = await download_feed(url)
|
||||||
if res[0]:
|
if res[0]:
|
||||||
feed = parse(res[0])
|
feed = parse(res[0])
|
||||||
title = await get_title(url, feed)
|
title = get_title(url, feed)
|
||||||
if feed.bozo:
|
if feed.bozo:
|
||||||
bozo = (
|
bozo = (
|
||||||
"Bozo detected. Failed to load: {}."
|
"Bozo detected. Failed to load: {}."
|
||||||
|
@ -570,7 +572,7 @@ async def download_feed(url):
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
|
|
||||||
async def get_title(url, feed):
|
def get_title(url, feed):
|
||||||
"""
|
"""
|
||||||
Get title of feed.
|
Get title of feed.
|
||||||
|
|
||||||
|
@ -593,160 +595,6 @@ async def get_title(url, feed):
|
||||||
return title
|
return title
|
||||||
|
|
||||||
|
|
||||||
# NOTE Read the documentation
|
|
||||||
# https://docs.python.org/3/library/urllib.parse.html#urllib.parse.urljoin
|
|
||||||
def complete_url(source, link):
|
|
||||||
"""
|
|
||||||
Check if URL is pathname and complete it into URL.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
source : str
|
|
||||||
Feed URL.
|
|
||||||
link : str
|
|
||||||
Link URL or pathname.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
str
|
|
||||||
URL.
|
|
||||||
"""
|
|
||||||
if link.startswith("www."):
|
|
||||||
return "http://" + link
|
|
||||||
parted_link = urlsplit(link)
|
|
||||||
parted_feed = urlsplit(source)
|
|
||||||
if parted_link.scheme == "magnet" and parted_link.query:
|
|
||||||
return link
|
|
||||||
if parted_link.scheme and parted_link.netloc:
|
|
||||||
return link
|
|
||||||
if link.startswith("//"):
|
|
||||||
if parted_link.netloc and parted_link.path:
|
|
||||||
new_link = urlunsplit([
|
|
||||||
parted_feed.scheme,
|
|
||||||
parted_link.netloc,
|
|
||||||
parted_link.path,
|
|
||||||
parted_link.query,
|
|
||||||
parted_link.fragment
|
|
||||||
])
|
|
||||||
elif link.startswith("/"):
|
|
||||||
new_link = urlunsplit([
|
|
||||||
parted_feed.scheme,
|
|
||||||
parted_feed.netloc,
|
|
||||||
parted_link.path,
|
|
||||||
parted_link.query,
|
|
||||||
parted_link.fragment
|
|
||||||
])
|
|
||||||
elif link.startswith("../"):
|
|
||||||
pathlink = parted_link.path.split("/")
|
|
||||||
pathfeed = parted_feed.path.split("/")
|
|
||||||
for i in pathlink:
|
|
||||||
if i == "..":
|
|
||||||
if pathlink.index("..") == 0:
|
|
||||||
pathfeed.pop()
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
while pathlink.count(".."):
|
|
||||||
if pathlink.index("..") == 0:
|
|
||||||
pathlink.remove("..")
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
pathlink = "/".join(pathlink)
|
|
||||||
pathfeed.extend([pathlink])
|
|
||||||
new_link = urlunsplit([
|
|
||||||
parted_feed.scheme,
|
|
||||||
parted_feed.netloc,
|
|
||||||
"/".join(pathfeed),
|
|
||||||
parted_link.query,
|
|
||||||
parted_link.fragment
|
|
||||||
])
|
|
||||||
else:
|
|
||||||
pathlink = parted_link.path.split("/")
|
|
||||||
pathfeed = parted_feed.path.split("/")
|
|
||||||
if link.startswith("./"):
|
|
||||||
pathlink.remove(".")
|
|
||||||
if not source.endswith("/"):
|
|
||||||
pathfeed.pop()
|
|
||||||
pathlink = "/".join(pathlink)
|
|
||||||
pathfeed.extend([pathlink])
|
|
||||||
new_link = urlunsplit([
|
|
||||||
parted_feed.scheme,
|
|
||||||
parted_feed.netloc,
|
|
||||||
"/".join(pathfeed),
|
|
||||||
parted_link.query,
|
|
||||||
parted_link.fragment
|
|
||||||
])
|
|
||||||
return new_link
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
|
||||||
TODO
|
|
||||||
Feed https://www.ocaml.org/feed.xml
|
|
||||||
Link %20https://frama-c.com/fc-versions/cobalt.html%20
|
|
||||||
|
|
||||||
FIXME
|
|
||||||
Feed https://cyber.dabamos.de/blog/feed.rss
|
|
||||||
Link https://cyber.dabamos.de/blog/#article-2022-07-15
|
|
||||||
"""
|
|
||||||
async def join_url(source, link):
|
|
||||||
"""
|
|
||||||
Join base URL with given pathname.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
source : str
|
|
||||||
Feed URL.
|
|
||||||
link : str
|
|
||||||
Link URL or pathname.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
str
|
|
||||||
URL.
|
|
||||||
"""
|
|
||||||
if link.startswith("www."):
|
|
||||||
new_link = "http://" + link
|
|
||||||
elif link.startswith("%20") and link.endswith("%20"):
|
|
||||||
old_link = link.split("%20")
|
|
||||||
del old_link[0]
|
|
||||||
old_link.pop()
|
|
||||||
new_link = "".join(old_link)
|
|
||||||
else:
|
|
||||||
new_link = urljoin(source, link)
|
|
||||||
return new_link
|
|
||||||
|
|
||||||
|
|
||||||
async def trim_url(url):
|
|
||||||
"""
|
|
||||||
Check URL pathname for double slash.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
url : str
|
|
||||||
URL.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
url : str
|
|
||||||
URL.
|
|
||||||
"""
|
|
||||||
parted_url = urlsplit(url)
|
|
||||||
protocol = parted_url.scheme
|
|
||||||
hostname = parted_url.netloc
|
|
||||||
pathname = parted_url.path
|
|
||||||
queries = parted_url.query
|
|
||||||
fragment = parted_url.fragment
|
|
||||||
while "//" in pathname:
|
|
||||||
pathname = pathname.replace("//", "/")
|
|
||||||
url = urlunsplit([
|
|
||||||
protocol,
|
|
||||||
hostname,
|
|
||||||
pathname,
|
|
||||||
queries,
|
|
||||||
fragment
|
|
||||||
])
|
|
||||||
return url
|
|
||||||
|
|
||||||
|
|
||||||
# TODO Improve scan by gradual decreasing of path
|
# TODO Improve scan by gradual decreasing of path
|
||||||
async def feed_mode_request(url, tree):
|
async def feed_mode_request(url, tree):
|
||||||
"""
|
"""
|
||||||
|
@ -993,7 +841,7 @@ async def feed_mode_auto_discovery(url, tree):
|
||||||
# title = disco["feed"]["title"]
|
# title = disco["feed"]["title"]
|
||||||
# msg += "{} \n {} \n\n".format(title, feed)
|
# msg += "{} \n {} \n\n".format(title, feed)
|
||||||
feed_name = feed.xpath('@title')[0]
|
feed_name = feed.xpath('@title')[0]
|
||||||
feed_addr = await join_url(url, feed.xpath('@href')[0])
|
feed_addr = join_url(url, feed.xpath('@href')[0])
|
||||||
# if feed_addr.startswith("/"):
|
# if feed_addr.startswith("/"):
|
||||||
# feed_addr = url + feed_addr
|
# feed_addr = url + feed_addr
|
||||||
msg += "{}\n{}\n\n".format(feed_name, feed_addr)
|
msg += "{}\n{}\n\n".format(feed_name, feed_addr)
|
||||||
|
@ -1002,76 +850,5 @@ async def feed_mode_auto_discovery(url, tree):
|
||||||
).format(url)
|
).format(url)
|
||||||
return msg
|
return msg
|
||||||
elif feeds:
|
elif feeds:
|
||||||
feed_addr = await join_url(url, feeds[0].xpath('@href')[0])
|
feed_addr = join_url(url, feeds[0].xpath('@href')[0])
|
||||||
return [feed_addr]
|
return [feed_addr]
|
||||||
|
|
||||||
|
|
||||||
async def feed_to_http(url):
|
|
||||||
"""
|
|
||||||
Replace scheme FEED by HTTP.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
url : str
|
|
||||||
URL.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
new_url : str
|
|
||||||
URL.
|
|
||||||
"""
|
|
||||||
par_url = urlsplit(url)
|
|
||||||
new_url = urlunsplit([
|
|
||||||
"http",
|
|
||||||
par_url.netloc,
|
|
||||||
par_url.path,
|
|
||||||
par_url.query,
|
|
||||||
par_url.fragment
|
|
||||||
])
|
|
||||||
return new_url
|
|
||||||
|
|
||||||
|
|
||||||
"""TODO"""
|
|
||||||
async def activitypub_to_http(namespace):
|
|
||||||
"""
|
|
||||||
Replace ActivityPub namespace by HTTP.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
namespace : str
|
|
||||||
Namespace.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
new_url : str
|
|
||||||
URL.
|
|
||||||
"""
|
|
||||||
par_url = urlsplit(namespace)
|
|
||||||
new_url = urlunsplit([
|
|
||||||
"http",
|
|
||||||
par_url.netloc,
|
|
||||||
par_url.path,
|
|
||||||
par_url.query,
|
|
||||||
par_url.fragment
|
|
||||||
])
|
|
||||||
return new_url
|
|
||||||
|
|
||||||
|
|
||||||
async def check_xmpp_uri(uri):
|
|
||||||
"""
|
|
||||||
Check validity of XMPP URI.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
uri : str
|
|
||||||
URI.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
jid : str
|
|
||||||
JID or None.
|
|
||||||
"""
|
|
||||||
jid = urlsplit(uri).path
|
|
||||||
if parseaddr(jid)[1] != jid:
|
|
||||||
jid = False
|
|
||||||
return jid
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ from datetime import datetime
|
||||||
from dateutil.parser import parse
|
from dateutil.parser import parse
|
||||||
from email.utils import parsedate, parsedate_to_datetime
|
from email.utils import parsedate, parsedate_to_datetime
|
||||||
|
|
||||||
async def now():
|
def now():
|
||||||
"""
|
"""
|
||||||
ISO 8601 Timestamp.
|
ISO 8601 Timestamp.
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ async def now():
|
||||||
return date
|
return date
|
||||||
|
|
||||||
|
|
||||||
async def current_time():
|
def current_time():
|
||||||
"""
|
"""
|
||||||
Print HH:MM:SS timestamp.
|
Print HH:MM:SS timestamp.
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ async def current_time():
|
||||||
return time
|
return time
|
||||||
|
|
||||||
|
|
||||||
async def validate(date):
|
def validate(date):
|
||||||
"""
|
"""
|
||||||
Validate date format.
|
Validate date format.
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ async def validate(date):
|
||||||
return date
|
return date
|
||||||
|
|
||||||
|
|
||||||
async def rfc2822_to_iso8601(date):
|
def rfc2822_to_iso8601(date):
|
||||||
"""
|
"""
|
||||||
Convert RFC 2822 into ISO 8601.
|
Convert RFC 2822 into ISO 8601.
|
||||||
|
|
||||||
|
|
|
@ -896,12 +896,12 @@ async def add_entry(cur, entry):
|
||||||
try:
|
try:
|
||||||
cur.execute(sql, entry)
|
cur.execute(sql, entry)
|
||||||
except:
|
except:
|
||||||
print(await current_time(), "COROUTINE OBJECT NOW")
|
print(current_time(), "COROUTINE OBJECT NOW")
|
||||||
print(entry[6])
|
print(entry[6])
|
||||||
print(type(entry[6]))
|
print(type(entry[6]))
|
||||||
print(entry)
|
print(entry)
|
||||||
print(type(entry))
|
print(type(entry))
|
||||||
print(await current_time(), "COROUTINE OBJECT NOW")
|
print(current_time(), "COROUTINE OBJECT NOW")
|
||||||
# breakpoint()
|
# breakpoint()
|
||||||
|
|
||||||
|
|
||||||
|
@ -990,14 +990,14 @@ async def remove_nonexistent_entries(db_file, feed, source):
|
||||||
else:
|
else:
|
||||||
title = feed["feed"]["title"]
|
title = feed["feed"]["title"]
|
||||||
if entry.has_key("link"):
|
if entry.has_key("link"):
|
||||||
link = await datahandler.join_url(source, entry.link)
|
link = datahandler.join_url(source, entry.link)
|
||||||
else:
|
else:
|
||||||
link = source
|
link = source
|
||||||
if entry.has_key("published") and item[4]:
|
if entry.has_key("published") and item[4]:
|
||||||
# print("compare11:", title, link, time)
|
# print("compare11:", title, link, time)
|
||||||
# print("compare22:", item[1], item[2], item[4])
|
# print("compare22:", item[1], item[2], item[4])
|
||||||
# print("============")
|
# print("============")
|
||||||
time = await rfc2822_to_iso8601(entry.published)
|
time = rfc2822_to_iso8601(entry.published)
|
||||||
if (item[1] == title and
|
if (item[1] == title and
|
||||||
item[2] == link and
|
item[2] == link and
|
||||||
item[4] == time):
|
item[4] == time):
|
||||||
|
@ -1413,8 +1413,8 @@ async def check_entry_exist(db_file, source, eid=None,
|
||||||
"timestamp": date
|
"timestamp": date
|
||||||
}).fetchone()
|
}).fetchone()
|
||||||
except:
|
except:
|
||||||
print(await current_time(), "ERROR DATE: source =", source)
|
print(current_time(), "ERROR DATE: source =", source)
|
||||||
print(await current_time(), "ERROR DATE: date =", date)
|
print(current_time(), "ERROR DATE: date =", date)
|
||||||
else:
|
else:
|
||||||
sql = (
|
sql = (
|
||||||
"SELECT id "
|
"SELECT id "
|
||||||
|
@ -1431,7 +1431,7 @@ async def check_entry_exist(db_file, source, eid=None,
|
||||||
else:
|
else:
|
||||||
None
|
None
|
||||||
except:
|
except:
|
||||||
print(await current_time(), "ERROR DATE: result =", source)
|
print(current_time(), "ERROR DATE: result =", source)
|
||||||
|
|
||||||
|
|
||||||
async def set_settings_value(db_file, key_value):
|
async def set_settings_value(db_file, key_value):
|
||||||
|
@ -1444,8 +1444,7 @@ async def set_settings_value(db_file, key_value):
|
||||||
Path to database file.
|
Path to database file.
|
||||||
key_value : list
|
key_value : list
|
||||||
key : str
|
key : str
|
||||||
enabled, filter-allow, filter-deny,
|
enabled, interval, masters, quantum, random.
|
||||||
interval, masters, quantum, random.
|
|
||||||
value : int
|
value : int
|
||||||
Numeric value.
|
Numeric value.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -77,6 +77,7 @@ await taskhandler.start_tasks(
|
||||||
|
|
||||||
"""
|
"""
|
||||||
async def start_tasks_xmpp(self, jid, tasks):
|
async def start_tasks_xmpp(self, jid, tasks):
|
||||||
|
print("start_tasks_xmpp", jid, tasks)
|
||||||
task_manager[jid] = {}
|
task_manager[jid] = {}
|
||||||
for task in tasks:
|
for task in tasks:
|
||||||
# print("task:", task)
|
# print("task:", task)
|
||||||
|
@ -107,6 +108,7 @@ async def start_tasks_xmpp(self, jid, tasks):
|
||||||
# await task
|
# await task
|
||||||
|
|
||||||
async def clean_tasks_xmpp(jid, tasks):
|
async def clean_tasks_xmpp(jid, tasks):
|
||||||
|
print("clean_tasks_xmpp", jid, tasks)
|
||||||
for task in tasks:
|
for task in tasks:
|
||||||
# if task_manager[jid][task]:
|
# if task_manager[jid][task]:
|
||||||
try:
|
try:
|
||||||
|
@ -129,6 +131,7 @@ Consider callback e.g. Slixfeed.send_status.
|
||||||
Or taskhandler for each protocol or specific taskhandler function.
|
Or taskhandler for each protocol or specific taskhandler function.
|
||||||
"""
|
"""
|
||||||
async def task_jid(self, jid):
|
async def task_jid(self, jid):
|
||||||
|
print("task_jid", jid)
|
||||||
"""
|
"""
|
||||||
JID (Jabber ID) task manager.
|
JID (Jabber ID) task manager.
|
||||||
|
|
||||||
|
@ -183,6 +186,7 @@ async def task_jid(self, jid):
|
||||||
|
|
||||||
|
|
||||||
async def send_update(self, jid, num=None):
|
async def send_update(self, jid, num=None):
|
||||||
|
print("send_update", jid)
|
||||||
# print(await current_time(), jid, "def send_update")
|
# print(await current_time(), jid, "def send_update")
|
||||||
"""
|
"""
|
||||||
Send news items as messages.
|
Send news items as messages.
|
||||||
|
@ -196,32 +200,37 @@ async def send_update(self, jid, num=None):
|
||||||
"""
|
"""
|
||||||
# print("Starting send_update()")
|
# print("Starting send_update()")
|
||||||
# print(jid)
|
# print(jid)
|
||||||
new = await initdb(
|
enabled = await initdb(
|
||||||
jid,
|
jid,
|
||||||
get_entry_unread,
|
get_settings_value,
|
||||||
num
|
"enabled"
|
||||||
)
|
)
|
||||||
if new:
|
if enabled:
|
||||||
# TODO Add while loop to assure delivery.
|
new = await initdb(
|
||||||
# print(await current_time(), ">>> ACT send_message",jid)
|
jid,
|
||||||
if await xmpphandler.Slixfeed.is_muc(self, jid):
|
get_entry_unread,
|
||||||
chat_type = "groupchat"
|
num
|
||||||
else:
|
)
|
||||||
chat_type = "chat"
|
if new:
|
||||||
xmpphandler.Slixfeed.send_message(
|
# TODO Add while loop to assure delivery.
|
||||||
|
# print(await current_time(), ">>> ACT send_message",jid)
|
||||||
|
chat_type = await xmpphandler.Slixfeed.is_muc(self, jid)
|
||||||
|
# NOTE Do we need "if statement"? See NOTE at is_muc.
|
||||||
|
if chat_type in ("chat", "groupchat"):
|
||||||
|
xmpphandler.Slixfeed.send_message(
|
||||||
|
self,
|
||||||
|
mto=jid,
|
||||||
|
mbody=new,
|
||||||
|
mtype=chat_type
|
||||||
|
)
|
||||||
|
# TODO Do not refresh task before
|
||||||
|
# verifying that it was completed.
|
||||||
|
await refresh_task(
|
||||||
self,
|
self,
|
||||||
mto=jid,
|
jid,
|
||||||
mbody=new,
|
send_update,
|
||||||
mtype=chat_type
|
"interval"
|
||||||
)
|
)
|
||||||
# TODO Do not refresh task before
|
|
||||||
# verifying that it was completed.
|
|
||||||
await refresh_task(
|
|
||||||
self,
|
|
||||||
jid,
|
|
||||||
send_update,
|
|
||||||
"interval"
|
|
||||||
)
|
|
||||||
# interval = await initdb(
|
# interval = await initdb(
|
||||||
# jid,
|
# jid,
|
||||||
# get_settings_value,
|
# get_settings_value,
|
||||||
|
@ -248,6 +257,7 @@ async def send_update(self, jid, num=None):
|
||||||
|
|
||||||
|
|
||||||
async def send_status(self, jid):
|
async def send_status(self, jid):
|
||||||
|
print("send_status", jid)
|
||||||
# print(await current_time(), jid, "def send_status")
|
# print(await current_time(), jid, "def send_status")
|
||||||
"""
|
"""
|
||||||
Send status message.
|
Send status message.
|
||||||
|
@ -325,6 +335,7 @@ async def send_status(self, jid):
|
||||||
|
|
||||||
|
|
||||||
async def refresh_task(self, jid, callback, key, val=None):
|
async def refresh_task(self, jid, callback, key, val=None):
|
||||||
|
print("refresh_task", jid, key)
|
||||||
"""
|
"""
|
||||||
Apply new setting at runtime.
|
Apply new setting at runtime.
|
||||||
|
|
||||||
|
@ -370,6 +381,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("check_updates", jid)
|
||||||
# print(await current_time(), jid, "def check_updates")
|
# print(await current_time(), jid, "def check_updates")
|
||||||
"""
|
"""
|
||||||
Start calling for update check up.
|
Start calling for update check up.
|
||||||
|
|
228
slixfeed/urlhandler.py
Normal file
228
slixfeed/urlhandler.py
Normal file
|
@ -0,0 +1,228 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
1) ActivityPub URL revealer activitypub_to_http
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from email.utils import parseaddr
|
||||||
|
from urllib.parse import urljoin, urlsplit, urlunsplit
|
||||||
|
|
||||||
|
|
||||||
|
def feed_to_http(url):
|
||||||
|
"""
|
||||||
|
Replace scheme FEED by HTTP.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
url : str
|
||||||
|
URL.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
new_url : str
|
||||||
|
URL.
|
||||||
|
"""
|
||||||
|
par_url = urlsplit(url)
|
||||||
|
new_url = urlunsplit([
|
||||||
|
"http",
|
||||||
|
par_url.netloc,
|
||||||
|
par_url.path,
|
||||||
|
par_url.query,
|
||||||
|
par_url.fragment
|
||||||
|
])
|
||||||
|
return new_url
|
||||||
|
|
||||||
|
|
||||||
|
def activitypub_to_http(namespace):
|
||||||
|
"""
|
||||||
|
Replace ActivityPub namespace by HTTP.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
namespace : str
|
||||||
|
Namespace.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
new_url : str
|
||||||
|
URL.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def check_xmpp_uri(uri):
|
||||||
|
"""
|
||||||
|
Check validity of XMPP URI.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
uri : str
|
||||||
|
URI.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
jid : str
|
||||||
|
JID or None.
|
||||||
|
"""
|
||||||
|
jid = urlsplit(uri).path
|
||||||
|
if parseaddr(jid)[1] != jid:
|
||||||
|
jid = False
|
||||||
|
return jid
|
||||||
|
|
||||||
|
|
||||||
|
# NOTE Read the documentation
|
||||||
|
# https://docs.python.org/3/library/urllib.parse.html#urllib.parse.urljoin
|
||||||
|
def complete_url(source, link):
|
||||||
|
"""
|
||||||
|
Check if URL is pathname and complete it into URL.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
source : str
|
||||||
|
Feed URL.
|
||||||
|
link : str
|
||||||
|
Link URL or pathname.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
str
|
||||||
|
URL.
|
||||||
|
"""
|
||||||
|
if link.startswith("www."):
|
||||||
|
return "http://" + link
|
||||||
|
parted_link = urlsplit(link)
|
||||||
|
parted_feed = urlsplit(source)
|
||||||
|
if parted_link.scheme == "magnet" and parted_link.query:
|
||||||
|
return link
|
||||||
|
if parted_link.scheme and parted_link.netloc:
|
||||||
|
return link
|
||||||
|
if link.startswith("//"):
|
||||||
|
if parted_link.netloc and parted_link.path:
|
||||||
|
new_link = urlunsplit([
|
||||||
|
parted_feed.scheme,
|
||||||
|
parted_link.netloc,
|
||||||
|
parted_link.path,
|
||||||
|
parted_link.query,
|
||||||
|
parted_link.fragment
|
||||||
|
])
|
||||||
|
elif link.startswith("/"):
|
||||||
|
new_link = urlunsplit([
|
||||||
|
parted_feed.scheme,
|
||||||
|
parted_feed.netloc,
|
||||||
|
parted_link.path,
|
||||||
|
parted_link.query,
|
||||||
|
parted_link.fragment
|
||||||
|
])
|
||||||
|
elif link.startswith("../"):
|
||||||
|
pathlink = parted_link.path.split("/")
|
||||||
|
pathfeed = parted_feed.path.split("/")
|
||||||
|
for i in pathlink:
|
||||||
|
if i == "..":
|
||||||
|
if pathlink.index("..") == 0:
|
||||||
|
pathfeed.pop()
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
while pathlink.count(".."):
|
||||||
|
if pathlink.index("..") == 0:
|
||||||
|
pathlink.remove("..")
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
pathlink = "/".join(pathlink)
|
||||||
|
pathfeed.extend([pathlink])
|
||||||
|
new_link = urlunsplit([
|
||||||
|
parted_feed.scheme,
|
||||||
|
parted_feed.netloc,
|
||||||
|
"/".join(pathfeed),
|
||||||
|
parted_link.query,
|
||||||
|
parted_link.fragment
|
||||||
|
])
|
||||||
|
else:
|
||||||
|
pathlink = parted_link.path.split("/")
|
||||||
|
pathfeed = parted_feed.path.split("/")
|
||||||
|
if link.startswith("./"):
|
||||||
|
pathlink.remove(".")
|
||||||
|
if not source.endswith("/"):
|
||||||
|
pathfeed.pop()
|
||||||
|
pathlink = "/".join(pathlink)
|
||||||
|
pathfeed.extend([pathlink])
|
||||||
|
new_link = urlunsplit([
|
||||||
|
parted_feed.scheme,
|
||||||
|
parted_feed.netloc,
|
||||||
|
"/".join(pathfeed),
|
||||||
|
parted_link.query,
|
||||||
|
parted_link.fragment
|
||||||
|
])
|
||||||
|
return new_link
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
TODO
|
||||||
|
Feed https://www.ocaml.org/feed.xml
|
||||||
|
Link %20https://frama-c.com/fc-versions/cobalt.html%20
|
||||||
|
|
||||||
|
FIXME
|
||||||
|
Feed https://cyber.dabamos.de/blog/feed.rss
|
||||||
|
Link https://cyber.dabamos.de/blog/#article-2022-07-15
|
||||||
|
"""
|
||||||
|
def join_url(source, link):
|
||||||
|
"""
|
||||||
|
Join base URL with given pathname.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
source : str
|
||||||
|
Feed URL.
|
||||||
|
link : str
|
||||||
|
Link URL or pathname.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
str
|
||||||
|
URL.
|
||||||
|
"""
|
||||||
|
if link.startswith("www."):
|
||||||
|
new_link = "http://" + link
|
||||||
|
elif link.startswith("%20") and link.endswith("%20"):
|
||||||
|
old_link = link.split("%20")
|
||||||
|
del old_link[0]
|
||||||
|
old_link.pop()
|
||||||
|
new_link = "".join(old_link)
|
||||||
|
else:
|
||||||
|
new_link = urljoin(source, link)
|
||||||
|
return new_link
|
||||||
|
|
||||||
|
|
||||||
|
def trim_url(url):
|
||||||
|
"""
|
||||||
|
Check URL pathname for double slash.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
url : str
|
||||||
|
URL.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
url : str
|
||||||
|
URL.
|
||||||
|
"""
|
||||||
|
parted_url = urlsplit(url)
|
||||||
|
protocol = parted_url.scheme
|
||||||
|
hostname = parted_url.netloc
|
||||||
|
pathname = parted_url.path
|
||||||
|
queries = parted_url.query
|
||||||
|
fragment = parted_url.fragment
|
||||||
|
while "//" in pathname:
|
||||||
|
pathname = pathname.replace("//", "/")
|
||||||
|
url = urlunsplit([
|
||||||
|
protocol,
|
||||||
|
hostname,
|
||||||
|
pathname,
|
||||||
|
queries,
|
||||||
|
fragment
|
||||||
|
])
|
||||||
|
return url
|
|
@ -55,7 +55,7 @@ import asyncio
|
||||||
import logging
|
import logging
|
||||||
# import os
|
# import os
|
||||||
import slixmpp
|
import slixmpp
|
||||||
from slixmpp.exceptions import IqError
|
from slixmpp.exceptions import IqError, IqTimeout
|
||||||
from random import randrange
|
from random import randrange
|
||||||
import datahandler as fetcher
|
import datahandler as fetcher
|
||||||
from datetimehandler import current_time
|
from datetimehandler import current_time
|
||||||
|
@ -63,6 +63,7 @@ from filehandler import initdb
|
||||||
import listhandler as lister
|
import listhandler as lister
|
||||||
import sqlitehandler as sqlite
|
import sqlitehandler as sqlite
|
||||||
import taskhandler as tasker
|
import taskhandler as tasker
|
||||||
|
import urlhandler as urlfixer
|
||||||
|
|
||||||
from slixmpp.plugins.xep_0363.http_upload import FileTooBig, HTTPError, UploadServiceNotFound
|
from slixmpp.plugins.xep_0363.http_upload import FileTooBig, HTTPError, UploadServiceNotFound
|
||||||
# from slixmpp.plugins.xep_0402 import BookmarkStorage, Conference
|
# from slixmpp.plugins.xep_0402 import BookmarkStorage, Conference
|
||||||
|
@ -97,6 +98,9 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
def __init__(self, jid, password, nick):
|
def __init__(self, jid, password, nick):
|
||||||
slixmpp.ClientXMPP.__init__(self, jid, password)
|
slixmpp.ClientXMPP.__init__(self, jid, password)
|
||||||
|
|
||||||
|
# NOTE
|
||||||
|
# The bot works fine when the nickname is hardcoded; or
|
||||||
|
# The bot won't join some MUCs when its nickname has brackets
|
||||||
self.nick = nick
|
self.nick = nick
|
||||||
|
|
||||||
# The session_start event will be triggered when
|
# The session_start event will be triggered when
|
||||||
|
@ -170,8 +174,9 @@ 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:
|
jid = presence["from"].bare
|
||||||
jid = presence["from"].bare
|
print("presence_available", jid)
|
||||||
|
if jid not in self.boundjid.bare:
|
||||||
await tasker.clean_tasks_xmpp(
|
await tasker.clean_tasks_xmpp(
|
||||||
jid,
|
jid,
|
||||||
["interval", "status", "check"]
|
["interval", "status", "check"]
|
||||||
|
@ -258,17 +263,27 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
# If a room password is needed, use:
|
# If a room password is needed, use:
|
||||||
# password=the_room_password,
|
# password=the_room_password,
|
||||||
)
|
)
|
||||||
|
await self.add_muc_to_bookmarks(muc_jid)
|
||||||
|
messages = [
|
||||||
|
"Greetings!",
|
||||||
|
"I'm {}, the news anchor.".format(self.nick),
|
||||||
|
"My job is to bring you the latest news "
|
||||||
|
"from sources you provide me with.",
|
||||||
|
"You may always reach me via "
|
||||||
|
"xmpp:{}?message".format(self.boundjid.bare)
|
||||||
|
]
|
||||||
|
for message in messages:
|
||||||
|
self.send_message(
|
||||||
|
mto=muc_jid,
|
||||||
|
mbody=message,
|
||||||
|
mtype="groupchat"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def add_muc_to_bookmarks(self, muc_jid):
|
||||||
result = await self.plugin['xep_0048'].get_bookmarks()
|
result = await self.plugin['xep_0048'].get_bookmarks()
|
||||||
bookmarks = result["private"]["bookmarks"]
|
bookmarks = result["private"]["bookmarks"]
|
||||||
conferences = bookmarks["conferences"]
|
conferences = bookmarks["conferences"]
|
||||||
print("RESULT")
|
|
||||||
print(result)
|
|
||||||
print("BOOKMARKS")
|
|
||||||
print(bookmarks)
|
|
||||||
print("CONFERENCES")
|
|
||||||
print(conferences)
|
|
||||||
# breakpoint()
|
|
||||||
mucs = []
|
mucs = []
|
||||||
for conference in conferences:
|
for conference in conferences:
|
||||||
jid = conference["jid"]
|
jid = conference["jid"]
|
||||||
|
@ -292,14 +307,29 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
# await self['xep_0402'].publish(bm)
|
# await self['xep_0402'].publish(bm)
|
||||||
|
|
||||||
|
|
||||||
async def remove_and_leave_muc(self, muc_jid):
|
async def close_muc(self, muc_jid):
|
||||||
self.send_message(
|
messages = [
|
||||||
mto=muc_jid,
|
"Whenever you need an RSS service again, "
|
||||||
mbody=(
|
"please don’t hesitate to contact me.",
|
||||||
"If you need me again, contact me directly at {}\n"
|
"My personal contact is xmpp:{}?message".format(self.boundjid.bare),
|
||||||
"Goodbye!"
|
"Farewell, and take care."
|
||||||
).format(self.boundjid.bare)
|
]
|
||||||
|
for message in messages:
|
||||||
|
self.send_message(
|
||||||
|
mto=muc_jid,
|
||||||
|
mbody=message,
|
||||||
|
mtype="groupchat"
|
||||||
|
)
|
||||||
|
await self.remove_muc_from_bookmarks(muc_jid)
|
||||||
|
self.plugin['xep_0045'].leave_muc(
|
||||||
|
muc_jid,
|
||||||
|
self.nick,
|
||||||
|
"Goodbye!",
|
||||||
|
self.boundjid.bare
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def remove_muc_from_bookmarks(self, muc_jid):
|
||||||
result = await self.plugin['xep_0048'].get_bookmarks()
|
result = await self.plugin['xep_0048'].get_bookmarks()
|
||||||
bookmarks = result["private"]["bookmarks"]
|
bookmarks = result["private"]["bookmarks"]
|
||||||
conferences = bookmarks["conferences"]
|
conferences = bookmarks["conferences"]
|
||||||
|
@ -317,12 +347,6 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
autojoin=True
|
autojoin=True
|
||||||
)
|
)
|
||||||
await self.plugin['xep_0048'].set_bookmarks(bookmarks)
|
await self.plugin['xep_0048'].set_bookmarks(bookmarks)
|
||||||
self.plugin['xep_0045'].leave_muc(
|
|
||||||
muc_jid,
|
|
||||||
self.nick,
|
|
||||||
"Goodbye!",
|
|
||||||
self.boundjid.bare
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def autojoin_muc(self, event):
|
async def autojoin_muc(self, event):
|
||||||
|
@ -332,7 +356,7 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
for conference in conferences:
|
for conference in conferences:
|
||||||
if conference["autojoin"]:
|
if conference["autojoin"]:
|
||||||
muc = conference["jid"]
|
muc = conference["jid"]
|
||||||
print(muc)
|
print(current_time(), "Autojoining groupchat", muc)
|
||||||
self.plugin['xep_0045'].join_muc(
|
self.plugin['xep_0045'].join_muc(
|
||||||
muc,
|
muc,
|
||||||
self.nick,
|
self.nick,
|
||||||
|
@ -342,14 +366,14 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def on_session_end(self, event):
|
async def on_session_end(self, event):
|
||||||
print(await current_time(), "Session ended. Attempting to reconnect.")
|
print(current_time(), "Session ended. Attempting to reconnect.")
|
||||||
print(event)
|
print(event)
|
||||||
logging.warning("Session ended. Attempting to reconnect.")
|
logging.warning("Session ended. Attempting to reconnect.")
|
||||||
await self.recover_connection(event)
|
await self.recover_connection(event)
|
||||||
|
|
||||||
|
|
||||||
async def on_connection_failed(self, event):
|
async def on_connection_failed(self, event):
|
||||||
print(await current_time(), "Connection failed. Attempting to reconnect.")
|
print(current_time(), "Connection failed. Attempting to reconnect.")
|
||||||
print(event)
|
print(event)
|
||||||
logging.warning("Connection failed. Attempting to reconnect.")
|
logging.warning("Connection failed. Attempting to reconnect.")
|
||||||
await self.recover_connection(event)
|
await self.recover_connection(event)
|
||||||
|
@ -360,10 +384,13 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
# if self.connection_attempts <= self.max_connection_attempts:
|
# if self.connection_attempts <= self.max_connection_attempts:
|
||||||
# self.reconnect(wait=5.0) # wait a bit before attempting to reconnect
|
# self.reconnect(wait=5.0) # wait a bit before attempting to reconnect
|
||||||
# else:
|
# else:
|
||||||
# print(await current_time(),"Maximum connection attempts exceeded.")
|
# print(current_time(),"Maximum connection attempts exceeded.")
|
||||||
# logging.error("Maximum connection attempts exceeded.")
|
# logging.error("Maximum connection attempts exceeded.")
|
||||||
print("Attempt:", self.connection_attempts)
|
print(current_time(), "Attempt number", self.connection_attempts)
|
||||||
self.reconnect(wait=5.0)
|
self.reconnect(wait=5.0)
|
||||||
|
seconds = 5
|
||||||
|
print(current_time(), "Next attempt within", seconds, "seconds")
|
||||||
|
await asyncio.sleep(seconds)
|
||||||
|
|
||||||
|
|
||||||
async def inspect_connection(self, event):
|
async def inspect_connection(self, event):
|
||||||
|
@ -481,18 +508,31 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
boolean
|
str
|
||||||
True or False.
|
"chat" or "groupchat.
|
||||||
"""
|
"""
|
||||||
iqresult = await self["xep_0030"].get_info(jid=jid)
|
try:
|
||||||
features = iqresult["disco_info"]["features"]
|
iqresult = await self["xep_0030"].get_info(jid=jid)
|
||||||
# identity = iqresult['disco_info']['identities']
|
features = iqresult["disco_info"]["features"]
|
||||||
# if 'account' in indentity:
|
# identity = iqresult['disco_info']['identities']
|
||||||
# if 'conference' in indentity:
|
# if 'account' in indentity:
|
||||||
if 'http://jabber.org/protocol/muc' in features:
|
# if 'conference' in indentity:
|
||||||
return True
|
if 'http://jabber.org/protocol/muc' in features:
|
||||||
else:
|
return "groupchat"
|
||||||
return False
|
# TODO elif <feature var='jabber:iq:gateway'/>
|
||||||
|
# NOTE Is it needed? We do not interact with gateways or services
|
||||||
|
else:
|
||||||
|
return "chat"
|
||||||
|
# TODO Test whether this exception is realized
|
||||||
|
except IqTimeout as e:
|
||||||
|
messages = [
|
||||||
|
("Timeout IQ"),
|
||||||
|
("IQ Stanza:", e),
|
||||||
|
("Jabber ID:", jid)
|
||||||
|
]
|
||||||
|
for message in messages:
|
||||||
|
print(current_time(), message)
|
||||||
|
logging.error(current_time(), message)
|
||||||
|
|
||||||
|
|
||||||
async def settle(self, msg):
|
async def settle(self, msg):
|
||||||
|
@ -538,7 +578,7 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
# mtype="headline",
|
# mtype="headline",
|
||||||
msubject="RSS News Bot",
|
msubject="RSS News Bot",
|
||||||
mbody=(
|
mbody=(
|
||||||
"Accept subscription request to receive updates"
|
"Accept subscription request to receive updates."
|
||||||
),
|
),
|
||||||
mfrom=self.boundjid.bare,
|
mfrom=self.boundjid.bare,
|
||||||
mnick=self.nick
|
mnick=self.nick
|
||||||
|
@ -548,7 +588,7 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
pfrom=self.boundjid.bare,
|
pfrom=self.boundjid.bare,
|
||||||
# Accept symbol 🉑️ 👍️ ✍
|
# Accept symbol 🉑️ 👍️ ✍
|
||||||
pstatus=(
|
pstatus=(
|
||||||
"✒️ Accept subscription request to receive updates"
|
"✒️ Accept subscription request to receive updates."
|
||||||
),
|
),
|
||||||
# ptype="subscribe",
|
# ptype="subscribe",
|
||||||
pnick=self.nick
|
pnick=self.nick
|
||||||
|
@ -656,8 +696,8 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
message = message[1:]
|
message = message[1:]
|
||||||
message_lowercase = message.lower()
|
message_lowercase = message.lower()
|
||||||
|
|
||||||
print(await current_time(), "ACCOUNT: " + str(msg["from"]))
|
print(current_time(), "ACCOUNT: " + str(msg["from"]))
|
||||||
print(await current_time(), "COMMAND:", message)
|
print(current_time(), "COMMAND:", message)
|
||||||
|
|
||||||
match message_lowercase:
|
match message_lowercase:
|
||||||
case "commands":
|
case "commands":
|
||||||
|
@ -863,7 +903,7 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
message_lowercase.startswith("feed:")):
|
message_lowercase.startswith("feed:")):
|
||||||
url = message
|
url = message
|
||||||
if url.startswith("feed:"):
|
if url.startswith("feed:"):
|
||||||
url = await fetcher.feed_to_http(url)
|
url = urlfixer.feed_to_http(url)
|
||||||
await tasker.clean_tasks_xmpp(
|
await tasker.clean_tasks_xmpp(
|
||||||
jid,
|
jid,
|
||||||
["status"]
|
["status"]
|
||||||
|
@ -934,7 +974,7 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
)
|
)
|
||||||
case "goodbye":
|
case "goodbye":
|
||||||
if msg["type"] == "groupchat":
|
if msg["type"] == "groupchat":
|
||||||
await self.remove_and_leave_muc(jid)
|
await self.close_muc(jid)
|
||||||
else:
|
else:
|
||||||
action = "This command is valid for groupchat only."
|
action = "This command is valid for groupchat only."
|
||||||
case _ if message_lowercase.startswith("interval"):
|
case _ if message_lowercase.startswith("interval"):
|
||||||
|
@ -969,7 +1009,7 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
else:
|
else:
|
||||||
action = "Missing value."
|
action = "Missing value."
|
||||||
case _ if message_lowercase.startswith("join"):
|
case _ if message_lowercase.startswith("join"):
|
||||||
muc = await fetcher.check_xmpp_uri(message[5:])
|
muc = urlfixer.check_xmpp_uri(message[5:])
|
||||||
if muc:
|
if muc:
|
||||||
"TODO probe JID and confirm it's a groupchat"
|
"TODO probe JID and confirm it's a groupchat"
|
||||||
await self.join_muc(jid, muc)
|
await self.join_muc(jid, muc)
|
||||||
|
@ -1100,7 +1140,7 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
["status"]
|
["status"]
|
||||||
)
|
)
|
||||||
if url.startswith("feed:"):
|
if url.startswith("feed:"):
|
||||||
url = await fetcher.feed_to_http(url)
|
url = urlfixer.feed_to_http(url)
|
||||||
match len(data):
|
match len(data):
|
||||||
case 1:
|
case 1:
|
||||||
if url.startswith("http"):
|
if url.startswith("http"):
|
||||||
|
@ -1116,7 +1156,7 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
case _:
|
case _:
|
||||||
action = (
|
action = (
|
||||||
"Enter command as follows:\n"
|
"Enter command as follows:\n"
|
||||||
"`read URL` or `read URL NUMBER`\n"
|
"`read <url>` or `read <url> <number>`\n"
|
||||||
"URL must not contain white space."
|
"URL must not contain white space."
|
||||||
)
|
)
|
||||||
await tasker.start_tasks_xmpp(
|
await tasker.start_tasks_xmpp(
|
||||||
|
@ -1166,7 +1206,7 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
if len(query) > 1:
|
if len(query) > 1:
|
||||||
action = await initdb(
|
action = await initdb(
|
||||||
jid,
|
jid,
|
||||||
search_entries,
|
sqlite.search_entries,
|
||||||
query
|
query
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
@ -1191,7 +1231,7 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
["interval", "status", "check"]
|
["interval", "status", "check"]
|
||||||
)
|
)
|
||||||
action = "Updates are enabled."
|
action = "Updates are enabled."
|
||||||
# print(await current_time(), "task_manager[jid]")
|
# print(current_time(), "task_manager[jid]")
|
||||||
# print(task_manager[jid])
|
# print(task_manager[jid])
|
||||||
case "stats":
|
case "stats":
|
||||||
action = await initdb(
|
action = await initdb(
|
||||||
|
@ -1248,7 +1288,7 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
# TODO Send an invitation.
|
# TODO Send an invitation.
|
||||||
action = "Join xmpp:slixmpp@muc.poez.io?join"
|
action = "Join xmpp:slixmpp@muc.poez.io?join"
|
||||||
case _ if message_lowercase.startswith("xmpp:"):
|
case _ if message_lowercase.startswith("xmpp:"):
|
||||||
muc = await fetcher.check_xmpp_uri(message)
|
muc = urlfixer.check_xmpp_uri(message)
|
||||||
if muc:
|
if muc:
|
||||||
"TODO probe JID and confirm it's a groupchat"
|
"TODO probe JID and confirm it's a groupchat"
|
||||||
await self.join_muc(jid, muc)
|
await self.join_muc(jid, muc)
|
||||||
|
|
Loading…
Reference in a new issue