├── .gitignore ├── LICENSE ├── README.md ├── admincmd.py ├── config.json ├── config.py ├── feedback.py ├── main.py ├── mysystemd.py └── shell ├── forwardbot_service.service ├── gitpull.sh ├── restart.sh └── status.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 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 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 98 | __pypackages__/ 99 | 100 | # Celery stuff 101 | celerybeat-schedule 102 | celerybeat.pid 103 | 104 | # SageMath parsed files 105 | *.sage.py 106 | 107 | # Environments 108 | .env 109 | .venv 110 | env/ 111 | venv/ 112 | ENV/ 113 | env.bak/ 114 | venv.bak/ 115 | 116 | # Spyder project settings 117 | .spyderproject 118 | .spyproject 119 | 120 | # Rope project settings 121 | .ropeproject 122 | 123 | # mkdocs documentation 124 | /site 125 | 126 | # mypy 127 | .mypy_cache/ 128 | .dmypy.json 129 | dmypy.json 130 | 131 | # Pyre type checker 132 | .pyre/ 133 | 134 | # pytype static type analyzer 135 | .pytype/ 136 | 137 | # Cython debug symbols 138 | cython_debug/ 139 | 140 | .vscode -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # telegram-forward-bot 2 | 将你的发言匿名转发到群聊的机器人 3 | 4 | 这个机器人的作用就是让群里的人通过机器人说话,目标是: 5 | 6 | * 完全匿名了发言者的信息 7 | * 规避公共群的个人信息被存档的问题 8 | * 防止群中有他人的帐号出现问题,泄漏你的个人信息 9 | * 通过对发出的内容加入顶和踩的功能让大家为匿名发送什么逐渐达成共识 10 | * 用Bot完成群管理员和Bot管理员的日常设置和操作 11 | * Bot支持对非普通文本的发言附带可随时定制的反馈投票按钮 12 | 13 | 注意,一个帐户注册后,你的`userid`是永远不变的,所以telegram并不真正安全。 14 | 15 | 我的机器人都运行在RaspberryPi上,可以来 https://t.me/RaspberryPiCN 讨论机器人的使用和有关RaspberryPi的内容。 16 | 17 | ## 安装 18 | 19 | 建议使用venv环境,本项目必须使用Python3,本人不打算再在Python2中做任何测试 20 | 21 | ``` 22 | python3 -m venv py3 23 | source py3/bin/activate 24 | pip install python-telegram-bot 25 | ``` 26 | 27 | ## 使用 28 | 29 | ``` 30 | mkdir -p ~/.config/forwardbot/ 31 | ``` 32 | 33 | 将项目中的`config.json`复制到这个目录中。你也可以把配置文件放到你自己喜欢的地方。 34 | 35 | ### 配置 36 | 37 | 在`config.json`中配置你的信息 38 | 39 | ``` 40 | { 41 | "Admin": 0, // 管理员用户ID(通常为8~9位数字) 42 | "Token": "", // Bot的Token 43 | "Feedback": false, // 是否打开转发时的Feedback 44 | "Update_shell": "", // 执行升级的脚本路径,用以支持 /update 命令 45 | "Restart_shell": "", // 执行重启服务的脚本路径,用以支持 /restart 命令 46 | "Publish_Group_ID": [] // 群ID(如:@channel)列表 47 | } 48 | ``` 49 | 50 | 有几种典型的使用方法: 51 | 52 | * Admin/Publish_Group_ID相同时,你就可以做最简单的测试 53 | * 可以在Publish_Group_ID中加入多个群或频道,这时发送的内容会发到多个你指定的频道里去,列表支持数字、字符串混合 54 | 55 | ### 管理员命令 56 | 57 | 当你是Publish_Group_ID中第一个群的管理员时,你可以向Bot发送以下管理指令 58 | 59 | * `/help` 显示帮助 60 | * `/feedbackon` 关闭所有匿名发送的反馈 61 | * `/feedbackoff` 打开所有匿名发送的反馈 62 | 63 | 当你是Bot管理员时,你可以向Bot发送以下管理指令 64 | 65 | * `/Admin` Bot重启、查看配置、升级更新等功能 66 | * `/setfeedback` 设置反馈按钮,每个按钮的文字用逗号分开 67 | * `/setanswer` 设置反馈按钮按下后的提示信息,应该和铵钮数量相同,用逗号分开 68 | 69 | ## 运行 70 | 71 | ### 手工运行 72 | 73 | ``` 74 | python main.py 75 | ``` 76 | 77 | 会从`~/.config/forwardbot/`目录中读取配置文件和存取data。 78 | 79 | 也可以使用 80 | 81 | ``` 82 | python main.py -c /usr/local/etc/forwardbot 83 | ``` 84 | 85 | 来指定配置文件和data的存储路径。 86 | 87 | ### 配置systemd运行 88 | 89 | 在你的venv或Python环境中安装systemd支持,你需要提前确认一下你的操作系统是不是支持systemd。 90 | 91 | ``` 92 | pip install systemd-python 93 | ``` 94 | 95 | 修改`forwardbot_service.service`中的内容 96 | 97 | ``` 98 | [Unit] 99 | ## 修改为你的说明 100 | Description=Telegram Forward Bot Service 101 | 102 | [Service] 103 | ## 修改venv和main.py以及config.json目录的路径 104 | ExecStart=/usr/bin/python path/to/your/main.py -c /home/pi/fbot/tssd 105 | Restart=on-failure 106 | Type=notify 107 | 108 | [Install] 109 | WantedBy=default.target 110 | ``` 111 | 112 | 先将`forwardbot_service.service`文件放入`~/.config/systemd/user/`然后使用以下命令 113 | 114 | 查看所有的service配置 115 | 116 | ``` 117 | systemctl --user list-unit-files 118 | ``` 119 | 120 | 确定识别后,重新加载一下配置(每次更新service文件后都需要重新加载) 121 | 122 | ``` 123 | systemctl --user daemon-reload 124 | ``` 125 | 126 | 启动/停止/查看/重启 service 127 | 128 | ``` 129 | systemctl --user start forwardbot_service 130 | systemctl --user stop forwardbot_service 131 | systemctl --user status forwardbot_service 132 | systemctl --user restart forwardbot_service 133 | ``` 134 | 135 | 可以查看服务的output 136 | 137 | ``` 138 | journalctl --user-unit forwardbot_service 139 | ``` 140 | 141 | 如果一切正常,先enable service,再打开当前用户的开机启动 142 | 143 | ``` 144 | systemctl --user enable forwardbot_service 145 | sudo loginctl enable-linger $USER 146 | ``` 147 | 148 | 如果你不想放到你的用户下运行,可以放到System中。测试都正常后,执行以下操作 149 | 150 | ``` 151 | sudo mv ~/.config/systemd/user/forwardbot_service /etc/systemd/system/ 152 | sudo chown root:root /etc/systemd/system/forwardbot_service 153 | sudo chmod 644 /etc/systemd/system/forwardbot_service 154 | sudo systemctl daemon-reload 155 | sudo systemctl enable forwardbot_service 156 | sudo systemctl start forwardbot_service 157 | ``` 158 | 159 | ## 感谢 160 | 161 | * 感谢 https://github.com/python-telegram-bot/python-telegram-bot 162 | * 代码最早使用了 https://github.com/Netrvin/telegram-submission-bot 感谢他的轮子 163 | * 有如何在systemd中启动Python的程序感谢 https://github.com/torfsen/python-systemd-tutorial 的文章 164 | * 感谢 https://github.com/systemd/python-systemd -------------------------------------------------------------------------------- /admincmd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | """使用说明 4 | 5 | import admincmd 6 | 7 | admincmd.add_dispatcher(dispatcher) 8 | 9 | 然后自己来改下cmds,设置命令名和按钮名。这样就支持 /admin 和所有的按钮回调了。注意,cmds的callback名一定要admin:开头。 10 | """ 11 | 12 | from telegram import Update,InlineKeyboardButton,InlineKeyboardMarkup 13 | from telegram.ext import CommandHandler,Dispatcher,CallbackQueryHandler,CallbackContext 14 | import config 15 | from json import dumps 16 | import os 17 | 18 | cmds = { 19 | "admin:config":"配置", 20 | "admin:update":"更新", 21 | "admin:restart":"重启", 22 | "admin:status":"状态", 23 | "admin:help":"帮助" 24 | } 25 | 26 | def admin_cmd_callback(update : Update, context : CallbackContext): 27 | if update.callback_query.from_user.id == config.CONFIG['Admin'] : 28 | msg="" 29 | query = update.callback_query 30 | if query.data == "admin:config": 31 | cfg = config.CONFIG.copy() 32 | cfg['Token'] = "***" 33 | query.answer("获取配置") 34 | msg = dumps(cfg,indent=4,ensure_ascii=False) 35 | elif query.data == "admin:status": 36 | shell=config.CONFIG['Status_shell'] + ' > /tmp/status.txt' 37 | os.system(shell) 38 | msg = "反回信息:\n" + open("/tmp/status.txt").read() 39 | query.answer("获取状态") 40 | elif query.data == "admin:restart": 41 | shell=config.CONFIG['Restart_shell'] + ' > /tmp/restart.txt' 42 | os.system(shell) 43 | msg = "反回信息:\n" + open("/tmp/restart.txt").read() 44 | query.answer("重启服务") 45 | elif query.data == "admin:help": 46 | msg = help() 47 | query.answer() 48 | elif query.data == "admin:update": 49 | shell=config.CONFIG['Update_shell'] + ' > /tmp/gitpull.txt' 50 | os.system(shell) 51 | msg = "反回信息:\n" + open("/tmp/gitpull.txt").read() 52 | query.answer("更新代码") 53 | if msg != query.message.text : 54 | query.edit_message_text(text=msg,reply_markup=init_replay_markup()) 55 | 56 | def init_buttons(): 57 | buttons = [] 58 | for key in cmds: 59 | buttons.append(InlineKeyboardButton(cmds[key], callback_data=key ) ) 60 | return buttons 61 | 62 | def init_replay_markup(): 63 | return InlineKeyboardMarkup([init_buttons()]) 64 | 65 | def help(): 66 | msg = """ 67 | 都按按钮吧 68 | """ 69 | return msg 70 | 71 | def admin_cmd(update : Update, context : CallbackContext): 72 | if update.message.from_user.id == config.CONFIG['Admin'] : 73 | msg = help() 74 | update.message.reply_text(msg,reply_markup=init_replay_markup()) 75 | 76 | def add_dispatcher(dp: Dispatcher): 77 | dp.add_handler(CommandHandler(["admin"], admin_cmd)) 78 | dp.add_handler(CallbackQueryHandler(admin_cmd_callback,pattern="^admin:[A-Za-z0-9_]*")) -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "Admin": 0, 3 | "Token": "", 4 | "Feedback": true, 5 | "Update_shell": "", 6 | "Restart_shell": "", 7 | "Publish_Channel_ID": [], 8 | "Feedback_alert": false, 9 | "Feedback_text": "👍,👎,🤮", 10 | "Feedback_answer": "赞了一把,踩了一脚,吐了一地" 11 | } 12 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | import json 5 | import os 6 | 7 | loads = json.loads 8 | load = json.load 9 | dumps = json.dumps 10 | dump = json.dump 11 | 12 | config_file = "" 13 | 14 | CONFIG = {} 15 | 16 | def load_config(): 17 | global CONFIG 18 | with open(config_file, 'r') as configfile: 19 | CONFIG = load( configfile ) 20 | return CONFIG 21 | 22 | def save_config(): 23 | (filepath,filename) = os.path.split(config_file) 24 | folder = os.path.exists(filepath) 25 | if not folder: 26 | os.makedirs(filepath) 27 | 28 | with open(config_file, 'w') as configfile: 29 | dump(CONFIG, configfile, indent=4,ensure_ascii=False) 30 | 31 | def setdefault(): 32 | CONFIG.setdefault("Admin","") 33 | CONFIG.setdefault("Token","") 34 | CONFIG.setdefault("Publish_Group_ID",[]) 35 | CONFIG.setdefault("Feedback",True) 36 | CONFIG.setdefault("Update_shell","") 37 | CONFIG.setdefault("Restart_shell","") 38 | CONFIG.setdefault("Feedback_alert",False) 39 | CONFIG.setdefault("Feedback_text","") 40 | CONFIG.setdefault("Feedback_answer","") 41 | save_config() 42 | 43 | def get_json(): 44 | return dumps(CONFIG,indent=4,ensure_ascii=False) -------------------------------------------------------------------------------- /feedback.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | from telegram.inline.inlinekeyboardbutton import InlineKeyboardButton 5 | from telegram.inline.inlinekeyboardmarkup import InlineKeyboardMarkup 6 | import telegram 7 | from datetime import date 8 | 9 | 10 | class Feedback: 11 | feedbacks = {} 12 | show_answer = True 13 | show_alert = False 14 | 15 | def __init__(self): 16 | pass 17 | 18 | def init_buttons(self): 19 | buttons = [] 20 | for key in self.feedbacks: 21 | buttons.append(InlineKeyboardButton(key, callback_data="%s:0"%key ) ) 22 | return buttons 23 | 24 | def init_replay_markup_str(self,feedback_text,feedback_answer): 25 | self.feedbacks = dict( zip( feedback_text.split(","),feedback_answer.split(",")) ) 26 | return self.init_replay_markup() 27 | 28 | def init_replay_markup(self): 29 | return InlineKeyboardMarkup([self.init_buttons()]) 30 | 31 | def get_update_replay_markupr(self,query): 32 | replay_markup = InlineKeyboardMarkup([self.get_updatebuttons(query)]) 33 | return replay_markup 34 | 35 | def get_updatebuttons(self,query): 36 | button,count = query.data.split(":") 37 | count = int(count) + 1 38 | 39 | buttons = query.message.reply_markup.inline_keyboard[0] 40 | update_buttons = [] 41 | 42 | if self.show_answer: 43 | query.answer(self.feedbacks[button],show_alert=self.show_alert) 44 | 45 | for b in buttons: 46 | if b.callback_data == query.data: 47 | update_buttons.append(InlineKeyboardButton("%s%s"%(b.text[0:1],count),callback_data="%s:%s"%(button,count) ) ) 48 | else: 49 | update_buttons.append(InlineKeyboardButton(b.text,callback_data=b.callback_data ) ) 50 | return update_buttons 51 | 52 | feedback = Feedback() 53 | 54 | 55 | def __show_buttons__(buttons): 56 | for k in buttons: 57 | print("%s: %s"%(k.text,k.callback_data)) 58 | 59 | if __name__ == '__main__': 60 | # feedbacks = {"👍":"赞了一把", 61 | # "👎":"踩了一脚", 62 | # "🤮":"吐了一地"} 63 | 64 | feedback_text=["👍","👎","🤮"] 65 | feedback_answer=["赞了一把","踩了一脚","吐了一地"] 66 | 67 | feedback.feedbacks = dict(zip(feedback_text,feedback_answer)) 68 | 69 | # 为了测试,关闭反馈和反馈提示 70 | feedback.show_alert = False 71 | feedback.show_answer = False 72 | 73 | # 用feedbacks初始化buttons 74 | bs = feedback.init_buttons() 75 | print("初始化buttons:") 76 | __show_buttons__(bs) 77 | 78 | # 79 | now = date.today() 80 | chat = telegram.Chat(1,'group') 81 | 82 | replay_markup = InlineKeyboardMarkup([bs]) 83 | msg = telegram.Message(1,1,now,chat,reply_markup=replay_markup) 84 | callback = telegram.CallbackQuery(1,1,1,message=msg,data="👎:0") 85 | bs = feedback.get_updatebuttons(callback) 86 | print("callback一次") 87 | __show_buttons__(bs) 88 | 89 | 90 | replay_markup = InlineKeyboardMarkup([bs]) 91 | msg = telegram.Message(1,1,now,chat,reply_markup=replay_markup) 92 | callback = telegram.CallbackQuery(1,1,1,message=msg,data="👎:1") 93 | bs = feedback.get_updatebuttons(callback) 94 | print("callback两次") 95 | __show_buttons__(bs) -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | import config 5 | from feedback import feedback 6 | from telegram.ext import Updater, CommandHandler, MessageHandler, Filters, CallbackQueryHandler 7 | import telegram 8 | import os 9 | import logging 10 | import getopt 11 | import sys 12 | import mysystemd 13 | import admincmd 14 | from telegram.inline.inlinekeyboardmarkup import InlineKeyboardMarkup 15 | from json import dumps 16 | 17 | logging.basicConfig(level=logging.INFO, 18 | format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' 19 | ) 20 | 21 | def check_member(bot,chatid,userid): 22 | try: 23 | bot.get_chat_member(chatid,userid) 24 | return True 25 | except telegram.TelegramError as e: 26 | return False 27 | 28 | def check_admin(bot,chatid,userid): 29 | try: 30 | member = bot.get_chat_member(chatid,userid) 31 | if member.status in [ 'administrator' , 'creator']: 32 | return True 33 | return False 34 | except telegram.TelegramError as e: 35 | return False 36 | 37 | 38 | def process_msg(update, context): 39 | bot = context.bot 40 | if update.channel_post != None: 41 | return 42 | 43 | if update.message.from_user.id == update.message.chat_id: 44 | member = False 45 | for chat_id in CONFIG['Publish_Group_ID']: 46 | if check_member(bot,chat_id,update.message.from_user.id): 47 | member = True 48 | if member : 49 | send_anonymous_post(bot, update.message,update.message.from_user) 50 | else: 51 | update.message.reply_text('您不是我们匿名了天群的用户,所以我什么都做不了。寂寞总让人伤感,找个朋友去聊天吧~') 52 | 53 | 54 | def process_command(update, context): 55 | bot = context.bot 56 | if update.channel_post != None: 57 | return 58 | command = update.message.text[1:].replace(CONFIG['Username'], '' 59 | ).lower() 60 | if command == 'start' or command == 'help': 61 | helptext = "将文字、图片、音频/语音、视频、文件发送给我,我将直接把对它们匿名转发到你所在的群" 62 | if update.message.from_user.id == CONFIG['Admin'] or check_admin(bot,CONFIG['Publish_Group_ID'][0],update.message.from_user.id): 63 | helptext += """ 64 | 65 | 管理员指令: 66 | /feedbackoff 关闭所有匿名发送的反馈 67 | /feedbackon 打开所有匿名发送的反馈 68 | """ 69 | 70 | if update.message.from_user.id == CONFIG['Admin']: 71 | helptext +=""" 72 | 73 | Bot管理员指令 74 | /admin 进入Bot管理员指令菜单 75 | /setfeedback 设置反馈按钮,每个按钮的文字用逗号分开 76 | /setanswer 设置反馈按钮按下后的提示信息,应该和铵钮数量相同,用逗号分开 77 | """ 78 | 79 | bot.send_message(chat_id=update.message.chat_id, 80 | text=helptext) 81 | return 82 | 83 | if update.message.from_user.id == CONFIG['Admin'] or check_admin(bot,CONFIG['Publish_Group_ID'][0],update.message.from_user.id): 84 | if command == 'feedbackoff': 85 | CONFIG['Feedback']=False 86 | config.save_config() 87 | bot.send_message(chat_id=update.message.chat_id, 88 | text="Feedback已经关闭") 89 | elif command == 'feedbackon': 90 | CONFIG['Feedback']=True 91 | config.save_config() 92 | bot.send_message(chat_id=update.message.chat_id, 93 | text="Feedback已经打开") 94 | return 95 | 96 | def set_answer(update,context): 97 | if update.message.from_user.id == CONFIG['Admin'] : 98 | try: 99 | CONFIG['Feedback_answer'] = context.args[0] 100 | config.save_config() 101 | update.message.reply_text('反馈消息已经更新为:%s' % CONFIG['Feedback_answer']) 102 | return 103 | except (IndexError, ValueError): 104 | update.message.reply_text('使用说明: /setanswer 赞了一把,踩了一脚,吐了一地\n请使用逗号将每个按钮的反馈消息分开') 105 | 106 | def set_feedback(update,context): 107 | if update.message.from_user.id == CONFIG['Admin'] : 108 | try: 109 | CONFIG['Feedback_text'] = context.args[0] 110 | config.save_config() 111 | update.message.reply_text('反馈按钮已经更新为:%s' % CONFIG['Feedback_text'] ) 112 | return 113 | except (IndexError, ValueError): 114 | update.message.reply_text('使用说明: /setfeedback 👍,👎,🤮\n请使用逗号将按钮分开') 115 | 116 | def send_anonymous_post(bot, msg, editor): 117 | if CONFIG['Feedback']: 118 | replay_markup = feedback.init_replay_markup_str(CONFIG['Feedback_text'],CONFIG['Feedback_answer']) 119 | else: 120 | replay_markup = InlineKeyboardMarkup([[]]) 121 | 122 | for chatid in CONFIG['Publish_Group_ID']: 123 | if msg.audio != None: 124 | r = bot.send_audio(chat_id=chatid, 125 | audio=msg.audio, caption=msg.caption, 126 | reply_markup=replay_markup) 127 | elif msg.document != None: 128 | r = bot.send_document(chat_id=chatid, 129 | document=msg.document, 130 | caption=msg.caption, 131 | reply_markup=replay_markup) 132 | elif msg.voice != None: 133 | r = bot.send_voice(chat_id=chatid, 134 | voice=msg.voice, caption=msg.caption) 135 | elif msg.video != None: 136 | r = bot.send_video(chat_id=chatid, 137 | video=msg.video, caption=msg.caption, 138 | reply_markup=replay_markup) 139 | elif msg.photo: 140 | r = bot.send_photo(chat_id=chatid, 141 | photo=msg.photo[0], caption=msg.caption, 142 | reply_markup=replay_markup) 143 | else: 144 | types = [] 145 | for i in msg.entities: 146 | types.append(i.type) 147 | 148 | # print(msg,"\n",types) 149 | if 'url' in types or 'text_link' in types: 150 | r = bot.send_message(chat_id=chatid, 151 | text=msg.text_markdown, 152 | parse_mode=telegram.ParseMode.MARKDOWN, 153 | reply_markup=replay_markup) 154 | else: 155 | r = bot.send_message(chat_id=chatid, 156 | text=msg.text_markdown, 157 | parse_mode=telegram.ParseMode.MARKDOWN) 158 | 159 | 160 | def process_callback(update, context): 161 | if update.channel_post != None: 162 | return 163 | query = update.callback_query 164 | replay_markup = feedback.get_update_replay_markupr(query) 165 | query.edit_message_reply_markup(replay_markup) 166 | 167 | def help(): 168 | return "'main.py -c '" 169 | 170 | if __name__ == '__main__': 171 | 172 | PATH = os.path.dirname(os.path.expanduser("~/.config/forwardbot/")) 173 | 174 | try: 175 | opts, args = getopt.getopt(sys.argv[1:],"hc:",["config="]) 176 | except getopt.GetoptError: 177 | print(help()) 178 | sys.exit(2) 179 | 180 | for opt, arg in opts: 181 | if opt == '-h': 182 | print(help()) 183 | sys.exit() 184 | elif opt in ("-c","--config"): 185 | PATH = arg 186 | 187 | config.config_file = os.path.join(PATH,"config.json") 188 | try: 189 | CONFIG = config.load_config() 190 | except FileNotFoundError: 191 | print("config.json not found.Generate a new configuration file in %s" % config.config_file) 192 | config.setdefault() 193 | sys.exit(2) 194 | 195 | updater = Updater(CONFIG['Token'], use_context=True) 196 | dispatcher = updater.dispatcher 197 | 198 | me = updater.bot.get_me() 199 | CONFIG['ID'] = me.id 200 | CONFIG['Username'] = '@' + me.username 201 | config.setdefault() 202 | print('Starting... (ID: ' + str(CONFIG['ID']) + ', Username: ' + CONFIG['Username'] + ')') 203 | 204 | if CONFIG['Feedback']: 205 | replay_markup = feedback.init_replay_markup_str(CONFIG['Feedback_text'],CONFIG['Feedback_answer']) 206 | 207 | # 加入/admin和它按钮的所有回调处理 208 | admincmd.add_dispatcher(dispatcher) 209 | 210 | dispatcher.add_handler(CommandHandler("setfeedback", set_feedback, 211 | pass_args=True)) 212 | dispatcher.add_handler(CommandHandler("setanswer", set_answer, 213 | pass_args=True)) 214 | dispatcher.add_handler(CallbackQueryHandler(process_callback)) 215 | dispatcher.add_handler(MessageHandler(Filters.command,process_command)) 216 | dispatcher.add_handler(MessageHandler( Filters.text 217 | | Filters.audio 218 | | Filters.photo 219 | | Filters.video 220 | | Filters.voice 221 | | Filters.document , process_msg)) 222 | 223 | updater.start_polling() 224 | print('Started') 225 | mysystemd.ready() 226 | 227 | updater.idle() 228 | print('Stopping...') 229 | print('Stopped.') 230 | -------------------------------------------------------------------------------- /mysystemd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | try: 5 | import systemd.daemon 6 | from systemd import journal 7 | systemd_enable=True 8 | except ImportError: 9 | systemd_enable=False 10 | 11 | def ready(): 12 | if systemd_enable: 13 | systemd.daemon.notify('READY=1') -------------------------------------------------------------------------------- /shell/forwardbot_service.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Telegram Forward Bot Service 3 | 4 | [Service] 5 | ExecStart=/home/pi/py3/bin/python path/to/your/main.py -c /home/pi/fbot/tssd 6 | Restart=on-failure 7 | Type=notify 8 | 9 | [Install] 10 | WantedBy=default.target 11 | -------------------------------------------------------------------------------- /shell/gitpull.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd /home/pi/telegram-forward-bot 4 | git pull -------------------------------------------------------------------------------- /shell/restart.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | systemctl --user restart forward_bot_service 3 | systemctl --user status forward_bot_service -------------------------------------------------------------------------------- /shell/status.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | systemctl --user status forward_bot_service --------------------------------------------------------------------------------