commit afa2a8ea176df3b7118aa815e9f8b1552a2ac458 Author: lifegpc Date: Tue Jan 5 23:53:22 2021 +0800 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..30ac2fc --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +__pycache__/ +*.db +*.txt +!requirements.txt +*.json diff --git a/database.py b/database.py new file mode 100644 index 0000000..1577ef8 --- /dev/null +++ b/database.py @@ -0,0 +1,63 @@ +import sqlite3 + + +class database: + def __check_database(self): + cur = self._db.execute('SELECT * FROM main.sqlite_master;') + self._exist_tables = {} + for i in cur: + if i[0] == 'table': + self._exist_tables[i[1]] = i + for i in ['config', 'RSSList']: + if i not in self._exist_tables: + return False + return True + + def __create_table(self): + if 'config' not in self._exist_tables: + self._db.execute(f'''CREATE TABLE config ( +version1 INT, +version2 INT, +version3 INT, +version4 INT +);''') + self.__write_version() + if 'RSSList' not in self._exist_tables: + self._db.execute(f'''CREATE TABLE RSSList ( +title TEXT, +url TEXT, +interval INT, +lastupdatetime INT, +type INT, +id TEXT, +PRIMARY KEY (url) +);''') + if 'userList' not in self._exist_tables: + self._db.execute('''CREATE TABLE userList ( +userId INT, +id TEXT +)''') + if 'channelList' not in self._exist_tables: + self._db.execute('''CREATE TABLE channelList ( +channelId INT, +id TEXT +)''') + if 'hashList' not in self._exist_tables: + self._db.execute('''CREATE TABLE hashList ( +id TEXT, +hash TEXT, +PRIMARY KEY (hash) +)''') + self._db.commit() + + def __init__(self): + self._version = [1, 0, 0, 0] + self._db = sqlite3.connect('data.db') + ok = self.__check_database() + if not ok: + self.__create_table() + + def __write_version(self): + self._db.execute( + f'INSERT INTO config VALUES ({self._version[0]}, {self._version[1]}, {self._version[2]}, {self._version[3]});') + self._db.commit() diff --git a/readset.py b/readset.py new file mode 100644 index 0000000..f426b9a --- /dev/null +++ b/readset.py @@ -0,0 +1,14 @@ +class settings: + def __init__(self, fn: str=None): + if fn is not None: + self.parse(fn) + + def parse(self, fn: str): + d = {} + with open(fn, 'r', encoding='utf8') as f: + t = f.read() + for i in t.splitlines(False): + l = i.split('=', 2) + if len(l) == 2: + d[l[0]] = l[1] + self._token = d['token'] if 'token' in d else None diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..65d7ffc --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +requests>=2.25.1 diff --git a/rssbot.py b/rssbot.py new file mode 100644 index 0000000..10457b4 --- /dev/null +++ b/rssbot.py @@ -0,0 +1,129 @@ +from database import database +from os.path import exists +from readset import settings +from requests import Session +from traceback import format_exc +from threading import Thread + + +class main: + def __init__(self): + pass + + def _request(self, methodName: str, HTTPMethod: str = 'get', data: dict = None, json: dict = None, returnType: str = 'json'): + try: + r = self._r.request( + HTTPMethod, f'https://api.telegram.org/bot{self._setting._token}/{methodName}', data=data, json=json) + if r.status_code != 200: + return None + if returnType == 'json': + return r.json() + elif returnType == 'text': + return r.text + elif returnType == 'content': + return r.content + except: + print(format_exc()) + return None + + def _updateLoop(self): + d = {'allowed_updates': [ + 'message', 'edited_message', 'channel_post', 'edited_channel_post']} + if self._upi is not None: + d['offset'] = self._upi + ud = self._request('getUpdates', 'post', json=d) + print(ud) + if ud is not None and 'ok' in ud and ud['ok']: + for i in ud['result']: + for key in ['message', 'edited_message', 'channel_post', 'edited_channel_post']: + if key in i: + m = messageHandle(self, i[key]) + m.start() + self._upi = i['update_id'] + 1 + + def start(self): + self._db = database() + if not exists('settings.txt'): + print('找不到settings.txt') + return -1 + self._setting = settings('settings.txt') + if self._setting._token is None: + print('没有机器人token') + return -1 + self._r = Session() + self._me = self._request('getMe') + print(self._me) + if self._me is None: + print('无法读取机器人信息') + self._upi = None + self._updateThread = updateThread(self) + self._updateThread.start() + + +class updateThread(Thread): + def __init__(self, main: main): + Thread.__init__(self) + self._main = main + + def run(self): + while True: + self._main._updateLoop() + + +class messageHandle(Thread): + def __init__(self, main: main, data: dict): + Thread.__init__(self) + self._main = main + self._data = data + + def __getBotCommand(self) -> str: + for i in self._data['entities']: + if i['type'] == 'bot_command': + v = self._data['text'][i['offset']: i['offset'] + i['length']] + founded = v.find('@') + if founded == -1: + return v + return v[0:founded] + return None + + def __getChatId(self) -> int: + if 'chat' in self._data: + return self._data['chat']['id'] + return None + + def __getChatType(self) -> str: + if 'chat' in self._data: + return self._data['chat']['type'] + return None + + def __getFromUserId(self) -> int: + if 'from' in self._data: + return self._data['from']['id'] + return None + + def run(self): + print(self._data) + self._messageId = self._data['message_id'] + self._chatId = self.__getChatId() + if self._chatId is None: + print('未知的chat id') + return -1 + if 'text' in self._data: + if 'entities' in self._data: + self._botCommand = self.__getBotCommand() + if self._botCommand is None: + self._botCommand = '/help' + if self._botCommand not in ['/help']: + self._botCommand = '/help' + di = {'chat_id': self._chatId} + self._fromUserId = self.__getFromUserId() + if self.__getChatType() in ['supergroup', 'group'] and self._fromUserId is not None: + di['reply_to_message_id'] = self._messageId + if self._botCommand == '/help': + di['text'] = '/help 查看帮助' + self._main._request('sendMessage', 'post', json=di) + + +if __name__ == "__main__": + m = main() + m.start() diff --git a/rssparser.py b/rssparser.py new file mode 100644 index 0000000..8348f9c --- /dev/null +++ b/rssparser.py @@ -0,0 +1,57 @@ +from xml.dom import minidom +import sys +import requests + + +class RSSParser: + def __init__(self): + pass + + def check(self): + self._root = self.xmldoc.documentElement + if self._root.localName != 'rss' or len(self._root.childNodes) != 1: + return False + self._root2 = self._root.childNodes[0] + if self._root2.localName != 'channel': + return False + m = {} + for i in self._root2.childNodes: + if i.localName == 'item': + pass + else: + m[i.localName] = i.firstChild.nodeValue if len( + i.childNodes) > 0 else i.nodeValue + print() + + def normalize(self): + self.removeblank(self.xmldoc.documentElement) + self.xmldoc.normalize() + + def parse(self, fn: str): + try: + if fn.find('://') > -1: + re = requests.get(fn) + if re.status_code == 200: + self.xmldoc = minidom.parseString(re.text) + else: + self.xmldoc = minidom.parse(fn) + self.normalize() + return True + except: + return False + + def removeblank(self, node): + for i in node.childNodes: + if i.nodeType == minidom.Node.TEXT_NODE: + if i.nodeValue: + i.nodeValue = i.nodeValue.strip() + elif i.nodeType == minidom.Node.ELEMENT_NODE: + self.removeblank(i) + + +if __name__ == "__main__": + if len(sys.argv) > 1: + fn = sys.argv[1] + p = RSSParser() + p.parse(fn) + p.check()