Skip to content

Commit 38e396c

Browse files
committed
Update logic for Max messenger
1 parent c440378 commit 38e396c

5 files changed

Lines changed: 48 additions & 39 deletions

File tree

README.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ ClearTranscriptBot
3939
│ │ ├── history.py
4040
│ │ ├── price.py
4141
│ │ ├── rate_transcription.py
42+
│ │ ├── send_as_text.py
4243
│ │ ├── summarize.py
4344
│ │ ├── text.py
4445
│ │ └── topup.py
@@ -51,6 +52,7 @@ ClearTranscriptBot
5152
│ ├── history.py
5253
│ ├── price.py
5354
│ ├── rate.py
55+
│ ├── send_as_text.py
5456
│ ├── summarize.py
5557
│ ├── text.py
5658
│ └── topup.py
@@ -187,7 +189,7 @@ CREATE TABLE IF NOT EXISTS users (
187189
CREATE TABLE IF NOT EXISTS transcription_history (
188190
id BIGINT PRIMARY KEY AUTO_INCREMENT,
189191
user_id BIGINT NOT NULL,
190-
platform VARCHAR(16) NOT NULL,
192+
user_platform VARCHAR(16) NOT NULL,
191193
status VARCHAR(32) NOT NULL,
192194
audio_s3_path TEXT NOT NULL,
193195
result_json TEXT,
@@ -204,11 +206,10 @@ CREATE TABLE IF NOT EXISTS transcription_history (
204206
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
205207
started_at TIMESTAMP,
206208
finished_at TIMESTAMP,
207-
FOREIGN KEY (user_id, user_platform) REFERENCES users(user_id, user_platform)
209+
FOREIGN KEY (user_id, user_platform) REFERENCES users(user_id, user_platform),
210+
INDEX idx_th_user (user_id, user_platform)
208211
);
209212

210-
CREATE INDEX idx_th_user ON transcription_history(user_id, user_platform);
211-
212213
-- Payments processed via Tinkoff acquiring
213214
CREATE TABLE IF NOT EXISTS payments (
214215
id INTEGER PRIMARY KEY AUTO_INCREMENT,
@@ -224,29 +225,28 @@ CREATE TABLE IF NOT EXISTS payments (
224225
tinkoff_response TEXT NOT NULL,
225226
next_check_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
226227
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
227-
FOREIGN KEY (user_id, user_platform) REFERENCES users(user_id, user_platform)
228+
FOREIGN KEY (user_id, user_platform) REFERENCES users(user_id, user_platform),
229+
INDEX idx_payments_user (user_id, user_platform)
228230
);
229231

230-
CREATE INDEX idx_payments_user ON payments(user_id, user_platform);
231-
232232
-- AI summarization requests for completed transcriptions
233233
CREATE TABLE IF NOT EXISTS summarizations (
234234
id INTEGER PRIMARY KEY AUTO_INCREMENT,
235235
transcription_id INTEGER NOT NULL REFERENCES transcription_history(id),
236236
user_id BIGINT NOT NULL,
237-
platform VARCHAR(16) NOT NULL,
237+
user_platform VARCHAR(16) NOT NULL,
238238
status VARCHAR(32) NOT NULL,
239239
operation_id VARCHAR(64),
240240
result_text TEXT,
241241
llm_model VARCHAR(64),
242242
message_id VARCHAR(64),
243243
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
244244
finished_at TIMESTAMP,
245-
FOREIGN KEY (user_id, user_platform) REFERENCES users(user_id, user_platform)
245+
FOREIGN KEY (user_id, user_platform) REFERENCES users(user_id, user_platform),
246+
INDEX idx_summarizations_transcription_id (transcription_id),
247+
INDEX idx_sum_user (user_id, user_platform)
246248
);
247249

248-
CREATE INDEX idx_summarizations_transcription_id ON summarizations(transcription_id);
249-
250250
-- Trigger to maintain users.total_topped_up automatically.
251251
-- Fires after each payment row update; adds amount only when status
252252
-- transitions to CONFIRMED to avoid double-counting.

handlers/max/rate.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@
1414

1515
@sentry_bind_user_max
1616
async def handle_max_rate(callback: aiomax.Callback, bot: aiomax.Bot) -> None:
17-
await callback.answer(notification="Спасибо за оценку!")
18-
1917
try:
2018
_, transcription_id_str, rating_str = callback.payload.split(":")
2119
transcription_id = int(transcription_id_str)
@@ -31,13 +29,14 @@ async def handle_max_rate(callback: aiomax.Callback, bot: aiomax.Bot) -> None:
3129

3230
update_transcription(transcription_id, rating=rating)
3331

34-
message_id = callback.message.body.message_id
32+
file_attachments = [
33+
att for att in (callback.message.body.attachments or [])
34+
if att.type == "file"
35+
]
3536
keyboard = make_rating_keyboard(transcription_id, selected=rating)
36-
await bot.edit_message(message_id, RATING_PROMPT, keyboard=keyboard)
37-
38-
39-
@sentry_bind_user_max
40-
async def handle_max_skip_rating(callback: aiomax.Callback, bot: aiomax.Bot) -> None:
41-
await callback.answer(notification="")
42-
message_id = callback.message.body.message_id
43-
await bot.edit_message(message_id, RATING_PROMPT, attachments=[])
37+
await callback.answer(
38+
notification="Спасибо за оценку!",
39+
text=RATING_PROMPT,
40+
keyboard=keyboard,
41+
attachments=file_attachments if file_attachments else None,
42+
)

handlers/telegram/rate_transcription.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,3 @@ async def handle_rate_transcription(update: Update, context: ContextTypes.DEFAUL
4949
caption=RATING_PROMPT,
5050
reply_markup=make_rating_keyboard(transcription_id, selected=rating),
5151
)
52-
53-
54-
@sentry_bind_user
55-
async def handle_skip_rating(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
56-
query = update.callback_query
57-
await query.answer()
58-
59-
await query.edit_message_reply_markup(reply_markup=None)

main.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
from handlers.telegram.price import handle_price
2626
from handlers.telegram.text import handle_text
2727
from handlers.telegram.topup import handle_topup, handle_topup_callback, handle_check_payment, handle_cancel_payment
28-
from handlers.telegram.rate_transcription import handle_rate_transcription, handle_skip_rating
28+
from handlers.telegram.rate_transcription import handle_rate_transcription
2929
from handlers.telegram.summarize import handle_summarize
3030
from handlers.telegram.send_as_text import handle_send_as_text
3131

@@ -35,7 +35,7 @@
3535
from handlers.max.file import handle_max_file
3636
from handlers.max.history import handle_max_history
3737
from handlers.max.price import handle_max_price
38-
from handlers.max.rate import handle_max_rate, handle_max_skip_rating
38+
from handlers.max.rate import handle_max_rate
3939
from handlers.max.summarize import handle_max_summarize
4040
from handlers.max.send_as_text import handle_max_send_as_text
4141
from handlers.max.text import handle_max_text
@@ -122,9 +122,6 @@ async def run_bots() -> None:
122122
application.add_handler(
123123
CallbackQueryHandler(handle_rate_transcription, pattern=r"^rate:\d+:[1-5]$")
124124
)
125-
application.add_handler(
126-
CallbackQueryHandler(handle_skip_rating, pattern=r"^rate_skip:\d+$")
127-
)
128125
application.add_handler(
129126
CallbackQueryHandler(handle_summarize, pattern=r"^summarize:\d+$")
130127
)
@@ -204,8 +201,6 @@ async def _on_max_callback(callback: aiomax.Callback) -> None:
204201
await handle_max_cancel_task(callback, max_bot)
205202
elif payload.startswith("rate:"):
206203
await handle_max_rate(callback, max_bot)
207-
elif payload.startswith("rate_skip:"):
208-
await handle_max_skip_rating(callback, max_bot)
209204
elif payload.startswith("summarize:"):
210205
await handle_max_summarize(callback, max_bot)
211206
elif payload.startswith("send_as_text:"):

utils/bot_sender.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,26 @@
44
from database.models import PLATFORM_TELEGRAM, PLATFORM_MAX
55

66

7+
class _MaxKeyboardAttachment:
8+
"""Wraps an aiomax KeyboardBuilder as an attachment-like object.
9+
10+
Workaround for an aiomax bug: send_message's AttachmentNotReady retry
11+
drops the keyboard= parameter, losing the inline keyboard. By encoding
12+
the keyboard as an element of attachments= it survives the retry.
13+
"""
14+
def __init__(self, keyboard):
15+
from aiomax.buttons import KeyboardBuilder
16+
if isinstance(keyboard, KeyboardBuilder):
17+
keyboard = keyboard.to_list()
18+
self._keyboard = keyboard
19+
20+
def as_dict(self):
21+
return {
22+
"type": "inline_keyboard",
23+
"payload": {"buttons": self._keyboard},
24+
}
25+
26+
727
class BotSender:
828
"""Routes message delivery to the correct bot based on platform."""
929

@@ -103,11 +123,14 @@ async def send_document(
103123
data = file_obj.read() if hasattr(file_obj, "read") else file_obj
104124
try:
105125
file_attachment = await self._max.upload_file(data, filename)
126+
if max_keyboard is not None:
127+
attachments = [_MaxKeyboardAttachment(max_keyboard), file_attachment]
128+
else:
129+
attachments = [file_attachment]
106130
return await self._max.send_message(
107131
caption,
108132
user_id=int(chat_id),
109-
attachments=[file_attachment],
110-
keyboard=max_keyboard,
133+
attachments=attachments,
111134
)
112135
except Exception:
113136
logging.exception("Max send_document failed chat=%s", chat_id)

0 commit comments

Comments
 (0)