5 Commits

Author SHA1 Message Date
goyban f5b16fab84 Bump VERSION to 1.0.2 for the list-truncation fix
VERSION had been left at 1.0.0 while the registry already carried 1.0.1, so
push.sh (which defaults to the VERSION file) would have rebuilt an existing
tag. This realigns the file with what is actually published.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 13:02:19 +00:00
goyban 5305b654c7 Merge pull request 'Fix list truncation' (#2) from codex/fix-list-truncation into main
Reviewed-on: #2
2026-09-01 14:57:45 +02:00
goyban 196edf1120 Merge branch 'main' into codex/fix-list-truncation 2026-09-01 14:57:30 +02:00
goyban faf4fee274 Merge pull request 'Add menu command' (#1) from snail/add-menu-command into main
Reviewed-on: #1
2026-07-27 12:02:19 +02:00
snail 2f694908bf Fix list truncation 2026-07-26 20:06:40 +02:00
3 changed files with 65 additions and 13 deletions
+1 -1
View File
@@ -1 +1 @@
1.0.0 1.0.2
+41 -10
View File
@@ -229,21 +229,52 @@ async def on_media_during_keywords(msg: Message):
# ── /list ──────────────────────────────────────────────────────────────────── # ── /list ────────────────────────────────────────────────────────────────────
LIST_PAGE_SIZE = 30
async def list_page(page: int) -> tuple[str, InlineKeyboardMarkup | None]:
total = await db.count_media()
if total == 0:
return "No memes saved yet.", None
total_pages = (total + LIST_PAGE_SIZE - 1) // LIST_PAGE_SIZE
page = max(0, min(page, total_pages - 1))
items = await db.list_media(page, LIST_PAGE_SIZE)
lines = [f"<code>{item['id']}</code> [{item['media_type']}] — {item['keywords']}" for item in items]
text = f"Page {page + 1} of {total_pages}\n" + "\n".join(lines)
buttons = []
if page > 0:
buttons.append(InlineKeyboardButton(text="‹ Previous", callback_data=f"list:{page - 1}"))
if page < total_pages - 1:
buttons.append(InlineKeyboardButton(text="Next ›", callback_data=f"list:{page + 1}"))
keyboard = InlineKeyboardMarkup(inline_keyboard=[buttons]) if buttons else None
return text, keyboard
@dp.message(Command("list")) @dp.message(Command("list"))
async def cmd_list(msg: Message): async def cmd_list(msg: Message):
if not is_allowed(msg.from_user.id): if not is_allowed(msg.from_user.id):
return return
items = await db.list_media() text, keyboard = await list_page(0)
if not items: await msg.answer(text, parse_mode="HTML", reply_markup=keyboard)
await msg.answer("No memes saved yet.")
@dp.callback_query(F.data.startswith("list:"))
async def on_list_page(callback: CallbackQuery):
if not is_allowed(callback.from_user.id):
await callback.answer("Not allowed.", show_alert=True)
return return
lines = []
for item in items[:30]: try:
lines.append(f"<code>{item['id']}</code> [{item['media_type']}] — {item['keywords']}") page = int(callback.data.split(":", 1)[1])
text = "\n".join(lines) except ValueError:
if len(items) > 30: await callback.answer("Invalid page.", show_alert=True)
text += f"\n…and {len(items) - 30} more." return
await msg.answer(text, parse_mode="HTML")
text, keyboard = await list_page(page)
await callback.message.edit_text(text, parse_mode="HTML", reply_markup=keyboard)
await callback.answer()
# ── /delete ────────────────────────────────────────────────────────────────── # ── /delete ──────────────────────────────────────────────────────────────────
+23 -2
View File
@@ -59,8 +59,29 @@ async def search_media(query: str) -> list[dict]:
return [dict(r) for r in rows] return [dict(r) for r in rows]
async def list_media() -> list[dict]: async def list_media(page: int, page_size: int) -> list[dict]:
return await search_media("") """Return one page of saved media, newest first."""
offset = page * page_size
async with aiosqlite.connect(DB_PATH) as db:
db.row_factory = aiosqlite.Row
cursor = await db.execute(
"""
SELECT id, file_id, file_unique_id, media_type, keywords
FROM media
ORDER BY added_at DESC, id DESC
LIMIT ? OFFSET ?
""",
(page_size, offset),
)
rows = await cursor.fetchall()
return [dict(r) for r in rows]
async def count_media() -> int:
async with aiosqlite.connect(DB_PATH) as db:
cursor = await db.execute("SELECT COUNT(*) FROM media")
row = await cursor.fetchone()
return row[0]
async def get_media_by_id(media_id: int) -> dict | None: async def get_media_by_id(media_id: int) -> dict | None: