Skip to content

Commit 70b29fc

Browse files
euribatessdelquin
authored andcommitted
New commands /status, /help and /start (#20)
* Añade comando /status para saber si el bot esta activo y desde cuando * Los mensajes del bot sobre /status van en ingles * Added a logger * Add function since to utils This gives a description of time since the program started, for the /status command. * Added values BOT_GREETING and LOG_LEVEL First one is used in the /start command, second one defines default log level for the modules using logging (default is WARNING) * New config variable POLL_INTERVAL (default value is 3) * Add commands /status, /start and /help * Fixed typo * Fixed error, call to main was deleted in merge * utils.py formatted with black
1 parent b500144 commit 70b29fc

4 files changed

Lines changed: 154 additions & 35 deletions

File tree

bot.py

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,29 @@
99
import utils
1010

1111

12+
logger = logging.getLogger('bot')
13+
14+
15+
def start(bot, update):
16+
logger.info('Received command /start')
17+
bot.send_message(chat_id=update.message.chat_id, text=config.BOT_GREETING)
18+
19+
20+
def help(bot, update):
21+
logger.info('Received command /help')
22+
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+
1231
def welcome(bot: Bot, update: Update):
32+
logger.info('Received new user event')
1333
new_member = update.message.new_chat_members[0]
34+
logger.info(f'send welcome message for {new_member.name}')
1435
msg = None
1536

1637
if new_member.is_bot:
@@ -41,47 +62,40 @@ def reply(bot, update):
4162
msg = update.message.text
4263
reply_spec = utils.triggers_reply(msg)
4364
if reply_spec is not None:
65+
logger.info(f'bot sends reply {reply_spec.reply}')
4466
bot.send_message(
4567
chat_id=update.message.chat_id,
4668
text=reply_spec.reply
4769
)
4870

4971

50-
def since(reference=datetime.datetime.now()):
51-
now = datetime.datetime.now()
52-
delta = now - reference
53-
buff = []
54-
if delta.days:
55-
buff.append('{} days'.format(delta.days))
56-
hours = delta.seconds // 3600
57-
if hours > 0:
58-
buff.append('{} hours'.format(hours))
59-
minutes = delta.seconds // 60
60-
if minutes > 0:
61-
buff.append('{} minutes'.format(minutes))
62-
seconds = delta.seconds % 60
63-
buff.append('{} seconds'.format(seconds))
64-
return ' '.join(buff)
65-
66-
6772
def status(bot, update):
73+
logger.info('bot asked to execute /status commamd')
6874
bot.send_message(
6975
chat_id=update.message.chat_id,
70-
text='Status is OK, running since {}'.format(since())
76+
text=f'Status is OK, running since {utils.since()}',
7177
)
7278

7379

7480
def main():
75-
logging.basicConfig(level=logging.INFO)
76-
logging.info('Starting bot...')
81+
logging.basicConfig(
82+
level=config.LOG_LEVEL,
83+
format='%(asctime)s [%(name)s] %(levelname)s: %(message)s',
84+
)
85+
logger.info('Starting bot...')
86+
logger.info(f'- Log level is {config.LOG_LEVEL}')
87+
logger.info(f'- Poll interval is {config.POLL_INTERVAL}')
7788
updater = Updater(config.TELEGRAM_BOT_TOKEN)
7889
dp = updater.dispatcher
7990

91+
dp.add_handler(CommandHandler('start', start))
92+
dp.add_handler(CommandHandler('help', help))
93+
dp.add_handler(CommandHandler('status', status))
8094
dp.add_handler(MessageHandler(Filters.status_update.new_chat_members, welcome))
8195
dp.add_handler(MessageHandler(Filters.group, reply))
82-
dp.add_handler(CommandHandler('status', status))
8396

84-
updater.start_polling()
97+
logger.info('Bot is ready')
98+
updater.start_polling(poll_interval=config.POLL_INTERVAL)
8599
updater.idle()
86100

87101

config.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,20 @@
55
default="put here the token of your bot"
66
)
77

8-
98
# How likely is the bot to be triggered by one of the patterns it recognises.
109
# - Allowed values: A float from 0 to 1 (0 will disable bot replies)
1110
VERBOSITY = config("BOT_VERBOSITY", float, default=0.33)
1211

1312

