Skip to content

Commit de2995c

Browse files
committed
Make telegram bot working async. Add async fixture and tests.
1 parent b0bc592 commit de2995c

File tree

10 files changed

+118
-102
lines changed

10 files changed

+118
-102
lines changed

app/main.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from app.database.database import engine
66
from app.dependencies import (
77
MEDIA_PATH, STATIC_PATH, templates)
8-
from app.telegram.pylander import pylander
8+
from app.telegram.bot import telegram_bot
99
from app.routers import agenda, email, event, invitation, profile, telegram
1010

1111
models.Base.metadata.create_all(bind=engine)
@@ -21,7 +21,7 @@
2121
app.include_router(email.router)
2222
app.include_router(invitation.router)
2323

24-
pylander.set_webhook()
24+
telegram_bot.set_webhook()
2525

2626

2727
@app.get("/")

app/routers/telegram.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ async def telegram(request: Request, session=Depends(get_db)):
2121

2222

2323
@router.post("/")
24-
def bot_client(req: dict = Body(...), session=Depends(get_db)):
24+
async def bot_client(req: dict = Body(...), session=Depends(get_db)):
2525
chat = Chat(req)
2626

2727
# Check if current chatter is registered to use the bot
2828
user = session.query(User).filter_by(telegram_id=chat.user_id).first()
2929
if user is None:
30-
return reply_unknown_user(chat)
30+
return await reply_unknown_user(chat)
3131

3232
message = MessageHandler(chat, user)
33-
return message.process_callback()
33+
return await message.process_callback()

app/telegram/pylander.py renamed to app/telegram/bot.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@
88
BOT_API = settings.bot_api
99
WEBHOOK_URL = settings.webhook_url
1010

11-
pylander = Bot(BOT_API, WEBHOOK_URL)
11+
telegram_bot = Bot(BOT_API, WEBHOOK_URL)

app/telegram/handlers.py

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from .keyboards import (
44
DATE_FORMAT, gen_inline_keyboard, get_this_week_buttons, show_events_kb)
55
from .models import Chat
6-
from .pylander import pylander
6+
from .bot import telegram_bot
77
from app.database.models import User
88

99

@@ -22,31 +22,31 @@ def __init__(self, chat: Chat, user: User):
2222
for button in row:
2323
self.handlers[button['text']] = self.chosen_day_handler
2424

25-
def process_callback(self):
25+
async def process_callback(self):
2626
if self.chat.message in self.handlers:
27-
return self.handlers[self.chat.message]()
28-
return self.default_handler()
27+
return await self.handlers[self.chat.message]()
28+
return await self.default_handler()
2929

30-
def default_handler(self):
30+
async def default_handler(self):
3131
answer = "Unknown command."
32-
pylander.send_message(chat_id=self.chat.user_id, text=answer)
32+
await telegram_bot.send_message(chat_id=self.chat.user_id, text=answer)
3333
return answer
3434

35-
def start_handler(self):
35+
async def start_handler(self):
3636
answer = f'''Hello, {self.chat.first_name}!
3737
Welcome to Pylander telegram client!'''
38-
pylander.send_message(chat_id=self.chat.user_id, text=answer)
38+
await telegram_bot.send_message(chat_id=self.chat.user_id, text=answer)
3939
return answer
4040

