1
from django.contrib import auth
3
from telethon.sync import TelegramClient, events
4
from telethon.tl.custom import Button
6
from authapp.models import AuthUser
7
from questions.operations import SettingRatingToQuestionByUser, AlreadyRemarkedByThisUser
12
def __init__(self, bot: TelegramClient, telegram_id: int, telegram_username: str):
14
self.telegram_id = telegram_id
15
self.telegram_username = telegram_username
18
async def _get_answer_from_conv(conv: TelegramClient.conversation, question: str):
20
Функция-обертка над фрагментом диалога
21
(отправит пользователю уведомление, есил время ожилания ответа истечет)
24
timeout_message = 'Время ответа истекло'
26
await conv.send_message(question)
27
answer = await conv.get_response()
29
except Exception as e:
30
await conv.send_message(timeout_message)
33
def _press_event(user_id: int) -> events.CallbackQuery:
35
Вспомогательная функция для отслеживания кнопки, нажатой в диалоге
37
return events.CallbackQuery(func=lambda e: e.sender_id == user_id)
40
def _authorize(username: str, password: str) -> bool:
41
user = auth.authenticate(username=username, password=password)
46
async def _merge_accounts(self, conv: TelegramClient.conversation) -> None:
48
Функция связывания аккаунтов:
49
- в случае успешной авторизации аккаунту в базе добавляется переданный telegram id
52
username = await self._get_answer_from_conv(conv=conv, question='Введи имя пользователя')
54
password = await self._get_answer_from_conv(conv=conv, question='Введи пароль')
57
authorized = self._authorize(username=username, password=password)
61
current_user = AuthUser.objects.get(username=username)
62
current_user.telegram_id = self.telegram_id
64
await conv.send_message(
65
f'Аккаунты связаны: login {current_user.username}, telegram_id {current_user.telegram_id}')
67
await conv.send_message(f'Неверный логин или пароль')
69
async def _create_account(self, conv: TelegramClient.conversation) -> None:
71
Функция создания аккаунта в системе на основе telegram id
74
new_user = AuthUser(telegram_id=self.telegram_id, username=self.telegram_username)
76
await conv.send_message(f'Создан новый аккаунт: login {new_user.username}, telegram_id {new_user.telegram_id}')
78
async def send_welcome_back(self):
79
await self.bot.send_message(self.telegram_id, 'С возвращением!')
81
async def create_or_merge_account(self):
83
Функция создания нового аккаунта на базе telegram id
84
или связи telegram id с существующим аккаунтом
87
async with self.bot.conversation(self.telegram_id) as conv:
88
buttons = [Button.inline('Да, связать аккаунты', b'merge'),
89
Button.inline('Нет, создать аккаунт', b'create')]
90
await conv.send_message('Аккаунт не найден. Ты уже регистрировался на сайте?', buttons=buttons)
93
press = await conv.wait_event(self._press_event(self.telegram_id))
94
if press.data == b'merge':
96
await self._merge_accounts(conv)
97
elif press.data == b'create':
99
await self._create_account(conv)
100
except Exception as e:
103
async def rate_questions(self, rating_process: SettingRatingToQuestionByUser):
105
def get_question_buttons() -> List[Button]:
107
Внутренняя функция для получения актуального состава inline-кнопок.
108
Их состав меняется в зависимости от наличия замечаний вообще и наличия замечаний текущего пользователя.
113
question_buttons = [Button.inline('👍', b'like'),
114
Button.inline('👎', b'dislike'),
115
Button.inline('🔚', b'cancel')]
118
remarks = rating_process.get_remarks_for_current_question()
120
question_buttons.append(Button.inline(f'👀 {len(remarks)}', b'remarks'), )
123
able_to_add_remark = rating_process.ability_to_remark_question()
124
if able_to_add_remark:
125
question_buttons.append(Button.inline('✏️', b'add_remark'))
127
return question_buttons
129
while rating_process.current_question:
132
question = rating_process.current_question.question
133
answer = rating_process.current_question.answer.answer
134
answer_type = rating_process.current_question.answer.subtype.type.name
135
answer_subtype = rating_process.current_question.answer.subtype.name
138
question_description_string = f'Вопрос: {question}\nОтвет: {answer}\nТип ответа: {answer_type}\nПодтип ответа: {answer_subtype}'
140
async with self.bot.conversation(self.telegram_id) as conv:
141
await conv.send_message(question_description_string, buttons=get_question_buttons())
143
press = await conv.wait_event(self._press_event(self.telegram_id))
144
if press.data == b'like':
146
rating_process.rate_current_question()
147
rating_process.get_next_question()
149
elif press.data == b'dislike':
151
rating_process.rate_current_question(bad=True)
152
rating_process.get_next_question()
154
elif press.data == b'remarks':
156
for remark in rating_process.get_remarks_for_current_question():
157
remark_text = remark.text
158
remark_buttons = [Button.inline('👍', b'like_remark'),
159
Button.inline('👎', b'dislike_remark'),
160
Button.inline('🔚', b'cancel_remark')]
161
await conv.send_message(f'Замечание: {remark_text}', buttons=remark_buttons)
163
press = await conv.wait_event(self._press_event(self.telegram_id))
164
if press.data == b'like_remark':
166
rating_process.rate_remark(remark=remark)
167
await conv.send_message('Like замечания принят')
169
elif press.data == b'dislike_remark':
171
rating_process.rate_remark(remark=remark, bad=True)
172
await conv.send_message('Dislike замечания принят')
174
elif press.data == b'cancel_remark':
176
await conv.send_message(question_description_string, buttons=get_question_buttons())
181
await conv.send_message(question_description_string, buttons=get_question_buttons())
183
elif press.data == b'add_remark':
185
remark_text = await self._get_answer_from_conv(conv=conv, question='Введи текст замечания')
187
rating_process.add_remark_to_current_question(text=remark_text)
189
elif press.data == b'cancel':
191
await conv.send_message('Оценка вопросов завершена')