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