Update sqlitehandler.py
This commit is contained in:
parent
1f3aa9459e
commit
85d98609c5
1 changed files with 102 additions and 83 deletions
|
@ -42,7 +42,7 @@ def create_connection(db_file):
|
||||||
def create_tables(db_file):
|
def create_tables(db_file):
|
||||||
"""
|
"""
|
||||||
Create SQLite tables.
|
Create SQLite tables.
|
||||||
|
|
||||||
:param db_file: Database filename.
|
:param db_file: Database filename.
|
||||||
"""
|
"""
|
||||||
with create_connection(db_file) as conn:
|
with create_connection(db_file) as conn:
|
||||||
|
@ -89,7 +89,7 @@ def create_tables(db_file):
|
||||||
def get_cursor(db_file):
|
def get_cursor(db_file):
|
||||||
"""
|
"""
|
||||||
Allocate a cursor to connection per database.
|
Allocate a cursor to connection per database.
|
||||||
|
|
||||||
:param db_file: Database filename.
|
:param db_file: Database filename.
|
||||||
:return: Cursor.
|
:return: Cursor.
|
||||||
"""
|
"""
|
||||||
|
@ -105,7 +105,7 @@ def get_cursor(db_file):
|
||||||
async def add_feed(db_file, title, url, res):
|
async def add_feed(db_file, title, url, res):
|
||||||
"""
|
"""
|
||||||
Add a new feed into the feeds table.
|
Add a new feed into the feeds table.
|
||||||
|
|
||||||
:param db_file: Database filename.
|
:param db_file: Database filename.
|
||||||
:param title: Feed title.
|
:param title: Feed title.
|
||||||
:param url: URL.
|
:param url: URL.
|
||||||
|
@ -134,14 +134,15 @@ async def add_feed(db_file, title, url, res):
|
||||||
cur.execute(sql, feed)
|
cur.execute(sql, feed)
|
||||||
|
|
||||||
source = title if title else '<' + url + '>'
|
source = title if title else '<' + url + '>'
|
||||||
msg = '> {}\nNews source "{}" has been added to subscription list'.format(url, source)
|
msg = """> {}\nNews source \"{}\" has been added to subscription list.
|
||||||
|
""".format(url, source)
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
|
|
||||||
async def remove_feed(db_file, ix):
|
async def remove_feed(db_file, ix):
|
||||||
"""
|
"""
|
||||||
Delete a feed by feed id.
|
Delete a feed by feed id.
|
||||||
|
|
||||||
:param db_file: Database filename.
|
:param db_file: Database filename.
|
||||||
:param ix: Index of feed.
|
:param ix: Index of feed.
|
||||||
:return: Message.
|
:return: Message.
|
||||||
|
@ -151,18 +152,20 @@ async def remove_feed(db_file, ix):
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
try:
|
try:
|
||||||
sql = "SELECT address FROM feeds WHERE id = ?"
|
sql = "SELECT address FROM feeds WHERE id = ?"
|
||||||
url = cur.execute(sql, (ix,))
|
# cur
|
||||||
for i in url:
|
# for i in url:
|
||||||
url = i[0]
|
# url = i[0]
|
||||||
|
url = cur.execute(sql, (ix,)).fetchone()[0]
|
||||||
|
sql = "SELECT name FROM feeds WHERE id = ?"
|
||||||
|
name = cur.execute(sql, (ix,)).fetchone()[0]
|
||||||
# NOTE Should we move DBLOCK to this line? 2022-12-23
|
# NOTE Should we move DBLOCK to this line? 2022-12-23
|
||||||
sql = "DELETE FROM entries WHERE source = ?"
|
sql = "DELETE FROM entries WHERE source = ?"
|
||||||
cur.execute(sql, (url,))
|
cur.execute(sql, (url,))
|
||||||
sql = "DELETE FROM feeds WHERE id = ?"
|
sql = "DELETE FROM feeds WHERE id = ?"
|
||||||
cur.execute(sql, (ix,))
|
cur.execute(sql, (ix,))
|
||||||
msg = """News source <{}> has been removed from subscription list
|
msg = "> {}\nNews source \"{}\" has been removed from subscription list.".format(url, name)
|
||||||
""".format(url)
|
|
||||||
except:
|
except:
|
||||||
msg = """No news source with ID {}""".format(ix)
|
msg = "No news source with ID {}.".format(ix)
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
|
|
||||||
|
@ -170,22 +173,21 @@ async def check_feed_exist(db_file, url):
|
||||||
"""
|
"""
|
||||||
Check whether a feed exists.
|
Check whether a feed exists.
|
||||||
Query for feeds by given url.
|
Query for feeds by given url.
|
||||||
|
|
||||||
:param db_file: Database filename.
|
:param db_file: Database filename.
|
||||||
:param url: URL.
|
:param url: URL.
|
||||||
:return: Index ID and Name or None.
|
:return: Index ID and Name or None.
|
||||||
"""
|
"""
|
||||||
cur = get_cursor(db_file)
|
cur = get_cursor(db_file)
|
||||||
sql = "SELECT id, name FROM feeds WHERE address = ?"
|
sql = "SELECT id, name FROM feeds WHERE address = ?"
|
||||||
cur.execute(sql, (url,))
|
result = cur.execute(sql, (url,)).fetchone()
|
||||||
result = cur.fetchone()
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
async def get_number_of_items(db_file, str):
|
async def get_number_of_items(db_file, str):
|
||||||
"""
|
"""
|
||||||
Return number of entries or feeds.
|
Return number of entries or feeds.
|
||||||
|
|
||||||
:param cur: Cursor object.
|
:param cur: Cursor object.
|
||||||
:param str: "entries" or "feeds".
|
:param str: "entries" or "feeds".
|
||||||
:return: Number of rows.
|
:return: Number of rows.
|
||||||
|
@ -193,8 +195,22 @@ async def get_number_of_items(db_file, str):
|
||||||
with create_connection(db_file) as conn:
|
with create_connection(db_file) as conn:
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
sql = "SELECT count(id) FROM {}".format(str)
|
sql = "SELECT count(id) FROM {}".format(str)
|
||||||
count = cur.execute(sql)
|
count = cur.execute(sql).fetchone()[0]
|
||||||
count = cur.fetchone()[0]
|
return count
|
||||||
|
|
||||||
|
|
||||||
|
async def get_number_of_feeds_active(db_file):
|
||||||
|
"""
|
||||||
|
Return number of active feeds.
|
||||||
|
|
||||||
|
:param db_file: Database filename.
|
||||||
|
:param cur: Cursor object.
|
||||||
|
:return: Number of rows.
|
||||||
|
"""
|
||||||
|
with create_connection(db_file) as conn:
|
||||||
|
cur = conn.cursor()
|
||||||
|
sql = "SELECT count(id) FROM feeds WHERE enabled = 1"
|
||||||
|
count = cur.execute(sql).fetchone()[0]
|
||||||
return count
|
return count
|
||||||
|
|
||||||
|
|
||||||
|
@ -209,8 +225,7 @@ async def get_number_of_entries_unread(db_file):
|
||||||
with create_connection(db_file) as conn:
|
with create_connection(db_file) as conn:
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
sql = "SELECT count(id) FROM entries WHERE read = 0"
|
sql = "SELECT count(id) FROM entries WHERE read = 0"
|
||||||
count = cur.execute(sql)
|
count = cur.execute(sql).fetchone()[0]
|
||||||
count = cur.fetchone()[0]
|
|
||||||
return count
|
return count
|
||||||
|
|
||||||
|
|
||||||
|
@ -223,26 +238,18 @@ async def get_entry_unread(db_file):
|
||||||
"""
|
"""
|
||||||
with create_connection(db_file) as conn:
|
with create_connection(db_file) as conn:
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
entry = []
|
|
||||||
sql = "SELECT id FROM entries WHERE read = 0"
|
sql = "SELECT id FROM entries WHERE read = 0"
|
||||||
ix = cur.execute(sql).fetchone()
|
ix = cur.execute(sql).fetchone()
|
||||||
if ix is None:
|
if ix is None:
|
||||||
return False
|
return False
|
||||||
ix = ix[0]
|
ix = ix[0]
|
||||||
sql = "SELECT title FROM entries WHERE id = :id"
|
sql = "SELECT title FROM entries WHERE id = :id"
|
||||||
cur.execute(sql, (ix,))
|
title = cur.execute(sql, (ix,)).fetchone()[0]
|
||||||
title = cur.fetchone()[0]
|
|
||||||
entry.append(title)
|
|
||||||
sql = "SELECT summary FROM entries WHERE id = :id"
|
sql = "SELECT summary FROM entries WHERE id = :id"
|
||||||
cur.execute(sql, (ix,))
|
summary = cur.execute(sql, (ix,)).fetchone()[0]
|
||||||
summary = cur.fetchone()[0]
|
|
||||||
entry.append(summary)
|
|
||||||
sql = "SELECT link FROM entries WHERE id = :id"
|
sql = "SELECT link FROM entries WHERE id = :id"
|
||||||
cur.execute(sql, (ix,))
|
link = cur.execute(sql, (ix,)).fetchone()[0]
|
||||||
link = cur.fetchone()[0]
|
entry = "{}\n\n{}\n\n{}".format(title, summary, link)
|
||||||
entry.append(link)
|
|
||||||
entry = "{}\n\n{}\n\n{}".format(entry[0], entry[1], entry[2])
|
|
||||||
# print(entry)
|
|
||||||
async with DBLOCK:
|
async with DBLOCK:
|
||||||
await mark_as_read(cur, ix)
|
await mark_as_read(cur, ix)
|
||||||
# async with DBLOCK:
|
# async with DBLOCK:
|
||||||
|
@ -264,17 +271,28 @@ async def mark_as_read(cur, ix):
|
||||||
async def statistics(db_file):
|
async def statistics(db_file):
|
||||||
"""
|
"""
|
||||||
Return table statistics.
|
Return table statistics.
|
||||||
|
|
||||||
:param db_file: Database filename.
|
:param db_file: Database filename.
|
||||||
:return: News item as message.
|
:return: News item as message.
|
||||||
"""
|
"""
|
||||||
feeds = await get_number_of_items(db_file, 'feeds')
|
feeds = await get_number_of_items(db_file, 'feeds')
|
||||||
|
active_feeds = await get_number_of_feeds_active(db_file)
|
||||||
entries = await get_number_of_items(db_file, 'entries')
|
entries = await get_number_of_items(db_file, 'entries')
|
||||||
unread_entries = await get_number_of_entries_unread(db_file)
|
unread_entries = await get_number_of_entries_unread(db_file)
|
||||||
msg = "You have {} unread news items out of {} from {} news sources.".format(unread_entries, entries, feeds)
|
# msg = """You have {} unread news items out of {} from {} news sources.
|
||||||
|
# """.format(unread_entries, entries, feeds)
|
||||||
|
with create_connection(db_file) as conn:
|
||||||
|
cur = conn.cursor()
|
||||||
|
sql = "SELECT value FROM settings WHERE key = \"enabled\""
|
||||||
|
status = cur.execute(sql).fetchone()[0]
|
||||||
|
sql = "SELECT value FROM settings WHERE key = \"interval\""
|
||||||
|
interval = cur.execute(sql).fetchone()[0]
|
||||||
|
msg = """News items: {} ({})\nNews sources: {} ({})\nUpdate interval: {}\nOperation status: {}
|
||||||
|
""".format(unread_entries, entries, active_feeds, feeds, interval, status)
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
|
|
||||||
|
#TODO statistics
|
||||||
async def update_statistics(cur):
|
async def update_statistics(cur):
|
||||||
"""
|
"""
|
||||||
Update table statistics.
|
Update table statistics.
|
||||||
|
@ -293,8 +311,7 @@ async def update_statistics(cur):
|
||||||
cur.execute(sql, {"title": i, "num": stat_dict[i]})
|
cur.execute(sql, {"title": i, "num": stat_dict[i]})
|
||||||
else:
|
else:
|
||||||
sql = "SELECT count(id) FROM statistics"
|
sql = "SELECT count(id) FROM statistics"
|
||||||
count = cur.execute(sql)
|
count = cur.execute(sql).fetchone()[0]
|
||||||
count = cur.fetchone()[0]
|
|
||||||
ix = count + 1
|
ix = count + 1
|
||||||
sql = "INSERT INTO statistics VALUES(?,?,?)"
|
sql = "INSERT INTO statistics VALUES(?,?,?)"
|
||||||
cur.execute(sql, (ix, i, stat_dict[i]))
|
cur.execute(sql, (ix, i, stat_dict[i]))
|
||||||
|
@ -312,33 +329,34 @@ async def toggle_status(db_file, ix):
|
||||||
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()
|
||||||
#cur = get_cursor(db_file)
|
try:
|
||||||
sql = "SELECT name FROM feeds WHERE id = :id"
|
#cur = get_cursor(db_file)
|
||||||
cur.execute(sql, (ix,))
|
sql = "SELECT name FROM feeds WHERE id = :id"
|
||||||
title = cur.fetchone()[0]
|
title = cur.execute(sql, (ix,)).fetchone()[0]
|
||||||
sql = "SELECT enabled FROM feeds WHERE id = ?"
|
sql = "SELECT enabled FROM feeds WHERE id = ?"
|
||||||
# NOTE [0][1][2]
|
# NOTE [0][1][2]
|
||||||
cur.execute(sql, (ix,))
|
status = cur.execute(sql, (ix,)).fetchone()[0]
|
||||||
status = cur.fetchone()[0]
|
# FIXME always set to 1
|
||||||
# FIXME always set to 1
|
# NOTE Maybe because is not integer
|
||||||
# NOTE Maybe because is not integer
|
# TODO Reset feed table before further testing
|
||||||
# TODO Reset feed table before further testing
|
if status == 1:
|
||||||
if status == 1:
|
status = 0
|
||||||
status = 0
|
state = "disabled"
|
||||||
state = "disabled"
|
else:
|
||||||
else:
|
status = 1
|
||||||
status = 1
|
state = "enabled"
|
||||||
state = "enabled"
|
sql = "UPDATE feeds SET enabled = :status WHERE id = :id"
|
||||||
sql = "UPDATE feeds SET enabled = :status WHERE id = :id"
|
cur.execute(sql, {"status": status, "id": ix})
|
||||||
cur.execute(sql, {"status": status, "id": ix})
|
msg = "Updates for '{}' are now {}.".format(title, state)
|
||||||
msg = "Updates for '{}' are now {}".format(title, state)
|
except:
|
||||||
|
msg = "No news source with ID {}.".format(ix)
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
|
|
||||||
async def set_date(cur, url):
|
async def set_date(cur, url):
|
||||||
"""
|
"""
|
||||||
Set last update date of feed.
|
Set last update date of feed.
|
||||||
|
|
||||||
:param cur: Cursor object.
|
:param cur: Cursor object.
|
||||||
:param url: URL.
|
:param url: URL.
|
||||||
"""
|
"""
|
||||||
|
@ -384,7 +402,7 @@ async def update_source_validity(db_file, source, valid):
|
||||||
async def add_entry(cur, entry):
|
async def add_entry(cur, entry):
|
||||||
"""
|
"""
|
||||||
Add a new entry into the entries table.
|
Add a new entry into the entries table.
|
||||||
|
|
||||||
:param cur: Cursor object.
|
:param cur: Cursor object.
|
||||||
:param entry:
|
:param entry:
|
||||||
"""
|
"""
|
||||||
|
@ -414,8 +432,7 @@ async def remove_entry(db_file, source, length):
|
||||||
with create_connection(db_file) as conn:
|
with create_connection(db_file) as conn:
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
sql = "SELECT count(id) FROM entries WHERE source = ?"
|
sql = "SELECT count(id) FROM entries WHERE source = ?"
|
||||||
count = cur.execute(sql, (source,))
|
count = cur.execute(sql, (source,)).fetchone()[0]
|
||||||
count = cur.fetchone()[0]
|
|
||||||
limit = count - length
|
limit = count - length
|
||||||
if limit:
|
if limit:
|
||||||
limit = limit;
|
limit = limit;
|
||||||
|
@ -432,7 +449,7 @@ async def remove_nonexistent_entries(db_file, feed, source):
|
||||||
Remove entries that don't exist in a given parsed feed.
|
Remove entries that don't exist in a given parsed feed.
|
||||||
Check the entries returned from feed and delete non
|
Check the entries returned from feed and delete non
|
||||||
existing entries
|
existing entries
|
||||||
|
|
||||||
:param db_file: Database filename.
|
:param db_file: Database filename.
|
||||||
:param feed: URL of parsed feed.
|
:param feed: URL of parsed feed.
|
||||||
:param source: URL of associated feed.
|
:param source: URL of associated feed.
|
||||||
|
@ -441,8 +458,7 @@ async def remove_nonexistent_entries(db_file, feed, source):
|
||||||
with create_connection(db_file) as conn:
|
with create_connection(db_file) as conn:
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
sql = "SELECT id, title, link FROM entries WHERE source = ?"
|
sql = "SELECT id, title, link FROM entries WHERE source = ?"
|
||||||
cur.execute(sql, (source,))
|
entries_db = cur.execute(sql, (source,)).fetchall()
|
||||||
entries_db = cur.fetchall()
|
|
||||||
for entry_db in entries_db:
|
for entry_db in entries_db:
|
||||||
exist = False
|
exist = False
|
||||||
for entry_feed in feed.entries:
|
for entry_feed in feed.entries:
|
||||||
|
@ -477,15 +493,14 @@ async def get_subscriptions(db_file):
|
||||||
with create_connection(db_file) as conn:
|
with create_connection(db_file) as conn:
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
sql = "SELECT address FROM feeds WHERE enabled = 1"
|
sql = "SELECT address FROM feeds WHERE enabled = 1"
|
||||||
cur.execute(sql)
|
result = cur.execute(sql).fetchall()
|
||||||
result = cur.fetchall()
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
async def list_subscriptions(db_file):
|
async def list_subscriptions(db_file):
|
||||||
"""
|
"""
|
||||||
Query table feeds and list items.
|
Query table feeds and list items.
|
||||||
|
|
||||||
:param db_file: Database filename.
|
:param db_file: Database filename.
|
||||||
:return: List of feeds.
|
:return: List of feeds.
|
||||||
"""
|
"""
|
||||||
|
@ -566,7 +581,7 @@ async def check_entry_exist(db_file, title, link):
|
||||||
"""
|
"""
|
||||||
Check whether an entry exists.
|
Check whether an entry exists.
|
||||||
Query entries by title and link.
|
Query entries by title and link.
|
||||||
|
|
||||||
:param db_file: Database filename.
|
:param db_file: Database filename.
|
||||||
:param link: Entry URL.
|
:param link: Entry URL.
|
||||||
:param title: Entry title.
|
:param title: Entry title.
|
||||||
|
@ -574,8 +589,7 @@ async def check_entry_exist(db_file, title, link):
|
||||||
"""
|
"""
|
||||||
cur = get_cursor(db_file)
|
cur = get_cursor(db_file)
|
||||||
sql = "SELECT id FROM entries WHERE title = :title and link = :link"
|
sql = "SELECT id FROM entries WHERE title = :title and link = :link"
|
||||||
cur.execute(sql, {"title": title, "link": link})
|
result = cur.execute(sql, {"title": title, "link": link}).fetchone()
|
||||||
result = cur.fetchone()
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
# TODO dictionary
|
# TODO dictionary
|
||||||
|
@ -597,20 +611,22 @@ async def check_entry_exist(db_file, title, link):
|
||||||
async def set_settings_value(db_file, key_value):
|
async def set_settings_value(db_file, key_value):
|
||||||
"""
|
"""
|
||||||
Set settings value.
|
Set settings value.
|
||||||
|
|
||||||
:param db_file: Database filename.
|
:param db_file: Database filename.
|
||||||
:param key_value: List of key ("enabled", "interval", "quantum") and value (Integer).
|
:param key_value: List of key ("enabled", "interval", "quantum") and value (Integer).
|
||||||
:return: Message.
|
:return: Message.
|
||||||
"""
|
"""
|
||||||
if isinstance(key_value, list):
|
# if isinstance(key_value, list):
|
||||||
key = key_value[0]
|
# key = key_value[0]
|
||||||
val = key_value[1]
|
# val = key_value[1]
|
||||||
elif key_value == "enable":
|
# elif key_value == "enable":
|
||||||
key = "enabled"
|
# key = "enabled"
|
||||||
val = 1
|
# val = 1
|
||||||
else:
|
# else:
|
||||||
key = "enabled"
|
# key = "enabled"
|
||||||
val = 0
|
# val = 0
|
||||||
|
key = key_value[0]
|
||||||
|
val = key_value[1]
|
||||||
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()
|
||||||
|
@ -618,11 +634,15 @@ async def set_settings_value(db_file, key_value):
|
||||||
sql = "UPDATE settings SET value = :value WHERE key = :key"
|
sql = "UPDATE settings SET value = :value WHERE key = :key"
|
||||||
cur.execute(sql, {"key": key, "value": val})
|
cur.execute(sql, {"key": key, "value": val})
|
||||||
if key == 'quantum':
|
if key == 'quantum':
|
||||||
msg = "Every update will contain {} news items.".format(val)
|
msg = "Each update will contain {} news items.".format(val)
|
||||||
elif key == 'interval':
|
elif key == 'interval':
|
||||||
msg = "Updates will be sent every {} minutes.".format(val)
|
msg = "Updates will be sent every {} minutes.".format(val)
|
||||||
else:
|
else:
|
||||||
msg = "Updates are {}d.".format(key_value)
|
if val:
|
||||||
|
status = "disabled"
|
||||||
|
else:
|
||||||
|
status = "enabled"
|
||||||
|
msg = "Updates are {}.".format(status)
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
|
|
||||||
|
@ -648,7 +668,7 @@ async def set_settings_value_default(cur, key):
|
||||||
async def get_settings_value(db_file, key):
|
async def get_settings_value(db_file, key):
|
||||||
"""
|
"""
|
||||||
Get settings value.
|
Get settings value.
|
||||||
|
|
||||||
:param db_file: Database filename.
|
:param db_file: Database filename.
|
||||||
:param key: "enabled", "interval", "quantum".
|
:param key: "enabled", "interval", "quantum".
|
||||||
"""
|
"""
|
||||||
|
@ -667,8 +687,7 @@ async def get_settings_value(db_file, key):
|
||||||
try:
|
try:
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
sql = "SELECT value FROM settings WHERE key = ?"
|
sql = "SELECT value FROM settings WHERE key = ?"
|
||||||
cur.execute(sql, (key,))
|
result = cur.execute(sql, (key,)).fetchone()[0]
|
||||||
result = cur.fetchone()[0]
|
|
||||||
except:
|
except:
|
||||||
result = await set_settings_value_default(cur, key)
|
result = await set_settings_value_default(cur, key)
|
||||||
if not result:
|
if not result:
|
||||||
|
|
Loading…
Reference in a new issue