Skip to content

Commit f992a26

Browse files
committed
Release v1.8.1 — answer/reply/answer_file/answer_voice return bound Message
- message.answer(), reply(), answer_thread(), answer_file(), answer_voice() now return a bound Message instead of Any, enabling sent.delete(), sent.edit_text() chaining without manually tracking chat_id/msg_id - Added /vanish example to echo_bot.py demonstrating the pattern - PRESENTATION.md added to .gitignore
1 parent f5542a0 commit f992a26

6 files changed

Lines changed: 59 additions & 12 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,4 @@ bench_report*.txt
2828
*.jsonl
2929
.claude/
3030
docs/*
31+
PRESENTATION.md

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/),
66
and this project adheres to [Semantic Versioning](https://semver.org/).
77

8+
## [1.8.1] - 2026-02-20
9+
10+
### Added
11+
- `message.answer()`, `reply()`, `answer_thread()`, `answer_file()`, `answer_voice()` now return a bound `Message` instead of `Any` — enables chaining `.delete()`, `.edit_text()` on the sent message directly
12+
- `examples/echo_bot.py`: added `/vanish` command demonstrating `sent = await message.answer(...); await sent.delete()`
13+
14+
### Changed
15+
- `PRESENTATION.md` added to `.gitignore` — kept out of public repository
16+
817
## [1.8.0] - 2026-02-18
918

1019
### Fixed

examples/echo_bot.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ async def cmd_help(message: Message) -> None:
3131
)
3232

3333

34+
@router.message(Command("vanish"))
35+
async def cmd_vanish(message: Message) -> None:
36+
sent = await message.answer("I will vanish in 5 seconds...")
37+
await asyncio.sleep(5)
38+
await sent.delete()
39+
40+
3441
@router.message(F.text)
3542
async def echo(message: Message) -> None:
3643
assert message.text is not None # guaranteed by F.text filter

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "vkworkspace"
7-
version = "1.8.0"
7+
version = "1.8.1"
88
description = "Fully async framework for building VK Teams (VK Workspace) bots, inspired by aiogram 3"
99
readme = "README.md"
1010
license = { text = "MIT" }

vkworkspace/__meta__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
__version__ = "1.8.0"
1+
__version__ = "1.8.1"
22
__api_version__ = "v1"

vkworkspace/types/message.py

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -224,11 +224,14 @@ async def answer(
224224
parse_mode: ParseMode | str | None = _UNSET,
225225
inline_keyboard_markup: Any = None,
226226
**kwargs: Any,
227-
) -> Any:
227+
) -> Message:
228228
"""Send a text message to the same chat.
229229
230230
If this message is from a thread, the reply stays in the same thread.
231231
232+
Returns a bound :class:`Message` — you can call ``.delete()``,
233+
``.edit_text()``, etc. on it directly.
234+
232235
Args:
233236
text: Message text.
234237
parse_mode: ``"HTML"`` / ``"MarkdownV2"`` / ``None``.
@@ -239,6 +242,11 @@ async def answer(
239242
240243
await message.answer("Got it!")
241244
await message.answer("*Bold*", parse_mode="MarkdownV2")
245+
246+
# Delete the sent message after a delay:
247+
sent = await message.answer("I will vanish in 5 seconds")
248+
await asyncio.sleep(5)
249+
await sent.delete()
242250
"""
243251
if parse_mode is not _UNSET:
244252
kwargs["parse_mode"] = parse_mode
@@ -247,22 +255,26 @@ async def answer(
247255
# If this message is from a thread, reply stays in the same thread
248256
if self.parent_topic is not None and "parent_topic" not in kwargs:
249257
kwargs["parent_topic"] = self.parent_topic
250-
return await self.bot.send_text(
258+
resp = await self.bot.send_text(
251259
chat_id=self.chat.chat_id,
252260
text=text,
253261
**kwargs,
254262
)
263+
sent = Message(msg_id=resp.msg_id or "", chat=self.chat, text=text)
264+
sent.set_bot(self.bot)
265+
return sent
255266

256267
async def answer_thread(
257268
self,
258269
text: str,
259270
parse_mode: ParseMode | str | None = _UNSET,
260271
inline_keyboard_markup: Any = None,
261272
**kwargs: Any,
262-
) -> Any:
273+
) -> Message:
263274
"""Create a thread under this message and post *text* into it.
264275
265276
If this message already lives in a thread, posts there instead.
277+
Returns a bound :class:`Message` — supports ``.delete()``, ``.edit_text()``.
266278
"""
267279
if parse_mode is not _UNSET:
268280
kwargs["parse_mode"] = parse_mode
@@ -276,22 +288,27 @@ async def answer_thread(
276288
messageId=int(self.msg_id) if self.msg_id.isdigit() else 0,
277289
type="thread",
278290
)
279-
return await self.bot.send_text(
291+
resp = await self.bot.send_text(
280292
chat_id=self.chat.chat_id,
281293
text=text,
282294
parent_topic=pt,
283295
**kwargs,
284296
)
297+
sent = Message(msg_id=resp.msg_id or "", chat=self.chat, text=text)
298+
sent.set_bot(self.bot)
299+
return sent
285300

286301
async def reply(
287302
self,
288303
text: str,
289304
parse_mode: ParseMode | str | None = _UNSET,
290305
inline_keyboard_markup: Any = None,
291306
**kwargs: Any,
292-
) -> Any:
307+
) -> Message:
293308
"""Reply with a quote — shows the original message above the response.
294309
310+
Returns a bound :class:`Message` — supports ``.delete()``, ``.edit_text()``.
311+
295312
Args:
296313
text: Reply text.
297314
parse_mode: ``"HTML"`` / ``"MarkdownV2"`` / ``None``.
@@ -305,12 +322,15 @@ async def reply(
305322
kwargs["parse_mode"] = parse_mode
306323
if inline_keyboard_markup is not None:
307324
kwargs["inline_keyboard_markup"] = inline_keyboard_markup
308-
return await self.bot.send_text(
325+
resp = await self.bot.send_text(
309326
chat_id=self.chat.chat_id,
310327
text=text,
311328
reply_msg_id=self.msg_id,
312329
**kwargs,
313330
)
331+
sent = Message(msg_id=resp.msg_id or "", chat=self.chat, text=text)
332+
sent.set_bot(self.bot)
333+
return sent
314334

315335
async def delete(self) -> Any:
316336
"""Delete this message from the chat."""
@@ -424,9 +444,11 @@ async def answer_file(
424444
parse_mode: ParseMode | str | None = _UNSET,
425445
inline_keyboard_markup: Any = None,
426446
**kwargs: Any,
427-
) -> Any:
447+
) -> Message:
428448
"""Send a file/image to the same chat.
429449
450+
Returns a bound :class:`Message` — supports ``.delete()``.
451+
430452
Args:
431453
file_id: ID of a previously uploaded file (no re-upload).
432454
file: ``InputFile`` or open ``BinaryIO`` to upload.
@@ -440,23 +462,28 @@ async def answer_file(
440462
kwargs["parse_mode"] = parse_mode
441463
if inline_keyboard_markup is not None:
442464
kwargs["inline_keyboard_markup"] = inline_keyboard_markup
443-
return await self.bot.send_file(
465+
resp = await self.bot.send_file(
444466
chat_id=self.chat.chat_id,
445467
file_id=file_id,
446468
file=file,
447469
caption=caption,
448470
**kwargs,
449471
)
472+
sent = Message(msg_id=resp.msg_id or "", chat=self.chat, text=caption)
473+
sent.set_bot(self.bot)
474+
return sent
450475

451476
async def answer_voice(
452477
self,
453478
file_id: str | None = None,
454479
file: Any = None,
455480
inline_keyboard_markup: Any = None,
456481
**kwargs: Any,
457-
) -> Any:
482+
) -> Message:
458483
"""Send a voice message to the same chat.
459484
485+
Returns a bound :class:`Message` — supports ``.delete()``.
486+
460487
Recommended format: OGG/Opus. Convert with
461488
``vkworkspace.utils.voice.convert_to_ogg_opus()`` if needed.
462489
@@ -471,9 +498,12 @@ async def answer_voice(
471498
"""
472499
if inline_keyboard_markup is not None:
473500
kwargs["inline_keyboard_markup"] = inline_keyboard_markup
474-
return await self.bot.send_voice(
501+
resp = await self.bot.send_voice(
475502
chat_id=self.chat.chat_id,
476503
file_id=file_id,
477504
file=file,
478505
**kwargs,
479506
)
507+
sent = Message(msg_id=resp.msg_id or "", chat=self.chat)
508+
sent.set_bot(self.bot)
509+
return sent

0 commit comments

Comments
 (0)