Add option to ignore old news items

This commit is contained in:
Schimon Jehudah 2023-11-29 15:32:35 +00:00
parent c66e09461d
commit 6e7c57d745
4 changed files with 167 additions and 39 deletions

View file

@ -47,6 +47,8 @@ async def get_value_default(key):
result = randrange(100000, 999999) result = randrange(100000, 999999)
case "token": case "token":
result = "none" result = "none"
case "old":
result = 0
return result return result

View file

@ -132,7 +132,12 @@ async def download_updates(db_file, url=None):
date = entry.updated date = entry.updated
date = await datetimehandler.rfc2822_to_iso8601(date) date = await datetimehandler.rfc2822_to_iso8601(date)
else: else:
date = None # TODO Just set date = "*** No date ***"
# date = await datetime.now().isoformat()
date = await datetimehandler.now()
# NOTE Would seconds result in better database performance
# date = datetime.datetime(date)
# date = (date-datetime.datetime(1970,1,1)).total_seconds()
exist = await sqlitehandler.check_entry_exist( exist = await sqlitehandler.check_entry_exist(
db_file, db_file,
source, source,
@ -143,22 +148,19 @@ async def download_updates(db_file, url=None):
) )
if not exist: if not exist:
# new_entry = new_entry + 1 # new_entry = new_entry + 1
if not date:
# TODO Just set date = "*** No date ***"
# date = await datetime.now().isoformat()
date = await datetimehandler.now()
# NOTE Would seconds result in better database performance
# date = datetime.datetime(date)
# date = (date-datetime.datetime(1970,1,1)).total_seconds()
# TODO Enhance summary # TODO Enhance summary
if entry.has_key("summary"): if entry.has_key("summary"):
summary = entry.summary summary = entry.summary
# Remove HTML tags # Remove HTML tags
summary = BeautifulSoup(summary, "lxml").text summary = BeautifulSoup(summary, "lxml").text
# TODO Limit text length # TODO Limit text length
summary = summary.replace("\n\n", "\n")[:300] + " ‍⃨" summary = summary.replace("\n\n\n", "\n\n")
summary = summary[:300] + " ‍⃨"
summary = summary.strip().split('\n')
summary = ["> " + line for line in summary]
summary = "\n".join(summary)
else: else:
summary = "*** No summary ***" summary = "> *** No summary ***"
read_status = 0 read_status = 0
pathname = urlsplit(link).path pathname = urlsplit(link).path
string = ( string = (

View file

@ -478,23 +478,26 @@ async def get_entry_unread(db_file, num=None):
str(summary), str(summary),
str(link) str(link)
) )
# TODO While `async with DBLOCK` does work well from
# outside of functions, it would be better practice
# to place it within the functions.
async with DBLOCK: async with DBLOCK:
# NOTE: We can use DBLOCK once for both # NOTE: We can use DBLOCK once for both
# functions, because, due to exclusive # functions, because, due to exclusive
# ID, only one can ever occur. # ID, only one can ever occur.
await mark_as_read(cur, ix) await mark_entry_as_read(cur, ix)
await delete_entry(cur, ix) await delete_entry(cur, ix)
return news_list return news_list
async def mark_as_read(cur, ix): async def mark_entry_as_read(cur, ix):
""" """
Set read status of entry. Set read status of entry as read.
Parameters Parameters
---------- ----------
db_file : str cur : object
Path to database file. Cursor object.
ix : str ix : str
Index of entry. Index of entry.
""" """
@ -506,6 +509,51 @@ async def mark_as_read(cur, ix):
cur.execute(sql, (ix,)) cur.execute(sql, (ix,))
async def mark_source_as_read(db_file, source):
"""
Set read status of entries of given source as read.
Parameters
----------
db_file : str
Path to database file.
source : str
URL.
"""
async with DBLOCK:
with create_connection(db_file) as conn:
cur = conn.cursor()
sql = (
"UPDATE entries "
"SET summary = '', read = 1 "
"WHERE source = ?"
)
cur.execute(sql, (source,))
async def mark_all_as_read(db_file):
"""
Set read status of all entries as read.
Parameters
----------
db_file : str
Path to database file.
"""
async with DBLOCK:
with create_connection(db_file) as conn:
cur = conn.cursor()
sql = (
"UPDATE entries "
"SET summary = '', read = 1 "
)
cur.execute(sql)
sql = (
"DELETE FROM archive"
)
cur.execute(sql)
async def delete_entry(cur, ix): async def delete_entry(cur, ix):
""" """
Delete entry from table archive. Delete entry from table archive.
@ -715,6 +763,9 @@ async def add_entry_and_set_date(db_file, source, entry):
entry : list entry : list
Entry properties. Entry properties.
""" """
# TODO While `async with DBLOCK` does work well from
# outside of functions, it would be better practice
# to place it within the functions.
async with DBLOCK: async with DBLOCK:
with create_connection(db_file) as conn: with create_connection(db_file) as conn:
cur = conn.cursor() cur = conn.cursor()

