import os import logging from flask import Flask, request, jsonify import requests from datetime import datetime # Настройка логирования logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__) app = Flask(__name__) # Конфигурация из переменных окружения EDU_HOST = os.getenv('EDU_HOST', 'edu.edu.vn.ua') EDU_LOGIN = os.getenv('EDU_LOGIN', '') EDU_PASSWORD = os.getenv('EDU_PASSWORD', '') BOT_PORT = int(os.getenv('BOT_PORT', '5000')) BOT_HOST = os.getenv('BOT_HOST', '0.0.0.0') # Кэш для хранения актуальной сессии session_cache = { 'phpsessid': None, 'expires_at': None } def login_and_get_session(): """ Выполняет логин и возвращает новый PHPSESSID """ url = f"https://{EDU_HOST}/user/login" headers = { 'Cache-Control': 'max-age=0', 'Sec-Ch-Ua': '"Chromium";v="141", "Not?A_Brand";v="8"', 'Sec-Ch-Ua-Mobile': '?0', 'Sec-Ch-Ua-Platform': '"Linux"', 'Accept-Language': 'ru-RU,ru;q=0.9', 'Origin': f'https://{EDU_HOST}', 'Content-Type': 'application/x-www-form-urlencoded', 'Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', 'Sec-Fetch-Site': 'same-origin', 'Sec-Fetch-Mode': 'navigate', 'Sec-Fetch-User': '?1', 'Sec-Fetch-Dest': 'document', 'Referer': f'https://{EDU_HOST}/', 'Accept-Encoding': 'gzip, deflate, br', 'Priority': 'u=0, i' } data = { 'login': EDU_LOGIN, 'password': EDU_PASSWORD } try: logger.info(f"Attempting login to {url}") response = requests.post( url, data=data, headers=headers, allow_redirects=False, timeout=10 ) # Получаем PHPSESSID из cookies phpsessid = response.cookies.get('PHPSESSID') if phpsessid: logger.info(f"Login successful, got PHPSESSID: {phpsessid[:10]}...") return { 'success': True, 'phpsessid': phpsessid, 'status_code': response.status_code } else: logger.warning(f"Login failed: no PHPSESSID in response. Status: {response.status_code}") return { 'success': False, 'error': 'No PHPSESSID in response', 'status_code': response.status_code } except requests.exceptions.RequestException as e: logger.error(f"Login request failed: {str(e)}") return { 'success': False, 'error': str(e) } def validate_phpsessid(phpsessid): """ Проверяет валидность существующего PHPSESSID """ url = f"https://{EDU_HOST}/" headers = { 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' } cookies = { 'PHPSESSID': phpsessid } try: response = requests.get(url, headers=headers, cookies=cookies, timeout=10) # Проверяем, не редиректит ли на страницу логина is_valid = response.status_code == 200 and '/user/login' not in response.url return { 'valid': is_valid, 'status_code': response.status_code, 'url': response.url } except requests.exceptions.RequestException as e: logger.error(f"Validation request failed: {str(e)}") return { 'valid': False, 'error': str(e) } @app.route('/health', methods=['GET']) def health(): """Health check endpoint""" return jsonify({'status': 'ok', 'timestamp': datetime.now().isoformat()}) @app.route('/get-session', methods=['POST', 'GET']) def get_session(): """ Основной endpoint для получения валидного PHPSESSID Возвращает кэшированную сессию или создает новую """ result = login_and_get_session() if result['success']: session_cache['phpsessid'] = result['phpsessid'] session_cache['last_updated'] = datetime.now().isoformat() return jsonify({ 'success': True, 'phpsessid': result['phpsessid'], 'timestamp': datetime.now().isoformat() }) else: return jsonify({ 'success': False, 'error': result.get('error', 'Login failed'), 'timestamp': datetime.now().isoformat() }), 400 @app.route('/validate-session', methods=['POST']) def validate_session(): """ Проверяет валидность переданного PHPSESSID """ data = request.get_json() or {} phpsessid = data.get('phpsessid') or request.args.get('phpsessid') if not phpsessid: return jsonify({ 'success': False, 'error': 'PHPSESSID not provided' }), 400 validation_result = validate_phpsessid(phpsessid) return jsonify({ 'success': True, 'valid': validation_result.get('valid', False), 'details': validation_result, 'timestamp': datetime.now().isoformat() }) @app.route('/refresh-session', methods=['POST', 'GET']) def refresh_session(): """ Принудительно обновляет сессию """ result = login_and_get_session() if result['success']: return jsonify({ 'success': True, 'phpsessid': result['phpsessid'], 'message': 'Session refreshed successfully', 'timestamp': datetime.now().isoformat() }) else: return jsonify({ 'success': False, 'error': result.get('error', 'Failed to refresh session'), 'timestamp': datetime.now().isoformat() }), 400 if __name__ == '__main__': if not EDU_LOGIN or not EDU_PASSWORD: logger.error("EDU_LOGIN and EDU_PASSWORD must be set!") exit(1) logger.info(f"Starting PHPSESSID validator bot on {BOT_HOST}:{BOT_PORT}") logger.info(f"Target host: {EDU_HOST}") app.run(host=BOT_HOST, port=BOT_PORT, debug=False)