Send all Magnit price matches
This commit is contained in:
parent
75a63bb6fc
commit
43503dc778
1 changed files with 45 additions and 20 deletions
59
main.py
59
main.py
|
|
@ -416,15 +416,16 @@ def _normalize_magnit_product(entry) -> dict[str, str]:
|
||||||
|
|
||||||
raise ValueError("MAGNIT_PRODUCTS должен содержать строки или словари.")
|
raise ValueError("MAGNIT_PRODUCTS должен содержать строки или словари.")
|
||||||
|
|
||||||
def _pick_magnit_item(data: dict):
|
def _pick_magnit_items(data: dict) -> list[dict]:
|
||||||
|
items = data.get("items")
|
||||||
|
if isinstance(items, list):
|
||||||
|
return [item for item in items if isinstance(item, dict)]
|
||||||
|
|
||||||
best_match = data.get("best_match")
|
best_match = data.get("best_match")
|
||||||
if isinstance(best_match, dict):
|
if isinstance(best_match, dict):
|
||||||
return best_match
|
return [best_match]
|
||||||
|
|
||||||
items = data.get("items")
|
return []
|
||||||
if isinstance(items, list) and items:
|
|
||||||
return items[0]
|
|
||||||
return None
|
|
||||||
|
|
||||||
def _format_money(value) -> str | None:
|
def _format_money(value) -> str | None:
|
||||||
if value is None:
|
if value is None:
|
||||||
|
|
@ -444,6 +445,26 @@ def _format_magnit_quantity(value) -> str:
|
||||||
return "нет данных"
|
return "нет данных"
|
||||||
return f"{value} шт."
|
return f"{value} шт."
|
||||||
|
|
||||||
|
async def _send_lines_in_chunks(message: Message, lines: list[str], limit: int = 4000) -> None:
|
||||||
|
if not lines:
|
||||||
|
await message.answer("Товары не найдены.")
|
||||||
|
return
|
||||||
|
|
||||||
|
chunk: list[str] = []
|
||||||
|
chunk_len = 0
|
||||||
|
for line in lines:
|
||||||
|
extra_len = len(line) + (1 if chunk else 0)
|
||||||
|
if chunk and chunk_len + extra_len > limit:
|
||||||
|
await message.answer("\n".join(chunk))
|
||||||
|
chunk = [line]
|
||||||
|
chunk_len = len(line)
|
||||||
|
continue
|
||||||
|
chunk.append(line)
|
||||||
|
chunk_len += extra_len
|
||||||
|
|
||||||
|
if chunk:
|
||||||
|
await message.answer("\n".join(chunk))
|
||||||
|
|
||||||
# --- Игровая логика (/penis) ---
|
# --- Игровая логика (/penis) ---
|
||||||
|
|
||||||
def play_penis(user_id: int, user_name: str | None = None, now: datetime | None = None) -> tuple[bool, str]:
|
def play_penis(user_id: int, user_name: str | None = None, now: datetime | None = None) -> tuple[bool, str]:
|
||||||
|
|
@ -608,7 +629,7 @@ async def handle_prices_cmd(message: Message):
|
||||||
await message.answer("Список MAGNIT_PRODUCTS пуст. Добавь товары в config.py.")
|
await message.answer("Список MAGNIT_PRODUCTS пуст. Добавь товары в config.py.")
|
||||||
return
|
return
|
||||||
|
|
||||||
async def fetch_product(product_cfg: dict[str, str]) -> str:
|
async def fetch_product(product_cfg: dict[str, str]) -> list[str]:
|
||||||
def fetch():
|
def fetch():
|
||||||
return requests.get(
|
return requests.get(
|
||||||
f"{config.MAGNIT_API_BASE_URL.rstrip('/')}/price",
|
f"{config.MAGNIT_API_BASE_URL.rstrip('/')}/price",
|
||||||
|
|
@ -624,29 +645,33 @@ async def handle_prices_cmd(message: Message):
|
||||||
resp = await asyncio.to_thread(fetch)
|
resp = await asyncio.to_thread(fetch)
|
||||||
if resp.status_code != 200:
|
if resp.status_code != 200:
|
||||||
logger.warning("Magnit API returned %s for %s", resp.status_code, product_cfg["query"])
|
logger.warning("Magnit API returned %s for %s", resp.status_code, product_cfg["query"])
|
||||||
return f"{label}, ошибка API ({resp.status_code}), -"
|
return [f"{label}, ошибка API ({resp.status_code}), -"]
|
||||||
|
|
||||||
data = resp.json()
|
data = resp.json()
|
||||||
if not isinstance(data, dict):
|
if not isinstance(data, dict):
|
||||||
return f"{label}, битый ответ API, -"
|
return [f"{label}, битый ответ API, -"]
|
||||||
|
|
||||||
item = _pick_magnit_item(data)
|
items = _pick_magnit_items(data)
|
||||||
if not isinstance(item, dict):
|
if not items:
|
||||||
return f"{label}, товар не найден, -"
|
return [f"{label}, товар не найден, -"]
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
for item in items:
|
||||||
name = str(item.get("name") or label).strip() or label
|
name = str(item.get("name") or label).strip() or label
|
||||||
price = _format_magnit_price(item)
|
price = _format_magnit_price(item)
|
||||||
quantity = _format_magnit_quantity(item.get("quantity"))
|
quantity = _format_magnit_quantity(item.get("quantity"))
|
||||||
return f"{name}, {price}, {quantity}"
|
lines.append(f"{name}, {price}, {quantity}")
|
||||||
|
return lines
|
||||||
except requests.RequestException:
|
except requests.RequestException:
|
||||||
logger.exception("Failed to fetch Magnit product: %s", product_cfg["query"])
|
logger.exception("Failed to fetch Magnit product: %s", product_cfg["query"])
|
||||||
return f"{label}, ошибка запроса, -"
|
return [f"{label}, ошибка запроса, -"]
|
||||||
except ValueError:
|
except ValueError:
|
||||||
logger.exception("Magnit API returned invalid JSON for %s", product_cfg["query"])
|
logger.exception("Magnit API returned invalid JSON for %s", product_cfg["query"])
|
||||||
return f"{label}, битый JSON, -"
|
return [f"{label}, битый JSON, -"]
|
||||||
|
|
||||||
lines = await asyncio.gather(*(fetch_product(product) for product in products))
|
result_groups = await asyncio.gather(*(fetch_product(product) for product in products))
|
||||||
await message.answer("\n".join(lines)[:4000])
|
lines = [line for group in result_groups for line in group]
|
||||||
|
await _send_lines_in_chunks(message, lines)
|
||||||
|
|
||||||
async def handle_fetch_cmd(message: Message):
|
async def handle_fetch_cmd(message: Message):
|
||||||
await handle_prices_cmd(message)
|
await handle_prices_cmd(message)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue