Skip to content

Commit 21cc1dd

Browse files
committed
Adapted to changes in main branch
2 parents b1ba75e + 6d5d281 commit 21cc1dd

9 files changed

Lines changed: 204 additions & 641 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ virtualenv
77
.DS_Store
88
.env
99
.pytest_cache
10+
.python-version

Pipfile

Lines changed: 0 additions & 18 deletions
This file was deleted.

Pipfile.lock

Lines changed: 0 additions & 500 deletions
This file was deleted.

README.md

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,19 @@ Telegram Bot made in Python to automate different tasks of [Python Canarias](htt
99
1010
## Installation
1111

12-
Create the virtualenv for Python3 and install dependencies with:
12+
Create a virtualenv for Python3 and install dependencies. In this
13+
example we are using pyenv:
1314

1415
~~~console
15-
$ pipenv install
16+
$ pyenv virtualenv 3.12.4 pydeckard
17+
$ pyenv activate pydeckard
18+
$ pip install -r requirements.txt
19+
~~~
20+
21+
A developer needs to install a few more packages:
22+
23+
~~~console
24+
$ pip install -r dev-requirements.txt
1625
~~~
1726

1827
Next step is to set your bot token for development:
@@ -27,9 +36,17 @@ Now you can launch the bot with:
2736
$ python bot.py
2837
~~~
2938

39+
You can use the flag `--verbose` (or `-v') to get more information in rhe console:
40+
41+
~~~console
42+
$ python bot.py --verbose
43+
~~~
44+
45+
3046
## Tests
3147

48+
Use pytest:
49+
3250
~~~console
33-
$ pipenv install --dev
34-
$ pytest
51+
$ python -m pytest
3552
~~~

bot.py

Lines changed: 152 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,111 +1,165 @@
1+
#!/usr/bin/enb python3
2+
3+
from datetime import datetime as DateTime
4+
import argparse
15
import logging
2-
from time import sleep
6+
import sys
7+
import time
38

49
import telegram
5-
from telegram.ext import Updater, Filters, MessageHandler, CommandHandler
610
from telegram import Update
11+
from telegram.ext import ApplicationBuilder, filters, MessageHandler, CommandHandler, ContextTypes
12+
from telegram.constants import ParseMode
713

814
import config
915
import utils
1016

1117

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

109162

110163
if __name__ == "__main__":
111-
main()
164+
bot = DeckardBot()
165+
bot.run()

0 commit comments

Comments
 (0)