You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

186 lines
8.8 KiB

import sqlite3
from sqlite3 import Error
import os
import functools
import operator
import math
import re
from Render import Article
class Cache:
def __init__(self, api):
self.conn = None
self.api = api
create_categories = """create table if not exists categories (
id text primary key,
name text not null,
unread_count integer,
timestamp integer,
date text
)
"""
create_feeds = """create table if not exists feeds (
id text primary key,
name text not null,
unread_count integer,
timestamp integer,
date text,
category_id text,
foreign key (category_id) references categories (id)
)
"""
create_articles = """create table if not exists articles (
id text primary key,
title text not null,
timestamp integer,
date text,
content text,
url text,
is_read boolean,
origin text,
category_id text,
foreign key (category_id) references categories (id),
foreign key (origin) references feeds (id)
)
"""
create_links = """create table if not exists links (
id text,
url text not null,
foreign key (id) references articles (id)
)
"""
try:
self.conn = sqlite3.connect(os.path.expanduser("~") + '/.config/inomnibus/cache.db')
self.conn.cursor().execute(create_categories)
self.conn.cursor().execute(create_feeds)
self.conn.cursor().execute(create_articles)
self.conn.cursor().execute(create_links)
except Error as e:
print(e)
def markStreamAsRead(self, streamId):
cur = self.conn.cursor()
if re.search("^feed/[0-9]+", streamId):
table = "feeds"
else:
table = "categories"
cur.execute("""select timestamp from """ + table + """ where id = ?""", (streamId,))
ts = cur.fetchone()[0]
if self.api.markStreamAsRead(streamId, ts):
if table == "feeds":
cur.execute("""select unread_count from feeds where id = ?""", (streamId,))
uc = int(cur.fetchone()[0])
cur.execute("""update feeds set unread_count = 0 where id = ?""", (streamId,))
cur.execute("""update categories set unread_count = unread_count - :uc
where id in (select category_id from feeds where id = :sID)""", {"uc": uc, "sID": streamId})
cur.execute("""update articles set is_read = 1 where origin = ?""", (streamId,))
else:
cur.execute("""update categories set unread_count = 0 where id = ?""", (streamId,))
cur.execute("""update feeds set unread_count = 0 where id in (select id from feeds where category_id = ?)""", (streamId,))
cur.execute("""update articles set is_read = 1 where category_id = ?""", (streamId,))
self.conn.commit()
def getArticle(self, id):
cur = self.conn.cursor()
cur.execute("""select title,content,url from articles where id = ?""", (id,))
return cur.fetchone()
def toggleArticleStatus(self, id):
inc = 0
cur = self.conn.cursor()
cur.execute("""update articles set is_read = not is_read where id = ?""", (id,))
cur.execute("""select origin, category_id, is_read from articles where id = ?""", (id,))
feed_id, category_id, is_read = cur.fetchone()
if is_read == 0:
inc = 1
else:
inc = -1
cur.execute("""update categories set unread_count = unread_count + ? where id = ?""", (inc, category_id,))
cur.execute("""update feeds set unread_count = unread_count + ? where id = ?""", (inc, feed_id,))
if self.api.toggleArticleStatus(id, is_read):
self.conn.commit()
else:
self.conn.rollback()
def getArticleLinks(self, id):
cur = self.conn.cursor()
cur.execute("""select url from links where id = ?""", (id,))
links = functools.reduce(operator.iconcat, cur.fetchall(), [])
return links
def getArticlesFromFeed(self, feed_id, is_read):
cur = self.conn.cursor()
cur.execute("""select * from articles where origin = ? and is_read = ? order by timestamp desc""", (feed_id, is_read,))
return cur.fetchall()
def getArticlesFromCategory(self, category_id, is_read):
cur = self.conn.cursor()
cur.execute("""select * from articles where category_id = ? and is_read = ? order by timestamp desc""", (category_id, is_read,))
return cur.fetchall()
def getCategories(self, show_read):
statement = """select * from categories where unread_count != 0 order by timestamp desc"""
if show_read == 1:
statement = """select * from categories order by timestamp desc"""
cur = self.conn.cursor()
cur.execute(statement)
return cur.fetchall()
def getFeeds(self, category_id, show_read):
statement = """select * from feeds where category_id = ? and unread_count != 0 order by timestamp desc"""
if show_read == 1:
statement = """select * from feeds where category_id = ? order by timestamp desc"""
cur = self.conn.cursor()
cur.execute(statement, (category_id,))
return cur.fetchall()
def refresh(self):
timestamps = {}
cur = self.conn.cursor()
cur.execute("""select id, timestamp from categories""")
for row in cur.fetchall():
timestamps[row[0]] = row[1]
self.api.refresh()
for item in self.api.unreadCounts.keys():
if item[0:13] != "user/-/label/":
continue
data = self.api.unreadCounts[item]
cur.execute("""insert into categories(id,name,unread_count,timestamp,date) values(:id,:name,:count,:ts,:d)
on conflict(id) do update set unread_count = :count, timestamp = :ts, date = :d;
""",
{"id": item, "name": item[13:], "count": data[0], "ts": data[1], "d": data[2]})
self.conn.commit()
for item in self.api.feeds:
data = self.api.unreadCounts[item["id"]]
cur.execute("""insert into feeds(id,name,unread_count,timestamp,date,category_id) values(:id,:name,:count,:ts,:d,:c_id)
on conflict(id) do update set unread_count = :count, timestamp = :ts, date = :d,category_id = :c_id;
""",
{"id": item["id"], "name": item["title"], "count": data[0], "ts": data[1], "d": data[2],
"c_id": item["categories"][0]["id"]})
self.conn.commit()
cur.execute("""select c.id, c.name, c.unread_count,
(select count(*) from articles a where a.category_id = c.id) as articles_num from categories c""")
for row in cur.fetchall():
yield "Fetching category " + row[1]
articles = self.api.articlesFromCategory(
row[0],
count=str(row[2]),
timestamp=str(math.floor(timestamps[row[0]] / 1000000)),
number=row[3])
for article in articles:
articleObj = Article(article)
cur.execute("""insert into articles(id,title,timestamp,date,content,url,is_read,origin,category_id)
values(:id,:t,:ts,:d,:c,:u,:r,:o,:c_id) on conflict(id) do update
set id = :id, title = :t, timestamp = :ts, date = :d, content = :c, url = :u, is_read = :r, category_id = :c_id,
origin = :o;
""",
{"id": articleObj.id, "t": articleObj.title, "ts": articleObj.timestamp, "d": articleObj.date,
"c": articleObj.text, "u": articleObj.url, "r": articleObj.is_read, "o": articleObj.origin, "c_id": row[0]})
for link in articleObj.links:
cur.execute("""insert into links(id,url) values(?,?)""", (articleObj.id, link))
self.conn.commit()