1
0
Fork 0
forked from zovos/bot_tg

Add Magnit prices command

This commit is contained in:
q 2026-03-09 11:48:20 +03:00
parent 682fc7422c
commit 75a63bb6fc
2 changed files with 117 additions and 55 deletions

View file

@ -21,6 +21,15 @@ PENIS_TOP_LIMIT = 10
# --- Казино --- # --- Казино ---
CASINO_MAX_BET = 1.0 CASINO_MAX_BET = 1.0
# --- Magnit API ---
MAGNIT_API_BASE_URL = os.getenv("MAGNIT_API_BASE_URL", "https://mirror.porno4free.ru/magnit")
MAGNIT_STORE_CODE = os.getenv("MAGNIT_STORE_CODE", "618224")
MAGNIT_REQUEST_TIMEOUT = int(os.getenv("MAGNIT_REQUEST_TIMEOUT", "15"))
# Можно указывать просто строку с названием или словарь с query/label/store_code.
MAGNIT_PRODUCTS = [
"RedBull",
]
# --- Конфигурация макетов --- # --- Конфигурация макетов ---
TEMPLATES = { TEMPLATES = {
"1": { "1": {
@ -103,6 +112,6 @@ def get_hint_text(templates_str: str) -> str:
"• /penis_casino [ставка] — казино на размер.\n" "• /penis_casino [ставка] — казино на размер.\n"
"• /gadanie [тема] — гадание на фене с мемом.\n" "• /gadanie [тема] — гадание на фене с мемом.\n"
"• /ebalnik — включить/выключить автоответы в чате.\n" "• /ebalnik — включить/выключить автоответы в чате.\n"
"• /prices /fetch — цены.\n" "• /prices /fetch — цены и остатки Магнита.\n"
"Подсказка: в группах пиши /команда@username_бота." "Подсказка: в группах пиши /команда@username_бота."
) )

161
main.py
View file

@ -388,6 +388,62 @@ def minutes_until_next_lesson(now: datetime | None = None) -> str:
minutes = (total_seconds % 3600) // 60 minutes = (total_seconds % 3600) // 60
return f"Твой мозг окончательно сгниет, а очко порвется через: {days} дн {hours} ч {minutes} мин" return f"Твой мозг окончательно сгниет, а очко порвется через: {days} дн {hours} ч {minutes} мин"
def _prepare_magnit_query(value: str) -> str:
value = re.sub(r"(?<=[a-zа-яё])(?=[A-ZА-ЯЁ])", " ", value)
value = re.sub(r"[_-]+", " ", value)
return re.sub(r"\s+", " ", value).strip()
def _normalize_magnit_product(entry) -> dict[str, str]:
if isinstance(entry, str):
raw_query = entry.strip()
if not raw_query:
raise ValueError("Пустой query в MAGNIT_PRODUCTS.")
return {
"query": _prepare_magnit_query(raw_query),
"label": raw_query,
"store_code": config.MAGNIT_STORE_CODE,
}
if isinstance(entry, dict):
raw_query = str(entry.get("query", "")).strip()
if not raw_query:
raise ValueError("У товара в MAGNIT_PRODUCTS отсутствует query.")
return {
"query": _prepare_magnit_query(raw_query),
"label": str(entry.get("label") or raw_query).strip() or raw_query,
"store_code": str(entry.get("store_code") or config.MAGNIT_STORE_CODE).strip(),
}
raise ValueError("MAGNIT_PRODUCTS должен содержать строки или словари.")
def _pick_magnit_item(data: dict):
best_match = data.get("best_match")
if isinstance(best_match, dict):
return best_match
items = data.get("items")
if isinstance(items, list) and items:
return items[0]
return None
def _format_money(value) -> str | None:
if value is None:
return None
amount = f"{float(value):.2f}".rstrip("0").rstrip(".")
return f"{amount}"
def _format_magnit_price(item: dict) -> str:
new_price = _format_money(item.get("price"))
old_price = _format_money(item.get("old_price"))
if old_price and new_price and item.get("old_price") and item.get("old_price") != item.get("price"):
return f"{old_price} -> {new_price}"
return new_price or "нет цены"
def _format_magnit_quantity(value) -> str:
if value is None:
return "нет данных"
return f"{value} шт."
# --- Игровая логика (/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]:
@ -542,61 +598,58 @@ async def handle_zvetok_cmd(message: Message):
await message.answer(minutes_until_next_lesson()) await message.answer(minutes_until_next_lesson())
async def handle_prices_cmd(message: Message): async def handle_prices_cmd(message: Message):
def fetch():
return requests.get(
"https://bebrik.xyz/magnit/products",
headers={"X-Token": "sisi"},
timeout=10,
)
try: try:
resp = await asyncio.to_thread(fetch) products = [_normalize_magnit_product(entry) for entry in config.MAGNIT_PRODUCTS]
if resp.status_code != 200: except ValueError as exc:
await message.answer("пошел нахуй") await message.answer(f"Проверь MAGNIT_PRODUCTS в config.py: {exc}")
return return
data = resp.json()
if not data: if not products:
await message.answer("иди нахуй") await message.answer("Список MAGNIT_PRODUCTS пуст. Добавь товары в config.py.")
return return
text = "смерть в 25:\n\n"
for item in data: async def fetch_product(product_cfg: dict[str, str]) -> str:
name = item.get("name") def fetch():
price = item.get("price") return requests.get(
text += f"{name}{price}\n" f"{config.MAGNIT_API_BASE_URL.rstrip('/')}/price",
await message.answer(text[:4000]) params={
except Exception: "store_code": product_cfg["store_code"],
await message.answer("unable to connect x-server гандон") "query": product_cfg["query"],
},
timeout=config.MAGNIT_REQUEST_TIMEOUT,
)
label = product_cfg["label"] or product_cfg["query"] or "товар"
try:
resp = await asyncio.to_thread(fetch)
if resp.status_code != 200:
logger.warning("Magnit API returned %s for %s", resp.status_code, product_cfg["query"])
return f"{label}, ошибка API ({resp.status_code}), -"
data = resp.json()
if not isinstance(data, dict):
return f"{label}, битый ответ API, -"
item = _pick_magnit_item(data)
if not isinstance(item, dict):
return f"{label}, товар не найден, -"
name = str(item.get("name") or label).strip() or label
price = _format_magnit_price(item)
quantity = _format_magnit_quantity(item.get("quantity"))
return f"{name}, {price}, {quantity}"
except requests.RequestException:
logger.exception("Failed to fetch Magnit product: %s", product_cfg["query"])
return f"{label}, ошибка запроса, -"
except ValueError:
logger.exception("Magnit API returned invalid JSON for %s", product_cfg["query"])
return f"{label}, битый JSON, -"
lines = await asyncio.gather(*(fetch_product(product) for product in products))
await message.answer("\n".join(lines)[:4000])
async def handle_fetch_cmd(message: Message): async def handle_fetch_cmd(message: Message):
def fetch(): await handle_prices_cmd(message)
return requests.get(
"https://mirror.porno4free.ru/magnit/magnit/prices/all",
headers={"x-token": "secret_token"},
timeout=10,
)
try:
resp = await asyncio.to_thread(fetch)
if resp.status_code != 200:
await message.reply("пошел нахуй")
return
data = resp.json()
if not isinstance(data, dict) or not data:
await message.reply("иди нахуй")
return
lines = ["смерть в 25:"]
for group in sorted(data.keys()):
items = data.get(group)
lines.append(f"\n{group}:")
if not isinstance(items, list):
continue
for item in items:
name = item.get("name")
price = item.get("price")
if not name or price is None:
continue
lines.append(f"{name}{price}")
await message.answer("\n".join(lines)[:4000])
except Exception:
await message.answer("unable to connect x-server гандон")
async def handle_svodka_cmd(message: Message): async def handle_svodka_cmd(message: Message):
data = await asyncio.to_thread(get_military_data, "creamy_caprice", 5) data = await asyncio.to_thread(get_military_data, "creamy_caprice", 5)
@ -790,8 +843,8 @@ def main():
BotCommand(command="size", description="хуй"), BotCommand(command="size", description="хуй"),
BotCommand(command="penis", description="миниигра 1 раз в 24ч"), BotCommand(command="penis", description="миниигра 1 раз в 24ч"),
BotCommand(command="top_penis", description="топ по длине"), BotCommand(command="top_penis", description="топ по длине"),
BotCommand(command="prices", description="цены x-server"), BotCommand(command="prices", description="цены и остатки Магнита"),
BotCommand(command="fetch", description="цены (новый источник)"), BotCommand(command="fetch", description="alias для /prices"),
BotCommand(command="zvetok", description="Цветянский бля"), BotCommand(command="zvetok", description="Цветянский бля"),
BotCommand(command="talk", description="Побазарить"), BotCommand(command="talk", description="Побазарить"),
BotCommand(command="ebalnik", description="вкл/выкл автответов"), BotCommand(command="ebalnik", description="вкл/выкл автответов"),