View file

@ -274,6 +274,13 @@ class Slixfeed(slixmpp.ClientXMPP):
async def remove_and_leave_muc(self, muc_jid): async def remove_and_leave_muc(self, muc_jid):
self.send_message(
mto=muc_jid,
mbody=(
"If you need me again, contact me directly at {}\n"
"Goodbye!"
).format(self.boundjid.bare)
)
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"]
@ -661,13 +668,28 @@ class Slixfeed(slixmpp.ClientXMPP):
datahandler.add_feed_no_check, datahandler.add_feed_no_check,
[url, title] [url, title]
) )
await taskhandler.refresh_task( old = await filehandler.initdb(
self,
jid, jid,
taskhandler.send_status, sqlitehandler.get_settings_value,
"status", "old"
20
) )
if old:
await taskhandler.clean_tasks_xmpp(
jid,
["status"]
)
# await taskhandler.send_status(jid)
await taskhandler.start_tasks_xmpp(
self,
jid,
["status"]
)
else:
await filehandler.initdb(
jid,
sqlitehandler.mark_source_as_read,
url
)
else: else:
action = "Missing URL." action = "Missing URL."
case _ if message_lowercase.startswith("allow +"): case _ if message_lowercase.startswith("allow +"):
@ -789,16 +811,28 @@ class Slixfeed(slixmpp.ClientXMPP):
# 20 # 20
# ) # )
# NOTE This would show the number of new unread entries # NOTE This would show the number of new unread entries
await taskhandler.clean_tasks_xmpp( old = await filehandler.initdb(
jid, jid,
["status"] sqlitehandler.get_settings_value,
) "old"
# await taskhandler.send_status(jid)
await taskhandler.start_tasks_xmpp(
self,
jid,
["status"]
) )
if old:
await taskhandler.clean_tasks_xmpp(
jid,
["status"]
)
# await taskhandler.send_status(jid)
await taskhandler.start_tasks_xmpp(
self,
jid,
["status"]
)
else:
await filehandler.initdb(
jid,
sqlitehandler.mark_source_as_read,
url
)
case _ if message_lowercase.startswith("feeds"): case _ if message_lowercase.startswith("feeds"):
query = message[6:] query = message[6:]
if query: if query:
@ -839,6 +873,8 @@ class Slixfeed(slixmpp.ClientXMPP):
sqlitehandler.set_settings_value, sqlitehandler.set_settings_value,
[key, val] [key, val]
) )
# NOTE Perhaps this should be replaced
# by functions clean and start
await taskhandler.refresh_task( await taskhandler.refresh_task(
self, self,
jid, jid,
@ -878,6 +914,15 @@ class Slixfeed(slixmpp.ClientXMPP):
).format(val) ).format(val)
else: else:
action = "Missing value." action = "Missing value."
case "new":
await filehandler.initdb(
jid,
sqlitehandler.set_settings_value,
["old", 0]
)
action = (
"Only new items of added feeds will be sent."
)
case _ if message_lowercase.startswith("next"): case _ if message_lowercase.startswith("next"):
num = message[5:] num = message[5:]
await taskhandler.clean_tasks_xmpp( await taskhandler.clean_tasks_xmpp(
@ -904,6 +949,15 @@ class Slixfeed(slixmpp.ClientXMPP):
# 20 # 20
# ) # )
# await taskhandler.refresh_task(jid, key, val) # await taskhandler.refresh_task(jid, key, val)
case "old":
await filehandler.initdb(
jid,
sqlitehandler.set_settings_value,
["old", 1]
)
action = (
"All items of added feeds will be sent."
)
case _ if message_lowercase.startswith("quantum"): case _ if message_lowercase.startswith("quantum"):
key = message[:7] key = message[:7]
val = message[8:] val = message[8:]
@ -1089,20 +1143,31 @@ def print_info():
""" """
msg = ( msg = (
"```\n" "```\n"
"NAME\n" "ABOUT\n"
"Slixfeed - News syndication bot for Jabber/XMPP\n" " Slixfeed aims to be an easy to use and fully-featured news\n"
" aggregator bot for XMPP. It provides a convenient access to Blogs,\n"
" Fediverse and News websites along with filtering functionality."
"\n" "\n"
"DESCRIPTION\n" " Slixfeed is primarily designed for XMPP (aka Jabber).\n"
" Slixfeed is a news aggregator bot for online news feeds.\n" " Visit https://xmpp.org/software/ for more information.\n"
" This program is primarily designed for XMPP.\n"
" For more information, visit https://xmpp.org/software/\n"
"\n" "\n"
# "PROTOCOLS\n" " XMPP is the Extensible Messaging and Presence Protocol, a set\n"
# " Supported prootcols are IRC, Matrix and XMPP.\n" " of open technologies for instant messaging, presence, multi-party\n"
" chat, voice and video calls, collaboration, lightweight\n"
" middleware, content syndication, and generalized routing of XML\n"
" data."
" Visit https://xmpp.org/about/ for more information on the XMPP\n"
" protocol."
" "
# "PLATFORMS\n"
# " Supported prootcols are IRC, Matrix, Tox and XMPP.\n"
# " For the best experience, we recommend you to use XMPP.\n" # " For the best experience, we recommend you to use XMPP.\n"
# "\n" # "\n"
"FILETYPES\n" "FILETYPES\n"
" Supported filetypes are Atom, RDF and RSS.\n" " Supported filetypes: Atom, RDF, RSS and XML.\n"
"\n"
"PROTOCOLS\n"
" Supported protocols: Dat, FTP, Gemini, Gopher, HTTP and IPFS.\n"
"\n" "\n"
"AUTHORS\n" "AUTHORS\n"
" Laura Harbinger, Schimon Zackary.\n" " Laura Harbinger, Schimon Zackary.\n"
@ -1118,11 +1183,15 @@ def print_info():
" Florent Le Coz (poezio, France)," " Florent Le Coz (poezio, France),"
"\n" "\n"
" George Vlahavas (SalixOS, Greece)," " George Vlahavas (SalixOS, Greece),"
" Maxime Buquet (slixmpp, France),"
"\n"
" Mathieu Pasquet (slixmpp, France),"
" Pierrick Le Brun (SalixOS, France)," " Pierrick Le Brun (SalixOS, France),"
"\n" "\n"
" Remko Tronçon (Swift, Germany),"
" Thorsten Mühlfelder (SalixOS, Germany)," " Thorsten Mühlfelder (SalixOS, Germany),"
" Yann Leboulanger (Gajim, France).\n"
"\n" "\n"
" Yann Leboulanger (Gajim, France).\n"
"COPYRIGHT\n" "COPYRIGHT\n"
" Slixfeed is free software; you can redistribute it and/or\n" " Slixfeed is free software; you can redistribute it and/or\n"
" modify it under the terms of the GNU General Public License\n" " modify it under the terms of the GNU General Public License\n"
@ -1135,7 +1204,7 @@ def print_info():
"\n" "\n"
"NOTE\n" "NOTE\n"
" You can run Slixfeed on your own computer, server, and\n" " You can run Slixfeed on your own computer, server, and\n"
" even on a Linux phone (i.e. Droidian, Mobian NixOS,\n" " even on a Linux phone (i.e. Droidian, Kupfer, Mobian, NixOS,\n"
" postmarketOS). You can also use Termux.\n" " postmarketOS). You can also use Termux.\n"
"\n" "\n"
" All you need is one of the above and an XMPP account to\n" " All you need is one of the above and an XMPP account to\n"
@ -1183,6 +1252,10 @@ def print_help():
" Display most recent 20 titles of given URL.\n" " Display most recent 20 titles of given URL.\n"
" read URL N\n" " read URL N\n"
" Display specified entry number from given URL.\n" " Display specified entry number from given URL.\n"
" new\n"
" Send only new items of added feeds.\n"
" old\n"
" Send all items of added feeds.\n"
"\n" "\n"
"MESSAGE OPTIONS\n" "MESSAGE OPTIONS\n"
" start\n" " start\n"