retryTTL support list
This commit is contained in:
@@ -1,4 +1,7 @@
|
|||||||
# Telegram RSS Bot
|
# Telegram RSS Bot
|
||||||
|
- [开始使用](#开始使用)
|
||||||
|
- [配置](#配置)
|
||||||
|
- [命令行参数](#命令行参数)
|
||||||
## 开始使用
|
## 开始使用
|
||||||
安装依赖库,配置好设置里的`token`参数,然后运行`rssbot.py`即可。
|
安装依赖库,配置好设置里的`token`参数,然后运行`rssbot.py`即可。
|
||||||
## 配置
|
## 配置
|
||||||
@@ -47,7 +50,9 @@ rssbotLib=rssbot.dll
|
|||||||
### databaseLocation
|
### databaseLocation
|
||||||
可选参数。数据库位置。默认值为`data.db`。
|
可选参数。数据库位置。默认值为`data.db`。
|
||||||
### retryTTL
|
### retryTTL
|
||||||
可选参数。RSS更新发生错误后,再次更新的间隔时间。默认值为`30`。单位为分。
|
可选参数。RSS更新发生错误后,再次更新的间隔时间。支持以`,`为分隔的列表,分别表示第一次更新错误后等待的时间、第二次更新错误后等待的时间……超过列表范围会采用列表中的最后一个值。
|
||||||
|
例如设置为`5,15`,则第一次更新错误后等待5分钟,第二次更新错误后等待15分钟,第三次更新错误后等待15分钟……
|
||||||
|
默认值为`30`。单位为分。
|
||||||
### botOwnerList
|
### botOwnerList
|
||||||
可选参数。具有特殊权限的用户ID,这些用户可以使用部分特殊功能。可以使用`,`分隔两个不同的ID。
|
可选参数。具有特殊权限的用户ID,这些用户可以使用部分特殊功能。可以使用`,`分隔两个不同的ID。
|
||||||
特殊权限:
|
特殊权限:
|
||||||
|
|||||||
@@ -139,5 +139,8 @@ class RSSEntry:
|
|||||||
self.forceupdate = False
|
self.forceupdate = False
|
||||||
if data is not None and data[6] is not None:
|
if data is not None and data[6] is not None:
|
||||||
self.forceupdate = bool(data[6])
|
self.forceupdate = bool(data[6])
|
||||||
|
self.errorcount = 0
|
||||||
|
if data is not None and data[7] is not None:
|
||||||
|
self.errorcount = data[7]
|
||||||
self.chatList = []
|
self.chatList = []
|
||||||
self.hashList = HashEntries(maxCount)
|
self.hashList = HashEntries(maxCount)
|
||||||
|
|||||||
20
database.py
20
database.py
@@ -55,6 +55,10 @@ class database:
|
|||||||
'ALTER TABLE RSSList ADD forceupdate BOOLEAN;')
|
'ALTER TABLE RSSList ADD forceupdate BOOLEAN;')
|
||||||
self._db.execute('UPDATE RSSList SET forceupdate=false;')
|
self._db.execute('UPDATE RSSList SET forceupdate=false;')
|
||||||
self._db.commit()
|
self._db.commit()
|
||||||
|
if v < [1, 0, 0, 3]:
|
||||||
|
self._db.execute('ALTER TABLE RSSList ADD errorcount INT;')
|
||||||
|
self._db.execute('UPDATE RSSList SET errorcount=0;')
|
||||||
|
self._db.commit()
|
||||||
self.__write_version()
|
self.__write_version()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -76,6 +80,7 @@ lastupdatetime INT,
|
|||||||
id TEXT,
|
id TEXT,
|
||||||
lasterrortime INT,
|
lasterrortime INT,
|
||||||
forceupdate BOOLEAN,
|
forceupdate BOOLEAN,
|
||||||
|
errorcount INT,
|
||||||
PRIMARY KEY (id)
|
PRIMARY KEY (id)
|
||||||
);''')
|
);''')
|
||||||
if 'chatList' not in self._exist_tables:
|
if 'chatList' not in self._exist_tables:
|
||||||
@@ -101,7 +106,7 @@ PRIMARY KEY (hash)
|
|||||||
self._db.commit()
|
self._db.commit()
|
||||||
|
|
||||||
def __init__(self, m, loc: str):
|
def __init__(self, m, loc: str):
|
||||||
self._version = [1, 0, 0, 2]
|
self._version = [1, 0, 0, 3]
|
||||||
self._value_lock = Lock()
|
self._value_lock = Lock()
|
||||||
self._db = sqlite3.connect(loc, check_same_thread=False)
|
self._db = sqlite3.connect(loc, check_same_thread=False)
|
||||||
ok = self.__check_database()
|
ok = self.__check_database()
|
||||||
@@ -145,7 +150,7 @@ PRIMARY KEY (hash)
|
|||||||
f"UPDATE RSSList SET title='{dealtext(title)}', interval={ttl if ttl is not None else 'null'} WHERE id='{hashd}'")
|
f"UPDATE RSSList SET title='{dealtext(title)}', interval={ttl if ttl is not None else 'null'} WHERE id='{hashd}'")
|
||||||
else:
|
else:
|
||||||
self._db.execute(
|
self._db.execute(
|
||||||
f"INSERT INTO RSSList VALUES ('{dealtext(title)}', '{dealtext(url)}', {ttl if ttl is not None else 'null'}, {int(time())}, '{hashd}', null, false)")
|
f"INSERT INTO RSSList VALUES ('{dealtext(title)}', '{dealtext(url)}', {ttl if ttl is not None else 'null'}, {int(time())}, '{hashd}', null, false, 0)")
|
||||||
cur = self._db.execute(
|
cur = self._db.execute(
|
||||||
f'SELECT * FROM chatList WHERE id="{hashd}" AND chatId={chatId}')
|
f'SELECT * FROM chatList WHERE id="{hashd}" AND chatId={chatId}')
|
||||||
has_data2 = False
|
has_data2 = False
|
||||||
@@ -199,11 +204,11 @@ PRIMARY KEY (hash)
|
|||||||
def getRSSListByChatId(self, chatId: int) -> List[RSSEntry]:
|
def getRSSListByChatId(self, chatId: int) -> List[RSSEntry]:
|
||||||
with self._value_lock:
|
with self._value_lock:
|
||||||
cur = self._db.execute(
|
cur = self._db.execute(
|
||||||
f"SELECT RSSList.title, RSSList.url, RSSList.interval, RSSList.lastupdatetime, RSSList.id, RSSList.lasterrortime, RSSList.forceupdate, 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, RSSList.forceupdate, RSSList.errorcount, chatList.config FROM RSSList, chatList WHERE chatList.chatId = {chatId} AND RSSList.id = chatList.id ORDER BY title")
|
||||||
RSSEntries = []
|
RSSEntries = []
|
||||||
for i in cur:
|
for i in cur:
|
||||||
rssEntry = RSSEntry(i, self._main._setting._maxCount)
|
rssEntry = RSSEntry(i, self._main._setting._maxCount)
|
||||||
rssEntry.chatList.append(ChatEntry((chatId, i[4], i[7])))
|
rssEntry.chatList.append(ChatEntry((chatId, i[4], i[8])))
|
||||||
RSSEntries.append(rssEntry)
|
RSSEntries.append(rssEntry)
|
||||||
return RSSEntries
|
return RSSEntries
|
||||||
|
|
||||||
@@ -307,7 +312,7 @@ PRIMARY KEY (hash)
|
|||||||
if not has_data:
|
if not has_data:
|
||||||
return False
|
return False
|
||||||
self._db.execute(
|
self._db.execute(
|
||||||
f"UPDATE RSSList SET title='{dealtext(title)}', interval={ttl if ttl is not None else 'null'}, lastupdatetime={lastupdatetime} WHERE id='{hashd}'")
|
f"UPDATE RSSList SET title='{dealtext(title)}', interval={ttl if ttl is not None else 'null'}, lastupdatetime={lastupdatetime}, errorcount=0 WHERE id='{hashd}'")
|
||||||
cur = self._db.execute(
|
cur = self._db.execute(
|
||||||
f"SELECT * FROM hashList WHERE id='{hashd}'")
|
f"SELECT * FROM hashList WHERE id='{hashd}'")
|
||||||
has_data2 = False
|
has_data2 = False
|
||||||
@@ -332,13 +337,14 @@ PRIMARY KEY (hash)
|
|||||||
cur = self._db.execute(
|
cur = self._db.execute(
|
||||||
f'SELECT * FROM RSSList WHERE id="{hashd}"')
|
f'SELECT * FROM RSSList WHERE id="{hashd}"')
|
||||||
has_data = False
|
has_data = False
|
||||||
for i in cur: # pylint: disable=unused-variable
|
for i in cur:
|
||||||
|
rss = RSSEntry(i, self._main._setting._maxCount)
|
||||||
has_data = True
|
has_data = True
|
||||||
break
|
break
|
||||||
if not has_data:
|
if not has_data:
|
||||||
return False
|
return False
|
||||||
self._db.execute(
|
self._db.execute(
|
||||||
f"UPDATE RSSList SET lasterrortime={lasterrortime} WHERE id='{hashd}'")
|
f"UPDATE RSSList SET lasterrortime={lasterrortime}, errorcount={rss.errorcount + 1} WHERE id='{hashd}'")
|
||||||
self._db.commit()
|
self._db.commit()
|
||||||
return True
|
return True
|
||||||
except:
|
except:
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
from typing import List
|
from typing import List
|
||||||
from getopt import getopt
|
from getopt import getopt
|
||||||
from botOwner import BotOwnerList
|
from botOwner import BotOwnerList
|
||||||
|
from retryTTL import RetryTTLList
|
||||||
|
|
||||||
|
|
||||||
class settings:
|
class settings:
|
||||||
@@ -49,8 +50,8 @@ class settings:
|
|||||||
d['sendFileURLScheme'])) if 'sendFileURLScheme' in d and d['sendFileURLScheme'].isnumeric() else False
|
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._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._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(
|
self._retryTTL = RetryTTLList(
|
||||||
) and int(d['retryTTL']) > 0 else 30
|
d['retryTTL']) if 'retryTTL' in d and d['retryTTL'] != '' else RetryTTLList()
|
||||||
self._botOwnerList = BotOwnerList(
|
self._botOwnerList = BotOwnerList(
|
||||||
self._main, d['botOwnerList']) if 'botOwnerList' in d and d['botOwnerList'] != '' else BotOwnerList(self._main)
|
self._main, d['botOwnerList']) if 'botOwnerList' in d and d['botOwnerList'] != '' else BotOwnerList(self._main)
|
||||||
|
|
||||||
|
|||||||
29
retryTTL.py
Normal file
29
retryTTL.py
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# (C) 2021 lifegpc
|
||||||
|
# This file is part of rssbot.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as published
|
||||||
|
# by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
class RetryTTLList:
|
||||||
|
def __init__(self, s: str = None):
|
||||||
|
self.__list = []
|
||||||
|
if s is not None:
|
||||||
|
l = s.split(',')
|
||||||
|
for i in l:
|
||||||
|
if i.isnumeric():
|
||||||
|
self.__list.append(int(i))
|
||||||
|
if len(self.__list) == 0:
|
||||||
|
self.__list.append(30)
|
||||||
|
|
||||||
|
def __getitem__(self, index: int) -> int:
|
||||||
|
index = int(index)
|
||||||
|
return None if index <= 0 else self.__list[index-1] if index <= len(self.__list) else self.__list[-1]
|
||||||
@@ -84,8 +84,8 @@ class RSSCheckerThread(Thread):
|
|||||||
def __needUpdate(self, rss: RSSEntry):
|
def __needUpdate(self, rss: RSSEntry):
|
||||||
if rss.forceupdate:
|
if rss.forceupdate:
|
||||||
return True
|
return True
|
||||||
if rss.lasterrortime is not None and rss.lasterrortime >= rss.lastupdatetime:
|
if rss.lasterrortime is not None and rss.lasterrortime >= rss.lastupdatetime and rss.errorcount > 0:
|
||||||
return True if int(time()) > rss.lasterrortime + self._main._setting._retryTTL * 60 else False
|
return True if int(time()) > rss.lasterrortime + self._main._setting._retryTTL[rss.errorcount] * 60 else False
|
||||||
if rss.lastupdatetime is None:
|
if rss.lastupdatetime is None:
|
||||||
return True
|
return True
|
||||||
TTL = self._main._setting._minTTL
|
TTL = self._main._setting._minTTL
|
||||||
|
|||||||
@@ -54,6 +54,9 @@ def getTextContentForRSSInList(rssEntry: RSSEntry) -> str:
|
|||||||
if rssEntry.lasterrortime is not None:
|
if rssEntry.lasterrortime is not None:
|
||||||
temp = f'上次更新失败时间:{timeToStr(rssEntry.lasterrortime)}'
|
temp = f'上次更新失败时间:{timeToStr(rssEntry.lasterrortime)}'
|
||||||
text.addtotext(temp)
|
text.addtotext(temp)
|
||||||
|
if rssEntry.errorcount > 0:
|
||||||
|
temp = f'连续更新失败次数:{rssEntry.errorcount}'
|
||||||
|
text.addtotext(temp)
|
||||||
if len(rssEntry.chatList) > 0:
|
if len(rssEntry.chatList) > 0:
|
||||||
chatEntry: ChatEntry = rssEntry.chatList[0]
|
chatEntry: ChatEntry = rssEntry.chatList[0]
|
||||||
config = chatEntry.config
|
config = chatEntry.config
|
||||||
|
|||||||
Reference in New Issue
Block a user