├── rss.db ├── requirements.txt ├── templates ├── admin.html ├── index.html └── subindex.html ├── config.py ├── .github └── workflows │ └── python-app.yml.bak ├── readme.md ├── rss.py ├── .gitignore ├── manage.py ├── models.py └── bot.py /rss.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/9bie/rsspusher/HEAD/rss.db -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | 2 | feedparser==6.0.0 3 | Flask==1.1.2 4 | peewee==3.14.0 5 | python-telegram-bot==13.1 6 | -------------------------------------------------------------------------------- /templates/admin.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Admin 6 | 7 | 8 | 实话实说吧,我懒得写了 9 | 启动bot 10 | 11 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | import os 3 | TIMER = 10*60 # second 4 | TIMEOUT = 30 5 | DEBUG = True 6 | if DEBUG: 7 | import logging 8 | logger = logging.getLogger('peewee') 9 | logger.setLevel(logging.DEBUG) 10 | logger.addHandler(logging.StreamHandler()) 11 | 12 | # Bot 13 | TELEGRAM_KEYS = os.environ["TELEGRAM_KEYS"] 14 | IS_WEBHOOK = False 15 | URL = "https://i.9bie.org" 16 | WEBHOOKING = URL + "/"+TELEGRAM_KEYS 17 | 18 | 19 | # DataBase 20 | ISMYSQL = False 21 | DB_PATH = "rss.db" 22 | MYSQL_HOST = "localhost" 23 | MYSQL_DATABASE = "rss" 24 | MYSQL_USERNAME = "root" 25 | MYSQL_PASSWORD = "root" 26 | MYSQL_PORT = 3306 27 | 28 | -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 |
9 |

Rss Pusher

10 |

11 | Author: @bakabie 12 |
13 | Blog: ⑨BIE 14 |
15 | Github: Rss Pusher 16 |
17 | Bot: @rsspusher_bot 18 |

