From 477ff6afc47f86c8c4603460ba062c7e045e18ad Mon Sep 17 00:00:00 2001 From: lifegpc Date: Mon, 18 Jan 2021 19:18:16 +0800 Subject: [PATCH] add support to set retryTTL and fix if once update error, it will retry every second --- README.md | 9 ++++++--- RSSEntry.py | 3 +++ database.py | 42 +++++++++++++++++++++++++++++++++++++----- readset.py | 1 + rsschecker.py | 8 +++++++- rsslist.py | 3 +++ 6 files changed, 57 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 0d90bb4..c1a555c 100644 --- a/README.md +++ b/README.md @@ -22,14 +22,15 @@ rssbotLib=rssbot.dll - [sendFileURLScheme](#sendfileurlscheme) - [rssbotLib](#rssbotlib) - [databaseLocation](#databaselocation) +- [retryTTL](#retryttl) ### token 必填参数。Telegram Bot API Token。向[@BotFather](https://t.me/BotFather)请求新建Bot,即可得到。 ### maxCount -可选参数。一个RSS订阅源中支持的最大条数,超出部分将会自动被忽略。默认值为100。 +可选参数。一个RSS订阅源中支持的最大条数,超出部分将会自动被忽略。默认值为`100`。 ### minTTL -可选参数。最小更新间隔。默认值为5。单位为分。 +可选参数。最小更新间隔。默认值为`5`。单位为分。 ### maxTTL -可选参数。最大更新间隔。默认值为1440。单位为分。如果该值小于`minTTL`,将会自动设为`minTTL`。 +可选参数。最大更新间隔。默认值为`1440`。单位为分。如果该值小于`minTTL`,将会自动设为`minTTL`。 ### maxRetryCount 可选参数。使用Telegram Bot API发送信息发生错误时的最大重试次数。默认值为3。 ### telegramBotApiServer @@ -44,3 +45,5 @@ rssbotLib=rssbot.dll - 发送视频时附带时长,视频分辨率大小信息(在视频文件大于10MB时非常有用)。 ### databaseLocation 可选参数。数据库位置。默认值为`data.db`。 +### retryTTL +可选参数。RSS更新发生错误后,再次更新的间隔时间。默认值为`30`。单位为分。 diff --git a/RSSEntry.py b/RSSEntry.py index f63b389..a064ddb 100644 --- a/RSSEntry.py +++ b/RSSEntry.py @@ -133,5 +133,8 @@ class RSSEntry: self.id = None if data is not None and data[4] is not None: self.id = data[4] + self.lasterrortime = None + if data is not None and data[5] is not None: + self.lasterrortime = data[5] self.chatList = [] self.hashList = HashEntries(maxCount) diff --git a/database.py b/database.py index 5967c44..d86e035 100644 --- a/database.py +++ b/database.py @@ -40,9 +40,17 @@ class database: for i in cur: if i[0] == 'table': self._exist_tables[i[1]] = i - for i in ['config', 'RSSList']: + for i in ['config', 'RSSList', 'chatList', 'userStatus', 'hashList']: if i not in self._exist_tables: return False + v = self.__read_version() + if v is None: + return False + if v < self._version: + if v == [1, 0, 0, 0]: + self._db.execute('ALTER TABLE RSSList ADD lasterrortime INT;') + self._db.commit() + self.__write_version() return True def __create_table(self): @@ -61,6 +69,7 @@ url TEXT, interval INT, lastupdatetime INT, id TEXT, +lasterrortime INT, PRIMARY KEY (id) );''') if 'chatList' not in self._exist_tables: @@ -86,7 +95,7 @@ PRIMARY KEY (hash) self._db.commit() def __init__(self, m, loc: str): - self._version = [1, 0, 0, 0] + self._version = [1, 0, 0, 1] self._value_lock = Lock() self._db = sqlite3.connect(loc, check_same_thread=False) ok = self.__check_database() @@ -109,6 +118,11 @@ PRIMARY KEY (hash) f'INSERT INTO config VALUES ({self._version[0]}, {self._version[1]}, {self._version[2]}, {self._version[3]});') self._db.commit() + def __read_version(self) -> List[int]: + cur = self._db.execute(f'SELECT * FROM config;') + for i in cur: + return [k for k in i] + def addRSSList(self, title: str, url: str, chatId: int, config: RSSConfig, ttl: int = None, hashEntries: HashEntries = None): with self._value_lock: try: @@ -124,7 +138,7 @@ PRIMARY KEY (hash) f"UPDATE RSSList SET title='{dealtext(title)}', interval={ttl if ttl is not None else 'null'} WHERE id='{hashd}'") else: self._db.execute( - f"INSERT INTO RSSList VALUES ('{dealtext(title)}', '{dealtext(url)}', {ttl if ttl is not None else 'null'}, {int(time())}, '{hashd}')") + f"INSERT INTO RSSList VALUES ('{dealtext(title)}', '{dealtext(url)}', {ttl if ttl is not None else 'null'}, {int(time())}, '{hashd}', null)") cur = self._db.execute( f'SELECT * FROM chatList WHERE id="{hashd}" AND chatId={chatId}') has_data2 = False @@ -178,11 +192,11 @@ PRIMARY KEY (hash) def getRSSListByChatId(self, chatId: int) -> List[RSSEntry]: with self._value_lock: cur = self._db.execute( - f"SELECT RSSList.title, RSSList.url, RSSList.interval, RSSList.lastupdatetime, RSSList.id, chatList.config FROM RSSList, chatList WHERE chatList.chatId = {chatId} AND RSSList.id = chatList.id ORDER BY title") + f"SELECT RSSList.title, RSSList.url, RSSList.interval, RSSList.lastupdatetime, RSSList.id, RSSList.lasterrortime, chatList.config FROM RSSList, chatList WHERE chatList.chatId = {chatId} AND RSSList.id = chatList.id ORDER BY title") RSSEntries = [] for i in cur: rssEntry = RSSEntry(i, self._main._setting._maxCount) - rssEntry.chatList.append(ChatEntry((chatId, i[4], i[5]))) + rssEntry.chatList.append(ChatEntry((chatId, i[4], i[6]))) RSSEntries.append(rssEntry) return RSSEntries @@ -283,3 +297,21 @@ PRIMARY KEY (hash) self._db.commit() except: return False + + def updateRSSWithError(self, url: str, lasterrortime: int): + with self._value_lock: + try: + hashd = sha256WithBase64(url) + cur = self._db.execute( + f'SELECT * FROM RSSList WHERE id="{hashd}"') + has_data = False + for i in cur: # pylint: disable=unused-variable + has_data = True + break + if not has_data: + return False + self._db.execute( + f"UPDATE RSSList SET lasterrortime={lasterrortime} WHERE id='{hashd}'") + self._db.commit() + except: + return False diff --git a/readset.py b/readset.py index f639bc4..6a95ea9 100644 --- a/readset.py +++ b/readset.py @@ -46,6 +46,7 @@ class settings: d['sendFileURLScheme'])) if 'sendFileURLScheme' in d and d['sendFileURLScheme'].isnumeric() else False self._rssbotLib = d['rssbotLib'] if 'rssbotLib' in d and d['rssbotLib'] != '' else None self._databaseLocation = d['databaseLocation'] if 'databaseLocation' in d and d['databaseLocation'] != '' else 'data.db' + self._retryTTL = int(d['retryTTL']) if 'retryTTL' in d and d['retryTTL'].isnumeric() and int(d['retryTTL']) > 0 else 30 class commandline: diff --git a/rsschecker.py b/rsschecker.py index 449eed2..f1a0f0c 100644 --- a/rsschecker.py +++ b/rsschecker.py @@ -47,7 +47,8 @@ class RSSCheckerThread(Thread): chatEntry: ChatEntry = info try: for i in range(self._main._setting._maxRetryCount + 1): - suc, text = self._main._sendMessage(chatEntry.chatId, meta, item, chatEntry.config, True) + suc, text = self._main._sendMessage( + chatEntry.chatId, meta, item, chatEntry.config, True) if suc: break sleep(5) @@ -61,10 +62,13 @@ class RSSCheckerThread(Thread): 'chat_id': chatEntry.chatId, 'text': f'已尝试重发{i}次,发送失败。\n{text}{text2}'}) except: print(format_exc()) + else: + raise ValueError('Unknown RSS.') self._main._db.updateRSS( rss.title, rss.url, updateTime, rss.hashList, p.ttl) except: print(format_exc()) + self._main._db.updateRSSWithError(rss.url, int(time())) if self._main._commandLine._rebuildHashlist and self._main._commandLine._exitAfterRebuild: _exit(0) self._main._commandLine._rebuildHashlist = False @@ -76,6 +80,8 @@ class RSSCheckerThread(Thread): self._main: main = m def __needUpdate(self, rss: RSSEntry): + if rss.lasterrortime is not None and rss.lasterrortime >= rss.lastupdatetime: + return True if int(time()) > rss.lasterrortime + self._main._setting._retryTTL * 60 else False if rss.lastupdatetime is None: return True TTL = self._main._setting._minTTL diff --git a/rsslist.py b/rsslist.py index 2366d19..b8da9bc 100644 --- a/rsslist.py +++ b/rsslist.py @@ -49,6 +49,9 @@ def getTextContentForRSSInList(rssEntry: RSSEntry) -> str: text.addtotext(temp) temp = '上次更新时间:未知' if rssEntry.lastupdatetime is None or rssEntry.lastupdatetime < 0 else f'上次更新时间:{timeToStr(rssEntry.lastupdatetime)}' text.addtotext(temp) + if rssEntry.lasterrortime is not None: + temp = f'上次更新失败时间:{timeToStr(rssEntry.lasterrortime)}' + text.addtotext(temp) if len(rssEntry.chatList) > 0: chatEntry: ChatEntry = rssEntry.chatList[0] config = chatEntry.config