Skip to content

Commit ee783be

Browse files
committed
feat: scanner statuses, iterative scanning, generalized routers tools
Closes #46
1 parent e8746d9 commit ee783be

21 files changed

Lines changed: 401 additions & 370 deletions

src/bot/api.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from src.config import settings
77
from src.config_schema import Printer, Scanner
88
from src.modules.printing.entity_models import JobAttributes, PreparePrintingResponse, PrinterStatus, PrintingOptions
9-
from src.modules.scanning.entity_models import ScanningOptions, ScanningResult
9+
from src.modules.scanning.entity_models import ScannerStatus, ScanningOptions, ScanningResult
1010

1111

1212
class InNoHasslePrintAPI:
@@ -101,9 +101,7 @@ async def get_printers_status_list(self, telegram_id: int) -> list[PrinterStatus
101101
adapter = TypeAdapter(list[PrinterStatus])
102102
return adapter.validate_python(response.json())
103103

104-
async def get_printer_status(self, telegram_id: int, printer_cups_name: str | None = None) -> PrinterStatus | None:
105-
if printer_cups_name is None:
106-
return None
104+
async def get_printer_status(self, telegram_id: int, printer_cups_name: str) -> PrinterStatus:
107105
params = {"printer_cups_name": printer_cups_name}
108106
async with self._create_client(telegram_id) as client:
109107
response = await client.get("/print/get_printer_status", params=params)
@@ -126,6 +124,14 @@ async def get_scanner(self, telegram_id: int, scanner_name: str | None = None) -
126124
return scanner
127125
return None
128126

127+
async def get_scanner_status(self, telegram_id: int, scanner_name: str | None = None) -> ScannerStatus | None:
128+
if scanner_name is None:
129+
return None
130+
async with self._create_client(telegram_id) as client:
131+
response = await client.get("/scan/debug/get_scanner_status", params={"scanner_name": scanner_name})
132+
response.raise_for_status()
133+
return ScannerStatus.model_validate(response.json())
134+
129135
async def start_manual_scan(self, telegram_id: int, scanner: Scanner, scanning_options: ScanningOptions) -> str:
130136
params = {"scanner_name": scanner.name}
131137
data = {"scanning_options": scanning_options.model_dump(by_alias=True)}

src/bot/routers/printing/print_settings/copies_setup.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from src.bot.api import api_client
99
from src.bot.routers.printing.printing_states import PrintWork
10-
from src.bot.routers.printing.printing_tools import MenuCallback, discard_job_settings_message, format_draft_message
10+
from src.bot.routers.printing.printing_tools import MenuCallback, discard_job_settings_message, format_configure_message
1111

1212
router = Router(name="copies_setup")
1313

@@ -57,8 +57,8 @@ async def handle_copies_action(
5757
if callback_data.action == "reset":
5858
data = await state.update_data(copies="1")
5959
assert "confirmation_message_id" in data
60-
printer = await api_client.get_printer(callback.message.chat.id, data.get("printer"))
61-
caption, markup = format_draft_message(data, printer)
60+
printer_status = await api_client.get_printer_status(callback.message.chat.id, data.get("printer"))
61+
caption, markup = format_configure_message(data, printer_status)
6262
await bot.edit_message_caption(
6363
caption=caption,
6464
chat_id=callback.message.chat.id,
@@ -87,8 +87,8 @@ async def apply_settings_copies(message: Message, state: FSMContext, bot: Bot):
8787
copies = str(max(0, min(50, int(message.text))))
8888
data = await state.update_data(copies=copies)
8989
assert "confirmation_message_id" in data
90-
printer = await api_client.get_printer(message.chat.id, data.get("printer"))
91-
caption, markup = format_draft_message(data, printer)
90+
printer_status = await api_client.get_printer_status(message.chat.id, data.get("printer"))
91+
caption, markup = format_configure_message(data, printer_status)
9292
await state.set_state(PrintWork.settings_menu)
9393
await bot.edit_message_caption(
9494
caption=caption,

src/bot/routers/printing/print_settings/layout_setup.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
from src.bot.api import api_client
1414
from src.bot.routers.printing.printing_states import PrintWork
15-
from src.bot.routers.printing.printing_tools import MenuCallback, discard_job_settings_message, format_draft_message
15+
from src.bot.routers.printing.printing_tools import MenuCallback, discard_job_settings_message, format_configure_message
1616

1717
router = Router(name="layout_setup")
1818

@@ -58,8 +58,8 @@ async def apply_settings_layout(callback: CallbackQuery, callback_data: LayoutCa
5858
data = await state.update_data(number_up=callback_data.number_up)
5959
await discard_job_settings_message(data, callback.message, state, bot)
6060
assert "confirmation_message_id" in data
61-
printer = await api_client.get_printer(callback.message.chat.id, data.get("printer"))
62-
caption, markup = format_draft_message(data, printer)
61+
printer_status = await api_client.get_printer_status(callback.message.chat.id, data.get("printer"))
62+
caption, markup = format_configure_message(data, printer_status)
6363
await state.set_state(PrintWork.settings_menu)
6464
await bot.edit_message_caption(
6565
caption=caption,

src/bot/routers/printing/print_settings/pages_setup.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
from src.bot.api import api_client
1010
from src.bot.routers.printing.printing_states import PrintWork
11-
from src.bot.routers.printing.printing_tools import MenuCallback, discard_job_settings_message, format_draft_message
11+
from src.bot.routers.printing.printing_tools import MenuCallback, discard_job_settings_message, format_configure_message
1212

1313
router = Router(name="pages_setup")
1414

@@ -100,8 +100,8 @@ async def handle_pages_action(callback: CallbackQuery, callback_data: PagesActio
100100
if callback_data.action == "reset":
101101
data = await state.update_data(page_ranges=None)
102102
assert "confirmation_message_id" in data
103-
printer = await api_client.get_printer(callback.message.chat.id, data.get("printer"))
104-
caption, markup = format_draft_message(data, printer)
103+
printer_status = await api_client.get_printer_status(callback.message.chat.id, data.get("printer"))
104+
caption, markup = format_configure_message(data, printer_status)
105105
await bot.edit_message_caption(
106106
caption=caption,
107107
chat_id=callback.message.chat.id,
@@ -144,8 +144,8 @@ async def change_settings_pages(message: Message, state: FSMContext, bot: Bot):
144144
await discard_job_settings_message(data, message, state, bot)
145145
data = await state.update_data(data)
146146
assert "confirmation_message_id" in data
147-
printer = await api_client.get_printer(message.chat.id, data.get("printer"))
148-
caption, markup = format_draft_message(data, printer)
147+
printer_status = await api_client.get_printer_status(message.chat.id, data.get("printer"))
148+
caption, markup = format_configure_message(data, printer_status)
149149
await state.set_state(PrintWork.settings_menu)
150150
await bot.edit_message_caption(
151151
caption=caption,
Lines changed: 37 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
import asyncio
2-
from collections.abc import Sequence
32
from typing import assert_never
43

54
from aiogram import Bot, F, Router, html
65
from aiogram.fsm.context import FSMContext
7-
from aiogram.fsm.state import State
86
from aiogram.types import (
97
CallbackQuery,
108
InlineKeyboardButton,
@@ -19,9 +17,10 @@
1917
MenuCallback,
2018
PrinterCallback,
2119
discard_job_settings_message,
22-
format_draft_message,
20+
format_configure_message,
2321
format_printer_status,
2422
)
23+
from src.bot.routers.tools import ensure_same_structural_message
2524
from src.config_schema import Printer
2625
from src.modules.printing.entity_models import PrinterStatus
2726

@@ -39,17 +38,46 @@ async def start_printer_setup(callback_or_message: CallbackQuery | Message, stat
3938

4039
asyncio.create_task(
4140
update_printer_statuses(
42-
message.chat.id,
43-
message.chat.id,
44-
msg.message_id,
41+
msg,
4542
printers,
4643
state,
47-
bot,
48-
checkable_state=PrintWork.setup_printer,
4944
)
5045
)
5146

5247

48+
async def update_printer_statuses(job_settings_message: Message, printers: list[Printer], state: FSMContext):
49+
printers_or_statuses = dict()
50+
for elem in printers:
51+
printers_or_statuses[elem.cups_name] = elem
52+
tasks = [api_client.get_printer_status(job_settings_message.chat.id, printer.cups_name) for printer in printers]
53+
for task in asyncio.as_completed(tasks):
54+
await ensure_same_structural_message(job_settings_message, "job_settings_message_id", state)
55+
status = await task
56+
printers_or_statuses[status.printer.cups_name] = status
57+
new_reply_markup = printers_keyboard(list(printers_or_statuses.values()))
58+
await ensure_same_structural_message(job_settings_message, "job_settings_message_id", state)
59+
await job_settings_message.edit_reply_markup(reply_markup=new_reply_markup)
60+
61+
62+
def printers_keyboard(statuses_and_printers: list[PrinterStatus | Printer]) -> InlineKeyboardMarkup:
63+
keyboard = InlineKeyboardBuilder()
64+
for status_or_printer in statuses_and_printers:
65+
if isinstance(status_or_printer, PrinterStatus):
66+
button = InlineKeyboardButton(
67+
text=format_printer_status(status_or_printer),
68+
callback_data=PrinterCallback(cups_name=status_or_printer.printer.cups_name).pack(),
69+
)
70+
elif isinstance(status_or_printer, Printer):
71+
button = InlineKeyboardButton(
72+
text=status_or_printer.display_name,
73+
callback_data=PrinterCallback(cups_name=status_or_printer.cups_name).pack(),
74+
)
75+
else:
76+
assert_never(status_or_printer)
77+
keyboard.row(button)
78+
return keyboard.as_markup()
79+
80+
5381
@router.callback_query(PrintWork.settings_menu, MenuCallback.filter(F.menu == "printer"))
5482
async def job_settings_printer(callback: CallbackQuery, state: FSMContext, bot: Bot):
5583
await callback.answer()
@@ -69,65 +97,11 @@ async def apply_settings_printer(callback: CallbackQuery, callback_data: Printer
6997
assert "printer" in data
7098
assert "confirmation_message_id" in data
7199
printer_status = await api_client.get_printer_status(callback.message.chat.id, data.get("printer"))
72-
caption, markup = format_draft_message(data, printer_status)
100+
caption, markup = format_configure_message(data, printer_status)
73101
await state.set_state(PrintWork.settings_menu)
74102
await bot.edit_message_caption(
75103
caption=caption,
76104
chat_id=callback.message.chat.id,
77105
message_id=data["confirmation_message_id"],
78106
reply_markup=markup,
79107
)
80-
81-
82-
def printers_keyboard(printers: Sequence[PrinterStatus | Printer]) -> InlineKeyboardMarkup:
83-
keyboard = InlineKeyboardBuilder()
84-
85-
for status_or_printer in printers:
86-
if isinstance(status_or_printer, PrinterStatus):
87-
printer = status_or_printer.printer
88-
show_text = format_printer_status(status_or_printer)
89-
elif isinstance(status_or_printer, Printer):
90-
printer = status_or_printer
91-
show_text = printer.display_name
92-
else:
93-
assert_never(status_or_printer)
94-
keyboard.row(
95-
InlineKeyboardButton(
96-
text=show_text,
97-
callback_data=PrinterCallback(cups_name=printer.cups_name).pack(),
98-
)
99-
)
100-
return keyboard.as_markup()
101-
102-
103-
async def update_printer_statuses(
104-
from_user_id: int,
105-
chat_id: int,
106-
message_id: int,
107-
printers: list,
108-
state: FSMContext,
109-
bot: Bot,
110-
checkable_state: State,
111-
):
112-
tasks = [
113-
api_client.get_printer_status(from_user_id, printer.cups_name)
114-
for printer in printers
115-
if isinstance(printer, Printer)
116-
]
117-
for t in asyncio.as_completed(tasks):
118-
if await state.get_state() != checkable_state:
119-
return
120-
result = await t
121-
if isinstance(result, PrinterStatus):
122-
for i, p in enumerate(printers):
123-
if isinstance(p, Printer) and p.cups_name == result.printer.cups_name:
124-
printers[i] = result # type: ignore
125-
126-
new_reply_markup = printers_keyboard(printers)
127-
if await state.get_state() != checkable_state:
128-
return
129-
await bot.edit_message_reply_markup(
130-
chat_id=chat_id,
131-
message_id=message_id,
132-
reply_markup=new_reply_markup,
133-
)

src/bot/routers/printing/print_settings/sides_setup.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
from src.bot.api import api_client
1414
from src.bot.routers.printing.printing_states import PrintWork
15-
from src.bot.routers.printing.printing_tools import MenuCallback, discard_job_settings_message, format_draft_message
15+
from src.bot.routers.printing.printing_tools import MenuCallback, discard_job_settings_message, format_configure_message
1616

1717
router = Router(name="sides_setup")
1818

@@ -52,8 +52,8 @@ async def apply_settings_sides(callback: CallbackQuery, callback_data: SidesCall
5252
data = await state.update_data(sides=callback_data.sides)
5353
await discard_job_settings_message(data, callback.message, state, bot)
5454
assert "confirmation_message_id" in data
55-
printer = await api_client.get_printer(callback.message.chat.id, data.get("printer"))
56-
caption, markup = format_draft_message(data, printer)
55+
printer_status = await api_client.get_printer_status(callback.message.chat.id, data.get("printer"))
56+
caption, markup = format_configure_message(data, printer_status)
5757
await state.set_state(PrintWork.settings_menu)
5858
await bot.edit_message_caption(
5959
caption=caption,

0 commit comments

Comments
 (0)