Add option to ignore old news items
This commit is contained in:
parent
c66e09461d
commit
6e7c57d745
4 changed files with 167 additions and 39 deletions
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 = (
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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"
|
||||||
|
|
Loading…
Reference in a new issue