Приветствую всех! Думаю, многие сталкивались с проблемой запоздалых уведомлений от Lolzteam Alert (бота уведомлений от lolz). Я в том числе. Поэтому решил написать похожего бота и поделиться им с вами. Функционал бота: Получение всех уведомлений Получение вашего баланса/холда (в планах: действия с новой темой(ответ), сортировка уведомлений(все, маркет) Требования Python 3.11.0 - скачать тут user_id в TG - тут API Token вашего бота - тут API Token Lolz(со всеми правами) - тут либо гайд В cmd: pip install aiogram==2.25.1 beautifulsoup4 asyncio aiohttp Code pip install aiogram==2.25.1 beautifulsoup4 asyncio aiohttp Инструкция Создайте файл main.py в удобном для вас месте. Вставьте код из спойлера снизу в main.py. Заполните данные в 9, 10 и 11 строках. Сохраните и запустите файл. Код from aiogram import Bot, Dispatcher, types from aiogram.types import BotCommand, ReplyKeyboardMarkup, KeyboardButton, ParseMode from aiogram.utils import executor from aiohttp import ClientSession import html import asyncio from bs4 import BeautifulSoup TOKEN = '' # токен вашего бота тг token_lolz = '' # токен lolz user_id = 0 # ваш user_id TG, получить можно в этом боте @getmyid_bot bot = Bot(token=TOKEN, parse_mode=ParseMode.MARKDOWN) dp = Dispatcher(bot) notify_id = [] notify_status = False ######### @dp.message_handler(text="Профиль", state="*") async def handle_profile(message: types.Message): await profile_command(message) ######### @dp.message_handler(commands=['start']) async def start_command(message: types.Message): if message.from_user.id == user_id: keyboard_re = await keyboard() await bot.send_message(user_id, f"Главное меню", parse_mode=ParseMode.MARKDOWN, reply_markup=keyboard_re) @dp.message_handler(commands=['profile']) async def profile_command(message: types.Message): if message.from_user.id == user_id: response = await lzt_profile() keyboard_re = await keyboard() await bot.send_message(message.from_user.id, f"[{response['username']}](https://lolz.live/members/{response['user_id']}/)\nБаланс: {response['balance']} {response['currency']}\nХолд: {response['hold']} {response['currency']}", parse_mode=ParseMode.MARKDOWN, reply_markup=keyboard_re) @dp.message_handler(lambda message: message.text in ["Уведомления: включены", "Уведомления: выключены"] or "/notify" in message.text.lower()) async def notify_command(message: types.Message): global notify_status if message.from_user.id == user_id: notify_status = not notify_status status = "включены" if notify_status else "выключены" keyboard_re = await keyboard() await bot.send_message(message.from_user.id, f'Уведомления {status}', parse_mode=ParseMode.MARKDOWN, reply_markup=keyboard_re) async def lzt_alert(): global notify_status url = "https://api.zelenka.guru/notifications" headers = { "accept": "application/json", "authorization": f"Bearer {token_lolz}" } async with ClientSession() as session: while True: if not notify_status: await asyncio.sleep(1) continue try: async with session.get(url, headers=headers) as response: if response.status != 429: data = await response.json() for notification in data['notifications']: if 'notification_id' in notification and notification['notification_id'] not in notify_id: notify_id.append(notification['notification_id']) text = html_text_link(notification.get('notification_html', '')) await bot.send_message(user_id, text) except Exception as e: print(e) await asyncio.sleep(10) async def lzt_profile(): url = "https://api.lzt.market/me" headers = { "accept": "application/json", "authorization": f"Bearer {token_lolz}" } async with ClientSession() as session: while True: try: async with session.get(url, headers=headers) as response: if response.status != 429: data = await response.json() currency = await find_currency(data['user']['currency']) profile_data = { 'username': data['user']['username'], 'user_id': data['user']['user_id'], 'balance': data['user']['balance'], 'currency': currency, 'hold': data['user']['hold'] } return profile_data except Exception as e: print(e) await asyncio.sleep(4) async def find_currency(currency_code): currency_symbols = { "uah": "₴", "rub": "₽", "usd": "$", "eur": "€", "kzt": "₸", "thb": "฿", "byn": "BYN" } if currency_code.lower() in currency_symbols: return currency_symbols[currency_code.lower()] else: return None def html_text_link(content): decoded_html = html.unescape(content) soup = BeautifulSoup(decoded_html, 'html.parser') for a in soup.find_all('a'): a_text = a.get_text() a_href = a['href'] a.replace_with(f'[{a_text}]({a_href})') clean_text = soup.get_text() return clean_text async def keyboard(): global notify_status profile = await lzt_profile() keyboard = ReplyKeyboardMarkup(row_width=2, resize_keyboard=True) profile_button = KeyboardButton("Профиль") balance_button = KeyboardButton(f"Баланс: {profile['balance']} {profile['currency']}") hold_button = KeyboardButton(f"Холд: {profile['hold']} {profile['currency']}") notify_button = KeyboardButton("Уведомления: включены" if notify_status else "Уведомления: выключены") keyboard.add(profile_button, balance_button) keyboard.add(notify_button, hold_button) return keyboard async def set_commands(bot: Bot): commands = [ BotCommand(command="/start", description="Главное меню"), BotCommand(command="/profile", description="Ваш профиль"), BotCommand(command="/notify", description="Включить/выключить уведомления"), ] await bot.set_my_commands(commands) async def on_startup(dp): await set_commands(bot) asyncio.create_task(lzt_alert()) if __name__ == "__main__": executor.start_polling(dp, skip_updates=True, on_startup=on_startup) Python from aiogram import Bot, Dispatcher, types from aiogram.types import BotCommand, ReplyKeyboardMarkup, KeyboardButton, ParseMode from aiogram.utils import executor from aiohttp import ClientSession import html import asyncio from bs4 import BeautifulSoup TOKEN = '' # токен вашего бота тг token_lolz = '' # токен lolz user_id = 0 # ваш user_id TG, получить можно в этом боте @getmyid_bot bot = Bot(token=TOKEN, parse_mode=ParseMode.MARKDOWN) dp = Dispatcher(bot) notify_id = [] notify_status = False ######### @dp.message_handler(text="Профиль", state="*") async def handle_profile(message: types.Message): await profile_command(message) ######### @dp.message_handler(commands=['start']) async def start_command(message: types.Message): if message.from_user.id == user_id: keyboard_re = await keyboard() await bot.send_message(user_id, f"Главное меню", parse_mode=ParseMode.MARKDOWN, reply_markup=keyboard_re) @dp.message_handler(commands=['profile']) async def profile_command(message: types.Message): if message.from_user.id == user_id: response = await lzt_profile() keyboard_re = await keyboard() await bot.send_message(message.from_user.id, f"[{response['username']}](https://lolz.live/members/{response['user_id']}/)\nБаланс: {response['balance']} {response['currency']}\nХолд: {response['hold']} {response['currency']}", parse_mode=ParseMode.MARKDOWN, reply_markup=keyboard_re) @dp.message_handler(lambda message: message.text in ["Уведомления: включены", "Уведомления: выключены"] or "/notify" in message.text.lower()) async def notify_command(message: types.Message): global notify_status if message.from_user.id == user_id: notify_status = not notify_status status = "включены" if notify_status else "выключены" keyboard_re = await keyboard() await bot.send_message(message.from_user.id, f'Уведомления {status}', parse_mode=ParseMode.MARKDOWN, reply_markup=keyboard_re) async def lzt_alert(): global notify_status url = "https://api.zelenka.guru/notifications" headers = { "accept": "application/json", "authorization": f"Bearer {token_lolz}" } async with ClientSession() as session: while True: if not notify_status: await asyncio.sleep(1) continue try: async with session.get(url, headers=headers) as response: if response.status != 429: data = await response.json() for notification in data['notifications']: if 'notification_id' in notification and notification['notification_id'] not in notify_id: notify_id.append(notification['notification_id']) text = html_text_link(notification.get('notification_html', '')) await bot.send_message(user_id, text) except Exception as e: print(e) await asyncio.sleep(10) async def lzt_profile(): url = "https://api.lzt.market/me" headers = { "accept": "application/json", "authorization": f"Bearer {token_lolz}" } async with ClientSession() as session: while True: try: async with session.get(url, headers=headers) as response: if response.status != 429: data = await response.json() currency = await find_currency(data['user']['currency']) profile_data = { 'username': data['user']['username'], 'user_id': data['user']['user_id'], 'balance': data['user']['balance'], 'currency': currency, 'hold': data['user']['hold'] } return profile_data except Exception as e: print(e) await asyncio.sleep(4) async def find_currency(currency_code): currency_symbols = { "uah": "₴", "rub": "₽", "usd": "$", "eur": "€", "kzt": "₸", "thb": "฿", "byn": "BYN" } if currency_code.lower() in currency_symbols: return currency_symbols[currency_code.lower()] else: return None def html_text_link(content): decoded_html = html.unescape(content) soup = BeautifulSoup(decoded_html, 'html.parser') for a in soup.find_all('a'): a_text = a.get_text() a_href = a['href'] a.replace_with(f'[{a_text}]({a_href})') clean_text = soup.get_text() return clean_text async def keyboard(): global notify_status profile = await lzt_profile() keyboard = ReplyKeyboardMarkup(row_width=2, resize_keyboard=True) profile_button = KeyboardButton("Профиль") balance_button = KeyboardButton(f"Баланс: {profile['balance']} {profile['currency']}") hold_button = KeyboardButton(f"Холд: {profile['hold']} {profile['currency']}") notify_button = KeyboardButton("Уведомления: включены" if notify_status else "Уведомления: выключены") keyboard.add(profile_button, balance_button) keyboard.add(notify_button, hold_button) return keyboard async def set_commands(bot: Bot): commands = [ BotCommand(command="/start", description="Главное меню"), BotCommand(command="/profile", description="Ваш профиль"), BotCommand(command="/notify", description="Включить/выключить уведомления"), ] await bot.set_my_commands(commands) async def on_startup(dp): await set_commands(bot) asyncio.create_task(lzt_alert()) if __name__ == "__main__": executor.start_polling(dp, skip_updates=True, on_startup=on_startup) p.s питонщики не бейте палками, писал бота с 1% знанием питона + гпт4
действительно, часто Alert работал не так, как надо(именно поэтому я его выключил). Респект за старания