41-
def show_events_handler(self):
41+
async def show_events_handler(self):
4242
answer = 'Choose events day.'
43-
pylander.send_message(
43+
await telegram_bot.send_message(
4444
chat_id=self.chat.user_id,
4545
text=answer,
4646
reply_markup=show_events_kb)
4747
return answer
4848

49-
def today_handler(self):
49+
async def today_handler(self):
5050
today = datetime.date.today()
5151
events = [
5252
event for event in self.user.events
@@ -60,20 +60,20 @@ def today_handler(self):
6060
for event in events:
6161
answer += f'\n\n{event.title}: from {event.start} to {event.ends}.'
6262

63-
pylander.send_message(chat_id=self.chat.user_id, text=answer)
63+
await telegram_bot.send_message(chat_id=self.chat.user_id, text=answer)
6464
return answer
6565

66-
def this_week_handler(self):
66+
async def this_week_handler(self):
6767
answer = 'Choose a day.'
6868
this_week_kb = gen_inline_keyboard(get_this_week_buttons())
6969

70-
pylander.send_message(
70+
await telegram_bot.send_message(
7171
chat_id=self.chat.user_id,
7272
text=answer,
7373
reply_markup=this_week_kb)
7474
return answer
7575

76-
def chosen_day_handler(self):
76+
async def chosen_day_handler(self):
7777
# Convert chosen day (string) to datetime format
7878
chosen_date = datetime.datetime.strptime(
7979
self.chat.message, DATE_FORMAT)
@@ -85,17 +85,17 @@ def chosen_day_handler(self):
8585
answer = f"{chosen_date.strftime('%B %d')}, \
8686
{chosen_date.strftime('%A')} Events:\n"
8787

88-
if not len(events):
88+
if not events:
8989
answer = f"There're no events on {chosen_date.strftime('%B %d')}."
9090

9191
for event in events:
9292
answer += f'\n\n{event.title}: from {event.start} to {event.ends}.'
9393

94-
pylander.send_message(chat_id=self.chat.user_id, text=answer)
94+
await telegram_bot.send_message(chat_id=self.chat.user_id, text=answer)
9595
return answer
9696

9797

98-
def reply_unknown_user(chat):
98+
async def reply_unknown_user(chat):
9999
answer = f'''
100100
Hello, {chat.first_name}!
101101
@@ -107,5 +107,5 @@ def reply_unknown_user(chat):
107107
108108
https://calendar.pythonic.guru/profile/
109109
'''
110-
pylander.send_message(chat_id=chat.user_id, text=answer)
110+
await telegram_bot.send_message(chat_id=chat.user_id, text=answer)
111111
return answer

app/telegram/keyboards.py

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,29 +15,27 @@
1515

1616
def get_this_week_buttons() -> List[List[Any]]:
1717
today = datetime.date.today()
18-
day1 = today + datetime.timedelta(days=1)
19-
day2 = today + datetime.timedelta(days=2)
20-
day3 = today + datetime.timedelta(days=3)
21-
day4 = today + datetime.timedelta(days=4)
22-
day5 = today + datetime.timedelta(days=5)
23-
day6 = today + datetime.timedelta(days=6)
18+
buttons = []
19+
for day in range(1, 7):
20+
day = today + datetime.timedelta(days=day)
21+
buttons.append(day.strftime(DATE_FORMAT))
2422

2523
return [
2624
[
27-
{'text': day1.strftime(DATE_FORMAT),
28-
'callback_data': day1.strftime(DATE_FORMAT)},
29-
{'text': day2.strftime(DATE_FORMAT),
30-
'callback_data': day2.strftime(DATE_FORMAT)},
31-
{'text': day3.strftime(DATE_FORMAT),
32-
'callback_data': day3.strftime(DATE_FORMAT)}
25+
{'text': buttons[0],
26+
'callback_data': buttons[0]},
27+
{'text': buttons[1],
28+
'callback_data': buttons[1]},
29+
{'text': buttons[2],
30+
'callback_data': buttons[2]}
3331
],
3432
[
35-
{'text': day4.strftime(DATE_FORMAT),
36-
'callback_data': day4.strftime(DATE_FORMAT)},
37-
{'text': day5.strftime(DATE_FORMAT),
38-
'callback_data': day5.strftime(DATE_FORMAT)},
39-
{'text': day6.strftime(DATE_FORMAT),
40-
'callback_data': day6.strftime(DATE_FORMAT)}
33+
{'text': buttons[3],
34+
'callback_data': buttons[3]},
35+
{'text': buttons[4],
36+
'callback_data': buttons[4]},
37+
{'text': buttons[5],
38+
'callback_data': buttons[5]}
4139
]
4240
]
4341

app/telegram/models.py

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,22 @@
44

55

66
class Chat:
7-
def __init__(self, data):
7+
def __init__(self, data: Dict):
88
self.message = self._get_message_content(data)
99
self.user_id = self._get_user_id(data)
1010
self.first_name = self._get_first_name(data)
1111

12-
def _get_message_content(self, data):
12+
def _get_message_content(self, data: Dict) -> str:
1313
if 'callback_query' in data:
1414
return data['callback_query']['data']
1515
return data['message']['text']
1616

17-
def _get_user_id(self, data):
17+
def _get_user_id(self, data: Dict) -> str:
1818
if 'callback_query' in data:
1919
return data['callback_query']['from']['id']
2020
return data['message']['from']['id']
2121

22-
def _get_first_name(self, data):
22+
def _get_first_name(self, data: Dict) -> str:
2323
if 'callback_query' in data:
2424
return data['callback_query']['from']['first_name']
2525
return data['message']['from']['first_name']
@@ -30,23 +30,20 @@ def __init__(self, bot_api: str, webhook_url: str):
3030
self.base = self._set_base_url(bot_api)
3131
self.webhook_setter_url = self._set_webhook_setter_url(webhook_url)
3232

33-
def _set_base_url(self, bot_api):
33+
def _set_base_url(self, bot_api: str) -> str:
3434
return f'https://api.telegram.org/bot{bot_api}/'
3535

36-
def _set_webhook_setter_url(self, webhook_url: str):
36+
def _set_webhook_setter_url(self, webhook_url: str) -> str:
3737
return f'{self.base}setWebhook?url={webhook_url}/telegram/'
3838

3939
def set_webhook(self):
4040
return requests.get(self.webhook_setter_url)
4141

4242
def drop_webhook(self):
43-
data = {
44-
'drop_pending_updates': True
45-
}
46-
return requests.get(
47-
url=f'{self.base}deleteWebhook', data=data)
43+
data = {'drop_pending_updates': True}
44+
return requests.get(url=f'{self.base}deleteWebhook', data=data)
4845

49-
def send_message(
46+
async def send_message(
5047
self, chat_id: str,
5148
text: str,
5249
reply_markup: Optional[Dict[str, Any]] = None):

tests/asyncio_fixture.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from httpx import AsyncClient
2+
import pytest
3+
4+
from app.database.database import Base
5+
from app.main import app
6+
from app.routers import telegram
7+
from tests.conftest import test_engine, get_test_db
8+
9+
10+
@pytest.fixture
11+
async def telegram_client():
12+
Base.metadata.create_all(bind=test_engine)
13+
app.dependency_overrides[telegram.get_db] = get_test_db
14+
async with AsyncClient(app=app, base_url="http://test") as ac:
15+
yield ac
16+
app.dependency_overrides = {}
17+
Base.metadata.drop_all(bind=test_engine)

tests/client_fixture.py

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from app.database.models import User
55
from app.main import app
66
from app.database.database import Base
7-
from app.routers import agenda, invitation, profile, telegram
7+
from app.routers import agenda, invitation, profile
88
from tests.conftest import test_engine, get_test_db
99

1010

@@ -59,15 +59,3 @@ def get_test_placeholder_user():
5959
full_name='FakeName',
6060
telegram_id='666666'
6161
)
62-
63-
64-
@pytest.fixture(scope="module")
65-
def telegram_client():
66-
Base.metadata.create_all(bind=test_engine)
67-
app.dependency_overrides[telegram.get_db] = get_test_db
68-
69-
with TestClient(app) as client:
70-
yield client
71-
72-
app.dependency_overrides = {}
73-
Base.metadata.drop_all(bind=test_engine)

tests/conftest.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
'tests.invitation_fixture',
1111
'tests.association_fixture',
1212
'tests.client_fixture',
13+
'tests.asyncio_fixture',
1314
'smtpdfix',
1415
]
1516

0 commit comments

Comments
 (0)