19 |
20 | 21 | -------------------------------------------------------------------------------- /.github/workflows/python-app.yml.bak: -------------------------------------------------------------------------------- 1 | 2 | name: RssPusher 3 | 4 | on: 5 | schedule: 6 | - cron: '0/10 * * * *' 7 | push: 8 | branches: 9 | - master 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: 'Checkout codes' 15 | uses: actions/checkout@v2 # 拉取最新的代码 16 | - name: Set up Python 3.8.15 17 | uses: actions/setup-python@v2 # 设置 python 版本 18 | with: 19 | python-version: 3.8.15 20 | - name: Install xmllint 21 | run: sudo apt install libgirepository1.0-dev 22 | - name: Install dependencies # 安装依赖 23 | run: | 24 | python -m pip install --upgrade pip 25 | pip install -r requirements.txt 26 | - name: send rss 27 | env: 28 | TELEGRAM_KEYS: ${{ secrets.TELEGRAM_TOKEN }} 29 | run: | 30 | python rss.py 31 | - name: Commit 32 | run: | 33 | git config --global user.email blackguwc@163.com 34 | git config --global user.name 9bie 35 | git add . 36 | git commit -m "update the rssdb" -a 37 | continue-on-error: true 38 | - name: Push changes 39 | uses: ad-m/github-push-action@master 40 | with: 41 | branch: master 42 | github_token: ${{ secrets.GITHUB_TOKEN }} 43 | 44 | -------------------------------------------------------------------------------- /templates/subindex.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | RssPusher 6 | 7 | 8 |
9 | 12 | 13 |
14 | {# #} 15 |
16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | {% for item in items %} 27 | 28 | 31 | 32 | 33 | 34 | 35 | {% endfor %} 36 |
FormTitleSummary
{{ item.Form }}{{ item.Title }}{{ item.Summary }}
37 |
38 |
39 |

40 | Author: @bakabie 41 |
42 | Github: Rss Pusher 43 |

44 |
45 | 46 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Rss Pusher 2 | 推送指定站点RSS消息到web和tg列表 3 | 4 | 请使用python3运行,当然理论上python2也是可以的 5 | 6 | ## how to build 7 | 修改 `config.py` 8 | 9 | 填写好`TELEGRAM_KEYS`,为你的bot keys 10 | 11 | 如果设置了`IS_WEBHOOK = True`,如果没有请忽略下面一行 12 | 13 | 填写好`URL`,确保tg服务器能访问到你的`URL/tg_keys` 14 | 15 | 修改`TIMER`为获取rss的间隔,单位秒,默认五分钟 16 | 17 | 之后运行`models.py`创建数据库 18 | 19 | 最后直接运行`python manager.py`可以用debug模式运行,然后用nginx反代。 20 | 21 | 或者使用正规方式`gunicorn -w 2 -b 127.0.0.1:5000 manage:app`启动服务 22 | 23 | 之后用nginx反代本地5000端口即可。 24 | 25 | 之后找到你的bot发送`/help`,bot正确运行 26 | 27 | 28 | # how to use 29 | ## en 30 | ###Rss Pusher Usage 31 | 32 | #### User 33 | - **/create** [id] Create a channel, other users can join your channel based on id 34 | - **/join** [id] join the source and recv the rss push 35 | - **/leave** [id] cancel recv the rss push.if you are master for this channel,this channel will delete 36 | - **/list** [id] View the rss subscription link in the channel 37 | - **/myself** View your own information, including channels created/administrated/joined 38 | - **/help** you see now 39 | #### Admin 40 | - **/add** [id] [title] [rss link] add the rss link 41 | - **/delete** [id] [rss_id] delete the rss target.id from **/list** 42 | - **/privilege** [id] [telegram_id] set ont follows to admin.(you must channel master) 43 | - **/update** Only for developers.Update rss subscription now 44 | ## zh 45 | #### User 46 | - **/create** [id] 创建个rss订阅频道,其他用户可以根据这个id加入你的频道 47 | - **/join** [id] 加入一个频道,之后你将会收到这个频道的更新推送 48 | - **/leave** [id] 离开某个频道,如果你是这个频道的创建者,频道将会删除 49 | - **/list** [id] 查看该频道的rss订阅列表 50 | - **/myself** 查看你创建/管理/加入的频道 51 | - **/help** 你现在正在看到的 52 | #### Admin 53 | - **/add** [id] [title] [rss link] 给频道添加一个rss订阅链接 54 | - **/delete** [id] [rss_id] 删除频道内一个rss订阅链接,rss_id可以从 **/list** 里查看 55 | - **/privilege** [id] [telegram_id] 设置一个telegram用户为管理员,该成员必须再本频道发送过 **/help** 或以外的参数(你必须为频道创建者从才能使用本命令) 56 | - **/update** 仅对开发者开放,立刻更新所有rss推送 57 | 58 | ## todo 59 | 60 | ### web主页 61 | 定制不同的rsschannel的不同独立rss主页页面 62 | 63 | ## 用到的模块 64 | 65 | - python-telegram-bot 66 | - peewee 67 | - feedparser -------------------------------------------------------------------------------- /rss.py: -------------------------------------------------------------------------------- 1 | import feedparser 2 | import re 3 | import models 4 | import socket 5 | from config import TIMEOUT 6 | from threading import Thread 7 | from bot import send_all_follows 8 | 9 | socket.setdefaulttimeout(TIMEOUT) 10 | def delete_html(html): 11 | dr = re.compile(r'<[^>]+>', re.S) 12 | dd = dr.sub('', html) 13 | return dd 14 | 15 | 16 | def check(target): 17 | result = feedparser.parse(target) 18 | if result.feed == {}: 19 | return "" 20 | else: 21 | if "title" in result.feed: 22 | return result.feed.title 23 | else: 24 | return "NoneTitle" 25 | 26 | def mutiThread(r): 27 | report = "" 28 | report_s = "" 29 | try: 30 | print("[RSS]Now:{}".format(r.Rss)) 31 | data = feedparser.parse(r.Rss) 32 | for entries in data.entries: 33 | summary = delete_html(entries.summary) 34 | if summary != "" and len(summary) >= 20: 35 | summary = summary[:50] 36 | if models.DataBase.select().where( 37 | models.DataBase.Url == entries.link 38 | ).exists(): 39 | continue 40 | models.DataBase.create( 41 | Title=entries.title, 42 | Url=entries.link, 43 | Summary=summary, 44 | Form=r, 45 | ) 46 | 47 | report_s += '\t{}\n'.format(entries.link, entries.title) 48 | 49 | if report_s != "": 50 | if "subtitle" not in data.feed: 51 | report += "{}:\n".format(data.feed.title) + report_s 52 | else: 53 | report += "{} - {}:\n".format(data.feed.title, data.feed.subtitle) + report_s 54 | 55 | if report != "": 56 | send_all_follows(r, report) 57 | except Exception as e: 58 | print("Some Error:{}".format(e)) 59 | 60 | def main(): 61 | rss = models.RssList.select() 62 | lists = [] 63 | 64 | for r in rss: 65 | lists.append(Thread(target=mutiThread,args=(r,))) 66 | for i in lists: 67 | i.start() 68 | for j in lists: 69 | j.join() 70 | 71 | 72 | if __name__ == '__main__': 73 | main() 74 | 75 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | *.db 9 | .idea/ 10 | # Distribution / packaging 11 | .Python 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | pip-wheel-metadata/ 25 | share/python-wheels/ 26 | *.egg-info/ 27 | .installed.cfg 28 | *.egg 29 | MANIFEST 30 | 31 | # PyInstaller 32 | # Usually these files are written by a python script from a template 33 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 34 | *.manifest 35 | *.spec 36 | 37 | # Installer logs 38 | pip-log.txt 39 | pip-delete-this-directory.txt 40 | 41 | # Unit test / coverage reports 42 | htmlcov/ 43 | .tox/ 44 | .nox/ 45 | .coverage 46 | .coverage.* 47 | .cache 48 | nosetests.xml 49 | coverage.xml 50 | *.cover 51 | *.py,cover 52 | .hypothesis/ 53 | .pytest_cache/ 54 | 55 | # Translations 56 | *.mo 57 | *.pot 58 | 59 | # Django stuff: 60 | *.log 61 | local_settings.py 62 | db.sqlite3 63 | db.sqlite3-journal 64 | 65 | # Flask stuff: 66 | instance/ 67 | .webassets-cache 68 | 69 | # Scrapy stuff: 70 | .scrapy 71 | 72 | # Sphinx documentation 73 | docs/_build/ 74 | 75 | # PyBuilder 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | .python-version 87 | 88 | # pipenv 89 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 90 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 91 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 92 | # install all needed dependencies. 93 | #Pipfile.lock 94 | 95 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 96 | __pypackages__/ 97 | 98 | # Celery stuff 99 | celerybeat-schedule 100 | celerybeat.pid 101 | 102 | # SageMath parsed files 103 | *.sage.py 104 | 105 | # Environments 106 | .env 107 | .venv 108 | env/ 109 | venv/ 110 | ENV/ 111 | env.bak/ 112 | venv.bak/ 113 | 114 | # Spyder project settings 115 | .spyderproject 116 | .spyproject 117 | 118 | # Rope project settings 119 | .ropeproject 120 | 121 | # mkdocs documentation 122 | /site 123 | 124 | # mypy 125 | .mypy_cache/ 126 | .dmypy.json 127 | dmypy.json 128 | 129 | # Pyre type checker 130 | .pyre/ 131 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | from threading import Timer, Thread 2 | 3 | from time import sleep 4 | 5 | from flask import * 6 | import rss 7 | from bot import * 8 | # from flask_login import login_user, logout_user, login_required,current_user 9 | from models import DataBase 10 | 11 | app = Flask(__name__) 12 | 13 | Timer(TIMER, rss.main).start() 14 | 15 | 16 | @app.route('/start') 17 | def start(): 18 | if IS_WEBHOOK: 19 | bot.setWebhook(WEBHOOKING) 20 | return "ok" 21 | 22 | 23 | 24 | @app.route("/" + TELEGRAM_KEYS, methods=["POST"]) 25 | def tg_event(): 26 | update = telegram.Update.de_json(request.get_json(force=True), bot) 27 | 28 | if update.message is None: 29 | return "Show me your TOKEN please!" 30 | Bot(update).handle() 31 | return "ok" 32 | 33 | 34 | @app.route('/') 35 | @app.route("/") 36 | def index(id=""): 37 | page = request.args.get('page', '') 38 | if not page: 39 | page = 0 40 | else: 41 | page = int(page) 42 | try: 43 | if id == "": 44 | return render_template('index.html') 45 | else: 46 | lists = [] 47 | if not models.RssChannel.select().where( 48 | models.RssChannel.Customize == id 49 | ).exists(): 50 | return "channel not found", 404 51 | items = DataBase.select().where( 52 | DataBase.Form == models.RssChannel.get(Customize=id) 53 | ).paginate(page, 50) 54 | for i in items: 55 | lists.append( 56 | { 57 | "Form": models.RssListFriendShip.get(RssList=i.Form).CustomizeTitle, 58 | "Title": i.Title, 59 | "Url": i.Url, 60 | "Summary": i.Summary if i.Summary is not None else "" 61 | } 62 | ) 63 | return render_template('subindex.html', items=lists) 64 | except Exception as e: 65 | return "Have some error:{}\nPlease link @bakabie".format(e), 500 66 | 67 | 68 | def update(): 69 | update_id = 0 70 | while True: 71 | bot.deleteWebhook() 72 | if update_id == 0: 73 | updates = telegram.Bot(TELEGRAM_KEYS).get_updates() 74 | else: 75 | updates = telegram.Bot(TELEGRAM_KEYS).get_updates(offset=update_id) 76 | for update in updates: 77 | update_id = update.update_id + 1 78 | print(update) 79 | Bot(update).handle() 80 | sleep(3) 81 | 82 | 83 | if not IS_WEBHOOK: 84 | Thread(target=update).start() 85 | 86 | if __name__ == '__main__': 87 | app.run() 88 | -------------------------------------------------------------------------------- /models.py: -------------------------------------------------------------------------------- 1 | import json 2 | import random 3 | import string 4 | 5 | from peewee import * 6 | 7 | from config import * 8 | 9 | db = SqliteDatabase(DB_PATH) if not ISMYSQL else MySQLDatabase(host=MYSQL_HOST, database=MYSQL_DATABASE, 10 | user=MYSQL_USERNAME, password=MYSQL_PASSWORD, 11 | port=MYSQL_PORT) 12 | 13 | 14 | class BaseModel(Model): 15 | class Meta: 16 | database = db 17 | 18 | 19 | class Follows(BaseModel): 20 | ID = PrimaryKeyField() 21 | Telegram_id = IntegerField(null=False, unique=True) 22 | PassWD = CharField(null=True) 23 | 24 | 25 | class RssChannel(BaseModel): 26 | ID = PrimaryKeyField() 27 | Customize = CharField(null=False, unique=True) 28 | Master = ForeignKeyField(Follows, related_name="master") 29 | 30 | 31 | class RssList(BaseModel): 32 | ID = PrimaryKeyField() 33 | # Title = CharField(null=False) 34 | Rss = CharField(null=False, unique=True) 35 | 36 | 37 | class RssListFriendShip(BaseModel): 38 | RssList = ForeignKeyField(RssList, related_name="rss_list") 39 | RssChannel = ForeignKeyField(RssChannel, related_name="rss_channel") 40 | CustomizeTitle = CharField(null=False) 41 | 42 | 43 | class RssMember(BaseModel): 44 | Follows = ForeignKeyField(Follows, related_name="follows") 45 | RssChannel = ForeignKeyField(RssChannel, related_name="rss_channel") 46 | 47 | 48 | class RssAdmin(BaseModel): 49 | Follows = ForeignKeyField(Follows, related_name="follows") 50 | RssChannel = ForeignKeyField(RssChannel, related_name="rss_channel") 51 | 52 | 53 | class DataBase(BaseModel): 54 | ID = PrimaryKeyField() 55 | Title = CharField(null=False) 56 | Url = CharField(null=False, unique=True) 57 | Summary = TextField(null=True) 58 | Form = ForeignKeyField(RssList, related_name="rss_list") 59 | 60 | 61 | def create_table(): 62 | db.connect() 63 | db.create_tables([Follows, RssChannel, RssList, RssListFriendShip, RssMember, RssAdmin, DataBase]) 64 | 65 | 66 | def random_password(): 67 | return ''.join(random.sample(string.ascii_letters + string.digits, 8)) 68 | 69 | 70 | ## 字符串转字典 71 | def str_to_dict(dict_str): 72 | if isinstance(dict_str, str) and dict_str != '': 73 | new_dict = json.loads(dict_str) 74 | else: 75 | new_dict = "" 76 | return new_dict 77 | 78 | 79 | # 字典转对象 80 | def dict_to_obj(dict, obj, exclude=None): 81 | for key in dict: 82 | if exclude: 83 | if key in exclude: 84 | continue 85 | setattr(obj, key, dict[key]) 86 | return obj 87 | 88 | 89 | # peewee转dict 90 | def obj_to_dict(obj, exclude=None): 91 | print(obj.__dict__) 92 | dict = obj.__dict__['__data__'] 93 | if exclude: 94 | for key in exclude: 95 | if key in dict: dict.pop(key) 96 | return dict 97 | 98 | 99 | # peewee转list 100 | def query_to_list(query, exclude=None): 101 | list = [] 102 | for obj in query: 103 | dict = obj_to_dict(obj, exclude) 104 | list.append(dict) 105 | return list 106 | 107 | 108 | if __name__ == '__main__': 109 | create_table() 110 | -------------------------------------------------------------------------------- /bot.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | import re 3 | 4 | import telegram 5 | 6 | import models 7 | from config import * 8 | from time import sleep 9 | # from rss import check 10 | bot = telegram.Bot(token=TELEGRAM_KEYS) 11 | 12 | 13 | class Bot: 14 | 15 | def __init__(self, update): 16 | self.update = update 17 | if update.message is None: 18 | self.command = "" 19 | self.param = [] 20 | return 21 | self.chat_id = update.message.chat_id 22 | self.data = update.message.to_dict() 23 | if "text" not in self.data: 24 | self.command = "" 25 | self.param = [] 26 | else: 27 | self.command = self.data["text"].split()[0] 28 | self.param = self.data["text"].split() 29 | 30 | def __grant(self, param_number): 31 | if len(self.param) < param_number: 32 | bot.send_message(chat_id=self.chat_id, text="参数错误.可以发送/help查询如何使用") 33 | return False 34 | if not models.Follows.select().where( 35 | models.Follows.Telegram_id == self.chat_id 36 | ).exists(): 37 | models.Follows.create( 38 | Telegram_id=self.chat_id 39 | ) 40 | return True 41 | 42 | def __is_channel_exists(self, id): 43 | if not models.RssChannel.select().where( 44 | models.RssChannel.Customize == id 45 | ).exists(): 46 | bot.send_message(chat_id=self.chat_id, text="找不到频道.") 47 | return False 48 | return True 49 | 50 | def __are_you_admin(self, channel_customize): 51 | if not models.RssAdmin.select().where( 52 | models.RssAdmin.RssChannel == models.RssChannel.get(Customize=channel_customize), 53 | models.RssAdmin.Follows == models.Follows.get(Telegram_id=self.chat_id) 54 | ).exists(): 55 | bot.send_message(chat_id=self.chat_id, text="你不是该频道的管理员.") 56 | return False 57 | return True 58 | 59 | def __create(self): 60 | 61 | if not self.__grant(param_number=2): 62 | return 63 | if models.RssChannel.select().where( 64 | models.RssChannel.Master == models.Follows.get(Telegram_id=self.chat_id) 65 | ).count() >= 3: 66 | bot.send_message(chat_id=self.chat_id, text="你已经超出最大频道限制(数量为3条,请联系管理员 @bakabie)") 67 | return 68 | is_match = re.match("^[_a-zA-Z0-9]+$",self.param[1]) 69 | if not is_match: 70 | bot.send_message(chat_id=self.chat_id,text="仅限字母数字下划线且不超过8位") 71 | return 72 | if len(self.param[1])> 8: 73 | bot.send_message("仅限字母数字下划线且不超过8位") 74 | return 75 | if models.RssChannel.select().where( 76 | models.RssChannel.Customize == self.param[1] 77 | ).exists(): 78 | bot.send_message(chat_id=self.chat_id, text="频道已经存在,请换个id.") 79 | return 80 | new_channel = models.RssChannel.create( 81 | Customize=self.param[1], 82 | Master=models.Follows.get(Telegram_id=self.chat_id) 83 | ) 84 | models.RssAdmin.create( 85 | Follows=models.Follows.get(Telegram_id=self.chat_id), 86 | RssChannel=new_channel 87 | ) 88 | models.RssMember.create( 89 | Follows=models.Follows.get(Telegram_id=self.chat_id), 90 | RssChannel=new_channel 91 | ) 92 | 93 | bot.send_message(chat_id=self.chat_id, text="成功, 你创建的频道id为:\n\t - {}\n" 94 | " 其他用户可以根据这个id加入你的频道接受推送.\n你的主页为:\n\t - {}".format(self.param[1],URL+"/"+self.param[1]),) 95 | 96 | def __join(self): 97 | if not self.__grant(param_number=2): 98 | return 99 | id = self.param[1] 100 | if not models.RssChannel.select().where( 101 | models.RssChannel.Customize == id 102 | ).exists(): 103 | bot.send_message(chat_id=self.chat_id, text="找不到频道.") 104 | return 105 | if models.RssMember.select().where( 106 | models.RssMember.Follows == models.Follows.get(Telegram_id=self.chat_id), 107 | models.RssMember.RssChannel == models.RssChannel.get(Customize=id) 108 | ).exists(): 109 | bot.send_message(chat_id=self.chat_id, text="你已经加入了这个频道.") 110 | return 111 | models.RssMember.create( 112 | Follows=models.Follows.get(Telegram_id=self.chat_id), 113 | RssChannel=models.RssChannel.get(Customize=id) 114 | ) 115 | bot.send_message(chat_id=self.chat_id, text="成功.") 116 | 117 | def __leave(self): 118 | if not self.__grant(param_number=2): 119 | return 120 | id = self.param[1] 121 | if not self.__is_channel_exists(id): 122 | return 123 | 124 | if not models.RssMember.select().where( 125 | models.RssMember.Follows == models.Follows.get(Telegram_id=self.chat_id), 126 | models.RssMember.RssChannel == models.RssChannel.get(Customize=id) 127 | ).exists(): 128 | bot.send_message(chat_id=self.chat_id, text="你已经加入了这个频道.") 129 | return 130 | models.RssMember.delete().where( 131 | models.RssMember.Follows == models.Follows.get(Telegram_id=self.chat_id), 132 | models.RssMember.RssChannel == models.RssChannel.get(Customize=id) 133 | ).execute() 134 | if models.RssChannel.get(Customize=id).Master == models.Follows.get(Telegram_id=self.chat_id): 135 | check = [] 136 | for i in models.RssListFriendShip.select().where( 137 | models.RssListFriendShip.RssChannel == models.RssChannel.get(Customize=id)): 138 | check.append(i.RssList) 139 | models.RssListFriendShip.delete().where( 140 | models.RssListFriendShip.RssChannel == models.RssChannel.get(Customize=id)).execute() 141 | for rss in check: 142 | if not models.RssListFriendShip.select().where( 143 | models.RssListFriendShip.RssList == rss 144 | ).exists(): 145 | models.RssList.delete().where(models.RssList.ID == rss.ID).execute() 146 | models.DataBase.delete().where(models.DataBase.Form == rss).execute() 147 | models.RssList.delete().where(models.RssList.ID) 148 | models.RssMember.delete().where( 149 | models.RssMember.RssChannel == models.RssChannel.get(Customize=id)).execute() 150 | models.RssAdmin.delete().where(models.RssAdmin.RssChannel == models.RssChannel.get(Customize=id)).execute() 151 | models.RssChannel.delete().where(models.RssChannel.Customize == id).execute() 152 | bot.send_message(chat_id=self.chat_id, text="成功!") 153 | 154 | def __list(self): 155 | if not self.__grant(param_number=2): 156 | return 157 | id = self.param[1] 158 | if not self.__is_channel_exists(id): 159 | return 160 | results = "" 161 | rsslists = models.RssListFriendShip.select().where( 162 | models.RssListFriendShip.RssChannel == models.RssChannel().get(Customize=id) 163 | ) 164 | for i in rsslists: 165 | results += "Rss id: {}\n\t - Title:{}\n\t - Rss:{}\n\t".format( 166 | i.RssList.ID, 167 | i.CustomizeTitle, 168 | i.RssList.Rss) 169 | if results == "": 170 | bot.send_message(chat_id=self.chat_id, text="没有任何东西在频道里.") 171 | else: 172 | bot.send_message(chat_id=self.chat_id, text=results, parse_mode="html") 173 | 174 | def __myself(self): 175 | if not self.__grant(param_number=1): 176 | return 177 | master = "\n*You are master for*:" 178 | rss_master = models.RssChannel.select().where( 179 | models.RssChannel.Master == models.Follows.get(Telegram_id=self.chat_id) 180 | ) 181 | 182 | for i in rss_master: 183 | master += "\n\t - Rss Channel ID: {}\n".format(i.Customize) 184 | rss_admin = models.RssAdmin.select().where( 185 | models.RssAdmin.Follows == models.Follows.get(Telegram_id=self.chat_id) 186 | ) 187 | admin = "\n*You are Admin for*:" 188 | for j in rss_admin: 189 | admin += "\n\t - Rss Channel ID: {}\n".format(j.RssChannel.Customize) 190 | rss_member = models.RssMember.select().where( 191 | models.RssMember.Follows == models.Follows.get(Telegram_id=self.chat_id) 192 | ) 193 | member = "\n*You are joined*:" 194 | for k in rss_member: 195 | member += "\n\t - Rss Channel ID: {}\n".format(k.RssChannel.Customize) 196 | bot.send_message(chat_id=self.chat_id, text=master + admin + member, parse_mode="markdown") 197 | 198 | def __add(self): 199 | if not self.__grant(param_number=3): 200 | return 201 | id = self.param[1] 202 | title = self.param[2] 203 | link = self.param[3] 204 | if not self.__is_channel_exists(id): 205 | return 206 | if not self.__are_you_admin(id): 207 | return 208 | pattern = re.compile(r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+') 209 | if len(re.findall(pattern, link)) == 0: 210 | bot.send_message(chat_id=self.chat_id, text="请输入正确的rss连接") 211 | return 212 | else: 213 | 214 | if not models.RssList.select().where( 215 | models.RssList.Rss == link 216 | ).exists(): 217 | models.RssList.create( 218 | # title = check(link) 219 | Rss=link, 220 | ) 221 | if models.RssListFriendShip.select().where( 222 | models.RssListFriendShip.RssList == models.RssList.get(Rss=link), 223 | models.RssListFriendShip.RssChannel == models.RssChannel.get(Customize=id) 224 | ).exists(): 225 | bot.send_message(chat_id=self.chat_id, text="您已经加入了") 226 | return 227 | models.RssListFriendShip.create( 228 | RssList=models.RssList.get(Rss=link), 229 | RssChannel=models.RssChannel.get(Customize=id), 230 | CustomizeTitle=title 231 | ) 232 | bot.send_message(chat_id=self.chat_id, text="成功!") 233 | 234 | def __delete(self): 235 | if not self.__grant(param_number=2): 236 | return 237 | id = self.param[1] 238 | if not self.__is_channel_exists(id): 239 | return 240 | if not self.__are_you_admin(id): 241 | return 242 | 243 | rss_id = self.param[2] 244 | if not models.RssList.select().where( 245 | models.RssList.ID == rss_id 246 | ).exists(): 247 | bot.send_message(chat_id=self.chat_id, text="找不到rss id.") 248 | return 249 | if not models.RssListFriendShip.select().where( 250 | models.RssListFriendShip.RssList == models.RssList.get(ID=rss_id), 251 | models.RssListFriendShip.RssChannel == models.RssChannel.get(Customize=id) 252 | ).exists(): 253 | bot.send_message(chat_id=self.chat_id, text="该频道为添加这个rss.") 254 | return 255 | models.RssListFriendShip.delete().where( 256 | models.RssListFriendShip.RssChannel == models.RssChannel.get(Customize=id), 257 | models.RssListFriendShip.RssList == models.RssList.get(ID=rss_id) 258 | ).execute() 259 | if not models.RssListFriendShip.select().where( 260 | models.RssListFriendShip.RssList == models.RssList.get(ID=rss_id) 261 | ).exists(): 262 | models.DataBase.delete().where( 263 | models.DataBase.Form == models.RssList.get(ID=int(rss_id)) 264 | ).execute() 265 | models.RssList.delete().where( 266 | models.RssList.ID == int(rss_id) 267 | ).execute() 268 | 269 | bot.send_message(chat_id=self.chat_id, text="成功!") 270 | 271 | def __privilege(self): 272 | if not self.__grant(param_number=3): 273 | return 274 | id = self.param[1] 275 | telegram_id = self.param[2] 276 | if not self.__is_channel_exists(id): 277 | return 278 | if models.RssChannel.get(Customize=id).Master != models.Follows.get(Telegram_id=self.chat_id): 279 | bot.send_message(chat_id=self.chat_id, text="抱歉,你不是该频道的管理员.") 280 | return 281 | if not models.Follows.select().where( 282 | models.Follows.Telegram_id == telegram_id 283 | ).exists(): 284 | bot.send_message(chat_id=self.chat_id, text="抱歉,目标并未加入我们这个bot,目标至少要在我们这发送一条以上正确指令(/help)就行") 285 | return 286 | if models.RssAdmin.select().where( 287 | models.RssAdmin.Follows == models.Follows.get(Telegram_id=telegram_id), 288 | models.RssAdmin.RssChannel == models.RssChannel.get(Customize=id) 289 | ).exists(): 290 | bot.send_message(chat_id=self.chat_id, text="目标用户已经是管理员了") 291 | return 292 | models.RssAdmin.create( 293 | Follows=models.Follows.get(Telegram_id=telegram_id), 294 | RssChannel=models.RssChannel.get(Customize=id) 295 | ) 296 | bot.send_message(chat_id=self.chat_id, text="成功!") 297 | return 298 | 299 | def __change_pwd(self): 300 | pass 301 | 302 | def __update(self): 303 | bot.send_message(chat_id=self.chat_id, text="mei xie.") 304 | return 305 | 306 | def handle(self): 307 | try: 308 | if self.command == "/help": 309 | self.__grant(1) 310 | if len(self.param) >= 2: 311 | if self.param[1] == "en": 312 | bot.send_message(chat_id=self.chat_id, 313 | text="*Rss Pusher Usage:*\n" 314 | "*User:*\n" 315 | "\t - /create [id] Create a channel, other users can join your channel based on id" 316 | "\t - /join [id] join the source and recv the rss push\n" 317 | "\t - /leave [id] cancel recv the rss push.if you are master for this channel," 318 | "this channel will delete\n" 319 | "\t - /list [id] View the rss subscription link in the channel\n" 320 | "\t - /myself View your own information, includi" 321 | "ng channels created/administrated/joined\n" 322 | "\t - /help you see now\n" 323 | "*Admin:*\n" 324 | "\t - /add [id] [title] [rss link] add the rss link\n" 325 | "\t - /delete [id] [rss_id] delete the rss target.id from /list\n" 326 | "\t - /privilege [id] [telegram_id] set ont follows to admin.(you must channel master)\n" 327 | "\t - /update Only for developers.Update rss subscription now\n" 328 | , parse_mode="markdown") 329 | return 330 | else: 331 | bot.send_message(chat_id=self.chat_id, 332 | text="*Rss Pusher Usage:*\n*" 333 | "User:*\n" 334 | "\t- /create [id] 创建个rss订阅频道,其他用户可以根据这个id加入你的频道\n" 335 | "\t- /join [id] 加入一个频道,之后你将会收到这个频道的更新推送\n" 336 | "\t- /leave** [id] 离开某个频道,如果你是这个频道的创建者,频道将会删除\n" 337 | "\t- /list [id] 查看该频道的rss订阅列表\n" 338 | "\t- /myself 查看你创建/管理/加入的频道\n" 339 | "\t- /help 你现在正在看到的\n" 340 | "*Admin:*\n" 341 | "\t- /add [id] [title] [rss link] 给频道添加一个rss订阅链接\n" 342 | "\t- /delete [id] [rss_id] 删除频道内一个rss订阅链接,rss_id可以从 **/list** 里查看\n" 343 | "\t- /privilege [id] [telegram_id] 设置一个telegram用户为管理员,该成员必须再本频道发送过 /help 或以外的参数(你必须为频道创建者从才能使用本命令)\n" 344 | "\t- /update 仅对开发者开放,立刻更新所有rss推送\n" 345 | , parse_mode="markdown" 346 | ) 347 | return 348 | 349 | elif self.command == "/about": 350 | bot.send_message(chat_id=self.chat_id, 351 | text="Made By 9bie's gongdi english and jiushi." 352 | "\nWeb:{}\nGithub: https://github.com/9bie/rsspusher".format(URL)) 353 | return 354 | elif self.command == "/create": 355 | self.__create() 356 | elif self.command == "/join": 357 | self.__join() 358 | elif self.command == "/add": 359 | self.__add() 360 | elif self.command == "/delete": 361 | self.__delete() 362 | elif self.command == "/leave": 363 | self.__leave() 364 | elif self.command == "/list": 365 | self.__list() 366 | elif self.command == "/myself": 367 | self.__myself() 368 | elif self.command == "/privilege": 369 | self.__privilege() 370 | elif self.command == "/change_pwd": 371 | self.__change_pwd() 372 | elif self.command == "/update": 373 | self.__update() 374 | elif self.command == "": 375 | return 376 | else: 377 | if self.chat_id >= 0: 378 | bot.send_message(chat_id=self.chat_id, 379 | text="我不知道你在说啥,你可以发送/help给我查询.") 380 | return 381 | except Exception as e: 382 | if DEBUG is False: 383 | e = "*" * 20 384 | bot.send_message(chat_id=self.chat_id, text="*RssPusher Exception*:\n\t - {}".format(e), 385 | parse_mode="markdown") 386 | 387 | 388 | def send_all_follows(rsslist, msg): 389 | try: 390 | 391 | rssfriendship = models.RssListFriendShip.select().where( 392 | models.RssListFriendShip.RssList == rsslist 393 | ) 394 | for c in rssfriendship: 395 | follows = models.RssMember.select().where( 396 | models.RssMember.RssChannel == c.RssChannel 397 | ) 398 | for f in follows: 399 | 400 | bot.send_message(chat_id=f.Follows.Telegram_id, text=msg, parse_mode="html") 401 | except Exception as e: 402 | print("Have some errors:{}".format(e)) 403 | --------------------------------------------------------------------------------