From b4003324233dc2d5f3ad2e479004c0b10c186873 Mon Sep 17 00:00:00 2001 From: lifegpc Date: Sun, 4 Sep 2022 15:00:24 +0000 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=AE=A1=E7=90=86=E8=8F=9C?= =?UTF-8?q?=E5=8D=95=EF=BC=88=E6=9C=AA=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- database.py | 37 ++++++++++++++++++++++++++++- manage.py | 39 ++++++++++++++++++++++++++++++ rssbot.py | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 141 insertions(+), 3 deletions(-) create mode 100644 manage.py diff --git a/database.py b/database.py index 17eb146..aff56eb 100644 --- a/database.py +++ b/database.py @@ -68,6 +68,12 @@ reason TEXT, name TEXT, PRIMARY KEY (userId) )''' +CHATNAMECACHE_TABLE = '''CREATE TABLE chatNameCache ( +id INT, +name TEXT, +time INT, +PRIMARY KEY (id) +)''' @unique @@ -142,6 +148,9 @@ class database: if v < [1, 0, 0, 8]: self._db.execute('ALTER TABLE RSSList ADD settings TEXT;') self._db.commit() + if v < [1, 0, 0, 9]: + self._db.execute(CHATNAMECACHE_TABLE) + self._db.commit() self._db.execute('VACUUM;') self.__updateExistsTable() self.__write_version() @@ -161,10 +170,12 @@ class database: self._db.execute(HASHLIST_TABLE) if 'userBlackList' not in self._exist_tables: self._db.execute(USERBLACKLIST_TABLE) + if 'chatNameCache' not in self._exist_tables: + self._db.execute(CHATNAMECACHE_TABLE) self._db.commit() def __init__(self, m, loc: str): - self._version = [1, 0, 0, 8] + self._version = [1, 0, 0, 9] self._value_lock = Lock() self._db = sqlite3.connect(loc, check_same_thread=False) self._db.execute('VACUUM;') @@ -327,6 +338,13 @@ class database: return i[0] return None + def getChatName(self, chat_id: int, maxCacheTime: int = 3600) -> Optional[str]: + with self._value_lock: + cur = self._db.execute('SELECT name FROM chatNameCache WHERE id = ? AND time > ?;', (chat_id, round(time()) - maxCacheTime)) + for i in cur: + return i[0] + return None + def getChatRSSCount(self) -> int: with self._value_lock: cur = self._db.execute('SELECT COUNT(*) FROM chatList;') @@ -341,6 +359,14 @@ class database: return i[0] return None + def getRSSList(self) -> Optional[List[RSSEntry]]: + with self._value_lock: + cur = self._db.execute(f'SELECT * FROM RSSList;') + r = [] + for i in cur: + r.append(RSSEntry(i, self._main._setting.maxCount)) + return r + def getRSSByIdAndChatId(self, id: int, chatId: int) -> RSSEntry: while self._value_lock: cur = self._db.execute('SELECT RSSList.title, RSSList.url, RSSList.interval, RSSList.lastupdatetime, RSSList.id, RSSList.lasterrortime, RSSList.forceupdate, RSSList.errorcount, RSSList.settings, chatList.config FROM chatList INNER JOIN RSSList ON RSSList.id = chatList.id WHERE chatList.chatId = ? AND chatlist.id = ?;', (chatId, id)) @@ -424,6 +450,15 @@ class database: except: return False + def saveChatName(self, chatId: int, name: str) -> bool: + with self._value_lock: + try: + self._db.execute('INSERT OR REPLACE INTO chatNameCache VALUES (?, ?, ?);', (chatId, name, round(time()))) + self._db.commit() + return True + except: + return False + def setRSSForceUpdate(self, id: int, forceupdate: bool) -> bool: with self._value_lock: try: diff --git a/manage.py b/manage.py new file mode 100644 index 0000000..5204301 --- /dev/null +++ b/manage.py @@ -0,0 +1,39 @@ +# (C) 2021-2022 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 . +from enum import Enum, unique + + +@unique +class InlineKeyBoardForManage(Enum): + Close = 0 + ManageByRSS = 1 + ManageByChatId = 2 + FirstPage = 3 + + +def getInlineKeyBoardForManage(): + d = [] + i = -1 + d.append([]) + i += 1 + d[i].append({'text': '按RSS管理', 'callback_data': f'3,{InlineKeyBoardForManage.ManageByRSS.value}'}) + d.append([]) + i += 1 + d[i].append({'text': '按用户管理', 'callback_data': f'3,{InlineKeyBoardForManage.ManageByChatId.value}'}) + d.append([]) + i += 1 + d[i].append({'text': '关闭', 'callback_data': f'3,{InlineKeyBoardForManage.Close.value}'}) + return {'inline_keyboard': d} diff --git a/rssbot.py b/rssbot.py index 3951817..ecc0e00 100644 --- a/rssbot.py +++ b/rssbot.py @@ -42,6 +42,7 @@ from miraiDatabase import MiraiDatabase from mirai import Mirai from blackList import BlackList, InlineKeyBoardForBlackList, getInlineKeyBoardForBlackList, getTextContentForBlackInfo, getInlineKeyBoardForBlackInfo, getTextContentForUnbanBlackInfo, getInlineKeyBoardForUnbanBlackInfo, BlackInfo from json import loads +from manage import getInlineKeyBoardForManage, InlineKeyBoardForManage MAX_ITEM_IN_MEDIA_GROUP = 10 @@ -856,6 +857,34 @@ class main: return False, '' return False + def getChatName(self, chatId: int) -> str: + name = self._db.getChatName(chatId) + if name is not None: + return name + re = self._request('getChat', 'post', {'chat_id': chatId}) + if re is not None and 'ok' in re and re['ok']: + name = None + re = re['result'] + type = re['type'] + if type == 'private': + name = re['first_name'] + if 'last_name' in re: + name = name + ' ' + re['last_name'] + if 'username' in re: + name = name + '(@' + re['username'] + ')' + else: + name = re['title'] + if 'username' in re: + name = name + '(@' + re['username'] + ')' + if name is not None: + self._db.saveChatName(chatId, name) + else: + name = str(chatId) + return name + else: + print(re) + return str(chatId) + def _updateLoop(self): d = {'allowed_updates': ['message', 'edited_message', 'channel_post', 'edited_channel_post', 'callback_query']} @@ -1164,7 +1193,7 @@ class messageHandle(Thread): return if self._botCommand is None and self._data['chat']['type'] in ['group', 'supergroup']: return - if self._botCommand is None or self._botCommand not in ['/help', '/rss', '/rsslist', '/ban', '/banlist', '/unban', '/status']: + if self._botCommand is None or self._botCommand not in ['/help', '/rss', '/rsslist', '/ban', '/banlist', '/unban', '/status', '/manage']: self._botCommand = '/help' di = {'chat_id': self._chatId} if self.__getChatType() in ['supergroup', 'group'] and self._fromUserId is not None: @@ -1176,7 +1205,8 @@ class messageHandle(Thread): /ban 封禁某用户 /banlist 查询被封禁列表 /unban 取消封禁某用户 -/status 返回Bot状态''' +/status 返回Bot状态 +/manage 管理所有RSS订阅''' elif self._botCommand == '/rss': self._botCommandPara = self._getCommandlinePara() self._uri = None @@ -1310,6 +1340,12 @@ RSS订阅总数: {self._main._db.getChatRSSCount()} 内容散列个数: {self._main._db.getHashCount()} 黑名单(不含配置文件)总数: {self._main._db.getUserBlackListCount()}''' di['parse_mode'] = 'HTML' + elif self._botCommand == '/manage': + if self._fromUserId is None or not self._main._setting.botOwnerList.isOwner(self._fromUserId): + di['text'] = '❌你没有权限操作,请与Bot主人进行PY交易以获得权限。' + else: + di['text'] = '请选择管理模式:' + di['reply_markup'] = getInlineKeyBoardForManage() re = self._main._request('sendMessage', 'post', json=di) if self._botCommand == '/rss' and self._uri is not None and re is not None and 'ok' in re and re['ok']: re = re['result'] @@ -1951,9 +1987,37 @@ class callbackQueryHandle(Thread): di['reply_markup'] = getInlineKeyBoardForBlackList(self._main._blackList.getBlackList(), itemIndex=int(self._inputList[2])) self._main._request("editMessageText", "post", json=di) return + elif self._loc == 3: + if 'message' not in self._data: + self.answer('找不到信息。') + return + if self._fromUserId is None or not self._isOwn: + self.answer('❌你没有权限操作,请与Bot主人进行PY交易以获得权限。') + return + try: + self._inlineKeyBoardForManageCommand = InlineKeyBoardForManage(int(self._inputList[1])) + except Exception: + self.answer('未知的按钮。') + return + di = {'chat_id': self._data['message']['chat']['id'], + 'message_id': self._data['message']['message_id']} + if self._inlineKeyBoardForManageCommand == InlineKeyBoardForManage.Close: + self._main._request("deleteMessage", "post", json=di) + return + elif self._inlineKeyBoardForManageCommand in [InlineKeyBoardForManage.ManageByRSS, InlineKeyBoardForManage.ManageByChatId]: + innerCommand = None + if len(self._inputList) > 2: + try: + innerCommand = InlineKeyBoardForManage(int(self._inputList[2])) + except Exception: + self.answer('未知的按钮。') + return + if innerCommand is None or innerCommand == InlineKeyBoardForManage.FirstPage: + pass else: self.answer('未知的按钮。') return + self.answer('未知的按钮。') if __name__ == "__main__":