feat: basic webinar checker bot
This commit is contained in:
@@ -13,9 +13,9 @@ services:
|
|||||||
retries: 5
|
retries: 5
|
||||||
|
|
||||||
playwright-service:
|
playwright-service:
|
||||||
image: mcr.microsoft.com/playwright:v1.56.0-noble
|
image: mcr.microsoft.com/playwright:v1.56.0-jammy
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
command: npx -y playwright run-server --port 3000 --path /ws
|
command: npx -y playwright@1.56.0 run-server --port 3000 --path /ws
|
||||||
ports:
|
ports:
|
||||||
- "3000:3000"
|
- "3000:3000"
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
FROM python:3.11-slim
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
RUN pip install --upgrade pip && pip install playwright==1.56.0 redis requests
|
||||||
|
|
||||||
|
COPY checker.py .
|
||||||
|
|
||||||
|
CMD ["python", "checker.py"]
|
||||||
@@ -0,0 +1,147 @@
|
|||||||
|
import os
|
||||||
|
import time
|
||||||
|
import logging
|
||||||
|
import redis
|
||||||
|
import requests
|
||||||
|
from playwright.sync_api import sync_playwright
|
||||||
|
|
||||||
|
# Configure logging
|
||||||
|
logging.basicConfig(
|
||||||
|
level=logging.INFO,
|
||||||
|
format='%(asctime)s - %(levelname)s - %(message)s'
|
||||||
|
)
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
# Load configuration
|
||||||
|
WEBINAR_URL = os.getenv('WEBINAR_URL', 'https://edu.edu.vn.ua/webinar/useractive')
|
||||||
|
WEBINAR_CHECK_INTERVAL = int(os.getenv('WEBINAR_CHECK_INTERVAL', 60))
|
||||||
|
REDIS_HOST = os.getenv('REDIS_HOST', 'redis')
|
||||||
|
REDIS_PORT = int(os.getenv('REDIS_PORT', 6379))
|
||||||
|
PLAYWRIGHT_WS = os.getenv('PLAYWRIGHT_WS', 'ws://playwright-service:3000/ws')
|
||||||
|
USER_AGENT = os.getenv('USER_AGENT', 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36')
|
||||||
|
WEBINAR_TELEGRAM_TOKEN = os.getenv('WEBINAR_TELEGRAM_TOKEN')
|
||||||
|
WEBINAR_TELEGRAM_CHAT_ID = os.getenv('WEBINAR_TELEGRAM_CHAT_ID')
|
||||||
|
|
||||||
|
def send_telegram_message(message):
|
||||||
|
"""Send message to Telegram."""
|
||||||
|
if not WEBINAR_TELEGRAM_TOKEN or not WEBINAR_TELEGRAM_CHAT_ID:
|
||||||
|
logger.warning("Telegram credentials not configured. Skipping message.")
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
url = f"https://api.telegram.org/bot{WEBINAR_TELEGRAM_TOKEN}/sendMessage"
|
||||||
|
payload = {
|
||||||
|
'chat_id': WEBINAR_TELEGRAM_CHAT_ID,
|
||||||
|
'text': message,
|
||||||
|
'parse_mode': 'HTML'
|
||||||
|
}
|
||||||
|
response = requests.post(url, json=payload)
|
||||||
|
if response.status_code == 200:
|
||||||
|
logger.info("Telegram message sent successfully.")
|
||||||
|
else:
|
||||||
|
logger.error(f"Failed to send Telegram message: {response.text}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error sending Telegram message: {e}")
|
||||||
|
|
||||||
|
def check_webinars(redis_client):
|
||||||
|
"""Check for active webinars and notify via Telegram."""
|
||||||
|
|
||||||
|
# Get PHPSESSID from Redis
|
||||||
|
phpsessid = redis_client.get('EDU_PHPSESSID')
|
||||||
|
if not phpsessid:
|
||||||
|
logger.warning("PHPSESSID not found in Redis. Waiting for session-keeper to provide it.")
|
||||||
|
return
|
||||||
|
|
||||||
|
logger.info(f"Using PHPSESSID from Redis: {phpsessid}")
|
||||||
|
|
||||||
|
with sync_playwright() as p:
|
||||||
|
try:
|
||||||
|
# Connect to remote Playwright server
|
||||||
|
browser = p.chromium.connect(PLAYWRIGHT_WS)
|
||||||
|
logger.info(f"Connected to Playwright server at {PLAYWRIGHT_WS}")
|
||||||
|
|
||||||
|
context = browser.new_context(
|
||||||
|
user_agent=USER_AGENT,
|
||||||
|
viewport={'width': 1280, 'height': 720}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Set PHPSESSID cookie
|
||||||
|
context.add_cookies([{
|
||||||
|
'name': 'PHPSESSID',
|
||||||
|
'value': phpsessid,
|
||||||
|
'domain': 'edu.edu.vn.ua',
|
||||||
|
'path': '/'
|
||||||
|
}])
|
||||||
|
|
||||||
|
page = context.new_page()
|
||||||
|
|
||||||
|
try:
|
||||||
|
logger.info(f"Navigating to {WEBINAR_URL}...")
|
||||||
|
page.goto(WEBINAR_URL, wait_until='domcontentloaded')
|
||||||
|
|
||||||
|
# Wait for the table to load (dynamic content)
|
||||||
|
try:
|
||||||
|
page.wait_for_selector('#meetings table', timeout=10000)
|
||||||
|
except Exception:
|
||||||
|
logger.error("Timeout waiting for #meetings table. Page might not have loaded correctly.")
|
||||||
|
return
|
||||||
|
|
||||||
|
content = page.content()
|
||||||
|
|
||||||
|
if "Жодного онлайн уроку зараз" in content:
|
||||||
|
logger.info("Webinars check: No active webinars.")
|
||||||
|
else:
|
||||||
|
# Webinars found!
|
||||||
|
logger.info("!!! WEBINAR FOUND !!!")
|
||||||
|
|
||||||
|
# Extract details
|
||||||
|
rows = page.locator('#meetings table tbody tr')
|
||||||
|
count = rows.count()
|
||||||
|
|
||||||
|
webinar_details = []
|
||||||
|
if count > 0:
|
||||||
|
for i in range(count):
|
||||||
|
text = rows.nth(i).inner_text()
|
||||||
|
# Skip the "no webinars" row
|
||||||
|
if "Жодного онлайн уроку зараз" not in text:
|
||||||
|
webinar_details.append(text.strip())
|
||||||
|
|
||||||
|
# Send Telegram notification (Russian)
|
||||||
|
if webinar_details:
|
||||||
|
message = "🎓 <b>Найден вебинар!</b>\n\n"
|
||||||
|
for detail in webinar_details:
|
||||||
|
message += f"📌 {detail}\n\n"
|
||||||
|
send_telegram_message(message)
|
||||||
|
else:
|
||||||
|
send_telegram_message("🎓 <b>Найден вебинар!</b>\n\nДетали не удалось извлечь.")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"An error occurred during check: {e}")
|
||||||
|
finally:
|
||||||
|
browser.close()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to connect to Playwright server: {e}")
|
||||||
|
|
||||||
|
def main():
|
||||||
|
logger.info("Starting Webinar Checker Bot")
|
||||||
|
|
||||||
|
# Connect to Redis
|
||||||
|
try:
|
||||||
|
redis_client = redis.Redis(host=REDIS_HOST, port=REDIS_PORT, decode_responses=True)
|
||||||
|
redis_client.ping()
|
||||||
|
logger.info(f"Connected to Redis at {REDIS_HOST}:{REDIS_PORT}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to connect to Redis: {e}")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Send startup message (Russian)
|
||||||
|
send_telegram_message("🤖 <b>Бот запущен</b>\n\nМониторинг вебинаров активирован...")
|
||||||
|
|
||||||
|
while True:
|
||||||
|
check_webinars(redis_client)
|
||||||
|
logger.info(f"Sleeping for {WEBINAR_CHECK_INTERVAL} seconds...")
|
||||||
|
time.sleep(WEBINAR_CHECK_INTERVAL)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user