13+
# Log level, default is WARNING
14+
LOG_LEVEL = config('LOG_LEVEL', default='WARNING')
15+
16+
# Poll interval for telegram API request, default is 3 seconds
17+
POLL_INTERVAL = config('POLL_INTERVAL', int, default=3)
18+
19+
# Bot message for start command
20+
BOT_GREETING = "Hi! I'm a friendly, ligthly psychopath robot"
21+
1422
# A username longer than this will be considered non-human
1523
# - Allowed values: An integer larger than 1
1624
MAX_HUMAN_USERNAME_LENGTH = config('MAX_HUMAN_USERNAME_LENGTH',

test/test_utils.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
import datetime
5+
6+
import pytest
7+
import utils
8+
9+
10+
def test_since_second():
11+
ref = datetime.datetime(2019, 5, 16, 13, 35, 15)
12+
now = datetime.datetime(2019, 5, 16, 13, 35, 16)
13+
assert utils.since(now, ref) == '1 second'
14+
15+
16+
def test_since_seconds():
17+
ref = datetime.datetime(2019, 5, 16, 13, 35, 15)
18+
now = datetime.datetime(2019, 5, 16, 13, 35, 21)
19+
assert utils.since(now, ref) == '6 seconds'
20+
21+
22+
def test_since_minute_and_seconds():
23+
ref = datetime.datetime(2019, 5, 16, 13, 35, 15)
24+
now = datetime.datetime(2019, 5, 16, 13, 36, 21)
25+
assert utils.since(now, ref) == '1 minute 6 seconds'
26+
27+
28+
def test_since_minutes_and_seconds():
29+
ref = datetime.datetime(2019, 5, 16, 13, 35, 15)
30+
now = datetime.datetime(2019, 5, 16, 13, 37, 21)
31+
assert utils.since(now, ref) == '2 minutes 6 seconds'
32+
33+
34+
def test_since_hour_and_minutes_and_seconds():
35+
ref = datetime.datetime(2019, 5, 16, 13, 35, 15)
36+
now = datetime.datetime(2019, 5, 16, 14, 37, 21)
37+
assert utils.since(now, ref) == '1 hour 2 minutes 6 seconds'
38+
39+
40+
def test_since_hours_and_minutes_and_seconds():
41+
ref = datetime.datetime(2019, 5, 16, 13, 35, 15)
42+
now = datetime.datetime(2019, 5, 16, 15, 37, 21)
43+
assert utils.since(now, ref) == '2 hours 2 minutes 6 seconds'
44+
45+
46+
def test_since_day_hours_and_minutes_and_seconds():
47+
ref = datetime.datetime(2019, 5, 16, 13, 35, 15)
48+
now = datetime.datetime(2019, 5, 17, 15, 37, 21)
49+
assert utils.since(now, ref) == '1 day 2 hours 2 minutes 6 seconds'
50+
51+
52+
def test_since_days_hours_and_minutes_and_seconds():
53+
ref = datetime.datetime(2019, 5, 16, 13, 35, 15)
54+
now = datetime.datetime(2019, 5, 19, 15, 37, 21)
55+
assert utils.since(now, ref) == '3 days 2 hours 2 minutes 6 seconds'
56+
57+
58+
if __name__ == "__main__":
59+
pytest.main()

utils.py

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import functools
2+
import datetime
23
import random
34
import re
45
import typing
@@ -13,13 +14,15 @@ def is_chinese(c):
1314
Returns True if the character passed as parameter is a Chinese one
1415
"""
1516
num = ord(c)
16-
return any((
17-
0x2E80 <= num <= 0x2FD5,
18-
0x3190 <= num <= 0x319F,
19-
0x3400 <= num <= 0x4DBF,
20-
0x4E00 <= num <= 0x9FCC,
21-
0x6300 <= num <= 0x77FF,
22-
))
17+
return any(
18+
(
19+
0x2E80 <= num <= 0x2FD5,
20+
0x3190 <= num <= 0x319F,
21+
0x3400 <= num <= 0x4DBF,
22+
0x4E00 <= num <= 0x9FCC,
23+
0x6300 <= num <= 0x77FF,
24+
)
25+
)
2326

2427

2528
def too_much_chinese_chars(s):
@@ -50,11 +53,13 @@ def is_bot(user: User):
5053
:rtype: bool
5154
"""
5255
# Add all the checks that you consider necessary
53-
return any((
54-
not is_valid_name(user),
55-
too_much_chinese_chars(user.first_name),
56-
is_tgmember_sect(user.first_name),
57-
))
56+
return any(
57+
(
58+
not is_valid_name(user),
59+
too_much_chinese_chars(user.first_name),
60+
is_tgmember_sect(user.first_name),
61+
)
62+
)
5863

5964

6065
@functools.lru_cache()
@@ -89,3 +94,36 @@ def triggers_reply(message: str) -> typing.Optional[BotReplySpec]:
8994
bot_reply = random.choice(bot_reply)
9095
return BotReplySpec(message, match.group(0), bot_reply)
9196
return None
97+
98+
99+
def since(dt=None, reference=datetime.datetime.now()) -> str:
100+
"""Returns a textual description of time passed.
101+
102+
Parameters:
103+
104+
- dt: datetime is the date to calculate the difference from
105+
reference. If not used, take the value from the current
106+
datetime.
107+
108+
- reference: datetime is the datetime used to get the difference
109+
ir delta. If not defined, default value is since the definition
110+
of the function, this is,since the moment the current run of the
111+
program started.
112+
"""
113+
dt = dt or datetime.datetime.now()
114+
delta = dt - reference
115+
buff = []
116+
days = delta.days
117+
if days:
118+
buff.append(f"{days} day" if days == 1 else f"{days} days")
119+
seconds = delta.seconds
120+
if seconds > 3600:
121+
hours = seconds // 3600
122+
buff.append(f"{hours} hour" if hours == 1 else f"{hours} hours")
123+
seconds = seconds % 3600
124+
minutes = seconds // 60
125+
if minutes > 0:
126+
buff.append(f"{minutes} minute" if minutes == 1 else f"{minutes} minutes")
127+
seconds = seconds % 60
128+
buff.append(f"{seconds} second" if seconds == 1 else f"{seconds} seconds")
129+
return " ".join(buff)

0 commit comments

Comments
 (0)