|
| 1 | +#!/usr/bin/enb python3 |
| 2 | + |
| 3 | +from datetime import datetime as DateTime |
| 4 | +import argparse |
1 | 5 | import logging |
2 | | -from time import sleep |
| 6 | +import sys |
| 7 | +import time |
3 | 8 |
|
4 | | -import telegram |
5 | | -from telegram.ext import Updater, Filters, MessageHandler, CommandHandler |
6 | 9 | from telegram import Update |
| 10 | +from telegram.constants import ParseMode |
| 11 | +from telegram.ext import ApplicationBuilder |
| 12 | +from telegram.ext import CommandHandler |
| 13 | +from telegram.ext import MessageHandler |
| 14 | +from telegram.ext import ContextTypes |
| 15 | +from telegram.ext import filters |
7 | 16 |
|
8 | 17 | import config |
9 | 18 | import utils |
10 | 19 |
|
11 | 20 |
|
12 | | -logger = logging.getLogger('bot') |
13 | | - |
14 | | - |
15 | | -def command_start(update, context): |
16 | | - logger.info('Received command /start') |
17 | | - context.bot.send_message(chat_id=update.message.chat_id, text=config.BOT_GREETING) |
18 | | - |
19 | | - |
20 | | -def command_help(update, context): |
21 | | - logger.info('Received command /help') |
22 | | - context.bot.send_message( |
23 | | - chat_id=update.message.chat_id, |
24 | | - text="Available commands:\n" |
25 | | - " - /start - start intereaction with the bot\n" |
26 | | - " - /help - Show commands\n" |
27 | | - " - /status - Show status and alive time\n" |
28 | | - ) |
29 | | - |
30 | | - |
31 | | -def command_status(update, context): |
32 | | - logger.info('bot asked to execute /status commamd') |
33 | | - context.bot.send_message( |
34 | | - chat_id=update.message.chat_id, |
35 | | - text=f'Status is OK, running since {utils.since()}', |
36 | | - ) |
37 | | - |
38 | | - |
39 | | -def welcome(update: Update, context): |
40 | | - logger.info('Received new user event') |
41 | | - new_member = update.message.new_chat_members[0] |
42 | | - |
43 | | - logger.info(f'Waiting {config.WELCOME_DELAY} seconds until user completes captcha...') |
44 | | - sleep(config.WELCOME_DELAY) |
45 | | - membership_info = context.bot.get_chat_member(update.message.chat_id, new_member.id) |
46 | | - if membership_info['status'] == 'left': |
47 | | - logger.info(f'Skipping welcome message, user {new_member.name} is no longer in the chat') |
48 | | - return |
49 | | - |
50 | | - logger.info(f'send welcome message for {new_member.name}') |
51 | | - msg = None |
52 | | - |
53 | | - if new_member.is_bot: |
54 | | - msg = f"{new_member.name} is a *bot*!! " \ |
55 | | - "-> It could be kindly removed 🗑" |
56 | | - else: |
57 | | - if utils.is_bot(new_member): |
58 | | - context.bot.delete_message(update.message.chat_id, |
59 | | - update.message.message_id) |
60 | | - if context.bot.kick_chat_member(update.message.chat_id, new_member.id): |
61 | | - msg = (f"*{new_member.username}* has been banned because I " |
62 | | - "considered it was a bot. ") |
| 21 | +class DeckardBot(): |
| 22 | + |
| 23 | + def __init__(self): |
| 24 | + self.get_options() |
| 25 | + self.set_logger() |
| 26 | + self.started_at = DateTime.now() |
| 27 | + |
| 28 | + def get_options(self): |
| 29 | + parser = argparse.ArgumentParser( |
| 30 | + prog='bot', |
| 31 | + description='PyDeckard Bot', |
| 32 | + epilog='Text at the bottom of help', |
| 33 | + ) |
| 34 | + parser.add_argument('-v', '--verbose', action='store_true') |
| 35 | + args = parser.parse_args() |
| 36 | + self.verbose = args.verbose |
| 37 | + |
| 38 | + def set_logger(self): |
| 39 | + self.logger = logging.getLogger('bot') |
| 40 | + logging.basicConfig( |
| 41 | + level=config.LOG_LEVEL, |
| 42 | + format='%(asctime)s [%(name)s] %(levelname)s: %(message)s', |
| 43 | + ) |
| 44 | + config.log(self.logger.info) |
| 45 | + |
| 46 | + def trace(self, msg): |
| 47 | + self.logger.info('bot asked to execute /status commamd') |
| 48 | + if self.verbose: |
| 49 | + print(msg) |
| 50 | + |
| 51 | + async def command_status(self, update: Update, context: ContextTypes.DEFAULT_TYPE): |
| 52 | + self.trace('bot asked to execute /status commamd') |
| 53 | + python_version = sys.version.split(maxsplit=1)[0] |
| 54 | + text = '\n'.join([ |
| 55 | + config.BOT_GREETING, |
| 56 | + f'Status is <b>OK</b>, running since {utils.since(self.started_at)}', |
| 57 | + f'Python version is {python_version}', |
| 58 | + ]) |
| 59 | + await context.bot.send_message( |
| 60 | + chat_id=update.effective_chat.id, |
| 61 | + text=text, |
| 62 | + parse_mode=ParseMode.HTML, |
| 63 | + ) |
| 64 | + self.trace(text) |
| 65 | + |
| 66 | + async def command_start(self, update: Update, context: ContextTypes.DEFAULT_TYPE): |
| 67 | + self.trace('Received command /start') |
| 68 | + await context.bot.send_message( |
| 69 | + chat_id=update.effective_chat.id, |
| 70 | + text=config.BOT_GREETING, |
| 71 | + parse_mode=ParseMode.HTML, |
| 72 | + ) |
| 73 | + |
| 74 | + async def command_help(self, update: Update, context: ContextTypes.DEFAULT_TYPE): |
| 75 | + self.trace('Received command /help') |
| 76 | + await context.bot.send_message( |
| 77 | + chat_id=update.effective_chat.id, |
| 78 | + text=( |
| 79 | + "Available commands:\n\n" |
| 80 | + "<code>/start</code> : start intereaction with the bot\n" |
| 81 | + "<code>/help</code> : Show commands\n" |
| 82 | + "<code>/status</code> : Show status and alive time\n" |
| 83 | + "<code>/zen</code> : Show the Zen of Python\n" |
| 84 | + ), |
| 85 | + parse_mode=ParseMode.HTML, |
| 86 | + ) |
| 87 | + |
| 88 | + async def command_zen(self, update: Update, context: ContextTypes.DEFAULT_TYPE): |
| 89 | + self.trace('Received command /zen') |
| 90 | + text = '\n'.join(config.THE_ZEN_OF_PYTHON) |
| 91 | + await context.bot.send_message( |
| 92 | + chat_id=update.effective_chat.id, |
| 93 | + text=text, |
| 94 | + parse_mode=ParseMode.HTML, |
| 95 | + ) |
| 96 | + |
| 97 | + async def welcome(self, update: Update, context: ContextTypes.DEFAULT_TYPE): |
| 98 | + self.trace('Received new user event') |
| 99 | + new_member = update.message.new_chat_members[0] |
| 100 | + self.trace( |
| 101 | + f'Waiting {config.WELCOME_DELAY} seconds' |
| 102 | + ' until user completes captcha...' |
| 103 | + ) |
| 104 | + time.sleep(config.WELCOME_DELAY) |
| 105 | + membership_info = context.bot.get_chat_member( |
| 106 | + update.message.chat_id, |
| 107 | + new_member.id, |
| 108 | + ) |
| 109 | + if membership_info['status'] == 'left': |
| 110 | + self.trace('Skipping welcome message, user is no longer in the chat') |
| 111 | + return |
| 112 | + |
| 113 | + self.trace(f'send welcome message for {new_member.name}') |
| 114 | + |
| 115 | + msg = f"Welcome {new_member.name}!! I am a friendly and polite *bot* 🤖" |
| 116 | + if new_member.is_bot: |
| 117 | + msg = ( |
| 118 | + f"{new_member.name} looks like a *bot*!! " |
| 119 | + "-> It could be kindly removed 🗑" |
| 120 | + ) |
63 | 121 | else: |
64 | | - msg = f"Welcome {new_member.name}!! " \ |
65 | | - "I am a friendly and polite *bot* 🤖" |
66 | | - if msg: |
67 | | - context.bot.send_message( |
| 122 | + if utils.is_bot(new_member): |
| 123 | + context.bot.delete_message( |
| 124 | + update.message.chat_id, |
| 125 | + update.message.message_id, |
| 126 | + ) |
| 127 | + if context.bot.kick_chat_member( |
| 128 | + update.message.chat_id, |
| 129 | + new_member.id |
| 130 | + ): |
| 131 | + msg = ( |
| 132 | + f"*{new_member.username}* has been banned because I " |
| 133 | + "considered it a bot. " |
| 134 | + ) |
| 135 | + await context.bot.send_message( |
68 | 136 | chat_id=update.message.chat_id, |
69 | 137 | text=msg, |
70 | | - parse_mode=telegram.ParseMode.MARKDOWN |
71 | | - ) |
72 | | - |
73 | | - |
74 | | -def reply(update, context): |
75 | | - if not config.bot_replies_enabled(): |
76 | | - return |
77 | | - |
78 | | - msg = update.message.text |
79 | | - reply_spec = utils.triggers_reply(msg) if msg else None |
80 | | - if reply_spec is not None: |
81 | | - logger.info(f'bot sends reply {reply_spec.reply}') |
82 | | - context.bot.send_message( |
83 | | - chat_id=update.message.chat_id, |
84 | | - text=reply_spec.reply |
85 | | - ) |
86 | | - |
87 | | - |
88 | | -def main(): |
89 | | - logging.basicConfig( |
90 | | - level=config.LOG_LEVEL, |
91 | | - format='%(asctime)s [%(name)s] %(levelname)s: %(message)s', |
92 | | - ) |
93 | | - logger.info('Starting bot...') |
94 | | - config.log(logger.info) |
95 | | - updater = Updater(config.TELEGRAM_BOT_TOKEN) |
96 | | - dp = updater.dispatcher |
97 | | - |
98 | | - dp.add_handler(CommandHandler('start', command_start)) |
99 | | - dp.add_handler(CommandHandler('help', command_help)) |
100 | | - dp.add_handler(CommandHandler('status', command_status)) |
101 | | - dp.add_handler(MessageHandler(Filters.status_update.new_chat_members, |
102 | | - welcome, run_async=True)) |
103 | | - dp.add_handler(MessageHandler(Filters.chat_type.groups, reply)) |
104 | | - |
105 | | - logger.info('Bot is ready') |
106 | | - updater.start_polling(poll_interval=config.POLL_INTERVAL) |
107 | | - updater.idle() |
| 138 | + parse_mode=ParseMode.HTML, |
| 139 | + ) |
| 140 | + |
| 141 | + async def reply(self, update: Update, context: ContextTypes.DEFAULT_TYPE): |
| 142 | + if config.bot_replies_enabled(): |
| 143 | + msg = update.message.text |
| 144 | + reply_spec = utils.triggers_reply(msg) if msg else None |
| 145 | + if reply_spec is not None: |
| 146 | + self.trace(f'bot sends reply {reply_spec.reply}') |
| 147 | + await context.bot.send_message( |
| 148 | + chat_id=update.message.chat_id, |
| 149 | + text=reply_spec.reply, |
| 150 | + parse_mode=ParseMode.HTML, |
| 151 | + ) |
| 152 | + |
| 153 | + def run(self): |
| 154 | + self.trace('Starting bot...') |
| 155 | + application = ApplicationBuilder().token(config.TELEGRAM_BOT_TOKEN).build() |
| 156 | + start_handler = CommandHandler('start', self.command_start) |
| 157 | + application.add_handler(start_handler) |
| 158 | + help_handler = CommandHandler('help', self.command_help) |
| 159 | + application.add_handler(help_handler) |
| 160 | + status_handler = CommandHandler('status', self.command_status) |
| 161 | + application.add_handler(status_handler) |
| 162 | + |
| 163 | + # Zen Command |
| 164 | + application.add_handler(CommandHandler('zen', self.command_zen)) |
| 165 | + |
| 166 | + welcome_handler = MessageHandler( |
| 167 | + filters.StatusUpdate.NEW_CHAT_MEMBERS, |
| 168 | + self.welcome, |
| 169 | + ) |
| 170 | + application.add_handler(welcome_handler) |
| 171 | + reply_handler = MessageHandler( |
| 172 | + filters.TEXT & (~filters.COMMAND), |
| 173 | + self.reply, |
| 174 | + ) |
| 175 | + application.add_handler(reply_handler) |
| 176 | + self.trace('Bot is ready') |
| 177 | + application.run_polling(poll_interval=config.POLL_INTERVAL) |
108 | 178 |
|
109 | 179 |
|
110 | 180 | if __name__ == "__main__": |
111 | | - main() |
| 181 | + bot = DeckardBot() |
| 182 | + bot.run() |
0 commit comments